diff --git a/README.md b/README.md index cc484c2c..09aab8c0 100644 --- a/README.md +++ b/README.md @@ -99,12 +99,16 @@ Useful variants: .\tools\epiphany_local_run.ps1 -Mode status .\tools\epiphany_local_run.ps1 -Mode plan .\tools\epiphany_local_run.ps1 -Mode run -MaxSteps 4 +.\tools\epiphany_local_run.ps1 -Mode mvp -FaceInput "Wake the local swarm and report through Face." -MaxSteps 4 .\tools\epiphany_local_run.ps1 -Mode status -ThreadId -Workspace E:\Projects\SomeRepo ``` `run` is the live coordinator loop. It also builds `epiphany-openai-runtime` and -uses the retained Codex auth/model transport spine. `status`, `plan`, and -`smoke` do not spend model calls. +uses the retained Codex auth/model transport spine. `mvp` is the local product +cycle: project Face's character turn, write a Face/Aquarium bubble, run the +bridge-equipped coordinator loop with auto-tools, then run heartbeat sleep/dream +maintenance. `status`, `plan`, and `smoke` do not spend model calls; `run` and +`mvp` do. ## Where This Leads diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 7eef4c9a..e322574f 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -33,7 +33,7 @@ remembers doctrine; the branch remembers the blade. ## Current Orientation - Do not copy exact branch or HEAD from this note. Run `git status --short --branch` and `git log --oneline -5`. -- The repo now has a one-command local operator path: `.\tools\epiphany_local_run.ps1`. Default mode is `smoke`; it builds the retained Codex app-server compatibility edge, builds native Epiphany operator binaries, runs the coordinator smoke, and writes launcher artifacts under `.epiphany-run/` plus coordinator artifacts under `.epiphany-dogfood/`. `-Mode status` is now Epiphany-native: it builds only Epiphany operator binaries, reads `state/thread-state.msgpack` when present, derives status through `epiphany-core`, and does not start or require `codex-app-server`. Use `-Mode plan` or `-Mode run -MaxSteps 4` for the bridge-equipped coordinator entrypoints; add `-ThreadId ` and `-Workspace ` to inspect or continue an existing thread. `status`, `plan`, and `smoke` do not spend model calls; `run` builds and uses `epiphany-openai-runtime`. +- The repo now has a one-command local operator path: `.\tools\epiphany_local_run.ps1`. Default mode is `smoke`; it builds the retained Codex app-server compatibility edge, builds native Epiphany operator binaries, runs the coordinator smoke, and writes launcher artifacts under `.epiphany-run/` plus coordinator artifacts under `.epiphany-dogfood/`. `-Mode status` is now Epiphany-native: it builds only Epiphany operator binaries, reads `state/thread-state.msgpack` when present, derives status through `epiphany-core`, and does not start or require `codex-app-server`. Use `-Mode plan` or `-Mode run -MaxSteps 4` for the raw bridge-equipped coordinator entrypoints; use `-Mode mvp -FaceInput "" -MaxSteps 4` for the local product cycle that projects Face's character turn, writes a Face/Aquarium bubble, runs the coordinator with auto-tools, then runs heartbeat sleep/dream maintenance. Add `-ThreadId ` and `-Workspace ` to inspect or continue an existing thread. `status`, `plan`, and `smoke` do not spend model calls; `run` and `mvp` build and use `epiphany-openai-runtime`. - Local operator runs now write typed CultMesh intent/receipt documents to `.epiphany-run/cultmesh/operator-runs.ccmp` through `epiphany-operator-run`. The wrapper writes intent before acting and a completion receipt after success; this is the local consent/trace rail, not a hidden scheduler queue. - Status-mode local runs now also write a native CultMesh operator snapshot to `.epiphany-run/cultmesh/operator-snapshots.ccmp` through `epiphany-operator-snapshot`. That snapshot distills the operator-safe MVP status artifact into typed fields such as thread id, state status, coordinator action, CRRC action, reorient action, available actions, and artifact refs; it does not preserve the raw JSON status blob as internal state. - `epiphany-mvp-status --source native` is the current provider-neutral status boundary. It projects scene, pressure, jobs, roles, planning, reorient, CRRC, and coordinator status from native core surfaces and returns provider/runtime worker results as `backendMissing` placeholders instead of asking Codex for model-worker state. Keep future pluggable model-provider work behind launch/result/runtime documents; do not let provider choice leak into status, prompt authority, scheduler policy, or durable `EpiphanyThreadState`. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 454a5860..1365c076 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index 66ad882e..9d8726e8 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -476,8 +476,12 @@ current_status: Runnability now has a thin operator entrypoint: `tools/epiphany_local_run.ps1` builds the retained Codex app-server compatibility edge, builds native Epiphany operator binaries, runs status, - plan, smoke, or live coordinator modes, and writes launcher artifacts under - `.epiphany-run/` plus coordinator evidence under `.epiphany-dogfood/`. + plan, smoke, live coordinator, or local MVP product-cycle modes, and writes + launcher artifacts under `.epiphany-run/` plus coordinator evidence under + `.epiphany-dogfood/`. `-Mode mvp` is the current Face-front-door wrapper: + it projects a typed Face character turn, writes a local Face/Aquarium + bubble, runs the bridge-equipped coordinator loop with auto-tools, then + invokes heartbeat sleep/dream maintenance unless explicitly skipped. This is scaffolding over the current compatibility shell, not a new policy owner. Native CultMesh operator status is landed too: `epiphany-core` can write, diff --git a/tools/epiphany_local_run.ps1 b/tools/epiphany_local_run.ps1 index 223aa881..f31ce4f3 100644 --- a/tools/epiphany_local_run.ps1 +++ b/tools/epiphany_local_run.ps1 @@ -1,5 +1,5 @@ param( - [ValidateSet("status", "plan", "smoke", "run")] + [ValidateSet("status", "plan", "smoke", "run", "mvp")] [string]$Mode = "smoke", [string]$Root = (Resolve-Path ".").Path, [string]$Workspace = "", @@ -8,9 +8,11 @@ param( [string]$TargetDir = "C:\Users\Meta\.cargo-target-codex", [int]$MaxSteps = 4, [int]$TimeoutSeconds = 240, + [string]$FaceInput = "", [switch]$SkipBuild, [switch]$AutoReview, - [switch]$NoEphemeral + [switch]$NoEphemeral, + [switch]$SkipSleep ) $ErrorActionPreference = "Stop" @@ -80,10 +82,16 @@ $coordinatorExe = Join-Path $TargetDir "debug\epiphany-mvp-coordinator.exe" $coordinatorSmokeExe = Join-Path $TargetDir "debug\epiphany-mvp-coordinator-smoke.exe" $modelRuntimeExe = Join-Path $TargetDir "debug\epiphany-model-runtime.exe" $toolAdapterExe = Join-Path $TargetDir "debug\epiphany-tool-codex-mcp-spine.exe" +$heartbeatExe = Join-Path $TargetDir "debug\epiphany-heartbeat-store.exe" +$faceExe = Join-Path $TargetDir "debug\epiphany-face-discord.exe" +$characterLoopExe = Join-Path $TargetDir "debug\epiphany-character-loop.exe" $modelProvider = "openai-codex" $operatorRunStore = Join-Path $Root ".epiphany-run\cultmesh\operator-runs.ccmp" $operatorSnapshotStore = Join-Path $Root ".epiphany-run\cultmesh\operator-snapshots.ccmp" $operatorSnapshotId = "$runId-status" +$agentStore = Join-Path $Root "state\agents.msgpack" +$heartbeatStore = Join-Path $Root "state\agent-heartbeats.msgpack" +$liveRuntimeMode = @("run", "mvp") -contains $Mode if (-not $SkipBuild) { if ($Mode -ne "status") { @@ -109,6 +117,7 @@ if (-not $SkipBuild) { "--bin", "epiphany-mvp-coordinator-smoke", "--bin", "epiphany-heartbeat-store", "--bin", "epiphany-face-discord", + "--bin", "epiphany-character-loop", "--bin", "epiphany-agent-telemetry", "--bin", "epiphany-void-memory" ) ` @@ -116,7 +125,7 @@ if (-not $SkipBuild) { -StdoutPath (Join-Path $artifactRoot "build-epiphany-core.stdout.log") ` -StderrPath (Join-Path $artifactRoot "build-epiphany-core.stderr.log") - if ($Mode -eq "run") { + if ($liveRuntimeMode) { Invoke-Checked ` -Label "build Epiphany model runtime" ` -FilePath "cargo" ` @@ -138,6 +147,12 @@ $requiredBinaries = @($statusExe, $operatorRunExe, $operatorSnapshotExe) if ($Mode -ne "status") { $requiredBinaries += @($codexAppServer, $coordinatorExe) } +if ($liveRuntimeMode) { + $requiredBinaries += @($modelRuntimeExe, $toolAdapterExe) +} +if ($Mode -eq "mvp") { + $requiredBinaries += @($heartbeatExe, $faceExe, $characterLoopExe) +} foreach ($required in $requiredBinaries) { if (-not (Test-Path -LiteralPath $required)) { throw "required binary not found: $required" @@ -259,14 +274,49 @@ if ($Mode -eq "smoke") { -StderrPath (Join-Path $artifactRoot "coordinator-smoke.stderr.log") } -if ($Mode -eq "run") { +if ($Mode -eq "mvp") { + if ($FaceInput.Trim() -eq "") { + $FaceInput = "Operator requested the local Epiphany MVP cycle. Face should surface the swarm state, then the coordinator may continue bounded work and sleep afterward." + } + $faceArtifactDir = Join-Path $dogfoodRoot "face" + $characterArtifactDir = Join-Path $dogfoodRoot "character-loop" + $faceBubblePath = Join-Path $artifactRoot "face-bubble.stdout.json" + $characterTurnPath = Join-Path $artifactRoot "face-character-turn.stdout.json" + Invoke-Checked ` + -Label "project Face character turn" ` + -FilePath $characterLoopExe ` + -Arguments @( + "turn", + "--role", "face", + "--agent-store", $agentStore, + "--artifact-dir", $characterArtifactDir, + "--stimulus", $FaceInput, + "--source", "epiphany/local-mvp", + "--mode", "local-mvp-front-door", + "--status", "ready", + "--mood", "attentive" + ) ` + -WorkingDirectory $Root ` + -StdoutPath $characterTurnPath ` + -StderrPath (Join-Path $artifactRoot "face-character-turn.stderr.log") + Invoke-Checked ` + -Label "write Face Aquarium bubble" ` + -FilePath $faceExe ` + -Arguments @( + "bubble", + "--artifact-dir", $faceArtifactDir, + "--content", $FaceInput, + "--source", "epiphany/local-mvp", + "--status", "ready", + "--mood", "attentive" + ) ` + -WorkingDirectory $Root ` + -StdoutPath $faceBubblePath ` + -StderrPath (Join-Path $artifactRoot "face-bubble.stderr.log") +} + +if ($liveRuntimeMode) { $resultPath = Join-Path $artifactRoot "coordinator-run.stdout.json" - if (-not (Test-Path -LiteralPath $modelRuntimeExe)) { - throw "required runtime binary not found: $modelRuntimeExe" - } - if (-not (Test-Path -LiteralPath $toolAdapterExe)) { - throw "required tool adapter binary not found: $toolAdapterExe" - } $runArgs = @( "--app-server", $codexAppServer, "--model-runtime-bin", $modelRuntimeExe, @@ -295,6 +345,46 @@ if ($Mode -eq "run") { -StderrPath (Join-Path $artifactRoot "coordinator-run.stderr.log") } +if ($Mode -eq "mvp" -and -not $SkipSleep) { + $sleepArtifactDir = Join-Path $dogfoodRoot "sleep" + if (-not (Test-Path -LiteralPath $heartbeatStore)) { + Invoke-Checked ` + -Label "initialize heartbeat store" ` + -FilePath $heartbeatExe ` + -Arguments @( + "init", + "--store", $heartbeatStore + ) ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "heartbeat-init.stdout.json") ` + -StderrPath (Join-Path $artifactRoot "heartbeat-init.stderr.log") + } + Invoke-Checked ` + -Label "run sleep and dream routine" ` + -FilePath $heartbeatExe ` + -Arguments @( + "routine", + "--store", $heartbeatStore, + "--artifact-dir", $sleepArtifactDir, + "--agent-store", $agentStore, + "--source", "epiphany/local-mvp" + ) ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "sleep-routine.stdout.json") ` + -StderrPath (Join-Path $artifactRoot "sleep-routine.stderr.log") + Invoke-Checked ` + -Label "project heartbeat sleep status" ` + -FilePath $heartbeatExe ` + -Arguments @( + "status", + "--store", $heartbeatStore, + "--artifact-dir", $sleepArtifactDir + ) ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "sleep-status.stdout.json") ` + -StderrPath (Join-Path $artifactRoot "sleep-status.stderr.log") +} + $summary = @" # Epiphany Local Run @@ -315,11 +405,16 @@ $summary = @" - coordinatorBinary: $coordinatorExe - modelRuntimeBinary: $modelRuntimeExe - modelProvider: $modelProvider +- faceBinary: $faceExe +- characterLoopBinary: $characterLoopExe +- heartbeatBinary: $heartbeatExe This is an operator entrypoint over the current MVP shell. Status mode is Epiphany-native and does not start Codex app-server; coordinator plan/smoke/run modes still use the sealed Codex compatibility bridge until their provider -boundary is cut. +boundary is cut. MVP mode wraps that bridge-equipped coordinator loop in the +local product cycle: Face front door, bounded swarm work, then heartbeat +sleep/dream maintenance. "@ Set-Content -LiteralPath (Join-Path $artifactRoot "README.md") -Value $summary -Encoding UTF8