/// FIST-Mbt core: task model & state machine.
/// 迁移自 FIST(Python) 的状态机与分层递归理念(七条金条第 4 条:唯一指挥官)。
/// 任务七态状态机
pub enum TaskStatus {
/// 待领取
Pending
/// 已领取
Claimed
/// 拆分中
Splitting
/// 执行中
Executing
/// 待验收
Reviewing
/// 已完成
Completed
/// 已归档
Archived
} derive(Eq, Debug)
pub fn TaskStatus::to_string(self : TaskStatus) -> String {
match self {
Pending => "待领取"
Claimed => "已领取"
Splitting => "拆分中"
Executing => "执行中"
Reviewing => "待验收"
Completed => "已完成"
Archived => "已归档"
}
}
pub fn TaskStatus::from_string(s : String) -> Option[TaskStatus] {
match s {
"待领取" => Some(Pending)
"已领取" => Some(Claimed)
"拆分中" => Some(Splitting)
"执行中" => Some(Executing)
"待验收" => Some(Reviewing)
"已完成" => Some(Completed)
"已归档" => Some(Archived)
_ => None
}
}
/// 排序权重(用于统计/展示)
pub fn TaskStatus::order(self : TaskStatus) -> Int {
match self {
Pending => 0
Claimed => 1
Splitting => 2
Executing => 3
Reviewing => 4
Completed => 5
Archived => 6
}
}
/// FIST-Mbt 任务实体
pub struct Task {
/// 形如 T0 / T0.1 / T0.1.2 的层级 id
id : String
parent_id : String?
project_dir : String
priority : String
importance : String
/// K 值:根=3,每拆一层减 1;K<=1 为原子任务
depth : Int
/// 拆分数量(默认 3)
split_n : Int
status : TaskStatus
assignee : String?
description : String
deliverable : String
created_at : String
updated_at : String
completed_by : String?
cleanup_mode : String
} derive(Eq, Debug)
/// 便捷状态访问
pub fn Task::status_to_string(self : Task) -> String { self.status.to_string() }
pub fn Task::get_id(self : Task) -> String { self.id }
pub fn Task::get_parent(self : Task) -> String? { self.parent_id }
pub fn Task::get_status(self : Task) -> TaskStatus { self.status }
pub fn Task::get_depth(self : Task) -> Int { self.depth }
pub fn Task::get_description(self : Task) -> String { self.description }
pub fn Task::get_assignee(self : Task) -> String? { self.assignee }
pub fn Task::get_updated_at(self : Task) -> String { self.updated_at }
pub fn Task::is_leaf(self : Task) -> Bool { self.depth <= 1 }
/// 构造器(字段带默认值)
pub fn Task::new(
id~ : String,
project_dir~ : String,
description~ : String = "",
priority~ : String = "中",
importance~ : String = "中",
depth~ : Int = 3,
split_n~ : Int = 3,
parent_id~ : String = "",
assignee~ : String = "",
cleanup_mode~ : String = "deferred",
created_at~ : String = "",
) -> Task {
{
id,
parent_id: if parent_id == "" { None } else { Some(parent_id) },
project_dir,
priority,
importance,
depth,
split_n,
status: Pending,
assignee: if assignee == "" { None } else { Some(assignee) },
description,
deliverable: "",
created_at,
updated_at: created_at,
completed_by: None,
cleanup_mode,
}
}
/// —— 状态迁移 ——
/// 每个迁移都是纯函数(返回新 Task),状态机非法流转直接拒绝。
/// 返回 Err(msg) 表示非法迁移。
/// 待领取 -> 已领取(角色:any active agent)
pub fn Task::claim(self : Task, assignee~ : String) -> Result[Task, String] {
match self.status {
Pending =>
if assignee == "" {
Err("claim 需要 assignee")
} else {
Ok({
..self,
status: Claimed,
assignee: Some(assignee),
updated_at: self.updated_at,
})
}
_ =>
Err(
"非法迁移: claim 要求状态 [待领取],当前是 [" +
self.status.to_string() +
"]",
)
}
}
/// 已领取 -> 拆分中(指挥官拆解)
pub fn Task::split(self : Task) -> Result[Task, String] {
match self.status {
Claimed =>
if self.is_leaf() {
Err("原子任务(K<=1)不可再拆分")
} else {
Ok({ ..self, status: Splitting, })
}
_ =>
Err(
"非法迁移: split 要求状态 [已领取],当前是 [" +
self.status.to_string() +
"]",
)
}
}
/// 拆分中 -> 执行中(进入执行)
pub fn Task::execute(self : Task) -> Result[Task, String] {
match self.status {
Splitting | Claimed => Ok({ ..self, status: Executing, })
_ =>
Err(
"非法迁移: execute 要求状态 [拆分中/已领取],当前是 [" +
self.status.to_string() +
"]",
)
}
}
/// 执行中 -> 待验收
pub fn Task::submit(self : Task) -> Result[Task, String] {
match self.status {
Executing => Ok({ ..self, status: Reviewing, })
_ =>
Err(
"非法迁移: submit 要求状态 [执行中],当前是 [" +
self.status.to_string() +
"]",
)
}
}
/// 待验收 -> 已完成(人类主权:completed_by 必须 human / human_steward 或明确授权)
pub fn Task::complete(self : Task, completed_by~ : String) -> Result[Task, String] {
match self.status {
Reviewing =>
if completed_by == "" {
Err("complete 需要 completed_by 身份")
} else {
Ok({
..self,
status: Completed,
completed_by: Some(completed_by),
})
}
_ =>
Err(
"非法迁移: complete 要求状态 [待验收],当前是 [" +
self.status.to_string() +
"]",
)
}
}
/// 已完成 -> 已归档
pub fn Task::archive(self : Task) -> Result[Task, String] {
match self.status {
Completed => Ok({ ..self, status: Archived, })
_ =>
Err(
"非法迁移: archive 要求状态 [已完成],当前是 [" +
self.status.to_string() +
"]",
)
}
}
/// 任意非归档状态 -> 已领取(被打回重做)
pub fn Task::reopen(self : Task) -> Result[Task, String] {
match self.status {
Archived => Err("已归档任务不可 reopen,请重新发布")
_ => Ok({ ..self, status: Claimed, })
}
}
/// 生成子任务 id:T0.1.2 -> T0.1.2.1
pub fn child_id(parent_id~ : String, idx~ : Int) -> String {
"\{parent_id}.\{idx}"
}
/// 任务转 JSON(供 MCP resource / tool 输出)
pub fn Task::to_json(self : Task) -> Json {
let m : Map[String, Json] = Map([])
m.set("id", Json::string(self.id))
match self.parent_id {
Some(p) => m.set("parent_id", Json::string(p))
None => m.set("parent_id", Json::null())
}
m.set("project_dir", Json::string(self.project_dir))
m.set("priority", Json::string(self.priority))
m.set("importance", Json::string(self.importance))
m.set("depth", Json::number(self.depth.to_double()))
m.set("split_n", Json::number(self.split_n.to_double()))
m.set("status", Json::string(self.status.to_string()))
match self.assignee {
Some(a) => m.set("assignee", Json::string(a))
None => m.set("assignee", Json::null())
}
m.set("description", Json::string(self.description))
m.set("deliverable", Json::string(self.deliverable))
m.set("created_at", Json::string(self.created_at))
m.set("updated_at", Json::string(self.updated_at))
match self.completed_by {
Some(c) => m.set("completed_by", Json::string(c))
None => m.set("completed_by", Json::null())
}
m.set("cleanup_mode", Json::string(self.cleanup_mode))
m.set("is_leaf", Json::boolean(self.is_leaf()))
Json::object(m)
}