Extract Epiphany reorient finding interpretation

This commit is contained in:
Meta Vens 2026-05-12 22:05:16 +01:00
commit e0a8c42ee0
7 changed files with 94 additions and 37 deletions

View file

@ -184,6 +184,7 @@ pub use surfaces::EpiphanyReorientAcceptanceFinding;
pub use surfaces::EpiphanyReorientAction;
pub use surfaces::EpiphanyReorientCheckpointStatus;
pub use surfaces::EpiphanyReorientDecision;
pub use surfaces::EpiphanyReorientFindingInterpretation;
pub use surfaces::EpiphanyReorientFreshnessStatus;
pub use surfaces::EpiphanyReorientInput;
pub use surfaces::EpiphanyReorientPressureLevel;
@ -228,6 +229,7 @@ pub use surfaces::derive_pressure_view;
pub use surfaces::derive_role_board;
pub use surfaces::derive_scene;
pub use surfaces::imagination_role_state_patch_policy_errors;
pub use surfaces::interpret_reorient_finding;
pub use surfaces::interpret_role_finding;
pub use surfaces::modeling_role_state_patch_policy_errors;
pub use surfaces::recommend_coordinator_action;

View file

@ -92,6 +92,7 @@ pub use role_board::role_board_job_status_to_role_status;
pub use role_result::EpiphanyAcceptanceBundle;
pub use role_result::EpiphanyReorientAcceptanceBundle;
pub use role_result::EpiphanyReorientAcceptanceFinding;
pub use role_result::EpiphanyReorientFindingInterpretation;
pub use role_result::EpiphanyRoleAcceptanceFinding;
pub use role_result::EpiphanyRoleFindingInterpretation;
pub use role_result::EpiphanyRoleResultRoleId;
@ -100,6 +101,7 @@ pub use role_result::EpiphanyRoleSelfPersistenceStatus;
pub use role_result::build_reorient_acceptance_bundle;
pub use role_result::build_role_acceptance_bundle;
pub use role_result::imagination_role_state_patch_policy_errors;
pub use role_result::interpret_reorient_finding;
pub use role_result::interpret_role_finding;
pub use role_result::modeling_role_state_patch_policy_errors;
pub use role_result::review_role_self_patch;

View file

@ -68,6 +68,22 @@ pub struct EpiphanyReorientAcceptanceFinding {
pub runtime_job_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EpiphanyReorientFindingInterpretation {
pub mode: Option<String>,
pub summary: Option<String>,
pub next_safe_move: Option<String>,
pub checkpoint_still_valid: Option<bool>,
pub files_inspected: Vec<String>,
pub frontier_node_ids: Vec<String>,
pub evidence_ids: Vec<String>,
pub artifact_refs: Vec<String>,
pub runtime_result_id: Option<String>,
pub runtime_job_id: Option<String>,
pub job_error: Option<String>,
pub item_error: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EpiphanyAcceptanceBundle {
pub accepted_receipt_id: String,
@ -147,6 +163,29 @@ pub fn interpret_role_finding(
}
}
pub fn interpret_reorient_finding(
raw_result: &serde_json::Value,
job_error: Option<String>,
item_error: Option<String>,
) -> EpiphanyReorientFindingInterpretation {
EpiphanyReorientFindingInterpretation {
mode: json_string_field(raw_result, "mode"),
summary: json_string_field(raw_result, "summary"),
next_safe_move: json_string_field(raw_result, "nextSafeMove"),
checkpoint_still_valid: raw_result
.get("checkpointStillValid")
.and_then(serde_json::Value::as_bool),
files_inspected: json_string_array_field(raw_result, "filesInspected"),
frontier_node_ids: json_string_array_field(raw_result, "frontierNodeIds"),
evidence_ids: json_string_array_field(raw_result, "evidenceIds"),
artifact_refs: json_string_array_field(raw_result, "artifactRefs"),
runtime_result_id: json_string_field(raw_result, "runtimeResultId"),
runtime_job_id: json_string_field(raw_result, "runtimeJobId"),
job_error,
item_error,
}
}
pub fn build_role_acceptance_bundle(
binding_id: &str,
role: EpiphanyRoleAcceptanceFinding,
@ -1074,6 +1113,31 @@ mod tests {
assert_eq!(finding.runtime_result_id.as_deref(), Some("result-1"));
}
#[test]
fn projects_reorient_structured_output() {
let finding = interpret_reorient_finding(
&serde_json::json!({
"mode": "resume",
"summary": "Checkpoint is still warm.",
"nextSafeMove": "Continue the bounded cut.",
"checkpointStillValid": true,
"filesInspected": ["state/map.yaml"],
"frontierNodeIds": ["node-1"],
"evidenceIds": ["ev-1"],
"artifactRefs": ["artifact:reorient"],
"runtimeResultId": "result-1",
"runtimeJobId": "job-1"
}),
None,
None,
);
assert_eq!(finding.mode.as_deref(), Some("resume"));
assert_eq!(finding.checkpoint_still_valid, Some(true));
assert_eq!(finding.frontier_node_ids, vec!["node-1"]);
assert_eq!(finding.runtime_job_id.as_deref(), Some("job-1"));
}
#[test]
fn reviews_acceptable_self_patch() {
let finding = interpret_role_finding(

View file

@ -32,7 +32,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`.
- Top priority is still foundation cleanup until the documented rebuild audit is closed. Read `notes/epiphany-architectural-teardown.md` before touching Epiphany control-plane code. The May 2026 suspicion pass found that the app-server Epiphany control plane had become architectural Jenga: too much policy, projection, lifecycle glue, prompt packet assembly, coordinator sequencing, and test authority lives in `vendor/codex/codex-rs/app-server/src/codex_message_processor.rs`. The rebuild has moved scene projection, freshness derivation, pressure policy, targeted context shards, bounded graph traversal, job/progress view derivation, planning view derivation, reorientation resume/regather verdict policy, pure CRRC recommendation policy, fixed-lane coordinator decision policy, role-board projection policy, role-result interpretation/self-persistence review policy, and role/reorient acceptance bundle policy into `epiphany-core`; typed acceptance receipts replaced summary-string identity for live accept paths, runtime links are dual-written on launch, and result read-back now prefers runtime links.
- Top priority is still foundation cleanup until the documented rebuild audit is closed. Read `notes/epiphany-architectural-teardown.md` before touching Epiphany control-plane code. The May 2026 suspicion pass found that the app-server Epiphany control plane had become architectural Jenga: too much policy, projection, lifecycle glue, prompt packet assembly, coordinator sequencing, and test authority lives in `vendor/codex/codex-rs/app-server/src/codex_message_processor.rs`. The rebuild has moved scene projection, freshness derivation, pressure policy, targeted context shards, bounded graph traversal, job/progress view derivation, planning view derivation, reorientation resume/regather verdict policy, pure CRRC recommendation policy, fixed-lane coordinator decision policy, role-board projection policy, role/reorient result interpretation, role self-persistence review policy, and role/reorient acceptance bundle policy into `epiphany-core`; typed acceptance receipts replaced summary-string identity for live accept paths, runtime links are dual-written on launch, and result read-back now prefers runtime links.
- Read `notes/epiphany-ideal-architecture-rebuild-plan.md` immediately after the teardown. It defines the smallest coherent replacement architecture: durable `EpiphanyState`, runtime-spine-owned `RuntimeState`, separate role memory/heartbeat state, `epiphany-core` as policy owner, app-server as adapter, Aquarium as reflector, typed acceptance receipts, and derived view lenses instead of a protocol verb zoo.
- Do not continue Aquarium UI, bridge, Face, or dogfood expansion until the teardown has a source-grounded cleanup slice plan. Epiphany is the foundation; patches on patches are not a purification rite, they are how the altar becomes load-bearing garbage.
- Phase 1 through Phase 5 are complete enough.
@ -369,7 +369,7 @@ Phase 6 bridge/UI trail. Landed rebuild cuts: `epiphany-core/src/surfaces/`
exists, pressure view derivation/tests, pure CRRC recommendation policy/tests,
fixed-lane coordinator decision policy/tests, role-board projection policy/tests,
role-result interpretation/self-persistence review policy/tests, and role/reorient
acceptance bundle policy/tests, scene projection/tests, freshness derivation/tests, targeted context and graph traversal derivation/tests, planning view derivation/tests, reorientation resume/regather verdict policy/tests, and job/progress view derivation/tests live in core, live acceptance writes typed receipts keyed by runtime result id,
acceptance bundle policy/tests, scene projection/tests, freshness derivation/tests, targeted context and graph traversal derivation/tests, planning view derivation/tests, reorientation resume/regather verdict policy/tests, role/reorient result interpretation/tests, and job/progress view derivation/tests live in core, live acceptance writes typed receipts keyed by runtime result id,
summary-string acceptance identity is gone for live paths, launches dual-write
runtime links, result read-back prefers those runtime links, normal public
`raw_result` is sealed, MVP consumers use `thread/epiphany/view`, heartbeat

Binary file not shown.

View file

@ -272,5 +272,5 @@ rejected_paths:
reason: persistent state that accumulates every local truth becomes memory cruft and weakens rehydration
current_status:
summary: Phase 1 durable state through Phase 6 coordinator/specialist/CRRC/backend organs are landed, and the May 2026 rebuild has cut the main app-server control-plane tumor down to routing/adaptation for the documented MVP surfaces. Scene projection, freshness derivation, pressure, targeted context, bounded graph traversal, job/progress view derivation, planning view derivation, reorientation resume/regather verdicts, CRRC, coordinator, role-board, role-result interpretation/self-persistence review, and role/reorient acceptance bundle policy now live in `epiphany-core`; live duplicate-acceptance checks use runtime result receipt identity instead of summary strings; launch writes durable `runtime_links`; role/reorient result read-back follows runtime links; and `jobBindings` no longer store launcher/backend/progress lifecycle fields.
summary: Phase 1 durable state through Phase 6 coordinator/specialist/CRRC/backend organs are landed, and the May 2026 rebuild has cut the main app-server control-plane tumor down to routing/adaptation for the documented MVP surfaces. Scene projection, freshness derivation, pressure, targeted context, bounded graph traversal, job/progress view derivation, planning view derivation, reorientation resume/regather verdicts, CRRC, coordinator, role-board, role/reorient result interpretation, role self-persistence review, and role/reorient acceptance bundle policy now live in `epiphany-core`; live duplicate-acceptance checks use runtime result receipt identity instead of summary strings; launch writes durable `runtime_links`; role/reorient result read-back follows runtime links; and `jobBindings` no longer store launcher/backend/progress lifecycle fields.
next_action: Audit the remaining success criteria in `notes/epiphany-ideal-architecture-rebuild-plan.md` after the context/graph extraction commit. If no app-server-owned Epiphany policy cluster remains in the documented migration scope, mark the rebuild migration complete enough to defend, commit the persistence update, and only then resume outward Aquarium/bridge/Face/dogfood expansion.

View file

@ -543,6 +543,7 @@ use epiphany_core::EpiphanyPressureStatus as CoreEpiphanyPressureStatus;
use epiphany_core::EpiphanyReorientAcceptanceFinding;
use epiphany_core::EpiphanyReorientAction as CoreEpiphanyReorientAction;
use epiphany_core::EpiphanyReorientCheckpointStatus as CoreEpiphanyReorientCheckpointStatus;
use epiphany_core::EpiphanyReorientFindingInterpretation;
use epiphany_core::EpiphanyReorientFreshnessStatus as CoreEpiphanyReorientFreshnessStatus;
use epiphany_core::EpiphanyReorientInput;
use epiphany_core::EpiphanyReorientPressureLevel as CoreEpiphanyReorientPressureLevel;
@ -589,6 +590,7 @@ use epiphany_core::derive_pressure_view;
use epiphany_core::derive_role_board;
use epiphany_core::derive_scene;
use epiphany_core::imagination_role_state_patch_policy_errors;
use epiphany_core::interpret_reorient_finding;
use epiphany_core::interpret_role_finding;
use epiphany_core::modeling_role_state_patch_policy_errors;
use epiphany_core::recommend_coordinator_action;
@ -13295,21 +13297,29 @@ fn map_epiphany_reorient_finding(
job_error: Option<String>,
item_error: Option<String>,
) -> ThreadEpiphanyReorientFinding {
ThreadEpiphanyReorientFinding {
mode: json_string_field(&raw_result, "mode"),
summary: json_string_field(&raw_result, "summary"),
next_safe_move: json_string_field(&raw_result, "nextSafeMove"),
checkpoint_still_valid: raw_result
.get("checkpointStillValid")
.and_then(serde_json::Value::as_bool),
files_inspected: json_string_array_field(&raw_result, "filesInspected"),
frontier_node_ids: json_string_array_field(&raw_result, "frontierNodeIds"),
evidence_ids: json_string_array_field(&raw_result, "evidenceIds"),
artifact_refs: json_string_array_field(&raw_result, "artifactRefs"),
runtime_result_id: json_string_field(&raw_result, "runtimeResultId"),
runtime_job_id: json_string_field(&raw_result, "runtimeJobId"),
map_protocol_reorient_finding(interpret_reorient_finding(
&raw_result,
job_error,
item_error,
))
}
fn map_protocol_reorient_finding(
finding: EpiphanyReorientFindingInterpretation,
) -> ThreadEpiphanyReorientFinding {
ThreadEpiphanyReorientFinding {
mode: finding.mode,
summary: finding.summary,
next_safe_move: finding.next_safe_move,
checkpoint_still_valid: finding.checkpoint_still_valid,
files_inspected: finding.files_inspected,
frontier_node_ids: finding.frontier_node_ids,
evidence_ids: finding.evidence_ids,
artifact_refs: finding.artifact_refs,
runtime_result_id: finding.runtime_result_id,
runtime_job_id: finding.runtime_job_id,
job_error: finding.job_error,
item_error: finding.item_error,
}
}
@ -13422,13 +13432,6 @@ fn epiphany_imagination_finding_has_reviewable_state_patch(
.is_some_and(|patch| imagination_role_accept_patch_errors(patch).is_empty())
}
fn json_string_field(value: &serde_json::Value, key: &str) -> Option<String> {
value
.get(key)
.and_then(serde_json::Value::as_str)
.map(str::to_string)
}
fn role_finding_runtime_result_id(finding: &ThreadEpiphanyRoleFinding) -> Option<String> {
finding.runtime_result_id.clone()
}
@ -13445,20 +13448,6 @@ fn reorient_finding_runtime_job_id(finding: &ThreadEpiphanyReorientFinding) -> O
finding.runtime_job_id.clone()
}
fn json_string_array_field(value: &serde_json::Value, key: &str) -> Vec<String> {
value
.get(key)
.and_then(serde_json::Value::as_array)
.map(|values| {
values
.iter()
.filter_map(serde_json::Value::as_str)
.map(str::to_string)
.collect()
})
.unwrap_or_default()
}
fn render_epiphany_role_result_note(
role_id: ThreadEpiphanyRoleId,
status: ThreadEpiphanyRoleResultStatus,