Files
nmfs-agents/tests/test_executor_constraint.py
qiuruiandClaude Sonnet 4.6 df59fc0c83 feat: NMFS Agents 全量入库(org v2 + dashboard + 多队列 + 组织架构)
包含从项目创建至今的全部代码首次入库:

核心框架:
- TaskQueue(SQLite,6 种状态,原子 dequeue)
- Executor(asyncio 并发,semaphore 限流,agent_role 路由)
- Scheduler(APScheduler,三队列独立调度)
- Watchdog(超时检测 + 优先级防饥饿)
- Scanner(项目扫描,README/TODO/CLAUDE.md 提取)

Agent 体系(20+ 角色):
- 项目交付组:architect/developer/tester/productizer
- 基础技术组:base-architect/validator/hw/os/kernel/lowlevel/system-tester
- 算法组:algo-antishake/position/nav
- 洞察组:planner/vision-analyst/media-producer
- 市场组:market-pm/sport/elder/safety
- 组织层:boss/group-leader/senior-dev/ops
- 平台扩展:nrf-dev/esp32-dev
- 三专项调研:rtp-researcher/net-researcher/kernel-analyzer

工具层:
- ProjectMemory(goals/facts/history SQLite)
- VersionPipeline(并行版本流水线 + 反幻觉门控)
- EventBus(Redis Streams,5 consumer groups)
- DailyReport(append-only 日报 + Boss 决策视图)
- AgentScorer(4 维评分:完成度/质量/自主性/协作)
- DeviceAgent(SSH rsync + 板端执行)
- EnvCollector(本机+SSH 环境采集)
- ArchVersion(快照/优化/promote/rollback)

Dashboard(React + Vite + Tailwind):
- 看板/项目/配置/洞察/日报/Visual 六标签页
- WebSocket 实时更新
- Markdown 渲染(react-markdown + remark-gfm)

测试:314 passed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 07:24:19 +08:00

96 lines
3.8 KiB
Python

from __future__ import annotations
import asyncio
from unittest.mock import MagicMock, patch
from nmfs_agents.core.executor import Executor
from nmfs_agents.core.queue import TaskQueue, Task
from nmfs_agents.config import AgentsConfig, SchedulerConfig, ClaudeConfig, FeishuConfig
from nmfs_agents.tools.project_memory import ProjectMemory
def _cfg():
return AgentsConfig(
projects={},
scheduler=SchedulerConfig(max_concurrent=2),
claude=ClaudeConfig(api_key="x"),
feishu=FeishuConfig(),
devices={},
)
def test_spawn_tag_creates_child_task(tmp_path):
"""SPAWN 标签应创建子任务入队"""
q = TaskQueue(db_path=tmp_path / "t.db")
tid = q.enqueue(Task(project="p", type="fix_bug", title="主任务",
priority=1, mode="auto", agent_role="developer"))
mem = ProjectMemory(db_path=tmp_path / "m.db")
executor = Executor(_cfg(), queue=q, memory=mem)
from nmfs_agents.agents.developer import AgentResult
mock_result = AgentResult(status="done",
summary="分析完成。[SPAWN:arch-reviewer] 请审查修复方案")
with patch("nmfs_agents.core.executor._make_agent") as mk:
mk.return_value.run.return_value = mock_result
asyncio.run(executor.run_next())
with q._conn() as c:
rows = c.execute(
"SELECT * FROM tasks WHERE agent_role='arch-reviewer'"
).fetchall()
assert len(rows) == 1
assert rows[0]["parent_task_id"] == tid
def test_veto_tag_requeues_parent(tmp_path):
"""arch-reviewer 输出 [VETO] 应将父任务重入队"""
q = TaskQueue(db_path=tmp_path / "t.db")
parent_id = q.enqueue(Task(project="p", type="fix_bug", title="主任务",
priority=1, mode="auto", agent_role="developer"))
# 将主任务标记为 waiting_approval,模拟已执行完毕等待审查的状态
q.mark_waiting_approval(parent_id)
q.enqueue(Task(project="p", type="code_review", title="审查主任务",
priority=1, mode="auto", agent_role="arch-reviewer",
parent_task_id=parent_id))
mem = ProjectMemory(db_path=tmp_path / "m.db")
executor = Executor(_cfg(), queue=q, memory=mem)
from nmfs_agents.agents.developer import AgentResult
mock_result = AgentResult(
status="done",
summary="[VETO] 存在 SQL 注入风险,需重构数据库访问层"
)
with patch("nmfs_agents.core.executor._make_agent") as mk:
mk.return_value.run.return_value = mock_result
asyncio.run(executor.run_next())
with q._conn() as c:
parent = c.execute(
"SELECT * FROM tasks WHERE id=?", (parent_id,)
).fetchone()
assert parent["status"] == "pending"
assert parent["retry_count"] == 1
assert "SQL 注入" in parent["context"]
def test_await_tag_marks_waiting_approval(tmp_path):
"""AWAIT 标签应将当前任务置为 waiting_approval"""
q = TaskQueue(db_path=tmp_path / "t.db")
tid = q.enqueue(Task(project="p", type="arch_optimize", title="架构方案",
priority=1, mode="auto", agent_role="arch-system"))
mem = ProjectMemory(db_path=tmp_path / "m.db")
executor = Executor(_cfg(), queue=q, memory=mem)
from nmfs_agents.agents.developer import AgentResult
mock_result = AgentResult(
status="done",
summary="方案详见附件。[AWAIT:arch-security]"
)
with patch("nmfs_agents.core.executor._make_agent") as mk:
mk.return_value.run.return_value = mock_result
asyncio.run(executor.run_next())
with q._conn() as c:
row = c.execute("SELECT * FROM tasks WHERE id=?", (tid,)).fetchone()
assert row["status"] == "waiting_approval"
assert row["awaiting_role"] == "arch-security"