diff --git a/AGENTS.md b/AGENTS.md index b006ec3..bd699cd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,5 +10,5 @@ - Helm charts are published to `harbor.k3s.k0.nu/ai-spel`; Argo CD uses the existing `ai-spel` project and namespace. - Player-facing speech uses the local Piper WebAssembly adapter when the player has activated audio. The separate `ai-spel-static` Nginx service serves pinned Swedish Piper models and ONNX/Piper runtime files from same-origin `/static/piper-wasm-v1/` URLs with immutable caching. Game text is synthesized on-device and must never be sent to a TTS provider. - This pipeline bundles only the Piper worker/client glue. Model/runtime downloads, image builds, and deployment belong to `ai-spel/ai-spel-static` and the existing `large` runner. Never build or run these assets locally. -- Browser local AI loads its client adapter, Wllama runtime, WebAssembly, Gemma model, manifest, YAML prompt, and license resources only from the same-origin `/static/wllama-gemma3-v2/` path owned by `ai-spel/ai-spel-static`. Do not add browser CDN, npm, or model-hub fallbacks. The player must be shown and accept applicable model terms before the model downloads or runs. Acceptance, model failure, or local-AI opt-out must never block play. Incompatible asset changes require a new immutable static path and a coordinated frontend release. +- Browser local AI is paused by default behind `FEATURE_FLAGS.localAI` in `index.html`. When disabled, do not load its adapter or any Wllama/WebAssembly/Gemma assets. If it is deliberately enabled in a later change, it must load the adapter, runtime, model, manifest, YAML prompt, and license resources only from the same-origin `/static/wllama-gemma3-v2/` path owned by `ai-spel/ai-spel-static`. Do not add browser CDN, npm, or model-hub fallbacks. The player must be shown and accept applicable model terms before the model downloads or runs. Acceptance, model failure, or local-AI opt-out must never block play. Incompatible asset changes require a new immutable static path and a coordinated frontend release. - Local model output is advisory only. Preserve the original player input, send local hints only as untrusted context to Rust, and label offline replies as unsaved. Local diagnostic logging is opt-in, browser-local, exportable/deletable, and expires after 30 days. diff --git a/README.md b/README.md index ec112be..0e04318 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,6 @@ CI needs repository Action secrets named `HARBOR_USERNAME` and `HARBOR_PASSWORD` The first Argo Application is described in `deploy/argocd/application.yaml`. The backend ingress routes `/api`, `/version`, and health checks to Rust while serving the static client at `/`. Both services share the same origin so the session cookie remains same-origin. Builds, checks, and runtime verification happen in the pipeline and Kubernetes. Do not run the app, tests, container images, or binaries locally. +# Browser-local AI status + +Gemma/Wllama assistance is currently paused. `FEATURE_FLAGS.localAI` in `index.html` is `false`; while disabled, the client does not load the adapter, download model/runtime assets, run local inference, or send local hints. Re-enabling it requires an explicit code change and the normal frontend release pipeline. This does not affect the regular Rust-backed dialogue flow. diff --git a/docs/adr/0004-pause-browser-local-ai.md b/docs/adr/0004-pause-browser-local-ai.md new file mode 100644 index 0000000..659ab35 --- /dev/null +++ b/docs/adr/0004-pause-browser-local-ai.md @@ -0,0 +1,19 @@ +# ADR 0004: Pause browser-local AI by default + +## Status + +Accepted + +## Decision + +Browser-local Gemma/Wllama assistance is disabled by the `FEATURE_FLAGS.localAI` flag in `index.html`. The adapter is loaded dynamically only when the flag is true. When it is false, the browser does not load the adapter, request model/runtime assets, initialize local inference, attach local hints to dialogue requests, or produce local offline replies. The normal text dialogue remains available through the Rust API. + +## Rationale + +Pause model execution while the rest of the game and narrator experience is stabilized. Keep the implementation available for a deliberate future reactivation without downloading model resources or sending local inference hints in the meantime. + +## Consequences + +- Re-enabling local AI requires an explicit code change and frontend release. +- Tests and the static frontend check must enforce the default-off behavior and lazy loading. +- Existing Gemma asset publication and documentation may remain in place; the browser does not request those assets while the flag is off. diff --git a/index.html b/index.html index d18fc00..d4face2 100644 --- a/index.html +++ b/index.html @@ -116,8 +116,25 @@ - ' index.html -grep -q '' index.html +grep -q 'const FEATURE_FLAGS = Object.freeze({localAI: false})' index.html +grep -q 'if (!FEATURE_FLAGS.localAI) return Promise.resolve(null)' index.html +grep -q "script.src = '/static/' + 'wllama-gemma3-v2/local-ai.js'" index.html +! grep -q '' index.html grep -q '' index.html grep -q 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0' nginx/default.conf grep -q 'Cross-Origin-Embedder-Policy "require-corp"' nginx/default.conf diff --git a/tests/local-ai-integration.test.cjs b/tests/local-ai-integration.test.cjs index b2fc7b4..e141c53 100644 --- a/tests/local-ai-integration.test.cjs +++ b/tests/local-ai-integration.test.cjs @@ -5,9 +5,12 @@ const test = require('node:test'); const page = fs.readFileSync(path.join(__dirname, '..', 'index.html'), 'utf8'); -test('local AI adapter comes from the static service and starts after authenticated game entry', () => { - assert.match(page, /