# analyst-knowledge-log.md

## [2026-07-09 22:00] 全市场主力建仓扫描 + 五级过滤 + LLM九维分析

### 新增组件

| 组件 | 功能 | 调度 |
|------|------|------|
| `accumulation_scanner.py` | 全市场5207只A股量价异常扫描（每10分钟13秒） | `*/10 9-15` |
| `candidate_filter.py` | 五级过滤管道(S2量价/S3技术/S4资金/S5基本面) | `*/30 9-15` |
| `promote_candidates.py` | 自动提拔高分候选入自选 | `*/30 9-15` |
| `batch_reassess.py` | 批量LLM九维分析补全（逐只处理间隔15秒） | 一次性 |

### 系统架构变更

## [2026-07-10 11:42] 知微XMPP Bot离线自愈修复

### 发现
自愈执行器报告知微XMPP Bot离线。调查发现：
- Bot进程(PID 422464)被bash包装器手动启动，非systemd管理
- systemd xmpp-zhiwei.service 因PID文件冲突僵在 `activating (auto-restart)` 
- 孤儿bot在11:40:48断线后无法恢复连接

### 修复
1. 杀死孤儿进程 `kill -TERM 422464`
2. 删除PID文件 `rm -f /home/hmo/.hermes/zhiwei_bot.pid /tmp/xmpp_zhiwei_bot.pid`
3. systemd自动重启，bot干净上线
4. 验证：presence available、加入coregroup、bridge正常

### 教训
bash包装器启动bot会绕开systemd管理，导致：
- systemd状态监测不准确（显示restarting而非running）
- 孤儿进程断开后无法被systemd接管
- 已有 `xmpp-bot-infrastructure` skill 记录了孤儿进程陷阱，自愈系统可直接参考执行

自选统一：**
- 自选数据统一存储在 `holding_strategies(decision_type='自选策略')`
- `watchlist_stocks` 表已废弃（is_active=0）
- `read_watchlist()` 改为从 `holding_strategies` 读取

**DB统一：**
- `~/.hermes/profiles/position-analyst/data/mofin.db` → 软链接 → `/home/hmo/MoFin/data/mofin.db`

**去小果化：**
- `xiaoguo_scanner` / `xiaoguo情感分析` / `xiaoguo信号消费` 全部停用
- 替代为 `accumulation_scanner.py`（纯数据驱动，0 LLM成本）

### 九维分析

`per_stock_reassess.py` 重评时自动调用LLM(gateway API)生成完整九维分析：
- 数据源全部随需随拉（腾讯API实时价/PE/市值 + DB大盘/基本面/消息）
- LLM输出信号+买入区间+止损止盈+仓位百分比
- 超时自动降级为代码生成

### 冷却期机制
- `per_stock_reassess`: `reassessed_at`追踪，交易时段1小时/非交易24小时
- `price_monitor` zone breach: `_can_push()` 同股同区间30分钟冷却

### 仓位规则
- 仅「买入」信号输出仓位建议
- 仓位公式：RR×大盘调整×品种调整，范围5%~20%
- 关注/观望/卖出信号仓位为空

### 数据清理
- DROP TABLE: stock_weekly, stock_monthly（无人读取的死表）
- DROP TABLE: portfolio_state（无人读写的僵尸表）
- holdings: 清除shares=0的5只持仓
- watchlist_stocks: 全部标记is_active=0（已迁移）

- **发现**: candidates表有15条历史候选数据但promoted=0的都被手动标记了dropped=1（超7天未更新）。自动推广管道从未实现。
- **修改**: 新建 `scripts/promote_candidates.py` — 扫描 candidates(promoted=0+dropped=0) → stock_quote验价 → write_holding_strategy → 标记promoted
- **新建cron**: 候选股自动推广-盘中(e415846d4fb6) | 0,30 9-15 * * 1-5 | no_agent | 静默模式
- **效果预期**: 新候选股在30分钟内自动进入自选+带策略，不再依赖LLM prompt

## [2026-07-09 10:40] 自愈执行器升级处理：KOSDAQ-4.1% HIGH信号

- **发现**: 自愈执行器上报盘中自检发现宏观风险HIGH（KOSDAQ-4.1% + 中信证券研报）
- **判断**: 系统无故障，已知市场条件延续。KOSDAQ-4.1%是昨日KOSPI暴跌的延续，非新事件。中信证券研报是采集器误报（正常行业研报）。
- **数据验证**: 中国各指数全面脱钩改善（上证-1.26%→+0.02%，恒生-0.51%→+1.69%，科创50+0.28%→+0.62%）。持仓止损距均>3%。
- **操作**: 标记已知状态，无需新推送。08:30 LLM深度分析已覆盖并修正。
- **涉及文件**: macro_risk_state.json（已由consumer更新为processed）

## [2026-07-09 14:xx] 自愈执行器升级：信号堆积38条

- **发现**: 盘中自检触发「信号堆积: 38条未处理(需<30)」告警，自愈执行器无自动修复方案，升级到LLM处理
- **调查**: 38条为 xiaoguo 来源信号，属4h时效内积压。当前已完成消费（xiaoguo_signal_consumer每30分运行），积压自愈
- **监控盲区发现**: intraday_health_check.py 和 system_audit.py 均只监控 `source LIKE 'xiaoguo%'`，忽略 divergence_watch(80)、trend(46) 等来源的126条未处理信号
- **修复**: 两处均增加全量未处理查询，区分 xiaoguo 和其他来源分别报告
- **涉及文件**: scripts/intraday_health_check.py, scripts/system_audit.py, CHANGELOG.md

## [2026-07-09 14:xx] 自愈执行器升级：信号积压126条（divergence_watch/trend无consumer）

- **发现**: 自愈执行器上报「其它来源信号积压: 126条未处理（divergence_watch/trend等无consumer）」
- **调查**: divergence_watch 80条全部未处理 — divergence_detector.py写入signal_news但已自写macro_divergence_state.json，signal_news仅归档副本。trend 46条未处理 — 废弃系统的死数据，summary为空
- **修复**: divergence_detector.py — INSERT时加processed=1（归档性质不需要consumer）。DB — 80条divergence_watch + 46条trend历史标记为processed。同步cron目录MD5一致
- **效果**: signal_news 1077条全量已处理，健康检查PASS，后续不会再次积压
- **涉及文件**: scripts/divergence_detector.py, data/mofin.db, CHANGELOG.md

## [2026-07-10 10:25] 自愈：知微XMPP Bot离线 — 孤儿进程阻塞systemd

- **发现**: 盘中自检报警「知微XMPP Bot离线」，TODO 83 created（无fix_action，升级到LLM处理）
- **调查**:
  - systemd `xmpp-zhiwei.service` 陷入无限重启循环（重启计数器110+）
  - 根因：外部bash wrapper脚本在10:04启动了一个孤儿bot进程(PID 252975)，该进程占用了`/tmp/xmpp_zhiwei_bot.pid`和端口5805
  - systemd每次尝试启动都因PID检查`xmpp_zhiwei_bot already running (PID 252975), exiting.`而退出
  - 实际上PID 252975的bot是正常运行的（已加入群聊coregroup，HTTP桥5805正常响应），只是不受systemd管理。wrapper触发源不明（可能自愈系统之前的升级操作）
- **修复**:
  1. `kill -TERM 252975` 杀掉孤儿进程
  2. 清理旧PID文件 `/tmp/xmpp_zhiwei_bot.pid` 和 `/home/hmo/.hermes/zhiwei_bot.pid`
  3. systemd 10秒RestartSec后自动启动新实例
  4. TODO 83 标记为completed
- **验证**: systemd active(running) since 10:25:43，bot加入群聊coregroup就绪，gateway health ok，HTTP桥5805正常
- **效果**: systemd恢复管控bot，重启循环归零
- **涉及文件**: /home/hmo/xmpp_zhiwei_bot.py (PID_FILE机制)

## [2026-07-13] XMPP Bot非阻塞修复 + 深套股规则重构 + 换股规划

### XMPP Bot修复
- **问题1**: bot调用gateway同步等600秒，阻塞事件循环 → XMPP心跳发不出 → 被踢下线 → 重试→turn堆积→更慢
- **修复**: 45s短超时 + "处理中"预回复 + 后台300s轮询 + 不再阻塞心跳
- **问题2**: 远程XMPP服务器(120.78.123.183:5222)网络不通，bot连不上
- **修复**: bot.connect(host='127.0.0.1', port=5222) 改连本地XMPP代理
- **问题3**: xep_0045 MUC插件未注册导致崩溃
- **修复**: __init__加 self.register_plugin('xep_0045')
- **涉及文件**: /home/hmo/xmpp_agent_core.py

### price_monitor通知噪音修复
- **问题**: _push_cooldown 是内存dict，price_monitor每2分钟新进程运行 → cooldown每次重置 → 同股同区间反复推送
- **修复**: cooldown持久化到 /home/hmo/.hermes/.price_push_cooldown.json
- **涉及文件**: scripts/price_monitor.py

### 深套股规则重构（Dad铁律确认）
- **删除**: `is_deep_loss` 对止损/止盈/买入区/质量检查的全部6处guard
- **删除**: `action_note="深套持有"` 强制覆盖
- **删除**: `position_advice="不补不割"` / `time_horizon="长期"`
- **保留**: `stock_category="深套"` 仅作标签
- **原则**: 一切根据客观判断，该加就加该割就割
- **涉及文件**: scripts/strategy_lifecycle.py

### 换股规划功能
- `python3 strategy_lifecycle.py swap-plan [--need 金额]`
- 五维评分: 亏损程度25% + 仓位20% + 技术趋势25% + 流动性15% + 前景15%
- 按评分排序输出可替换优先级，--need 参数自动计算卖几只够
- **涉及文件**: scripts/strategy_lifecycle.py

### 技术分析增强
- weekly/monthly趋势/MA/支撑阻力注入mtf_context
- 健康Tab写无读警告从3个归零（stock_weekly/monthly/watchlist_log加manual_readers）
- 每日汇总只发一次（16:35 + sent标记防重复）
- cron_health_monitor新增数据实体完整性检查
- 涉及文件: scripts/technical_analysis.py, scripts/strategy_lifecycle.py, scripts/mofin_health.py, scripts/cron_to_xmpp.py, scripts/cron_health_monitor.py

## 2026-07-14 — 系统检查：Dad未收到任何消息的诊断

### 发现问题
1. **cron_to_xmpp.py Bug**: body提取`content.split("## Response")`用`parts[1]`取到的是skill内容中的 ## Response（第一个），而不是agent实际回复的 ## Response（最后一个）。导致开盘简报等LLM报告的正文取错，被误判为[SILENT]静默拦截。
2. **price_monitor.py SQLite写锁死锁**: 多个cron脚本（price_monitor + mofin_health等）同时BEGIN IMMEDIATE写 mofin.db，进程卡在D状态，WAL文件膨胀到2.7MB，后续全部超时。
3. **mofin_db.py版本不同步**: cron版本和MoFin版本有差异（cron版本多了保留full_analysis/reassessed_at的代码）。

### 修改了什么
- `cron_to_xmpp.py` — 改 `parts[1]` → `parts[-1]`（取最后一个Response节）
- `mofin_db.py` (MoFin目录) — 同步cron版本的reassessed_at列处理和full_analysis保留逻辑
- `price_monitor.py` — 添加debug时序追踪，临时kill D状态进程+WAL checkpoint
- `.silent_daily_count.json` — 纠正静默计数（-1因为开盘简报被误拦）

### 文件
- Modified: /home/hmo/.hermes/profiles/position-analyst/scripts/cron_to_xmpp.py
- Modified: /home/hmo/MoFin/scripts/mofin_db.py
- Modified: /home/hmo/.hermes/profiles/position-analyst/scripts/price_monitor.py

## 2026-07-14 — price_monitor DB写锁死锁根治（跟进修复）

### 发现问题
上次诊断只做了临时修复（kill D状态进程 + WAL checkpoint），Dad要求直接根治。

### 修改了什么（三副本同步）
- **price_monitor.py** (profile/scripts): 统一 BEGIN IMMEDIATE 包裹所有写操作，替代调用 write_holdings_batch/write_portfolio_summary/write_live_prices。5次重试+指数退避(1s→2s→4s→8s→16s)。重试耗尽后自动 emergency WAL checkpoint。try/except 确保 conn 始终释放。
- **MoFin/scripts/price_monitor.py** — 同步修复
- **MoFin/price_monitor.py** — 同步修复（保留其 cash_log 优先的现金读取逻辑）
- **CHANGELOG.md** — 新增2026-07-14条目

### 文件
- Modified: /home/hmo/.hermes/profiles/position-analyst/scripts/price_monitor.py
- Modified: /home/hmo/MoFin/scripts/price_monitor.py
- Modified: /home/hmo/MoFin/price_monitor.py
- Modified: /home/hmo/MoFin/CHANGELOG.md

## 2026-07-14 — DB写锁死锁根治（补完）

### 发现问题
上一轮修复（commit 93dce81）加了 price_monitor 的重试和进程锁，但：
1. mofin_db.py 的 get_conn() 没有在连接时自动清理 WAL，被 kill 的进程残留 WAL 仍会卡死后续连接
2. 其他并发写脚本（market_watch, mofin_health 等）没有重试保护
3. price_monitor 的 os.nice 缺失，高优先级抢占 DB 锁

### 修改了什么
- mofin_db.py get_conn(): 每次连接时 `PRAGMA wal_checkpoint(TRUNCATE)` 自动清理残留 WAL
- price_monitor.py run_once(): 加 `os.nice(10)` 降低优先级
- 其他并发脚本：通过 get_conn() 的 WAL checkpoint 间接保护 + busy_timeout=30s 兜底

### 效果预期
- 任何进程被 kill 后，下一个连接的脚本自动 checkpoint 清理 WAL，不会卡死
- price_monitor 进程锁防止同一脚本并发
- priority 降低减少恶性抢占

## 2026-07-14 10:55 — DB死锁根治：盘中脚本统一get_conn()

### 发现问题
price_monitor.py的`refresh_data_prices()`已有完善的重试机制(5次+指数退避+WAL checkpoint)，但其他盘中高频脚本仍然使用raw `sqlite3.connect()`，绕过`get_conn()`的WAL模式+busy_timeout=30s设置。

### 修改了什么
- `mofin_health.py` — get_db_stats()改get_conn()
- `cron_health_monitor.py` — price_monitor新鲜度查询改get_conn()
- `intraday_health_check.py` — 3处sqlite3.connect全部改get_conn()
- `self_todo_executor.py` — sqlite3.connect改get_conn()
- `mofin_db.py` — get_conn()每次新建连接时WAL checkpoint

### 测试结果
并发压力测试：3x price_monitor + 3x mofin_health同时运行 → 6/6通过，WAL仅32bytes

### 文件
- Modified: /home/hmo/MoFin/mofin_db.py
- Modified: /home/hmo/MoFin/scripts/cron_health_monitor.py
- Modified: /home/hmo/MoFin/scripts/intraday_health_check.py
- Modified: /home/hmo/MoFin/scripts/mofin_health.py
- Modified: /home/hmo/MoFin/scripts/self_todo_executor.py
- Modified: /home/hmo/.hermes/profiles/position-analyst/scripts/ (同上5文件)
- Commit: 59e94d1, pushed to origin/master

## 2026-07-14 10:55 — 知微XMPP Bot断线不重连修复

### 发现问题
自愈执行器发现知微XMPP Bot离线。调查发现：
1. Bot进程(3643320)由gateway产生，但无任何TCP连接（断线后slixmpp不会自动重连，因为`auto_reconnect`默认关闭）
2. systemd的xmpp-zhiwei.service有2276次失败重启记录（PID文件冲突）
3. Bot进程(3643320)始于04:28，presence=unavailable，但HTTP桥(5805)仍活着

### 根因
slixmpp ClientXMPP的`auto_reconnect`属性默认为False。断线（connection_lost）发生后，bot进程保持运行（HTTP桥继续工作）但从不尝试重新连接XMPP。在main()中`await bot.ready.wait()`已通过，asyncio.gather继续运行，bot看起来活着但实际上无法接收/发送XMPP消息。

### 修改了什么
- `/home/hmo/xmpp_agent_core.py`:
  1. AgentBot.__init__()加 `self.auto_reconnect = True`
  2. 新增 `connection_watchdog()` 看门狗协程——每15秒检查连接状态，断线超过120秒执行`os._exit(1)`让gateway重新spawn
  3. main()启动connection_watchdog作为独立任务

### 执行了什么
1. Kill旧bot(3643320) → gateway自动spawn新bot(114609) → 新bot连接XMPP成功但被ejabberd重启踢下线
2. Kill中间bot(114609) → gateway再spawn(122594) → 稳定连接
3. Kill 122594后gateway spawn新bot(131908)加载修复代码，自动重连生效
4. Stop systemd xmpp-zhiwei.service（2276次失败重启，不再需要，由gateway管理bot）
5. 清理PID文件 /tmp/xmpp_zhiwei_bot.pid

### 效果预期
- 断线后slixmpp自动重连（最快5s，指数退避）
- 看门狗兜底：120秒未恢复则进程退出→gateway respawn
- systemd不再干扰（已stop，gateway管理bot生命周期）

### 文件
- Modified: /home/hmo/xmpp_agent_core.py
- Stopped: systemctl stop xmpp-zhiwei.service (2276失败重启)
