KeiSeiKit-1.0/_primitives/_rust/kei-task/tests/integration.rs
Parfii-bot adc007b7b0 feat(primitives): 10 Rust crates extracted from LBM (Genesis-scrubbed)
- kei-router — keyword-dispatch meta-tool (CfC ML fallback removed)
- kei-sage — Obsidian-style knowledge graph, FTS5 + BFS + PageRank
- kei-task — task DAG with deps, milestones, dependency-chain queries
- kei-chat-store — Claude conversation session persistence + FTS search
- kei-crossdomain — typed-edge store + BFS cross-domain glue
- kei-search-core — 3-wave deep research with microcent budget cap
- kei-content-store — asset + prompt + campaign registry
- kei-social-store — people + interactions CRM (lite)
- kei-curator — edge-decay graph hygiene utility
- kei-auth — multi-tenant session tokens (replaces single-bearer)

Genesis-scan pre-import pass: skipped pkg/mxl1/*, pkg/inference/*, pkg/trainer/*,
pkg/nc01/*, internal/ml/* (all Genesis/CfC adjacent, sensitive IP).
Security: skipped tools_threat/radio/protocol/med/mlreg (offensive/banned).
Domain verticals skipped: hr/legal/infra/ops/api/osint/edu/geo/hw/finance.

New 'mcp' profile in MANIFEST.toml bundles all 10 for MCP server deployment.

Workspace now 24 crates, cargo check --workspace clean, 94 workspace tests pass.
2026-04-22 12:48:56 +08:00

95 lines
2.8 KiB
Rust

//! kei-task integration tests.
use kei_task::deps::{add_dependency, dependency_chain};
use kei_task::graph::list_edges;
use kei_task::milestones::{create_milestone, link_task_to_milestone, tasks_in_milestone};
use kei_task::search::search;
use kei_task::{Milestone, Store, Task};
fn mk() -> Store { Store::open_memory().unwrap() }
fn mktask(title: &str) -> Task {
Task { title: title.into(), priority: "high".into(), ..Default::default() }
}
#[test]
fn create_and_get() {
let s = mk();
let id = s.create_task(&mktask("a")).unwrap();
let t = s.get_task(id).unwrap().unwrap();
assert_eq!(t.title, "a");
assert_eq!(t.status, "pending");
}
#[test]
fn update_persists() {
let s = mk();
let id = s.create_task(&mktask("a")).unwrap();
let mut t = s.get_task(id).unwrap().unwrap();
t.status = "in_progress".into();
s.update_task(&t).unwrap();
let u = s.get_task(id).unwrap().unwrap();
assert_eq!(u.status, "in_progress");
}
#[test]
fn cycle_detected() {
let s = mk();
let a = s.create_task(&mktask("a")).unwrap();
let b = s.create_task(&mktask("b")).unwrap();
let c = s.create_task(&mktask("c")).unwrap();
add_dependency(&s, a, b, "blocks").unwrap();
add_dependency(&s, b, c, "blocks").unwrap();
// a -> b -> c; now c -> a would be a cycle
let err = add_dependency(&s, c, a, "blocks");
assert!(err.is_err(), "cycle detection must reject");
}
#[test]
fn milestone_linking() {
let s = mk();
let t = s.create_task(&mktask("design")).unwrap();
let ms_id = create_milestone(&s, &Milestone {
name: "v1".into(), ..Default::default() }).unwrap();
link_task_to_milestone(&s, t, ms_id).unwrap();
let tasks = tasks_in_milestone(&s, ms_id).unwrap();
assert_eq!(tasks, vec![t]);
}
#[test]
fn dependency_chain_traversal() {
let s = mk();
let a = s.create_task(&mktask("a")).unwrap();
let b = s.create_task(&mktask("b")).unwrap();
let c = s.create_task(&mktask("c")).unwrap();
add_dependency(&s, a, b, "blocks").unwrap();
add_dependency(&s, b, c, "blocks").unwrap();
let chain = dependency_chain(&s, a).unwrap();
assert!(chain.contains(&b));
assert!(chain.contains(&c));
assert_eq!(chain.len(), 2);
}
#[test]
fn task_graph_edges() {
let s = mk();
let a = s.create_task(&mktask("a")).unwrap();
let b = s.create_task(&mktask("b")).unwrap();
add_dependency(&s, a, b, "blocks").unwrap();
let edges = list_edges(&s).unwrap();
assert_eq!(edges.len(), 1);
assert_eq!(edges[0].task_id, a);
assert_eq!(edges[0].depends_on, b);
}
#[test]
fn search_finds_task() {
let s = mk();
s.create_task(&Task {
title: "refactor router".into(),
description: "split monolith".into(),
..Default::default()
}).unwrap();
let hits = search(&s, "refactor", 10).unwrap();
assert_eq!(hits.len(), 1);
}