Backend (Go, in this commit):
- migration 029_memory_dream_usage: per (date, owner) counters for
tokens_in/out, jobs_started/succeeded/failed/circuit_broken
- DreamUsageStore + UsageGate (internal/messaging/dream_usage.go).
Gate inspects today's usage against new env knobs:
- SYNAPBUS_DREAM_RECENT_WINDOW (default 336h / 14d)
- SYNAPBUS_DREAM_DAILY_TOKEN_LIMIT_IN (default 1M)
- SYNAPBUS_DREAM_DAILY_TOKEN_LIMIT_OUT (default 200k)
- SYNAPBUS_DREAM_DAILY_JOB_LIMIT (default 100)
- Consolidator now bounds watermarks + core_rewrite eligibility by the
recency window. core_rewrite skipped for owners with no in-window
activity. ForceRun honors the breaker.
- Recency fallback in BuildContextPacket + memory_list_unprocessed now
accept RecentWindowDays so injection and dream queries see the same
14d slice.
- Prometheus metrics registered (internal/metrics/metrics.go):
synapbus_dream_jobs_total{owner,job_type,status},
synapbus_dream_tokens_total{owner,direction},
synapbus_dream_job_duration_seconds{owner,job_type},
synapbus_dream_circuit_broken_total{owner,reason},
synapbus_injection_packets_total{tool},
synapbus_injection_memories_per_packet{tool},
synapbus_injection_packet_chars{tool},
synapbus_injection_skipped_total{tool,reason}.
- deploy/kubic/deployment.yaml: liveness/readiness timeoutSeconds: 1→5
(root-causes the "connection refused" mcpproxy errors at 13:02 today —
/readyz occasionally exceeded 1s under dream-worker tick load, so the
pod fell out of the Service endpoints intermittently).
Dream-claude agent (Python, in /dream-agent/):
- dream_runner.py uses claude-agent-sdk 0.1.48 to drive Claude Code
against SynapBus's MCP server. MCP transport carries
Authorization: Bearer <api_key> AND X-Synapbus-Dispatch-Token from env
via the SDK's McpHttpServerConfig.headers field — confirmed supported.
- Tools restricted via allowed_tools to mcp__synapbus__memory_*.
- Final JSON envelope reports tokens_in/out so harness.Usage stays
populated and the circuit breaker can count consumption.
- Dockerfile builds linux/amd64 at 189 MB, mirroring searcher's
agents/universal recipe.
- k8s-job-template.yaml: backoffLimit 0, ttl 600s, 512Mi/1CPU,
Anthropic credentials via secret-ref.
Grafana dashboard (deploy/kubic/grafana/):
- dream-dashboard.json — 14 panels across 5 rows (dream activity,
token usage vs limit, circuit breaker, injection layer, MCP
transport health), all templated to ${DS_PROMETHEUS}.
- import.sh: resolves the cluster's Prometheus DS uid and POSTs the
dashboard via Grafana API.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SynapBus on kubic
Plain Kubernetes manifests for the kubic single-node MicroK8s cluster
(kubic.home.arpa). No Helm — the image is built locally, imported directly
into MicroK8s containerd, and rolled with kubectl set image.
Files
| File | Purpose |
|---|---|
namespace.yaml |
synapbus namespace |
pvc.yaml |
2 Gi PVC on microk8s-hostpath for /data (DB + WAL + attachments + HNSW index) |
secret.example.yaml |
Template for synapbus-secrets (OpenAI/Gemini keys, mounted via envFrom) |
deployment.yaml |
Single replica, docker.io/library/synapbus:vX.Y.Z-amd64, imagePullPolicy: IfNotPresent (image is pre-loaded into containerd) |
service.yaml |
NodePort 30088 on port 8080 |
otel-collector.yaml |
OpenTelemetry collector for traces/metrics |
Initial install
kubectl apply -f deploy/kubic/namespace.yaml
kubectl apply -f deploy/kubic/pvc.yaml
# Edit secret.example.yaml first — never commit real keys.
kubectl apply -f deploy/kubic/secret.example.yaml
kubectl apply -f deploy/kubic/service.yaml
kubectl apply -f deploy/kubic/deployment.yaml
Releasing a new version
scripts/deploy-kubic.sh v0.17.0
The script:
docker buildx build --platform linux/amd64with the version baked in.docker saveto a tarball.scptokubic.home.arpa.ssh kubic 'sudo microk8s ctr image import …'(loads the image into the in-cluster containerd registry — the image is not pushed to a remote registry).kubectl set image deploy/synapbus synapbus=docker.io/library/synapbus:vX.Y.Z-amd64.kubectl rollout status …and a/healthzsmoke test.
The docker.io/library/ prefix is required because that's how containerd
resolves image references that don't specify a registry — synapbus:v…
written into the deployment is normalised to docker.io/library/synapbus:v…
on the node.
Why no Helm?
The original chart under deploy/helm/ (since deleted) was used for the very
first install (Mar 2026) and then went into a failed state when someone
ran kubectl set image for a hotfix; subsequent helm upgrade attempts hit
server-side-apply ownership conflicts. Rather than reconcile, we now own the
manifests directly. The deploy flow is simple enough that templating buys
nothing.
Backups
Before any version that touches schema, snapshot /data:
kubectl exec -n synapbus deploy/synapbus -- \
tar -C /data -cf - synapbus.db synapbus.db-shm synapbus.db-wal vapid_keys.json \
| tar -xf - -C "$HOME/synapbus-backups/$(date -u +%Y%m%dT%H%M%SZ)/"
Then sqlite3 synapbus.db 'PRAGMA wal_checkpoint(TRUNCATE); PRAGMA integrity_check;'
to fold the WAL into the main file and verify integrity before archiving.