From e4d7cc1924e589dc6482169cadacc981eb583b69 Mon Sep 17 00:00:00 2001 From: Hare Date: Tue, 28 Apr 2026 11:53:08 +0900 Subject: [PATCH] =?UTF-8?q?memory=E3=81=8C.insomnia=E9=85=8D=E4=B8=8B?= =?UTF-8?q?=E3=81=A7=E3=81=AF=E3=81=AA=E3=81=8Fworkspace=20root=E7=9B=B4?= =?UTF-8?q?=E4=B8=8B=E3=82=92=E6=83=B3=E5=AE=9A=E3=81=97=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=9F=E5=95=8F=E9=A1=8C=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/memory/src/linter/mod.rs | 32 +++++++------- crates/memory/src/resident.rs | 8 ++-- crates/memory/src/scope.rs | 4 +- crates/memory/src/tool/edit.rs | 2 +- crates/memory/src/tool/query.rs | 32 +++++++------- crates/memory/src/tool/read.rs | 6 +-- crates/memory/src/tool/write.rs | 6 +-- crates/memory/src/workspace.rs | 60 ++++++++++++++++---------- docs/plan/memory.md | 2 + resources/prompts/common/tool-usage.md | 3 ++ resources/prompts/default.md | 2 - 11 files changed, 87 insertions(+), 70 deletions(-) diff --git a/crates/memory/src/linter/mod.rs b/crates/memory/src/linter/mod.rs index 943695a2..1a37e3e6 100644 --- a/crates/memory/src/linter/mod.rs +++ b/crates/memory/src/linter/mod.rs @@ -322,7 +322,7 @@ mod tests { #[test] fn workflow_write_rejected() { let (dir, linter) = workspace(); - let path = dir.path().join("memory/workflow/wf.md"); + let path = dir.path().join(".insomnia/memory/workflow/wf.md"); let content = format!( "---\nupdated_at: {now}\ndescription: x\nauto_invoke: false\nuser_invocable: true\n---\nbody", now = iso_now() @@ -352,7 +352,7 @@ mod tests { #[test] fn decision_with_unknown_replaced_by_errors() { let (dir, linter) = workspace(); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); let content = format!( "---\ncreated_at: {now}\nupdated_at: {now}\nsources: []\nstatus: replaced\nreplaced_by: ghost\n---\nbody\n", now = iso_now() @@ -369,7 +369,7 @@ mod tests { #[test] fn decision_replaced_by_self_errors() { let (dir, linter) = workspace(); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); let content = format!( "---\ncreated_at: {now}\nupdated_at: {now}\nsources: []\nstatus: replaced\nreplaced_by: foo\n---\nbody\n", now = iso_now() @@ -387,7 +387,7 @@ mod tests { fn decision_replaced_by_existing_ok() { let (dir, linter) = workspace(); // Pre-create the target. - let target = dir.path().join("memory/decisions/bar.md"); + let target = dir.path().join(".insomnia/memory/decisions/bar.md"); write( &target, &format!( @@ -395,7 +395,7 @@ mod tests { now = iso_now() ), ); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); let content = format!( "---\ncreated_at: {now}\nupdated_at: {now}\nsources: []\nstatus: replaced\nreplaced_by: bar\n---\nbody\n", now = iso_now() @@ -407,7 +407,7 @@ mod tests { #[test] fn missing_required_field_errors() { let (dir, linter) = workspace(); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); // Missing `status`. let content = format!( "---\ncreated_at: {now}\nupdated_at: {now}\nsources: []\n---\nbody\n", @@ -423,7 +423,7 @@ mod tests { #[test] fn knowledge_long_description_with_model_invokation_errors() { let (dir, linter) = workspace(); - let path = dir.path().join("knowledge/foo.md"); + let path = dir.path().join(".insomnia/knowledge/foo.md"); let big_desc = "x".repeat(2000); let content = format!( "---\ncreated_at: {now}\nupdated_at: {now}\nkind: rule\ndescription: {big_desc}\nmodel_invokation: true\nuser_invocable: true\nlast_sources: []\n---\nbody\n", @@ -441,7 +441,7 @@ mod tests { #[test] fn knowledge_long_description_without_model_invokation_ok() { let (dir, linter) = workspace(); - let path = dir.path().join("knowledge/foo.md"); + let path = dir.path().join(".insomnia/knowledge/foo.md"); let big_desc = "x".repeat(2000); let content = format!( "---\ncreated_at: {now}\nupdated_at: {now}\nkind: rule\ndescription: {big_desc}\nmodel_invokation: false\nuser_invocable: true\nlast_sources: []\n---\nbody\n", @@ -454,7 +454,7 @@ mod tests { #[test] fn summary_path_accepted() { let (dir, linter) = workspace(); - let path = dir.path().join("memory/summary.md"); + let path = dir.path().join(".insomnia/memory/summary.md"); let content = format!( "---\nupdated_at: {now}\n---\nsummary body\n", now = iso_now() @@ -466,7 +466,7 @@ mod tests { #[test] fn create_when_existing_errors() { let (dir, linter) = workspace(); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); write( &path, &format!( @@ -491,7 +491,7 @@ mod tests { fn workflow_lint_accepts_valid_record() { let (dir, linter) = workspace(); // Place a Knowledge record that the workflow will reference. - let kn = dir.path().join("knowledge/foo.md"); + let kn = dir.path().join(".insomnia/knowledge/foo.md"); write( &kn, &format!( @@ -548,14 +548,14 @@ mod tests { // `db-pol` (1 deletion), `db-pools` (1 insertion). for slug in ["db-pol", "db-pools"] { write( - &dir.path().join(format!("memory/decisions/{slug}.md")), + &dir.path().join(format!(".insomnia/memory/decisions/{slug}.md")), &format!( "---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n", n = iso_now() ), ); } - let path = dir.path().join("memory/decisions/db-pool.md"); + let path = dir.path().join(".insomnia/memory/decisions/db-pool.md"); let content = format!( "---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\nbody\n", n = iso_now() @@ -577,14 +577,14 @@ mod tests { let (dir, linter) = workspace(); for slug in ["alpha", "bravo"] { write( - &dir.path().join(format!("memory/decisions/{slug}.md")), + &dir.path().join(format!(".insomnia/memory/decisions/{slug}.md")), &format!( "---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n", n = iso_now() ), ); } - let path = dir.path().join("memory/decisions/charlie.md"); + let path = dir.path().join(".insomnia/memory/decisions/charlie.md"); let content = format!( "---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n", n = iso_now() @@ -603,7 +603,7 @@ mod tests { #[test] fn body_size_limit_errors() { let (dir, linter) = workspace(); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); let big_body = "x".repeat(8001); let content = format!( "---\ncreated_at: {now}\nupdated_at: {now}\nsources: []\nstatus: open\n---\n{body}", diff --git a/crates/memory/src/resident.rs b/crates/memory/src/resident.rs index 57c958b9..1b50e2ac 100644 --- a/crates/memory/src/resident.rs +++ b/crates/memory/src/resident.rs @@ -84,7 +84,7 @@ mod tests { model_invokation: bool, body: &str, ) { - let path = dir.join("knowledge").join(format!("{slug}.md")); + let path = dir.join(".insomnia/knowledge").join(format!("{slug}.md")); let content = format!( "---\ncreated_at: {n}\nupdated_at: {n}\nkind: policy\ndescription: \"{description}\"\nmodel_invokation: {flag}\nuser_invocable: true\nlast_sources: []\n---\n{body}", n = now(), @@ -95,7 +95,7 @@ mod tests { fn setup() -> (TempDir, WorkspaceLayout) { let dir = TempDir::new().unwrap(); - std::fs::create_dir_all(dir.path().join("knowledge")).unwrap(); + std::fs::create_dir_all(dir.path().join(".insomnia/knowledge")).unwrap(); let layout = WorkspaceLayout::new(dir.path().to_path_buf()); (dir, layout) } @@ -141,7 +141,7 @@ mod tests { write_knowledge(dir.path(), "good", "ok", true, ""); // Garbage in frontmatter — must be skipped, not panic. std::fs::write( - dir.path().join("knowledge/bad.md"), + dir.path().join(".insomnia/knowledge/bad.md"), "---\nthis is not yaml: : :\n---\nbody\n", ) .unwrap(); @@ -155,7 +155,7 @@ mod tests { fn non_md_files_ignored() { let (dir, layout) = setup(); write_knowledge(dir.path(), "good", "ok", true, ""); - std::fs::write(dir.path().join("knowledge/note.txt"), "not markdown\n").unwrap(); + std::fs::write(dir.path().join(".insomnia/knowledge/note.txt"), "not markdown\n").unwrap(); let got = collect_resident_knowledge(&layout); assert_eq!(got.len(), 1); diff --git a/crates/memory/src/scope.rs b/crates/memory/src/scope.rs index 2ddc7d96..5c4a60f9 100644 --- a/crates/memory/src/scope.rs +++ b/crates/memory/src/scope.rs @@ -41,9 +41,9 @@ mod tests { let layout = WorkspaceLayout::new(PathBuf::from("/ws")); let rules = deny_write_rules(&layout); assert_eq!(rules.len(), 2); - assert_eq!(rules[0].target, PathBuf::from("/ws/memory")); + assert_eq!(rules[0].target, PathBuf::from("/ws/.insomnia/memory")); assert_eq!(rules[0].permission, Permission::Write); assert!(rules[0].recursive); - assert_eq!(rules[1].target, PathBuf::from("/ws/knowledge")); + assert_eq!(rules[1].target, PathBuf::from("/ws/.insomnia/knowledge")); } } diff --git a/crates/memory/src/tool/edit.rs b/crates/memory/src/tool/edit.rs index db5d6193..a657d517 100644 --- a/crates/memory/src/tool/edit.rs +++ b/crates/memory/src/tool/edit.rs @@ -174,7 +174,7 @@ mod tests { fn setup() -> (TempDir, WorkspaceLayout, PathBuf) { let dir = TempDir::new().unwrap(); let layout = WorkspaceLayout::new(dir.path().to_path_buf()); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); std::fs::create_dir_all(path.parent().unwrap()).unwrap(); let initial = format!( "---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\nbody body\n", diff --git a/crates/memory/src/tool/query.rs b/crates/memory/src/tool/query.rs index afc605bd..35f3c4d7 100644 --- a/crates/memory/src/tool/query.rs +++ b/crates/memory/src/tool/query.rs @@ -6,11 +6,11 @@ //! omitted, returns one entry per file (no excerpt) so the agent can //! enumerate what records exist without knowing what's inside them. //! -//! - `MemoryQuery` walks `memory/summary.md`, `memory/decisions/`, -//! `memory/requests/`. `memory/workflow/` and `memory/_staging/` -//! are excluded by construction. -//! - `KnowledgeQuery` walks `knowledge/*.md` and supports a `kind` -//! filter against the Knowledge frontmatter's `kind` field. +//! - `MemoryQuery` walks `.insomnia/memory/{summary.md,decisions/, +//! requests/}`. `.insomnia/memory/workflow/` and +//! `.insomnia/memory/_staging/` are excluded by construction. +//! - `KnowledgeQuery` walks `.insomnia/knowledge/*.md` and supports a +//! `kind` filter against the Knowledge frontmatter's `kind` field. //! //! No derived index — the file tree is the source of truth and is //! re-scanned per call. 出現順: within a file by line order, across @@ -441,16 +441,16 @@ mod tests { fn setup() -> (TempDir, WorkspaceLayout) { let dir = TempDir::new().unwrap(); let layout = WorkspaceLayout::new(dir.path().to_path_buf()); - std::fs::create_dir_all(dir.path().join("memory/decisions")).unwrap(); - std::fs::create_dir_all(dir.path().join("memory/requests")).unwrap(); - std::fs::create_dir_all(dir.path().join("memory/workflow")).unwrap(); - std::fs::create_dir_all(dir.path().join("memory/_staging")).unwrap(); - std::fs::create_dir_all(dir.path().join("knowledge")).unwrap(); + std::fs::create_dir_all(dir.path().join(".insomnia/memory/decisions")).unwrap(); + std::fs::create_dir_all(dir.path().join(".insomnia/memory/requests")).unwrap(); + std::fs::create_dir_all(dir.path().join(".insomnia/memory/workflow")).unwrap(); + std::fs::create_dir_all(dir.path().join(".insomnia/memory/_staging")).unwrap(); + std::fs::create_dir_all(dir.path().join(".insomnia/knowledge")).unwrap(); (dir, layout) } fn write_decision(dir: &Path, slug: &str, body: &str) { - let path = dir.join("memory/decisions").join(format!("{slug}.md")); + let path = dir.join(".insomnia/memory/decisions").join(format!("{slug}.md")); let content = format!( "---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\n{body}", n = now() @@ -459,7 +459,7 @@ mod tests { } fn write_knowledge(dir: &Path, slug: &str, kind: &str, description: &str, body: &str) { - let path = dir.join("knowledge").join(format!("{slug}.md")); + let path = dir.join(".insomnia/knowledge").join(format!("{slug}.md")); let content = format!( "---\ncreated_at: {n}\nupdated_at: {n}\nkind: {kind}\ndescription: \"{description}\"\nmodel_invokation: false\nuser_invocable: true\nlast_sources: []\n---\n{body}", n = now() @@ -514,7 +514,7 @@ mod tests { let (dir, layout) = setup(); write_decision(dir.path(), "alpha", "body\n"); write_decision(dir.path(), "beta", "body\n"); - let summary_path = dir.path().join("memory/summary.md"); + let summary_path = dir.path().join(".insomnia/memory/summary.md"); std::fs::write( &summary_path, format!("---\nupdated_at: {n}\n---\nhello\n", n = now()), @@ -534,7 +534,7 @@ mod tests { #[tokio::test] async fn memory_query_finds_summary() { let (dir, layout) = setup(); - let summary_path = dir.path().join("memory/summary.md"); + let summary_path = dir.path().join(".insomnia/memory/summary.md"); std::fs::write( &summary_path, format!("---\nupdated_at: {n}\n---\nthe needle is here\n", n = now()), @@ -552,9 +552,9 @@ mod tests { #[tokio::test] async fn memory_query_excludes_workflow_and_staging() { let (dir, layout) = setup(); - let wf = dir.path().join("memory/workflow/wf.md"); + let wf = dir.path().join(".insomnia/memory/workflow/wf.md"); std::fs::write(&wf, "needle in workflow\n").unwrap(); - let stg = dir.path().join("memory/_staging/abc.json"); + let stg = dir.path().join(".insomnia/memory/_staging/abc.json"); std::fs::write(&stg, "needle in staging\n").unwrap(); let (_, tool) = memory_query_tool(layout, QueryConfig::default())(); diff --git a/crates/memory/src/tool/read.rs b/crates/memory/src/tool/read.rs index 0d149179..75ebe101 100644 --- a/crates/memory/src/tool/read.rs +++ b/crates/memory/src/tool/read.rs @@ -144,7 +144,7 @@ mod tests { #[tokio::test] async fn read_decision_by_slug() { let (dir, layout) = setup(); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); std::fs::create_dir_all(path.parent().unwrap()).unwrap(); std::fs::write(&path, "alpha\nbeta\n").unwrap(); @@ -159,7 +159,7 @@ mod tests { #[tokio::test] async fn read_summary_without_slug() { let (dir, layout) = setup(); - let path = dir.path().join("memory/summary.md"); + let path = dir.path().join(".insomnia/memory/summary.md"); std::fs::create_dir_all(path.parent().unwrap()).unwrap(); std::fs::write(&path, "summary body\n").unwrap(); @@ -199,7 +199,7 @@ mod tests { #[tokio::test] async fn knowledge_path_resolution() { let (dir, layout) = setup(); - let path = dir.path().join("knowledge/policy.md"); + let path = dir.path().join(".insomnia/knowledge/policy.md"); std::fs::create_dir_all(path.parent().unwrap()).unwrap(); std::fs::write(&path, "k\n").unwrap(); diff --git a/crates/memory/src/tool/write.rs b/crates/memory/src/tool/write.rs index d41d8c04..6ca72ab8 100644 --- a/crates/memory/src/tool/write.rs +++ b/crates/memory/src/tool/write.rs @@ -149,7 +149,7 @@ mod tests { #[tokio::test] async fn write_creates_summary() { let (dir, layout) = setup(); - let path = dir.path().join("memory/summary.md"); + let path = dir.path().join(".insomnia/memory/summary.md"); let content = format!("---\nupdated_at: {n}\n---\nbody\n", n = now()); let (meta, tool) = write_tool(layout)(); @@ -187,7 +187,7 @@ mod tests { #[tokio::test] async fn write_update_existing() { let (dir, layout) = setup(); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); std::fs::create_dir_all(path.parent().unwrap()).unwrap(); let initial = format!( "---\ncreated_at: {n}\nupdated_at: {n}\nsources: []\nstatus: open\n---\nold\n", @@ -220,7 +220,7 @@ mod tests { #[tokio::test] async fn write_does_not_persist_on_lint_failure() { let (dir, layout) = setup(); - let path = dir.path().join("memory/decisions/foo.md"); + let path = dir.path().join(".insomnia/memory/decisions/foo.md"); let bad = "no frontmatter at all"; let (_, tool) = write_tool(layout)(); let inp = serde_json::json!({ diff --git a/crates/memory/src/workspace.rs b/crates/memory/src/workspace.rs index 9fe24e99..bf7ea1c3 100644 --- a/crates/memory/src/workspace.rs +++ b/crates/memory/src/workspace.rs @@ -1,20 +1,28 @@ //! Workspace-level path layout for the memory subsystem. //! -//! Resolves a workspace root into the concrete directories the linter -//! and tools operate on: +//! `WorkspaceLayout` carries the workspace root (typically the Pod's +//! pwd). All insomnia-managed content lives under the conventional +//! `/.insomnia/` subdirectory — the same place that holds +//! `manifest.toml` and `prompts/`. The memory subsystem nests its +//! trees inside it: //! -//! - `/memory/summary.md` -//! - `/memory/decisions/.md` -//! - `/memory/requests/.md` -//! - `/memory/workflow/.md` -//! - `/memory/_staging/.json` -//! - `/knowledge/.md` +//! - `/.insomnia/memory/summary.md` +//! - `/.insomnia/memory/decisions/.md` +//! - `/.insomnia/memory/requests/.md` +//! - `/.insomnia/memory/workflow/.md` +//! - `/.insomnia/memory/_staging/.json` +//! - `/.insomnia/knowledge/.md` +//! +//! Configuring `[memory]` with an empty body is therefore sufficient +//! for any workspace that already uses the `.insomnia/` convention; no +//! `workspace_root` override is needed. use std::path::{Path, PathBuf}; use crate::error::LintError; use crate::slug::Slug; +const INSOMNIA_DIR: &str = ".insomnia"; const MEMORY_DIR: &str = "memory"; const KNOWLEDGE_DIR: &str = "knowledge"; const SUMMARY_FILE: &str = "summary.md"; @@ -81,12 +89,17 @@ impl WorkspaceLayout { &self.root } + /// `/.insomnia/`. The base of every other memory path. + pub fn insomnia_dir(&self) -> PathBuf { + self.root.join(INSOMNIA_DIR) + } + pub fn memory_dir(&self) -> PathBuf { - self.root.join(MEMORY_DIR) + self.insomnia_dir().join(MEMORY_DIR) } pub fn knowledge_dir(&self) -> PathBuf { - self.root.join(KNOWLEDGE_DIR) + self.insomnia_dir().join(KNOWLEDGE_DIR) } pub fn summary_path(&self) -> PathBuf { @@ -126,13 +139,14 @@ impl WorkspaceLayout { } /// Classify a path under the memory tree. Returns `None` if the - /// path is not under `memory/` or `knowledge/` of this workspace, - /// or if it lives in `_staging/` (which is opaque to the linter). + /// path is not under `.insomnia/memory/` or `.insomnia/knowledge/` + /// of this workspace, or if it lives in `_staging/` (which is + /// opaque to the linter). /// /// On a conventional path that's *almost* a record but malformed - /// (e.g. `decisions/Foo.md` with an invalid slug), returns - /// `Err(LintError::InvalidSlug | InvalidPath)` so the caller can - /// surface it as a write violation. + /// (e.g. `.insomnia/memory/decisions/Foo.md` with an invalid slug), + /// returns `Err(LintError::InvalidSlug | InvalidPath)` so the caller + /// can surface it as a write violation. pub fn classify(&self, path: &Path) -> Result, LintError> { let memory = self.memory_dir(); let knowledge = self.knowledge_dir(); @@ -221,7 +235,7 @@ mod tests { #[test] fn classifies_summary() { let cp = layout() - .classify(&PathBuf::from("/ws/memory/summary.md")) + .classify(&PathBuf::from("/ws/.insomnia/memory/summary.md")) .unwrap() .unwrap(); assert_eq!(cp.kind, RecordKind::Summary); @@ -231,7 +245,7 @@ mod tests { #[test] fn classifies_decision_with_slug() { let cp = layout() - .classify(&PathBuf::from("/ws/memory/decisions/foo-bar.md")) + .classify(&PathBuf::from("/ws/.insomnia/memory/decisions/foo-bar.md")) .unwrap() .unwrap(); assert_eq!(cp.kind, RecordKind::Decision); @@ -241,7 +255,7 @@ mod tests { #[test] fn classifies_knowledge() { let cp = layout() - .classify(&PathBuf::from("/ws/knowledge/x.md")) + .classify(&PathBuf::from("/ws/.insomnia/knowledge/x.md")) .unwrap() .unwrap(); assert_eq!(cp.kind, RecordKind::Knowledge); @@ -250,7 +264,7 @@ mod tests { #[test] fn classifies_workflow() { let cp = layout() - .classify(&PathBuf::from("/ws/memory/workflow/wf.md")) + .classify(&PathBuf::from("/ws/.insomnia/memory/workflow/wf.md")) .unwrap() .unwrap(); assert_eq!(cp.kind, RecordKind::Workflow); @@ -260,7 +274,7 @@ mod tests { fn staging_returns_none() { assert!( layout() - .classify(&PathBuf::from("/ws/memory/_staging/abc.json")) + .classify(&PathBuf::from("/ws/.insomnia/memory/_staging/abc.json")) .unwrap() .is_none() ); @@ -285,7 +299,7 @@ mod tests { #[test] fn invalid_slug_rejected() { let err = layout() - .classify(&PathBuf::from("/ws/memory/decisions/Foo.md")) + .classify(&PathBuf::from("/ws/.insomnia/memory/decisions/Foo.md")) .unwrap_err(); assert!(matches!(err, LintError::InvalidSlug(_))); } @@ -293,7 +307,7 @@ mod tests { #[test] fn nested_under_record_dir_rejected() { let err = layout() - .classify(&PathBuf::from("/ws/memory/decisions/sub/foo.md")) + .classify(&PathBuf::from("/ws/.insomnia/memory/decisions/sub/foo.md")) .unwrap_err(); assert!(matches!(err, LintError::InvalidPath(_))); } @@ -301,7 +315,7 @@ mod tests { #[test] fn unknown_top_level_dir_rejected() { let err = layout() - .classify(&PathBuf::from("/ws/memory/something/foo.md")) + .classify(&PathBuf::from("/ws/.insomnia/memory/something/foo.md")) .unwrap_err(); assert!(matches!(err, LintError::InvalidPath(_))); } diff --git a/docs/plan/memory.md b/docs/plan/memory.md index 7e8f050a..ded4d6e5 100644 --- a/docs/plan/memory.md +++ b/docs/plan/memory.md @@ -14,6 +14,8 @@ Workflow(`/` で呼び出される制約付き作業フロー)は別 p ### 記録対象の 4 種 +本ドキュメント以下のパスはすべて **`/.insomnia/`** からの相対表記。`.insomnia/` は manifest / prompts と同じく workspace に紐付く insomnia コンテンツのルートで、memory もこの規約に従う。`workspace_root` 既定は Pod の pwd。 + | 種別 | パス | 備考 | | ---------------- | ---------------------------- | ------------------------------------------------------------------------------------------- | | Always-on サマリ | `memory/summary.md` | 1-5k tokens 目安 | diff --git a/resources/prompts/common/tool-usage.md b/resources/prompts/common/tool-usage.md index 4263c9e3..73b29ac9 100644 --- a/resources/prompts/common/tool-usage.md +++ b/resources/prompts/common/tool-usage.md @@ -2,3 +2,6 @@ Prefer the most specific tool for the job. When reading files you already know the path of, use the file-read tool directly instead of searching. When searching, use grep/glob primitives rather than shell pipelines. + +You can run multiple tools simultaneously by calling them within a single response. +It is recommended to run tools that handle asynchronous processing, such as queries and readings, in batches. diff --git a/resources/prompts/default.md b/resources/prompts/default.md index 81abe351..577fdc32 100644 --- a/resources/prompts/default.md +++ b/resources/prompts/default.md @@ -1,7 +1,5 @@ You are here as an agent of the "insomnia system". -Stay precise, edit code directly when asked, and avoid speculative refactoring. Explain what you changed in one short paragraph at the end of each turn. - {% include "common/workspace" %} {% include "common/tool-usage" %}