Skip to content

Commit 32c8880

Browse files
author
DavidQ
committed
Normalize Object Vector Studio object ID slug naming and rename behavior - PR_26133_035-object-id-slug-normalization
1 parent a40ec7a commit 32c8880

12 files changed

Lines changed: 312 additions & 184 deletions
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# PR_26133_035 Object ID Slug Normalization Report
2+
3+
Date: 2026-05-15
4+
5+
## Canonical Rule
6+
7+
Object Vector Studio V2 now generates object ids as:
8+
9+
```text
10+
object.<game-id>.<slug>
11+
```
12+
13+
The slug is lowercase, dash-separated, and readable. The generator removes a leading duplicate game slug, normalizes known noun/size order such as `asteroid-medium` to `medium-asteroid`, and avoids using `-1` as the first collision suffix for asteroid/UFO-style names.
14+
15+
## Collision Behavior
16+
17+
- First `Medium Asteroid`: `object.asteroids.medium-asteroid`
18+
- First collision: `object.asteroids.medium-asteroid-2`
19+
- Next collision: `object.asteroids.medium-asteroid-3`
20+
- Duplicate Large Asteroid followed by rename to Medium Asteroid was verified to regenerate `object.asteroids.medium-asteroid-3`.
21+
22+
## Schema And Validation
23+
24+
- Tightened Object Vector Studio object id validation to reject extra dotted slug segments after `object.<game-id>.`.
25+
- Updated the standalone Object Vector Studio V2 schema, game manifest schema, Object Vector Studio schema service, and runtime asset validator to use the same canonical object id pattern.
26+
- Existing `object.*` runtime SSoT is preserved.
27+
28+
## Asteroids Manifest
29+
30+
Canonical Asteroids ids are now:
31+
32+
- `object.asteroids.ship`
33+
- `object.asteroids.large-asteroid`
34+
- `object.asteroids.medium-asteroid`
35+
- `object.asteroids.medium-asteroid-2`
36+
- `object.asteroids.small-asteroid`
37+
- `object.asteroids.large-ufo`
38+
- `object.asteroids.small-ufo`
39+
40+
Runtime bindings in `game.gameData.objectVectorRuntime.objectIds` now point at the canonical active role ids. The active Medium Asteroid and duplicate Medium Asteroid entries both use `["asteroid", "medium"]`; the active Medium Asteroid keeps the 7-point medium asteroid geometry so tag resolution does not accidentally select a large asteroid shape for the medium role.
41+
42+
## Validation
43+
44+
- PASS - `npm run test:workspace-v2` -> 49 passed.
45+
- PASS - targeted Asteroids Asset Reference Adoption test.
46+
- PASS - targeted Asteroids Platform Demo test.
47+
- PASS - targeted Asteroids collision timing/stress checks.
48+
- PASS - targeted Asteroids canonical Object Vector runtime validation loaded 7 objects and resolved canonical role ids by tags.

docs/dev/reports/playwright_v8_coverage_report.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# PR_26133_034 Playwright V8 Coverage Report
1+
# PR_26133_035 Playwright V8 Coverage Report
22

3-
Task: PR_26133_034-asteroids-runtime-object-resolution-by-tags
4-
Date: 2026-05-14
3+
Task: PR_26133_035-object-id-slug-normalization
4+
Date: 2026-05-15
55

66
## Result
77

@@ -26,6 +26,8 @@ PASS - Coverage reporting was generated during `npm run test:workspace-v2`.
2626
## Changed Runtime JS Coverage
2727

2828
```text
29+
(93%) tools/object-vector-studio-v2/js/ToolStarterApp.js - executed lines 4350/4350; executed functions 456/488
30+
(95%) tools/object-vector-studio-v2/js/services/ObjectVectorStudioV2SchemaService.js - executed lines 453/453; executed functions 55/58
2931
(97%) src/engine/rendering/ObjectVectorRuntimeAssetService.js - executed lines 1056/1056; executed functions 123/127
3032
```
3133

@@ -37,4 +39,4 @@ PASS - Coverage reporting was generated during `npm run test:workspace-v2`.
3739

3840
## PR-Specific Note
3941

40-
The Workspace V2 run exercised Asteroids gameplay Object Vector runtime loading and rendering with role/tag cache diagnostics, plus Object Vector Studio V2 launch/save flows. Coverage remains advisory only.
42+
The Workspace V2 run exercised Object Vector Studio V2 rename, duplicate, save/load, schema validation, and Asteroids runtime Object Vector rendering with canonical object ids. Coverage remains advisory only.
Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# PR_26133_034 Workspace V2 Playwright Results
1+
# PR_26133_035 Workspace V2 Playwright Results
22

3-
Task: PR_26133_034-asteroids-runtime-object-resolution-by-tags
4-
Date: 2026-05-14
3+
Task: PR_26133_035-object-id-slug-normalization
4+
Date: 2026-05-15
55

66
## Result
77

@@ -14,17 +14,18 @@ PASS - `npm run test:workspace-v2` completed successfully.
1414

1515
## PR-Specific Coverage
1616

17-
- Asteroids gameplay rendering now resolves Object Vector runtime objects through role/tag options for ship, UFO, and asteroid roles.
18-
- Workspace V2 runtime rendering test was updated to expect role-based cache diagnostics for ship and small UFO.
19-
- Object Vector Studio V2 still loads the Asteroids object payload from `games/Asteroids/game.manifest.json`.
20-
- Asteroids manifest runtime validation confirmed the current large, medium, and small asteroid objects expose the required tag metadata.
17+
- Object Vector Studio V2 rename preview and commit flows were verified for normalized ids such as `object.asteroids.medium-asteroid`.
18+
- Collision numbering was verified as `object.asteroids.medium-asteroid-2`, with no `medium-asteroid-1` generated.
19+
- Duplicate Large Asteroid followed by rename to Medium Asteroid was verified to regenerate `object.asteroids.medium-asteroid-3`.
20+
- Workspace Manager V2 manifest load/save paths validated the canonical Asteroids object ids and rejected the older mixed `asteroid.*` / `ufo.*` forms from the active data.
21+
- Asteroids runtime rendering still loaded and rendered Object Vector runtime assets with the canonical ids.
2122

2223
## Additional Validation
2324

24-
PASS - Targeted recreated Medium Asteroid resolution tests confirmed `["asteroid", "medium"]` tags select the recreated object even when an explicit stale medium object id is present.
25+
PASS - Targeted Asteroids Asset Reference Adoption test.
2526

26-
PASS - Targeted Asteroids collision timing/stress checks still load asteroid collision profiles from Object Vector Studio V2 geometry.
27+
PASS - Targeted Asteroids Platform Demo test.
2728

28-
PASS - Targeted Asteroids validation smoke completed.
29+
PASS - Targeted Asteroids collision timing/stress checks.
2930

30-
PASS - Targeted Asteroids manifest Object Vector runtime validation loaded 6 objects and resolved the current medium asteroid by tags.
31+
PASS - Targeted Asteroids canonical Object Vector runtime validation loaded 7 objects and resolved large, medium, small asteroid, and small UFO roles by tags.

games/Asteroids/game.manifest.json

Lines changed: 89 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
"objectVectorRuntime": {
1616
"objectIds": {
1717
"ship": "object.asteroids.ship",
18-
"asteroidLarge": "object.asteroids.asteroid.large",
19-
"asteroidMedium": "object.asteroids.asteroid.medium",
20-
"asteroidSmall": "object.asteroids.asteroid.small",
21-
"ufoLarge": "object.asteroids.ufo.large",
22-
"ufoSmall": "object.asteroids.ufo.small"
18+
"asteroidLarge": "object.asteroids.large-asteroid",
19+
"asteroidMedium": "object.asteroids.medium-asteroid",
20+
"asteroidSmall": "object.asteroids.small-asteroid",
21+
"ufoLarge": "object.asteroids.large-ufo",
22+
"ufoSmall": "object.asteroids.small-ufo"
2323
}
2424
}
2525
},
@@ -390,7 +390,7 @@
390390
]
391391
},
392392
{
393-
"id": "object.asteroids.asteroid.large",
393+
"id": "object.asteroids.large-asteroid",
394394
"name": "Large Asteroid",
395395
"shapes": [
396396
{
@@ -490,87 +490,7 @@
490490
]
491491
},
492492
{
493-
"id": "object.asteroids.medium-asteroid-1",
494-
"name": "Medium Asteroid 1",
495-
"shapes": [
496-
{
497-
"tool": "polygon",
498-
"order": 0,
499-
"visible": true,
500-
"locked": false,
501-
"geometry": {
502-
"points": [
503-
{
504-
"x": -16,
505-
"y": -10
506-
},
507-
{
508-
"x": -2,
509-
"y": -18
510-
},
511-
{
512-
"x": 16,
513-
"y": -14
514-
},
515-
{
516-
"x": 20,
517-
"y": 2
518-
},
519-
{
520-
"x": 8,
521-
"y": 18
522-
},
523-
{
524-
"x": -10,
525-
"y": 16
526-
},
527-
{
528-
"x": -20,
529-
"y": 4
530-
}
531-
]
532-
},
533-
"style": {
534-
"fill": "transparent",
535-
"stroke": "#CBD5E1",
536-
"strokeWidth": 2,
537-
"fillOpacity": 1,
538-
"strokeOpacity": 1
539-
},
540-
"transform": {
541-
"x": 0,
542-
"y": 0,
543-
"rotation": 0,
544-
"scaleX": 1,
545-
"scaleY": 1,
546-
"origin": {
547-
"x": 0,
548-
"y": 0
549-
}
550-
}
551-
}
552-
],
553-
"states": [
554-
{
555-
"id": "active",
556-
"name": "Active",
557-
"frames": [
558-
{
559-
"id": "active-frame-1",
560-
"order": 0,
561-
"durationFrames": 1,
562-
"shapeOverrides": []
563-
}
564-
]
565-
}
566-
],
567-
"tags": [
568-
"asteroid",
569-
"medium"
570-
]
571-
},
572-
{
573-
"id": "object.asteroids.asteroid.small",
493+
"id": "object.asteroids.small-asteroid",
574494
"name": "Small Asteroid",
575495
"shapes": [
576496
{
@@ -646,7 +566,7 @@
646566
]
647567
},
648568
{
649-
"id": "object.asteroids.ufo.large",
569+
"id": "object.asteroids.large-ufo",
650570
"name": "Large UFO",
651571
"shapes": [
652572
{
@@ -730,7 +650,7 @@
730650
]
731651
},
732652
{
733-
"id": "object.asteroids.ufo.small",
653+
"id": "object.asteroids.small-ufo",
734654
"name": "Small UFO",
735655
"shapes": [
736656
{
@@ -816,6 +736,86 @@
816736
{
817737
"id": "object.asteroids.medium-asteroid",
818738
"name": "Medium Asteroid",
739+
"shapes": [
740+
{
741+
"tool": "polygon",
742+
"order": 0,
743+
"visible": true,
744+
"locked": false,
745+
"geometry": {
746+
"points": [
747+
{
748+
"x": -16,
749+
"y": -10
750+
},
751+
{
752+
"x": -2,
753+
"y": -18
754+
},
755+
{
756+
"x": 16,
757+
"y": -14
758+
},
759+
{
760+
"x": 20,
761+
"y": 2
762+
},
763+
{
764+
"x": 8,
765+
"y": 18
766+
},
767+
{
768+
"x": -10,
769+
"y": 16
770+
},
771+
{
772+
"x": -20,
773+
"y": 4
774+
}
775+
]
776+
},
777+
"style": {
778+
"fill": "transparent",
779+
"stroke": "#CBD5E1",
780+
"strokeWidth": 2,
781+
"fillOpacity": 1,
782+
"strokeOpacity": 1
783+
},
784+
"transform": {
785+
"x": 0,
786+
"y": 0,
787+
"rotation": 0,
788+
"scaleX": 1,
789+
"scaleY": 1,
790+
"origin": {
791+
"x": 0,
792+
"y": 0
793+
}
794+
}
795+
}
796+
],
797+
"states": [
798+
{
799+
"id": "active",
800+
"name": "Active",
801+
"frames": [
802+
{
803+
"id": "active-frame-1",
804+
"order": 0,
805+
"durationFrames": 1,
806+
"shapeOverrides": []
807+
}
808+
]
809+
}
810+
],
811+
"tags": [
812+
"asteroid",
813+
"medium"
814+
]
815+
},
816+
{
817+
"id": "object.asteroids.medium-asteroid-2",
818+
"name": "Medium Asteroid",
819819
"shapes": [
820820
{
821821
"tool": "polygon",

src/engine/rendering/ObjectVectorRuntimeAssetService.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function clone(value) {
1010
}
1111

1212
function isObjectIdentityId(value) {
13-
return /^object\.[a-z0-9-]+\.[a-z0-9][a-z0-9.-]*$/.test(String(value || ""));
13+
return /^object\.[a-z0-9-]+\.[a-z0-9][a-z0-9-]*$/.test(String(value || ""));
1414
}
1515

1616
function typeMatches(expectedType, value) {

0 commit comments

Comments
 (0)