From 4034aab1d1aa59c22640e39015853b5be3fadbf8 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 20 May 2026 21:06:13 +0100 Subject: [PATCH] Start Bifrost local stack with VoidBot --- .env.example | 2 + notes/fresh-workspace-handoff.md | 1 + notes/voidbot-current-system-map.md | 1 + scripts/start-voidbot-stack.ps1 | 67 +++++++++++++++++++++++++++++ state/evidence.jsonl | 1 + state/map.yaml | 1 + 6 files changed, 73 insertions(+) diff --git a/.env.example b/.env.example index 40a10e8..3aca350 100644 --- a/.env.example +++ b/.env.example @@ -74,6 +74,8 @@ REPO_FACE_HEARTBEAT_INTERVAL_MINUTES=15 REPO_FACE_HEARTBEAT_MAX_JOBS_PER_TICK=2 REPO_FACE_HEARTBEAT_DEFAULT_CHANNEL_ID= EPIPHANY_AGENT_ROOT=E:/Projects/EpiphanyAgent +BIFROST_ROOT=E:/Projects/Bifrost +BIFROST_HEALTH_URL=http://127.0.0.1:5080/healthz INDEX_ALL_CHANNELS=false INDEXED_CHANNEL_IDS= EXCLUDED_CHANNEL_IDS= diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 7129042..f8d68dd 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -34,6 +34,7 @@ Git history and smoke artifacts carry routine proof. `state/evidence.jsonl` shou - `scripts/simulate-void-mood.mjs` owns typed sleep/speaking-pressure over `.voidbot/private/void-self-state.cc`. During sleep, it invokes typed memory maintenance once per nap unless that nap already completed a pass; use `--skip-memory-maintenance` for smoke runs that must not call Codex. - `npm run moderation:memory-maintenance:sleep-fixture` now proves the non-skip sleep path without spending a live model call: it seeds a temporary `.cc`, forces mood drift through sleep maintenance, uses a fake Codex child to propose `apply_memory_distillation`, and verifies short-term residue is gone while the durable memory keeps subject, claim, tension, action implication, and anchor. - The live local pulse is now one hidden scheduled task: `GameCult Local Orchestrator`. It invokes Bifrost dispatch, repo Face CTB heartbeats, Void mood drift, Void moderation rumination, and the operations watchdog with one lock, one status surface, per-organ logs, and per-organ timeouts. The old per-organ tasks are disabled and should remain disabled unless testing one organ in isolation. +- `scripts/start-voidbot-stack.ps1` now treats the local Bifrost container stack as a startup dependency. It reads `BIFROST_ROOT` and `BIFROST_HEALTH_URL`, runs `E:\Projects\Bifrost\compose.local.yaml` when the health endpoint is down, and records the result under `runtime-stack.json` as `bifrost`. - `npm run moderation:rumination:fixture` proves the non-skip typed rumination branch without spending a live model call: it seeds a temporary `.cc`, routes the runner through a fake Codex child, and verifies short-term memory, incubation, agency pressure, and candidate intervention proposals are parent-applied typed operations with no exact timestamp leakage in the prompt-facing context. - `npm run moderation:rumination:speech-fixture` proves queued speech has a parent-owned action loop: fake Codex queues one candidate with a delivery target, fake Discord send writes a receipt, and the parent runner marks the candidate spoken through typed state. The child prompt now forbids direct send-script calls. - The first live sleep-maintenance gate passed on real state. A manual typed nap ran `scripts/run-void-memory-maintenance.ps1`, consumed the scheduled rumination short-term memory with one `apply_memory_distillation` operation, and left `thoughtMemory.shortTerm` empty while preserving the durable identity seam with target, claim, tension, action implication, and anchors. diff --git a/notes/voidbot-current-system-map.md b/notes/voidbot-current-system-map.md index 9b47776..9fb88fc 100644 --- a/notes/voidbot-current-system-map.md +++ b/notes/voidbot-current-system-map.md @@ -110,6 +110,7 @@ This note is the source-grounded description of how the live VoidBot stack is sh - `scripts/start-voidbot-stack.ps1` - stack bootstrap, health checks, fresh build, stale-process cleanup, source-repo reconcile, bot/worker restart, runtime status emission. + - It now also ensures the local Bifrost Docker Compose stack is healthy through `BIFROST_ROOT` and `BIFROST_HEALTH_URL`, because VoidBot's repo Face proposal/article/comment and Discord persona crossing paths call Bifrost bridge/intake tooling. - `scripts/install-stack-startup-task.ps1` - installs the hidden logon task that runs `start-voidbot-stack.ps1` automatically after reboot or sign-in. - `scripts/check-voidbot-operations.ps1` diff --git a/scripts/start-voidbot-stack.ps1 b/scripts/start-voidbot-stack.ps1 index 75eed17..72c1193 100644 --- a/scripts/start-voidbot-stack.ps1 +++ b/scripts/start-voidbot-stack.ps1 @@ -120,6 +120,20 @@ function Test-JsonEndpoint { } } +function Test-HttpEndpoint { + param( + [Parameter(Mandatory = $true)] + [string] $Url + ) + + try { + & curl.exe -fsS --connect-timeout 5 --max-time 15 $Url *> $null + return ($LASTEXITCODE -eq 0) + } catch { + return $false + } +} + function Wait-Until { param( [Parameter(Mandatory = $true)] @@ -239,6 +253,52 @@ function Ensure-DockerOnPath { } -FailureMessage "Docker is installed but the daemon is not ready." -Attempts 45 -SleepSeconds 2 } +function Ensure-BifrostLocalStack { + param( + [Parameter(Mandatory = $true)] + [string] $BifrostRoot, + [Parameter(Mandatory = $true)] + [string] $HealthUrl + ) + + if (Test-HttpEndpoint -Url $HealthUrl) { + return @{ + root = $BifrostRoot + healthUrl = $HealthUrl + startedByScript = $false + healthy = $true + } + } + + if (-not (Test-Path $BifrostRoot)) { + throw "Bifrost root does not exist at $BifrostRoot." + } + + $composeFile = Join-Path $BifrostRoot "compose.local.yaml" + + if (-not (Test-Path $composeFile)) { + throw "Bifrost local compose file does not exist at $composeFile." + } + + Ensure-DockerOnPath + + & docker compose -f $composeFile --project-directory $BifrostRoot up -d + + if ($LASTEXITCODE -ne 0) { + throw "Docker Compose failed to start Bifrost." + } + + Wait-Until -Condition { Test-HttpEndpoint -Url $HealthUrl } -FailureMessage "Bifrost did not become reachable at $HealthUrl in time." -Attempts 45 -SleepSeconds 2 + + return @{ + root = $BifrostRoot + composeFile = $composeFile + healthUrl = $HealthUrl + startedByScript = $true + healthy = $true + } +} + function Ensure-Qdrant { param( [Parameter(Mandatory = $true)] @@ -496,6 +556,8 @@ $localLlmEnabled = if ($config.ContainsKey("ENABLED_PROVIDERS")) { $config["ENAB $localLlmBaseUrl = if ($config.ContainsKey("LOCAL_LLM_OLLAMA_BASE_URL")) { $config["LOCAL_LLM_OLLAMA_BASE_URL"] } else { "http://127.0.0.1:11434" } $localLlmModel = if ($config.ContainsKey("LOCAL_LLM_OLLAMA_MODEL")) { $config["LOCAL_LLM_OLLAMA_MODEL"] } else { "qwen3.5:9b" } $localLlmSocialReadModel = if ($config.ContainsKey("LOCAL_LLM_SOCIAL_READ_OLLAMA_MODEL") -and -not [string]::IsNullOrWhiteSpace($config["LOCAL_LLM_SOCIAL_READ_OLLAMA_MODEL"])) { $config["LOCAL_LLM_SOCIAL_READ_OLLAMA_MODEL"] } else { $localLlmModel } +$bifrostRoot = if ($config.ContainsKey("BIFROST_ROOT")) { [System.IO.Path]::GetFullPath($config["BIFROST_ROOT"]) } else { "E:\Projects\Bifrost" } +$bifrostHealthUrl = if ($config.ContainsKey("BIFROST_HEALTH_URL")) { $config["BIFROST_HEALTH_URL"] } else { "http://127.0.0.1:5080/healthz" } if ($stateStorageBackend -eq "postgres") { $status.stage = "postgres" @@ -569,6 +631,11 @@ if ($localLlmEnabled) { Write-StatusFile -Path $statusPath -Status $status } +$status.stage = "bifrost" +Write-StatusFile -Path $statusPath -Status $status +$status.bifrost = Ensure-BifrostLocalStack -BifrostRoot $bifrostRoot -HealthUrl $bifrostHealthUrl +Write-StatusFile -Path $statusPath -Status $status + $npmCommand = Get-Command npm.cmd -ErrorAction Stop $nodeCommand = Get-Command node.exe -ErrorAction Stop diff --git a/state/evidence.jsonl b/state/evidence.jsonl index 37d82ac..dec988f 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -202,3 +202,4 @@ {"ts":"2026-05-20T19:01:40Z","type":"implementation","status":"ok","note":"Repo Face heartbeats now carry jurisdiction-respect doctrine: Faces may comment across domains, but should route ownership to the steward Face such as Heimdall for auth, Bifrost for governed transport, Nibu for Aetheria lore, Void for GameCult website/heraldry, Aqua for AquaSynth, Mimir for realtime fusion, Epiphany for agent state, and Libby for CultNet/CultCache/CultMesh."} {"ts":"2026-05-20T19:09:28Z","type":"implementation","status":"ok","note":"Repo Face heartbeats and Void direct reply lanes now carry distilled Dan Harmon comedy/improv doctrine: accept the frame, add one honest character-specific turn, find status/vulnerability/false-authority charge, heighten with specificity, avoid dominance-weapon jokes, and leave before explaining."} {"ts":"2026-05-20T19:21:00Z","type":"implementation","status":"ok","note":"Ambient Discord mentions now route into CTB instead of direct provider jobs: repo Face mentions still enqueue pending Face obligations, ordinary Void mentions/DMs enqueue pending mentions for built-in void, the CTB scheduler pulls the mentioned agent forward, and Void moderation receives pending mention packets in its context."} +{"ts":"2026-05-20T20:04:40Z","type":"implementation","status":"ok","note":"VoidBot stack startup now treats local Bifrost as a dependency: scripts/start-voidbot-stack.ps1 checks BIFROST_HEALTH_URL, starts BIFROST_ROOT/compose.local.yaml when needed, records runtime-stack.json.bifrost, and a live startup run brought bifrost-web/bifrost-postgres up healthy before bot/worker readiness."} diff --git a/state/map.yaml b/state/map.yaml index 7282512..5238787 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -190,6 +190,7 @@ landed_baseline: - `npm run moderation:memory-lifecycle:fixture` verifies memory lifecycle flow: short-term promotion, durable revision, superseded-memory retirement, and crystallization into one active identity memory plus self-profile value. - The sleep-maintenance path has a model-branch fixture: `npm run moderation:memory-maintenance:sleep-fixture` seeds a temporary `.cc`, forces mood drift into sleep maintenance, routes the non-skip Codex branch through a fake child, and verifies short-term memory is consumed into one durable meaning-preserving record. - The local `GameCult Local Orchestrator` scheduled task is installed as the hidden one-minute pulse for Bifrost dispatch, repo Face CTB heartbeats, Void mood drift, Void moderation rumination, and the operations watchdog. It writes per-organ logs under `.voidbot/logs/orchestrator`, summary/status under `.voidbot/status/gamecult-orchestrator*.json`, freezes overlap with one orchestrator lock, and enforces per-organ timeouts so a hung child cannot occupy the whole clock forever. + - VoidBot stack startup now treats Bifrost's local Docker Compose stack as a dependency. `scripts/start-voidbot-stack.ps1` checks `BIFROST_HEALTH_URL`, runs `BIFROST_ROOT/compose.local.yaml` when needed, and records `runtime-stack.json.bifrost` before starting the bot and worker. - The typed rumination path now has a model-branch fixture: `npm run moderation:rumination:fixture` seeds a temporary `.cc`, routes the non-skip Codex branch through a fake child, and verifies short-term memory, incubation, agency-pressure, and candidate-intervention proposals cross only through parent-applied typed operations without leaking exact timestamps into the prompt-facing context. - The typed rumination speech path is parent-owned now. Candidate interventions can carry an optional delivery target; the child may queue candidates but must not call Discord send scripts. The parent runner delivers at most one newly queued deliverable candidate per pass, records a delivery receipt, and marks the candidate spoken through `mark_candidate_intervention_spoken`. `npm run moderation:rumination:speech-fixture` verifies this loop with fake Codex and fake Discord send helpers. - The live sleep-maintenance gate has passed once on real state. A manual typed nap triggered `scripts/run-void-memory-maintenance.ps1`, which consumed the scheduled rumination short-term memory with one `apply_memory_distillation` operation and left `thoughtMemory.shortTerm` empty while preserving the durable `identity_seam` target, claim, tension, action implication, and anchors.