Compare commits

...

8 Commits

Author SHA1 Message Date
Kevin Liu
5512869f01 [codex] fix memory prompt tests on windows 2026-04-07 17:04:35 -07:00
Kevin Liu
451d6685b0 [codex] fix memory prompt test on windows 2026-04-07 16:36:03 -07:00
Kevin Liu
3a5c7db657 [codex] rename memory extension instructions file 2026-04-07 15:22:51 -07:00
Kevin Liu
3887307f99 [codex] simplify memory extension prompt wiring 2026-04-07 15:13:00 -07:00
Kevin Liu
70381d9f11 Merge remote-tracking branch 'origin/main' into kevinliu/memory-modules 2026-04-07 14:56:47 -07:00
Kevin Liu
8f1f9fab7d comment 2026-04-07 14:56:36 -07:00
Kevin Liu
8fbdc4df04 Better memory extension architecture 2026-04-07 14:55:21 -07:00
Kevin Liu
73472c8967 [codex] add consolidation module extension paths 2026-03-30 12:36:16 -07:00
4 changed files with 78 additions and 8 deletions

View File

@@ -25,6 +25,7 @@ pub(crate) use control::clear_memory_root_contents;
pub(crate) use start::start_memories_startup_task;
mod artifacts {
pub(super) const EXTENSIONS_SUBDIR: &str = "memories_extensions";
pub(super) const ROLLOUT_SUMMARIES_SUBDIR: &str = "rollout_summaries";
pub(super) const RAW_MEMORIES_FILENAME: &str = "raw_memories.md";
}
@@ -106,6 +107,10 @@ fn rollout_summaries_dir(root: &Path) -> PathBuf {
root.join(artifacts::ROLLOUT_SUMMARIES_SUBDIR)
}
fn memory_extensions_root(root: &Path) -> PathBuf {
root.with_file_name(artifacts::EXTENSIONS_SUBDIR)
}
fn raw_memories_file(root: &Path) -> PathBuf {
root.join(artifacts::RAW_MEMORIES_FILENAME)
}

View File

@@ -1,3 +1,4 @@
use crate::memories::memory_extensions_root;
use crate::memories::memory_root;
use crate::memories::phase_one;
use crate::memories::storage::rollout_summary_file_stem_from_parts;
@@ -44,19 +45,22 @@ pub(super) fn build_consolidation_prompt(
memory_root: &Path,
selection: &Phase2InputSelection,
) -> String {
let memory_extensions_root = memory_extensions_root(memory_root);
let memory_root = memory_root.display().to_string();
let memory_extensions_root = memory_extensions_root.display().to_string();
let phase2_input_selection = render_phase2_input_selection(selection);
CONSOLIDATION_PROMPT_TEMPLATE
.render([
("memory_root", memory_root.as_str()),
("memory_extensions_root", memory_extensions_root.as_str()),
("phase2_input_selection", phase2_input_selection.as_str()),
])
.unwrap_or_else(|err| {
warn!("failed to render memories consolidation prompt template: {err}");
format!(
"## Memory Phase 2 (Consolidation)\nConsolidate Codex memories in: {memory_root}\n\n{phase2_input_selection}"
)
})
warn!("failed to render memories consolidation prompt template: {err}");
format!(
"## Memory Phase 2 (Consolidation)\nConsolidate Codex memories in: {memory_root}\n\n{phase2_input_selection}"
)
})
}
fn render_phase2_input_selection(selection: &Phase2InputSelection) -> String {

View File

@@ -55,14 +55,57 @@ fn build_stage_one_input_message_uses_default_limit_when_model_context_window_mi
#[test]
fn build_consolidation_prompt_renders_embedded_template() {
let prompt =
build_consolidation_prompt(Path::new("/tmp/memories"), &Phase2InputSelection::default());
let temp = tempdir().unwrap();
let memories_dir = temp.path().join("memories");
let memory_extensions_dir = temp.path().join("memories_extensions");
assert!(prompt.contains("Folder structure (under /tmp/memories/):"));
let prompt = build_consolidation_prompt(&memories_dir, &Phase2InputSelection::default());
assert!(prompt.contains(&format!(
"Folder structure (under {}/):",
memories_dir.display()
)));
assert!(prompt.contains(&format!(
"Memory extensions (under {}/)",
memory_extensions_dir.display()
)));
assert!(prompt.contains("**Diff since last consolidation:**"));
assert!(prompt.contains("- selected inputs this run: 0"));
}
#[tokio::test]
async fn build_consolidation_prompt_points_to_extensions_without_inlining_them() {
let temp = tempdir().unwrap();
let memories_dir = temp.path().join("memories");
let extension_dir = temp.path().join("memories_extensions/tape_recorder");
tokio_fs::create_dir_all(extension_dir.join("resources"))
.await
.unwrap();
tokio_fs::write(
extension_dir.join("instructions.md"),
"source-specific instructions\n",
)
.await
.unwrap();
tokio_fs::write(
extension_dir.join("resources/notes.md"),
"source-specific resource\n",
)
.await
.unwrap();
let prompt = build_consolidation_prompt(&memories_dir, &Phase2InputSelection::default());
let memory_extensions_dir = temp.path().join("memories_extensions");
assert!(prompt.contains(&format!(
"Memory extensions (under {}/)",
memory_extensions_dir.display()
)));
assert!(prompt.contains("<extension_name>/instructions.md"));
assert!(!prompt.contains("source-specific instructions"));
assert!(!prompt.contains("source-specific resource"));
}
#[tokio::test]
async fn build_memory_tool_developer_instructions_renders_embedded_template() {
let temp = tempdir().unwrap();

View File

@@ -34,6 +34,17 @@ Folder structure (under {{ memory_root }}/):
pointers/references, and pruned raw evidence snippets. Distilled version of
everything valuable from the raw rollout.
Memory extensions (under {{ memory_extensions_root }}/):
- <extension_name>/instructions.md
- Source-specific guidance for interpreting additional memory signals. If an
extension folder exists, you must read its instructions.md to determine how to use this memory
source.
If the user has any memory extensions, you MUST read the instructions for each extension to
determine how to use the memory source. If `{{ memory_extensions_root }}` does not exist or has no
extension folders, continue with the standard memory inputs only.
============================================================
GLOBAL SAFETY, HYGIENE, AND NO-FILLER RULES (STRICT)
============================================================
@@ -136,6 +147,13 @@ Under `{{ memory_root }}/`:
- `skills/*`
- read existing skills so updates are incremental and non-duplicative
Optional source-specific inputs:
Under `{{ memory_extensions_root }}/`:
- `<extension_name>/instructions.md`
- If extension folders exist, read each instructions.md first and follow it when interpreting
that extension's memory source.
Mode selection:
- INIT phase: existing artifacts are missing/empty (especially `memory_summary.md`