- Read-only only. Managed by separate Ansible repo.
-
**3GW (local network):** LXC container at `3gw.lan`, zmx session `3gw`
-
-
## Process Rules
-
-
### Agent Delegation Model
-
-
- **Opus orchestrates, Sonnet implements.** No Opus manager layer.
-
- **ALL subagents run in background** (`run_in_background: true`), no exceptions.
-
- **Worktree isolation required** for code changes. Parent dir is NOT a git repo — must scope to specific repo.
-
-
### Implementation Workflow
-
-
See [[Design/Implementation_Workflow]] for full process. Pipeline: Plan (Opus) → Plan Review (Sonnet) → Implement (Sonnet, worktree) → Chico review → Zeppo review → Fix → Re-review → Verify.
+
**3GW (local network):** LXC container at `3gw.lan`, zmx session `3gw`.
-
### Feedback Rules (Hard-Won Lessons)
+
### feedback_reproducible_vps.md (scope: deploy)
-
**Rule of Two:** Never accept a subagent finding without independent verification. A test agent once reported a 404 bug using the wrong URL — it was accepted and written into the wiki before anyone checked.
+
**NEVER run SSH commands that mutate the VPS.** Allowed: read-only diagnostics (`journalctl`, `systemctl status`, `curl`, `cat`, `ls`, `sqlite3 SELECT`). NOT allowed: `pip install`, `sed -i`, `systemctl restart`, `rm`, `mkdir`, or any state-changing command.
-
**Fix, don't defer:** Never suggest carrying known debt when the fix is bounded and small. Default is always: fix it now.
+
Correct workflow: Edit Ansible role → commit → `ansible-playbook deploy.yml` → verify via read-only SSH.
-
**Self-sufficient:** Don't ask questions you can answer by reading code, wiki, or design docs. Only escalate when genuinely blocked or when a decision requires user judgment.
+
Corrected five times. The 45-second deploy cycle is the cost of reproducibility and it is always worth paying. Subagents must also follow this rule.
-
**Reproducible VPS:** NEVER mutate the VPS via SSH. All changes through Ansible. This has been corrected five times. Allowed via SSH: read-only diagnostics only (`journalctl`, `systemctl status`, `curl`, `cat`, `ls`, `sqlite3 SELECT`).
**Pre-merge verification:** Always dispatch a verification agent before merging any subagent's branch. Read the diff, confirm changes match spec, run tests.
+
Otterwiki's `update_app_config()` loads preferences from the active DB and overwrites Flask config. Load order: defaults → settings.cfg → env vars → DB (DB wins). The startup default DB creates empty-string rows that overwrite settings.cfg.
-
**TDD by default:** Red/green TDD whenever possible. Write failing test first, then implementation. Discuss with user before skipping.
+
Always seed config values in per-wiki preferences table via `_init_wiki_db()`. Do NOT rely on settings.cfg for user-modifiable config.
-
**No ignored failures:** If a test is failing before your changes, fix it or flag it. Don't normalize broken tests.
+
### reference_db_locations.md (scope: db)
-
**Plan Review:** Always dispatch a Plan Review agent after Plan, before implementation. Include deployment context (gunicorn timeout, etc.).
**Opus never implements:** Always dispatch a subagent, even for trivial tasks. Opus holds the steering wheel, not the wrench.
+
**Per-wiki DBs** (`/srv/data/wikis/{slug}/wiki.db`): Otterwiki's own SQLAlchemy schema. Tables: `preferences`, `user`, drafts. Code: `app/resolver.py` (`_init_wiki_db`). Initialized on first access (idempotent).
-
**Question the premise:** When a finding says X is slow, ask whether X should exist at all before optimizing. The bcrypt linear scan fix was "add a prefix column" when the answer was "don't use bcrypt for API tokens."
+
These are NOT the same schema. Code that writes to one does not affect the other.
**Otterwiki config override:** `update_app_config()` loads DB preferences and overwrites Flask config. DB wins over settings.cfg. Always seed values via `_init_wiki_db()`.
+
Three MCP connections. Do NOT confuse them.
-
**Read memories first:** Read MEMORY.md and Implementation_Workflow wiki page before dispatching any agents. Create full task list before launching first agent.
-
-
## Project Context
-
-
### Per-Wiki SQLite DB (COMPLETED)
-
-
Each wiki gets `/srv/data/wikis/{slug}/wiki.db`. Resolver swaps DB per-request. `_init_wiki_db()` seeds SITE_NAME, access levels, AUTH_METHOD, schema version.
+
- **dev-wiki** (`mcp__dev-wiki__*`) = dev.robot.wtf — platform dev instance
+
- **thirdgulfwar** (`mcp__thirdgulfwar__*`) = 3gw.robot.wtf — research wiki (LXC/Caddy)
+
- **claude_ai_Third_Gulf_War_research_wiki** — same as thirdgulfwar, via Claude.ai connector
-
### Cold Start / Performance
+
### mcp-auth.md (scope: mcp)
-
Lambda cold starts: ~4.5s mean (512MB, Python 3.12). .pyc files make it WORSE (+700ms from extra decompression). CDN caching is the path forward, not Lambda optimization.
+
`MultiAuth` composes `InMemoryOAuthProvider` (OAuth 2.1 for Claude.ai) + `StaticTokenVerifier` (bearer token for Claude Code). OAuth is the transport layer — Caddy basic auth on `/authorize*` is the actual gate. Tokens are in-memory; server restart forces re-auth.
-
### Shared Worktree Trial
+
Key gotchas: Claude.ai does NOT support bearer tokens. DCR disabled by default. Claude.ai URL must include `/mcp` path. `StaticTokenVerifier` (not `DebugTokenVerifier`) for bearer fallback.
-
Trial file-level parallelism: multiple agents writing different files in a shared worktree. Use `EnterWorktree` to create shared worktree, dispatch agents to same path with assigned files.
- **To-Do page** in dev wiki is the authoritative task tracker (supersedes Tasks/ pages)
-
- **Implementation Workflow** at [[Design/Implementation_Workflow]]
-
- **OWASP Audit** at [[Security/OWASP_2025_Audit]]
+
No standing "Fix" task. Fix tasks created only if Loop Check determines they're needed. Loop Check tasks completed by the orchestrator, not a subagent.