mavgpud.service, the Maven GPU supervisor, is an enabled systemd user unit that binds *:8080 and restarts on kill. The correx server wanted the same port, so qa-stack died with BindException and the QA stack never came up. Worse, qa-stack's --stop ran `fuser -k 8080/tcp`, which killed mavgpud rather than a correx server; systemd then restarted it straight into the port it had just freed, so it won the race every time. Moves the default to 8090 in the four places that have to agree: ServerConfig, ConfigLoader's fallback, the CLI's DEFAULT_PORT, and the TUI's -port flag. A mismatch between any two of them is a client that cannot find its own server. The machine-local halves are not in this diff and were applied on disk: `~/.config/correx/config.toml` pinned `port = 8080` explicitly, which overrides the code default, and `scripts/` is gitignored so qa-stack.sh's five references (including the --stop kill, now aimed at 8090) live only on this box. Verified live: the server binds 8090 and answers /health while mavgpud keeps 8080. Left open in #695: mavgpud also spawns a llama-server on :10000, which is qa-stack's router port, and qa-stack pkills that pattern. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5.7 KiB
Correx live-QA environment — bring-up runbook
The plans in docs/qa/QA-*.md cite observable signals (events, logs, files, TUI
renders). This runbook stands up the stack that produces them. Run it on a capable box
(JDK 21, Go ≥ 1.24, Docker, a GPU + GGUF model for any model-dependent plan).
Helper scripts live in scripts/qa/ (see scripts/qa/README.md).
Low-RAM note: a machine-local
~/.gradle/gradle.propertieson the dev box caps the Gradle/Kotlin heap (-Xmx768m,parallel=false) for a 1.9 GB machine. It is not committed. On a QA box with real RAM, delete it (or ignore it) so builds aren't throttled.
Prerequisites
- JDK 21 (
java -version→ 21). - Go ≥ 1.24 — the TUI builds via
GOTOOLCHAIN=auto(go.mod pinsgo 1.24.2); the toolchain auto-downloads if yourgois older. - Docker — only for SearXNG (research-workflow QA).
- llama-server binary + at least one GGUF model — for any model-dependent plan.
- (optional) an embedder model/endpoint — required for the architect-contradiction plan
and any L3-retrieval-dependent behavior (
[router.embedder] backend = "llamacpp").
1. Config
Correx reads ~/.config/correx/config.toml plus workflows/, prompts/, schemas/
alongside it. Stale copies cause silent bugs (BACKLOG ops note), so sync from the repo:
scripts/qa/sync-config.sh # copies examples/workflows + prompts + docs/schemas
# and seeds config.toml from docs/sample-config.toml IF ABSENT
Then edit ~/.config/correx/config.toml for the plan you're running:
- Model — pick ONE:
- Managed (
[[models]]+[models]): correx spawns llama-server at[models].host:port(default127.0.0.1:10000) and kills it on shutdown. Simplest. - Static (
[[providers]], typellamacpp,url): you run llama-server yourself. Use this for the llama-health plan so you can stop the server independently of correx.
- Managed (
[project] enabled = true— required for project memory + the architect-contradiction plan (it queries theproject:<repoRoot>L3 namespace written at session end).[router.embedder] backend = "llamacpp"(notnoop) — required wherever embeddings matter (architect contradiction, L3 retrieval).noopmakes every distance meaningless.[tools.research] enabled = true+searxng_url— for the research/egress plan.[health] enabled = true— for the llama-health plan; noteinterval_ms(probe cadence).
A [[artifacts]] entry must exist for every LLM-emitted artifact kind a workflow produces
(schemas under ~/.config/correx/schemas/). sync-config.sh copies the schemas; confirm the
[[artifacts]] table in config.toml references the kinds your workflow uses.
2. llama-server
- Managed: nothing to start — correx launches it. The health probe pings
http://<[models].host>:<[models].port>/health. - External/static: start your llama-server on the
urlhost:port; its/healthmust 2xx.llama-server -m ~/models/<model>.gguf --host 127.0.0.1 --port 10000
3. SearXNG (research-workflow QA only)
scripts/qa/searxng-up.sh # http://localhost:8888, JSON format enabled
# ... run research QA ...
scripts/qa/searxng-down.sh
Gotcha: SearXNG ships with only the
htmloutput format; the researchweb_searchneeds the JSON API.searxng-up.shwrites asettings.ymlenablingformats: [html, json]and mounts it. Without that,web_searchreturns nothing and the workflow stalls.
4. Start the server
./gradlew :apps:server:run # mainClass com.correx.apps.server.MainKt, listens on :8090
# or build a runnable dist once and reuse it:
./gradlew :apps:server:installDist
apps/server/build/install/server/bin/server
Gotcha: do not rebuild jars while the server JVM is running — lazy classloading breaks (
NoClassDefFoundError). Stop the server first, rebuild, restart.
5. Start the TUI
cd apps/tui-go
GOTOOLCHAIN=auto go build -o correx-tui .
./correx-tui -host localhost -port 8090 # flags default to localhost:8090
6. Evidence tools (what the plans cite)
| Source | Command / where |
|---|---|
| Event log (the truth) | ./gradlew :apps:cli:run --args="events <sessionId>" or GET /sessions/{id}/events |
| Deterministic replay | ./gradlew :apps:cli:run --args="replay <sessionId>" |
| System health | ./gradlew :apps:cli:run --args="health" |
| Server logs | stdout of :apps:server:run — MDC carries sessionId |
| Files on disk | e.g. <workspaceRoot>/.correx/project.toml (idea-promotion plan) |
| TUI render | the running correx-tui |
(Once :apps:cli:installDist is built, apps/cli/build/install/cli/bin/cli events <id> works too.)
Teardown
- Stop the server (Ctrl-C) — a managed
[[models]]llama-server is killed by the shutdown hook. scripts/qa/searxng-down.shif you started it.- External llama-server: stop it yourself.
Per-plan env matrix
| QA plan | model | embedder=llamacpp | SearXNG | project.enabled |
workspace .correx/ |
|---|---|---|---|---|---|
QA-research-egress |
yes (tool-calling) | no | yes | no | no |
QA-architect-contradiction |
yes | yes | no | yes | repo root, 2 sessions same process |
QA-llama-health-probe |
yes (static path to kill) | no | no | no | no |
QA-idea-promotion |
router only (or seed event) | no | no | no | yes (bound workspace) |
QA-reviewer-static-first |
yes | no | no | no | seed StaticFindingsRecordedEvent |
QA-brief-echo-gate |
yes (the prod candidate) | no | no | no | analyst brief with criteria |