const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); test('Piper asset manifest pins every Swedish voice and required ONNX loader files', async () => { const {assetPrefix, voiceFiles, requiredOnnxFiles} = await import('../scripts/assets.mjs'); assert.equal(assetPrefix, 'piper-wasm-v1'); assert.deepEqual([...new Set(voiceFiles.map(file => file.path.match(/sv_SE\/(\w+)\//)?.[1]))].sort(), ['alma', 'lisa', 'nst']); assert.ok(voiceFiles.every(file => Number.isInteger(file.size) && (file.sha256 || file.gitBlobSha1))); assert.ok(requiredOnnxFiles.includes('ort-wasm-simd-threaded.mjs')); assert.ok(requiredOnnxFiles.includes('ort-wasm-simd-threaded.wasm')); }); test('browser local AI prompt declares non-authoritative, bounded assistance tasks', async () => { const prompt = fs.readFileSync(path.join(__dirname, '..', 'prompts', 'browser-assistance.yaml'), 'utf8'); for (const required of ['id: browser-assistance', 'version: 1', 'task:', 'trust: untrusted-data', 'intent_hint', 'preflight', 'continuity', 'offline_help', 'excerpts_max_items: 3']) { assert.ok(prompt.includes(required), `missing ${required}`); } }); test('local AI runtime and model are published only under the owned static origin', async () => { const source = fs.readFileSync(path.join(__dirname, '..', 'scripts', 'build-assets.mjs'), 'utf8'); assert.ok(source.includes('wllama-gemma3-v2')); assert.ok(source.includes('wllama-3.8.1.tgz')); assert.ok(source.includes('gemma-3-1b-it-Q4_K_M.gguf')); assert.ok(source.includes('manifest.json')); }); test('Gemma terms, prohibited-use policy, notice, provenance, and runtime license are shipped', () => { const root = path.join(__dirname, '..', 'licenses'); for (const name of ['GEMMA_USER_TERMS.html', 'GEMMA_TERMS.html', 'GEMMA_PROHIBITED_USE_POLICY.html', 'GEMMA_NOTICE.txt', 'GEMMA_SOURCE.txt', 'LLAMA_CPP_LICENSE.txt']) { assert.ok(fs.statSync(path.join(root, name)).size > 0, `missing ${name}`); } const script = fs.readFileSync(path.join(__dirname, '..', 'scripts', 'build-assets.mjs'), 'utf8'); for (const name of ['GEMMA_USER_TERMS.html', 'GEMMA_TERMS.html', 'GEMMA_PROHIBITED_USE_POLICY.html', 'GEMMA_NOTICE.txt', 'GEMMA_SOURCE.txt', 'WLLAMA_LICENSE.txt', 'LLAMA_CPP_LICENSE.txt']) { assert.ok(script.includes(name), `build does not publish ${name}`); } assert.match(script, /acceptance_id: acceptanceId/); assert.match(script, /terms_sha256: termsSha256/); assert.match(script, /policy_sha256: policySha256/); assert.match(script, /user_terms_sha256: userTermsSha256/); const terms = fs.readFileSync(path.join(root, 'GEMMA_TERMS.html'), 'utf8'); assert.match(terms, /3\.1 Distribution and Redistribution/); assert.match(terms, /must include the use restrictions/); assert.doesNotMatch(terms, /