@plasius/learning 0.2.13 → 0.2.14

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
@@ -76,6 +76,7 @@ import {
76
76
  SERVO_CREATURE_MISSION_ONE_AUTHORING_V1,
77
77
  SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1,
78
78
  STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1,
79
+ VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1,
79
80
  assertValidMissionAuthoringBundle,
80
81
  } from "@plasius/learning";
81
82
 
@@ -118,6 +119,9 @@ const obstacleExplorer = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
118
119
  const rainbowRescueRover = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
119
120
  (module) => module.slug === "rainbow-rescue-rover",
120
121
  );
122
+ const vibeGameRemixLab = JUNIOR_CODER_ROBOT_RESCUE_PATH_V1_1.modules.find(
123
+ (module) => module.slug === "vibe-game-remix-lab",
124
+ );
121
125
 
122
126
  if (
123
127
  !roadHopper ||
@@ -132,7 +136,8 @@ if (
132
136
  !servoCreature ||
133
137
  !danceRover ||
134
138
  !obstacleExplorer ||
135
- !rainbowRescueRover
139
+ !rainbowRescueRover ||
140
+ !vibeGameRemixLab
136
141
  ) {
137
142
  throw new Error("Junior Coder module is missing");
138
143
  }
@@ -189,6 +194,10 @@ assertValidMissionAuthoringBundle(
189
194
  RAINBOW_RESCUE_ROVER_MISSION_ONE_AUTHORING_V1,
190
195
  rainbowRescueRover,
191
196
  );
197
+ assertValidMissionAuthoringBundle(
198
+ VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1,
199
+ vibeGameRemixLab,
200
+ );
192
201
  ```
193
202
 
194
203
  ## Contract rules
@@ -231,6 +240,10 @@ assertValidMissionAuthoringBundle(
231
240
  the family Raspberry Pi. The website receives no frames, opens no camera or
232
241
  serial port, never activates motors, and every physical component remains
233
242
  pending adult bench verification.
243
+ - Vibe Game Remix Lab exposes one authored, evidence-bound diff against one
244
+ permitted learner artifact. The learner predicts, reviews and explicitly
245
+ accepts or rejects it; rejection preserves source, deterministic completion
246
+ never needs AI, and open chat or automatic edits are outside the contract.
234
247
 
235
248
  See [the foundation design](docs/design/junior-coder-catalog-foundation.md),
236
249
  [the uniform pricing design](docs/design/junior-coder-uniform-pricing.md),
@@ -242,6 +255,7 @@ See [the foundation design](docs/design/junior-coder-catalog-foundation.md),
242
255
  [TDR 0006](docs/tdrs/tdr-0006-servo-creature-safe-movement-and-power-authoring.md),
243
256
  [TDR 0007](docs/tdrs/tdr-0007-dance-rover-fail-safe-movement-and-power-authoring.md),
244
257
  and [TDR 0008](docs/tdrs/tdr-0008-obstacle-explorer-sensing-watchdog-and-fail-safe-authoring.md).
258
+ See also [TDR 0010](docs/tdrs/tdr-0010-vibe-game-remix-bounded-suggestion-authoring.md).
245
259
 
246
260
  ## Development
247
261
 
package/dist/index.cjs CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  SERVO_CREATURE_MISSION_ONE_AUTHORING_V1: () => SERVO_CREATURE_MISSION_ONE_AUTHORING_V1,
40
40
  SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1: () => SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1,
41
41
  STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1: () => STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1,
42
+ VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1: () => VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1,
42
43
  assertValidLearningPath: () => assertValidLearningPath,
43
44
  assertValidMissionAuthoringBundle: () => assertValidMissionAuthoringBundle,
44
45
  calculateAssessment: () => calculateAssessment,
@@ -1151,6 +1152,19 @@ function validateMissionAuthoringBundle(bundle, module3) {
1151
1152
  );
1152
1153
  }
1153
1154
  }
1155
+ if (learner.boundedSuggestion) {
1156
+ const suggestion = learner.boundedSuggestion;
1157
+ const invalidBoundedSuggestion = suggestion.id.trim().length === 0 || suggestion.source !== "authored-fallback" || suggestion.intent.trim().length === 0 || suggestion.constraints.length === 0 || suggestion.constraints.some((constraint) => constraint.trim().length === 0) || !learnerArtifactIds.has(suggestion.permittedArtifactId) || suggestion.originalSnippet.trim().length === 0 || suggestion.replacementSnippet.trim().length === 0 || suggestion.originalSnippet === suggestion.replacementSnippet || suggestion.explanationPrompt.trim().length === 0 || suggestion.aiOptional !== false || suggestion.learnerApprovalRequired !== true || suggestion.alternatives.length !== 2 || suggestion.alternatives[0] !== "accept" || suggestion.alternatives[1] !== "reject";
1158
+ if (invalidBoundedSuggestion) {
1159
+ issues.push(
1160
+ authoringIssue(
1161
+ "invalid-bounded-suggestion",
1162
+ "A bounded suggestion requires one learner artifact, authored constraints, a visible diff and explicit accept/reject approval.",
1163
+ "learner.boundedSuggestion"
1164
+ )
1165
+ );
1166
+ }
1167
+ }
1154
1168
  const hardware = bundle.hardware;
1155
1169
  if (hardware) {
1156
1170
  if (module3.category !== "robot" || module3.hardware.mode !== "physical-first" || !module3.hardware.simulatorAvailable) {
@@ -4637,6 +4651,280 @@ var METEOR_SHIELD_MISSION_ONE_AUTHORING_V1 = {
4637
4651
  ]
4638
4652
  }
4639
4653
  };
4654
+ var VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1 = {
4655
+ version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
4656
+ moduleId: "junior-coder.vibe-game-remix-lab",
4657
+ moduleVersion: "1.1.0",
4658
+ missionId: "vibe-game-remix-lab-mission-1",
4659
+ learner: {
4660
+ estimatedMinutes: 20,
4661
+ stages: [
4662
+ {
4663
+ kind: "learn",
4664
+ instruction: "Read how setRescueSpeed(), setGateSpacing() and setGoalCount() change the supplied mini-game.",
4665
+ artifactIds: ["vibe-game-remix-lab-m1-guide"]
4666
+ },
4667
+ {
4668
+ kind: "predict",
4669
+ instruction: "Choose one bounded intent card and predict what its one-line diff will change before viewing it.",
4670
+ artifactIds: ["vibe-game-remix-lab-m1-intent-cards"]
4671
+ },
4672
+ {
4673
+ kind: "build",
4674
+ instruction: "Open the supplied mini-game and keep changes inside its documented settings file.",
4675
+ artifactIds: ["vibe-game-remix-lab-m1-code"]
4676
+ },
4677
+ {
4678
+ kind: "run",
4679
+ instruction: "Use the Run action button to start the private JavaScript preview.",
4680
+ artifactIds: ["vibe-game-remix-lab-m1-code"]
4681
+ },
4682
+ {
4683
+ kind: "assess",
4684
+ instruction: "Run deterministic checks before requesting or applying any suggestion.",
4685
+ artifactIds: []
4686
+ },
4687
+ {
4688
+ kind: "inspect",
4689
+ instruction: "Compare the single authored diff with your prediction and the failed goal evidence.",
4690
+ artifactIds: ["vibe-game-remix-lab-m1-code"]
4691
+ },
4692
+ {
4693
+ kind: "fix",
4694
+ instruction: "Accept or reject the proposed change yourself, then rerun the preview and assessment.",
4695
+ artifactIds: ["vibe-game-remix-lab-m1-code"]
4696
+ },
4697
+ {
4698
+ kind: "explain",
4699
+ instruction: "Explain why you accepted or rejected the change and what the new evidence shows.",
4700
+ artifactIds: []
4701
+ },
4702
+ {
4703
+ kind: "reward",
4704
+ instruction: "Collect the evidence-bound badge after the deterministic score reaches 80 and every safety check passes.",
4705
+ artifactIds: []
4706
+ }
4707
+ ],
4708
+ readinessChecks: [
4709
+ {
4710
+ id: "vibe-game-remix-lab-m1-find-setting",
4711
+ prompt: "Point to the documented function that changes how many rescue goals appear.",
4712
+ scored: false
4713
+ }
4714
+ ],
4715
+ artifacts: [
4716
+ {
4717
+ id: "vibe-game-remix-lab-m1-code",
4718
+ kind: "starter-code",
4719
+ audience: "learner",
4720
+ solutionBearing: false
4721
+ },
4722
+ {
4723
+ id: "vibe-game-remix-lab-m1-guide",
4724
+ kind: "starter-assets",
4725
+ audience: "learner",
4726
+ solutionBearing: false
4727
+ },
4728
+ {
4729
+ id: "vibe-game-remix-lab-m1-intent-cards",
4730
+ kind: "printable",
4731
+ audience: "learner",
4732
+ solutionBearing: false
4733
+ }
4734
+ ],
4735
+ goals: [
4736
+ {
4737
+ id: "vibe-game-remix-lab-m1-starts",
4738
+ statement: "The supplied JavaScript mini-game remains structurally valid and starts.",
4739
+ visibility: "visible",
4740
+ criterionIds: ["vibe-game-remix-lab-build"],
4741
+ completionRequired: true,
4742
+ aiRequired: false
4743
+ },
4744
+ {
4745
+ id: "vibe-game-remix-lab-m1-bounded-remix",
4746
+ statement: "The approved one-file change matches the chosen intent and every published behaviour goal.",
4747
+ visibility: "visible",
4748
+ criterionIds: [
4749
+ "vibe-game-remix-lab-goal-one",
4750
+ "vibe-game-remix-lab-goal-two",
4751
+ "vibe-game-remix-lab-goal-three"
4752
+ ],
4753
+ completionRequired: true,
4754
+ aiRequired: false
4755
+ },
4756
+ {
4757
+ id: "vibe-game-remix-lab-m1-private-runtime",
4758
+ statement: "The remix stays inside the private sandbox with no network, personal data or automatic code changes.",
4759
+ visibility: "visible",
4760
+ criterionIds: ["vibe-game-remix-lab-safety"],
4761
+ completionRequired: true,
4762
+ aiRequired: false
4763
+ }
4764
+ ],
4765
+ interactions: [
4766
+ {
4767
+ id: "vibe-game-remix-lab-m1-run-control",
4768
+ description: "Start the supplied mini-game preview.",
4769
+ primaryMode: "pointer",
4770
+ alternativeIds: ["vibe-game-remix-lab-m1-keyboard-run"]
4771
+ },
4772
+ {
4773
+ id: "vibe-game-remix-lab-m1-diff-review",
4774
+ description: "Read the removed and added source line before choosing what to do.",
4775
+ primaryMode: "text",
4776
+ alternativeIds: []
4777
+ },
4778
+ {
4779
+ id: "vibe-game-remix-lab-m1-accept-control",
4780
+ description: "Approve the exact immutable suggestion snapshot.",
4781
+ primaryMode: "pointer",
4782
+ alternativeIds: ["vibe-game-remix-lab-m1-keyboard-review"]
4783
+ },
4784
+ {
4785
+ id: "vibe-game-remix-lab-m1-reject-control",
4786
+ description: "Reject the suggestion and preserve the current source.",
4787
+ primaryMode: "pointer",
4788
+ alternativeIds: ["vibe-game-remix-lab-m1-keyboard-review"]
4789
+ }
4790
+ ],
4791
+ accessibilityAlternatives: [
4792
+ {
4793
+ id: "vibe-game-remix-lab-m1-keyboard-run",
4794
+ modes: ["keyboard"],
4795
+ equivalentOutcome: true,
4796
+ description: "Press Enter or Space on the play-icon Run button to start the same preview."
4797
+ },
4798
+ {
4799
+ id: "vibe-game-remix-lab-m1-keyboard-review",
4800
+ modes: ["keyboard", "text", "reduced-motion"],
4801
+ equivalentOutcome: true,
4802
+ description: "Read the labelled removed and added lines, then focus Accept or Reject and press Enter or Space."
4803
+ }
4804
+ ],
4805
+ evidenceRequirements: [
4806
+ {
4807
+ id: "vibe-game-remix-lab-m1-assessment",
4808
+ goalIds: [
4809
+ "vibe-game-remix-lab-m1-starts",
4810
+ "vibe-game-remix-lab-m1-bounded-remix",
4811
+ "vibe-game-remix-lab-m1-private-runtime"
4812
+ ],
4813
+ kind: "assessment-result",
4814
+ retention: "entitlement",
4815
+ containsPersonalData: false
4816
+ },
4817
+ {
4818
+ id: "vibe-game-remix-lab-m1-explanation",
4819
+ goalIds: ["vibe-game-remix-lab-m1-bounded-remix"],
4820
+ kind: "learner-explanation",
4821
+ retention: "attempt",
4822
+ containsPersonalData: false
4823
+ }
4824
+ ],
4825
+ sideAdventures: [
4826
+ {
4827
+ id: "vibe-game-remix-lab-m1-inventor",
4828
+ prompt: "Write a new bounded remix intent card with one permitted setting, one constraint and one success test.",
4829
+ completionRequired: false
4830
+ }
4831
+ ],
4832
+ rewardBindings: [
4833
+ {
4834
+ id: "vibe-game-remix-lab-m1-badge",
4835
+ badgeId: "vibe-game-remix-lab-mission-complete",
4836
+ goalIds: [
4837
+ "vibe-game-remix-lab-m1-starts",
4838
+ "vibe-game-remix-lab-m1-bounded-remix",
4839
+ "vibe-game-remix-lab-m1-private-runtime"
4840
+ ],
4841
+ deterministic: true,
4842
+ random: false,
4843
+ tokenConvertible: false
4844
+ }
4845
+ ],
4846
+ functionReference: [
4847
+ {
4848
+ id: "vibe-game-remix-lab-function-speed",
4849
+ signature: "setRescueSpeed(speed)",
4850
+ summary: "Sets the supplied rescue robot's bounded movement speed.",
4851
+ parameters: [{ name: "speed", type: "whole number", description: "A safe speed from 1 to 5." }],
4852
+ effect: "Changes only the private mini-game simulation speed.",
4853
+ example: "setRescueSpeed(3);"
4854
+ },
4855
+ {
4856
+ id: "vibe-game-remix-lab-function-spacing",
4857
+ signature: "setGateSpacing(spacing)",
4858
+ summary: "Sets the gap between original rescue gates.",
4859
+ parameters: [{ name: "spacing", type: "whole number", description: "A bounded spacing from 2 to 6." }],
4860
+ effect: "Changes only the generated gate layout in the private preview.",
4861
+ example: "setGateSpacing(4);"
4862
+ },
4863
+ {
4864
+ id: "vibe-game-remix-lab-function-goals",
4865
+ signature: "setGoalCount(count)",
4866
+ summary: "Chooses how many fictional rescue goals the round contains.",
4867
+ parameters: [{ name: "count", type: "whole number", description: "A bounded goal count from 1 to 4." }],
4868
+ effect: "Changes the labelled rescue-goal count without network or account access.",
4869
+ example: "setGoalCount(3);"
4870
+ }
4871
+ ],
4872
+ boundedSuggestion: {
4873
+ id: "vibe-game-remix-lab-m1-authored-goal-diff",
4874
+ source: "authored-fallback",
4875
+ intent: "Make the round contain one more rescue goal.",
4876
+ constraints: [
4877
+ "Change exactly one documented setting.",
4878
+ "Keep the goal count inside the published range.",
4879
+ "Do not add network, storage, DOM or account access."
4880
+ ],
4881
+ permittedArtifactId: "vibe-game-remix-lab-m1-code",
4882
+ originalSnippet: "setGoalCount(2);",
4883
+ replacementSnippet: "setGoalCount(3);",
4884
+ explanationPrompt: "Did the new goal count match your prediction, and which assessment evidence proves it?",
4885
+ aiOptional: false,
4886
+ learnerApprovalRequired: true,
4887
+ alternatives: ["accept", "reject"]
4888
+ }
4889
+ },
4890
+ facilitator: {
4891
+ artifacts: [
4892
+ {
4893
+ id: "vibe-game-remix-lab-m1-answer-key",
4894
+ kind: "answer-key",
4895
+ audience: "facilitator",
4896
+ solutionBearing: true
4897
+ },
4898
+ {
4899
+ id: "vibe-game-remix-lab-m1-protected-tests",
4900
+ kind: "protected-test",
4901
+ audience: "facilitator",
4902
+ solutionBearing: true
4903
+ },
4904
+ {
4905
+ id: "vibe-game-remix-lab-m1-safety-notes",
4906
+ kind: "facilitator-note",
4907
+ audience: "facilitator",
4908
+ solutionBearing: true
4909
+ }
4910
+ ],
4911
+ protectedGoals: [
4912
+ {
4913
+ id: "vibe-game-remix-lab-m1-protected-resilience",
4914
+ statement: "The sandbox rejects prompt injection, answer dumping, disallowed files, network access and changes outside the approved diff.",
4915
+ visibility: "protected",
4916
+ criterionIds: ["vibe-game-remix-lab-edge-one", "vibe-game-remix-lab-edge-two"],
4917
+ completionRequired: false,
4918
+ aiRequired: false
4919
+ }
4920
+ ],
4921
+ prompts: [
4922
+ "Ask for the learner's prediction before revealing the authored diff.",
4923
+ "Do not invite free-form chat; keep intent, evidence and suggestions bound to the current project, rubric and permitted artifact.",
4924
+ "A rejection must leave source unchanged, and AI/provider failure must never block deterministic completion."
4925
+ ]
4926
+ }
4927
+ };
4640
4928
  var ROAD_HOPPER_RALLY_MISSION_ONE_AUTHORING_V1 = {
4641
4929
  version: MISSION_AUTHORING_CONTRACT_VERSION_V1,
4642
4930
  moduleId: "junior-coder.road-hopper-rally",
@@ -5005,6 +5293,7 @@ ${summary}`);
5005
5293
  SERVO_CREATURE_MISSION_ONE_AUTHORING_V1,
5006
5294
  SKYWING_SPRINT_MISSION_ONE_AUTHORING_V1,
5007
5295
  STAR_DEFENDER_SQUADRON_MISSION_ONE_AUTHORING_V1,
5296
+ VIBE_GAME_REMIX_LAB_MISSION_ONE_AUTHORING_V1,
5008
5297
  assertValidLearningPath,
5009
5298
  assertValidMissionAuthoringBundle,
5010
5299
  calculateAssessment,