From 7660a460a523c8c0f96b1d024156addd4c7bb445 Mon Sep 17 00:00:00 2001 From: Timmy Date: Tue, 12 May 2026 19:25:47 +0100 Subject: [PATCH] =?UTF-8?q?wip(929):=20stage=209=20=E2=80=94=20drop=20FS-a?= =?UTF-8?q?rchived-deps=20scan;=20story=5Ftools/story/create.rs=20reads=20?= =?UTF-8?q?CRDT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit io/watcher and io/watcher/sweep were already CRDT-only — the watcher only watches .huskies/{project,agents}.toml, work-item events come from CRDT subscribe — so the remaining FS shadow reader was the bug-503 archived-dep warning in story_tools/story/create.rs (via check_archived_deps_from_list, which scanned .huskies/work/6_archived/). Migrate that call to the CRDT-direct `dep_is_archived_crdt`. Drop the now-unused helper and the four dead imports in bug/spike/refactor/criteria.rs that referenced it. io/story_metadata/deps.rs is reduced to a module-level comment pointing callers at the crdt_state helpers; nothing in io/ now scans the FS shadow tree. Co-Authored-By: Claude Opus 4.7 (1M context) --- server/src/http/mcp/story_tools/bug.rs | 2 +- server/src/http/mcp/story_tools/criteria.rs | 2 +- server/src/http/mcp/story_tools/refactor.rs | 2 +- server/src/http/mcp/story_tools/spike.rs | 2 +- .../src/http/mcp/story_tools/story/create.rs | 11 ++- server/src/io/story_metadata/deps.rs | 82 ++----------------- server/src/io/story_metadata/mod.rs | 1 - 7 files changed, 17 insertions(+), 85 deletions(-) diff --git a/server/src/http/mcp/story_tools/bug.rs b/server/src/http/mcp/story_tools/bug.rs index 31e68c93..582e584f 100644 --- a/server/src/http/mcp/story_tools/bug.rs +++ b/server/src/http/mcp/story_tools/bug.rs @@ -13,7 +13,7 @@ use crate::http::workflow::{ list_refactor_files, load_pipeline_state, load_upcoming_stories, remove_criterion_from_file, update_story_in_file, validate_story_dirs, }; -use crate::io::story_metadata::{check_archived_deps_from_list, parse_unchecked_todos}; +use crate::io::story_metadata::parse_unchecked_todos; use crate::service::story::parse_test_cases; use crate::slog_warn; #[allow(unused_imports)] diff --git a/server/src/http/mcp/story_tools/criteria.rs b/server/src/http/mcp/story_tools/criteria.rs index c88f8010..368eae1b 100644 --- a/server/src/http/mcp/story_tools/criteria.rs +++ b/server/src/http/mcp/story_tools/criteria.rs @@ -13,7 +13,7 @@ use crate::http::workflow::{ list_refactor_files, load_pipeline_state, load_upcoming_stories, remove_criterion_from_file, update_story_in_file, validate_story_dirs, }; -use crate::io::story_metadata::{check_archived_deps_from_list, parse_unchecked_todos}; +use crate::io::story_metadata::parse_unchecked_todos; use crate::service::story::parse_test_cases; use crate::slog_warn; #[allow(unused_imports)] diff --git a/server/src/http/mcp/story_tools/refactor.rs b/server/src/http/mcp/story_tools/refactor.rs index 55dd8ec8..b6156081 100644 --- a/server/src/http/mcp/story_tools/refactor.rs +++ b/server/src/http/mcp/story_tools/refactor.rs @@ -13,7 +13,7 @@ use crate::http::workflow::{ list_refactor_files, load_pipeline_state, load_upcoming_stories, remove_criterion_from_file, update_story_in_file, validate_story_dirs, }; -use crate::io::story_metadata::{check_archived_deps_from_list, parse_unchecked_todos}; +use crate::io::story_metadata::parse_unchecked_todos; use crate::service::story::parse_test_cases; use crate::slog_warn; #[allow(unused_imports)] diff --git a/server/src/http/mcp/story_tools/spike.rs b/server/src/http/mcp/story_tools/spike.rs index a77539c4..535e7c41 100644 --- a/server/src/http/mcp/story_tools/spike.rs +++ b/server/src/http/mcp/story_tools/spike.rs @@ -13,7 +13,7 @@ use crate::http::workflow::{ list_refactor_files, load_pipeline_state, load_upcoming_stories, remove_criterion_from_file, update_story_in_file, validate_story_dirs, }; -use crate::io::story_metadata::{check_archived_deps_from_list, parse_unchecked_todos}; +use crate::io::story_metadata::parse_unchecked_todos; use crate::service::story::parse_test_cases; use crate::slog_warn; #[allow(unused_imports)] diff --git a/server/src/http/mcp/story_tools/story/create.rs b/server/src/http/mcp/story_tools/story/create.rs index 8b2f9647..921ec776 100644 --- a/server/src/http/mcp/story_tools/story/create.rs +++ b/server/src/http/mcp/story_tools/story/create.rs @@ -2,7 +2,6 @@ use crate::http::context::AppContext; use crate::http::workflow::create_story_file; -use crate::io::story_metadata::check_archived_deps_from_list; use crate::slog_warn; use serde_json::Value; @@ -51,9 +50,15 @@ pub(crate) fn tool_create_story(args: &Value, ctx: &AppContext) -> Result = depends_on .as_deref() - .map(|deps| check_archived_deps_from_list(&root, deps)) + .map(|deps| { + deps.iter() + .copied() + .filter(|&d| crate::crdt_state::dep_is_archived_crdt(d)) + .collect() + }) .unwrap_or_default(); if !archived_deps.is_empty() { slog_warn!( diff --git a/server/src/io/story_metadata/deps.rs b/server/src/io/story_metadata/deps.rs index 6a956b64..8c218c89 100644 --- a/server/src/io/story_metadata/deps.rs +++ b/server/src/io/story_metadata/deps.rs @@ -1,78 +1,6 @@ -//! Dependency resolution helpers — filesystem-backed lookups that don't -//! require any in-memory CRDT state. +//! Dependency resolution helpers. //! -//! The CRDT-backed equivalents (`check_unmet_deps_crdt`, -//! `check_archived_deps_crdt`) live in `crate::crdt_state::read`; callers -//! that already have a CRDT entry should prefer those. This module exists -//! for the story-creation path, where dependency IDs are known in memory -//! before any CRDT entry has been written. -use std::fs; -use std::path::Path; - -/// Return `true` if a story with the given numeric ID exists specifically in `6_archived`. -fn dep_is_archived(project_root: &Path, dep_number: u32) -> bool { - let prefix = format!("{dep_number}_"); - let exact = dep_number.to_string(); - let dir = project_root - .join(".huskies") - .join("work") - .join("6_archived"); - if let Ok(entries) = fs::read_dir(&dir) { - for entry in entries.flatten() { - let path = entry.path(); - if path.extension().and_then(|e| e.to_str()) != Some("md") { - continue; - } - if let Some(stem) = path.file_stem().and_then(|s| s.to_str()) - && (stem == exact || stem.starts_with(&prefix)) - { - return true; - } - } - } - false -} - -/// Given an explicit list of dep numbers, return those already in `6_archived`. -/// -/// Used at story-creation time when the dep list is known in memory (before -/// the story file has been written), so the caller does not need to parse -/// the story. -pub fn check_archived_deps_from_list(project_root: &Path, deps: &[u32]) -> Vec { - deps.iter() - .copied() - .filter(|&dep| dep_is_archived(project_root, dep)) - .collect() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn check_archived_deps_from_list_returns_archived_ids() { - let tmp = tempfile::tempdir().unwrap(); - let done = tmp.path().join(".huskies/work/5_done"); - let archived = tmp.path().join(".huskies/work/6_archived"); - std::fs::create_dir_all(&done).unwrap(); - std::fs::create_dir_all(&archived).unwrap(); - std::fs::write(done.join("10_story_done.md"), "# done\n").unwrap(); - std::fs::write(archived.join("20_story_old.md"), "# old\n").unwrap(); - let result = check_archived_deps_from_list(tmp.path(), &[10, 20, 30]); - assert_eq!(result, vec![20]); - } - - #[test] - fn dep_is_archived_distinguishes_done_from_archived() { - let tmp = tempfile::tempdir().unwrap(); - let done = tmp.path().join(".huskies/work/5_done"); - let archived = tmp.path().join(".huskies/work/6_archived"); - std::fs::create_dir_all(&done).unwrap(); - std::fs::create_dir_all(&archived).unwrap(); - std::fs::write(done.join("10_story_done.md"), "# done\n").unwrap(); - std::fs::write(archived.join("20_story_old.md"), "# old\n").unwrap(); - assert!(!dep_is_archived(tmp.path(), 10)); - assert!(dep_is_archived(tmp.path(), 20)); - assert!(!dep_is_archived(tmp.path(), 99)); - } -} +//! Story 929: all dep-status checks now go through the CRDT-backed +//! equivalents in `crate::crdt_state::read` (`check_unmet_deps_crdt`, +//! `check_archived_deps_crdt`, `dep_is_archived_crdt`). This module no +//! longer hosts a filesystem-backed scan of `6_archived/`. diff --git a/server/src/io/story_metadata/mod.rs b/server/src/io/story_metadata/mod.rs index d9c0a7b0..9f71e14a 100644 --- a/server/src/io/story_metadata/mod.rs +++ b/server/src/io/story_metadata/mod.rs @@ -10,6 +10,5 @@ mod deps; mod parser; mod types; -pub use deps::check_archived_deps_from_list; pub use parser::{is_story_frozen_in_store, parse_unchecked_todos, resolve_qa_mode}; pub use types::QaMode;