| 1 | import test from 'node:test' |
| 2 | import assert from 'node:assert/strict' |
| 3 | import { transformStockSnapshot } from '../dist/stock-adapters.mjs' |
| 4 | import { createHarnessModule } from '../dist/builtin/harness.mjs' |
| 5 | const native = extra => ({ kind:'ocr_process', state:'native', status:'success', can_fallback:false, ...extra }) |
| 6 | const tess = extra => ({ kind:'ocr_process', state:'tesseract', status:'complete', success:true, exit_code:0, ...extra }) |
| 7 | const metadata = value => transformStockSnapshot(value).result.metadata |
| 8 | const owner = { plugin_id:'host:harness', generation:3, owner_token:'fixture-owner' } |
| 9 | const params = { owner, execution_id:'opaque-ocr-job', ticket:'native-grant', deadline_ms:1000 } |
| 10 | |
| 11 | test('Native success, error and missing backend are finite private-text directives', () => { |
| 12 | assert.deepEqual(metadata(native({})),{kind:'ocr_decision',code:'native_success',trim_end:false}) |
| 13 | assert.deepEqual(metadata(native({status:'error'})),{kind:'ocr_decision',code:'native_error',trim_end:false}) |
| 14 | assert.equal(metadata(native({status:'unavailable'})).code,'no_backend') |
| 15 | assert.match(metadata(native({status:'unavailable'})).message,/no local OCR backend/) |
| 16 | }) |
| 17 | test('OCR fallback is admitted only with a separate exact continuation grant', () => { |
| 18 | for (const status of ['error','unavailable']) assert.deepEqual(metadata(native({status,can_fallback:true,next_ticket:'tesseract-grant'})),{kind:'ocr_decision',code:'fallback',trim_end:false}) |
| 19 | for (const value of [native({status:'error',can_fallback:true}),native({status:'error',next_ticket:'not-admitted'}),native({can_fallback:true,next_ticket:'extra'}),native({status:'error',can_fallback:true,next_ticket:'x'.repeat(257)})]) assert.throws(()=>metadata(value)) |
| 20 | }) |
| 21 | test('Tesseract success requests private Rust trimming and failure prefix without private diagnostics', () => { |
| 22 | assert.deepEqual(metadata(tess({})),{kind:'ocr_decision',code:'tesseract_success',trim_end:true}) |
| 23 | assert.equal(metadata(tess({success:false,exit_code:2})).message,'tesseract failed (exit Some(2)): ') |
| 24 | assert.equal(metadata(tess({success:false,exit_code:null})).message,'tesseract failed (exit None): ') |
| 25 | assert.deepEqual(metadata({kind:'ocr_process',state:'tesseract',status:'fault'}),{kind:'ocr_decision',code:'fault',trim_end:false}) |
| 26 | }) |
| 27 | test('unknown, contradictory, private-byte or oversized OCR projections refuse', () => { |
| 28 | for (const value of [native({status:'retry'}),native({can_fallback:'yes'}),native({path:'/private/image.png'}),native({stdout:'private text'}),tess({status:'pending'}),tess({exit_code:1.5}),tess({exit_code:2**31}),tess({success:null}),tess({stderr:'x'.repeat(1024*1024)}),tess({next_ticket:'third-launch'}),{kind:'ocr_process',state:'tesseract',status:'fault',stdout:'private'}]) assert.throws(()=>metadata(value)) |
| 29 | }) |
| 30 | test('actual compiled runner redeems ordered Native and Tesseract grants once', async () => { |
| 31 | const calls=[] |
| 32 | const runner=createHarnessModule({async request(method,input) {calls.push([method,input]);return calls.length===1?native({status:'error',can_fallback:true,next_ticket:'tesseract-grant'}):tess({})}},owner) |
| 33 | const result=await runner.run(params,new AbortController().signal) |
| 34 | assert.deepEqual(result.result.metadata,{kind:'ocr_decision',code:'tesseract_success',trim_end:true}) |
| 35 | assert.deepEqual(calls,[['exec/redeem',{owner,execution_id:'opaque-ocr-job',ticket:'native-grant'}],['exec/redeem',{owner,execution_id:'opaque-ocr-job',ticket:'tesseract-grant'}]]) |
| 36 | assert.equal(JSON.stringify(calls).includes('path'),false) |
| 37 | await runner.dispose() |
| 38 | }) |
| 39 | test('Native completion or no fallback performs no Tesseract redemption', async () => { |
| 40 | for (const value of [native({}),native({status:'error'}),native({status:'unavailable'})]) { |
| 41 | let calls=0 |
| 42 | const runner=createHarnessModule({async request(){calls++;return value}},owner) |
| 43 | await runner.run(params,new AbortController().signal) |
| 44 | assert.equal(calls,1);await runner.dispose() |
| 45 | } |
| 46 | }) |
| 47 | test('wrong initial/continuation stage and wrong invocation owner refuse', async () => { |
| 48 | const first=createHarnessModule({async request(){return tess({})}},owner) |
| 49 | await assert.rejects(first.run(params,new AbortController().signal),/must begin/);await first.dispose() |
| 50 | let calls=0 |
| 51 | const second=createHarnessModule({async request(){calls++;return native({status:'error',can_fallback:true,next_ticket:'next-grant'})}},owner) |
| 52 | await assert.rejects(second.run(params,new AbortController().signal),/wrong stage/) |
| 53 | assert.equal(calls,2);await second.dispose() |
| 54 | const forbidden=createHarnessModule({async request(){throw new Error('must never reach RPC')}},owner) |
| 55 | await assert.rejects(forbidden.run({...params,owner:{...owner,owner_token:'wrong-owner'}},new AbortController().signal),/stale/);await forbidden.dispose() |
| 56 | }) |
| 57 | test('OCR cancellation before continuation or late reply never retries', async () => { |
| 58 | const stop=new AbortController();let calls=0 |
| 59 | const first=createHarnessModule({async request(){calls++;stop.abort();return native({status:'error',can_fallback:true,next_ticket:'next-grant'})}},owner) |
| 60 | await assert.rejects(first.run(params,stop.signal),/cancelled/);assert.equal(calls,1);await first.dispose() |
| 61 | const abort=new AbortController();let finish;calls=0 |
| 62 | const second=createHarnessModule({request(){calls++;return calls===1?Promise.resolve(native({status:'unavailable',can_fallback:true,next_ticket:'next-grant'})):new Promise(resolve=>{finish=resolve})}},owner) |
| 63 | const pending=second.run(params,abort.signal) |
| 64 | while(!finish) await Promise.resolve() |
| 65 | abort.abort();await assert.rejects(pending,/cancelled/) |
| 66 | finish(tess({}));assert.equal(calls,2);await second.dispose() |
| 67 | }) |
| 68 | test('Core or Host rejection never attempts another backend or grant', async () => { |
| 69 | let calls=0 |
| 70 | const runner=createHarnessModule({async request(){calls++;throw new Error('Core authority withdrawn')}},owner) |
| 71 | await assert.rejects(runner.run(params,new AbortController().signal),/withdrawn/) |
| 72 | assert.equal(calls,1);await runner.dispose() |
| 73 | }) |
| 74 |