@plasius/learning 0.2.11 → 0.2.12

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 CHANGED
@@ -66,6 +66,7 @@ import {
66
66
  DANCE_ROVER_MISSION_ONE_AUTHORING_V1,
67
67
  JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1,
68
68
  METEOR_SHIELD_MISSION_ONE_AUTHORING_V1,
69
+ OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1,
69
70
  PADDLE_PULSE_MISSION_ONE_AUTHORING_V1,
70
71
  PIXEL_TRAIL_CHALLENGE_MISSION_ONE_AUTHORING_V1,
71
72
  RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1,
@@ -110,6 +111,9 @@ const servoCreature = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
110
111
  const danceRover = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
111
112
  (module) => module.slug === "dance-rover",
112
113
  );
114
+ const obstacleExplorer = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
115
+ (module) => module.slug === "obstacle-explorer",
116
+ );
113
117
 
114
118
  if (
115
119
  !roadHopper ||
@@ -122,7 +126,8 @@ if (
122
126
  !starDefenderSquadron ||
123
127
  !beaconBot ||
124
128
  !servoCreature ||
125
- !danceRover
129
+ !danceRover ||
130
+ !obstacleExplorer
126
131
  ) {
127
132
  throw new Error("Junior Coder module is missing");
128
133
  }
@@ -171,6 +176,10 @@ assertValidMissionAuthoringBundle(
171
176
  DANCE_ROVER_MISSION_ONE_AUTHORING_V1,
172
177
  danceRover,
173
178
  );
179
+ assertValidMissionAuthoringBundle(
180
+ OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1,
181
+ obstacleExplorer,
182
+ );
174
183
  ```
175
184
 
176
185
  ## Contract rules
@@ -205,6 +214,9 @@ assertValidMissionAuthoringBundle(
205
214
  - Dance Rover documents bounded direction, 0–60 percent simulated speed,
206
215
  timing, repeat and emergency-stop calls while every driver, motor, chassis
207
216
  and switched power arrangement remains pending adult lifted-wheel testing.
217
+ - Obstacle Explorer documents bounded simulated IR readings, Boolean route
218
+ decisions, recovery attempts, watchdog timing and fail-safe stop while every
219
+ rover and sensor remains pending adult calibration and lifted-wheel testing.
208
220
 
209
221
  See [the foundation design](docs/design/junior-coder-catalog-foundation.md),
210
222
  [the uniform pricing design](docs/design/junior-coder-uniform-pricing.md),
@@ -214,7 +226,8 @@ See [the foundation design](docs/design/junior-coder-catalog-foundation.md),
214
226
  [ADR 0003](docs/adrs/adr-0003-mission-authoring-manifests-are-additive-and-separated.md),
215
227
  [ADR 0004](docs/adrs/adr-0004-robot-mission-hardware-disclosures-are-additive-and-fail-closed.md),
216
228
  [TDR 0006](docs/tdrs/tdr-0006-servo-creature-safe-movement-and-power-authoring.md),
217
- and [TDR 0007](docs/tdrs/tdr-0007-dance-rover-fail-safe-movement-and-power-authoring.md).
229
+ [TDR 0007](docs/tdrs/tdr-0007-dance-rover-fail-safe-movement-and-power-authoring.md),
230
+ and [TDR 0008](docs/tdrs/tdr-0008-obstacle-explorer-sensing-watchdog-and-fail-safe-authoring.md).
218
231
 
219
232
  ## Development
220
233
 
package/dist/index.cjs CHANGED
@@ -29,6 +29,7 @@ __export(index_exports, {
29
29
  JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1: () => JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1,
30
30
  METEOR_SHIELD_MISSION_ONE_AUTHORING_V1: () => METEOR_SHIELD_MISSION_ONE_AUTHORING_V1,
31
31
  MISSION_AUTHORING_CONTRACT_VERSION_V1: () => MISSION_AUTHORING_CONTRACT_VERSION_V1,
32
+ OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1: () => OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1,
32
33
  PADDLE_PULSE_MISSION_ONE_AUTHORING_V1: () => PADDLE_PULSE_MISSION_ONE_AUTHORING_V1,
33
34
  PIXEL_TRAIL_CHALLENGE_MISSION_ONE_AUTHORING_V1: () => PIXEL_TRAIL_CHALLENGE_MISSION_ONE_AUTHORING_V1,
34
35
  RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1: () => RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1,
@@ -3477,6 +3478,360 @@ var DANCE_ROVER_MISSION_ONE_AUTHORING_V1 = {
3477
3478
  }
3478
3479
  }
3479
3480
  };
3481
+ var OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1 = {
3482
+ version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
3483
+ moduleId: "junior-coder.obstacle-explorer",
3484
+ moduleVersion: "1.1.0",
3485
+ missionId: "obstacle-explorer-mission-1",
3486
+ learner: {
3487
+ estimatedMinutes: 20,
3488
+ stages: [
3489
+ {
3490
+ kind: "learn",
3491
+ instruction: "Read what readObstacle(), chooseSafeRoute(), setRecoveryAttempts(), armWatchdog() and failSafeStop() do in the private Obstacle Explorer simulator.",
3492
+ artifactIds: ["obstacle-explorer-m1-art"]
3493
+ },
3494
+ {
3495
+ kind: "predict",
3496
+ instruction: "Predict the simulated obstacle reading, safe route, recovery count, watchdog time and final stopped state before the explorer runs.",
3497
+ artifactIds: []
3498
+ },
3499
+ {
3500
+ kind: "build",
3501
+ instruction: "Adjust the five documented C++-style calls to make one bounded obstacle decision with a watchdog and fail-safe stop.",
3502
+ artifactIds: ["obstacle-explorer-m1-code"]
3503
+ },
3504
+ {
3505
+ kind: "run",
3506
+ instruction: "Use the Run action button to start the private Obstacle Explorer simulator.",
3507
+ artifactIds: ["obstacle-explorer-m1-code"]
3508
+ },
3509
+ {
3510
+ kind: "assess",
3511
+ instruction: "Run the visible and protected deterministic sensor, route, recovery, watchdog and stop checks.",
3512
+ artifactIds: []
3513
+ },
3514
+ {
3515
+ kind: "inspect",
3516
+ instruction: "Compare the highlighted C++-style line with the first explorer goal that did not pass.",
3517
+ artifactIds: []
3518
+ },
3519
+ {
3520
+ kind: "fix",
3521
+ instruction: "Change one bounded sensor side, route, recovery count, watchdog or stop call, then rerun and inspect the text telemetry.",
3522
+ artifactIds: ["obstacle-explorer-m1-code"]
3523
+ },
3524
+ {
3525
+ kind: "explain",
3526
+ instruction: "Explain how a Boolean obstacle reading selected a route and why the watchdog and fail-safe stop protect every explorer state.",
3527
+ artifactIds: []
3528
+ },
3529
+ {
3530
+ kind: "reward",
3531
+ instruction: "Collect the simulated badge when the score and mandatory safety checks pass; physical completion remains adult-only.",
3532
+ artifactIds: []
3533
+ }
3534
+ ],
3535
+ readinessChecks: [
3536
+ {
3537
+ id: "obstacle-explorer-m1-find-stop",
3538
+ prompt: "Find failSafeStop() and explain why the explorer must stop when a sensor or watchdog result is uncertain.",
3539
+ scored: false
3540
+ }
3541
+ ],
3542
+ artifacts: [
3543
+ {
3544
+ id: "obstacle-explorer-m1-code",
3545
+ kind: "starter-code",
3546
+ audience: "learner",
3547
+ solutionBearing: false
3548
+ },
3549
+ {
3550
+ id: "obstacle-explorer-m1-art",
3551
+ kind: "starter-assets",
3552
+ audience: "learner",
3553
+ solutionBearing: false
3554
+ },
3555
+ {
3556
+ id: "obstacle-explorer-m1-printable",
3557
+ kind: "printable",
3558
+ audience: "learner",
3559
+ solutionBearing: false
3560
+ }
3561
+ ],
3562
+ goals: [
3563
+ {
3564
+ id: "obstacle-explorer-m1-starts",
3565
+ statement: "The documented C++-style settings are valid and the private simulator starts.",
3566
+ visibility: "visible",
3567
+ criterionIds: ["obstacle-explorer-build"],
3568
+ completionRequired: true,
3569
+ aiRequired: false
3570
+ },
3571
+ {
3572
+ id: "obstacle-explorer-m1-navigation",
3573
+ statement: "The explorer reads one simulated obstacle and chooses a bounded route with three recovery attempts.",
3574
+ visibility: "visible",
3575
+ criterionIds: ["obstacle-explorer-goal-one", "obstacle-explorer-goal-two"],
3576
+ completionRequired: true,
3577
+ aiRequired: false
3578
+ },
3579
+ {
3580
+ id: "obstacle-explorer-m1-private-runtime",
3581
+ statement: "The program arms a watchdog, ends fail-safe stopped and never accesses sensors, motors, the network or browser storage.",
3582
+ visibility: "visible",
3583
+ criterionIds: ["obstacle-explorer-safety"],
3584
+ completionRequired: true,
3585
+ aiRequired: false
3586
+ }
3587
+ ],
3588
+ interactions: [
3589
+ {
3590
+ id: "obstacle-explorer-m1-run-control",
3591
+ description: "Start the private Obstacle Explorer navigation simulation.",
3592
+ primaryMode: "pointer",
3593
+ alternativeIds: ["obstacle-explorer-m1-keyboard-run"]
3594
+ },
3595
+ {
3596
+ id: "obstacle-explorer-m1-code-control",
3597
+ description: "Edit the documented sensor, route, recovery, watchdog and stop calls.",
3598
+ primaryMode: "keyboard",
3599
+ alternativeIds: []
3600
+ },
3601
+ {
3602
+ id: "obstacle-explorer-m1-route-preview",
3603
+ description: "Observe the bounded obstacle decision, route and stopped state.",
3604
+ primaryMode: "motion",
3605
+ alternativeIds: ["obstacle-explorer-m1-telemetry"]
3606
+ }
3607
+ ],
3608
+ accessibilityAlternatives: [
3609
+ {
3610
+ id: "obstacle-explorer-m1-keyboard-run",
3611
+ modes: ["keyboard"],
3612
+ equivalentOutcome: true,
3613
+ description: "Press Enter or Space on the play-icon Run button to start the same simulator."
3614
+ },
3615
+ {
3616
+ id: "obstacle-explorer-m1-telemetry",
3617
+ modes: ["text", "shape", "symbol", "reduced-motion"],
3618
+ equivalentOutcome: true,
3619
+ description: "Read sensor side, blocked state, route, recovery count, watchdog milliseconds and stopped state without animation or colour alone."
3620
+ }
3621
+ ],
3622
+ evidenceRequirements: [
3623
+ {
3624
+ id: "obstacle-explorer-m1-assessment",
3625
+ goalIds: [
3626
+ "obstacle-explorer-m1-starts",
3627
+ "obstacle-explorer-m1-navigation",
3628
+ "obstacle-explorer-m1-private-runtime"
3629
+ ],
3630
+ kind: "assessment-result",
3631
+ retention: "entitlement",
3632
+ containsPersonalData: false
3633
+ },
3634
+ {
3635
+ id: "obstacle-explorer-m1-explanation",
3636
+ goalIds: ["obstacle-explorer-m1-navigation"],
3637
+ kind: "learner-explanation",
3638
+ retention: "attempt",
3639
+ containsPersonalData: false
3640
+ }
3641
+ ],
3642
+ sideAdventures: [
3643
+ {
3644
+ id: "obstacle-explorer-m1-remix",
3645
+ prompt: "Invent an original maze response and add a text or symbol cue that explains the Boolean decision without motion or colour alone.",
3646
+ completionRequired: false
3647
+ }
3648
+ ],
3649
+ rewardBindings: [
3650
+ {
3651
+ id: "obstacle-explorer-m1-simulated-badge",
3652
+ badgeId: "obstacle-explorer-mission-complete",
3653
+ goalIds: [
3654
+ "obstacle-explorer-m1-starts",
3655
+ "obstacle-explorer-m1-navigation",
3656
+ "obstacle-explorer-m1-private-runtime"
3657
+ ],
3658
+ deterministic: true,
3659
+ random: false,
3660
+ tokenConvertible: false
3661
+ }
3662
+ ],
3663
+ functionReference: [
3664
+ {
3665
+ id: "obstacle-explorer-function-read",
3666
+ signature: "readObstacle(side)",
3667
+ summary: "Reads one labelled obstacle state from the private simulator.",
3668
+ parameters: [
3669
+ {
3670
+ name: "side",
3671
+ type: "string",
3672
+ description: "Use front, left or right."
3673
+ }
3674
+ ],
3675
+ effect: "Returns a simulator Boolean blocked or clear reading and never accesses an IR sensor or GPIO pin.",
3676
+ example: 'readObstacle("front");'
3677
+ },
3678
+ {
3679
+ id: "obstacle-explorer-function-route",
3680
+ signature: "chooseSafeRoute(blockedAction, clearAction)",
3681
+ summary: "Chooses one bounded route for blocked and clear simulated states.",
3682
+ parameters: [
3683
+ {
3684
+ name: "blockedAction",
3685
+ type: "string",
3686
+ description: "Use turn-left, turn-right, back-up or stop."
3687
+ },
3688
+ {
3689
+ name: "clearAction",
3690
+ type: "string",
3691
+ description: "Use forward or stop."
3692
+ }
3693
+ ],
3694
+ effect: "Updates labelled simulator navigation state without energising motors or a driver.",
3695
+ example: 'chooseSafeRoute("turn-left", "forward");'
3696
+ },
3697
+ {
3698
+ id: "obstacle-explorer-function-recovery",
3699
+ signature: "setRecoveryAttempts(count)",
3700
+ summary: "Sets a bounded number of simulated recovery attempts.",
3701
+ parameters: [
3702
+ {
3703
+ name: "count",
3704
+ type: "whole number",
3705
+ description: "A bounded recovery count from 1 to 3."
3706
+ }
3707
+ ],
3708
+ effect: "Limits the private simulator recovery state so an uncertain route cannot loop forever.",
3709
+ example: "setRecoveryAttempts(3);"
3710
+ },
3711
+ {
3712
+ id: "obstacle-explorer-function-watchdog",
3713
+ signature: "armWatchdog(duration)",
3714
+ summary: "Arms a bounded simulated watchdog timer.",
3715
+ parameters: [
3716
+ {
3717
+ name: "duration",
3718
+ type: "whole number",
3719
+ description: "A bounded timeout from 250 to 1000 milliseconds."
3720
+ }
3721
+ ],
3722
+ effect: "Records simulator timeout telemetry and cannot hold or control physical movement.",
3723
+ example: "armWatchdog(500);"
3724
+ },
3725
+ {
3726
+ id: "obstacle-explorer-function-stop",
3727
+ signature: "failSafeStop()",
3728
+ summary: "Ends the navigation simulation in a fail-safe stopped state.",
3729
+ parameters: [],
3730
+ effect: "Marks the private simulator stopped on completion or uncertainty; it cannot activate, stop or otherwise control physical hardware.",
3731
+ example: "failSafeStop();"
3732
+ }
3733
+ ]
3734
+ },
3735
+ facilitator: {
3736
+ artifacts: [
3737
+ {
3738
+ id: "obstacle-explorer-m1-answer-key",
3739
+ kind: "answer-key",
3740
+ audience: "facilitator",
3741
+ solutionBearing: true
3742
+ },
3743
+ {
3744
+ id: "obstacle-explorer-m1-protected-tests",
3745
+ kind: "protected-test",
3746
+ audience: "facilitator",
3747
+ solutionBearing: true
3748
+ },
3749
+ {
3750
+ id: "obstacle-explorer-m1-adult-hardware-guide",
3751
+ kind: "facilitator-note",
3752
+ audience: "facilitator",
3753
+ solutionBearing: true
3754
+ }
3755
+ ],
3756
+ protectedGoals: [
3757
+ {
3758
+ id: "obstacle-explorer-m1-protected-resilience",
3759
+ statement: "The simulator rejects unsupported sensor sides, unsafe routes, excessive recovery attempts, invalid watchdogs, missing stop calls and physical-hardware requests.",
3760
+ visibility: "protected",
3761
+ criterionIds: ["obstacle-explorer-edge-one", "obstacle-explorer-edge-two"],
3762
+ completionRequired: false,
3763
+ aiRequired: false
3764
+ }
3765
+ ],
3766
+ prompts: [
3767
+ "Ask the learner to predict the Boolean blocked state, labelled route and final stopped state before suggesting one bounded change.",
3768
+ "Use the function reference and visible telemetry; never provide sensor wiring, motor power or movement advice to a learner.",
3769
+ "Physical export stays unavailable until an adult acknowledges the exact manifest and every rover and sensor component has calibration and bench-test evidence."
3770
+ ]
3771
+ },
3772
+ hardware: {
3773
+ requirementsVersion: "1.0.0",
3774
+ hardwareIncluded: false,
3775
+ completePathItemIds: [
3776
+ "pico-2-w",
3777
+ "breadboard",
3778
+ "usb-data-cable",
3779
+ "jumper-wires",
3780
+ "verified-rover",
3781
+ "obstacle-sensors"
3782
+ ],
3783
+ incrementalItemIds: [
3784
+ "verified-rover",
3785
+ "obstacle-sensors"
3786
+ ],
3787
+ components: [
3788
+ { itemId: "pico-2-w", quantity: 1, acquisitionScope: "complete-path", verificationStatus: "pending-bench-test", compatibilityClaimed: false, physicalCompletionEligible: false },
3789
+ { itemId: "breadboard", quantity: 1, acquisitionScope: "complete-path", verificationStatus: "pending-bench-test", compatibilityClaimed: false, physicalCompletionEligible: false },
3790
+ { itemId: "usb-data-cable", quantity: 1, acquisitionScope: "complete-path", verificationStatus: "pending-bench-test", compatibilityClaimed: false, physicalCompletionEligible: false },
3791
+ { itemId: "jumper-wires", quantity: 12, acquisitionScope: "complete-path", verificationStatus: "pending-bench-test", compatibilityClaimed: false, physicalCompletionEligible: false },
3792
+ { itemId: "verified-rover", quantity: 1, acquisitionScope: "incremental", verificationStatus: "pending-bench-test", compatibilityClaimed: false, physicalCompletionEligible: false },
3793
+ { itemId: "obstacle-sensors", quantity: 2, acquisitionScope: "incremental", verificationStatus: "pending-bench-test", compatibilityClaimed: false, physicalCompletionEligible: false }
3794
+ ],
3795
+ safeguards: {
3796
+ adultAssemblyRequired: true,
3797
+ adultAcknowledgementRequiredForExport: true,
3798
+ websiteMayControlHardware: false,
3799
+ simulatorCompletionAvailable: true,
3800
+ simulatedBadgeId: "obstacle-explorer-mission-complete",
3801
+ physicalBadgeId: "obstacle-explorer-physical-builder",
3802
+ physicalBadgeRequiresAdultSignoff: true,
3803
+ adultAssemblySteps: [
3804
+ "Confirm the exact bench-signed rover and IR sensor identities against the requirements manifest.",
3805
+ "Assemble and inspect all disconnected sensor wiring, then complete the adult sensor calibration record for clear and blocked surfaces.",
3806
+ "Complete direction, obstacle recovery, watchdog and fail-safe-stop tests with the wheels lifted clear of the surface."
3807
+ ],
3808
+ powerRequirements: [
3809
+ "Use the verified switched protected motor supply and sensor voltage; never power motors or unsuitable sensors from a Pico GPIO pin.",
3810
+ "Connect one common signal ground between the verified sensor, motor supply, driver and Pico only as shown in the adult guide.",
3811
+ "Keep the power switch accessible and disconnect every source before changing wiring, sensors, wheels or chassis parts."
3812
+ ],
3813
+ cableRequirements: [
3814
+ "One known data-capable USB cable compatible with the Pico 2 W.",
3815
+ "Insulated jumper leads and verified sensor, motor, driver and power connectors documented by the adult guide."
3816
+ ],
3817
+ softwarePrerequisites: [
3818
+ "Supported Pico SDK toolchain on Raspberry Pi OS or a documented desktop environment.",
3819
+ "Known-good Obstacle Explorer recovery firmware with adult-owned watchdog, sensor-failure and emergency-stop behaviour."
3820
+ ],
3821
+ warnings: [
3822
+ "Hardware is not included with the module.",
3823
+ "No listed rover or sensor currently claims compatibility or physical-completion eligibility for this module.",
3824
+ "Moving wheels, pinch points, stalled motors, reflective sensor errors and unsuitable supplies can cause unsafe movement or heat; adult assembly, calibration and testing are mandatory.",
3825
+ "The simulator and simulated badge remain available without physical equipment."
3826
+ ],
3827
+ unrelatedHardwareNotRequired: [
3828
+ "Camera Module 3 or Raspberry Pi Zero 2 W",
3829
+ "colour targets or camera ribbon",
3830
+ "servo, LED or infrared beacon parts"
3831
+ ]
3832
+ }
3833
+ }
3834
+ };
3480
3835
  var RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1 = {
3481
3836
  version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
3482
3837
  moduleId: "junior-coder.rescue-crew-commander",
@@ -4281,6 +4636,7 @@ ${summary}`);
4281
4636
  JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1,
4282
4637
  METEOR_SHIELD_MISSION_ONE_AUTHORING_V1,
4283
4638
  MISSION_AUTHORING_CONTRACT_VERSION_V1,
4639
+ OBSTACLE_EXPLORER_MISSION_ONE_AUTHORING_V1,
4284
4640
  PADDLE_PULSE_MISSION_ONE_AUTHORING_V1,
4285
4641
  PIXEL_TRAIL_CHALLENGE_MISSION_ONE_AUTHORING_V1,
4286
4642
  RESCUE_CREW_COMMANDER_MISSION_ONE_AUTHORING_V1,