@taifoon/jev 0.1.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/LICENSE +18 -0
- package/README.md +222 -0
- package/bin/jev.mjs +37 -0
- package/dist/abi.d.ts +11 -0
- package/dist/abi.js +81 -0
- package/dist/ask.d.ts +27 -0
- package/dist/ask.js +47 -0
- package/dist/contracts.d.ts +37 -0
- package/dist/contracts.js +27 -0
- package/dist/evaluator/assurance-hook.d.ts +6 -0
- package/dist/evaluator/assurance-hook.js +15 -0
- package/dist/evaluator/bitagent-erc8183.d.ts +7 -0
- package/dist/evaluator/bitagent-erc8183.js +18 -0
- package/dist/evaluator/index.d.ts +12 -0
- package/dist/evaluator/index.js +20 -0
- package/dist/evaluator/judge-adapter.d.ts +5 -0
- package/dist/evaluator/judge-adapter.js +16 -0
- package/dist/evaluator/types.d.ts +27 -0
- package/dist/evaluator/types.js +6 -0
- package/dist/evaluator/virtuals-erc8183.d.ts +6 -0
- package/dist/evaluator/virtuals-erc8183.js +15 -0
- package/dist/evaluator/virtuals-memo-acp.d.ts +5 -0
- package/dist/evaluator/virtuals-memo-acp.js +15 -0
- package/dist/facts.d.ts +16 -0
- package/dist/facts.js +15 -0
- package/dist/grade.d.ts +32 -0
- package/dist/grade.js +33 -0
- package/dist/hash.d.ts +10 -0
- package/dist/hash.js +132 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +20 -0
- package/dist/receipt.d.ts +68 -0
- package/dist/receipt.js +42 -0
- package/dist/record.d.ts +32 -0
- package/dist/record.js +41 -0
- package/dist/records.d.ts +78 -0
- package/dist/records.js +55 -0
- package/dist/rubric.d.ts +109 -0
- package/dist/rubric.js +91 -0
- package/dist/verify.d.ts +40 -0
- package/dist/verify.js +80 -0
- package/package.json +73 -0
- package/workflows/0.1.0/README.md +104 -0
- package/workflows/0.1.0/batch-judge.json +341 -0
- package/workflows/0.1.0/hire-judge-settle.json +767 -0
- package/workflows/0.1.0/jev-grader.json +433 -0
- package/workflows/0.1.0/manifest.json +151 -0
- package/workflows/0.1.0/schemas/answers.json +248 -0
- package/workflows/0.1.0/schemas/common.json +394 -0
- package/workflows/0.1.0/schemas/delivery.json +233 -0
- package/workflows/0.1.0/schemas/facts.json +225 -0
- package/workflows/0.1.0/schemas/hire.json +337 -0
- package/workflows/0.1.0/schemas/job.json +96 -0
- package/workflows/0.1.0/schemas/settlement.json +225 -0
- package/workflows/0.1.0/schemas/verdict.json +314 -0
- package/workflows/0.1.0/stamp-grade.json +175 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Taifoon — batch judge scores for the coordination layer (TypeSafe/Jev)",
|
|
3
|
+
"nodes": [
|
|
4
|
+
{
|
|
5
|
+
"parameters": {},
|
|
6
|
+
"id": "trigger",
|
|
7
|
+
"name": "Grade a batch",
|
|
8
|
+
"type": "n8n-nodes-base.manualTrigger",
|
|
9
|
+
"typeVersion": 1,
|
|
10
|
+
"position": [
|
|
11
|
+
200,
|
|
12
|
+
300
|
|
13
|
+
],
|
|
14
|
+
"notes": "in: — → out: — · start a batch (pass { subjects, jobId, threshold } or run the demo set)",
|
|
15
|
+
"notesInFlow": true
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"parameters": {
|
|
19
|
+
"jsCode": "// The batch: subjects already delivered (a handshake, or a job read from the chain), one canonical HIRE each. The\n// judge builds every evidence pack itself from DELIVERY + FACTS (schemas/GRADEABLE.md) — nothing here hands Jev a\n// state. Pass { subjects: [{ handshake_id } | { chainId, jobId }], jobId, threshold } on the trigger, or run the demo set.\nconst t = $input.first().json || {};\nconst subjects = Array.isArray(t.subjects) && t.subjects.length ? t.subjects : [\n { handshake_id: 'hs_97dcf5942e294f7ca28efd0a' }, { handshake_id: 'hs_ec150f74dbe6568982c6c93d' }, { handshake_id: 'hs_c07ccb807a29b94dffb18459' },\n];\nreturn subjects.map((s) => {\n const hs = typeof s.handshake_id === 'string' && /^hs_[0-9a-f]{24}$/.test(s.handshake_id) ? s.handshake_id : null;\n const chainId = s.chainId != null ? Number(s.chainId) : hs ? 36927 : 8453;\n const id = hs ?? String(s.jobId);\n const job = hs ? { key: 'hs:' + hs, lane: 'handshake', chain_id: chainId, id: hs, contract: null }\n : { key: 'erc8183:' + chainId + ':' + id, lane: 'erc8183', chain_id: chainId, id, contract: '0x238e541bfefd82238730d00a2208e5497f1832e0' };\n return { json: {\n schema: 'taifoon.hire.v1', job, lane: job.lane, tenant: null, buyer: null, seller: null, seller_agent_key: null, seller_ids: [],\n evaluator: null, hook: null, evaluator_kind: null, task: null, required_skills: [], budget: null, funding: null,\n created_at: null, deadline: null, handshake_id: hs, offer_nonce: null, state: 'Delivered', ending: null,\n anchors: [{ kind: 'offchain', store: hs ? 'coordd:coordination_handshakes' : 'observatory', key: id, digest: null, anchored_by: null, what: 'the subject this batch grades' }],\n source: { kind: hs ? 'handshake' : 'observatory-job', url: hs ? 'https://www.taifoon.io/v1/handshake/' + hs : 'https://www.taifoon.io/v1/judge/evidence/' + chainId + '/' + id, read_at: Math.floor(Date.now() / 1000) },\n } };\n});"
|
|
20
|
+
},
|
|
21
|
+
"id": "e177aad3-f294-4ac5-beae-395993bd7de5",
|
|
22
|
+
"name": "Build the batch",
|
|
23
|
+
"type": "n8n-nodes-base.code",
|
|
24
|
+
"typeVersion": 2,
|
|
25
|
+
"position": [
|
|
26
|
+
420,
|
|
27
|
+
300
|
|
28
|
+
],
|
|
29
|
+
"notes": "in: — → out: hire.json · one canonical HIRE per subject (a delivered handshake, or a job on chain); no state is built here",
|
|
30
|
+
"notesInFlow": true
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "Judge · prepare",
|
|
34
|
+
"type": "CUSTOM.taifoon",
|
|
35
|
+
"typeVersion": 1,
|
|
36
|
+
"position": [
|
|
37
|
+
640,
|
|
38
|
+
300
|
|
39
|
+
],
|
|
40
|
+
"parameters": {
|
|
41
|
+
"resource": "judge",
|
|
42
|
+
"operation": "compose",
|
|
43
|
+
"composeSubject": "={{ $json.lane === 'handshake' ? 'handshake' : 'job' }}",
|
|
44
|
+
"composeHandshakeId": "={{ $json.handshake_id }}",
|
|
45
|
+
"composeMode": "prepare",
|
|
46
|
+
"composeJobId": "={{ $json.job.id }}",
|
|
47
|
+
"composeChainId": "={{ $json.job.chain_id }}"
|
|
48
|
+
},
|
|
49
|
+
"credentials": {
|
|
50
|
+
"taifoonRelayerApi": {
|
|
51
|
+
"id": "",
|
|
52
|
+
"name": "REPLACE: taifoonRelayerApi"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"id": "62dca0ae-d853-414f-ac98-89592623c7d2",
|
|
56
|
+
"notes": "in: hire.json → out: facts.json · POST /v1/judge/compose (prepare) per subject: the facts decide first; the pack is built from DELIVERY + FACTS; else the exact text Jev reads + prepare_digest",
|
|
57
|
+
"notesInFlow": true
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "Hard fail?",
|
|
61
|
+
"type": "n8n-nodes-base.if",
|
|
62
|
+
"typeVersion": 2.2,
|
|
63
|
+
"position": [
|
|
64
|
+
860,
|
|
65
|
+
300
|
|
66
|
+
],
|
|
67
|
+
"parameters": {
|
|
68
|
+
"conditions": {
|
|
69
|
+
"options": {
|
|
70
|
+
"caseSensitive": true,
|
|
71
|
+
"leftValue": "",
|
|
72
|
+
"typeValidation": "strict",
|
|
73
|
+
"version": 2
|
|
74
|
+
},
|
|
75
|
+
"conditions": [
|
|
76
|
+
{
|
|
77
|
+
"id": "h1",
|
|
78
|
+
"leftValue": "={{ $json.hard_fail === true }}",
|
|
79
|
+
"rightValue": "",
|
|
80
|
+
"operator": {
|
|
81
|
+
"type": "boolean",
|
|
82
|
+
"operation": "true",
|
|
83
|
+
"singleValue": true
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"combinator": "and"
|
|
88
|
+
},
|
|
89
|
+
"options": {}
|
|
90
|
+
},
|
|
91
|
+
"id": "65ffd12f-ea5f-4a36-98c4-eea5f9afec86",
|
|
92
|
+
"notes": "in: facts.json → out: facts.json · branch: a hard fail is final (Jev is not asked) and goes straight to the batch",
|
|
93
|
+
"notesInFlow": true
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "Jev · TypeSafe (our credential)",
|
|
97
|
+
"type": "@taifoon/n8n-nodes-typesafe.taifoonTypeSafe",
|
|
98
|
+
"typeVersion": 1,
|
|
99
|
+
"position": [
|
|
100
|
+
1080,
|
|
101
|
+
420
|
|
102
|
+
],
|
|
103
|
+
"parameters": {
|
|
104
|
+
"operation": "ask",
|
|
105
|
+
"connection": "direct",
|
|
106
|
+
"state": "={{ JSON.stringify($json.jev.state) }}",
|
|
107
|
+
"questions": {},
|
|
108
|
+
"questionsJson": "={{ JSON.stringify($json.jev.questions) }}",
|
|
109
|
+
"routing": "{}",
|
|
110
|
+
"replyLanguage": "off",
|
|
111
|
+
"failClosed": true
|
|
112
|
+
},
|
|
113
|
+
"credentials": {
|
|
114
|
+
"taifoonTypeSafeApi": {
|
|
115
|
+
"id": "",
|
|
116
|
+
"name": "REPLACE: taifoonTypeSafeApi"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"notes": "in: facts.json → out: answers.json · TypeSafe ask on the prepared text (jevStateOf): every RUBRIC_ASKED answer with its whole distribution",
|
|
120
|
+
"id": "f2965735-6523-490f-a551-865edd654baf",
|
|
121
|
+
"notesInFlow": true
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "Judge · answers",
|
|
125
|
+
"type": "CUSTOM.taifoon",
|
|
126
|
+
"typeVersion": 1,
|
|
127
|
+
"position": [
|
|
128
|
+
1300,
|
|
129
|
+
420
|
|
130
|
+
],
|
|
131
|
+
"parameters": {
|
|
132
|
+
"resource": "judge",
|
|
133
|
+
"operation": "compose",
|
|
134
|
+
"composeSubject": "={{ $('Build the batch').item.json.lane === 'handshake' ? 'handshake' : 'job' }}",
|
|
135
|
+
"composeHandshakeId": "={{ $('Build the batch').item.json.handshake_id }}",
|
|
136
|
+
"composeMode": "answers",
|
|
137
|
+
"composeAnswers": "={{ JSON.stringify($json.answers) }}",
|
|
138
|
+
"composeModel": "={{ $json.model }}",
|
|
139
|
+
"composePrepareDigest": "={{ $('Judge · prepare').item.json.prepare_digest }}",
|
|
140
|
+
"composeAnsweredBy": "n8n-typesafe",
|
|
141
|
+
"composeExecutionId": "={{ $execution.id }}",
|
|
142
|
+
"composeLatencyMs": "={{ $json.latency_ms }}",
|
|
143
|
+
"composeJobId": "={{ $('Build the batch').item.json.job.id }}",
|
|
144
|
+
"composeChainId": "={{ $('Build the batch').item.json.job.chain_id }}"
|
|
145
|
+
},
|
|
146
|
+
"credentials": {
|
|
147
|
+
"taifoonRelayerApi": {
|
|
148
|
+
"id": "",
|
|
149
|
+
"name": "REPLACE: taifoonRelayerApi"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"id": "0ca9f21a-aff6-4fa1-8cc7-c0924dc1cce3",
|
|
153
|
+
"notes": "in: answers.json → out: verdict.json · POST /v1/judge/compose (answers): recompose under THRESHOLDS_v1, record decision.v2 and the answers (jev.answer.v1), anchor both",
|
|
154
|
+
"notesInFlow": true
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"parameters": {
|
|
158
|
+
"jsCode": "// The batch outcome from the recorded verdicts — each item was composed under THRESHOLDS_v1 and recorded (decision.v2\n// + jev.answer.v1) by Judge · answers; a hard fail was final at prepare. complete → Conformant, reject → NonConformant,\n// needs_review → NoGrade (the verdict crate's batch mapping). Runs once per branch that reaches it; the batch record\n// is keyed by jobId, so the last (complete) run is the one that stays.\nconst t = $('Grade a batch').first().json || {};\nconst jobId = t.jobId || 'batch-' + $execution.id;\nconst threshold = typeof t.threshold === 'number' ? t.threshold : 0.2;\nconst prepared = $('Judge · prepare').all().map((i) => i.json);\nlet answered = [];\ntry { answered = $('Judge · answers').all().map((i) => i.json); } catch (e) { answered = []; }\nconst items = [];\nfor (const p of prepared.filter((x) => x.hard_fail === true)) items.push({ item_id: p.subject, verdict: 'NonConformant', composed: 'reject', forced: 'hard_fail', mode: 'Deterministic', decision_id: null, answers_digest: null });\nfor (const a of answered) {\n const v = a.receipt && a.receipt.verdict;\n items.push({ item_id: (a.decision && a.decision.subject_id) || null, verdict: v === 'complete' ? 'Conformant' : v === 'reject' ? 'NonConformant' : 'NoGrade', composed: v || null, forced: null, mode: 'Calibrated',\n decision_id: a.decision ? a.decision.id : null, decision_digest: a.decision ? a.decision.digest : null, answers_digest: a.decision ? a.decision.answers_digest ?? null : null });\n}\nconst conformant = items.filter((i) => i.verdict === 'Conformant').length, nonconformant = items.filter((i) => i.verdict === 'NonConformant').length, nograde = items.length - conformant - nonconformant;\nconst graded = conformant + nonconformant, failFraction = graded === 0 ? 1 : nonconformant / graded;\nreturn [{ json: { jobId, mode: 'Calibrated', total: items.length, conformant, nonconformant, nograde, failFraction, threshold,\n verdict: graded === 0 ? 'NoGrade' : failFraction <= threshold ? 'Conformant' : 'NonConformant', items } }];"
|
|
159
|
+
},
|
|
160
|
+
"id": "64dce113-21e8-454e-8a12-53858bd7a303",
|
|
161
|
+
"name": "Grade + aggregate",
|
|
162
|
+
"type": "n8n-nodes-base.code",
|
|
163
|
+
"typeVersion": 2,
|
|
164
|
+
"position": [
|
|
165
|
+
1520,
|
|
166
|
+
300
|
|
167
|
+
],
|
|
168
|
+
"notes": "in: facts.json | verdict.json → out: — · the batch outcome from the recorded verdicts (Conformant / NonConformant / NoGrade counts, fail fraction vs threshold) — a batch record, not a canonical entity",
|
|
169
|
+
"notesInFlow": true
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"parameters": {
|
|
173
|
+
"method": "POST",
|
|
174
|
+
"url": "https://www.taifoon.io/v1/judge/batch",
|
|
175
|
+
"authentication": "predefinedCredentialType",
|
|
176
|
+
"nodeCredentialType": "taifoonRelayerApi",
|
|
177
|
+
"sendBody": true,
|
|
178
|
+
"specifyBody": "json",
|
|
179
|
+
"jsonBody": "={{ JSON.stringify($json) }}",
|
|
180
|
+
"options": {}
|
|
181
|
+
},
|
|
182
|
+
"id": "record",
|
|
183
|
+
"name": "Record the batch to the coordination layer",
|
|
184
|
+
"type": "n8n-nodes-base.httpRequest",
|
|
185
|
+
"typeVersion": 4.2,
|
|
186
|
+
"position": [
|
|
187
|
+
1740,
|
|
188
|
+
300
|
|
189
|
+
],
|
|
190
|
+
"credentials": {
|
|
191
|
+
"taifoonRelayerApi": {
|
|
192
|
+
"id": "",
|
|
193
|
+
"name": "REPLACE: taifoonRelayerApi"
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"notes": "in: — → out: — · POST /v1/judge/batch (relayer key): the batch record, keyed batch:<jobId>",
|
|
197
|
+
"notesInFlow": true
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
"connections": {
|
|
201
|
+
"Grade a batch": {
|
|
202
|
+
"main": [
|
|
203
|
+
[
|
|
204
|
+
{
|
|
205
|
+
"node": "Build the batch",
|
|
206
|
+
"type": "main",
|
|
207
|
+
"index": 0
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
"Build the batch": {
|
|
213
|
+
"main": [
|
|
214
|
+
[
|
|
215
|
+
{
|
|
216
|
+
"node": "Judge · prepare",
|
|
217
|
+
"type": "main",
|
|
218
|
+
"index": 0
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
"Judge · prepare": {
|
|
224
|
+
"main": [
|
|
225
|
+
[
|
|
226
|
+
{
|
|
227
|
+
"node": "Hard fail?",
|
|
228
|
+
"type": "main",
|
|
229
|
+
"index": 0
|
|
230
|
+
}
|
|
231
|
+
]
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
"Hard fail?": {
|
|
235
|
+
"main": [
|
|
236
|
+
[
|
|
237
|
+
{
|
|
238
|
+
"node": "Grade + aggregate",
|
|
239
|
+
"type": "main",
|
|
240
|
+
"index": 0
|
|
241
|
+
}
|
|
242
|
+
],
|
|
243
|
+
[
|
|
244
|
+
{
|
|
245
|
+
"node": "Jev · TypeSafe (our credential)",
|
|
246
|
+
"type": "main",
|
|
247
|
+
"index": 0
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
]
|
|
251
|
+
},
|
|
252
|
+
"Jev · TypeSafe (our credential)": {
|
|
253
|
+
"main": [
|
|
254
|
+
[
|
|
255
|
+
{
|
|
256
|
+
"node": "Judge · answers",
|
|
257
|
+
"type": "main",
|
|
258
|
+
"index": 0
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"Judge · answers": {
|
|
264
|
+
"main": [
|
|
265
|
+
[
|
|
266
|
+
{
|
|
267
|
+
"node": "Grade + aggregate",
|
|
268
|
+
"type": "main",
|
|
269
|
+
"index": 0
|
|
270
|
+
}
|
|
271
|
+
]
|
|
272
|
+
]
|
|
273
|
+
},
|
|
274
|
+
"Grade + aggregate": {
|
|
275
|
+
"main": [
|
|
276
|
+
[
|
|
277
|
+
{
|
|
278
|
+
"node": "Record the batch to the coordination layer",
|
|
279
|
+
"type": "main",
|
|
280
|
+
"index": 0
|
|
281
|
+
}
|
|
282
|
+
]
|
|
283
|
+
]
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
"settings": {
|
|
287
|
+
"executionOrder": "v1"
|
|
288
|
+
},
|
|
289
|
+
"active": false,
|
|
290
|
+
"meta": {
|
|
291
|
+
"taifoon": {
|
|
292
|
+
"contract": "https://www.taifoon.io/schemas/coordination/v1/",
|
|
293
|
+
"steps": {
|
|
294
|
+
"Grade a batch": {
|
|
295
|
+
"in": null,
|
|
296
|
+
"out": null,
|
|
297
|
+
"does": "start a batch (pass { subjects, jobId, threshold } or run the demo set)"
|
|
298
|
+
},
|
|
299
|
+
"Build the batch": {
|
|
300
|
+
"in": null,
|
|
301
|
+
"out": "https://www.taifoon.io/schemas/coordination/v1/hire.json",
|
|
302
|
+
"does": "one canonical HIRE per subject (a delivered handshake, or a job on chain); no state is built here"
|
|
303
|
+
},
|
|
304
|
+
"Judge · prepare": {
|
|
305
|
+
"in": "https://www.taifoon.io/schemas/coordination/v1/hire.json",
|
|
306
|
+
"out": "https://www.taifoon.io/schemas/coordination/v1/facts.json",
|
|
307
|
+
"does": "POST /v1/judge/compose (prepare) per subject: the facts decide first; the pack is built from DELIVERY + FACTS; else the exact text Jev reads + prepare_digest"
|
|
308
|
+
},
|
|
309
|
+
"Hard fail?": {
|
|
310
|
+
"in": "https://www.taifoon.io/schemas/coordination/v1/facts.json",
|
|
311
|
+
"out": "https://www.taifoon.io/schemas/coordination/v1/facts.json",
|
|
312
|
+
"does": "branch: a hard fail is final (Jev is not asked) and goes straight to the batch"
|
|
313
|
+
},
|
|
314
|
+
"Jev · TypeSafe (our credential)": {
|
|
315
|
+
"in": "https://www.taifoon.io/schemas/coordination/v1/facts.json",
|
|
316
|
+
"out": "https://www.taifoon.io/schemas/coordination/v1/answers.json",
|
|
317
|
+
"does": "TypeSafe ask on the prepared text (jevStateOf): every RUBRIC_ASKED answer with its whole distribution"
|
|
318
|
+
},
|
|
319
|
+
"Judge · answers": {
|
|
320
|
+
"in": "https://www.taifoon.io/schemas/coordination/v1/answers.json",
|
|
321
|
+
"out": "https://www.taifoon.io/schemas/coordination/v1/verdict.json",
|
|
322
|
+
"does": "POST /v1/judge/compose (answers): recompose under THRESHOLDS_v1, record decision.v2 and the answers (jev.answer.v1), anchor both"
|
|
323
|
+
},
|
|
324
|
+
"Grade + aggregate": {
|
|
325
|
+
"in": [
|
|
326
|
+
"https://www.taifoon.io/schemas/coordination/v1/facts.json",
|
|
327
|
+
"https://www.taifoon.io/schemas/coordination/v1/verdict.json"
|
|
328
|
+
],
|
|
329
|
+
"out": null,
|
|
330
|
+
"does": "the batch outcome from the recorded verdicts (Conformant / NonConformant / NoGrade counts, fail fraction vs threshold) — a batch record, not a canonical entity"
|
|
331
|
+
},
|
|
332
|
+
"Record the batch to the coordination layer": {
|
|
333
|
+
"in": null,
|
|
334
|
+
"out": null,
|
|
335
|
+
"does": "POST /v1/judge/batch (relayer key): the batch record, keyed batch:<jobId>"
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
"tags": []
|
|
341
|
+
}
|