feat: introduce spec system + dashboard + health pipeline (AgentsMeeting template)
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"module": "dashboard",
|
||||
"version": "1.0",
|
||||
"purpose": "MoFin 管理门户。独立 Flask 应用(端口 5804),统一展示系统健康状态、模块 spec 帮助和监控数据。",
|
||||
|
||||
"human_help": {
|
||||
"title": "Dashboard — 管理门户",
|
||||
"description": [
|
||||
"MoFin 统一管理面板,提供系统健康状态总览和各模块的帮助文档。",
|
||||
"采用深色主题 Web UI,与 AgentsMeeting Dashboard 一致的视觉风格。",
|
||||
"访问地址: http://192.168.1.246:5804"
|
||||
],
|
||||
"usage": [
|
||||
"打开浏览器访问 http://192.168.1.246:5804",
|
||||
"F 健康 Tab — 查看所有服务运行状态和健康管线数据",
|
||||
"G 规范 Tab — 查看开发规范文档",
|
||||
"点击 ? 按钮 — 查看面向人类的模块帮助",
|
||||
"点击 § 按钮 — 查看面向 AI 的接口约束文档"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"Dashboard 不响应 → ssh 246 'sudo systemctl restart mofin-dashboard'",
|
||||
"F Tab 无数据 → 检查 crontab 中健康检查任务是否运行",
|
||||
"Spec 加载失败 → 检查 specs/ 目录权限和 JSON 格式"
|
||||
]
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/health", "returns": "{status:'ok', uptime:N}"},
|
||||
{"method": "GET", "path": "/api/services", "returns": "{services[{name, type, port, status}]} — 所有注册服务的运行状态"},
|
||||
{"method": "GET", "path": "/api/expected", "returns": "{expected[{name, port, expected, critical}], actual{name:status}} — 期望状态矩阵"},
|
||||
{"method": "GET", "path": "/api/monitor", "returns": "{tier1{summary{ok,total}}, tier2{summary{ok,total}}, tasks[{name,status}]} — 聚合监控数据"},
|
||||
{"method": "GET", "path": "/api/module-spec/<module>", "returns": "specs/{module}.json 内容"}
|
||||
],
|
||||
"dependencies": [
|
||||
"specs/ 目录 — 所有模块的 spec JSON 文件",
|
||||
"agents_health_check.py — Tier1 健康检查(生成 last_health_check.json)",
|
||||
"agents_daily_health.py — Tier2 日检(生成 last_daily_health.json)",
|
||||
"server.py :8899 — 业务 API(Dashboard 通过 HTTP 检测其可达性)"
|
||||
],
|
||||
"constraints": [
|
||||
"Dashboard 部署在 Linux 246 上,端口 5804",
|
||||
"通过 systemd 守护(mofin-dashboard.service)",
|
||||
"不依赖 server.py :8899(可独立运行)",
|
||||
"前端 5 秒轮询 /api/services + /api/expected",
|
||||
"?§ 按钮通过 /api/module-spec/<module> 读取 spec JSON"
|
||||
],
|
||||
"must_not": [
|
||||
"不要修改 server.py :8899 来集成 Dashboard(保持独立)",
|
||||
"不要在 Dashboard 中硬编码业务数据(只做监控和文档展示)",
|
||||
"不要移除 ?§ 按钮系统(这是 spec 可视化的核心)"
|
||||
],
|
||||
"related_files": [
|
||||
"dashboard.py — Flask 后端",
|
||||
"templates/dashboard.html — 前端",
|
||||
"specs/ — Spec 文件目录",
|
||||
"gateway/logs/ — 运行时日志"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"module": "decisions",
|
||||
"version": "1.0",
|
||||
"purpose": "策略决策库。管理持仓和自选股的策略决策(止损/止盈/买入区/操作建议),支持新旧格式兼容。",
|
||||
|
||||
"human_help": {
|
||||
"title": "策略决策库",
|
||||
"description": [
|
||||
"存储每只持仓/自选股的策略决策数据,包括止损价、止盈价、买入区间、操作建议等。",
|
||||
"数据来自知微 LLM 分析,通过 /api/analysis/batch 写入。",
|
||||
"支持新旧两种数据格式的自动兼容(新格式:stop_loss/take_profit 顶层字段;旧格式:trigger 对象)。"
|
||||
],
|
||||
"usage": [
|
||||
"GET /api/decisions — 获取全部决策(按标签+执行状态排序)",
|
||||
"POST /api/decisions/add — 新增/更新一条决策(同股票旧决策自动标记 superseded)",
|
||||
"POST /api/decisions/tag — 设置/清除推荐标签(current_recommend / active_manual)",
|
||||
"GET /api/decisions/pending — 获取有未确认建议的条目"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"决策列表为空 → 确认 regenerate_all 已执行或知微已写入",
|
||||
"旧格式不显示 → 检查归一化逻辑(/api/decisions GET handler)"
|
||||
]
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/decisions", "returns": "{decisions[{code, name, type, status, tag, action, trigger{stop_loss, take_profit, entry_zone}, current, zone_breach, updated_reason, advice_timeline, changelog, execution, analysis}], total, regenerated_at}"},
|
||||
{"method": "POST", "path": "/api/decisions/add", "returns": "{status:'ok', entry:{...}}"},
|
||||
{"method": "POST", "path": "/api/decisions/tag", "returns": "{status:'ok', code, tag}"},
|
||||
{"method": "GET", "path": "/api/decisions/pending", "returns": "[{code, name, current, pending_advice[{date, direction, price, summary, status}]}]"}
|
||||
],
|
||||
"dependencies": [
|
||||
"mo_data.py — read_decisions()",
|
||||
"mofin_db.py — write_holding_strategy()",
|
||||
"strategy_lifecycle.py — regenerate_all 触发全量重评"
|
||||
],
|
||||
"constraints": [
|
||||
"支持新旧两种格式的读取兼容(normalized 逻辑)",
|
||||
"同股票新决策会自动将旧决策标记为 superseded",
|
||||
"排序规则:current_recommend 标签 > 执行状态(partial_exit > executing > observing) > code",
|
||||
"advice_timeline 去重:同日期+同方向+摘要前40字相同 → skip"
|
||||
],
|
||||
"must_not": [
|
||||
"不要在决策中硬编码价格阈值(应由 LLM 分析生成)",
|
||||
"不要删除 superseded 的旧决策(保留历史记录)"
|
||||
],
|
||||
"related_files": [
|
||||
"server.py — /api/decisions* 路由",
|
||||
"mo_data.py — read_decisions()",
|
||||
"mofin_db.py — holding_strategies 表"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"module": "evaluation",
|
||||
"version": "1.0",
|
||||
"purpose": "策略评估系统。提供策略双维度评估结果查询、手动触发评估和准确率统计。",
|
||||
|
||||
"human_help": {
|
||||
"title": "策略评估",
|
||||
"description": [
|
||||
"评估每只股票策略的有效性,来自 strategy_evaluator.py(每周六 21:00 自动运行)。",
|
||||
"支持手动触发评估(POST /api/evaluation/trigger)。",
|
||||
"评估数据主源为 evaluation.json,备选为 decisions.json 中的 evaluation 字段。"
|
||||
],
|
||||
"usage": [
|
||||
"GET /api/evaluation — 获取全部策略评估结果",
|
||||
"POST /api/evaluation/trigger — 手动触发策略评估(执行 strategy_evaluator.py)",
|
||||
"GET /api/stats/accuracy — 获取准确率统计数据",
|
||||
"GET /api/feedback — 获取策略反馈数据"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"评估数据为空 → 确认 strategy_evaluator.py 已运行过",
|
||||
"触发失败 → 检查 strategy_evaluator.py 路径是否正确"
|
||||
]
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/evaluation", "returns": "[{code, name, type, current, evaluations[{date, dimension, score, reason}]}]"},
|
||||
{"method": "POST", "path": "/api/evaluation/trigger", "returns": "{status:'ok', output, error} — 执行 strategy_evaluator.py,timeout 60s"},
|
||||
{"method": "GET", "path": "/api/stats/accuracy", "returns": "accuracy_stats.json 内容"},
|
||||
{"method": "GET", "path": "/api/feedback", "returns": "strategy_feedback.json 内容"}
|
||||
],
|
||||
"dependencies": [
|
||||
"strategy_evaluator.py — 双维度评估脚本(cron: 周六 21:00)",
|
||||
"evaluation.json — 评估结果主数据源",
|
||||
"accuracy_stats.json — 准确率统计",
|
||||
"strategy_feedback.json — 反馈数据"
|
||||
],
|
||||
"constraints": [
|
||||
"POST /api/evaluation/trigger 会阻塞最多 60 秒",
|
||||
"评估数据优先读 evaluation.json,fallback 读 decisions.json 的 evaluation 字段"
|
||||
],
|
||||
"related_files": [
|
||||
"server.py — /api/evaluation, /api/evaluation/trigger, /api/stats/accuracy, /api/feedback",
|
||||
"strategy_evaluator.py",
|
||||
"strategy_feedback.py"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"module": "health",
|
||||
"version": "1.0",
|
||||
"purpose": "MoFin 系统健康监控管线。三层监控(Tier1 快速检查 + Tier2 日检),聚合到 Dashboard F Tab 展示。",
|
||||
|
||||
"human_help": {
|
||||
"title": "F 健康 — 系统健康",
|
||||
"description": [
|
||||
"实时监控 MoFin 所有关键服务(Flask API、数据库、cron 任务)的运行状态。",
|
||||
"两层监控:",
|
||||
" Tier1 — 每 5 分钟快速端口/进程检查",
|
||||
" Tier2 — 每日 8:00 开盘前全面体检(进程+端口+DB+磁盘+cron)",
|
||||
"检查结果聚合到 Dashboard F Tab,异常自动告警。"
|
||||
],
|
||||
"usage": [
|
||||
"1. 打开 Dashboard → F 健康 Tab 查看概览",
|
||||
"2. 绿色 = 正常,黄色 = 部分异常,红色 = 严重异常",
|
||||
"3. 异常服务列表直接显示影响描述",
|
||||
"4. 定时任务区域检查所有 cron 是否正常运行"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"F Tab 显示无数据 → 检查 crontab 中健康检查是否部署",
|
||||
"服务显示 down 但实际在运行 → 检查端口或 health 端点是否正确",
|
||||
"TODO 堆积 → 检查 self_todo_executor 是否在 crontab 中"
|
||||
]
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/services", "returns": "{services[{name, type, port, health{ok}, status}]}"},
|
||||
{"method": "GET", "path": "/api/expected", "returns": "{expected[{name, port, expected, critical}], actual{name:status}}"},
|
||||
{"method": "GET", "path": "/api/monitor", "returns": "{tier1{summary{ok,total}}, tier2{summary{ok,total}}, tasks[{name,status}]}"}
|
||||
],
|
||||
"dependencies": [
|
||||
"agents_health_check.py — Tier1(每 5 分钟,socket 端口 + HTTP /health)",
|
||||
"agents_daily_health.py — Tier2(每日 8:00,端口+进程+DB+磁盘+cron)",
|
||||
"mofin.db — SQLite 数据库(检查可读写)"
|
||||
],
|
||||
"architecture": {
|
||||
"monitored_services": [
|
||||
{"name": "mofin_api", "port": 8899, "type": "http", "check": "GET /api/portfolio"},
|
||||
{"name": "mofin_dashboard", "port": 5804, "type": "http", "check": "GET /api/health"},
|
||||
{"name": "zhiwei_gateway", "port": 8643, "type": "http", "check": "GET /v1/health"},
|
||||
{"name": "ejabberd", "port": 5222, "type": "tcp", "check": "socket connect"},
|
||||
{"name": "mofin_db", "port": 0, "type": "file", "check": "sqlite3 connect + SELECT"}
|
||||
]
|
||||
},
|
||||
"constraints": [
|
||||
"Tier1 全正常时静默(不输出日志)",
|
||||
"Tier1 异常写入 gateway/temp/health_todos.jsonl",
|
||||
"Tier1 报告写入 gateway/temp/last_health_check.json",
|
||||
"Tier2 报告写入 gateway/temp/last_daily_health.json",
|
||||
"Dashboard /api/monitor 聚合读取以上 JSON 文件"
|
||||
],
|
||||
"must_not": [
|
||||
"不要在健康检查中修改业务数据",
|
||||
"不要硬编码 Windows 路径或命令",
|
||||
"不要检查已停用的服务(wechat_agent 等)"
|
||||
],
|
||||
"tests": [
|
||||
{"id": "H01", "name": "/api/services 返回服务列表", "endpoint": "GET /api/services"},
|
||||
{"id": "H02", "name": "/api/expected 返回期望矩阵", "endpoint": "GET /api/expected"},
|
||||
{"id": "H03", "name": "/api/monitor 返回监控数据", "endpoint": "GET /api/monitor"}
|
||||
],
|
||||
"related_files": [
|
||||
"agents_health_check.py — Tier1 健康检查",
|
||||
"agents_daily_health.py — Tier2 日检",
|
||||
"dashboard.py — /api/services, /api/expected, /api/monitor",
|
||||
"templates/dashboard.html — F Tab 渲染",
|
||||
"specs/health.json — 本 spec 文件"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"module": "market",
|
||||
"version": "1.0",
|
||||
"purpose": "市场观察数据。提供大盘指数和板块数据的查询和更新。",
|
||||
|
||||
"human_help": {
|
||||
"title": "市场观察",
|
||||
"description": [
|
||||
"展示大盘指数(上证、深证、恒生等)和板块热度数据。",
|
||||
"数据由 market_watch.py cron(每 30 分钟)自动采集。",
|
||||
"优先从 DB 读取(market_snapshots / sector_snapshots 表),DB 无数据时 fallback 到 market.json。"
|
||||
],
|
||||
"usage": [
|
||||
"GET /api/market — 获取最新市场数据(指数 + 板块)",
|
||||
"POST /api/update/market — 更新市场数据(由 market_watch 调用)"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"市场数据为空 → 检查 market_watch cron 是否正常运行",
|
||||
"数据显示旧 → 手动运行 python3 market_watch.py 更新"
|
||||
]
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/market", "returns": "{indices[{name, code, price, change_pct}], sectors[{name, change_pct, leader}]}"},
|
||||
{"method": "POST", "path": "/api/update/market", "returns": "{status:'ok'}"}
|
||||
],
|
||||
"dependencies": [
|
||||
"mofin_db.py — market_snapshots / sector_snapshots 表",
|
||||
"market_watch.py — 大盘采集 cron(*/30 9-15)",
|
||||
"market_screener.py — 全市场筛选 cron"
|
||||
],
|
||||
"constraints": [
|
||||
"DB 优先读取,JSON 仅做 fallback"
|
||||
],
|
||||
"related_files": [
|
||||
"server.py — /api/market, /api/update/market",
|
||||
"market_watch.py — 大盘数据采集",
|
||||
"market_screener.py — 全市场筛选"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"module": "portfolio",
|
||||
"version": "1.0",
|
||||
"purpose": "持仓数据查询与管理。提供持仓列表、资产概览、实时价格更新。",
|
||||
|
||||
"human_help": {
|
||||
"title": "持仓管理",
|
||||
"description": [
|
||||
"本模块管理老爸的股票持仓数据,包括个股持仓明细和总资产概览。",
|
||||
"数据存储在 SQLite (mofin.db),由 price_monitor cron 每 2 分钟更新价格。",
|
||||
"港股以 HKD 存储,汇总时自动转换为 CNY。"
|
||||
],
|
||||
"usage": [
|
||||
"GET /api/portfolio — 获取完整持仓列表(含价格、涨跌幅、盈亏)",
|
||||
"GET /api/overview — 获取总资产概览(总资产、股票市值、现金、仓位、top movers)",
|
||||
"POST /api/update/portfolio — 批量更新持仓数据(由 cron 调用)",
|
||||
"POST /api/update/realtime — 实时价格更新(由 price_monitor 调用)"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"数据库查询失败 → 检查 mofin.db 是否存在且可读写",
|
||||
"港股价格异常 → 确认 hk_rate.py 汇率 API 可达",
|
||||
"数据不更新 → 检查 crontab 中 price_monitor 是否正常运行"
|
||||
]
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/portfolio", "returns": "{total_assets, stock_value, cash, position_pct, total_pnl, holdings[{code, name, price, cost, shares, change_pct, currency, ...}]}"},
|
||||
{"method": "GET", "path": "/api/overview", "returns": "{total_assets, stock_value, cash, position_pct, total_pnl, top_movers, market, alerts, updated_at}"},
|
||||
{"method": "POST", "path": "/api/update/portfolio", "returns": "{status:'ok'}"},
|
||||
{"method": "POST", "path": "/api/update/realtime", "returns": "{status:'ok'}"}
|
||||
],
|
||||
"dependencies": [
|
||||
"mo_data.py — read_portfolio() 统一读取层",
|
||||
"mofin_db.py — get_conn(), query_holdings(), query_portfolio_summary()",
|
||||
"price_monitor.py — 唯一价格写入者,cron: */2 9-16 1-5"
|
||||
],
|
||||
"constraints": [
|
||||
"港股个股价格/成本以 HKD 存储,currency='HKD'",
|
||||
"A股个股价格/成本以 CNY 存储,currency='CNY'",
|
||||
"总资产/总市值以 CNY 汇总(calc_total_assets 自动转换)",
|
||||
"禁止跨币种直接比较或加减",
|
||||
"price_monitor 是唯一的价格写入源,其他脚本禁止直接写价格"
|
||||
],
|
||||
"must_not": [
|
||||
"不要在各业务脚本中直接写 SQL(必须通过 mofin_db.py)",
|
||||
"不要硬编码汇率(必须通过 hk_rate.py 的 get_hk_rate())",
|
||||
"不要直接 json.load 读数据(必须通过 mo_data.py)",
|
||||
"不要自己实现 calc_total_assets / is_hk_stock(必须用 mo_models.py)"
|
||||
],
|
||||
"related_files": [
|
||||
"server.py — API 路由定义",
|
||||
"mo_models.py — 数据模型(calc_total_assets, is_hk_stock, to_cny)",
|
||||
"mo_data.py — 统一读取层",
|
||||
"mofin_db.py — DB 层",
|
||||
"price_monitor.py — 价格更新 cron",
|
||||
"hk_rate.py — 港币汇率"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"module": "signals",
|
||||
"version": "1.0",
|
||||
"purpose": "信号与扫描数据。提供市场信号查询和小果扫描统计。",
|
||||
|
||||
"human_help": {
|
||||
"title": "信号与扫描",
|
||||
"description": [
|
||||
"展示系统产生的交易信号和小果 LLM 扫描结果。",
|
||||
"信号来自多个来源:xiaoguo_scanner(全市场)、macro_context_collector(宏观)、divergence_detector(背离)。",
|
||||
"所有信号存储在 signal_news 表中。"
|
||||
],
|
||||
"usage": [
|
||||
"GET /api/signals — 获取最近 20 条信号(含板块信号关联)",
|
||||
"GET /api/xiaoguo-scan — 获取小果扫描统计(扫描总数/发现信号数/近期记录/今日来源分布)"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"信号为空 → 检查 xiaoguo_scanner 和 macro_context_collector cron 状态",
|
||||
"小果扫描数据停更 → 检查小果 LLM API 是否可达"
|
||||
]
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/signals", "returns": "[{id, sector, overall_sentiment, summary, source, created_at, signal_type, severity}] — 最近 20 条信号"},
|
||||
{"method": "GET", "path": "/api/xiaoguo-scan", "returns": "{total_scanned, found_signals, recent[{code, name, last_scanned_at, found_count}], source_today{source:cnt}}"}
|
||||
],
|
||||
"dependencies": [
|
||||
"mofin_db.py — signal_news / xiaoguo_scan_tracker 表",
|
||||
"xiaoguo_scanner.py — 全市场扫描 cron(*/5 9-15)",
|
||||
"macro_context_collector.py — 宏观信号采集 cron",
|
||||
"divergence_detector.py — 背离检测 cron"
|
||||
],
|
||||
"constraints": [
|
||||
"signal_news 和 sector_signals 通过 LEFT JOIN 关联",
|
||||
"xiaoguo_scan_tracker 的 source 统计只取最近 24 小时"
|
||||
],
|
||||
"related_files": [
|
||||
"server.py — /api/signals, /api/xiaoguo-scan",
|
||||
"xiaoguo_scanner.py",
|
||||
"macro_context_collector.py"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"module": "watchlist",
|
||||
"version": "1.0",
|
||||
"purpose": "自选股列表管理。提供自选股查询和批量更新。",
|
||||
|
||||
"human_help": {
|
||||
"title": "自选股管理",
|
||||
"description": [
|
||||
"管理老爸的自选股列表,与持仓分开存储。",
|
||||
"数据存储在 SQLite (mofin.db) 的 watchlist_stocks 表。",
|
||||
"小果扫描器会消费自选股信号并自动添加到自选列表。"
|
||||
],
|
||||
"usage": [
|
||||
"GET /api/watchlist — 获取完整自选股列表",
|
||||
"POST /api/update/watchlist — 批量更新自选股(由 cron 调用)"
|
||||
],
|
||||
"troubleshooting": [
|
||||
"数据库查询失败 → 检查 mofin.db 是否可读写",
|
||||
"自选股列表为空 → 确认 regenerate_all 或手动添加过自选股"
|
||||
]
|
||||
},
|
||||
|
||||
"ai_spec": {
|
||||
"apis": [
|
||||
{"method": "GET", "path": "/api/watchlist", "returns": "{stocks[{code, name, price, change_pct, currency, analysis{...}}]}"},
|
||||
{"method": "POST", "path": "/api/update/watchlist", "returns": "{status:'ok'}"}
|
||||
],
|
||||
"dependencies": [
|
||||
"mo_data.py — read_watchlist()",
|
||||
"mofin_db.py — query_watchlist(), write_watchlist_stock()",
|
||||
"xiaoguo_signal_consumer.py — 消费小果信号,自动加自选"
|
||||
],
|
||||
"constraints": [
|
||||
"自选股也必须标注 currency 字段(HKD/CNY)"
|
||||
],
|
||||
"related_files": [
|
||||
"server.py — API 路由定义",
|
||||
"mo_data.py — read_watchlist()",
|
||||
"mofin_db.py — watchlist_stocks 表"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user