Skip to content

Commit 64a807d

Browse files
author
DavidQ
committed
Complete Tilemap Studio V2 with HTML-first shell and session-only behavior - PR 11.198
1 parent a3b4d1d commit 64a807d

5 files changed

Lines changed: 198 additions & 93 deletions

File tree

docs/dev/codex_commands.md

Lines changed: 79 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,94 @@
1-
# Codex Commands — PR_11_197B
1+
MODEL: gpt-5.3-codex
2+
REASONING: medium
23

3-
Model: GPT-5.4-codex
4-
Reasoning: high
4+
# PR_11_198 — Tilemap Studio V2 Completion + Validation
55

66
## Execute
7-
8-
Use this PR as a Codex implementation task. Do not ask questions. Make the smallest scoped valid change.
9-
10-
### Required Task
11-
Complete Asset Browser V2 as the testable implementation target and bundle it with V2 validation hardening.
12-
13-
### Scope Lock
14-
Only edit files required for:
15-
- `tools/asset-browser-v2/index.html`
16-
- `tools/asset-browser-v2/index.js`
17-
- narrowly scoped V2 validation/test files if needed
18-
- docs/dev/reports evidence
19-
- docs/dev/roadmaps/MASTER_ROADMAP_ENGINE.md status-only marker change if execution-backed
20-
21-
Do not edit schemas, samples, games, Workspace Manager v1, platformShell, or `tools/shared/*`.
22-
23-
### Implementation Rules
24-
- Re-engineer the tool. Do not copy/paste legacy Asset Browser code.
25-
- `index.html` owns static shell, CSS links, header mount, layout, and DOM nodes.
26-
- `index.js` owns behavior only.
27-
- Use `data-tool-id="asset-browser-v2"`.
28-
- Header mount must be `<div id="shared-theme-header"></div>`.
29-
- Use existing `src/engine/theme` and existing accordion styling where applicable.
30-
- Use two menu areas only if needed: `menuTool` and `menuWorkspace`.
31-
- Read session data only, using the established V2 hostContextId/session pattern.
32-
- Do not fetch, guess, synthesize, default, or fallback data.
33-
- Empty state and invalid state must be explicit and actionable.
34-
- No helper classes. Single class only.
35-
- No alias/pass-through variables.
36-
- No abstraction layers.
37-
38-
### Banned Patterns
39-
Reject your own diff if it includes:
40-
- `document.body.innerHTML` for page construction
41-
- `document.head.insertAdjacentHTML` for CSS/style injection
42-
- dynamic header script injection from JS
43-
- `platformShell`
44-
- `assetUsageIntegration`
45-
- `tools/shared/`
46-
- Workspace Manager v1 wiring
47-
- fallback/default/sample data
48-
- copied legacy code blocks
49-
50-
### Validation Commands
7+
Implement the smallest valid testable change for Tilemap Studio V2.
8+
9+
## Hard Boundaries
10+
- Codex writes implementation code.
11+
- Do not change schemas.
12+
- Do not change samples.
13+
- Do not change games.
14+
- Do not touch Workspace Manager v1.
15+
- Do not patch legacy tools.
16+
- Do not use platformShell.
17+
- Do not use tools/shared except the explicitly required theme/header mount path already used by the repo theme system.
18+
- Do not copy old tool code. Re-engineer the V2 tool.
19+
20+
## Required Files To Inspect/Edit
21+
- tools/tilemap-studio-v2/index.html
22+
- tools/tilemap-studio-v2/index.js
23+
24+
If either file does not exist, create only the missing file required for this tool.
25+
26+
## Implementation Rules
27+
1. `tools/tilemap-studio-v2/index.html` must own the static shell:
28+
- include theme CSS
29+
- include `<div id="shared-theme-header"></div>`
30+
- include static page shell/root container
31+
- include static menuTool section
32+
- include static menuWorkspace section
33+
- include `../../src/engine/theme/mount-shared-header.js`
34+
- include `./index.js`
35+
36+
2. `tools/tilemap-studio-v2/index.js` must be behavior-only:
37+
- single class
38+
- no helper classes
39+
- no alias/pass-through variables
40+
- no full-page `innerHTML` construction
41+
- no CSS injection
42+
- no dynamic header injection
43+
- read session only
44+
- update existing DOM nodes only
45+
- handle missing, invalid, and valid session states
46+
47+
3. Enforce naming:
48+
- visible name: `Tilemap Studio V2`
49+
- `document.title`: `Tilemap Studio V2`
50+
- `data-tool-id`: `tilemap-studio-v2`
51+
52+
4. Session rules:
53+
- no fallback data
54+
- no defaults
55+
- no fetch
56+
- no guessed payloads
57+
- no hidden samples
58+
59+
## Validation Commands
5160
Run targeted validation only:
5261

53-
1. Syntax checks for changed JS files.
54-
2. Static checks for V2 shell compliance:
55-
- Asset Browser V2 `index.html` includes `shared-theme-header`.
56-
- Asset Browser V2 `index.js` does not include `document.body.innerHTML`.
57-
- Asset Browser V2 `index.js` does not include `document.head.insertAdjacentHTML`.
58-
- Asset Browser V2 references `asset-browser-v2`.
59-
3. Manual/UAT or lightweight browser validation evidence for:
60-
- direct open empty state
61-
- invalid session state
62-
- valid session state render
63-
- shared header visible
62+
```powershell
63+
node --check tools/tilemap-studio-v2/index.js
64+
```
6465

65-
Do not run full samples smoke unless a broad shared sample loader/framework file is changed. If skipped, document why.
66+
Manual validation:
67+
- Open `tools/tilemap-studio-v2/index.html`.
68+
- Confirm shared header renders in `#shared-theme-header`.
69+
- Confirm missing session shows clear actionable state.
70+
- Confirm valid session renders tilemap content.
71+
- Confirm browser console has no errors.
6672

67-
### Evidence
68-
Write results to:
73+
## Evidence Report
74+
Create or update:
6975

70-
`docs/dev/reports/PR_11_197B_v2_asset_browser_validation.md`
76+
```text
77+
docs/dev/reports/PR_11_198_report.md
78+
```
7179

72-
Include:
80+
Report must include:
7381
- files changed
7482
- validation commands run
7583
- pass/fail results
76-
- full samples smoke skipped/running decision and reason
77-
- screenshots/log snippets if available
84+
- manual test notes
85+
- statement that full samples smoke was skipped and why
7886

79-
### Final Artifact
80-
Create final ZIP at:
87+
## Local ZIP Output
88+
After validation, Codex must create:
8189

82-
`tmp/PR_11_197B.zip`
90+
```text
91+
<project folder>/tmp/PR_11_198.zip
92+
```
8393

84-
The ZIP must preserve repo-relative structure and include implementation changes and evidence.
94+
The ZIP must preserve repo-relative structure and include the final changed files plus docs/dev evidence.

docs/dev/commit_comment.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Complete Asset Browser V2 and harden V2 validation with targeted evidence - PR 11.197B
1+
Complete Tilemap Studio V2 with HTML-first shell and session-only behavior - PR 11.198
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# PR_11_198 Report
2+
3+
## Files Changed
4+
- `tools/tilemap-studio-v2/index.js`
5+
- `docs/dev/reports/PR_11_198_report.md`
6+
7+
## Validation Commands Run
8+
- `node --check tools/tilemap-studio-v2/index.js`
9+
10+
## Validation Results
11+
- `node --check tools/tilemap-studio-v2/index.js`: **PASS** (exit code 0)
12+
13+
## Manual Test Notes
14+
- Open `tools/tilemap-studio-v2/index.html`: not executed in this CLI-only run (no interactive browser session available in terminal tooling).
15+
- Shared header mount target check (`#shared-theme-header` exists in HTML shell): **PASS** by static source inspection.
16+
- Missing session actionable state handling: **PASS** by source inspection of `renderMissing(...)`.
17+
- Valid session tilemap render path: **PASS** by source inspection of `renderTilemap(...)`.
18+
- Console error-free browser run: not executed in this CLI-only run (requires manual browser verification).
19+
20+
## Samples Smoke Statement
21+
- Full samples smoke was skipped because this PR is scoped to `tools/tilemap-studio-v2` behavior-only changes and does not modify samples, games, schemas, or shared engine runtime contracts.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# PR_11_198 — Tilemap Studio V2 Completion + Validation
2+
3+
## Purpose
4+
Complete Tilemap Studio V2 as a testable V2 re-engineered tool while enforcing HTML-first shell, session-only runtime behavior, and shared-theme header compliance.
5+
6+
## Scope
7+
- Tilemap Studio V2 only.
8+
- Codex writes implementation code.
9+
- ChatGPT bundle supplies PR docs, Codex commands, commit comment, and report requirements only.
10+
- No schema changes.
11+
- No sample changes.
12+
- No game changes.
13+
- No Workspace Manager v1 work.
14+
- No legacy tool patching.
15+
- No platformShell or tools/shared coupling.
16+
17+
## Required Architecture
18+
- `tools/tilemap-studio-v2/index.html` owns the static shell.
19+
- `tools/tilemap-studio-v2/index.js` owns behavior only.
20+
- Tool reads session-backed data only.
21+
- Tool does not fetch, guess, default, or fallback.
22+
- Tool name and visible title must end with `V2`.
23+
- Header must mount through `<div id="shared-theme-header"></div>`.
24+
25+
## HTML-First Requirements
26+
`index.html` must contain:
27+
- theme CSS links
28+
- shared header mount
29+
- static app shell
30+
- static menuTool area
31+
- static menuWorkspace area
32+
- script includes for shared header mount and local `index.js`
33+
34+
`index.js` must not contain:
35+
- full-page `document.body.innerHTML` construction
36+
- `document.head.insertAdjacentHTML` stylesheet injection
37+
- inline `<style>` injection
38+
- dynamic header script injection
39+
- legacy imports
40+
- helper classes
41+
- alias/pass-through variables
42+
43+
## Testable Completion Criteria
44+
- Tilemap Studio V2 loads standalone.
45+
- Missing session shows a clear actionable empty/error state.
46+
- Valid session renders tilemap content.
47+
- Header renders from shared theme mount.
48+
- Browser console has no errors during load.
49+
- `node --check tools/tilemap-studio-v2/index.js` passes.
50+
51+
## Full Samples Smoke Test Decision
52+
Do not run full samples smoke by default. This PR is scoped to one V2 tool. Run targeted syntax and manual Tilemap Studio V2 checks only unless Codex changes shared loaders/frameworks.

tools/tilemap-studio-v2/index.js

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
11
class TilemapStudioV2 {
22
constructor() {
3-
console.log("[TILEMAP_V2_ENTRY]");
4-
this.start();
5-
}
6-
7-
start() {
83
document.title = "Tilemap Studio V2";
94
document.body.dataset.toolId = "tilemap-studio-v2";
105
this.readSession();
116
}
127

138
readSession() {
14-
console.log("[SESSION_CONTEXT_READ]");
159
try {
1610
if (!new URL(window.location.href).searchParams.get("hostContextId")) {
17-
this.renderEmpty("No hostContextId was provided. Open Tilemap Studio V2 with a valid Tool V2 session URL.");
11+
this.renderMissing("No hostContextId was provided. Re-open Tilemap Studio V2 from a valid Tool V2 session link.");
1812
return;
1913
}
20-
if (!window.sessionStorage.getItem(`toolboxaid.toolHost.context.${new URL(window.location.href).searchParams.get("hostContextId")}`)) {
21-
this.renderEmpty("No session context was found for the provided hostContextId.");
14+
if (
15+
!window.sessionStorage.getItem(
16+
`toolboxaid.toolHost.context.${new URL(window.location.href).searchParams.get("hostContextId")}`
17+
)
18+
) {
19+
this.renderMissing("No session context was found for the provided hostContextId.");
2220
return;
2321
}
24-
this.loadContract(JSON.parse(window.sessionStorage.getItem(`toolboxaid.toolHost.context.${new URL(window.location.href).searchParams.get("hostContextId")}`)));
22+
this.loadContract(
23+
JSON.parse(
24+
window.sessionStorage.getItem(
25+
`toolboxaid.toolHost.context.${new URL(window.location.href).searchParams.get("hostContextId")}`
26+
)
27+
)
28+
);
2529
} catch (error) {
2630
this.renderError(`Unable to read Tilemap Studio V2 session context: ${error instanceof Error ? error.message : "unknown error"}`);
2731
}
2832
}
2933

3034
loadContract(sessionContext) {
31-
console.log("[TILEMAP_V2_CONTRACT_LOADED]");
3235
if (!sessionContext || typeof sessionContext !== "object" || Array.isArray(sessionContext)) {
3336
this.renderError("Session context is invalid. Expected an object containing payloadJson.tileMapDocument.");
3437
return;
@@ -62,7 +65,7 @@ class TilemapStudioV2 {
6265
return;
6366
}
6467
if (tileMapDocument.layers.length === 0) {
65-
this.renderEmpty("Tilemap Studio V2 loaded a valid tilemap document with zero layers.");
68+
this.renderMissing("Tilemap Studio V2 loaded a valid tilemap document with zero layers.");
6669
return;
6770
}
6871
if (tileMapDocument.layers.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.name !== "string" || !entry.name.trim() || typeof entry.kind !== "string" || !entry.kind.trim() || !Array.isArray(entry.data))) {
@@ -75,19 +78,42 @@ class TilemapStudioV2 {
7578
document.getElementById("tilemapV2Name").textContent = tileMapDocument.map.name.trim();
7679
document.getElementById("tilemapV2Count").textContent = `${tileMapDocument.layers.length} layer${tileMapDocument.layers.length === 1 ? "" : "s"}`;
7780
document.getElementById("tilemapV2State").textContent = "Tilemap Studio V2 loaded the session tilemap.";
78-
document.getElementById("tilemapV2LayerList").innerHTML = tileMapDocument.layers.map((entry) => `<li><strong>${this.escapeHtml(entry.name.trim())}</strong><br>${this.escapeHtml(entry.kind.trim())} - ${entry.data.length} row${entry.data.length === 1 ? "" : "s"}</li>`).join("");
79-
document.getElementById("tilemapV2Preview").innerHTML = `<pre>${this.escapeHtml(JSON.stringify({ map: tileMapDocument.map, layers: tileMapDocument.layers.map((entry) => ({ name: entry.name, kind: entry.kind, rows: entry.data.length })) }, null, 2))}</pre>`;
81+
document.getElementById("tilemapV2LayerList").replaceChildren();
82+
tileMapDocument.layers.forEach((entry) => {
83+
const layerItem = document.createElement("li");
84+
const layerName = document.createElement("strong");
85+
const layerKind = document.createElement("div");
86+
layerName.textContent = entry.name.trim();
87+
layerKind.textContent = `${entry.kind.trim()} - ${entry.data.length} row${entry.data.length === 1 ? "" : "s"}`;
88+
layerItem.append(layerName, layerKind);
89+
document.getElementById("tilemapV2LayerList").appendChild(layerItem);
90+
});
91+
document.getElementById("tilemapV2Preview").replaceChildren();
92+
const tilemapPreview = document.createElement("pre");
93+
tilemapPreview.textContent = JSON.stringify(
94+
{
95+
map: tileMapDocument.map,
96+
layers: tileMapDocument.layers.map((entry) => ({
97+
name: entry.name,
98+
kind: entry.kind,
99+
rows: entry.data.length
100+
}))
101+
},
102+
null,
103+
2
104+
);
105+
document.getElementById("tilemapV2Preview").appendChild(tilemapPreview);
80106
}
81107

82-
renderEmpty(message) {
108+
renderMissing(message) {
83109
document.getElementById("tilemapV2SessionReadout").textContent = "Session: missing";
84110
document.getElementById("tilemapV2ContractReadout").textContent = "payloadJson.tileMapDocument not loaded";
85111
document.getElementById("tilemapV2WorkspaceReadout").textContent = "Workspace session context is not available.";
86112
document.getElementById("tilemapV2Name").textContent = "No tilemap loaded";
87113
document.getElementById("tilemapV2Count").textContent = "0 layers";
88114
document.getElementById("tilemapV2State").textContent = message;
89-
document.getElementById("tilemapV2LayerList").innerHTML = "";
90-
document.getElementById("tilemapV2Preview").innerHTML = "";
115+
document.getElementById("tilemapV2LayerList").replaceChildren();
116+
document.getElementById("tilemapV2Preview").replaceChildren();
91117
}
92118

93119
renderError(message) {
@@ -97,12 +123,8 @@ class TilemapStudioV2 {
97123
document.getElementById("tilemapV2Name").textContent = "Tilemap Studio V2 error";
98124
document.getElementById("tilemapV2Count").textContent = "0 layers";
99125
document.getElementById("tilemapV2State").textContent = message;
100-
document.getElementById("tilemapV2LayerList").innerHTML = "";
101-
document.getElementById("tilemapV2Preview").innerHTML = "";
102-
}
103-
104-
escapeHtml(value) {
105-
return String(value).replace(/[&<>"]/g, (character) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;" }[character]));
126+
document.getElementById("tilemapV2LayerList").replaceChildren();
127+
document.getElementById("tilemapV2Preview").replaceChildren();
106128
}
107129
}
108130

0 commit comments

Comments
 (0)