Skip to content

Commit ffc340b

Browse files
authored
Merge pull request #130 from QuantStrategyLab/codex/clarify-health-execution-state
fix: clarify unconfirmed health actions
2 parents fd40aa9 + 90dd93f commit ffc340b

3 files changed

Lines changed: 29 additions & 8 deletions

File tree

ops/quant-monitor/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ Token 从 GCP Secret `quant-sentinel-telegram-bot-token` 加载;**不要**把
3939
监控证据只触发研究审查,不自动修改策略代码、live 参数、仓位、风险预算,不自动
4040
merge 或 deploy。成功记录策略劣化后,monitor 正常结束,不再重复通知人工。
4141

42+
因此健康卡片里的 `canary_eligible`
43+
`pause_request_pending_confirmation`**证据状态**,不是券商侧已执行的事实。
44+
只有日后接入并回传执行回执的预授权运行时,才能把暂停或 canary 推进标为已完成。
45+
4246
| 变量 | 说明 |
4347
|------|------|
4448
| `QUANT_SENTINEL_TELEGRAM_SECRET_NAME` | 默认 `quant-sentinel-telegram-bot-token` |

ops/quant-monitor/scripts/build_dashboard_snapshot.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
MAX_STRATEGIES = 100
2525
DECISIONS = {
2626
"healthy": {
27-
"code": "auto_advance",
28-
"label": "系统可自动推进下一阶段",
29-
"reason": "机器检查通过;仅在预批准的 canary 预算内推进,不自动进入正常 live。",
27+
"code": "canary_eligible",
28+
"label": "满足 canary 条件,等待预授权执行器确认",
29+
"reason": "机器检查通过;监控只生成证据。仅已接入的预授权 canary 执行器才能推进,绝不自动进入正常 live。",
3030
},
3131
"watch": {
3232
"code": "stay_shadow",
@@ -39,9 +39,9 @@
3939
"reason": "健康度进入复核区,先确认数据、成本和风险。",
4040
},
4141
"critical": {
42-
"code": "auto_pause",
43-
"label": "自动暂停 / 回滚复核",
44-
"reason": "触发严重告警,系统先控制风险,不等待人工确认。",
42+
"code": "pause_request_pending_confirmation",
43+
"label": "已提出暂停请求,待实际运行时确认",
44+
"reason": "触发严重告警;监控会隔离晋级并生成可审计的暂停请求。缺少运行时回执时,券商执行状态为未知。",
4545
},
4646
}
4747

@@ -181,7 +181,7 @@ def _decision(status: str, requested_stage: str | None = None) -> dict[str, str]
181181
return {
182182
"code": "human_live_gate",
183183
"label": "机器检查通过,等待你批准正常 live",
184-
"reason": "进入正常资金暴露前仍需人工确认,不会因健康分自动上线。",
184+
"reason": "进入正常资金暴露前仍需人工确认;健康监控本身不具备下单、暂停或上线权限。",
185185
}
186186
return dict(DECISIONS.get(status, {
187187
"code": "evidence_missing",

ops/quant-monitor/tests/test_dashboard_snapshot.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def test_normalizes_health_scores_and_review_evidence(self):
6262
self.assertEqual(payload["data_status"], "ready")
6363
self.assertEqual(payload["summary"]["healthy"], 1)
6464
self.assertEqual(strategy["review"]["requested_stage"], "shadow_candidate")
65-
self.assertEqual(strategy["decision"]["code"], "auto_advance")
65+
self.assertEqual(strategy["decision"]["code"], "canary_eligible")
6666
self.assertEqual(strategy["freshness"]["status"], "unknown")
6767
self.assertEqual(strategy["source_revision"], "https://example.invalid/revisions/rev-1")
6868
self.assertEqual(strategy["review"]["evidence_package_id"], "https://example.invalid/evidence-1")
@@ -272,6 +272,23 @@ def test_healthy_live_candidate_still_waits_for_human(self):
272272

273273
self.assertEqual(payload["strategies"][0]["decision"]["code"], "human_live_gate")
274274

275+
def test_critical_status_never_claims_an_unconfirmed_broker_pause(self):
276+
with tempfile.TemporaryDirectory() as tmp:
277+
health = Path(tmp) / "health.json"
278+
health.write_text(json.dumps({"strategies": [{
279+
"strategy_profile": "critical_strategy",
280+
"domain": "us_equity",
281+
"status": "critical",
282+
"overall_score": 12,
283+
}]}), encoding="utf-8")
284+
285+
payload = build_payload(health_file=health)
286+
287+
decision = payload["strategies"][0]["decision"]
288+
self.assertEqual(decision["code"], "pause_request_pending_confirmation")
289+
self.assertIn("待实际运行时确认", decision["label"])
290+
self.assertNotIn("已停单", decision["reason"])
291+
275292

276293
if __name__ == "__main__":
277294
unittest.main()

0 commit comments

Comments
 (0)