Auto-select Epiphany proposal observations
This commit is contained in:
parent
fe7de41b76
commit
1add304813
7 changed files with 369 additions and 48 deletions
|
|
@ -17,6 +17,7 @@ use std::path::PathBuf;
|
|||
|
||||
const SUMMARY_LIMIT: usize = 220;
|
||||
const SEMANTIC_REUSE_MIN_SCORE: usize = 4;
|
||||
const AUTO_OBSERVATION_SELECTION_LIMIT: usize = 4;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct SelectionQuality {
|
||||
|
|
@ -43,6 +44,21 @@ struct ArchitectureMatch {
|
|||
kind: ArchitectureMatchKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct ObservationSelectionCandidate {
|
||||
observation_id: String,
|
||||
score: usize,
|
||||
index: usize,
|
||||
path_keys: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
struct ProposalFocus {
|
||||
dirty_paths: HashSet<String>,
|
||||
active_paths: HashSet<String>,
|
||||
mapped_paths: HashSet<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EpiphanyMapProposalInput {
|
||||
pub state: EpiphanyThreadState,
|
||||
|
|
@ -59,7 +75,7 @@ pub struct EpiphanyMapProposal {
|
|||
}
|
||||
|
||||
pub fn propose_map_update(input: EpiphanyMapProposalInput) -> Result<EpiphanyMapProposal> {
|
||||
let observation_ids = normalize_observation_ids(input.observation_ids)?;
|
||||
let observation_ids = proposal_observation_ids(&input.state, input.observation_ids)?;
|
||||
let observations = select_observations(&input.state, &observation_ids)?;
|
||||
let selection_quality = evaluate_selection_quality(&input.state, &observations)?;
|
||||
let code_refs = collect_code_refs(&observations)?;
|
||||
|
|
@ -184,7 +200,19 @@ pub fn propose_map_update(input: EpiphanyMapProposalInput) -> Result<EpiphanyMap
|
|||
})
|
||||
}
|
||||
|
||||
fn normalize_observation_ids(observation_ids: Vec<String>) -> Result<Vec<String>> {
|
||||
fn proposal_observation_ids(
|
||||
state: &EpiphanyThreadState,
|
||||
observation_ids: Vec<String>,
|
||||
) -> Result<Vec<String>> {
|
||||
let normalized = normalize_observation_ids(observation_ids);
|
||||
if normalized.is_empty() {
|
||||
select_automatic_observation_ids(state)
|
||||
} else {
|
||||
Ok(normalized)
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_observation_ids(observation_ids: Vec<String>) -> Vec<String> {
|
||||
let mut normalized = Vec::new();
|
||||
let mut seen = HashSet::new();
|
||||
for id in observation_ids {
|
||||
|
|
@ -196,11 +224,169 @@ fn normalize_observation_ids(observation_ids: Vec<String>) -> Result<Vec<String>
|
|||
normalized.push(id.to_string());
|
||||
}
|
||||
}
|
||||
if normalized.is_empty() {
|
||||
Err(anyhow!("observationIds must include at least one id"))
|
||||
} else {
|
||||
Ok(normalized)
|
||||
normalized
|
||||
}
|
||||
|
||||
fn select_automatic_observation_ids(state: &EpiphanyThreadState) -> Result<Vec<String>> {
|
||||
let focus = proposal_focus(state);
|
||||
let mut candidates = Vec::new();
|
||||
|
||||
for (index, observation) in state.observations.iter().enumerate() {
|
||||
if !is_verified_status(&observation.status) || observation.code_refs.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let Some(evidence_score) = accepting_evidence_score(state, observation) else {
|
||||
continue;
|
||||
};
|
||||
let path_keys = observation_path_keys(observation);
|
||||
if path_keys.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let score = observation_priority_score(observation)
|
||||
+ evidence_score
|
||||
+ observation_focus_score(&path_keys, &focus);
|
||||
candidates.push(ObservationSelectionCandidate {
|
||||
observation_id: observation.id.clone(),
|
||||
score,
|
||||
index,
|
||||
path_keys,
|
||||
});
|
||||
}
|
||||
|
||||
candidates.sort_by(|left, right| {
|
||||
right
|
||||
.score
|
||||
.cmp(&left.score)
|
||||
.then_with(|| left.index.cmp(&right.index))
|
||||
.then_with(|| left.observation_id.cmp(&right.observation_id))
|
||||
});
|
||||
|
||||
let Some(anchor) = candidates.first() else {
|
||||
return Err(anyhow!(
|
||||
"observationIds was omitted and no proposal-ready observations were found"
|
||||
));
|
||||
};
|
||||
let anchor_path_keys = anchor.path_keys.iter().cloned().collect::<HashSet<_>>();
|
||||
let mut selected = candidates
|
||||
.iter()
|
||||
.filter(|candidate| {
|
||||
candidate
|
||||
.path_keys
|
||||
.iter()
|
||||
.any(|path_key| anchor_path_keys.contains(path_key))
|
||||
})
|
||||
.take(AUTO_OBSERVATION_SELECTION_LIMIT)
|
||||
.map(|candidate| (candidate.index, candidate.observation_id.clone()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
selected.sort_by_key(|(index, _)| *index);
|
||||
Ok(selected
|
||||
.into_iter()
|
||||
.map(|(_, observation_id)| observation_id)
|
||||
.collect())
|
||||
}
|
||||
|
||||
fn accepting_evidence_score(
|
||||
state: &EpiphanyThreadState,
|
||||
observation: &EpiphanyObservation,
|
||||
) -> Option<usize> {
|
||||
if observation.evidence_ids.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut score = 0usize;
|
||||
for evidence_id in &observation.evidence_ids {
|
||||
let evidence = state
|
||||
.recent_evidence
|
||||
.iter()
|
||||
.find(|evidence| evidence.id == *evidence_id)?;
|
||||
if !is_verified_status(&evidence.status) {
|
||||
return None;
|
||||
}
|
||||
score += evidence_priority_score(evidence);
|
||||
}
|
||||
Some(score)
|
||||
}
|
||||
|
||||
fn proposal_focus(state: &EpiphanyThreadState) -> ProposalFocus {
|
||||
let mut focus = ProposalFocus::default();
|
||||
if let Some(frontier) = state.graph_frontier.as_ref() {
|
||||
for dirty_path in &frontier.dirty_paths {
|
||||
focus.dirty_paths.insert(path_key(dirty_path));
|
||||
}
|
||||
for active_node_id in &frontier.active_node_ids {
|
||||
collect_active_node_paths(&mut focus.active_paths, &state.graphs, active_node_id);
|
||||
}
|
||||
}
|
||||
|
||||
collect_mapped_paths(&mut focus.mapped_paths, &state.graphs.architecture.nodes);
|
||||
collect_mapped_paths(&mut focus.mapped_paths, &state.graphs.dataflow.nodes);
|
||||
for link in &state.graphs.links {
|
||||
collect_code_ref_paths(&mut focus.mapped_paths, &link.code_refs);
|
||||
}
|
||||
|
||||
focus
|
||||
}
|
||||
|
||||
fn collect_active_node_paths(
|
||||
target: &mut HashSet<String>,
|
||||
graphs: &EpiphanyGraphs,
|
||||
active_node_id: &str,
|
||||
) {
|
||||
for node in graphs
|
||||
.architecture
|
||||
.nodes
|
||||
.iter()
|
||||
.chain(graphs.dataflow.nodes.iter())
|
||||
{
|
||||
if node.id == active_node_id {
|
||||
collect_code_ref_paths(target, &node.code_refs);
|
||||
}
|
||||
}
|
||||
for link in &graphs.links {
|
||||
if link.architecture_node_id == active_node_id || link.dataflow_node_id == active_node_id {
|
||||
collect_code_ref_paths(target, &link.code_refs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_mapped_paths(target: &mut HashSet<String>, nodes: &[EpiphanyGraphNode]) {
|
||||
for node in nodes {
|
||||
collect_code_ref_paths(target, &node.code_refs);
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_code_ref_paths(target: &mut HashSet<String>, code_refs: &[EpiphanyCodeRef]) {
|
||||
for code_ref in code_refs {
|
||||
target.insert(path_key(&code_ref.path));
|
||||
}
|
||||
}
|
||||
|
||||
fn observation_path_keys(observation: &EpiphanyObservation) -> Vec<String> {
|
||||
let mut path_keys = Vec::new();
|
||||
let mut seen = HashSet::new();
|
||||
for code_ref in &observation.code_refs {
|
||||
let key = path_key(&code_ref.path);
|
||||
if seen.insert(key.clone()) {
|
||||
path_keys.push(key);
|
||||
}
|
||||
}
|
||||
path_keys
|
||||
}
|
||||
|
||||
fn observation_focus_score(path_keys: &[String], focus: &ProposalFocus) -> usize {
|
||||
let mut score = 0usize;
|
||||
for path_key in path_keys {
|
||||
if focus.dirty_paths.contains(path_key) {
|
||||
score += 4;
|
||||
}
|
||||
if focus.active_paths.contains(path_key) {
|
||||
score += 3;
|
||||
}
|
||||
if focus.mapped_paths.contains(path_key) {
|
||||
score += 2;
|
||||
}
|
||||
}
|
||||
score
|
||||
}
|
||||
|
||||
fn select_observations<'a>(
|
||||
|
|
@ -662,13 +848,17 @@ fn fingerprint(
|
|||
fn code_ref_key(code_ref: &EpiphanyCodeRef) -> String {
|
||||
format!(
|
||||
"{}:{}:{}:{}",
|
||||
code_ref.path.to_string_lossy(),
|
||||
path_key(&code_ref.path),
|
||||
code_ref.start_line.unwrap_or_default(),
|
||||
code_ref.end_line.unwrap_or_default(),
|
||||
code_ref.symbol.as_deref().unwrap_or_default()
|
||||
)
|
||||
}
|
||||
|
||||
fn path_key(path: &Path) -> String {
|
||||
path.to_string_lossy().replace('\\', "/")
|
||||
}
|
||||
|
||||
fn push_code_ref_semantic_terms(
|
||||
target: &mut Vec<String>,
|
||||
seen: &mut HashSet<String>,
|
||||
|
|
@ -1085,6 +1275,128 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn propose_map_update_auto_selects_best_proposal_ready_observations_when_ids_are_omitted() {
|
||||
let mut state = state_with_observation("ok");
|
||||
state.observations[0].id = "obs-weak".to_string();
|
||||
state.observations[0].source_kind = "observation".to_string();
|
||||
state.observations[0].summary = "Prompt renderer might be involved".to_string();
|
||||
state.observations[0].evidence_ids = vec!["ev-weak".to_string()];
|
||||
state.recent_evidence[0].id = "ev-weak".to_string();
|
||||
state.recent_evidence[0].kind = "observation".to_string();
|
||||
state.recent_evidence[0].summary = "Manual note mentioned prompt renderer".to_string();
|
||||
state.observations.push(EpiphanyObservation {
|
||||
id: "obs-failed".to_string(),
|
||||
summary: "Failed candidate should not be selected".to_string(),
|
||||
source_kind: "verification".to_string(),
|
||||
status: "failed".to_string(),
|
||||
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
|
||||
evidence_ids: vec!["ev-failed".to_string()],
|
||||
});
|
||||
state.recent_evidence.push(EpiphanyEvidenceRecord {
|
||||
id: "ev-failed".to_string(),
|
||||
kind: "verification".to_string(),
|
||||
status: "failed".to_string(),
|
||||
summary: "Verifier rejected the failed candidate".to_string(),
|
||||
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
|
||||
});
|
||||
state.observations.push(EpiphanyObservation {
|
||||
id: "obs-strong".to_string(),
|
||||
summary: "Live smoke verified prompt renderer Epiphany state injection".to_string(),
|
||||
source_kind: "smoke".to_string(),
|
||||
status: "ok".to_string(),
|
||||
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
|
||||
evidence_ids: vec!["ev-strong".to_string()],
|
||||
});
|
||||
state.recent_evidence.push(EpiphanyEvidenceRecord {
|
||||
id: "ev-strong".to_string(),
|
||||
kind: "verification".to_string(),
|
||||
status: "ok".to_string(),
|
||||
summary: "Verifier accepted prompt renderer state injection".to_string(),
|
||||
code_refs: vec![code_ref("epiphany-core/src/prompt.rs")],
|
||||
});
|
||||
|
||||
let proposal = propose_map_update(EpiphanyMapProposalInput {
|
||||
state,
|
||||
observation_ids: Vec::new(),
|
||||
})
|
||||
.expect("auto-selected proposal");
|
||||
|
||||
assert!(
|
||||
proposal
|
||||
.observation
|
||||
.summary
|
||||
.contains("primary observation: obs-strong")
|
||||
);
|
||||
assert!(!proposal.observation.summary.contains("obs-failed"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn propose_map_update_auto_selection_prefers_frontier_dirty_path_cluster() {
|
||||
let mut state = state_with_observation("ok");
|
||||
state.graph_frontier = Some(EpiphanyGraphFrontier {
|
||||
dirty_paths: vec![PathBuf::from("epiphany-core/src/prompt.rs")],
|
||||
..Default::default()
|
||||
});
|
||||
state.observations.push(EpiphanyObservation {
|
||||
id: "obs-other".to_string(),
|
||||
summary: "Proposal engine update is verified but not current frontier focus"
|
||||
.to_string(),
|
||||
source_kind: "verification".to_string(),
|
||||
status: "ok".to_string(),
|
||||
code_refs: vec![code_ref("epiphany-core/src/proposal.rs")],
|
||||
evidence_ids: vec!["ev-other".to_string()],
|
||||
});
|
||||
state.recent_evidence.push(EpiphanyEvidenceRecord {
|
||||
id: "ev-other".to_string(),
|
||||
kind: "verification".to_string(),
|
||||
status: "ok".to_string(),
|
||||
summary: "Verifier accepted proposal engine behavior".to_string(),
|
||||
code_refs: vec![code_ref("epiphany-core/src/proposal.rs")],
|
||||
});
|
||||
|
||||
let proposal = propose_map_update(EpiphanyMapProposalInput {
|
||||
state,
|
||||
observation_ids: Vec::new(),
|
||||
})
|
||||
.expect("auto-selected proposal");
|
||||
|
||||
assert!(
|
||||
proposal.observation.summary.contains("obs-verified"),
|
||||
"{}",
|
||||
proposal.observation.summary
|
||||
);
|
||||
assert!(
|
||||
proposal
|
||||
.graph_frontier
|
||||
.dirty_paths
|
||||
.contains(&PathBuf::from("epiphany-core/src/prompt.rs"))
|
||||
);
|
||||
assert!(
|
||||
!proposal
|
||||
.graph_frontier
|
||||
.dirty_paths
|
||||
.contains(&PathBuf::from("epiphany-core/src/proposal.rs"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn propose_map_update_auto_selection_rejects_when_no_candidate_is_ready() {
|
||||
let mut state = state_with_observation("failed");
|
||||
state.recent_evidence.clear();
|
||||
|
||||
let err = propose_map_update(EpiphanyMapProposalInput {
|
||||
state,
|
||||
observation_ids: Vec::new(),
|
||||
})
|
||||
.expect_err("auto-selection needs proposal-ready observations");
|
||||
|
||||
assert!(
|
||||
err.to_string()
|
||||
.contains("no proposal-ready observations were found")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn propose_map_update_focuses_linked_nodes_and_incident_edges() {
|
||||
let mut state = state_with_observation("verified");
|
||||
|
|
|
|||
|
|
@ -677,18 +677,18 @@ Distillation is read-only. It does not mutate `SessionState`, does not persist r
|
|||
A client sends experimental `thread/epiphany/propose` for a loaded thread with:
|
||||
|
||||
- `threadId`
|
||||
- `observationIds`
|
||||
- optional `observationIds`
|
||||
|
||||
### Plain-language role
|
||||
|
||||
Proposal is the tracing-paper path. It starts from observations that are already in the thread's typed state, requires those observations to have verified/accepted status, requires each selected observation to cite accepting `recent_evidence`, requires source-grounding through code refs, and returns a candidate patch that can replace graph/frontier/churn fields only if a later promotion accepts it.
|
||||
Proposal is the tracing-paper path. It starts from observations that are already in the thread's typed state, chooses a small proposal-ready set when `observationIds` is omitted, requires selected observations to have verified/accepted status, requires each selected observation to cite accepting `recent_evidence`, requires source-grounding through code refs, and returns a candidate patch that can replace graph/frontier/churn fields only if a later promotion accepts it.
|
||||
|
||||
This is the first shipped chewing motion. It is deliberately small: no model call, no watcher invalidation, no automatic graph truth. It now first checks that selected observations are backed by current accepting evidence, scores the selected observations so the strongest verifier/test/smoke-backed signal becomes the proposal's primary summary, then tries to match observed code refs against existing architecture nodes. Concrete matching still wins: exact code refs, same-path refs, and deterministic path-node ids are tried before anything semantic. Only after those fail can strict semantic overlap reuse an existing architecture node, and only when that graph node has no code refs yet; anchored nodes stay governed by concrete refs because otherwise the map starts doing interpretive dance in a trench coat. Proposal then enriches matching nodes with newly observed refs, creates path-derived candidate nodes only for genuinely unmapped surfaces, expands frontier focus through graph links, marks named incident edges active, emits a proposal observation/evidence pair, and marks churn according to whether the proposal refined, expanded, or mixed the map. Diff pressure now reflects the proposed map delta, touched paths, observation count, and unresolved write risk instead of blindly inheriting the previous pressure. It is a candidate, not an oracle. We do not crown the goblin because it found a wrench.
|
||||
This is the first shipped chewing motion. It is deliberately small: no model call, no watcher invalidation, no automatic graph truth. When ids are omitted, proposal now ranks proposal-ready observations by source/evidence strength, code refs, and current map focus, then keeps a bounded coherent path cluster instead of grabbing every shiny pebble in the yard. It then checks that selected observations are backed by current accepting evidence, scores the selected observations so the strongest verifier/test/smoke-backed signal becomes the proposal's primary summary, and tries to match observed code refs against existing architecture nodes. Concrete matching still wins: exact code refs, same-path refs, and deterministic path-node ids are tried before anything semantic. Only after those fail can strict semantic overlap reuse an existing architecture node, and only when that graph node has no code refs yet; anchored nodes stay governed by concrete refs because otherwise the map starts doing interpretive dance in a trench coat. Proposal then enriches matching nodes with newly observed refs, creates path-derived candidate nodes only for genuinely unmapped surfaces, expands frontier focus through graph links, marks named incident edges active, emits a proposal observation/evidence pair, and marks churn according to whether the proposal refined, expanded, or mixed the map. Diff pressure now reflects the proposed map delta, touched paths, observation count, and unresolved write risk instead of blindly inheriting the previous pressure. It is a candidate, not an oracle. We do not crown the goblin because it found a wrench.
|
||||
|
||||
Protocol shape:
|
||||
|
||||
- `threadId`
|
||||
- `observationIds`
|
||||
- optional `observationIds`; empty or omitted means deterministic auto-selection from existing proposal-ready observations
|
||||
|
||||
Response shape:
|
||||
|
||||
|
|
@ -720,33 +720,36 @@ The app-server handler:
|
|||
`propose_map_update`:
|
||||
|
||||
1. normalizes and deduplicates requested observation ids.
|
||||
2. rejects unknown observations.
|
||||
3. rejects observations whose status is not accepting: `ok`, `accepted`, `verified`, `pass`, or `passed`.
|
||||
4. rejects selected observations that do not cite existing accepting `recent_evidence`.
|
||||
5. rejects proposals without code refs.
|
||||
6. scores selected observations and evidence by source kind, evidence kind, code refs, and summary presence so proposal wording is anchored to the strongest selected signal instead of raw id order.
|
||||
7. builds semantic terms from selected observations, accepting evidence, code-ref paths, symbols, and notes.
|
||||
8. clones the current graphs and searches architecture nodes for exact code-ref overlap, same-path overlap, then the deterministic path-node id.
|
||||
9. if no concrete match exists, searches unanchored architecture nodes for a unique strong semantic match and refuses tied semantic matches.
|
||||
10. enriches matching architecture nodes with newly observed refs, preserving their existing title/purpose/status.
|
||||
11. creates path-derived candidate architecture nodes only when no existing node matches that code path or unanchored graph language.
|
||||
12. expands focused node ids through graph links so architecture nodes pull their linked dataflow nodes into the frontier, and vice versa.
|
||||
13. marks named graph edges incident to focused nodes as active.
|
||||
14. merges focused node ids, active edge ids, and observed paths into the graph frontier.
|
||||
15. emits a proposal observation/evidence pair tied to the candidate patch, including evidence-backed selection counts, priority label, primary observation id, and reused/created node counts.
|
||||
16. emits churn with `proposal_refines_map`, `proposal_expands_map`, or `proposal_updates_map` depending on whether the candidate reused existing nodes, created new nodes, or did both.
|
||||
17. emits `diff_pressure` from the proposal shape: low for narrow refinements, medium for new single-surface expansion, and high for mixed/multi-path/multi-observation changes or existing unexplained writes.
|
||||
2. when no ids are supplied, ranks proposal-ready observations and selects up to four observations from the strongest coherent path cluster.
|
||||
3. the automatic ranker ignores observations without accepting status, code refs, or accepting `recent_evidence`; it scores source kind, evidence kind, code refs, summary presence, frontier dirty paths, active-node paths, and already mapped paths.
|
||||
4. rejects unknown explicitly requested observations.
|
||||
5. rejects selected observations whose status is not accepting: `ok`, `accepted`, `verified`, `pass`, or `passed`.
|
||||
6. rejects selected observations that do not cite existing accepting `recent_evidence`.
|
||||
7. rejects proposals without code refs.
|
||||
8. scores selected observations and evidence by source kind, evidence kind, code refs, and summary presence so proposal wording is anchored to the strongest selected signal instead of raw id order.
|
||||
9. builds semantic terms from selected observations, accepting evidence, code-ref paths, symbols, and notes.
|
||||
10. clones the current graphs and searches architecture nodes for exact code-ref overlap, same-path overlap, then the deterministic path-node id.
|
||||
11. if no concrete match exists, searches unanchored architecture nodes for a unique strong semantic match and refuses tied semantic matches.
|
||||
12. enriches matching architecture nodes with newly observed refs, preserving their existing title/purpose/status.
|
||||
13. creates path-derived candidate architecture nodes only when no existing node matches that code path or unanchored graph language.
|
||||
14. expands focused node ids through graph links so architecture nodes pull their linked dataflow nodes into the frontier, and vice versa.
|
||||
15. marks named graph edges incident to focused nodes as active.
|
||||
16. merges focused node ids, active edge ids, and observed paths into the graph frontier.
|
||||
17. emits a proposal observation/evidence pair tied to the candidate patch, including evidence-backed selection counts, priority label, primary observation id, and reused/created node counts.
|
||||
18. emits churn with `proposal_refines_map`, `proposal_expands_map`, or `proposal_updates_map` depending on whether the candidate reused existing nodes, created new nodes, or did both.
|
||||
19. emits `diff_pressure` from the proposal shape: low for narrow refinements, medium for new single-surface expansion, and high for mixed/multi-path/multi-observation changes or existing unexplained writes.
|
||||
|
||||
Code refs:
|
||||
|
||||
- [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4244)
|
||||
- [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4287)
|
||||
- [codex_message_processor.rs](E:/Projects/EpiphanyAgent/vendor/codex/codex-rs/app-server/src/codex_message_processor.rs:4301)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:61)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:228)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:419)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:479)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:770)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:77)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:203)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:230)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:310)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:376)
|
||||
- [epiphany-core/src/proposal.rs](E:/Projects/EpiphanyAgent/epiphany-core/src/proposal.rs:1008)
|
||||
|
||||
### Output
|
||||
|
||||
|
|
@ -858,7 +861,7 @@ stored Epiphany state
|
|||
-> explicit update patches can revise durable map/evidence/churn state
|
||||
```
|
||||
|
||||
The current remaining missing organ is not the red pen and not the first chewing motion. Those exist. Proposal now has the first bits of map memory, focus, and selection hygiene: it requires accepting recent evidence behind selected observations, prioritizes stronger selected observations for proposal wording, reuses existing architecture nodes by concrete code-ref/path/id checks before creating new path nodes, can rescue unanchored graph nodes through strict unique semantic overlap, follows graph links and incident edges into the frontier, and reports churn pressure from the actual proposal shape. The missing organ is broader judgment: automatic observation selection beyond caller-supplied ids, watcher/freshness inputs, and eventually role-scoped specialist ownership without silently auto-promoting anything.
|
||||
The current remaining missing organ is not the red pen and not the first chewing motion. Those exist. Proposal now has the first bits of map memory, focus, and selection hygiene: it can auto-select a bounded evidence-backed observation cluster when ids are omitted, requires accepting recent evidence behind selected observations, prioritizes stronger selected observations for proposal wording, reuses existing architecture nodes by concrete code-ref/path/id checks before creating new path nodes, can rescue unanchored graph nodes through strict unique semantic overlap, follows graph links and incident edges into the frontier, and reports churn pressure from the actual proposal shape. The missing organ is broader judgment from fresh tool/model output, watcher/freshness inputs, richer map-delta classification, and eventually role-scoped specialist ownership without silently auto-promoting anything.
|
||||
|
||||
```text
|
||||
model/tool observations
|
||||
|
|
@ -869,9 +872,9 @@ model/tool observations
|
|||
-> durable evidence/map/churn mutation
|
||||
```
|
||||
|
||||
The typed write path exists, the first deterministic observation/evidence distillation path exists, the first deterministic map/churn proposal path exists, proposal-quality hardening now requires accepting recent evidence, reuses existing graph nodes by observed code refs, prioritizes stronger selected observations, rescues unanchored graph nodes by strict semantic overlap, focuses linked frontier context, reports map-delta pressure, and the first verifier-backed promotion gate exists. The first map/churn safety layer also exists: promotion can reject state replacement patches that are not tied to explicit observations/evidence or that contain structurally broken subgoal, invariant, graph, frontier, checkpoint, or churn fields.
|
||||
The typed write path exists, the first deterministic observation/evidence distillation path exists, the first deterministic map/churn proposal path exists, proposal-quality hardening now auto-selects bounded observation clusters when ids are omitted, requires accepting recent evidence, reuses existing graph nodes by observed code refs, prioritizes stronger selected observations, rescues unanchored graph nodes by strict semantic overlap, focuses linked frontier context, reports map-delta pressure, and the first verifier-backed promotion gate exists. The first map/churn safety layer also exists: promotion can reject state replacement patches that are not tied to explicit observations/evidence or that contain structurally broken subgoal, invariant, graph, frontier, checkpoint, or churn fields.
|
||||
|
||||
In natural language: current Epiphany can preserve a map, show a map, retrieve evidence for the map, draft one explicit observation/evidence patch, derive a bounded graph/frontier/churn candidate from verified evidence-backed observations with code refs, favor the strongest selected observation when drafting that candidate, reject or accept a verified candidate, apply explicit map/evidence/churn edits, and sanity-check those edits before they hit the ledger. It still does not automatically choose the observation set, invalidate stale graph regions, or coordinate specialist ownership. Teeth are installed; chewing is supervised; the next slices are about taste, not jawbones.
|
||||
In natural language: current Epiphany can preserve a map, show a map, retrieve evidence for the map, draft one explicit observation/evidence patch, derive a bounded graph/frontier/churn candidate from verified evidence-backed observations with code refs, choose a small coherent observation set when the caller does not provide one, favor the strongest selected observation when drafting that candidate, reject or accept a verified candidate, apply explicit map/evidence/churn edits, and sanity-check those edits before they hit the ledger. It still does not ingest fresh tool/model output into richer map deltas automatically, invalidate stale graph regions, or coordinate specialist ownership. Teeth are installed; chewing is supervised; the next slices are about taste, not jawbones.
|
||||
|
||||
## Verification Hooks
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ This note tracks Epiphany as a fork of Codex with an opinionated modeling archit
|
|||
- a frontier-focus hardening slice that expands proposal frontier focus through existing graph links and marks named incident graph edges active, so prompt rendering gets the relevant architecture/dataflow context instead of one lonely node with a tiny hat
|
||||
- an evidence-selection/churn hardening slice that requires selected proposal observations to cite accepting `recent_evidence` and derives proposal `diff_pressure` from the candidate map delta, touched paths, selected observation count, and unresolved write risk
|
||||
- a graph-semantic proposal hardening slice that scores selected observations/evidence, uses the strongest selected signal for proposal wording, and can reuse unanchored architecture graph nodes through strict unique semantic overlap while refusing ambiguous matches and leaving code-anchored nodes under concrete ref/path/id matching
|
||||
- an automatic observation-selection slice that lets read-only `thread/epiphany/propose` omit `observationIds`; `epiphany-core` then chooses a bounded coherent path cluster from existing verified, evidence-backed observations using source/evidence quality and current graph-frontier focus
|
||||
- current phase: Phase 5 semantic distillation/promotion/proposal machinery
|
||||
|
||||
The next job is no longer to prove the retriever exists, sketch the persistent follow-up in prose, invent the first red-pen path, build the first observation proposal surface, make promotion notice broken map/churn replacements, ship the first read-only map/churn proposal surface, teach proposal to avoid duplicating already-mapped code surfaces, make proposal frontier focus follow existing graph links, make selected observations evidence-backed with non-haunted churn pressure, or rescue unanchored graph nodes with strict semantic matching. Those parts are landed. The next job is to keep the landing zone honest: do not casually turn `thread/epiphany/retrieve`, `thread/epiphany/distill`, or `thread/epiphany/propose` into durable Epiphany-state writers, and do not widen the explicit indexing/update paths into watcher-driven or GUI-shaped machinery before they earn it.
|
||||
The next job is no longer to prove the retriever exists, sketch the persistent follow-up in prose, invent the first red-pen path, build the first observation proposal surface, make promotion notice broken map/churn replacements, ship the first read-only map/churn proposal surface, teach proposal to avoid duplicating already-mapped code surfaces, make proposal frontier focus follow existing graph links, make selected observations evidence-backed with non-haunted churn pressure, rescue unanchored graph nodes with strict semantic matching, or let proposal choose a bounded ready observation set when ids are omitted. Those parts are landed. The next job is to keep the landing zone honest: do not casually turn `thread/epiphany/retrieve`, `thread/epiphany/distill`, or `thread/epiphany/propose` into durable Epiphany-state writers, and do not widen the explicit indexing/update paths into watcher-driven or GUI-shaped machinery before they earn it.
|
||||
|
||||
## Summary
|
||||
|
||||
|
|
@ -272,7 +273,7 @@ Add tests for:
|
|||
|
||||
## Immediate Next Step
|
||||
|
||||
Treat the current retrieval baseline and explicit indexing follow-up as landed Phase 4. Treat the explicit update path, distillation proposal path, read-only map/churn proposal path, verifier-backed promotion gate, structural map/churn promotion validation, graph-node reuse, linked frontier focus, evidence-backed selection, map-delta churn pressure, selected-observation prioritization, and strict unanchored-node semantic reuse as the active Phase 5 baseline. The next machine gap is no longer "can Epiphany retrieve code?", "can it propose one durable observation patch?", "can it draft one bounded map/churn candidate?", "can it avoid duplicating an existing graph node when an observation points at already-mapped code?", "can it focus linked graph context?", "can it reject selected observations that are not backed by accepting recent evidence?", or "can it use graph language when no concrete refs exist yet?" It can. The next gap is "can Epiphany choose good observation sets and richer map deltas from tool/model output without silently promoting them?"
|
||||
Treat the current retrieval baseline and explicit indexing follow-up as landed Phase 4. Treat the explicit update path, distillation proposal path, read-only map/churn proposal path, verifier-backed promotion gate, structural map/churn promotion validation, graph-node reuse, linked frontier focus, evidence-backed selection, map-delta churn pressure, selected-observation prioritization, strict unanchored-node semantic reuse, and automatic bounded observation-set selection as the active Phase 5 baseline. The next machine gap is no longer "can Epiphany retrieve code?", "can it propose one durable observation patch?", "can it draft one bounded map/churn candidate?", "can it avoid duplicating an existing graph node when an observation points at already-mapped code?", "can it focus linked graph context?", "can it reject selected observations that are not backed by accepting recent evidence?", "can it use graph language when no concrete refs exist yet?", or "can it choose a proposal-ready observation set when ids are omitted?" It can. The next gap is "can Epiphany make richer map-delta judgments from tool/model output without silently promoting them?"
|
||||
|
||||
1. treat the current verified-and-landed query-time hybrid retriever as the Phase 4 slice 1 baseline
|
||||
2. treat the verified and live-smoked `thread/epiphany/index` slice as the bounded persistent-semantic follow-up
|
||||
|
|
@ -280,8 +281,8 @@ Treat the current retrieval baseline and explicit indexing follow-up as landed P
|
|||
4. do not add durable retrieval-summary writes from `thread/epiphany/retrieve` without a clean out-of-band rollout/update semantic
|
||||
5. continue Phase 5 by hardening the layer above the landed distill/propose/promote/update surfaces:
|
||||
- richer typed observation distillation from tool/model outputs
|
||||
- better proposal heuristics beyond the current exact-code-ref, same-path, deterministic-id, graph-link, accepting-evidence, semantic-unanchored-node, selected-priority, and map-delta-pressure checks
|
||||
- better observation set selection beyond caller-supplied ids and evidence links
|
||||
- better proposal heuristics beyond the current exact-code-ref, same-path, deterministic-id, graph-link, accepting-evidence, semantic-unanchored-node, selected-priority, auto-selection, and map-delta-pressure checks
|
||||
- richer map-delta judgment beyond the current bounded path-cluster proposal heuristic
|
||||
- promotion policy beyond structural validation, but only when it can stay evidence-backed
|
||||
- verifier-backed acceptance/rejection evidence
|
||||
- no hidden retrieval writes
|
||||
|
|
|
|||
|
|
@ -356,7 +356,8 @@ If a future session wakes up from compaction and starts bluffing, this is the pa
|
|||
- dedicated experimental `thread/epiphany/update`, `thread/epiphany/distill`, and `thread/epiphany/promote` exist and are live-smoked
|
||||
- structural map/churn promotion validation is landed in `epiphany-core`
|
||||
- proposal selection now rejects observations without accepting `recent_evidence`, and churn pressure now reflects map-delta shape
|
||||
- the next bounded follow-up is richer observation-set selection and map-delta judgment beyond caller-supplied ids/evidence/path/link/semantic-unanchored matching, not proving the retriever exists again
|
||||
- proposal can now omit `observationIds` and let `epiphany-core` choose a bounded coherent path cluster from existing verified, evidence-backed observations using source/evidence quality plus graph-frontier focus
|
||||
- the next bounded follow-up is richer map-delta judgment beyond the current evidence/path/link/semantic-unanchored/auto-selected path-cluster matching, not proving the retriever exists again
|
||||
- There is still no live `thread/epiphany/*` notification stream.
|
||||
- The next phase is **not** GUI work.
|
||||
- The current pushed baseline also extracted most Epiphany-owned implementation into `epiphany-core`:
|
||||
|
|
@ -451,9 +452,9 @@ Without that, you get to learn about `symlink_dir failed: ... A required privile
|
|||
|
||||
## Recommended Next Implementation
|
||||
|
||||
Do not restart verification from superstition. Phase 4 retrieval/indexing/core-extraction is already verified, committed, and pushed. Phase 5 distill/propose/promote/update, the first structural promotion safety layer, graph-node reuse, linked frontier focus, evidence-backed proposal selection, selected-observation prioritization, strict unanchored-node semantic reuse, and map-delta churn pressure are also landed.
|
||||
Do not restart verification from superstition. Phase 4 retrieval/indexing/core-extraction is already verified, committed, and pushed. Phase 5 distill/propose/promote/update, the first structural promotion safety layer, graph-node reuse, linked frontier focus, evidence-backed proposal selection, selected-observation prioritization, strict unanchored-node semantic reuse, automatic bounded observation selection, and map-delta churn pressure are also landed.
|
||||
|
||||
The durable state seam exists, the turn loop reads it, clients can load typed Epiphany state directly, the first retrieval slice is real, the explicit persistent-semantic indexing path is landed, the distill/propose/promote/update path is live-smoked, promotion now has a first structural map/churn safety layer, and proposal now reuses existing architecture nodes before creating new path nodes, expands frontier focus through linked graph context, rejects selected observations without accepting recent evidence, prioritizes stronger selected observations for proposal wording, can reuse unanchored architecture nodes through strict semantic overlap, and reports churn pressure from the proposal shape. The next clean move is automatic observation-set selection and richer map-delta judgment, not pretending the already-shipped slices still need ceremony.
|
||||
The durable state seam exists, the turn loop reads it, clients can load typed Epiphany state directly, the first retrieval slice is real, the explicit persistent-semantic indexing path is landed, the distill/propose/promote/update path is live-smoked, promotion now has a first structural map/churn safety layer, and proposal now reuses existing architecture nodes before creating new path nodes, expands frontier focus through linked graph context, rejects selected observations without accepting recent evidence, prioritizes stronger selected observations for proposal wording, can reuse unanchored architecture nodes through strict semantic overlap, can auto-select a bounded evidence-backed observation cluster when ids are omitted, and reports churn pressure from the proposal shape. The next clean move is richer map-delta judgment, not pretending the already-shipped slices still need ceremony.
|
||||
|
||||
Current Phase 5 implementation move:
|
||||
|
||||
|
|
@ -462,7 +463,7 @@ Current Phase 5 implementation move:
|
|||
3. keep `thread/epiphany/retrieve`, `thread/epiphany/distill`, and `thread/epiphany/propose` read-only
|
||||
4. continue Phase 5 by hardening the next layer above the distill/propose/promote/update surfaces:
|
||||
- richer map/churn patch generation from verified observations and tool/model outputs
|
||||
- better observation-set selection beyond caller-supplied ids/evidence links, plus richer map-delta judgment than the current exact refs/same path/deterministic ids/graph links/strict unanchored semantic matching
|
||||
- richer map-delta judgment than the current exact refs/same path/deterministic ids/graph links/strict unanchored semantic matching and bounded auto-selected path clusters
|
||||
- promotion policy beyond structural validation only when the evidence path stays explicit
|
||||
- verifier-backed acceptance/rejection evidence
|
||||
- no GUI, watcher, or specialist-agent machinery yet
|
||||
|
|
@ -503,4 +504,4 @@ cmd /c "\"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxi
|
|||
|
||||
The repo is in a good state.
|
||||
|
||||
Phase 1, Phase 2, the minimal Phase 3 typed read surface, Phase 4 retrieval/indexing/core-extraction, and the current Phase 5 distill/propose/promote/update baseline are landed and verified. `vendor/codex` is first-class in the parent repo now, with the heavier Epiphany organs living in `epiphany-core`. The next clean move is richer observation-set selection and map-delta judgment above the read-only proposal path, not GUI paint, watcher magic, or re-proving retrieval. Pre-compaction persistence is now an explicit design rule, not a lucky habit.
|
||||
Phase 1, Phase 2, the minimal Phase 3 typed read surface, Phase 4 retrieval/indexing/core-extraction, and the current Phase 5 distill/propose/promote/update baseline are landed and verified. `vendor/codex` is first-class in the parent repo now, with the heavier Epiphany organs living in `epiphany-core`. Read-only proposal can now auto-select a bounded evidence-backed observation cluster when ids are omitted. The next clean move is richer map-delta judgment above the read-only proposal path, not GUI paint, watcher magic, or re-proving retrieval. Pre-compaction persistence is now an explicit design rule, not a lucky habit.
|
||||
|
|
|
|||
|
|
@ -112,3 +112,5 @@
|
|||
{"ts": "2026-04-25T02:31:31+00:00", "type": "implementation", "status": "ok", "note": "Hardened read-only thread/epiphany/propose graph semantics in epiphany-core. propose_map_update now scores selected observations/evidence, uses the strongest selected verifier/test/smoke-backed signal for candidate wording, reuses unanchored architecture nodes through strict unique semantic overlap, refuses ambiguous semantic matches, and keeps code-anchored nodes governed by concrete exact-ref/same-path/deterministic-id matching."}
|
||||
{"ts": "2026-04-25T02:31:35+00:00", "type": "verification", "status": "ok", "note": "Verified graph-semantic proposal hardening with cargo fmt --manifest-path .\\epiphany-core\\Cargo.toml, cargo test --manifest-path .\\epiphany-core\\Cargo.toml proposal (13 tests), full cargo test --manifest-path .\\epiphany-core\\Cargo.toml (31 tests), and CARGO_TARGET_DIR=C:\\Users\\Meta\\.cargo-target-codex cargo test -p codex-core --lib proposal."}
|
||||
{"ts": "2026-04-25T02:34:20+00:00", "type": "verification", "status": "ok", "note": "Verified compact-rehydrate-reorient-continuity after e51b74c. Confirmed git is clean/synced before doc patch, state/map.yaml current_status points to Phase 5 observation-set selection and map-delta judgment, AGENTS.md keeps bootstrap/re-entry protocol without volatile phase status, handoff contains compaction workflow and current next implementation, and patched stale Short Version text that still pointed back to Phase 4 retrieval."}
|
||||
{"ts": "2026-04-25T02:45:07+00:00", "type": "implementation", "status": "ok", "note": "Hardened read-only thread/epiphany/propose observation selection in epiphany-core. When observationIds is omitted, propose_map_update now ranks existing verified, code-ref-bearing observations with accepting evidence, scores source/evidence quality plus graph-frontier focus, and selects up to four observations from the strongest coherent path cluster without mutating state or bypassing promotion."}
|
||||
{"ts": "2026-04-25T02:45:29+00:00", "type": "verification", "status": "ok", "note": "Verified automatic proposal observation selection with cargo fmt --manifest-path .\\epiphany-core\\Cargo.toml, cargo test --manifest-path .\\epiphany-core\\Cargo.toml proposal (16 tests), full cargo test --manifest-path .\\epiphany-core\\Cargo.toml (34 tests), and CARGO_TARGET_DIR=C:\\Users\\Meta\\.cargo-target-codex cargo test -p codex-core --lib proposal. git diff --check only reported expected CRLF warnings."}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ active_subgoals:
|
|||
- Keep the Phase 5 distill/propose/promote/update work aligned with reality in code and repo memory.
|
||||
- Keep vendored Codex as a thin typed host seam while Epiphany-owned prompt and retrieval/indexing logic live in the repo-owned `epiphany-core` crate.
|
||||
- Preserve exact/path lookup and BM25 fallback while the Qdrant path stays explicit and bounded.
|
||||
- Harden the next layer above the landed typed distill/propose/promote/update paths: richer observation-set selection and map-delta judgment beyond graph-node reuse, linked frontier focus, evidence-backed selection, selected-observation prioritization, strict unanchored-node semantic reuse, and map-delta churn pressure while keeping verifier-backed acceptance/rejection explicit.
|
||||
- Harden the next layer above the landed typed distill/propose/promote/update paths: richer map-delta judgment beyond graph-node reuse, linked frontier focus, evidence-backed selection, selected-observation prioritization, strict unanchored-node semantic reuse, automatic bounded observation selection, and map-delta churn pressure while keeping verifier-backed acceptance/rejection explicit.
|
||||
|
||||
accepted_design:
|
||||
- external typed state files
|
||||
|
|
@ -101,6 +101,7 @@ accepted_design:
|
|||
- harden proposal frontier focus incrementally: `thread/epiphany/propose` should follow existing graph links between architecture and dataflow nodes and mark named incident graph edges active so prompt rendering sees relevant connected context
|
||||
- harden proposal selection and churn incrementally: `thread/epiphany/propose` should require selected verified observations to cite accepting `recent_evidence`, summarize the evidence-backed selection in the candidate observation/evidence, and derive `diff_pressure` from the candidate map delta, touched paths, selected observation count, and unresolved write risk instead of merely inheriting old churn
|
||||
- harden proposal graph semantics incrementally: `thread/epiphany/propose` should score selected observations/evidence, use the strongest selected signal for candidate wording, and reuse unanchored architecture graph nodes only through strict unique semantic overlap while refusing ambiguous semantic matches and keeping code-anchored nodes under concrete ref/path/id matching
|
||||
- harden proposal observation selection incrementally: when `observationIds` is omitted, read-only `thread/epiphany/propose` should choose a bounded coherent path cluster from existing verified, evidence-backed observations using source/evidence quality plus graph-frontier focus, without mutating state or bypassing promotion
|
||||
|
||||
rejected_paths:
|
||||
- name: pinned_map_only
|
||||
|
|
@ -117,5 +118,5 @@ rejected_paths:
|
|||
reason: audited candidates were either terminal-only, stale/aspirational, or incoherent wrappers; the comparison clones were removed from vendor to avoid building on untrusted drift
|
||||
|
||||
current_status:
|
||||
summary: Workspace initialized with protocol files, typed state, handoff notes, architecture maps, and a rolling implementation plan against vendored Codex. Phase 1 durable state, Phase 2 prompt integration, the minimal Phase 3 typed read surface, and Phase 4 retrieval/indexing/core-extraction are landed on `main`. Phase 5 semantic distillation/promotion/proposal is now active: the current baseline includes explicit Qdrant indexing with BM25 fallback, typed `thread/epiphany/update`, read-only `thread/epiphany/distill`, read-only `thread/epiphany/propose`, verifier-backed `thread/epiphany/promote`, structural map/churn promotion validation, graph-node reuse, linked frontier focus, evidence-backed proposal selection, selected-observation prioritization, strict unanchored-node semantic reuse, map-delta churn pressure in `epiphany-core`, and thin vendored Codex host seams. The Windows app-server stack-pressure regression was narrowed to test-thread stack size; repo-local Cargo config sets `RUST_MIN_STACK=67108864`, and boxed-future request-dispatch experiments were removed after config-only verification passed. The repo also has source-available/commercial licensing plus a CLA gate for external contributions.
|
||||
next_action: Continue Phase 5 by hardening the layer above `thread/epiphany/distill`, `thread/epiphany/propose`, `thread/epiphany/promote`, and `thread/epiphany/update`: richer observation-set selection and map-delta judgment beyond current exact-ref/same-path/deterministic-id/graph-link/recent-evidence/semantic-unanchored-node matching, selected-observation prioritization, and map-delta churn pressure, while keeping retrieval/distillation/proposal read-only and avoiding watcher, GUI, or specialist-agent machinery.
|
||||
summary: Workspace initialized with protocol files, typed state, handoff notes, architecture maps, and a rolling implementation plan against vendored Codex. Phase 1 durable state, Phase 2 prompt integration, the minimal Phase 3 typed read surface, and Phase 4 retrieval/indexing/core-extraction are landed on `main`. Phase 5 semantic distillation/promotion/proposal is now active: the current baseline includes explicit Qdrant indexing with BM25 fallback, typed `thread/epiphany/update`, read-only `thread/epiphany/distill`, read-only `thread/epiphany/propose`, verifier-backed `thread/epiphany/promote`, structural map/churn promotion validation, graph-node reuse, linked frontier focus, evidence-backed proposal selection, selected-observation prioritization, strict unanchored-node semantic reuse, automatic bounded observation selection, map-delta churn pressure in `epiphany-core`, and thin vendored Codex host seams. The Windows app-server stack-pressure regression was narrowed to test-thread stack size; repo-local Cargo config sets `RUST_MIN_STACK=67108864`, and boxed-future request-dispatch experiments were removed after config-only verification passed. The repo also has source-available/commercial licensing plus a CLA gate for external contributions.
|
||||
next_action: Continue Phase 5 by hardening the layer above `thread/epiphany/distill`, `thread/epiphany/propose`, `thread/epiphany/promote`, and `thread/epiphany/update`: richer map-delta judgment beyond current exact-ref/same-path/deterministic-id/graph-link/recent-evidence/semantic-unanchored-node matching, selected-observation prioritization, automatic bounded observation selection, and map-delta churn pressure, while keeping retrieval/distillation/proposal read-only and avoiding watcher, GUI, or specialist-agent machinery.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ This file is intentionally disposable.
|
|||
|
||||
## Current Subgoal
|
||||
|
||||
- Continue Phase 5 proposal-quality hardening beyond graph-node reuse, linked frontier focus, evidence-backed selection, selected-observation prioritization, strict unanchored-node semantic reuse, and map-delta churn pressure, without hidden writes.
|
||||
- Continue Phase 5 proposal-quality hardening beyond graph-node reuse, linked frontier focus, evidence-backed selection, selected-observation prioritization, strict unanchored-node semantic reuse, automatic bounded observation selection, and map-delta churn pressure, without hidden writes.
|
||||
|
||||
## Working Notes
|
||||
|
||||
|
|
@ -18,6 +18,7 @@ This file is intentionally disposable.
|
|||
- proposal expands frontier focus through existing graph links, marks named incident architecture/dataflow edges active, emits proposal observation/evidence with evidence-backed selection counts plus reused/created node counts, and marks churn as `proposal_refines_map`, `proposal_expands_map`, or `proposal_updates_map`
|
||||
- proposal now scores selected observations/evidence so candidate wording uses the strongest selected verifier/test/smoke-backed signal instead of raw id order
|
||||
- proposal can reuse an unanchored architecture graph node through strict unique semantic overlap, but refuses tied semantic matches and leaves code-anchored nodes under concrete exact/path/deterministic-id matching
|
||||
- proposal can now omit `observationIds`; in that case `epiphany-core` ranks existing verified, code-ref-bearing observations with accepting evidence, scores them by source/evidence quality plus graph-frontier focus, and selects up to four observations from the strongest coherent path cluster
|
||||
- churn `diff_pressure` now comes from the candidate map delta, touched path count, selected observation count, and existing unexplained write risk, with existing pressure kept as a floor
|
||||
- app-server exposes experimental loaded-thread-only `thread/epiphany/propose`
|
||||
- live stdio smoke proved propose is read-only, and propose -> promote persists graph/churn only after verifier evidence
|
||||
|
|
|
|||
Reference in a new issue