Files
MoFin/docs/dev-spec.md
T

17 KiB
Raw Blame History

MoFin 开发规范

版本: v2.1 | 更新: 2026-07-20 | 基于 AgentsMeeting 样板重构 + 冗余事件复盘

📋 样板参考: AgentsMeeting TEMPLATE-GUIDE.md


十条红线

  1. 先读/写 Spec,再写代码 — 新增功能先写 spec 再实现;修改已有功能先读对应 spec 了解架构和约束再动手。没有 spec 的模块在 Dashboard 不可见,视为未完成
  2. 部署必验 — 部署后不打开 Dashboard F Tab 验证 = 部署未完成
  3. 不可见即不存在 — 组件不在 Dashboard 中显示 = 等于没部署。离线不告警 = 监控缺陷
  4. 实现后同步 Spec — 每轮开发完毕后,必须将 specs/{module}.json 更新为与实际实现一致的状态。文档过期 = 等于没写
  5. 部署目标即验收标准 — 所有代码必须以部署目标环境(Linux 246)为基准编写和测试。禁止使用 Windows 专属 APItasklistnetstatschtaskswmic)在 246 部署的代码中
  6. 单一事实源(SSOT — 每个文件全系统只有一个权威位置,其他位置只允许硬链接(同 inode),禁止独立副本。权威位置:deploy/profile-scripts/cron 脚本)、/home/hmo/MoFin/(被 import 的库)、deploy/bot/(XMPP bot)。硬链接破坏只会发生在部署动作(scp 替换文件 / git checkout/merge),因此部署链路自带三层自动修复,不需要靠记性:
    • systemd path watcherprofile-scripts-sync.path):监听 deploy/profile-scripts/ 目录变化,任何 scp/替换自动触发 sync_profile_scripts.sh
    • git hooks.git/hooks/post-merge + post-checkout):git 操作后自动重链
    • 手动兜底bash deploy/profile-scripts/sync_profile_scripts.sh(改完文件随手跑)
    • 同步日志:gateway/logs/link_sync.log;断链检测同时是 L2 卫生审计的检查项
    • 部署守卫deploy_guard.py,每 15 分钟全天候):①被跟踪代码文件出现未提交改动 → 自动回滚+重链+告警(git 提交不受影响)②session-work 领先 master 且可快进 → 自动 merge+重链+(触及 dashboard 时)重启服务 ③幂等重链 ④cron 引用完整性检查。状态落盘 gateway/logs/deploy_guard_status.json,有动作即 XMPP 报备。禁止直接编辑 246 上任何被跟踪的代码文件——所有改动必须经 git(详见 docs/zhiwei-ops-discipline.md
  7. 数据路径必须绝对 — 引用数据文件/数据库时,必须写绝对路径并指向权威位置(/home/hmo/MoFin/data/)。禁止Path(__file__).parent / "data" 这类相对解析——同一个模块被硬链接到不同位置时会解析出不同的数据库(2026-07-20 三库事件的根因)
  8. 备份/遗留物禁止留在生产数据目录.bakdecisions_backup_*、迁移残留 JSON、废弃 DB,必须在迁移/变更完成时移到 archive/。生产数据目录(MoFin/data = web-dashboard/data)只放活文件。监控脚本扫描生产目录时,遗留物就是未来的假警报
  9. 文件居住宪法(源头防副本) — 新文件只允许落在三处 canonical:cron 脚本 → deploy/profile-scripts/;被 import 的库 → repo 根目录;独立服务 → deploy/bot/禁止scripts/ 下新建 cron 脚本副本或库副本(scripts/ 只放被系统引用的工具)。一次性诊断/修复脚本 → 用完即归档 archive/YYYYMMDD-*/ 或放 temp/。违者由 L2 卫生审计的自动收尸处理:scripts/ 下的影子副本(deploy 同名)和零引用孤儿(mtime>7天)会被自动 git mvarchive/YYYYMM-auto/ 并自动提交——不需要人工清理,也不会再堆积(2026-07-22 起,scripts/ 从 186 个文件收尸到个位数)
  10. 死模块必须收尸 — 宣布模块废弃时,必须在同一轮操作中完成收尸六步:①杀进程 ②stop+disable systemd 服务 ③删 cron job ④归档脚本到 archive/ ⑤归档数据文件 ⑥从期望矩阵/监控中移除。只说"已废弃"不收尸 = 没废弃(小果 bot 以 root 白跑 8 天 2.5GB 的教训)
  11. 监控查"活"不查"在" — 健康检查必须验证数据新鲜度DB 表 MAX(时间列))而非"文件存在/进程存在"。文件 mtime、进程存活都不构成健康证据——数据 24h 不更新才是事故。禁止拿遗留文件的 mtime 当管道健康指标("数据管道停滞14天"假警报的根因)
  12. 批量 LLM 调用禁止走 hermes gateway agent 通道 — hermes gateway 的 /v1/chat/completions 不是透传,是完整 agent 运行时:每个请求创建带工具(terminal/websearch/patch)的 agent 会话,可能螺旋几十轮、累积 150k+ token,客户端超时后服务端仍空转,重试会叠加新会话形成自我 DDoS2026-07-21 603288 事件:单次重评螺旋 35 分钟、44 次 terminal 调用)。所有批量/脚本化 LLM 调用必须经 llm_client.call_llm()OCG 上游直连为主(裸 completionkey 运行时从 hermes config.yaml 读取,不落盘),gateway 仅作应急兜底。新增 LLM 调用点一律复用 llm_client,禁止手写 HTTP 调用
  13. 告警信噪比纪律 — 所有系统 XMPP 告警必须经 alert_helper.notify(),禁止直 POST :5805。两级通道:ACTION(买入信号/重点推荐/需人工核查)直通不限速、🚨 前缀独立成条,永不被限速INFO(部署/卫生/修复/监控报备)同类 30 分钟限 1 条、≤8 行、24h 内容去重(同一问题不重复轰炸)。有意义的信号(重点推荐操作)绝不允许被纯通知淹没;通知型信息零问题 = 零消息(沉默即正常)
  14. 股票代码是唯一权威标识,名称只是显示属性 — 任何匹配/join/去重/外键必须基于 code,禁止基于 name。名称随时可变:ST 加摘帽、XD/XR/DR 除权息标记(当日所有行情源的简称都被截断,拿不到干净名)、公司改名。写库时 name 缺失必须先查 stocks 已有真名、再腾讯 quote 兜底(mofin_db.fetch_stock_name_tencent),禁止拿 code 冒充 name;名称劣化由 stock_name_hygiene 周频任务自愈(2026-08-22 名称治理确立,当日审计确认全系统表结构/代码/前端均无 name 匹配点)

一、双轨同源规范体系

每新增/修改一个独立功能模块,必须先写 specs/{module}.json。 一个来源同时产出两套文档:

specs/{module}.json
├── human_help  → ? 按钮(人类看说明/排错)
└── ai_spec     → § 按钮(AI 看接口/约束/依赖)

什么算一个模块

满足以下任一条件即视为独立模块,必须写 spec:

  • 暴露独立的 HTTP API 端点
  • 在 Dashboard 上有独立 UI 面板(? + § 按钮)
  • 有独立的配置文件 / 数据文件
  • 可独立部署(如定时任务、数据采集脚本)

Spec 字段标准

{
  "module": "模块名(与 Dashboard 引用名一致)",
  "version": "1.0",
  "purpose": "一句话说明这个模块干什么",

  "human_help": {
    "title": "面向人类的标题",
    "description": ["说明段落数组"],
    "usage": ["使用步骤数组"],
    "troubleshooting": ["常见问题数组"]
  },

  "ai_spec": {
    "apis": [
      {"method": "GET", "path": "/api/xxx", "returns": "返回值说明"}
    ],
    "dependencies": ["依赖的服务或文件"],
    "constraints": ["AI 必须遵守的约束"],
    "must_not": ["AI 绝对不能做的事"],
    "tests": [{"id": "T1", "name": "测试用例名"}],
    "related_files": ["实现文件路径"]
  }
}

当前模块清单

模块 spec 路径 说明 状态
portfolio specs/portfolio.json 持仓数据 + 总览
watchlist specs/watchlist.json 自选股管理
decisions specs/decisions.json 策略决策库
market specs/market.json 市场观察数据
signals specs/signals.json 信号 + 全市场扫描
scanner specs/scanner.json 全市场选股机制
evaluation specs/evaluation.json 策略评估
prompts specs/prompts.json 提示词版本管理
reports specs/reports.json 分析报告管理
dashboard specs/dashboard.json Dashboard 自身
health specs/health.json 健康监控管线
xmpp_monitor specs/xmpp_monitor.json XMPP 通信可观测性
hygiene specs/hygiene.json 系统卫生审计(防冗余)
price_monitor specs/price_monitor.json 价格监控 cron 📋
strategy_lifecycle specs/strategy_lifecycle.json 策略生命周期 📋

状态: = spec 已完成 | 📋 = 待编写


二、文件位置宪法(2026-07-20 冗余事件后确立)

内容类型 唯一权威位置 其他位置的合法形态
cron 脚本(被调度直接执行) deploy/profile-scripts/ profile scripts 目录硬链接(经 sync_profile_scripts.sh 同步)
被 import 的库(mo_/mofin_/strategy_/technical_ /home/hmo/MoFin/(根目录) 禁止副本;deploy/profile-scripts 中的同名库文件只能是对 root 的硬链接
XMPP bot deploy/bot/ /home/hmo/xmpp_zhiwei_bot.py 符号链接
Dashboard 服务 web-dashboard/server.py= /home/hmo/MoFin/server.py 硬链接)
数据文件/数据库 /home/hmo/MoFin/data/= web-dashboard/data 硬链接) 禁止任何第二个数据目录
归档 archive/<主题>-<日期>/
待销毁 trashbox/ 定期人工清空

禁止出现的位置MoFin/scripts/*.pyMoFin/ 根目录的 cron 脚本副本、.hermes/*/scripts/data/(任何 profile 本地 data 目录存业务数据)、projects/ 下与生产同名的项目副本。

死模块收尸清单(红线9 的执行版)

宣布模块 X 废弃时,同一轮操作内必须完成:
□ 杀进程:pkill 或 systemctl stop(确认 ps 无残留)
□ 服务:systemctl disable + rm unit 文件 + daemon-reload
□ cron:两个 jobs.json 中删除 X 的 job,确认无残留
□ 脚本:移到 archive/<模块>-retired-<日期>/
□ 数据文件:同上
□ 监控:从期望矩阵/健康检查注册表中移除 X
□ 记录:CHANGELOG 写明收尸动作

三、验证闭环

┌────────────┐     ┌──────────┐     ┌──────────┐
│ G: 规范体系 │────→│ K: 测试  │────→│ F: 健康  │
│ 定义期望    │     │ 验证实现  │     │ 持续监控  │
└────────────┘     └──────────┘     └──────────┘
       ↑                ↑                │
       └────────────────┼────────────────┘
                        │
               ┌────────┴────────┐
               │ F 异常 → 触发 K  │
               │ K 失败 → 更新 G │
               └─────────────────┘

核心反馈链路

方向 触发条件 动作
G → K 新增/修改 spec 对应测试 ID 必须新增/更新
K → F 测试全部通过 F Tab 组件标记为已验证
F → K F Tab 发现异常 触发对应测试重跑,确认是服务故障还是测试过期
F → G F Tab 持续异常但测试通过 期望矩阵或 spec 过时,应更新 G 和对应 spec

F — 系统健康度(Dashboard F Tab

  • 期望矩阵:应该运行的服务 vs 实际状态
  • 监控数据L05min 心跳)/ L1-L2(功能与卫生)作为实时状态输入,详见「四、自检体系责任矩阵」
  • 服务拓扑:所有服务的健康、端口状态
  • ?§ 覆盖:F Tab 中的每条服务必须有对应的 ?human_help)和 §(ai_spec)按钮

四、自检体系责任矩阵(L0-L4

2026-07-20 确立。原则:每层职责单一,不重叠不疏漏;判据是"功能是否达成",不是"进程是否活着"

组件 频率 职责(唯一) 判据
L0 执行心跳 agents_health_check.py(系统 crontab 5min 端口/HTTP/DB 存活 + auto_heal 执行(gateway 重启/key 切换/bot 重启) 端口通 + HTTP 200 + DB 可写
L1 功能健康 functional_health_check.pyhermes cron 交易时段 15min 核心模块功能是否达成:检查输出物新鲜度/有效性(live_prices/market_snapshots/mtf_cache/macro_context/bot/LLM/cron引擎) 每模块注册表判据(REGISTRY),输出 functional_health.json
L2 系统卫生 system_hygiene_audit.pyhermes cron 每日 08:20 分叉副本/断裂硬链接/僵尸进程/孤儿文件/死cron/DB新鲜度(红线6-10 enforcement 输出 hygiene_report.json
L3 修复循环 self_repair.pyhermes cron 30min 读 L1/L2 失败项 → LLM 诊断 → 白名单动作直接修复(报备制)repair_log.jsonl + XMPP LLM 只能选白名单动作;每模块每天≤2次防循环
L4 元监控 meta_watchdog.pyhermes cron 每小时 自检系统的自检:L0-L3 输出物新鲜度 + L3 注册状态 + XMPP 桥 任何一层死亡直接 XMPP 点名(最后兜底)

已退休(职责被合并)Cron监护-高频cron_watchdog,并入 L3)、全局cron健康监控-每10分cron_health_monitor,并入 L1)。

报备制(L3 的核心纪律)

发现问题 → 直接修复 → 记录日志 → XMPP 报备。不是"发现问题→报告→等指示"。LLM 介入诊断但只能执行白名单动作rerun_script/restart_service/sync_links/switch_llm_key/none),不允许任意代码执行。白名单兜不住的,在 XMPP 里明确说"需要人工"。


五、开发流程

新增功能流程

确定模块边界
  │
  ├─ 1. 创建 specs/{module}.json
  │      human_help + ai_spec
  │
  ├─ 2. 实现功能代码
  │      包含 /health 端点 + PID 锁(proc_guard
  │
  ├─ 3. 注册到系统
  │      - 端口注册
  │      - 添加到期望矩阵(F Tab 自动检测)
  │
  ├─ 4. 编写测试
  │      - ai_spec.tests 添加对应测试标识
  │
  ├─ 5. 同步更新 Spec
  │      - 将 specs/{module}.json 更新为与实际实现一致
  │
  └─ 6. 提交 → 部署 → 验证

修改已有功能流程

识别要修改的模块(查看模块清单确定 module 名)
  │
  ├─ 1. 读 specs/{module}.json
  │      重点读 ai_specapis / constraints / dependencies / must_not
  │
  ├─ 2. 确认理解
  │      - 如果 spec 描述与代码实际行为不一致,优先怀疑 spec 过期
  │
  ├─ 3. 修改功能代码
  │      只改动需求直接涉及的部分,不顺手优化无关代码
  │
  ├─ 4. 同步更新 Spec
  │
  └─ 5. 提交 → 部署 → 验证

Git 操作规范

# 规则 说明
1 开工前必 pull git pull --rebase
2 改完即 commit 一个逻辑单元一次提交。禁止含密钥
3 推前必拉 + 配代理 push 前 git pull --rebase。远程操作前配 :15000 代理
4 trunk-based 日常在 main。仅长周期大改开分支

已有编码规范

MoFin 已有的编码规范见 docs/DEVELOPMENT_STANDARDS.md,包含:

  • 代码结构(mo_models → mo_data → mofin_db 三层)
  • 数据规范(币种、汇率、数据源)
  • DB 规范(表设计、迁移)
  • LLM Prompt 规范
  • Cron 规范(独立运行、幂等性)
  • 测试要求(run_all_tests.py

以上规范与本文件互补,不冲突。本文件侧重"先 spec 后代码"和"通过 Dashboard 保证可见性"。


六、部署环境

项目
生产环境 Linux 192.168.1.246
代码目录 /home/hmo/MoFin/
数据库 /home/hmo/web-dashboard/data/mofin.dbSQLite
Flask API server.py:8899(含 Dashboard
Python 系统 Python 3

七、文档索引

文档 用途
docs/dev-spec.md 本文件 — 开发规范(含十条红线)
docs/DEVELOPMENT_STANDARDS.md 编码规范(已有)
SYSTEM_ARCHITECTURE.md 系统架构(已有)
docs/cron-catalog.md Cron 任务清单(已有)
docs/DEPLOY.md 部署指南
docs/QUICKSTART.md 快速操作
docs/DASHBOARD.md Dashboard API 参考
docs/HEALTH-PIPELINE.md 健康管线文档
docs/learned.md 经验教训记录
docs/decisions/ 架构决策日志