2026-07-11 18:42:05 +01:00
# Native Coordinator Liberation Map
## Objective
Make `epiphany-mvp-coordinator` an Epiphany-native control loop. It must read
and mutate typed Epiphany state, launch and inspect runtime work, and accept or
refuse findings without sending `thread/epiphany/*` JSON-RPC requests through
Codex.
Codex remains the OpenAI authentication/model-transport bridge and may retain
legacy app-server wrappers for named Codex clients. It is not the coordinator's
nervous system.
## Current Mechanism
The coordinator is compiled from
`epiphany-core/src/bin/epiphany-mvp-coordinator.rs` , but starts a Codex app-server
process and uses `status_cli::AppServerClient` for the authoritative loop:
- state bootstrap and revision writes use `thread/epiphany/update`
- freshness and coordinator projections use `thread/epiphany/freshness` and
`thread/epiphany/view`
- specialist lifecycle uses `thread/epiphany/roleLaunch` ,
`thread/epiphany/roleResult` , and `thread/epiphany/roleAccept`
- recovery lifecycle uses `thread/epiphany/reorientLaunch` and
`thread/epiphany/reorientResult`
The typed machinery already exists below that shell:
- `epiphany-core/src/thread_state_store.rs` owns CultCache-backed typed thread
state persistence.
- `epiphany-core/src/runtime_spine.rs` owns typed job, launch, result, event, and
receipt persistence.
- `epiphany-core/src/agent_launch.rs` builds typed role and reorientation launch
documents.
- `epiphany-core/src/surfaces/role_result.rs` interprets typed findings and
constructs acceptance bundles.
- `epiphany-core/src/mind_gateway.rs` , `hands_gateway.rs` , and the receipt proof
machinery own admission, action, and verification contracts.
- `epiphany-codex-bridge/src/mutation_service.rs` currently composes much of
this policy behind an `EpiphanyMutationHost` , but its host contract still
assumes a Codex-hosted compatibility snapshot and persistence hook.
- `vendor/codex/codex-rs/app-server/src/codex_message_processor/
epiphany_mutation_routes.rs` is already mostly a transport shell over that
bridge service. It should become a compatibility caller of the native owner,
not the place where the owner remains hosted.
## Authority Map
### Owner
One Epiphany-native coordinator service owns the control decision and delegates
typed persistence to the thread-state store and runtime-spine.
### Inputs
- typed operator/coordinator intent
- CultCache-backed `EpiphanyThreadState`
- runtime-spine job, result, and receipt documents
- typed watcher, retrieval, token-pressure, and dynamic prompt context
- model events returned by the model-transport adapter
### Outputs
- revision-gated typed state updates
- typed runtime launch and interrupt receipts
- typed role/reorientation findings
- Mind review and state-commit receipts
- read-only typed coordinator, freshness, role, and recovery projections
### Derived State
JSON-RPC responses, app-server notifications, Aquarium panels, CLI JSON, TUI
rows, CultMesh mirrors, and operator summaries are projections. They do not own
lifecycle, scheduling, acceptance, prompt doctrine, or durable truth.
### Forbidden Writers
- `codex_message_processor.rs` and its route modules
- Codex thread/session prompt machinery
- JSON-RPC request/response types
- GUI/Aquarium clients
- CultMesh mirrors and status snapshots
- watcher or reorientation verdicts
- raw model or MCP JSON
Each may submit or translate a typed intent. None may preserve an independent
decision after the native owner responds.
### Shared Paths
Manual CLI actions, programmatic coordinator turns, heartbeat scheduling,
Aquarium actions, and legacy Codex JSON-RPC calls must use the same native
operations for:
1. state read/update
2. freshness and coordinator derivation
3. role/reorientation launch
4. result readback
5. accept/refuse
6. interrupt
### Deletion Line
Delete `status_cli::AppServerClient` from the coordinator control path. Delete
its direct `thread/epiphany/*` request construction. After the native loop is
proved, reduce Codex mutation routes to protocol parsing, native service calls,
response mapping, and compatibility notifications. Then remove bridge policy
that exists only to compensate for Codex-hosted state.
## Migration Order
This is one vertical ownership migration, landed in buildable cuts. No cut may
introduce a second authoritative store or a native/JSON-RPC mode flag.
1. Move route-independent mutation/launch/accept orchestration out of
`epiphany-codex-bridge` into an Epiphany-native service whose host ports are
typed state persistence, runtime-spine, clock, and context inputs. Preserve
the existing bridge service as a thin delegating compatibility wrapper.
2. Add native read operations for state, freshness, coordinator/role views, and
typed result readback over the same stores used by mutation operations.
3. Rewire `epiphany-mvp-coordinator` to the native service and remove
`AppServerClient` plus every `thread/epiphany/*` request from the binary.
4. Prove bootstrap, manual/programmatic launch, pending/completed result,
acceptance, refusal, interruption, and recovery against native stores.
5. Make Codex JSON-RPC routes delegate to the same service. Remove duplicated
route/bridge policy and mapper-only tests that no longer protect a boundary.
2026-07-11 19:17:58 +01:00
## Native Organ Boundary
The native service is a façade, not a new host brain. The first extraction
proved the authority direction but allowed `epiphany-core/src/coordinator_service.rs`
to grow to 1,122 lines, almost the same size as the 1,143-line bridge mutation
service it is starving. That shape is rejected. Do not continue pouring bridge
functions into one core file.
The native body must be split before further authority moves:
- coordinator state owner: CultCache thread-state load, revision gate,
validation, write, and changed-field report
- coordinator result reader: runtime-link selection, runtime-spine lifecycle,
typed finding interpretation, and result notes
- coordinator acceptance organ: completed-finding admission, launch-contract
proof checks, role/reorientation acceptance construction, receipt persistence,
proof enforcement, and Mind commit
- coordinator launch organ: typed dynamic context, launch document construction,
runtime-spine opening/interruption, and state linkage
- coordinator projection organ: freshness, role board, CRRC, and coordinator
views derived from typed inputs without persistence
- coordinator façade: narrow composition over those organs; no policy bodies,
protocol DTOs, JSON, or Codex host hooks
Each organ owns one invariant and must be testable against injected paths and
typed inputs without starting Codex. A source guard should fail if the façade
regrows policy bodies or if any native organ imports app-server protocol types.
2026-07-11 20:30:47 +01:00
Launch-context ownership is now native. `coordinator_launch_context` owns local
Verse context, memory-graph cuts, Hands consequence evidence, Soul/Modeling
work-loop telemetry, and bounded prompt rendering. The compatibility bridge's
`launch_context` module is only a re-export membrane. Coordinator rewiring must
use these same functions; a context-free launch is not an acceptable shortcut.
2026-07-11 20:35:05 +01:00
The coordinator façade now exposes typed `launch_job` and `accept_role`
actuators. `launch_job` composes native planning with the atomic launch commit;
`accept_role` loads the typed completed finding, builds and proof-checks the
Mind-gated acceptance, and atomically publishes state plus witnesses. Callers
must delegate to these methods rather than replaying their choreography. The
2026-07-11 20:39:28 +01:00
bridge supplies host state,
thread identity, reference turn, timestamp, and nonce to
`EpiphanyCoordinatorService::accept_role` , then maps the typed result to the
compatibility response. It no longer builds evidence packets, Soul verdicts,
proof sets, Mind receipts, or state commits. Reorientation acceptance is the
2026-07-11 20:44:05 +01:00
same shape: `accept_reorient` owns typed result admission, Continuity recovery
proof, Mind witness, and atomic state publication. The bridge delegates both
acceptance families and contains zero direct witness commits.
2026-07-11 20:35:05 +01:00
2026-07-11 19:40:04 +01:00
## Acceptance Transaction Wound
The compatibility bridge currently persists prerequisite receipts, writes
thread state, then writes the Mind state-commit receipt in a separate
runtime-spine store. If the final write fails, accepted durable state survives
without its promised commit witness. Moving that sequence into core unchanged
is forbidden.
Before final acceptance persistence moves, define one typed transaction law:
either co-locate state admission and its commit witness in one CultCache
transaction boundary, or persist a prepared acceptance transaction whose
recovery protocol can deterministically finish or refuse admission after
interruption. Best-effort rollback across two files is not atomicity. A negative
smoke must inject failure after prerequisite receipts and after state write and
prove no unwitnessed accepted state becomes authoritative.
2026-07-11 20:24:48 +01:00
## Launch Transaction Law
2026-07-11 20:16:28 +01:00
Launch planning now belongs to `coordinator_launch` : it validates the expected
thread revision, inspects the prior runtime binding, prepares the heartbeat
launch documents, and derives the new thread-state linkage without writing.
The Codex bridge is a compatibility actuator for that plan; it no longer owns
those policy decisions.
2026-07-11 20:24:48 +01:00
`commit_coordinator_job_launch` is the single launch publication owner. It
prepares runtime identity, session, job, opened event, worker request, optional
Research Substrate Gate grant, and linked thread state against one loaded
CultCache snapshot, then publishes the heterogeneous set in one atomic batch.
The compatibility bridge cannot write any member separately. Injected batch
refusal proves the prior snapshot survives with no job, worker request, grant,
or new state linkage. Rollback and reconciliation are not owners.
2026-07-11 20:16:28 +01:00
2026-07-11 18:42:05 +01:00
## Invariants
- There is one durable thread-state owner and one runtime lifecycle owner.
- Revision validation is identical for CLI, coordinator, heartbeat, Aquarium,
and compatibility JSON-RPC callers.
- A view or watcher verdict cannot launch or accept work.
- Raw JSON is parsed once at a hostile edge and does not cross native service
ports.
- Model transport cannot inject organ doctrine, scheduler decisions, or state
mutation policy.
- Compatibility wrappers cannot override or repair the native result after the
fact.
## Verification Layer
The proof must observe the stores and receipts where the invariant lives:
- unit tests for each native operation with injected state store, runtime
store, clock, and context inputs
- adjacent-operation smokes for launch -> result -> review -> state commit
- a native coordinator smoke with no app-server binary available
- a compatibility smoke proving JSON-RPC delegates to the same native result
- negative tests proving Codex routes cannot write around revision/admission
gates and the coordinator binary contains no `thread/epiphany/*` methods
The migration is not complete because the coordinator eventually converges on
the same state after an app-server round trip. The old path must be structurally
unable to decide the result.
2026-07-11 20:48:19 +01:00
Coordinator sight has crossed the boundary. `collect_coordinator_status` , role
result readback, and reorientation result readback now use the native status
projection over the shared thread/runtime CultCache store. The coordinator no
2026-07-11 20:50:51 +01:00
longer calls Codex for `view` , `roleResult` , or `reorientResult` .
Role mutation has now crossed too. `epiphany-mvp-coordinator` builds role launch
requests from native state plus the full native Verse/memory/work-loop context,
publishes them through `EpiphanyCoordinatorService::launch_job` , and dispatches
auto-review through `accept_role` . The role launch and role acceptance routes
2026-07-12 00:31:43 +01:00
are gone.
`epiphany-mvp-coordinator` is now fully native. Reorientation launch consumes
the typed native status decision, preserves native prompt context, and uses the
same atomic launch actuator. Bootstrap and supersession use typed state updates.
The binary starts no app-server, contains no production `thread/epiphany/*`
strings, and emits telemetry with `appServerCalls=0` . Its smoke harness no
longer builds or requires codex-app-server and passes cold, local bootstrap,
pressure, Hands gate, and real commit-receipt scenarios.
2026-07-12 00:35:15 +01:00
Role-board `authorityScopes` now publish typed capability identifiers such as
`epiphany.coordinator.role.launch` , `epiphany.coordinator.role.accept` , and
`epiphany.coordinator.reorient.result.read` . Source proof rejects slash-shaped
authority, and rendered native status contains no `thread/epiphany/*` scopes.
2026-07-12 00:41:05 +01:00
The remaining source vocabulary is classified. Active worker launch contracts
now describe typed coordinator capabilities and Mind-admitted `statePatch`
cargo. `epiphany-mvp-status` defaults to native state; its route calls exist only
behind explicit `--codex` compatibility. `epiphany-phase6-*-smoke` binaries are
compatibility contract probes, coordinator source occurrences are negative
2026-07-12 00:46:53 +01:00
tests, and the distillation occurrence is a historical-input test fixture.
Interruption now has a native owner. `interrupt_coordinator_job` validates the
binding and revision, records the operator reason through the canonical state
owner, and reports `cancelRequested=false` rather than inventing backend
cancellation. `epiphany-mvp-status --interrupt-binding` uses this path by
2026-07-12 00:52:19 +01:00
default; `--codex` selects the compatibility route explicitly. The bridge now
delegates interruption to `EpiphanyCoordinatorService::interrupt_job` ; a source
guard rejects local binding mutation, and stale unified state is refused before
2026-07-12 00:57:14 +01:00
commit.
Generic update and promotion now commit through
`EpiphanyCoordinatorService::apply_state_update_from` . A rollout snapshot may
seed native state only when the unified store has no state document; once native
truth exists, stale host input is refused even without an expected revision.
2026-07-12 01:21:18 +01:00
The Codex rollout mirror is deleted. New turns neither persist Epiphany state as
rollout items nor inject a rendered Epiphany state developer message. App-server
read and automation paths load unified CultCache first and fail closed when that
document is corrupt; session state is only an empty-store migration seed.
`stateUpdated` notifications carry the exact native commit result directly.
Historical rollout reconstruction remains a compatibility reader, not an owner
or a writer.
2026-07-12 01:33:00 +01:00
Codex session custody is deleted as well. `SessionState` , `Session` , and
`CodexThread` carry no Epiphany state cache or accessor; normal Codex rollout
reconstruction ignores historical Epiphany items. The app-server compatibility
host reads unified CultCache first and, only when it is empty, invokes the
legacy rollout reader directly at the boundary. A source guard rejects renewed
session custody.
2026-07-12 01:47:55 +01:00
The historical rollout parser has now moved out of `codex-core` as well. It
lives in app-server's explicitly quarantined `legacy_epiphany_rollout` module,
where two migration tests prove latest-surviving selection and rollback
rejection. `codex-core` no longer declares or exports an Epiphany rollout
parser. The legacy `RolloutItem` variant remains readable so old files do not
become undecodable, but normal core reconstruction treats it as inert cargo.
2026-07-12 01:51:44 +01:00
`CodexThread` is now generic again at the remaining host seam. Its
Epiphany-named reference-turn and runtime-spine-path helpers are deleted;
app-server derives the compatibility store path from the generic config
snapshot and calls a generic `reference_turn_id` accessor. The core source guard
rejects any `pub async fn epiphany_*` API on `CodexThread` .
2026-07-12 02:19:47 +01:00
`codex-protocol` no longer republishes Epiphany's anatomy. App-server-protocol,
app-server compatibility code, and legacy-focused core tests import
`epiphany-state-model` directly. Protocol retains a private
`EpiphanyStateItem` import solely to decode the historical rollout variant; its
two round-trip tests and app-server's two migration tests pass. A source guard
forbids `pub use epiphany_state_model::*` from returning.
2026-07-12 05:02:47 +01:00
The historical rollout payload is now opaque inside Codex protocol:
`RolloutItem::EpiphanyState(serde_json::Value)` . App-server's legacy quarantine
alone decodes that value into `EpiphanyStateItem` , returns a typed state only
after validation, and rejects malformed payloads. The old tagged JSON shape,
latest-surviving selection, and rollback semantics remain covered. Codex
protocol no longer has a production dependency on `epiphany-state-model` ; a
source guard proves both the opaque variant and dependency boundary.
2026-07-12 05:17:19 +01:00
Codex protocol's obsolete native-state test authority is deleted too. The
giant `EpiphanyThreadState` fixture and native round-trip tests are replaced by
one minimal opaque-envelope preservation test. `codex-protocol` has no
`epiphany-state-model` dependency in production or dev configuration; native
state serialization is tested by its actual owner.
2026-07-12 05:38:03 +01:00
The opaque Rust variant is now named `LegacyEpiphanyState` , with an explicit
`#[serde(rename = "epiphany_state")]` preserving the historical wire/file tag.
Every remaining Codex match therefore declares that it handles quarantine
cargo rather than live Epiphany authority. Protocol shape and app-server
migration tests prove the rename did not change old-file compatibility.
2026-07-12 05:40:08 +01:00
Generic unknown rollout cargo is rejected. `RolloutRecorder::load_rollout_items`
parses each line into strict `RolloutLine` /`RolloutItem` , counts parse failures,
and feeds the result into history replay, metadata, listing, state extraction,
and agent control. A catch-all variant would turn malformed or future live
items into silent success across every consumer to preserve one extinct record.
The deletion path is narrower: app-server's migration quarantine should read
raw rollout lines, recognize only `type=epiphany_state` , decode its payload,
and combine those migration records with strictly decoded Codex lifecycle items.
Then `LegacyEpiphanyState` can leave Codex protocol and all core consumers.
2026-07-12 06:03:17 +01:00
That final deletion is complete. `RolloutItem` has no Epiphany variant, and
protocol/core/rollout/state/app-server-protocol contain no legacy-state match.
App-server's migration quarantine reads raw JSONL, recognizes only the exact
historical `type=epiphany_state` tag, validates its payload into native
`EpiphanyStateItem` , and strictly decodes ordinary `RolloutLine` items needed
for turn and rollback semantics. Unknown ordinary lines remain parse failures
for the normal Codex loader; the migration scan ignores them without teaching
Codex global tolerance. Four quarantine tests prove raw-tag recognition,
latest-surviving selection, rollback rejection, and malformed-payload refusal.
Obsolete core legacy fixtures and the final core state-model dev dependency are
deleted.
2026-07-12 06:08:51 +01:00
Codex-owned Epiphany reflexes are deleted too. The app-server event loop no
longer auto-compacts on Epiphany pressure, launches reorientation workers at
turn boundaries, or steers pre-compaction checkpoint instructions into active
turns. `epiphany_automation.rs` and its per-thread checkpoint intervention
state are gone. Native coordinator/heartbeat/Continuity organs own scheduling,
launch, pressure, and recovery; app-server retains explicit compatibility
routes, notifications, and read projection only. A source guard rejects renewed
automation authority in the event loop, processor module list, or thread state.
2026-07-12 06:18:28 +01:00
The remaining app-server surface is now mechanically classified and guarded.
2026-07-12 06:40:12 +01:00
Mutation routes may call only the explicit update or interruption bridge
delegate; forbidden local receipt/binding/runtime writes,
2026-07-12 06:18:28 +01:00
prompt steering, compaction submission, and automation selection fail the
source test. Read routes reject every mutation, launch, interruption, indexing,
prompt-steering, compaction, or scheduler symbol. Migration, read projection,
notification projection, and explicit delegated actuation are the only allowed
categories. The deleted event-loop reflex also left dead bridge automation and
checkpoint-pressure wrappers; those zero-caller exports and imports are gone.
2026-07-12 06:20:54 +01:00
Executable-client discovery is recorded in
`notes/epiphany-app-server-client-matrix.md` . Only eight routes have named
in-repo consumers, all explicit phase-6 smokes or
`epiphany-mvp-status --codex` fallbacks. Ten routes are advertised but
unconsumed: role/reorientation launch and accept, index, distill, propose,
promote, job launch, and retrieve. Definitions, generated bindings, README
claims, and serialization tests do not count as clients. Those ten request
2026-07-12 06:40:12 +01:00
registrations, dispatch arms, handlers, tests, and README claims are deleted.
The registration guard now fixes the compatibility surface at the eight named
client routes and rejects restoration of the unconsumed methods.
2026-07-12 07:01:13 +01:00
The orphan audit then removed the deleted methods' request/response DTOs from
app-server protocol, including the duplicate generic job-launch worker document
hierarchy and retrieval result/index projection shapes. Bridge-only distill,
propose, job-document, index, and retrieve conversions plus the entire
`retrieve_protocol` module are deleted. Regenerated JSON/TypeScript fixtures
contain none of those types; their in-memory fixture comparison passes.
2026-07-12 07:30:03 +01:00
The final eight-route compatibility surface is gone too. Seven phase-6
app-server smoke binaries and the app-server-backed MVP status smoke were
deleted; `epiphany-mvp-status` has one native status/interruption path and no
Codex transport client. App-server request/notification registrations,
dispatch, route modules, all `ThreadEpiphany*` DTOs, generated exports, generic
Codex `Thread.epiphanyState` , and legacy rollout-state migration are deleted.
`codex-app-server-protocol` no longer depends on `epiphany-state-model` .
2026-07-12 07:37:30 +01:00
The apparent final bridge consumer, the Codex-hosted file-watcher invalidation
manager, had no watch creator or snapshot reader after route deletion; only
no-op teardown calls survived. It and that listener plumbing were deleted.
`epiphany-codex-bridge` and both remaining Codex dependency edges are gone.