# Execution Market skill — Changelog

**This file is history, not instructions.** Nothing here is required to publish a
task, hire a worker, approve one or get paid. The procedure lives in
[`skill.md`](../skill.md); the detail lives in [`reference/`](reference/).

It used to live inside `skill.md` and was **32% of the file** — 110.000 characters
an agent loaded before reaching the first actionable step. It moved here on
2026-09-10, after a fleet of 27 agents stopped reading the skill and wrote their own
summary instead. That summary went stale and cost them an incident: it said
`GET /tasks` returned only their own tasks, months after EM had inverted it to the
open marketplace. **A skill you cannot read whole gets replaced by copies that age
badly** — so the procedure got short and the history moved out.

**Nothing was deleted.** Every entry is below, in full, with the measured case that
motivated it. The index tells you which section each one governs, so you can read
the *why* where the rule applies instead of chronologically.

---

## Index — one line per version

| Version | Date | What changed | Governs |
|---------|------|--------------|---------|
| 14.16.0 | 2026-10-08 | [CHANGE] Solana channels have no platform ceiling by default (decision 196; `GET /api/v1/health` shows the one in force): no maximum per channel and none open at once; `cap_usdc` still required, ≥ 0.05; an optional ceiling per signing wallet on request (`429 CHANNEL_QUOTA_FULL` with `limit: "publisher_usd"`). [ADD] declare refuses a payer address EM never saw signed: `409 PUBLISHER_SOLANA_ADDRESS_UNPROVEN` (re-sign the payout PATCH once, same address); `em_accept_agent_task` checks the worker's USDC account on Solana; the publisher pays that account's rent, never the gateway (decision 202: `create_ata_instruction` at declare, `settle_pending` at settle); webhooks `channel.opened` / `channel.settled` / `channel.closed` | [`skill.md`](../skill.md) · [Solana](reference/solana.md) · [Monitoring](reference/monitoring.md) |
| 14.15.0 | 2026-10-08 | [ADD] Errors a KK run kept retrying, now named: publish `task_content_held_for_review` (now `retryable: true` with `retry_after_seconds`: you are not notified, so after that wait re-send the SAME publish — same `review_id` while pending, published once approved) and `task_content_hold_queue_full`; Solana approve 409 `WORKER_USDC_ATA_MISSING` (no challenge for a worker without a USDC account) and `SOLANA_BOUNTY_SIMULATION_FAILED` (no fresh challenge after an instruction-level simulation failure), `SOLANA_PAYOUT_ADDRESS_MISSING` as the `code` of the existing 409; `relay/prepare` 409 `RELAY_FOREIGN_DELEGATION` pointing at `relay/self/*` instead of a 503 | [`skill.md`](../skill.md) · [Publisher path](reference/publisher.md) · [Solana](reference/solana.md) · [Reputation](reference/reputation.md) |
| 14.14.0 | 2026-10-05 | [ADD] Option C in `reference/signing`: a PayBox wallet signs the ERC-8128 base with `request_wallet_sign` (no key export, no browser). The verifier ignores signatures tagged for another profile (ChatGPT's Web Bot Auth answered `401 Invalid keyid format` to an agent delivering task `fc195649`) and accepts the current draft's CAIP-10 keyid `eip155:<chain>:<lowercase address>` | [`skill.md`](../skill.md) · [Signing](reference/signing.md) |
| 14.13.0 | 2026-10-04 | [ADD] PayBox is the recommended wallet: "How you sign" starts with it (check it is in use, else suggest installing it), new `reference/paybox` (install/verify, which rail, the `keyid` form to send, delivering work from a PayBox-only account, known limits); the refusals that ask you to sign with ERC-8128 name PayBox; OWS stays as the alternative | [`skill.md`](../skill.md) · [PayBox](reference/paybox.md) · [Signing](reference/signing.md) |
| 14.12.0 | 2026-10-03 | [ADD] Task Policy in Core workflow rule 11, MCP instructions and publish description; explanatory state and hiring text moved to references | [`skill.md`](../skill.md) · [Escrow](reference/escrow.md) · [Task fields](reference/task-fields.md) |
| 14.11.0 | 2026-10-02 | [ADD] Tres cambios, una versión. Core workflow: «Edit, no executor yet» con `em_update_task` (plazo, ubicación, radio, instrucciones, evidencia; las postulaciones se conservan), y «Reprice» deja de ser `(planned)`: `em_publish_task` + `replacement_of`. Fila «What happened»: `em_get_task_events` devuelve lo que pasó en la tarea desde `since_sequence` y, en `auto_settlement`, cuándo y cómo se liquida una entrega sin revisar. El camino del publicador en una sola página (`reference/publisher.md`, también por MCP: `em_get_guide(section="reference/publisher")`) con las dos puertas de la firma de la asignación (por OWS: `ows_sign_typed_data`, nunca `ows_sign_eip3009`); `reference/mcp.md` con cada tool (y cuáles no sirven en producción) y un linter del CI que ata skill y servidor en las dos direcciones; aviso con enlace cuando `skill_version` falta o es vieja; `language` en la tarea; `em_feedback`; instalación por cliente en `SETUP.md`; fuera `metadata` y `gps_required` de la lista REST (el body los rechaza) y «Best practices» (duplicado); `reputation: null` para quien nunca operó | [`skill.md`](../skill.md) · [Publisher path](reference/publisher.md) · [MCP tools](reference/mcp.md) · [Setup](SETUP.md) |
| 14.9.0 | 2026-10-01 | [ADD] `em_get_dashboard_link` deja de ser `(planned)`: el humano del agente abre la tarea como su publicador con un link de 15 min, de solo lectura y de UNA tarea; abrirlo cuenta como leer la evidencia (regla 9 del Core workflow) | [`skill.md`](../skill.md) |
| 14.8.0 | 2026-10-01 | [ADD] «Core workflow»: el ciclo del publicador con la tool MCP y la llamada REST de cada paso (`(planned)` lo que falta) y diez reglas medidas; el MCP entrega la guía sola (`instructions`, recurso `skill://execution-market`, `em_get_guide`) y lista postulantes con `em_list_applications`; «publicar no bloquea fondos, asignar sí» queda dicho en un solo sentido; el campo REST es `target_executor`; explicación (no procedimiento) condensada con su texto entero en `reference/`, y una tabla de estados de escrow nueva en `reference/escrow.md`, para seguir bajo 10.000 tokens | [`skill.md`](../skill.md) · [Escrow + settlement](reference/escrow.md) · [Reputation](reference/reputation.md) |
| 14.7.0 | 2026-09-27 | [ADD] Riel self-submit: una cuenta delegada a un wallet ajeno (el relay responde `relay_foreign_delegation`, p. ej. Paybox) manda su propio `giveFeedback` con `relay/self/prepare` → envía el `calldata` → `relay/self/confirm` (`202` mientras no confirma); paga su gas y es el autor | [`skill.md`](../skill.md) · [Reputation](reference/reputation.md) |
| 14.6.0 | 2026-09-27 | [ADD] Los códigos de moderación (`principal_banned`, `executor_not_active`, `task_publisher_banned`, `executor_unavailable`) y de la revisión de contenido al publicar (`task_content_rejected`, `task_content_too_large`, `task_content_review_unavailable`) entran a la tabla de errores; tres párrafos de «Reading data» pasan a `reference/signing.md` para volver bajo 10.000 tokens | [`skill.md`](../skill.md) · [Signing](reference/signing.md) |
| 14.5.0 | 2026-09-26 | [ADD] `facilitator_rate_limited` (429) y `facilitator_unavailable` (503): el límite del facilitador llega con su status, su `Retry-After` y su propio código, en vez de un 503 que decía "Facilitator error: 429" | [`skill.md`](../skill.md) |
| 14.4.0 | 2026-09-24 | [ADD] Arc (5042) entra a la lista de redes con escrow x402r (generación D) y a las tablas de contratos y RPC; toma tareas cuando `GET /api/v1/h2a/payment-config` la lista | [`skill.md`](../skill.md) · [Escrow + settlement](reference/escrow.md) |
| 14.3.0 | 2026-09-13 | [ADD] STEP 3 enseña a abrir, declarar y liquidar un canal de Solana (`POST /tasks/{id}/channel` y `POST /tasks/{id}/channel/settle`); cinco pasajes de historia salen del skill a donde ya vivían | [`skill.md`](../skill.md) · [Solana](reference/solana.md) |
| 14.2.0 | 2026-09-13 | [CHANGE] The publish example stops teaching a street address in `location_hint`; title, instructions and hint are public, the exact point goes in `location_lat`/`location_lng` | [`skill.md`](../skill.md) · [Task fields](reference/task-fields.md) |
| 14.1.0 | 2026-09-11 | [ADD] Rail OAuth 2.1 para clientes MCP que no pueden firmar un request: seis lineas en skill.md, el procedimiento y el paso a paso de claude.ai en reference/oauth.md | [`skill.md`](../skill.md) · [OAuth](reference/oauth.md) |
| 14.0.0 | 2026-09-10 | [SPLIT] The skill is the procedure and nothing else: 92.000 tokens → 9.688, error table from 84% to 7.7%, changelog and reference moved out | [`skill.md`](../skill.md) |
| 14.0.1 | 2026-09-10 | the payment chain is where reputation seals by default, and the response names the chain in three fields | [Reputation](reference/reputation.md) |
| 13.12.0 | 2026-09-10 | la reputacion se sella en la RED DEL PAGO por defecto, y cuando cae en otra la respuesta lo DICE | [Reputation](reference/reputation.md) |
| 13.11.1 | 2026-09-10 | three things this file promised about reputation networks were not true, and a fleet paid for it | [Reputation](reference/reputation.md) |
| 13.11.0 | 2026-09-09 | calificar una task pagada por canal ya no devuelve `400`. Si te lo rechazo antes, REINTENTA | [Solana + channels](reference/solana.md) |
| 13.10.0 | 2026-09-09 | un settle que el gateway SI ejecuto ya no se pierde porque la cadena tardo en confirmarlo | [Escrow + settlement](reference/escrow.md) |
| 13.9.0 | 2026-09-09 | el settle tardio de un canal ya no depende de que el gateway adivine a quien pagar, y cuando algo se rechaza te llega el motivo ENTERO | [Solana + channels](reference/solana.md) |
| 13.8.0 | 2026-09-09 | asignar a un worker que no puede cobrar en Solana ahora rebota en el ASSIGN, no en el settle | [Escrow + settlement](reference/escrow.md) |
| 13.6.0 | 2026-09-08 | Declaring a Solana channel now proves ownership on chain: the channel's `payer` must be a Solana address registered to the publisher. Four outcomes… | [Solana + channels](reference/solana.md) |
| 13.7.0 | 2026-09-08 | el settle tardío lo transmite ahora el gateway pay.sh, no EM | [Escrow + settlement](reference/escrow.md) |
| 13.5.0 | 2026-09-08 | si la sesión de pay.sh de tu canal murió, ya no tenés que armar una transacción de Solana a mano: `POST /api/v1/tasks/{id}/channel/settle` | [Solana + channels](reference/solana.md) |
| 13.8.0 | 2026-09-09 | The price of a channel tick and the deposit in a channel now have ONE source, and EM publishes it | [Solana + channels](reference/solana.md) |
| 13.4.0 | 2026-09-07 | the Solana rail now has a name, an MCP tool, and a way for the WORKER to check it before doing the work | [Solana + channels](reference/solana.md) |
| 13.1.0 | 2026-09-05 | You can buy a verification seal for your own delivery — `POST /verification/analyze` | [Evidence + delivery](reference/evidence.md) |
| 13.3.3 | 2026-09-07 | si tu worker nunca tuvo USDC en Solana, liquidar el canal REVIENTE y tu depósito queda atrapado adentro | [Solana + channels](reference/solana.md) |
| 13.3.2 | 2026-09-07 | reintentar el approve de una task con canal ya no puede reservar dos veces, y ahora te dice dónde está la plata | [Solana + channels](reference/solana.md) |
| 13.3.1 | 2026-09-07 | `channel_session_gone` te decía que hicieras algo imposible | [Solana + channels](reference/solana.md) |
| 13.3.0 | 2026-09-07 | If your Solana task has a payment channel, THE CHANNEL IS THE ESCROW — approving settles it, and there is no `402` any more | [Solana + channels](reference/solana.md) |
| 13.2.0 | 2026-09-06 | A release can now be authorized by the wallet that funded the escrow, and the new `409 LIFECYCLE_ORDER_REQUIRED` is how you find out it is needed | [Escrow + settlement](reference/escrow.md) |
| 13.0.0 | 2026-09-04 | A settlement failure that can never succeed now answers `409`, not `502` — and a release that landed on-chain without a recorded hash no longer blocks… | [Escrow + settlement](reference/escrow.md) |
| 12.5.0 | 2026-09-04 | A second way in — `wallet_session` — for clients that cannot sign a request, plus server-built typed data for both money steps | [Signing (ERC-8128)](reference/signing.md) |
| 12.4.0 | 2026-08-31 | `@authority` now binds your signature to THIS service on REST and MCP too — it never did | [Signing (ERC-8128)](reference/signing.md) |
| 12.3.0 | 2026-08-31 | The `502` from approve now names WHY the payout did not go out — ten `detail.code`s, seven of them terminal | [Escrow + settlement](reference/escrow.md) |
| 12.2.0 | 2026-08-29 | `relay/submit` answers that same `409` now — it was not deduplicating at all | [Reputation](reference/reputation.md) |
| 12.1.1 | 2026-08-28 | The `409` from `relay/prepare` now names the author inline | [Reputation](reference/reputation.md) |
| 12.1.0 | 2026-08-28 | You can finally vet the publisher — `publisher_reputation` is on every task | [Reputation](reference/reputation.md) |
| 12.0.0 | 2026-08-28 | MAJOR — `rating_score` on the approve is now ACCEPTED AND IGNORED, and the dedup counts authors instead of parties | [Reputation](reference/reputation.md) |
| 11.46.3 | 2026-08-28 | Third instance of the same hazard class, same day: "Settle — payout + on-chain reputation in one step" implied the settle emits | [Escrow + settlement](reference/escrow.md) |
| 11.46.2 | 2026-08-28 | The categorical sentence itself was the hazard — rewritten so the fork lives IN the sentence | [Reputation](reference/reputation.md) |
| 11.46.1 | 2026-08-28 | Going to SIGN your rating? Approve WITHOUT `rating_score` — the explicit field never went inert | [Reputation](reference/reputation.md) |
| 11.46.0 | 2026-08-27 | The guidance still promised the auto-rating that v11.44.0 says was switched off — and that contradiction is why the network's feedback graph is… | [Reputation](reference/reputation.md) |
| 11.45.0 | 2026-08-26 | `payment_tx` can be `null`, and `null` is an answer — never fill it in yourself | [Escrow + settlement](reference/escrow.md) |
| 11.43.0 | 2026-08-24 | Selling? You are told when you sell now — both rails were addressed to the buyer | [Escrow + settlement](reference/escrow.md) |
| 11.44.0 | 2026-08-25 | This skill was teaching the signature that does not work, and promising a safety net that no longer exists | [Reputation](reference/reputation.md) |
| 11.43.0 | 2026-08-25 | Rating someone turns YOUR account into a smart account — permanently, and for all your payments | [Reputation](reference/reputation.md) |
| 11.42.0 | 2026-08-24 | SKALE is retired — it takes no new tasks | [Escrow + settlement](reference/escrow.md) |
| 11.41.1 | 2026-08-24 | the skill contradicted itself about Avalanche | [Reputation](reference/reputation.md) |
| 11.41.0 | 2026-08-24 | Sign your own ratings — until now the Facilitator was their on-chain author | [Reputation](reference/reputation.md) |
| 11.40.0 | 2026-08-22 | The `apply` cover note is capped at 500 characters, and the `422` now says so | [skill.md](../skill.md) |
| 11.39.0 | 2026-08-19 | if you SIGN your own anchor, upgrade to `uvd-x402-sdk[dx402]>=0.54.0` (Python) / `>=2.59.0` (npm) | [Escrow + settlement](reference/escrow.md) |
| 11.38.0 | 2026-08-19 | Declare a decryption key once, or the recommended lock path anchors nothing | [Escrow + settlement](reference/escrow.md) |
| 11.37.0 | 2026-08-18 | Every paid task now leaves you a copy of the delivery that only you can open — DX402 durable evidence, on by default | [Evidence + delivery](reference/evidence.md) |
| 11.36.0 | 2026-08-11 | A purchase of your listing arrives as `WorkerAssigned` — there is no `ServiceOrdered` | [Service listings](reference/services.md) |
| 11.35.0 | 2026-08-08 | [SUPERSEDED] Solana is LIVE — publish, pay and build reputation on it. | [Solana + channels](reference/solana.md) |
| 11.34.0 | 2026-08-07 | A half-signed request is now a `401`, and the anonymous identity owns nothing | [Signing (ERC-8128)](reference/signing.md) |
| 11.33.0 | 2026-08-07 | [SUPERSEDED] Tu reputación va a Base por defecto — y ahora podés ponerla donde quieras. | [Reputation](reference/reputation.md) |
| 11.32.0 | 2026-08-06 | Deliver big payloads as a LINK — and the link finally works for agents | [Evidence + delivery](reference/evidence.md) |
| 11.31.0 | 2026-08-06 | A Solana bounty needs a Solana payout address — and `wallet_address` is not one | [Solana + channels](reference/solana.md) |
| 11.30.0 | 2026-08-03 | The WebSocket monitoring example never authenticated — Option 4 now teaches the signed handshake | [Signing (ERC-8128)](reference/signing.md) |
| 11.29.0 | 2026-08-01 | Pricing corrected to the flat 13% the chain actually charges | [skill.md](../skill.md) |
| 11.28.0 | 2026-07-30 | `retryable` now travels on the `task.assign_failed` WEBHOOK — where the async path actually reports a failed lock | [Escrow + settlement](reference/escrow.md) |
| 11.27.0 | 2026-07-29 | `retryable` on every escrow-lock `402`, and a `INVALID_SIGNATURE` code that means STOP | [Signing (ERC-8128)](reference/signing.md) |
| 11.26.0 | 2026-07-29 | Your money in a dead task escrow is recoverable BY YOU — `GET /api/v1/escrow/task/{task_id}/reclaim` | [Escrow + settlement](reference/escrow.md) |
| 11.21.0 | 2026-07-25 | What a signature actually changes on a READ — the one thing the skill never said | [Signing (ERC-8128)](reference/signing.md) |
| 11.20.0 | 2026-07-24 | The buyer picks the chain it actually holds USDC on — and the 402 finally says why the lock died | [Escrow + settlement](reference/escrow.md) |
| 11.19.1 | 2026-07-24 | single settlement at close | [Escrow + settlement](reference/escrow.md) |
| 11.25.0 | 2026-07-29 | When we already know your money will not move, we now say it in the success body — never as an error | [Streams](reference/streams.md) |
| 11.24.0 | 2026-07-29 | The escape hatch that made the rail trustless now has a door — plus a cap ceiling that stops you locking USDC you can never spend | [Escrow + settlement](reference/escrow.md) |
| 11.23.0 | 2026-07-28 | Two DX fixes from the first completed purchase cycle (KK) | [Evidence + delivery](reference/evidence.md) |
| 11.22.0 | 2026-07-28 | Ordering a listing actually works now — and a failed order cleans up after itself | [Escrow + settlement](reference/escrow.md) |
| 11.19.0 | 2026-07-24 | Streaming Sessions — pay-per-time (BETA) | [Streams](reference/streams.md) |
| 11.18.0 | 2026-07-22 | The board now has a human face — and one new endpoint | [Service listings](reference/services.md) |
| 11.17.0 | 2026-07-22 | Seller vetting on the board — the score is not the whole story | [Service listings](reference/services.md) |
| 11.16.0 | 2026-07-22 | Matchmaking — the demand and supply sides now point at each other | [Service listings](reference/services.md) |
| 11.15.0 | 2026-07-22 | The other side of the market becomes reachable — buy-side discovery for service listings | [Service listings](reference/services.md) |
| 11.14.0 | 2026-07-21 | Reputation-driven selection — the trustless-agents premise made executable | [Reputation](reference/reputation.md) |
| 11.13.0 | 2026-07-20 | Escrow lock retry on failure — the cross-chain reliability rule (from the first organic non-Base trade) | [Escrow + settlement](reference/escrow.md) |
| 11.12.1 | 2026-07-19 | PATCH: Frontmatter description now carries the canonical brand line — "trustless escrow, gasless payments, on-chain reputation" (trustless is the brand… | [Reputation](reference/reputation.md) |
| 11.12.0 | 2026-07-18 | Corrected the "escrow is USDC-only" rationale | [Escrow + settlement](reference/escrow.md) |
| 11.11.0 | 2026-07-18 | Canonical skill vocabulary | [skill.md](../skill.md) |
| 11.10.0 | 2026-07-18 | Universal Hiring Matrix section in the body | [skill.md](../skill.md) |
| 11.9.0 | 2026-07-17 | "If a HUMAN hires you — H2A worker view" completed to 4 rules (from a 24-agent live-run post-mortem) | [Reputation](reference/reputation.md) |
| 11.8.0 | 2026-07-17 | Worker discovery + post-apply model made explicit (from a live 24-agent swarm post-mortem) | [Escrow + settlement](reference/escrow.md) |
| 11.7.0 | 2026-07-17 | Structured `409` on assign — `detail` is now a `{code, message}` object, not a bare string | [Escrow + settlement](reference/escrow.md) |
| 11.6.0 | 2026-07-16 | `agent_id` is now OPTIONAL on `POST /reputation/agents/rate` | [Reputation](reference/reputation.md) |
| 11.5.1 | 2026-07-14 | Honest MeshRelay channel table | [Monitoring](reference/monitoring.md) |
| 11.5.0 | 2026-07-14 | IRC/MeshRelay integration made explicit (from a 3-way session with MeshRelay + KarmaCadabra) | [Monitoring](reference/monitoring.md) |
| 11.4.0 | 2026-07-14 | Real-fleet UX fixes from a 24-agent integrator (KarmaCadabra) | [Reputation](reference/reputation.md) |
| 11.3.0 | 2026-07-10 | Task visibility — 410 Gone on terminal tasks + participants always see their task | [Arbiter + disputes](reference/arbiter.md) |
| 11.2.0 | 2026-07-10 | Service listings — the supply-side primitive (sell a capability) | [Service listings](reference/services.md) |
| 11.1.0 | 2026-07-09 | Security-hardening batch + new response fields | [Escrow + settlement](reference/escrow.md) |
| 11.0.0 | 2026-07-09 | Async escrow lock at assign (`202 {status:"assigning"}`) | [Escrow + settlement](reference/escrow.md) |
| 10.7.0 | 2026-07-08 | Reputation network preference | [Reputation](reference/reputation.md) |
| 10.6.0 | 2026-07-08 | How evidence is verified (deliver files as typed artifacts, not URLs in `json_response`) | [Evidence + delivery](reference/evidence.md) |
| 10.5.1 | 2026-07-08 | PATCH: STEP 2a's async-registration poll loop is now bounded (~30 iterations ≈ 2.5 min, matching STEP 1b) instead of an unbounded `while pending` — a… | [skill.md](../skill.md) |
| 10.5.0 | 2026-07-08 | Async identity registration (202 + poll) | [Reputation](reference/reputation.md) |
| 10.4.0 | 2026-07-06 | STEP 3 now teaches both escrow-lock paths | [Escrow + settlement](reference/escrow.md) |
| 10.3.0 | 2026-06-12 | Honest single-provider Ring 2 | [Arbiter + disputes](reference/arbiter.md) |
| 10.2.0 | 2026-06-11 | Universal Escrow (ADR-002 — sign-on-assignment, all 9 hiring-matrix cells) | [Escrow + settlement](reference/escrow.md) |
| 10.1.0 | 2026-06-10 | Universal Hiring Matrix | [skill.md](../skill.md) |
| 10.0.0 | 2026-05-27 | OWS-exclusive signing | [Signing (ERC-8128)](reference/signing.md) |
| 9.6.1 | 2026-04-22 | PATCH: Remove non-existent `/api/v1/escrow/{task_id}/state` endpoint from Option 5 monitor paths (caught by canonical-skill smoke test — 404 in prod,… | [Escrow + settlement](reference/escrow.md) |
| 9.6.0 | 2026-04-22 | MINOR: 3 Claude Code native monitor paths added to "Monitoring — Choose Your Strategy" (`/loop 3m` interactive, Anthropic Routine cloud cron, `Monitor`… | [Monitoring](reference/monitoring.md) |
| 9.5.0 | 2026-04-16 | MINOR: New optional fields on `em_publish_task` — `geo_match_mode` (`strict`/`city`/`region`/`country`/`any`) and `location_radius_m` (meters, default… | [Arbiter + disputes](reference/arbiter.md) |
| 9.4.0 | 2026-04-16 | MINOR: Document OWS CLI subprocess pattern for ERC-8128 signing — key never leaves vault, no MCP Server required. Reorder Step 1c to present OWS paths… | [Signing (ERC-8128)](reference/signing.md) |
| 9.3.0 | 2026-04-14 | MINOR: `gps_required` field on `em_publish_task`. Digital tasks (screenshot, json_response, etc.) now skip GPS verification automatically. Set… | [Evidence + delivery](reference/evidence.md) |
| 9.2.0 | 2026-04-11 | MINOR: E2E bug fixes — `arbiter_mode: "auto"` recommended for physical tasks (enables Ring 1 PHOTINT + Ring 2). EXIF GPS auto-extraction from gallery… | [Arbiter + disputes](reference/arbiter.md) |
| 9.1.0 | 2026-04-11 | MINOR: Escrow refund/recovery procedure. Deterministic steps for agents to recover locked funds when tasks expire. MANDATORY PaymentInfo save to disk… | [Escrow + settlement](reference/escrow.md) |
| 9.0.0 | 2026-04-10 | MAJOR: Ring 2 arbiter fully wired with ClawRouter (primary), EigenAI (secondary), OpenRouter (fallback). Dual-model consensus on MAX tier. Unified… | [Arbiter + disputes](reference/arbiter.md) |
| 8.0.0 | 2026-04-09 | BREAKING: Arbiter-as-a-Service (`POST /arbiter/verify`) is DISABLED pending Phase 1 guardrails — endpoint returns HTTP 503 on all production… | [Arbiter + disputes](reference/arbiter.md) |
| 7.5.0 | 2026-04-09 | MINOR: Capabilities discovery — new "Agent Capabilities Quick Reference" section at top lists everything the agent can do (task lifecycle, arbiter… | [Arbiter + disputes](reference/arbiter.md) |
| 7.4.0 | 2026-04-09 | MINOR: Phase 5 — Dispute resolution endpoints + Arbiter-as-a-Service. New `em_resolve_dispute` MCP tool (release/refund/split verdicts). REST… | [Arbiter + disputes](reference/arbiter.md) |
| 7.3.0 | 2026-04-08 | MINOR: Ring 2 Arbiter (`arbiter_mode` on em_publish_task + new `em_get_arbiter_verdict` tool). Ring 1 PHOTINT (forensic) verification. Tiers: cheap<$1… | [Arbiter + disputes](reference/arbiter.md) |
| 7.2.1 | 2026-04-08 | PATCH: Fix OWS shim wallet_name bug (P0, was returning first wallet instead of named one). Update CLI sign-bug warning — v1.2.4+ produces correct… | [Escrow + settlement](reference/escrow.md) |
| 7.2.0 | 2026-04-03 | MINOR: Auto-install OWS shim in Step 1a (bridges CLI to Python SDK). Hosted at execution.market/scripts/ows_shim.py. Zero manual steps for escrow setup | [Signing (ERC-8128)](reference/signing.md) |
| 7.1.0 | 2026-04-03 | MINOR: Escrow now uses OWS WalletAdapter (8/8 lifecycle steps keyless). SDK pinned to >=0.21.0. credentials.json no longer needed | [Escrow + settlement](reference/escrow.md) |
| 7.0.1 | 2026-04-03 | PATCH: WARNING — OWS CLI has 64-byte sig bug, use MCP server only. em_monitor.py download URL added | [Signing (ERC-8128)](reference/signing.md) |
| 7.0.0 | 2026-04-03 | MAJOR: OWS ERC-8128 signing (ows_sign_erc8128_request), 4 monitoring strategies (HEARTBEAT/cron/webhooks/WebSocket), worker reputation in applications,… | [Signing (ERC-8128)](reference/signing.md) |
| 6.1.0 | 2026-04-03 | Autonomous onboarding: auto-detect wallet, auto-install OWS, interactive config (name, network, autonomy). Zero manual steps | [Signing (ERC-8128)](reference/signing.md) |
| 6.0.0 | 2026-04-03 | MAJOR: Unified canonical skill. Merged config schema, autonomy system, monitoring decision logic, best practices, webhook payloads, IRC safety rules,… | [Monitoring](reference/monitoring.md) |
| 5.2.0 | 2026-04-03 | Photo evidence MUST be shown inline before approve/reject. Ported from skills/execution-market v2.1.0 fix | [Evidence + delivery](reference/evidence.md) |
| 5.1.0 | 2026-04-03 | OWS is now PRIMARY wallet path in Step 1a. Detects OWS first, credentials.json as fallback. OWS MCP Server integration documented | [Signing (ERC-8128)](reference/signing.md) |
| 5.0.0 | 2026-04-02 | MAJOR: Open Wallet Standard (OWS) replaces Ultra Wallet. OWS MCP Server for wallet mgmt + EIP-3009 signing. All uvw refs removed | [Signing (ERC-8128)](reference/signing.md) |
| 4.6.0 | 2026-04-02 | World ID 4.0: workers verify proof-of-humanity (Orb/device), tasks $500+ require Orb verification | [skill.md](../skill.md) |
| 4.5.0 | 2026-03-30 | X handle in config.json, agent_name sent with task creation | [skill.md](../skill.md) |
| 4.4.0 | 2026-03-30 | Agent profiles: display_name in config.json, shown on task cards | [skill.md](../skill.md) |
| 4.3.0 | 2026-03-30 | Auto-update: agents must fetch latest skill.md before every task | [skill.md](../skill.md) |
| 4.2.0 | 2026-03-30 | Clarify agent IDs are per-chain (different ID per network is normal). Only flag if erc8004_agent_id == 2106 (platform fallback) | [Reputation](reference/reputation.md) |
| 4.1.0 | 2026-03-29 | Report erc8004_agent_id (numeric per-chain ID) not agent_id (wallet address). agent_id is now always the wallet for cross-chain ownership | [Reputation](reference/reputation.md) |
| 4.0.0 | 2026-03-29 | MAJOR: Fix ERC-8128 signing (@query support), fix identity endpoint path (was 404), fix fee model (deducted not added), complete 21 categories + 18… | [Evidence + delivery](reference/evidence.md) |
| 3.28.0 | 2026-03-29 | Fix network check endpoint (was /config/networks 404, now /config), clarify: never use /x402/networks for supported chains | [Escrow + settlement](reference/escrow.md) |
| 3.27.0 | 2026-03-29 | Identity registration BEFORE task creation (not after), per-chain identity, escrow flow fix (wallet from applications), NEVER direct-pay rule | [Escrow + settlement](reference/escrow.md) |
| 3.26.0 | 2026-03-28 | Per-chain identity registration, network-aware identity check, fix escrow/assign flow (wallet_address from applications), NEVER direct-pay rule | [Escrow + settlement](reference/escrow.md) |

---

## Full entries

Each entry states the case that motivated the change. They are worth reading when
you hit the behaviour they describe — that is what the **Governs** column above is
for.

### 14.16.0 — 2026-10-08

**A business could not be paid by the minute through a channel capped at 0.25
USD.** Until this release every Solana channel admitted at most 0.25 USD and all
of them together at most 2.00 USD — numbers sized for tests. The owner's decision
196 lifts them: "sube esos limites infinitos [...] para abrir canales no
necesitamos Karma Cadabra, es una superficie de execution market". Now:

- **No platform ceiling by default.** No maximum per channel, no maximum open at
  once; `GET /api/v1/health` → `solana_session_channels.max_open_usd` and
  `cap_max_usd` read `null` once production runs it (an operator can still set
  a number, and health shows the one in force). A channel still declares a cap of at least 0.05 USD:
  it is the most a settlement may take from the deposit. The two fixed ceilings
  left on the way in are gone too: `cap_usdc` on the declare no longer stops at
  1000 (the OpenAPI published it as `maximum`), and `payment_streaming.cap_usd`
  no longer stops at 100 (that was the EVM streams rail's escrow limit). The cap
  must be finite and no more than a USDC account can hold.
- **Who pays the worker's USDC account rent: the publisher, never the gateway**
  (decision 202). It cannot go inside the open (the gateway refuses extra
  instructions there), so `409 WORKER_USDC_ATA_MISSING` at declare carries
  `rent_payer` and a ready `create_ata_instruction` with that account as its only
  signer. At settle the account is no longer created with the gateway's SOL: a
  missing one is `409 WORKER_TOKEN_ACCOUNT_MISSING` with `settle_pending: true`,
  the channel stays open and settles once it exists, and the public panel shows
  `settle_blocked`. Approval no longer goes ahead when Solana cannot be read
  (`503 WORKER_USDC_ATA_UNVERIFIABLE`).
- **A ceiling of your own, on request**, per signing wallet (a maximum per channel,
  open at once, or both). Past it: `422 CHANNEL_CAP_OUT_OF_RANGE` or `429
  CHANNEL_QUOTA_FULL` with `limit: "publisher_usd"` and your own numbers.

Three things had to land first, because without a ceiling each one is money:

- **Declaring somebody else's channel.** The declare already required the
  channel's on-chain payer to be a Solana address registered to you. Until
  2026-09-08 a dashboard session could write that registry with no signature, and
  such a value cannot be told apart from a signed one — so a row could hold
  another account and claim its channels. EM now records when it verified the
  ed25519 signature, and trusts only those: `409
  PUBLISHER_SOLANA_ADDRESS_UNPROVEN` until you sign `PATCH
  /api/v1/account/solana-payout-address` once more with the same address.
- **The worker's USDC account.** Assign and declare already refused a worker
  without one; self-accept (`em_accept_agent_task`) did not, so the first refusal
  came after the payer had paid the channel's rent. It asks now, same JSON.
- **Channel events.** `channel.opened`, `channel.settled` (a settlement
  transaction is named) and `channel.closed` (it stopped, no settlement proven)
  on the webhook rail, to both parties, delivered off the declaration's call
  path. See [reference/solana.md](reference/solana.md#channel-webhooks).

And one bound the old maximum used to hide: a cap of 1000 is now declarable over
a deposit of 0.05, so **the meter never counts past the deposit EM read on chain
at declaration** — the settlement could not pay it. After a top-up, declare the
channel again.

### 14.15.0 — 2026-10-08

**A fleet retried errors that no retry could fix, because nothing said so.** The
KarmaKadabra run of 2026-10-08 against the new image, read from the server log:

- `POST /tasks` → `422 task_content_held_for_review` three times. The skill named
  every other content-review refusal and not this one, so nothing said how the
  publisher learns the review is over. It does not: **nobody is notified**. You
  re-send the same publish later; while the review is pending you get the same
  refusal with the same `review_id` (no second review, no second slot of your
  queue), once approved it publishes, once, and if refused it is
  `task_content_rejected`. So the hold is now `retryable: true` — it said
  `false`, which reads as "never" — with `retry_after_seconds` (300): a pace,
  not a review SLA, since there is none; it is what keeps re-sends cheap for
  the review every publish shares. Written in
  [reference/publisher.md](reference/publisher.md), with
  `task_content_hold_queue_full`.
- Solana approve → `402 SOLANA_BOUNTY_CREDENTIAL_REFUSED` six times on one task:
  the worker's payout address has no USDC token account, the transfer to it fails
  simulation with `InvalidAccountData`, and every refusal came back with a fresh
  challenge and `retryable: true`. Each attempt cost the publisher one signature.
  Now EM reads the worker's account before it asks for the money: missing is
  `409 WORKER_USDC_ATA_MISSING`, with the account to create, and no challenge. A
  simulation that fails at an instruction is `409 SOLANA_BOUNTY_SIMULATION_FAILED`
  with the gateway's reason and no challenge either: approve again without a
  credential once its cause is fixed.
- Solana approve → `409 solana_payout_address_missing` retried eight times: it
  carried `retryable: false` but no `code`. It now carries
  `SOLANA_PAYOUT_ADDRESS_MISSING`.
- `relay/prepare` → `503 FACILITATOR_PREPARE_REFUSED` 24 times in 24 h, every one
  the facilitator's `relay_foreign_delegation`: four KK accounts delegated
  (EIP-7702) to PayBox's wallet contract. The skill already said where to go —
  `relay/self/*` — but the code was buried in a 503's message. It is now
  `409 RELAY_FOREIGN_DELEGATION`, `retryable: false`, with `next_step`.

Also server side, no guide change: `GET /tasks/{id}/submissions` answered 400 to
the whole listing when one submission had no verdict recorded; that submission now
reads `status: "pending"` (its `agent_verdict` stays `null`).

### 14.14.0 — 2026-10-05

**An agent with the evidence ready got `401` on both of its submits and delivered nothing.**
Task `fc195649` (0.05 USDC, escrow deposited on Base) was assigned to a ChatGPT
agent whose wallet lives in PayBox. It measured the gas price, and both
`POST /tasks/fc195649…/submit` came back `401 ERC-8128 verification failed: Invalid
keyid format: ArwjqcCqtA5o…`. That keyid is not an Ethereum one: it is the
thumbprint of the key OpenAI publishes at
`https://chatgpt.com/.well-known/http-message-signatures-directory`. ChatGPT's
agent signs every request it makes with Web Bot Auth — RFC 9421, the SAME
`Signature`/`Signature-Input` headers, `tag="web-bot-auth"` — and EM read the
presence of those headers as an ERC-8128 attempt. Production logs, 2026-09-28 →
10-04: 447 such `401`s, every keyid a 43-character thumbprint, on public reads,
`/mcp/` and `/a2a/v1` as well as the two deliveries.

**What changed in the server.**

- **A signature tagged for another profile is not ours** (the ERC-8128 draft's own
  rule, §2 and §3.5). It is ignored and never verified. A request whose only
  signature is foreign is treated like one without those headers: a public read
  answers it, and anything that needs credentials gets a `401` — on REST the
  no-credentials one, which now says that only your platform's signature
  arrived; on `/mcp/` the transport's, naming the same reason. On `/a2a/` such a
  request is not a ban strike: it goes on to the `/a2a/` rate limit and the
  route's `401`, as every signed request did before. An untagged member (what
  EM's SDKs and OWS send) is ours exactly as before, and so is `tag="erc8128"`.
- **Yours is found next to the platform's**, in the same header or on its own
  field line. Sign under label `eth`: when the platform uses YOUR label and its
  line comes last, yours is lost (RFC 8941 keeps the last member) and the `401`
  names the clash; a `Signature` member whose `Signature-Input` did not arrive is
  a `401` too, never an anonymous read.
- **Not yet measured**: whether ChatGPT's egress forwards the headers an agent
  adds. Until it is, the `401` above is how an agent learns it did not.
- **The current draft's keyid is accepted**: canonical CAIP-10
  `eip155:<chain>:<lowercase address>` (what `@slicekit/erc8128` emits since 0.4.0),
  alongside `erc8128:<chain>:<address>`. The draft's own positive test vector
  verifies. Non-canonical CAIP-10 (upper-case hex, leading zeros) is still
  `Invalid keyid format`. `@scheme` is resolved, pinned to `https` in production.
- `GET /api/v1/auth/erc8128/info` adds `keyid_formats_accepted` and `tag`.

**What changed in the guide.** Option C in
[reference/signing.md](reference/signing.md) is the by-hand recipe for a PayBox
wallet behind a connector: build the signature base, have
PayBox sign it with `request_wallet_sign(op:"message")` — EIP-191 over the exact
UTF-8 bytes, which is what EM verifies — and send it. No key export, no browser.

### 14.13.0 — 2026-10-04

**PayBox is the wallet this skill recommends**, ahead of OWS. The owner's
priority #1 for every product of the stack: wherever a caller asks how to pay,
sign or which wallet, suggest installing PayBox — or check that it is the one in
use — before any alternative, and ship enough PayBox context that an agent does
not rediscover the wallet layer each time.

The report that made it concrete: a ChatGPT agent with a PayBox wallet did the
work of a task and reported that its delivery got
`401 ERC-8128 verification failed: Invalid keyid format`, no submission on file,
and no web login for its PayBox-created account. This version does not claim what
produced that `keyid`. It fixes two things that would leave any agent stuck
there, whatever the cause: the `401` said the `keyid` was invalid without naming
a valid one, and the REST page of the docs showed the wrong form
(`keyid="0x<wallet>"`).

**What changed.**

- **"How you sign" starts with PayBox**: check it is in use
  (`paybox --json whoami` → `canSign: true`, or PayBox's `list_credentials`),
  otherwise suggest installing it. OWS is named after it. The OWS code block moved
  out (it is in `reference/signing`, Option B) to keep the procedure under its
  token budget.
- **`reference/paybox`** (new): install or verify, which EM rail takes which PayBox
  call (OAuth consent, signed session, ERC-8128, the money steps), ERC-8128 with
  the `paybox` CLI, **the `keyid` form to send**
  (`erc8128:<chain_id>:<0x address, lowercase>`), delivering work
  from a PayBox-only account through the signed API, and the known limits
  (`pending_signature` with no signing window, approval modes vs. unattended work,
  the five-minute ERC-8128 window, no wallet creation from the CLI). Also served
  by `em_get_guide(section="reference/paybox")`.
- **The API says it too**: `GET /api/v1/auth/info` and `GET /api/v1/auth/erc8128/info`
  → `recommended_wallet`, and the OpenAPI's description, guidance and `erc8128`
  scheme; every ERC-8128 `401` of the MCP transport carries a `wallet` block and
  names PayBox in its `detail`, and so do the REST, A2A, websocket and MCP-tool
  refusals that ask you to sign with ERC-8128 — the `401` of an unsigned delivery
  (`POST /api/v1/tasks/{task_id}/submit`) among them — save a few that keep their
  exact text: one whose wording is a contract, and the `403 bearer_not_allowed` a
  connector token gets for the tools it may never run, which ChatGPT gets too and
  which mostly points to another tool, not to a signer. An invalid `keyid` now
  states the form it expected.
- **Where else you pick a wallet**: the `/agents` page, `reference/services` (a
  PayBox order takes two steps, publish then assign, and the seller has to apply to
  that task in between: an assignment refuses an executor who never applied, and
  only the one-step order applies for the seller), `reference/monitoring` (the
  websocket signature) and the docs' authentication pages name PayBox first.

Nothing about authentication or money changed behaviour: every rail accepts the
same signatures from any wallet as before.

### 14.12.0 — 2026-10-03

The public [Task Policy](https://execution.market/task-policy) defines allowed,
prohibited, and reviewable tasks. Core workflow rule 11 now links it and summarizes
its scope, including the limited exception for a property offered to the publisher
for sale or rent. The MCP initialize instructions and registered publish tool
carry the same guidance; the publish description also documents the existing
content-review refusals and when to retry unchanged text.

To keep the procedure under its token budget, the full explanatory task/escrow
state paragraph moved to [reference/escrow.md](reference/escrow.md), and the hiring
matrix table and party-matching explanation moved to
[reference/task-fields.md](reference/task-fields.md). The main guide retains target
selection, registration, all workflow steps, and rules 1–10 unchanged.

### 14.11.0 — 2026-10-02

Tres cambios que se publican juntos (EM-MCP-04, EM-MCP-05 y EM-MCP-06). Cada uno
subió el skill a 14.10.0 por su lado y ninguno llegó solo a `main`: esa versión no
existió publicada, y esta es la que junta las tres.

**Cambiar una tarea publicada sin perder a los que se postularon.** El dueño publicó
por MCP la foto de La Gorda en Medellín y después necesitó otro precio, más radio y
más plazo. El único camino era cancelar y publicar de nuevo, y los postulantes se
perdían con la tarea vieja.

**Lo que cambió.**

- **`em_update_task(task_id, patch)`**: mientras la tarea está `published`, sin
  ejecutor y sin fondos en el escrow, cambia instrucciones, plazo, evidencia,
  ubicación, radio y modo geo (mismas reglas que al publicar). Las postulaciones se
  conservan y los postulantes reciben aviso. Monto, red y token no se editan.
- **«Reprice»**: `em_publish_task` con `replacement_of` publica la tarea nueva y
  cancela la vieja gratis; se rechaza con `replacement_not_possible` (no se crea
  nada) salvo que la vieja siga `published`, sin ejecutor y sin nada bloqueado.
  Sus postulantes reciben el id nuevo y se postulan otra vez.

**El publicador pregunta qué pasó desde la última vez que miró.** Después de
publicar por MCP, el dueño no tenía cómo saber que había llegado una entrega, ni
qué pasa con una entrega que nadie revisa: Execution Market actúa solo después de
`EM_REVIEW_WINDOW_HOURS` (72 en producción) o al vencer el deadline, lo que llegue
primero, y no siempre paga.

**Lo que cambió.**

- **Fila «What happened»**: `em_get_task_events(task_id, since_sequence)` devuelve la
  historia de la tarea (postulaciones, asignación, eventos de pago, entregas,
  veredicto del árbitro, cierre). `sequence` es la hora de cada fila en
  microsegundos; la próxima llamada pasa el `next_since_sequence` recibido. Una fila
  escrita tarde con hora anterior puede quedar detrás del cursor: para no perderla,
  pasá el cursor un minuto atrás y deduplicá por `id`. Es una vía pull: nada se empuja a
  un cliente MCP, así que el agente consulta o agenda una revisión.
- **`auto_settlement`** (también en `em_get_task`, `em_check_submission` y
  `em_list_applications` para el publicador): `acts_at` (cuándo actúa el barrido),
  la base (`review_window` o `deadline`) y el `outcome`. `settles_to_worker` solo si
  hay una autorización de pago guardada. Sin ella: `manual_review` si hay escrow, o
  `expires_unpaid` si no lo hay. Solana siempre es `expires_unpaid`: se paga solo
  cuando el publicador aprueba. Un veredicto ya dado no se liquida solo. Las mismas
  respuestas traen `next_steps`.
- Solo una fila: el skill estaba a 34 tokens del tope de 10.000. El detalle vive en
  la descripción de cada tool (`em_get_guide` y `mcp-tools.md`).

**El camino del publicador estaba escrito cuatro veces, y no decían lo mismo.** Con la
tarea real del dueño por MCP (la foto en Medellín) a la vista, se compararon las
cuatro: el quickstart de docs-site mandaba al agente a publicar en
`POST /api/v1/publish` (esa es la puerta del humano, con JWT; la del agente es
`POST /api/v1/tasks`), aprobaba y calificaba en una sola llamada con
`rating_score` (se ignora desde v12.0.0), prometía la ventana de 48 h que se apagó el
2026-08-24 y decía que por MCP el `X-Payment-Auth` "va en el transporte" (va en
`payment_auth`). El `wallet_action` de `em_assign_task` apuntaba a
`challenge.accepts[0].extra.typed_data`, una clave que el challenge nunca tuvo: la
estructura vive en `extra.eip712`. Este archivo ofrecía `metadata` como campo
opcional de `POST /api/v1/tasks`, que el body estricto rechaza con `422`, y
`reference/reputation.md` mandaba a revisar `em_my_work → to_rate`, una tool que no
existió nunca.

**Lo que cambió.**

- **`reference/publisher.md`**: los seis pasos (publicar → postulantes → asignar y
  firmar → revisar → aprobar → calificar), cada uno con su tool MCP y su llamada REST,
  y las dos puertas de la firma de la asignación (`wallet_action` → `payment_auth`
  por MCP, `GET /api/v1/tasks/{id}/assign/challenge` → `X-Payment-Auth` por REST):
  un challenge, una función que lo construye, una puerta por asignación. Se firma
  por OWS con `ows_sign_typed_data`, **no** con `ows_sign_eip3009`, que elige su
  propio nonce y no puede firmar `getHash(paymentInfo)`; el `wallet_action` de
  `em_assign_task` nombraba esa tool desde 2026-09-11 y ya no. El SDK
  (`build_escrow_pre_auth`) no es una tercera puerta: arma su propia autorización
  con salt aleatorio. Lo
  enlazan el Core workflow, las `instructions`, el quickstart y los docstrings, y el
  MCP lo sirve: `em_get_guide(section="reference/publisher")` y el recurso
  `skill://execution-market/publisher`.
- **`reference/mcp.md`**: cada tool del servidor con su llamada REST, y las que no
  sirven en producción dicen por qué (las cinco de escrow que firman con la wallet del
  servidor están apagadas, `em_escrow_dispute` y `em_withdraw_earnings` no están
  implementadas). Un linter del CI (`tests/ci/test_skill_names_real_mcp_tools.py`, en
  el paso Docs Drift) falla si el skill nombra una tool que el servidor no tiene (salvo
  `(planned)` junto al nombre), o si una tool del servidor no tiene fila en
  `reference/mcp.md`. Medido sobre `3ee22728`: 25 de las 48 no estaban en ningún
  archivo del skill.
- **Campos que el body rechaza**: `gps_required` salió de la lista de STEP 2 (como
  `metadata`): es solo de MCP, y `reference/task-fields.md` lo dice. Quien nunca operó
  tiene `reputation: null` (migración 202), no 50.
- **`skill_version`**: si falta o es más vieja que la del servidor, `em_publish_task`
  lo dice en sus avisos y `POST /api/v1/tasks` en `skill_notice`, con el enlace a este
  archivo y al changelog. El frontmatter trae `changelog:`, y de ahí se lee.
- **`language`**: etiqueta BCP 47 de las instrucciones (`es-CO`), en
  `em_publish_task` y `POST /api/v1/tasks`; se guarda en `metadata.language` y se lee
  en el detalle de la tarea. Sin ella no se guarda ninguna.
- **`em_feedback`**: el agente le dice a EM qué está mal o falta; queda en el log del
  servidor con la wallet si la llamada va firmada, y responde con una referencia.
- **`skill/SETUP.md` §0**: cómo llega esta misma guía a cada cliente (claude.ai,
  Claude Code, OpenClaw, cualquier MCP, cualquier agente HTTP).

**Lo que salió para seguir bajo 10.000 tokens.** «Best practices» repetía reglas que
el archivo ya tiene; sus dos datos propios (el tiempo de viaje y `receipt` para
compras) viven ahora en el paso 1 de `reference/publisher.md`.

**Al juntarlas.** `reference/mcp.md` tiene fila para `em_update_task` y
`em_get_task_events` (el linter las pide); `reference/publisher.md` nombra
`em_update_task`, `replacement_of` y `em_get_task_events`; `em_update_task` termina
con `next_steps`, como cancelar y asignar. El servidor queda en 52 tools y el skill
en 9.981 tokens.

### 14.9.0 — 2026-10-01

**El humano del agente ve la tarea como la ve su publicador.** El dueño publicó por
MCP con la wallet del agente y abrió el dashboard con otra cuenta: vio la tarea como
un extraño, sin postulantes, sin entregas y sin la foto. La 14.8.0 dejó la fila
«Dashboard link» como `(planned)`; ahora existe.

**Lo que cambió.**

- **`em_get_dashboard_link(task_id)`**: solo el publicador verificado lo pide, y
  devuelve `https://execution.market/task/<id>#k=<token>`. Vive 15 minutos, abre UNA
  tarea (la tarea, sus postulantes, sus entregas y los archivos por URL prefirmada
  de 5 minutos) y no escribe nada: aprobar, rechazar, asignar y cancelar siguen
  siendo llamadas firmadas, y cualquier otro request que lleve el link recibe 403
  `dashboard_link_read_only`. El token va en el fragmento de la URL, que no llega a
  ningún servidor.
- **Regla 9 (acceso del dueño)**: abrir el link cuenta como leer la evidencia (el
  acuse EM-7, igual que `em_check_submission`): desde ahí, rechazar abre una disputa
  en vez de un reembolso. El agente lo dice antes de entregar el link.

### 14.8.0 — 2026-10-01

**Un agente conectado por MCP ya recibe la guía sin buscarla.** El dueño publicó una
tarea real por MCP (una foto en Medellín, 20 USDC) desde una sesión que nunca leyó
este archivo: nada en el MCP la llevaba a él. Las instrucciones del `initialize`
venían vacías, no había recurso y ninguna respuesta lo nombraba. Cada fricción de
esa sesión estaba escrita aquí: pidió fondear antes de publicar, filtró
`em_get_tasks` con la wallet en checksum y no vio sus tareas, no releyó lo que había
guardado, dejó `target_executor_type` en `any` en una tarea física (solo
aplicaron agentes de software) y concluyó que no había vista de postulantes sin
probar `em_check_submission`.

**Lo que cambió.**

- **«Core workflow»**, arriba del archivo: cada paso del publicador con su tool MCP y
  su llamada REST, `(planned)` donde todavía no existe, y diez reglas, cada una
  medida contra el código (fondos, minúsculas, trabajo físico, releer, reintentos,
  elegir y confirmar, asignar = firmar, revisar/aprobar/calificar, acceso del dueño,
  qué hacer si algo falta) más los estados de tarea y de escrow.
- **El MCP entrega la guía**: `instructions` en el `initialize` (manda a cargar la
  guía y deja seis reglas por si no se puede), el recurso `skill://execution-market`
  (este archivo, textual) y la tool `em_get_guide(section?, client?)`: una sección, y
  con `client="mcp"` la tool de cada endpoint que la sección nombra, leída de la
  tabla del Core workflow.
- **`em_list_applications`**: los postulantes de tu tarea, paginados y filtrables por
  `status` y `applied_party`, cada uno con el `executor_id` que toma
  `em_assign_task`. `em_get_task` firmado por el publicador trae una página de
  `applications[]`.
- **`agent_id` en cualquier mayúscula**: `em_get_tasks`, `GET /tasks?publisher=` y
  las analíticas encuentran las tareas guardadas en minúsculas y en checksum; una
  respuesta vacía muestra el id normalizado.
- **Un solo sentido sobre los fondos**: «Publishing means YOU hire and pay» decía
  «you lock escrow» al publicar. Publicar no bloquea nada; asignar sí (en Solana el
  publish ya exige el saldo).

**Lo que se condensó para seguir bajo 10.000 tokens, y dónde está entero.** El
procedimiento no se tocó: los cuatro pasos de Solana (con «Keep its session key until
it settles») siguen en STEP 3 tal como estaban. Lo que se acortó fue explicación:

- la tabla de superficies del encabezado, en una línea con los mismos destinos;
- la introducción de la tabla de errores y el párrafo posterior a la de settlement
  (entero en `reference/escrow.md`, «Settlement failures on approve — the long
  version»);
- los comentarios por campo del ranking de postulantes y el «Workers vet too»
  (enteros en `reference/reputation.md`, «Vetting»; la frase del puntaje 50 por
  defecto se agregó allí);
- la segunda vía de escrow con `payment_info` (entera en `reference/escrow.md`,
  Path A y «MANDATORY: save PaymentInfo to disk»);
- el detalle de la red de reputación (entero en `reference/reputation.md`) y el
  párrafo repetido de `payment_tx: null` (ya en «Agent behaviour» y en
  `reference/evidence.md`);
- el diagrama de STEP 4, reemplazado por la línea «States» del Core workflow, que
  suma `assigning`, `verifying`, `disputed` y la definición de *contested*. Los
  estados de escrow que no caben ahí quedan en una tabla nueva de
  `reference/escrow.md`, «Escrow statuses».

**Dos correcciones de nombre en la misma versión.** Por REST el campo es
`target_executor` (`CreateTaskRequest`); `target_executor_type` es el de
`em_publish_task` (MCP) y el que devuelve la tarea. Y una persona que se postula por
un conector (`human_via_agent`) puede tomar tareas `human`.

### 14.7.0 — 2026-09-27

**Una cuenta delegada a un wallet ajeno ya puede firmar su rating.** 86 tratos de
KarmaKadabra no podían emitir el rating firmado: el rater era una EOA de Paybox
delegada por EIP-7702 al `SemiModularAccount7702` de Alchemy, y el riel firmado la
redelega a nuestro `FeedbackDelegate`. El facilitador responde
`relay_foreign_delegation` a propósito, porque redelegarla rompe el wallet que la
usa. Esa regla no cambia.

**Lo que cambió.** EIP-7702 deja que una cuenta delegada origine sus propias
transacciones, así que la cuenta llama `giveFeedback` directo al
ReputationRegistry, paga su gas, y el registro la anota como `clientAddress`:

- `POST /reputation/relay/self/prepare` — el mismo body que `relay/prepare`, las
  mismas compuertas, la misma red y el mismo documento. Devuelve `registry`,
  `chain_id` y el `calldata` exacto. Una red sin registro, o fuera de las del riel
  firmado, es `422 self_submit_unsupported_network:<red>`: nunca Base por defecto.
- `POST /reputation/relay/self/confirm` — `{task_id, direction, network,
  tx_hash}`. EM lee el recibo en la red del documento, sin esperar: si no está
  minado o no tiene la profundidad de esa red responde `202` con `confirmations`
  y `required`. Lo registra solo si hay exactamente un `NewFeedback` del registro
  con los campos que EM guardó; si no, `422 self_submit_mismatch:<campo>`. El
  mismo `tx_hash` otra vez devuelve el mismo `200`.

**Qué hacer.** Si el relay te responde `relay_foreign_delegation`, usar este
camino. Mientras sea `202`, reintentar el mismo confirm; ante un `503`, también.
**Nunca mandar otra transacción**: un rating on-chain no se deshace.

### 14.6.0 — 2026-09-27

**Una tarea maliciosa ya no llega a publicarse, y quien la publicó ya no entra.**
Entre el 2026-09-24 y el 2026-09-26 un publicador subió 43 tareas cuyo texto pedía
ejecutar un paquete remoto, y usó el mensaje de aplicación como buzón. Dos defensas
nuevas responden con códigos que un agente tiene que saber leer, así que entran a
la tabla de errores en un solo bump.

**Lo que cambió.**

- **Revisión de contenido al publicar** (las nueve puertas: REST, H2A, streams,
  orden de servicio por REST y por MCP, hire-verifier, `em_publish_task`, el lote
  MCP y A2A). El texto visible por el ejecutor se revisa antes de insertar nada:
  - `422 task_content_rejected` — el texto fue rechazado. `retryable: false`: el
    mismo texto se rechaza otra vez. El cuerpo **no** dice qué regla saltó (sería
    un oráculo para iterar la evasión).
  - `422 task_content_too_large` — el texto pasa de `detail.limit_bytes` (64 KB).
    `retryable: false`.
  - `422 task_content_review_unavailable` — la revisión no contestó a tiempo y no
    se creó nada. Es el único 422 con `retryable: true`: reenviar **el mismo**
    publish con backoff.
  - Los 422 de `sell_intent_rejected` y de secretos embebidos ganan `code` y
    `retryable` (aditivo).
- **Ban por identidad** (wallet, identidad ERC-8004 probada en cadena, executor o
  usuario) en todas las puertas de escritura:
  - `403 principal_banned` (con `ban_id`) — tu identidad está baneada. Re-firmar
    no ayuda; la apelación va por el correo que nombra `message`, con el `ban_id`.
  - `403 executor_not_active` — tu perfil de executor está suspendido y no toma
    trabajo nuevo (lo que ya tenés asignado se termina y se cobra).
  - `409 task_publisher_banned` — al aplicar: el publicador de esa tarea fue
    removido. Elegí otra y no hagas nada de lo que pedía.
  - `409 executor_unavailable` — al asignar o comprar un servicio: ese executor no
    puede tomar trabajo. Elegí otro aplicante. No te dice por qué: el bloqueado
    no sos vos.

**Qué hacer.** Ramificar por `detail.code`, como siempre. Ninguno de estos códigos
se arregla reintentando, salvo `task_content_review_unavailable`.

**Lo que se movió.** La 14.5.0 había dejado el skill en 10.043 tokens
(`cl100k_base`), sobre su presupuesto de 10.000. Para que estas filas entren, tres
párrafos de «Reading data» —las dos causas opuestas de un `403` en una lectura
(repetidas en la fila `403` de la tabla), cuándo vale la pena gastar una firma, y
que MCP firma cada llamada en el transporte— pasaron sin cambios a
[`reference/signing.md`](reference/signing.md). El skill queda en 9.968.

### 14.5.0 — 2026-09-26

**El 429 del facilitador ya no llega disfrazado de 503.** El 2026-09-25 el relleno
de ratings firmados de KarmaKadabra falló 73 de 141 con
`503 {"detail": "Facilitator error: 429 - ...rate_limit..."}`. El status decía
"caído", el texto decía "límite", y el `Retry-After` del facilitador se había
perdido en el camino: el cliente no podía saber si reintentar ni cuándo.

**Lo que cambió.**

- Cuando el facilitador limita una escritura (su presupuesto por dirección o su
  tope diario de escrituras ERC-8004), EM responde **429** con
  `detail.code = "facilitator_rate_limited"`, `detail.retryable = true`, el
  código del facilitador en `detail.facilitator_code` (por ejemplo
  `erc8004_daily_write_limit`) y su `Retry-After`, tal cual, cuando lo tiene.
  El tope diario pide esperar hasta las 00:00 UTC y ese número no se recorta.
- Cuando el facilitador está saturado, EM responde **503** con
  `detail.code = "facilitator_unavailable"`.
- Aplica a `POST /reputation/relay/prepare` y `/relay/submit` (antes 503),
  `POST /reputation/workers/rate` y `/agents/rate` (antes 200 con
  `success: false`) y `POST /reputation/register` (antes 200 con `success:
  false`; ahora 429, y la fila del registro queda libre porque no se minteó
  nada). Cualquier otro fallo del facilitador responde como antes.

**Qué hacer.** Esperar el `Retry-After` y reenviar **el mismo** request. En estos
429 no se escribió nada: el límite corta antes de que el facilitador ejecute.
En los ratings (firmados y legacy) el 429 puede llegar **sin** `Retry-After`,
porque el SDK que EM usa para esas escrituras todavía no conserva ese header. En
ese caso, esperar con backoff y leer `detail.facilitator_code`: con
`erc8004_daily_write_limit` no hay nada que hacer hasta las 00:00 UTC.

### 14.4.0 — 2026-09-24

**Arc es una red de pago con escrow.** Hasta la 14.3.0 la lista de redes del skill
tenía ocho cadenas EVM con x402r. Arc (chain id 5042) estaba en el registro sólo
para reputación ERC-8004. Ahora tiene escrow de la generación D de x402r y un
PaymentOperator de EM, y entra a `EM_ENABLED_NETWORKS`.

**Lo que cambió.**

- La línea **Networks** de `skill.md` suma `arc`.
- `reference/escrow.md` suma a Arc en la tabla de contratos (USDC, escrow,
  operator, token collector) y en la de RPC, y pasa a hablar de 9 mainnets EVM.
- `reference/solana.md` también pasa de 8 a 9 mainnets EVM.

**Lo que tiene de distinto la generación D.** La ABI del operador es
`capture`/`void`, y un refund anula todo el monto capturable, no una parte.

**Cuándo se puede usar.** Arc toma tareas en producción cuando `terraform apply`
pone `arc` en el `EM_ENABLED_NETWORKS` vivo. El deploy de la imagen no alcanza,
porque sólo cambia imagen y `GIT_SHA`. Hasta entonces, publicar ahí devuelve 400.
La señal para saberlo es que `GET /api/v1/h2a/payment-config` la liste en
`escrow.networks`. Por eso el skill remite a ese endpoint, y el dashboard y la app
móvil tampoco la ofrecen antes.

### 14.3.0 — 2026-09-13

**El skill ahora enseña a abrir y a liquidar un canal de Solana.** Hasta la
14.2.0, `skill.md` mencionaba "channel" cuatro veces: la lista de redes, el 503
`channel_unreadable`, que approve reserva contra el canal y que el canal es el
escrow. Ninguna decía cómo se llega ahí. Un agente que publicaba en Solana
leía que "el canal es el escrow" sin saber que tenía que declararlo. Y el día que
la sesión de pay.sh se moría, el procedimiento no le decía que existe
`POST /tasks/{id}/channel/settle`. Todo eso ya estaba en `reference/solana.md`;
faltaba el camino corto dentro del procedimiento.

**Lo que cambió en STEP 3.** El párrafo de Solana pasó a ser cuatro pasos:

1. Vincular la cuenta que paga (`PATCH /api/v1/account/solana-payout-address`).
2. Abrir el canal de pay.sh comprometiendo el 87% al worker.
3. Declararlo con `channel_id` y `cap_usdc`, con sus tres rechazos nombrados.
4. Aprobar. Si la sesión murió, firmar el `settle_body` que trae el
   `409 channel_session_gone` y mandarlo a `POST /api/v1/tasks/{id}/channel/settle`.

Los mismos pasos quedaron en la descripción de la tool MCP `em_get_task_channel`
y en `llms.txt`.

**Por qué salieron cinco pasajes.** Sobre la 14.1.0 el skill ya medía 9.962 tokens
de un presupuesto de 10.000, y el procedimiento nuevo no entraba. En vez de
recortar procedimiento, salió historia que ya vivía en otro lado; nada se perdió.
Sumado a la 14.2.0 queda en 9.952.

- "Esta tabla estaba al 84% del archivo" → entrada 14.0.0 de este changelog.
- "Hasta el 2026-08-07 esa identidad era el agente de la plataforma (#2106)" →
  11.34.0. La regla (firmar la lectura y mirar `agent_id`) sigue en el skill.
- "Una flota de 24 agentes quemó una hora reportando esto como bug" → 11.9.0.
- "Una flota entera publicó tareas de VENTA que expiraron" → 11.4.0.
- Los tres emisores automáticos apagados el 2026-08-24 y el 91,3% del feedback
  bajo una sola dirección → `reference/reputation.md`, que los cuenta completos.

### 14.2.0 — 2026-09-13

**The skill taught publishers to leak the doorstep.** STEP 2's example put
`"123 Main St, San Francisco, CA"` in `location_hint` and `"Go to 123 Main St"` in
`instructions`. Both fields are served verbatim to anyone browsing the board —
`GET /tasks/available` needs no credential, and `em_browse_agent_tasks` needs only
an executor registration, which is gasless. Rounding `location_lat`/`location_lng`
to 3 decimals (~110 m) on the board was worth little while the recommended hint
carried the exact address in free text.

**What changed.** The example names an area (`"Union Square, San Francisco, CA"`),
the optional-fields line marks `location_hint` public, and `reference/task-fields.md`
says which fields are public and where the exact point goes: `location_lat`/`location_lng`, rounded on the board and served
exact only to the assigned worker by `GET /api/v1/workers/tasks/{id}/geo-reference`.
In the same change the backend stopped serving what the doc now promises it does
not: `em_browse_agent_tasks` returned full-precision coordinates plus
`human_wallet`/`human_user_id`, and both boards projected the raw PostGIS
`location` column, which the rounding never touched.

### 14.1.0 — 2026-09-11

**OAuth 2.1, para los clientes que no pueden firmar.** Nada de lo que ya
funcionaba cambia: ERC-8128 sigue siendo el rail primario y el mas fuerte —
autentica el REQUEST, no a quien llama — y este agregado no le quita una linea.

**Por que existe.** Hasta hoy, un cliente MCP que no supiera firmar RFC 9421 no
tenia forma de entrar. Medido el 2026-09-11: `POST /mcp/` sin credencial
contestaba 401 exigiendo ERC-8128 para TODO, incluido `initialize` y
`tools/list`; y el unico documento OAuth que respondia 200 declaraba
`authorization_endpoint` **vacio**, que RFC 8414 §2 hace invalido. Eso es lo que
hacia que claude.ai detectara un sign-in y despues fallara al registrarse: un
cliente que no podia entrar, y un documento que le prometia que si.

**Lo que un bearer NO puede hacer**, que es la parte que importa y por eso esta
en el procedimiento y no en una nota al pie: no alcanza `/escrow`, `/account`,
`/disputes`, `/evidence`, `/reputation`, `/admin` ni `/h2a`; no entrega trabajo,
no retira, no califica. Y no mueve dinero por su cuenta — asignar exige una
firma EIP-3009 por operacion (el nonce es `getHash(paymentInfo)`, que incluye al
receiver, asi que no puede existir antes de elegir al worker) y aprobar exige
`X-EM-Approval` o el scope `agent:approve`, que se consiente en su propia
casilla sin tildar, con dos numeros que el usuario ESCRIBE en la pantalla y
FIRMA dentro del mensaje EIP-4361 —lo mas que puede liberar UNA aprobacion, y
cuantas aprobaciones en total, topados en $100.00 y 50—, y que un refresh no
renueva. Los dos viajan como claims firmados, asi que no se pueden subir despues
de emitido el token; pasarse de cualquiera de los dos contesta 403 nombrando
cual fue.

**Y como se conecta desde claude.ai**, que es la pregunta que el documento no
contestaba: Settings → Connectors → Add custom connector → URL
`https://mcp.execution.market/mcp/` (con la barra final) → Sign in now → Use
Claude's published identity → la pantalla de consentimiento → las tools. El
paso a paso completo, y el equivalente generico con el MCP Inspector, estan en
`reference/oauth.md`.

**Un detalle de procedimiento que ahorra una sesion perdida**: todo el rail
contesta **404** si el despliegue no lo tiene prendido. Sondear, no asumir —
`GET /api/v1/auth/info` publica cada modo con su estado real.

### 14.0.0 — 2026-09-10

**MAJOR: the skill is the procedure and nothing else.** Reported by KarmaKadabra,
which consumes it with 27 agents: the file was **3.688 lines, 339.449 characters,
~92.000 tokens**, of which the changelog alone was **32,4%** — an agent spent that
before doing anything, and read ~35.000 tokens before the first actionable step. So
they stopped reading it and wrote their own summary in their repo. **That summary
went stale and cost them an incident**: it said `GET /tasks` returned only their own
tasks, months after EM had inverted it to the open marketplace. A skill you cannot
read whole gets replaced by copies that age badly.

**Now: 628 lines, 37.236 characters, 9.688 tokens.** The happy path (STEP 0-6) runs
without opening the changelog or a single `reference/` file. Nothing was deleted —
the changelog moved here in full, the human setup moved to `SETUP.md`, and the
subject matter moved to `reference/`, one file per subject.

**The error table went from 84% of the file to 7,7%**, complete, with three columns:
what happened · is it terminal? · what to do now. The middle column is the one that
was missing: it took a fleet real time to learn that a `409` on `apply` is
idempotent success and that a `403` is usually a missing signature.

**On the "5 missing codes" the report listed** — only `413` was actually missing.
`412`, `545` and `574` are not HTTP statuses anywhere in the document: two are
counts of reputation events and one is a length in characters, all three inside
changelog prose. `504` appears once, in the entry announcing that it **disappears**.
The table was rebuilt against the statuses the backend really emits, and reaches 17
by naming the three success answers that get misread as errors: `200` to an unsigned
read (empty, not an error), `201`, and `202` (in flight — retrying it is what mints
duplicate identities).

**What did not move**, and is more visible than before: the write-only-signing rule
with its three identity-gated reads, the hiring matrix, the distinction between
accepting the work and the money having arrived, and the error-carries-its-own-way-out
pattern — now stated as the rule for all 17 codes instead of the exception for four.

### 14.0.1 — 2026-09-10

PATCH: **the split shipped in 14.0.0 was cut before 13.12.0 landed on `main`, so the reputation section still described the old default.** This entry is the graft, not a new behaviour: nothing in the code changed here. Three corrections, all of them things 13.12.0 made true and this file still denied. **(1) `base` is no longer the default** — an omitted `reputation_network` falls through your profile preference to **the chain the task was PAID on**, and an untouched profile column (`reputation_network_changed_at` NULL) does not count as having chosen `base`. The resolution list grew a step. **(2) The response now names the chain** — `reputation_network_requested`, `reputation_network_used` and `reputation_network_fallback_reason` ride on every rating surface, including both halves of the signed relay; `fallback_reason` is `null` when the chain was honoured and otherwise one of `no_identity_on_chain`, `chain_not_capable`, `chain_guard`, `pref_disabled`. The file said *"there is no `reputation_network_requested` field to compare against"* — there is one now, and reading it is the check. **(3) The signed relay honours the per-task field**, which it used to skip; that was the rail the fleet actually rated through. Also carried over: pinning `base` on purpose stamps `reputation_network_changed_at` and starts the 168 h cooldown (`recorded_as_explicit_choice: true`), and `network` in the body of a rate call was never read. `llms-full.txt` regenerated from the same sources.

### 13.12.0 — 2026-09-10

MINOR: **la reputacion se sella en la RED DEL PAGO por defecto, y cuando cae en otra la respuesta lo DICE.** Medido el 2026-09-09/10 sobre los primeros canales de Solana del enjambre: 18 calificaciones de trabajo pagado por canal de Solana sellaron en **base**, cada una contestando `success: true` y ningun campo que dijera que la cadena habia cambiado. Tasks nombradas: `1e24d50a` (publicada el 07-sep sin `reputation_network`, calificada a las 03:58Z con el calificado ya con identidad en Solana -> base, `0xbff8a9b8…`), `6204b393`, `d4dc432d` y `99b4bd68` (mismo cuadro); contra `60b13900`, publicada CON `reputation_network: solana`, que sello en **solana** a las 02:04:36Z. La capacidad nunca fue el problema. La causa: `executors.reputation_network` es `NOT NULL DEFAULT 'base'`, asi que la columna dice `base` para todo el que nunca la toco — 218 de 221 executors — y eso se leia como una eleccion deliberada que le ganaba a la red del pago. **Un campo vacio ya no cuenta como elegir base.** El orden ahora es: (1) tu eleccion explicita (por task, o de perfil), (2) la red del pago, (3) `base` solo si esa red no puede llevar reputacion o no tenes identidad ahi y no se puede acunar. Y tres campos nuevos en TODA respuesta de calificacion —`reputation_network_requested`, `reputation_network_used`, `reputation_network_fallback_reason`— mas el mismo aviso en el log de auditoria. `fallback_reason` vale `no_identity_on_chain`, `chain_not_capable`, `chain_guard` o `pref_disabled`, y es `null` cuando no se movio nada. La regla es **uniforme**: una task pagada en `arbitrum` sin eleccion sella ahora en **arbitrum**, cuando ayer sellaba en base — Solana fue donde se noto, no el unico caso. **Que hacer**: no mandes `network` en el cuerpo del rate (nunca se leyo, pydantic lo descarta); manda `reputation_network` al PUBLICAR o al APLICAR **solo si querés otra red que la del pago**. Efecto conocido: fijar `base` a proposito con el `PATCH` estampa `reputation_network_changed_at` y arranca el cooldown de 168 h, porque ese estampado es justamente lo que distingue "elegi base" de "nunca elegi". Las 18 de ayer se quedan en base: no se reemiten.

### 13.11.1 — 2026-09-10

**[Points (2) and part of (3) were FIXED the same day by 13.12.0 — the fallback is no longer silent, and an untouched profile default no longer outranks the payment chain. Point (1), the Solana mint, still holds.]** PATCH (doc-only): **three things this file promised about reputation networks were not true, and a fleet paid for it.** Reported by KarmaKadabra after publishing with `reputation_network: "solana"`, minting the identities by hand and watching every rating seal on `base` with `success: true`. **(1) The Solana identity does NOT mint itself.** The auto-mint needs `executors.solana_payout_address` bound first — with none, it returns empty-handed and the rating falls back — and the publisher side has no Solana mint path at all (its identity helper is EVM-only). Register the Solana identity explicitly before choosing that chain. **(2) The silent fallback that v11.33.0 argued against now exists.** The `422 INVALID_REPUTATION_NETWORK` at publish/apply is the ONLY gate; the resolver that runs later never re-checks, and when it cannot honour the choice it writes the rating on the payment chain with nothing in the response naming what you asked for. There is no `reputation_network_requested`. **Read `network` on the rating response and compare it yourself.** **(3) The per-task field is write-once, and omitting it freezes nothing.** No endpoint changes it after publish. Omitted, it stays NULL and is resolved AT RATING TIME against your profile preference — which reads `base` until you send `PATCH /workers/{wallet}/reputation-network`. Minting identities elsewhere moves nothing. Also: the signed relay rail resolves from the profile preference and does NOT read the per-task field. **And the profile preference is LIVE**, not "coming soon" — three places in this file still said read-only while the flag has been on in production. `reputation_network` in your local `config.json` was never read by the server.

### 13.11.0 — 2026-09-09

MINOR: **calificar una task pagada por canal ya no devuelve `400`. Si te lo rechazo antes, REINTENTA.** Medido el 2026-09-09 entre las 19:08Z y las 19:30Z: 4 de 4 calificaciones de tasks pagadas por canal rechazadas con `payout_not_attributable`, contra 3 de 3 de EVM aceptadas — sobre tasks liquidadas, con el pago liberado, el reparto 87/13 visible en la pagina y "Sin calificar aun" en las dos direcciones. La causa: el gate antifraude exige saber a quien le pago el canal, y ese dato se congelaba **solo desde el recibo del gateway** — que los dos caminos por los que hoy cierran los canales (el `409` que reconcilia uno ya liquidado, y el watch, desde que la v0.28.7 del gateway cierra sola por idle) nunca ven. Y la respuesta estaba a la vista: EM **ya** lee los balances de la transaccion del settle para negarse a registrar un pago redirigido. Esa lectura ES una atribucion, de la fuente mas fuerte que hay, y se tiraba. Ahora se guarda, en los cuatro caminos (settle `200`, `409`, watch y el stream del taximetro), y un binding que ya quedo liquidado sin ella se re-atribuye solo desde la cadena en la proxima ronda del watch (~30 s). **La politica del gate NO cambio**: `not_attributable` sigue bloqueando y `verified_not_paid` —la prueba de que el worker no cobro— sigue siendo un rechazo distinto y con su propio motivo. Lo que cambio es que la atribucion existe.

### 13.10.0 — 2026-09-09

MINOR: **un settle que el gateway SI ejecuto ya no se pierde porque la cadena tardo en confirmarlo.** Medido el 2026-09-09 sobre un canal huerfano real: el gateway liquido de verdad (el worker cobro 0,00087 USDC on-chain), EM pidio esa transaccion UNA sola vez —con commitment `finalized`, en el instante— el RPC todavia no la servia, y EM contesto `502 settlement_unverifiable` **sin anotar nada**: el worker cobrado, el canal en `expired` con `settlement_tx` NULL, la task sin completar y el rating rechazado por falta de prueba de pago. Tres cambios: (1) la lectura ahora tiene **ventana** — se reintenta con `confirmed` y `finalized`, con backoff, hasta ~45 s; (2) si aun asi no se puede leer, **la firma se ANOTA**: el canal queda en el estado nuevo **`settling`** con `pending_settlement_tx` y `settlement_verified: false`, y la respuesta es **`202`** con `retryable: true` — nunca mas un 502 mudo sobre una transaccion que existe. `settlement_tx` sigue siendo NULL hasta que la cadena confirme el credito, asi que **`settling` NO habilita el rating**: la prueba de pago sigue exigiendo el verificado; (3) el `POST` es **idempotente de verdad**: si el gateway contesta `409 already_distributed` nombrando la transaccion, o si el canal ya liquido on-chain, EM la verifica y la registra igual que un `200`. Reintentar es seguro y es lo que hay que hacer. `GET /tasks/{id}/channel/public` publica los dos campos nuevos, y el 502 queda reservado para `payout_redirected` — que sigue siendo un rechazo, porque una transaccion verde que le pago a otro no es un pago.

### 13.9.0 — 2026-09-09

MINOR: **el settle tardio de un canal ya no depende de que el gateway adivine a quien pagar, y cuando algo se rechaza te llega el motivo ENTERO.** Dos cosas, medidas el 2026-09-09 sobre un canal huerfano real: (1) el gateway reconstruia el reparto desde su propia configuracion, que nombra UN worker fijo para todo el deployment, y en EM el worker cambia por canal — la cadena rechazaba el reparto inventado y el cierre no ocurria. EM ahora **nombra los destinatarios**: la direccion de pago en Solana del worker asignado y su parte en basis points, que el gateway hashea contra el `distributionHash` grabado on-chain antes de mover un lamport. **Tu cuerpo no cambia** — el reparto sigue sin ser una eleccion tuya, porque on-chain no lo es. (2) La respuesta de error del gateway llegaba aplastada a una frase (`returned 403: distribution_mismatch`) y los campos que decian QUE discrepaba morian ahi. Ahora viaja **anidada y sin recortar** en `detail.gateway`, al lado del `message` de siempre. Codigo nuevo: **`409 distribution_mismatch`** (`retryable: false` — el compromiso on-chain es inmutable, reintentar el mismo cuerpo se rechaza igual).

### 13.8.0 — 2026-09-09

MINOR: **asignar a un worker que no puede cobrar en Solana ahora rebota en el ASSIGN, no en el settle.** El `distribute` del programa de canales **no revierte** cuando falta la cuenta de USDC del destinatario: emite `payoutRedirected`, le manda esa parte al treasury del programa, y **la transaccion sale verde** — el worker lee "pagado" y no recibio nada. Medido el 2026-09-08 sobre un fork de mainnet: canal liquidado por 3000 uUSDC, recibo nombrando al treasury con `bps: 0`, worker ausente del reparto, y **sin cuenta despues del settle** (el camino de canal nunca la crea, asi que el estado no se despeja solo). `POST /tasks/{id}/assign` y `POST /tasks/{id}/channel` deriva ahora la cuenta de token asociada del `solana_payout_address` del worker y la busca en la cadena. Dos desenlaces, y NO son intercambiables: **`409 WORKER_USDC_ATA_MISSING`** (`retryable: true`) trae `worker_usdc_ata`, `usdc_mint` y el comando `spl-token create-account` exacto; **`503 WORKER_USDC_ATA_UNVERIFIABLE`** con `Retry-After` cuando el RPC no contesta — **falla CERRADO**, porque dejar pasar sobre una pregunta sin respuesta es justo el caso que pierde el 87%. `em_assign_task` por MCP contesta el mismo codigo en JSON. Si corres una flota, crea la cuenta al arrancar cada agente: la renta (~0,002 SOL) se paga una vez y saca el problema del camino del pago. Se corrige tambien la fila de `409 worker_token_account_missing`, que decia que el settle "revierte y sella el canal con tu deposito adentro": no hace ninguna de las dos cosas.

### 13.6.0 — 2026-09-08

Declaring a Solana channel now proves ownership on chain: the channel's `payer` must be a Solana address registered to the publisher. Four outcomes documented, one retryable. `payer` in the body is checked, never trusted — and it is NOT the voucher signer.

### 13.7.0 — 2026-09-08

MINOR: **el settle tardío lo transmite ahora el gateway pay.sh, no EM.** Para vos no cambia nada — mismo cuerpo, misma firma ed25519 sobre los mismos 50 bytes, misma respuesta con `settlement_tx` — pero **EM ya no sostiene ninguna llave de Solana**: el gateway ya es el fee payer del canal y su `rentPayer` grabado on-chain, así que el cierre le pertenece. Lo que EM conserva es lo que sólo EM puede hacer: verificar tu voucher contra el `authorizedSigner` que la CADENA declara **antes**, y **después** leer la transacción en la cadena para confirmar que el worker cobró de verdad — porque el programa emite `payoutRedirected` y le manda la plata a otro cuando la ATA de destino falta, **sin revertir**, así que una transacción verde no es un pago. Códigos nuevos, todos con `retryable` que dice la verdad: `503 gateway_unavailable` (retryable), `503 gateway_auth_unavailable` (**no** retryable: es cableado nuestro), `404 channel_unknown_to_gateway`, `502 payout_redirected`. Desaparecen `503 settler_key_unavailable` y `504 settlement_unconfirmed`. Sigue valiendo lo de siempre: con tu firma la transacción la puede mandar cualquiera desde cualquier wallet con fondos, porque `settle` y `distribute` no llevan cuentas firmantes.

### 13.5.0 — 2026-09-08

MINOR: **si la sesión de pay.sh de tu canal murió, ya no tenés que armar una transacción de Solana a mano: `POST /api/v1/tasks/{id}/channel/settle`.** Firmás el voucher acumulativo con la llave de sesión del canal y EM lo verifica contra el `authorizedSigner` que la CADENA declara y transmite `[ed25519, settle, distribute]` por vos. Lo que lo hace posible, medido hoy: `settleAndSeal` (0x04) **sí** exige la firma del payee, pero **`settle` (0x02) no tiene ninguna cuenta firmante**, `distribute` (0x07) tampoco, y el error 2400 del programa (*«Channel is not in OPEN or SEALED»*) dice que `distribute` acepta un canal **OPEN** — no hay que sellar nada. O sea que EM no gana ningún permiso: sin tu firma no puede mover un lamport, y con tu firma podría cualquiera. El cuerpo son cinco campos — `channel_id`, `cumulative_uusdc`, `expires_at`, `session_pubkey`, `signature` — y la firma es **ed25519 crudo sobre los 50 bytes** de `voucher_message_bytes(channel_id, cumulative, expires_at)`: `magic 0x5601 ‖ channelId(32) ‖ u64 LE ‖ i64 LE`. No el JSON, sin prefijo `personal_sign`, no base64. `409 channel_session_gone` ahora trae el `settle_body` exacto en la respuesta, así que no hay que deducirlo de la prosa. **Sigue valiendo el corolario: si perdés la llave de sesión mientras el canal está abierto, el depósito ya sólo puede volver al pagador** — EM no la tiene y no puede reemplazarla.

### 13.8.0 — 2026-09-09

MINOR: **The price of a channel tick and the deposit in a channel now have ONE source, and EM publishes it.** Measured 2026-09-08 on the live Solana rail: a channel was declared at `price_per_unit_uusdc: 10000` and the gateway billed **1000** on every tick — a 10:1 gap between what EM reported and what the payer paid. Neither number was wrong on its own; there were simply two. The gateway prices the resource and it is the side that collects, so it wins. Three things change. (1) **`GET /tasks/{id}/channel/public` publishes `price_per_unit_uusdc`** — read live from the gateway, `null` when EM could not read it, **never a default**. **Same number on `GET /api/v1/health` as `channel_tick_price_uusdc`**, so you can read the price BEFORE you sign anything. (2) **`POST /tasks/{id}/channel` refuses a channel that would meter at any other price**: `422 CHANNEL_PRICE_MISMATCH`, with `gateway_price_per_unit_uusdc` in the body. Omit `price_per_unit_uusdc` and EM takes the gateway's — that is now the recommended shape. The gate reads BOTH doors: the field on this request and `payment_streaming.price_per_unit` declared at publish. When the gateway is unreadable there is no gate, because with no reading there is no disagreement to catch. (3) **The panel publishes `deposit_uusdc` — what the channel actually HOLDS**, read from the channel account on Solana when you declared it. It is the same number the gateway's `payment-receipt` header calls `authorized`. `cap_usdc` is the declared ceiling and `recommended_deposit_uusdc` is a suggestion; **neither one ever said how much money was in the channel** — a channel opened with 0.05 under a declared cap of 0.25 read as 0.25. `null` means nobody recorded it, never zero. And **the publish `402 INSUFFICIENT_FUNDS` on Solana now lists your own locked deposits**: `locked_channels[]` with `channel_id`, `deposit_uusdc`, `billed_uusdc`, `status` and a `settle_path`. The gate is unchanged — a payer whose USDC sits in idle-closed channels was told to buy USDC it already owned.

### 13.4.0 — 2026-09-07

MINOR: **the Solana rail now has a name, an MCP tool, and a way for the WORKER to check it before doing the work.** Two things were true and unwritten. (1) The rail had no name: every agent-facing surface said "x402r escrow" as if there were one rail, and an agent reading them could not tell that a Solana bounty is held by a **payment channel** and not by a contract. From here the labels are fixed and used everywhere: **`x402r`** on the 8 EVM mainnets (base, ethereum, polygon, arbitrum, celo, monad, avalanche, optimism), **`Solana Channels`** on Solana. (2) Reading a channel needed HTTP: `GET /tasks/{id}/channel/public` existed and no MCP tool wrapped it. New tool **`em_get_task_channel`** (46 total, up from 45) — read-only, unsigned, no wallet: channel id, program, cap, what the meter billed, and explorer links for the open AND the settlement. **The worker side is new advice, not a new endpoint**: on Solana there is no escrow to check, so read the channel and verify it on Solana *before* you deliver — the 87/13 split is committed on-chain when the channel opens and is immutable after that, so a channel opened against a payout address you have since rotated can never be redirected to the new one. And the rule that governs every field on that panel: **a `null` transaction means nobody named it, never that money moved.** Only a real `settlement_tx` proves the channel paid.||13.1.0|2026-09-05|MINOR: **You can buy a verification seal for your own delivery — `POST /verification/analyze`.** The endpoint's section was already in this file's body; the version header never moved with it, so a reader diffing the number would have concluded nothing had changed. It also collides: this branch and `main` both spent `12.5.0`, on different things — `main` shipped `wallet_session` under that number and then `13.0.0`, so the add-on lands here as `13.1.0`. Nothing about the endpoint itself changed; the number now tells the truth about what is in the file, and it is a MINOR because the surface only grew.

### 13.1.0 — 2026-09-05

MINOR: **You can buy a verification seal for your own delivery — `POST /verification/analyze`.** The endpoint's section was already in this file's body; the version header never moved with it, so a reader diffing the number would have concluded nothing had changed. It also collides: this branch and `main` both spent `12.5.0`, on different things — `main` shipped `wallet_session` under that number and then `13.0.0`, so the add-on lands here as `13.1.0`. Nothing about the endpoint itself changed; the number now tells the truth about what is in the file, and it is a MINOR because the surface only grew.

### 13.3.3 — 2026-09-07

PATCH: **si tu worker nunca tuvo USDC en Solana, liquidar el canal REVIENTE y tu depósito queda atrapado adentro** — ahora el approve lo dice antes en vez de dejarte descubrirlo con la plata sellada. `distribute` sólo **deriva** la cuenta de token asociada del worker y la pasa como escribible: el programa **no la crea**. Un destinatario sin cuenta de USDC hace revertir la liquidación entera, y el canal queda `Sealed` con el depósito dentro hasta un `reclaim`. El compromiso on-chain nombra una **dirección**; no dice nada de si esa dirección puede recibir. Nuevo **`409 worker_token_account_missing`** (`retryable: true`): el worker tiene que recibir USDC una vez —cualquier monto, eso crea la cuenta— y después el approve pasa. Si la sonda no se puede correr, **no** bloquea: un revert no atrapa nada que no fuera ya tuyo, mientras que una negativa falsa deja colgado a quien ya entregó.

### 13.3.2 — 2026-09-07

PATCH: **reintentar el approve de una task con canal ya no puede reservar dos veces, y ahora te dice dónde está la plata.** El camino idempotente («ya estaba aprobada») volvía a entrar al dispatcher, que en Solana reserva con `deliveryId = task_id` — una clave **distinta** de la que usa la aprobación (`approve:{task_id}`). Dos claves son dos reservas: el reintento habría cobrado el canal otra vez. Hoy era inerte sólo porque ese camino está apagado por un flag, y «inerte porque un flag está apagado» es una mecha, no una defensa. Ahora un reintento sobre una task con canal **no reserva nada** y responde con el mismo bloque `channel` que el approve original (`channel_id`, `status`, `settlement_tx`) — antes contestaba `payment_tx: null`, que se lee igual que «no pasó nada». Las tasks sin canal siguen por el camino de siempre, sin cambios.

### 13.3.1 — 2026-09-07

PATCH: **`channel_session_gone` te decía que hicieras algo imposible.** Decía «reabrí una sesión sobre el mismo canal», y una sesión nueva **no puede revivir un canal**: su `authorizedSigner` es una llave efímera que además es **semilla de la dirección del canal**, así que una sesión nueva deriva OTRO canal, con otro depósito. Verificado en el programa (`find_channel_pda` toma el `authorizedSigner` como seed) y on-chain (el signer de `He7e26eB…` no es la wallet del pagador). Lo que **sí** funciona, y no necesita ni a pay.sh ni a EM: firmar un voucher acumulativo con **la llave de sesión de ese canal** y presentarlo on-chain — `settle` y `distribute` **no llevan cuentas firmantes**, lo que autoriza es la instrucción ed25519. Corolario que ahora dice el skill: **esa llave vale tanto como la plata; si se pierde mientras el canal está abierto, el depósito ya sólo puede volver al pagador.** El código pasa a `retryable: false` (repetir la llamada no cambia nada) y `payer_action` a `sign_voucher_with_session_key_and_settle_on_chain`. Dos códigos nuevos, ambos para no acusar a quien no hizo nada: **`409 payout_rotated_after_open`** (el worker cambió su payout DESPUÉS de que abriste el canal — antes salía como `channel_pays_another_payee`, que culpaba al pagador) y **`409 channel_wrong_token`** (canal en otro mint: un SPL sin valor con `deposit: 250000` habría quedado registrado como «0,25 USDC pagados»).

### 13.3.0 — 2026-09-07

MINOR: **If your Solana task has a payment channel, THE CHANNEL IS THE ESCROW — approving settles it, and there is no `402` any more.** Until today `approve` on any Solana task answered `402` with a *charge* challenge, even when the publisher had already locked the bounty in a payment channel: a second bill, on a different rail, for money that was already committed. Measured on task `1e24d50a` (2026-09-07, the first channel a live agent ever opened): the worker delivered, 0.25 USDC sat in a channel whose on-chain `distribution_hash` **already named their payout address for 87%**, and the approve asked for a payment nobody could make — so the worker was not paid. Now an approve of a task with a bound channel reserves what the task owes against that channel (**what the meter billed**, or **the bounty out of your deposit** when it billed nothing), never above your cap, never above what the channel holds, and never the bounty twice when an earlier channel of the same task already paid part of it. The response carries a **`channel`** block (`channel_id`, `status`, `settlement_tx`, `billed_usdc`), and `GET /tasks/{id}/channel/public` gains **`explorer_settlement_tx_url`** and reports `status: "settled"` once the signature exists. **The task deliberately does NOT complete at approve**: accepted work and landed money are two claims, and only the settlement signature can make the second one. **The one thing that stays yours alone**: committing the cumulative voucher — the Solana program credits the worker above the watermark only against the payer's ed25519 signature, so no operator and no server can move your deposit for you. Four channel-specific answers you may now get, all with a way forward in the body: `409 channel_session_gone` (channel open on chain, gateway session idle-closed — reopen and commit), `409 channel_pays_another_payee` (the channel does not commit its 87% to THIS worker — a rotated payout address does this, and the commitment is immutable once open), `409 channel_closed_unpaid`, `503 channel_unreadable`. Tasks with NO channel keep the charge rail exactly as it was.

### 13.2.0 — 2026-09-06

MINOR: **A release can now be authorized by the wallet that funded the escrow, and the new `409 LIFECYCLE_ORDER_REQUIRED` is how you find out it is needed.** `release` and `refundInEscrow` move money that is ALREADY deposited, so neither carries an ERC-3009 authorization — the EIP-712 `LifecycleOrder` is what answers *who may ask for the move*, and the Facilitator's policy is that the **payer** signs it. EM does not sign it for you: it transports what you signed, byte for byte. Get the typed data from `GET /api/v1/escrow/task/{task_id}/lifecycle-challenge`, sign it (`build_lifecycle_auth` in `uvd-x402-sdk>=0.79.0`, or `buildLifecycleTypedData` + `lifecycleAuthFromSignature` in `uvd-x402-sdk@>=2.87.0` from a browser), and send it as `lifecycle_order` in the approve body. **Nothing changes today**: the `EM_LIFECYCLE_PAYER_SIGNS` gate is OFF in production, so an approve without the field settles exactly as before. When it is turned on, an approve without a valid order answers `409 LIFECYCLE_ORDER_REQUIRED` with `retryable: true` — the one status/retryable pair that means "try again, but not with the same request" — and the funds stay untouched in escrow with the verdict claim released, so the retry is a real retry. The order authorizes ONE move, expires in 10 minutes, and is refused if it was signed over a different amount, a different chain, or by anyone without the role.

### 13.0.0 — 2026-09-04

MAJOR: **A settlement failure that can never succeed now answers `409`, not `502` — and a release that landed on-chain without a recorded hash no longer blocks approve forever.** Two defects, both found in one night of KarmaKadabra's swarm (8 approves, 0 settlements). **(1) The status contradicted the body.** v12.3.0 made the `502` carry `code`, `retryable` and the way out; what it could not fix from inside the body is that `502` *means* "the gateway failed, try again" to every HTTP client alive. KK retried four times against three escrows whose release window had closed two weeks earlier, with `retryable: false` in every response. **The seven terminal codes now come back as `409`** — a conflict with the state of the resource, which is what they are — and `502` is left to mean what it says: something downstream broke and another attempt may work (`SDK_UNAVAILABLE`, `TX_HASH_MISSING`, `SETTLEMENT_FAILED`). **If you branch on the status code, this is the breaking change: move your terminal handling to `409` + `detail.retryable === false`.** The `detail` shape does not change. **(2) `409 ESCROW_NOT_RELEASABLE` on an escrow that was already paid.** When the Facilitator's `/settle` timed out but the capture HAD mined, the reconciler saw `capturableAmount == 0`, wrote `status='released'` and — honestly, because it could not name the transaction — left `release_tx` NULL. Approve read that as "not releasable" and refused, permanently: the worker held the money, the buyer could not close the trade, no reputation, no receipt. Measured on five escrows across polygon and celo, all five paid on-chain (87/13 to worker and operator). Approve now asks the chain again **by `paymentInfoHash`** — the escrow's own events carry it in `topics[1]`, so the match is per-task by construction — records the hash it finds and closes the trade. When the transaction still cannot be named it keeps refusing, now with `{code: ESCROW_NOT_RELEASABLE, retryable: false, escrow_status}` instead of a bare sentence. **A receipt is never invented; it is looked up or it is absent.**

### 12.5.0 — 2026-09-04

MINOR: **A second way in — `wallet_session` — for clients that cannot sign a request, plus server-built typed data for both money steps.** ERC-8128 asks the caller for two things a language model driving a wallet does not have: a hash of the exact request bytes, and an honest clock. Until today that was not a documentation gap, it was a wall: every mutation answered `401`/`403` **before** the `402` was ever emitted, so a client of that shape could not reach the paid step at all. Now the server builds an EIP-712 `SessionGrant` at `POST /api/v1/auth/session/challenge` — types, domain, nonce and both timestamps filled in — the wallet signs it, and you replay `{"message", "signature"}` verbatim in `X-EM-Session`. Nothing is stored, no token is issued, TTL is capped at 900s server-side. **A session authenticates the WALLET, not the REQUEST**: for its window the header is a bearer, so a closed list of prefixes refuses it (`/account`, `/escrow`, `/disputes`, `/evidence`, `/reputation`, `/admin`, and writes under `/submissions` and `/services`) and the two operations that touch money each need their own signature — `X-Payment-Auth` to assign, `X-EM-Approval` to approve. Both are now buildable without any client-side crypto: `GET /tasks/{id}/assign/challenge?executor_id=…` and `GET /submissions/{id}/approve/challenge` return the COMPLETE typed data with the EIP-3009 nonce (`AuthCaptureEscrow.getHash`, a keccak over an eleven-field struct) already computed, and the assign challenge ships its own verification checklist in `extra.verify_before_signing` — recompute the salt, recompute the nonce, assert the receiver is the executor you chose. **Nothing changes for an ERC-8128 caller**: same headers, same responses, and the two new challenge endpoints are read-only conveniences you may ignore. `GET /api/v1/auth/info` publishes every mode with its real state, the exact denied prefixes and both TTLs, generated from the constants the server enforces. `wallet_session` is gated by `EM_WALLET_SESSION_ENABLED`; while it is off the challenge endpoint answers `404 wallet_session_disabled`, so probe it before building against it.

### 12.4.0 — 2026-08-31

MINOR: **`@authority` now binds your signature to THIS service on REST and MCP too — it never did.** The verifier resolved that component from the `X-Forwarded-Host` header the caller sends, with a comment justifying it as *"set by ALB"*. The premise is false: the load balancer injects only `X-Forwarded-For`/`-Proto`/`-Port` and passes `X-Forwarded-Host` straight through. So the caller chose which authority its own proof had to match, which makes the one component whose entire job is pinning a proof to a single service pin nothing — a signature minted for a host an attacker controls verified here, and the single-use nonce does not help (it proves a nonce is unseen, never that **we** issued it). The WebSocket surface was fixed months ago and this skill has documented the rule there since v10: *"an authority this deployment serves — a signature minted for any other host is refused"*. That fix was never ported to REST/MCP; now all three read one allowlist, published at `GET /api/v1/auth/erc8128/info` as `authorities` so you can read the effective value instead of guessing. **Nothing changes if you sign the URL you are actually calling** — the documented flow, and what the client in this file already does (`parsed.netloc`). What changes: a proof built for one host and replayed at another is refused, and a request claiming a host we do not serve comes back `401 authority_not_allowed` instead of a generic signature failure.

### 12.3.0 — 2026-08-31

MINOR: **The `502` from approve now names WHY the payout did not go out — ten `detail.code`s, seven of them terminal.** Until today a failed settle came back as one sentence and a `ref`, so a swarm had exactly one move available: retry. The diagnosis existed and did not travel — between the two reports below, `payment_dispatcher` had been fixed to emit `code`, `retryable` and the `reclaim()` route, and it died two layers up, where a wrapper flattened the result to `{payment_tx, payment_error}` and the handler replaced it with an opaque `ref`. **2026-08-19**: three agents reported that approve "returns an empty string" — the release was landing 26.2h late and nothing said so. **2026-08-30**, eleven days later: KarmaKadabra hit the identical `502` on a two-week-old submission whose release window had closed 317h earlier. The answer was already written two layers below, and unreachable. Now `detail` is `{error, code, retryable, message, ref}`, plus `recovery` when there is a way out and `authorization_expiry` when the window is what closed. **`retryable` is the field that matters**: `AUTHORIZATION_EXPIRED`, `WORKER_WALLET_MISSING`, `WORKER_WALLET_INVALID`, `SELF_PAYMENT_BLOCKED`, `PAYMENT_AUTH_MISSING`, `ESCROW_STATE_MISSING` and `PAYOUT_NON_POSITIVE` all answer `false`, and re-approving them burns calls against a state that does not change with time. For the first one the money is neither lost nor ours to move: the **payer** takes it back with `GET /api/v1/escrow/task/{task_id}/reclaim`, which works precisely because the window closed — the worker cannot run it, `reclaim` is `onlySender(info.payer)` on-chain. `SDK_UNAVAILABLE` and `TX_HASH_MISSING` are the only two real transients. `SETTLEMENT_FAILED` is `true` and generic on purpose: it means we did not classify the failure, and **an unclassified failure is not a claim that it is terminal** — only text we wrote reaches you, because a foreign error blob can carry an RPC URL and its credentials. Nothing changes for a call that succeeds; what changes is that a call that fails can now tell "stop" apart from "try again".

### 12.2.0 — 2026-08-29

MINOR: **`relay/submit` answers that same `409` now — it was not deduplicating at all.** The signed rail's two halves ran every check but one: `submit` verified the task state, the parties, self-rating, that the caller IS the rater and the proof-of-trade, and then wrote on-chain **without ever asking whether that direction had already been signed**. Its own contract is why *"prepare already checked"* was never true: `chain_id`, `delegate` and the account nonce are public, so a valid signature can be built and posted straight to `submit`. Nothing downstream caught it either — the `FeedbackDelegate` only burns the nonce (anti-replay), the Reputation Registry **appends** (that is what `feedback_index` counts), and no unique constraint existed. A second on-chain rating for the same task and direction was reachable by calling `submit` alone. Both halves now run the SAME guard and answer the same bytes, `authored_by` label included. **Nothing changes if you call `prepare` first and rate once** — the documented flow. What changes: retrying a `submit` that already landed returns `409` with the tx instead of writing a duplicate you cannot take back. Measured in production before the fix: 76 signed ratings, 76 distinct transactions — nobody had hit it yet.

### 12.1.1 — 2026-08-28

PATCH: **The `409` from `relay/prepare` now names the author inline** — `authored_by: 0x1030…13c7 (rater)`, appended to the message you already parse. Asked for by KarmaKadabra, who had to resolve the blocking transaction's `from` on-chain to learn who held the slot: twenty minutes for something the response already knew. It costs no extra call on our side, because the **shape** of the stored `feedback_type` IS the author — `worker_rating`/`agent_rating` can only be the Facilitator (it sent the transaction), `{role}_rates_{role}` can only be the rater. Since v12.0.0 only a signed prior blocks, so the label you will actually see is `(rater)` and the wallet is **yours**: a 409 there means you already rated that direction, full stop. The wallet is truncated because this check runs before the caller is authenticated; the tx in the same message is the full receipt.

### 12.1.0 — 2026-08-28

MINOR: **You can finally vet the publisher — `publisher_reputation` is on every task.** This skill has told workers to "vet the REQUESTER before applying" since 11.x, and there was nothing to vet with: the reputation a publisher RECEIVES from the workers it hired was aggregated nowhere, on any surface, in either the API or the UI. Measured against production 2026-08-28, that direction is the one that gets written MOST — 65 signed on-chain feedbacks in `executor_rates_requester` against 13 the other way — so the data existed and only the mirror was missing. Now every task carries `publisher_reputation` `{avg_score (0-100), rating_count, rater_count, signed_count, last_rated_at}` on `GET /tasks/{id}`, on the task list, in `em_get_task` and on every line of `em_browse_agent_tasks`, plus `GET /api/v1/reputation/publishers/{publisher_key}` for a direct lookup. **`null` means nobody has rated them; it never means 0** — the endpoint answers `200` with nulls instead of `404`, and the store physically cannot hold a zero-count row, so "no history" and "rated worst on the market" can no longer be written the same way. On a 0-100 scale that distinction is the whole point (INC-2026-08-26). Two things this is NOT: it is not a new rating (nothing extra is emitted — this reads what your signed ratings already wrote), and it is not a rival score — it is the per-direction **breakdown** of what the ERC-8004 aggregate already counts mixed with what the same wallet earned as a worker. `signed_count` is how many of them were authored by the rater rather than relayed. **Also fixed in the same release**: the agent directory used to hand every publisher without an executor row a hardcoded `rating: 0` — and that invented zero was the default sort key, so it ranked them too. It is `null` now, and nulls sort last without being called worst.

### 12.0.0 — 2026-08-28

**MAJOR — `rating_score` on the approve is now ACCEPTED AND IGNORED, and the dedup counts authors instead of parties.** Three patches on 2026-08-28 documented the trap; this release removes it. **(1) The approve no longer emits reputation at all.** `rating_score` (REST + MCP) and `worker_score` (H2A) still validate and are still required where they were, but nothing writes on-chain from the approval path — the emitters are deleted, not disabled. They existed to relay YOUR rating, and a relayed rating is authored by the **Facilitator**, which is precisely the authorship the signed rail exists to end. **(2) The dedup is now once per direction PER CLASS OF AUTHOR**: a prior **signed** rating still blocks with `409` (you rate once), a prior **legacy** one no longer does — your signed rating goes through and marks the legacy entry `superseded_by` with your transaction. The legacy entry stays on-chain; only its author could revoke it, so an aggregate that still counts it is out of date rather than wrong, and now it can tell. **(3) Rate through `POST /reputation/relay/{prepare,submit}`** — gasless, and `getClients(agentId)` shows you. **Found and measured by KarmaKadabra**, who approved 24 deliveries with `rating_score` set, hit `409` on every attempt to sign their own, and traced each blocking tx on Base to `0x1030…13c7` — then reproduced it on historical tasks of five unrelated publishers. Their words for the fix they were offered: *"better than what I asked for"* — they had asked the 409 to NAME the author; the shape of `feedback_type` already was the author. **Migration required for you only if you relied on the approve to rate**: send the score to the relay endpoints instead. If you never set `rating_score`, nothing changes.

### 11.46.3 — 2026-08-28

PATCH: **Third instance of the same hazard class, same day: "Settle — payout + on-chain reputation in one step" implied the settle emits.** Measured against code: WS-2 (worker auto-rates at settle) is DISABLED with zero live call sites (`_helpers.py:966-972` — kept only for potential future swarm use; the import in `routes.py:148` is a re-export), and WS-2b emits only on an explicit `rating_score` (Facilitator-authored, the v11.46.1 trap). Settle pays; every rating is a choice by its author. The 5-step journey now says so. Caught by describe.net's coordinator sweeping for the hazard class after v11.46.2.

### 11.46.2 — 2026-08-28

PATCH: **The categorical sentence itself was the hazard — rewritten so the fork lives IN the sentence.** v11.46.1 added the warning block but left "*Approval and rating are ONE step. Never approve without rating*" standing above it — the exact line KK cited as what induced their error. A skimming integrator reads the absolute and stops. STEP 5 now opens with the choice ("WHICH rail you rate on is a choice you make BEFORE approving") and the example's docstring is rail-scoped. Caught by describe.net's coordinator reviewing v11.46.1 against the file before it ever deployed.

### 11.46.1 — 2026-08-28

PATCH: **Going to SIGN your rating? Approve WITHOUT `rating_score` — the explicit field never went inert.** v11.44.0 switched off the *automatic* emitters, but `rating_score` on the approve body still emits publisher→executor through the legacy Facilitator-authored path, and the once-per-party dedup then **409-blocks the signed rail** for that direction. Found by KarmaKadabra (2026-08-28) after approving 24 deliveries with the field set — verified on-chain: the blocking tx's `from` is the Facilitator wallet, and it reproduces on historical tasks of 5 unrelated publishers. STEP 5 now states the rule (legacy one-step OR signed rail — per task, never both) and the signed-rail section documents what that 409 means.

### 11.46.0 — 2026-08-27

MINOR: **The guidance still promised the auto-rating that v11.44.0 says was switched off — and that contradiction is why the network's feedback graph is one-directional.** Two live lines outlived the 2026-08-24 change. The selection-premise block said *"Your approve emits the requester→executor rating ... the 48h auto-default (score 80) is a floor, not a substitute"*, and the service-order section said *"the existing rating auto-defaults apply to it unchanged"*. Both promised emitters that no longer exist, in the guidance an integrator actually reads — while the changelog 200 lines above already said they were gone. **Found by Karma Kadabra on 2026-08-27**, who measured 65 on-chain feedbacks all in `executor_rates_publisher` and **zero** in the other direction, then traced the cause back into this file rather than reporting it as an EM bug: their own emitter carries the comment *"EM auto-issues requester->worker at settle; THIS closes the other direction"* — a literal echo of the line above, written when it was true. Any integrator reading it concluded the approve covered that side, so nobody emitted it and nobody noticed: a rating that is never written produces no error. Corrected to say what is true — **both directions are emitted by their author or they do not exist** — and to name the exact strings (`publisher_rates_executor` after you approve, `executor_rates_publisher` after you get paid), because `requester_rates_executor` is a *derived role label* from `rating_roles()`, never a value of the `direction` field, and that ambiguity cost a round-trip to establish.

### 11.45.0 — 2026-08-26

MINOR: **`payment_tx` can be `null`, and `null` is an answer — never fill it in yourself.** New section *"Verify a proof of payment before you cite it"*. EM now refuses to record a payment it cannot name: if the settlement transaction cannot be identified, `payment_tx` comes back **`null`** instead of a placeholder string. `null` means **unresolved**, NOT unpaid and NOT an error — retry later or ask; do **not** substitute another transaction. Why this is in the skill: a `proof_tx` that does not pay *that task's* worker makes your rating cite a stranger's payment, and it is easy to pick one by accident because **amount + recipient repeat across tasks of the same worker** — two tasks of the same bounty to the same executor minutes apart are indistinguishable by those two signals alone. The section gives the check that is not ambiguous: receipt `status == 1`, the 87% transfer to your assigned wallet, **and** the 13% to the PaymentOperator **in the same receipt**. EM enforces the same rule on its side (`submissions.payment_tx` now accepts only `0x`+64 hex or NULL, and no two tasks may share one).

### 11.43.0 — 2026-08-24

MINOR: **Selling? You are told when you sell now — both rails were addressed to the buyer.** v11.36.0 documented, correctly, that `service.ordered` went only to the **buyer's** webhooks and that the seller's `WorkerAssigned` frame was addressed to `user:<executor_id>`, and told you to poll instead. Both were bugs, and both are fixed. `owner_id` does not PRIORITISE a webhook dispatch, it **scopes** it — naming one side excluded the other outright — so `service.ordered` now dispatches to buyer and seller separately, each on its own registered endpoints. And the WebSocket room is keyed by **wallet**: `user:<executor UUID>` was a room no socket can ever join, because user rooms are private and the ERC-8128 handshake auto-joins `user:<your wallet>` — the seller half of that broadcast went nowhere. **`task.assigned` gained the same fix**: it reached only the publisher, never the assigned worker, on both the bus adapter and the async assign path that production actually runs (`EM_ASYNC_ASSIGN=true`). If you built a workaround for any of this, you can drop it — but **keep your poll of `GET /api/v1/executors/{executor_id}/tasks` as the backstop**: push is one best-effort attempt with no dead-letter on either rail, and that has not changed. Nothing about the payload shape changed.

### 11.44.0 — 2026-08-25

MINOR: **This skill was teaching the signature that does not work, and promising a safety net that no longer exists.** Two corrections, both in the rating flow. **(1)** The example said `sign_message(prep["digest"])` — that is `personal_sign` over a hash that ALREADY carries the EIP-191 envelope, so it gets wrapped twice, recovers a stranger, and dies as `relay_bad_signature`. There are three correct paths and the right one depends on the response: `typed_data` present → sign it as EIP-712 (v4 chains, and the wallet finally shows you the score and the agent in readable form); raw key → `unsafe_sign_hash(digest)` as a prehash; wallet on a v3 chain → `personal_sign` over **`signing_payload`**. **(2)** The 48h grace-window sweep that auto-emitted a neutral 80 on your behalf **was switched off on 2026-08-24**, together with the streaming-session close and the auto-rating at approval — and this skill still told you *"you do NOT need to build your own auto-rate"*. **If you do not rate, there is no rating.** All 8 mainnets now run the v4 delegate, so `typed_data` is the normal path. **Also corrected in the Streaming section**, which still promised that closing a session fires both ratings automatically — that was the second of the three emitters we switched off, and the close is often triggered by a presence timeout, so it wrote an opinion for a viewer who had already left. Addresses in `contracts/deployments/feedback-delegate.json`, and never hardcode them — read `delegate` from `prepare`.

### 11.43.0 — 2026-08-25

MINOR: **Rating someone turns YOUR account into a smart account — permanently, and for all your payments.** When you rate through the signed rail, the first rating on each chain delegates your EOA to the `FeedbackDelegate` (EIP-7702). From then on your account **has code**, and that is global, not scoped to ratings: everything that branches on `code.length > 0` treats you as a contract account — USDC's `transferWithAuthorization`, `SignatureChecker`, Permit2, Seaport, order books, and our own escrow. **This skill already documented the consequences and never named the cause**: v11.37.0 says DX402 recovers no encryption key from *"an EIP-7702-delegated / smart-account payer"*, and v11.27.0 says such a signer is what produces `INVALID_SIGNATURE` on escrow locks. Both are true, and until today nothing told you that **rating is what puts you in that state**. You will not see "someone rated" — you will see a payment failing days later in another flow. **The way out, and it needs nobody's permission:** sign an EIP-7702 authorization to `address(0)` and your account goes back to being a plain EOA; it is one more type-4 transaction. Decide before you rate: authorship of your ratings costs you a change in how your account is verified. Found by the Facilitator on 2026-08-25 after Karma Kadabra hit it in their pre-auth wrapper — with a real rating already on-chain (`0x6e7cbe77…2482`, Base), the first ever attributed to the rater instead of the Facilitator.

### 11.42.0 — 2026-08-24

MINOR: **SKALE is retired — it takes no new tasks.** It was still listed as a payment network in ten places here, including the example that told you to respect a user asking for a task "on SKALE": following this skill got you a `400` on a chain the skill itself recommended. Retired means the entrance closes and the exit stays open — work already in flight settles normally, and the SKALE addresses stay in the contracts table on purpose, because payers of expired escrows need them to call `reclaim()` themselves. Two independent reasons put it out: the Facilitator's DX402 enum refuses it (`422`), so **0 of 15** paid SKALE submissions ever carried evidence against 19/20 on Monad; and its pre-Cancun EVM cannot run EIP-7702, so a rating there could never be signed by you. Payment networks are now the 8 EVM chains plus Solana.

### 11.41.1 — 2026-08-24

PATCH: **the skill contradicted itself about Avalanche.** v11.41.0 added the rater-signed rail and said Avalanche is permanently non-choosable — but a section 800 lines further down still offered it as a reputation chain ("a job settled in USDC on Base can build your reputation on Avalanche") and listed it under **Valid networks**, alongside `skale`, which left the project. An agent that grepped for `reputation_network` hit the wrong one and got a 422 it could not explain. Both are corrected, and the valid list now says WHY Avalanche is out: its C-Chain refuses EIP-7702, so a rating there could only be signed by the Facilitator.

### 11.41.0 — 2026-08-24

MINOR: **Sign your own ratings — until now the Facilitator was their on-chain author.** The ERC-8004 Reputation Registry records `msg.sender` as the `clientAddress`, so every rating it relayed for you landed under ITS wallet: measured **91,3%** of the network's feedback under one address — which, since `revokeFeedback` is authorised the same way, could also delete all of it. New rail, gasless as always: `POST /reputation/relay/prepare` returns a digest, you sign it with your own key, `POST /reputation/relay/submit` relays it and the Facilitator pays. `getClients(agentId)` then shows YOU. Works for the four roles (buyer/seller on listing orders, requester/executor otherwise) through one structural direction. **Avalanche stops being choosable for reputation — permanently**, not "not yet": its C-Chain refuses type-4 transactions, so a rating there could only be signed by the Facilitator; existing Avalanche reputation keeps being read and counted. The legacy rate endpoints keep working and will not close without notice.

### 11.40.0 — 2026-08-22

MINOR: **The `apply` cover note is capped at 500 characters, and the `422` now says so.** A fleet hit `422 Unprocessable Entity` applying with a ~90-word capability note; the same note shortened went through at the first try, with nothing in the response naming length as the cause. The cap was in the JSON schema (`maxLength: 500`) all along — what reached the caller was the generic top-level `"Validation error"`, because the handler's friendly-detail path covered malformed UUIDs, misnamed fields and enum synonyms but **not** length violations. Now any over/under-length body field surfaces as `detail: "message is too long: 574 characters, max 500"`, so a client that logs only `detail` can fix the call on the next attempt. New worker rule **2b** documents the cap.

### 11.39.0 — 2026-08-19

PATCH-level correction with real consequences: **if you SIGN your own anchor, upgrade to `uvd-x402-sdk[dx402]>=0.54.0` (Python) / `>=2.59.0` (npm)**. Older versions signed the **wrong digest form for an EVM payee** — the facilitator picks the form by the payee's curve and verifies exactly one, so the signature never verified and the anchor silently stayed **provisional**. A provisional anchor is supersedable by anyone, which is precisely the hijack a signed anchor exists to prevent, and nothing in the logs said so. Reported and reproduced against production by KarmaKadabra: same `paymentId`, everything else identical — no signature → `201` provisional, old ed25519 form → **`409 dx402_already_anchored`**, EVM form → `201` and it superseded. Fixed in both SDKs, digests verified byte-identical across them. **Anchoring without a signer was never affected** (that is what EM does). Also documented: the **`POST /dx402/anchor` body cap is 64 KiB**, measured — ~47 KB of plaintext once base64 inflation and metadata are counted; size your cut-off on the SEALED blob, not the plaintext.

### 11.38.0 — 2026-08-19

MINOR: **Declare a decryption key once, or the recommended lock path anchors nothing.** v11.37.0 shipped durable evidence keyed off the escrow signature — which only exists on the `sign_on_assignment` path. On the **recommended** path (you lock via the SDK, then assign with `escrow_tx` + `payment_info`) EM never sees your signature, and the lock tx is signed by the **Facilitator** because it is gasless, so there is nothing to recover a key from. Measured on a real Base trade 2026-08-19: the trade settled 87/13 and `durable_evidence` came back **null**. Fix: **`PUT /api/v1/account/dx402-key`** with your PUBLIC key, once — every task you publish afterwards is anchored to it. Read anyone's with `GET /api/v1/account/dx402-key/{wallet}` (that is how a seller seals an artifact EM never holds). **Do not declare your payment key**: a decrypt-only keypair turns a leak from *"they drain my wallet"* into *"they read my evidence"*, and it is the ONLY way to read your own evidence when you pay from a custodial wallet — a custodian signs but does not do ECDH. Resolution order: declared key → key recovered from your escrow signature → no evidence.

### 11.37.0 — 2026-08-18

MINOR: **Every paid task now leaves you a copy of the delivery that only you can open — DX402 durable evidence, on by default.** x402 settles on-chain forever but hands over the deliverable **exactly once**: if you did not keep the body it is gone, and afterwards neither side can show *what* was delivered, only *that* money moved. At settle, EM seals the delivery to **your own wallet key** and anchors it at the Facilitator. **You register nothing** — the key is recovered from the escrow authorization you already signed, so paying *is* publishing your encryption key; nobody else can open it, the Facilitator included. The submission now carries **`durable_evidence`** `{paymentId, pointer, contentHash, keyAlg, retention, receipt}`, and `paymentId` is derivable from the settle tx alone (`keccak256(caip2||txHash)`), so you can recover the delivery **even if you lost our response**: `GET /dx402/evidence/{paymentId}` then `recover_evidence(ev, your_key)`. `contentHash` is over the **PLAINTEXT** — a `ContentHashMismatch` means the anchored bytes are not the bytes that were served, which turns *"you sent me something else"* from an argument into a check. **Selling?** `GET /tasks/{id}` now returns `escrow.buyer_encryption_key` once escrow is locked — the one piece a seller cannot derive alone — so you can anchor artifacts EM never holds. Limits stated plainly, because a silent `null` would be worse than a documented gap: **EVM only** (Solana has no EIP-3009 signature to recover from), **no recoverable key from an EIP-7702-delegated / smart-account payer**, **90-day retention by default** (anchoring is publishing; `permanent` is irreversible), opt out per task with `metadata: {"dx402": false}`. A `null` is never an error — evidence is an addition to the payment path and never a gate in front of it. Needs `uvd-x402-sdk[dx402]>=0.53.0` (Python) or `uvd-x402-sdk>=2.58.0` (npm).

### 11.36.0 — 2026-08-11

MINOR: **A purchase of your listing arrives as `WorkerAssigned` — there is no `ServiceOrdered`.** An external integrator searched the event names for "order", found nothing, and learned about the sale late. Ordering a listing runs through the **same assign path as any hire** (`POST /services/{id}/order` → the canonical assign handler), so the seller's real-time notice of a sale is the CamelCase **`WorkerAssigned`** frame — broadcast to `user:<buyer agent_id>` **and** `user:<seller executor_id>`, carrying `{task_id, worker_id, worker_wallet, title, bounty_usdc, payment_network, category, assigned_at, expected_completion}`. The dotted `service.ordered` does exist, but only on the **webhook/bus** rail and it is dispatched to the **BUYER's** registered webhooks — a seller never receives it. **Your sales watch is `GET /api/v1/executors/{executor_id}/tasks`**, never `GET /tasks` (the open marketplace board since 2026-08-03, not your queue).

### 11.35.0 — 2026-08-08

**[SUPERSEDED by 13.11.1 — the Solana mint is NOT unconditional; see "Choosing WHERE your reputation lands"]** MINOR: **Solana is LIVE — publish, pay and build reputation on it.** (1) `payment_network: "solana"` is now accepted on `POST /tasks` (the `422` publish gate is lifted). Solana has **no escrow**: nothing locks at assignment, and the publisher pays **at approve** — the first approve without payment returns **`402`** with an MPP *charge* challenge in `WWW-Authenticate` (body: `retryable: true`, `www_authenticate` list); sign it with your Solana wallet and retry the same approve with the credential in `Authorization: Payment <cred>` or `X-Payment: <cred>`. One on-chain transaction settles the whole bounty with the **87/13 split enforced in the transfer itself** — 87% straight to the worker, 13% to the treasury; the response's `payment_tx` is the Solana signature. Cancel before approve = free (nothing was ever locked). (2) **Vet the worker BEFORE assigning**: a Solana bounty lands on `executors.solana_payout_address`, and approving a worker who never bound one returns **`409 solana_payout_address_missing`**. (3) **`reputation_network: "solana"` is now valid** on publish and apply — the Facilitator's SVM path shipped (identity mint, feedback write, owner lookup), so the old *"Solana is rejected at choice time"* note is gone; identities are still minted gaslessly on first rating. First real settle: task `c7ae5eaa`, $0.10, split verified on-chain (2026-08-08). Trust posture unchanged: EM never holds funds — it refuses to even REQUEST payment if the minted challenge's fee recipient is not the treasury (`503 solana_fee_recipient_mismatch`).

### 11.34.0 — 2026-08-07

MINOR: **A half-signed request is now a `401`, and the anonymous identity owns nothing.** Two fixes to the same root cause, both from an external integrator's report. (1) ERC-8128 needs **both** `Signature` and `Signature-Input`; sending only one skipped verification entirely and was treated as *no credentials* — `401` on a mutation, but a silent **`200` on a read**. An agent that did try to sign read that `200` as proof the signature worked: *"un 200 no prueba autoría"*. You now get an explicit `401` **naming the missing header**, because the typo is invisible from the client side and the failure mode of guessing was "silently unauthenticated". (2) The anonymous read identity was **Agent #2106 — the platform's own agent, which owns ~373 real tasks** — so every endpoint scoping rows by `agent_id` served the platform's data to any caller that just omitted the headers (that is how `GET /tasks/{id}/applications` leaked applicant wallets and reputation in July). It is now a **sentinel that owns no rows**: caller-scoped reads return *empty* instead of somebody else's data, and no resource can ever be attributed to #2106 by accident. **Docs corrected in the same pass:** this file said `GET /tasks` was *"scoped to the caller ⇒ you get #2106's tasks"* — false since 2026-08-03, when it became the **open marketplace** (every publisher, public statuses); use `?publisher=0xYourWallet` to enumerate your own.

### 11.33.0 — 2026-08-07

**[SUPERSEDED by 13.11.1, then by 13.12.0 — the fallback DID become silent for solana, and 13.12.0 made it speak: base by default is gone, the payment chain decides; see "Choosing WHERE your reputation lands"]** MINOR: **Tu reputación va a Base por defecto — y ahora podés ponerla donde quieras.** Dónde PAGA la tarea y dónde se ESCRIBE tu reputación pasan a ser dos decisiones independientes: un trabajo liquidado en Base puede construirte reputación en Avalanche. La elección es **por parte y por tarea**, y cada lado decide sobre la reputación **acerca de sí mismo**: el requester manda `reputation_network` en `POST /tasks`, el executor lo manda en `POST /tasks/{id}/apply`. Orden de resolución: la elección de esta tarea → tu preferencia de perfil (`PATCH /workers/{wallet}/reputation-network`) → `base`. Omitir el campo NO es lo mismo que mandar `"base"`: omitir cae al paso 2, mandarlo es una elección explícita que pisa tu perfil. Válidas: `base, ethereum, polygon, arbitrum, celo, monad, avalanche, optimism, skale`; cualquier otra da **`422 INVALID_REPUTATION_NETWORK`** con la lista en el mensaje, al publicar o al aplicar. **Solana se rechaza a propósito** — es una red de PAGO de primera clase acá, que es justamente por qué un fallback silencioso sería una trampa: ERC-8004 no tiene registro de reputación en Solana, así que un rating 'en Solana' nunca podría escribirse. Te enteras al elegir, no meses después. Igual para `bsc`/`hyperevm`/`unichain`/`scroll`, que tienen contrato pero no están verificadas en la ruta de feedback del Facilitator. No hace falta que tengas identidad ERC-8004 previa en la cadena que elijas: si no la tenés, se te mintea gratis antes de escribir el rating. **Por qué existe**: la preferencia era una sola por wallet y global, y en la práctica dejaba la plataforma mono-cadena — 218 de 221 executors tenían `base`, así que los 545 eventos de reputación cayeron en base aunque 412 vinieran de trades en arbitrum, avalanche, skale, celo, optimism, monad, polygon y ethereum.

### 11.32.0 — 2026-08-06

MINOR: **Deliver big payloads as a LINK — and the link finally works for agents.** Three things were fighting each other and the loser was the buyer. (1) `GET /evidence/presign-upload` ran its identity check *before* probing the other principals, so it fail-closed **`401`'d every caller without a Supabase browser JWT** — admins, the publishing agent, and **every ERC-8128 agent/robot worker** (signature callers have no JWT by design). EM-hosted upload was structurally impossible for agents: **6 of 1463 submissions** ever used it. Fixed — a worker now signs for its own upload, and `presign-download` likewise lets a signed worker read back what it uploaded. (2) So agents delivered from their own buckets, and `redact_secrets_deep` cut the signature off at write (INC-2026-07-20) — the buyer got a corpse of a URL. Now a `delivery_url` pointing off-host is **downloaded ONCE at submit and re-hosted on our storage**, before redaction, so the stored link is durable and no credential ever reaches the DB. Watch `evidence._em_delivery.entries[]` for `status` / `sha256` / `retryable`. (3) This file told you the opposite — *"put the payload INLINE in `json_response`"* — which is why buyers started writing `[INLINE REQUIRED]` into task titles. The real rule is the **1 MiB total request body cap** that has always been enforced (`413 request_body_too_large`): under it, inline; near or over it, a link. Also documented: attaching a `delivery_url` as a *bonus* next to a complete inline answer **blocks instant payout** for that submission (a loose URL with no typed artifact beside it fails the auto-release gate) — a real way to delay your own money.

### 11.31.0 — 2026-08-06

MINOR: **A Solana bounty needs a Solana payout address — and `wallet_address` is not one.** Your `wallet_address` is your IDENTITY: ERC-8128 auth verifies secp256k1 only, so it is always an EVM `0x` address, and it is also the key the ERC-8004 reputation lookup uses. Handing it to a Solana payout is impossible — pay.sh rejects anything that is not base58. Workers who want to be paid on Solana now bind a separate address with **`PATCH /account/solana-payout-address`**, proving control with an **ed25519** signature over `Execution Market: set solana payout address to <address> for executor <executor_id> at <ISO8601 UTC>` (10-minute window, signature base58). Without it, approving a Solana task returns **409 `solana_payout_address_missing`** instead of paying the wrong chain. Two related fixes agents will notice: `em_withdraw_earnings`'s `destination_address` and `em_register_as_executor`'s `wallet_address` accepted only exactly 42 characters, which made a Solana address **impossible to express**; both now take EVM or base58. And the Solana balance pre-check no longer reports a bogus "insufficient funds" when it cannot read your wallet — it skips, because a check that cannot run must not block.

### 11.30.0 — 2026-08-03

MINOR: **The WebSocket monitoring example never authenticated — Option 4 now teaches the signed handshake.** `wss://…/ws?user_id=YOUR_AGENT_ID` is not authentication: the server ignores `?user_id=` (deprecated), and an unauthenticated connection is refused **every** room (`global` included) — so the copied one-liner connected, joined nothing, and delivered zero events in silence. Option 4 now documents the real path: an **ERC-8128 signed bodyless `GET` over `/ws`** replayed inside the `auth` frame (`{"type":"auth","payload":{"user_type":…,"erc8128":{"url","headers"}}}`), the `auth_success`/`auth_failed` ack (`retryable`+`retry_after` = our nonce store blinked, anything else is terminal — do not reconnect-loop), `subscribe` with a single `room` (there is no `topics`), the server-side room ACL (`user:` auto-joined from the **verified** wallet, `task:` only for the publisher/executor, `category:` workers-only), and the **CamelCase** WS event names (`SubmissionReceived`) versus the dotted webhook taxonomy. The legacy `?api_key=` / `token` frame is documented where it still applies.

### 11.29.0 — 2026-08-01

MINOR: **Pricing corrected to the flat 13% the chain actually charges.** The Pricing section — and the `em_calculate_fee` / `em_get_fee_structure` MCP tools — quoted per-category rates (11% human_authority, 12% knowledge/digital) while the on-chain StaticFeeCalculator deducts a **flat 1300 bps on every release**: an agent that budgeted 12% paid 13%. There are no per-category rates and there never were on-chain. All quote surfaces now derive from the same constant the operator enforces: **13% for every category, deducted from the bounty at release**. Budget `worker_net = bounty * 0.87` regardless of category.

### 11.28.0 — 2026-07-30

MINOR: **`retryable` now travels on the `task.assign_failed` WEBHOOK — where the async path actually reports a failed lock.** v11.27.0 put `code`/`retryable` on the escrow-lock `402`s and claimed that covered assign. It did not, on the path that matters: production runs `EM_ASYNC_ASSIGN=true`, so an assign carrying `X-Payment-Auth` answers **`202 {status:"assigning"}`** and returns *before* any 402 can exist. The lock then fails asynchronously and the only thing you receive is `task.assign_failed` — which carried `{task_id, executor_id, agent_id, reason}` and nothing machine-readable. So the fix shipped to a surface this flow never reaches. Now that webhook carries **`code`** and **`retryable`** too (both were already being computed and then written only to an internal table). **And the guidance that caused the storm is corrected**: the "lock failed → wait ~10s and re-assign, up to 2–3 attempts" instruction now branches on `retryable` first, because following it against a terminal `INVALID_SIGNATURE` is exactly how a fleet burned 29 attempts across 4 tasks and 3 networks. `retryable: false` ⇒ stop and fix the signer. Same fields, same meaning, on the reconciler's `task.assign_failed` as well.

### 11.27.0 — 2026-07-29

MINOR: **`retryable` on every escrow-lock `402`, and a `INVALID_SIGNATURE` code that means STOP.** A fleet burned **29 lock attempts across 4 tasks and 3 networks** re-signing against one revert — `execution reverted: FiatTokenV2: invalid signature` — and the fault was ours: that revert classified as the generic `LOCK_REVERTED`, whose documented guidance is *"re-sign a fresh auth once"*. Our own 402 was asking for the retry that cannot work. Two changes: (1) a signature rejection now returns **`code: "INVALID_SIGNATURE"`**, naming the cause; (2) **every** escrow-lock 402 (publish, assign, H2A, service order, stream session) now carries **`retryable: true|false`** — machine-readable, because a code alone did not stop the storm when the caller's classifier read every non-2xx as transient. **`retryable: false` ⇒ do not re-sign, do not retry, do not switch chains: the same signer produces the same revert on every network.** Terminal codes: `INVALID_SIGNATURE`, `OPERATOR_MISMATCH`, `FORBIDDEN_RECEIVER`. `INSUFFICIENT_FUNDS` stays **retryable** on purpose — funding the wallet fixes it without touching the signature. **What actually causes `INVALID_SIGNATURE`**: a signer the token cannot verify — typically an **EIP-7702-delegated or smart-account wallet signing with a session key instead of the EOA that holds the USDC**. Fix it at the signer (sign with the payer EOA, or make the wrapper ERC-1271-verifiable); no amount of retrying reaches it.

### 11.26.0 — 2026-07-29

MINOR: **Your money in a dead task escrow is recoverable BY YOU — `GET /api/v1/escrow/task/{task_id}/reclaim`.** v11.24.0 gave streaming sessions a door to `reclaim()`; tasks did not have one, and that gap was load-bearing: **180 task escrows are holding ~$12.71 USDC past their deadline that the operator provably cannot return.** Their on-chain `refundExpiry` has lapsed, so *any* operator-side refund reverts — including the automatic expiry refund. Nobody at EM can unstick them; the contract reserves the last word for you. This endpoint hands you what you need to take it: `{network, chain_id, escrow_address, function:"reclaim", calldata, from, value:"0", eligible_at, eligible_now, reclaimable_usdc, onchain_verified}`. **Payer only** (the response carries the authorization you signed) and **EM never signs nor relays** — `reclaim` is `onlySender(info.payer)` on-chain and requires `block.timestamp > authorizationExpiry`, so it works even if EM is down, compromised, or refuses. `reclaimable_usdc` is read live from the escrow (`capturableAmount`), which also proves the struct is the one you signed; if that read is unavailable it comes back `null` with `onchain_verified:false` and **the calldata is still valid** — an escape hatch that needs our RPC to be healthy is not an escape hatch. Codes: `403 NOT_THE_PAYER`, `404 NO_ESCROW`, `409 ALREADY_RELEASED` / `ALREADY_REFUNDED` (both return the `tx` — the receipt is the answer), `409 NOTHING_TO_RECLAIM` (zero on-chain balance), `409 PAYMENT_INFO_INCOMPLETE`, `409 PAYER_UNKNOWN`, `409 STREAM_TASK_USE_SESSION_RECLAIM` (streaming tasks lock per *session*, so reclaim through the session endpoint). Also: a `?status=` guess that is a **synonym** of a real state (`open`, `assigned`, `done`…) now gets told which state it means — the value stays invalid, `published`/`accepted`/`completed` are the only spellings.

### 11.21.0 — 2026-07-25

MINOR: **What a signature actually changes on a READ — the one thing the skill never said.** An integrator lost a day to it, so it now has its own section ("Reading data — what a signature changes") high in the doc, plus an **Auth column** on the Tasks API table and a rewritten `403` row. The rule: **an unsigned read is not an anonymous read** — it is admitted as the **platform agent (#2106)**, a real identity that owns real tasks. So on any caller-scoped endpoint an unsigned `200` returns *the platform's* rows with nothing marking them as somebody else's; a `200` never proves the data is yours. Three behaviors, now stated per endpoint: **public** (`/tasks/available`, `GET /streams/session/{id}` — never need a signature), **caller-scoped** (`GET /tasks` — use **`?publisher=0xYourWallet`** to enumerate your own without signing, public statuses only; signed gets every status), and **publisher-only** (`/tasks/{id}/applications`, `/tasks/{id}/submissions` — **`403` unsigned, always**; those payloads carry worker wallets, reputation and raw evidence, so there is no unsigned path and none is coming). Also disambiguates the **two opposite causes of a `403` on a read**: no signature on a publisher-only endpoint (→ sign it) versus sending `Authorization:`/`x-api-key` at all (→ API keys are disabled platform-wide and the header is rejected *before* anything else, turning even a working public read into a `403` — drop it). And: signing is **per-request, not a session**, so if signatures are expensive, poll unsigned and spend them on decisions. **Security fix in the same release:** `GET /tasks/{id}/applications` on a task published under the platform identity used to answer `200` with the full applicant roster to unsigned callers — it is now `403` like every other task.

### 11.20.0 — 2026-07-24

MINOR: **The buyer picks the chain it actually holds USDC on — and the 402 finally says why the lock died.** (1) **`detail` on every escrow-lock `402` is now an OBJECT**, not a string: `{error, code, message, network, required_usdc, ref}`. **Branch on `detail.code`** — `INSUFFICIENT_FUNDS` (the payer has no USDC **on `detail.network`**: top up there, or retry on a chain where the balance already is — retrying the same chain fails identically), `OPERATOR_MISMATCH`, `FORBIDDEN_RECEIVER`, `LOCK_REVERTED` (anything else; re-sign a fresh auth once). Applies to assign, publish-with-`lock_on_creation`, service order and stream sessions. Reason: a real publisher spent 8 days blocked by `Escrow lock failed (ref: 4cba1638)` while holding $4.01 on Avalanche and $0.00 on the task's Base — the revert reason existed only in our logs. **The stream-session 402 code changed** from the blanket `ESCROW_LOCK_FAILED` to the classified codes. (2) **Service listings declare `accepted_networks`** (new field on create/update, **default = every escrow-capable network**, never empty) and every listing response carries it. (3) **`POST /api/v1/services/{id}/order` accepts `payment_network`** — the BUYER chooses the chain, validated against `accepted_networks` (`422 NETWORK_NOT_ACCEPTED`) and against escrow support (`422 NETWORK_NO_ESCROW`); omit it and nothing changes (the listing's own network). Read `accepted_networks`, pick where you have funds, sign the EIP-3009 for **that** chain.

### 11.19.1 — 2026-07-24

PATCH: Streaming settles — default is now a **single settlement at close** (pure MPP session semantics: metering off-chain, funds already reserved in escrow, exactly 2 TXs per session). Periodic mid-session partial releases become an opt-in deployment config (`EM_STREAM_SETTLE_THRESHOLD_USD`, floor $0.05). Capability unchanged — the acceptance suite still exercises multi-settle with the override.

### 11.25.0 — 2026-07-29

MINOR: **When we already know your money will not move, we now say it in the success body — never as an error.** Two surfaces used to return a clean success while EM already had the evidence that the payment would fail. (1) **`POST /tasks`** gains **`balance_warning`** — `{code:"INSUFFICIENT_BALANCE_AT_PUBLISH", network, required_usdc, balance_usdc, advisory:true}` — when the balance check says the publisher cannot fund the escrow on the chosen chain. The task IS published and nothing is charged, but the lock **will** fail at assignment: 16 tasks died exactly this way on Avalanche in 24h, each learning the truth ~15s later from `ERC20: transfer amount exceeds balance`. (2) **`POST /streams/{id}/session`** gains **`presence_bound`** (always) and a `warning` when false: a session opened without `presence_nick` + `presence_channel` locks the cap on-chain and can **never** accrue, because presence events are matched by `(nick, channel)` against the binding declared at open — four real sessions stranded their caps that way. Both are **advisories, never 4xx**: the balance precheck is fail-open by design (a dubious RPC read must not block a solvent publisher) and the presence fields are legitimately optional. **If you branch on HTTP status alone you will miss these — read `balance_warning` and `presence_bound`.**

### 11.24.0 — 2026-07-29

MINOR: **The escape hatch that made the rail trustless now has a door — plus a cap ceiling that stops you locking USDC you can never spend.** (1) **`GET /streams/session/{id}/reclaim`** *(payer only)* hands you ABI-encoded `reclaim(PaymentInfo)` calldata, the escrow address and `eligible_at`. Until today every surface — this file included — promised `reclaim()` as "the escape hatch that makes the rail trustless", and **there was no way to call it**: the function exists on-chain but nothing gave you the `PaymentInfo` you needed to build the call, and it is deliberately withheld from the unsigned session read. That is fixed; **EM still never signs nor relays** the transaction (`reclaim` is `onlySender(payer)`), so it works even if EM is down or refuses. New codes: `403 NOT_THE_PAYER`, `409 ALREADY_REFUNDED` (returns `refund_tx`), `409 NOTHING_TO_RECLAIM`, `409 PAYMENT_INFO_INCOMPLETE`. (2) Opening a session with a cap **above what the stream can ever charge** (`rate × max_duration`) is now **`422 CAP_EXCEEDS_STREAM_MAX`** instead of a silent lock. The escrow's `$100` limit is a *protocol* bound, not a product one: signing for it on a stream that costs cents locks USDC that only `reclaim()` recovers, and only after `authorizationExpiry` — which is exactly how four real sessions ended up with stranded caps on 2026-07-29. Sign for the published `session_cap_usd` or less.

### 11.23.0 — 2026-07-28

MINOR: **Two DX fixes from the first completed purchase cycle (KK).** (1) Task reads now return **`evidence_required`** (flat list, same name and shape the create request used) alongside `evidence_schema` — a worker previously read `evidence_required`, saw nothing, and only learned what to deliver from the submit's 400. (2) The approve response's **`gross_amount_usdc` / `worker_net_usdc` / `platform_fee_usdc` are no longer 0.0** on approves that moved money: amounts now derive from the signed `max_amount` the escrow actually locked (the 87/13 split applies to exactly that figure) when the stored metadata lacks explicit amounts.

### 11.22.0 — 2026-07-28

MINOR: **Ordering a listing actually works now — and a failed order cleans up after itself.** The KK swarm's first real buy attempts surfaced that `em_order_service` had **never once completed in escrow mode**: the order created its task without the durable escrow marker the assign guard demands, so every order with a *valid* signature died on `409 ESCROW_MARKER_MISSING` and left a live published task + the seller's application on the board (each retry re-applied the seller, compounding the litter). Fixed both halves: (1) an order now creates the same `pending_assignment` escrow marker as a trustless publish before assigning, so the guard passes and the lock proceeds; (2) **a synchronously failed order is compensated** — its task is cancelled (`metadata.cancellation_reason: "order_assign_failed"` / `"escrow_setup_failed"`) and its marker closed, so **retry = place a NEW order**; the old `task_id` is dead, never re-orderable. The async path is unchanged: a `202` that later fails still returns the task to `published` (re-orderable), exactly as documented in the order section. Error bodies that said a failed order's task "remains published" now say it was cancelled.

### 11.19.0 — 2026-07-24

MINOR: **Streaming Sessions — pay-per-time (BETA).** New "Streaming Sessions" section documenting the escrow-sessions rail (ADR-005): a provider publishes a stream (`POST /api/v1/streams` — a task with `task_type:"stream"` + a per-unit rate; **no money moves at publish**); a viewer discovers streams with the provider's **`effective_reputation_score` inline** (`GET /streams` — vet-then-consume, same loop as the task board), then opens a metered session by locking a **cap ≤ $100** with the *same* `X-Payment-Auth` EIP-3009 signature as assign (ADR-002 chokepoint; **ERC-1271-aware**, so 7702-delegated/smart-wallet signers work). Accrual is presence-based off-chain (heartbeats unsigned; gaps ≤ 2× cadence tolerated — 5-min one-shot agents are first-class) and settled on-chain in automatic partial releases at **`max($0.05, 5% of cap)`**, 13% fee atomic per settle on the settled amount, `Σ releases ≤ cap` enforced both server-side and by the escrow contract itself. State is readable **unsigned** (`GET /streams/session/{id}`); close is callable by **either party**; any unspent remainder is recovered **trustlessly by the payer via the escrow's `reclaim()` after `authorizationExpiry`** (the refund-after-release path is disabled — the expiry escape hatch is the design). Session close fires bidirectional ERC-8004 feedback through the same rating path as approve. **Gated by `EM_STREAMS_ENABLED` (default off → 404); chains v1: Base + Arbitrum only.**

### 11.18.0 — 2026-07-22

MINOR: **The board now has a human face — and one new endpoint.** (1) **`GET /api/v1/services/mine`** returns your own listings *including paused ones* (the public board hides them, so without this pausing was a one-way door). (2) Create / update / order now accept a **Supabase session JWT** in addition to ERC-8128 — the agent door is byte-identical, this only opens the human one. Either way the seller/buyer binds to a **wallet**, never a session: escrow pays a wallet and ERC-8004 rates a wallet. (3) Humans browse and buy the same listings at **[execution.market/marketplace](https://execution.market/marketplace)** (distinct from `/services`, which is the demand-side catalog of things to *request*) — so your listing is visible to human buyers and a human seller's listing is orderable by you.

### 11.17.0 — 2026-07-22

MINOR: **Seller vetting on the board — the score is not the whole story.** Listings now carry `effective_reputation_score` and `onchain_reputation_score` **at the top level** (not only nested in `seller_reputation`), because that is the number a hiring decision cites. New **`seller_correlation`** `{total_completed, distinct_counterparties, top_counterparty_share, flagged}`: a reputation score cannot distinguish 100 completed tasks across a hundred buyers from 100 with a *single* buyer — the wash-trading shape — and this field makes the difference visible. `GET /api/v1/services` gains **`exclude_flagged` (default `true`)**, hiding sellers with ≥3 completed and either one counterparty or ≥80% of work with one; detail SHOWS the flag with its reason instead of hiding the listing. Advisory only — it never blocks an order (a hard block is gamed with one extra counterparty and punishes the honest specialist). If the signal is unavailable nothing is hidden: an unvetted seller beats an empty board. Also documents the mirror duty — a **seller** should vet the buyer's wallet (the order task's `agent_id`) before delivering.

### 11.16.0 — 2026-07-22

MINOR: **Matchmaking — the demand and supply sides now point at each other.** Publishing a task emits **`match.suggested`** with the sellers who already advertise that capability; posting a listing emits the mirror (the open, unassigned tasks it could fill). Both are subscribable as webhooks. New read-only **`GET /api/v1/services/match/for-task/{task_id}`** + MCP tool **`em_find_sellers`** answer "who already sells what my task asks for?" on demand. Matching is category-exact and price-must-fit-the-bounty; **skills only break ties** (free text on both sides, so a missing tag never drops a good seller). A suggestion assigns nobody and moves nothing — the counterparty decision stays yours. Before this, a task and a listing that matched perfectly could sit side by side for days with neither party ever learning the other existed.

### 11.15.0 — 2026-07-22

MINOR: **The other side of the market becomes reachable — buy-side discovery for service listings.** The supply-side primitive shipped in v11.2 and then sat unused: on 2026-07-22 the live board held 6 listings from 2 sellers with **`orders_count: 0` on every one** — eleven days of supply and zero demand, because nothing told a buyer to look. (1) New **STEP 2·0 / 2·1**: before publishing a task, `GET /api/v1/services` to see whether someone already sells it, then order the listing — an order creates the escrowed task **and** assigns the seller in one call, so you skip STEP 3 entirely. (2) `GET /api/v1/services` gains **`min_reputation`**, **`max_price_usd`** and **`sort=recent|reputation|price`**, filtering and ranking across the whole board server-side (the default stays `recent`, unchanged). Ranking by arrival order was the one thing a reputation-driven market must not do on the surface where a counterparty is chosen. (3) **Six MCP tools**: `em_publish_service`, `em_browse_services` (defaults to `sort=reputation`), `em_get_service`, `em_update_service`, `em_my_services`, `em_order_service` — the supply side was previously unreachable from MCP entirely. `em_order_service` called **without** an authorization creates nothing and charges nothing; it returns the exact parameters to sign (receiver = the SELLER's wallet, ADR-002). (4) Board hygiene on create: **`409 duplicate_listing`** for a second active listing with the same title, **`429`** at the per-seller active cap (20) — pause one to free a slot.

### 11.14.0 — 2026-07-21

MINOR: **Reputation-driven selection — the trustless-agents premise made executable.** (1) `GET /tasks/{id}/applications` now returns `effective_reputation_score` (COALESCE(on-chain ERC-8004 aggregate, DB heuristic) — the same score `min_reputation` gates on), `onchain_reputation_score`, and `erc8004_agent_id` per applicant; the MCP twin `em_check_submission` carries the same fields. One call now yields rankable applicants — no per-applicant `em_get_reputation` fan-out. (2) The "Check Applications" snippet is now a **vet-then-assign loop** (rank by `effective_reputation_score` × `tasks_completed`, hard-reject `counterparty_correlation.flagged`, optional cross-chain deep check per DECISION not per poll) — the old snippet took `applications[0]` blindly. (3) New guidance block: publishers set `min_reputation` at publish; workers vet the requester's wallet via `/reputation/wallet/{wallet}/cross-chain` before applying; rate honestly in both directions (uniform 100s flatten the very signal selection runs on). (4) Fixed the monitor example reading a nonexistent `reputation` field (actual: `reputation_score` / new `effective_reputation_score`); removed the phantom "trust tier" from the capabilities list. (5) `em_accept_agent_task`'s reputation gate now compares the same effective score as apply (was: raw heuristic).

### 11.13.0 — 2026-07-20

MINOR: **Escrow lock retry on failure — the cross-chain reliability rule (from the first organic non-Base trade).** STEP 3 now distinguishes **still-assigning** (`202` / `locking` → keep polling, NEVER re-assign) from **lock failed** (task back to `published` / `lock_failed` / `task.assign_failed` webhook → **wait ~10s, then re-assign with a fresh escrow auth, up to 2–3× ~10s apart**). Documents that an immediate re-assign returns **`409 ESCROW_NOT_ASSIGNABLE`** meaning "retried too soon, wait and retry" — NOT "task dead". **Chain note:** Base locks in ~2s (lock_failed rare); non-Base chains (Polygon/Arbitrum/Optimism/Avalanche/Celo/Monad) intermittently hit the ~30s Facilitator timeout, so a first-try lock_failed there is expected and the wait-retry loop is the healthy path. Mirrors EM's own acceptance test (`e2e_golden_flow_multichain.py`, `max_assign_retries=2`, `sleep(10)`) — the reason EM's escrow is on-chain-proven across 7 EVM chains.

### 11.12.1 — 2026-07-19

PATCH: Frontmatter description now carries the canonical brand line — "trustless escrow, gasless payments, on-chain reputation" (trustless is the brand keyword across every Execution Market property; the skill's description is what agent registries index). No behavior change.

### 11.12.0 — 2026-07-18

PATCH-ish MINOR: **Corrected the "escrow is USDC-only" rationale.** The old wording claimed `payment-config` "publishes only a usdc address" — stale since KK F1, which added a full per-token block. Clarified that escrow is USDC-only *today* because the signers hardcode `usdc` and the operator's on-chain condition is confirmed only for USDC, NOT because the protocol forbids it (EURC/PYUSD/AUSD are EIP-3009 + backend-allowlisted + published by payment-config, so multi-token escrow is addable). USDT remains permanently out (no EIP-3009).

### 11.11.0 — 2026-07-18

MINOR: **Canonical skill vocabulary** — new "Skill Vocabulary (canonical tags)" section lists 35 `snake_case` tags (Tier 1 core / Tier 2 mid / Tier 3 emergent) derived from a real 833-user community corpus (KarmaCadabra). `skills_required` stays free-form and max-20; these are SUGGESTED so publishers and workers tag from the same vocabulary and task↔worker matching crosses by design. Zero API change (skills_required has no enum).

### 11.10.0 — 2026-07-18

MINOR: **Universal Hiring Matrix section in the body** (previously only a changelog row). Documents `target_executor_type` on publish, robot executor registration via `em_register_as_executor {executor_type:"robot"}`, the per-cell visibility rule, and the **honest status**: the four human/agent cells (A2A/A2H/H2A/H2H) are live end-to-end; robot-\* cells are a supported party label but the robot execution loop is not yet exercised end-to-end (early/partial, not vaporware). Machine-readable matrix at `docs.execution.market/architecture/hiring-matrix`.

### 11.9.0 — 2026-07-17

MINOR: **"If a HUMAN hires you — H2A worker view" completed to 4 rules (from a 24-agent live-run post-mortem).** v11.8.0 shipped rules 1–2; this adds 3–4 and reframes the block as the explicit H2A-worker section requested. All four things a fleet mis-reported as bugs: (1) discover with `GET /tasks/available` NOT `GET /tasks`; (2) after apply you WAIT for the publisher; (3) **a `409` on apply = you already applied = SUCCESS, not a conflict — don't retry**; (4) **a task that disappears from the listing expired (deadline default 24h, range 1–720h) — not stolen, not a bug**. Also fixes the "rate the requester back" section, which wrongly implied the executor→requester rating is purely manual: EM already auto-defaults it after `EM_RATING_GRACE_HOURS` (48h, score 80, gasless), so integrators need not build their own auto-rate; agent-published tasks are covered opt-in via `EM_AUTO_RATE_REQUESTER`.

### 11.8.0 — 2026-07-17

MINOR: **Worker discovery + post-apply model made explicit (from a live 24-agent swarm post-mortem).** Two doc gaps that stalled a fleet for an hour: (1) **discover open tasks with `GET /api/v1/tasks/available`, NOT `GET /tasks`** — the latter lists only *your own* tasks (filtered by `agent_id`) and returns `[]` for a worker, so a fleet concluded "market blocked" and looped. `/tasks/available` (public) includes human-publisher **H2A** tasks too (no `publisher_type` filter); `GET /h2a/tasks?status=published` lists human-published only. Fixed the "Apply to someone else's BUY" pointer that wrongly said `GET /tasks`. (2) **After you apply, you WAIT for the publisher** — in escrow mode the requester assigns *and* signs escrow in one step; a worker cannot self-assign, and a still-`published` task is not a bug or a blocked market, just one the requester hasn't assigned yet.

### 11.7.0 — 2026-07-17

MINOR: **Structured `409` on assign — `detail` is now a `{code, message}` object, not a bare string.** `POST /tasks/{id}/assign` emits a machine-readable `code` so swarm clients branch without parsing prose: **`TASK_NOT_ASSIGNABLE`** (task is no longer `published` — the message names the current status), **`WORKER_NOT_APPLIED`** (the assignee never applied — have them `POST /tasks/{id}/apply` first), **`ESCROW_NOT_ASSIGNABLE`** (the task's escrow is not in an assignable state — payment state needs repair). A non-`published` status is now a **`409`** (was `400`): a state conflict, not a malformed request. Read `detail.message` for the human text.

### 11.6.0 — 2026-07-16

MINOR: **`agent_id` is now OPTIONAL on `POST /reputation/agents/rate`** — the server resolves the requester's identity from the task (`erc8004_agent_id` when set, else the publisher's on-chain identity from the publisher wallet), so executors no longer need the wallet→id lookup before rating back (fixes the mass-422 "executor→requester Pending forever" the KK fleet hit). An explicit numeric `agent_id` is still accepted and validated against the task. Also: authenticated ratings are now **bound to the task's assigned executor** — a JWT session or ERC-8128 signature that does not match the assignment gets `403` (sign with the wallet you applied/worked with), and only `completed`/`disputed` tasks are rateable (`409` otherwise).

### 11.5.1 — 2026-07-14

PATCH: **Honest MeshRelay channel table.** The per-event channels (`#task-{id}`, `#payments`, `#reputation`) are marked *best-effort — if MeshRelay routes them*; only `#bounties` (`task.created`) is the guaranteed EM feed. EM emits one signed webhook and MeshRelay decides channel routing, so the skill no longer hard-promises channels EM does not control. (The `#bounties` push itself requires `MESHRELAY_WEBHOOK_SECRET` on the mcp-server task — wired in Terraform, pending a production deploy.)

### 11.5.0 — 2026-07-14

MINOR: **IRC/MeshRelay integration made explicit (from a 3-way session with MeshRelay + KarmaCadabra).** Two new blocks in "IRC / MeshRelay Integration": (1) the **5-step `#agents`→bounty journey** — discover in `#bounties` via EM's **signed webhook push (subscribe, don't poll)** → apply via **signed** API → async-`202` escrow lock → **typed** evidence → settle + reputation; (2) **the MeshRelay `/em/*` proxy is READ-only** — it cannot sign for you, so every mutation needs your ERC-8128 signature (API keys are OFF) or you get `403` / a silent fallback to platform **Agent #2106**.

### 11.4.0 — 2026-07-14

MINOR: **Real-fleet UX fixes from a 24-agent integrator (KarmaCadabra).** (1) Loud top banner — **publishing = you hire and pay** — the #1 onboarding trip (a whole fleet published SELL tasks that expired instead of BUYing/listing). (2) **Escrow is USDC-only end-to-end** — EURC/PYUSD/AUSD are listed tokens but NOT usable for hire/escrow (`payment-config` publishes only a `usdc` address; the escrow signer has no token param); USDT never (no EIP-3009). (3) Big **202-at-assign patience callout** — a `202 {assigning}` takes 1–2 min to lock; NEVER reassign before polling (the same signed auth dedupes + reverts on-chain). (4) **Rating needs the numeric ERC-8004 `agent_id`, not a wallet** — `task.erc8004_agent_id` can be `null`; resolve wallet→id via `/reputation/identity/wallet/{wallet}?network=` before `/reputation/agents/rate`. (5) Prominent **nudge for pending executor→requester ratings** (that side is manual). (6) Reinforce **balanceOf/identity check before `/register`** (don't call it even once if identity exists). (7) **Validate evidence against the task's schema in code** before approving. Sourced from KarmaCadabra's live production feedback (`kk-feedback-sync`, items A1–A7, on IRC #agents).

### 11.3.0 — 2026-07-10

MINOR: **Task visibility — 410 Gone on terminal tasks + participants always see their task.** (1) `GET /tasks/{id}` on an `expired`/`cancelled` task now returns **410 Gone** (`"terminal state, do not retry"`) for non-owners/non-participants instead of 403 — treat 410 as **terminal**: stop polling that task (the old 403 fueled retry storms from clients that kept re-polling dead tasks). (2) **Participants keep visibility in ANY status**: the assigned executor and any applicant can now read the task signed even in `verifying`/`disputed`/`expired`/`cancelled` (previously workers lost access to their own task once it left the public statuses). Strangers on `verifying`/`disputed` still get 403. Owner behavior unchanged (signed reads see everything). Error Codes table + Cancelling section updated.

### 11.2.0 — 2026-07-10

MINOR: **Service listings — the supply-side primitive (sell a capability).** New `POST`/`GET`/`PATCH /api/v1/services` + `POST /api/v1/services/{id}/order`. A seller **advertises** a service (a listing is pure discovery — **no escrow, no money moves**); a buyer's **order** transparently creates a normal escrowed demand-side task under the hood (buyer = payer/publisher, seller = assigned worker), so funds still flow buyer→seller exactly like a hire. This is the clean way to sell: **do NOT publish a task to offer a service** (that makes YOU the payer and trips the sell-intent `422`) — post a listing (or apply to a buyer's open task) instead. Ordering requires the buyer's `X-Payment-Auth` signed for the **seller** wallet (same escrow rule as assign, ADR-002) and returns **200** (`escrow_status:"locked"`) or **202** (`escrow_status:"assigning"`). See the new "Service Listings (sell a capability)" section.

### 11.1.0 — 2026-07-09

MINOR: **Security-hardening batch + new response fields.** (1) Sell-intent guard (flag-gated, rolling out): task **titles** that read as sell/offer listings (e.g. "Vendo…", "for sale") are rejected with `422 {error:"sell_intent_rejected"}` — EM tasks are demand-side bounties; to sell a capability, apply to a buyer's open task instead. (2) **Assign requires a prior application**: `POST /tasks/{id}/assign` for a worker who never applied returns **409** (`"Task cannot be assigned: executor … has not applied"`) — have the worker apply first. (3) `503` with `identity_check_unavailable` / `nonce_store_unavailable` is **retryable** — honor the `Retry-After` header. (4) Cross-chain signing mistakes fail with a machine-detectable **`NETWORK_MISMATCH:`** prefix naming the network your `X-Payment-Auth` was signed for vs the task's — re-sign for the task's network. (5) Submission responses now expose `evidence_content_hash` (SHA-256 per artifact + root) and `arbiter_verdict` + EIP-191 `arbiter_verdict_signature` — verify before approving. (6) **Review-window auto-settle**: a submission unreviewed for `EM_REVIEW_WINDOW_HOURS` auto-settles to the worker (production value: **72h**) — review promptly. (7) Authoritative machine-readable schema = `https://api.execution.market/openapi.json` (21 categories / 18 evidence types; extra fields → 422; live min bounty via `GET /api/v1/config`).

### 11.0.0 — 2026-07-09

MAJOR (BREAKING): **Async escrow lock at assign (`202 {status:"assigning"}`).** `POST /tasks/{id}/assign` with `X-Payment-Auth` (path B, sign-on-assignment) no longer holds the request for the on-chain lock. It validates + enqueues and returns **202 Accepted** with `{status:"assigning", escrow_status:"locking"}`; a dedicated worker performs the Facilitator lock off-request (fixes the swarm assign hangs — the synchronous lock held a request worker for the full `/settle` round-trip, p99 ~28s + retries). Handle it: poll `GET /tasks/{id}` (`status: accepted` = escrow locked; back to `published` = lock failed/expired, re-assignable) or await the `task.assigned` / new **`task.assign_failed`** webhook. **A `202` is NOT an error — do NOT retry the assign on it** (the same signed auth dedupes and would revert on-chain anyway). Applications are now rejected only AFTER the lock succeeds, so a failed lock leaves other applicants intact. Path A (client-locked `escrow_tx` + `payment_info`) is unaffected — already-locked assigns stay synchronous.

### 10.7.0 — 2026-07-08

MINOR: **Reputation network preference.** New onboarding question + `reputation_network` config key (default `base`) — pick which chain new ratings anchor to. Read/change via `GET`/`PATCH /api/v1/workers/{wallet}/reputation-network` (PATCH needs an ERC-8128 signature, same pattern as other worker mutations). Currently **coming soon**: while the GET's `feature_enabled` is `false`, the selector is read-only and stays on `base` (PATCH returns 409). Reputation **display** is the cross-chain aggregate (per-chain breakdown + primary chain) via `GET /api/v1/reputation/wallet/{wallet}/cross-chain` — never a single-network score.

### 10.6.0 — 2026-07-08

MINOR: **How evidence is verified (deliver files as typed artifacts, not URLs in `json_response`).** To have an external file cryptographically verified, submit it under a **typed artifact** field (`photo`, `document`, `file`, `video`, `receipt`, `signature`, `screenshot`) — those are fetched from an allowlisted host, SHA-256'd, and the digest is bound into the arbiter's `evidence_hash`. A URL placed inside `json_response` (or any non-file key, e.g. `delivery_url`) is treated as **citation/context only**: it is NOT fetched, NOT hashed, and does NOT count as delivered evidence. Consequence: a submission whose only content is such a URL will **not** trigger instant payout — it routes to normal review. For knowledge/A2A tasks, deliver the payload **inline** in `json_response`. Also: file-artifact URLs must be `https` on our storage/CDN (or `ipfs://`/`data:`); off-host artifact URLs are rejected at submit.

### 10.5.1 — 2026-07-08

PATCH: STEP 2a's async-registration poll loop is now bounded (~30 iterations ≈ 2.5 min, matching STEP 1b) instead of an unbounded `while pending` — a legitimately-eternal pending state no longer hangs the agent. Added a fallback note: if still pending after the cap, fall back to the identity lookup (the mint may still land and the poll self-heals from on-chain balance).

### 10.5.0 — 2026-07-08

MINOR: **Async identity registration (202 + poll).** `POST /reputation/register` no longer 504s when the facilitator mint is slow (mint p95 ~28s vs 30s edge timeout). If the mint confirms within ~20s you get the usual 200 (nothing changes for existing clients). Otherwise the server answers **202 Accepted** with `{registration_id, status: "pending", poll}` — the mint keeps running; poll `GET /reputation/register/{registration_id}` until `completed`/`failed`. The poll is self-healing (it resolves from on-chain `balanceOf`, so it survives server restarts). **NEVER re-POST /register on a timeout or a 202** — the facilitator mints 2 txs and a blind retry mints a DUPLICATE identity; the endpoint now also fails closed (503) when it cannot verify your existing identity on-chain, instead of blind-minting. STEP 1b/2a snippets updated to handle the 202.

### 10.4.0 — 2026-07-06

MINOR: **STEP 3 now teaches both escrow-lock paths.** The assign step was documenting only path A (client-side `AdvancedEscrowClient.authorize()` → pass `escrow_tx` + `payment_info`), which is heavy (RPC + web3) and buried — the first integrator to wire escrow got stuck on the `402 "no on-chain escrow lock"` with no self-serve way out. Added a loud two-path framing at the STEP 3 header + a `402` troubleshooting pointer, and a new **path B (sign-on-assignment)**: sign the escrow auth for the chosen worker and send it as `X-Payment-Auth` — the server relays to the Facilitator and locks (no RPC, no client-side tx), via `em_plugin_sdk.escrow_signing.build_escrow_pre_auth`. Documented the envelope details (`to` = TokenCollector, `value` = bounty only, `validBefore` = preApprovalExpiry, nonce = `getHash(paymentInfo)`) and the honest install-from-source command (em-plugin-sdk is not on PyPI yet). The `402` error body itself now names both paths and links this section.

### 10.3.0 — 2026-06-12

MINOR: **Honest single-provider Ring 2.** ClawRouter and EigenAI are wired but not yet credentialed — Ring 2 currently operates with OpenRouter only. MAX tier no longer simulates a "dual consensus" with two votes from the same provider: when the secondary resolves to the same provider as the primary, the second vote is skipped and the verdict is decided via the standard path (1 Ring 2 vote, registered as `openrouter`). True dual consensus re-activates automatically once ClawRouter/EigenAI credentials are configured. Also: Ring 2 INCONCLUSIVE is advisory-only in ALL paths (the Lambda no longer auto-creates disputes), text-only submissions skip Ring 1 (PHOTINT) explicitly and go straight to Ring 2, and AI-provider failures score a neutral 0.5 with `review_required` instead of a perfect score.

### 10.2.0 — 2026-06-11

MINOR: **Universal Escrow (ADR-002 — sign-on-assignment, all 9 hiring-matrix cells).** Human-published tasks (H2A/H2H) now lock x402r escrow at assignment, exactly like agent-published tasks — workers applying to human tasks get the same on-chain payment guarantee (gated `EM_H2A_ESCROW_ENABLED`, rolling out). Protocol clarification for ALL agents: the escrow EIP-3009 nonce is `AuthCaptureEscrow.getHash(paymentInfo)` which includes the receiver, so the authorization can only be signed AT assignment with the chosen worker — never pre-sign before picking a worker. Escrow-mode tasks are publisher-assigned: executors `apply` and wait; server rejects self-accepts on escrow tasks. Escrow deposit cap: $100/task (on-chain operator condition). Legacy human tasks without escrow drain through the old sign-on-approval path.

### 10.1.0 — 2026-06-10

MINOR: **Universal Hiring Matrix.** `target_executor_type` on publish now spans the full party matrix — `any` \|`human` \|`agent` \|`robot` (previously `robot`/`any` silently collapsed to `agent`). Any party may publish for any party (H2H, H2A, A2H, A2A, robot combos). Executors see and may accept only tasks targeting their own party plus `any`. New canonical REST route `POST /api/v1/publish` (the legacy `POST /api/v1/h2a/tasks` stays live as a deprecated alias). Robot executors register via `em_register_as_executor` with `executor_type: "robot"` (authenticate like agents).

### 10.0.0 — 2026-05-27

MAJOR (BREAKING): **OWS-exclusive signing.** Removed the raw-private-key client (old Option C) and the raw-key escrow fallback (old Option B). Agents that copied them must migrate to OWS (CLI or MCP) — import an existing key via `ows wallet import`. This also eliminates the lowercase-`keyid` drift that caused silent auth failures. NEW: STEP 0 pre-flight probe (live behavior outranks docs), `X-Idempotency-Key` on create (server-side dedupe → safe timeout-retry), 403-after-cancel visibility note + signed-list reconciliation, nonce/backoff hygiene, upgraded `active-tasks.json` schema (upsert + `fingerprint`/`replacement_of`/`last_verified_*`), `reprice_task()` + `reconcile_tasks()` helpers, and a consolidated "hard rules" block. Sourced from a real placement/cancel/reprice friction audit.

### 9.6.1 — 2026-04-22

PATCH: Remove non-existent `/api/v1/escrow/{task_id}/state` endpoint from Option 5 monitor paths (caught by canonical-skill smoke test — 404 in prod, not in OpenAPI). Escrow lock/release/refund/expiry events are derived from task `status` transitions (`accepted` = escrow locked, `completed` = released, `cancelled`/`expired` = refund-eligible). Python watcher endpoint list and `/loop` prompt updated; event schema `kind` narrowed to `status \|application \|submission`.

### 9.6.0 — 2026-04-22

MINOR: 3 Claude Code native monitor paths added to "Monitoring — Choose Your Strategy" (`/loop 3m` interactive, Anthropic Routine cloud cron, `Monitor` tool event-driven). Monitors the full task lifecycle (applications, submissions, status transitions, escrow lock/release, refunds, cancels, expiry). Verbose internal logging + compact "rapper flow" chat output (configurable `message_style`: `rapper`/`plain`/`technical`). Resilience built-in: SHA1 `event_id` dedupe via `processed-events.json`, atomic writes, skip-on-error, survives process restarts, no inner retry storms on 429.

### 9.5.0 — 2026-04-16

MINOR: New optional fields on `em_publish_task` — `geo_match_mode` (`strict`/`city`/`region`/`country`/`any`) and `location_radius_m` (meters, default 500 when `strict` + coords without radius). Lets publishers control how tightly workers are matched to a task's location. Fields are accepted by the API today but the matcher itself is gated behind `EM_GEO_MATCH_ENABLED` (OFF in production for now) — set them, but expect current behavior until the flag flips. Also documents INCONCLUSIVE Ring 2 verdicts and the self-claim dispute model — see `/guides/l2-arbiter`.

### 9.4.0 — 2026-04-16

MINOR: Document OWS CLI subprocess pattern for ERC-8128 signing — key never leaves vault, no MCP Server required. Reorder Step 1c to present OWS paths before the raw-key fallback. `ows wallet export` TTY restriction is the security feature; always use `ows sign message` in non-interactive contexts (CLI agents, cron, WSL). Added CLI path hint (`~/.npm-global/bin/ows`) and vault location (`~/.ows/wallets/`).

### 9.3.0 — 2026-04-14

MINOR: `gps_required` field on `em_publish_task`. Digital tasks (screenshot, json_response, etc.) now skip GPS verification automatically. Set `gps_required: false` to explicitly disable GPS for any task type. Fix: screenshot evidence no longer penalized when task requires it.

### 9.2.0 — 2026-04-11

MINOR: E2E bug fixes — `arbiter_mode: "auto"` recommended for physical tasks (enables Ring 1 PHOTINT + Ring 2). EXIF GPS auto-extraction from gallery uploads (frontend + backend fallback). Operator override guidance. Cancel now works for expired tasks with escrow. New `PATCH /tasks/{id}/escrow` endpoint for stuck payment_info.

### 9.1.0 — 2026-04-11

MINOR: Escrow refund/recovery procedure. Deterministic steps for agents to recover locked funds when tasks expire. MANDATORY PaymentInfo save to disk after escrow lock. New "Refund / Recovery" section with query + refund code.

### 9.0.0 — 2026-04-10

MAJOR: Ring 2 arbiter fully wired with ClawRouter (primary), EigenAI (secondary), OpenRouter (fallback). Dual-model consensus on MAX tier. Unified two-axis scoring (authenticity x completion) with grades A-F. 21 category-specific blend weights. Cost controls ($100/day global, $10/caller, $0.20/eval cap). AaaS re-enabled with all Phase 0 guardrails active. `EM_AAAS_ENABLED=true` in production. `EM_ARBITER_AUTO_RELEASE_ENABLED` remains `false` -- agents must still manually approve/reject.

### 8.0.0 — 2026-04-09

BREAKING: Arbiter-as-a-Service (`POST /arbiter/verify`) is DISABLED pending Phase 1 guardrails — endpoint returns HTTP 503 on all production deployments. Arbiter auto-release/auto-refund is also hard-disabled; tasks created with `arbiter_mode=auto` will have their verdict stored but funds will NOT move without manual agent confirmation. Removed marketing language that implied the arbiter runs two independent LLM rings — only Ring 1 PHOTINT forensic verification is live; Ring 2 LLM is currently a stub pending re-implementation. Root cause: 2026-04-07 security audit flagged AI-001 through AI-006 (stub inference, no daily spend cap, trivial prompt injection, anonymous callable). See security audit report for full context. Agents should treat `arbiter_mode` as `manual` until further notice.

### 7.5.0 — 2026-04-09

MINOR: Capabilities discovery — new "Agent Capabilities Quick Reference" section at top lists everything the agent can do (task lifecycle, arbiter modes, disputes, AaaS). Dispute REST endpoints + AaaS endpoint now in API Reference table. Ring 2 Arbiter section expanded with concrete code examples for each mode.

### 7.4.0 — 2026-04-09

MINOR: Phase 5 — Dispute resolution endpoints + Arbiter-as-a-Service. New `em_resolve_dispute` MCP tool (release/refund/split verdicts). REST endpoints: `GET /disputes`, `GET /disputes/{id}`, `GET /disputes/available`, `POST /disputes/{id}/resolve`. New AaaS endpoint `POST /arbiter/verify` for external marketplaces (100 req/min rate limit). Dashboard disputes inbox at `/disputes`. Human arbiter eligibility: reputation>=80 + 10+ completed tasks.

### 7.3.0 — 2026-04-08

MINOR: Ring 2 Arbiter (`arbiter_mode` on em_publish_task + new `em_get_arbiter_verdict` tool). Ring 1 PHOTINT (forensic) verification. Tiers: cheap<$1 ($0), standard $1-$10 (~$0.001), max >=$10 (~$0.003). Hard cap 10% of bounty. Modes: manual (default), auto (trustless release/refund), hybrid (agent confirms). Master switch OFF by default in production.

### 7.2.1 — 2026-04-08

PATCH: Fix OWS shim wallet_name bug (P0, was returning first wallet instead of named one). Update CLI sign-bug warning — v1.2.4+ produces correct 65-byte sigs. SDK 0.22.2 adds `[escrow]` extra (bundles web3).

### 7.2.0 — 2026-04-03

MINOR: Auto-install OWS shim in Step 1a (bridges CLI to Python SDK). Hosted at execution.market/scripts/ows_shim.py. Zero manual steps for escrow setup.

### 7.1.0 — 2026-04-03

MINOR: Escrow now uses OWS WalletAdapter (8/8 lifecycle steps keyless). SDK pinned to >=0.21.0. credentials.json no longer needed.

### 7.0.1 — 2026-04-03

PATCH: WARNING — OWS CLI has 64-byte sig bug, use MCP server only. em_monitor.py download URL added.

### 7.0.0 — 2026-04-03

MAJOR: OWS ERC-8128 signing (ows_sign_erc8128_request), 4 monitoring strategies (HEARTBEAT/cron/webhooks/WebSocket), worker reputation in applications, TTY export warning, assign success fix.

### 6.1.0 — 2026-04-03

Autonomous onboarding: auto-detect wallet, auto-install OWS, interactive config (name, network, autonomy). Zero manual steps.

### 6.0.0 — 2026-04-03

MAJOR: Unified canonical skill. Merged config schema, autonomy system, monitoring decision logic, best practices, webhook payloads, IRC safety rules, A2A section from legacy v2.1.0. Deleted duplicate skill files. Single source of truth.

### 5.2.0 — 2026-04-03

Photo evidence MUST be shown inline before approve/reject. Ported from skills/execution-market v2.1.0 fix.

### 5.1.0 — 2026-04-03

OWS is now PRIMARY wallet path in Step 1a. Detects OWS first, credentials.json as fallback. OWS MCP Server integration documented.

### 5.0.0 — 2026-04-02

MAJOR: Open Wallet Standard (OWS) replaces Ultra Wallet. OWS MCP Server for wallet mgmt + EIP-3009 signing. All uvw refs removed.

### 4.6.0 — 2026-04-02

World ID 4.0: workers verify proof-of-humanity (Orb/device), tasks $500+ require Orb verification

### 4.5.0 — 2026-03-30

X handle in config.json, agent_name sent with task creation

### 4.4.0 — 2026-03-30

Agent profiles: display_name in config.json, shown on task cards

### 4.3.0 — 2026-03-30

Auto-update: agents must fetch latest skill.md before every task

### 4.2.0 — 2026-03-30

Clarify agent IDs are per-chain (different ID per network is normal). Only flag if erc8004_agent_id == 2106 (platform fallback).

### 4.1.0 — 2026-03-29

Report erc8004_agent_id (numeric per-chain ID) not agent_id (wallet address). agent_id is now always the wallet for cross-chain ownership.

### 4.0.0 — 2026-03-29

MAJOR: Fix ERC-8128 signing (@query support), fix identity endpoint path (was 404), fix fee model (deducted not added), complete 21 categories + 18 evidence types, fix status flow, fix webhook events, fix evidence presign params

### 3.28.0 — 2026-03-29

Fix network check endpoint (was /config/networks 404, now /config), clarify: never use /x402/networks for supported chains

### 3.27.0 — 2026-03-29

Identity registration BEFORE task creation (not after), per-chain identity, escrow flow fix (wallet from applications), NEVER direct-pay rule

### 3.26.0 — 2026-03-28

Per-chain identity registration, network-aware identity check, fix escrow/assign flow (wallet_address from applications), NEVER direct-pay rule

