@escro/sdk 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -61,20 +61,25 @@ interface EscrowAccount {
61
61
  state: EscrowState;
62
62
  /**
63
63
  * SHA-256 hex digest of the canonical UTF-8 JSON serialisation of the {@link TaskSpec}.
64
- * Stored on-chain; used by the oracle to verify it is evaluating the correct spec.
64
+ * Recorded on-chain (the account's `spec_hash` holds this hash, bare, or as `ipfs://<hash>` on
65
+ * escrows created before P18.T0c), so the buyer and worker (and an arbitrator) can check that a
66
+ * spec is the one the escrow was created for.
65
67
  */
66
68
  taskSpecHash: string;
67
69
  /**
68
- * Content-addressed URI (ipfs:// or ar://) where the full {@link TaskSpec} JSON is pinned.
69
- * `null` until the maker uploads the spec via `POST /v1/task-specs`.
70
+ * The exact string the escrow's on-chain `spec_hash` holds: the bare 64-hex `taskSpecHash`
71
+ * (escrows created since P18.T0c), `ipfs://<taskSpecHash>` (earlier), `null` before the
72
+ * spec_uri migration ran. A label for the {@link TaskSpec}'s hash, not a fetchable copy (Escro
73
+ * stores no spec body; the buyer shares the spec).
70
74
  */
71
75
  taskSpecUri: string | null;
72
76
  /** Base-58 public key of the oracle authority permitted to sign timeout_release / refund_buyer. */
73
77
  oracle: string;
74
78
  /**
75
- * Percentage of `amount` charged as a platform fee, in basis points.
76
- * Deducted from the escrow vault on successful settlement.
77
- * Valid range: 0–10 000 (0 %–100 %).
79
+ * Platform fee in basis points. The API serves the value it recorded at registration
80
+ * (`PLATFORM_FEE_BPS`, the mirror of PlatformConfig `fee_bps`); on chain `create_escrow`
81
+ * stores PlatformConfig's value. Additive: the buyer deposits `amount` plus the fee and
82
+ * the worker receives the full `amount`.
78
83
  */
79
84
  oracleFeeBps: number;
80
85
  /** Unix timestamp (seconds) when the escrow PDA was initialised. */
@@ -108,8 +113,8 @@ interface EscrowAccount {
108
113
  /** Solana cluster this account belongs to. */
109
114
  network: Network;
110
115
  }
111
- /** Protocol-wide aggregate statistics — public, unauthenticated. */
112
- interface ProtocolStats {
116
+ /** One set of `GET /v1/stats` figures: the public block, or the operator block. */
117
+ interface ProtocolStatsFigures {
113
118
  totalEscrows: number;
114
119
  totalVolumeUsdc: string;
115
120
  /**
@@ -125,6 +130,16 @@ interface ProtocolStats {
125
130
  byState: Record<EscrowState, number>;
126
131
  activeEscrows: number;
127
132
  }
133
+ /** Protocol-wide aggregate statistics: public, unauthenticated. */
134
+ interface ProtocolStats extends ProtocolStatsFigures {
135
+ /**
136
+ * Escro-operated fleet figures (ARCHITECTURE section 9): the same fields over
137
+ * escrows whose buyer and assigned worker are both in the API's operator
138
+ * allowlist. They are real settlements but not third-party demand, so every
139
+ * public field excludes them; never sum this block with the public fields.
140
+ */
141
+ operator: ProtocolStatsFigures;
142
+ }
128
143
 
129
144
  /**
130
145
  * Broad categories of agent work.
@@ -194,14 +209,16 @@ interface AcceptanceCriterion {
194
209
  * This object is:
195
210
  * 1. Serialised to canonical UTF-8 JSON (sorted keys, no trailing whitespace).
196
211
  * 2. Hashed with SHA-256 → stored on-chain as `EscrowAccount.taskSpecHash`.
197
- * 3. Pinned to IPFS or Arweave → URI stored as `EscrowAccount.taskSpecUri`.
212
+ * 3. Written into `create_escrow`'s `spec_hash` bare (since P18.T0c; `ipfs://<hash>` before) and
213
+ * recorded as `EscrowAccount.taskSpecUri` (a label for the hash; Escro stores no spec body,
214
+ * and the buyer shares the spec itself).
198
215
  *
199
216
  * Any mutation of the spec changes its hash, invalidating the on-chain record.
200
217
  */
201
218
  interface TaskSpec {
202
219
  /**
203
220
  * Semver string identifying the task spec schema version (e.g. `"1.0.0"`).
204
- * Allows the oracle and API server to handle format evolution gracefully.
221
+ * Lets the API, SDKs and bots handle format evolution gracefully.
205
222
  * Increment the minor version for backwards-compatible additions;
206
223
  * the major version for breaking changes.
207
224
  */
@@ -211,13 +228,14 @@ interface TaskSpec {
211
228
  */
212
229
  taskType: TaskType;
213
230
  /**
214
- * Complete description of the task, written for both the agent performing it
215
- * and the oracle evaluating the result.
231
+ * Complete description of the task, written for both the worker performing it
232
+ * and the buyer judging the result (or, in a dispute, the human arbitrator
233
+ * reading it against the delivery). Escro never evaluates a deliverable.
216
234
  *
217
235
  * Good descriptions:
218
236
  * - State the goal, not just the method.
219
237
  * - Include any non-obvious constraints (language, style, performance bounds).
220
- * - Are precise enough that an LLM could verify correctness without ambiguity.
238
+ * - Are precise enough that the buyer can check the delivery without ambiguity.
221
239
  */
222
240
  description: string;
223
241
  /**
@@ -236,8 +254,9 @@ interface TaskSpec {
236
254
  }
237
255
 
238
256
  /**
239
- * Exhaustive set of machine-readable error codes returned by the escro.ai REST API
240
- * in the `code` field of an {@link ApiError} response.
257
+ * Every machine-readable error code the escro.ai REST API's route handlers send in the `code`
258
+ * field of an error response (a test derives the set from the API source). A request Fastify
259
+ * refuses before a handler runs carries Fastify's own `FST_ERR_*` code instead.
241
260
  *
242
261
  * Consumers should switch on this value to handle errors programmatically
243
262
  * rather than parsing the human-readable `error` string.
@@ -247,32 +266,40 @@ type EscrowErrorCode =
247
266
  "ESCROW_NOT_FOUND"
248
267
  /** The requested operation is not permitted in the escrow's current state. */
249
268
  | "ESCROW_INVALID_STATE"
250
- /** The referenced task spec hash has not been registered. */
251
- | "TASK_SPEC_NOT_FOUND"
252
- /** The submitted task spec failed schema validation. */
253
- | "TASK_SPEC_INVALID"
254
- /** The caller does not have permission to perform this action. */
255
- | "UNAUTHORIZED"
256
- /** The provided transaction signature is invalid or does not match the escrow. */
257
- | "INVALID_SIGNATURE"
258
- /** The requested token amount is zero, negative, or exceeds the u64 maximum. */
259
- | "INVALID_AMOUNT"
260
- /** The escrow's network does not match the caller's requested network. */
261
- | "NETWORK_MISMATCH"
262
- /** The caller has exceeded the rate limit; retry after the indicated backoff. */
263
- | "RATE_LIMITED"
264
- /** An unexpected server-side error occurred; report to escro.ai support. */
265
- | "INTERNAL_ERROR"
266
- /** Request body or query parameters failed schema validation. */
267
- | "VALIDATION_ERROR"
269
+ /** Release: the API's RPC still shows the escrow account open at `confirmed`; retry once the release lands. */
270
+ | "ESCROW_NOT_SETTLED"
268
271
  /** Confirm: no transaction for the signature at `confirmed` yet; retry once it lands. */
269
272
  | "TX_NOT_FOUND"
270
273
  /** Confirm: the transaction landed with an error. */
271
274
  | "TX_FAILED"
272
275
  /** Confirm: the transaction holds no single escrow instruction this route records for the escrow. */
273
276
  | "TX_MISMATCH"
274
- /** Confirm: the Solana RPC read failed; retry. */
275
- | "RPC_UNAVAILABLE";
277
+ /** The Solana RPC read failed; retry. */
278
+ | "RPC_UNAVAILABLE"
279
+ /** Missing, invalid or expired authentication, or a caller not permitted the action. */
280
+ | "UNAUTHORIZED"
281
+ /** EscroBots removal: the signer is not the directory-admin wallet. */
282
+ | "FORBIDDEN"
283
+ /** EscroBots: the bot descriptor's wallet signature does not verify. */
284
+ | "INVALID_DESCRIPTOR_SIGNATURE"
285
+ /** EscroBots: the descriptor names a wallet other than the signer. */
286
+ | "WALLET_MISMATCH"
287
+ /** EscroBots: the wallet was removed from the directory for fraud. */
288
+ | "WALLET_REMOVED"
289
+ /** EscroBots: the descriptor's timestamp is outside the accepted window. */
290
+ | "STALE_DESCRIPTOR"
291
+ /** EscroBots: a newer or equal registration already exists for the wallet. */
292
+ | "DESCRIPTOR_REPLAYED"
293
+ /** EscroBots: no bot is registered for the wallet. */
294
+ | "BOT_NOT_FOUND"
295
+ /** EscroBots: the requested sort needs a reputation source the deployment lacks. */
296
+ | "SORT_UNAVAILABLE"
297
+ /** The caller has exceeded the rate limit; retry after the indicated backoff. */
298
+ | "RATE_LIMITED"
299
+ /** An unexpected server-side error occurred. */
300
+ | "INTERNAL_ERROR"
301
+ /** Request body or query parameters failed schema validation. */
302
+ | "VALIDATION_ERROR";
276
303
 
277
304
  /**
278
305
  * EscroBots v0 - the permissionless capability directory (ARCHITECTURE §8).
@@ -322,6 +349,35 @@ interface BotDescriptor extends UnsignedBotDescriptor {
322
349
  signature: string;
323
350
  }
324
351
 
352
+ /** The submitted deliverable as the Buyer's review reads it off the escrow read model. */
353
+ interface ReviewDeliverable {
354
+ /**
355
+ * SHA-256 hex the worker submitted on-chain (mirrored to the read model). It is the
356
+ * worker's claim about the artifact: a review re-hashes the real artifact and never
357
+ * trusts this value on its own.
358
+ */
359
+ contentHash: string;
360
+ /** URI the worker gave for the deliverable or its proof, or null if it gave none. */
361
+ proofUri: string | null;
362
+ }
363
+ /** A release decision. */
364
+ interface ReviewResult {
365
+ /** Release payment to the worker. */
366
+ accept: boolean;
367
+ /**
368
+ * When NOT accepting, whether to raise a dispute (human arbitration) rather than hold.
369
+ * A held SUBMITTED escrow is auto-released to the worker by the 24h protocol timeout,
370
+ * so a real reject predicate disputes to contest.
371
+ */
372
+ dispute: boolean;
373
+ reason: string;
374
+ }
375
+ /** A named release policy the Buyer's review wires in. */
376
+ interface ReviewPolicy {
377
+ name: string;
378
+ evaluate(deliverable: ReviewDeliverable): ReviewResult | Promise<ReviewResult>;
379
+ }
380
+
325
381
  type SolanaCluster = "devnet" | "mainnet";
326
382
 
327
383
  /** Dispute tally with its outcome split (from the wallet's perspective). */
@@ -413,6 +469,64 @@ interface ServedWalletReputation extends SerializedWalletReputation {
413
469
  walletAgeSeconds: number | null;
414
470
  }
415
471
 
472
+ /**
473
+ * Base class for all errors thrown by the @escro/sdk. `retryAfterMs` is the
474
+ * server's Retry-After delay, when it sent one in seconds.
475
+ */
476
+ declare class EscroError extends Error {
477
+ readonly code: string;
478
+ readonly retryAfterMs?: number | undefined;
479
+ constructor(message: string, code?: string, retryAfterMs?: number | undefined);
480
+ }
481
+ /** The requested escrow was not found (HTTP 404). */
482
+ declare class EscrowNotFoundError extends EscroError {
483
+ constructor(address: string);
484
+ }
485
+ /**
486
+ * The reputation endpoint is not available on this deployment (HTTP 404). A 404
487
+ * from `GET /rep` means no `ReputationSource` is mounted (the surface is
488
+ * unmounted), NOT that a wallet is unknown - unknown wallets return zeroed raw
489
+ * components, never a 404. Kept distinct from {@link EscrowNotFoundError}, whose
490
+ * 404 is about a missing escrow.
491
+ */
492
+ declare class ReputationUnavailableError extends EscroError {
493
+ constructor();
494
+ }
495
+ /** The operation is not valid for the escrow's current state (HTTP 409). */
496
+ declare class EscrowStateError extends EscroError {
497
+ constructor(message: string);
498
+ }
499
+ /** Polling timed out after 24 hours without reaching the expected state. */
500
+ declare class EscrowTimeoutError extends EscroError {
501
+ constructor(address: string);
502
+ }
503
+ /**
504
+ * A transaction landed (or was sent) but the API did not record it. `code` is the
505
+ * server's code (e.g. TX_MISMATCH, TX_FAILED, or TX_NOT_FOUND after the retry
506
+ * window), `NETWORK_ERROR` when the last attempt never reached the API, or
507
+ * `HTTP_<status>` when the answer carried no code. Call {@link Escro.confirm} again
508
+ * with `address` and `signature` to retry, no sooner than `retryAfterMs` when the
509
+ * API sent one.
510
+ */
511
+ declare class EscroConfirmError extends EscroError {
512
+ readonly address: string;
513
+ readonly signature: string;
514
+ constructor(address: string, signature: string, code: string, message: string, retryAfterMs?: number);
515
+ }
516
+ /** The caller is not authorized to perform this action (HTTP 401/403). */
517
+ declare class UnauthorizedError extends EscroError {
518
+ constructor(message?: string);
519
+ }
520
+ /**
521
+ * A payment rail was requested that is not enabled in this build. The `x402`
522
+ * (synchronous) rail is reserved (ARCHITECTURE §7a) and lands in Phase 9;
523
+ * {@link Escro.pay} throws this until then. `rail` names the unavailable rail.
524
+ */
525
+ declare class EscroRailNotEnabledError extends EscroError {
526
+ readonly rail: string;
527
+ constructor(rail: string);
528
+ }
529
+
416
530
  /** Constructor options for the {@link Escro} client. */
417
531
  interface EscroOptions {
418
532
  /**
@@ -430,7 +544,7 @@ interface EscroOptions {
430
544
  }
431
545
  /** Parameters for creating a new escrow. */
432
546
  interface CreateEscrowParams {
433
- /** Full task specification uploaded to IPFS. */
547
+ /** The full task specification; the API records its hash, never its body. */
434
548
  taskSpec: TaskSpec;
435
549
  /**
436
550
  * Worker's net payment in μUSDC (1 USDC = 1_000_000). Minimum: 5_000_000.
@@ -456,6 +570,21 @@ interface CreateEscrowResult {
456
570
  /** Solana transaction signature. */
457
571
  signature: string;
458
572
  }
573
+ /**
574
+ * Return value from {@link Escro.releasePaymentWithOutcome}. The release landed on
575
+ * chain either way; `confirm` says whether the API recorded it. A failed confirm
576
+ * carries an `EscroConfirmError` (`address`, `signature`, `code`).
577
+ */
578
+ interface ReleasePaymentOutcome {
579
+ /** Solana transaction signature of the landed `release_payment`. */
580
+ signature: string;
581
+ confirm: {
582
+ landed: true;
583
+ } | {
584
+ landed: false;
585
+ error: EscroConfirmError;
586
+ };
587
+ }
459
588
  /** Parameters for submitting a deliverable. */
460
589
  interface SubmitDeliverableParams {
461
590
  /** SHA-256 hex digest (or content-addressed hash) of the deliverable content. */
@@ -465,7 +594,7 @@ interface SubmitDeliverableParams {
465
594
  }
466
595
  /** Parameters for raising a dispute. */
467
596
  interface RaiseDisputeParams {
468
- /** Human-readable reason for the dispute (max 200 chars). */
597
+ /** Human-readable reason for the dispute: non-empty, at most 200 UTF-8 bytes. */
469
598
  reason: string;
470
599
  /** Optional URL to evidence supporting the dispute. */
471
600
  evidence?: string;
@@ -532,7 +661,7 @@ interface WorkerCandidate {
532
661
  *
533
662
  * PLUMBING ONLY. The escrow rail is the sole implemented backend; the `x402`
534
663
  * (synchronous) rail is reserved and lands in Phase 9 as an additive backend.
535
- * Every name here is a FREEZE CONTRACT that Phase 9 (P9.T5) inherits "by name":
664
+ * Every name here is a FREEZE CONTRACT that Phase 9 inherits "by name":
536
665
  * enabling x402 must not be a breaking change for any kit-generated bot. The
537
666
  * shapes below are pinned by a type-level test (src/__tests__/payments.test.ts);
538
667
  * Phase 9 may add only OPTIONAL fields.
@@ -607,12 +736,24 @@ declare class Escro {
607
736
  /**
608
737
  * Release payment to the worker. Buyer must be the wallet in the constructor.
609
738
  * Builds and submits the `release_payment` on-chain tx FIRST (the chain is the
610
- * source of truth), then confirms DB state. The DB confirmation is best-effort:
611
- * the oracle sweep reconciles it if it fails.
739
+ * source of truth), then has the API record it, retrying as
740
+ * {@link Escro.releasePaymentWithOutcome} does. Use that method to see whether the
741
+ * API recorded the release.
612
742
  *
613
743
  * @returns Solana transaction signature.
614
744
  */
615
745
  releasePayment(address: string): Promise<string>;
746
+ /**
747
+ * {@link Escro.releasePayment}, reporting whether the API recorded the release.
748
+ * `ESCROW_NOT_SETTLED` (the API's RPC does not yet show the escrow closed), the codes
749
+ * {@link Escro.confirm} retries and a network failure are retried for about 30 s. A
750
+ * failure never throws: the release already landed, so the signature is returned with
751
+ * `confirm.landed: false` and an `EscroConfirmError` (the API's code, or
752
+ * `NETWORK_ERROR` when the last call never reached it).
753
+ *
754
+ * @returns `{ signature, confirm }`.
755
+ */
756
+ releasePaymentWithOutcome(address: string): Promise<ReleasePaymentOutcome>;
616
757
  /**
617
758
  * Raise a dispute for an escrow. Either the buyer or the assigned worker
618
759
  * may call this. Signs and submits the `raise_dispute` on-chain tx, then confirms it with the API.
@@ -720,6 +861,7 @@ declare class Escro {
720
861
  confirm(address: string, signature: string, opts?: {
721
862
  evidence?: string;
722
863
  }): Promise<EscrowAccount>;
864
+ private retryRecord;
723
865
  private send;
724
866
  private sendAndConfirm;
725
867
  /**
@@ -794,8 +936,11 @@ declare class ApiClient {
794
936
  unsignedTx: string;
795
937
  }>;
796
938
  /**
797
- * POST /v1/escrows/:address/release — DB-only state update.
798
- * Requires auth (buyer). No on-chain tx returned.
939
+ * POST /v1/escrows/:address/release: records the landed release once the API's RPC shows
940
+ * the escrow closed. Requires auth (buyer). No on-chain tx returned. A 409
941
+ * `ESCROW_NOT_SETTLED`, a 5xx or a 429 throws an {@link EscroError} with the server's code,
942
+ * or `HTTP_<status>` when the answer carries none; {@link Escro.releasePaymentWithOutcome}
943
+ * decides which to retry. Other refusals throw as every route does.
799
944
  */
800
945
  releasePaymentDb(address: string): Promise<void>;
801
946
  /**
@@ -871,63 +1016,6 @@ interface ServiceAdapter {
871
1016
  */
872
1017
  declare function serviceResultToSubmitParams(result: ServiceResult): SubmitDeliverableParams;
873
1018
 
874
- /**
875
- * Base class for all errors thrown by the @escro/sdk. `retryAfterMs` is the
876
- * server's Retry-After delay, when it sent one in seconds.
877
- */
878
- declare class EscroError extends Error {
879
- readonly code: string;
880
- readonly retryAfterMs?: number | undefined;
881
- constructor(message: string, code?: string, retryAfterMs?: number | undefined);
882
- }
883
- /** The requested escrow was not found (HTTP 404). */
884
- declare class EscrowNotFoundError extends EscroError {
885
- constructor(address: string);
886
- }
887
- /**
888
- * The reputation endpoint is not available on this deployment (HTTP 404). A 404
889
- * from `GET /rep` means no `ReputationSource` is mounted (the surface is
890
- * unmounted), NOT that a wallet is unknown - unknown wallets return zeroed raw
891
- * components, never a 404. Kept distinct from {@link EscrowNotFoundError}, whose
892
- * 404 is about a missing escrow.
893
- */
894
- declare class ReputationUnavailableError extends EscroError {
895
- constructor();
896
- }
897
- /** The operation is not valid for the escrow's current state (HTTP 409). */
898
- declare class EscrowStateError extends EscroError {
899
- constructor(message: string);
900
- }
901
- /** Polling timed out after 24 hours without reaching the expected state. */
902
- declare class EscrowTimeoutError extends EscroError {
903
- constructor(address: string);
904
- }
905
- /**
906
- * A transaction landed (or was sent) but the API did not record it. `code` is the
907
- * server's code (e.g. TX_MISMATCH, TX_FAILED, or TX_NOT_FOUND after the retry
908
- * window), `NETWORK_ERROR` when the last attempt never reached the API, or
909
- * `HTTP_<status>` when the answer carried no code. Call {@link Escro.confirm} again
910
- * with `address` and `signature` to retry.
911
- */
912
- declare class EscroConfirmError extends EscroError {
913
- readonly address: string;
914
- readonly signature: string;
915
- constructor(address: string, signature: string, code: string, message: string);
916
- }
917
- /** The caller is not authorized to perform this action (HTTP 401/403). */
918
- declare class UnauthorizedError extends EscroError {
919
- constructor(message?: string);
920
- }
921
- /**
922
- * A payment rail was requested that is not enabled in this build. The `x402`
923
- * (synchronous) rail is reserved (ARCHITECTURE §7a) and lands in Phase 9;
924
- * {@link Escro.pay} throws this until then. `rail` names the unavailable rail.
925
- */
926
- declare class EscroRailNotEnabledError extends EscroError {
927
- readonly rail: string;
928
- constructor(rail: string);
929
- }
930
-
931
1019
  /** Options controlling {@link assertServiceAdapterContract}. */
932
1020
  interface AdapterContractOptions {
933
1021
  /**
@@ -1020,7 +1108,7 @@ interface GradientsAdapterConfig {
1020
1108
  /** Health-check port. Default: resolves `true`. */
1021
1109
  checkHealth?: () => Promise<boolean>;
1022
1110
  }
1023
- /** Stable id/capabilities, LOCKED against `ADAPTER_DESCRIPTORS.gradients` by a kit test (consult C2). */
1111
+ /** Stable id/capabilities, LOCKED against `ADAPTER_DESCRIPTORS.gradients` by a kit test. */
1024
1112
  declare const GRADIENTS_ADAPTER_ID = "bittensor:sn56";
1025
1113
  declare const GRADIENTS_CAPABILITIES: readonly ["fine-tune"];
1026
1114
  /** Stable marker on the demo spec's metadata so the default subnet stub recognizes it. */
@@ -1029,7 +1117,7 @@ declare const GRADIENTS_DEMO_MARKER = "gradients-sn56-demo-v1";
1029
1117
  declare const GRADIENTS_DEMO_EVAL_FLOOR = 0.8;
1030
1118
  /**
1031
1119
  * The canned Gradients demo job. Deterministic; its specHash is pinned by a test
1032
- * (consult C8) because the buyer journey depends on hash stability.
1120
+ * because the buyer journey depends on hash stability.
1033
1121
  */
1034
1122
  declare const gradientsDemoJobSpec: TaskSpec;
1035
1123
  /**
@@ -1042,7 +1130,7 @@ declare function solveGradientsDemo(): string;
1042
1130
  * The BUYER's independent recompute of the demo eval score in [0, 1]. Reads the
1043
1131
  * substantive output (the predictions) and compares it to the target map the buyer
1044
1132
  * itself defines; it deliberately IGNORES any self-reported `eval.score` in the
1045
- * deliverable, so release can never be worker-controlled (consult C10). Malformed
1133
+ * deliverable, so release can never be worker-controlled. Malformed
1046
1134
  * or unparseable content scores 0 and never throws.
1047
1135
  */
1048
1136
  declare function scoreGradientsDemoDeliverable(content: string | Buffer): number;
@@ -1097,8 +1185,8 @@ declare function solveRidgesDemo(): string;
1097
1185
  * The BUYER's independent recompute of the demo acceptance, as a score in [0, 1].
1098
1186
  * It reads the substantive output (the delivered test outputs) and recomputes the
1099
1187
  * expected FizzBuzz result for each; it deliberately IGNORES any self-reported
1100
- * pass/coverage in the deliverable, so release can never be worker-controlled
1101
- * (consult C10). Semantics:
1188
+ * pass/coverage in the deliverable, so release can never be worker-controlled.
1189
+ * Semantics:
1102
1190
  * - Any delivered test whose output is wrong = the suite did not pass (exit != 0):
1103
1191
  * score 0, no matter how much of the battery is covered.
1104
1192
  * - Otherwise the score is coverage = (distinct battery inputs delivered) / (battery
@@ -1114,7 +1202,7 @@ declare function createRidgesAdapter(config?: RidgesAdapterConfig): ServiceAdapt
1114
1202
 
1115
1203
  /**
1116
1204
  * 404gen (Bittensor SN17) ServiceAdapter: a batch 3D-generation reference adapter,
1117
- * built to the pattern the shipped Gradients (SN56) adapter established (P6.T6a). A
1205
+ * built to the pattern the shipped Gradients (SN56) adapter established. A
1118
1206
  * Worker Bot wraps the 404gen text-to-3D subnet behind the `ServiceAdapter` interface:
1119
1207
  * it swaps a per-task USDC budget into TAO internally, pays subnet miners in TAO to
1120
1208
  * generate a batch of 3D assets, collects the batch deliverable, and returns a
@@ -1159,7 +1247,7 @@ interface Gen404AdapterConfig {
1159
1247
  /** Health-check port. Default: resolves `true`. */
1160
1248
  checkHealth?: () => Promise<boolean>;
1161
1249
  }
1162
- /** Stable id/capabilities, to be locked against `ADAPTER_DESCRIPTORS["404gen"]` by a kit test at merge (consult C2). */
1250
+ /** Stable id/capabilities, to be locked against `ADAPTER_DESCRIPTORS["404gen"]` by a kit test at merge. */
1163
1251
  declare const GEN404_ADAPTER_ID = "bittensor:sn17";
1164
1252
  declare const GEN404_CAPABILITIES: readonly ["3d-generation"];
1165
1253
  /** Stable marker on the demo spec's metadata so the default subnet stub recognizes it. */
@@ -1168,7 +1256,7 @@ declare const GEN404_DEMO_MARKER = "404gen-sn17-demo-v1";
1168
1256
  declare const GEN404_DEMO_EVAL_FLOOR = 1;
1169
1257
  /**
1170
1258
  * The canned 404gen demo job. Deterministic; its specHash is pinned by a test
1171
- * (consult C8) because the buyer journey depends on hash stability.
1259
+ * because the buyer journey depends on hash stability.
1172
1260
  */
1173
1261
  declare const gen404DemoJobSpec: TaskSpec;
1174
1262
  /**
@@ -1432,7 +1520,7 @@ declare function solveRenderDemo(): string;
1432
1520
  * the deliverable satisfies all three criteria and 0 otherwise. It checks completion
1433
1521
  * (status), frame presence, and a frame match by RE-RENDERING the scripted scene and
1434
1522
  * comparing the substantive frame; it deliberately IGNORES any self-reported
1435
- * `frameHash`, so release can never be worker-controlled (consult C10). Malformed or
1523
+ * `frameHash`, so release can never be worker-controlled. Malformed or
1436
1524
  * unparseable content scores 0 and never throws.
1437
1525
  */
1438
1526
  declare function scoreRenderDemoDeliverable(content: string | Buffer): number;
@@ -1562,7 +1650,7 @@ declare const gensynDemoJobSpec: TaskSpec;
1562
1650
  */
1563
1651
  declare function createGensynAdapter(config?: GensynAdapterConfig): ServiceAdapter;
1564
1652
 
1565
- /** Stable id/capabilities; locked against the EscroBots registry descriptor by a kit test at merge (consult C2). */
1653
+ /** Stable id/capabilities; locked against the EscroBots registry descriptor by a kit test at merge. */
1566
1654
  declare const ZKML_ADAPTER_ID = "zkml";
1567
1655
  declare const ZKML_CAPABILITIES: readonly ["zk-verified-inference"];
1568
1656
  /** Marker on the demo spec's metadata so the default inference port recognizes it. */
@@ -1637,34 +1725,11 @@ declare function verifyZkmlProof(proof: unknown, expected: ZkmlExpectation): Zkm
1637
1725
  /** Decode an inline proof URI (or reject a missing/foreign one) and verify it. */
1638
1726
  declare function verifyZkmlProofUri(uri: string | null | undefined, expected: ZkmlExpectation): ZkmlVerification;
1639
1727
  /** The submitted deliverable as the Buyer's review reads it off the escrow read model. */
1640
- interface ZkmlDeliverable {
1641
- /**
1642
- * SHA-256 hex the WORKER submitted on-chain (mirrored to the read model). It is the
1643
- * worker's CLAIM about the artifact; {@link zkmlProofAutoRelease} re-hashes the real
1644
- * artifact (via its `fetchContent` port) and never trusts this value on its own.
1645
- */
1646
- contentHash: string;
1647
- /** URI where the ZK proof is (inline `zkml-proof:` or a pinned `ipfs://`), or null. */
1648
- proofUri: string | null;
1649
- }
1728
+ type ZkmlDeliverable = ReviewDeliverable;
1650
1729
  /** A release decision: release, and if not, whether to contest via dispute. */
1651
- interface ZkmlReviewResult {
1652
- accept: boolean;
1653
- dispute: boolean;
1654
- reason: string;
1655
- }
1656
- /**
1657
- * A named release policy the Buyer's review wires in. Field-for-field this mirrors the
1658
- * buyer template's `ReviewPolicy`
1659
- * (packages/create-escro-bot/templates/buyer/src/review.ts). The SDK cannot import the
1660
- * scaffolding templates, and promoting the shared review shapes into `@escro/shared` is
1661
- * a cross-package change owned by `main`, not this lane -- tracked as a merge-time
1662
- * follow-up (LANE-NOTES).
1663
- */
1664
- interface ZkmlReviewPolicy {
1665
- name: string;
1666
- evaluate(deliverable: ZkmlDeliverable): Promise<ZkmlReviewResult>;
1667
- }
1730
+ type ZkmlReviewResult = ReviewResult;
1731
+ /** A named release policy the Buyer's review wires in; `evaluate` may be sync or async. */
1732
+ type ZkmlReviewPolicy = ReviewPolicy;
1668
1733
  /** Options for {@link zkmlProofAutoRelease}. */
1669
1734
  interface ZkmlProofAutoReleaseOptions {
1670
1735
  /**
@@ -1751,4 +1816,5 @@ declare function solveZkmlDemo(): string;
1751
1816
  */
1752
1817
  declare function createZkmlAdapter(config?: ZkmlAdapterConfig): ServiceAdapter;
1753
1818
 
1754
- export { AKASH_ADAPTER_ID, AKASH_CAPABILITIES, AKASH_DEMO_ACCEPT_FLOOR, AKASH_DEMO_MARKER, type AcceptanceCriterion, AdapterContractError, type AdapterContractOptions, type AkashAdapterConfig, type Akt, ApiClient, type AutoReleaseDecision, type BotDescriptor, type BotRole, type CreateEscrowParams, type CreateEscrowResult, type DeliverableFormat, type DeliverableType, ENABLED_RAILS, Escro, EscroConfirmError, EscroError, type EscroOptions, EscroRailNotEnabledError, type EscrowAccount, type EscrowErrorCode, EscrowNotFoundError, EscrowPaymentRouter, EscrowState, EscrowStateError, EscrowTimeoutError, GEN404_ADAPTER_ID, GEN404_CAPABILITIES, GEN404_DEMO_EVAL_FLOOR, GEN404_DEMO_MARKER, GENSYN_ADAPTER_ID, GENSYN_CAPABILITIES, GENSYN_DEMO_MARKER, GENSYN_REE_SCHEME, GRADIENTS_ADAPTER_ID, GRADIENTS_CAPABILITIES, GRADIENTS_DEMO_EVAL_FLOOR, GRADIENTS_DEMO_MARKER, type Gen404AdapterConfig, type GensynAdapterConfig, type GensynDeliverableBundle, type GradientsAdapterConfig, LIUM_ADAPTER_ID, LIUM_CAPABILITIES, LIUM_DEMO_ACCEPT_FLOOR, LIUM_DEMO_MARKER, type ListBotsParams, type ListOptions, type LiumAdapterConfig, type Network, type PaginatedResult, type PayParams, type PaymentResult, type PaymentRouter, type PinContent$3 as PinContent, type PollOptions, type ProtocolStats, RAILS, RAILS_DOCS_URL, REFERENCE_MICRO_USDC_PER_AKT, REFERENCE_MICRO_USDC_PER_RENDER, RENDER_ADAPTER_ID, RENDER_CAPABILITIES, RENDER_DEMO_ACCEPT_FLOOR, RENDER_DEMO_MARKER, RIDGES_ADAPTER_ID, RIDGES_CAPABILITIES, RIDGES_DEMO_COVERAGE_TARGET, RIDGES_DEMO_MARKER, type Rail, type RaiseDisputeParams, type ReeExecution, type ReeProof, type ReeVerification, type ReeVerifyContext, type Render, type RenderAdapterConfig, type ReproduceCompute, ReputationUnavailableError, type RidgesAdapterConfig, type RunAkashDeployment, type RunCodingAgent, type RunGpuJob, type RunRenderJob, type ServedWalletReputation, type ServiceAdapter, type ServiceResult, type SubmitDeliverableParams, type SubnetCall, type Tao, type TaskSpec, type TaskType, type TxShape, UnauthorizedError, type UnsignedBotDescriptor, type UsdcToAktSwap, type UsdcToRenderSwap, type UsdcToTaoSwap, type WorkerCandidate, ZKML_ADAPTER_ID, ZKML_CAPABILITIES, ZKML_DEMO_MARKER, ZKML_PROOF_SCHEME, ZKML_PROOF_URI_PREFIX, type ZkmlAdapterConfig, type ZkmlDeliverable, type ZkmlExpectation, type ZkmlInferenceOutput, type ZkmlProof, type ZkmlProofAutoReleaseOptions, type ZkmlReviewPolicy, type ZkmlReviewResult, type ZkmlVerification, akashDemoJobSpec, akt, assertServiceAdapterContract, buildReeProof, buildZkmlProof, computeAkashDemoArtifact, computeLiumDemoArtifact, computeRenderDemoArtifact, create404genAdapter, createAkashAdapter, createGensynAdapter, createGradientsAdapter, createLiumAdapter, createRenderAdapter, createRidgesAdapter, createZkmlAdapter, decodeZkmlProofUri, encodeZkmlProofUri, gen404DemoJobSpec, gensynAutoRelease, gensynDemoJobSpec, gradientsDemoJobSpec, liumDemoJobSpec, renderAmount, renderDemoJobSpec, reproduceGensynCompute, ridgesDemoJobSpec, score404genDemoDeliverable, scoreAkashDemoDeliverable, scoreGradientsDemoDeliverable, scoreLiumDemoDeliverable, scoreRenderDemoDeliverable, scoreRidgesDemoDeliverable, serviceResultToSubmitParams, solveAkashDemo, solveGen404Demo, solveGradientsDemo, solveLiumDemo, solveRenderDemo, solveRidgesDemo, solveZkmlDemo, tao, verifyReeProof, verifyZkmlProof, verifyZkmlProofUri, zkmlDemoJobSpec, zkmlProofAutoRelease };
1819
+ export { AKASH_ADAPTER_ID, AKASH_CAPABILITIES, AKASH_DEMO_ACCEPT_FLOOR, AKASH_DEMO_MARKER, AdapterContractError, ApiClient, ENABLED_RAILS, Escro, EscroConfirmError, EscroError, EscroRailNotEnabledError, EscrowNotFoundError, EscrowPaymentRouter, EscrowState, EscrowStateError, EscrowTimeoutError, GEN404_ADAPTER_ID, GEN404_CAPABILITIES, GEN404_DEMO_EVAL_FLOOR, GEN404_DEMO_MARKER, GENSYN_ADAPTER_ID, GENSYN_CAPABILITIES, GENSYN_DEMO_MARKER, GENSYN_REE_SCHEME, GRADIENTS_ADAPTER_ID, GRADIENTS_CAPABILITIES, GRADIENTS_DEMO_EVAL_FLOOR, GRADIENTS_DEMO_MARKER, LIUM_ADAPTER_ID, LIUM_CAPABILITIES, LIUM_DEMO_ACCEPT_FLOOR, LIUM_DEMO_MARKER, RAILS, RAILS_DOCS_URL, REFERENCE_MICRO_USDC_PER_AKT, REFERENCE_MICRO_USDC_PER_RENDER, RENDER_ADAPTER_ID, RENDER_CAPABILITIES, RENDER_DEMO_ACCEPT_FLOOR, RENDER_DEMO_MARKER, RIDGES_ADAPTER_ID, RIDGES_CAPABILITIES, RIDGES_DEMO_COVERAGE_TARGET, RIDGES_DEMO_MARKER, ReputationUnavailableError, UnauthorizedError, ZKML_ADAPTER_ID, ZKML_CAPABILITIES, ZKML_DEMO_MARKER, ZKML_PROOF_SCHEME, ZKML_PROOF_URI_PREFIX, akashDemoJobSpec, akt, assertServiceAdapterContract, buildReeProof, buildZkmlProof, computeAkashDemoArtifact, computeLiumDemoArtifact, computeRenderDemoArtifact, create404genAdapter, createAkashAdapter, createGensynAdapter, createGradientsAdapter, createLiumAdapter, createRenderAdapter, createRidgesAdapter, createZkmlAdapter, decodeZkmlProofUri, encodeZkmlProofUri, gen404DemoJobSpec, gensynAutoRelease, gensynDemoJobSpec, gradientsDemoJobSpec, liumDemoJobSpec, renderAmount, renderDemoJobSpec, reproduceGensynCompute, ridgesDemoJobSpec, score404genDemoDeliverable, scoreAkashDemoDeliverable, scoreGradientsDemoDeliverable, scoreLiumDemoDeliverable, scoreRenderDemoDeliverable, scoreRidgesDemoDeliverable, serviceResultToSubmitParams, solveAkashDemo, solveGen404Demo, solveGradientsDemo, solveLiumDemo, solveRenderDemo, solveRidgesDemo, solveZkmlDemo, tao, verifyReeProof, verifyZkmlProof, verifyZkmlProofUri, zkmlDemoJobSpec, zkmlProofAutoRelease };
1820
+ export type { AcceptanceCriterion, AdapterContractOptions, AkashAdapterConfig, Akt, AutoReleaseDecision, BotDescriptor, BotRole, CreateEscrowParams, CreateEscrowResult, DeliverableFormat, DeliverableType, EscroOptions, EscrowAccount, EscrowErrorCode, Gen404AdapterConfig, GensynAdapterConfig, GensynDeliverableBundle, GradientsAdapterConfig, ListBotsParams, ListOptions, LiumAdapterConfig, Network, PaginatedResult, PayParams, PaymentResult, PaymentRouter, PinContent$3 as PinContent, PollOptions, ProtocolStats, Rail, RaiseDisputeParams, ReeExecution, ReeProof, ReeVerification, ReeVerifyContext, ReleasePaymentOutcome, Render, RenderAdapterConfig, ReproduceCompute, RidgesAdapterConfig, RunAkashDeployment, RunCodingAgent, RunGpuJob, RunRenderJob, ServedWalletReputation, ServiceAdapter, ServiceResult, SubmitDeliverableParams, SubnetCall, Tao, TaskSpec, TaskType, TxShape, UnsignedBotDescriptor, UsdcToAktSwap, UsdcToRenderSwap, UsdcToTaoSwap, WorkerCandidate, ZkmlAdapterConfig, ZkmlDeliverable, ZkmlExpectation, ZkmlInferenceOutput, ZkmlProof, ZkmlProofAutoReleaseOptions, ZkmlReviewPolicy, ZkmlReviewResult, ZkmlVerification };