Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 60 additions & 3 deletions assets/toolbox/sprites/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const elements = {
paletteStatus: document.querySelector("[data-sprites-palette-status]"),
previewPanel: document.querySelector("[data-sprites-preview-panel]"),
refresh: document.querySelector("[data-sprites-refresh]"),
referencePanel: document.querySelector("[data-sprites-reference-panel]"),
referenceStatus: document.querySelector("[data-sprites-reference-status]"),
replace: document.querySelector("[data-sprites-replace]"),
replaceStatus: document.querySelector("[data-sprites-replace-status]"),
search: document.querySelector("[data-sprites-search]"),
Expand Down Expand Up @@ -193,8 +195,12 @@ function usageCountFor(sprite) {
return Number.isFinite(count) && count >= 0 ? String(count) : "0";
}

function referencesFor(sprite) {
return Array.isArray(sprite?.references) ? sprite.references : [];
}

function numericUsageCount(sprite) {
const count = Number(sprite?.usageCount ?? sprite?.usage_count ?? sprite?.references?.length);
const count = Number(sprite?.usageCount ?? sprite?.usage_count ?? referencesFor(sprite).length);
return Number.isFinite(count) && count >= 0 ? count : 0;
}

Expand Down Expand Up @@ -324,8 +330,10 @@ function renderUnavailable(message) {
setText(elements.paletteSelectionStatus, "Palette/Colors selection unavailable until API-backed key records are available.");
setText(elements.storageStatus, "Storage import unavailable because the Sprites API is not responding.");
setText(elements.filterStatus, "Filters unavailable until Sprites records load from the API.");
setText(elements.referenceStatus, "References unavailable until Sprites records load from the API.");
setText(elements.replaceStatus, "Replace metadata unavailable until the Sprites API responds.");
renderPreviewPanel(null);
renderReferencePanel(null);
setText(elements.updated, new Date().toLocaleTimeString());
setHidden(elements.emptyState, false);
setHidden(elements.errorState, false);
Expand Down Expand Up @@ -400,18 +408,66 @@ function renderPreviewPanel(sprite) {
setDisabled(elements.replace, false);
}

function renderReferencePanel(sprite) {
if (!elements.referencePanel) {
return;
}
elements.referencePanel.replaceChildren();
if (!sprite) {
setText(elements.referenceStatus, "Select a sprite to review API-provided usage references.");
elements.referencePanel.append(createParagraph("No sprite selected for reference review.", "status"));
return;
}
const references = referencesFor(sprite);
const usageCount = numericUsageCount(sprite);
setText(
elements.referenceStatus,
usageCount > 0
? `${usageCount} usage reference${usageCount === 1 ? "" : "s"} reported by the Sprites API.`
: "No usage references reported by the Sprites API."
);
if (!references.length) {
elements.referencePanel.append(createParagraph("No references reported yet. Future Objects and Worlds references will appear here when the API supplies them.", "status"));
return;
}
const wrapper = document.createElement("div");
wrapper.className = "table-wrapper";
const table = document.createElement("table");
table.className = "data-table";
table.setAttribute("aria-label", "Sprite usage references");
const head = document.createElement("thead");
const headRow = document.createElement("tr");
headRow.append(createCell("Source Type"), createCell("Source Key"), createCell("Label"));
head.append(headRow);
const body = document.createElement("tbody");
references.forEach((reference) => {
const row = document.createElement("tr");
row.append(
createCell(normalizeText(reference.sourceType)),
createCell(normalizeText(reference.sourceKey)),
createCell(normalizeText(reference.label, "No label"))
);
body.append(row);
});
table.append(head, body);
wrapper.append(table);
elements.referencePanel.append(wrapper);
}

function selectSprite(sprite) {
selectedSpriteKey = sprite?.key || "";
if (!sprite) {
setText(elements.metadata, "Select a sprite row to review its metadata.");
renderPreviewPanel(null);
renderReferencePanel(null);
return;
}
const key = normalizeText(sprite?.key, "Unavailable");
const mimeType = normalizeText(sprite?.mimeType ?? sprite?.mime_type, "Unavailable");
const sizeBytes = normalizeText(sprite?.sizeBytes ?? sprite?.size_bytes, "Unavailable");
setText(elements.metadata, `${normalizeText(sprite?.name)} (${key}) | ${mimeType} | ${formatDimensions(sprite)} | ${sizeBytes} bytes`);
renderPreviewPanel(sprite);
renderReferencePanel(sprite);
}

function renderRows(sprites, emptyMessage = "No Sprites records returned by the API.") {
Expand Down Expand Up @@ -491,9 +547,10 @@ function createSpriteRow(sprite) {
actions.append(
createButton("Edit", "spritesEdit", sprite?.key || "", { label: `Edit ${name}` }),
createButton("Duplicate", "spritesDuplicateRow", sprite?.key || "", { label: `Duplicate ${name}` }),
createButton(archived ? "Archived" : "Archive", "spritesArchive", sprite?.key || "", {
createButton(archived ? "Archived" : usageCount > 0 ? "Archive Safely" : "Archive", "spritesArchive", sprite?.key || "", {
disabled: archived,
label: archived ? `${name} is already archived` : `Archive ${name}`,
label: archived ? `${name} is already archived` : usageCount > 0 ? `Archive safely ${name}` : `Archive ${name}`,
title: usageCount > 0 ? "Sprite is referenced. Archive is the safe action; destructive delete is blocked." : "",
}),
createButton(usageCount > 0 ? "Delete Blocked" : "Delete", "spritesDelete", sprite?.key || "", {
disabled: usageCount > 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# PR_26177_CHARLIE_015 Branch Validation

Status: PASS

## Checks

- PASS: PR015 was created as a stacked branch from `PR_26177_CHARLIE_014-sprites-tags-categories-search`.
- PASS: Stacking is required because reference protection builds on the PR014 Sprites table/actions.
- PASS: Current work branch is `PR_26177_CHARLIE_015-sprites-reference-protection`.
- PASS: Branch contains only the Sprites reference protection PR scope relative to PR014.
- PASS: No merge was performed.
- PASS: No `start_of_day` path is changed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# PR_26177_CHARLIE_015 Manual Validation Notes

Status: PASS

## Manual Review

- Verified API-provided references render in the inspector.
- Verified empty reference state appears when the API returns no references.
- Verified referenced sprites show usage counts.
- Verified delete is disabled for referenced sprites.
- Verified archive remains available and clearly labeled as the safe action for referenced sprites.
- Verified no fake Objects or Worlds references were added.
- Verified future reference ownership remains API/database-backed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# PR_26177_CHARLIE_015 Requirements Checklist

Status: PASS

- PASS: Added reference viewer for where a sprite is used.
- PASS: Reference viewer consumes API-provided references only.
- PASS: Did not invent fake references.
- PASS: Prevents destructive delete when a sprite is referenced.
- PASS: Allows safe archive action with clear labeling for referenced sprites.
- PASS: Shows usage counts in the table.
- PASS: Shows usage reference details in the inspector.
- PASS: Establishes future Objects/Worlds reference contract through API/database references.
- PASS: Shows visible empty state when no real references are available.
- PASS: Did not add browser storage product-data source of truth.
- PASS: Did not introduce MEM DB, local-mem, fake-login, or silent fallback.
- PASS: Targeted Playwright coverage passed.
- PASS: Required report artifacts were created.
- PASS: Repo-structured ZIP artifact was created under `tmp/`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# PR_26177_CHARLIE_015 Validation Lane

Status: PASS

## Commands

```powershell
rg -n "<style|style=|onclick=|onchange=|oninput=|onsubmit=|<script>" toolbox/sprites/index.html assets/toolbox/sprites/js/index.js tests/playwright/tools/SpritesToolShell.spec.mjs
```

Result: PASS, no matches.

```powershell
rg -n "localStorage|sessionStorage|indexedDB|imageDataUrl|MEM DB|local-mem|fake-login|silent fallback" toolbox/sprites/index.html assets/toolbox/sprites/js/index.js tests/playwright/tools/SpritesToolShell.spec.mjs
```

Result: PASS, no matches.

```powershell
git diff --check
```

Result: PASS. Git reported only repository line-ending warnings for changed HTML/test files.

```powershell
node ./node_modules/@playwright/test/cli.js test tests/playwright/tools/SpritesToolShell.spec.mjs --project=playwright --workers=1 --reporter=list
```

Result: PASS, 10 passed.

## Playwright Coverage

Targeted Playwright coverage updated `docs_build/dev/reports/playwright_v8_coverage_report.txt` for the Sprites browser module.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# PR_26177_CHARLIE_015-sprites-reference-protection

Team: Charlie

Status: PASS

## Scope

Added API-provided reference visibility and strengthened destructive delete protection for Sprites.

## Changed Files

- `toolbox/sprites/index.html`
- `assets/toolbox/sprites/js/index.js`
- `tests/playwright/tools/SpritesToolShell.spec.mjs`
- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
- `docs_build/dev/reports/codex_review.diff`
- `docs_build/dev/reports/codex_changed_files.txt`
- `docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection.md`
- `docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-branch-validation.md`
- `docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-requirements-checklist.md`
- `docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-validation-lane.md`
- `docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-manual-validation-notes.md`

## Implementation Notes

- Added reference viewer for API-provided usage references.
- Displays source type, source key, and label for each usage reference.
- Shows empty reference state when the API reports no references.
- Keeps usage count visible in table and details.
- Destructive delete remains disabled when usage count is greater than zero.
- Referenced sprites show `Archive Safely` to make the safe action explicit.
- No fake Objects or Worlds references were added.

## Reference Contract

The UI consumes the existing Sprites API `references` array. Future Objects/Worlds integrations should supply real usage rows through the API/database reference contract rather than browser-local inference.

## Validation

- PASS: `git diff --check`
- PASS: inline CSS/script/handler scan for Sprites files found no matches.
- PASS: browser storage and forbidden local data pattern scan found no matches.
- PASS: no `start_of_day` files changed.
- PASS: `node ./node_modules/@playwright/test/cli.js test tests/playwright/tools/SpritesToolShell.spec.mjs --project=playwright --workers=1 --reporter=list`

## ZIP Artifact

- `tmp/PR_26177_CHARLIE_015-sprites-reference-protection_delta.zip`
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# PR_26177_CHARLIE_015-sprites-reference-protection

Generated: 2026-06-26
Team: Charlie
GitHub PR: #225
Branch: PR_26177_CHARLIE_015-sprites-reference-protection
Base: PR_26177_CHARLIE_014-sprites-tags-categories-search

## Branch Validation

| Check | Result | Notes |
| --- | --- | --- |
| Branch exists locally | PASS | PR_26177_CHARLIE_015-sprites-reference-protection |
| Branch pushed to origin | PASS | Existing upstream branch is present. |
| Worktree clean before report generation | PASS | Verified before companion reports were written. |
| Runtime/UI/API/database change in this report commit | PASS | None; report-only completion. |
| start_of_day changes | PASS | None. |
| GitHub draft state | PENDING | PR remains draft until Owner review. |
| GitHub mergeable state at EOD snapshot | PASS | mergeable=true; not merged because no Owner approval was provided. |

## Result

Report artifact completion is PASS. Merge readiness remains pending Owner review and dependency-order workflow.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# PR_26177_CHARLIE_015-sprites-reference-protection

Generated: 2026-06-26
Team: Charlie
GitHub PR: #225
Branch: PR_26177_CHARLIE_015-sprites-reference-protection
Base: PR_26177_CHARLIE_014-sprites-tags-categories-search

## Manual Validation Notes

- PR scope: Adds usage/reference viewer, usage counts, and destructive delete protection contract.
- Manual review should verify the PR in dependency order after prior Sprites branches are approved or merged.
- Browser-owned product data, page-local reusable color arrays, and silent fallback behavior should remain absent.
- Palette/Colors must remain the authoritative owner of reusable colors; Sprites may reference color keys only.
- Because this EOD update is report-only, no new manual UI behavior was introduced.

## EOD Status

Open draft PR. Not merged. Awaiting Owner review and dependency-order workflow.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# PR_26177_CHARLIE_015-sprites-reference-protection

Generated: 2026-06-26
Team: Charlie
GitHub PR: #225
Branch: PR_26177_CHARLIE_015-sprites-reference-protection
Base: PR_26177_CHARLIE_014-sprites-tags-categories-search

## Requirement Checklist

| Requirement | Result | Notes |
| --- | --- | --- |
| One PR purpose only | PASS | Adds usage/reference viewer, usage counts, and destructive delete protection contract. |
| Theme V2 / current GFS patterns preserved | PASS | Validated in original PR lane where UI was touched. |
| Browser -> API -> Database flow preserved | PASS | No browser-owned authoritative product data added. |
| Palette/Colors remains color SSoT | PASS | Sprites references Palette/Colors keys only where applicable. |
| No MEM DB/local-mem/fake-login/silent fallback introduced | PASS | No forbidden runtime patterns introduced in original PR scope. |
| No start_of_day changes | PASS | Confirmed for report completion. |
| Required companion reports present | PASS | Branch validation, checklist, validation lane, and manual notes added by this EOD report-only commit. |
| Repo ZIP under tmp | PASS | Local EOD ZIP was regenerated under tmp for this PR. |

## Result

PASS for report completion. PR remains unmerged pending review/approval.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# PR_26177_CHARLIE_015-sprites-reference-protection

Generated: 2026-06-26
Team: Charlie
GitHub PR: #225
Branch: PR_26177_CHARLIE_015-sprites-reference-protection
Base: PR_26177_CHARLIE_014-sprites-tags-categories-search

## Validation Lane

Original targeted validation recorded by the PR:

- git diff --check
- inline style/script/handler scan
- browser storage/forbidden local data scan
- Playwright SpritesToolShell (10 passed)

EOD report-completion validation:

- PASS: report-only changed-file intent.
- PASS: no source/runtime files changed by this companion report commit.
- PASS: ZIP artifact regenerated locally under tmp.

## Result

PASS for documented targeted validation. No additional runtime validation was run during EOD report generation because no implementation files changed.
30 changes: 15 additions & 15 deletions docs_build/dev/reports/codex_changed_files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ M assets/toolbox/sprites/js/index.js
M docs_build/dev/reports/playwright_v8_coverage_report.txt
M tests/playwright/tools/SpritesToolShell.spec.mjs
M toolbox/sprites/index.html
?? docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search-branch-validation.md
?? docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search-manual-validation-notes.md
?? docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search-requirements-checklist.md
?? docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search-validation-lane.md
?? docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search.md
?? docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-branch-validation.md
?? docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-manual-validation-notes.md
?? docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-requirements-checklist.md
?? docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-validation-lane.md
?? docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection.md

# git ls-files --others --exclude-standard
docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search-branch-validation.md
docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search-manual-validation-notes.md
docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search-requirements-checklist.md
docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search-validation-lane.md
docs_build/dev/reports/PR_26177_CHARLIE_014-sprites-tags-categories-search.md
docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-branch-validation.md
docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-manual-validation-notes.md
docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-requirements-checklist.md
docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection-validation-lane.md
docs_build/dev/reports/PR_26177_CHARLIE_015-sprites-reference-protection.md

# git diff --stat
assets/toolbox/sprites/js/index.js | 151 ++++++++++++++++++++-
.../dev/reports/playwright_v8_coverage_report.txt | 4 +-
tests/playwright/tools/SpritesToolShell.spec.mjs | 71 ++++++++++
toolbox/sprites/index.html | 15 ++
4 files changed, 232 insertions(+), 9 deletions(-)
assets/toolbox/sprites/js/index.js | 63 +++++++++++++++++++-
.../dev/reports/playwright_v8_coverage_report.txt | 2 +-
tests/playwright/tools/SpritesToolShell.spec.mjs | 69 +++++++++++++++++++++-
toolbox/sprites/index.html | 9 +++
4 files changed, 138 insertions(+), 5 deletions(-)
Loading
Loading