Skip to content

Commit 1eb8bfc

Browse files
author
DavidQ
committed
Bundle Workspace V2 session UX stabilization and state consistency fixes - PR_11_263
1 parent 27baaca commit 1eb8bfc

5 files changed

Lines changed: 313 additions & 6 deletions
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# PR_11_263 Session UX Stabilization Report
2+
3+
## Scope
4+
Workspace V2 session library / diff / merge / delete / refresh UX only.
5+
6+
## Files Changed
7+
- tools/workspace-v2/index.js
8+
- tests/runtime/V2SessionUxStabilization.test.mjs
9+
- docs/pr/PLAN_PR_11_263_WORKSPACE_V2_SESSION_UX_STABILIZATION_BUNDLE.md
10+
- docs/pr/BUILD_PR_11_263_WORKSPACE_V2_SESSION_UX_STABILIZATION_BUNDLE.md
11+
12+
## Implementation Summary
13+
- Added `updateSessionLibraryActionState()` as centralized enablement wiring for session library actions.
14+
- Wired library action-state updates to:
15+
- session-id input edits
16+
- startup initialization
17+
- library render
18+
- refresh action
19+
- programmatic session-id fills from row actions
20+
- Updated refresh flow to rerender both library and history, re-evaluate button state, and show current refresh status.
21+
- Normalized current-state status text:
22+
- Diff enabled text: `Compute Diff is enabled.`
23+
- Merge enabled texts:
24+
- `Preview Merge is enabled.`
25+
- `Confirm Preview is enabled.`
26+
- `Apply Merge is enabled.`
27+
- Confirm summary text:
28+
- `Preview confirmed. Apply Merge is enabled.`
29+
- Merged-session availability text:
30+
- `Merged session is available for save.`
31+
- Kept existing stale merge-state clearing behavior from prior PRs intact.
32+
33+
## Validation Commands
34+
1. `node --check tools/workspace-v2/index.js`
35+
- PASS
36+
2. `node --check tests/runtime/V2SessionUxStabilization.test.mjs`
37+
- PASS
38+
3. `node tests/runtime/V2SessionUxStabilization.test.mjs`
39+
- PASS
40+
- Results file: `tmp/v2-session-ux-stabilization-results.json`
41+
- Failures: `[]`
42+
43+
## Targeted Validation Coverage
44+
- session library actions disabled when session input is empty
45+
- session library actions enabled when session input is present
46+
- refresh action consistency across library/history/session action-state
47+
- merge enable-state messaging reflects current state only
48+
- diff enable-state messaging reflects current state only
49+
- deprecated hint/future wording removed from stabilized session UX text
50+
51+
## Full Samples Smoke Decision
52+
- Skipped full samples smoke test.
53+
- Reason: PR scope is limited to Workspace V2 session UX state wiring and targeted runtime validation only.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# BUILD_PR_11_263_WORKSPACE_V2_SESSION_UX_STABILIZATION_BUNDLE
2+
3+
## Purpose
4+
Implement a single Workspace V2 UX stabilization bundle for session library/diff/merge/delete/refresh consistency.
5+
6+
## Files
7+
- tools/workspace-v2/index.js
8+
- tests/runtime/V2SessionUxStabilization.test.mjs
9+
- docs/dev/reports/PR_11_263_session_ux_stabilization_report.md
10+
11+
## Implementation
12+
1. Add `updateSessionLibraryActionState()` and wire it to:
13+
- session input changes
14+
- initial load
15+
- session library render
16+
- refresh flow
17+
- programmatic session-id assignments
18+
2. Normalize refresh behavior from the session refresh control:
19+
- rerender library + history
20+
- rerun action-state wiring
21+
- set current-state refresh message
22+
3. Normalize current-state enable text (remove hint/future phrasing):
23+
- Diff: `Compute Diff is enabled.`
24+
- Merge: `Preview Merge is enabled.` / `Confirm Preview is enabled.` / `Apply Merge is enabled.`
25+
4. Update merged-session availability text to current-state wording.
26+
27+
## Acceptance
28+
- Session library actions disable when input is empty and enable when present.
29+
- Refresh keeps library/history/button states in sync.
30+
- Merge/diff status text reflects present state only.
31+
- No stale preview-state regressions introduced.
32+
33+
## Validation
34+
- node --check tools/workspace-v2/index.js
35+
- node --check tests/runtime/V2SessionUxStabilization.test.mjs
36+
- node tests/runtime/V2SessionUxStabilization.test.mjs
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# PLAN_PR_11_263_WORKSPACE_V2_SESSION_UX_STABILIZATION_BUNDLE
2+
3+
## Purpose
4+
Bundle Workspace V2 session UX stabilization fixes across library, diff, merge, delete, and refresh flows.
5+
6+
## Scope
7+
- tools/workspace-v2/index.js
8+
- tests/runtime/V2SessionUxStabilization.test.mjs
9+
- PR docs/report only
10+
11+
## Goals
12+
- Normalize session action button enable states
13+
- Normalize merge/diff enable-state text to current-state wording
14+
- Improve refresh consistency for library/history/session state
15+
- Keep stale merge state clearing consistent
16+
17+
## Out of Scope
18+
- No schema/sample/game/tool-wide changes
19+
- No UI redesign
20+
- No repo-wide cleanup
21+
22+
## Validation
23+
- node --check tools/workspace-v2/index.js
24+
- node --check tests/runtime/V2SessionUxStabilization.test.mjs
25+
- node tests/runtime/V2SessionUxStabilization.test.mjs
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import assert from "node:assert/strict";
2+
import fs from "node:fs";
3+
import path from "node:path";
4+
import { execFileSync } from "node:child_process";
5+
import { fileURLToPath, pathToFileURL } from "node:url";
6+
7+
const __filename = fileURLToPath(import.meta.url);
8+
const __dirname = path.dirname(__filename);
9+
const repoRoot = path.resolve(__dirname, "..", "..");
10+
const jsPath = path.join(repoRoot, "tools", "workspace-v2", "index.js");
11+
const resultsPath = path.join(repoRoot, "tmp", "v2-session-ux-stabilization-results.json");
12+
13+
function checkSyntax(filePath) {
14+
try {
15+
execFileSync(process.execPath, ["--check", filePath], {
16+
cwd: repoRoot,
17+
stdio: ["ignore", "pipe", "pipe"]
18+
});
19+
return { ok: true, error: "" };
20+
} catch (error) {
21+
return { ok: false, error: (error?.stderr || error?.stdout || error?.message || "").toString().trim() };
22+
}
23+
}
24+
25+
function libraryActionState(sessionName) {
26+
const hasSessionInput = Boolean(typeof sessionName === "string" && sessionName.trim());
27+
return {
28+
saveDisabled: !hasSessionInput,
29+
overwriteDisabled: !hasSessionInput,
30+
loadDisabled: !hasSessionInput,
31+
deleteDisabled: !hasSessionInput
32+
};
33+
}
34+
35+
function mergeEnableText({ canPreviewMerge, previewFresh, previewHasConflicts, previewConfirmed, previewExists }) {
36+
if (!canPreviewMerge) {
37+
return "Select two different sessions to enable Preview Merge.";
38+
}
39+
if (previewExists && !previewFresh) {
40+
return "Preview is stale. Run Preview Merge again.";
41+
}
42+
if (previewExists && previewHasConflicts) {
43+
return "Preview has conflicts. Resolve conflicts before applying.";
44+
}
45+
if (previewExists && previewConfirmed && previewFresh && !previewHasConflicts) {
46+
return "Apply Merge is enabled.";
47+
}
48+
if (previewExists && !previewConfirmed && previewFresh && !previewHasConflicts) {
49+
return "Confirm Preview is enabled.";
50+
}
51+
return "Preview Merge is enabled.";
52+
}
53+
54+
function diffEnableText(canRunDiff) {
55+
return canRunDiff ? "Compute Diff is enabled." : "Select two different sessions to enable Compute Diff.";
56+
}
57+
58+
export function run() {
59+
const failures = [];
60+
const jsExists = fs.existsSync(jsPath);
61+
const js = jsExists ? fs.readFileSync(jsPath, "utf8") : "";
62+
const jsSyntax = checkSyntax(jsPath);
63+
const testSyntax = checkSyntax(path.join(repoRoot, "tests", "runtime", "V2SessionUxStabilization.test.mjs"));
64+
65+
if (!jsExists) failures.push("Missing tools/workspace-v2/index.js.");
66+
if (!jsSyntax.ok) failures.push("tools/workspace-v2/index.js failed syntax check.");
67+
if (!testSyntax.ok) failures.push("tests/runtime/V2SessionUxStabilization.test.mjs failed syntax check.");
68+
69+
const requiredTokens = [
70+
"updateSessionLibraryActionState()",
71+
"this.sessionNameNode.addEventListener(\"input\", () => {",
72+
"this.renderSessionLibrary();",
73+
"this.renderSessionHistory();",
74+
"Workspace V2 session views refreshed.",
75+
"Compute Diff is enabled.",
76+
"Preview Merge is enabled.",
77+
"Confirm Preview is enabled.",
78+
"Apply Merge is enabled.",
79+
"Preview confirmed. Apply Merge is enabled.",
80+
"Merged session is available for save.",
81+
"clearMergePanelTransientState("
82+
];
83+
requiredTokens.forEach((token) => {
84+
if (!js.includes(token)) failures.push(`Missing PR_11_263 UX stabilization token/text: ${token}`);
85+
});
86+
87+
const removedTokens = [
88+
"Ready to compute diff.",
89+
"Ready to preview merge.",
90+
"Preview ready. Confirm to enable apply.",
91+
"Preview confirmed. Ready to apply merge.",
92+
"Merged session ready. Choose an ID and save if desired."
93+
];
94+
removedTokens.forEach((token) => {
95+
if (js.includes(token)) failures.push(`Deprecated/misleading hint text still present: ${token}`);
96+
});
97+
98+
const emptyInput = libraryActionState("");
99+
if (!emptyInput.saveDisabled || !emptyInput.overwriteDisabled || !emptyInput.loadDisabled || !emptyInput.deleteDisabled) {
100+
failures.push("Library actions should be disabled when session input is empty.");
101+
}
102+
const filledInput = libraryActionState("asset-browser-v2-123");
103+
if (filledInput.saveDisabled || filledInput.overwriteDisabled || filledInput.loadDisabled || filledInput.deleteDisabled) {
104+
failures.push("Library actions should be enabled when session input is present.");
105+
}
106+
107+
const mergeNoPreview = mergeEnableText({
108+
canPreviewMerge: true,
109+
previewFresh: false,
110+
previewHasConflicts: false,
111+
previewConfirmed: false,
112+
previewExists: false
113+
});
114+
if (mergeNoPreview !== "Preview Merge is enabled.") {
115+
failures.push("Merge enable text should reflect immediate current state when selection is valid and preview not present.");
116+
}
117+
const mergeReadyConfirm = mergeEnableText({
118+
canPreviewMerge: true,
119+
previewFresh: true,
120+
previewHasConflicts: false,
121+
previewConfirmed: false,
122+
previewExists: true
123+
});
124+
if (mergeReadyConfirm !== "Confirm Preview is enabled.") {
125+
failures.push("Merge enable text should indicate Confirm enablement for fresh conflict-free preview.");
126+
}
127+
const mergeReadyApply = mergeEnableText({
128+
canPreviewMerge: true,
129+
previewFresh: true,
130+
previewHasConflicts: false,
131+
previewConfirmed: true,
132+
previewExists: true
133+
});
134+
if (mergeReadyApply !== "Apply Merge is enabled.") {
135+
failures.push("Merge enable text should indicate Apply enablement after confirmed fresh preview.");
136+
}
137+
138+
if (diffEnableText(true) !== "Compute Diff is enabled.") {
139+
failures.push("Diff enable text should indicate immediate enabled state.");
140+
}
141+
142+
fs.mkdirSync(path.dirname(resultsPath), { recursive: true });
143+
fs.writeFileSync(resultsPath, `${JSON.stringify({
144+
generatedAt: new Date().toISOString(),
145+
failures,
146+
checks: { jsExists, jsSyntax, testSyntax },
147+
scenarios: {
148+
emptyInput,
149+
filledInput,
150+
mergeNoPreview,
151+
mergeReadyConfirm,
152+
mergeReadyApply,
153+
diffEnabled: diffEnableText(true)
154+
}
155+
}, null, 2)}\n`, "utf8");
156+
157+
console.log(`v2 session-ux-stabilization results: ${resultsPath}`);
158+
assert.equal(failures.length, 0, `V2 session-ux-stabilization failures: ${failures.join(" | ")}`);
159+
return { failures };
160+
}
161+
162+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
163+
try {
164+
const summary = run();
165+
console.log(JSON.stringify(summary, null, 2));
166+
} catch (error) {
167+
console.error(error);
168+
process.exitCode = 1;
169+
}
170+
}

0 commit comments

Comments
 (0)