From 6073d50cc3ef1be763bf82747010ee793eeeffac Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 21 May 2026 10:17:38 +0100 Subject: [PATCH] Add Epiphany local run entrypoint --- .gitignore | 1 + README.md | 25 ++++ notes/fresh-workspace-handoff.md | 1 + state/ledgers.msgpack | Bin 147094 -> 147460 bytes state/map.yaml | 9 +- tools/epiphany_local_run.ps1 | 228 +++++++++++++++++++++++++++++++ 6 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 tools/epiphany_local_run.ps1 diff --git a/.gitignore b/.gitignore index c0581326..da5c44da 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ apps/epiphany-gui/src-tauri/target/ .epiphany-heartbeats/ .epiphany-face/ .epiphany-rumination/ +.epiphany-run/ .voidbot/ state/agent-heartbeats.json state/*.msgpack.lock diff --git a/README.md b/README.md index 406d6d95..c1fce4b1 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,31 @@ Phase 1 through Phase 6 are landed enough for the current experiment. The open questions are now about observability, invalidation, coordination, authority, and safe capability growth, not whether typed state can exist at all. +## Run Locally + +The current one-command operator path is: + +```powershell +.\tools\epiphany_local_run.ps1 +``` + +Default mode is `smoke`: it builds the retained Codex app-server compatibility +edge, builds the native Epiphany operator binaries, runs the coordinator smoke, +and writes launcher artifacts under `.epiphany-run/` plus coordinator evidence +under `.epiphany-dogfood/`. + +Useful variants: + +```powershell +.\tools\epiphany_local_run.ps1 -Mode status +.\tools\epiphany_local_run.ps1 -Mode plan +.\tools\epiphany_local_run.ps1 -Mode run -MaxSteps 4 +``` + +`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. + ## Where This Leads The architectural goal is not one giant agent that does archaeology, design, diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index a0b06852..64d3537c 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -33,6 +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/`. Use `-Mode status`, `-Mode plan`, or `-Mode run -MaxSteps 4` for the other current entrypoints. `status`, `plan`, and `smoke` do not spend model calls; `run` builds and uses `epiphany-openai-runtime`. - The active foundation directive is now `notes/codex-starvation-and-cultnet-liberation-plan.md`. The previous Codex app-server control-plane rebuild made Epiphany less rotten inside Codex, but that is not the destination. Epiphany must become a native CultCache/CultNet runtime while remaining an honest modified Codex-derived backend for subscription auth/model use. Codex is a compatibility reliquary for OpenAI subscription auth and model transport, not the host brain and not a mask for impersonation. - `notes/codex-auth-spine-inventory.md` is the source-grounded keeper list for that reliquary. Corrected compliance invariant: Codex-compatible auth identity stays anchored in vendored Codex-derived auth machinery. `epiphany-openai-auth-spine` is now a thin Epiphany-named boundary over `codex-login`, not a clean-room clone of credential storage or token refresh. Codex apps, skills, marketplace, plugin UX, broad app-server workflow, and JSON-RPC sprawl remain cuttable because they are not subscription-auth legitimacy. - Edge JSON is allowed for schema description, hostile ingress before immediate typed parsing, sealed forensic artifacts, or named quarantine experiments. When both subsystems are ours, runtime data must remain typed CultCache documents and move over CultNet typed contracts. Generic `serde_json::Value` in worker launch/result/selfPatch/runtime flow is contamination until classified and replaced. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index b22e66fe3eeec98d6f316cb136f7c4430e1a24eb..6a6c051d37e2dc14a497ab8d0099290a3fc68d25 100644 GIT binary patch delta 375 zcmZ{gze>bF5XMO=|FjlYj)>hQCIJzAHa7IT*c!m%Nf4;ecv~aUrYD5%MTmj!Ta;(We~jFb-}a?g10URKli(jwQzMM zJx%uVbT?0u*;C%TIUI0~92}9fTd0MunVJkGl}rvzt72_aU>01BKnkOhnuaM3zXBkQ zhB-2T%9)8KpA*I0fuNbIp=gEV7LJJHH88EC6N_ey20YgbL?NVb z6F@$~{#>m5evEMZmu+EM2*r#*+Xo-i&ejLL@s$w{ElAd?vi4YJoTymoEVPRIIi5F+ j{0V5;TJKDTd(uyh|K*%U6%mhLvn1PzlI0M2|5tN;K2 diff --git a/state/map.yaml b/state/map.yaml index ff65d917..1fdd2972 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -450,4 +450,11 @@ current_status: model. The larger typed-view wall remains under judgment. The bridge still depends on vendored Codex for app-server protocol DTOs and absolute path validation, so the purification is not done. - next_action: Continue Codex starvation and CultNet liberation by cutting bridge-internal response/projection authority. Prioritize the next coordinator/view seam that still composes policy-shaped facts instead of merely loading host facts and projecting core surfaces; keep MCP/OpenAI JSON only at their true protocol/text edges. Do not add compatibility adapters unless they protect a named ownership invariant. + 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/`. + This is scaffolding over the current compatibility shell, not a new policy + owner. + next_action: Continue Codex starvation and CultNet liberation while preserving the working local run path. The next cut should make the same operator loop less dependent on Codex app-server JSON-RPC, not add another convenience throne beside it. diff --git a/tools/epiphany_local_run.ps1 b/tools/epiphany_local_run.ps1 new file mode 100644 index 00000000..f608c7ff --- /dev/null +++ b/tools/epiphany_local_run.ps1 @@ -0,0 +1,228 @@ +param( + [ValidateSet("status", "plan", "smoke", "run")] + [string]$Mode = "smoke", + [string]$Root = (Resolve-Path ".").Path, + [string]$CodexHome = "", + [string]$TargetDir = "C:\Users\Meta\.cargo-target-codex", + [int]$MaxSteps = 4, + [int]$TimeoutSeconds = 240, + [switch]$SkipBuild, + [switch]$AutoReview, + [switch]$NoEphemeral +) + +$ErrorActionPreference = "Stop" + +function Invoke-Checked { + param( + [string]$Label, + [string]$FilePath, + [string[]]$Arguments, + [string]$WorkingDirectory, + [string]$StdoutPath = "", + [string]$StderrPath = "" + ) + + Write-Host "==> $Label" + Push-Location -LiteralPath $WorkingDirectory + $previousErrorActionPreference = $ErrorActionPreference + try { + $ErrorActionPreference = "Continue" + if ($StdoutPath -ne "" -and $StderrPath -ne "") { + & $FilePath @Arguments 1> $StdoutPath 2> $StderrPath + } elseif ($StdoutPath -ne "") { + & $FilePath @Arguments 1> $StdoutPath + } elseif ($StderrPath -ne "") { + & $FilePath @Arguments 2> $StderrPath + } else { + & $FilePath @Arguments + } + $exitCode = $LASTEXITCODE + } finally { + $ErrorActionPreference = $previousErrorActionPreference + Pop-Location + } + if ($exitCode -ne 0) { + throw "$Label failed with exit code $exitCode" + } +} + +Set-Location -LiteralPath $Root +$Root = (Resolve-Path ".").Path +$env:CARGO_TARGET_DIR = $TargetDir + +if ($CodexHome -eq "") { + if ($env:CODEX_HOME) { + $CodexHome = $env:CODEX_HOME + } else { + $CodexHome = Join-Path $env:USERPROFILE ".codex" + } +} + +$runId = "local-" + (Get-Date -Format "yyyyMMdd-HHmmss") +$artifactRoot = Join-Path $Root ".epiphany-run\$runId" +$dogfoodRoot = Join-Path $Root ".epiphany-dogfood\$runId" +New-Item -ItemType Directory -Force -Path $artifactRoot | Out-Null +New-Item -ItemType Directory -Force -Path $dogfoodRoot | Out-Null + +$codexAppServer = Join-Path $TargetDir "debug\codex-app-server.exe" +$statusExe = Join-Path $TargetDir "debug\epiphany-mvp-status.exe" +$coordinatorExe = Join-Path $TargetDir "debug\epiphany-mvp-coordinator.exe" +$coordinatorSmokeExe = Join-Path $TargetDir "debug\epiphany-mvp-coordinator-smoke.exe" +$openaiRuntimeExe = Join-Path $TargetDir "debug\epiphany-openai-runtime.exe" + +if (-not $SkipBuild) { + Invoke-Checked ` + -Label "build Codex app-server compatibility organ" ` + -FilePath "cargo" ` + -Arguments @("build", "-p", "codex-app-server", "--manifest-path", ".\vendor\codex\codex-rs\Cargo.toml") ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "build-codex-app-server.stdout.log") ` + -StderrPath (Join-Path $artifactRoot "build-codex-app-server.stderr.log") + + Invoke-Checked ` + -Label "build Epiphany operator binaries" ` + -FilePath "cargo" ` + -Arguments @( + "build", + "--manifest-path", ".\epiphany-core\Cargo.toml", + "--bin", "epiphany-mvp-status", + "--bin", "epiphany-mvp-coordinator", + "--bin", "epiphany-mvp-coordinator-smoke", + "--bin", "epiphany-heartbeat-store", + "--bin", "epiphany-face-discord", + "--bin", "epiphany-agent-telemetry" + ) ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "build-epiphany-core.stdout.log") ` + -StderrPath (Join-Path $artifactRoot "build-epiphany-core.stderr.log") + + if ($Mode -eq "run") { + Invoke-Checked ` + -Label "build Epiphany OpenAI runtime" ` + -FilePath "cargo" ` + -Arguments @("build", "--manifest-path", ".\epiphany-openai-runtime\Cargo.toml", "--bin", "epiphany-openai-runtime") ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "build-openai-runtime.stdout.log") ` + -StderrPath (Join-Path $artifactRoot "build-openai-runtime.stderr.log") + } +} + +foreach ($required in @($codexAppServer, $statusExe, $coordinatorExe)) { + if (-not (Test-Path -LiteralPath $required)) { + throw "required binary not found: $required" + } +} + +$ephemeralArg = "--ephemeral" +if ($NoEphemeral) { + $ephemeralArg = "--no-ephemeral" +} + +if ($Mode -eq "status") { + $statusJson = Join-Path $artifactRoot "status.json" + Invoke-Checked ` + -Label "run operator status" ` + -FilePath $statusExe ` + -Arguments @( + "--app-server", $codexAppServer, + "--codex-home", $CodexHome, + "--cwd", $Root, + $ephemeralArg, + "--json", + "--result", $statusJson, + "--transcript", (Join-Path $artifactRoot "status-transcript.jsonl"), + "--stderr", (Join-Path $artifactRoot "status-app-server.stderr.log") + ) ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "status.stdout.json") ` + -StderrPath (Join-Path $artifactRoot "status.stderr.log") +} + +if ($Mode -eq "plan") { + Invoke-Checked ` + -Label "run coordinator plan" ` + -FilePath $coordinatorExe ` + -Arguments @( + "--app-server", $codexAppServer, + "--codex-home", $CodexHome, + "--cwd", $Root, + "--artifact-dir", (Join-Path $dogfoodRoot "coordinator"), + "--runtime-store", (Join-Path $dogfoodRoot "runtime-spine.msgpack"), + "--mode", "plan", + "--max-steps", "1", + "--timeout-seconds", "$TimeoutSeconds" + ) ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "coordinator-plan.stdout.json") ` + -StderrPath (Join-Path $artifactRoot "coordinator-plan.stderr.log") +} + +if ($Mode -eq "smoke") { + if (-not (Test-Path -LiteralPath $coordinatorSmokeExe)) { + throw "required binary not found: $coordinatorSmokeExe" + } + Invoke-Checked ` + -Label "run coordinator smoke" ` + -FilePath $coordinatorSmokeExe ` + -Arguments @( + "--app-server", $codexAppServer, + "--artifact-root", (Join-Path $dogfoodRoot "coordinator-smoke"), + "--coordinator-exe", $coordinatorExe + ) ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "coordinator-smoke.stdout.json") ` + -StderrPath (Join-Path $artifactRoot "coordinator-smoke.stderr.log") +} + +if ($Mode -eq "run") { + if (-not (Test-Path -LiteralPath $openaiRuntimeExe)) { + throw "required runtime binary not found: $openaiRuntimeExe" + } + $runArgs = @( + "--app-server", $codexAppServer, + "--openai-runtime-bin", $openaiRuntimeExe, + "--codex-home", $CodexHome, + "--cwd", $Root, + "--artifact-dir", (Join-Path $dogfoodRoot "coordinator"), + "--runtime-store", (Join-Path $dogfoodRoot "runtime-spine.msgpack"), + "--mode", "run", + "--max-steps", "$MaxSteps", + "--timeout-seconds", "$TimeoutSeconds" + ) + if ($AutoReview) { + $runArgs += "--auto-review" + } + Invoke-Checked ` + -Label "run coordinator loop" ` + -FilePath $coordinatorExe ` + -Arguments $runArgs ` + -WorkingDirectory $Root ` + -StdoutPath (Join-Path $artifactRoot "coordinator-run.stdout.json") ` + -StderrPath (Join-Path $artifactRoot "coordinator-run.stderr.log") +} + +$summary = @" +# Epiphany Local Run + +- mode: $Mode +- root: $Root +- codexHome: $CodexHome +- targetDir: $TargetDir +- artifactRoot: $artifactRoot +- dogfoodRoot: $dogfoodRoot +- codexAppServer: $codexAppServer +- statusBinary: $statusExe +- coordinatorBinary: $coordinatorExe +- openaiRuntimeBinary: $openaiRuntimeExe + +This is an operator entrypoint over the current compatibility shell. Codex +app-server remains the JSON-RPC edge for now; Epiphany state, heartbeat, role +memory, runtime-spine, and artifacts remain typed native surfaces behind it. +"@ +Set-Content -LiteralPath (Join-Path $artifactRoot "README.md") -Value $summary -Encoding UTF8 + +Write-Host "" +Write-Host "Epiphany local run complete." +Write-Host "Launcher artifacts: $artifactRoot" +Write-Host "Coordinator artifacts: $dogfoodRoot"