RMI Backend β 2026 Architecture Design
Why this exists
The current backend (/root/backend/) has grown organically:
main.pyis 10,305 lines- 124 router files flat in
app/routers/ - 14 RAG modules scattered at top of
app/ token_scanner.pyis 4,109 linesx402_tools.pyis 5,817 lines- Cross-cutting concerns (redis, auth, errors) duplicated across modules
- Domain logic entangled with FastAPI
- No tests, no type safety, no clear boundaries
15 mechanical refactor tasks would patch symptoms. This design fixes the architecture.
Target Layout
/root/backend/
βββ pyproject.toml uv + ruff + mypy + pytest config (single source)
βββ .pre-commit-config.yaml ruff + mypy + size cap + gitleaks
βββ Dockerfile
βββ alembic/ async migrations
β
βββ app/
β βββ main.py <100 lines: app factory + lifespan + middleware ONLY
β βββ config.py pydantic-settings, env loading
β β
β βββ core/ cross-cutting, NO business logic
β β βββ logging.py structlog JSON + correlation ID
β β βββ errors.py AppError hierarchy + FastAPI handlers
β β βββ redis.py async client + get_redis() Depends()
β β βββ db.py async SQLAlchemy session
β β βββ auth.py JWT decode + role guards
β β βββ lifespan.py startup/shutdown
β β βββ middleware.py CORS, rate limit, correlation ID
β β βββ websocket.py WS connection manager
β β βββ tracing.py OpenTelemetry + Langfuse v4 init
β β βββ http.py async httpx client
β β βββ pagination.py cursor-based
β β βββ metrics.py Prometheus /metrics endpoint (P0 v3)
β β βββ legacy.py @legacy decorator for deprecation tracking
β β
β βββ api/ HTTP transport, thin routes
β β βββ deps.py shared Depends (current_user, redis, etc)
β β βββ v1/
β β β βββ public/ no auth β scanner, wallet, token, pricing, health
β β β βββ auth/ JWT β portfolio, alerts, intel, profile
β β β βββ admin/ admin β users, system, ops
β β β βββ x402/ paid β tools, tokens, wallets, defi, security
β β β βββ mcp/ MCP β tools.py
β β βββ ws/ WebSocket
β β βββ alerts.py
β β
β βββ domain/ pure business logic, NO FastAPI imports
β β βββ scanner/ core + honeypot + rugcheck + holders + contract + deployer + models + service
β β βββ wallet/ analyzer + labels + behavior + models + service
β β βββ token/ discovery + supply + models + service
β β βββ rag/ embeddings + chunking + search + ingest + firehose + feedback + agentic + evaluation + tracing + router + permanence + models + service
β β βββ x402/ facilitator + tokens + enforcement + settlement + models + service
β β βββ intel/ feeds + narratives + graph + models + service
β β βββ scam/ classifier + patterns + models + service
β β βββ databus/ client + chains(96) + models + service
β β βββ bulletin/ board + models + service
β β
β βββ infra/ external integrations
β β βββ ollama.py
β β βββ langfuse.py
β β βββ vector_store.py
β β βββ chains/ evm + solana + bitcoin + base + ...
β β βββ apis/ coingecko + etherscan + birdeye + goplus + arkham + dune + ...
β β βββ providers/ ollama + openrouter + huggingface + ...
β β
β βββ agents/ v3 NEW β bounded-task AI agent loops (M1)
β β βββ loop.py frozen: TaskInput/LoopBudget/TaskOutput Pydantic models
β β βββ fact_store.py Redis-backed long-term memory
β β βββ kill_switches.py budget enforcers (iterations, tokens, wall, spend)
β β βββ executor.py bounded loop runner
β β
β βββ mcp/ v3 NEW β MCP mesh v2 (M2)
β β βββ manifest.py frozen: MCPToolManifest Pydantic model
β β βββ registry.py FastAPI on :8643 β list/resolve tools
β β βββ auth.py gopass-backed auth scopes
β β βββ servers/ opencti + dify + n8n FastMCP servers
β β
β βββ middleware/ v3 NEW β Starlette middleware classes (M7)
β β βββ cost_tracking.py frozen: per-tenant/per-route cost middleware
β β βββ rate_limit_v2.py per-tier sliding window
β β βββ auth_deps.py JWT/API key on legacy routes
β β βββ security_headers.py CSP, HSTS, X-Frame-Options
β β βββ shadow_traffic.py v1/v2 response diffing
β β
β βββ workers/ background jobs (separate from API)
β βββ firehose.py
β βββ scanner_queue.py
β βββ ingest_cron.py
β βββ cleanup.py
β
βββ docs/
β βββ adr/ v3 NEW β Architecture Decision Records (M6)
β βββ runbooks/ v3 NEW β incident response (M6)
β βββ postmortems/ v3 NEW β incident learnings (M6)
β βββ oncall/ v3 NEW β rotation doc (M6)
β βββ load/ v3 NEW β k6 baseline reports (P2 #26)
β βββ contract/ v3 NEW β Pact contract specs (P2 #27)
β βββ plans/
β βββ UNFUCK-V1.md Frozen β superseded
β βββ UNFUCK-V2.md Frozen β superseded
β βββ UNFUCK-V3.md ACTIVE β AI-Forward Ship Edition (this document's parent)
β βββ INTEGRATION-LOG.md append-only worklog of v3 execution
β
βββ tests/
βββ conftest.py
βββ unit/
β βββ core/ 33+ core tests
β βββ domain/ 58+ domain tests
βββ e2e/ v3 NEW β Playwright (P2 #25)
βββ contract/ v3 NEW β Pact (P2 #25)
βββ load/ v3 NEW β k6 scripts (P2 #25)
βββ rag/
βββ eval_suite.py v3 NEW β retrieval quality regression (M3)
βββ prompts/
βββ test_snapshots.py v3 NEW β prompt regression
Key Design Principles
- STRICT LAYERING.
api β domain β infra. Never reverse. Domain knows nothing about HTTP. - ONE SOURCE OF TRUTH for cross-cutting. redis/auth/errors/logging live in
core/exactly once. Routes import, never redefine. - HARD SIZE CAP. 500 lines per file. Enforced in pre-commit. No 4,109-line
token_scanner.pyever again. - THIN ROUTES. Routes parse β call service β return. No business logic in HTTP layer.
- DOMAIN = PURE PYTHON.
domain/scanner/can be unit tested without spinning up FastAPI. This is the test that proves the architecture. - WORKERS SEPARATED. Background jobs don't pollute the API. firehose, scanner_queue, ingest_cron live in
workers/. - PYDANTIC V2 EVERYWHERE. Every domain has
models.py. Nodicttypes crossing boundaries. - ASYNC-ONLY. No sync I/O in handlers. Same shape for the whole codebase.
- OBSERVABILITY BY DEFAULT. structlog JSON + correlation ID + OTel + Langfuse in
core/tracing.py. Every endpoint instrumented without opt-in. - STRANGLER FIG MIGRATION. New skeleton co-exists with old code. Old
main.pykeeps importing the old routers. New routes added alongside. Per-domain cutover, not big-bang.
Migration Order
| Order | Domain | Why |
|---|---|---|
| 0 | rag_engine shim |
unblock prod crash, temp until app/rag/ lands |
| 1 | core/ |
foundation everyone depends on |
| 2 | infra/ |
external integrations domain depends on |
| 3 | alerts |
smallest, well-bounded, has WS + JWT + redis β proves full pattern |
| 4 | wallet |
high-value, used by frontend |
| 5 | token |
high-value |
| 6 | scanner |
biggest (4,109 lines), do last when pattern is mature |
| 7 | x402 |
payment system, critical, mature pattern by then |
| 8 | intel, scam, databus, bulletin |
long tail |
| 9 | rag consolidation (was 14 files) |
last because it's the most coupled |
THE 14-POINT MODERN BUILDER BAR (v3 β non-negotiable quality gate)
Every file that touches the unfuck MUST clear this. Pre-commit enforces what can be enforced.
# Standard Status Enforcement
1 Pydantic v2 strict (ConfigDict) PARTIAL pre-commit mypy
2 async-only handlers DONE pre-commit AST scan
3 <500 lines/file (pre-commit) DONE pre-commit file-size-cap
4 pre-commit hooks (ruff+mypy+gitleaks+
detect-secrets+bandit+file-size+pytest) PARTIAL install on dev + CI
5 typed errors (18/18) β currently 4/18 4/18 pre-commit AST scan
6 1 type per layer (apiβdomainβcoreβinfra) PARTIAL architecture test
7 structlog everywhere DONE pre-commit no-print()
8 event bus (Redis pub/sub) PARTIAL manual review
9 per-domain /health/{domain} PARTIAL manual review
10 per-route cost tracking NONE M7 middleware (P2)
11 no from-main-import DONE pre-commit AST scan
12 single get_redis() DONE pre-commit no-new-get-redis
13 OTel trace coverage >85% 0% M4 wiring (P1)
14 Langfuse span coverage >95% LLM calls PARTIAL M4 wiring (P1)
Items 5, 10, 13, 14 are the v3 additions.
THE 30 MUST-DO ITEMS (v3 β ACTIVE PLAN)
P0 β Week 1 (32h total β 16h human + 16h M3)
| # | Item | Hours | Owner | Status | File |
|---|---|---|---|---|---|
| 1 | main.py lifespan merge crash fixed | 1 | human | β DONE | main.py (94 lines) |
| 2 | Audit 53 uncommitted modifications | 3 | human | β³ TODO | git diff HEAD |
| 3 | 65 broken crons β Tailscale IP | 4 | human | β³ TODO | crons 167.86.116.51 β 100.100.18.18 |
| 4 | /metrics endpoint | 2 | M3 | β³ TODO | app/core/metrics.py (NEW) |
| 5 | AlertManager β Telegram | 2 | M3 | β³ TODO | docker-compose.yml + alertmanager.yml |
| 6 | Embedder dual-dim wrapper (M3) | 8 | M3 | β³ TODO | app/rag/embedder.py (NEW) |
| 7 | WalletService proper async impl | 6 | M3 | β³ STUBS DONE, REAL PENDING | app/domain/wallet/service.py |
| 8 | Frontend SPA migrate Contaboβnetcup | 2 | human | β³ TODO | /var/www/rmi/ |
| 9 | GHOST_ADMIN_KEY from gopass | 1 | human | β³ TODO | .env |
| 10 | Load avg 14.19 β identify cause | 3 | human | β³ TODO | Erigon or Ollama? |
P1 β Week 2 (37h total β 3h human + 34h M3)
| # | Item | Hours | Owner | Status | File |
|---|---|---|---|---|---|
| 11 | GlitchTip self-host + wire SDK | 4 | M3 | β³ TODO | docker-compose.glitchtip.yml (NEW) |
| 12 | OTel auto-instrumentation (M4) | 6 | M3 | β³ TODO | app/core/tracing.py wire into lifespan |
| 13 | GitHub Actions CI | 8 | M3 | β³ TODO | .github/workflows/ci.yml (NEW) |
| 14 | Renovate + Dependabot | 2 | M3 | β³ TODO | .github/dependabot.yml (NEW) |
| 15 | Trivy in CI | 2 | M3 | β³ TODO | .github/workflows/ci.yml |
| 16 | Semgrep SAST in CI | 2 | M3 | β³ TODO | .github/workflows/ci.yml |
| 17 | Gitleaks + Trufflehog | 2 | M3 | β³ TODO | .pre-commit-config.yaml + CI |
| 18 | Vault rotation script (gopass) | 3 | human | β³ TODO | scripts/rotate_secrets.sh (NEW) |
| 19 | Rate limit middleware on all /api/v1/* | 4 | M3 | β³ TODO | app/core/middleware.py |
| 20 | Auth Depends() on legacy routes | 4 | M3 | β³ TODO | app/core/middleware.py |
P2 β Week 3 (46h total β 12h human + 34h M3)
| # | Item | Hours | Owner | Status | File |
|---|---|---|---|---|---|
| 21 | Security headers (CSP, HSTS, X-Frame) | 3 | M3 | β³ TODO | app/core/middleware.py |
| 22 | Backup restore drill | 3 | human | β³ TODO | R2 bucket test |
| 23 | 4 Grafana dashboards | 5 | M3 | β³ TODO | grafana/dashboards/*.json |
| 24 | Container memory limits (all 36) | 3 | M3 | β³ TODO | docker-compose.yml |
| 25 | tests/{e2e,contract,load}/ scaffolding | 4 | M3 | β³ TODO | tests/e2e/ tests/contract/ tests/load/ |
| 26 | k6 baselines (top 50 routes) | 6 | M3 | β³ TODO | tests/load/baseline.js |
| 27 | Pact contracts + openapi-generator SDK | 5 | M3 | β³ TODO | tests/contract/ |
| 28 | Top 10 ADRs | 5 | human | β³ TODO | docs/adr/0001-0010.md |
| 29 | Runbooks + postmortem + oncall | 4 | human | β³ TODO | docs/runbooks/ docs/postmortems/ docs/oncall/ |
| 30 | Agent Loop Spec productionization (M1) | 8 | M3 | β³ TODO | app/agents/loop.py (NEW, frozen on creation) |
P3 β Defer until revenue
Multi-region read replicas. SOC2 audit. Paid third-party pen-test. SBOM distribution. AsyncAPI WebSocket spec. Frontend RUM (Sentry browser SDK, web vitals). Pyroscope continuous profiling. OWASP ZAP.
THE 8 AI-FORWARD MODULES (v3)
M1: Agent Loop Productionization (P2 #30)
Deliverable: app/agents/loop.py (frozen on creation)
from pydantic import BaseModel, Field, ConfigDict
class TaskInput(BaseModel):
model_config = ConfigDict(strict=True, frozen=True)
task_id: str = Field(..., pattern=r"^\d+-[a-z0-9-]+$")
description: str = Field(..., max_length=500)
context_budget_tokens: int = Field(default=8000, le=32000)
allowed_tools: list[str] = Field(..., min_length=1)
success_criteria: str = Field(..., max_length=300)
verify_command: str = Field(..., max_length=200)
class LoopBudget(BaseModel):
model_config = ConfigDict(strict=True, frozen=True)
max_iterations: int = Field(default=20, le=100)
max_tokens: int = Field(default=50_000, le=500_000)
max_wallclock_seconds: int = Field(default=900, le=3600)
max_spend_usd: float = Field(default=5.0, le=50.0)
class TaskOutput(BaseModel):
task_id: str
files_touched: list[str]
lines_added: int
lines_removed: int
verify_passed: bool
worklog_entry: str
spend_usd: float
iterations_used: int
Kill switches (every iteration):
- max_iterations β€ 20 (max 100)
- max_tokens β€ 50K (max 500K)
- max_wallclock β€ 900s (max 3600s)
- max_spend β€ $5 (max $50)
- verify_command_failed_3x β human review
fact_store companion (app/agents/fact_store.py):
- Redis key:
fact:{namespace}:{key} - TTL: 86400s
- Loaded at loop start, written at loop end
- Prevents re-discovery of known facts
Acceptance gate: 7 consecutive days zero runaway.
M2: MCP Mesh v2 (P2 #24, D9)
Deliverable: app/mcp/manifest.py (frozen on creation)
from pydantic import BaseModel, Field
from typing import Any
class MCPToolManifest(BaseModel):
name: str = Field(..., pattern=r"^[a-z_]+:[a-z_]+$") # e.g. "rmi-netcup:docker_ps"
version: str = Field(..., pattern=r"^\d+\.\d+\.\d+$")
server: str = Field(..., pattern=r"^[a-z-]+$")
description: str = Field(..., max_length=200)
input_schema: dict[str, Any]
output_schema: dict[str, Any]
auth_scope: str = Field(..., pattern=r"^[a-z_]+:[a-z_]+$") # gopass scope
deprecated: bool = False
successor: str | None = None
Mesh registry on netcup :8643 with:
- GET /tools (list all with filters)
- GET /tools/{name} (full manifest)
- POST /resolve (name+MAJOR version β executor endpoint)
3 unwired servers to wire in D9:
- OpenCTI (40 tools) β wire with FastMCP
- Dify (18 tools) β wire with FastMCP
- n8n (20 tools) β wire with FastMCP
Acceptance gate: 332+ tools versioned, all gopass-backed auth, OpenCTI+Dify+n8n wired.
M3: RAG Dual-Dim Wrapper (P0 #6)
Deliverable: app/rag/embedder.py (wraps frozen app/crypto_embeddings.py)
from enum import Enum
class EmbedderBackend(Enum):
BGE_M3 = "bge-m3" # 1024d, legacy
QWEN3_4B = "qwen3-embedding:4b" # 2048d, target
class DualDimEmbedder:
def __init__(self, backend: EmbedderBackend):
self.backend = backend
self.dim = 1024 if backend == EmbedderBackend.BGE_M3 else 2048
async def embed(self, texts: list[str]) -> list[list[float]]:
return await self._ollama_embed(texts, self.backend.value)
async def reindex_collection(self, name: str, target: EmbedderBackend) -> bool:
old = DualDimEmbedder(EmbedderBackend.BGE_M3)
new = DualDimEmbedder(target)
# 1. Read all docs from collection
# 2. Re-embed with new backend
# 3. Write to new collection {name}_v2
# 4. Atomic swap: {name} β {name}_legacy, {name}_v2 β {name}
# 5. Verify: query 10 known docs, confirm retrieval
return True
The math:
| Metric | bge-m3 | qwen3-4b | Delta |
|---|---|---|---|
| Dimensions | 1024 | 2048 | +2x |
| RAM (loaded) | 1.2GB | 2.0GB | +800MB |
| Embed latency | ~80ms | ~140ms | +60ms |
| Retrieval (nDCG@10) | 0.71 | 0.83 (est) | +12% |
| Reindex time | β | 6h overnight | one-time |
| Storage/coll | ~50MB | ~100MB | +650MB total |
Strategy: collection-by-collection overnight, smallest first, verify each morning. If <8%, defer.
Acceptance gate: All 13 collections reindexed, eval harness +8% nDCG@10, bge-m3 unloaded.
M4: Observability Triangle (P1 #11, #12, P2 #21)
Three pillars wired into the 94-line lifespan:
# main.py additions (~15 lines to existing 94)
from contextlib import asynccontextmanager
from app.core.tracing import setup_otel
from app.core.langfuse import langfuse
from app.core.errors import init_glitchtip
@asynccontextmanager
async def lifespan(app: FastAPI):
_otel = setup_otel() # OTel: httpx, redis, asyncpg, neo4j
init_glitchtip() # Sentry-compatible SDK
await app.state.redis.initialize()
yield
_otel.shutdown()
langfuse.flush()
await app.state.redis.close()
app = FastAPI(lifespan=lifespan)
Pillars:
- OTel: auto-instrument httpx/redis/asyncpg/neo4j, export to local OTel collector
- Langfuse:
@observe()decorator on every LLM call, >95% coverage - GlitchTip: Sentry-compatible SDK, DSN from gopass, captures every unhandled exception
Acceptance gate: 7 consecutive days triangle lit.
M5: CI/CD Standards (P1 #13-17, P1 #19, P1 #20)
Pipeline stages:
PRE-COMMIT (local): ruff + mypy + gitleaks + detect-secrets + bandit + file-size + pytest-smoke
CI (GH Actions): lint + test-full + build + trivy + semgrep + gitleaks-history + grype
DEPLOY (blue-green): build-green β start β health-gate β swap-router β verify-5xx β keep-blue-10min
ROLLBACK (auto): swap-back-to-blue on 5xx spike β page β freeze-deploys-1h
Justfile deploy target:
deploy:
docker compose -f docker-compose.green.yml build
docker compose -f docker-compose.green.yml up -d
./scripts/health-check.sh http://127.0.0.1:8001/health 60
./scripts/swap-upstream.sh green
./scripts/watch-errors.sh 600 0.01
docker compose -f docker-compose.blue.yml stop
M6: ADRs + Runbooks + Postmortems + Oncall (P2 #28, #29)
Top 10 ADRs (write these first):
- Why FastAPI over Litestar/Flask/Django
- Why 5 DBs (Postgres+Redis+CH+Neo4j+Qdrant)
- Why strangler-fig over rewrite
- Why bge-m3 β qwen3-embedding:4b (M3)
- Why self-host GlitchTip over Sentry SaaS
- Why single-VPS blue-green over k3s
- Why gopass over Vault/Doppler/AWS SM
- Why Hermes cron over systemd/Airflow
- Why MCP mesh over direct API calls
- Why Tailscale over WireGuard/ZeroTier
ADR Template:
# ADR-XXXX: [Title]
## Status: Accepted | Rejected | Superseded
## Date: YYYY-MM-DD
## Decider: @cryptorugmunch
## Context: What we're solving
## Decision: What we chose
## Alternatives Considered: What we rejected
## Consequences: Easier / Harder / Mitigations
M7: Cost Tracking + SLOs + Error Budgets (P2 #21)
Per-tenant cost middleware (app/middleware/cost_tracking.py):
class CostTrackingMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request, call_next):
tenant = request.headers.get("X-Tenant-ID", "anonymous")
t0 = time.monotonic()
response = await call_next(request)
elapsed_ms = (time.monotonic() - t0) * 1000
cost = self._estimate_cost(route, response, elapsed_ms)
await self._buffer_cost(tenant, route, cost, elapsed_ms)
return response
SLO Targets:
| Service | SLO | Error budget |
|---|---|---|
| /api/v1/* p99 latency | < 500ms | 43min/mo |
| /api/v2/* p99 latency | < 200ms | 43min/mo |
| /health uptime | β₯ 99.5% | 3.6h/mo |
| /api/* error rate (5xx) | < 0.1% | 43min of 5xx/mo |
| RAG retrieval success | > 95% | 43min of failures/mo |
| LLM calls timeout rate | < 1% | 7.2h of timeouts/mo |
Auto-freeze deploys on 4x burn:
- alert: SLOBurnRate4x
expr: (sum(rate(http_requests_total{status=~"5.."}[1h])) / sum(rate(http_requests_total[1h]))) > 0.02
for: 2m
annotations:
webhook: "http://127.0.0.1:8642/ci/freeze"
M8: AI Tool Wiring Matrix
| Task | Best tool | Worst tool |
|---|---|---|
| Bounded code edit (1 file, <50 lines) | aider | claude-code |
| Multi-file refactor (3β10 files) | claude-code | aider |
| Codebase search | Bloop (when installed) | grep |
| Test generation | claude-code | aider |
| Doc generation (ADR, runbook) | GLM-5.2 | aider |
| Security review | Semgrep (not LLM) | any LLM |
| Dependency upgrade | Renovate (not LLM) | any LLM |
| Prompt engineering | GLM-5.2 + DSPy | claude-code |
| RAG eval | Custom harness + LLM-as-judge | any LLM alone |
| Long-context (β₯100K) | Kimi K2.7 (256K) | DeepSeek (slow) |
| Vision | Gemini 2.5-pro | text-only LLM |
| Fast small (β€500 tokens) | Groq | DeepSeek |
| Autonomous (bounded loop) | Hermes | claude-code |
10 INCIDENT SCENARIOS (v3)
v2's 7 (preserved)
- rmi-redis crashes at 3am β auto-restart
- Disk full on netcup β AlertManager page at 80%
- Postgres corruption β restore from nightly backup
- SSL cert expiry β Cloudflare manages, Tailscale renew
- OOM kill on rmi-backend β Docker limit + py-spy/memray
- DDoS on rugmunch.io β Cloudflare "Under Attack" mode
- DeepSeek balance hits $0 β failover to Ollama Cloud/Gemini
v3's 3 NEW (AI-specific)
Scenario 8 β Agent Loop Runaway
Symptom: LLM spend spikes ($50+/h). Hermes logs show task iterating >50Γ.
Detect: Daily spend alert (M7) at $20/h. Hermes /cron/health shows iterations >20.
Mitigate: pkill -f "hermes.*task_id=X". Disable cron job.
Recover: Audit input contract β likely missing success_criteria or verify_command.
Root cause: vague description or missing verify_command.
Scenario 9 β RAG Poisoning
Symptom: RAG retrieval returns adversarial content. User reports "the AI told me to send funds to X." Detect: Langfuse span shows suspicious source. Eval harness flags quality regression. Mitigate: Disable affected collection. Roll back FAISS index. Recover: Add source allowlist to ingest step. Root cause: open ingestion endpoint or untrusted RSS feed.
Scenario 10 β MCP Tool Compromise
Symptom: Unusual gopass access pattern. MCP tool called from unexpected IP. Lateral movement.
Detect: gopass audit log. CrowdSec flags anomalous SSH. Tailscale ACL violation.
Mitigate: gopass rm rmi/infra/compromised/scope + rotate. Revoke Tailscale node. Block IP.
Recover: Audit all gopass accesses in last 30 days. Rotate ALL keys.
Root cause: over-broad auth_scope or leaked Tailscale key. SEV1.
FROZEN FILE MANIFEST v3 (14 entries)
| # | File | Why frozen |
|---|---|---|
| 1 | main.py |
Front door (was 8475, now 94) |
| 2 | _legacy_main.py |
Strangler-fig target |
| 3 | app/core/redis.py |
Single Redis source |
| 4 | app/core/config.py |
Env var loader |
| 5 | app/databus/core.py |
96-chain fetch interface |
| 6 | app/rag/pipeline.py |
RAG pipeline (frozen for M3) |
| 7 | app/crypto_embeddings.py |
bge-m3 embedder (replaced via wrapper) |
| 8 | app/api/v1/__init__.py |
Router registry |
| 9 | docker-compose.yml |
All 36 containers |
| 10 | app/core/tracing.py |
OTel (not wired β M4) |
| 11 | app/agents/loop.py |
M1 deliverable (frozen on creation) |
| 12 | app/mcp/server.py |
M2 deliverable (frozen on creation) |
| 13 | app/core/metrics.py |
P0 deliverable (frozen on creation) |
| 14 | app/middleware/cost_tracking.py |
M7 deliverable (frozen on creation) |
Rule: Modified only via bounded-task delegation with Task ID in /home/z/my-project/worklog.md. Out-of-process edits reverted.
THE MATH (v3 BRUTAL TRUTH)
Solo With M3
P0 + P1 + P2 hours 115h 115h
Available budget (21dΓ8h) 168h 168h human + 152h M3 = 320h
Buffer (30% incident tax) β50h β50h human, β46h M3
Effective capacity 118h 224h
NET (capacity β work) +3h +109h
β Phase 4 fits here
Plus 20h passive waits (eval soaks, mesh verifications)
β Solo: 138h needed vs 118h available β slips to Day 25
β M3: 138h needed vs 224h available β fits comfortably
Verdict: Solo, v3 is a 25-day plan. With M3 parallel, v3 is a 21-day plan.
90-DAY ROADMAP (after the unfuck)
Month 2 β Agent Mesh + RAG Eval + SDK
- Agent mesh: Hermes orchestrating multiple claude-code/aider in parallel
- RAG eval harness: automated retrieval-quality regression on every push
- SDK v1: TypeScript + Python clients from OpenAPI spec
Month 3 β Multi-Region + SOC2 + Paid Pilots
- Multi-region read replicas (Contabo β Cloudflare LB)
- SOC2 prep (ADRs + runbooks = 60% of evidence)
- 3 paid pilots, $500/mo each, 60-day commitment
Month 4+ β Hire or Stay Solo
- If 3 pilots + 1 conversion β hire senior backend engineer
- If pilots but no conversion β focus on conversion
- If no pilots β pivot
What Ships This Pass (Foundation)
- β
Fix crash β
rag_enginere-export shim, backend healthy (Phase 0) - β
pyproject.tomlβ uv + ruff + mypy strict + pytest - β
.pre-commit-config.yamlβ ruff + mypy + size cap (500) + gitleaks - β
app/core/β 11 modules, each <200 lines - β
app/api/v1/__init__.pyβ router aggregator - β
main.pyβ 94 lines (Phase 0 just restored) - β Verify: backend boots, all 1249 routes respond, health 200
- β
Commit + deploy (
4a8a16d)
What Does NOT Ship This Pass (v3 P0-P2)
- Migrating alerts/wallet/token/scanner to new
domain/. That's the current unfuck. - The 15 mechanical refactors. Replaced with the layered architecture.
- Deleting old code. Strangler fig β old stays until domain is migrated.
- v3 new: M1 Agent Loop, M2 MCP Mesh, M3 RAG dual-dim, M4 Observability Triangle, M5 CI/CD, M6 ADRs, M7 Cost+SLOs, M8 AI Tool Matrix.
Phase 2: Alerts Vertical Slice (proves the pattern) β COMPLETE
After foundation lands, migrate alerts end-to-end as the reference:
app/domain/alerts/
βββ models.py # Alert, AlertRule, Notification β Pydantic v2
βββ repository.py # async SQLAlchemy queries
βββ service.py # business logic, pure Python
βββ broadcaster.py # WebSocket broadcast helper
app/api/v1/auth/alerts.py # thin route: parse β call service β return
This proves the pattern works: domain is pure Python, route is <100 lines, can be unit tested without HTTP.