diff --git a/assets/theme-v2/css/tables.css b/assets/theme-v2/css/tables.css index a8c75090a..c39ef19f0 100644 --- a/assets/theme-v2/css/tables.css +++ b/assets/theme-v2/css/tables.css @@ -38,6 +38,67 @@ td { color: var(--text) } +.idea-board-table-caption { + position: relative; + z-index: var(--z-index-sm); + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-10); + padding: var(--space-10); + font-weight: var(--font-weight-heavy) +} + +.idea-board-show-filter { + position: relative; + z-index: var(--z-index-md); + color: var(--text); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-bold) +} + +.idea-board-show-filter summary { + display: inline-flex; + align-items: center; + min-height: var(--space-28); + padding: var(--space-3) var(--space-10); + border: var(--border-standard); + border-radius: var(--radius-md); + background: var(--panel-soft); + cursor: pointer; + list-style: none +} + +.idea-board-show-filter summary::-webkit-details-marker { + display: none +} + +.idea-board-show-filter__menu { + position: static; + min-width: 12rem; + margin-top: var(--space-6); + padding: var(--space-10); + border: var(--border-standard); + border-radius: var(--radius-md); + background: var(--panel); + box-shadow: var(--shadow-md) +} + +.idea-board-show-filter__options { + display: grid; + gap: var(--space-6); + margin-top: var(--space-10) +} + +.idea-board-show-filter__option { + display: flex; + align-items: center; + gap: var(--space-8); + color: var(--text); + font-weight: var(--font-weight-regular); + white-space: nowrap +} + .data-table th { color: var(--gold); font-size: var(--font-size-sm); @@ -60,8 +121,13 @@ td { gap: .35em; color: inherit; font: inherit; - line-height: inherit; - vertical-align: baseline + line-height: var(--line-height-single); + vertical-align: baseline; + white-space: nowrap +} + +.idea-board-idea-label__text { + line-height: var(--line-height-single) } .idea-board-idea-chevron { diff --git a/assets/theme-v2/js/tool-display-mode.js b/assets/theme-v2/js/tool-display-mode.js index 9c23ba67e..e77b7a9df 100644 --- a/assets/theme-v2/js/tool-display-mode.js +++ b/assets/theme-v2/js/tool-display-mode.js @@ -157,7 +157,7 @@ const diagnostic = document.createElement("p"); diagnostic.className = "status"; diagnostic.setAttribute("role", "status"); - diagnostic.textContent = "Tool navigation could not load from the server API. Start the local server API and refresh."; + 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 4b9b70b93..bb7de5d8d 100644 --- a/docs_build/dev/reports/codex_changed_files.txt +++ b/docs_build/dev/reports/codex_changed_files.txt @@ -1,37 +1,91 @@ -# Codex Changed Files - PR_26171_063-codex-instruction-enforcement-hardening +# Codex Changed Files - PR_26171_041-idea-board-production-polish -## Conflict Resolution Note -- Merged latest `origin/main` into the PR branch after GitHub reported merge conflicts. -- Regenerated Codex artifacts from the PR_063 delta against updated `origin/main`. -- No implementation scope was changed while resolving conflicts. +## 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. -## Changed Files -- docs_build/dev/PROJECT_INSTRUCTIONS.md -- docs_build/dev/PROJECT_MULTI_PC.txt -- docs_build/dev/reports/PR_26171_063-codex-instruction-enforcement-hardening.md -- docs_build/dev/reports/PR_26171_063-instruction-compliance-checklist.md -- docs_build/dev/reports/PR_26171_063-validation.md -- docs_build/dev/reports/PR_26171_063-manual-validation-notes.md -- docs_build/dev/reports/codex_review.diff -- docs_build/dev/reports/codex_changed_files.txt +## Git Status +```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 +``` -## Git Diff Stat Against Updated origin/main +## Diff Stat ```text - docs_build/dev/PROJECT_INSTRUCTIONS.md | 47 ++ - docs_build/dev/PROJECT_MULTI_PC.txt | 58 ++ - ..._063-codex-instruction-enforcement-hardening.md | 48 ++ - ...R_26171_063-instruction-compliance-checklist.md | 37 ++ - .../PR_26171_063-manual-validation-notes.md | 19 + - docs_build/dev/reports/PR_26171_063-validation.md | 32 + - docs_build/dev/reports/codex_changed_files.txt | 48 ++ - docs_build/dev/reports/codex_review.diff | 699 +++++++++------------ - 8 files changed, 569 insertions(+), 419 deletions(-) + 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(-) ``` +## 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. + ## Validation -- PASS: `git diff --check` after conflict resolution. -- PASS: targeted required instruction-anchor validation after conflict resolution. -- SKIP: Playwright, because the PR explicitly requires no Playwright and changes docs/workflow only. +- 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: `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. ## ZIP -- Path: `tmp/PR_26171_063-codex-instruction-enforcement-hardening_delta.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 diff --git a/docs_build/dev/reports/codex_review.diff b/docs_build/dev/reports/codex_review.diff index ef70a97af..9d13c1ccf 100644 --- a/docs_build/dev/reports/codex_review.diff +++ b/docs_build/dev/reports/codex_review.diff @@ -1,281 +1,886 @@ -diff --git a/docs_build/dev/PROJECT_INSTRUCTIONS.md b/docs_build/dev/PROJECT_INSTRUCTIONS.md -index 6a2014f2f..528312412 100644 ---- a/docs_build/dev/PROJECT_INSTRUCTIONS.md -+++ b/docs_build/dev/PROJECT_INSTRUCTIONS.md -@@ -2008,3 +2008,50 @@ Required Git workflow report fields: - - PR URL - - merge result - - final main commit -+ -+## CODEX INSTRUCTION ENFORCEMENT START GATE -+ -+Codex must run this gate before every PR execution and before any file changes. -+ -+Required instruction reads: -+- Read `docs_build/dev/PROJECT_INSTRUCTIONS.md`. -+- Read `docs_build/dev/PROJECT_MULTI_PC.txt`. -+- Treat the newest applicable section in `PROJECT_INSTRUCTIONS.md` as authoritative when rules overlap. -+- Treat the current owner/parity section in `PROJECT_MULTI_PC.txt` as authoritative for PC/Laptop routing. -+ -+Required pre-change report: -+- Codex must report instruction compliance as `PASS` or `FAIL` before making file changes. -+- The report must include branch, clean status, PR owner, PR parity, implementation path, validation scope, required report list, and ZIP requirement. -+- Any `FAIL` is a hard stop unless the PR explicitly scopes branch audit or recovery documentation without implementation. -+ -+Hard stops before changes: -+- If the current branch is not `main`, HARD STOP. -+- If the repository is not clean before the PR branch is created, HARD STOP. -+- If the PR owner does not match the PC/Laptop ownership map in `PROJECT_MULTI_PC.txt`, HARD STOP. -+- If the PR number parity does not match the assigned machine in `PROJECT_MULTI_PC.txt`, HARD STOP. -+- If the PR asks for implementation and the implementation path is wrong, HARD STOP. -+- If a PR asks for functional parity and only placeholder-only work is possible, HARD STOP and report the missing source or blocker. -+- If scoped validation is skipped without a documented reason, HARD STOP. -+ -+Path enforcement: -+- Use the active path named by the PR and verified in the repository. -+- Do not create wrong replacement paths. -+- For Text To Speech work, the active toolbox path is `toolbox/text-to-speech/`. -+- Do not create `tools/text2speech/` for new work. -+- If a PR names archived tools, games, or samples as a functionality sample, treat the archive as a read-only reference sample, not as a reason to skip implementation. -+ -+Completion hard stops: -+- If the required repo ZIP is missing, HARD STOP. -+- If the required repo ZIP is empty or not under `tmp/`, HARD STOP. -+- If required reports are missing, HARD STOP. -+- If `docs_build/dev/reports/codex_review.diff` is missing, HARD STOP. -+- If `docs_build/dev/reports/codex_changed_files.txt` is missing, HARD STOP. -+- If manual validation notes are missing, HARD STOP. -+- If the PR-specific report is missing, HARD STOP. -+- If an instruction compliance checklist is required and missing, HARD STOP. -+- If requested scoped validation did not run and no explicit skip reason is recorded, HARD STOP. -+ -+Functional parity rule: -+- A PR that asks to restore or rebuild working functionality must produce functional parity with the approved sample or source. -+- Placeholder shells, dead controls, static mockups, and nonfunctional UI are not acceptable completion states for functional parity PRs. -+- If functional parity cannot be reached in scope, Codex must stop and report the exact blocker instead of packaging placeholder-only work. -diff --git a/docs_build/dev/PROJECT_MULTI_PC.txt b/docs_build/dev/PROJECT_MULTI_PC.txt -index 3be408469..60ef4881a 100644 ---- a/docs_build/dev/PROJECT_MULTI_PC.txt -+++ b/docs_build/dev/PROJECT_MULTI_PC.txt -@@ -448,3 +448,61 @@ Queue next PR +diff --git a/assets/theme-v2/css/tables.css b/assets/theme-v2/css/tables.css +index a8c75090a..c39ef19f0 100644 +--- a/assets/theme-v2/css/tables.css ++++ b/assets/theme-v2/css/tables.css +@@ -38,6 +38,67 @@ td { + color: var(--text) + } + ++.idea-board-table-caption { ++ position: relative; ++ z-index: var(--z-index-sm); ++ display: flex; ++ align-items: center; ++ justify-content: space-between; ++ gap: var(--space-10); ++ padding: var(--space-10); ++ font-weight: var(--font-weight-heavy) ++} ++ ++.idea-board-show-filter { ++ position: relative; ++ z-index: var(--z-index-md); ++ color: var(--text); ++ font-size: var(--font-size-xs); ++ font-weight: var(--font-weight-bold) ++} ++ ++.idea-board-show-filter summary { ++ display: inline-flex; ++ align-items: center; ++ min-height: var(--space-28); ++ padding: var(--space-3) var(--space-10); ++ border: var(--border-standard); ++ border-radius: var(--radius-md); ++ background: var(--panel-soft); ++ cursor: pointer; ++ list-style: none ++} ++ ++.idea-board-show-filter summary::-webkit-details-marker { ++ display: none ++} ++ ++.idea-board-show-filter__menu { ++ position: static; ++ min-width: 12rem; ++ margin-top: var(--space-6); ++ padding: var(--space-10); ++ border: var(--border-standard); ++ border-radius: var(--radius-md); ++ background: var(--panel); ++ box-shadow: var(--shadow-md) ++} ++ ++.idea-board-show-filter__options { ++ display: grid; ++ gap: var(--space-6); ++ margin-top: var(--space-10) ++} ++ ++.idea-board-show-filter__option { ++ display: flex; ++ align-items: center; ++ gap: var(--space-8); ++ color: var(--text); ++ font-weight: var(--font-weight-regular); ++ white-space: nowrap ++} ++ + .data-table th { + color: var(--gold); + font-size: var(--font-size-sm); +@@ -60,8 +121,13 @@ td { + gap: .35em; + color: inherit; + font: inherit; +- line-height: inherit; +- vertical-align: baseline ++ line-height: var(--line-height-single); ++ vertical-align: baseline; ++ white-space: nowrap ++} ++ ++.idea-board-idea-label__text { ++ line-height: var(--line-height-single) + } + + .idea-board-idea-chevron { +diff --git a/assets/theme-v2/js/tool-display-mode.js b/assets/theme-v2/js/tool-display-mode.js +index 9c23ba67e..e77b7a9df 100644 +--- a/assets/theme-v2/js/tool-display-mode.js ++++ b/assets/theme-v2/js/tool-display-mode.js +@@ -157,7 +157,7 @@ + const diagnostic = document.createElement("p"); + diagnostic.className = "status"; + diagnostic.setAttribute("role", "status"); +- diagnostic.textContent = "Tool navigation could not load from the server API. Start the local server API and refresh."; ++ 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 4b9b70b93..bb7de5d8d 100644 +--- a/docs_build/dev/reports/codex_changed_files.txt ++++ b/docs_build/dev/reports/codex_changed_files.txt +@@ -1,37 +1,91 @@ +-# Codex Changed Files - PR_26171_063-codex-instruction-enforcement-hardening ++# Codex Changed Files - PR_26171_041-idea-board-production-polish + +-## Conflict Resolution Note +-- Merged latest `origin/main` into the PR branch after GitHub reported merge conflicts. +-- Regenerated Codex artifacts from the PR_063 delta against updated `origin/main`. +-- No implementation scope was changed while resolving conflicts. ++## 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. + +-## Changed Files +-- docs_build/dev/PROJECT_INSTRUCTIONS.md +-- docs_build/dev/PROJECT_MULTI_PC.txt +-- docs_build/dev/reports/PR_26171_063-codex-instruction-enforcement-hardening.md +-- docs_build/dev/reports/PR_26171_063-instruction-compliance-checklist.md +-- docs_build/dev/reports/PR_26171_063-validation.md +-- docs_build/dev/reports/PR_26171_063-manual-validation-notes.md +-- docs_build/dev/reports/codex_review.diff +-- docs_build/dev/reports/codex_changed_files.txt ++## Git Status ++```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 ++``` + +-## Git Diff Stat Against Updated origin/main ++## Diff Stat + ```text +- docs_build/dev/PROJECT_INSTRUCTIONS.md | 47 ++ +- docs_build/dev/PROJECT_MULTI_PC.txt | 58 ++ +- ..._063-codex-instruction-enforcement-hardening.md | 48 ++ +- ...R_26171_063-instruction-compliance-checklist.md | 37 ++ +- .../PR_26171_063-manual-validation-notes.md | 19 + +- docs_build/dev/reports/PR_26171_063-validation.md | 32 + +- docs_build/dev/reports/codex_changed_files.txt | 48 ++ +- docs_build/dev/reports/codex_review.diff | 699 +++++++++------------ +- 8 files changed, 569 insertions(+), 419 deletions(-) ++ 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(-) ``` - That is probably the fastest path to doubling throughput without creating chaos. -+ -+---------------------------------------------------------------------------------------- -+ -+Current Authoritative Multi-PC Gate -+ -+Codex must read this file before every PR execution. -+ -+Machine parity: -+ -+PC / Environment 1: -+- Uses even-numbered PR sequence values. -+- Example: `PR_26171_064-*`. -+ -+Laptop / Environment 2: -+- Uses odd-numbered PR sequence values. -+- Example: `PR_26171_063-*`. -+ -+Owner map: -+ -+PC / Environment 1 owns Creator Journey work: -+- Game Journey -+- Game Hub -+- Idea -+- Design -+- Objects -+- Worlds -+- Interface -+- Controls -+- Rules -+- Progression -+- Play Test -+- Progress Tracking -+- Game Design -+- Game Crew -+ -+Laptop / Environment 2 owns Content Creation and asset/publishing work: -+- Graphics -+- Toolbox images -+- Audio -+- MIDI -+- Messages -+- Text To Speech -+- TTS -+- Publishing -+- Marketplace -+- Community -+- Arcade -+ -+Governance, recovery, diagnostics, and instruction-hardening PRs: -+- Follow PR number parity unless Master Control explicitly assigns an owner. -+- Must not implement tool/runtime work from the opposite owner. -+- Must document owner/parity compliance in the PR report. -+ -+Hard stop rules: -+- If the PR number parity does not match the current machine, stop before changes. -+- If the PR scope belongs to the other machine owner, stop before changes. -+- If the PR crosses PC and Laptop ownership, stop and require Master Control to split or assign the work. -+- If the requested implementation path conflicts with the active owner path, stop before changes. -diff --git a/docs_build/dev/reports/PR_26171_063-codex-instruction-enforcement-hardening.md b/docs_build/dev/reports/PR_26171_063-codex-instruction-enforcement-hardening.md -new file mode 100644 -index 000000000..30bcba263 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_063-codex-instruction-enforcement-hardening.md -@@ -0,0 +1,48 @@ -+# PR_26171_063 Codex Instruction Enforcement Hardening -+ -+## Purpose -+ -+Make Codex explicitly obey `docs_build/dev/PROJECT_INSTRUCTIONS.md` and `docs_build/dev/PROJECT_MULTI_PC.txt` before every PR. -+ -+## Scope -+ -+- Added a Codex instruction enforcement start gate to `docs_build/dev/PROJECT_INSTRUCTIONS.md`. -+- Added current authoritative PC/Laptop owner and PR parity rules to `docs_build/dev/PROJECT_MULTI_PC.txt`. -+- Documented hard stops for branch state, clean status, owner mismatch, parity mismatch, wrong implementation paths, missing reports, missing ZIPs, skipped validation, and placeholder-only functional parity work. -+ -+## Requirement Checklist -+ -+- PASS: Codex must read `docs_build/dev/PROJECT_INSTRUCTIONS.md` before execution. -+- PASS: Codex must read `docs_build/dev/PROJECT_MULTI_PC.txt` before execution. -+- PASS: Codex must report instruction compliance PASS/FAIL before changes. -+- PASS: Codex must hard stop when not on `main` before starting. -+- PASS: Codex must hard stop when the repo is not clean before starting. -+- PASS: Codex must hard stop when PR owner does not match PC/Laptop ownership. -+- PASS: Codex must hard stop when PR number parity does not match assigned machine. -+- PASS: Codex must hard stop when required ZIP is missing. -+- PASS: Codex must hard stop when required reports are missing. -+- PASS: Codex must hard stop when implementation path is wrong. -+- PASS: Codex must hard stop when scoped validation was skipped without reason. -+- PASS: Codex must not continue with placeholder-only work when the PR asks for functional parity. -+- PASS: Codex must not create wrong paths such as `tools/text2speech` when active path is `toolbox/text-to-speech`. -+- PASS: Codex must not treat archived tools as "do not implement" when the PR says they are the functionality sample. -+ -+## Owner And Parity Evidence -+ -+- Current PR: `PR_26171_063-codex-instruction-enforcement-hardening`. -+- Sequence: `063`. -+- Sequence parity: odd. -+- Assigned machine under the new authoritative gate: Laptop / Environment 2. -+- Scope type: governance, recovery, diagnostics, and instruction-hardening. -+- Result: PASS because governance/instruction-hardening PRs follow PR number parity unless Master Control explicitly assigns another owner. -+ -+## Validation Scope -+ -+- Playwright impacted: No. -+- No Playwright impact. This PR is docs/workflow only. -+- Validation is docs/static only. -+- Runtime, tool, engine, samples, and Game Hub validation are skipped because no runtime, UI, toolState, engine, or sample behavior changed. -+ -+## ZIP -+ -+- Required ZIP path: `tmp/PR_26171_063-codex-instruction-enforcement-hardening_delta.zip`. -diff --git a/docs_build/dev/reports/PR_26171_063-instruction-compliance-checklist.md b/docs_build/dev/reports/PR_26171_063-instruction-compliance-checklist.md -new file mode 100644 -index 000000000..9d2277ab5 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_063-instruction-compliance-checklist.md -@@ -0,0 +1,37 @@ -+# PR_26171_063 Instruction Compliance Checklist -+ -+## Pre-Change 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: Starting branch was `main`. -+- PASS: Starting repository status was clean. -+- PASS: Created scoped branch `pr/26171-063-codex-instruction-enforcement-hardening` after the clean `main` check. -+ -+## Current PR Routing -+ -+- PASS: PR number `063` is odd. -+- PASS: Odd PR parity maps to Laptop / Environment 2 under the new authoritative Multi-PC gate. -+- PASS: PR scope is instruction/governance hardening and follows parity because no Master Control owner override was provided. -+- PASS: No PC-owned tool implementation was changed. -+- PASS: No Laptop-owned tool implementation was changed. -+ -+## Path And Functional Parity Gate -+ -+- PASS: No implementation path was changed by this docs-only PR. -+- PASS: `toolbox/text-to-speech/` is documented as the active Text To Speech path. -+- PASS: `tools/text2speech/` is documented as a wrong new-work path. -+- PASS: Placeholder-only functional parity work is prohibited. -+- PASS: Archived functionality samples are documented as read-only reference samples when explicitly named by a PR. -+ -+## Completion Gate -+ -+- PASS: Required PR-specific report exists. -+- PASS: Required instruction compliance checklist exists. -+- PASS: Required manual validation notes exist. -+- PASS: Required `docs_build/dev/reports/codex_review.diff` exists after artifact generation. -+- PASS: Required `docs_build/dev/reports/codex_changed_files.txt` exists after artifact generation. -+- PASS: Required ZIP exists after packaging. -+- PASS: Scoped validation was not skipped; docs/static validation was run. -+- PASS: Playwright was not run because the PR explicitly requires no Playwright. -diff --git a/docs_build/dev/reports/PR_26171_063-manual-validation-notes.md b/docs_build/dev/reports/PR_26171_063-manual-validation-notes.md -new file mode 100644 -index 000000000..43af53cc8 ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_063-manual-validation-notes.md -@@ -0,0 +1,19 @@ -+# PR_26171_063 Manual Validation Notes -+ -+## Manual Review -+ -+- Confirmed the new start gate requires reading `PROJECT_INSTRUCTIONS.md` and `PROJECT_MULTI_PC.txt` before every PR. -+- Confirmed the new gate requires visible PASS/FAIL instruction compliance before file changes. -+- Confirmed the hard stop list covers branch, clean status, owner, parity, required ZIP, required reports, wrong paths, skipped validation, and placeholder-only functional parity work. -+- Confirmed Text To Speech path enforcement names `toolbox/text-to-speech/` as active and rejects new `tools/text2speech/` work. -+- Confirmed archived tools can be used as read-only functionality samples when a PR explicitly names them. -+ -+## Manual Runtime Checks -+ -+- No Playwright was run. -+- No browser runtime checks were performed. -+- No Project Workspace/Game Hub runtime checks were performed. -+- No Local API checks were performed. -+- No Text To Speech runtime checks were performed. -+ -+These checks are out of scope because this PR only changes documentation and governance reports. -diff --git a/docs_build/dev/reports/PR_26171_063-validation.md b/docs_build/dev/reports/PR_26171_063-validation.md -new file mode 100644 -index 000000000..cedb0134a ---- /dev/null -+++ b/docs_build/dev/reports/PR_26171_063-validation.md -@@ -0,0 +1,32 @@ -+# PR_26171_063 Validation -+ -+## Scope -+ -+Docs/static validation only. -+ -+No Playwright was run because the PR explicitly says "No Playwright" and the changed files are governance docs and reports only. -+ -+## Commands -+ -+- `git diff --check` -+ - PASS: no whitespace errors. -+- Targeted required-text validation for `docs_build/dev/PROJECT_INSTRUCTIONS.md`, `docs_build/dev/PROJECT_MULTI_PC.txt`, and PR_26171_063 reports. -+ - PASS: all required hardening anchors were found. -+ - Note: the first targeted text check found missing exact `No Playwright` wording in manual notes; the note was corrected and the validation was rerun successfully. -+ -+## Skipped -+ -+- `npm run test:workspace-v2` -+ - SKIP: legacy command name for Project Workspace/Game Hub validation; no workspace or toolState behavior changed. -+- `npm run test:playwright:static` -+ - SKIP: command name is Playwright-scoped and this PR explicitly says no Playwright. -+- Runtime, tool, engine, samples, and browser validation -+ - SKIP: docs/workflow-only change. -+ -+## 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_063-codex-instruction-enforcement-hardening_delta.zip` exists. -+- PASS: ZIP size is greater than zero. -+- PASS: ZIP contents preserve repo-relative paths. ++## 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. ++ + ## Validation +-- PASS: `git diff --check` after conflict resolution. +-- PASS: targeted required instruction-anchor validation after conflict resolution. +-- SKIP: Playwright, because the PR explicitly requires no Playwright and changes docs/workflow only. ++- 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: `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. + + ## ZIP +-- Path: `tmp/PR_26171_063-codex-instruction-enforcement-hardening_delta.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 +diff --git a/docs_build/dev/reports/coverage_changed_js_guardrail.txt b/docs_build/dev/reports/coverage_changed_js_guardrail.txt +index 076d27690..66dd0cb12 100644 +--- a/docs_build/dev/reports/coverage_changed_js_guardrail.txt ++++ b/docs_build/dev/reports/coverage_changed_js_guardrail.txt +@@ -6,10 +6,9 @@ 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/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only + (0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only +-(70%) toolbox/idea-board/index.js - executed lines 480/480; executed functions 23/33 ++(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 + + Guardrail warnings: +-(0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file missing from coverage; advisory only + (0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file missing from coverage; advisory only +diff --git a/docs_build/dev/reports/playwright_v8_coverage_report.txt b/docs_build/dev/reports/playwright_v8_coverage_report.txt +index cb35b4d50..4a9f71ff1 100644 +--- a/docs_build/dev/reports/playwright_v8_coverage_report.txt ++++ b/docs_build/dev/reports/playwright_v8_coverage_report.txt +@@ -17,9 +17,9 @@ Exercised tool entry points detected: + (63%) Theme V2 Shared JS - exercised 2 runtime JS files + + Changed runtime JS files covered: +-(0%) src/dev-runtime/server/local-api-router.mjs - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only + (0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only +-(70%) toolbox/idea-board/index.js - executed lines 480/480; executed functions 23/33 ++(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 + + Files with executed line/function counts where available: + (25%) src/api/session-api-client.js - executed lines 68/68; executed functions 3/12 +@@ -30,17 +30,16 @@ Files with executed line/function counts where available: + (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 +-(70%) toolbox/idea-board/index.js - executed lines 480/480; executed functions 23/33 ++(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 + + Uncovered or low-coverage changed JS files: +-(0%) src/dev-runtime/server/local-api-router.mjs - WARNING: uncovered changed runtime JS file; advisory only + (0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: uncovered changed runtime JS file; advisory only + + Changed JS files considered: +-(0%) src/dev-runtime/server/local-api-router.mjs - changed JS file not collected as browser runtime coverage + (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 +-(70%) toolbox/idea-board/index.js - changed JS file with browser V8 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 +diff --git a/src/shared/toolbox/tool-metadata-inventory.js b/src/shared/toolbox/tool-metadata-inventory.js +index db04eac5b..6d2ed68fa 100644 +--- a/src/shared/toolbox/tool-metadata-inventory.js ++++ b/src/shared/toolbox/tool-metadata-inventory.js +@@ -72,14 +72,14 @@ export const TOOL_REGISTRY = Object.freeze([ + "id": "idea-board", + "name": "Idea Board", + "displayName": "Idea Board", +- "shortDescription": "Capture, compare, and shape game ideas in a table.", ++ "shortDescription": "Capture, compare, and shape game ideas.", + "shortLabel": "Idea Board", + "path": "idea-board", + "folderName": "idea-board", + "entryPoint": "idea-board/index.html", + "badge": "/assets/theme-v2/images/badges/game-design.png", + "tool": "/assets/theme-v2/images/tools/game-design.png", +- "description": "Capture, compare, and shape game ideas with notes under each idea row.", ++ "description": "Capture, compare, and shape game ideas.", + "category": "Idea", + "colorGroup": "tool-group-idea", + "active": true, +@@ -93,7 +93,7 @@ export const TOOL_REGISTRY = Object.freeze([ + "progressChecklist": [ + "Idea table workflow visible", + "Add Idea and Add Note actions remain inline", +- "Create Project remains unavailable until an idea is ready" ++ "Ready ideas show project actions in their row" + ], + "deferred": false, + "hidden": false, +diff --git a/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs b/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs +index f5544ca88..38085a4d2 100644 +--- a/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs ++++ b/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs +@@ -13,10 +13,13 @@ function restoreEnvValue(key, value) { + async function expectIdeaChevron(page, ideaId, iconName) { + const metrics = await page.locator(`[data-idea-board-idea-row='${ideaId}'] th`).evaluate((cell, targetIdeaId) => { + const label = cell.querySelector(".idea-board-idea-label"); ++ const text = label.querySelector(".idea-board-idea-label__text"); + const icon = cell.querySelector(`[data-idea-board-chevron='${targetIdeaId}']`); + const cellStyles = getComputedStyle(cell); + const labelStyles = getComputedStyle(label); + const iconStyles = getComputedStyle(icon); ++ const textRect = text.getBoundingClientRect(); ++ const iconRect = icon.getBoundingClientRect(); + return { + iconName: icon.dataset.ideaBoardChevronIcon, + labelDisplay: labelStyles.display, +@@ -24,7 +27,11 @@ async function expectIdeaChevron(page, ideaId, iconName) { + iconHeight: Number.parseFloat(iconStyles.height), + fontSize: Number.parseFloat(cellStyles.fontSize), + iconColor: iconStyles.backgroundColor, ++ iconBottom: iconRect.bottom, ++ iconLeft: iconRect.left, + textColor: cellStyles.color, ++ textBottom: textRect.bottom, ++ textLeft: textRect.left, + maskImage: iconStyles.getPropertyValue("-webkit-mask-image") || iconStyles.maskImage, + }; + }, ideaId); +@@ -33,6 +40,8 @@ async function expectIdeaChevron(page, ideaId, iconName) { + expect(Math.abs(metrics.iconWidth - metrics.fontSize)).toBeLessThanOrEqual(1); + expect(Math.abs(metrics.iconHeight - metrics.fontSize)).toBeLessThanOrEqual(1); + expect(metrics.iconColor).toBe(metrics.textColor); ++ expect(metrics.iconLeft).toBeLessThan(metrics.textLeft); ++ expect(Math.abs(metrics.iconBottom - metrics.textBottom)).toBeLessThanOrEqual(2); + expect(metrics.maskImage).toContain(iconName); + } + +@@ -92,7 +101,7 @@ async function expectExpandedNotesChildIndentation(page, ideaId, expectedInputRo + + async function expectProductionCopy(page) { + await expect(page.locator("main")).not.toContainText( +- /\bDB-shaped\b|\bin-page data model\b|\buserId\b|\bideaId\b|\bnoteId\b|\bsystem flag\b|\bmetadata\b|\bseed\b|\bdebug\b|\bselected context\b|\bmock\b|\btest\b|\binternal implementation\b|\bplaceholder\b|\bproject records\b|\bmutating API\b|\bauth\b|\bAI\b|\bdatabase behavior\b/i, ++ /\bDB-shaped\b|\bin-page data model\b|\buserId\b|\bideaId\b|\bnoteId\b|\bsystem flag\b|\bmetadata\b|\bseed\b|\bdebug\b|\bselected context\b|\bmock\b|\btest\b|\binternal implementation\b|\bplaceholder\b|\bproject records\b|\bmutating API\b|\bserver\b|\bAPI\b|\blocal server\b|\bport\b|\bunderlying systems\b|\bauth\b|\bAI\b|\bdatabase behavior\b/i, + ); + } + +@@ -141,6 +150,28 @@ test("Idea Board uses accordion table ideas and notes", async ({ page }) => { + await expect(page.locator("[data-idea-board-add-idea-row]")).toHaveCount(1); + await expect(page.locator("[data-idea-board-add-idea]")).toHaveText("Add Idea"); + await expectButtonLeftAligned(page, "[data-idea-board-add-idea]", "[data-idea-board-add-idea-row] > td"); ++ await expect(page.locator("[data-idea-board-show-filter] summary")).toHaveText("Show"); ++ const captionMetrics = await page.locator(".idea-board-table-caption").evaluate((caption) => { ++ const label = caption.querySelector("span"); ++ const filter = caption.querySelector("[data-idea-board-show-filter]"); ++ const labelRect = label.getBoundingClientRect(); ++ const filterRect = filter.getBoundingClientRect(); ++ return { ++ filterRight: filterRect.right, ++ filterTop: filterRect.top, ++ labelRight: labelRect.right, ++ labelTop: labelRect.top, ++ }; ++ }); ++ expect(captionMetrics.filterRight).toBeGreaterThan(captionMetrics.labelRight); ++ expect(Math.abs(captionMetrics.filterTop - captionMetrics.labelTop)).toBeLessThanOrEqual(4); ++ await page.locator("[data-idea-board-show-filter] summary").click(); ++ await expect(page.locator("[data-idea-board-status-filter-option]")).toHaveCount(6); ++ const checkedStatuses = await page.locator("[data-idea-board-status-filter-option]:checked").evaluateAll((inputs) => ( ++ inputs.map((input) => input.value) ++ )); ++ expect(checkedStatuses).toEqual(["New", "Exploring", "Refining", "Ready", "Project"]); ++ await expect(page.locator("[data-idea-board-status-filter-option][value='Archived']")).not.toBeChecked(); + await expect(page.getByText(/another/i)).toHaveCount(0); + await expect(page.locator("[data-idea-board-notes-chevron]")).toHaveCount(0); + await expect(page.getByText("Selected idea context")).toHaveCount(0); +@@ -223,11 +254,19 @@ test("Idea Board uses accordion table ideas and notes", async ({ page }) => { + const ideaInputRow = page.locator("[data-idea-board-idea-input-row]").last(); + await expect(ideaInputRow.locator("[data-idea-board-idea-action]")).toHaveText(["Save", "Cancel"]); + await expect(ideaInputRow.locator("[data-idea-board-idea-status-input]")).toHaveCount(1); ++ await expect(ideaInputRow.locator("[data-idea-board-idea-status-input] option")).toHaveText([ ++ "New", ++ "Exploring", ++ "Refining", ++ "Ready", ++ "Project", ++ "Archived", ++ ]); + await expect(ideaInputRow.locator("td").nth(2)).toHaveText(/\d{4}-\d{2}-\d{2}/); + await expect(ideaInputRow.locator("td").nth(3)).toHaveText("0 Notes"); + await page.locator("[data-idea-board-idea-input]").fill("Lantern Reef"); + await page.locator("[data-idea-board-pitch-input]").fill("Guide light through a reef that rearranges at dusk."); +- await page.locator("[data-idea-board-idea-status-input]").selectOption("Parked"); ++ await page.locator("[data-idea-board-idea-status-input]").selectOption("Refining"); + await page.locator("[data-idea-board-idea-action='save']").click(); + await expect(page.locator("[data-idea-board-idea-row='lantern-reef']")).toBeVisible(); + await expect(page.locator("[data-idea-board-notes-count='lantern-reef']")).toHaveText("0 Notes"); +@@ -236,9 +275,33 @@ test("Idea Board uses accordion table ideas and notes", async ({ page }) => { + await page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action='edit']").click(); + await expect(page.locator("[data-idea-board-idea-input-row] [data-idea-board-idea-action]")).toHaveText(["Save", "Cancel"]); + await expect(page.locator("[data-idea-board-idea-status-input]")).toHaveCount(1); +- await page.locator("[data-idea-board-idea-status-input]").selectOption("Ready to Shape"); ++ await page.locator("[data-idea-board-idea-status-input]").selectOption("Ready"); + await page.locator("[data-idea-board-idea-action='save']").click(); +- await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] td").nth(1)).toHaveText("Ready to Shape"); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] td").nth(1)).toHaveText("Ready"); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action]")).toHaveText(["Edit", "Create Project", "Delete"]); ++ await page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action='create-project']").click(); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] td").nth(1)).toHaveText("Project"); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action]")).toHaveText(["Edit", "Open Project", "Archive"]); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action='delete']")).toHaveCount(0); ++ await page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action='open-project']").click(); ++ await expect(page.locator("[data-idea-board-status]")).toHaveText("Opening Lantern Reef."); ++ await page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action='archive']").click(); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef']")).toHaveCount(0); ++ await page.locator("[data-idea-board-status-filter-option][value='Archived']").check(); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef']")).toBeVisible(); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] td").nth(1)).toHaveText("Archived"); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action]")).toHaveText(["Restore", "Delete"]); ++ await page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action='restore']").click(); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] td").nth(1)).toHaveText("Project"); ++ await page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action='archive']").click(); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action]")).toHaveText(["Restore", "Delete"]); ++ await page.locator("[data-idea-board-idea-row='lantern-reef'] [data-idea-board-idea-action='delete']").click(); ++ await expect(page.locator("[data-idea-board-idea-row='lantern-reef']")).toHaveCount(0); ++ await page.locator("[data-idea-board-filter-clear-all]").click(); ++ await expect(page.locator("[data-idea-board-idea-row]")).toHaveCount(0); ++ await expect(page.locator("[data-idea-board-add-idea]")).toBeVisible(); ++ await page.locator("[data-idea-board-filter-select-all]").click(); ++ await expect(page.locator("[data-idea-board-idea-row]")).toHaveCount(3); + + expect(mutatingApiRequests).toEqual([]); + expect(failedRequests).toEqual([]); +diff --git a/tests/playwright/tools/ToolboxRoutePages.spec.mjs b/tests/playwright/tools/ToolboxRoutePages.spec.mjs +index b3033e10d..9f40a19ad 100644 +--- a/tests/playwright/tools/ToolboxRoutePages.spec.mjs ++++ b/tests/playwright/tools/ToolboxRoutePages.spec.mjs +@@ -115,10 +115,13 @@ function restoreEnvValue(key, value) { + async function expectIdeaChevron(page, ideaId, iconName) { + const metrics = await page.locator(`[data-idea-board-idea-row='${ideaId}'] th`).evaluate((cell, targetIdeaId) => { + const label = cell.querySelector(".idea-board-idea-label"); ++ const text = label.querySelector(".idea-board-idea-label__text"); + const icon = cell.querySelector(`[data-idea-board-chevron='${targetIdeaId}']`); + const cellStyles = getComputedStyle(cell); + const labelStyles = getComputedStyle(label); + const iconStyles = getComputedStyle(icon); ++ const textRect = text.getBoundingClientRect(); ++ const iconRect = icon.getBoundingClientRect(); + return { + iconName: icon.dataset.ideaBoardChevronIcon, + labelDisplay: labelStyles.display, +@@ -126,7 +129,11 @@ async function expectIdeaChevron(page, ideaId, iconName) { + iconHeight: Number.parseFloat(iconStyles.height), + fontSize: Number.parseFloat(cellStyles.fontSize), + iconColor: iconStyles.backgroundColor, ++ iconBottom: iconRect.bottom, ++ iconLeft: iconRect.left, + textColor: cellStyles.color, ++ textBottom: textRect.bottom, ++ textLeft: textRect.left, + maskImage: iconStyles.getPropertyValue("-webkit-mask-image") || iconStyles.maskImage, + }; + }, ideaId); +@@ -135,6 +142,8 @@ async function expectIdeaChevron(page, ideaId, iconName) { + expect(Math.abs(metrics.iconWidth - metrics.fontSize)).toBeLessThanOrEqual(1); + expect(Math.abs(metrics.iconHeight - metrics.fontSize)).toBeLessThanOrEqual(1); + expect(metrics.iconColor).toBe(metrics.textColor); ++ expect(metrics.iconLeft).toBeLessThan(metrics.textLeft); ++ expect(Math.abs(metrics.iconBottom - metrics.textBottom)).toBeLessThanOrEqual(2); + expect(metrics.maskImage).toContain(iconName); + } + +@@ -194,7 +203,7 @@ async function expectExpandedNotesChildIndentation(page, ideaId, expectedInputRo + + async function expectIdeaBoardProductionCopy(page) { + await expect(page.locator("main")).not.toContainText( +- /\bDB-shaped\b|\bin-page data model\b|\buserId\b|\bideaId\b|\bnoteId\b|\bsystem flag\b|\bmetadata\b|\bseed\b|\bdebug\b|\bselected context\b|\bmock\b|\btest\b|\binternal implementation\b|\bplaceholder\b|\bproject records\b|\bmutating API\b|\bauth\b|\bAI\b|\bdatabase behavior\b/i, ++ /\bDB-shaped\b|\bin-page data model\b|\buserId\b|\bideaId\b|\bnoteId\b|\bsystem flag\b|\bmetadata\b|\bseed\b|\bdebug\b|\bselected context\b|\bmock\b|\btest\b|\binternal implementation\b|\bplaceholder\b|\bproject records\b|\bmutating API\b|\bserver\b|\bAPI\b|\blocal server\b|\bport\b|\bunderlying systems\b|\bauth\b|\bAI\b|\bdatabase behavior\b/i, + ); + } + +@@ -302,7 +311,6 @@ test("Idea Board launches from Toolbox with accordion table notes model", async + "Workflow", + "Status", + "Idea Table", +- "Create Project", + "Notes Governance", + "Diagnostics", + ]); +@@ -335,12 +343,10 @@ test("Idea Board launches from Toolbox with accordion table notes model", async + await expect(page.locator("[data-idea-board-add-note='top-thoughts']")).toBeVisible(); + await expect(page.locator("[data-idea-board-add-note='top-thoughts']")).toHaveText("Add Note"); + await expectExpandedNotesChildIndentation(page, "top-thoughts"); +- await expect(page.locator("[data-idea-board-create-project]")).toBeVisible(); +- await expect(page.locator("[data-idea-board-create-project]")).toBeDisabled(); ++ await expect(page.locator("[data-idea-board-create-project]")).toHaveCount(0); + await expect(page.locator("style, [style], script:not([src])")).toHaveCount(0); + await expect(page.locator("script[src='toolbox/idea-board/index.js']")).toHaveCount(1); + mutatingApiRequests.length = 0; +- await page.locator("[data-idea-board-create-project]").evaluate((button) => button.click()); + await page.locator("[data-idea-board-add-note='top-thoughts']").click(); + await page.locator("[data-idea-board-note-input]").fill("Capture traversal risks before project creation."); + await page.locator("[data-idea-board-note-action='save']").click(); +@@ -348,6 +354,16 @@ test("Idea Board launches from Toolbox with accordion table notes model", async + await page.locator("[data-idea-board-idea-cell='clockwork-courier']").click(); + await expect(page.locator("[data-idea-board-expanded-row='clockwork-courier']")).toBeVisible(); + await expect(page.locator("[data-idea-board-notes-table='clockwork-courier']")).not.toContainText("Capture traversal risks before project creation."); ++ await page.locator("[data-idea-board-add-idea]").click(); ++ await page.locator("[data-idea-board-idea-input]").fill("Launch Tile"); ++ await page.locator("[data-idea-board-pitch-input]").fill("Turn a polished board idea into a project."); ++ await page.locator("[data-idea-board-idea-status-input]").selectOption("Ready"); ++ await page.locator("[data-idea-board-idea-action='save']").click(); ++ await expect(page.locator("[data-idea-board-idea-row='launch-tile'] [data-idea-board-idea-action]")).toHaveText(["Edit", "Create Project", "Delete"]); ++ await page.locator("[data-idea-board-idea-row='launch-tile'] [data-idea-board-idea-action='create-project']").click(); ++ await expect(page.locator("[data-idea-board-idea-row='launch-tile'] td").nth(1)).toHaveText("Project"); ++ await expect(page.locator("[data-idea-board-idea-row='launch-tile'] [data-idea-board-idea-action]")).toHaveText(["Edit", "Open Project", "Archive"]); ++ await expect(page.locator("[data-idea-board-idea-row='launch-tile'] [data-idea-board-idea-action='delete']")).toHaveCount(0); + expect(mutatingApiRequests).toEqual([]); + + expect(failedRequests).toEqual([]); +diff --git a/toolbox/idea-board/index.html b/toolbox/idea-board/index.html +index 214a303fb..422d67b1b 100644 +--- a/toolbox/idea-board/index.html ++++ b/toolbox/idea-board/index.html +@@ -18,7 +18,7 @@ +
Capture, compare, and shape game ideas in one table.
++Capture, compare, and shape game ideas.
+Use status to show where each idea stands: New, Exploring, Parked, or Ready to Shape.
++Use status to show where each idea stands: New, Exploring, Refining, Ready, Project, or Archived.
+Scan, compare, and update early ideas without leaving the table.
++Scan, compare, and update early ideas.
++| Idea | +@@ -69,14 +81,7 @@ +
|---|
| Idea | @@ -69,14 +81,7 @@
|---|