import test from 'node:test' import assert from 'node:assert/strict' import { plan, execute, executionOptions, validateManifest, fixtureSource, expectedRows, scale, verifyActual, runCase, redact, multipartAdapter, requestInit, validateResumeProof, validateResumeLive, resumeMeasurementDraft, validateZeroWorkTask, validatePreparedResume, originalCompletionCommand, verifyPhysicalFacts, verifyOldOwnersUnchanged, verifyDownstream } from './partial-loading-actual-test-env.mjs' import { fileURLToPath } from 'node:url' import { resolve } from 'node:path' import { createServer } from 'node:http' const runId = 'PARTIAL-ACTUAL-offline' const evidence = Object.fromEntries(['PHOTO_STEP_1','PHOTO_STEP_2','PHOTO_STEP_3','PHOTO_STEP_4','SEAL'].map(type => [type, 'sample.png'])) function fixture(kind = 'B') { const definitions = kind === 'B' ? [[1, 11, 2, 'BUY_DECLARATION'], [2, 22, 1, 'TAX_REFUND']] : [[1, 11, 3, 'TAX_REFUND'], [2, 11, 1, 'TAX_REFUND'], [3, 22, 1, 'BUY_DECLARATION'], [4, 33, 1, 'TAX_REFUND']] const task = { id: '91', loadingPlanId: '90', containerBookingId: '92', version: 0, items: definitions.map(([n, tenant, count]) => ({ id: String(n), loadingPlanItemId: String(n + 100), tenantId: String(tenant), inboundId: String(kind === 'A' && n === 2 ? 1 : n), inboundDetailId: String(n + 200), plannedPackageCount: count, pickedPackageCount: 0, itemStatus: 'PENDING', unitType: 'PACKAGE', palletId: null, version: 0 })) } const preload = { items: definitions.map(([n, tenant, count, tax]) => ({ itemId: String(n + 100), accountId: String(tenant), inboundId: String(kind === 'A' && n === 2 ? 1 : n), inboundDetailId: String(n + 200), customsTaxMode: tax, orderId: String(n + 300), packageCount: count, productQuantity: count * 7, unitsPerPackage: 7, grossWeightKg: '10.001', netWeightKg: '8.002', dimensionalWeightKg: '6.004', volumeCbm: '0.1001' })) } const spec = { kind, sourceReport: `${kind}.json`, evidence, sealNo: 'SEAL-TEST', actions: definitions.map(([n]) => ({ itemId: String(n), action: n === 1 ? 'PARTIAL' : kind === 'A' && n === 3 ? 'PICK' : 'SKIP', ...(n === 1 ? { finalPickedPackageCount: kind === 'A' ? 2 : 1 } : {}) })) } const expected = expectedRows(spec, task, preload) const actualItems = expected.filter(row => row.actual > 0).map(row => ({ ...row.frozen, packageCount: row.actual, productQuantity: row.actual * 7, ...Object.fromEntries(['grossWeightKg','netWeightKg','dimensionalWeightKg','volumeCbm'].map(field => [field, scale(row.frozen[field], row.actual, row.planned, field === 'volumeCbm' ? 4 : 3)])) })) const sum = (field, digits) => Number(actualItems.reduce((value, item) => value + BigInt(scale(item[field], 1, 1, digits).replace('.', '')), 0n)) / 10 ** digits const detail = { items: actualItems, summary: { totalPackageCount: actualItems.reduce((sum, row) => sum + row.packageCount, 0), totalQuantity: actualItems.reduce((sum, row) => sum + row.productQuantity, 0), totalGrossWeightKg: sum('grossWeightKg', 3), totalNetWeightKg: sum('netWeightKg', 3), totalVolumeCbm: sum('volumeCbm', 4) } } const customs = { actualBoxCount: detail.summary.totalPackageCount, inbounds: expected.filter(row => row.actual > 0), taxRefundCount: kind === 'B' ? 0 : 1, version: 0, status: kind === 'B' ? 'READY_TO_START' : 'WAITING_CUSTOMER_DOCUMENTS' } const source = { pdaTaskId: '91', loadingPlanId: '90', containerBookingId: '92', warehouseId: '1', sourceMarker: `${runId}-${kind}` } return { task, preload, spec, expected, detail, customs, source } } test('default plan and --plan make zero network calls', async () => { const original = globalThis.fetch globalThis.fetch = () => { throw Error('No network in plan') } try { assert.deepEqual(await execute([], [], {}), plan()); assert.equal((await execute(['--plan'], [], {})).networkRequests, 0) } finally { globalThis.fetch = original } }) test('execution refuses absent explicit TEST/profile/cwd', () => { assert.throws(() => executionOptions(['--execute'], [], {})) assert.throws(() => executionOptions(['--execute','--environment=TEST',`--run-id=${runId}`,'--fixture=x.json'], [], {}, 'C:/other')) }) test('NEW mode uses the configured /api base and does not accept a bare origin', () => { const cwd = fileURLToPath(new URL('..', import.meta.url)) const env = { CHONGCHONG_ENV: 'test', CHONGCHONG_ADMIN_API_BASE_URL: 'https://test.invalid/api', CHONGCHONG_ADMIN_USERNAME: 'admin', CHONGCHONG_ADMIN_PASSWORD: 'test-only', ADMIN_PDA_USERNAME: 'pda', ADMIN_PDA_PASSWORD: 'test-only' } const args = ['--execute','--environment=TEST',`--run-id=${runId}`,'--fixture=NEW'] const execArgs = [`--env-file=${resolve('/.codex/env/chongchong-global/test-acceptance.env')}`] assert.equal(executionOptions(args, execArgs, env, cwd).fixture, 'NEW') assert.equal(executionOptions(args, execArgs, env, cwd).gateway, 'https://test.invalid') assert.throws(() => executionOptions(args, execArgs, { ...env, CHONGCHONG_ADMIN_API_BASE_URL: 'https://test.invalid' }, cwd), /end in/) }) test('nested generated customer passwords and login/refresh tokens never reach saved evidence', () => { const value = redact({ requests: [{ response: { data: { temporaryPassword: 'SECRET', nested: { accessToken: 'TOKEN', refreshToken: 'REFRESH' }, tenantId: '11' } } }] }) const json = JSON.stringify(value) assert.ok(!json.includes('SECRET') && !json.includes('TOKEN') && !json.includes('REFRESH')) assert.ok(json.includes('"tenantId":"11"')) }) test('real HTTP multipart adapter preserves descriptor bytes, existing form fields and generated boundary', async () => { const received = [], original = Uint8Array.from([137,80,78,71,13,10,26,10,0,255,10,13,0,200]) const server = createServer(async (request, response) => { const chunks = []; for await (const chunk of request) chunks.push(chunk) received.push({ headers: request.headers, body: Buffer.concat(chunks), method: request.method }) response.writeHead(200, { 'Content-Type': 'application/json' }); response.end('{"code":"200"}') }) await new Promise(done => server.listen(0, '127.0.0.1', done)) try { const base = `http://127.0.0.1:${server.address().port}` const adapter = multipartAdapter((method, path, body, role, headers) => { assert.equal(role, 'admin'); return fetch(base + path, requestInit(method, body, 'test-token', headers)) }, () => 'admin') await adapter('POST', '/upload', { content: original, type: 'image/png', name: 'weight.png' }, 'token') const form = new FormData(); form.append('expectedVersion', '4'); form.append('file', new Blob([original], { type: 'image/png' }), 'original.png') await adapter('POST', '/upload', form, 'token', { 'Content-Type': 'application/json', 'Idempotency-Key': 'same-key' }) assert.equal(received.length, 2) for (const request of received) { assert.match(request.headers['content-type'], /^multipart\/form-data; boundary=/) const boundary = request.headers['content-type'].split('boundary=')[1] assert.ok(request.body.subarray(0, boundary.length + 2).equals(Buffer.from(`--${boundary}`))) assert.ok(request.body.includes(Buffer.from(original)), 'The original byte array reaches HTTP without JSON conversion') assert.ok(request.body.includes(Buffer.from('name="file"'))) assert.ok(!request.body.includes(Buffer.from('name="content"'))) assert.equal(request.method, 'POST') } assert.ok(received[1].body.includes(Buffer.from('name="expectedVersion"\r\n\r\n4'))) assert.equal(received[1].headers['idempotency-key'], 'same-key') } finally { server.closeAllConnections(); await new Promise(done => server.close(done)) } }) test('explicit resume proves the original failed sample and refuses state/identity drift before writes', () => { const summary = { id: '2106706513799155714', tenantId: '2106706477225971713', orderId: '2106706495895306242', orderNo: 'FL2106706495895306242', inboundCode: 'NYEXX2610040025', processStatus: 'WAIT_MEASURE', version: 4 } const measurement = { measurementId: '2106706548955811842', measurementStatus: 'DRAFT', version: 4, weightResults: [] } const readback = { verified: true, sessionClosed: true, inbound: { summary }, measurement } const report = { runId: 'PARTIAL-ACTUAL-20261004-r1', success: false, cases: [], requests: [{ path: '/api/platform/v1/files/measurements/2106706477225971713/2106706513799155714', http: 200, code: 'S0500', requestId: 'original-id' }] } const owner = validateResumeProof(report, readback) validateResumeLive(owner, readback, readback.inbound, measurement) assert.throws(() => validateResumeProof({ ...report, runId: 'unrelated' }, readback), /explicitly authorized/) assert.throws(() => validateResumeLive(owner, readback, { summary: { ...summary, version: 5 } }, measurement), /changed/) assert.throws(() => validateResumeLive(owner, readback, readback.inbound, { ...measurement, weightResults: [{ id: '1' }] }), /changed/) assert.throws(() => validateResumeProof(report, { ...readback, measurement: { ...measurement, measurementStatus: 'APPROVED' } }), /Frozen/) }) test('original draft resumes by upload/measurement only, with independent 3+1 SKU rows', async () => { const owner = { tenantId: '11', inboundId: '12', orderId: '13', marker: 'ORIGINAL' } const initial = { measurementId: '14', version: 5, latestDeclaration: { items: [ { inboundDetailId: '21', itemNo: 1, cargoName: 'SKU1', packageCount: 3, lengthCm: 30, widthCm: 20, heightCm: 20 }, { inboundDetailId: '22', itemNo: 2, cargoName: 'SKU2', packageCount: 1, lengthCm: 40, widthCm: 30, heightCm: 30 }] } } const calls = []; let approved = false const context = { token: 'own-token', createdResources: {}, request: async (method, path, body) => { calls.push({ method, path, body }); let data if (path.includes('/files/measurements/')) data = { fileId: '41' } else if (path.includes('/measurement/draft?')) data = { measurementId: '14' } else if (path.includes('/weight-pallet-options?')) data = { records: [{ palletId: '51', palletCode: 'YW-TP-002' }] } else if (path.includes('/weight-results/61/confirm?')) data = { recognitionStatus: 'CONFIRMED' } else if (path.includes('/weight-results?')) data = { id: '61', version: 0 } else if (path.includes('/measurement/submit?')) data = { processStatus: 'MEASURE_PENDING' } else if (path.includes('/measurements/approve?')) { approved = true; data = {} } else if (path.includes('/measurement?')) data = { measurementId: '14', version: 6, measurementStatus: approved ? 'APPROVED' : 'DRAFT', processStatus: approved ? 'WAIT_SPLIT' : 'WAIT_MEASURE', items: initial.latestDeclaration.items } else if (path.startsWith('/api/platform/inbounds/')) data = { summary: { version: 7 } } else throw Error('Unexpected original-recovery endpoint') return { path, http: 200, body: { code: '200', data } } } } context.requestMultipart = multipartAdapter(context.request, () => 'admin') await resumeMeasurementDraft(context, owner, initial) assert.equal(context.createdResources.inboundMeasurement.inboundId, '12') assert.equal(context.createdResources.inboundMeasurement.processStatus, 'WAIT_SPLIT') assert.ok(calls[0].body instanceof FormData) assert.deepEqual(calls.find(call => call.path.includes('/measurement/draft?')).body.items.map(item => [item.inboundDetailId, item.packageCount]), [['21',3],['22',1]]) assert.ok(!calls.some(call => /carton-scans|\/iam\/tenants|\/orders/.test(call.path)), 'No qualification, creation, order submission or re-scan') }) test('zero-work checkpoint accepts own preassignment but rejects another operator or any physical pick', () => { const { source, task } = fixture() task.taskStatus = 'LOADING'; task.workflowStatus = 'IN_PROGRESS'; task.assignment = { assigneeId: '99' } source.beforeTaskVersion = 0 validateZeroWorkTask(source, task, '99') assert.throws(() => validateZeroWorkTask(source, task, '98'), /own PDA/) task.items[0].pickedPackageCount = 1 assert.throws(() => validateZeroWorkTask(source, task, '99'), /physical work/) }) test('prepared continuation binds the two original-source checkpoints and refuses to redo PDA writes', () => { const report = { runId: 'PARTIAL-ACTUAL-20261004-recovery-r3', success: false, cases: [], requests: [], recovery: { originalOwner: { inboundId: '2106706513799155714' }, originalSha256: 'frozen-original-hash' }, preparation: ['A','B'].map(kind => ({ kind, stage: 'PDA_UNASSIGNED', source: { sourceMarker: `PARTIAL-ACTUAL-20261004-recovery-r3-${kind}` }, spec: { kind } })) } assert.equal(validatePreparedResume(report).length, 2) assert.throws(() => validatePreparedResume({ ...report, requests: [{ method: 'POST', path: '/api/platform/v1/first-leg/pda-loading/tasks/91/batch' }] }), /repeat any PDA/) assert.throws(() => validatePreparedResume({ ...report, cases: [{ completed: true }] }), /Only this/) }) test('A recovery takes only the original command id and immutable version/operation/remark', () => { const body = { expectedTaskVersion: 2, operationId: 'PARTIAL-ACTUAL-20261004-recovery-r3-A-complete', remark: 'PARTIAL-ACTUAL-20261004-recovery-r3-A' } const report = { runId: 'PARTIAL-ACTUAL-20261004-recovery-r7', success: false, requests: [{ method: 'POST', path: '/api/platform/v1/first-leg/pda-loading/tasks/2106713892758491138/complete', state: 'RECEIVED', http: 200, code: '200', request: body, response: { data: { completionCommand: { id: '2106716718935052290', operationId: body.operationId, expectedTaskVersion: 2 } } } }] } assert.deepEqual(originalCompletionCommand(report), { commandId: '2106716718935052290', body }) const changed = structuredClone(report); changed.requests[0].request.expectedTaskVersion = 4 assert.throws(() => originalCompletionCommand(changed), /immutable/) const duplicated = structuredClone(report); duplicated.requests.push(duplicated.requests[0]) assert.throws(() => originalCompletionCommand(duplicated), /Exactly one/) }) test('physical A facts exclude skipped rows and unchanged owners/stock detect a repeated completion or deduction', () => { const sample = fixture('A') sample.task.items = sample.task.items.map(row => ({ ...row, itemStatus: { PARTIAL: 'PARTIAL', PICK: 'PICKED', SKIP: 'SKIPPED' }[sample.expected.find(item => item.pickId === row.id).action], pickedPackageCount: sample.expected.find(item => item.pickId === row.id).actual })) verifyPhysicalFacts(sample.expected, sample.task) const drift = structuredClone(sample.task); drift.items[0].pickedPackageCount++ assert.throws(() => verifyPhysicalFacts(sample.expected, drift), /drift/) const before = { sources: [{ owner: { inboundId: '1' }, view: { summary: { id: '1', processStatus: 'LOADED', version: 12 }, statusHistory: [{ action: 'COMPLETE_LOADING' }], palletLocations: [] } }], inventory: { inbounds: [] } } verifyOldOwnersUnchanged(before, structuredClone(before), sample.expected) const repeated = structuredClone(before); repeated.sources[0].view.statusHistory.push({ action: 'COMPLETE_LOADING' }) assert.throws(() => verifyOldOwnersUnchanged(before, repeated, sample.expected), /must not repeat/) const deducted = structuredClone(before); deducted.inventory.inbounds.push({ availablePackageCount: 1 }) assert.throws(() => verifyOldOwnersUnchanged(before, deducted, sample.expected), /deducted again/) }) test('transit evidence uses raw balance identity and excludes transit from physical total, with no skipped source or duplicate ledger', () => { const sample = fixture('A'); sample.source.containerNo = 'TEST-CONTAINER' for (const row of sample.expected) { row.frozen.inboundCode = `IN-${row.inboundId}`; row.frozen.skuCode = `SKU-${row.itemId}` } const snapshot = ['1','3','4'].map(inboundId => { const active = sample.expected.filter(row => row.inboundId === inboundId && row.actual > 0), ownerRow = sample.expected.find(row => row.inboundId === inboundId) const owner = { inboundId, tenantId: ownerRow.accountId }, count = active.reduce((sum,row) => sum + row.actual, 0) if (!count) return { owner, orders: [], balances: [], ledger: [], details: [] } const order = { id: `100${inboundId}`, orderNo: `LL-${inboundId}`, customerId: owner.tenantId, sourceInboundId: inboundId, sourceContainerBookingId: sample.source.containerBookingId, containerNo: sample.source.containerNo, packageCount: count } return { owner, orders: [order], details: [{ cargo: active.map(row => ({ skuCode: row.frozen.skuCode, packageCount: row.actual })), statusHistory: [{ toStatus: 'PENDING_ASSIGNMENT', remark: '头程装柜完成自动生成' }] }], balances: [{ customerId: owner.tenantId, inboundCode: `IN-${inboundId}`, inboundOrderId: order.id, inTransitPackages: count, totalPackages: 0, availablePackages: 0, holdPackages: 0, allocatedPackages: 0, pickedPackages: 0, receivingPackages: 0, procurementPackages: 0 }], ledger: [{ customerId: owner.tenantId, inboundCode: `IN-${inboundId}`, inboundOrderId: order.id, businessOrderNo: order.orderNo, beforePackages: 0, deltaPackages: count, afterPackages: count }] } }) assert.equal(verifyDownstream(sample, snapshot).actualPackages, 3) const doubled = structuredClone(snapshot); doubled[0].ledger.push(doubled[0].ledger[0]) assert.throws(() => verifyDownstream(sample, doubled), /inventory movement/) const grouped = structuredClone(snapshot); grouped[0].balances[0].inboundOrderId = null assert.throws(() => verifyDownstream(sample, grouped), /transit inventory/) const skipped = structuredClone(snapshot); skipped[2].orders.push(snapshot[0].orders[0]) assert.throws(() => verifyDownstream(sample, skipped), /Skipped owner/) }) test('manifest needs two ordered cases, unique actions and all five photos', () => { const manifest = { schemaVersion: 1, runId, environment: 'TEST', cases: [fixture('A').spec, fixture('B').spec] } assert.equal(validateManifest(manifest, runId), manifest) const duplicate = structuredClone(manifest); duplicate.cases[1].actions[1].itemId = '1' assert.throws(() => validateManifest(duplicate, runId), /unique/) const missing = structuredClone(manifest); delete missing.cases[0].evidence.SEAL assert.throws(() => validateManifest(missing, runId), /Five/) }) test('official source must be fresh, passing, unclaimed and run-bound', () => { const now = Date.parse('2026-10-04T12:00:00Z'), report = { success: true, fatal: null, summary: { failed: 0 }, gateway: 'https://test.invalid', createdResources: { manualPdaBatchFixture: { ...fixture().source, schemaVersion: 1, stage: 'MANUAL_PDA_CLAIM_AND_BATCH_READY', preparedAt: new Date(now).toISOString(), taskItems: fixture().task.items } } } assert.ok(fixtureSource(report, runId, report.gateway, now)) assert.throws(() => fixtureSource(report, runId, report.gateway, now + 25 * 3600_000), /within/) const old = structuredClone(report); old.createdResources.manualPdaBatchFixture.sourceMarker = 'old' assert.throws(() => fixtureSource(old, runId, report.gateway, now), /run-bound/) const failed = structuredClone(report); failed.summary.failed = 1 assert.throws(() => fixtureSource(failed, runId, report.gateway, now), /did not pass/) }) test('exact HALF_UP handles non-half ratios, ties, nullable metrics and invalid ratios', () => { assert.equal(scale('10.001', 2, 3, 3), '6.667') assert.equal(scale('8.002', 2, 3, 3), '5.335') assert.equal(scale('0.1001', 2, 3, 4), '0.0667') assert.equal(scale('1', 1, 2, 0), '1') assert.equal(scale(null, 1, 2, 3), null) assert.throws(() => scale('10', 4, 3, 3)) }) test('A and B require the exact actual/skip shapes before any mutation', () => { assert.equal(fixture('A').expected.filter(row => row.actual > 0).length, 2) assert.ok(fixture('B').expected.filter(row => row.actual > 0).every(row => row.action === 'PARTIAL')) const { spec, task, preload } = fixture('B') spec.actions[0] = { itemId: '1', action: 'PICK' } assert.throws(() => expectedRows(spec, task, preload), /exactly one/) spec.actions[0] = { itemId: '1', action: 'PARTIAL', finalPickedPackageCount: 2 } assert.throws(() => expectedRows(spec, task, preload), /less than/) }) test('duplicate, missing, already picked and wrong-customer source rows reject preflight', () => { const a = fixture('A'); a.spec.actions.pop() assert.throws(() => expectedRows(a.spec, a.task, a.preload), /cover every/) const b = fixture(); b.task.items[0].pickedPackageCount = 1 assert.throws(() => expectedRows(b.spec, b.task, b.preload), /zero-picked/) const c = fixture(); c.preload.items[0].accountId = '999' assert.throws(() => expectedRows(c.spec, c.task, c.preload), /identity/) }) test('actual scope, metrics and refund customer/coverage are independently checked', () => { for (const kind of ['A', 'B']) { const sample = fixture(kind) assert.equal(verifyActual(sample.expected, sample.detail, sample.customs).actualRows, kind === 'A' ? 2 : 1) const contaminated = structuredClone(sample.detail); contaminated.items.push(sample.preload.items.at(-1)) assert.throws(() => verifyActual(sample.expected, contaminated, sample.customs), /Actual loading row set/) const stale = structuredClone(sample.customs); stale.actualBoxCount++ assert.throws(() => verifyActual(sample.expected, sample.detail, stale), /Customs actual boxes/) const wrong = structuredClone(sample.customs); wrong.inbounds[0].accountId = '999' assert.throws(() => verifyActual(sample.expected, sample.detail, wrong), /Customs source/) } }) function transport(sample, { drift = false, failCompletion = false, incomplete = false } = {}) { const calls = [], task = structuredClone(sample.task), customs = structuredClone(sample.customs) const history = [], pda = `/api/platform/v1/first-leg/pda-loading/tasks/${sample.source.pdaTaskId}` let completes = 0 return { calls, request: async (method, path, body, role, headers) => { calls.push({ method, path, body: body instanceof FormData ? 'multipart' : structuredClone(body), role, headers }) let data if (method === 'POST' && path === `${pda}/claim`) { task.workflowStatus = 'IN_PROGRESS'; data = task } else if (method === 'POST' && /\/items\/\d+\/skip$/.test(path)) { const itemId = path.split('/').at(-2) task.items = task.items.map(row => row.id === itemId ? { ...row, itemStatus: 'SKIPPED', pickedPackageCount: 0 } : row) data = task } else if (method === 'POST' && path === `${pda}/batch`) { task.workflowStatus = 'AWAITING_REVIEW'; task.items = task.items.map(row => { const expected = sample.expected.find(item => item.pickId === row.id) return { ...row, itemStatus: { PICK: 'PICKED', PARTIAL: 'PARTIAL', SKIP: 'SKIPPED' }[expected.action], pickedPackageCount: expected.actual } }); data = task } else if (method === 'POST' && path === `${pda}/evidence`) data = {} else if (path.startsWith(`${pda}/evidence?`)) data = { evidences: Object.keys(evidence).map(type => ({ evidenceType: type, status: 'ACTIVE', sealNo: sample.spec.sealNo })) } else if (method === 'POST' && path === `${pda}/complete`) { completes++ if (failCompletion) throw Error('Response lost') task.taskStatus = incomplete ? 'COMPLETING' : 'COMPLETED'; task.workflowStatus = incomplete ? 'COMPLETING' : 'COMPLETED' if (completes === 1) history.push({ actionType: 'COMPLETE_LOADING' }) if (drift && completes > 1) task.version++ data = task } else if (path.startsWith(`${pda}/inventory-snapshot?`)) data = { snapshotToken: 'fresh-snapshot' } else if (path.startsWith(`${pda}?`)) data = task else if (path === `${pda}/operations`) data = history else if (path.includes('/loading-lists/')) data = sample.detail else if (path.endsWith('/send-to-broker')) return { path, http: 200, body: { code: 'A0409' } } else if (path.endsWith('/start')) { customs.status = 'DECLARING'; customs.version++; data = customs } else if (path.endsWith('/complete-all-buy')) { customs.status = 'COMPLETED'; customs.version++; data = customs } else if (path.includes('/customs/loading-plans/')) data = customs else throw Error(`Unexpected ${method} ${path}`) return { path, http: 200, body: { code: '200', data: structuredClone(data) } } } } } test('both cases execute actual completion; B is all PARTIAL and follows all-buy gates', async () => { for (const kind of ['A', 'B']) { const sample = fixture(kind), http = transport(sample), images = Object.fromEntries(Object.keys(evidence).map(type => [type, { bytes: new Uint8Array([1,2,3]), type: 'image/png' }])) const result = await runCase(sample.spec, sample.source, { ...sample, images }, http.request, async () => {}) assert.equal(result.completed, true); assert.equal(result.allActualRowsPartial, kind === 'B') const completes = http.calls.filter(call => call.path.endsWith('/complete')) assert.equal(completes.length, 2); assert.deepEqual(completes[0].body, completes[1].body) const batches = http.calls.filter(call => call.path.endsWith('/batch')) assert.equal(batches.length, 1) if (kind === 'A') { const skipIndex = http.calls.findIndex(call => /\/items\/\d+\/skip$/.test(call.path)) assert.ok(skipIndex >= 0 && skipIndex < http.calls.findIndex(call => call.path.endsWith('/batch'))) assert.ok(!batches[0].body.items.some(item => item.itemId === '2'), 'Resolved same-owner SKIP does not repeat in full pending batch') } if (kind === 'B') assert.ok(http.calls.some(call => call.path.endsWith('/complete-all-buy'))) } }) test('replay version/history drift is a hard failure', async () => { const sample = fixture(), http = transport(sample, { drift: true }), images = Object.fromEntries(Object.keys(evidence).map(type => [type, { bytes: new Uint8Array([1]), type: 'image/png' }])) await assert.rejects(runCase(sample.spec, sample.source, { ...sample, images }, http.request), /zero projection/) }) test('unknown completion result is never retried and no later customs write is attempted', async () => { const sample = fixture(), http = transport(sample, { failCompletion: true }), images = Object.fromEntries(Object.keys(evidence).map(type => [type, { bytes: new Uint8Array([1]), type: 'image/png' }])) await assert.rejects(runCase(sample.spec, sample.source, { ...sample, images }, http.request), /Response lost/) assert.equal(http.calls.filter(call => call.path.endsWith('/complete')).length, 1) assert.equal(http.calls.filter(call => call.method === 'POST' && call.path.includes('/customs/')).length, 0) }) test('accepted completion without terminal state fails rather than claiming success', async () => { const sample = fixture(), http = transport(sample, { incomplete: true }), images = Object.fromEntries(Object.keys(evidence).map(type => [type, { bytes: new Uint8Array([1]), type: 'image/png' }])) await assert.rejects(runCase(sample.spec, sample.source, { ...sample, images }, http.request, async () => {}), /polling exhausted/) })