feat(manifold): add matcher versioning to separate legacy accepted matches from v3_outcome_guard metrics
CI/CD / build-and-push (push) Successful in 9s

Add MANIFOLD_MATCHER_VERSION="v3_outcome_guard" tag persisted to
manifold_match_audit.matcher_version so metrics can isolate current-matcher
stats from pre-versioning records, whose accepted matches the outcome
guard would now reject.

- schema: add matcher_version column + index; idempotent startup backfill
  tagging NULL rows as legacy_pre_outcome_guard (no outcome types) or
  v2_outcome_guard_no_version (has outcome type, version not persisted)
- save_manifold_audit: write matcher_version on every new record
- get_manifold_matches: split summary into current_version / all_time /
  legacy; recent_matches now carry matcher_version

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
chemavx
2026-06-02 08:59:19 +00:00
parent 34fd1f8719
commit 664ecab174
5 changed files with 99 additions and 18 deletions
+14 -8
View File
@@ -211,16 +211,22 @@ async def get_attribution():
@app.get("/api/metrics/manifold-matches")
async def get_manifold_matches():
"""Manifold match audit — summary stats and recent match attempts.
"""Manifold match audit — version-split summary and recent match attempts.
summary:
total_accepted — matches accepted (score >= 0.40, inversion unambiguous)
total_rejected — matches rejected (low score or ambiguous inversion)
total_no_results — no Manifold market found or API error
avg_match_score — mean Jaccard score for accepted matches
trades_dominated_by_mfld — open trades where feat_mfld_lo is the largest signal
summary.current_version — stats for the active matcher (MANIFOLD_MATCHER_VERSION):
version — the matcher version string
total_accepted — matches accepted (score >= 0.40, inversion unambiguous)
total_rejected — matches rejected (low score or ambiguous inversion)
total_no_results — no Manifold market found or API error
avg_match_score — mean Jaccard score for accepted matches
used_in_trade — accepted matches that were actually executed
summary.all_time — accepted/rejected/no_results across every matcher version.
summary.legacy.accepted_without_outcome_type — pre-outcome-guard accepted
records that the current matcher would reject (not counted in current_version).
summary.trades_dominated_by_mfld — open trades where feat_mfld_lo is the largest signal.
recent_matches: last 50 rows from manifold_match_audit, newest first.
recent_matches: last 50 rows from manifold_match_audit, newest first, each
tagged with matcher_version.
used_in_trade=True only when status='accepted' AND a trade was actually executed.
"""
data = await db.get_manifold_matches(limit=50)