@plasius/learning 0.2.20 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -7
- package/dist/index.cjs +457 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -2
- package/dist/index.d.ts +147 -2
- package/dist/index.js +439 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,22 +7,39 @@ The package does **not** provide HTTP handlers, persistence, authentication, Tok
|
|
|
7
7
|
## Junior Coder catalog
|
|
8
8
|
|
|
9
9
|
The initial immutable catalog is exported as
|
|
10
|
-
`JUNIOR_CODER_ROBOT_RESCUE_PATH_V1
|
|
11
|
-
|
|
12
|
-
`
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
`JUNIOR_CODER_ROBOT_RESCUE_PATH_V1`, and its uniformly priced successor remains
|
|
11
|
+
available as `JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1`. Path `1.2.0` upgrades Road
|
|
12
|
+
Hopper Rally; path `1.3.0` is exported as
|
|
13
|
+
`JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_3` and selected by
|
|
14
|
+
`JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT`. It also upgrades Paddle Pulse to
|
|
15
|
+
module `2.0.0`; the other seventeen modules retain their prior immutable
|
|
16
|
+
versions. Each path
|
|
17
|
+
contains 19 independently sellable, self-contained project modules:
|
|
15
18
|
|
|
16
19
|
- 8 original arcade game modules;
|
|
17
20
|
- 5 simulator-backed robotics modules;
|
|
18
21
|
- 3 constrained Vibe Coding modules;
|
|
19
22
|
- 3 web application modules.
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
`1.1.0` modules each cost 50 Tokens (50,000 subunits), carrying a
|
|
24
|
+
All catalogs remain in `pilot-grant-only` commercial state. The immutable
|
|
25
|
+
`1.1.0` modules, Road Hopper Rally `2.0.0` and Paddle Pulse `2.0.0` each cost 50 Tokens (50,000 subunits), carrying a
|
|
23
26
|
non-redeemable £5 reference value. Price metadata is not authorization to
|
|
24
27
|
enable public checkout.
|
|
25
28
|
|
|
29
|
+
Road Hopper Rally `2.0.0` is a 450-minute, six-mission catalog record whose
|
|
30
|
+
54-stage course, starter project, deterministic runtime, original assets and
|
|
31
|
+
assessment definitions live in `@plasius/learning-road-hopper-rally@1.0.0`.
|
|
32
|
+
The catalog pins the exact `ROAD_HOPPER_RALLY_COURSE_V2` export and its canonical
|
|
33
|
+
SHA-256 digest through `ExternalLearningContentReferenceV1`; it does not import
|
|
34
|
+
or bundle the executable content package.
|
|
35
|
+
|
|
36
|
+
Paddle Pulse `2.0.0` is a 360-minute, six-mission catalog record whose 54-stage
|
|
37
|
+
course, declarative program contracts, deterministic 60 Hz engine and protected
|
|
38
|
+
assessment live in `@plasius/learning-paddle-pulse@0.1.0`. The catalog pins the
|
|
39
|
+
exact `PADDLE_PULSE_MODULE_V2` export, schema `2` and canonical SHA-256 digest
|
|
40
|
+
without importing the package. Paddle Pulse `1.1.0` and its mission-authoring
|
|
41
|
+
export remain available unchanged.
|
|
42
|
+
|
|
26
43
|
## Install
|
|
27
44
|
|
|
28
45
|
```bash
|
|
@@ -40,6 +57,20 @@ import {
|
|
|
40
57
|
assertValidLearningPath(JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT);
|
|
41
58
|
```
|
|
42
59
|
|
|
60
|
+
Consumers resolving external course content must verify all five reference
|
|
61
|
+
fields before use:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import {
|
|
65
|
+
ROAD_HOPPER_RALLY_EXTERNAL_CONTENT_V1,
|
|
66
|
+
isExternalLearningContentReferenceV1,
|
|
67
|
+
} from "@plasius/learning";
|
|
68
|
+
|
|
69
|
+
if (!isExternalLearningContentReferenceV1(ROAD_HOPPER_RALLY_EXTERNAL_CONTENT_V1)) {
|
|
70
|
+
throw new Error("Invalid external learning content reference");
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
43
74
|
## Calculate an assessment
|
|
44
75
|
|
|
45
76
|
```ts
|
|
@@ -54,6 +85,37 @@ const result = calculateAssessment(rubric, [
|
|
|
54
85
|
console.log(result.score, result.completed);
|
|
55
86
|
```
|
|
56
87
|
|
|
88
|
+
## Bind contextual and spoken help
|
|
89
|
+
|
|
90
|
+
Contextual-help identifiers are immutable module/manifest references rather
|
|
91
|
+
than free-form learner text. Voice consent is separate from general AI consent,
|
|
92
|
+
and version one permits private-edge transcription only.
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import {
|
|
96
|
+
CONTEXTUAL_HELP_CONTRACT_VERSION_V1,
|
|
97
|
+
assertValidContextualHelpIdentifier,
|
|
98
|
+
type ContextualHelpIdentifierV1,
|
|
99
|
+
} from "@plasius/learning";
|
|
100
|
+
|
|
101
|
+
const help: ContextualHelpIdentifierV1 = {
|
|
102
|
+
schemaVersion: "1",
|
|
103
|
+
contractVersion: CONTEXTUAL_HELP_CONTRACT_VERSION_V1,
|
|
104
|
+
kind: "command",
|
|
105
|
+
moduleId: "junior-coder.road-hopper-rally",
|
|
106
|
+
moduleVersion: "1.1.0",
|
|
107
|
+
manifestVersion: "1.0.0",
|
|
108
|
+
helpId: "command.draw-lane",
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
assertValidContextualHelpIdentifier(help);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The package also exports `GuardianVoiceConsentV1`,
|
|
115
|
+
`VoiceHelpAvailabilityV1`, bounded voice question metadata/results and
|
|
116
|
+
`CanonicalSpokenHelpDescriptorV1`. It does not record audio, persist consent,
|
|
117
|
+
call a transcription or synthesis provider, or evaluate runtime rollout flags.
|
|
118
|
+
|
|
57
119
|
## Validate a Guardian-approved static project
|
|
58
120
|
|
|
59
121
|
The publishing contracts cover only immutable evidence and safe render models.
|
|
@@ -272,6 +334,8 @@ assertValidMissionAuthoringBundle(
|
|
|
272
334
|
## Contract rules
|
|
273
335
|
|
|
274
336
|
- Published IDs and versions are immutable.
|
|
337
|
+
- External course content uses exact package and export names, a stable semantic
|
|
338
|
+
version and a lower-case canonical SHA-256 digest; version ranges are invalid.
|
|
275
339
|
- Reference prices are product-copy metadata and never create cash redemption
|
|
276
340
|
rights.
|
|
277
341
|
- A module entitlement must bind to an exact module version.
|
package/dist/index.cjs
CHANGED
|
@@ -22,20 +22,31 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
ADVENTURE_MISSION_PLANNER_MISSION_ONE_AUTHORING_V1: () => ADVENTURE_MISSION_PLANNER_MISSION_ONE_AUTHORING_V1,
|
|
24
24
|
BEACON_BOT_MISSION_ONE_AUTHORING_V1: () => BEACON_BOT_MISSION_ONE_AUTHORING_V1,
|
|
25
|
+
CONTEXTUAL_HELP_CONTRACT_VERSION_V1: () => CONTEXTUAL_HELP_CONTRACT_VERSION_V1,
|
|
26
|
+
CONTEXTUAL_HELP_KINDS_V1: () => CONTEXTUAL_HELP_KINDS_V1,
|
|
27
|
+
CONTEXTUAL_VOICE_INTENTS_V1: () => CONTEXTUAL_VOICE_INTENTS_V1,
|
|
28
|
+
CONTEXTUAL_VOICE_SUGGESTED_ACTIONS_V1: () => CONTEXTUAL_VOICE_SUGGESTED_ACTIONS_V1,
|
|
25
29
|
CREATURE_CARE_DASHBOARD_MISSION_ONE_AUTHORING_V1: () => CREATURE_CARE_DASHBOARD_MISSION_ONE_AUTHORING_V1,
|
|
26
30
|
DANCE_ROVER_MISSION_ONE_AUTHORING_V1: () => DANCE_ROVER_MISSION_ONE_AUTHORING_V1,
|
|
31
|
+
EXTERNAL_LEARNING_CONTENT_REFERENCE_VERSION_V1: () => EXTERNAL_LEARNING_CONTENT_REFERENCE_VERSION_V1,
|
|
27
32
|
JUNIOR_CODER_MISSION_STAGE_ORDER_V1: () => JUNIOR_CODER_MISSION_STAGE_ORDER_V1,
|
|
28
33
|
JUNIOR_CODER_MODULE_PRICE_V1_1: () => JUNIOR_CODER_MODULE_PRICE_V1_1,
|
|
34
|
+
JUNIOR_CODER_PADDLE_PULSE_V2: () => JUNIOR_CODER_PADDLE_PULSE_V2,
|
|
35
|
+
JUNIOR_CODER_ROAD_HOPPER_RALLY_V2: () => JUNIOR_CODER_ROAD_HOPPER_RALLY_V2,
|
|
29
36
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT: () => JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT,
|
|
30
37
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1: () => JUNIOR_CODER_ROBOT_RESCUE_PATH_V1,
|
|
31
38
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1: () => JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1,
|
|
39
|
+
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_2: () => JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_2,
|
|
40
|
+
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_3: () => JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_3,
|
|
32
41
|
METEOR_SHIELD_MISSION_ONE_AUTHORING_V1: () => METEOR_SHIELD_MISSION_ONE_AUTHORING_V1,
|
|
33
42
|
MISSION_AUTHORING_CONTRACT_VERSION_V1: () => MISSION_AUTHORING_CONTRACT_VERSION_V1,
|
|
34
43
|
OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1: () => OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1,
|
|
44
|
+
PADDLE_PULSE_EXTERNAL_CONTENT_V1: () => PADDLE_PULSE_EXTERNAL_CONTENT_V1,
|
|
35
45
|
PADDLE_PULSE_MISSION_ONE_AUTHORING_V1: () => PADDLE_PULSE_MISSION_ONE_AUTHORING_V1,
|
|
36
46
|
PIXEL_TRAIL_CHALLENGE_MISSION_ONE_AUTHORING_V1: () => PIXEL_TRAIL_CHALLENGE_MISSION_ONE_AUTHORING_V1,
|
|
37
47
|
RAINBOW_RESCUE_ROVER_MISSION_ONE_AUTHORING_V1: () => RAINBOW_RESCUE_ROVER_MISSION_ONE_AUTHORING_V1,
|
|
38
48
|
RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1: () => RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1,
|
|
49
|
+
ROAD_HOPPER_RALLY_EXTERNAL_CONTENT_V1: () => ROAD_HOPPER_RALLY_EXTERNAL_CONTENT_V1,
|
|
39
50
|
ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1: () => ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1,
|
|
40
51
|
ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1: () => ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1,
|
|
41
52
|
ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1: () => ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1,
|
|
@@ -51,12 +62,19 @@ __export(index_exports, {
|
|
|
51
62
|
VIBE_BUG_DETECTIVE_MISSION_ONE_AUTHORING_V1: () => VIBE_BUG_DETECTIVE_MISSION_ONE_AUTHORING_V1,
|
|
52
63
|
VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1: () => VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1,
|
|
53
64
|
VIBE_IDEA_STUDIO_MISSION_ONE_AUTHORING_V1: () => VIBE_IDEA_STUDIO_MISSION_ONE_AUTHORING_V1,
|
|
65
|
+
assertValidCanonicalSpokenHelpDescriptor: () => assertValidCanonicalSpokenHelpDescriptor,
|
|
66
|
+
assertValidContextualHelpIdentifier: () => assertValidContextualHelpIdentifier,
|
|
67
|
+
assertValidContextualVoiceQuestionMetadata: () => assertValidContextualVoiceQuestionMetadata,
|
|
68
|
+
assertValidContextualVoiceQuestionResult: () => assertValidContextualVoiceQuestionResult,
|
|
69
|
+
assertValidGuardianVoiceConsent: () => assertValidGuardianVoiceConsent,
|
|
54
70
|
assertValidLearningPath: () => assertValidLearningPath,
|
|
55
71
|
assertValidMissionAuthoringBundle: () => assertValidMissionAuthoringBundle,
|
|
56
72
|
assertValidStaticProjectGuardianApproval: () => assertValidStaticProjectGuardianApproval,
|
|
57
73
|
assertValidStaticProjectPublication: () => assertValidStaticProjectPublication,
|
|
58
74
|
assertValidStaticProjectSnapshot: () => assertValidStaticProjectSnapshot,
|
|
75
|
+
assertValidVoiceHelpAvailability: () => assertValidVoiceHelpAvailability,
|
|
59
76
|
calculateAssessment: () => calculateAssessment,
|
|
77
|
+
isExternalLearningContentReferenceV1: () => isExternalLearningContentReferenceV1,
|
|
60
78
|
validateAssessmentRubric: () => validateAssessmentRubric,
|
|
61
79
|
validateLearningPath: () => validateLearningPath,
|
|
62
80
|
validateMissionAuthoringBundle: () => validateMissionAuthoringBundle,
|
|
@@ -634,11 +652,410 @@ var JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1 = {
|
|
|
634
652
|
}
|
|
635
653
|
}))
|
|
636
654
|
};
|
|
637
|
-
var
|
|
655
|
+
var ROAD_HOPPER_RALLY_EXTERNAL_CONTENT_V1 = Object.freeze({
|
|
656
|
+
packageName: "@plasius/learning-road-hopper-rally",
|
|
657
|
+
packageVersion: "1.0.0",
|
|
658
|
+
exportName: "ROAD_HOPPER_RALLY_COURSE_V2",
|
|
659
|
+
schemaVersion: "2",
|
|
660
|
+
sha256: "1a20741beba028004e0be527d05aae2b2881082d3b578e0d62308a59bf1323f0"
|
|
661
|
+
});
|
|
662
|
+
var roadHopperV1_1 = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
|
|
663
|
+
(entry) => entry.id === "junior-coder.road-hopper-rally"
|
|
664
|
+
);
|
|
665
|
+
var ROAD_HOPPER_RALLY_V2_MISSIONS = [
|
|
666
|
+
{
|
|
667
|
+
id: "board",
|
|
668
|
+
title: "Build the Rally Board",
|
|
669
|
+
concepts: ["coordinate grids", "arrays", "entity state", "rendering"],
|
|
670
|
+
statement: "Create the road, median, river and five distinct home bays in board.js.",
|
|
671
|
+
sideAdventure: "Design an original high-contrast board palette without changing its mechanics."
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
id: "hopper",
|
|
675
|
+
title: "Move the Hopper",
|
|
676
|
+
concepts: ["events", "bounded movement", "keyboard input", "touch input", "respawning"],
|
|
677
|
+
statement: "Implement four-direction tile movement, bounds, equivalent inputs and respawning in hopper.js.",
|
|
678
|
+
sideAdventure: "Add an accessible movement status phrase for every successful hop."
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
id: "traffic",
|
|
682
|
+
title: "Create Rally Traffic",
|
|
683
|
+
concepts: ["spawning", "fixed-step updates", "wrapping", "collision detection", "difficulty"],
|
|
684
|
+
statement: "Implement five deterministic traffic lanes, collisions, lives and difficulty in traffic.js.",
|
|
685
|
+
sideAdventure: "Invent an original vehicle type while preserving the entity and collision limits."
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
id: "river",
|
|
689
|
+
title: "Cross the Moving River",
|
|
690
|
+
concepts: ["moving platforms", "carrying", "hazards", "state machines", "off-screen bounds"],
|
|
691
|
+
statement: "Implement logs, carrying, water deaths, diving platforms and edge hazards in river.js.",
|
|
692
|
+
sideAdventure: "Create an original visual warning for a platform that is about to dive."
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
id: "rules",
|
|
696
|
+
title: "Add Rally Rules",
|
|
697
|
+
concepts: ["timers", "lives", "scoring", "bonuses", "levels", "game over"],
|
|
698
|
+
statement: "Implement homes, occupied and blocked bays, timer, scoring, bonuses and level progression in rules.js.",
|
|
699
|
+
sideAdventure: "Tune a practice-speed preset that keeps every rule deterministic."
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
id: "game",
|
|
703
|
+
title: "Complete Road Hopper Rally",
|
|
704
|
+
concepts: ["system assembly", "pause and restart", "alternating players", "audio", "accessibility", "testing"],
|
|
705
|
+
statement: "Assemble the systems, accessibility modes and alternating-player finale in game.js, then pass the protected challenge.",
|
|
706
|
+
sideAdventure: "Polish the finished game with original captions, visual cues and reduced-motion feedback."
|
|
707
|
+
}
|
|
708
|
+
];
|
|
709
|
+
var JUNIOR_CODER_ROAD_HOPPER_RALLY_V2 = {
|
|
710
|
+
...roadHopperV1_1,
|
|
711
|
+
version: "2.0.0",
|
|
712
|
+
contentRevision: "2026-08-11.1",
|
|
713
|
+
summary: "Recreate the systems behind a classic road-and-river crossing game using original Road Hopper Rally code, art, audio and presentation.",
|
|
714
|
+
estimatedMinutes: 450,
|
|
715
|
+
tools: [
|
|
716
|
+
"JavaScript",
|
|
717
|
+
"QuickJS sandbox",
|
|
718
|
+
"Deterministic 30 Hz engine",
|
|
719
|
+
"Road Hopper renderer"
|
|
720
|
+
],
|
|
721
|
+
concepts: [
|
|
722
|
+
"coordinates",
|
|
723
|
+
"arrays and entity state",
|
|
724
|
+
"events and input",
|
|
725
|
+
"fixed-step update and render",
|
|
726
|
+
"spawning and movement",
|
|
727
|
+
"collision detection",
|
|
728
|
+
"state machines",
|
|
729
|
+
"timers, lives and scoring",
|
|
730
|
+
"difficulty progression",
|
|
731
|
+
"audio integration",
|
|
732
|
+
"debugging",
|
|
733
|
+
"deterministic testing"
|
|
734
|
+
],
|
|
735
|
+
missions: ROAD_HOPPER_RALLY_V2_MISSIONS.map((missionDefinition, index) => ({
|
|
736
|
+
id: `road-hopper-rally-mission-${index + 1}-${missionDefinition.id}`,
|
|
737
|
+
title: missionDefinition.title,
|
|
738
|
+
estimatedMinutes: 75,
|
|
739
|
+
concepts: [...missionDefinition.concepts],
|
|
740
|
+
goals: [
|
|
741
|
+
{
|
|
742
|
+
id: `road-hopper-rally-v2-${missionDefinition.id}`,
|
|
743
|
+
statement: missionDefinition.statement,
|
|
744
|
+
evidence: "assessment"
|
|
745
|
+
}
|
|
746
|
+
],
|
|
747
|
+
sideAdventure: missionDefinition.sideAdventure
|
|
748
|
+
})),
|
|
749
|
+
assessment: {
|
|
750
|
+
version: "2.0.0",
|
|
751
|
+
completionScore: 80,
|
|
752
|
+
criteria: [
|
|
753
|
+
{ id: "road-hopper-v2-structure", label: "All six bounded JavaScript files compile and assemble.", dimension: "structure", points: 20, mandatory: true, visibility: "visible" },
|
|
754
|
+
{ id: "road-hopper-v2-road", label: "Board, input and traffic behaviours pass deterministic scenarios.", dimension: "behaviour", points: 15, mandatory: true, visibility: "visible" },
|
|
755
|
+
{ id: "road-hopper-v2-river", label: "River platforms, carrying and hazards pass deterministic scenarios.", dimension: "behaviour", points: 15, mandatory: true, visibility: "visible" },
|
|
756
|
+
{ id: "road-hopper-v2-rules", label: "Homes, timer, lives, scoring, bonuses and levels behave correctly.", dimension: "behaviour", points: 20, mandatory: true, visibility: "visible" },
|
|
757
|
+
{ id: "road-hopper-v2-final", label: "The complete game passes the server-only protected final challenge.", dimension: "resilience", points: 20, mandatory: true, visibility: "protected" },
|
|
758
|
+
{ id: "road-hopper-v2-safety", label: "The project stays within the sandbox, resource and privacy boundaries.", dimension: "safety", points: 10, mandatory: true, visibility: "visible" }
|
|
759
|
+
]
|
|
760
|
+
},
|
|
761
|
+
badges: [
|
|
762
|
+
{
|
|
763
|
+
id: "road-hopper-rally-v2-complete",
|
|
764
|
+
title: "Road Hopper Rally Champion",
|
|
765
|
+
evidence: "module-score",
|
|
766
|
+
tradeable: false,
|
|
767
|
+
tokenConvertible: false
|
|
768
|
+
}
|
|
769
|
+
],
|
|
770
|
+
externalContent: ROAD_HOPPER_RALLY_EXTERNAL_CONTENT_V1
|
|
771
|
+
};
|
|
772
|
+
var JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_2 = {
|
|
773
|
+
...JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1,
|
|
774
|
+
version: "1.2.0",
|
|
775
|
+
modules: JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.map((entry) => entry.id === JUNIOR_CODER_ROAD_HOPPER_RALLY_V2.id ? JUNIOR_CODER_ROAD_HOPPER_RALLY_V2 : entry)
|
|
776
|
+
};
|
|
777
|
+
var PADDLE_PULSE_EXTERNAL_CONTENT_V1 = Object.freeze({
|
|
778
|
+
packageName: "@plasius/learning-paddle-pulse",
|
|
779
|
+
packageVersion: "0.1.0",
|
|
780
|
+
exportName: "PADDLE_PULSE_MODULE_V2",
|
|
781
|
+
schemaVersion: "2",
|
|
782
|
+
sha256: "19f3666bdb523a3faf069341b0bc748996b3db282f89171e3c9f0a373a8c8f7e"
|
|
783
|
+
});
|
|
784
|
+
var paddlePulseV1_1 = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
|
|
785
|
+
(entry) => entry.id === "junior-coder.paddle-pulse"
|
|
786
|
+
);
|
|
787
|
+
var PADDLE_PULSE_V2_MISSIONS = [
|
|
788
|
+
{
|
|
789
|
+
id: "court-coordinates",
|
|
790
|
+
title: "Court & Coordinates",
|
|
791
|
+
concepts: ["coordinates", "canvas primitives", "game loops", "bounds"],
|
|
792
|
+
statement: "Build a responsive 640 \xD7 480 logical court with a bounded paddle and ball.",
|
|
793
|
+
sideAdventure: "Create an original high-contrast court palette without changing its geometry."
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
id: "paddle-controls",
|
|
797
|
+
title: "Paddle Controls",
|
|
798
|
+
concepts: ["input state", "Pointer Events", "keyboard input", "clamping"],
|
|
799
|
+
statement: "Implement equivalent Arrow/A/D and direct horizontal pointer-drag controls.",
|
|
800
|
+
sideAdventure: "Add a semantic movement trace that does not rely on animation."
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
id: "ball-motion",
|
|
804
|
+
title: "Ball Motion & Bounces",
|
|
805
|
+
concepts: ["velocity", "fixed timesteps", "reflection", "contact normals", "paddle angles"],
|
|
806
|
+
statement: "Implement deterministic ball motion plus controlled wall and paddle reflections.",
|
|
807
|
+
sideAdventure: "Design a reduced-motion trajectory inspector for one rally."
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
id: "bricks-collisions",
|
|
811
|
+
title: "Bricks & Collisions",
|
|
812
|
+
concepts: ["arrays", "loops", "brick grids", "AABB collision", "resolution"],
|
|
813
|
+
statement: "Create an original brick grid whose bricks score once and disappear on impact.",
|
|
814
|
+
sideAdventure: "Invent a new visual brick pattern using the same bounded collision rules."
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
id: "score-lives-states",
|
|
818
|
+
title: "Score, Lives & States",
|
|
819
|
+
concepts: ["state machines", "invariants", "scoring", "lives", "HUD state"],
|
|
820
|
+
statement: "Implement serve, pause, life loss, level clear, game over, score and HUD states.",
|
|
821
|
+
sideAdventure: "Add a printable state-transition table for a facilitator or screen-reader user."
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
id: "levels-final-game",
|
|
825
|
+
title: "Levels, Sound & Final Game",
|
|
826
|
+
concepts: ["level data", "difficulty", "responsive rendering", "accessible audio", "testing"],
|
|
827
|
+
statement: "Assemble multiple original levels, optional generated cues and the integrated final game.",
|
|
828
|
+
sideAdventure: "After completion, add an optional original power-up without changing core assessment."
|
|
829
|
+
}
|
|
830
|
+
];
|
|
831
|
+
var JUNIOR_CODER_PADDLE_PULSE_V2 = {
|
|
832
|
+
...paddlePulseV1_1,
|
|
833
|
+
version: "2.0.0",
|
|
834
|
+
contentRevision: "2026-08-11.1",
|
|
835
|
+
summary: "Build an original Plasius brick-breaker while learning rendering, equivalent input, deterministic physics, collisions, score, lives, states, levels, accessible sound and testing.",
|
|
836
|
+
estimatedMinutes: 360,
|
|
837
|
+
tools: [
|
|
838
|
+
"JavaScript",
|
|
839
|
+
"QuickJS sandbox",
|
|
840
|
+
"Deterministic 60 Hz engine",
|
|
841
|
+
"Responsive Paddle Pulse renderer"
|
|
842
|
+
],
|
|
843
|
+
concepts: [
|
|
844
|
+
"coordinates and rendering",
|
|
845
|
+
"game loops and fixed timesteps",
|
|
846
|
+
"keyboard and pointer input",
|
|
847
|
+
"velocity and reflection",
|
|
848
|
+
"collision detection and resolution",
|
|
849
|
+
"arrays and brick grids",
|
|
850
|
+
"scoring, lives and state machines",
|
|
851
|
+
"level data and difficulty",
|
|
852
|
+
"accessible generated audio",
|
|
853
|
+
"debugging and deterministic testing"
|
|
854
|
+
],
|
|
855
|
+
missions: PADDLE_PULSE_V2_MISSIONS.map((missionDefinition, index) => ({
|
|
856
|
+
id: `paddle-pulse-mission-${index + 1}-${missionDefinition.id}`,
|
|
857
|
+
title: missionDefinition.title,
|
|
858
|
+
estimatedMinutes: 60,
|
|
859
|
+
concepts: [...missionDefinition.concepts],
|
|
860
|
+
goals: [{
|
|
861
|
+
id: `paddle-pulse-v2-${missionDefinition.id}`,
|
|
862
|
+
statement: missionDefinition.statement,
|
|
863
|
+
evidence: "assessment"
|
|
864
|
+
}],
|
|
865
|
+
sideAdventure: missionDefinition.sideAdventure
|
|
866
|
+
})),
|
|
867
|
+
assessment: {
|
|
868
|
+
version: "2.0.0",
|
|
869
|
+
completionScore: 80,
|
|
870
|
+
criteria: [
|
|
871
|
+
{ id: "paddle-pulse-v2-court", label: "The logical court, paddle and initial scene are finite, responsive and bounded.", dimension: "structure", points: 20, mandatory: false, visibility: "visible" },
|
|
872
|
+
{ id: "paddle-pulse-v2-controls", label: "Keyboard and pointer paths produce equivalent clamped paddle input.", dimension: "behaviour", points: 15, mandatory: false, visibility: "visible" },
|
|
873
|
+
{ id: "paddle-pulse-v2-motion", label: "Ball motion and wall/paddle reflections pass deterministic trajectories.", dimension: "behaviour", points: 15, mandatory: false, visibility: "visible" },
|
|
874
|
+
{ id: "paddle-pulse-v2-bricks", label: "Brick face, corner and adjacent impacts resolve without double-scoring.", dimension: "behaviour", points: 20, mandatory: false, visibility: "visible" },
|
|
875
|
+
{ id: "paddle-pulse-v2-states", label: "Score, lives, serve, pause, level-clear and game-over transitions preserve invariants.", dimension: "resilience", points: 10, mandatory: false, visibility: "visible" },
|
|
876
|
+
{ id: "paddle-pulse-v2-final", label: "Multiple original levels and the integrated game pass protected deterministic scenarios.", dimension: "resilience", points: 10, mandatory: false, visibility: "protected" },
|
|
877
|
+
{ id: "paddle-pulse-v2-safety", label: "Source, commands, runtime resources and assessment remain inside sandbox limits.", dimension: "safety", points: 10, mandatory: true, visibility: "visible" }
|
|
878
|
+
]
|
|
879
|
+
},
|
|
880
|
+
badges: [
|
|
881
|
+
{ id: "paddle-pulse-v2-court-builder", title: "Court Builder", evidence: "mission-score", tradeable: false, tokenConvertible: false },
|
|
882
|
+
{ id: "paddle-pulse-v2-paddle-pilot", title: "Paddle Pilot", evidence: "mission-score", tradeable: false, tokenConvertible: false },
|
|
883
|
+
{ id: "paddle-pulse-v2-rally-master", title: "Rally Master", evidence: "mission-score", tradeable: false, tokenConvertible: false },
|
|
884
|
+
{ id: "paddle-pulse-v2-brick-breaker", title: "Brick Breaker", evidence: "mission-score", tradeable: false, tokenConvertible: false },
|
|
885
|
+
{ id: "paddle-pulse-v2-game-keeper", title: "Game Keeper", evidence: "mission-score", tradeable: false, tokenConvertible: false },
|
|
886
|
+
{ id: "paddle-pulse-v2-complete", title: "Paddle Pulse Champion", evidence: "module-score", tradeable: false, tokenConvertible: false }
|
|
887
|
+
],
|
|
888
|
+
externalContent: PADDLE_PULSE_EXTERNAL_CONTENT_V1
|
|
889
|
+
};
|
|
890
|
+
var JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_3 = {
|
|
891
|
+
...JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_2,
|
|
892
|
+
version: "1.3.0",
|
|
893
|
+
modules: JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_2.modules.map((entry) => entry.id === JUNIOR_CODER_PADDLE_PULSE_V2.id ? JUNIOR_CODER_PADDLE_PULSE_V2 : entry)
|
|
894
|
+
};
|
|
895
|
+
var JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_3;
|
|
638
896
|
|
|
639
897
|
// src/contracts.ts
|
|
898
|
+
var EXTERNAL_LEARNING_CONTENT_REFERENCE_VERSION_V1 = "1";
|
|
640
899
|
var MISSION_AUTHORING_CONTRACT_VERSION_V1 = "1.0.0";
|
|
641
900
|
|
|
901
|
+
// src/contextual-help.ts
|
|
902
|
+
var CONTEXTUAL_HELP_CONTRACT_VERSION_V1 = "1.0.0";
|
|
903
|
+
var CONTEXTUAL_HELP_KINDS_V1 = Object.freeze([
|
|
904
|
+
"command",
|
|
905
|
+
"visual-block",
|
|
906
|
+
"generated-code",
|
|
907
|
+
"assessment-diagnostic"
|
|
908
|
+
]);
|
|
909
|
+
var CONTEXTUAL_VOICE_INTENTS_V1 = Object.freeze([
|
|
910
|
+
"describe-command",
|
|
911
|
+
"describe-inputs",
|
|
912
|
+
"show-example",
|
|
913
|
+
"explain-assessment-failure",
|
|
914
|
+
"suggest-next-experiment",
|
|
915
|
+
"repeat",
|
|
916
|
+
"stop",
|
|
917
|
+
"unresolved"
|
|
918
|
+
]);
|
|
919
|
+
var CONTEXTUAL_VOICE_SUGGESTED_ACTIONS_V1 = Object.freeze([
|
|
920
|
+
"open-help",
|
|
921
|
+
"insert-example",
|
|
922
|
+
"show-inputs",
|
|
923
|
+
"show-assessment-evidence",
|
|
924
|
+
"try-next-experiment",
|
|
925
|
+
"repeat",
|
|
926
|
+
"stop",
|
|
927
|
+
"type-question"
|
|
928
|
+
]);
|
|
929
|
+
var OPAQUE_ID = /^[a-z0-9]+(?:[._:-][a-z0-9]+)*$/u;
|
|
930
|
+
var SEMVER = /^[0-9]+\.[0-9]+\.[0-9]+(?:[-+][A-Za-z0-9.-]+)?$/u;
|
|
931
|
+
var SHA_256 = /^sha256:[a-f0-9]{64}$/u;
|
|
932
|
+
var LOCALE = /^[a-z]{2,3}(?:-[A-Z]{2})?$/u;
|
|
933
|
+
var MEDIA_TYPE = /^audio\/[a-z0-9.+-]+$/u;
|
|
934
|
+
function containsDisallowedControlCharacter(value) {
|
|
935
|
+
return [...value].some((character) => {
|
|
936
|
+
const code = character.codePointAt(0) ?? 0;
|
|
937
|
+
return code <= 8 || code === 11 || code === 12 || code >= 14 && code <= 31 || code === 127;
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
function requireOpaqueId(value, label, maximum = 160) {
|
|
941
|
+
if (value.length === 0 || value.length > maximum || !OPAQUE_ID.test(value)) {
|
|
942
|
+
throw new Error(`${label} must be a bounded opaque identifier.`);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
function requireSemver(value, label) {
|
|
946
|
+
if (!SEMVER.test(value)) {
|
|
947
|
+
throw new Error(`${label} must be an immutable semantic version.`);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
function requireIsoTimestamp(value, label) {
|
|
951
|
+
if (!/^\d{4}-\d{2}-\d{2}T/u.test(value) || !Number.isFinite(Date.parse(value))) {
|
|
952
|
+
throw new Error(`${label} must be an ISO-8601 timestamp.`);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
function assertValidContextualHelpIdentifier(value) {
|
|
956
|
+
if (value.schemaVersion !== "1") {
|
|
957
|
+
throw new Error("schemaVersion must be 1.");
|
|
958
|
+
}
|
|
959
|
+
if (value.contractVersion !== CONTEXTUAL_HELP_CONTRACT_VERSION_V1) {
|
|
960
|
+
throw new Error("contractVersion is unsupported.");
|
|
961
|
+
}
|
|
962
|
+
if (!CONTEXTUAL_HELP_KINDS_V1.includes(value.kind)) {
|
|
963
|
+
throw new Error("kind is unsupported.");
|
|
964
|
+
}
|
|
965
|
+
requireOpaqueId(value.moduleId, "moduleId");
|
|
966
|
+
requireSemver(value.moduleVersion, "moduleVersion");
|
|
967
|
+
requireSemver(value.manifestVersion, "manifestVersion");
|
|
968
|
+
requireOpaqueId(value.helpId, "helpId");
|
|
969
|
+
}
|
|
970
|
+
function assertValidGuardianVoiceConsent(value) {
|
|
971
|
+
if (value.schemaVersion !== "1") {
|
|
972
|
+
throw new Error("schemaVersion must be 1.");
|
|
973
|
+
}
|
|
974
|
+
requireOpaqueId(value.actorAccountId, "actorAccountId");
|
|
975
|
+
requireOpaqueId(value.subjectAccountId, "subjectAccountId");
|
|
976
|
+
requireSemver(value.policyVersion, "policyVersion");
|
|
977
|
+
if (value.state !== "granted" && value.state !== "withdrawn") {
|
|
978
|
+
throw new Error("state must be granted or withdrawn.");
|
|
979
|
+
}
|
|
980
|
+
if (value.permittedProcessingRoute !== "private-edge-only") {
|
|
981
|
+
throw new Error("permittedProcessingRoute must be private-edge-only.");
|
|
982
|
+
}
|
|
983
|
+
requireIsoTimestamp(value.recordedAt, "recordedAt");
|
|
984
|
+
}
|
|
985
|
+
function assertValidContextualVoiceQuestionMetadata(value) {
|
|
986
|
+
assertValidContextualHelpIdentifier(value.help);
|
|
987
|
+
if (!LOCALE.test(value.locale)) throw new Error("locale is invalid.");
|
|
988
|
+
if (!MEDIA_TYPE.test(value.mediaType)) throw new Error("mediaType is invalid.");
|
|
989
|
+
if (!Number.isInteger(value.durationMs) || value.durationMs < 1 || value.durationMs > 1e4) {
|
|
990
|
+
throw new Error("durationMs must be between 1 and 10000.");
|
|
991
|
+
}
|
|
992
|
+
if (!Number.isInteger(value.audioBytes) || value.audioBytes < 1 || value.audioBytes > 2097152) {
|
|
993
|
+
throw new Error("audioBytes must be between 1 and 2097152.");
|
|
994
|
+
}
|
|
995
|
+
if (value.assessmentEvidenceId !== void 0) {
|
|
996
|
+
requireOpaqueId(value.assessmentEvidenceId, "assessmentEvidenceId");
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
function assertValidVoiceHelpAvailability(value) {
|
|
1000
|
+
if (value.schemaVersion !== "1") throw new Error("schemaVersion must be 1.");
|
|
1001
|
+
if (value.questionProcessingRoute !== "private-edge-only") {
|
|
1002
|
+
throw new Error("questionProcessingRoute must be private-edge-only.");
|
|
1003
|
+
}
|
|
1004
|
+
if (value.guardianVoiceConsentRequired !== true) {
|
|
1005
|
+
throw new Error("guardianVoiceConsentRequired must remain true.");
|
|
1006
|
+
}
|
|
1007
|
+
if (value.maximumRecordingDurationMs !== 1e4 || value.maximumAudioBytes !== 2097152 || value.rawAudioRetention !== "request-memory-only" || value.transcriptRetention !== "request-memory-only") {
|
|
1008
|
+
throw new Error("Voice limits and transient retention are immutable in version one.");
|
|
1009
|
+
}
|
|
1010
|
+
if (value.microphoneAvailable !== (value.microphoneReason === "available")) {
|
|
1011
|
+
throw new Error("microphoneReason must match microphone availability.");
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
function assertValidCanonicalSpokenHelpDescriptor(value) {
|
|
1015
|
+
if (value.schemaVersion !== "1") throw new Error("schemaVersion must be 1.");
|
|
1016
|
+
assertValidContextualHelpIdentifier(value.help);
|
|
1017
|
+
requireOpaqueId(value.canonicalTextId, "canonicalTextId");
|
|
1018
|
+
if (!SHA_256.test(value.authoritativeTextDigest)) {
|
|
1019
|
+
throw new Error("authoritativeTextDigest must be a SHA-256 digest.");
|
|
1020
|
+
}
|
|
1021
|
+
if (!LOCALE.test(value.locale)) throw new Error("locale is invalid.");
|
|
1022
|
+
requireOpaqueId(value.voiceProfile, "voiceProfile");
|
|
1023
|
+
requireSemver(value.pronunciationVersion, "pronunciationVersion");
|
|
1024
|
+
if (value.utteranceClass !== "system-generic" || value.sharingScope !== "global" || value.reuse !== "exact-only" || value.containsPersonalData !== false || value.containsLearnerContent !== false) {
|
|
1025
|
+
throw new Error("Canonical spoken help must use global system-generic exact-only reuse.");
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
function assertValidContextualVoiceQuestionResult(value) {
|
|
1029
|
+
if (value.schemaVersion !== "1") throw new Error("schemaVersion must be 1.");
|
|
1030
|
+
assertValidContextualHelpIdentifier(value.help);
|
|
1031
|
+
if (!CONTEXTUAL_VOICE_INTENTS_V1.includes(value.intent)) {
|
|
1032
|
+
throw new Error("intent is unsupported.");
|
|
1033
|
+
}
|
|
1034
|
+
if (value.transcriptRetention !== "request-memory-only") {
|
|
1035
|
+
throw new Error("transcriptRetention must be request-memory-only.");
|
|
1036
|
+
}
|
|
1037
|
+
if (value.status !== "resolved" && value.status !== "suggestions" && value.status !== "stopped") {
|
|
1038
|
+
throw new Error("status is unsupported.");
|
|
1039
|
+
}
|
|
1040
|
+
if (value.transientTranscript.length > 500 || containsDisallowedControlCharacter(value.transientTranscript)) {
|
|
1041
|
+
throw new Error("transientTranscript is invalid.");
|
|
1042
|
+
}
|
|
1043
|
+
if (value.answer) {
|
|
1044
|
+
requireOpaqueId(value.answer.helpId, "answer.helpId");
|
|
1045
|
+
if (value.answer.source !== "module-documentation" && value.answer.source !== "assessment-evidence" && value.answer.source !== "authored-fallback" || value.answer.text.length === 0 || value.answer.text.length > 800 || containsDisallowedControlCharacter(value.answer.text)) {
|
|
1046
|
+
throw new Error("answer.text is invalid.");
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
if (value.suggestedActions.some(
|
|
1050
|
+
(action) => !CONTEXTUAL_VOICE_SUGGESTED_ACTIONS_V1.includes(action)
|
|
1051
|
+
)) {
|
|
1052
|
+
throw new Error("suggestedActions contains an unsupported action.");
|
|
1053
|
+
}
|
|
1054
|
+
if (value.mayAssignScore !== false || value.mayAwardReward !== false || value.mayPublish !== false || value.mayControlHardware !== false) {
|
|
1055
|
+
throw new Error("mayAssignScore, reward, publish and hardware authority must remain false.");
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
|
|
642
1059
|
// src/publishing.ts
|
|
643
1060
|
var STATIC_PROJECT_PUBLISHING_CONTRACT_VERSION_V1 = "1.0.0";
|
|
644
1061
|
var STATIC_PROJECT_SCANNER_VERSION_V1 = "junior-coder-static-scan-v1";
|
|
@@ -6670,6 +7087,16 @@ var ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1 = {
|
|
|
6670
7087
|
|
|
6671
7088
|
// src/validation.ts
|
|
6672
7089
|
var CANONICAL_TOKEN_SUBUNITS = /^(0|[1-9][0-9]*)$/u;
|
|
7090
|
+
var EXACT_PACKAGE_NAME = /^@plasius\/[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u;
|
|
7091
|
+
var EXACT_SEMVER = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/u;
|
|
7092
|
+
var EXPORT_NAME = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;
|
|
7093
|
+
var CONTENT_SCHEMA_VERSION = /^(0|[1-9][0-9]*)$/u;
|
|
7094
|
+
var SHA256 = /^[a-f0-9]{64}$/u;
|
|
7095
|
+
function isExternalLearningContentReferenceV1(value) {
|
|
7096
|
+
if (typeof value !== "object" || value === null) return false;
|
|
7097
|
+
const candidate = value;
|
|
7098
|
+
return Object.keys(value).length === 5 && typeof candidate.packageName === "string" && EXACT_PACKAGE_NAME.test(candidate.packageName) && typeof candidate.packageVersion === "string" && EXACT_SEMVER.test(candidate.packageVersion) && typeof candidate.exportName === "string" && EXPORT_NAME.test(candidate.exportName) && typeof candidate.schemaVersion === "string" && CONTENT_SCHEMA_VERSION.test(candidate.schemaVersion) && typeof candidate.sha256 === "string" && SHA256.test(candidate.sha256);
|
|
7099
|
+
}
|
|
6673
7100
|
function issue(code, message, path, moduleId) {
|
|
6674
7101
|
return { code, message, path, ...moduleId ? { moduleId } : {} };
|
|
6675
7102
|
}
|
|
@@ -6784,6 +7211,17 @@ function validateModule(module3, moduleIndex) {
|
|
|
6784
7211
|
)
|
|
6785
7212
|
);
|
|
6786
7213
|
}
|
|
7214
|
+
const externalContent = module3.externalContent;
|
|
7215
|
+
if (externalContent && !isExternalLearningContentReferenceV1(externalContent)) {
|
|
7216
|
+
issues.push(
|
|
7217
|
+
issue(
|
|
7218
|
+
"invalid-external-content-reference",
|
|
7219
|
+
"External content must use an exact @plasius package, stable semantic version, named export, schema version and lower-case SHA-256 digest.",
|
|
7220
|
+
`${base}.externalContent`,
|
|
7221
|
+
module3.id
|
|
7222
|
+
)
|
|
7223
|
+
);
|
|
7224
|
+
}
|
|
6787
7225
|
return issues;
|
|
6788
7226
|
}
|
|
6789
7227
|
function validateLearningPath(path) {
|
|
@@ -6828,20 +7266,31 @@ ${summary}`);
|
|
|
6828
7266
|
0 && (module.exports = {
|
|
6829
7267
|
ADVENTURE_MISSION_PLANNER_MISSION_ONE_AUTHORING_V1,
|
|
6830
7268
|
BEACON_BOT_MISSION_ONE_AUTHORING_V1,
|
|
7269
|
+
CONTEXTUAL_HELP_CONTRACT_VERSION_V1,
|
|
7270
|
+
CONTEXTUAL_HELP_KINDS_V1,
|
|
7271
|
+
CONTEXTUAL_VOICE_INTENTS_V1,
|
|
7272
|
+
CONTEXTUAL_VOICE_SUGGESTED_ACTIONS_V1,
|
|
6831
7273
|
CREATURE_CARE_DASHBOARD_MISSION_ONE_AUTHORING_V1,
|
|
6832
7274
|
DANCE_ROVER_MISSION_ONE_AUTHORING_V1,
|
|
7275
|
+
EXTERNAL_LEARNING_CONTENT_REFERENCE_VERSION_V1,
|
|
6833
7276
|
JUNIOR_CODER_MISSION_STAGE_ORDER_V1,
|
|
6834
7277
|
JUNIOR_CODER_MODULE_PRICE_V1_1,
|
|
7278
|
+
JUNIOR_CODER_PADDLE_PULSE_V2,
|
|
7279
|
+
JUNIOR_CODER_ROAD_HOPPER_RALLY_V2,
|
|
6835
7280
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT,
|
|
6836
7281
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1,
|
|
6837
7282
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1,
|
|
7283
|
+
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_2,
|
|
7284
|
+
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_3,
|
|
6838
7285
|
METEOR_SHIELD_MISSION_ONE_AUTHORING_V1,
|
|
6839
7286
|
MISSION_AUTHORING_CONTRACT_VERSION_V1,
|
|
6840
7287
|
OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1,
|
|
7288
|
+
PADDLE_PULSE_EXTERNAL_CONTENT_V1,
|
|
6841
7289
|
PADDLE_PULSE_MISSION_ONE_AUTHORING_V1,
|
|
6842
7290
|
PIXEL_TRAIL_CHALLENGE_MISSION_ONE_AUTHORING_V1,
|
|
6843
7291
|
RAINBOW_RESCUE_ROVER_MISSION_ONE_AUTHORING_V1,
|
|
6844
7292
|
RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1,
|
|
7293
|
+
ROAD_HOPPER_RALLY_EXTERNAL_CONTENT_V1,
|
|
6845
7294
|
ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1,
|
|
6846
7295
|
ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1,
|
|
6847
7296
|
ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1,
|
|
@@ -6857,12 +7306,19 @@ ${summary}`);
|
|
|
6857
7306
|
VIBE_BUG_DETECTIVE_MISSION_ONE_AUTHORING_V1,
|
|
6858
7307
|
VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1,
|
|
6859
7308
|
VIBE_IDEA_STUDIO_MISSION_ONE_AUTHORING_V1,
|
|
7309
|
+
assertValidCanonicalSpokenHelpDescriptor,
|
|
7310
|
+
assertValidContextualHelpIdentifier,
|
|
7311
|
+
assertValidContextualVoiceQuestionMetadata,
|
|
7312
|
+
assertValidContextualVoiceQuestionResult,
|
|
7313
|
+
assertValidGuardianVoiceConsent,
|
|
6860
7314
|
assertValidLearningPath,
|
|
6861
7315
|
assertValidMissionAuthoringBundle,
|
|
6862
7316
|
assertValidStaticProjectGuardianApproval,
|
|
6863
7317
|
assertValidStaticProjectPublication,
|
|
6864
7318
|
assertValidStaticProjectSnapshot,
|
|
7319
|
+
assertValidVoiceHelpAvailability,
|
|
6865
7320
|
calculateAssessment,
|
|
7321
|
+
isExternalLearningContentReferenceV1,
|
|
6866
7322
|
validateAssessmentRubric,
|
|
6867
7323
|
validateLearningPath,
|
|
6868
7324
|
validateMissionAuthoringBundle,
|