Skip to content

Commit 2217270

Browse files
author
DavidQ
committed
Complete final V2 tool sweep with HTML-first shells and session-only runtime behavior - PR 11.199
1 parent d81c6c0 commit 2217270

9 files changed

Lines changed: 459 additions & 264 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# PR_11_199 Report
2+
3+
## V2 Directories Inspected
4+
- `tools/asset-browser-v2`
5+
- `tools/palette-manager-v2`
6+
- `tools/svg-asset-studio-v2`
7+
- `tools/tilemap-studio-v2`
8+
- `tools/vector-map-editor-v2`
9+
10+
## Files Changed
11+
- `tools/asset-browser-v2/index.html`
12+
- `tools/asset-browser-v2/index.js`
13+
- `tools/palette-manager-v2/index.html`
14+
- `tools/palette-manager-v2/index.js`
15+
- `tools/svg-asset-studio-v2/index.html`
16+
- `tools/svg-asset-studio-v2/index.js`
17+
- `tools/vector-map-editor-v2/index.html`
18+
- `tools/vector-map-editor-v2/index.js`
19+
- `docs/dev/reports/PR_11_199_report.md`
20+
21+
## Validation Commands Run
22+
- `node --check tools/asset-browser-v2/index.js`
23+
- `node --check tools/palette-manager-v2/index.js`
24+
- `node --check tools/svg-asset-studio-v2/index.js`
25+
- `node --check tools/vector-map-editor-v2/index.js`
26+
27+
## Validation Results
28+
- `node --check tools/asset-browser-v2/index.js`: **PASS** (exit code 0)
29+
- `node --check tools/palette-manager-v2/index.js`: **PASS** (exit code 0)
30+
- `node --check tools/svg-asset-studio-v2/index.js`: **PASS** (exit code 0)
31+
- `node --check tools/vector-map-editor-v2/index.js`: **PASS** (exit code 0)
32+
33+
## Manual Validation Results By Tool
34+
- `asset-browser-v2`: browser-interactive manual run not executed in this CLI-only session (no interactive browser in terminal tooling). Static checks by source inspection: header mount present, no-session empty state region present, malformed-session invalid state region present, valid/render region present, no banned JS `innerHTML` page construction.
35+
- `palette-manager-v2`: browser-interactive manual run not executed in this CLI-only session (no interactive browser in terminal tooling). Static checks by source inspection: header mount present, no-session empty state region present, malformed-session invalid state region present, valid/render region present, no banned JS `innerHTML` page construction.
36+
- `svg-asset-studio-v2`: browser-interactive manual run not executed in this CLI-only session (no interactive browser in terminal tooling). Static checks by source inspection: header mount present, no-session empty state region present, malformed-session invalid state region present, valid/render region present, no banned JS `innerHTML` page construction, URL payload writeback path removed.
37+
- `vector-map-editor-v2`: browser-interactive manual run not executed in this CLI-only session (no interactive browser in terminal tooling). Static checks by source inspection: header mount present, no-session empty state region present, malformed-session invalid state region present, valid/render region present, no banned JS `innerHTML` page construction, vector preview rendered via SVG DOM nodes.
38+
- `tilemap-studio-v2`: no code changes in this PR; existing V2 structure re-inspected and left unchanged.
39+
40+
## Full Smoke Decision
41+
- Full samples smoke was **skipped**. Reason: this PR is scoped to V2 tool HTML/JS only and does not modify shared sample infrastructure.
42+
43+
## Scope Guard Confirmation
44+
- No schemas changed.
45+
- No samples changed.
46+
- No games changed.
47+
- No Workspace Manager v1 files changed.
48+
- No `platformShell` files changed.
49+
- No `tools/shared/*` files changed.
50+
- No legacy tool directories changed.
51+
- No root `/index.html` changed.
52+
- No `tools/index.html` changed.

tools/asset-browser-v2/index.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ <h3>menuTool</h3>
2424
<section class="asset-browser-v2-panel" aria-live="polite">
2525
<h3 id="assetBrowserV2Title">No assets loaded</h3>
2626
<span id="assetBrowserV2Count" class="badge">0 assets</span>
27-
<div id="assetBrowserV2State">No asset catalog session data found. Open Asset Browser V2 with a valid hostContextId session.</div>
28-
<pre id="assetBrowserV2Preview" aria-label="Asset Browser V2 preview"></pre>
27+
<div id="assetBrowserV2EmptyState">No asset catalog session data found. Open Asset Browser V2 with a valid hostContextId session.</div>
28+
<div id="assetBrowserV2InvalidState" hidden>Asset Browser V2 session data is invalid. Re-open the tool from a valid host session.</div>
29+
<div id="assetBrowserV2ValidState" hidden>
30+
<div id="assetBrowserV2State">Asset Browser V2 loaded the session asset catalog.</div>
31+
<pre id="assetBrowserV2Preview" aria-label="Asset Browser V2 preview"></pre>
32+
</div>
2933
</section>
3034
<aside class="asset-browser-v2-panel" data-menu-workspace>
3135
<h3>menuWorkspace</h3>

tools/asset-browser-v2/index.js

Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
class AssetBrowserV2 {
22
constructor() {
3-
console.log("[ASSET_BROWSER_V2_ENTRY]");
4-
this.assets = [];
5-
this.start();
6-
}
7-
8-
start() {
3+
console.log("[AssetBrowserV2]");
94
document.title = "Asset Browser V2";
105
document.body.dataset.toolId = "asset-browser-v2";
11-
this.bindAssetSelection();
126
this.readSession();
137
}
148

159
readSession() {
1610
console.log("[SESSION_CONTEXT_READ]");
1711
try {
1812
if (!new URL(window.location.href).searchParams.get("hostContextId")) {
19-
this.renderEmpty("No hostContextId was provided. Open Asset Browser V2 with a valid Tool V2 session URL.");
13+
this.renderMissing("No hostContextId was provided. Re-open Asset Browser V2 from a valid Tool V2 session link.");
2014
return;
2115
}
22-
if (!window.sessionStorage.getItem(`toolboxaid.toolHost.context.${new URL(window.location.href).searchParams.get("hostContextId")}`)) {
23-
this.renderEmpty("No session context was found for the provided hostContextId.");
16+
if (
17+
!window.sessionStorage.getItem(
18+
`toolboxaid.toolHost.context.${new URL(window.location.href).searchParams.get("hostContextId")}`
19+
)
20+
) {
21+
this.renderMissing("No session context was found for the provided hostContextId.");
2422
return;
2523
}
26-
this.loadContract(JSON.parse(window.sessionStorage.getItem(`toolboxaid.toolHost.context.${new URL(window.location.href).searchParams.get("hostContextId")}`)));
24+
this.loadContract(
25+
JSON.parse(
26+
window.sessionStorage.getItem(
27+
`toolboxaid.toolHost.context.${new URL(window.location.href).searchParams.get("hostContextId")}`
28+
)
29+
)
30+
);
2731
} catch (error) {
2832
this.renderError(`Unable to read Asset Browser V2 session context: ${error instanceof Error ? error.message : "unknown error"}`);
2933
}
@@ -36,96 +40,113 @@ class AssetBrowserV2 {
3640
return;
3741
}
3842
if (!sessionContext.payloadJson || typeof sessionContext.payloadJson !== "object" || Array.isArray(sessionContext.payloadJson)) {
39-
this.renderError("Asset catalog session data is invalid. Expected payloadJson only.");
43+
this.renderError("Asset Browser V2 session data is invalid. Expected payloadJson only.");
4044
return;
4145
}
4246
if (!sessionContext.payloadJson.assetCatalog || typeof sessionContext.payloadJson.assetCatalog !== "object" || Array.isArray(sessionContext.payloadJson.assetCatalog)) {
43-
this.renderError("Asset catalog session data is invalid. Expected payloadJson.assetCatalog.");
47+
this.renderError("Asset Browser V2 session data is invalid. Expected payloadJson.assetCatalog.");
4448
return;
4549
}
4650
this.renderCatalog(sessionContext.payloadJson.assetCatalog, sessionContext);
4751
}
4852

4953
renderCatalog(assetCatalog, sessionContext) {
5054
if (typeof assetCatalog.name !== "string" || !assetCatalog.name.trim()) {
51-
this.renderError("Asset catalog session data is invalid. Expected assetCatalog.name.");
55+
this.renderError("Asset Browser V2 session data is invalid. Expected assetCatalog.name.");
5256
return;
5357
}
5458
if (!Array.isArray(assetCatalog.entries)) {
55-
this.renderError("Asset catalog session data is invalid. Expected assetCatalog.entries[].");
56-
return;
57-
}
58-
if (assetCatalog.entries.length === 0) {
59-
this.assets = [];
60-
document.getElementById("assetBrowserV2SessionReadout").textContent = `Session: loaded\nContext: ${new URL(window.location.href).searchParams.get("hostContextId")}\nTool: ${typeof sessionContext.toolId === "string" && sessionContext.toolId.trim() ? sessionContext.toolId.trim() : "not provided"}`;
61-
document.getElementById("assetBrowserV2ContractReadout").textContent = "payloadJson loaded\npayloadJson.assetCatalog valid\nentries[] valid but empty";
62-
document.getElementById("assetBrowserV2WorkspaceReadout").textContent = "Workspace session context was read. Workspace writes are deferred for this isolated V2 entry.";
63-
document.getElementById("assetBrowserV2Title").textContent = assetCatalog.name.trim();
64-
document.getElementById("assetBrowserV2Count").textContent = "0 assets";
65-
document.getElementById("assetBrowserV2State").textContent = "Asset Browser V2 loaded a valid session asset catalog with zero entries. Add explicit entries to assetCatalog.entries[].";
66-
document.getElementById("assetBrowserV2List").innerHTML = "";
67-
document.getElementById("assetBrowserV2Preview").textContent = "";
59+
this.renderError("Asset Browser V2 session data is invalid. Expected assetCatalog.entries[].");
6860
return;
6961
}
70-
if (assetCatalog.entries.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.id !== "string" || !entry.id.trim() || typeof entry.label !== "string" || !entry.label.trim() || typeof entry.kind !== "string" || !entry.kind.trim() || typeof entry.path !== "string" || !entry.path.trim())) {
71-
this.renderError("Asset catalog session data is invalid. Every entry requires id, label, kind, and path.");
62+
if (
63+
assetCatalog.entries.some(
64+
(entry) =>
65+
!entry ||
66+
typeof entry !== "object" ||
67+
Array.isArray(entry) ||
68+
typeof entry.id !== "string" ||
69+
!entry.id.trim() ||
70+
typeof entry.label !== "string" ||
71+
!entry.label.trim() ||
72+
typeof entry.kind !== "string" ||
73+
!entry.kind.trim() ||
74+
typeof entry.path !== "string" ||
75+
!entry.path.trim()
76+
)
77+
) {
78+
this.renderError("Asset Browser V2 session data is invalid. Every entry requires id, label, kind, and path.");
7279
return;
7380
}
74-
this.assets = assetCatalog.entries.map((entry) => ({
75-
id: entry.id.trim(),
76-
label: entry.label.trim(),
77-
kind: entry.kind.trim(),
78-
path: entry.path.trim()
79-
}));
81+
8082
document.getElementById("assetBrowserV2SessionReadout").textContent = `Session: loaded\nContext: ${new URL(window.location.href).searchParams.get("hostContextId")}\nTool: ${typeof sessionContext.toolId === "string" && sessionContext.toolId.trim() ? sessionContext.toolId.trim() : "not provided"}`;
8183
document.getElementById("assetBrowserV2ContractReadout").textContent = "payloadJson loaded\npayloadJson.assetCatalog valid\nentries[] valid";
8284
document.getElementById("assetBrowserV2WorkspaceReadout").textContent = "Workspace session context was read. Workspace writes are deferred for this isolated V2 entry.";
8385
document.getElementById("assetBrowserV2Title").textContent = assetCatalog.name.trim();
84-
document.getElementById("assetBrowserV2Count").textContent = `${this.assets.length} asset${this.assets.length === 1 ? "" : "s"}`;
85-
document.getElementById("assetBrowserV2State").textContent = "Asset Browser V2 loaded the session asset catalog.";
86-
document.getElementById("assetBrowserV2List").innerHTML = this.assets.map((entry) => `<button type="button" data-asset-id="${this.escapeHtml(entry.id)}"><strong>${this.escapeHtml(entry.label)}</strong><br><span>${this.escapeHtml(entry.kind)} | ${this.escapeHtml(entry.path)}</span></button>`).join("");
87-
document.getElementById("assetBrowserV2Preview").textContent = "Select an asset entry to inspect its session-backed metadata.";
88-
}
86+
document.getElementById("assetBrowserV2Count").textContent = `${assetCatalog.entries.length} asset${assetCatalog.entries.length === 1 ? "" : "s"}`;
87+
document.getElementById("assetBrowserV2State").textContent = assetCatalog.entries.length === 0
88+
? "Asset Browser V2 loaded a valid session asset catalog with zero entries."
89+
: "Asset Browser V2 loaded the session asset catalog.";
90+
document.getElementById("assetBrowserV2EmptyState").hidden = true;
91+
document.getElementById("assetBrowserV2InvalidState").hidden = true;
92+
document.getElementById("assetBrowserV2ValidState").hidden = false;
8993

90-
bindAssetSelection() {
91-
document.getElementById("assetBrowserV2List").addEventListener("click", (event) => {
92-
if (!(event.target instanceof Element) || !event.target.closest("[data-asset-id]")) {
93-
return;
94-
}
95-
if (!this.assets.some((entry) => entry.id === event.target.closest("[data-asset-id]").dataset.assetId)) {
96-
return;
97-
}
98-
document.getElementById("assetBrowserV2Preview").textContent = JSON.stringify(this.assets.find((entry) => entry.id === event.target.closest("[data-asset-id]").dataset.assetId), null, 2);
94+
document.getElementById("assetBrowserV2List").replaceChildren();
95+
assetCatalog.entries.forEach((entry) => {
96+
const assetItem = document.createElement("button");
97+
const assetName = document.createElement("strong");
98+
const assetMeta = document.createElement("div");
99+
assetItem.type = "button";
100+
assetName.textContent = entry.label.trim();
101+
assetMeta.textContent = `${entry.kind.trim()} | ${entry.path.trim()}`;
102+
assetItem.append(assetName, assetMeta);
103+
assetItem.addEventListener("click", () => {
104+
document.getElementById("assetBrowserV2Preview").textContent = JSON.stringify(
105+
{
106+
id: entry.id.trim(),
107+
label: entry.label.trim(),
108+
kind: entry.kind.trim(),
109+
path: entry.path.trim()
110+
},
111+
null,
112+
2
113+
);
114+
});
115+
document.getElementById("assetBrowserV2List").appendChild(assetItem);
99116
});
117+
118+
document.getElementById("assetBrowserV2Preview").textContent = assetCatalog.entries.length === 0
119+
? "No assets are available in this session catalog."
120+
: "Select an asset entry to inspect its session metadata.";
100121
}
101122

102-
renderEmpty(message) {
103-
this.assets = [];
123+
renderMissing(message) {
104124
document.getElementById("assetBrowserV2SessionReadout").textContent = "Session: missing";
105125
document.getElementById("assetBrowserV2ContractReadout").textContent = "payloadJson.assetCatalog not loaded";
106126
document.getElementById("assetBrowserV2WorkspaceReadout").textContent = "Workspace session context is not available.";
107127
document.getElementById("assetBrowserV2Title").textContent = "No assets loaded";
108128
document.getElementById("assetBrowserV2Count").textContent = "0 assets";
109-
document.getElementById("assetBrowserV2State").textContent = message;
110-
document.getElementById("assetBrowserV2List").innerHTML = "";
129+
document.getElementById("assetBrowserV2EmptyState").textContent = message;
130+
document.getElementById("assetBrowserV2EmptyState").hidden = false;
131+
document.getElementById("assetBrowserV2InvalidState").hidden = true;
132+
document.getElementById("assetBrowserV2ValidState").hidden = true;
133+
document.getElementById("assetBrowserV2List").replaceChildren();
111134
document.getElementById("assetBrowserV2Preview").textContent = "";
112135
}
113136

114137
renderError(message) {
115-
this.assets = [];
116138
document.getElementById("assetBrowserV2SessionReadout").textContent = "Session: read attempted";
117139
document.getElementById("assetBrowserV2ContractReadout").textContent = "payloadJson.assetCatalog invalid";
118140
document.getElementById("assetBrowserV2WorkspaceReadout").textContent = "Workspace writes are disabled for invalid Asset Browser V2 session data.";
119141
document.getElementById("assetBrowserV2Title").textContent = "Asset Browser V2 error";
120142
document.getElementById("assetBrowserV2Count").textContent = "0 assets";
121-
document.getElementById("assetBrowserV2State").textContent = message;
122-
document.getElementById("assetBrowserV2List").innerHTML = "";
143+
document.getElementById("assetBrowserV2InvalidState").textContent = `${message} Re-open Asset Browser V2 from a host session that provides payloadJson.assetCatalog.`;
144+
document.getElementById("assetBrowserV2EmptyState").hidden = true;
145+
document.getElementById("assetBrowserV2InvalidState").hidden = false;
146+
document.getElementById("assetBrowserV2ValidState").hidden = true;
147+
document.getElementById("assetBrowserV2List").replaceChildren();
123148
document.getElementById("assetBrowserV2Preview").textContent = "";
124149
}
125-
126-
escapeHtml(value) {
127-
return String(value).replace(/[&<>"]/g, (character) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;" }[character]));
128-
}
129150
}
130151

131152
new AssetBrowserV2();

tools/palette-manager-v2/index.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ <h3>menuTool</h3>
2323
<section class="palette-manager-v2-panel" aria-live="polite">
2424
<h3 id="paletteManagerName">No palette loaded</h3>
2525
<span id="paletteManagerCount" class="badge palette-manager-v2-count">0 colors</span>
26-
<div id="paletteManagerState" class="palette-manager-v2-state">No palette session data found. Open Palette Manager V2 with a valid hostContextId session.</div>
27-
<div id="paletteManagerSwatches" class="palette-manager-v2-swatches" aria-label="Palette Manager V2 swatches"></div>
26+
<div id="paletteManagerEmptyState" class="palette-manager-v2-state">No palette session data found. Open Palette Manager V2 with a valid hostContextId session.</div>
27+
<div id="paletteManagerInvalidState" class="palette-manager-v2-state palette-manager-v2-state--error" hidden>Palette Manager V2 session data is invalid. Re-open the tool from a valid host session.</div>
28+
<div id="paletteManagerValidState" hidden>
29+
<div id="paletteManagerState" class="palette-manager-v2-state">Palette Manager V2 loaded the session palette.</div>
30+
<div id="paletteManagerSwatches" class="palette-manager-v2-swatches" aria-label="Palette Manager V2 swatches"></div>
31+
</div>
2832
</section>
2933
<aside class="palette-manager-v2-panel" data-menu-workspace>
3034
<h3>menuWorkspace</h3>

0 commit comments

Comments
 (0)