- 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.
95 lines
2.8 KiB
Rust
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);
|
|
}
|