@plasius/learning 0.2.18 → 0.2.20
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 +39 -1
- package/dist/index.cjs +438 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +108 -1
- package/dist/index.d.ts +108 -1
- package/dist/index.js +424 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,6 +54,30 @@ const result = calculateAssessment(rubric, [
|
|
|
54
54
|
console.log(result.score, result.completed);
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
## Validate a Guardian-approved static project
|
|
58
|
+
|
|
59
|
+
The publishing contracts cover only immutable evidence and safe render models.
|
|
60
|
+
HTTP, persistence, identity checks, scanning implementations and hosting remain
|
|
61
|
+
consumer responsibilities. A public renderer must consume the allow-listed
|
|
62
|
+
`renderModel`; it must never execute learner source.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import {
|
|
66
|
+
assertValidStaticProjectGuardianApproval,
|
|
67
|
+
assertValidStaticProjectPublication,
|
|
68
|
+
assertValidStaticProjectSnapshot,
|
|
69
|
+
} from "@plasius/learning";
|
|
70
|
+
|
|
71
|
+
assertValidStaticProjectSnapshot(snapshot);
|
|
72
|
+
assertValidStaticProjectGuardianApproval(approval);
|
|
73
|
+
assertValidStaticProjectPublication(publication);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The version-one contract supports the three launch web projects, requires a
|
|
77
|
+
score of at least 80 plus mandatory safety evidence, records all eight scanner
|
|
78
|
+
checks, binds adult approval to the exact snapshot digest, and requires an
|
|
79
|
+
unlisted HTTPS URL with a random slug and explicit expiry.
|
|
80
|
+
|
|
57
81
|
## Validate mission authoring
|
|
58
82
|
|
|
59
83
|
Mission authoring is additive to the immutable catalog. A bundle contains
|
|
@@ -74,6 +98,7 @@ import {
|
|
|
74
98
|
RAINBOW_RESCUE_ROVER_MISSION_ONE_AUTHORING_V1,
|
|
75
99
|
RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1,
|
|
76
100
|
ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1,
|
|
101
|
+
ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1,
|
|
77
102
|
ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1,
|
|
78
103
|
SERVO_CREATURE_MISSION_ONE_AUTHORING_V1,
|
|
79
104
|
SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1,
|
|
@@ -138,6 +163,9 @@ const adventureMissionPlanner = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find
|
|
|
138
163
|
const creatureCareDashboard = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
|
|
139
164
|
(module) => module.slug === "creature-care-dashboard",
|
|
140
165
|
);
|
|
166
|
+
const robotMissionControl = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
|
|
167
|
+
(module) => module.slug === "robot-mission-control",
|
|
168
|
+
);
|
|
141
169
|
|
|
142
170
|
if (
|
|
143
171
|
!roadHopper ||
|
|
@@ -157,7 +185,8 @@ if (
|
|
|
157
185
|
!vibeBugDetective ||
|
|
158
186
|
!vibeIdeaStudio ||
|
|
159
187
|
!adventureMissionPlanner ||
|
|
160
|
-
!creatureCareDashboard
|
|
188
|
+
!creatureCareDashboard ||
|
|
189
|
+
!robotMissionControl
|
|
161
190
|
) {
|
|
162
191
|
throw new Error("Junior Coder module is missing");
|
|
163
192
|
}
|
|
@@ -234,6 +263,10 @@ assertValidMissionAuthoringBundle(
|
|
|
234
263
|
CREATURE_CARE_DASHBOARD_MISSION_ONE_AUTHORING_V1,
|
|
235
264
|
creatureCareDashboard,
|
|
236
265
|
);
|
|
266
|
+
assertValidMissionAuthoringBundle(
|
|
267
|
+
ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1,
|
|
268
|
+
robotMissionControl,
|
|
269
|
+
);
|
|
237
270
|
```
|
|
238
271
|
|
|
239
272
|
## Contract rules
|
|
@@ -294,6 +327,10 @@ assertValidMissionAuthoringBundle(
|
|
|
294
327
|
displays, responsive layouts and equivalent reduced-motion feedback. The
|
|
295
328
|
learner controls the exact accessibility diff; no network, real schedule,
|
|
296
329
|
background task or personal information enters the preview.
|
|
330
|
+
- Robot Mission Control documents commands, a fail-safe state machine, explicit
|
|
331
|
+
confirmation, bounded telemetry and responsive chart/text views. The learner
|
|
332
|
+
controls the exact confirmation diff; Web Serial, physical hardware and
|
|
333
|
+
automatic approval remain outside the simulator.
|
|
297
334
|
|
|
298
335
|
See [the foundation design](docs/design/junior-coder-catalog-foundation.md),
|
|
299
336
|
[the uniform pricing design](docs/design/junior-coder-uniform-pricing.md),
|
|
@@ -310,6 +347,7 @@ See also [TDR 0011](docs/tdrs/tdr-0011-vibe-bug-detective-evidence-led-repair.md
|
|
|
310
347
|
See also [TDR 0012](docs/tdrs/tdr-0012-vibe-idea-studio-bounded-goal-prototyping.md).
|
|
311
348
|
See also [TDR 0013](docs/tdrs/tdr-0013-adventure-mission-planner-private-persistence.md).
|
|
312
349
|
See also [TDR 0014](docs/tdrs/tdr-0014-creature-care-dashboard-bounded-timers-and-motion.md).
|
|
350
|
+
See also [TDR 0015](docs/tdrs/tdr-0015-robot-mission-control-fail-safe-simulation.md).
|
|
313
351
|
|
|
314
352
|
## Development
|
|
315
353
|
|
package/dist/index.cjs
CHANGED
|
@@ -38,18 +38,31 @@ __export(index_exports, {
|
|
|
38
38
|
RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1: () => RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1,
|
|
39
39
|
ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1: () => ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1,
|
|
40
40
|
ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1: () => ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1,
|
|
41
|
+
ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1: () => ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1,
|
|
41
42
|
SERVO_CREATURE_MISSION_ONE_AUTHORING_V1: () => SERVO_CREATURE_MISSION_ONE_AUTHORING_V1,
|
|
42
43
|
SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1: () => SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1,
|
|
43
44
|
STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1: () => STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1,
|
|
45
|
+
STATIC_PROJECT_APPROVAL_STATEMENT_VERSION_V1: () => STATIC_PROJECT_APPROVAL_STATEMENT_VERSION_V1,
|
|
46
|
+
STATIC_PROJECT_DEFAULT_LIFETIME_DAYS_V1: () => STATIC_PROJECT_DEFAULT_LIFETIME_DAYS_V1,
|
|
47
|
+
STATIC_PROJECT_MAX_SOURCE_CHARACTERS_V1: () => STATIC_PROJECT_MAX_SOURCE_CHARACTERS_V1,
|
|
48
|
+
STATIC_PROJECT_PUBLISHING_CONTRACT_VERSION_V1: () => STATIC_PROJECT_PUBLISHING_CONTRACT_VERSION_V1,
|
|
49
|
+
STATIC_PROJECT_SAFETY_CHECK_IDS_V1: () => STATIC_PROJECT_SAFETY_CHECK_IDS_V1,
|
|
50
|
+
STATIC_PROJECT_SCANNER_VERSION_V1: () => STATIC_PROJECT_SCANNER_VERSION_V1,
|
|
44
51
|
VIBE_BUG_DETECTIVE_MISSION_ONE_AUTHORING_V1: () => VIBE_BUG_DETECTIVE_MISSION_ONE_AUTHORING_V1,
|
|
45
52
|
VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1: () => VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1,
|
|
46
53
|
VIBE_IDEA_STUDIO_MISSION_ONE_AUTHORING_V1: () => VIBE_IDEA_STUDIO_MISSION_ONE_AUTHORING_V1,
|
|
47
54
|
assertValidLearningPath: () => assertValidLearningPath,
|
|
48
55
|
assertValidMissionAuthoringBundle: () => assertValidMissionAuthoringBundle,
|
|
56
|
+
assertValidStaticProjectGuardianApproval: () => assertValidStaticProjectGuardianApproval,
|
|
57
|
+
assertValidStaticProjectPublication: () => assertValidStaticProjectPublication,
|
|
58
|
+
assertValidStaticProjectSnapshot: () => assertValidStaticProjectSnapshot,
|
|
49
59
|
calculateAssessment: () => calculateAssessment,
|
|
50
60
|
validateAssessmentRubric: () => validateAssessmentRubric,
|
|
51
61
|
validateLearningPath: () => validateLearningPath,
|
|
52
|
-
validateMissionAuthoringBundle: () => validateMissionAuthoringBundle
|
|
62
|
+
validateMissionAuthoringBundle: () => validateMissionAuthoringBundle,
|
|
63
|
+
validateStaticProjectGuardianApproval: () => validateStaticProjectGuardianApproval,
|
|
64
|
+
validateStaticProjectPublication: () => validateStaticProjectPublication,
|
|
65
|
+
validateStaticProjectSnapshot: () => validateStaticProjectSnapshot
|
|
53
66
|
});
|
|
54
67
|
module.exports = __toCommonJS(index_exports);
|
|
55
68
|
|
|
@@ -626,6 +639,135 @@ var JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1
|
|
|
626
639
|
// src/contracts.ts
|
|
627
640
|
var MISSION_AUTHORING_CONTRACT_VERSION_V1 = "1.0.0";
|
|
628
641
|
|
|
642
|
+
// src/publishing.ts
|
|
643
|
+
var STATIC_PROJECT_PUBLISHING_CONTRACT_VERSION_V1 = "1.0.0";
|
|
644
|
+
var STATIC_PROJECT_SCANNER_VERSION_V1 = "junior-coder-static-scan-v1";
|
|
645
|
+
var STATIC_PROJECT_APPROVAL_STATEMENT_VERSION_V1 = "guardian-static-publication-v1";
|
|
646
|
+
var STATIC_PROJECT_DEFAULT_LIFETIME_DAYS_V1 = 90;
|
|
647
|
+
var STATIC_PROJECT_MAX_SOURCE_CHARACTERS_V1 = 8e3;
|
|
648
|
+
var STATIC_PROJECT_SAFETY_CHECK_IDS_V1 = [
|
|
649
|
+
"allow-listed-source",
|
|
650
|
+
"no-personal-details",
|
|
651
|
+
"no-external-network",
|
|
652
|
+
"no-executable-markup",
|
|
653
|
+
"no-transmitting-forms",
|
|
654
|
+
"no-uploads-or-embeds",
|
|
655
|
+
"no-trackers-or-advertising",
|
|
656
|
+
"no-account-identifiers"
|
|
657
|
+
];
|
|
658
|
+
var DIGEST_PATTERN = /^sha256:[a-f0-9]{64}$/u;
|
|
659
|
+
var IDENTIFIER_PATTERN = /^(?:account|approval|publication|snapshot)_[A-Za-z0-9_-]{20,128}$/u;
|
|
660
|
+
var VERSION_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+(?:[-+][A-Za-z0-9.-]+)?$/u;
|
|
661
|
+
var RANDOM_SLUG_PATTERN = /^[A-Za-z0-9_-]{40,128}$/u;
|
|
662
|
+
function validDate(value) {
|
|
663
|
+
return typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
664
|
+
}
|
|
665
|
+
function allSafetyChecksPresent(scan) {
|
|
666
|
+
if (!Array.isArray(scan.checks) || scan.checks.length !== STATIC_PROJECT_SAFETY_CHECK_IDS_V1.length) {
|
|
667
|
+
return false;
|
|
668
|
+
}
|
|
669
|
+
const supplied = new Set(scan.checks.map((check) => check.id));
|
|
670
|
+
return STATIC_PROJECT_SAFETY_CHECK_IDS_V1.every((id) => supplied.has(id)) && scan.checks.every((check) => check.passed === true);
|
|
671
|
+
}
|
|
672
|
+
function safeAdventureRender(value) {
|
|
673
|
+
const headings = ["Moonbase Missions", "Forest Rescue Plans", "Ocean Quest Board"];
|
|
674
|
+
const titles = ["Find the moon crystal", "Guide the lost firefly", "Map the coral garden"];
|
|
675
|
+
const days = ["Saturday", "Sunday", "School holiday"];
|
|
676
|
+
const messages = ["Choose a day", "Add a mission title", "Mission ready!"];
|
|
677
|
+
return headings.includes(value.heading) && Array.isArray(value.missions) && value.missions.length >= 1 && value.missions.length <= 3 && value.missions.every((mission2) => titles.includes(mission2.title) && days.includes(mission2.day)) && messages.includes(value.validationMessage) && value.savedAcrossRestart === true && value.accessibleSummaryEnabled === true;
|
|
678
|
+
}
|
|
679
|
+
function safeCreatureRender(value) {
|
|
680
|
+
return ["Moon Moth", "Cloud Cat", "Pebble Dragon"].includes(value.creature) && ["Resting", "Ready to play", "Snack time"].includes(value.status) && [5, 10, 15].includes(value.timerSeconds) && ["single", "cosy-grid", "wide-grid"].includes(value.layout) && value.reducedMotion === true;
|
|
681
|
+
}
|
|
682
|
+
function safeRobotRender(value) {
|
|
683
|
+
return ["scan", "hold-position", "return-to-base"].includes(value.command) && value.safetyConfirmed === true && [1, 2, 4].includes(value.telemetryRate) && ["line", "bars", "text-only"].includes(value.chartMode) && value.serialSimulation === true && ["SCANNING", "HOLDING", "RETURNING"].includes(value.state);
|
|
684
|
+
}
|
|
685
|
+
function validateStaticProjectSnapshot(value) {
|
|
686
|
+
const issues = [];
|
|
687
|
+
if (value.schemaVersion !== "1") issues.push("invalid-schema-version");
|
|
688
|
+
if (value.contractVersion !== STATIC_PROJECT_PUBLISHING_CONTRACT_VERSION_V1) {
|
|
689
|
+
issues.push("invalid-contract-version");
|
|
690
|
+
}
|
|
691
|
+
if (!IDENTIFIER_PATTERN.test(value.snapshotId) || !IDENTIFIER_PATTERN.test(value.subjectAccountId)) {
|
|
692
|
+
issues.push("invalid-identifier");
|
|
693
|
+
}
|
|
694
|
+
if (!value.moduleId.startsWith("junior-coder.") || value.moduleId !== `junior-coder.${value.moduleSlug}`) {
|
|
695
|
+
issues.push("invalid-module");
|
|
696
|
+
}
|
|
697
|
+
if (!VERSION_PATTERN.test(value.moduleVersion)) issues.push("invalid-version");
|
|
698
|
+
if (!DIGEST_PATTERN.test(value.sourceDigest)) issues.push("invalid-source-digest");
|
|
699
|
+
if (!DIGEST_PATTERN.test(value.snapshotDigest)) issues.push("invalid-snapshot-digest");
|
|
700
|
+
if (!Number.isInteger(value.sourceCharacterCount) || value.sourceCharacterCount < 1 || value.sourceCharacterCount > STATIC_PROJECT_MAX_SOURCE_CHARACTERS_V1) {
|
|
701
|
+
issues.push("invalid-source-size");
|
|
702
|
+
}
|
|
703
|
+
if (!Number.isInteger(value.assessmentScore) || value.assessmentScore < 80 || value.assessmentScore > 100) {
|
|
704
|
+
issues.push("assessment-score-incomplete");
|
|
705
|
+
}
|
|
706
|
+
if (value.mandatorySafetyPassed !== true) issues.push("mandatory-safety-missing");
|
|
707
|
+
if (value.scan?.passed !== true || value.scan?.scannerVersion !== STATIC_PROJECT_SCANNER_VERSION_V1) {
|
|
708
|
+
issues.push("scan-not-passed");
|
|
709
|
+
}
|
|
710
|
+
if (!value.scan || !allSafetyChecksPresent(value.scan)) issues.push("scan-checks-incomplete");
|
|
711
|
+
if (value.moduleSlug !== value.renderModel?.kind) issues.push("module-render-model-mismatch");
|
|
712
|
+
const renderSafe = value.renderModel?.kind === "adventure-mission-planner" ? safeAdventureRender(value.renderModel) : value.renderModel?.kind === "creature-care-dashboard" ? safeCreatureRender(value.renderModel) : value.renderModel?.kind === "robot-mission-control" ? safeRobotRender(value.renderModel) : false;
|
|
713
|
+
if (!renderSafe) issues.push("unsafe-render-model");
|
|
714
|
+
if (value.state !== "pending-review" || !validDate(value.createdAt)) issues.push("invalid-created-at");
|
|
715
|
+
return [...new Set(issues)];
|
|
716
|
+
}
|
|
717
|
+
function assertValidStaticProjectSnapshot(value) {
|
|
718
|
+
const issues = validateStaticProjectSnapshot(value);
|
|
719
|
+
if (issues.length > 0) throw new Error(`Invalid static project snapshot: ${issues.join(", ")}`);
|
|
720
|
+
}
|
|
721
|
+
function validateStaticProjectGuardianApproval(value) {
|
|
722
|
+
const issues = [];
|
|
723
|
+
if (value.schemaVersion !== "1") issues.push("invalid-schema-version");
|
|
724
|
+
if (!IDENTIFIER_PATTERN.test(value.approvalId) || !IDENTIFIER_PATTERN.test(value.snapshotId) || !IDENTIFIER_PATTERN.test(value.guardianActorAccountId)) {
|
|
725
|
+
issues.push("invalid-identifier");
|
|
726
|
+
}
|
|
727
|
+
if (!DIGEST_PATTERN.test(value.snapshotDigest)) issues.push("invalid-snapshot-digest");
|
|
728
|
+
if (value.statementVersion !== STATIC_PROJECT_APPROVAL_STATEMENT_VERSION_V1) {
|
|
729
|
+
issues.push("invalid-approval-statement");
|
|
730
|
+
}
|
|
731
|
+
if (!validDate(value.approvedAt)) issues.push("invalid-approved-at");
|
|
732
|
+
return [...new Set(issues)];
|
|
733
|
+
}
|
|
734
|
+
function assertValidStaticProjectGuardianApproval(value) {
|
|
735
|
+
const issues = validateStaticProjectGuardianApproval(value);
|
|
736
|
+
if (issues.length > 0) throw new Error(`Invalid static project approval: ${issues.join(", ")}`);
|
|
737
|
+
}
|
|
738
|
+
function validateStaticProjectPublication(value) {
|
|
739
|
+
const issues = [];
|
|
740
|
+
if (value.schemaVersion !== "1") issues.push("invalid-schema-version");
|
|
741
|
+
if (!IDENTIFIER_PATTERN.test(value.publicationId) || !IDENTIFIER_PATTERN.test(value.snapshotId) || !IDENTIFIER_PATTERN.test(value.approvalId)) {
|
|
742
|
+
issues.push("invalid-identifier");
|
|
743
|
+
}
|
|
744
|
+
if (!DIGEST_PATTERN.test(value.snapshotDigest)) issues.push("invalid-snapshot-digest");
|
|
745
|
+
if (!RANDOM_SLUG_PATTERN.test(value.randomSlug)) issues.push("invalid-random-slug");
|
|
746
|
+
let parsedUrl;
|
|
747
|
+
try {
|
|
748
|
+
parsedUrl = new URL(value.publicUrl);
|
|
749
|
+
} catch {
|
|
750
|
+
parsedUrl = void 0;
|
|
751
|
+
}
|
|
752
|
+
if (!parsedUrl || parsedUrl.protocol !== "https:" || parsedUrl.username || parsedUrl.password) {
|
|
753
|
+
issues.push("invalid-public-url");
|
|
754
|
+
}
|
|
755
|
+
if (!parsedUrl?.pathname.endsWith(`/${value.randomSlug}`)) issues.push("public-url-slug-mismatch");
|
|
756
|
+
if (value.state !== "published") issues.push("published-state-required");
|
|
757
|
+
if (!validDate(value.publishedAt)) issues.push("invalid-published-at");
|
|
758
|
+
if (!validDate(value.expiresAt) || validDate(value.publishedAt) && Date.parse(value.expiresAt) <= Date.parse(value.publishedAt)) {
|
|
759
|
+
issues.push("invalid-publication-expiry");
|
|
760
|
+
}
|
|
761
|
+
if (value.renewedAt !== void 0 && !validDate(value.renewedAt) || value.unpublishedAt !== void 0 && !validDate(value.unpublishedAt)) {
|
|
762
|
+
issues.push("invalid-lifecycle-timestamp");
|
|
763
|
+
}
|
|
764
|
+
return [...new Set(issues)];
|
|
765
|
+
}
|
|
766
|
+
function assertValidStaticProjectPublication(value) {
|
|
767
|
+
const issues = validateStaticProjectPublication(value);
|
|
768
|
+
if (issues.length > 0) throw new Error(`Invalid static project publication: ${issues.join(", ")}`);
|
|
769
|
+
}
|
|
770
|
+
|
|
629
771
|
// src/rubric-validation.ts
|
|
630
772
|
var DIMENSION_TOTALS = {
|
|
631
773
|
structure: 20,
|
|
@@ -5770,6 +5912,287 @@ var CREATURE_CARE_DASHBOARD_MISSION_ONE_AUTHORING_V1 = {
|
|
|
5770
5912
|
]
|
|
5771
5913
|
}
|
|
5772
5914
|
};
|
|
5915
|
+
var ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1 = {
|
|
5916
|
+
version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
|
|
5917
|
+
moduleId: "junior-coder.robot-mission-control",
|
|
5918
|
+
moduleVersion: "1.1.0",
|
|
5919
|
+
missionId: "robot-mission-control-mission-1",
|
|
5920
|
+
learner: {
|
|
5921
|
+
estimatedMinutes: 20,
|
|
5922
|
+
stages: [
|
|
5923
|
+
{
|
|
5924
|
+
kind: "learn",
|
|
5925
|
+
instruction: "Read how commands, a fail-safe state machine, confirmations, telemetry charts and the five documented functions build a simulated mission-control panel.",
|
|
5926
|
+
artifactIds: ["robot-mission-control-m1-guide"]
|
|
5927
|
+
},
|
|
5928
|
+
{
|
|
5929
|
+
kind: "predict",
|
|
5930
|
+
instruction: "Predict whether a planned command may leave STOP when the safety confirmation is disabled.",
|
|
5931
|
+
artifactIds: ["robot-mission-control-m1-command-cards"]
|
|
5932
|
+
},
|
|
5933
|
+
{
|
|
5934
|
+
kind: "build",
|
|
5935
|
+
instruction: "Change only the supplied command, confirmation, telemetry rate, chart mode and serial-simulation settings.",
|
|
5936
|
+
artifactIds: ["robot-mission-control-m1-code"]
|
|
5937
|
+
},
|
|
5938
|
+
{
|
|
5939
|
+
kind: "run",
|
|
5940
|
+
instruction: "Use the action-icon Run button to update the private simulated controls, chart and text telemetry.",
|
|
5941
|
+
artifactIds: ["robot-mission-control-m1-code"]
|
|
5942
|
+
},
|
|
5943
|
+
{
|
|
5944
|
+
kind: "assess",
|
|
5945
|
+
instruction: "Run deterministic command, state-machine, safety-confirmation, telemetry and responsive-layout checks.",
|
|
5946
|
+
artifactIds: []
|
|
5947
|
+
},
|
|
5948
|
+
{
|
|
5949
|
+
kind: "inspect",
|
|
5950
|
+
instruction: "Compare the observed STOP state with the planned command and highlighted safety-confirmation setting.",
|
|
5951
|
+
artifactIds: ["robot-mission-control-m1-code"]
|
|
5952
|
+
},
|
|
5953
|
+
{
|
|
5954
|
+
kind: "fix",
|
|
5955
|
+
instruction: "Review and accept or reject the exact safety-confirmation change yourself, then rerun every check.",
|
|
5956
|
+
artifactIds: ["robot-mission-control-m1-code"]
|
|
5957
|
+
},
|
|
5958
|
+
{
|
|
5959
|
+
kind: "explain",
|
|
5960
|
+
instruction: "Explain how confirmation changes the state machine and why the chart and text telemetry must agree.",
|
|
5961
|
+
artifactIds: []
|
|
5962
|
+
},
|
|
5963
|
+
{
|
|
5964
|
+
kind: "reward",
|
|
5965
|
+
instruction: "Collect the evidence-bound mission-control badge after the score reaches 80 and every mandatory STOP test passes.",
|
|
5966
|
+
artifactIds: []
|
|
5967
|
+
}
|
|
5968
|
+
],
|
|
5969
|
+
readinessChecks: [
|
|
5970
|
+
{
|
|
5971
|
+
id: "robot-mission-control-m1-stop-check",
|
|
5972
|
+
prompt: "Find the planned command, current STOP state, confirmation and text telemetry before running the simulator.",
|
|
5973
|
+
scored: false
|
|
5974
|
+
}
|
|
5975
|
+
],
|
|
5976
|
+
artifacts: [
|
|
5977
|
+
{
|
|
5978
|
+
id: "robot-mission-control-m1-code",
|
|
5979
|
+
kind: "starter-code",
|
|
5980
|
+
audience: "learner",
|
|
5981
|
+
solutionBearing: false
|
|
5982
|
+
},
|
|
5983
|
+
{
|
|
5984
|
+
id: "robot-mission-control-m1-guide",
|
|
5985
|
+
kind: "starter-assets",
|
|
5986
|
+
audience: "learner",
|
|
5987
|
+
solutionBearing: false
|
|
5988
|
+
},
|
|
5989
|
+
{
|
|
5990
|
+
id: "robot-mission-control-m1-command-cards",
|
|
5991
|
+
kind: "sample-data",
|
|
5992
|
+
audience: "learner",
|
|
5993
|
+
solutionBearing: false
|
|
5994
|
+
}
|
|
5995
|
+
],
|
|
5996
|
+
goals: [
|
|
5997
|
+
{
|
|
5998
|
+
id: "robot-mission-control-m1-starts",
|
|
5999
|
+
statement: "The responsive control component, chart and text telemetry build with a valid simulated command state machine.",
|
|
6000
|
+
visibility: "visible",
|
|
6001
|
+
criterionIds: ["robot-mission-control-build"],
|
|
6002
|
+
completionRequired: true,
|
|
6003
|
+
aiRequired: false
|
|
6004
|
+
},
|
|
6005
|
+
{
|
|
6006
|
+
id: "robot-mission-control-m1-behaviour",
|
|
6007
|
+
statement: "A confirmed command moves the state machine from STOP and updates the chart and serial simulation with matching bounded telemetry.",
|
|
6008
|
+
visibility: "visible",
|
|
6009
|
+
criterionIds: [
|
|
6010
|
+
"robot-mission-control-goal-one",
|
|
6011
|
+
"robot-mission-control-goal-two",
|
|
6012
|
+
"robot-mission-control-goal-three"
|
|
6013
|
+
],
|
|
6014
|
+
completionRequired: true,
|
|
6015
|
+
aiRequired: false
|
|
6016
|
+
},
|
|
6017
|
+
{
|
|
6018
|
+
id: "robot-mission-control-m1-safe-private",
|
|
6019
|
+
statement: "Without confirmation the simulator stays in STOP, exposes responsive text telemetry and never opens a real serial port or controls hardware.",
|
|
6020
|
+
visibility: "visible",
|
|
6021
|
+
criterionIds: ["robot-mission-control-safety"],
|
|
6022
|
+
completionRequired: true,
|
|
6023
|
+
aiRequired: false
|
|
6024
|
+
}
|
|
6025
|
+
],
|
|
6026
|
+
interactions: [
|
|
6027
|
+
{
|
|
6028
|
+
id: "robot-mission-control-m1-editor",
|
|
6029
|
+
description: "Edit the five documented mission-control calls using keyboard or pointer controls.",
|
|
6030
|
+
primaryMode: "keyboard",
|
|
6031
|
+
alternativeIds: []
|
|
6032
|
+
},
|
|
6033
|
+
{
|
|
6034
|
+
id: "robot-mission-control-m1-run",
|
|
6035
|
+
description: "Activate the labelled action-icon Run control.",
|
|
6036
|
+
primaryMode: "pointer",
|
|
6037
|
+
alternativeIds: ["robot-mission-control-m1-keyboard-run"]
|
|
6038
|
+
},
|
|
6039
|
+
{
|
|
6040
|
+
id: "robot-mission-control-m1-review",
|
|
6041
|
+
description: "Review and accept or reject the exact labelled safety diff.",
|
|
6042
|
+
primaryMode: "keyboard",
|
|
6043
|
+
alternativeIds: []
|
|
6044
|
+
}
|
|
6045
|
+
],
|
|
6046
|
+
accessibilityAlternatives: [
|
|
6047
|
+
{
|
|
6048
|
+
id: "robot-mission-control-m1-keyboard-run",
|
|
6049
|
+
description: "Focus the Run action button and press Enter or Space to produce the same controls, chart and text telemetry.",
|
|
6050
|
+
modes: ["keyboard"],
|
|
6051
|
+
equivalentOutcome: true
|
|
6052
|
+
}
|
|
6053
|
+
],
|
|
6054
|
+
evidenceRequirements: [
|
|
6055
|
+
{
|
|
6056
|
+
id: "robot-mission-control-m1-assessment",
|
|
6057
|
+
goalIds: [
|
|
6058
|
+
"robot-mission-control-m1-starts",
|
|
6059
|
+
"robot-mission-control-m1-behaviour",
|
|
6060
|
+
"robot-mission-control-m1-safe-private"
|
|
6061
|
+
],
|
|
6062
|
+
kind: "assessment-result",
|
|
6063
|
+
retention: "entitlement",
|
|
6064
|
+
containsPersonalData: false
|
|
6065
|
+
},
|
|
6066
|
+
{
|
|
6067
|
+
id: "robot-mission-control-m1-explanation",
|
|
6068
|
+
goalIds: ["robot-mission-control-m1-safe-private"],
|
|
6069
|
+
kind: "learner-explanation",
|
|
6070
|
+
retention: "attempt",
|
|
6071
|
+
containsPersonalData: false
|
|
6072
|
+
}
|
|
6073
|
+
],
|
|
6074
|
+
sideAdventures: [
|
|
6075
|
+
{
|
|
6076
|
+
id: "robot-mission-control-m1-remix",
|
|
6077
|
+
prompt: "Choose another supplied command or chart mode and explain which confirmation and STOP evidence must remain.",
|
|
6078
|
+
completionRequired: false
|
|
6079
|
+
}
|
|
6080
|
+
],
|
|
6081
|
+
rewardBindings: [
|
|
6082
|
+
{
|
|
6083
|
+
id: "robot-mission-control-m1-badge",
|
|
6084
|
+
badgeId: "robot-mission-control-mission-complete",
|
|
6085
|
+
goalIds: [
|
|
6086
|
+
"robot-mission-control-m1-starts",
|
|
6087
|
+
"robot-mission-control-m1-behaviour",
|
|
6088
|
+
"robot-mission-control-m1-safe-private"
|
|
6089
|
+
],
|
|
6090
|
+
deterministic: true,
|
|
6091
|
+
random: false,
|
|
6092
|
+
tokenConvertible: false
|
|
6093
|
+
}
|
|
6094
|
+
],
|
|
6095
|
+
functionReference: [
|
|
6096
|
+
{
|
|
6097
|
+
id: "robot-mission-control-function-command",
|
|
6098
|
+
signature: "planCommand(command)",
|
|
6099
|
+
summary: "Plans one supplied command for the simulated robot state machine.",
|
|
6100
|
+
parameters: [{ name: "command", type: "text", description: "Use scan, hold-position or return-to-base." }],
|
|
6101
|
+
effect: "Updates the planned-command panel but cannot leave STOP without confirmation.",
|
|
6102
|
+
example: 'planCommand("scan");'
|
|
6103
|
+
},
|
|
6104
|
+
{
|
|
6105
|
+
id: "robot-mission-control-function-confirmation",
|
|
6106
|
+
signature: "setSafetyConfirmation(enabled)",
|
|
6107
|
+
summary: "Controls whether the planned simulated command has explicit safety confirmation.",
|
|
6108
|
+
parameters: [{ name: "enabled", type: "Boolean", description: "Use true only after checking the planned command." }],
|
|
6109
|
+
effect: "Allows the simulator state machine to leave STOP; it never approves or controls physical hardware.",
|
|
6110
|
+
example: "setSafetyConfirmation(true);"
|
|
6111
|
+
},
|
|
6112
|
+
{
|
|
6113
|
+
id: "robot-mission-control-function-rate",
|
|
6114
|
+
signature: "setTelemetryRate(samplesPerSecond)",
|
|
6115
|
+
summary: "Sets a bounded simulated telemetry sampling rate.",
|
|
6116
|
+
parameters: [{ name: "samplesPerSecond", type: "number", description: "Use 1, 2 or 4 simulated samples per second." }],
|
|
6117
|
+
effect: "Changes bounded chart and text sample spacing without starting background work.",
|
|
6118
|
+
example: "setTelemetryRate(2);"
|
|
6119
|
+
},
|
|
6120
|
+
{
|
|
6121
|
+
id: "robot-mission-control-function-chart",
|
|
6122
|
+
signature: "setChartMode(mode)",
|
|
6123
|
+
summary: "Chooses one supplied responsive telemetry presentation.",
|
|
6124
|
+
parameters: [{ name: "mode", type: "text", description: "Use line, bars or text-only." }],
|
|
6125
|
+
effect: "Changes the preview chart while preserving equivalent labelled text telemetry.",
|
|
6126
|
+
example: 'setChartMode("line");'
|
|
6127
|
+
},
|
|
6128
|
+
{
|
|
6129
|
+
id: "robot-mission-control-function-serial",
|
|
6130
|
+
signature: "simulateSerial(enabled)",
|
|
6131
|
+
summary: "Turns the bounded serial-message simulator on or off.",
|
|
6132
|
+
parameters: [{ name: "enabled", type: "Boolean", description: "Use true to show simulated messages." }],
|
|
6133
|
+
effect: "Produces labelled local simulator messages; it never opens Web Serial or a physical connection.",
|
|
6134
|
+
example: "simulateSerial(true);"
|
|
6135
|
+
}
|
|
6136
|
+
],
|
|
6137
|
+
boundedSuggestion: {
|
|
6138
|
+
id: "robot-mission-control-m1-confirmation-diff",
|
|
6139
|
+
source: "authored-fallback",
|
|
6140
|
+
intent: "Confirm the supplied simulated command before the state machine leaves STOP.",
|
|
6141
|
+
constraints: [
|
|
6142
|
+
"Change exactly one documented safety-confirmation setting.",
|
|
6143
|
+
"Preserve the supplied command, telemetry rate, chart mode, serial simulation and text telemetry.",
|
|
6144
|
+
"Do not add Web Serial, network, external scripts, hardware control, personal data or automatic approval."
|
|
6145
|
+
],
|
|
6146
|
+
permittedArtifactId: "robot-mission-control-m1-code",
|
|
6147
|
+
originalSnippet: "setSafetyConfirmation(false);",
|
|
6148
|
+
replacementSnippet: "setSafetyConfirmation(true);",
|
|
6149
|
+
explanationPrompt: "Which state-machine transition became possible, and what keeps the exercise separate from physical hardware?",
|
|
6150
|
+
aiOptional: false,
|
|
6151
|
+
learnerApprovalRequired: true,
|
|
6152
|
+
alternatives: ["accept", "reject"]
|
|
6153
|
+
}
|
|
6154
|
+
},
|
|
6155
|
+
facilitator: {
|
|
6156
|
+
artifacts: [
|
|
6157
|
+
{
|
|
6158
|
+
id: "robot-mission-control-m1-answer-key",
|
|
6159
|
+
kind: "answer-key",
|
|
6160
|
+
audience: "facilitator",
|
|
6161
|
+
solutionBearing: true
|
|
6162
|
+
},
|
|
6163
|
+
{
|
|
6164
|
+
id: "robot-mission-control-m1-protected-tests",
|
|
6165
|
+
kind: "protected-test",
|
|
6166
|
+
audience: "facilitator",
|
|
6167
|
+
solutionBearing: true
|
|
6168
|
+
},
|
|
6169
|
+
{
|
|
6170
|
+
id: "robot-mission-control-m1-safety-notes",
|
|
6171
|
+
kind: "facilitator-note",
|
|
6172
|
+
audience: "facilitator",
|
|
6173
|
+
solutionBearing: true
|
|
6174
|
+
}
|
|
6175
|
+
],
|
|
6176
|
+
protectedGoals: [
|
|
6177
|
+
{
|
|
6178
|
+
id: "robot-mission-control-m1-protected-boundary",
|
|
6179
|
+
statement: "The dashboard rejects arbitrary commands, invalid rates, scripts, network access, Web Serial, hardware control, personal data and any unconfirmed transition away from STOP.",
|
|
6180
|
+
visibility: "protected",
|
|
6181
|
+
criterionIds: [
|
|
6182
|
+
"robot-mission-control-edge-one",
|
|
6183
|
+
"robot-mission-control-edge-two"
|
|
6184
|
+
],
|
|
6185
|
+
completionRequired: false,
|
|
6186
|
+
aiRequired: false
|
|
6187
|
+
}
|
|
6188
|
+
],
|
|
6189
|
+
prompts: [
|
|
6190
|
+
"Ask the learner to identify the planned command, current state, confirmation and equivalent text telemetry before suggesting a change.",
|
|
6191
|
+
"Keep every command and message inside the simulator; the website never opens serial or controls hardware.",
|
|
6192
|
+
"Reject must preserve source, and provider failure must never block deterministic completion."
|
|
6193
|
+
]
|
|
6194
|
+
}
|
|
6195
|
+
};
|
|
5773
6196
|
var ADVENTURE_MISSION_PLANNER_MISSION_ONE_AUTHORING_V1 = {
|
|
5774
6197
|
version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
|
|
5775
6198
|
moduleId: "junior-coder.adventure-mission-planner",
|
|
@@ -6421,17 +6844,30 @@ ${summary}`);
|
|
|
6421
6844
|
RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1,
|
|
6422
6845
|
ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1,
|
|
6423
6846
|
ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1,
|
|
6847
|
+
ROBOT_MISSION_CONTROL_MISSION_ONE_AUTHORING_V1,
|
|
6424
6848
|
SERVO_CREATURE_MISSION_ONE_AUTHORING_V1,
|
|
6425
6849
|
SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1,
|
|
6426
6850
|
STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1,
|
|
6851
|
+
STATIC_PROJECT_APPROVAL_STATEMENT_VERSION_V1,
|
|
6852
|
+
STATIC_PROJECT_DEFAULT_LIFETIME_DAYS_V1,
|
|
6853
|
+
STATIC_PROJECT_MAX_SOURCE_CHARACTERS_V1,
|
|
6854
|
+
STATIC_PROJECT_PUBLISHING_CONTRACT_VERSION_V1,
|
|
6855
|
+
STATIC_PROJECT_SAFETY_CHECK_IDS_V1,
|
|
6856
|
+
STATIC_PROJECT_SCANNER_VERSION_V1,
|
|
6427
6857
|
VIBE_BUG_DETECTIVE_MISSION_ONE_AUTHORING_V1,
|
|
6428
6858
|
VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1,
|
|
6429
6859
|
VIBE_IDEA_STUDIO_MISSION_ONE_AUTHORING_V1,
|
|
6430
6860
|
assertValidLearningPath,
|
|
6431
6861
|
assertValidMissionAuthoringBundle,
|
|
6862
|
+
assertValidStaticProjectGuardianApproval,
|
|
6863
|
+
assertValidStaticProjectPublication,
|
|
6864
|
+
assertValidStaticProjectSnapshot,
|
|
6432
6865
|
calculateAssessment,
|
|
6433
6866
|
validateAssessmentRubric,
|
|
6434
6867
|
validateLearningPath,
|
|
6435
|
-
validateMissionAuthoringBundle
|
|
6868
|
+
validateMissionAuthoringBundle,
|
|
6869
|
+
validateStaticProjectGuardianApproval,
|
|
6870
|
+
validateStaticProjectPublication,
|
|
6871
|
+
validateStaticProjectSnapshot
|
|
6436
6872
|
});
|
|
6437
6873
|
//# sourceMappingURL=index.cjs.map
|