Skip to content

Promote dev to main: Serialized onboarding, bench scoring fixes, 001 node reference - #2269

Open
Flotapponnier wants to merge 326 commits into
mainfrom
dev
Open

Flotapponnier wants to merge 326 commits into
mainfrom
dev

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

Staging state on dev since 2026-09-05, reviewed at https://staging-openchainbench.vercel.app.

What this promotes

Serialized (serialized.xyz) as a provider

Bench integrity fixes, all as separate series so history is preserved

Audit doc docs/methodology/serialized-onboarding-audit.md v1.3 (#2264, #2265): every number, every correction, two methodology defects in our own benches, a verified 5.2x BONK mispricing traced to a pool-ranking unit bug on their side.

What merging to main does beyond the site

The three Railway head-lag services (Aggregator east usa, Agg eu west, agg sgp) build from main, root harnesses/aggregator-head-lag. After this merge, trigger a fresh git build on each (serviceInstanceDeployV2); SERIALIZED_API_KEY is already set on all three. Agg eu west has three failed snapshot-upload deploys since 2026-09-05 14:32 (lstat …/harnesses: no such file or directory), a railway up from a directory without the harness path; a git build replaces it.

Known state at promotion time

  • 004: Serialized is producing (p50 53.3% on the spec query) but the leaderboard still shows the pre-outage snapshot because Mobula/Codex/Jupiter quantiles are NaN while the dead hours (webshare proxy quota, 429) remain in the 24h window; quorum fails 1/4 and the worker keeps the previous render. Self-heals once those hours roll out.
  • 008: Serialized 3rd at 76.75% (n=1,188). 005: last at 19. 090: 4th of 5 at 19 (Sim by Dune is dead: api.sim.dune.com no longer resolves).

🤖 Generated with Claude Code

https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Flotapponnier and others added 30 commits September 4, 2026 01:26
feat(speedtest): dedicated social card
fix(speedtest): satori-compatible OG card
feat: crowdsourced RPC latency world map
feat(map): search + compare + smart viewport
feat(map): clickable areas + history panel
feat(map): near me + pin with nearest results
fix(speedtest): fail-open prefill check
fix(bench-205): apples-to-apples Solana scoping
Wires serialized.xyz into metadata-coverage (004) and wallet-labels (008),
the two benches where their endpoints map 1:1 to the existing scoring rule.

Both providers throttle client-side at ~16 rps: Serialized enforces a hard
40 req/s burst cap and an unthrottled worker pool turns coverage into a
rate-limit artifact (measured 77% -> 37%).

Adds the registry entry, logo and a full onboarding audit documenting the
apples-to-apples numbers and two scoring flaws the tests exposed in our
own benches (logo presence vs resolution on 004, name-service strings
counted as entity labels on 008).


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
The harnesses emit provider="serialized" but the leaderboards are
driven by the explicit providers block in each spec, so the series
never rendered. Adds the block for both benches, same query shape as
the incumbents.

Validated with SpecSchema.safeParse across all 218 specs; every
formula stays under the 240-char cap that silently drops a spec.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Serialized publishes its chain list at the free GET /v1/meta/chains.
The same list answers both benches: they run their own indexers and
do not separate asset-registry coverage from DEX-pool coverage, so
the count is identical on 005 and 090 by construction.

Only chains the endpoint marks status=live are counted, so a future
beta or deprecated status cannot inflate the number.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ups (#2264)

v1.0 claimed bench 001 references archive nodes and was therefore
unaffected by provider clock disagreement. That repeated the spec
instead of reading the harness: there is no archive-node reference in
aggregator-head-lag at all, and the leaderboard gauge is computed from
each provider's own timestamp. The spec says the opposite in three
places.

Also records the now-conclusive bench 067 result (verified 5 of 19
chains), probe-confirmed negative capabilities, and a verified 5.2x
BONK mispricing traced to pool discovery missing the main market.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…en-security feasibility (#2265)

The v1.1 text said the deep Orca pool was absent from their pool list.
It is present, ranked second. The real defect is that the ranking
compares liquidityNative across different quote assets without
converting to USD, so a $4,347 USDC-quoted pool outranks a $75,679
SOL-quoted one because 4,346 > 728. Seven of eight pools agree on the
price; rank 1 is the lone outlier and the token is priced from it.

Adds section 17: token-security bench feasibility, including the
provider cohort, a latency table where Mobula is last by 17x, three
measured design traps, a retrospective backtest and its limits, and
which fields actually carry signal.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both benches score a proxy for the thing they claim to measure.

Bench 004 scores the logo field as "non-empty string", which any
provider wins by construction by rewriting logos onto its own CDN at a
deterministic path. The current beneficiary is Mobula, at 100% logo on
every chain against 22.9/37.8/78.9 for a provider returning upstream
URLs. Adds logo_resolved: HEAD the URL, fall back to a ranged GET on
403/405, cache 6h so we do not hammer third-party CDNs.

Bench 008 scores a hit as "any non-generic name", which cannot tell a
curated entity from a personal name-service record. Measured: 25% of
Serialized's hits and 25.4% of Mobula's named something other than the
curated entity. The anchor list already carries a Hint for every
address and the scoring path ignored it. Adds
wallet_labels_accurate_total scored against that Hint.

Both land as SEPARATE series, not as redefinitions, so the published
leaderboards and their history stay intact while the stricter numbers
build up alongside.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… clock (#2267)

The spec promises "Reference: archive nodes per chain, validated against
block hashes" in three places. The harness never did that: both provider
paths compute receiveTime minus the timestamp the provider itself sent.
grep for archive/getBlockByNumber/blockTimestamp over the harness returns
nothing.

Measured consequence: on the same transaction hash, Serialized and Mobula
disagree about when it happened by 707 ms on Solana and 1,000 ms on Base,
so the leaderboard partly ranks where each vendor puts its clock.

Adds one WebSocket subscription per monitored pool straight to a node,
timestamping every swap on receipt, matched to provider emissions by
transaction hash. Published as head_lag_ref_seconds beside the legacy
series so the old one keeps its history while the two are compared.

Validated before shipping at a 100% hash match rate on Base and Solana.
That validation also surfaced the binding constraint: against public
endpoints the reference node is SLOWER than the providers, so the series
carries the node's own latency as an offset and must be read as a
relative comparison until REF_WS_URL_<CHAIN> points at a paid node. All
of this is documented at the call site.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Their trades stream is keyed by token with an optional pools filter,
while the bench is keyed by pool. Subscribing by the pool's native side
(SOL, WETH, WBNB) acknowledges and delivers nothing; subscribing by the
side their own /v1/pool reports as `token` (USDC, BUSD, USDG) with
pools=<bench pool> delivers exactly that market. Verified on all four
bench pools before shipping (events with txHash: solana 4, base 10,
bnb 2, robinhood 79).

One connection per process, four pools multiplexed: their key allows 5
concurrent connections and this harness runs in three regions.

Records both series: head_lag_seconds from their own `at`, same
treatment as the incumbents, and head_lag_ref_seconds against the node
reference clock matched by txHash.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…he 2025-01-01 floor (#2271)

keyed-rpc-robinhood (live since 2026-08-27) and every bench added
since the last regeneration emitted datePublished 2025-01-01 in
JSON-LD, the FLOOR_PUBLISHED fallback in src/lib/seo/bench-dates.ts.
A datePublished a year before the site existed, next to a
dateModified that moves hourly, is exactly the freshness signal the
file header warns about.

Regenerated with scripts/generate-bench-published.mjs as documented.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…Asia-Pacific claim (#2273)

Same rescoping as the main hotfix, applied to the two-region dev
version: the headline still cites Singapore, the region tabs stay,
every chain-wide superlative and the unsourced Asia-Pacific
justification are gone.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…product URLs (dev twin) (#2275)

Same two changes as the main hotfix. On dev, keyed-rpc-robinhood declares
its region tabs so the payload guard is a no-op there; the sitemap filter
is identical.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…ditorial (dev twin) (#2277)

Same change as the main hotfix. On dev, keyed-rpc-robinhood declares its
region tabs so it is returned untouched; the page-level guard from the
previous twin is removed.


Claude-Session: https://claude.ai/code/session_01CpArutAtXuBb1BVNUDXoYA

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Reverts #2268 before it reaches main. Measured 2026-09-08: their `at` is
the block timestamp exactly, so the ruler matches, but on Base every
sampled trade arrives before its own block exists (11/11 received while
the node head was still target-1, median 1.04 s ahead of publication).

They stream sequencer preconfirmations; Mobula, Codex and GeckoTerminal
read sealed blocks. That is a latency/finality trade-off, not a speed
gap, and one ranking would present it as superiority. RecordHeadLag also
drops negatives, so on the legacy series they would read as no data on
Base while being the fastest.

Audit §18.1 records the measurements, the two open questions for them
(preconfirmed=false on all lead events, 0 Robinhood events in 240 s) and
the conditions to reopen. Serialized stays on benches 004, 005, 008, 090.

Claude-Session: https://claude.ai/code/session_01LtBjM1FhTKxiZhwzb3Y61c

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nominator (#2279)

Two problems on /products/[slug], both visible on Serialized.

rankPerChainForBench only holds one real per-chain fact: the leader, from
bestPerChain. For every other provider it reused the unfiltered aggregate
order shifted by one slot, so a chip reading "#3 on Solana" was the global
rank with a chain label on it, repeated identically across every chain of
the bench. That reads as a measurement and is not one. Non-leader chips
are gone: a chip now means "leads this chain", and its absence means
"does not lead", not "ranks lower".

The chips also hid how many providers were measured on the chain. "#1 on
Solana" was #1 of 2 on bench 008 while sitting next to "#3 of 8" for the
aggregate. They now read "#1 of 4 on Ethereum", with the denominator taken
from providersPerChain and omitted when that set is unknown rather than
substituting the global count.

Wins accounting is unchanged: it already counted rank === 1 entries only.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…he mix (#2280)

On a bench with chain dimensions the cross-chain aggregate is a mix, not a
comparison. Ranking on it alone let a provider measured on one chain that
nobody else reported finish above a provider that led several contested
ones. Five live benches shipped that way:

  rpc-capabilities        Binance 1st on 1 chain, PublicNode led 6
  wallet-labels-coverage  XRPScan 1st on 1 chain, Serialized led 4
  token-quote-coverage    Jupiter 1st on 1 chain, Mobula led 2
  bridge-fee              Squid Router 1st on 1 chain
  perp-liq-rate           Lighter 1st on 1 chain

rankedCandidates now sorts by contested-chain wins first and uses the
aggregate value only to break ties. A chain counts only when at least two
providers reported on it, so an uncontested chain awards nothing: you do
not win a race you ran alone.

Guarded by the per-chain stashes, which materialize/load.ts populates only
on the unfiltered view. A chain-filtered variant has none, so ?chain=bnb
keeps ranking by value as before.

providers.ts reuses the same ordering. The two surfaces disagreeing is what
put "#3 of 8" next to five chain-leadership chips on the same bench row.

Known and accepted: a provider with one contested win now ranks above one
with none and a higher aggregate figure (TonAPI over XRPScan on 008). That
is what ranking on head-to-head record means; the win count is on the row.

Rule documented in methodology, section II.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Flotapponnier and others added 30 commits September 19, 2026 21:33
…te, hub tooltip) instead of reading as unresponsive; the HyperEVM tab waits for a product priced there; EVM_DAILY_TARGET default 1000; copy on which rows price the gas coin where (#2528)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…se gauges and a 7-day window (p50/p90/p99 were one execution), method label and full fallback accounting, real freshness from a persisted last-execution time, RPC keys out of the log, Near Intents quoted fee, stuck deposits in the success denominator, ticket dimension the site could not render removed, realized fee panel (#2529)

ocb-bench-audit on bridge-execution-latency (staging, 9135212): NOT
READY, 4 blockers, 5 majors.

Blocker 1 (and major 4): bridge_exec_latency_ms, slippage, gas, realized
output and fees were last-value gauges that persisted for days;
quantile_over_time over them returned the last execution (p50 = p90 =
p99 on every row) and the "24h" panels averaged Thursday's $30 legs into
Saturday. They are now pulses: set once per execution, deleted after
75 s (2 to 3 scrapes), so every execution weighs the same in a range
query. The recording rules move to a 7-day window (ocb:*:p50_7d ...,
plus :last, fees and onchain), and the specs read them: one execution
per corridor per day makes a 24h quantile meaningless. n =
round(increase(success + reverts + stuck)[7d]).

Blocker 2: the amount_usd dimension was in the specs but the variant API
and the tab strip never carried it, so the "$30" view was the pooled
view under a formula that claimed a selection. Dimension removed from
both specs; copy says $3 and $30 are pooled (label kept in Prometheus).

Blocker 3: freshness_metric pointed at a histogram family (no bare
series) and the loader fell back to "now", so a dead harness read
"updated 4 min ago" forever. New prometheus.freshness_timestamp_metric
(schema + load.ts): a persistent gauge whose value is the unix time of
the last run; bridge_last_execution_timestamp_seconds is set on every
terminal execution and persisted in /state/last-execution.json so a
restart re-exposes it (seeded on the VPS with today's 18:36 cycle).
With no run recorded the bench reads epoch, never "now".

Blocker 4: tx_executor logged the three keyed RPC URLs at start; hosts
only now. The keys themselves stay valid until rotated (Alchemy
dashboard, owner action: docker log history holds them).

Major 1: bridge_exec_latency_ms carries a method label (watch,
watch-broadcast, blocks, poll); the fallback counter counts every
non-watch method with the same label; the spec says so. Solana source
inclusion is stamped from `processed` so a relayer acting on processed
cannot credit before our stamp and push the leg to the broadcast
fallback.
Major 2: stuck deposits enter the success denominator and n; FAQ and
outcome bullet updated.
Major 3: Near Intents sets QuoteFeeUSD from the 1Click quote, and the
slippage gauge is published only when a quoted fee exists (it was the
whole realized fee before).
Major 5: "Realized fee" panel (ocb:bridge_fees_usd:avg_7d) on both
benches, amount sent minus amount received on-chain.
Minors: cohort named as four in title, description and intro; findings
wording; shortHash guard on the success log line; histogram help text.

Deployed: rules reloaded on ocb-prom (promtool: 13 rules), harness
rebuilt (log shows hosts only, last-execution times restored), 7-day
recording series present for the 12 corridors. validate 236, tsc, bun
test 255, go vet/build/test.


Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…x), not the raw unix time; prom.scalar keeps 6 significant digits and rounded 18:36:50 to 17:46:40 (#2530)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…sell straight through Uniswap, 2 of 2 sellers among 14 recent buyers, the rest still holding): the hold is permanent, the copy says so (#2531)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ies now aggregate the recorded cells, region pinned to EU-West, meme route and execution-path quotes excluded, mean fixed, Mobula timed like the others and keyed by header, Near Intents' fixed 3 s wait disclosed (#2532)

ocb-bench-audit on bridge-quote-latency-solana (and confirmed on the
production bridge-quote-latency page):

- Blocker: the recording rules keep (bridge, region, chain, amount_usd)
  and the spec queries selected on bridge only, so
  histogram_quantile(...{bridge="mobula"}) returned 39 series and
  prom.scalar took result[0], which Prometheus orders by Go map
  iteration. The live production page read Mobula p50 31 / p90 57 /
  p99 4172 ms and Near Intents p99 108 below p90 4700: a different cell
  on every materialization. Every p50/p90/p99 query is now
  histogram_quantile(q, sum by (le) (...)), mean is
  sum(rate_sum)/sum(rate_count) (the previous clamp_min(count_rate, 1)
  floored a per-second rate to 1 and printed ms per second, 300x too
  small), success is avg(...), n is round(sum(increase)). Verified on
  the VPS Prometheus: one series, Mobula 43.7 / 345.8 / 982.6 ms, mean
  118.3.
- Region pinned to eu-west on every headline query: the us-east probe is
  live (the copy said paused) and was part of the random draw; sgp is
  down. Copy corrected on both specs.
- Rules (infrastructure/monitoring/prometheus/recording_rules/
  ocb_bridge_quote.yml, source of truth for the VPS file that was only
  on the host, and ocb_bridge_quote_solana.yml) exclude the R4 TRUMP to
  BRETT meme route the same loop quotes (it pooled a cross-asset swap
  into the Base USDC cells: Mobula 34.6 ms USDC-only vs 139.3 pooled)
  and the $3 / $30 execution-path quotes.
- Harness: execution-path quote latency goes to its own histogram
  (bridge_exec_quote_latency_ms); Mobula's stopwatch stops after the
  body is read like the five other providers; the Mobula key travels in
  the Authorization header instead of the query string (a transport
  error wrapped the full URL into the log and Slack); the quote
  histogram gains 500 ms buckets between 1 and 5 s.
- Near Intents: its dry quote waits a fixed 3 s solver window
  (quoteWaitingTimeMs: 3000), so its row measures that wait; disclosed
  in the methodology and the finding, the "bimodal, sub-100 ms" claim
  removed. Robinhood coverage bullet (four providers quote it now) and
  the Across / Near Intents coverage (Base and Arbitrum only, our maps)
  corrected.

Deployed: rules reloaded (promtool 6 + 5), harness rebuilt, Mobula
quotes verified with header auth. validate 236, go vet/build/test.


Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…finition (ticket minus quoted output), realized cost published only from the on-chain read, realized fee in bps of the ticket from an execution-only metric, stale threshold and window wording follow the spec, pre-pulse history purged (#2533)

ocb-bench-audit on bridge-realized-cost: NOT READY, 4 blockers, 7 majors.

- Blocker 4: Mobula's slippage was a constant negative offset at every
  ticket (-$0.0015 on Base at $3 and at $30) because its quoted fee summed
  TotalFeeUsd + GasFeeUsd, gas the realized fee (ticket minus landed) can
  never contain; Relay and LI.FI derived theirs from the output. Every
  bridge now uses ticket minus the output the quote promised
  (QuotedOutputUSD), so both sides of the subtraction are defined the same
  way. Gas we pay stays its own panel.
- Blocker 3 and major 2: the "Realized fee" panel read bridge_fees_usd,
  which the quote loop also writes at $5/$50/$300 and on off-triangle
  routes (LI.FI $0.417 shown against $0.032 executed), and the realized
  output panel was a ticket-mix number. New execution-only pulses
  bridge_exec_realized_fee_usd and bridge_exec_realized_fee_bps; the panel
  is "Realized fee (bps of ticket)"; the output panel is gone.
- Major 1 and 3: fee, output and slippage pulses are published only when
  the destination balance delta was read (RealizedOnChain); a failed leg
  no longer publishes the quote's projection as "landed" and a fallback
  is counted in bridge_realized_fallback_total instead of an exact zero.
- Blocker 1: the 7-day window still held the pre-pulse persistent samples
  (about 2,880 per old execution against 3 per new one), so no new
  execution could move a median before 2026-09-26. Deleted from
  Prometheus for the execution cost series and the retired 24h rules;
  the benches read empty until the 10:00 UTC cycle tomorrow.
- Major 4: LiveIndicator takes staleAfterSec from the bench
  (prometheus.expected_freshness_seconds, carried on Benchmark as
  expectedFreshnessSec), so a daily bench is not "Stale" 23 hours a day.
- Major 5: Benchmark.window (prometheus.window) drives the Results
  caption, the infobox "Leader (7d)" and the citation suffix instead of a
  hardcoded 24h.
- Copy: quoted-fee definition, gating, cohort of four, 7-day findings.

Rules reloaded (14), harness redeployed. validate 236, tsc, eslint, bun
test 255, go vet/build/test.


Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…LANA_RPC comma-separated, Helius appended, public node last; the next endpoint on a rate limit or a transport error instead of a sleep): production runs Chainstack's shared node first, Alchemy's free app for the overflow, Helius third; Robinhood Chain gets Chainstack behind QuickNode (#2535)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ghbour screen, no neighbourhood read when the exact mid is known), FAIL_SCAN_BLOCKS per chain, NATIVE_POLL_EVERY ticks; production moves to 150 draws a day per row, no sandwich, fail-rate blocks bnb 3 / base 2 / ethereum 1 / robinhood 0, EVM logs every 3 ticks: about 27,000 calls a day instead of 146,000 (#2536)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…te, not on a positive quoted fee (Mobula Sol to Base quoted the full ticket back and its +$0.003 slippage was skipped) (#2537)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…03 name the live leader and number; the fee FAQ and the three bridge answers drop the claims the harness never measured ($1000/$10000 buckets, 10x, 100 to 400 ms, three regions, Ethereum to Base); the USDC-to-Base answer reads the Sol to Base cell; answers get compare links and citation meta, bench pages and the /bridge hub list their answers; the hub hides region columns whose variant is stale (US/SGP showed 2026-09-09 figures) and shows an as-of line; products meta uses short bench labels; compare pages dedupe the FAQ, date from the newest run and carry the count in the title; ad hoc compare pairs enter the sitemap; validator lints answers placeholders and typed cohorts (#2538)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… metric ("faster on quote latency") instead of the lowercased bench title (#2539)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…channel, bench and harness health, Dune) (#2540)

* crm: internal dashboard on Railway (traffic from PostHog with an AI-referral channel, bench and harness health, Dune credits); a fixed list of 11 HogQL queries per hourly refresh writes a snapshot the pages read, so the PostHog query budget stays under 1 % of the organisation's 2400/hour

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

* crm, review round 1: crm/ excluded from the site's tsconfig and eslint (the root typecheck pulled it into the Vercel build) with its own CI job; sessions are random, signed with a separate secret, listed on the volume and revoked on logout, login limited per client; snapshot cache, refresh mutex and PostHog budget on globalThis with mtime re-reads (instrumentation and routes are separate bundler layers); history append-only and tolerant of a torn line; bench health from index.json so expired chain RPC benches show instead of vanishing; exact AI/search 7 d uniques in the KPIs; page and referrer rows ranked on either week so losses survive the LIMIT

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

* crm, review round 2: the login limiter keys on the last forwarded hop with a global cap and evicts idle keys; session writes serialised with unique temp files; one referrer rule for the SQL KPIs and the TS channel table (Google and Bing country hosts count as search on both sides); sitemap body parse guarded; Dune sub text keys on the recorded error

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

---------

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
)

* posthog: three custom events (outbound_click by delegated listener, copy with kind/bench, search with the query and the result picked) so the CRM measures what the traffic turns into; crm: Actions page (outbound hosts, copies per bench, search queries), four more HogQL queries per hourly refresh (15 total)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

* posthog events, review: config snippets on /mcp tagged mcp_config with their name, the badges catalog copy tagged embed with format and bench, track() typed per event, action labels rendered

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

---------

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ariable; vercel pull hands sensitive env vars back as the literal "[SENSITIVE]" and that string shipped as the PostHog token since 2026-08-24 (#2542)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… set (#2544)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…5 % of the org budget), manual cooldown 5 min, next refresh shown in the header (#2546)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…olumns and labels an unpublished row Filling (threshold wording) instead of Unresponsive (probe wording); the dense layout stays inside its card instead of bleeding 80 to 128 px past it; bench 268 opts in (#2548)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…), Web Vitals, time on page; site: not_found and search_no_result events (#2547)

* crm: Search Console (service account, clicks/impressions/CTR/position, opportunities), Vercel log drain receiver (AI crawlers by bot and section, search bots, 404s, API and llms.txt callers, cache ratio), Core Web Vitals p75, time on page by section, searches with no result; site: not_found and search_no_result events

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

* crm, review: 404 map capped on fold, merge and read; flush swaps the day out before writing and merges it back on failure; NEXT_MANUAL_SIG_HANDLE so the shutdown flush runs; content-length guard on the drain route; one status key for Search Console; page keys folded across www/http variants

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

---------

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ge (funding leg, on Ethereum via Relay, Base) instead of the internal slug (basedbot-funding, fomo-ethereum, binance-wallet-base) (#2549)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…etween the user's Solana and EVM wallets, both directions (18 Robinhood to Solana, 10 Solana to Robinhood in the last 50 requests), not a deposit mechanism to trade on Solana; spec, harness note, README, audit-table badge (#2550)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ws binance-wallet-bnb, -ethereum, -base showed the BW chip) (#2551)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ad of the 200 px PNG; same mark, sharp at every size (#2552)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ricing backend, GMX v2 oracle price API) instead of a Pyth Hermes proxy; hermes.pyth.network has answered 401 since 2026-08-27 and both rows were empty for 24 days; spec copy no longer assumes a near-zero deviation, it shows the measured one (#2553)

Claude-Session: https://claude.ai/code/session_01HJgbZCqjR4nvCfcJSzofbw

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…he final pool, terminal and network: routers' cuts, hop leftovers) instead of leaving it in Pool; pooled rows rank on the effective sample size; a pooled component the flow gate withholds is cleared; native fail rate from 20 sampled transactions; BasedBot's wallet set from both ends of every Relay leg; hub page cached 5 min; sampling-rate and coverage copy match production (#2554)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…hed rows (#2554 set it on the held branch only) (#2555)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ee breakdown: actual execution, else the quoted gas fee) is network cost; relay = fixed + price fees + the solver's spread (#2556)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… 0xdab3f5fc…, 15 bps, gas sponsored; Robinhood Chain, BNB, HyperEVM, Arc), rows pump-fun-<chain> pooled with its Solana row (#2557)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…elay reports minus the app-sponsored part (the quoted userPays overstated it: 0.204 vs 0.126 $ on a pump.fun buy) (#2558)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…riced (previous trade on the curve, quote = gas coin / stable / WETH / a route-bought token), ETH-quoted v4 pools priced as the gas coin when no ERC20 moved the quote, a launch's first buy rejected as launch_first_trade: Robinhood Chain draws priced 8 of 40 -> 33 of 35 fills (#2559)

Claude-Session: https://claude.ai/code/session_01L4rjxemTvgRwrCG6D2iK5D

Co-authored-by: Flotapponnier <florent@mobula.io>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant