mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
memories: add rollout_summary_file header to raw memories and tune prompts (#12221)
## Summary - Add `rollout_summary_file: <generated>.md` to each thread header in `raw_memories.md` so Phase 2 can reliably reference the canonical rollout summary filename. - Update the memory prompts/templates (`stage_one_system`, `consolidation`, `read_path`) for the new task-oriented raw-memory / MEMORY.md schema and stronger consolidation guidance. ## Details - `codex-rs/core/src/memories/storage.rs` - Writes the generated `rollout_summary_file` path into the per-thread metadata header when rebuilding `raw_memories.md`. - `codex-rs/core/src/memories/tests.rs` - Verifies the canonical `rollout_summary_file` header is present and ordered after `updated_at`/`cwd` in `raw_memories.md`. - Verifies task-structured raw-memory content is preserved while the canonical header is added. - `codex-rs/core/templates/memories/*.md` - Updates the stage-1 raw-memory format to task-grouped sections (`task`, `task_group`, `task_outcome`). - Updates Phase 2 consolidation guidance around recency (`updated_at`), task-oriented `MEMORY.md` blocks, and richer evidence-backed consolidation. - Tweaks the quick memory pass wording to emphasize topics/workflows in addition to keywords. ## Testing - `cargo test -p codex-core memories`
This commit is contained in:
committed by
GitHub
Unverified
parent
18bd6d2d71
commit
e747a8eb74
@@ -82,11 +82,11 @@ async fn rebuild_raw_memories_file(
|
||||
)
|
||||
.map_err(raw_memories_format_error)?;
|
||||
writeln!(body, "cwd: {}", memory.cwd.display()).map_err(raw_memories_format_error)?;
|
||||
writeln!(body).map_err(raw_memories_format_error)?;
|
||||
let rollout_summary_file = format!("{}.md", rollout_summary_file_stem(memory));
|
||||
let raw_memory =
|
||||
replace_rollout_summary_file_in_raw_memory(&memory.raw_memory, &rollout_summary_file);
|
||||
body.push_str(raw_memory.trim());
|
||||
writeln!(body, "rollout_summary_file: {rollout_summary_file}")
|
||||
.map_err(raw_memories_format_error)?;
|
||||
writeln!(body).map_err(raw_memories_format_error)?;
|
||||
body.push_str(memory.raw_memory.trim());
|
||||
body.push_str("\n\n");
|
||||
}
|
||||
|
||||
@@ -161,26 +161,6 @@ fn rollout_summary_format_error(err: std::fmt::Error) -> std::io::Error {
|
||||
std::io::Error::other(format!("format rollout summary: {err}"))
|
||||
}
|
||||
|
||||
fn replace_rollout_summary_file_in_raw_memory(
|
||||
raw_memory: &str,
|
||||
rollout_summary_file: &str,
|
||||
) -> String {
|
||||
const ROLLOUT_SUMMARY_PREFIX: &str = "rollout_summary_file: ";
|
||||
|
||||
let replacement = format!("rollout_summary_file: {rollout_summary_file}");
|
||||
raw_memory
|
||||
.split('\n')
|
||||
.map(|line| {
|
||||
if line.starts_with(ROLLOUT_SUMMARY_PREFIX) {
|
||||
replacement.as_str()
|
||||
} else {
|
||||
line
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
pub(crate) fn rollout_summary_file_stem(memory: &Stage1Output) -> String {
|
||||
rollout_summary_file_stem_from_parts(
|
||||
memory.thread_id,
|
||||
@@ -270,7 +250,6 @@ pub(super) fn rollout_summary_file_stem_from_parts(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::replace_rollout_summary_file_in_raw_memory;
|
||||
use super::rollout_summary_file_stem;
|
||||
use super::rollout_summary_file_stem_from_parts;
|
||||
use chrono::TimeZone;
|
||||
@@ -339,71 +318,4 @@ mod tests {
|
||||
|
||||
assert_eq!(rollout_summary_file_stem(&memory), FIXED_PREFIX);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_rollout_summary_file_in_raw_memory_replaces_existing_value() {
|
||||
let raw_memory = "\
|
||||
---
|
||||
rollout_summary_file: wrong.md
|
||||
description: demo
|
||||
keywords: one, two
|
||||
---
|
||||
- body line";
|
||||
let normalized = replace_rollout_summary_file_in_raw_memory(
|
||||
raw_memory,
|
||||
"2025-01-01T00-00-00-abcd-demo.md",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
normalized,
|
||||
"\
|
||||
---
|
||||
rollout_summary_file: 2025-01-01T00-00-00-abcd-demo.md
|
||||
description: demo
|
||||
keywords: one, two
|
||||
---
|
||||
- body line"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_rollout_summary_file_in_raw_memory_replaces_placeholder() {
|
||||
let raw_memory = "\
|
||||
---
|
||||
rollout_summary_file: <system_populated_file.md>
|
||||
description: demo
|
||||
keywords: one, two
|
||||
---
|
||||
- body line";
|
||||
let normalized = replace_rollout_summary_file_in_raw_memory(
|
||||
raw_memory,
|
||||
"2025-01-01T00-00-00-abcd-demo.md",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
normalized,
|
||||
"\
|
||||
---
|
||||
rollout_summary_file: 2025-01-01T00-00-00-abcd-demo.md
|
||||
description: demo
|
||||
keywords: one, two
|
||||
---
|
||||
- body line"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_rollout_summary_file_in_raw_memory_leaves_text_without_field_unchanged() {
|
||||
let raw_memory = "\
|
||||
---
|
||||
description: demo
|
||||
keywords: one, two
|
||||
---
|
||||
- body line";
|
||||
let normalized = replace_rollout_summary_file_in_raw_memory(
|
||||
raw_memory,
|
||||
"2025-01-01T00-00-00-abcd-demo.md",
|
||||
);
|
||||
assert_eq!(normalized, raw_memory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ async fn sync_rollout_summaries_and_raw_memories_file_keeps_latest_memories_only
|
||||
}
|
||||
files.sort_unstable();
|
||||
assert_eq!(files.len(), 1);
|
||||
let canonical_rollout_summary_file = &files[0];
|
||||
|
||||
let raw_memories = tokio::fs::read_to_string(raw_memories_file(&root))
|
||||
.await
|
||||
@@ -134,6 +135,30 @@ async fn sync_rollout_summaries_and_raw_memories_file_keeps_latest_memories_only
|
||||
assert!(raw_memories.contains("raw memory"));
|
||||
assert!(raw_memories.contains(&keep_id));
|
||||
assert!(raw_memories.contains("cwd: /tmp/workspace"));
|
||||
assert!(raw_memories.contains(&format!(
|
||||
"rollout_summary_file: {canonical_rollout_summary_file}"
|
||||
)));
|
||||
let thread_header = format!("## Thread `{keep_id}`");
|
||||
let thread_pos = raw_memories
|
||||
.find(&thread_header)
|
||||
.expect("thread header should exist");
|
||||
let updated_pos = raw_memories[thread_pos..]
|
||||
.find("updated_at: ")
|
||||
.map(|offset| thread_pos + offset)
|
||||
.expect("updated_at should exist after thread header");
|
||||
let cwd_pos = raw_memories[thread_pos..]
|
||||
.find("cwd: /tmp/workspace")
|
||||
.map(|offset| thread_pos + offset)
|
||||
.expect("cwd should exist after thread header");
|
||||
let file_pos = raw_memories[thread_pos..]
|
||||
.find(&format!(
|
||||
"rollout_summary_file: {canonical_rollout_summary_file}"
|
||||
))
|
||||
.map(|offset| thread_pos + offset)
|
||||
.expect("rollout_summary_file should exist after thread header");
|
||||
assert!(thread_pos < updated_pos);
|
||||
assert!(updated_pos < cwd_pos);
|
||||
assert!(cwd_pos < file_pos);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -229,7 +254,7 @@ async fn sync_rollout_summaries_uses_timestamp_hash_and_sanitized_slug_filename(
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn rebuild_raw_memories_file_rewrites_rollout_summary_file_to_canonical_filename() {
|
||||
async fn rebuild_raw_memories_file_adds_canonical_rollout_summary_file_header() {
|
||||
let dir = tempdir().expect("tempdir");
|
||||
let root = dir.path().join("memory");
|
||||
ensure_layout(&root).await.expect("ensure layout");
|
||||
@@ -241,11 +266,20 @@ async fn rebuild_raw_memories_file_rewrites_rollout_summary_file_to_canonical_fi
|
||||
source_updated_at: Utc.timestamp_opt(200, 0).single().expect("timestamp"),
|
||||
raw_memory: "\
|
||||
---
|
||||
rollout_summary_file: state_migration_uniqueness_test.md
|
||||
description: Added a migration test
|
||||
keywords: codex-state, migrations
|
||||
---
|
||||
- Kept details."
|
||||
### Task 1: migration-test
|
||||
task: add-migration-test
|
||||
task_group: codex-state
|
||||
task_outcome: success
|
||||
- Added regression coverage for migration uniqueness.
|
||||
|
||||
### Task 2: validate-migration
|
||||
task: validate-migration-ordering
|
||||
task_group: codex-state
|
||||
task_outcome: success
|
||||
- Confirmed no ordering regressions."
|
||||
.to_string(),
|
||||
rollout_summary: "short summary".to_string(),
|
||||
rollout_slug: Some("Unsafe Slug/With Spaces & Symbols + EXTRA_LONG_12345".to_string()),
|
||||
@@ -285,8 +319,11 @@ keywords: codex-state, migrations
|
||||
assert!(raw_memories.contains(&format!(
|
||||
"rollout_summary_file: {canonical_rollout_summary_file}"
|
||||
)));
|
||||
assert!(!raw_memories.contains("rollout_summary_file: state_migration_uniqueness_test.md"));
|
||||
assert!(raw_memories.contains("description: Added a migration test"));
|
||||
assert!(raw_memories.contains("### Task 1: migration-test"));
|
||||
assert!(raw_memories.contains("task: add-migration-test"));
|
||||
assert!(raw_memories.contains("task_group: codex-state"));
|
||||
assert!(raw_memories.contains("task_outcome: success"));
|
||||
}
|
||||
|
||||
mod phase2 {
|
||||
|
||||
Reference in New Issue
Block a user