@plasius/learning 0.2.8 → 0.2.9
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 +18 -2
- package/dist/index.cjs +495 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -2
- package/dist/index.d.ts +63 -2
- package/dist/index.js +494 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,6 +62,7 @@ the exact catalog module that owns its rubric, mission and badges.
|
|
|
62
62
|
|
|
63
63
|
```ts
|
|
64
64
|
import {
|
|
65
|
+
BEACON_BOT_MISSION_ONE_AUTHORING_V1,
|
|
65
66
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1,
|
|
66
67
|
METEOR_SHIELD_MISSION_ONE_AUTHORING_V1,
|
|
67
68
|
PADDLE_PULSE_MISSION_ONE_AUTHORING_V1,
|
|
@@ -98,6 +99,9 @@ const pixelTrailChallenge = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
|
|
|
98
99
|
const starDefenderSquadron = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
|
|
99
100
|
(module) => module.slug === "star-defender-squadron",
|
|
100
101
|
);
|
|
102
|
+
const beaconBot = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
|
|
103
|
+
(module) => module.slug === "beacon-bot",
|
|
104
|
+
);
|
|
101
105
|
|
|
102
106
|
if (
|
|
103
107
|
!roadHopper ||
|
|
@@ -107,7 +111,8 @@ if (
|
|
|
107
111
|
!meteorShield ||
|
|
108
112
|
!rescueCrewCommander ||
|
|
109
113
|
!pixelTrailChallenge ||
|
|
110
|
-
!starDefenderSquadron
|
|
114
|
+
!starDefenderSquadron ||
|
|
115
|
+
!beaconBot
|
|
111
116
|
) {
|
|
112
117
|
throw new Error("Junior Coder module is missing");
|
|
113
118
|
}
|
|
@@ -144,6 +149,10 @@ assertValidMissionAuthoringBundle(
|
|
|
144
149
|
STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1,
|
|
145
150
|
starDefenderSquadron,
|
|
146
151
|
);
|
|
152
|
+
assertValidMissionAuthoringBundle(
|
|
153
|
+
BEACON_BOT_MISSION_ONE_AUTHORING_V1,
|
|
154
|
+
beaconBot,
|
|
155
|
+
);
|
|
147
156
|
```
|
|
148
157
|
|
|
149
158
|
## Contract rules
|
|
@@ -166,13 +175,20 @@ assertValidMissionAuthoringBundle(
|
|
|
166
175
|
- Completion requires a score of at least 80 and every mandatory criterion.
|
|
167
176
|
- Module agents may explain evidence and propose a bounded next step, but cannot assign scores or rewards.
|
|
168
177
|
- Physical requirements are disclosed by a versioned manifest before purchase.
|
|
178
|
+
- Robotics authoring distinguishes the complete reusable path kit from the
|
|
179
|
+
module's incremental items. Each component carries verification,
|
|
180
|
+
compatibility-claim and physical-completion status.
|
|
181
|
+
- Unverified components cannot claim compatibility or physical completion.
|
|
182
|
+
Simulator completion remains separate; physical export and its distinct
|
|
183
|
+
badge require adult acknowledgement and evidence.
|
|
169
184
|
|
|
170
185
|
See [the foundation design](docs/design/junior-coder-catalog-foundation.md),
|
|
171
186
|
[the uniform pricing design](docs/design/junior-coder-uniform-pricing.md),
|
|
172
187
|
[the mission authoring design](docs/design/junior-coder-mission-authoring.md),
|
|
173
188
|
[ADR 0001](docs/adrs/adr-0001-learning-domain-and-catalog-boundary.md), and
|
|
174
189
|
[ADR 0002](docs/adrs/adr-0002-immutable-module-repricing-and-admin-test-source.md),
|
|
175
|
-
|
|
190
|
+
[ADR 0003](docs/adrs/adr-0003-mission-authoring-manifests-are-additive-and-separated.md),
|
|
191
|
+
and [ADR 0004](docs/adrs/adr-0004-robot-mission-hardware-disclosures-are-additive-and-fail-closed.md).
|
|
176
192
|
|
|
177
193
|
## Development
|
|
178
194
|
|
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
BEACON_BOT_MISSION_ONE_AUTHORING_V1: () => BEACON_BOT_MISSION_ONE_AUTHORING_V1,
|
|
23
24
|
JUNIOR_CODER_MISSION_STAGE_ORDER_V1: () => JUNIOR_CODER_MISSION_STAGE_ORDER_V1,
|
|
24
25
|
JUNIOR_CODER_MODULE_PRICE_V1_1: () => JUNIOR_CODER_MODULE_PRICE_V1_1,
|
|
25
26
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT: () => JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT,
|
|
@@ -1124,6 +1125,112 @@ function validateMissionAuthoringBundle(bundle, module3) {
|
|
|
1124
1125
|
);
|
|
1125
1126
|
}
|
|
1126
1127
|
}
|
|
1128
|
+
if (learner.functionReference) {
|
|
1129
|
+
const functionIds = new Set(
|
|
1130
|
+
learner.functionReference.map((entry) => entry.id)
|
|
1131
|
+
);
|
|
1132
|
+
const invalidFunctionReference = functionIds.size !== learner.functionReference.length || learner.functionReference.length === 0 || learner.functionReference.some((entry) => {
|
|
1133
|
+
const parameterNames = new Set(
|
|
1134
|
+
entry.parameters.map((parameter) => parameter.name)
|
|
1135
|
+
);
|
|
1136
|
+
return entry.id.trim().length === 0 || entry.signature.trim().length === 0 || entry.summary.trim().length === 0 || entry.effect.trim().length === 0 || entry.example.trim().length === 0 || parameterNames.size !== entry.parameters.length || entry.parameters.some(
|
|
1137
|
+
(parameter) => parameter.name.trim().length === 0 || parameter.type.trim().length === 0 || parameter.description.trim().length === 0
|
|
1138
|
+
);
|
|
1139
|
+
});
|
|
1140
|
+
if (invalidFunctionReference) {
|
|
1141
|
+
issues.push(
|
|
1142
|
+
authoringIssue(
|
|
1143
|
+
"invalid-function-reference",
|
|
1144
|
+
"Function references require unique IDs, signatures, parameters, effects and examples.",
|
|
1145
|
+
"learner.functionReference"
|
|
1146
|
+
)
|
|
1147
|
+
);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
const hardware = bundle.hardware;
|
|
1151
|
+
if (hardware) {
|
|
1152
|
+
if (module3.category !== "robot" || module3.hardware.mode !== "physical-first" || !module3.hardware.simulatorAvailable) {
|
|
1153
|
+
issues.push(
|
|
1154
|
+
authoringIssue(
|
|
1155
|
+
"hardware-module-mismatch",
|
|
1156
|
+
"Mission hardware disclosure requires a simulator-backed physical robot module.",
|
|
1157
|
+
"hardware"
|
|
1158
|
+
)
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
if (hardware.requirementsVersion !== module3.hardware.requirementsVersion) {
|
|
1162
|
+
issues.push(
|
|
1163
|
+
authoringIssue(
|
|
1164
|
+
"hardware-requirements-version-mismatch",
|
|
1165
|
+
`Hardware disclosure ${hardware.requirementsVersion} does not match catalog requirements ${module3.hardware.requirementsVersion}.`,
|
|
1166
|
+
"hardware.requirementsVersion"
|
|
1167
|
+
)
|
|
1168
|
+
);
|
|
1169
|
+
}
|
|
1170
|
+
const catalogHardwareById = new Map(
|
|
1171
|
+
module3.hardware.items.map((item) => [item.id, item])
|
|
1172
|
+
);
|
|
1173
|
+
const completePathIds = new Set(hardware.completePathItemIds);
|
|
1174
|
+
const incrementalIds = new Set(hardware.incrementalItemIds);
|
|
1175
|
+
const componentIds = new Set(hardware.components.map((component) => component.itemId));
|
|
1176
|
+
const catalogIds = new Set(catalogHardwareById.keys());
|
|
1177
|
+
const hasDuplicateHardwareIds = completePathIds.size !== hardware.completePathItemIds.length || incrementalIds.size !== hardware.incrementalItemIds.length || componentIds.size !== hardware.components.length;
|
|
1178
|
+
const hasUnknownOrMissingItems = hasDuplicateHardwareIds || completePathIds.size !== catalogIds.size || componentIds.size !== catalogIds.size || [...catalogIds].some(
|
|
1179
|
+
(itemId) => !completePathIds.has(itemId) || !componentIds.has(itemId)
|
|
1180
|
+
) || [...incrementalIds].some((itemId) => !catalogIds.has(itemId));
|
|
1181
|
+
const hasMismatchedComponent = hardware.components.some((component) => {
|
|
1182
|
+
const catalogItem = catalogHardwareById.get(component.itemId);
|
|
1183
|
+
const expectedScope = incrementalIds.has(component.itemId) ? "incremental" : "complete-path";
|
|
1184
|
+
return !catalogItem || component.quantity !== catalogItem.quantity || component.acquisitionScope !== expectedScope;
|
|
1185
|
+
});
|
|
1186
|
+
if (hasUnknownOrMissingItems || hasMismatchedComponent) {
|
|
1187
|
+
issues.push(
|
|
1188
|
+
authoringIssue(
|
|
1189
|
+
"hardware-item-mismatch",
|
|
1190
|
+
"Complete, incremental and per-component hardware disclosures must match the immutable catalog manifest.",
|
|
1191
|
+
"hardware.components"
|
|
1192
|
+
)
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
if (hardware.components.some(
|
|
1196
|
+
(component) => component.verificationStatus !== "verified" && component.compatibilityClaimed
|
|
1197
|
+
) || module3.hardware.verificationStatus !== "verified" && !module3.hardware.publicSaleBlocked) {
|
|
1198
|
+
issues.push(
|
|
1199
|
+
authoringIssue(
|
|
1200
|
+
"hardware-verification-claim",
|
|
1201
|
+
"Unverified hardware cannot claim compatibility or unblock public physical sale.",
|
|
1202
|
+
"hardware.components"
|
|
1203
|
+
)
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
1206
|
+
const safeguards = hardware.safeguards;
|
|
1207
|
+
if (safeguards.adultAssemblyRequired !== true || safeguards.adultAcknowledgementRequiredForExport !== true || safeguards.websiteMayControlHardware !== false || safeguards.simulatorCompletionAvailable !== true || safeguards.physicalBadgeRequiresAdultSignoff !== true || safeguards.adultAssemblySteps.length === 0 || safeguards.powerRequirements.length === 0 || safeguards.cableRequirements.length === 0 || safeguards.softwarePrerequisites.length === 0 || safeguards.warnings.length === 0 || hardware.components.some(
|
|
1208
|
+
(component) => component.physicalCompletionEligible && (component.verificationStatus !== "verified" || module3.hardware.verificationStatus !== "verified")
|
|
1209
|
+
)) {
|
|
1210
|
+
issues.push(
|
|
1211
|
+
authoringIssue(
|
|
1212
|
+
"unsafe-physical-export",
|
|
1213
|
+
"Physical export and completion require adult acknowledgement, verified hardware and a website that never controls hardware.",
|
|
1214
|
+
"hardware.safeguards"
|
|
1215
|
+
)
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
1218
|
+
const simulatedBadge = module3.badges.find(
|
|
1219
|
+
(badge) => badge.id === safeguards.simulatedBadgeId
|
|
1220
|
+
);
|
|
1221
|
+
const physicalBadge = module3.badges.find(
|
|
1222
|
+
(badge) => badge.id === safeguards.physicalBadgeId
|
|
1223
|
+
);
|
|
1224
|
+
if (simulatedBadge?.evidence === "adult-physical-signoff" || physicalBadge?.evidence !== "adult-physical-signoff") {
|
|
1225
|
+
issues.push(
|
|
1226
|
+
authoringIssue(
|
|
1227
|
+
"invalid-hardware-reward",
|
|
1228
|
+
"Simulated and physical badges must be distinct, and only the physical badge may require adult sign-off.",
|
|
1229
|
+
"hardware.safeguards"
|
|
1230
|
+
)
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1127
1234
|
return issues;
|
|
1128
1235
|
}
|
|
1129
1236
|
function assertValidMissionAuthoringBundle(bundle, module3) {
|
|
@@ -2227,6 +2334,393 @@ var STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1 = {
|
|
|
2227
2334
|
]
|
|
2228
2335
|
}
|
|
2229
2336
|
};
|
|
2337
|
+
var BEACON_BOT_MISSION_ONE_AUTHORING_V1 = {
|
|
2338
|
+
version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
|
|
2339
|
+
moduleId: "junior-coder.beacon-bot",
|
|
2340
|
+
moduleVersion: "1.1.0",
|
|
2341
|
+
missionId: "beacon-bot-mission-1",
|
|
2342
|
+
learner: {
|
|
2343
|
+
estimatedMinutes: 20,
|
|
2344
|
+
stages: [
|
|
2345
|
+
{
|
|
2346
|
+
kind: "learn",
|
|
2347
|
+
instruction: "Read what setVisibleSignal(), waitMs(), repeatSignal() and readIrReceiver() do in the private Beacon Bot simulator.",
|
|
2348
|
+
artifactIds: ["beacon-bot-m1-art"]
|
|
2349
|
+
},
|
|
2350
|
+
{
|
|
2351
|
+
kind: "predict",
|
|
2352
|
+
instruction: "Predict the visible signal order, elapsed time and simulated IR reading before the sequence runs.",
|
|
2353
|
+
artifactIds: []
|
|
2354
|
+
},
|
|
2355
|
+
{
|
|
2356
|
+
kind: "build",
|
|
2357
|
+
instruction: "Adjust the four documented C++-style calls to create one bounded rescue signal.",
|
|
2358
|
+
artifactIds: ["beacon-bot-m1-code"]
|
|
2359
|
+
},
|
|
2360
|
+
{
|
|
2361
|
+
kind: "run",
|
|
2362
|
+
instruction: "Use the Run action button to start the private Beacon Bot simulator.",
|
|
2363
|
+
artifactIds: ["beacon-bot-m1-code"]
|
|
2364
|
+
},
|
|
2365
|
+
{
|
|
2366
|
+
kind: "assess",
|
|
2367
|
+
instruction: "Run the visible and protected deterministic beacon checks.",
|
|
2368
|
+
artifactIds: []
|
|
2369
|
+
},
|
|
2370
|
+
{
|
|
2371
|
+
kind: "inspect",
|
|
2372
|
+
instruction: "Compare the highlighted C++-style line with the first signal goal that did not pass.",
|
|
2373
|
+
artifactIds: []
|
|
2374
|
+
},
|
|
2375
|
+
{
|
|
2376
|
+
kind: "fix",
|
|
2377
|
+
instruction: "Change one signal, wait, repeat or simulated IR setting, then rerun and inspect the text telemetry.",
|
|
2378
|
+
artifactIds: ["beacon-bot-m1-code"]
|
|
2379
|
+
},
|
|
2380
|
+
{
|
|
2381
|
+
kind: "explain",
|
|
2382
|
+
instruction: "Explain how the function calls created a timed signal and how the simulated receiver changed the result.",
|
|
2383
|
+
artifactIds: []
|
|
2384
|
+
},
|
|
2385
|
+
{
|
|
2386
|
+
kind: "reward",
|
|
2387
|
+
instruction: "Collect the simulated badge when the score and private-runtime safety check pass; physical completion remains adult-only.",
|
|
2388
|
+
artifactIds: []
|
|
2389
|
+
}
|
|
2390
|
+
],
|
|
2391
|
+
readinessChecks: [
|
|
2392
|
+
{
|
|
2393
|
+
id: "beacon-bot-m1-find-wait",
|
|
2394
|
+
prompt: "Point to the documented call that controls how long a visible signal stays on.",
|
|
2395
|
+
scored: false
|
|
2396
|
+
}
|
|
2397
|
+
],
|
|
2398
|
+
artifacts: [
|
|
2399
|
+
{
|
|
2400
|
+
id: "beacon-bot-m1-code",
|
|
2401
|
+
kind: "starter-code",
|
|
2402
|
+
audience: "learner",
|
|
2403
|
+
solutionBearing: false
|
|
2404
|
+
},
|
|
2405
|
+
{
|
|
2406
|
+
id: "beacon-bot-m1-art",
|
|
2407
|
+
kind: "starter-assets",
|
|
2408
|
+
audience: "learner",
|
|
2409
|
+
solutionBearing: false
|
|
2410
|
+
},
|
|
2411
|
+
{
|
|
2412
|
+
id: "beacon-bot-m1-printable",
|
|
2413
|
+
kind: "printable",
|
|
2414
|
+
audience: "learner",
|
|
2415
|
+
solutionBearing: false
|
|
2416
|
+
}
|
|
2417
|
+
],
|
|
2418
|
+
goals: [
|
|
2419
|
+
{
|
|
2420
|
+
id: "beacon-bot-m1-starts",
|
|
2421
|
+
statement: "The documented C++-style settings are valid and the private simulator starts.",
|
|
2422
|
+
visibility: "visible",
|
|
2423
|
+
criterionIds: ["beacon-bot-build"],
|
|
2424
|
+
completionRequired: true,
|
|
2425
|
+
aiRequired: false
|
|
2426
|
+
},
|
|
2427
|
+
{
|
|
2428
|
+
id: "beacon-bot-m1-signal-sequence",
|
|
2429
|
+
statement: "The beacon produces a bounded timed pattern and reports one simulated IR receiver state.",
|
|
2430
|
+
visibility: "visible",
|
|
2431
|
+
criterionIds: ["beacon-bot-goal-one", "beacon-bot-goal-two"],
|
|
2432
|
+
completionRequired: true,
|
|
2433
|
+
aiRequired: false
|
|
2434
|
+
},
|
|
2435
|
+
{
|
|
2436
|
+
id: "beacon-bot-m1-private-runtime",
|
|
2437
|
+
statement: "The program stays inside the private simulator and never accesses physical hardware, the network or browser storage.",
|
|
2438
|
+
visibility: "visible",
|
|
2439
|
+
criterionIds: ["beacon-bot-safety"],
|
|
2440
|
+
completionRequired: true,
|
|
2441
|
+
aiRequired: false
|
|
2442
|
+
}
|
|
2443
|
+
],
|
|
2444
|
+
interactions: [
|
|
2445
|
+
{
|
|
2446
|
+
id: "beacon-bot-m1-run-control",
|
|
2447
|
+
description: "Start the private Beacon Bot signal simulation.",
|
|
2448
|
+
primaryMode: "pointer",
|
|
2449
|
+
alternativeIds: ["beacon-bot-m1-keyboard-run"]
|
|
2450
|
+
},
|
|
2451
|
+
{
|
|
2452
|
+
id: "beacon-bot-m1-code-control",
|
|
2453
|
+
description: "Edit the documented signal, timing, repeat and receiver calls.",
|
|
2454
|
+
primaryMode: "keyboard",
|
|
2455
|
+
alternativeIds: []
|
|
2456
|
+
},
|
|
2457
|
+
{
|
|
2458
|
+
id: "beacon-bot-m1-signal-colour",
|
|
2459
|
+
description: "Observe the visible rescue signal without relying on colour alone.",
|
|
2460
|
+
primaryMode: "colour",
|
|
2461
|
+
alternativeIds: ["beacon-bot-m1-signal-telemetry"]
|
|
2462
|
+
},
|
|
2463
|
+
{
|
|
2464
|
+
id: "beacon-bot-m1-signal-motion",
|
|
2465
|
+
description: "Observe the bounded signal sequence and receiver state changes.",
|
|
2466
|
+
primaryMode: "motion",
|
|
2467
|
+
alternativeIds: ["beacon-bot-m1-signal-telemetry"]
|
|
2468
|
+
}
|
|
2469
|
+
],
|
|
2470
|
+
accessibilityAlternatives: [
|
|
2471
|
+
{
|
|
2472
|
+
id: "beacon-bot-m1-keyboard-run",
|
|
2473
|
+
modes: ["keyboard"],
|
|
2474
|
+
equivalentOutcome: true,
|
|
2475
|
+
description: "Press Enter or Space on the play-icon Run button to start the same simulator."
|
|
2476
|
+
},
|
|
2477
|
+
{
|
|
2478
|
+
id: "beacon-bot-m1-signal-telemetry",
|
|
2479
|
+
modes: ["text", "shape", "symbol", "reduced-motion"],
|
|
2480
|
+
equivalentOutcome: true,
|
|
2481
|
+
description: "Read the signal name, step count, elapsed milliseconds and receiver state without colour or animation."
|
|
2482
|
+
}
|
|
2483
|
+
],
|
|
2484
|
+
evidenceRequirements: [
|
|
2485
|
+
{
|
|
2486
|
+
id: "beacon-bot-m1-assessment",
|
|
2487
|
+
goalIds: [
|
|
2488
|
+
"beacon-bot-m1-starts",
|
|
2489
|
+
"beacon-bot-m1-signal-sequence",
|
|
2490
|
+
"beacon-bot-m1-private-runtime"
|
|
2491
|
+
],
|
|
2492
|
+
kind: "assessment-result",
|
|
2493
|
+
retention: "entitlement",
|
|
2494
|
+
containsPersonalData: false
|
|
2495
|
+
},
|
|
2496
|
+
{
|
|
2497
|
+
id: "beacon-bot-m1-explanation",
|
|
2498
|
+
goalIds: ["beacon-bot-m1-signal-sequence"],
|
|
2499
|
+
kind: "learner-explanation",
|
|
2500
|
+
retention: "attempt",
|
|
2501
|
+
containsPersonalData: false
|
|
2502
|
+
}
|
|
2503
|
+
],
|
|
2504
|
+
sideAdventures: [
|
|
2505
|
+
{
|
|
2506
|
+
id: "beacon-bot-m1-remix",
|
|
2507
|
+
prompt: "Invent an original rescue-signal name and describe a text or shape cue that makes it understandable without colour.",
|
|
2508
|
+
completionRequired: false
|
|
2509
|
+
}
|
|
2510
|
+
],
|
|
2511
|
+
rewardBindings: [
|
|
2512
|
+
{
|
|
2513
|
+
id: "beacon-bot-m1-simulated-badge",
|
|
2514
|
+
badgeId: "beacon-bot-mission-complete",
|
|
2515
|
+
goalIds: [
|
|
2516
|
+
"beacon-bot-m1-starts",
|
|
2517
|
+
"beacon-bot-m1-signal-sequence",
|
|
2518
|
+
"beacon-bot-m1-private-runtime"
|
|
2519
|
+
],
|
|
2520
|
+
deterministic: true,
|
|
2521
|
+
random: false,
|
|
2522
|
+
tokenConvertible: false
|
|
2523
|
+
}
|
|
2524
|
+
],
|
|
2525
|
+
functionReference: [
|
|
2526
|
+
{
|
|
2527
|
+
id: "beacon-bot-function-visible-signal",
|
|
2528
|
+
signature: "setVisibleSignal(colour)",
|
|
2529
|
+
summary: "Chooses the named visible signal used by the next bounded step.",
|
|
2530
|
+
parameters: [
|
|
2531
|
+
{
|
|
2532
|
+
name: "colour",
|
|
2533
|
+
type: "string",
|
|
2534
|
+
description: "Use red, amber or green."
|
|
2535
|
+
}
|
|
2536
|
+
],
|
|
2537
|
+
effect: "Updates the simulator's labelled light and equivalent shape cue without accessing a physical LED.",
|
|
2538
|
+
example: 'setVisibleSignal("green");'
|
|
2539
|
+
},
|
|
2540
|
+
{
|
|
2541
|
+
id: "beacon-bot-function-wait",
|
|
2542
|
+
signature: "waitMs(duration)",
|
|
2543
|
+
summary: "Adds one safe wait to the simulated signal timeline.",
|
|
2544
|
+
parameters: [
|
|
2545
|
+
{
|
|
2546
|
+
name: "duration",
|
|
2547
|
+
type: "whole number",
|
|
2548
|
+
description: "A bounded number of milliseconds from 100 to 1000."
|
|
2549
|
+
}
|
|
2550
|
+
],
|
|
2551
|
+
effect: "Advances simulated elapsed time; it never blocks the website or controls hardware.",
|
|
2552
|
+
example: "waitMs(250);"
|
|
2553
|
+
},
|
|
2554
|
+
{
|
|
2555
|
+
id: "beacon-bot-function-repeat",
|
|
2556
|
+
signature: "repeatSignal(count)",
|
|
2557
|
+
summary: "Repeats the current visible signal a safe number of times.",
|
|
2558
|
+
parameters: [
|
|
2559
|
+
{
|
|
2560
|
+
name: "count",
|
|
2561
|
+
type: "whole number",
|
|
2562
|
+
description: "A bounded repeat count from 1 to 4."
|
|
2563
|
+
}
|
|
2564
|
+
],
|
|
2565
|
+
effect: "Adds a fixed number of labelled signal steps to the private simulator timeline.",
|
|
2566
|
+
example: "repeatSignal(3);"
|
|
2567
|
+
},
|
|
2568
|
+
{
|
|
2569
|
+
id: "beacon-bot-function-ir-receiver",
|
|
2570
|
+
signature: "readIrReceiver()",
|
|
2571
|
+
summary: "Reads the simulator's fictional infrared receiver state.",
|
|
2572
|
+
parameters: [],
|
|
2573
|
+
effect: "Returns detected or clear from simulator state only; it cannot access a real sensor.",
|
|
2574
|
+
example: "const receiverState = readIrReceiver();"
|
|
2575
|
+
}
|
|
2576
|
+
]
|
|
2577
|
+
},
|
|
2578
|
+
facilitator: {
|
|
2579
|
+
artifacts: [
|
|
2580
|
+
{
|
|
2581
|
+
id: "beacon-bot-m1-answer-key",
|
|
2582
|
+
kind: "answer-key",
|
|
2583
|
+
audience: "facilitator",
|
|
2584
|
+
solutionBearing: true
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
id: "beacon-bot-m1-protected-tests",
|
|
2588
|
+
kind: "protected-test",
|
|
2589
|
+
audience: "facilitator",
|
|
2590
|
+
solutionBearing: true
|
|
2591
|
+
},
|
|
2592
|
+
{
|
|
2593
|
+
id: "beacon-bot-m1-adult-hardware-guide",
|
|
2594
|
+
kind: "facilitator-note",
|
|
2595
|
+
audience: "facilitator",
|
|
2596
|
+
solutionBearing: true
|
|
2597
|
+
}
|
|
2598
|
+
],
|
|
2599
|
+
protectedGoals: [
|
|
2600
|
+
{
|
|
2601
|
+
id: "beacon-bot-m1-protected-resilience",
|
|
2602
|
+
statement: "The simulator rejects unsupported signals, excessive waits or repeats and any hardware, network or storage request.",
|
|
2603
|
+
visibility: "protected",
|
|
2604
|
+
criterionIds: ["beacon-bot-edge-one", "beacon-bot-edge-two"],
|
|
2605
|
+
completionRequired: false,
|
|
2606
|
+
aiRequired: false
|
|
2607
|
+
}
|
|
2608
|
+
],
|
|
2609
|
+
prompts: [
|
|
2610
|
+
"Ask the learner to predict the labelled signal timeline before suggesting one bounded change.",
|
|
2611
|
+
"Use the function reference and visible telemetry; never provide wiring or physical power advice to a learner.",
|
|
2612
|
+
"Physical export stays unavailable until an adult acknowledges the exact manifest and every component has verified bench-test evidence."
|
|
2613
|
+
]
|
|
2614
|
+
},
|
|
2615
|
+
hardware: {
|
|
2616
|
+
requirementsVersion: "1.0.0",
|
|
2617
|
+
hardwareIncluded: false,
|
|
2618
|
+
completePathItemIds: [
|
|
2619
|
+
"pico-2-w",
|
|
2620
|
+
"breadboard",
|
|
2621
|
+
"usb-data-cable",
|
|
2622
|
+
"jumper-wires",
|
|
2623
|
+
"led-pack",
|
|
2624
|
+
"led-resistors",
|
|
2625
|
+
"ir-pair"
|
|
2626
|
+
],
|
|
2627
|
+
incrementalItemIds: ["led-pack", "led-resistors", "ir-pair"],
|
|
2628
|
+
components: [
|
|
2629
|
+
{
|
|
2630
|
+
itemId: "pico-2-w",
|
|
2631
|
+
quantity: 1,
|
|
2632
|
+
acquisitionScope: "complete-path",
|
|
2633
|
+
verificationStatus: "pending-bench-test",
|
|
2634
|
+
compatibilityClaimed: false,
|
|
2635
|
+
physicalCompletionEligible: false
|
|
2636
|
+
},
|
|
2637
|
+
{
|
|
2638
|
+
itemId: "breadboard",
|
|
2639
|
+
quantity: 1,
|
|
2640
|
+
acquisitionScope: "complete-path",
|
|
2641
|
+
verificationStatus: "pending-bench-test",
|
|
2642
|
+
compatibilityClaimed: false,
|
|
2643
|
+
physicalCompletionEligible: false
|
|
2644
|
+
},
|
|
2645
|
+
{
|
|
2646
|
+
itemId: "usb-data-cable",
|
|
2647
|
+
quantity: 1,
|
|
2648
|
+
acquisitionScope: "complete-path",
|
|
2649
|
+
verificationStatus: "pending-bench-test",
|
|
2650
|
+
compatibilityClaimed: false,
|
|
2651
|
+
physicalCompletionEligible: false
|
|
2652
|
+
},
|
|
2653
|
+
{
|
|
2654
|
+
itemId: "jumper-wires",
|
|
2655
|
+
quantity: 12,
|
|
2656
|
+
acquisitionScope: "complete-path",
|
|
2657
|
+
verificationStatus: "pending-bench-test",
|
|
2658
|
+
compatibilityClaimed: false,
|
|
2659
|
+
physicalCompletionEligible: false
|
|
2660
|
+
},
|
|
2661
|
+
{
|
|
2662
|
+
itemId: "led-pack",
|
|
2663
|
+
quantity: 3,
|
|
2664
|
+
acquisitionScope: "incremental",
|
|
2665
|
+
verificationStatus: "pending-bench-test",
|
|
2666
|
+
compatibilityClaimed: false,
|
|
2667
|
+
physicalCompletionEligible: false
|
|
2668
|
+
},
|
|
2669
|
+
{
|
|
2670
|
+
itemId: "led-resistors",
|
|
2671
|
+
quantity: 3,
|
|
2672
|
+
acquisitionScope: "incremental",
|
|
2673
|
+
verificationStatus: "pending-bench-test",
|
|
2674
|
+
compatibilityClaimed: false,
|
|
2675
|
+
physicalCompletionEligible: false
|
|
2676
|
+
},
|
|
2677
|
+
{
|
|
2678
|
+
itemId: "ir-pair",
|
|
2679
|
+
quantity: 1,
|
|
2680
|
+
acquisitionScope: "incremental",
|
|
2681
|
+
verificationStatus: "pending-bench-test",
|
|
2682
|
+
compatibilityClaimed: false,
|
|
2683
|
+
physicalCompletionEligible: false
|
|
2684
|
+
}
|
|
2685
|
+
],
|
|
2686
|
+
safeguards: {
|
|
2687
|
+
adultAssemblyRequired: true,
|
|
2688
|
+
adultAcknowledgementRequiredForExport: true,
|
|
2689
|
+
websiteMayControlHardware: false,
|
|
2690
|
+
simulatorCompletionAvailable: true,
|
|
2691
|
+
simulatedBadgeId: "beacon-bot-mission-complete",
|
|
2692
|
+
physicalBadgeId: "beacon-bot-physical-builder",
|
|
2693
|
+
physicalBadgeRequiresAdultSignoff: true,
|
|
2694
|
+
adultAssemblySteps: [
|
|
2695
|
+
"Confirm every exact component identity against the requirements manifest.",
|
|
2696
|
+
"Assemble and inspect the disconnected breadboard circuit before learner use.",
|
|
2697
|
+
"Run known-good recovery firmware and complete the adult bench-test record."
|
|
2698
|
+
],
|
|
2699
|
+
powerRequirements: [
|
|
2700
|
+
"Use Pico USB power only for the published Beacon Bot reference circuit.",
|
|
2701
|
+
"Disconnect USB power before changing any wiring."
|
|
2702
|
+
],
|
|
2703
|
+
cableRequirements: [
|
|
2704
|
+
"One known data-capable USB cable compatible with the Pico 2 W.",
|
|
2705
|
+
"Insulated male-to-male breadboard jumper wires matching the manifest quantity."
|
|
2706
|
+
],
|
|
2707
|
+
softwarePrerequisites: [
|
|
2708
|
+
"Supported Pico SDK toolchain on Raspberry Pi OS or a documented desktop environment.",
|
|
2709
|
+
"Known-good Beacon Bot recovery firmware prepared by an adult."
|
|
2710
|
+
],
|
|
2711
|
+
warnings: [
|
|
2712
|
+
"Hardware is not included with the module.",
|
|
2713
|
+
"No listed component currently claims compatibility or physical-completion eligibility.",
|
|
2714
|
+
"The simulator and simulated badge remain available without physical equipment."
|
|
2715
|
+
],
|
|
2716
|
+
unrelatedHardwareNotRequired: [
|
|
2717
|
+
"Camera Module 3",
|
|
2718
|
+
"motor driver or motors",
|
|
2719
|
+
"servo"
|
|
2720
|
+
]
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
};
|
|
2230
2724
|
var RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1 = {
|
|
2231
2725
|
version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
|
|
2232
2726
|
moduleId: "junior-coder.rescue-crew-commander",
|
|
@@ -3022,6 +3516,7 @@ ${summary}`);
|
|
|
3022
3516
|
}
|
|
3023
3517
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3024
3518
|
0 && (module.exports = {
|
|
3519
|
+
BEACON_BOT_MISSION_ONE_AUTHORING_V1,
|
|
3025
3520
|
JUNIOR_CODER_MISSION_STAGE_ORDER_V1,
|
|
3026
3521
|
JUNIOR_CODER_MODULE_PRICE_V1_1,
|
|
3027
3522
|
JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT,
|