@plasius/learning 0.2.7 → 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/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,
@@ -33,6 +34,7 @@ __export(index_exports, {
33
34
  ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1: () => ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1,
34
35
  ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1: () => ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1,
35
36
  SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1: () => SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1,
37
+ STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1: () => STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1,
36
38
  assertValidLearningPath: () => assertValidLearningPath,
37
39
  assertValidMissionAuthoringBundle: () => assertValidMissionAuthoringBundle,
38
40
  calculateAssessment: () => calculateAssessment,
@@ -1123,6 +1125,112 @@ function validateMissionAuthoringBundle(bundle, module3) {
1123
1125
  );
1124
1126
  }
1125
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
+ }
1126
1234
  return issues;
1127
1235
  }
1128
1236
  function assertValidMissionAuthoringBundle(bundle, module3) {
@@ -2006,6 +2114,613 @@ var PIXEL_TRAIL_CHALLENGE_MISSION_ONE_AUTHORING_V1 = {
2006
2114
  ]
2007
2115
  }
2008
2116
  };
2117
+ var STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1 = {
2118
+ version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
2119
+ moduleId: "junior-coder.star-defender-squadron",
2120
+ moduleVersion: "1.1.0",
2121
+ missionId: "star-defender-squadron-mission-1",
2122
+ learner: {
2123
+ estimatedMinutes: 20,
2124
+ stages: [
2125
+ {
2126
+ kind: "learn",
2127
+ instruction: "Read what createSquadron(), setRescueWave(), setShieldHealth() and launchRescueBeam() do in the private JavaScript preview.",
2128
+ artifactIds: ["star-defender-squadron-m1-art"]
2129
+ },
2130
+ {
2131
+ kind: "predict",
2132
+ instruction: "Predict where the squadron and rescue beam will travel, and which health value will change after the wave.",
2133
+ artifactIds: []
2134
+ },
2135
+ {
2136
+ kind: "build",
2137
+ instruction: "Adjust the four documented JavaScript calls so the original squadron launches a safe rescue wave.",
2138
+ artifactIds: ["star-defender-squadron-m1-code"]
2139
+ },
2140
+ {
2141
+ kind: "run",
2142
+ instruction: "Use the Run action button to start the private Star Defender preview.",
2143
+ artifactIds: ["star-defender-squadron-m1-code"]
2144
+ },
2145
+ {
2146
+ kind: "assess",
2147
+ instruction: "Run the visible and protected deterministic squadron checks.",
2148
+ artifactIds: []
2149
+ },
2150
+ {
2151
+ kind: "inspect",
2152
+ instruction: "Compare the highlighted JavaScript line with the first mission goal that did not pass.",
2153
+ artifactIds: []
2154
+ },
2155
+ {
2156
+ kind: "fix",
2157
+ instruction: "Change one squadron, wave, shield or beam setting, then rerun and inspect the entity and health telemetry.",
2158
+ artifactIds: ["star-defender-squadron-m1-code"]
2159
+ },
2160
+ {
2161
+ kind: "explain",
2162
+ instruction: "Explain how the wave pattern moved the entities and how shields protected the rescue mission.",
2163
+ artifactIds: []
2164
+ },
2165
+ {
2166
+ kind: "reward",
2167
+ instruction: "Collect the evidence-bound badge when the score and private-runtime safety check pass.",
2168
+ artifactIds: []
2169
+ }
2170
+ ],
2171
+ readinessChecks: [
2172
+ {
2173
+ id: "star-defender-squadron-m1-find-wave",
2174
+ prompt: "Point to the JavaScript call that chooses the rescue-wave pattern.",
2175
+ scored: false
2176
+ }
2177
+ ],
2178
+ artifacts: [
2179
+ {
2180
+ id: "star-defender-squadron-m1-code",
2181
+ kind: "starter-code",
2182
+ audience: "learner",
2183
+ solutionBearing: false
2184
+ },
2185
+ {
2186
+ id: "star-defender-squadron-m1-art",
2187
+ kind: "starter-assets",
2188
+ audience: "learner",
2189
+ solutionBearing: false
2190
+ },
2191
+ {
2192
+ id: "star-defender-squadron-m1-printable",
2193
+ kind: "printable",
2194
+ audience: "learner",
2195
+ solutionBearing: false
2196
+ }
2197
+ ],
2198
+ goals: [
2199
+ {
2200
+ id: "star-defender-squadron-m1-starts",
2201
+ statement: "The JavaScript settings are valid and the private squadron preview starts.",
2202
+ visibility: "visible",
2203
+ criterionIds: ["star-defender-squadron-build"],
2204
+ completionRequired: true,
2205
+ aiRequired: false
2206
+ },
2207
+ {
2208
+ id: "star-defender-squadron-m1-rescue-wave",
2209
+ statement: "The original squadron follows the chosen pattern, keeps safe shield health and launches a rescue beam.",
2210
+ visibility: "visible",
2211
+ criterionIds: [
2212
+ "star-defender-squadron-goal-one",
2213
+ "star-defender-squadron-goal-two"
2214
+ ],
2215
+ completionRequired: true,
2216
+ aiRequired: false
2217
+ },
2218
+ {
2219
+ id: "star-defender-squadron-m1-private-runtime",
2220
+ statement: "The program stays inside the private JavaScript worker and host-provided space-rescue API.",
2221
+ visibility: "visible",
2222
+ criterionIds: ["star-defender-squadron-safety"],
2223
+ completionRequired: true,
2224
+ aiRequired: false
2225
+ }
2226
+ ],
2227
+ interactions: [
2228
+ {
2229
+ id: "star-defender-squadron-m1-run-control",
2230
+ description: "Start the private JavaScript squadron simulation.",
2231
+ primaryMode: "pointer",
2232
+ alternativeIds: ["star-defender-squadron-m1-keyboard-run"]
2233
+ },
2234
+ {
2235
+ id: "star-defender-squadron-m1-code-control",
2236
+ description: "Edit the documented squadron, wave, shield and beam calls.",
2237
+ primaryMode: "keyboard",
2238
+ alternativeIds: []
2239
+ },
2240
+ {
2241
+ id: "star-defender-squadron-m1-wave-motion",
2242
+ description: "Observe squadron entities, wave paths, shields and the rescue beam.",
2243
+ primaryMode: "motion",
2244
+ alternativeIds: ["star-defender-squadron-m1-telemetry"]
2245
+ }
2246
+ ],
2247
+ accessibilityAlternatives: [
2248
+ {
2249
+ id: "star-defender-squadron-m1-keyboard-run",
2250
+ modes: ["keyboard"],
2251
+ equivalentOutcome: true,
2252
+ description: "Press Enter or Space on the play-icon Run button to start the same preview."
2253
+ },
2254
+ {
2255
+ id: "star-defender-squadron-m1-telemetry",
2256
+ modes: ["text", "shape", "reduced-motion"],
2257
+ equivalentOutcome: true,
2258
+ description: "Read entity count, pattern, shield health, beam state and rescue result without animation or colour dependence."
2259
+ }
2260
+ ],
2261
+ evidenceRequirements: [
2262
+ {
2263
+ id: "star-defender-squadron-m1-assessment",
2264
+ goalIds: [
2265
+ "star-defender-squadron-m1-starts",
2266
+ "star-defender-squadron-m1-rescue-wave",
2267
+ "star-defender-squadron-m1-private-runtime"
2268
+ ],
2269
+ kind: "assessment-result",
2270
+ retention: "entitlement",
2271
+ containsPersonalData: false
2272
+ },
2273
+ {
2274
+ id: "star-defender-squadron-m1-explanation",
2275
+ goalIds: ["star-defender-squadron-m1-rescue-wave"],
2276
+ kind: "learner-explanation",
2277
+ retention: "attempt",
2278
+ containsPersonalData: false
2279
+ }
2280
+ ],
2281
+ sideAdventures: [
2282
+ {
2283
+ id: "star-defender-squadron-m1-remix",
2284
+ prompt: "Invent an original rescue-squadron emblem and describe a new safe wave pattern for a later level.",
2285
+ completionRequired: false
2286
+ }
2287
+ ],
2288
+ rewardBindings: [
2289
+ {
2290
+ id: "star-defender-squadron-m1-badge",
2291
+ badgeId: "star-defender-squadron-mission-complete",
2292
+ goalIds: [
2293
+ "star-defender-squadron-m1-starts",
2294
+ "star-defender-squadron-m1-rescue-wave",
2295
+ "star-defender-squadron-m1-private-runtime"
2296
+ ],
2297
+ deterministic: true,
2298
+ random: false,
2299
+ tokenConvertible: false
2300
+ }
2301
+ ]
2302
+ },
2303
+ facilitator: {
2304
+ artifacts: [
2305
+ {
2306
+ id: "star-defender-squadron-m1-answer-key",
2307
+ kind: "answer-key",
2308
+ audience: "facilitator",
2309
+ solutionBearing: true
2310
+ },
2311
+ {
2312
+ id: "star-defender-squadron-m1-protected-tests",
2313
+ kind: "protected-test",
2314
+ audience: "facilitator",
2315
+ solutionBearing: true
2316
+ }
2317
+ ],
2318
+ protectedGoals: [
2319
+ {
2320
+ id: "star-defender-squadron-m1-protected-resilience",
2321
+ statement: "The worker rejects invalid entity, pattern, health and projectile settings and terminates bounded wave simulations.",
2322
+ visibility: "protected",
2323
+ criterionIds: [
2324
+ "star-defender-squadron-edge-one",
2325
+ "star-defender-squadron-edge-two"
2326
+ ],
2327
+ completionRequired: false,
2328
+ aiRequired: false
2329
+ }
2330
+ ],
2331
+ prompts: [
2332
+ "Ask the learner to predict the squadron path and shield change before suggesting a JavaScript edit.",
2333
+ "Use the function reference and visible telemetry; never reveal protected numeric targets, pattern answers or expected source fragments."
2334
+ ]
2335
+ }
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
+ };
2009
2724
  var RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1 = {
2010
2725
  version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
2011
2726
  moduleId: "junior-coder.rescue-crew-commander",
@@ -2801,6 +3516,7 @@ ${summary}`);
2801
3516
  }
2802
3517
  // Annotate the CommonJS export names for ESM import in node:
2803
3518
  0 && (module.exports = {
3519
+ BEACON_BOT_MISSION_ONE_AUTHORING_V1,
2804
3520
  JUNIOR_CODER_MISSION_STAGE_ORDER_V1,
2805
3521
  JUNIOR_CODER_MODULE_PRICE_V1_1,
2806
3522
  JUNIOR_CODER_ROBOT_RESCUE_PATH_CURRENT,
@@ -2814,6 +3530,7 @@ ${summary}`);
2814
3530
  ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1,
2815
3531
  ROBOT_MAZE_DASH_MISSION_ONE_AUTHORING_V1,
2816
3532
  SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1,
3533
+ STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1,
2817
3534
  assertValidLearningPath,
2818
3535
  assertValidMissionAuthoringBundle,
2819
3536
  calculateAssessment,