diff --git a/assets/theme-v2/js/tool-display-mode.js b/assets/theme-v2/js/tool-display-mode.js index e77b7a9df..08bada607 100644 --- a/assets/theme-v2/js/tool-display-mode.js +++ b/assets/theme-v2/js/tool-display-mode.js @@ -154,11 +154,6 @@ body.appendChild(navigationRow); } catch (error) { console.warn("Tool navigation could not be loaded.", error); - const diagnostic = document.createElement("p"); - diagnostic.className = "status"; - diagnostic.setAttribute("role", "status"); - diagnostic.textContent = "Tool navigation is temporarily unavailable. Refresh the page or try again shortly."; - body.appendChild(diagnostic); } } diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt index 2a3c37ce3..15213f1d6 100644 --- a/docs_build/dev/reports/codex_changed_files.txt +++ b/docs_build/dev/reports/codex_changed_files.txt @@ -1,54 +1,78 @@ -# Codex Changed Files - PR_26171_061-text2speech-engine-audio-feature-parity - -## Git Workflow -- Starting branch: `main`. -- Created branch: `pr/26171-061-text2speech-engine-audio-feature-parity`. -- Initial commit: `e4541d63719ab777b0654c8fecf4b13237d31256`. -- PR branch was merged with `origin/main` during PR conflict recovery. -- Conflicts were limited to generated report artifacts. - -## Scoped Diff Stat -```text -...R_26171_061-engine-audio-ownership-checklist.md | 25 + - ...R_26171_061-instruction-compliance-checklist.md | 32 + - .../PR_26171_061-manual-validation-notes.md | 27 + - ...R_26171_061-old-tts-feature-parity-checklist.md | 48 ++ - ..._061-text2speech-engine-audio-feature-parity.md | 71 ++ - docs_build/dev/reports/PR_26171_061-validation.md | 42 + - docs_build/dev/reports/codex_changed_files.txt | 118 +-- - .../dev/reports/coverage_changed_js_guardrail.txt | 7 +- - .../dev/reports/playwright_v8_coverage_report.txt | 36 +- - src/engine/audio/TextToSpeechEngine.js | 208 ++++- - .../tools/TextToSpeechFunctional.spec.mjs | 30 + - toolbox/text-to-speech/index.html | 119 +-- - toolbox/text-to-speech/text2speech.js | 853 +++++++++++++++++---- - 13 files changed, 1317 insertions(+), 299 deletions(-) -``` - -## Changed Files -- src/engine/audio/TextToSpeechEngine.js -- toolbox/text-to-speech/index.html -- toolbox/text-to-speech/text2speech.js -- tests/playwright/tools/TextToSpeechFunctional.spec.mjs -- docs_build/dev/reports/coverage_changed_js_guardrail.txt -- docs_build/dev/reports/playwright_v8_coverage_report.txt -- docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md -- docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md -- docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md -- docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md -- docs_build/dev/reports/PR_26171_061-validation.md -- docs_build/dev/reports/PR_26171_061-manual-validation-notes.md -- docs_build/dev/reports/codex_review.diff -- docs_build/dev/reports/codex_changed_files.txt +# PR_26171_042 Codex Changed Files Report + +## Instruction Compliance Gate + +- Current branch before execution: `main` +- Required execution branch before PR branch: `main` +- Branch validation: PASS +- Clean repository before branch creation: PASS +- PR owner/parity: PASS, `042` is even and Idea/Tool Display navigation scope maps to PC / Environment 1. +- Implementation path: PASS, active Idea Board and Theme V2 files only. +- Validation scope: PASS, targeted Idea Board, targeted Toolbox route for Idea Board, and workspace contract lane because shared Tool Display Mode behavior changed. +- Required reports: PASS, `docs_build/dev/reports/codex_review.diff` and this report are updated. +- ZIP requirement: PASS, `tmp/PR_26171_042-idea-board-navigation-fallback-cleanup_delta.zip` is required and produced before final delivery. + +## Git Workflow Fields + +- Created branch: `codex/pr-26171-042-idea-board-navigation-fallback-cleanup` +- Push result: PASS, branch pushed to `origin/codex/pr-26171-042-idea-board-navigation-fallback-cleanup`. +- PR URL: `https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/19` +- Merge result: recorded in final Codex delivery after GitHub merge returns the merge SHA. +- Final main commit: recorded in final Codex delivery after returning to `main` and pulling latest. +- Conflict resolution: PASS, merged latest `origin/main` (`9df4942226b0c1a25cfc9567040fc237d90df8f9`) and resolved conflicts only in singleton generated report artifacts. + +## Scoped Files + +- `assets/theme-v2/js/tool-display-mode.js` +- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs` +- `tests/playwright/tools/ToolboxRoutePages.spec.mjs` +- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md` +- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md` +- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md` +- `docs_build/dev/reports/coverage_changed_js_guardrail.txt` +- `docs_build/dev/reports/playwright_v8_coverage_report.txt` +- `docs_build/dev/reports/codex_review.diff` +- `docs_build/dev/reports/codex_changed_files.txt` + +## Requirement Evidence + +- PASS: Removed creator-visible Tool Display Mode navigation diagnostic fallback. `tool-display-mode.js` now logs the navigation load failure to console only and appends no status paragraph. +- PASS: Removed visible message `Tool navigation is temporarily unavailable. Refresh the page or try again shortly.` +- PASS: Idea Board stays usable when registry-backed navigation cannot load. Static/no-registry Playwright path expands notes and adds a note successfully. +- PASS: Creator-facing UI does not mention server, API, local server, port, registry, snapshot, or implementation details in the navigation fallback area. +- PASS: Navigation failure does not affect Idea Board table functionality. +- PASS: API-backed local route validated by targeted Idea Board and Toolbox route Playwright. +- PASS: Static/no-registry route behavior validated by targeted Idea Board Playwright with the registry snapshot returning no data. +- PASS: Optional previous/next navigation is omitted when unavailable. +- PASS: Idea Board lifecycle, Show filter, Create Project, Archive, chevron, and table row editing behavior were not changed. ## Validation -- PASS: `node --check src\engine\audio\TextToSpeechEngine.js`. -- PASS: `node --check toolbox\text-to-speech\text2speech.js`. -- PASS: `node --test tests\tools\Text2SpeechShell.test.mjs`. -- PASS: `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs`. -- PASS: `npm run test:workspace-v2` (legacy command name; user-facing language is Project Workspace). -- PASS: `git diff --check`. -- PASS: Post-conflict validation rerun after merging `origin/main` into the PR branch. - -## ZIP -- Path: `tmp/PR_26171_061-text2speech-engine-audio-feature-parity_delta.zip`. + +- PASS: `node --check assets/theme-v2/js/tool-display-mode.js` +- PASS: `node --check toolbox/idea-board/index.js` +- PASS: `node --check tests/playwright/tools/IdeaBoardTableNotes.spec.mjs` +- PASS: `node --check tests/playwright/tools/ToolboxRoutePages.spec.mjs` +- PASS: `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --project=playwright --workers=1 --reporter=line --timeout=90000` +- PASS: `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --project=playwright --workers=1 --reporter=line -g "Idea Board launches" --timeout=90000` +- PASS: `npm run test:workspace-v2` +- PASS: `git diff --check` +- SKIP: Full samples smoke, per user instruction. + +## Coverage Evidence + +- PASS: `docs_build/dev/reports/playwright_v8_coverage_report.txt` updated. +- PASS: `docs_build/dev/reports/coverage_changed_js_guardrail.txt` updated. +- PASS: Changed runtime JS coverage lists `assets/theme-v2/js/tool-display-mode.js` at 64% advisory function coverage. + +## ZIP Contents + +- `assets/theme-v2/js/tool-display-mode.js` +- `docs_build/dev/reports/codex_changed_files.txt` +- `docs_build/dev/reports/codex_review.diff` +- `docs_build/dev/reports/coverage_changed_js_guardrail.txt` +- `docs_build/dev/reports/playwright_v8_coverage_report.txt` +- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md` +- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md` +- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md` +- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs` +- `tests/playwright/tools/ToolboxRoutePages.spec.mjs` diff --git a/docs_build/dev/reports/codex_review.diff b/docs_build/dev/reports/codex_review.diff index 98f10d77f..19a61b590 100644 --- a/docs_build/dev/reports/codex_review.diff +++ b/docs_build/dev/reports/codex_review.diff @@ -1,1995 +1,465 @@ -diff --git a/docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md b/docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md -new file mode 100644 -index 000000000..5e18e0955 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md -@@ -0,0 +1,25 @@ -+# PR_26171_061 Engine Audio Ownership Checklist -+ -+## Engine Ownership -+ -+- PASS: Reusable TTS voice filtering lives in `src/engine/audio/TextToSpeechEngine.js`. -+- PASS: Reusable TTS preset shaping lives in `src/engine/audio/TextToSpeechEngine.js`. -+- PASS: Reusable TTS queue item helpers live in `src/engine/audio/TextToSpeechEngine.js`. -+- PASS: Existing defaults remain in `src/engine/audio/TextToSpeechDefaults.js`. -+- PASS: Active toolbox UI consumes the engine module instead of duplicating all engine behavior locally. -+ -+## Active Tool Ownership -+ -+- PASS: Active tool remains under `toolbox/text-to-speech/`. -+- PASS: Active HTML remains Theme V2 only. -+- PASS: Active JavaScript remains external. -+- PASS: Active tool owns DOM wiring, status display, and control event handling. -+- PASS: Active tool does not create database behavior. -+ -+## Boundary Checks -+ -+- PASS: No `tools/text2speech/` path was created. -+- PASS: Archived `old_text2speech-V2` was used as a read-only functionality sample. -+- PASS: Archived tool files were not activated in navigation. -+- PASS: Browser SpeechSynthesis is the implemented local provider. -+- PASS: Planned providers remain documented but do not block browser preview. -diff --git a/docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md b/docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md -new file mode 100644 -index 000000000..ffb2cb288 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md -@@ -0,0 +1,32 @@ -+# PR_26171_061 Instruction Compliance Checklist -+ -+## Pre-Work Gate -+ -+- PASS: Read `docs_build/dev/PROJECT_INSTRUCTIONS.md` before file changes. -+- PASS: Read `docs_build/dev/PROJECT_MULTI_PC.txt` before file changes. -+- PASS: Reported instruction compliance PASS/FAIL before file changes. -+- PASS: `git branch --show-current` reported `main` before branch creation. -+- PASS: `git checkout main` completed before branch creation. -+- PASS: `git pull origin main` completed before branch creation. -+- PASS: `git status` reported a clean working tree before branch creation. -+- PASS: Created branch `pr/26171-061-text2speech-engine-audio-feature-parity` from clean latest `main`. -+ -+## Owner And Parity -+ -+- PASS: PR number `061` is odd. -+- PASS: Odd parity maps to Laptop / Environment 2. -+- PASS: Text To Speech / TTS is owned by Laptop / Environment 2. -+- PASS: Implementation path matches active owner path: `toolbox/text-to-speech/`. -+- PASS: Shared engine path matches approved reusable audio path: `src/engine/audio/`. -+ -+## Hard Stop Checks -+ -+- PASS: Instructions were present and readable. -+- PASS: Branch workflow could be followed. -+- PASS: Repository was clean before branching. -+- PASS: No owner mismatch. -+- PASS: No parity mismatch. -+- PASS: No wrong implementation path. -+- PASS: Scoped validation was not skipped. -+- PASS: Required reports were created. -+- PASS: Required repo ZIP was created. -diff --git a/docs_build/dev/reports/PR_26171_061-manual-validation-notes.md b/docs_build/dev/reports/PR_26171_061-manual-validation-notes.md -new file mode 100644 -index 000000000..3341b14ba ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_061-manual-validation-notes.md -@@ -0,0 +1,27 @@ -+# PR_26171_061 Manual Validation Notes -+ -+## Manual Review -+ -+- Confirmed active Text To Speech path is `toolbox/text-to-speech/`. -+- Confirmed no `tools/text2speech/` directory was created. -+- Confirmed old functionality sample path is `archive/v1-v2/tools/old_text2speech-V2/`. -+- Confirmed active HTML has external scripts only. -+- Confirmed active HTML has no inline style attributes or inline event handlers. -+- Confirmed no database files were changed. -+ -+## Automated Browser Coverage Used For Manual Equivalents -+ -+- Opened active Text To Speech page through targeted Playwright validation. -+- Verified browser voices render. -+- Verified restored control groups render. -+- Verified preset shaping updates pitch and volume values. -+- Verified named sentence Add, Duplicate, and Delete. -+- Verified output summary includes queue JSON. -+- Verified Speak, Pause, Resume, and Stop call the browser SpeechSynthesis mock. -+- Verified unavailable SpeechSynthesis shows actionable error. -+ -+## Out Of Scope Manual Checks -+ -+- No paid provider was manually exercised. -+- No generated audio file export was manually exercised. -+- No database behavior was manually exercised. -diff --git a/docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md b/docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md -new file mode 100644 -index 000000000..e09e0f974 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md -@@ -0,0 +1,48 @@ -+# PR_26171_061 Old TTS Feature Parity Checklist -+ -+Functionality sample: `archive/v1-v2/tools/old_text2speech-V2/` -+ -+## Controls And Options -+ -+- PASS: Gender helper filter restored. -+- PASS: Language filter restored. -+- PASS: Voice dropdown restored. -+- PASS: Voice details restored. -+- PASS: Voice Age select restored. -+- PASS: Character Preset select restored. -+- PASS: SSML-like Preset select restored. -+- PASS: Volume slider restored with visible value. -+- PASS: Rate / Speed slider restored with visible value. -+- PASS: Pitch slider restored with visible value. -+- PASS: Name field restored. -+- PASS: Text To Speak editor restored. -+ -+## Queue And JSON -+ -+- PASS: Named Sentences queue restored. -+- PASS: Add named sentence restored. -+- PASS: Duplicate named sentence restored. -+- PASS: Delete named sentence restored. -+- PASS: Output Summary JSON restored. -+- PASS: Import JSON restored for standalone launch. -+- PASS: Copy JSON restored for standalone launch. -+- PASS: Export JSON restored for standalone launch. -+- PASS: URL JSON source loading restored through `samplePresetPath`. -+ -+## Playback And Status -+ -+- PASS: Speak restored. -+- PASS: Pause restored when browser support exists. -+- PASS: Resume restored when browser support exists. -+- PASS: Stop restored. -+- PASS: Clearable status log restored. -+- PASS: Actionable unavailable-browser error restored. -+- PASS: No placeholder provider-blocking behavior remains for browser preview. -+ -+## Workspace -+ -+- PASS: Project Workspace launch detection restored. -+- PASS: Standalone JSON actions hide during Project Workspace launch. -+- PASS: Return to Project Workspace action restored. -+- PASS: Project Workspace toolState loading restored. -+- PASS: Project Workspace dirty-state writeback restored. -diff --git a/docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md b/docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md -new file mode 100644 -index 000000000..b2f4a44d3 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md -@@ -0,0 +1,71 @@ -+# PR_26171_061 Text To Speech Engine Audio Feature Parity -+ -+## Summary -+ -+Restored active Text To Speech feature parity from the archived `old_text2speech-V2` functionality sample while keeping active implementation in `toolbox/text-to-speech/` and reusable engine behavior in `src/engine/audio/`. -+ -+## Changed Scope -+ -+- Rebuilt reusable Text To Speech voice filtering, preset shaping, and queue-item helpers in `src/engine/audio/TextToSpeechEngine.js`. -+- Expanded `toolbox/text-to-speech/index.html` with Theme V2 controls for the old V2 feature set. -+- Rebuilt `toolbox/text-to-speech/text2speech.js` so the active tool consumes the engine audio module. -+- Expanded targeted browser validation in `tests/playwright/tools/TextToSpeechFunctional.spec.mjs`. -+- Updated Playwright V8 coverage artifacts for changed runtime JavaScript. -+ -+## Requirement Checklist -+ -+- PASS: Used `archive/v1-v2/tools/old_text2speech-V2/` as the required functionality sample. -+- PASS: Reusable TTS behavior lives in `src/engine/audio/`. -+- PASS: `toolbox/text-to-speech/` consumes `src/engine/audio/TextToSpeechEngine.js`. -+- PASS: Restored old controls/options/features in the active tool. -+- PASS: Browser SpeechSynthesis provider remains implemented. -+- PASS: Planned provider adapters do not block browser preview behavior. -+- PASS: No `tools/text2speech/` path was created. -+- PASS: No database files were changed. -+- PASS: Theme V2 remains the styling source. -+- PASS: HTML uses external JavaScript only. -+- PASS: No inline script, style, or event handler was added. -+ -+## Restored Feature Set -+ -+- Import JSON. -+- Copy JSON. -+- Export JSON. -+- Project Workspace return action during workspace launch. -+- Gender helper filter. -+- Language filter. -+- Browser voice selection. -+- Voice details. -+- Voice age shaping. -+- Character presets. -+- SSML-like presets. -+- Volume, rate, and pitch sliders with visible values. -+- Named sentence Name field. -+- Add, Duplicate, and Delete named sentence actions. -+- Text To Speak editor. -+- Speak, Pause, Resume, and Stop playback actions. -+- Named Sentences queue. -+- Output Summary JSON. -+- Clearable Status log. -+- URL JSON preset loading through `samplePresetPath`. -+- Project Workspace toolState loading and dirty-state writeback. -+ -+## Validation Summary -+ -+- PASS: `node --check src\engine\audio\TextToSpeechEngine.js` -+- PASS: `node --check toolbox\text-to-speech\text2speech.js` -+- PASS: `node --test tests\tools\Text2SpeechShell.test.mjs` -+- PASS: `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs` -+- PASS: `npm run test:workspace-v2` -+ - Note: command name is legacy; user-facing language is Project Workspace. -+- PASS: `git diff --check` -+- PASS: changed runtime JS coverage collected for `src/engine/audio/TextToSpeechEngine.js`. -+- PASS: changed runtime JS coverage collected for `toolbox/text-to-speech/text2speech.js`. -+ -+## Out Of Scope -+ -+- No database changes. -+- No external paid provider implementation. -+- No generated audio file export provider. -+- No new `tools/text2speech/` path. -+- No archived tool activation. -diff --git a/docs_build/dev/reports/PR_26171_061-validation.md b/docs_build/dev/reports/PR_26171_061-validation.md -new file mode 100644 -index 000000000..bf864dc27 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_061-validation.md -@@ -0,0 +1,42 @@ -+# PR_26171_061 Validation Report -+ -+## Commands Run -+ -+- `node --check src\engine\audio\TextToSpeechEngine.js` -+ - PASS. -+- `node --check toolbox\text-to-speech\text2speech.js` -+ - PASS. -+- `node --test tests\tools\Text2SpeechShell.test.mjs` -+ - PASS: 3 tests passed. -+- `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs` -+ - PASS: 2 tests passed. -+ - Covers restored controls, preset shaping, queue add/duplicate/delete, output summary, pause/resume, speak, stop, and unavailable SpeechSynthesis error handling. -+ - PASS: rerun after merging `origin/main` into the PR branch for conflict resolution. -+- `npm run test:workspace-v2` -+ - PASS: 5 Project Workspace tests passed. -+ - Note: command name is legacy; user-facing language is Project Workspace. -+ - Note: first execution used a 120s timeout and timed out before completion; rerun with a longer timeout completed successfully. -+ - PASS: rerun after merging `origin/main` into the PR branch for conflict resolution. -+- `git diff --check` -+ - PASS. -+ -+## Coverage -+ -+- PASS: `docs_build/dev/reports/playwright_v8_coverage_report.txt` produced changed runtime JS coverage. -+- PASS: `docs_build/dev/reports/coverage_changed_js_guardrail.txt` reports no changed runtime JS coverage warnings. -+- PASS: `src/engine/audio/TextToSpeechEngine.js` covered at 71%. -+- PASS: `toolbox/text-to-speech/text2speech.js` covered at 71%. -+ -+## Artifact Verification -+ -+- PASS: `docs_build/dev/reports/codex_review.diff` exists. -+- PASS: `docs_build/dev/reports/codex_changed_files.txt` exists. -+- PASS: `tmp/PR_26171_061-text2speech-engine-audio-feature-parity_delta.zip` exists. -+- PASS: ZIP size is greater than zero. -+- PASS: ZIP contents preserve repo-relative paths. -+ -+## Skipped -+ -+- Full samples validation skipped because no sample JSON or sample runtime behavior changed. -+- Database validation skipped because no database files or runtime persistence changed. -+- External provider validation skipped because paid/provider generation is out of scope and browser SpeechSynthesis is the implemented provider for this PR. -diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt -index bb7de5d8d..2a3c37ce3 100644 ---- a/docs_build/dev/reports/codex_changed_files.txt -+++ b/docs_build/dev/reports/codex_changed_files.txt -@@ -1,91 +1,54 @@ --# Codex Changed Files - PR_26171_041-idea-board-production-polish -+# Codex Changed Files - PR_26171_061-text2speech-engine-audio-feature-parity - - ## Git Workflow --- Current branch: `codex/pr-26171-041-idea-board-production-polish`. --- Expected starting branch: `main` (PASS before branch creation). --- Created branch: `codex/pr-26171-041-idea-board-production-polish`. --- Commit before conflict resolution: `ca626873a4cf19925229851b0da2a4ff55c2073f`. --- Initial push result: PASS, branch pushed to `origin/codex/pr-26171-041-idea-board-production-polish`. --- PR URL: `https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/17`. --- Conflict resolution: merged `origin/main` at `0a364f85516aea82e38eea2f498fde5980f9adf9`; conflicts were limited to `codex_changed_files.txt` and `codex_review.diff`. --- Conflict resolution push result: pending until after merge-validation commit. --- Merge result: pending until after PR validation/merge. --- Final main sync: pending until after merge and final pull. -+- Starting branch: `main`. -+- Created branch: `pr/26171-061-text2speech-engine-audio-feature-parity`. -+- Initial commit: `e4541d63719ab777b0654c8fecf4b13237d31256`. -+- PR branch was merged with `origin/main` during PR conflict recovery. -+- Conflicts were limited to generated report artifacts. - --## Git Status -+## Scoped Diff Stat - ```text -- M assets/theme-v2/css/tables.css -- M assets/theme-v2/js/tool-display-mode.js -- M docs_build/dev/reports/codex_changed_files.txt -- M docs_build/dev/reports/codex_review.diff -- M docs_build/dev/reports/coverage_changed_js_guardrail.txt -- M docs_build/dev/reports/playwright_v8_coverage_report.txt -- M src/shared/toolbox/tool-metadata-inventory.js -- M tests/playwright/tools/IdeaBoardTableNotes.spec.mjs -- M tests/playwright/tools/ToolboxRoutePages.spec.mjs -- M toolbox/idea-board/index.html -- M toolbox/idea-board/index.js -+...R_26171_061-engine-audio-ownership-checklist.md | 25 + -+ ...R_26171_061-instruction-compliance-checklist.md | 32 + -+ .../PR_26171_061-manual-validation-notes.md | 27 + -+ ...R_26171_061-old-tts-feature-parity-checklist.md | 48 ++ -+ ..._061-text2speech-engine-audio-feature-parity.md | 71 ++ -+ docs_build/dev/reports/PR_26171_061-validation.md | 42 + -+ docs_build/dev/reports/codex_changed_files.txt | 118 +-- -+ .../dev/reports/coverage_changed_js_guardrail.txt | 7 +- -+ .../dev/reports/playwright_v8_coverage_report.txt | 36 +- -+ src/engine/audio/TextToSpeechEngine.js | 208 ++++- -+ .../tools/TextToSpeechFunctional.spec.mjs | 30 + -+ toolbox/text-to-speech/index.html | 119 +-- -+ toolbox/text-to-speech/text2speech.js | 853 +++++++++++++++++---- -+ 13 files changed, 1317 insertions(+), 299 deletions(-) - ``` +diff --git a/assets/theme-v2/js/tool-display-mode.js b/assets/theme-v2/js/tool-display-mode.js +index e77b7a9df..08bada607 100644 +--- a/assets/theme-v2/js/tool-display-mode.js ++++ b/assets/theme-v2/js/tool-display-mode.js +@@ -154,11 +154,6 @@ + body.appendChild(navigationRow); + } catch (error) { + console.warn("Tool navigation could not be loaded.", error); +- const diagnostic = document.createElement("p"); +- diagnostic.className = "status"; +- diagnostic.setAttribute("role", "status"); +- diagnostic.textContent = "Tool navigation is temporarily unavailable. Refresh the page or try again shortly."; +- body.appendChild(diagnostic); + } + } --## Diff Stat --```text -- assets/theme-v2/css/tables.css | 70 +++++++- -- assets/theme-v2/js/tool-display-mode.js | 2 +- -- .../dev/reports/coverage_changed_js_guardrail.txt | 5 +- -- .../dev/reports/playwright_v8_coverage_report.txt | 11 +- -- src/shared/toolbox/tool-metadata-inventory.js | 6 +- -- .../playwright/tools/IdeaBoardTableNotes.spec.mjs | 71 +++++++- -- tests/playwright/tools/ToolboxRoutePages.spec.mjs | 26 ++- -- toolbox/idea-board/index.html | 31 ++-- -- toolbox/idea-board/index.js | 191 ++++++++++++++++++++- -- 9 files changed, 368 insertions(+), 45 deletions(-) +diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.tx +index 2a3c37ce3..15213f1d6 100644 +--- a/docs_build/dev/reports/codex_changed_files.tx ++++ b/docs_build/dev/reports/codex_changed_files.tx +@@ -1,54 +1,78 @@ +-# Codex Changed Files - PR_26171_061-text2speech-engine-audio-feature-parity +- +-## Git Workflow +-- Starting branch: `main`. +-- Created branch: `pr/26171-061-text2speech-engine-audio-feature-parity`. +-- Initial commit: `e4541d63719ab777b0654c8fecf4b13237d31256`. +-- PR branch was merged with `origin/main` during PR conflict recovery. +-- Conflicts were limited to generated report artifacts. +- +-## Scoped Diff Sta +-```tex +-...R_26171_061-engine-audio-ownership-checklist.md | 25 + +- ...R_26171_061-instruction-compliance-checklist.md | 32 + +- .../PR_26171_061-manual-validation-notes.md | 27 + +- ...R_26171_061-old-tts-feature-parity-checklist.md | 48 ++ +- ..._061-text2speech-engine-audio-feature-parity.md | 71 ++ +- docs_build/dev/reports/PR_26171_061-validation.md | 42 + +- docs_build/dev/reports/codex_changed_files.txt | 118 +-- +- .../dev/reports/coverage_changed_js_guardrail.txt | 7 +- +- .../dev/reports/playwright_v8_coverage_report.txt | 36 +- +- src/engine/audio/TextToSpeechEngine.js | 208 ++++- +- .../tools/TextToSpeechFunctional.spec.mjs | 30 + +- toolbox/text-to-speech/index.html | 119 +-- +- toolbox/text-to-speech/text2speech.js | 853 +++++++++++++++++---- +- 13 files changed, 1317 insertions(+), 299 deletions(-) -``` - --## Requirement Evidence --- PASS: Removed creator-visible Create Project from the right-side Next Steps area; no disabled `data-idea-board-create-project` panel remains. --- PASS: Create Project is shown only in a Ready idea row's Actions column. --- PASS: Clicking Create Project changes the idea status from Ready to Project and replaces Create Project/Delete with Open Project and Archive. --- PASS: Project rows show Open Project and Archive and do not show Delete. --- PASS: Added Archived status; archived rows are hidden by default. --- PASS: Archived rows show Restore and Delete. --- PASS: Restore returns archived ideas to their previous non-archived status, with Refining fallback in runtime. --- PASS: Delete is guarded so Project ideas cannot be deleted unless archived first. --- PASS: Status dropdown uses New, Exploring, Refining, Ready, Project, and Archived. --- PASS: Added compact Show checkbox dropdown beside the visible table description line, with default statuses New, Exploring, Refining, Ready, and Project selected and Archived unselected. --- PASS: Show dropdown supports any checkbox combination plus Select All and Clear All. --- PASS: Updated creator-facing copy to "Capture, compare, and shape game ideas." and "Scan, compare, and update early ideas." --- PASS: Replaced creator-visible Tool Display Mode navigation error with safe copy that does not mention server/API/local server/port/implementation details. --- PASS: Chevron renders to the left of the Idea text, inline, same size, same color, and on the same text line; the whole Idea cell remains the expansion target. --- PASS: Notes count remains informational only. --- PASS: Table-first structure, inline Add Idea/Add Note, row-level Save/Cancel, status dropdown edit mode, notes indentation, and single-open accordion behavior remain covered. -+## Changed Files -+- src/engine/audio/TextToSpeechEngine.js -+- toolbox/text-to-speech/index.html -+- toolbox/text-to-speech/text2speech.js -+- tests/playwright/tools/TextToSpeechFunctional.spec.mjs -+- docs_build/dev/reports/coverage_changed_js_guardrail.txt -+- docs_build/dev/reports/playwright_v8_coverage_report.txt -+- docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md -+- docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md -+- docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md -+- docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md -+- docs_build/dev/reports/PR_26171_061-validation.md -+- docs_build/dev/reports/PR_26171_061-manual-validation-notes.md -+- docs_build/dev/reports/codex_review.diff -+- docs_build/dev/reports/codex_changed_files.txt +-## Changed Files +-- src/engine/audio/TextToSpeechEngine.js +-- toolbox/text-to-speech/index.html +-- toolbox/text-to-speech/text2speech.js +-- tests/playwright/tools/TextToSpeechFunctional.spec.mjs +-- docs_build/dev/reports/coverage_changed_js_guardrail.tx +-- docs_build/dev/reports/playwright_v8_coverage_report.tx +-- docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md +-- docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md +-- docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md +-- docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md +-- docs_build/dev/reports/PR_26171_061-validation.md +-- docs_build/dev/reports/PR_26171_061-manual-validation-notes.md +-- docs_build/dev/reports/codex_review.diff +-- docs_build/dev/reports/codex_changed_files.tx ++# PR_26171_042 Codex Changed Files Repor ++ ++## Instruction Compliance Gate ++ ++- Current branch before execution: `main` ++- Required execution branch before PR branch: `main` ++- Branch validation: PASS ++- Clean repository before branch creation: PASS ++- PR owner/parity: PASS, `042` is even and Idea/Tool Display navigation scope maps to PC / Environment 1. ++- Implementation path: PASS, active Idea Board and Theme V2 files only. ++- Validation scope: PASS, targeted Idea Board, targeted Toolbox route for Idea Board, and workspace contract lane because shared Tool Display Mode behavior changed. ++- Required reports: PASS, `docs_build/dev/reports/codex_review.diff` and this report are updated. ++- ZIP requirement: PASS, `tmp/PR_26171_042-idea-board-navigation-fallback-cleanup_delta.zip` is required and produced before final delivery. ++ ++## Git Workflow Fields ++ ++- Created branch: `codex/pr-26171-042-idea-board-navigation-fallback-cleanup` ++- Push result: PASS, branch pushed to `origin/codex/pr-26171-042-idea-board-navigation-fallback-cleanup`. ++- PR URL: `https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/19` ++- Merge result: recorded in final Codex delivery after GitHub merge returns the merge SHA. ++- Final main commit: recorded in final Codex delivery after returning to `main` and pulling latest. ++- Conflict resolution: PASS, merged latest `origin/main` (`9df4942226b0c1a25cfc9567040fc237d90df8f9`) and resolved conflicts only in singleton generated report artifacts. ++ ++## Scoped Files ++ ++- `assets/theme-v2/js/tool-display-mode.js` ++- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs` ++- `tests/playwright/tools/ToolboxRoutePages.spec.mjs` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md` ++- `docs_build/dev/reports/coverage_changed_js_guardrail.txt` ++- `docs_build/dev/reports/playwright_v8_coverage_report.txt` ++- `docs_build/dev/reports/codex_review.diff` ++- `docs_build/dev/reports/codex_changed_files.txt` ++ ++## Requirement Evidence ++ ++- PASS: Removed creator-visible Tool Display Mode navigation diagnostic fallback. `tool-display-mode.js` now logs the navigation load failure to console only and appends no status paragraph. ++- PASS: Removed visible message `Tool navigation is temporarily unavailable. Refresh the page or try again shortly.` ++- PASS: Idea Board stays usable when registry-backed navigation cannot load. Static/no-registry Playwright path expands notes and adds a note successfully. ++- PASS: Creator-facing UI does not mention server, API, local server, port, registry, snapshot, or implementation details in the navigation fallback area. ++- PASS: Navigation failure does not affect Idea Board table functionality. ++- PASS: API-backed local route validated by targeted Idea Board and Toolbox route Playwright. ++- PASS: Static/no-registry route behavior validated by targeted Idea Board Playwright with the registry snapshot returning no data. ++- PASS: Optional previous/next navigation is omitted when unavailable. ++- PASS: Idea Board lifecycle, Show filter, Create Project, Archive, chevron, and table row editing behavior were not changed. ## Validation --- PASS: `node --check toolbox/idea-board/index.js`. --- PASS: `node --check assets/theme-v2/js/tool-display-mode.js`. --- PASS: `node --check src/shared/toolbox/tool-metadata-inventory.js`. --- PASS: `node --check tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`. --- PASS: `node --check tests/playwright/tools/ToolboxRoutePages.spec.mjs`. --- PASS: `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --project=playwright --workers=1 --reporter=line --timeout=90000`. --- PASS: `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --project=playwright --workers=1 --reporter=line -g "Idea Board launches" --timeout=90000`. --- PASS: `npm run test:workspace-v2` (workspace-contract lane, 5 passed). -+- PASS: `node --check src\engine\audio\TextToSpeechEngine.js`. -+- PASS: `node --check toolbox\text-to-speech\text2speech.js`. -+- PASS: `node --test tests\tools\Text2SpeechShell.test.mjs`. -+- PASS: `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs`. -+- PASS: `npm run test:workspace-v2` (legacy command name; user-facing language is Project Workspace). - - PASS: `git diff --check`. --- PASS: Post-conflict rerun completed after merging `origin/main` at `0a364f85516aea82e38eea2f498fde5980f9adf9`. --- PASS: Playwright V8 coverage report produced because runtime JavaScript changed. --- WARN: Coverage report marks `src/shared/toolbox/tool-metadata-inventory.js` as not collected by browser V8 coverage; advisory only per project instructions. --- SKIPPED: Full samples smoke was not run per request. -+- PASS: Post-conflict validation rerun after merging `origin/main` into the PR branch. - - ## ZIP --- Path: `tmp/PR_26171_041-idea-board-production-polish_delta.zip`. --- Size: final size reported in the delivery summary after conflict-resolution ZIP refresh. --- Contents: -- - assets/theme-v2/css/tables.css -- - assets/theme-v2/js/tool-display-mode.js -- - docs_build/dev/reports/codex_changed_files.txt -- - docs_build/dev/reports/codex_review.diff -- - docs_build/dev/reports/coverage_changed_js_guardrail.txt -- - docs_build/dev/reports/playwright_v8_coverage_report.txt -- - src/shared/toolbox/tool-metadata-inventory.js -- - tests/playwright/tools/IdeaBoardTableNotes.spec.mjs -- - tests/playwright/tools/ToolboxRoutePages.spec.mjs -- - toolbox/idea-board/index.html -- - toolbox/idea-board/index.js -+- Path: `tmp/PR_26171_061-text2speech-engine-audio-feature-parity_delta.zip`. -diff --git a/docs_build/dev/reports/coverage_changed_js_guardrail.txt b/docs_build/dev/reports/coverage_changed_js_guardrail.txt -index 66dd0cb12..807990e9f 100644 ---- a/docs_build/dev/reports/coverage_changed_js_guardrail.txt -+++ b/docs_build/dev/reports/coverage_changed_js_guardrail.txt -@@ -6,9 +6,8 @@ Missing changed runtime JS files are WARN, not FAIL. +-- PASS: `node --check src\engine\audio\TextToSpeechEngine.js`. +-- PASS: `node --check toolbox\text-to-speech\text2speech.js`. +-- PASS: `node --test tests\tools\Text2SpeechShell.test.mjs`. +-- PASS: `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs`. +-- PASS: `npm run test:workspace-v2` (legacy command name; user-facing language is Project Workspace). +-- PASS: `git diff --check`. +-- PASS: Post-conflict validation rerun after merging `origin/main` into the PR branch. +- +-## ZIP +-- Path: `tmp/PR_26171_061-text2speech-engine-audio-feature-parity_delta.zip`. ++ ++- PASS: `node --check assets/theme-v2/js/tool-display-mode.js` ++- PASS: `node --check toolbox/idea-board/index.js` ++- PASS: `node --check tests/playwright/tools/IdeaBoardTableNotes.spec.mjs` ++- PASS: `node --check tests/playwright/tools/ToolboxRoutePages.spec.mjs` ++- PASS: `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --project=playwright --workers=1 --reporter=line --timeout=90000` ++- PASS: `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --project=playwright --workers=1 --reporter=line -g "Idea Board launches" --timeout=90000` ++- PASS: `npm run test:workspace-v2` ++- PASS: `git diff --check` ++- SKIP: Full samples smoke, per user instruction. ++ ++## Coverage Evidence ++ ++- PASS: `docs_build/dev/reports/playwright_v8_coverage_report.txt` updated. ++- PASS: `docs_build/dev/reports/coverage_changed_js_guardrail.txt` updated. ++- PASS: Changed runtime JS coverage lists `assets/theme-v2/js/tool-display-mode.js` at 64% advisory function coverage. ++ ++## ZIP Contents ++ ++- `assets/theme-v2/js/tool-display-mode.js` ++- `docs_build/dev/reports/codex_changed_files.txt` ++- `docs_build/dev/reports/codex_review.diff` ++- `docs_build/dev/reports/coverage_changed_js_guardrail.txt` ++- `docs_build/dev/reports/playwright_v8_coverage_report.txt` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md` ++- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs` ++- `tests/playwright/tools/ToolboxRoutePages.spec.mjs` +diff --git a/docs_build/dev/reports/coverage_changed_js_guardrail.txt b/docs_build/dev/reports/coverage_changed_js_guardrail.tx +index 807990e9f..242796c4f 100644 +--- a/docs_build/dev/reports/coverage_changed_js_guardrail.tx ++++ b/docs_build/dev/reports/coverage_changed_js_guardrail.tx +@@ -6,8 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL. Source: Playwright/Chromium built-in V8 coverage from the active Playwright run. Changed runtime JS files considered: --(0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only --(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14 --(74%) toolbox/idea-board/index.js - executed lines 640/640; executed functions 37/50 -+(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52 -+(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86 +-(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52 +-(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86 ++(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14 Guardrail warnings: --(0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file missing from coverage; advisory only -+(100%) none - no changed runtime JS coverage warnings -diff --git a/docs_build/dev/reports/playwright_v8_coverage_report.txt b/docs_build/dev/reports/playwright_v8_coverage_report.txt -index 4a9f71ff1..dd573eabd 100644 ---- a/docs_build/dev/reports/playwright_v8_coverage_report.txt -+++ b/docs_build/dev/reports/playwright_v8_coverage_report.txt -@@ -12,34 +12,28 @@ Note: entry percentages use function coverage when available, otherwise line cov + (100%) none - no changed runtime JS coverage warnings +diff --git a/docs_build/dev/reports/playwright_v8_coverage_report.txt b/docs_build/dev/reports/playwright_v8_coverage_report.tx +index dd573eabd..17eb943d2 100644 +--- a/docs_build/dev/reports/playwright_v8_coverage_report.tx ++++ b/docs_build/dev/reports/playwright_v8_coverage_report.tx +@@ -12,28 +12,45 @@ Note: entry percentages use function coverage when available, otherwise line cov Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran. Exercised tool entry points detected: --(78%) Toolbox Index - exercised 4 runtime JS files -+(72%) Toolbox Index - exercised 2 runtime JS files +-(72%) Toolbox Index - exercised 2 runtime JS files ++(72%) Toolbox Index - exercised 10 runtime JS files (0%) Tool Template V2 - not exercised by this Playwright run --(63%) Theme V2 Shared JS - exercised 2 runtime JS files -+(56%) Theme V2 Shared JS - exercised 2 runtime JS files +-(56%) Theme V2 Shared JS - exercised 2 runtime JS files ++(61%) Theme V2 Shared JS - exercised 7 runtime JS files Changed runtime JS files covered: --(0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only --(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14 --(74%) toolbox/idea-board/index.js - executed lines 640/640; executed functions 37/50 -+(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52 -+(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86 +-(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52 +-(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86 ++(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14 Files with executed line/function counts where available: --(25%) src/api/session-api-client.js - executed lines 68/68; executed functions 3/12 --(33%) src/api/toolbox-votes-api-client.js - executed lines 46/46; executed functions 2/6 --(44%) src/api/server-api-client.js - executed lines 167/167; executed functions 8/18 --(63%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 977/977; executed functions 54/86 -+(36%) src/api/server-api-client.js - executed lines 167/167; executed functions 5/14 -+(38%) src/api/public-config-client.js - executed lines 209/209; executed functions 10/26 -+(54%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 977/977; executed functions 46/85 - (64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14 --(65%) src/api/public-config-client.js - executed lines 209/209; executed functions 17/26 --(67%) src/api/game-journey-completion-api-client.js - executed lines 15/15; executed functions 2/3 --(67%) toolbox/game-workspace/game-workspace-api-client.js - executed lines 20/20; executed functions 2/3 --(74%) toolbox/idea-board/index.js - executed lines 640/640; executed functions 37/50 --(78%) toolbox/tools-page-accordions.js - executed lines 1156/1156; executed functions 87/111 --(86%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 25/29 -+(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52 -+(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86 -+(76%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 22/29 -+(100%) src/engine/audio/TextToSpeechDefaults.js - executed lines 108/108; executed functions 1/1 +-(36%) src/api/server-api-client.js - executed lines 167/167; executed functions 5/14 +-(38%) src/api/public-config-client.js - executed lines 209/209; executed functions 10/26 +-(54%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 977/977; executed functions 46/85 +-(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14 +-(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52 +-(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86 +-(76%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 22/29 +-(100%) src/engine/audio/TextToSpeechDefaults.js - executed lines 108/108; executed functions 1/1 ++(14%) assets/theme-v2/js/account-auth-service.js - executed lines 64/64; executed functions 1/7 ++(14%) assets/theme-v2/js/admin-setup-actions.js - executed lines 55/55; executed functions 1/7 ++(18%) assets/theme-v2/js/account-page-data.js - executed lines 150/150; executed functions 3/17 ++(20%) assets/theme-v2/js/admin-owner-navigation.js - executed lines 58/58; executed functions 2/10 ++(25%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 1/4 ++(25%) src/api/session-api-client.js - executed lines 68/68; executed functions 3/12 ++(29%) src/engine/input/NormalizedInputRegistry.js - executed lines 341/341; executed functions 6/21 ++(33%) src/api/admin-setup-api-client.js - executed lines 13/13; executed functions 1/3 ++(33%) src/api/toolbox-votes-api-client.js - executed lines 46/46; executed functions 2/6 ++(56%) toolbox/colors/colors.js - executed lines 1848/1848; executed functions 115/204 ++(58%) src/api/server-api-client.js - executed lines 167/167; executed functions 11/19 ++(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14 ++(64%) toolbox/controls/controls.js - executed lines 610/610; executed functions 36/56 ++(65%) src/api/public-config-client.js - executed lines 209/209; executed functions 17/26 ++(67%) src/api/game-journey-completion-api-client.js - executed lines 15/15; executed functions 2/3 ++(74%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 977/977; executed functions 67/90 ++(75%) toolbox/game-workspace/game-workspace.js - executed lines 458/458; executed functions 33/44 ++(89%) toolbox/tools-page-accordions.js - executed lines 1156/1156; executed functions 105/118 ++(90%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 26/29 ++(91%) toolbox/game-design/game-design.js - executed lines 254/254; executed functions 21/23 ++(94%) assets/theme-v2/js/marketplace-page.js - executed lines 170/170; executed functions 16/17 ++(100%) src/api/marketplace-api-client.js - executed lines 16/16; executed functions 3/3 ++(100%) toolbox/colors/palette-api-client.js - executed lines 28/28; executed functions 4/4 ++(100%) toolbox/controls/controls-api-client.js - executed lines 33/33; executed functions 5/5 ++(100%) toolbox/game-design/game-design-api-client.js - executed lines 13/13; executed functions 2/2 ++(100%) toolbox/game-workspace/game-workspace-api-client.js - executed lines 20/20; executed functions 3/3 Uncovered or low-coverage changed JS files: --(0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: uncovered changed runtime JS file; advisory only -+(100%) none - no low-coverage changed runtime JS files + (100%) none - no low-coverage changed runtime JS files Changed JS files considered: --(0%) src/shared/toolbox/tool-metadata-inventory.js - changed JS file not collected as browser runtime coverage --(0%) tests/playwright/tools/IdeaBoardTableNotes.spec.mjs - changed JS file not collected as browser runtime coverage --(0%) tests/playwright/tools/ToolboxRoutePages.spec.mjs - changed JS file not collected as browser runtime coverage --(64%) assets/theme-v2/js/tool-display-mode.js - changed JS file with browser V8 coverage --(74%) toolbox/idea-board/index.js - changed JS file with browser V8 coverage -+(0%) tests/playwright/tools/TextToSpeechFunctional.spec.mjs - changed JS file not collected as browser runtime coverage -+(71%) src/engine/audio/TextToSpeechEngine.js - changed JS file with browser V8 coverage -+(71%) toolbox/text-to-speech/text2speech.js - changed JS file with browser V8 coverage -diff --git a/src/engine/audio/TextToSpeechEngine.js b/src/engine/audio/TextToSpeechEngine.js -index c8e1dced3..a5f3ccabd 100644 ---- a/src/engine/audio/TextToSpeechEngine.js -+++ b/src/engine/audio/TextToSpeechEngine.js -@@ -1,7 +1,10 @@ - import { -+ TEXT_TO_SPEECH_CHARACTER_PRESET_DEFAULTS, - TEXT_TO_SPEECH_DEFAULTS, - TEXT_TO_SPEECH_DISPLAY_NAME, -- TEXT_TO_SPEECH_RANGE_DEFAULTS -+ TEXT_TO_SPEECH_RANGE_DEFAULTS, -+ TEXT_TO_SPEECH_SSML_LIKE_PRESET_DEFAULTS, -+ TEXT_TO_SPEECH_VOICE_AGE_PRESET_DEFAULTS - } from "./TextToSpeechDefaults.js"; - - function finiteNumber(value, fallback) { -@@ -9,8 +12,180 @@ function finiteNumber(value, fallback) { - return Number.isFinite(number) ? number : fallback; - } - --function boundedNumber(value, { fallback, max, min }) { -- return Math.min(max, Math.max(min, finiteNumber(value, fallback))); -+function boundedNumber(value, { fallback, max, min, value: defaultValue }) { -+ const fallbackValue = fallback ?? defaultValue ?? min; -+ return Math.min(max, Math.max(min, finiteNumber(value, fallbackValue))); -+} -+ -+function shapedNumber(value, { fallback, max, min, step }) { -+ const boundedValue = boundedNumber(value, { fallback, max, min }); -+ const stepText = String(step || "1"); -+ const decimalPart = stepText.includes(".") ? stepText.split(".")[1] : ""; -+ const multiplier = 10 ** decimalPart.length; -+ return Math.round(boundedValue * multiplier) / multiplier; -+} -+ -+function textToSpeechSlugFromName(name) { -+ const slug = String(name || "") -+ .trim() -+ .toLowerCase() -+ .replace(/[^a-z0-9]+/g, "-") -+ .replace(/^-+|-+$/g, ""); -+ return slug || "speech-item"; -+} -+ -+function textToSpeechVoiceGender(option) { -+ const voiceText = `${option?.gender || ""} ${option?.name || ""} ${option?.label || ""}`; -+ const voiceLanguage = String(option?.language || "").toLowerCase(); -+ if (/\bneutral\b|\bnon[-\s]?binary\b|\bandrogynous\b/i.test(voiceText)) return "neutral"; -+ if (voiceLanguage === "es-es" || /\bmale\b|\bman\b|\bdavid\b|\bmark\b/i.test(voiceText)) return "male"; -+ if (/\bfemale\b|\bwoman\b|\bzira\b/i.test(voiceText)) return "female"; -+ return "unknown"; -+} -+ -+function genderFilterLabel(value) { -+ if (value === "male-preferred") return "Male"; -+ if (value === "female-preferred") return "Female"; -+ if (value === "neutral") return "Neutral"; -+ return "Any"; -+} -+ -+function ageFilterLabel(value) { -+ if (value === "adult") return "Adult"; -+ if (value === "child") return "Child"; -+ if (value === "elderly") return "Elderly"; -+ if (value === "teen") return "Teen"; -+ return "Any"; -+} -+ -+function payloadGenderValue(value) { -+ return value === "neutral" ? "any" : value; -+} +-(0%) tests/playwright/tools/TextToSpeechFunctional.spec.mjs - changed JS file not collected as browser runtime coverage +-(71%) src/engine/audio/TextToSpeechEngine.js - changed JS file with browser V8 coverage +-(71%) toolbox/text-to-speech/text2speech.js - changed JS file with browser V8 coverage ++(0%) tests/playwright/tools/IdeaBoardTableNotes.spec.mjs - changed JS file not collected as browser runtime coverage ++(0%) tests/playwright/tools/ToolboxRoutePages.spec.mjs - changed JS file not collected as browser runtime coverage ++(64%) assets/theme-v2/js/tool-display-mode.js - changed JS file with browser V8 coverage +diff --git a/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md +new file mode 100644 +index 000000000..7dcde1b3e +--- /dev/null ++++ b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md +@@ -0,0 +1,20 @@ ++# PR_26171_042-idea-board-navigation-fallback-cleanup Apply ++ ++## Apply Steps ++ ++1. Start from `main`. ++2. Pull latest `main`. ++3. Create `codex/pr-26171-042-idea-board-navigation-fallback-cleanup`. ++4. Implement the BUILD scope. ++5. Run requested validation. ++6. Stage scoped files only. ++7. Commit. ++8. Push branch. ++9. Create PR. ++10. Merge after validation passes. ++11. Return to `main` and pull latest. ++12. Confirm final report fields and repo-structured ZIP. ++ ++## Merge Conflict Handling ++ ++If conflicts occur, preserve latest `main`, preserve PR scope, resolve only touched files, rerun validation, regenerate reports and ZIP, then continue. +diff --git a/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md +new file mode 100644 +index 000000000..874f6dc4e +--- /dev/null ++++ b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md +@@ -0,0 +1,57 @@ ++# PR_26171_042-idea-board-navigation-fallback-cleanup Build ++ ++## Source Of Truth ++ ++Use the user request for `PR_26171_042-idea-board-navigation-fallback-cleanup`, `docs_build/dev/PROJECT_INSTRUCTIONS.md`, `docs_build/dev/PROJECT_MULTI_PC.txt`, and this BUILD doc. ++ ++## Singular Purpose ++ ++Clean up the optional Tool Display Mode navigation fallback for Idea Board without changing Idea Board table behavior. ++ ++## Exact Targets ++ ++- `assets/theme-v2/js/tool-display-mode.js` ++- `toolbox/idea-board/index.js` ++- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs` ++- `tests/playwright/tools/ToolboxRoutePages.spec.mjs` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md` ++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md` ++- `docs_build/dev/reports/coverage_changed_js_guardrail.txt` ++- `docs_build/dev/reports/playwright_v8_coverage_report.txt` ++- `docs_build/dev/reports/codex_review.diff` ++- `docs_build/dev/reports/codex_changed_files.txt` ++ ++## Implementation Requirements ++ ++- Do not show creator-visible navigation diagnostics when optional Tool Display Mode navigation cannot load. ++- Remove the visible message `Tool navigation is temporarily unavailable. Refresh the page or try again shortly.` ++- Keep Idea Board usable when the navigation registry cannot load. ++- Log the navigation failure to console only. ++- Do not mention server, API, local server, port, registry, snapshot, or implementation details in creator-facing UI. ++- Do not let navigation failure affect Idea Board table functionality. ++- Validate both API-backed local route and static route without registry response. ++- In both cases, Idea Board renders, no creator-visible navigation error appears, and optional previous/next navigation is hidden or omitted when unavailable. ++- Ensure final Codex report fields are non-pending for PR URL, merge result, final main commit, created branch, and push result. ++ ++## Explicit Non-Goals ++ ++- Do not change Idea Board lifecycle behavior. ++- Do not change Show filter behavior. ++- Do not change Create Project behavior. ++- Do not change Archive behavior. ++- Do not change Chevron behavior. ++- Do not change table row editing behavior. ++ ++## Validation ++ ++- `node --check assets/theme-v2/js/tool-display-mode.js` ++- `node --check toolbox/idea-board/index.js` ++- `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --project=playwright --workers=1 --reporter=line --timeout=90000` ++- `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --project=playwright --workers=1 --reporter=line -g "Idea Board launches" --timeout=90000` ++- `npm run test:workspace-v2` ++- `git diff --check` + -+function filterTextToSpeechVoicesByGender(voiceOptions, genderFilter = "any") { -+ if (genderFilter === "any") return voiceOptions; -+ if (genderFilter === "male-preferred") { -+ return voiceOptions.filter((option) => textToSpeechVoiceGender(option) === "male"); -+ } -+ if (genderFilter === "female-preferred") { -+ return voiceOptions.filter((option) => textToSpeechVoiceGender(option) === "female"); -+ } -+ if (genderFilter === "neutral") { -+ return voiceOptions.filter((option) => ["neutral", "unknown"].includes(textToSpeechVoiceGender(option))); -+ } -+ return voiceOptions; -+} ++## ZIP + -+function optionLabelCompare(left, right) { -+ return String(left.label).localeCompare(String(right.label), undefined, { -+ numeric: true, -+ sensitivity: "base" -+ }); -+} ++Create `tmp/PR_26171_042-idea-board-navigation-fallback-cleanup_delta.zip` with repo-structured changed files only. +diff --git a/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md +new file mode 100644 +index 000000000..3b5d5fbfe +--- /dev/null ++++ b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md +@@ -0,0 +1,36 @@ ++# PR_26171_042-idea-board-navigation-fallback-cleanup Plan + -+function textToSpeechLanguageOptionsFromVoices(voiceOptions) { -+ const languageCounts = new Map(); -+ voiceOptions.forEach((option) => { -+ const language = String(option.language || "").trim(); -+ if (language) { -+ languageCounts.set(language, (languageCounts.get(language) || 0) + 1); -+ } -+ }); -+ return Array.from(languageCounts.entries()) -+ .map(([language, count]) => ({ -+ label: `${language} (${count} ${count === 1 ? "voice" : "voices"})`, -+ value: language -+ })) -+ .sort(optionLabelCompare); -+} ++## Purpose + -+function filterTextToSpeechVoiceOptions(voiceOptions, { gender = "any", language = "" } = {}) { -+ const filteredByGender = filterTextToSpeechVoicesByGender(voiceOptions, gender); -+ const matchingVoices = filteredByGender -+ .filter((option) => !language || option.language === language) -+ .sort(optionLabelCompare); -+ return { -+ filteredVoiceCount: filteredByGender.length, -+ gender, -+ genderLabel: genderFilterLabel(gender), -+ language, -+ languageOptions: textToSpeechLanguageOptionsFromVoices(filteredByGender), -+ matchingVoices, -+ voiceCount: voiceOptions.length -+ }; -+} ++Fix the optional Tool Display Mode navigation fallback so Idea Board stays clean and usable when registry-backed previous/next navigation cannot load. + -+function shapeTextToSpeechOptions({ -+ characterPreset = TEXT_TO_SPEECH_DEFAULTS.characterPreset, -+ pitch = TEXT_TO_SPEECH_DEFAULTS.pitch, -+ rate = TEXT_TO_SPEECH_DEFAULTS.rate, -+ ssmlLikePreset = TEXT_TO_SPEECH_DEFAULTS.ssmlLikePreset, -+ voiceAge = TEXT_TO_SPEECH_DEFAULTS.voiceAge, -+ volume = TEXT_TO_SPEECH_DEFAULTS.volume -+} = {}, sliderOverrides = {}) { -+ const character = TEXT_TO_SPEECH_CHARACTER_PRESET_DEFAULTS[characterPreset] || TEXT_TO_SPEECH_CHARACTER_PRESET_DEFAULTS.manual; -+ const age = TEXT_TO_SPEECH_VOICE_AGE_PRESET_DEFAULTS[voiceAge] || TEXT_TO_SPEECH_VOICE_AGE_PRESET_DEFAULTS.any; -+ const ssmlLike = TEXT_TO_SPEECH_SSML_LIKE_PRESET_DEFAULTS[ssmlLikePreset] || TEXT_TO_SPEECH_SSML_LIKE_PRESET_DEFAULTS.normal; -+ return { -+ characterPreset, -+ pitch: sliderOverrides.pitch -+ ? boundedNumber(pitch, TEXT_TO_SPEECH_RANGE_DEFAULTS.pitch) -+ : shapedNumber(Number(character.pitch) + Number(age.pitchOffset) + Number(ssmlLike.pitchOffset), TEXT_TO_SPEECH_RANGE_DEFAULTS.pitch), -+ rate: sliderOverrides.rate -+ ? boundedNumber(rate, TEXT_TO_SPEECH_RANGE_DEFAULTS.rate) -+ : shapedNumber(Number(character.rate) * Number(age.rateMultiplier) * Number(ssmlLike.rateMultiplier), TEXT_TO_SPEECH_RANGE_DEFAULTS.rate), -+ ssmlLikePreset, -+ voiceAge, -+ volume: sliderOverrides.volume -+ ? boundedNumber(volume, TEXT_TO_SPEECH_RANGE_DEFAULTS.volume) -+ : shapedNumber(Number(character.volume) * Number(ssmlLike.volumeMultiplier), TEXT_TO_SPEECH_RANGE_DEFAULTS.volume) -+ }; -+} ++## Scope + -+function uniqueTextToSpeechName(baseName, existingItems = []) { -+ const requestedName = String(baseName || "").trim() || "New speech item"; -+ const existingNames = new Set(existingItems.map((item) => item.name)); -+ if (!existingNames.has(requestedName)) return requestedName; -+ for (let index = 2; index < 1000; index += 1) { -+ const candidate = `${requestedName} ${index}`; -+ if (!existingNames.has(candidate)) return candidate; -+ } -+ return `${requestedName} ${Date.now().toString(36)}`; -+} ++- Remove the creator-visible Tool Display Mode navigation fallback diagnostic. ++- Keep navigation failures logged to the browser console. ++- Preserve Idea Board lifecycle, filtering, project, archive, chevron, and row editing behavior. ++- Validate API-backed and static/no-registry Idea Board rendering. ++- Update final Codex reports with non-pending Git workflow fields. + -+function uniqueTextToSpeechId(baseName, existingItems = []) { -+ const existingIds = new Set(existingItems.map((item) => item.id)); -+ const baseId = textToSpeechSlugFromName(baseName); -+ if (!existingIds.has(baseId)) return baseId; -+ for (let index = 2; index < 1000; index += 1) { -+ const candidate = `${baseId}-${index}`; -+ if (!existingIds.has(candidate)) return candidate; -+ } -+ return `${baseId}-${Date.now().toString(36)}`; -+} ++## Required Validation + -+function createTextToSpeechQueueItem({ -+ existingItems = [], -+ id = "", -+ name = "", -+ text = "", -+ ...options -+} = {}) { -+ const itemName = uniqueTextToSpeechName(name, id ? [] : existingItems); -+ return { -+ characterPreset: options.characterPreset || TEXT_TO_SPEECH_DEFAULTS.characterPreset, -+ gender: payloadGenderValue(options.gender || TEXT_TO_SPEECH_DEFAULTS.gender), -+ id: id || uniqueTextToSpeechId(itemName, existingItems), -+ language: options.language || TEXT_TO_SPEECH_DEFAULTS.language, -+ name: itemName, -+ pitch: boundedNumber(options.pitch, TEXT_TO_SPEECH_RANGE_DEFAULTS.pitch), -+ rate: boundedNumber(options.rate, TEXT_TO_SPEECH_RANGE_DEFAULTS.rate), -+ ssmlLikePreset: options.ssmlLikePreset || TEXT_TO_SPEECH_DEFAULTS.ssmlLikePreset, -+ text: String(text || "").trim() || "New speech line.", -+ voice: String(options.voice || ""), -+ voiceAge: options.voiceAge || TEXT_TO_SPEECH_DEFAULTS.voiceAge, -+ volume: boundedNumber(options.volume, TEXT_TO_SPEECH_RANGE_DEFAULTS.volume) -+ }; ++- `node --check assets/theme-v2/js/tool-display-mode.js` ++- `node --check toolbox/idea-board/index.js` ++- Targeted Idea Board Playwright. ++- Targeted Toolbox route Playwright for Idea Board. ++- `npm run test:workspace-v2` ++- Do not run full samples smoke. ++ ++## Required Reports ++ ++- `docs_build/dev/reports/codex_review.diff` ++- `docs_build/dev/reports/codex_changed_files.txt` ++ ++## Required Delivery ++ ++- Commit changes. ++- Push branch. ++- Create PR. ++- Merge after validation passes. ++- Return to main and pull latest main. ++- Produce repo-structured ZIP under `tmp/`. +diff --git a/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs b/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs +index 38085a4d2..1a42e53d7 100644 +--- a/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs ++++ b/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs +@@ -105,6 +105,11 @@ async function expectProductionCopy(page) { + ); } - class TextToSpeechEngine { -@@ -58,6 +233,18 @@ class TextToSpeechEngine { - })); - } - -+ filterVoiceOptions(options = {}) { -+ return filterTextToSpeechVoiceOptions(this.voiceOptions(), options); -+ } -+ -+ shapeOptions(options = {}, sliderOverrides = {}) { -+ return shapeTextToSpeechOptions(options, sliderOverrides); -+ } -+ -+ createQueueItem(options = {}) { -+ return createTextToSpeechQueueItem(options); -+ } ++async function expectNoNavigationFallbackUi(page) { ++ await expect(page.locator("body")).not.toContainText("Tool navigation is temporarily unavailable. Refresh the page or try again shortly."); ++ await expect(page.locator(".tool-display-mode")).not.toContainText(/\bserver\b|\bAPI\b|\blocal server\b|\bport\b|\bregistry\b|\bsnapshot\b/i); ++} + - voiceForValue(value) { - const normalizedValue = String(value || "").trim(); - if (!normalizedValue) { -@@ -248,5 +435,18 @@ class TextToSpeechEngine { + test("Idea Board uses accordion table ideas and notes", async ({ page }) => { + const server = await startRepoServer(); + const previousApiUrl = process.env.GAMEFOUNDRY_API_URL; +@@ -137,6 +142,7 @@ test("Idea Board uses accordion table ideas and notes", async ({ page }) => { + await page.goto(`${server.baseUrl}/toolbox/idea-board/index.html`, { waitUntil: "networkidle" }); + await expect(page.getByRole("heading", { level: 1, name: "Idea Board" })).toBeVisible(); + await expectProductionCopy(page); ++ await expectNoNavigationFallbackUi(page); + await expect(page.locator("[data-idea-board-table] > thead th[scope='col']")).toHaveText([ + "Idea", + "Pitch", +@@ -313,3 +319,55 @@ test("Idea Board uses accordion table ideas and notes", async ({ page }) => { + await server.close(); } - } - --export { TextToSpeechEngine }; -+export { -+ ageFilterLabel as textToSpeechAgeFilterLabel, -+ createTextToSpeechQueueItem, -+ filterTextToSpeechVoiceOptions, -+ genderFilterLabel as textToSpeechGenderFilterLabel, -+ payloadGenderValue as textToSpeechPayloadGenderValue, -+ shapeTextToSpeechOptions, -+ textToSpeechLanguageOptionsFromVoices, -+ textToSpeechSlugFromName, -+ textToSpeechVoiceGender, -+ TextToSpeechEngine, -+ uniqueTextToSpeechId, -+ uniqueTextToSpeechName -+}; - export default TextToSpeechEngine; -diff --git a/tests/playwright/tools/TextToSpeechFunctional.spec.mjs b/tests/playwright/tools/TextToSpeechFunctional.spec.mjs -index ccf95e3e3..17e2c0b62 100644 ---- a/tests/playwright/tools/TextToSpeechFunctional.spec.mjs -+++ b/tests/playwright/tools/TextToSpeechFunctional.spec.mjs -@@ -66,7 +66,13 @@ async function openTextToSpeechPage(page, { speechAvailable = true } = {}) { - getVoices() { - return voices; - }, -+ pause() { -+ window.__textToSpeechCalls.push({ type: "pause" }); -+ }, - removeEventListener() {}, -+ resume() { -+ window.__textToSpeechCalls.push({ type: "resume" }); -+ }, - speak(utterance) { - window.__textToSpeechCalls.push({ - lang: utterance.lang, -@@ -101,8 +107,22 @@ test("Text To Speech page loads and speaks through browser speech synthesis", as - await expect(page.locator("[data-tts-voice-select]")).toContainText("Arcade Voice"); - await expect(page.locator("[data-tts-voice-count]")).toHaveText("2"); - await expect(page.locator("[data-tts-engine-label]")).toHaveText("Ready"); -+ await expect(page.locator("[data-tts-gender-select]")).toBeVisible(); -+ await expect(page.locator("[data-tts-language-select]")).toBeVisible(); -+ await expect(page.locator("[data-tts-age-select]")).toBeVisible(); -+ await expect(page.locator("[data-tts-character-preset-select]")).toBeVisible(); -+ await expect(page.locator("[data-tts-ssml-preset-select]")).toBeVisible(); -+ await expect(page.locator("[data-tts-import-json]")).toBeEnabled(); -+ await expect(page.locator("[data-tts-copy-json]")).toBeEnabled(); -+ await expect(page.locator("[data-tts-export-json]")).toBeEnabled(); - - await page.locator("[data-tts-text-input]").fill("Launch the next wave."); -+ await page.locator("[data-tts-item-name]").fill("Wave intro"); -+ await page.locator("[data-tts-character-preset-select]").selectOption("dramatic"); -+ await page.locator("[data-tts-age-select]").selectOption("teen"); -+ await page.locator("[data-tts-ssml-preset-select]").selectOption("whisper-ish"); -+ await expect(page.locator("[data-tts-pitch-value]")).toHaveText("1.1"); -+ await expect(page.locator("[data-tts-volume-value]")).toHaveText("0.6"); - await page.locator("[data-tts-voice-select]").selectOption("arcade-voice-uri"); - await page.locator("[data-tts-rate]").fill("1.4"); - await page.locator("[data-tts-pitch]").fill("0.8"); -@@ -111,6 +131,13 @@ test("Text To Speech page loads and speaks through browser speech synthesis", as - await expect(page.locator("[data-tts-pitch-value]")).toHaveText("0.8"); - await expect(page.locator("[data-tts-volume-value]")).toHaveText("0.55"); - await expect(page.locator("[data-tts-text-count]")).toHaveText("21"); -+ await page.locator("[data-tts-add-item]").click(); -+ await expect(page.locator("[data-tts-queue-list]")).toContainText("Wave intro"); -+ await expect(page.locator("[data-tts-output-summary]")).toContainText("\"name\": \"Wave intro\""); -+ await page.locator("[data-tts-duplicate-item]").click(); -+ await expect(page.locator("[data-tts-queue-list]")).toContainText("Wave intro 2 copy"); -+ await page.locator("[data-tts-delete-item]").click(); -+ await expect(page.locator("[data-tts-queue-list] [data-tts-queue-item]")).toHaveCount(2); - - await expect(page.locator("[data-tts-speak]")).toBeEnabled(); - await page.locator("[data-tts-speak]").click(); -@@ -126,10 +153,13 @@ test("Text To Speech page loads and speaks through browser speech synthesis", as - volume: 0.55, - })); - -+ await page.locator("[data-tts-pause]").click(); -+ await page.locator("[data-tts-resume]").click(); - await page.locator("[data-tts-stop]").click(); - await expect(page.locator("[data-tts-status]")).toContainText("Speech stopped"); - calls = await page.evaluate(() => window.__textToSpeechCalls); - expect(calls.at(-1)).toEqual({ type: "cancel" }); -+ expect(calls).toEqual(expect.arrayContaining([{ type: "pause" }, { type: "resume" }])); - - expect(failures.failedRequests).toEqual([]); - expect(failures.pageErrors).toEqual([]); -diff --git a/toolbox/text-to-speech/index.html b/toolbox/text-to-speech/index.html -index adaaff3a7..f5b29b19a 100644 ---- a/toolbox/text-to-speech/index.html -+++ b/toolbox/text-to-speech/index.html -@@ -6,7 +6,7 @@ - - - Text To Speech - GameFoundryStudio -- -+ - - - -@@ -18,52 +18,100 @@ -
-
Project Workspace / Audio
-

Text To Speech

--

Preview spoken game text with local browser speech synthesis before deciding whether a generated audio provider is needed.

-+

Create named speech lines, shape browser voices, and preview spoken game text through the shared engine audio Text To Speech module.

-
- -
-
-+ -+ -
- -
-
--

Browser Preview

--

Use the browser Web Speech API for immediate local preview. This does not create files, call paid providers, or fake generated audio.

--
-+

Speech Composition

-+
-
0Characters
-
0Voices
-
CheckingEngine
-
-
-
--
--
Preview Controls
--

Speak Browser Preview

--
--
-- -+ -+ -+
-+ -+ -+ - -
-
Loading browser Text To Speech.
-@@ -72,45 +120,30 @@ -
-
-
--
Ownership Boundary
--

Preview Only

-+
Named Sentences
-+

Queue

-
--

Message text remains Design-owned. Browser preview is local playback only. Future generated audio files remain Audio-owned when a real provider/export flow is added.

-+
-
-
-
-