refactor: unify Memory feature configuration authority

This commit is contained in:
2026-09-04 22:55:37 +09:00
parent 5ee77698db
commit 1e674d70c2
20 changed files with 947 additions and 637 deletions
+13 -5
View File
@@ -152,13 +152,10 @@ pub enum MemoryStagingAffectedMemoryOperation {
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MemoryConsolidateStagingOperation {
#[serde(default)]
pub force: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub threshold_files: Option<usize>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub threshold_bytes: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -450,10 +447,21 @@ mod tests {
use super::*;
use crate::extract::{CandidateKind, ExtractedCandidate};
#[test]
fn consolidation_operation_rejects_caller_owned_thresholds() {
let error =
serde_json::from_value::<MemoryConsolidateStagingOperation>(serde_json::json!({
"force": false,
"threshold_files": 1,
}))
.unwrap_err();
assert!(error.to_string().contains("threshold_files"));
}
#[test]
fn staging_list_read_close_records_reason_and_deletes_candidate() {
let temp = tempfile::tempdir().unwrap();
let layout = WorkspaceLayout::resolve(&manifest::MemoryConfig::default(), temp.path());
let layout = WorkspaceLayout::resolve(temp.path());
let source = SourceRef {
segment_id: "segment-1".into(),
range: [0, 1],
+1 -2
View File
@@ -21,8 +21,7 @@ pub struct StagingEntry {
pub id: Uuid,
pub path: PathBuf,
pub record: StagingRecord,
/// このファイルのバイト長。閾値判定 (`consolidation_threshold_bytes`)
/// に使う。
/// このファイルのバイト長。Backendのconsolidation閾値判定に使用する。
pub bytes: u64,
}
+8 -33
View File
@@ -70,24 +70,12 @@ impl WorkspaceLayout {
Self { root: root.into() }
}
/// Resolve a layout from a `MemoryConfig`.
/// Resolve a layout from the nearest Memory marker.
///
/// An explicit `memory.workspace_root` is honored exactly. Without an
/// explicit root, resolution searches `default_root` and its ancestors for
/// the nearest `.yoi/memory` directory. This keeps child worktrees that
/// contain `.yoi` project records such as tickets from
/// becoming independent memory roots merely because they contain `.yoi`.
///
/// If no memory marker exists, this falls back to `default_root` because
/// existing call sites require a concrete layout. That fallback is a
/// no-marker compatibility path, not a `.yoi` marker interpretation; it
/// must not be used as evidence that `.yoi` alone enables repo-local
/// memory.
pub fn resolve(cfg: &manifest::MemoryConfig, default_root: &Path) -> Self {
if let Some(root) = &cfg.workspace_root {
return Self::new(root.clone());
}
/// Resolution searches `default_root` and its ancestors for the nearest
/// `.yoi/memory` directory. This legacy local-storage helper owns its path
/// policy directly; resolved Worker Manifests do not carry storage paths.
pub fn resolve(default_root: &Path) -> Self {
let root =
find_memory_marker_root(default_root).unwrap_or_else(|| default_root.to_path_buf());
Self::new(root)
@@ -335,16 +323,6 @@ mod tests {
assert!(matches!(err, LintError::InvalidPath(_)));
}
#[test]
fn resolve_uses_workspace_root_when_set() {
let cfg = manifest::MemoryConfig {
workspace_root: Some(PathBuf::from("/explicit")),
..Default::default()
};
let layout = WorkspaceLayout::resolve(&cfg, Path::new("/fallback"));
assert_eq!(layout.root(), Path::new("/explicit"));
}
#[test]
fn resolve_selects_nearest_ancestor_memory_marker_when_workspace_root_missing() {
let tmp = TempDir::new().unwrap();
@@ -353,8 +331,7 @@ mod tests {
std::fs::create_dir_all(workspace.join(".yoi/memory")).unwrap();
std::fs::create_dir_all(&child).unwrap();
let cfg = manifest::MemoryConfig::default();
let layout = WorkspaceLayout::resolve(&cfg, &child);
let layout = WorkspaceLayout::resolve(&child);
assert_eq!(layout.root(), workspace.as_path());
}
@@ -366,8 +343,7 @@ mod tests {
std::fs::create_dir_all(workspace.join(".yoi/memory")).unwrap();
std::fs::create_dir_all(child.join(".yoi/tickets")).unwrap();
let cfg = manifest::MemoryConfig::default();
let layout = WorkspaceLayout::resolve(&cfg, &child);
let layout = WorkspaceLayout::resolve(&child);
assert_eq!(layout.root(), workspace.as_path());
}
@@ -381,8 +357,7 @@ mod tests {
assert_eq!(find_memory_marker_root(&child), None);
let cfg = manifest::MemoryConfig::default();
let layout = WorkspaceLayout::resolve(&cfg, &child);
let layout = WorkspaceLayout::resolve(&child);
assert_eq!(layout.root(), child.as_path());
}
}