althing-chamber: add valkey for Phase 3.1 cross-process streaming

Phase 3.1 closes the cross-process gap the Phase 3 smoke surfaced —
streaming events (msg_start/thinking/delta/complete/curated) flow
from agent-runner → chamber via valkey pub/sub rather than the
SQLite bridge (too high-volume + ephemeral for the DB).

New service: `althing-valkey` (stock `valkey/valkey:8-alpine`).
Internal-only — no exposed port, no volume. chamber + agent-runner
reach via docker DNS at `valkey:6379` on the compose default
network. healthcheck via `valkey-cli ping` (5s interval). chamber
+ agent-runner gain `depends_on: valkey: service_healthy` so the
bridge is up before either side starts publishing or subscribing.

Forseti unchanged — never publishes Phase 3 events.

Operational properties (per forseti's deployment notes):
  - Mixed-state safe at every step. Missing valkey.url config key
    → chamber + runner stay on v3.0 / Phase 2 equivalent paths.
  - Backward path is single config-key delete + restart.
  - streaming_enabled: true (set on agent-runner 2026-05-17) is
    unaffected by this change.

README's services table + playbook header + verify section all
extended to reflect the four-service shape. Forseti's contract
at vh/althing:docs/contracts/phase3_1_valkey_bridge.contract.md
carries the wire-protocol spec.
This commit is contained in:
vh
2026-05-17 08:36:46 -07:00
parent 59899e4e0f
commit 5704fbb08f
3 changed files with 61 additions and 23 deletions
+10 -4
View File
@@ -2,14 +2,16 @@
# Docker host following the PFI /opt/docker/ convention (ana-docker by
# default, but the playbook works against any host with Docker in place).
#
# Brings up THREE compose services from a single image:
# Brings up FOUR compose services:
# althing-chamber — FastAPI/HTMX web UI, port 7881 host → 8000 container
# althing-forseti — moderator daemon, no port
# althing-agent-runner — Phase 2 worldtree-driver dispatcher, no port
# althing-valkey — Phase 3.1 valkey 8 alpine, pub/sub bridge (internal only)
#
# All three processes share the SQLite store via the same bind-mount under
# /opt/docker/conf/althing-chamber/data. eventbus.bridge_from_db is the
# cross-process glue.
# The three althing services use the same image (built from vh/althing);
# valkey is a stock upstream image. SQLite-backed state shares between the
# three althing services via the bind-mount under /opt/docker/conf/althing-chamber/data;
# streaming events ride pub/sub on the docker default network via valkey.
#
# Idempotent: rerunning is safe. Creates-gates skip work that's already
# done; `docker compose up -d` is itself idempotent (no restart unless
@@ -139,3 +141,7 @@ verify:
- name: agent-runner container running
shell: docker ps --filter name=^/althing-agent-runner$ --format '{{.Status}}' | grep -q '^Up'
changed_when: "false"
- name: valkey container running + healthy
shell: docker ps --filter name=^/althing-valkey$ --format '{{.Status}}' | grep -q 'healthy'
changed_when: "false"