agents / @flop-lab/challenger
Challenge watcher
Suite entry: flop challenge. The README below lists the package options.
Reading progress
FLOP challenger
Is a settlement worth review and is its challenge window still open? Challenger ranks payouts and watches forced claims by their indexed end block. Each dossier carries verifier v2 checks, raw evidence and a content hash for offline replay. It never submits a dispute.
Quick start
From the repository root with Node 22 and pnpm. This reads a recorded tape without a wallet or API key:
pnpm install --frozen-lockfile
pnpm --filter @flop-lab/challenger build
node packages/challenger/dist/cli.js windows --recordedRead current data
node packages/challenger/dist/cli.js watch --limit 5
node packages/challenger/dist/cli.js watch --sort priority --json
node packages/challenger/dist/cli.js windows --jsonThe binary is flop-challenger. The direct Node command works from a checkout without a global install.
This private workspace package imports the shared MCP and verifier source directly, matching the existing package layout. The suite also exposes flop challenge. No second MCP client is implemented.
Build a dossier for the channel in the recorded sample:
node packages/challenger/dist/cli.js dossier 0xa5d0a1722a5c7b8b86d7489ff1e76d0c3eb0a72e39e9c47edee1681ef766deec --recorded --jsonUse an exact channel ID from watch or windows for a live dossier. --recorded does not access the network. Recorded verifier bundles cover the example payout and one open forced claim. Other recorded channels attach an empty bundle and report unavailable checks.
Export a forced claim and replay it offline:
node packages/challenger/dist/cli.js dossier 0x161ebefffec5b47ef34c74a1a2c4f2003918fa569f566a242ee3eeac276bae14 --recorded --json > dossier.json
node packages/challenger/dist/cli.js replay dossier.json
node packages/challenger/dist/cli.js dossier 0x161ebefffec5b47ef34c74a1a2c4f2003918fa569f566a242ee3eeac276bae14 --recorded > dossier.mdReplay exits with the verifier result: 0 for complete passing checks, 1 for failed checks and 3 for incomplete evidence. The recorded forced claim exits 3. The dossier hash can match while proof remains unavailable.
watch reads one snapshot. It does not run a background loop. The output prints its source, observation times, evaluation time, coverage and request count. --limit affects display only. Ranking uses the retrieved cohort.
Import
import { Watcher, analyze, draftDossier } from "@flop-lab/challenger";
import { McpClient } from "@flop-lab/mcp";
const client = new McpClient({ retries: 1 });
const watcher = new Watcher(client);
const report = analyze(await watcher.read(), Date.now());
const first = report.rows[0];
if (first) {
const dossier = await draftDossier(report, first.settlement.channelId, client);
console.log(dossier.mode, dossier.checks);
}Exact block windows
The published SDK 0.4.0 chain wrapper documents cooperative settle as immediate payout with no standard dispute window. forceSettle emits SettlementPosted with challengeEnd. finalize pays after that window closes. The broader challenge-design page describes other audit lanes but does not establish their availability for a tape row.
Cooperative computeChannel.Settled rows therefore show no-standard-window with no invented expiry. Non-cooperative final payouts show unknown because the posting time is missing. A final payout does not start a new window.
The pinned protocol parameter file, recorded at 2026-11-06T03:49:31.027Z, defines channel_dispute_window_blocks:
on_chain: {constants: [ComputeChannel.DisputeWindow]}
value: 604_800
unit: blocksThe calculation uses the channel's explicit challengeEnd, not its last status update block. Remaining blocks are max(0, challengeEnd - finalizedBlock). Positive remaining blocks are open. The final 7200 blocks are closing under this tool's attention policy. That threshold is not a protocol response deadline. Zero remaining blocks are closed. Equality is conservatively treated as closed because the exact runtime endpoint inclusion rule is not established by the public parameter file. Closed does not mean finalized payment.
The pinned paper section 12.1g requires finalized-prefix deadlines and freezing during finality stalls. Missing reported finality stays unknown. Best head is never substituted. Reported safe mode suppresses time extrapolation. A deployed runtime constant and finality proof remain unverified.
Estimated time remaining is remainingBlocks * (lastTimestamp - firstTimestamp) / (lastHeight - firstHeight). The estimate is anchored at the head's capture time. It is never advanced using the viewer's clock. Missing or invalid cadence leaves time unavailable without discarding the block result. Documentation is not a live runtime observation. The capacity-bond revocation window is a different parameter and is not used here.
Forced claims sort closing, open, unknown then closed, with end block as the tie-breaker. The payout tape retains its separate review score. A posting timestamp alone no longer creates a seven-day wall-clock estimate.
Review formula
These weights are review policy choices, not measured probabilities. The score sums available components without renormalizing. Ratio components are truncated to two decimal places using integer arithmetic. Amounts and decimal prices never pass through floating-point conversion before comparison.
| Signal | Points | Observed inputs |
|---|---|---|
| Payment exposure | 25 * minerPaid / max(minerPaid) | Retrieved tape. Miner stake is not available. |
| Non-cooperative settlement | 20 if cooperative = false, else 0 | Settlement row. No fraud inference. |
| Unused escrow | 15 * unusedEscrow / escrow | Unavailable when escrow is zero or unused exceeds escrow. |
| Reported assurance | Soft: 10. Hard: 0. Other: unavailable. | Reported tier only. |
| Miner history | 15 * priorNonCooperative / priorCount | Same miner, earlier block and no later timestamp. Excludes current channel. Unavailable without history. |
| Price outlier | 15 if price exceeds twice the upper median, else 0 | At least three other nonzero-compute rows matching model, tier, market and GPU SKU, including null SKU. Unavailable for zero median or zero current compute. |
Payment exposure is unavailable when all observed payments are zero. A missing model or tier makes the price cohort unavailable. Price comparison uses the full retrieved tape, not a historical backtest.
Confidence is the count of available signals out of the defined signals plus tape completeness. It is field coverage, not statistical confidence. Missing data is visible and earns no points. A low score with missing data does not mean low risk. The tool has no slashing-history feed.
Evidence and feasibility
Dossiers include the raw settlement row when present, a verifier v2 bundle and its replayed report. Checks include exact arithmetic, indexer cross-view agreement, receipt links, quote envelopes, declared digests and TCB bindings when evidence exists. Missing attestation or receipt bytes remain unverifiable. Simulated service output never becomes proof. Unpaid forced claims have no invented payout or review score.
JSON exports hash canonical UTF-8 JSON with sorted object keys, excluding only the top-level sha256 field. Markdown includes the same hash and complete JSON attachment. replayDossier() checks the outer hash, observation hashes, channel binding, verifier results and block-window replay without network access. Hashes detect edits relative to the recorded hash; anyone can reseal altered content. They do not authenticate its author or the upstream source. Legacy review-score fields are preserved under the hash but are not recomputed by replay.
The SDK defines DA transcript encoding, TOPLOC checker interfaces, bisection helpers and DisputeEvidence. The selected public channel does not supply the required per-turn inputs. DA retrieval, prefill reproduction, TOPLOC comparison, signed-turn evidence, finality and caller eligibility remain explicitly unverifiable.
Dossiers name the documented validator-quorum call computeChannel.reportToplocMismatch(channelId, miner, attestations) as a reference. No attestation bundle is available and no call is constructed. The discretionary open_dispute signature is not exposed by the inspected chain wrapper. Its documented 100 FLOP bond is a separate lane and can be forfeited if frivolous. Its live value is not verified. The executable extrinsic remains null. See FEASIBILITY.md.
Data, cost and tests
The web workbench is at /challenger. It shows a scroll-linked closing timeline with filters, a separate payout tape, verifier-backed dossiers and local replay. See the page README for cache and request limits.
Raw SSE fixtures are in fixtures/. The tools response uses lossless base64 transport encoding to retain its original punctuation without changing bytes. manifest.json records the exact requests and UTC capture times from 2026-11-05T09:00:00.819Z through 09:00:03.613Z. The recorded tape has 336 rows across four pages. All are cooperative payouts. None establishes a standard dispute window. The two recorded blocks span 100 intervals and 102000 milliseconds, giving 1020 milliseconds per interval. These are indexer observations at capture time. fixtures/sdk/ preserves the inspected SDK declarations and chain implementation with hashes and retrieval times.
fixtures/windows/ retains the parameter source, introspected channel schema, forced claims, recent blocks and verifier bundles. The window capture at 2026-11-06T03:52:08.729Z observed 10 forced claims: 3 open and 7 closed against reported finalized head 3013999. It used 4 HTTP attempts. The block sample spans 100 intervals and measured 1000 ms per block. The complete window and two-bundle recording used 17 HTTP attempts with no retries. These are capture facts, not current network claims.
Tape collection defaults to at most 1000 rows in pages of at most 100, plus stats and two blocks. Window collection reads at most 100 forced claims, a finalized head and two blocks. Truncation is explicit. Verifier collection reads at most 100 matching-agent settlement rows and the bounded v2 evidence set. The shared client spaces requests and backs off on 429 or 5xx. The default watcher allows one retry. There is no failure polling loop.
Watcher shares concurrent reads and caches snapshots or failures for 60000 milliseconds after collection ends. Cached data keeps its original timestamps. There is no disk cache. Pagination is not atomic. Duplicates, changing totals, limits and empty pages that claim more data mark coverage partial. Malformed required rows fail the read. A cadence failure leaves the tape usable with a warning.
pnpm --filter @flop-lab/challenger check
FLOP_LIVE=1 pnpm --filter @flop-lab/challenger exec vitest run test/live.test.tsThe live check skips when the endpoint is unavailable. Fixture tests cover boundaries, hostile inputs, exact decimal thresholds, missing evidence, unstable pagination and cache behavior. pnpm --filter @flop-lab/challenger record deliberately refreshes the recorded public fixtures. It makes bounded read-only calls.
What this does not verify
This tool does not establish fraud, runtime challengeability, exact endpoint inclusion, finalized inclusion, caller eligibility, current bond requirements, miner stake, hardware authenticity or inference correctness. It does not retrieve DA audit blobs, re-run a prefill, compare TOPLOC fingerprints or perform bisection. It never submits a dispute. Public views share infrastructure and captures are non-atomic. The indexer can be stale and devnet can reset. A block classification is conditional on its observations. A time estimate is not a safe filing deadline.