Add Epiphany MVP dogfood runner
This commit is contained in:
parent
0e7f8a7685
commit
f1771e11df
10 changed files with 439 additions and 16 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,3 +3,4 @@ __pycache__/
|
|||
epiphany-core/target/
|
||||
epiphany-core/Cargo.lock
|
||||
.epiphany-smoke/
|
||||
.epiphany-dogfood/
|
||||
|
|
|
|||
|
|
@ -30,10 +30,11 @@ The spine exists in twenty-four live paths:
|
|||
- targeted context reflection: app-server declares experimental read-only `thread/epiphany/context`, reads the same live/stored Epiphany state view used by scene/jobs, and derives a bounded state shard containing selected graph nodes/edges, links, active frontier, checkpoint, the full durable investigation-checkpoint packet, observations, direct evidence, linked evidence, and missing requested ids without retrieval, proposal, promotion, notification, mutation, or persistence in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:355), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4253), [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4261), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:11152).
|
||||
- context-pressure reflection: core token telemetry carries `model_auto_compact_token_limit` beside total/last usage and `model_context_window`; app-server declares experimental read-only `thread/epiphany/pressure`, reads live token usage or the latest stored rollout `TokenCount`, and derives `unknown`/`low`/`elevated`/`high`/`critical` pressure plus a non-acting compaction-prep recommendation without mutating Epiphany state or scheduling compaction in [protocol.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/protocol/src/protocol.rs:2237), [turn_context.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/session/turn_context.rs:103), [session/mod.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/core/src/session/mod.rs:2716), [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:360), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4361), [token_usage_replay.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor/token_usage_replay.rs:75), [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4306), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:11028).
|
||||
- reorientation policy: app-server declares experimental read-only `thread/epiphany/reorient`, reuses the same live/stored thread view plus mapped pressure/freshness/watcher signals, and derives a bounded `resume`/`regather` verdict with checkpoint-path/frontier reasons without mutating, compacting, scheduling, notifying, or continuing work in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:365), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4514), [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4394), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:11424).
|
||||
- CRRC coordinator recommendation: app-server declares experimental read-only `thread/epiphany/crrc`, reuses the same pressure/freshness/watcher/reorientation mapping plus the fixed `reorient-worker` binding and result read-back helper, and returns one bounded recommendation such as continue, prepare checkpoint, launch worker, wait, review, accept, or regather manually without mutating, launching, accepting, compacting, notifying, scheduling, or silently continuing work in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:370), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4661), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4546).
|
||||
- CRRC coordinator recommendation: app-server declares experimental read-only `thread/epiphany/crrc`, reuses the same pressure/freshness/watcher/reorientation mapping plus the fixed `reorient-worker` binding and result read-back helper, recognizes already accepted reorientation findings so an accepted result is not recommended for acceptance again, and returns one bounded recommendation such as continue, prepare checkpoint, launch worker, wait, review, accept, or regather manually without mutating, launching, accepting, compacting, notifying, scheduling, or silently continuing work in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:370), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4661), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4546).
|
||||
- role ownership projection: app-server declares experimental read-only `thread/epiphany/roles`, reuses the same state/jobs/pressure/reorient/result/CRRC signals as the coordinator loop, and projects implementation, modeling/checkpoint, verification/review, and reorientation lanes with owner roles, status, linked jobs, authority scopes, and recommended scene actions without launching, scheduling, accepting, compacting, notifying, or mutating state in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:350), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4161), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4310).
|
||||
- role specialist launch/read-back: app-server declares experimental `thread/epiphany/roleLaunch` and read-only `thread/epiphany/roleResult`. `roleLaunch` accepts only fixed modeling/checkpoint and verification/review role ids, builds bounded specialist payloads from authoritative Epiphany state, routes them through the existing `epiphany_launch_job` job-control seam, and emits the normal `jobLaunch` state update for `jobBindings` only. `roleResult` resolves the fixed or requested binding through the current `agent_jobs` backend and projects structured output as a reviewable finding with verdict, summary, next safe move, inspected files, frontier/evidence ids, raw result, and errors without mutation, promotion, scheduling, or hidden continuation. Implementation stays owned by the main coding agent, and reorientation stays on the CRRC-specific `reorientLaunch` / `reorientResult` path.
|
||||
- MVP operator view: `tools/epiphany_mvp_status.py` launches app-server over stdio, starts or reads one thread, gathers scene, pressure, reorient, jobs, roles, reorient result, and CRRC responses, and renders them as text or JSON so the loop can be dogfooded without reading Rust.
|
||||
- MVP operator view: `tools/epiphany_mvp_status.py` launches app-server over stdio, starts or reads one thread, gathers scene, pressure, reorient, jobs, roles, modeling/verification role results, reorient result, and CRRC responses, and renders them as text or JSON so the loop can be dogfooded without reading Rust.
|
||||
- MVP dogfood runner: `tools/epiphany_mvp_dogfood.py` launches app-server over stdio, drives a bounded state/role/CRRC/reorientation loop, and writes local JSON/text/transcript artifacts under `.epiphany-dogfood/mvp-loop` so a human can audit the run and compare it against a vanilla Codex reference.
|
||||
- reorientation launch: app-server now declares experimental `thread/epiphany/reorientLaunch`, requires a loaded thread plus durable investigation checkpoint, consumes the live reorientation verdict, and launches one fixed `reorient-worker` binding through the existing job-control seam with explicit resume-versus-regather scope, checkpoint-derived payload, and structured-output expectations instead of pretending CRRC suddenly grew a scheduler in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:370), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4575), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4519).
|
||||
- reorientation result read-back: app-server now declares experimental read-only `thread/epiphany/reorientResult`, defaults to the fixed `reorient-worker` binding, resolves that binding through the current `agent_jobs` backend when available, reads the single backend item result, and projects a reviewable finding with mode, summary, next safe move, checkpoint-validity flag, inspected files, frontier ids, evidence ids, raw result, and any job/item errors without mutating state, promoting evidence, or scheduling follow-up work in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:374), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4610), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4684).
|
||||
- reorientation finding acceptance: app-server now declares experimental `thread/epiphany/reorientAccept`, requires a loaded thread and a completed `reorient-worker` backend result, appends accepted observation/evidence records, optionally banks the finding into scratch and the durable investigation checkpoint, persists through the normal typed update path, and emits `thread/epiphany/stateUpdated` with source `reorientAccept` without accepting pending work, auto-promoting arbitrary worker output, launching follow-up work, or silently continuing implementation in [common.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/common.rs:378), [v2.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server-protocol/src/protocol/v2.rs:4635), and [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4885).
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ The landed machine now has:
|
|||
- read-only Phase 6 role ownership through `thread/epiphany/roles`, projecting implementation, modeling/checkpoint, verification/review, and reorientation lanes from typed state plus jobs/CRRC/result signals
|
||||
- explicit Phase 6 role launch/read-back through `thread/epiphany/roleLaunch` and read-only `thread/epiphany/roleResult`, limited to fixed modeling/checkpoint and verification/review templates over the existing job-control seam
|
||||
- first Phase 6 dogfood operator view through `tools/epiphany_mvp_status.py`
|
||||
- first auditable Phase 6 dogfood runner through `tools/epiphany_mvp_dogfood.py`, producing local status snapshots, raw app-server transcript, final status artifacts, vanilla-reference output, and comparison notes
|
||||
- live Phase 6 reorientation app-server smoke coverage in `tools/epiphany_phase6_reorient_smoke.py`
|
||||
- live Phase 6 reorient-launch app-server smoke coverage in `tools/epiphany_phase6_reorient_launch_smoke.py`
|
||||
- live Phase 6 MVP status smoke coverage in `tools/epiphany_mvp_status_smoke.py`
|
||||
|
|
@ -187,9 +188,12 @@ blockers are now landed as
|
|||
`thread/epiphany/roleResult`. A human can now ask the harness what it believes,
|
||||
what it recommends, which role lane owns the next visible work, explicitly
|
||||
launch modeling/checkpoint or verification/review workers, and read their
|
||||
findings back without reading Rust. The next MVP question is dogfood, not
|
||||
another imagined organ: use the landed loop on real bounded coding work and fix
|
||||
only concrete blockers.
|
||||
findings back without reading Rust. The first auditable dogfood pass then added
|
||||
`tools/epiphany_mvp_dogfood.py`, rendered modeling/verification findings in the
|
||||
status view, and fixed CRRC's repeat-acceptance recommendation after
|
||||
`reorientAccept`. The next MVP question is human operator testing, not another
|
||||
imagined organ: use the landed loop and artifact bundle, then fix only concrete
|
||||
blockers.
|
||||
|
||||
## Phase 6 Direction
|
||||
|
||||
|
|
@ -197,7 +201,7 @@ Phase 6 should grow observable harness state outward from the typed spine.
|
|||
|
||||
Useful candidates:
|
||||
|
||||
1. Dogfood the landed MVP loop on real bounded coding work through state, status, roles, roleLaunch/roleResult, and CRRC.
|
||||
1. Put the dogfooded MVP loop in front of a human operator through status/artifact review, then fix concrete usability blockers.
|
||||
2. Keep accepted worker findings review-gated; do not convert acceptance into automatic promotion of arbitrary worker output.
|
||||
3. Add targeted operator-view fields only when dogfooding exposes a real gap.
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ Do not trust this file for the exact live HEAD. Always check git.
|
|||
- Do not copy exact branch or HEAD from this note. Run `git status --short --branch` and `git log --oneline -5`.
|
||||
- Phase 1 through Phase 5 are complete enough.
|
||||
- Phase 6 has read-only `thread/epiphany/scene`, `thread/epiphany/jobs`, `thread/epiphany/roles`, `thread/epiphany/freshness`, `thread/epiphany/context`, `thread/epiphany/pressure`, `thread/epiphany/reorient`, `thread/epiphany/crrc`, `thread/epiphany/reorientResult`, and `thread/epiphany/roleResult`; durable `jobBindings` now act as a thin Epiphany-owned launcher seam with launcher id, authority scope, and backend kind/job id, `thread/epiphany/jobLaunch` / `thread/epiphany/jobInterrupt` / `thread/epiphany/roleLaunch` now provide explicit bounded authority over that seam, jobs can overlay it onto live runtime `agent_jobs` progress for loaded threads, and `thread/epiphany/jobsUpdated` now translates live `agent_job_progress:{json}` background events into changed launcher-bound notifications without polling or scheduling. Freshness carries watcher-backed invalidation inputs, roles project implementation/modeling/verification/reorientation ownership from existing signals without becoming a scheduler, `roleLaunch` can launch only fixed modeling/checkpoint or verification/review specialists, `roleResult` reads those outputs back as reviewable findings without mutation, reorient turns checkpoint plus freshness/pressure/watcher signals into a read-only resume-versus-regather verdict, `thread/epiphany/reorientLaunch` is the explicit runtime consumer over that verdict, `thread/epiphany/reorientResult` reads the launched worker output back as a reviewable finding without mutation or promotion, `thread/epiphany/reorientAccept` explicitly banks completed findings into accepted observation/evidence plus optional scratch/checkpoint state, and `thread/epiphany/crrc` recommends the next explicit CRRC action without launching, accepting, compacting, scheduling, or mutating.
|
||||
- `tools/epiphany_mvp_status.py` is the first dogfood operator view. It starts or reads a thread through app-server and prints scene, pressure, reorient, jobs, roles, reorient result, and CRRC recommendation as text or JSON.
|
||||
- `tools/epiphany_mvp_status.py` is the first dogfood operator view. It starts or reads a thread through app-server and prints scene, pressure, reorient, jobs, roles, modeling/verification role result read-backs, reorient result, and CRRC recommendation as text or JSON.
|
||||
- `tools/epiphany_mvp_dogfood.py` is the first auditable dogfood runner. It drives a bounded state/role/CRRC/reorientation loop and writes local artifacts under `.epiphany-dogfood/mvp-loop`, including raw app-server transcript, rendered snapshots, final status, vanilla-reference prompt/output, and comparison notes.
|
||||
- Durable in-flight investigation checkpointing is now landed in authoritative typed state, writable through `thread/epiphany/update` or accepted `thread/epiphany/promote`, rendered into the prompt, and reflected through scene/context.
|
||||
- The repo is an Epiphany fork of Codex, not a Codex preset.
|
||||
- `vendor/codex` is tracked directly, not a submodule.
|
||||
|
|
@ -70,6 +71,7 @@ The current spine:
|
|||
- read-only reorient-worker result read-back through `thread/epiphany/reorientResult`
|
||||
- explicit reorient-worker finding acceptance through `thread/epiphany/reorientAccept`
|
||||
- read-only CRRC coordinator recommendation through `thread/epiphany/crrc`
|
||||
- CRRC now recognizes already accepted reorientation findings so `reorientAccept` does not leave the operator stuck on a repeat `acceptReorientResult` recommendation.
|
||||
- thin launcher metadata in durable `jobBindings`
|
||||
- live bound-job progress notification through `thread/epiphany/jobsUpdated`
|
||||
- read-only compact reflection through `thread/epiphany/scene`
|
||||
|
|
@ -261,10 +263,15 @@ still explicit even though read-only job ownership/progress reflection now has a
|
|||
real runtime seam, the thin launcher boundary is landed, and one explicit
|
||||
reorient-guided launch surface can consume the verdict on purpose.
|
||||
|
||||
When the user asks to continue, dogfood the landed MVP loop on real bounded
|
||||
coding work through the state, status, roles, roleLaunch/roleResult, and CRRC
|
||||
surfaces. Fix concrete blockers that prevent a human from testing that loop;
|
||||
do not build a broad hidden scheduler, marketplace, or GUI-as-source-of-truth.
|
||||
The first auditable dogfood pass has run. It exercised the landed MVP loop,
|
||||
produced `.epiphany-dogfood/mvp-loop` artifacts, ran a read-only Vanilla Codex
|
||||
reference, and fixed the concrete blocker where CRRC recommended accepting the
|
||||
same reorientation result again after `reorientAccept`.
|
||||
|
||||
When the user asks to continue, put the testable MVP in front of a human
|
||||
operator through `tools/epiphany_mvp_status.py` and the dogfood artifact bundle.
|
||||
Fix concrete blockers in that operator loop; do not build a broad hidden
|
||||
scheduler, marketplace, or GUI-as-source-of-truth.
|
||||
|
||||
Live `thread/epiphany/scene`, `thread/epiphany/jobs`, `thread/epiphany/roles`,
|
||||
`thread/epiphany/freshness`, `thread/epiphany/context`,
|
||||
|
|
|
|||
|
|
@ -55,3 +55,4 @@
|
|||
{"ts": "2026-04-28T11:13:43+00:00", "type": "implementation", "status": "ok", "note": "Extended the MVP status view with derived implementation, modeling/checkpoint, verification/review, and reorientation lanes over existing app-server signals; the status smoke now asserts the four role lanes and rendered operator section."}
|
||||
{"ts": "2026-04-28T13:55:36+00:00", "type": "implementation", "status": "ok", "note": "Landed read-only thread/epiphany/roles as the harness-native MVP role ownership surface. It projects implementation, modeling/checkpoint, verification/review, and reorientation lanes from typed state plus jobs/pressure/reorient/CRRC/result signals without scheduling or mutation; the MVP status tool now consumes that surface. Focused protocol/app-server tests, schema fixtures, app-server build, and live MVP status smoke passed."}
|
||||
{"ts": "2026-04-28T14:48:10+00:00", "type": "implementation", "status": "ok", "note": "Landed explicit thread/epiphany/roleLaunch and read-only thread/epiphany/roleResult for fixed modeling/checkpoint and verification/review specialists over the existing job-control seam. Launch mutates only jobBindings; result projects reviewable findings without mutation. Focused protocol/app-server tests, schema fixtures, app-server build, and tools/epiphany_phase6_role_smoke.py passed."}
|
||||
{"ts": "2026-04-28T15:32:47+00:00", "type": "implementation", "status": "ok", "note": "Ran the first auditable Epiphany MVP dogfood pass through state, modeling/verification roleLaunch/roleResult, CRRC drift, reorientLaunch/reorientResult/reorientAccept, final status rendering, and a read-only Vanilla Codex reference. Dogfood artifacts live under .epiphany-dogfood/mvp-loop. The pass exposed and fixed a concrete operator-loop blocker: after reorientAccept, CRRC no longer recommends accepting the same completed reorientation finding again; it recognizes the accepted evidence and recommends regatherManually for accepted regather findings."}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ active_subgoals:
|
|||
- Treat Phase 5 update/distill/propose/promote/read/notification as complete enough unless a concrete regression appears.
|
||||
- Preserve read-only boundaries for retrieve, distill, propose, scene, jobs, roles, roleResult, freshness, context, pressure, reorient, crrc, and reorientResult.
|
||||
- Extend Phase 6 observability only where it reflects authoritative state or retrieval summaries without becoming a scheduler.
|
||||
- Dogfood the landed MVP loop on real bounded coding work before adding larger organs.
|
||||
- Put the dogfooded MVP loop in front of a human operator before adding larger organs.
|
||||
- Keep persistent project state ruthlessly distilled so rehydration strengthens the next turn instead of bloating it.
|
||||
|
||||
accepted_design:
|
||||
|
|
@ -82,12 +82,14 @@ accepted_design:
|
|||
- `thread/epiphany/pressure` is the first read-only context-pressure surface: it derives pressure from token telemetry and auto-compact/context limits without compacting, scheduling, mutating, or notifying.
|
||||
- `thread/epiphany/reorient` is the first bounded CRRC policy surface: it derives a read-only `resume` versus `regather` verdict from checkpoint, freshness, watcher, and pressure signals without mutating state, compacting, scheduling, or silently continuing work.
|
||||
- `thread/epiphany/crrc` is the first bounded CRRC coordinator recommendation surface: it composes pressure, the reorientation verdict, fixed reorient-worker binding/result status, finding read-back, and available actions into one read-only recommendation without launching, accepting, compacting, scheduling, or mutating state.
|
||||
- `tools/epiphany_mvp_status.py` is the first dogfood operator view: it starts or reads a thread through app-server and renders scene, pressure, reorient, jobs, reorient result, CRRC recommendation, and MVP role lanes as text or JSON without becoming a state store.
|
||||
- `tools/epiphany_mvp_status.py` is the first dogfood operator view: it starts or reads a thread through app-server and renders scene, pressure, reorient, jobs, role result read-backs, reorient result, CRRC recommendation, and MVP role lanes as text or JSON without becoming a state store.
|
||||
- `thread/epiphany/roles` is the first harness-native role ownership surface: it projects implementation, modeling/checkpoint, verification/review, and reorientation lanes from authoritative typed state, bound jobs, pressure/reorient/CRRC, and worker result status without launching, scheduling, accepting, compacting, or mutating state.
|
||||
- `thread/epiphany/roleLaunch` and `thread/epiphany/roleResult` are the first explicit role-scoped specialist templates: modeling/checkpoint and verification/review can be launched through fixed bindings over the existing job-control seam and read back as reviewable findings, while implementation stays owned by the main coding agent and reorientation stays on the CRRC-specific launch/result path.
|
||||
- `thread/epiphany/reorientLaunch` is the first bounded runtime consumer over the reorientation verdict: it launches one fixed `reorient-worker` job through the existing job-control seam with explicit resume-versus-regather scope, authority, and checkpoint-derived payload, without making `thread/epiphany/reorient` a writer or turning CRRC into an ambient scheduler.
|
||||
- `thread/epiphany/reorientResult` is the first bounded read-back surface for that worker: it reads the fixed or requested reorient-worker binding through the current `agent_jobs` backend and projects completed output as a reviewable finding without mutation, promotion, scheduling, or hidden continuation.
|
||||
- `thread/epiphany/reorientAccept` is the first explicit acceptance write for completed reorient-worker findings: it appends accepted observation/evidence records, can optionally update scratch and investigation checkpoint state, and emits `stateUpdated` with source `reorientAccept` without accepting pending work or launching follow-up work.
|
||||
- After `thread/epiphany/reorientAccept`, CRRC recognizes the accepted reorientation finding and does not recommend accepting the same completed result again.
|
||||
- `tools/epiphany_mvp_dogfood.py` is the auditable MVP dogfood runner: it drives state, role launch/result, CRRC drift, reorient launch/result/accept, rendered status snapshots, and raw app-server transcript into a local artifact bundle for comparison against a vanilla Codex reference.
|
||||
- Epiphany safety doctrine is to separate cognition from actuation, keep authority explicit, make interruption sacred, stage capability release, and treat operator misuse as a normal design input rather than a rude hypothetical.
|
||||
- Epiphany is built in the open, but publication mode is not one-size-fits-all: use FOSS where viable, source-available licensing where economics or capability risk demand it, and commercial terms where organizations extract real enterprise value.
|
||||
- `thread/epiphany/jobLaunch` and `thread/epiphany/jobInterrupt` are the first bounded authority surfaces over the thin job seam: they mutate durable `job_bindings`, create or cancel the current `agent_jobs` backend binding, and preserve explicit launcher identity and interruption without turning `thread/epiphany/jobs` into a scheduler.
|
||||
|
|
@ -109,6 +111,7 @@ landed_baseline:
|
|||
- Phase 6 read-back: read-only reorient-worker result reflection through `thread/epiphany/reorientResult`.
|
||||
- Phase 6 acceptance: explicit reorient-worker finding acceptance through `thread/epiphany/reorientAccept`.
|
||||
- Phase 6 dogfood view: first CLI operator status over scene/pressure/reorient/jobs/result/CRRC.
|
||||
- Phase 6 dogfood runner: auditable scripted MVP loop over state, role results, CRRC, reorientation acceptance, status snapshots, and transcript artifacts.
|
||||
- Phase 6 role ownership: read-only `thread/epiphany/roles` over implementation, modeling/checkpoint, verification/review, and reorientation lanes.
|
||||
- Phase 6 role specialists: explicit `thread/epiphany/roleLaunch` and read-only `thread/epiphany/roleResult` templates for modeling/checkpoint and verification/review.
|
||||
guardrails:
|
||||
|
|
@ -144,5 +147,5 @@ rejected_paths:
|
|||
reason: persistent state that accumulates every local truth becomes memory cruft and weakens rehydration
|
||||
|
||||
current_status:
|
||||
summary: Phase 1 durable state, Phase 2 prompt integration, Phase 3 typed read, Phase 4 retrieval/indexing, Phase 5 update/distill/propose/promote/read/notification, and Phase 6 read-only scene, jobs, roles, freshness, targeted context, pressure, reorient, CRRC, reorient launch/result/accept, explicit modeling/checkpoint and verification/review role launch/result templates, and first dogfood MVP status are landed. `thread/epiphany/roleLaunch` now launches only fixed modeling/checkpoint or verification/review specialists over the existing job-control seam, and `thread/epiphany/roleResult` reads their backend output back as reviewable findings without mutation. Implementation remains main-agent work; reorientation remains on the CRRC-specific launch/result path. Persistent state remains distilled; evidence is a belief ledger, not an activity feed.
|
||||
next_action: Dogfood the MVP loop on a real bounded coding task using the landed state, status, roles, roleLaunch/roleResult, and CRRC surfaces; fix only concrete blockers that prevent a human from testing the product loop. Automatic broad specialist scheduling, GUI-as-source-of-truth, a specialist marketplace, and a second job backend remain future work.
|
||||
summary: Phase 1 durable state, Phase 2 prompt integration, Phase 3 typed read, Phase 4 retrieval/indexing, Phase 5 update/distill/propose/promote/read/notification, and Phase 6 read-only scene, jobs, roles, freshness, targeted context, pressure, reorient, CRRC, reorient launch/result/accept, explicit modeling/checkpoint and verification/review role launch/result templates, first dogfood MVP status, and auditable MVP dogfood runner are landed. The dogfood runner exercised state, role launch/result, CRRC drift, reorient launch/result/accept, and rendered status snapshots; it exposed and fixed the repeat-acceptance CRRC recommendation after `reorientAccept`. Implementation remains main-agent work; reorientation remains on the CRRC-specific launch/result path. Persistent state remains distilled; evidence is a belief ledger, not an activity feed.
|
||||
next_action: Put the testable MVP in front of a human operator using the dogfood artifact bundle and `tools/epiphany_mvp_status.py`; fix only concrete blockers in the operator loop. Automatic broad specialist scheduling, GUI-as-source-of-truth, a specialist marketplace, autonomous specialist quality, and a second job backend remain future work.
|
||||
|
|
|
|||
295
tools/epiphany_mvp_dogfood.py
Normal file
295
tools/epiphany_mvp_dogfood.py
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from epiphany_mvp_status import DEFAULT_APP_SERVER
|
||||
from epiphany_mvp_status import collect_status
|
||||
from epiphany_mvp_status import render_status
|
||||
from epiphany_phase5_smoke import AppServerClient
|
||||
from epiphany_phase5_smoke import ROOT
|
||||
from epiphany_phase5_smoke import require
|
||||
from epiphany_phase6_reorient_launch_smoke import BINDING_ID as REORIENT_BINDING_ID
|
||||
from epiphany_phase6_reorient_launch_smoke import complete_reorient_backend_job
|
||||
from epiphany_phase6_reorient_smoke import WATCHED_RELATIVE_PATH
|
||||
from epiphany_phase6_reorient_smoke import prepare_workspace
|
||||
from epiphany_phase6_reorient_smoke import reorient_patch
|
||||
from epiphany_phase6_reorient_smoke import wait_for_regather_reorient
|
||||
from epiphany_phase6_role_smoke import MODELING_BINDING_ID
|
||||
from epiphany_phase6_role_smoke import VERIFICATION_BINDING_ID
|
||||
from epiphany_phase6_role_smoke import complete_role_backend_job
|
||||
|
||||
|
||||
DEFAULT_ARTIFACT_DIR = ROOT / ".epiphany-dogfood" / "mvp-loop"
|
||||
|
||||
|
||||
def reset_artifact_dir(path: Path) -> None:
|
||||
root = (ROOT / ".epiphany-dogfood").resolve()
|
||||
resolved = path.resolve()
|
||||
if resolved == root or root not in resolved.parents:
|
||||
raise ValueError(f"refusing to delete non-dogfood artifact dir: {path}")
|
||||
if path.exists():
|
||||
shutil.rmtree(path)
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def write_json(path: Path, value: Any) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(json.dumps(value, indent=2, ensure_ascii=False) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def write_text(path: Path, value: str) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(value, encoding="utf-8")
|
||||
|
||||
|
||||
def snapshot(
|
||||
client: AppServerClient,
|
||||
*,
|
||||
thread_id: str,
|
||||
cwd: Path,
|
||||
label: str,
|
||||
) -> dict[str, Any]:
|
||||
status = collect_status(client, thread_id=thread_id, cwd=cwd, ephemeral=True)
|
||||
return {"label": label, "status": status, "rendered": render_status(status)}
|
||||
|
||||
|
||||
def launch_role(
|
||||
client: AppServerClient,
|
||||
thread_id: str,
|
||||
*,
|
||||
role_id: str,
|
||||
expected_revision: int,
|
||||
) -> dict[str, Any]:
|
||||
launch = client.send(
|
||||
"thread/epiphany/roleLaunch",
|
||||
{
|
||||
"threadId": thread_id,
|
||||
"roleId": role_id,
|
||||
"expectedRevision": expected_revision,
|
||||
"maxRuntimeSeconds": 90,
|
||||
},
|
||||
)
|
||||
assert launch is not None
|
||||
require(launch["roleId"] == role_id, f"{role_id} launch should echo role id")
|
||||
require(
|
||||
launch["changedFields"] == ["jobBindings"],
|
||||
f"{role_id} launch should mutate only job bindings",
|
||||
)
|
||||
return launch
|
||||
|
||||
|
||||
def run_dogfood(args: argparse.Namespace) -> dict[str, Any]:
|
||||
app_server = args.app_server.resolve()
|
||||
if not app_server.exists():
|
||||
raise FileNotFoundError(f"codex app-server binary not found: {app_server}")
|
||||
|
||||
artifact_dir = args.artifact_dir.resolve()
|
||||
reset_artifact_dir(artifact_dir)
|
||||
codex_home = artifact_dir / "codex-home"
|
||||
workspace = artifact_dir / "workspace"
|
||||
transcript_path = artifact_dir / "epiphany-transcript.jsonl"
|
||||
stderr_path = artifact_dir / "epiphany-server.stderr.log"
|
||||
codex_home.mkdir(parents=True, exist_ok=True)
|
||||
watched_file = prepare_workspace(workspace)
|
||||
|
||||
snapshots: list[dict[str, Any]] = []
|
||||
|
||||
with AppServerClient(app_server, codex_home, transcript_path, stderr_path) as client:
|
||||
client.send(
|
||||
"initialize",
|
||||
{
|
||||
"clientInfo": {
|
||||
"name": "epiphany-mvp-dogfood",
|
||||
"title": "Epiphany MVP Dogfood",
|
||||
"version": "0.1.0",
|
||||
},
|
||||
"capabilities": {"experimentalApi": True},
|
||||
},
|
||||
)
|
||||
client.send("initialized", expect_response=False)
|
||||
started = client.send("thread/start", {"cwd": str(workspace), "ephemeral": True})
|
||||
assert started is not None
|
||||
thread_id = started["thread"]["id"]
|
||||
|
||||
snapshots.append(snapshot(client, thread_id=thread_id, cwd=workspace, label="cold-start"))
|
||||
|
||||
update = client.send(
|
||||
"thread/epiphany/update",
|
||||
{"threadId": thread_id, "expectedRevision": 0, "patch": reorient_patch()},
|
||||
)
|
||||
assert update is not None
|
||||
require(update["revision"] == 1, "checkpoint update should advance revision to 1")
|
||||
snapshots.append(snapshot(client, thread_id=thread_id, cwd=workspace, label="checkpoint-ready"))
|
||||
|
||||
modeling_launch = launch_role(
|
||||
client,
|
||||
thread_id,
|
||||
role_id="modeling",
|
||||
expected_revision=1,
|
||||
)
|
||||
modeling_payload = complete_role_backend_job(
|
||||
codex_home,
|
||||
modeling_launch["job"]["backendJobId"],
|
||||
binding_id=MODELING_BINDING_ID,
|
||||
role_id="modeling",
|
||||
verdict="checkpoint-ready",
|
||||
)
|
||||
modeling_result = client.send(
|
||||
"thread/epiphany/roleResult", {"threadId": thread_id, "roleId": "modeling"}
|
||||
)
|
||||
assert modeling_result is not None
|
||||
require(modeling_result["status"] == "completed", "modeling result should complete")
|
||||
snapshots.append(snapshot(client, thread_id=thread_id, cwd=workspace, label="modeling-result"))
|
||||
|
||||
verification_launch = launch_role(
|
||||
client,
|
||||
thread_id,
|
||||
role_id="verification",
|
||||
expected_revision=2,
|
||||
)
|
||||
verification_payload = complete_role_backend_job(
|
||||
codex_home,
|
||||
verification_launch["job"]["backendJobId"],
|
||||
binding_id=VERIFICATION_BINDING_ID,
|
||||
role_id="verification",
|
||||
verdict="pass",
|
||||
)
|
||||
verification_result = client.send(
|
||||
"thread/epiphany/roleResult",
|
||||
{"threadId": thread_id, "roleId": "verification"},
|
||||
)
|
||||
assert verification_result is not None
|
||||
require(verification_result["status"] == "completed", "verification result should complete")
|
||||
snapshots.append(snapshot(client, thread_id=thread_id, cwd=workspace, label="verification-result"))
|
||||
|
||||
watched_file.write_text(
|
||||
"pub fn reorient_target() -> &'static str {\n \"after\"\n}\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
regather = wait_for_regather_reorient(client, thread_id)
|
||||
require(regather["decision"]["action"] == "regather", "source drift should force regather")
|
||||
snapshots.append(snapshot(client, thread_id=thread_id, cwd=workspace, label="drift-detected"))
|
||||
|
||||
reorient_launch = client.send(
|
||||
"thread/epiphany/reorientLaunch",
|
||||
{"threadId": thread_id, "expectedRevision": 3, "maxRuntimeSeconds": 90},
|
||||
)
|
||||
assert reorient_launch is not None
|
||||
require(reorient_launch["revision"] == 4, "reorient launch should advance revision to 4")
|
||||
reorient_payload = complete_reorient_backend_job(
|
||||
codex_home,
|
||||
reorient_launch["job"]["backendJobId"],
|
||||
mode="regather",
|
||||
)
|
||||
reorient_result = client.send(
|
||||
"thread/epiphany/reorientResult",
|
||||
{"threadId": thread_id, "bindingId": REORIENT_BINDING_ID},
|
||||
)
|
||||
assert reorient_result is not None
|
||||
require(reorient_result["status"] == "completed", "reorient result should complete")
|
||||
|
||||
accepted = client.send(
|
||||
"thread/epiphany/reorientAccept",
|
||||
{
|
||||
"threadId": thread_id,
|
||||
"expectedRevision": 4,
|
||||
"bindingId": REORIENT_BINDING_ID,
|
||||
"updateScratch": True,
|
||||
"updateInvestigationCheckpoint": True,
|
||||
},
|
||||
)
|
||||
assert accepted is not None
|
||||
require(accepted["revision"] == 5, "accepting reorient result should advance revision")
|
||||
snapshots.append(snapshot(client, thread_id=thread_id, cwd=workspace, label="accepted-reorient"))
|
||||
|
||||
final_status = collect_status(client, thread_id=thread_id, cwd=workspace, ephemeral=True)
|
||||
require(
|
||||
final_status["crrc"]["recommendation"]["action"] == "regatherManually",
|
||||
"accepted regather findings should not be recommended for acceptance again",
|
||||
)
|
||||
final_rendered = render_status(final_status)
|
||||
final_read = client.send("thread/read", {"threadId": thread_id, "includeTurns": False})
|
||||
assert final_read is not None
|
||||
|
||||
summary = {
|
||||
"objective": "Dogfood the Epiphany MVP loop on a bounded continuity/role-separation task.",
|
||||
"artifactDir": str(artifact_dir),
|
||||
"threadId": thread_id,
|
||||
"workspace": str(workspace),
|
||||
"finalRevision": final_read["thread"]["epiphanyState"]["revision"],
|
||||
"snapshots": [item["label"] for item in snapshots],
|
||||
"modeling": {
|
||||
"revision": modeling_launch["revision"],
|
||||
"bindingId": MODELING_BINDING_ID,
|
||||
"backendJobId": modeling_launch["job"]["backendJobId"],
|
||||
"resultStatus": modeling_result["status"],
|
||||
"payload": modeling_payload,
|
||||
},
|
||||
"verification": {
|
||||
"revision": verification_launch["revision"],
|
||||
"bindingId": VERIFICATION_BINDING_ID,
|
||||
"backendJobId": verification_launch["job"]["backendJobId"],
|
||||
"resultStatus": verification_result["status"],
|
||||
"payload": verification_payload,
|
||||
},
|
||||
"crrc": {
|
||||
"driftDecision": regather["decision"],
|
||||
"launchRevision": reorient_launch["revision"],
|
||||
"resultStatus": reorient_result["status"],
|
||||
"acceptedRevision": accepted["revision"],
|
||||
"payload": reorient_payload,
|
||||
},
|
||||
"finalRecommendation": final_status["crrc"]["recommendation"],
|
||||
"artifactManifest": [
|
||||
"epiphany-dogfood-summary.json",
|
||||
"epiphany-final-status.json",
|
||||
"epiphany-final-status.txt",
|
||||
"epiphany-snapshots.json",
|
||||
"epiphany-transcript.jsonl",
|
||||
"epiphany-server.stderr.log",
|
||||
"vanilla-reference-prompt.md",
|
||||
"vanilla-reference.md",
|
||||
"vanilla-reference.stdout.log",
|
||||
"vanilla-reference.stderr.log",
|
||||
"comparison.md",
|
||||
],
|
||||
}
|
||||
|
||||
write_json(artifact_dir / "epiphany-snapshots.json", snapshots)
|
||||
write_json(artifact_dir / "epiphany-final-status.json", final_status)
|
||||
write_text(artifact_dir / "epiphany-final-status.txt", final_rendered)
|
||||
write_json(artifact_dir / "epiphany-dogfood-summary.json", summary)
|
||||
write_json(
|
||||
artifact_dir / "artifact-manifest.json",
|
||||
{
|
||||
"artifactDir": str(artifact_dir),
|
||||
"files": summary["artifactManifest"],
|
||||
"notes": [
|
||||
"transcript contains JSON-RPC request/response audit trail",
|
||||
"stderr captures app-server diagnostics",
|
||||
"snapshots preserve rendered and raw status at each dogfood checkpoint",
|
||||
"vanilla reference and comparison files are added after the control agent run",
|
||||
],
|
||||
},
|
||||
)
|
||||
return summary
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Run an auditable Epiphany MVP dogfood pass over state, roles, and CRRC."
|
||||
)
|
||||
parser.add_argument("--app-server", type=Path, default=DEFAULT_APP_SERVER)
|
||||
parser.add_argument("--artifact-dir", type=Path, default=DEFAULT_ARTIFACT_DIR)
|
||||
args = parser.parse_args()
|
||||
result = run_dogfood(args)
|
||||
print(json.dumps(result, indent=2, ensure_ascii=False))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
|
@ -73,6 +73,14 @@ def collect_status(
|
|||
reorient = client.send("thread/epiphany/reorient", {"threadId": thread_id})
|
||||
jobs = client.send("thread/epiphany/jobs", {"threadId": thread_id})
|
||||
roles = client.send("thread/epiphany/roles", {"threadId": thread_id})
|
||||
role_results = {
|
||||
"modeling": client.send(
|
||||
"thread/epiphany/roleResult", {"threadId": thread_id, "roleId": "modeling"}
|
||||
),
|
||||
"verification": client.send(
|
||||
"thread/epiphany/roleResult", {"threadId": thread_id, "roleId": "verification"}
|
||||
),
|
||||
}
|
||||
reorient_result = client.send("thread/epiphany/reorientResult", {"threadId": thread_id})
|
||||
crrc = client.send("thread/epiphany/crrc", {"threadId": thread_id})
|
||||
|
||||
|
|
@ -84,6 +92,7 @@ def collect_status(
|
|||
"reorient": reorient,
|
||||
"jobs": jobs,
|
||||
"roles": roles,
|
||||
"roleResults": role_results,
|
||||
"reorientResult": reorient_result,
|
||||
"crrc": crrc,
|
||||
}
|
||||
|
|
@ -99,6 +108,7 @@ def render_status(status: dict[str, Any]) -> str:
|
|||
result = status["reorientResult"]
|
||||
crrc = status["crrc"]
|
||||
roles = status["roles"]["roles"]
|
||||
role_results = status.get("roleResults") or {}
|
||||
recommendation = crrc["recommendation"]
|
||||
checkpoint = scene.get("investigationCheckpoint") or {}
|
||||
|
||||
|
|
@ -142,6 +152,25 @@ def render_status(status: dict[str, Any]) -> str:
|
|||
f"- {lane['title']}: {lane['status']} ({lane['ownerRole']}) - {lane['note']}"
|
||||
)
|
||||
|
||||
lines.extend(
|
||||
[
|
||||
"",
|
||||
"Role Findings",
|
||||
]
|
||||
)
|
||||
for role_id in ("modeling", "verification"):
|
||||
role_result = role_results.get(role_id) or {}
|
||||
finding = role_result.get("finding")
|
||||
label = "Modeling / Checkpoint" if role_id == "modeling" else "Verification / Review"
|
||||
lines.append(
|
||||
f"- {label}: {maybe(role_result.get('status'))} for "
|
||||
f"{maybe(role_result.get('bindingId'))}"
|
||||
)
|
||||
if finding:
|
||||
lines.append(f" verdict: {maybe(finding.get('verdict'))}")
|
||||
lines.append(f" summary: {maybe(finding.get('summary'))}")
|
||||
lines.append(f" next: {maybe(finding.get('nextSafeMove'))}")
|
||||
|
||||
lines.extend(
|
||||
[
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -80,11 +80,18 @@ def run_smoke(args: argparse.Namespace) -> dict[str, object]:
|
|||
"Role Lanes" in rendered and "Verification / Review" in rendered,
|
||||
"rendered status should expose the role lane section",
|
||||
)
|
||||
require(
|
||||
"Role Findings" in rendered
|
||||
and status["roleResults"]["modeling"]["status"] == "missingState"
|
||||
and status["roleResults"]["verification"]["status"] == "missingState",
|
||||
"rendered status should expose fixed role result read-back status",
|
||||
)
|
||||
|
||||
result = {
|
||||
"threadId": status["threadId"],
|
||||
"recommendation": status["crrc"]["recommendation"],
|
||||
"roles": status["roles"],
|
||||
"roleResults": status["roleResults"],
|
||||
"stateStatus": status["scene"]["scene"]["stateStatus"],
|
||||
"availableActions": status["scene"]["scene"]["availableActions"],
|
||||
"rendered": rendered,
|
||||
|
|
|
|||
|
|
@ -4438,6 +4438,12 @@ impl CodexMessageProcessor {
|
|||
result_status,
|
||||
checkpoint_present,
|
||||
finding.is_some(),
|
||||
finding.as_ref().is_some_and(|finding| {
|
||||
thread
|
||||
.epiphany_state
|
||||
.as_ref()
|
||||
.is_some_and(|state| epiphany_reorient_finding_already_accepted(state, finding))
|
||||
}),
|
||||
);
|
||||
|
||||
let roles = map_epiphany_roles(
|
||||
|
|
@ -5077,6 +5083,12 @@ impl CodexMessageProcessor {
|
|||
.and_then(|state| state.investigation_checkpoint.as_ref())
|
||||
.is_some(),
|
||||
finding.is_some(),
|
||||
finding.as_ref().is_some_and(|finding| {
|
||||
thread
|
||||
.epiphany_state
|
||||
.as_ref()
|
||||
.is_some_and(|state| epiphany_reorient_finding_already_accepted(state, finding))
|
||||
}),
|
||||
);
|
||||
let note = format!(
|
||||
"{} Result status: {:?}. {}",
|
||||
|
|
@ -13170,6 +13182,7 @@ fn map_epiphany_crrc_recommendation(
|
|||
result_status: ThreadEpiphanyReorientResultStatus,
|
||||
checkpoint_present: bool,
|
||||
finding_present: bool,
|
||||
finding_accepted: bool,
|
||||
) -> ThreadEpiphanyCrrcRecommendation {
|
||||
let build = |action: ThreadEpiphanyCrrcAction,
|
||||
recommended_scene_action: Option<ThreadEpiphanySceneAction>,
|
||||
|
|
@ -13205,13 +13218,20 @@ fn map_epiphany_crrc_recommendation(
|
|||
);
|
||||
}
|
||||
ThreadEpiphanyReorientResultStatus::Completed => {
|
||||
if finding_present {
|
||||
if finding_present && !finding_accepted {
|
||||
return build(
|
||||
ThreadEpiphanyCrrcAction::AcceptReorientResult,
|
||||
Some(ThreadEpiphanySceneAction::ReorientAccept),
|
||||
"A completed reorientation finding is available; review and explicitly accept it before continuing.",
|
||||
);
|
||||
}
|
||||
if finding_accepted && decision.action == ThreadEpiphanyReorientAction::Regather {
|
||||
return build(
|
||||
ThreadEpiphanyCrrcAction::RegatherManually,
|
||||
Some(ThreadEpiphanySceneAction::Reorient),
|
||||
"The reorientation finding is already accepted; re-gather from the banked checkpoint before implementation continues.",
|
||||
);
|
||||
}
|
||||
return build(
|
||||
ThreadEpiphanyCrrcAction::ReviewReorientResult,
|
||||
Some(ThreadEpiphanySceneAction::ReorientResult),
|
||||
|
|
@ -13262,6 +13282,18 @@ fn map_epiphany_crrc_recommendation(
|
|||
)
|
||||
}
|
||||
|
||||
fn epiphany_reorient_finding_already_accepted(
|
||||
state: &EpiphanyThreadState,
|
||||
finding: &ThreadEpiphanyReorientFinding,
|
||||
) -> bool {
|
||||
let accepted_summary = reorient_finding_summary(finding);
|
||||
state.recent_evidence.iter().any(|evidence| {
|
||||
evidence.kind == "reorient_result"
|
||||
&& evidence.status == "accepted"
|
||||
&& evidence.summary == accepted_summary
|
||||
})
|
||||
}
|
||||
|
||||
fn map_epiphany_roles(
|
||||
state: Option<&EpiphanyThreadState>,
|
||||
jobs: &[ThreadEpiphanyJob],
|
||||
|
|
@ -17491,6 +17523,7 @@ mod tests {
|
|||
ThreadEpiphanyReorientResultStatus::MissingBinding,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
|
||||
assert_eq!(recommendation.action, ThreadEpiphanyCrrcAction::Continue);
|
||||
|
|
@ -17527,6 +17560,7 @@ mod tests {
|
|||
ThreadEpiphanyReorientResultStatus::MissingBinding,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
|
@ -17566,6 +17600,7 @@ mod tests {
|
|||
ThreadEpiphanyReorientResultStatus::Completed,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
|
@ -17578,6 +17613,46 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_epiphany_crrc_recommendation_does_not_reaccept_banked_finding() {
|
||||
let pressure = map_epiphany_pressure(None);
|
||||
let decision = ThreadEpiphanyReorientDecision {
|
||||
action: ThreadEpiphanyReorientAction::Regather,
|
||||
checkpoint_status: ThreadEpiphanyReorientCheckpointStatus::RegatherRequired,
|
||||
checkpoint_id: Some("ix-accepted".to_string()),
|
||||
pressure_level: pressure.level,
|
||||
retrieval_status: ThreadEpiphanyRetrievalFreshnessStatus::Ready,
|
||||
graph_status: ThreadEpiphanyGraphFreshnessStatus::Ready,
|
||||
watcher_status: ThreadEpiphanyInvalidationStatus::Clean,
|
||||
reasons: vec![ThreadEpiphanyReorientReason::CheckpointRequestedRegather],
|
||||
checkpoint_dirty_paths: Vec::new(),
|
||||
checkpoint_changed_paths: Vec::new(),
|
||||
active_frontier_node_ids: Vec::new(),
|
||||
next_action: "Regather from the accepted result.".to_string(),
|
||||
note: "accepted".to_string(),
|
||||
};
|
||||
|
||||
let recommendation = map_epiphany_crrc_recommendation(
|
||||
true,
|
||||
ThreadEpiphanyReorientStateStatus::Ready,
|
||||
&pressure,
|
||||
&decision,
|
||||
ThreadEpiphanyReorientResultStatus::Completed,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
recommendation.action,
|
||||
ThreadEpiphanyCrrcAction::RegatherManually
|
||||
);
|
||||
assert_eq!(
|
||||
recommendation.recommended_scene_action,
|
||||
Some(ThreadEpiphanySceneAction::Reorient)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_epiphany_roles_projects_mvp_ownership_lanes() {
|
||||
let state = codex_protocol::protocol::EpiphanyThreadState {
|
||||
|
|
|
|||
Reference in a new issue