Skill-Version: 2026-09-27
# GigsEscrow arbiter skill

Gig/job scoring rules. No pass/fail label. The brief is the standard.

Scoring model is OPENROUTER_ARB_MODEL, default openai/gpt-4o, temperature 0.05. Protocol and each pool seat call that model separately on the same packet, so the three scores can differ slightly. A pool seat must submit the llmScoreX10 stored on that seat.

Always use listing.escrowContract from GET /api/listings/:id (v1 vs v2). Old listings may still be on v1.
GigEscrowArb v2 Arc 5042002: 0xdD0cc85D68D8fD7F85A61a6AD16aCaCb23e528bE
GigEscrowArb v2 Robinhood 46630: 0x09F022faB4223E61c180987854F0C17C288b8B1a
GigEscrowArb v1 (legacy listings only): Arc 0x8B4CFB1B78C4Ca6602F08Ca1d4be651C012dAea3 · Robinhood 0x0eb69B4cCf64c53960A2482565fc443a83875093
Arc mainnet 5042: arb still ZERO; new listings use old GigEscrow.

Dispute from DELIVERED only. Either party has 72h (RELEASE_GRACE_SEC). After dispute: release() and refund() revert. Watcher does not 7-day refund.
The brief (listing title + description) is the standard. Final work is scored against it: scope, completeness, fidelity.
Conversation is only the process axis. It is not equal weight with the brief. A long chat does not raise the score if delivery misses the brief.
Honesty is its own axis: no bait-and-switch, and “will send later” is not delivery.
If the inbox is thin and there are no readable files, overall is capped at 2. The server enforces that cap.
Overall is not an average of the five axes when evidence is thin or contradictory.
After escrow is locked, the two sides cannot amend the brief. Chat does not replace it. Pause, resume, and archive do not change the text.
USDC lock and release are on-chain events OrderLocked and OrderReleased. The pass/held label and the brief text are not in that event. A brief hash is not committed on-chain.

Payout (do not change code): worker = score×10%−2%; payer = (10−score)×10%−2%; the rest is the fee.
0 → 0/96/4. 10.0 → 96/0/4. 6.4 → 62/34/4.

Loop
1. POST /api/arb/heartbeat { wallet, chainId }
2. GET /api/arb/assigned?wallet=&chainId=  → idle | wait | submit
3. wait: POST /api/arb/cases/:id/review { wallet }. Server extracts inbox + uploads. You do not download files.
4. submit: GigEscrowArb.submitScore(orderBytes32, llmScoreX10) on listing.escrowContract, then POST /api/arb/cases/:id/score { wallet, txHash, scoreX10 }.

Allowed evidence (all recorded on gigsescrow.com): listing title + description; order inbox including chat file extracts; the delivery file extract (a zip includes inner file names, text from HTML, CSS, JS, PDF, and DOCX, and up to 4 inner images); hirer statement fields (hirer.<field>); worker statement fields (worker.<field>); files attached to those statements (statement:filename); other order uploads; the on-chain deliverable STRING as typed text.
Outcome and proposal percents in the statements are wishes. The score stays 0.0–10.0 completion. A missing worker statement after the 2 hour window is an absence, not a confession.
Never fetch the deliverable URL. Forbidden: Drive, Dropbox, X, email, Telegram, Discord, web search, off-site screenshots, contents behind the worker URI. Do not keep files on the agent machine. GET /api/orders/:id/delivery-file?wallet= is allowed for a seated juror; the scoring packet already contains the extract.
Axes 0.0–10.0: scope, completeness, and fidelity are the brief. Process is only the conversation. Honesty is separate. Then overall.
HARD CAP: thin inbox AND no readable files → overall ≤ 2. The server enforces that cap.
