6e704a33b7
Migrate the last three callers of the FS-scanning dependency helpers to the CRDT-direct equivalents and delete the dead helpers: - agents/pool/auto_assign/story_checks.rs: has_unmet_dependencies and check_archived_dependencies now wrap check_unmet_deps_crdt / check_archived_deps_crdt directly. Tests rewritten to seed the CRDT. - http/mcp/story_tools/story/update.rs: bug-503 archived-dep warning now reads from CRDT instead of scanning 6_archived. - agents/pool/pipeline/advance/helpers.rs: resolve_qa_mode_from_store is CRDT-only (the FS fallback for content-store-empty stories is gone). - io/story_metadata/parser.rs: resolve_qa_mode_from_content removed. - io/story_metadata/deps.rs: check_unmet_deps and dep_is_done deleted, along with the unused check_unmet_deps_from_list helper. - io/story_metadata/mod.rs: re-exports trimmed accordingly. check_archived_deps_from_list survives because story-creation still calls it before the CRDT entry exists (used from story_tools/story/create.rs). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
84 lines
2.6 KiB
Rust
84 lines
2.6 KiB
Rust
//! Pure-content helpers and CRDT-backed metadata lookups.
|
|
//!
|
|
//! Story 865 stripped YAML front matter from stored content and the codebase
|
|
//! at large; the only remaining functions here read the CRDT or operate on
|
|
//! the markdown body directly.
|
|
use super::types::QaMode;
|
|
|
|
/// Parse unchecked todo items (`- [ ] ...`) from a markdown string.
|
|
pub fn parse_unchecked_todos(contents: &str) -> Vec<String> {
|
|
contents
|
|
.lines()
|
|
.filter_map(|line| {
|
|
let trimmed = line.trim();
|
|
trimmed.strip_prefix("- [ ] ").map(|text| text.to_string())
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
/// Resolve the effective QA mode for a story by ID via the CRDT.
|
|
///
|
|
/// Returns `default` when the story has no entry or its `qa_mode` register is
|
|
/// unset. Spikes are **not** handled here — callers override to `Human` for
|
|
/// spikes themselves.
|
|
pub fn resolve_qa_mode(story_id: &str, default: QaMode) -> QaMode {
|
|
crate::crdt_state::read_item(story_id)
|
|
.and_then(|view| view.qa_mode().map(str::to_string))
|
|
.as_deref()
|
|
.and_then(QaMode::from_str)
|
|
.unwrap_or(default)
|
|
}
|
|
|
|
/// Return `true` if the story is in the `Frozen` pipeline stage.
|
|
///
|
|
/// Checks the typed CRDT stage via `read_typed`. Used by the pipeline advance
|
|
/// code to suppress stage transitions for frozen stories.
|
|
pub fn is_story_frozen_in_store(story_id: &str) -> bool {
|
|
crate::pipeline_state::read_typed(story_id)
|
|
.ok()
|
|
.flatten()
|
|
.map(|item| item.stage.is_frozen())
|
|
.unwrap_or(false)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn parse_unchecked_todos_mixed() {
|
|
let input = "## AC\n- [ ] First thing\n- [x] Done thing\n- [ ] Second thing\n";
|
|
assert_eq!(
|
|
parse_unchecked_todos(input),
|
|
vec!["First thing", "Second thing"]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn parse_unchecked_todos_all_checked() {
|
|
let input = "- [x] Done\n- [x] Also done\n";
|
|
assert!(parse_unchecked_todos(input).is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_unchecked_todos_no_checkboxes() {
|
|
let input = "# Story\nSome text\n- A bullet\n";
|
|
assert!(parse_unchecked_todos(input).is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_unchecked_todos_leading_whitespace() {
|
|
let input = " - [ ] Indented item\n";
|
|
assert_eq!(parse_unchecked_todos(input), vec!["Indented item"]);
|
|
}
|
|
|
|
#[test]
|
|
fn resolve_qa_mode_falls_back_to_default_when_crdt_empty() {
|
|
crate::crdt_state::init_for_test();
|
|
assert_eq!(
|
|
resolve_qa_mode("9999_no_such_story", QaMode::Server),
|
|
QaMode::Server
|
|
);
|
|
}
|
|
}
|