* End-to-end ATP task completion driver. * * @param {object} opts * @param {string} opts.taskId - Hub task row id (required) * @param {string} opts.orderId - ATP DeliveryProof id (required) * @param {string} opts.answerFile - Path to file holding the merchant answer (required) * @param
(opts)
| 207 | * @returns {Promise<{ok:boolean, stage?:string, error?:string, assetId?:string}>} |
| 208 | */ |
| 209 | async function completeAtpTask(opts) { |
| 210 | const taskId = opts && opts.taskId; |
| 211 | const orderId = opts && opts.orderId; |
| 212 | const answerFile = opts && opts.answerFile; |
| 213 | if (!taskId || !orderId || !answerFile) { |
| 214 | return { ok: false, stage: 'input', error: 'taskId, orderId, answerFile are required' }; |
| 215 | } |
| 216 | |
| 217 | let answer; |
| 218 | try { |
| 219 | answer = _readAnswer(answerFile); |
| 220 | } catch (e) { |
| 221 | return { ok: false, stage: 'read_answer', error: e && e.message }; |
| 222 | } |
| 223 | |
| 224 | const handshakeOk = await _ensureNodeSecret(); |
| 225 | if (!handshakeOk) { |
| 226 | return { ok: false, stage: 'hello', error: 'failed to register with hub; node_secret missing' }; |
| 227 | } |
| 228 | |
| 229 | const gene = _buildGene(opts.capabilities, opts.signals); |
| 230 | const capsule = _buildCapsule({ |
| 231 | gene, |
| 232 | answer, |
| 233 | summary: opts.summary, |
| 234 | orderId, |
| 235 | taskId, |
| 236 | capabilities: opts.capabilities, |
| 237 | signals: opts.signals, |
| 238 | }); |
| 239 | |
| 240 | const pub = await _publishBundle(gene, capsule); |
| 241 | if (!pub.ok) { |
| 242 | return { ok: false, stage: 'publish', error: pub.error || 'publish_failed', details: pub }; |
| 243 | } |
| 244 | const decision = pub.data && pub.data.payload && pub.data.payload.decision; |
| 245 | if (decision && decision !== 'accept') { |
| 246 | const reason = pub.data.payload.reason || 'unknown'; |
| 247 | return { ok: false, stage: 'publish', error: 'publish_rejected: ' + reason, details: pub.data }; |
| 248 | } |
| 249 | |
| 250 | const complete = await _completeTaskOnHub(taskId, capsule.asset_id); |
| 251 | if (!complete.ok) { |
| 252 | return { ok: false, stage: 'complete', error: complete.error || 'complete_failed', details: complete }; |
| 253 | } |
| 254 | |
| 255 | const proofPayload = { |
| 256 | asset_id: capsule.asset_id, |
| 257 | result: capsule.summary, |
| 258 | content_hash: capsule.asset_id, |
| 259 | pass_rate: 1.0, |
| 260 | delivered_by: getNodeId(), |
| 261 | task_id: taskId, |
| 262 | }; |
| 263 | |
| 264 | const delivery = await submitDelivery(orderId, proofPayload); |
| 265 | if (!delivery || !delivery.ok) { |
| 266 | return { |
no test coverage detected