fist-mbt

    FIST commander task orchestration rewritten in pure MoonBit, exposed as an MCP server.

    MCP
    task-orchestration
    multi-agent
    FIST
    Download zip
    Author
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    3 hours ago
    Downloads
    1

    #AIGC: Label: "1" ContentProducer: 001191440300708461136T1XGW3 ProduceID: 9f2a11add43fbf12a546606fb2b962ab_d6da448aa8e311f1a393525400f8a581 ReservedCode1: GRSWKKcGS+h75rRxWqwGNxtMKibO8CYeDd9QifndbDCNr64hZqY8aT7XDiY4qeVSpsLrDQv1ZIPpWWKx1A7KftfgIBoeC66TS6YB89/6jVD8qk7JUFwhnHzofKO0i5p56pwt/4995ml2uT5EUgNLh+hSlI55QPNg5iJ7aPSKh9X9yXgSRZDtCB8Skt0= ContentPropagator: 001191440300708461136T1XGW3 PropagateID: 9f2a11add43fbf12a546606fb2b962ab_d6da448aa8e311f1a393525400f8a581 ReservedCode2: GRSWKKcGS+h75rRxWqwGNxtMKibO8CYeDd9QifndbDCNr64hZqY8aT7XDiY4qeVSpsLrDQv1ZIPpWWKx1A7KftfgIBoeC66TS6YB89/6jVD8qk7JUFwhnHzofKO0i5p56pwt/4995ml2uT5EUgNLh+hSlI55QPNg5iJ7aPSKh9X9yXgSRZDtCB8Skt0=

    #FIST-Mbt

    Made with MoonBit

    CI

    FIST 指挥官任务分配体系(原 Python 实现)用 纯 MoonBit 原生重写 并包装为 MCP Server 的参赛作品(2026 MoonBit 九月黑客松)。

    指挥官(人类 / 主力模型)通过标准 MCP 协议调用 FIST-Mbt 暴露的 15 个 MCP 工具,完成任务的 发布 → 认领 → 拆分 → 执行 → 提交 → 验收 → 归档 完整闭环,全程贯彻 FIST 七条金条原则。

    该项目为 E:\IDEProjects\AI\FIST(Python)的 MoonBit 原生重写 + MCP 化,非原代码搬运。


    #快速开始

    依赖:MoonBit 工具链(≥ 0.1.20260827,需支持 errdeferasync)。

    # 依赖解析 & 编译 moon check moon build --target native # 运行测试(7 项核心状态机单测) moon test # 启动 MCP Server(STDIO 传输) moon run # 或直接运行编译产物(等价) ./_build/native/debug/build/cmd/main/main.exe

    任意 MCP 客户端(Claude Desktop / MCP Host / 自研 JSON-RPC 客户端)以 STDIO 方式拉起该可执行文件即可交互。

    #最小调用示例(JSON-RPC over STDIO)

    {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ "name":"publish", "arguments":{"project_dir":"E:/proj/demo","description":"示例根任务","created_by":"human_steward","now":"2026-09-05T10:00:00Z"}, "_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28"} }}


    #MCP 暴露面

    #Tools(10)

    工具说明关键参数
    publish发布根任务(仅 human_steward/human)project_dir, description, created_by, now
    plan对已认领任务拆分为子任务task_id, split_n, by, now
    claim认领任务(待领取 → 已领取)task_id, assignee, now
    execute记录执行交付物(→ 执行中)task_id, deliverable, now
    submit提交验收(→ 待验收)task_id, now
    verify验收(→ 已完成)task_id, verifier, now
    archive归档(→ 已归档,仅人类指挥官)task_id, by, now
    list列出全部任务,可按状态过滤status(可选)
    get查询单个任务详情task_id
    delete删除任务(仅限已归档)task_id

    #Resources(2)

    URI内容
    fist://principlesFIST 七条金条原则(JSON)
    fist://overview任务体系概览

    #Prompts(2)

    名称用途
    fist:check_in执行者开工打卡自查模板
    fist:verify验收人验收要点模板


    #架构

    E:\IDEProjects\AI\FIST-Mbt ├── core_task.mbt # 任务实体 + 七态状态机(待领取/已领取/拆分中/执行中/待验收/已完成/已归档) ├── core_role.mbt # 八角色权限矩阵(human_steward/leader/executor/searcher/reviewer/cleaner/verifier/documenter) ├── core_principle.mbt # 七条金条原则常量 ├── store.mbt # Store trait + MemoryStore 内存实现(后续可换 SQLite) ├── engine.mbt # FistEngine:publish/plan/claim/execute/submit/verify/archive/list/get/delete 完整闭环 ├── server.mbt # MCPServer 装配:tools/resources/prompts 注册 + run_stdio ├── cmd/main/ # 可执行入口(async fn main → run_server) ├── fist-mbt_test.mbt # 黑盒单测(moon test) ├── README.mbt.md # 本文档 └── CHANGELOG.md

    设计要点

    • 纯 MoonBit 实现,无 Rust / C 包装;MCP 协议层使用 colmugx/mcp(Apache-2.0,协议 2026-07-28)。
    • 领域核心(core*/store/engine)与协议层(server)分离,核心为纯逻辑、易单测。
    • K 值递归衰减:根任务 depth=3,每拆一层减 1,depth≤1 为原子任务不再拆分。
    • plan 需任务处于已领取态(先 claimplan),保证拆分动作归属到具体负责人。


    #状态机(七态)

    待领取 --claim--> 已领取 --plan--> 拆分中 --execute--> 执行中 已领取 --execute--> 执行中 执行中 --submit--> 待验收 --verify--> 已完成 --archive--> 已归档 --delete--> 移除 待验收 --reopen--> 已领取(被打回重做)

    非法迁移由状态机拒绝并返回错误,例如未认领直接 plan / execute 会报「非法迁移」。


    #测试

    moon test # 7 项黑盒测试全部通过

    覆盖:根任务发布、发布权限(仅人类指挥官)、claim/plan/execute/submit/verify/archive/delete 全闭环、 非法迁移拦截(未认领 plan / execute、未归档 delete)、按状态过滤查询。

    另含 MCP 全链路冒烟验证(JSON-RPC over STDIO):publish → claim → plan → 子任务 claim/execute/submit/verify → list/get → resources/read,全部通过。


    #移植与合规声明

    • 来源E:\IDEProjects\AI\FIST(Python),作者 victo。
    • 许可证:Apache-2.0。
    • 本期范围:用 MoonBit 原生重写核心领域逻辑与状态机,并封装为 MCP Server; 未搬运 Python 原代码,未包含原项目未开源的业务数据。
    • 原 Python 项目中的 scheduler / executor / webpanel 等模块不在本期范围内(见 CHANGELOG 演进说明)。


    #License

    Apache-2.0 (内容由AI生成,仅供参考)

    Store

    pub trait Store {
    fn create_task(Self, Task) -> Result[Unit, String]
    fn get_task(Self, String) -> Task?
    fn update_task(Self, Task) -> Result[Unit, String]
    fn list_tasks(Self) -> Array[Task]
    fn delete_task(Self, String) -> Result[Unit, String]
    fn clear(Self) -> Unit
    }
    仓库统一接口

    Action

    pub enum Action {
    Publish
    Dispatch
    Search
    Allocate
    Claim
    Execute
    Submit
    Verify
    Complete
    Archive
    Reopen
    Observe
    ManageProject
    } derive(Eq,
    Debug
    )
    每个任务的完整操作清单

    Action::to_string

    fn Action::to_string(self : Action) -> String
    Action 可读名(供错误消息)

    FistEngine

    pub struct FistEngine {
    store : StoreBackend
    }
    核心引擎:持有 store,暴露指挥-执行-验收完整闭环。 store 为后端路由(内存 / SQLite),业务逻辑不感知具体实现。

    FistEngine::all_subtasks_completed

    fn FistEngine::all_subtasks_completed(self : FistEngine, parent : Task) -> Bool
    是否为「非叶节点且所有直接子任务都已完成」

    FistEngine::archive

    fn FistEngine::archive(self : FistEngine, task_id~ : String, by~ : String, now~ : String) -> Result[Task, String]
    人类确认归档:Completed -> Archived(仅限人类指挥官)

    FistEngine::children_of

    fn FistEngine::children_of(self : FistEngine, task_id : String) -> Array[Task]
    列出某任务的所有直接子任务

    FistEngine::claim

    fn FistEngine::claim(self : FistEngine, task_id~ : String, assignee~ : String, now~ : String) -> Result[Task, String]
    认领任务(executor 认领,待领取 -> 已领取 -> 执行中)

    FistEngine::delete_task

    fn FistEngine::delete_task(self : FistEngine, task_id : String) -> Result[Unit, String]
    删除任务(仅限已归档,ARCHIVING 清理)

    FistEngine::execute

    fn FistEngine::execute(self : FistEngine, task_id~ : String, deliverable~ : String, now~ : String) -> Result[Task, String]
    记录执行交付物

    FistEngine::get_task

    fn FistEngine::get_task(self : FistEngine, task_id : String) -> Task?
    查询单个任务

    FistEngine::list_all

    fn FistEngine::list_all(self : FistEngine) -> Array[Task]
    列出全部任务

    FistEngine::list_by_status

    fn FistEngine::list_by_status(self : FistEngine, status : TaskStatus) -> Array[Task]
    按状态过滤列出

    FistEngine::new

    fn FistEngine::new(store? : StoreBackend) -> FistEngine

    FistEngine::open_sqlite

    fn FistEngine::open_sqlite(db_path : String) -> FistEngine?
    以指定 SQLite 数据库打开持久化引擎(内建数据库入口;失败返回 None 供调用方回退)。

    FistEngine::plan

    fn FistEngine::plan(self : FistEngine, task_id~ : String, split_n? : Int, by~ : String, now~ : String) -> Result[Array[String], String]
    对指定任务生成子任务树(一层)。非原子任务才可拆分。 返回生成的子任务 id 列表。

    FistEngine::plan_deep

    fn FistEngine::plan_deep(self : FistEngine, task_id~ : String, split_n? : Int, by~ : String, spec? : Json?, now~ : String) -> Result[Json, String]
    AO 式递归拆解入口:对指定任务拆出整棵子任务树并写库。

    入参: task_id 要拆解的根/拳节任务 id(非原子任务才可拆); split_n 每层默认拆分数(无 spec.laws 时生效,默认 3); by 执行拆解的拳长身份(仅记录); spec 可选 omega spec JSON(laws 作切割依据,fingerprint 作验收基准); now 时间戳。

    返回:{ "root", "by", "created", "tree" },tree 为多层子树结构; 任一子节点非叶时将继续递归(depth 递减,is_leaf=depth<=1 停止)。

    FistEngine::publish

    fn FistEngine::publish(self : FistEngine, project_dir~ : String, description~ : String, created_by~ : String, now~ : String) -> Result[String, String]
    发布根任务(仅限人类指挥官)

    FistEngine::reopen_task

    fn FistEngine::reopen_task(self : FistEngine, task_id : String, now : String) -> Result[Task, String]
    回滚/重派:任意非归档任务 -> 已领取(M4 heal watchdog 用)。返回回滚后的任务。

    FistEngine::submit

    fn FistEngine::submit(self : FistEngine, task_id~ : String, now~ : String) -> Result[Task, String]
    提交验收(执行中 -> 待验收)

    FistEngine::verify

    fn FistEngine::verify(self : FistEngine, task_id~ : String, verifier~ : String, now~ : String) -> Result[Task, String]
    验收(verifier):Reviewing -> Completed;若因此父任务全部子任务完成,则父任务自动待验收。

    Heartbeat

    pub struct Heartbeat {
    signals : Map[String, String]
    last_seen : Map[String, String]
    }
    心跳登记表:task_id -> (signal, last_seen)。

    Heartbeat::beat

    fn Heartbeat::beat(self : Heartbeat, task_id : String, signal? : String, now~ : String) -> Unit
    上报心跳:登记任务信号(pre-execution / active / submit)与时间戳。

    Heartbeat::clear

    fn Heartbeat::clear(self : Heartbeat, task_id : String) -> Unit
    清除某任务的心跳记录(heal 回滚后调用)。

    Heartbeat::is_stale

    fn Heartbeat::is_stale(self : Heartbeat, task_id : String, now : String, timeout_sec? : Int) -> Bool
    是否"超时静默"(no_signal):
    • 无任何心跳记录 -> 视作从未活动(stale,交由 watchdog 处理);
    • 有记录但距上次心跳超过 timeout_sec -> stale。 时间戳解析失败时保守返回 false(不误伤)。

    Heartbeat::last_seen_of

    fn Heartbeat::last_seen_of(self : Heartbeat, task_id : String) -> String
    查询某任务最近心跳时间;无记录返回空串。

    Heartbeat::new

    fn Heartbeat::new() -> Heartbeat

    Heartbeat::signal_of

    fn Heartbeat::signal_of(self : Heartbeat, task_id : String) -> String
    查询某任务最近一次心跳信号;无记录返回空串。

    MemoryStore

    pub struct MemoryStore {
    tasks : Map[String, Task]
    }
    内存实现:进程内 Map,简单可靠,配合单机 MCP server 足够。

    MemoryStore::clear

    fn MemoryStore::clear(self : MemoryStore) -> Unit
    提升声明:允许通过具体类型直接调用 trait 方法(避免 deprecated 隐式提升)。

    MemoryStore::create_task

    fn MemoryStore::create_task(self : MemoryStore, task : Task) -> Result[Unit, String]
    提升声明:允许通过具体类型直接调用 trait 方法(避免 deprecated 隐式提升)。

    MemoryStore::delete_task

    fn MemoryStore::delete_task(self : MemoryStore, id : String) -> Result[Unit, String]
    提升声明:允许通过具体类型直接调用 trait 方法(避免 deprecated 隐式提升)。

    MemoryStore::get_task

    fn MemoryStore::get_task(self : MemoryStore, id : String) -> Task?
    提升声明:允许通过具体类型直接调用 trait 方法(避免 deprecated 隐式提升)。

    MemoryStore::list_tasks

    fn MemoryStore::list_tasks(self : MemoryStore) -> Array[Task]
    提升声明:允许通过具体类型直接调用 trait 方法(避免 deprecated 隐式提升)。

    MemoryStore::new

    MemoryStore::update_task

    fn MemoryStore::update_task(self : MemoryStore, task : Task) -> Result[Unit, String]
    提升声明:允许通过具体类型直接调用 trait 方法(避免 deprecated 隐式提升)。

    Principle

    pub struct Principle {
    index : Int
    title : String
    body : String
    } derive(Eq,
    Debug
    )
    单条原则

    Principle::get_body

    fn Principle::get_body(self : Principle) -> String

    Principle::get_index

    fn Principle::get_index(self : Principle) -> Int

    Principle::get_title

    fn Principle::get_title(self : Principle) -> String

    Principle::to_json

    fn Principle::to_json(self : Principle) -> Json
    单条原则转 JSON(供 resource 输出)

    Role

    pub enum Role {
    HumanSteward
    Leader
    Searcher
    Allocator
    Executor
    Verifier
    Recorder
    Observer
    } derive(Eq,
    Debug
    )
    八角色

    Role::description

    fn Role::description(self : Role) -> String
    角色职责说明

    Role::from_string

    fn Role::from_string(s : String) -> Role?

    Role::to_string

    fn Role::to_string(self : Role) -> String

    SqliteStore

    pub struct SqliteStore {
    db :
    Database
    ?
    }
    SQLite 后端:持有打开的 Database(Option 以承载 open 失败场景)。

    SqliteStore::archive_task

    fn SqliteStore::archive_task(self : SqliteStore, t : Task, archived_at~ : String) -> Result[Unit, String]
    将已归档任务写入 archive 表快照。

    SqliteStore::clear

    fn SqliteStore::clear(self : SqliteStore) -> Unit
    提升声明:允许通过具体类型直接调用 trait 方法。

    SqliteStore::create_task

    fn SqliteStore::create_task(self : SqliteStore, task : Task) -> Result[Unit, String]
    提升声明:允许通过具体类型直接调用 trait 方法。

    SqliteStore::delete_task

    fn SqliteStore::delete_task(self : SqliteStore, id : String) -> Result[Unit, String]
    提升声明:允许通过具体类型直接调用 trait 方法。

    SqliteStore::get_task

    fn SqliteStore::get_task(self : SqliteStore, id : String) -> Task?
    提升声明:允许通过具体类型直接调用 trait 方法。

    SqliteStore::list_archived

    fn SqliteStore::list_archived(self : SqliteStore) -> Array[(String, String)]
    列出全部归档快照(id -> 原 task_json)。

    SqliteStore::list_tasks

    fn SqliteStore::list_tasks(self : SqliteStore) -> Array[Task]
    提升声明:允许通过具体类型直接调用 trait 方法。

    SqliteStore::new

    fn SqliteStore::new() -> SqliteStore?
    以默认路径(fist-mbt.db,随运行目录)打开的便捷构造。

    SqliteStore::open

    fn SqliteStore::open(db_path : String) -> SqliteStore?
    打开数据库并初始化五表 schema。失败返回 None(调用方决定是否 abort / 回退内存)。

    SqliteStore::update_task

    fn SqliteStore::update_task(self : SqliteStore, task : Task) -> Result[Unit, String]
    提升声明:允许通过具体类型直接调用 trait 方法。

    StoreBackend

    pub enum StoreBackend {
    Mem(MemoryStore)
    Sql(SqliteStore)
    }
    后端路由:内存版(默认,测试/演示)或 SQLite 持久化(运行时内建数据库)。 FistEngine 持此类型,业务层不感知具体后端。

    StoreBackend::clear

    fn StoreBackend::clear(self : StoreBackend) -> Unit

    StoreBackend::create_task

    fn StoreBackend::create_task(self : StoreBackend, task : Task) -> Result[Unit, String]

    StoreBackend::delete_task

    fn StoreBackend::delete_task(self : StoreBackend, id : String) -> Result[Unit, String]

    StoreBackend::get_task

    fn StoreBackend::get_task(self : StoreBackend, id : String) -> Task?

    StoreBackend::list_tasks

    fn StoreBackend::list_tasks(self : StoreBackend) -> Array[Task]

    StoreBackend::update_task

    fn StoreBackend::update_task(self : StoreBackend, task : Task) -> Result[Unit, String]

    Task

    pub struct Task {
    id : String
    parent_id : String?
    project_dir : String
    priority : String
    importance : String
    depth : Int
    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
    )
    FIST-Mbt 任务实体

    Task::archive

    fn Task::archive(self : Task) -> Result[Task, String]
    已完成 -> 已归档

    Task::claim

    fn Task::claim(self : Task, assignee~ : String) -> Result[Task, String]
    待领取 -> 已领取(角色:any active agent)

    Task::complete

    fn Task::complete(self : Task, completed_by~ : String) -> Result[Task, String]
    待验收 -> 已完成(人类主权:completed_by 必须 human / human_steward 或明确授权)

    Task::execute

    fn Task::execute(self : Task) -> Result[Task, String]
    拆分中 -> 执行中(进入执行)

    Task::get_assignee

    fn Task::get_assignee(self : Task) -> String?

    Task::get_depth

    fn Task::get_depth(self : Task) -> Int

    Task::get_description

    fn Task::get_description(self : Task) -> String

    Task::get_id

    fn Task::get_id(self : Task) -> String

    Task::get_parent

    fn Task::get_parent(self : Task) -> String?

    Task::get_status

    fn Task::get_status(self : Task) -> TaskStatus

    Task::get_updated_at

    fn Task::get_updated_at(self : Task) -> String

    Task::is_leaf

    fn Task::is_leaf(self : Task) -> Bool

    Task::new

    fn Task::new(id~ : String, project_dir~ : String, description? : String, priority? : String, importance? : String, depth? : Int, split_n? : Int, parent_id? : String, assignee? : String, cleanup_mode? : String, created_at? : String) -> Task
    构造器(字段带默认值)

    Task::reopen

    fn Task::reopen(self : Task) -> Result[Task, String]
    任意非归档状态 -> 已领取(被打回重做)

    Task::split

    fn Task::split(self : Task) -> Result[Task, String]
    已领取 -> 拆分中(指挥官拆解)

    Task::status_to_string

    fn Task::status_to_string(self : Task) -> String
    便捷状态访问

    Task::submit

    fn Task::submit(self : Task) -> Result[Task, String]
    执行中 -> 待验收

    Task::to_json

    fn Task::to_json(self : Task) -> Json
    任务转 JSON(供 MCP resource / tool 输出)

    TaskStatus

    pub enum TaskStatus {
    Pending
    Claimed
    Splitting
    Executing
    Reviewing
    Completed
    Archived
    } derive(Eq,
    Debug
    )
    任务七态状态机

    TaskStatus::from_string

    fn TaskStatus::from_string(s : String) -> TaskStatus?

    TaskStatus::order

    fn TaskStatus::order(self : TaskStatus) -> Int
    排序权重(用于统计/展示)

    TaskStatus::to_string

    fn TaskStatus::to_string(self : TaskStatus) -> String

    can

    fn can(role : Role, action : Action) -> Bool
    权限判定:Can(HumanSteward, 任意) = true; 非人类角色只能做自己职责内的非破坏性动作。

    check_claim

    fn check_claim(engine : FistEngine, task_id : String, assignee : String) -> Result[Unit, String]
    认领前冲突校验:任务不存在、已被他人/本人持有则返回冲突详情。 返回 Ok(()) 表示可安全认领(状态为待领取)。

    child_id

    fn child_id(parent_id~ : String, idx~ : Int) -> String
    生成子任务 id:T0.1.2 -> T0.1.2.1

    cleanup_archived

    fn cleanup_archived(engine : FistEngine, now : String, retention_days? : Int) -> Result[Array[String], String]
    清理一轮:删除超过保留期的已归档任务。返回被清理的任务 id 列表。

    decompose_slices

    fn decompose_slices(spec : Json, split_n : Int, parent_desc~ : String) -> Array[String]
    从 omega spec JSON 提取切割依据(slices)。 规则:
    • spec 为对象且 laws 为非空字符串数组 → 以 laws 为准(AO "break into focused tasks":每条 law 一个聚焦子任务,等价于把 plan 拆成可执行单元);
    • 否则 → 退化为按 split_n 生成通用拆解条目。 返回切片描述数组。

    ensure_can

    fn ensure_can(role : Role, action : Action) -> Result[Unit, String]
    权限校验函数(带可读错误消息)

    heal_stale_tasks

    fn heal_stale_tasks(engine : FistEngine, hb : Heartbeat, now : String, timeout_sec? : Int) -> Result[Array[String], String]
    看护一轮:扫描引擎全部任务,对心跳超时静默的活跃任务执行回滚。 返回本轮被回滚(重派)的任务 id 列表。

    iso_to_secs

    fn iso_to_secs(s : String) -> Int
    YYYY-MM-DDTHH:MM:SS... 起始的时间戳解析为累计秒。解析失败返回 -1。 以 2024-01-01 为参考基准(仅用于同体系先后比较,非绝对 UTC): 避免 year36586400 在 32 位 Int 下溢出。

    list_contested

    fn list_contested(engine : FistEngine) -> Array[Task]
    列出全部处于"被持有"(非待领取/已完成/已归档)状态的任务,供审计。

    list_holdings

    fn list_holdings(engine : FistEngine, assignee : String) -> Array[Task]
    列出某人当前持有中的任务(已领取/拆分中/执行中/待验收),供 --no-takeover 决策。

    principles

    fn principles() -> Array[Principle]
    七条金条的权威定义(与 FIST-SKILL/Python 版保持同源)

    principles_json

    fn principles_json() -> Json
    全部原则转 JSON 数组

    role_of

    fn role_of(s : String) -> Result[Role, String]
    从字符串解析角色(MCP 参数用)

    root_task_id

    fn root_task_id() -> String
    根任务 id

    run_server

    async fn run_server() -> Unit
    —— MCP server 构建与运行 ——