The monolith feature where pasting a polymarket.com/ link makes the bot reply with the cohort holders for that specific bet (plus a category-consensus fallback when no high-edge signal exists) was never ported to pmv2. Restored 2026-06-24 over the live NATS query channel — same plumbing as the just-restored /topbets / /consensus / /filters. This is a 1:1 verbatim port from the monolith, reviewed (fidelity + 4 adversarial lenses) and gated green.
For Agents — state at a glance
- Contract:
pmv2-contractsc6b3a15— additiveQueryKind::BetInspect { url }, serde back-compat (internally-tagged + flattened, same discriminator pattern as the otherQueryKindvariants).- Responder:
cohort_algo1d573b8(= prior299cf1a+ therender_bet_inspecthandler; still carries the rustls fix from pmv2-self-watch-rustls-cryptoprovider-crashloop).- Trigger:
telegram_connectordetects a non-slash message containingpolymarket.com/and publishesBetInspect { url }. NO new NATS subjects/permits — reusesquery.request/query.results.- Connector arm pending: non-slash detection = @pmv2_telegram (babylon task #517). Cohort side is shipped + gated.
- Deploy order: ship cohort
1d573b8before/with the connector. An unknownbetinspectreaching an old cohort is a fail-safe skip (no crash).
Data flow
Identical plumbing to query-commands-restoration — this is just one more QueryKind variant on the existing channel:
telegram_connectordetects a non-slash message body containingpolymarket.com/→ publishesQueryKind::BetInspect { url }onquery.request.- cohort
query-responder→render_bet_inspect:score_bet(url)— bet-scoped holder lookup (the specific condition/outcome of the pasted link) + gauge body formatter.- If
!has_high_edge_signal→resolve_fallback_category+category_consensus_section→ appended fallback.
- Publishes
QueryReply { rendered }onquery.results. - connector posts
renderedas HTML.
This mirrors the monolith’s MessageAction::BetLink auto-analyzer (see pmv2-bet-link-analyzer-flow) — same two empty-states, same edge-scored cohort, same category-consensus fallback semantics — now relocated behind the query channel instead of running in-process in the bot.
Notable engineering
- DRY shared SQL const — extracted
BET_HOLDER_SELECT(a single SELECT body) shared byload_bet_holders+all_cohort_holders, with a byte-identity guard test so the two callers can never silently diverge. - Backpressure semaphore (cap 4) added to the query-responder. The monolith had one; the earlier query-channel port had dropped it — restored here so concurrent bet-inspect/topbets/consensus requests can’t unbounded-fan-out the DB.
Deferred follow-up
Advisory-lock dedup in
run_and_persist— duplicate same-category consensus recompute is currently wasted work (two requests for the same category recompute independently). Not corruption, just redundant load. Also affects/consensus. Wrap recompute in a per-category Postgres advisory lock so the second caller waits on / reuses the first’s result.
Review
1:1 verbatim port from the monolith. Reviewed for fidelity plus 4 adversarial lenses: DB-schema, concurrency, DRY/SOLID, regression/serde. Gate green.
Pins
| Crate | Pin | Note |
|---|---|---|
pmv2-contracts | c6b3a15 | additive QueryKind::BetInspect { url }, serde back-compat |
cohort_algo | 1d573b8 | = 299cf1a + render_bet_inspect; carries rustls fix |
Related
- query-commands-restoration — the query channel this rides on (/topbets, /consensus, /filters)
- pmv2-bet-link-analyzer-flow — the monolith original being ported
- category-consensus — the fallback section’s compute core
- pmv2-self-watch-rustls-cryptoprovider-crashloop — the rustls fix carried in cohort
- pmv2-telegram-connector-fleet-integration — connector bot surface