# Backend bootstrap — initializing a suitable graph backend

The praxis skills run **without any backend**: filesystem-fallback is a designed, first-class
mode. Initialize a backend only if you want the graph-backed features — coverage grids, active
swarm state, bridge consultation, and cross-session audit persistence.

Throughout the skill bodies, `<praxis-backend>` names the root of whatever backend you
initialize. If none exists locally, bootstrap one as follows.

## 1. Choose and initialize the root

```
mkdir praxis-backend && cd praxis-backend
py -m venv .venv          # Windows (never bare `python` — Store-stub trap)
python3 -m venv .venv     # macOS / Linux
```

Convention the skills assume (so their auto-start and probe steps work unchanged):
- server entrypoint at `<praxis-backend>/server.py`
- dedicated interpreter at `<praxis-backend>/.venv/Scripts/python.exe` (Windows) or
  `<praxis-backend>/.venv/bin/python` (macOS/Linux) — launch is
  `.venv/Scripts/python.exe server.py` / `.venv/bin/python server.py` respectively
- HTTP on `http://localhost:8080`

**Port note:** the skills probe `:8080` by default. If 8080 is already occupied on your
machine, run the backend on another port and adjust the port in the skills' health-probe and
auto-start lines to match. The collision failure mode is loud (a bind error at startup),
never silent — but there is no environment-variable override today; the port lives in the
skill text.

## 2. The contract a "suitable" backend satisfies

Any server that answers these routes with these minimal shapes qualifies. Field-level
graceful degradation is built into the skills: empty-but-schema-valid responses render as
honest empty states, never as errors.

| Route | Method | Minimal conforming response |
|---|---|---|
| `/api/health` | GET | `{"status": "healthy"}` |
| `/api/search?q=&scope=nodes&limit=` | GET | `[]` or `{"nodes": []}` — rows are `{id, graph_id, name}` |
| `/api/megapraxis/mgs_coverage?cwd=` | GET | `{"version":"1","layers":{"meta":[],"genesis":[],"shadow":[],"mgs":[]},"totals":{"total":0,"per_layer":{"meta":0,"genesis":0,"shadow":0,"mgs":0},"unclassified":0,"dark":0},"tarski_unclassified":[]}` |
| `/api/megapraxis/agents_coverage?cwd=` | GET | same shape, agent rows |
| `/api/megapraxis/verify_completeness?cwd=` | GET | `{"converge":{"verdict":"incomplete","decidable_gaps":0,"tarski_acknowledged":true}}` (honest verdict while empty) |
| `/api/megapraxis/swarms_active?cwd=` | GET | `{"active":[],"methodology_active":[],"recommended":[],"total_scanned":0}` |
| `/api/nodes/<id>` | GET | node row JSON, or a JSON 404 |
| node create/update | POST/PUT | persist name + position; audit records are **name-encoded** (`SwarmInvocation::…`, `Contribution::…`, `Bridge::…` — encodings documented in the skill bodies) |

Optional richest tier: a stdio MCP server exposing `megapraxis_boot`, the coverage tools, and
node CRUD. Without MCP the skills fall back to HTTP; without HTTP, to filesystem. Every tier
is a designed mode, not an error.

## 3. Escalation path

- **Tier 0 — no backend.** Skills fully usable: deterministic disk scans, briefing contract intact.
  Coverage grids and swarm state are omitted with an explicit one-line footer.
- **Tier 1 — minimal stub.** A ~100-line HTTP server returning the shapes above. The skills'
  health and auto-start probes succeed, and HTTP consumers (exporters, ops) work against it.
  Note honestly: the skills' own graph-backed rendering is gated on the optional MCP layer,
  not on HTTP — with a stub but no MCP server, the briefing stays in filesystem mode by design.
  A stub that persists name-encoded nodes to SQLite already supports the audit trail and
  bridge manifest for HTTP consumers.
- **Tier 2 — full knowledge-graph server.** Real search, node CRUD, layer classification, and the
  megapraxis routes computing live coverage. This is what the origin system (Pharosiraptor, a
  self-evolving knowledge-graph platform) provides; any equivalent works — the routes above are
  the entire coupling surface.

## 4. Verify your bootstrap

```
curl -s http://localhost:8080/api/health
```

must return `{"status": "healthy", ...}`. Then invoke `/megapraxis`. The briefing footer flips
from `_via: filesystem_` to `_via: graph_` (or a hybrid) only once an MCP server exposing
`megapraxis_boot` is registered (Tier 2 with MCP); with an HTTP-only backend the footer honestly
stays `_via: filesystem_` while health/auto-start and HTTP consumers use your server.
