feat(sense): T-X5 云端评判晋升表×conformal 双闸门——本地档自动接管(采纳 cortiq promotion)
- gateway/sense/promotion.py:PromotionTable 状态机(candidate/promoted/demoted)
* 晋升门:n_total>=n_min 且 通过率>=promote_lb 且 soak 浸泡期满足
* 退化:promoted 期间通过率<demote_lb 自动降级;降级后可凭数据恢复
* 一票否决:tier=T3 观察不进通过率统计,已晋升者立即降级
* 持久化 sense_promotion 表(CREATE IF NOT EXISTS 幂等)
- grader:live 模式对已晋升标签的 T2 决策(无 T3 信号/非 fallback)升级 T1,
hard_gates.promotion_applied 如实标注;T1/T3/fallback 路径不受影响
- 回填链路:T1 审计抽样带 promo:<label> 标签 -> 人工 verdict approve=ok
经 /review/{id} 提交时回填晋升表(失败不影响审核主流程)
- 双闸门语义:conformal 阈值保证单条决策风险率,晋升表保证标签级接管节奏;
collect 数据不足(n_min 未满)不晋升,全部迁移可经 T-X4 留痕审计
pytest 474 passed(T-X4 后 466 + 8)
This commit is contained in:
@@ -41,6 +41,14 @@ CREATE TABLE IF NOT EXISTS sense_decisions(
|
||||
candidate_scores TEXT NOT NULL DEFAULT '{}',
|
||||
rejected TEXT NOT NULL DEFAULT '[]');
|
||||
CREATE INDEX IF NOT EXISTS idx_dec_ts ON sense_decisions(ts);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sense_promotion(
|
||||
label TEXT PRIMARY KEY, n_total INTEGER NOT NULL DEFAULT 0,
|
||||
n_ok INTEGER NOT NULL DEFAULT 0,
|
||||
state TEXT NOT NULL DEFAULT 'candidate',
|
||||
first_ts INTEGER NOT NULL DEFAULT 0,
|
||||
promoted_ts INTEGER NOT NULL DEFAULT 0,
|
||||
last_ts INTEGER NOT NULL DEFAULT 0);
|
||||
"""
|
||||
|
||||
|
||||
@@ -178,6 +186,30 @@ class SenseStore:
|
||||
out.append(d)
|
||||
return out
|
||||
|
||||
# ---------- 晋升表(T-X5:本地档自动接管的双闸门之一) ----------
|
||||
def upsert_promotion(self, row: Dict[str, Any]) -> None:
|
||||
with self._lock, self._connect() as conn:
|
||||
conn.execute(
|
||||
"""INSERT OR REPLACE INTO sense_promotion
|
||||
(label, n_total, n_ok, state, first_ts, promoted_ts, last_ts)
|
||||
VALUES (?,?,?,?,?,?,?)""",
|
||||
(row["label"], int(row.get("n_total", 0)),
|
||||
int(row.get("n_ok", 0)), str(row.get("state", "candidate")),
|
||||
int(row.get("first_ts", 0)), int(row.get("promoted_ts", 0)),
|
||||
int(row.get("last_ts", 0))))
|
||||
|
||||
def get_promotion(self, label: str) -> Optional[Dict[str, Any]]:
|
||||
with self._lock, self._connect() as conn:
|
||||
row = conn.execute(
|
||||
"SELECT * FROM sense_promotion WHERE label = ?", (label,)).fetchone()
|
||||
return dict(row) if row else None
|
||||
|
||||
def list_promotions(self) -> List[Dict[str, Any]]:
|
||||
with self._lock, self._connect() as conn:
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM sense_promotion ORDER BY last_ts DESC").fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
# ---------- 工件 ----------
|
||||
def register_artifact(self, version: str, kind: str, path: str,
|
||||
metrics: Dict[str, Any], active: bool = False,
|
||||
|
||||
Reference in New Issue
Block a user