Skip to content

Commit 407cf72

Browse files
author
DavidQ
committed
Level 18.2 Boundary Hardening (Overlay Slice)
- Enforced layer boundaries in overlay runtime - Removed cross-layer leakage - Maintained test pass status
1 parent 0b8482a commit 407cf72

9 files changed

Lines changed: 196 additions & 54 deletions

docs/dev/CODEX_COMMANDS.md

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
1-
MODEL: GPT-5.4
2-
REASONING: medium
3-
4-
COMMAND:
5-
Rebase progression to Level 18:
6-
- Confirm Level 17 is fully complete
7-
- Resume Level 18 runtime hardening
8-
- Do not modify prior completed levels
9-
- Update roadmap status only
1+
# Codex Command
2+
3+
MODEL: GPT-5.4-codex
4+
REASONING: high
5+
6+
Use the repository root as the working directory.
7+
8+
Implement `BUILD_PR_LEVEL_18_1_ENGINE_USAGE_ENFORCEMENT_AUDIT_SLICE` exactly as specified in `docs/pr/BUILD_PR_LEVEL_18_1_ENGINE_USAGE_ENFORCEMENT_AUDIT_SLICE.md`.
9+
10+
Requirements:
11+
- keep scope bounded to the overlay runtime hardening slice
12+
- do not scan or edit unrelated repo areas
13+
- migrate only clearly duplicated local logic to already-existing stable `src/engine` or `src/shared` surfaces
14+
- update or add only the smallest necessary tests
15+
- update roadmap status markers only for directly completed work
16+
- package the finished repo-structured ZIP to:
17+
`<project folder>/tmp/BUILD_PR_LEVEL_18_1_ENGINE_USAGE_ENFORCEMENT_AUDIT_SLICE.zip`
18+
19+
Output required in the ZIP:
20+
- implementation changes
21+
- updated roadmap status markers
22+
- any validation-backed test changes
23+
- `docs/dev/reports/change_summary.txt`
24+
- `docs/dev/reports/validation_checklist.txt`
25+
- `docs/dev/reports/file_tree.txt`

docs/dev/COMMIT_COMMENT.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
Rebase to Level 18 after confirming Level 17 completion.
2-
3-
- Resets progression starting point
4-
- Ensures correct roadmap alignment
1+
Level 18 hardening: audit bounded overlay runtime slice for engine/shared usage, remove local reimplementation where stable shared surfaces already exist, and add validation-backed enforcement
2+
BUILD_PR_LEVEL_18_1_ENGINE_USAGE_ENFORCEMENT_AUDIT_SLICE
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
Summary:
2-
This PR adds a testable multi-layer composition step for Level 19 overlays.
3-
It allows multiple gameplay-safe overlays to render together with deterministic ordering while preserving input safety and gameplay visibility.
1+
BUILD_PR_LEVEL_18_1_ENGINE_USAGE_ENFORCEMENT_AUDIT_SLICE
42

5-
Roadmap Impact:
6-
- Improves Level 19 with a concrete, testable composition milestone
7-
- Keeps roadmap handling status-only as required by the updated instructions
3+
Scope executed (bounded overlay runtime hardening slice):
4+
- Audited `samples/phase-17/shared/overlayGameplayRuntime.js` for local helper duplication against existing `src/shared` surfaces.
5+
- Migrated duplicated finite-number normalization usage from local helper `normalizePointerNumber` to shared `asFiniteNumber` from `src/shared/number/index.js`.
6+
- Removed the local duplicate helper and updated all in-slice pointer/gesture/layout call sites to use the shared helper.
7+
- Added enforcement coverage in `tests/runtime/Phase19OverlayExpansionFramework.test.mjs` to validate the overlay runtime slice imports shared number normalization and no longer defines the local duplicate helper.
8+
- Updated Level 18 Track A roadmap markers only for directly advanced bounded-slice progress.
9+
10+
No new features were added and no unrelated runtime/game/tool areas were modified.

docs/dev/reports/file_tree.txt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
docs/
2-
pr/
3-
BUILD_PR_LEVEL_17_52_DEBUG_OVERLAY_CYCLE_KEY_AND_SAMPLE_STACK_MAP.md
42
dev/
5-
codex_commands.md
6-
commit_comment.txt
3+
roadmaps/
4+
MASTER_ROADMAP_HIGH_LEVEL.md
75
reports/
86
change_summary.txt
9-
file_tree.txt
107
validation_checklist.txt
8+
file_tree.txt
9+
samples/
10+
phase-17/
11+
shared/
12+
overlayGameplayRuntime.js
13+
tests/
14+
runtime/
15+
Phase19OverlayExpansionFramework.test.mjs
Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
1-
[ ] Level 17 complete
2-
[ ] Baseline stable
3-
[ ] Level 18 ready to proceed
4-
[ ] Roadmap updated
1+
Validation checklist for Codex:
2+
- [x] Run targeted tests covering edited overlay runtime files
3+
Command: custom Node runner with alias hooks for:
4+
- `./tests/runtime/Phase19OverlayExpansionFramework.test.mjs`
5+
- `./tests/runtime/Phase17OverlayGameplayRuntimeIntegration.test.mjs`
6+
- `./tests/runtime/Phase17OverlayInputEdgeCases.test.mjs`
7+
Result: PASS all three tests.
8+
- [x] Run existing overlay integration tests impacted by edited imports
9+
Covered by:
10+
- `Phase19OverlayExpansionFramework.test.mjs` (includes pointer/gesture/runtime coverage and new enforcement assertion)
11+
- `Phase17OverlayGameplayRuntimeIntegration.test.mjs`
12+
- `Phase17OverlayInputEdgeCases.test.mjs`
13+
- [x] Confirm no unrelated files changed
14+
Changed implementation/test/roadmap files are limited to this audit slice plus required report artifacts.
15+
- [x] Confirm no gameplay behavior drift beyond duplicate-removal remediation
16+
Existing Phase17 and Phase19 overlay runtime integration tests passed after migration.
17+
- [x] Confirm roadmap wording unchanged except status markers
18+
Updated only marker states in Level 18 Track A items.
19+
- [x] Confirm ZIP written to `<project folder>/tmp/BUILD_PR_LEVEL_18_1_ENGINE_USAGE_ENFORCEMENT_AUDIT_SLICE.zip`

docs/dev/roadmaps/MASTER_ROADMAP_HIGH_LEVEL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,9 @@
722722
[ ] Document contracts
723723

724724
### Track A — Engine Usage Enforcement
725-
- [ ] verify all `samples/` use engine systems (no local reimplementation)
725+
- [.] verify all `samples/` use engine systems (no local reimplementation)
726726
- [ ] verify all `games/` use engine systems
727-
- [ ] migrate any local logic into engine/shared where appropriate
727+
- [.] migrate any local logic into engine/shared where appropriate
728728
- [ ] remove sample-specific logic from engine paths
729729

730730
### Track B — Boundary Hardening
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# BUILD_PR_LEVEL_18_1_ENGINE_USAGE_ENFORCEMENT_AUDIT_SLICE
2+
3+
## PR Purpose
4+
Create the first executable Level 18 hardening slice by auditing a bounded runtime surface for engine-usage compliance, removing local reimplementation only where clearly duplicated inside the targeted slice, and adding validation-backed enforcement for that same slice.
5+
6+
## Why This PR
7+
Level 18 is deferred execution for engine finalization and hardening. The roadmap explicitly requires additive-only, validation-backed changes with no blind refactors and no structural churn without move-map PRs. This PR starts that lane with the smallest scoped valid change: one bounded audit slice with enforcement and tests, rather than a repo-wide sweep.
8+
9+
## Scope
10+
Bound this PR to the overlay/runtime hardening lane that was active at the end of Level 17 / Level 22 work.
11+
12+
Included scope:
13+
- audit the Phase 17 / Phase 19 shared overlay runtime surfaces and any directly-coupled helper files they use
14+
- identify any local reimplementation of behavior that already exists in `src/engine/` or `src/shared/`
15+
- migrate only clearly duplicated logic inside this bounded slice to the correct engine/shared surface
16+
- add or update validation that proves the bounded slice now relies on engine/shared surfaces instead of local copies
17+
- update roadmap status markers only for items directly advanced by this PR
18+
19+
Excluded scope:
20+
- no repo-wide sample/game scan
21+
- no folder moves
22+
- no start_of_day changes
23+
- no CSS normalization
24+
- no docs bucket cleanup outside this PR's own docs
25+
- no broad naming cleanup
26+
- no new features
27+
- no gameplay behavior changes unless required to remove duplicated local logic in the audited slice
28+
29+
## Required File Targets
30+
Primary bounded targets:
31+
- `samples/phase-17/shared/overlayGameplayRuntime.js`
32+
- any directly imported overlay-runtime helper modules used by that file
33+
- any matching test files already covering the overlay runtime slice
34+
- roadmap status file(s) only for status marker updates tied to this PR
35+
36+
Allowed engine/shared targets only if the audited slice already duplicates their logic:
37+
- `src/engine/**`
38+
- `src/shared/**`
39+
40+
Do not touch unrelated games, tools, or samples.
41+
42+
## Execution Steps
43+
1. Inspect the bounded overlay runtime slice and list local helper logic that appears duplicated.
44+
2. Compare each duplicate only against existing `src/engine/` and `src/shared/` public or stable helper surfaces.
45+
3. Migrate only exact-match or near-exact-match duplicate logic where the destination is already stable and appropriate.
46+
4. Replace local usage with the engine/shared import.
47+
5. Remove only the local duplicated helper code made unnecessary by the migration.
48+
6. Add or update targeted tests proving the audited slice still passes and uses the shared/engine surface.
49+
7. Update the roadmap status markers for the directly-advanced Level 18 items.
50+
8. Package the complete repo-structured ZIP to `<project folder>/tmp/BUILD_PR_LEVEL_18_1_ENGINE_USAGE_ENFORCEMENT_AUDIT_SLICE.zip`.
51+
52+
## Required Deliverables
53+
- bounded audit + remediation implementation for the overlay runtime slice
54+
- validation updates for that slice
55+
- roadmap status updates only
56+
- repo-structured ZIP artifact
57+
58+
## Validation Requirements
59+
Must run and record results for the smallest relevant set first, then the broader overlay suite if unchanged dependencies require it.
60+
61+
Minimum required validation:
62+
- targeted overlay runtime tests that cover the edited files
63+
- any existing Phase 17 / Phase 19 / overlay integration tests that exercise the edited slice
64+
65+
If the bounded changes touch shared helpers used outside the slice, also run the smallest additional dependent test set needed to prove no regression.
66+
67+
## Acceptance Criteria
68+
- the audited overlay runtime slice no longer contains clearly duplicated logic when an existing stable engine/shared surface already covers it
69+
- no unrelated files are changed
70+
- no new feature behavior is introduced
71+
- all targeted validation passes
72+
- roadmap status markers reflect only the work actually completed
73+
- ZIP is produced at the required `<project folder>/tmp/` location
74+
75+
## Roadmap Status Update Rules
76+
Update only status markers that are directly advanced by this PR. Preserve wording.
77+
78+
Expected likely marker progression if implementation succeeds:
79+
- `18. Engine Finalization & Hardening (Deferred Execution)` remains active but may move from fully planned toward partial progress
80+
- `Track A — Engine Usage Enforcement`
81+
- `[.] verify all samples/ use engine systems (bounded slice only; if roadmap wording must remain unchanged, update only if execution meaningfully advances the item)`
82+
- `[.] migrate any local logic into engine/shared where appropriate` if the bounded slice migration is completed
83+
84+
Do not mark broader Track A complete from this PR.
85+
86+
## Guardrails
87+
- additive only
88+
- smallest scoped valid change
89+
- one PR purpose only
90+
- no repo-wide scanning unless required by direct imports in the bounded slice
91+
- no structural churn
92+
- no move-map work in this PR
93+
- no implementation in this doc bundle beyond instructions for Codex

samples/phase-17/shared/overlayGameplayRuntime.js

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
isOverlayRuntimeToggleModifierActive,
1010
LEVEL17_OVERLAY_CYCLE_KEY,
1111
} from '/samples/phase-17/shared/overlayCycleInput.js';
12+
import { asFiniteNumber } from '/src/shared/number/index.js';
1213

1314
const overlayRuntimePreferenceMemoryStore = new Map();
1415
const OVERLAY_RUNTIME_SHARE_PACKAGE_FORMAT = 'overlay-runtime-share-package';
@@ -2424,21 +2425,13 @@ export function stepOverlayGameplayRuntimeControls(runtime, input, options = {})
24242425
return true;
24252426
}
24262427

2427-
function normalizePointerNumber(value, fallback = 0) {
2428-
const numeric = Number(value);
2429-
if (!Number.isFinite(numeric)) {
2430-
return fallback;
2431-
}
2432-
return numeric;
2433-
}
2434-
24352428
function normalizePointerState(pointerState = {}, runtime = null) {
24362429
const down = pointerState?.down === true;
24372430
const previousDown = runtime?.interactionPointerLastDown === true;
24382431
const pressed = pointerState?.pressed === true || (down && !previousDown);
24392432
const released = pointerState?.released === true || (!down && previousDown);
2440-
const x = normalizePointerNumber(pointerState?.x, -1);
2441-
const y = normalizePointerNumber(pointerState?.y, -1);
2433+
const x = asFiniteNumber(pointerState?.x, -1);
2434+
const y = asFiniteNumber(pointerState?.y, -1);
24422435
const modifiers = pointerState?.modifiers && typeof pointerState.modifiers === 'object'
24432436
? pointerState.modifiers
24442437
: {};
@@ -2482,10 +2475,10 @@ function resolveTopMostInteractiveFrame(frames, x, y) {
24822475
}
24832476

24842477
function clampOverlayLayoutRect(rect, canvasWidth, canvasHeight, minPanelWidth, minPanelHeight) {
2485-
const width = Math.max(minPanelWidth, Math.min(canvasWidth, normalizePointerNumber(rect?.width, minPanelWidth)));
2486-
const height = Math.max(minPanelHeight, Math.min(canvasHeight, normalizePointerNumber(rect?.height, minPanelHeight)));
2487-
const x = Math.max(0, Math.min(canvasWidth - width, normalizePointerNumber(rect?.x, 0)));
2488-
const y = Math.max(0, Math.min(canvasHeight - height, normalizePointerNumber(rect?.y, 0)));
2478+
const width = Math.max(minPanelWidth, Math.min(canvasWidth, asFiniteNumber(rect?.width, minPanelWidth)));
2479+
const height = Math.max(minPanelHeight, Math.min(canvasHeight, asFiniteNumber(rect?.height, minPanelHeight)));
2480+
const x = Math.max(0, Math.min(canvasWidth - width, asFiniteNumber(rect?.x, 0)));
2481+
const y = Math.max(0, Math.min(canvasHeight - height, asFiniteNumber(rect?.y, 0)));
24892482
return {
24902483
x: Math.round(x),
24912484
y: Math.round(y),
@@ -2499,8 +2492,8 @@ function normalizeGesturePointerState(pointerState = {}, runtime = null) {
24992492
const previousDown = runtime?.interactionGestureLastDown === true;
25002493
const pressed = pointerState?.pressed === true || (down && !previousDown);
25012494
const released = pointerState?.released === true || (!down && previousDown);
2502-
const x = normalizePointerNumber(pointerState?.x, -1);
2503-
const y = normalizePointerNumber(pointerState?.y, -1);
2495+
const x = asFiniteNumber(pointerState?.x, -1);
2496+
const y = asFiniteNumber(pointerState?.y, -1);
25042497
const modifiers = pointerState?.modifiers && typeof pointerState.modifiers === 'object'
25052498
? pointerState.modifiers
25062499
: {};
@@ -2605,8 +2598,8 @@ export function stepOverlayGameplayRuntimeGestures(runtime, pointerState = {}, o
26052598

26062599
const gestureState = runtime.interactionGestureState;
26072600
if (gestureState && pointer.down) {
2608-
const dx = pointer.x - normalizePointerNumber(gestureState.startX, pointer.x);
2609-
const dy = pointer.y - normalizePointerNumber(gestureState.startY, pointer.y);
2601+
const dx = pointer.x - asFiniteNumber(gestureState.startX, pointer.x);
2602+
const dy = pointer.y - asFiniteNumber(gestureState.startY, pointer.y);
26102603
const distance = Math.sqrt((dx * dx) + (dy * dy));
26112604
gestureState.lastX = pointer.x;
26122605
gestureState.lastY = pointer.y;
@@ -2625,8 +2618,8 @@ export function stepOverlayGameplayRuntimeGestures(runtime, pointerState = {}, o
26252618
}
26262619

26272620
if (gestureState && pointer.released) {
2628-
const dx = pointer.x - normalizePointerNumber(gestureState.startX, pointer.x);
2629-
const dy = pointer.y - normalizePointerNumber(gestureState.startY, pointer.y);
2621+
const dx = pointer.x - asFiniteNumber(gestureState.startX, pointer.x);
2622+
const dy = pointer.y - asFiniteNumber(gestureState.startY, pointer.y);
26302623
const distance = Math.sqrt((dx * dx) + (dy * dy));
26312624
const elapsedSeconds = Math.max(0, Number(gestureState.elapsedSeconds) || 0);
26322625

@@ -2709,8 +2702,8 @@ export function stepOverlayGameplayRuntimePointerInteractions(runtime, pointerSt
27092702
activeOverlayId: String(options?.activeOverlayId || options?.context?.activeOverlayId || ''),
27102703
};
27112704
const canvasSize = context.renderer?.getCanvasSize?.() || { width: 960, height: 540 };
2712-
const canvasWidth = Math.max(320, normalizePointerNumber(canvasSize.width, 960));
2713-
const canvasHeight = Math.max(180, normalizePointerNumber(canvasSize.height, 540));
2705+
const canvasWidth = Math.max(320, asFiniteNumber(canvasSize.width, 960));
2706+
const canvasHeight = Math.max(180, asFiniteNumber(canvasSize.height, 540));
27142707
const minPanelWidth = Math.max(120, Number(options?.minPanelWidth) || 120);
27152708
const minPanelHeight = Math.max(32, Number(options?.minPanelHeight) || 32);
27162709
const resizeHandleSize = Math.max(8, Number(options?.resizeHandleSize) || 14);
@@ -2748,8 +2741,8 @@ export function stepOverlayGameplayRuntimePointerInteractions(runtime, pointerSt
27482741
}
27492742

27502743
if (activeDragState && normalizedPointer.down) {
2751-
const dx = normalizedPointer.x - normalizePointerNumber(activeDragState.pointerStartX, normalizedPointer.x);
2752-
const dy = normalizedPointer.y - normalizePointerNumber(activeDragState.pointerStartY, normalizedPointer.y);
2744+
const dx = normalizedPointer.x - asFiniteNumber(activeDragState.pointerStartX, normalizedPointer.x);
2745+
const dy = normalizedPointer.y - asFiniteNumber(activeDragState.pointerStartY, normalizedPointer.y);
27532746
const originRect = normalizeLayoutOverrideRect(activeDragState.originRect) || {
27542747
x: 0,
27552748
y: 0,

tests/runtime/Phase19OverlayExpansionFramework.test.mjs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ David Quesenberry
55
Phase19OverlayExpansionFramework.test.mjs
66
*/
77
import assert from 'node:assert/strict';
8+
import { readFileSync } from 'node:fs';
89
import { LEVEL17_OVERLAY_CYCLE_KEY } from '../../samples/phase-17/shared/overlayCycleInput.js';
910
import {
1011
isOverlayRuntimeCycleModifierActive,
@@ -68,6 +69,23 @@ function makeInput(keys = []) {
6869
};
6970
}
7071

72+
function assertOverlayRuntimeSliceUsesSharedFiniteNumberHelper() {
73+
const runtimeSource = readFileSync(
74+
new URL('../../samples/phase-17/shared/overlayGameplayRuntime.js', import.meta.url),
75+
'utf8'
76+
);
77+
assert.equal(
78+
runtimeSource.includes("import { asFiniteNumber } from '/src/shared/number/index.js';"),
79+
true,
80+
'Overlay runtime slice should import finite-number normalization from shared number helpers.'
81+
);
82+
assert.equal(
83+
runtimeSource.includes('function normalizePointerNumber('),
84+
false,
85+
'Overlay runtime slice should not keep a local duplicate pointer-number normalization helper.'
86+
);
87+
}
88+
7189
function assertExpansionRegistrationAndCompatibility() {
7290
const counters = { step: 0, render: 0 };
7391
const framework = createPhase19OverlayExpansionFramework();
@@ -1207,6 +1225,7 @@ function assertOverlaySharePackageExportImportCompatibility() {
12071225
}
12081226

12091227
export function run() {
1228+
assertOverlayRuntimeSliceUsesSharedFiniteNumberHelper();
12101229
assertExpansionRegistrationAndCompatibility();
12111230
assertExtensionLifecycleMutations();
12121231
assertDynamicPanelSizingCapability();

0 commit comments

Comments
 (0)