@almadar/std 16.173.0 → 16.175.0

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.
Files changed (220) hide show
  1. package/behaviors/lolo/infra/atoms/std-cross-reference.lolo +2 -4
  2. package/behaviors/lolo/ui/core/atoms/std-board.lolo +5 -9
  3. package/behaviors/lolo/ui/core/atoms/std-browse.lolo +8 -1
  4. package/behaviors/lolo/ui/core/atoms/std-esign-flow.lolo +2 -2
  5. package/behaviors/lolo/ui/core/atoms/std-event-log.lolo +3 -7
  6. package/behaviors/lolo/ui/core/atoms/std-form-advanced.lolo +1 -1
  7. package/behaviors/lolo/ui/core/atoms/std-image-upload-multi.lolo +1 -1
  8. package/behaviors/lolo/ui/core/atoms/std-list.lolo +3 -3
  9. package/behaviors/lolo/ui/core/atoms/std-modal.lolo +2 -2
  10. package/behaviors/lolo/ui/core/atoms/std-multi-party-flow.lolo +2 -4
  11. package/behaviors/lolo/ui/core/atoms/std-rating-review.lolo +5 -13
  12. package/behaviors/lolo/ui/core/atoms/std-recurrence.lolo +3 -7
  13. package/behaviors/lolo/ui/core/atoms/std-saved-search.lolo +1 -1
  14. package/behaviors/lolo/ui/core/atoms/std-signature-capture.lolo +2 -2
  15. package/behaviors/lolo/ui/core/atoms/std-step-flow.lolo +2 -4
  16. package/behaviors/lolo/ui/core/atoms/std-tag-taxonomy.lolo +1 -1
  17. package/behaviors/lolo/ui/core/atoms/std-thread.lolo +2 -2
  18. package/behaviors/lolo/ui/core/atoms/std-vote.lolo +2 -2
  19. package/behaviors/lolo/ui/core/atoms/std-wizard.lolo +3 -7
  20. package/behaviors/lolo/ui/core/atoms/ui-atlas-image.lolo +1 -1
  21. package/behaviors/lolo/ui/core/atoms/ui-atlas-panel.lolo +1 -1
  22. package/behaviors/lolo/ui/core/atoms/ui-center.lolo +1 -1
  23. package/behaviors/lolo/ui/core/atoms/ui-hstack.lolo +1 -1
  24. package/behaviors/lolo/ui/core/atoms/ui-icon.lolo +1 -1
  25. package/behaviors/lolo/ui/core/atoms/ui-stack.lolo +1 -1
  26. package/behaviors/lolo/ui/core/atoms/ui-typography.lolo +1 -1
  27. package/behaviors/lolo/ui/core/atoms/ui-vstack.lolo +1 -1
  28. package/behaviors/lolo/ui/core/molecules/ui-content-renderer.lolo +1 -1
  29. package/behaviors/lolo/ui/core/molecules/ui-form-layout.lolo +1 -1
  30. package/behaviors/lolo/ui/core/molecules/ui-grid.lolo +1 -1
  31. package/behaviors/lolo/ui/core/molecules/ui-table-view.lolo +4 -9
  32. package/behaviors/lolo/ui/core/organisms/ui-chat-bar.lolo +1 -1
  33. package/behaviors/lolo/ui/core/organisms/ui-dashboard-grid.lolo +1 -1
  34. package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +1 -1
  35. package/behaviors/lolo/ui/core/organisms/ui-entity-cards.lolo +1 -1
  36. package/behaviors/lolo/ui/core/organisms/ui-entity-list.lolo +1 -1
  37. package/behaviors/lolo/ui/core/organisms/ui-entity-table.lolo +1 -1
  38. package/behaviors/lolo/ui/core/organisms/ui-form-section.lolo +9 -3
  39. package/behaviors/lolo/ui/core/organisms/ui-form.lolo +9 -3
  40. package/behaviors/lolo/ui/core/organisms/ui-master-detail.lolo +1 -1
  41. package/behaviors/lolo/ui/core/organisms/ui-media-gallery.lolo +1 -1
  42. package/behaviors/lolo/ui/core/organisms/ui-segment-renderer.lolo +7 -1
  43. package/behaviors/lolo/ui/core/organisms/ui-stat-card.lolo +1 -1
  44. package/behaviors/lolo/ui/core/organisms/ui-subagent-trace-panel.lolo +1 -1
  45. package/behaviors/lolo/ui/game/atoms/ui-action-tile.lolo +1 -1
  46. package/behaviors/lolo/ui/game/atoms/ui-draw-shape-layer.lolo +41 -9
  47. package/behaviors/lolo/ui/game/atoms/ui-draw-shape.lolo +40 -8
  48. package/behaviors/lolo/ui/game/atoms/ui-draw-sprite-layer.lolo +13 -3
  49. package/behaviors/lolo/ui/game/atoms/ui-draw-sprite.lolo +12 -2
  50. package/behaviors/lolo/ui/game/atoms/ui-draw-text-layer.lolo +3 -3
  51. package/behaviors/lolo/ui/game/atoms/ui-draw-text.lolo +2 -2
  52. package/behaviors/lolo/ui/game/organisms/std-tactics-board-3d.lolo +32 -2
  53. package/behaviors/lolo/ui/learning/atoms/std-learn-classify.lolo +133 -23
  54. package/behaviors/lolo/ui/learning/atoms/std-learn-compare.lolo +397 -0
  55. package/behaviors/lolo/ui/learning/atoms/std-learn-coupled-sim.lolo +537 -0
  56. package/behaviors/lolo/ui/learning/atoms/std-learn-derivation.lolo +428 -0
  57. package/behaviors/lolo/ui/learning/atoms/std-learn-doser.lolo +520 -0
  58. package/behaviors/lolo/ui/learning/atoms/std-learn-estimate.lolo +419 -0
  59. package/behaviors/lolo/ui/learning/atoms/std-learn-goal-seek.lolo +591 -0
  60. package/behaviors/lolo/ui/learning/atoms/std-learn-grid-sim.lolo +425 -0
  61. package/behaviors/lolo/ui/learning/atoms/std-learn-hotspot.lolo +398 -0
  62. package/behaviors/lolo/ui/learning/atoms/std-learn-measure.lolo +325 -0
  63. package/behaviors/lolo/ui/learning/atoms/std-learn-perturb.lolo +494 -0
  64. package/behaviors/lolo/ui/learning/atoms/std-learn-predict.lolo +408 -0
  65. package/behaviors/lolo/ui/learning/atoms/std-learn-scatter-fit.lolo +805 -0
  66. package/behaviors/lolo/ui/learning/atoms/std-learn-scenario.lolo +307 -0
  67. package/behaviors/lolo/ui/learning/atoms/std-learn-sim-3d.lolo +318 -0
  68. package/behaviors/lolo/ui/learning/atoms/std-learn-speed-drill.lolo +336 -0
  69. package/behaviors/lolo/ui/learning/atoms/std-learn-tour-3d.lolo +409 -0
  70. package/behaviors/lolo/ui/learning/atoms/std-learn-transport.lolo +186 -0
  71. package/behaviors/lolo/ui/learning/atoms/std-learn-tree.lolo +522 -0
  72. package/behaviors/lolo/ui/learning/atoms/ui-algo-graph-canvas.lolo +192 -0
  73. package/behaviors/lolo/ui/learning/atoms/ui-algorithm-canvas.lolo +111 -2
  74. package/behaviors/lolo/ui/learning/atoms/ui-biology-canvas.lolo +193 -5
  75. package/behaviors/lolo/ui/learning/atoms/ui-chemistry-canvas.lolo +173 -5
  76. package/behaviors/lolo/ui/learning/atoms/ui-learning-canvas.lolo +48 -1
  77. package/behaviors/lolo/ui/learning/atoms/ui-math-canvas.lolo +141 -1
  78. package/behaviors/lolo/ui/learning/atoms/ui-physics-canvas.lolo +242 -5
  79. package/behaviors/lolo/ui/marketing/organisms/ui-book-viewer.lolo +1 -1
  80. package/behaviors/lolo/ui/marketing/organisms/ui-case-study-organism.lolo +1 -1
  81. package/behaviors/lolo/ui/marketing/organisms/ui-feature-grid-organism.lolo +1 -1
  82. package/behaviors/lolo/ui/marketing/organisms/ui-hero-organism.lolo +1 -1
  83. package/behaviors/lolo/ui/marketing/organisms/ui-pricing-organism.lolo +1 -1
  84. package/behaviors/lolo/ui/marketing/organisms/ui-showcase-organism.lolo +1 -1
  85. package/behaviors/lolo/ui/marketing/organisms/ui-stats-organism.lolo +1 -1
  86. package/behaviors/lolo/ui/marketing/organisms/ui-step-flow-organism.lolo +1 -1
  87. package/behaviors/lolo/ui/marketing/organisms/ui-team-organism.lolo +1 -1
  88. package/behaviors/registry/agent/atoms/std-agent-session.orb +22 -1
  89. package/behaviors/registry/agent/atoms/std-agent-tool-call.orb +38 -2
  90. package/behaviors/registry/agent/atoms/std-agent-tool-loop.orb +38 -2
  91. package/behaviors/registry/agent/organisms/std-agent-rabit.orb +23 -1
  92. package/behaviors/registry/infra/atoms/std-approval-gate.orb +8 -16
  93. package/behaviors/registry/infra/atoms/std-cache-aside.orb +31 -62
  94. package/behaviors/registry/infra/atoms/std-circuit-breaker.orb +16 -32
  95. package/behaviors/registry/infra/atoms/std-cross-reference.orb +32 -4
  96. package/behaviors/registry/infra/atoms/std-data-erasure.orb +8 -16
  97. package/behaviors/registry/infra/atoms/std-mod-queue.orb +8 -16
  98. package/behaviors/registry/infra/atoms/std-rate-limiter.orb +14 -28
  99. package/behaviors/registry/infra/atoms/std-row-access-control.orb +30 -2
  100. package/behaviors/registry/ui/core/atoms/std-billable-hour.orb +1 -2
  101. package/behaviors/registry/ui/core/atoms/std-board.orb +19 -5
  102. package/behaviors/registry/ui/core/atoms/std-browse.orb +29 -7
  103. package/behaviors/registry/ui/core/atoms/std-dashboard-grid-embedded.orb +1 -2
  104. package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +3 -5
  105. package/behaviors/registry/ui/core/atoms/std-esign-request.orb +3 -6
  106. package/behaviors/registry/ui/core/atoms/std-event-log.orb +17 -3
  107. package/behaviors/registry/ui/core/atoms/std-export.orb +2 -4
  108. package/behaviors/registry/ui/core/atoms/std-form-advanced.orb +1 -1
  109. package/behaviors/registry/ui/core/atoms/std-gallery.orb +9 -18
  110. package/behaviors/registry/ui/core/atoms/std-graphs.orb +15 -1
  111. package/behaviors/registry/ui/core/atoms/std-import.orb +2 -4
  112. package/behaviors/registry/ui/core/atoms/std-list.orb +4 -6
  113. package/behaviors/registry/ui/core/atoms/std-modal.orb +2 -2
  114. package/behaviors/registry/ui/core/atoms/std-multi-party-flow.orb +16 -2
  115. package/behaviors/registry/ui/core/atoms/std-pagination.orb +15 -1
  116. package/behaviors/registry/ui/core/atoms/std-rating-review.orb +19 -5
  117. package/behaviors/registry/ui/core/atoms/std-recurrence.orb +17 -3
  118. package/behaviors/registry/ui/core/atoms/std-rich-editor.orb +15 -1
  119. package/behaviors/registry/ui/core/atoms/std-scatter.orb +15 -1
  120. package/behaviors/registry/ui/core/atoms/std-signature-capture.orb +2 -2
  121. package/behaviors/registry/ui/core/atoms/std-stats.orb +15 -1
  122. package/behaviors/registry/ui/core/atoms/std-step-flow.orb +16 -2
  123. package/behaviors/registry/ui/core/atoms/std-thread.orb +2 -2
  124. package/behaviors/registry/ui/core/atoms/std-vote.orb +2 -2
  125. package/behaviors/registry/ui/core/atoms/std-wizard.orb +17 -3
  126. package/behaviors/registry/ui/core/atoms/ui-atlas-image.orb +4 -1
  127. package/behaviors/registry/ui/core/atoms/ui-atlas-panel.orb +4 -1
  128. package/behaviors/registry/ui/core/atoms/ui-center.orb +4 -1
  129. package/behaviors/registry/ui/core/atoms/ui-hstack.orb +4 -1
  130. package/behaviors/registry/ui/core/atoms/ui-icon.orb +4 -1
  131. package/behaviors/registry/ui/core/atoms/ui-stack.orb +4 -1
  132. package/behaviors/registry/ui/core/atoms/ui-typography.orb +4 -1
  133. package/behaviors/registry/ui/core/atoms/ui-vstack.orb +4 -1
  134. package/behaviors/registry/ui/core/molecules/ui-accordion.orb +3 -3
  135. package/behaviors/registry/ui/core/molecules/ui-content-renderer.orb +4 -1
  136. package/behaviors/registry/ui/core/molecules/ui-form-layout.orb +4 -1
  137. package/behaviors/registry/ui/core/molecules/ui-grid.orb +4 -1
  138. package/behaviors/registry/ui/core/molecules/ui-table-view.orb +4 -39
  139. package/behaviors/registry/ui/core/molecules/ui-tabs.orb +2 -2
  140. package/behaviors/registry/ui/core/molecules/ui-wizard-container.orb +1 -1
  141. package/behaviors/registry/ui/core/organisms/ui-chat-bar.orb +4 -1
  142. package/behaviors/registry/ui/core/organisms/ui-dashboard-grid.orb +5 -2
  143. package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +5 -2
  144. package/behaviors/registry/ui/core/organisms/ui-entity-cards.orb +4 -1
  145. package/behaviors/registry/ui/core/organisms/ui-entity-list.orb +4 -1
  146. package/behaviors/registry/ui/core/organisms/ui-entity-table.orb +4 -1
  147. package/behaviors/registry/ui/core/organisms/ui-form-section.orb +34 -2
  148. package/behaviors/registry/ui/core/organisms/ui-form.orb +34 -2
  149. package/behaviors/registry/ui/core/organisms/ui-master-detail.orb +4 -1
  150. package/behaviors/registry/ui/core/organisms/ui-media-gallery.orb +4 -1
  151. package/behaviors/registry/ui/core/organisms/ui-segment-renderer.orb +24 -2
  152. package/behaviors/registry/ui/core/organisms/ui-stat-card.orb +4 -1
  153. package/behaviors/registry/ui/core/organisms/ui-subagent-trace-panel.orb +4 -1
  154. package/behaviors/registry/ui/core/organisms/ui-tabbed-container.orb +1 -1
  155. package/behaviors/registry/ui/core/organisms/ui-ui-slot-renderer.orb +1 -1
  156. package/behaviors/registry/ui/game/atoms/std-fx-particles.orb +35 -1
  157. package/behaviors/registry/ui/game/atoms/ui-action-tile.orb +4 -1
  158. package/behaviors/registry/ui/game/atoms/ui-draw-shape-layer.orb +183 -13
  159. package/behaviors/registry/ui/game/atoms/ui-draw-shape.orb +104 -9
  160. package/behaviors/registry/ui/game/atoms/ui-draw-sprite-layer.orb +56 -2
  161. package/behaviors/registry/ui/game/atoms/ui-draw-sprite.orb +36 -4
  162. package/behaviors/registry/ui/game/atoms/ui-draw-text-layer.orb +21 -2
  163. package/behaviors/registry/ui/game/atoms/ui-draw-text.orb +19 -4
  164. package/behaviors/registry/ui/game/organisms/std-tactics-board-3d.orb +173 -2
  165. package/behaviors/registry/ui/learning/atoms/std-learn-classify.orb +1288 -197
  166. package/behaviors/registry/ui/learning/atoms/std-learn-compare.orb +2814 -0
  167. package/behaviors/registry/ui/learning/atoms/std-learn-coupled-sim.orb +3183 -0
  168. package/behaviors/registry/ui/learning/atoms/std-learn-derivation.orb +2512 -0
  169. package/behaviors/registry/ui/learning/atoms/std-learn-doser.orb +3678 -0
  170. package/behaviors/registry/ui/learning/atoms/std-learn-estimate.orb +2394 -0
  171. package/behaviors/registry/ui/learning/atoms/std-learn-goal-seek.orb +3951 -0
  172. package/behaviors/registry/ui/learning/atoms/std-learn-grid-sim.orb +3458 -0
  173. package/behaviors/registry/ui/learning/atoms/std-learn-hotspot.orb +2646 -0
  174. package/behaviors/registry/ui/learning/atoms/std-learn-measure.orb +1979 -0
  175. package/behaviors/registry/ui/learning/atoms/std-learn-perturb.orb +2994 -0
  176. package/behaviors/registry/ui/learning/atoms/std-learn-predict.orb +2682 -0
  177. package/behaviors/registry/ui/learning/atoms/std-learn-scatter-fit.orb +6539 -0
  178. package/behaviors/registry/ui/learning/atoms/std-learn-scenario.orb +1842 -0
  179. package/behaviors/registry/ui/learning/atoms/std-learn-sim-3d.orb +1648 -0
  180. package/behaviors/registry/ui/learning/atoms/std-learn-speed-drill.orb +2307 -0
  181. package/behaviors/registry/ui/learning/atoms/std-learn-tour-3d.orb +3118 -0
  182. package/behaviors/registry/ui/learning/atoms/std-learn-transport.orb +986 -0
  183. package/behaviors/registry/ui/learning/atoms/std-learn-tree.orb +3333 -0
  184. package/behaviors/registry/ui/learning/atoms/ui-algo-graph-canvas.orb +716 -0
  185. package/behaviors/registry/ui/learning/atoms/ui-algorithm-canvas.orb +679 -5
  186. package/behaviors/registry/ui/learning/atoms/ui-biology-canvas.orb +962 -18
  187. package/behaviors/registry/ui/learning/atoms/ui-chemistry-canvas.orb +919 -30
  188. package/behaviors/registry/ui/learning/atoms/ui-learning-canvas.orb +372 -1
  189. package/behaviors/registry/ui/learning/atoms/ui-math-canvas.orb +936 -16
  190. package/behaviors/registry/ui/learning/atoms/ui-physics-canvas.orb +1328 -43
  191. package/behaviors/registry/ui/marketing/atoms/std-marketing-article.orb +1 -2
  192. package/behaviors/registry/ui/marketing/atoms/std-marketing-footer.orb +1 -2
  193. package/behaviors/registry/ui/marketing/atoms/std-marketing-split.orb +1 -2
  194. package/behaviors/registry/ui/marketing/atoms/std-marketing-stats.orb +1 -2
  195. package/behaviors/registry/ui/marketing/atoms/std-marketing-steps.orb +1 -2
  196. package/behaviors/registry/ui/marketing/atoms/std-marketing-team.orb +1 -2
  197. package/behaviors/registry/ui/marketing/organisms/ui-book-viewer.orb +4 -1
  198. package/behaviors/registry/ui/marketing/organisms/ui-case-study-organism.orb +4 -1
  199. package/behaviors/registry/ui/marketing/organisms/ui-feature-grid-organism.orb +4 -1
  200. package/behaviors/registry/ui/marketing/organisms/ui-hero-organism.orb +4 -1
  201. package/behaviors/registry/ui/marketing/organisms/ui-pricing-organism.orb +4 -1
  202. package/behaviors/registry/ui/marketing/organisms/ui-showcase-organism.orb +4 -1
  203. package/behaviors/registry/ui/marketing/organisms/ui-stats-organism.orb +4 -1
  204. package/behaviors/registry/ui/marketing/organisms/ui-step-flow-organism.orb +4 -1
  205. package/behaviors/registry/ui/marketing/organisms/ui-team-organism.orb +4 -1
  206. package/dist/behaviors/exports-reader.js +3704 -2189
  207. package/dist/behaviors/functions/index.d.ts +2638 -254
  208. package/dist/behaviors/functions/index.js +3648 -2190
  209. package/dist/behaviors/index.d.ts +1 -1
  210. package/dist/behaviors/index.js +3705 -2190
  211. package/dist/behaviors/query.js +3704 -2189
  212. package/dist/behaviors-embeddings.hash.json +3 -3
  213. package/dist/behaviors-embeddings.json +289 -213
  214. package/dist/behaviors-registry.json +7900 -587
  215. package/dist/index.d.ts +1 -1
  216. package/dist/index.js +3705 -2190
  217. package/dist/knob-embeddings.hash.json +3 -3
  218. package/dist/knob-embeddings.json +1 -1
  219. package/dist/registry/factory-signatures.json +1 -1
  220. package/package.json +2 -2
@@ -0,0 +1,419 @@
1
+ app std-learn-estimate "1.0.0"
2
+ "Generic estimation drill — a config-declared prompt roster asks for a quantity, the learner commits an estimate on a slider and locks it in, and the guess is graded by relative-error band: within the exact band scores full points, within the close band partial, outside none, with the true answer and the learner's percentage error revealed after each lock-in and a running score across the round. All vocabulary and bands are config-declared, so the same mechanism serves any quantitative intuition: orders of magnitude, unit conversions, historical dates, population sizes, physical constants, probabilities. Standalone by default; behind a lab router set matchMode and it renders only when MODE_SELECTED matches."
3
+ orbital EstimateOrbital {
4
+ type EstimatePrompt = {
5
+ prompt : string!
6
+ answer : number!
7
+ unit : string
8
+ hint : string
9
+ }
10
+
11
+ entity EstimateScene [runtime] {
12
+ id : string!
13
+ active : boolean = false
14
+ title : string
15
+ promptIndex : number = 0
16
+ totalPrompts : number = 0
17
+ estimate : number = 0
18
+ locked : boolean = false
19
+ band : string
20
+ score : number = 0
21
+ done : boolean = false
22
+ promptText : string
23
+ promptHint : string
24
+ answer : number = 0
25
+ unit : string
26
+ feedback : string
27
+ view : [node]
28
+ }
29
+
30
+ trait EstimateSim -> @rebindable EstimateScene [interaction, instance] {
31
+ initial: idle
32
+
33
+ state idle {
34
+ INIT -> idle when (== @config.matchMode "")
35
+ (let (
36
+ (first (array/nth @config.prompts 0))
37
+ )
38
+ (do
39
+ (set @entity.active true)
40
+ (set @entity.title @config.title)
41
+ (set @entity.promptIndex 0)
42
+ (set @entity.totalPrompts (array/len @config.prompts))
43
+ (set @entity.estimate @config.sliderDefault)
44
+ (set @entity.locked false)
45
+ (set @entity.band "")
46
+ (set @entity.score 0)
47
+ (set @entity.done false)
48
+ (set @entity.promptText (object/get @first prompt))
49
+ (set @entity.promptHint (object/get @first hint ""))
50
+ (set @entity.answer (object/get @first answer))
51
+ (set @entity.unit (object/get @first unit ""))
52
+ (set @entity.feedback "")
53
+ (set @entity.view [
54
+ { type: card, variant: bordered, padding: md, children: [
55
+ { type: typography, variant: body, content: @entity.promptText },
56
+ { type: typography, variant: caption, color: muted, content: @entity.promptHint }
57
+ ] },
58
+ { type: stack, direction: vertical, gap: xs, children: [
59
+ { type: typography, variant: caption, content: (str/concat "Your estimate: " (math/round @entity.estimate 2) " " @entity.unit) },
60
+ { type: range-slider, min: @config.sliderMin, max: @config.sliderMax, step: @config.sliderStep, value: @entity.estimate, showTooltip: true, action: "SET_ESTIMATE" }
61
+ ] },
62
+ { type: stack, direction: horizontal, gap: sm, children: [
63
+ { type: button, action: LOCK_IN, label: @config.lockLabel, variant: primary, disabled: (if @entity.locked true false) },
64
+ { type: button, action: NEXT, label: @config.nextLabel, variant: secondary, disabled: (if @entity.locked false true) }
65
+ ] },
66
+ { type: stack, direction: horizontal, gap: xs, children: [
67
+ { type: typography, variant: caption, content: @entity.feedback }
68
+ ] },
69
+ { type: stat-display, label: "Score", value: @entity.score, max: (* @entity.totalPrompts @config.exactPoints) }
70
+ ])))
71
+ (render-ui main {
72
+ type: box
73
+ padding: md
74
+ children: [
75
+ { type: stack, direction: vertical, gap: md, children: [
76
+ { type: typography, variant: h4, content: @entity.title },
77
+ { type: progress-bar, value: (+ @entity.promptIndex 1), max: @entity.totalPrompts, showPercentage: false, label: (str/concat "Prompt " (str/concat "" (+ @entity.promptIndex 1)) " of " (str/concat "" @entity.totalPrompts)) },
78
+ { type: stack, direction: vertical, gap: md, children: @entity.view }
79
+ ] }
80
+ ]
81
+ })
82
+
83
+ MODE_SELECTED -> idle when (== ?mode @config.matchMode)
84
+ (let (
85
+ (first (array/nth @config.prompts 0))
86
+ )
87
+ (do
88
+ (set @entity.active true)
89
+ (set @entity.title @config.title)
90
+ (set @entity.promptIndex 0)
91
+ (set @entity.totalPrompts (array/len @config.prompts))
92
+ (set @entity.estimate @config.sliderDefault)
93
+ (set @entity.locked false)
94
+ (set @entity.band "")
95
+ (set @entity.score 0)
96
+ (set @entity.done false)
97
+ (set @entity.promptText (object/get @first prompt))
98
+ (set @entity.promptHint (object/get @first hint ""))
99
+ (set @entity.answer (object/get @first answer))
100
+ (set @entity.unit (object/get @first unit ""))
101
+ (set @entity.feedback "")
102
+ (set @entity.view [
103
+ { type: card, variant: bordered, padding: md, children: [
104
+ { type: typography, variant: body, content: @entity.promptText },
105
+ { type: typography, variant: caption, color: muted, content: @entity.promptHint }
106
+ ] },
107
+ { type: stack, direction: vertical, gap: xs, children: [
108
+ { type: typography, variant: caption, content: (str/concat "Your estimate: " (math/round @entity.estimate 2) " " @entity.unit) },
109
+ { type: range-slider, min: @config.sliderMin, max: @config.sliderMax, step: @config.sliderStep, value: @entity.estimate, showTooltip: true, action: "SET_ESTIMATE" }
110
+ ] },
111
+ { type: stack, direction: horizontal, gap: sm, children: [
112
+ { type: button, action: LOCK_IN, label: @config.lockLabel, variant: primary, disabled: (if @entity.locked true false) },
113
+ { type: button, action: NEXT, label: @config.nextLabel, variant: secondary, disabled: (if @entity.locked false true) }
114
+ ] },
115
+ { type: stack, direction: horizontal, gap: xs, children: [
116
+ { type: typography, variant: caption, content: @entity.feedback }
117
+ ] },
118
+ { type: stat-display, label: "Score", value: @entity.score, max: (* @entity.totalPrompts @config.exactPoints) }
119
+ ])))
120
+ (render-ui main {
121
+ type: box
122
+ padding: md
123
+ children: [
124
+ { type: stack, direction: vertical, gap: md, children: [
125
+ { type: typography, variant: h4, content: @entity.title },
126
+ { type: progress-bar, value: (+ @entity.promptIndex 1), max: @entity.totalPrompts, showPercentage: false, label: (str/concat "Prompt " (str/concat "" (+ @entity.promptIndex 1)) " of " (str/concat "" @entity.totalPrompts)) },
127
+ { type: stack, direction: vertical, gap: md, children: @entity.view }
128
+ ] }
129
+ ]
130
+ })
131
+
132
+ SET_ESTIMATE -> idle when (and (== @entity.active true) (and (== @entity.locked false) (== @entity.done false)))
133
+ (set @entity.estimate (math/clamp ?value @config.sliderMin @config.sliderMax))
134
+ (set @entity.view [
135
+ { type: card, variant: bordered, padding: md, children: [
136
+ { type: typography, variant: body, content: @entity.promptText },
137
+ { type: typography, variant: caption, color: muted, content: @entity.promptHint }
138
+ ] },
139
+ { type: stack, direction: vertical, gap: xs, children: [
140
+ { type: typography, variant: caption, content: (str/concat "Your estimate: " (math/round @entity.estimate 2) " " @entity.unit) },
141
+ { type: range-slider, min: @config.sliderMin, max: @config.sliderMax, step: @config.sliderStep, value: @entity.estimate, showTooltip: true, action: "SET_ESTIMATE" }
142
+ ] },
143
+ { type: stack, direction: horizontal, gap: sm, children: [
144
+ { type: button, action: LOCK_IN, label: @config.lockLabel, variant: primary, disabled: (if @entity.locked true false) },
145
+ { type: button, action: NEXT, label: @config.nextLabel, variant: secondary, disabled: (if @entity.locked false true) }
146
+ ] },
147
+ { type: stack, direction: horizontal, gap: xs, children: [
148
+ { type: typography, variant: caption, content: @entity.feedback }
149
+ ] },
150
+ { type: stat-display, label: "Score", value: @entity.score, max: (* @entity.totalPrompts @config.exactPoints) }
151
+ ])
152
+ (render-ui main {
153
+ type: box
154
+ padding: md
155
+ children: [
156
+ { type: stack, direction: vertical, gap: md, children: [
157
+ { type: typography, variant: h4, content: @entity.title },
158
+ { type: progress-bar, value: (+ @entity.promptIndex 1), max: @entity.totalPrompts, showPercentage: false, label: (str/concat "Prompt " (str/concat "" (+ @entity.promptIndex 1)) " of " (str/concat "" @entity.totalPrompts)) },
159
+ { type: stack, direction: vertical, gap: md, children: @entity.view }
160
+ ] }
161
+ ]
162
+ })
163
+
164
+ LOCK_IN -> idle when (and (== @entity.active true) (and (== @entity.locked false) (== @entity.done false)))
165
+ (let (
166
+ (err (math/abs (- @entity.estimate @entity.answer)))
167
+ (rel (/ @err (math/max (math/abs @entity.answer) 0.0001)))
168
+ (band (if (<= @rel @config.exactPct) "exact" (if (<= @rel @config.closePct) "close" "off")))
169
+ (points (if (== @band "exact") @config.exactPoints (if (== @band "close") @config.closePoints 0)))
170
+ )
171
+ (do
172
+ (set @entity.locked true)
173
+ (set @entity.band @band)
174
+ (set @entity.score (+ @entity.score @points))
175
+ (set @entity.feedback (str/concat "Answer: " (math/round @entity.answer 2) " " @entity.unit " — you were off by " (math/round @err 2) " (" (math/round (* @rel 100) 1) "%). +" (str/concat "" @points) " points."))
176
+ (set @entity.view [
177
+ { type: card, variant: bordered, padding: md, children: [
178
+ { type: typography, variant: body, content: @entity.promptText },
179
+ { type: typography, variant: caption, color: muted, content: @entity.promptHint }
180
+ ] },
181
+ { type: stack, direction: vertical, gap: xs, children: [
182
+ { type: typography, variant: caption, content: (str/concat "Your estimate: " (math/round @entity.estimate 2) " " @entity.unit) },
183
+ { type: range-slider, min: @config.sliderMin, max: @config.sliderMax, step: @config.sliderStep, value: @entity.estimate, showTooltip: true, action: "SET_ESTIMATE" }
184
+ ] },
185
+ { type: stack, direction: horizontal, gap: sm, children: [
186
+ { type: button, action: LOCK_IN, label: @config.lockLabel, variant: primary, disabled: (if @entity.locked true false) },
187
+ { type: button, action: NEXT, label: @config.nextLabel, variant: secondary, disabled: (if @entity.locked false true) }
188
+ ] },
189
+ { type: stack, direction: horizontal, gap: xs, children: [
190
+ { type: badge, variant: (if (== @entity.band "exact") "success" (if (== @entity.band "close") "warning" "danger")), label: (if (== @entity.band "exact") "Spot on" (if (== @entity.band "close") "Close" "Off")) },
191
+ { type: typography, variant: caption, content: @entity.feedback }
192
+ ] },
193
+ { type: stat-display, label: "Score", value: @entity.score, max: (* @entity.totalPrompts @config.exactPoints) }
194
+ ])))
195
+ (render-ui main {
196
+ type: box
197
+ padding: md
198
+ children: [
199
+ { type: stack, direction: vertical, gap: md, children: [
200
+ { type: typography, variant: h4, content: @entity.title },
201
+ { type: progress-bar, value: (+ @entity.promptIndex 1), max: @entity.totalPrompts, showPercentage: false, label: (str/concat "Prompt " (str/concat "" (+ @entity.promptIndex 1)) " of " (str/concat "" @entity.totalPrompts)) },
202
+ { type: stack, direction: vertical, gap: md, children: @entity.view }
203
+ ] }
204
+ ]
205
+ })
206
+ (emit ESTIMATE_JUDGED { band: @entity.band, estimate: @entity.estimate, answer: @entity.answer, score: @entity.score })
207
+
208
+ NEXT -> idle when (and (== @entity.active true) (and (== @entity.locked true) (== @entity.done false)))
209
+ (let (
210
+ (nextIndex (+ @entity.promptIndex 1))
211
+ (finished (>= @nextIndex (array/len @config.prompts)))
212
+ (next (array/nth @config.prompts (math/min @nextIndex (- (array/len @config.prompts) 1))))
213
+ )
214
+ (do
215
+ (set @entity.promptIndex (if @finished @entity.promptIndex @nextIndex))
216
+ (set @entity.done (if @finished true false))
217
+ (set @entity.locked false)
218
+ (set @entity.band "")
219
+ (set @entity.estimate @config.sliderDefault)
220
+ (set @entity.promptText (if @finished @entity.promptText (object/get @next prompt)))
221
+ (set @entity.promptHint (if @finished @entity.promptHint (object/get @next hint "")))
222
+ (set @entity.answer (if @finished @entity.answer (object/get @next answer)))
223
+ (set @entity.unit (if @finished @entity.unit (object/get @next unit "")))
224
+ (set @entity.feedback "")
225
+ (set @entity.view (if @finished
226
+ [
227
+ { type: typography, variant: h4, content: "Round Complete" },
228
+ { type: stat-display, label: "Final score", value: @entity.score, max: (* @entity.totalPrompts @config.exactPoints) },
229
+ { type: button, action: RETRY, label: @config.retryLabel, variant: primary }
230
+ ]
231
+ [
232
+ { type: card, variant: bordered, padding: md, children: [
233
+ { type: typography, variant: body, content: @entity.promptText },
234
+ { type: typography, variant: caption, color: muted, content: @entity.promptHint }
235
+ ] },
236
+ { type: stack, direction: vertical, gap: xs, children: [
237
+ { type: typography, variant: caption, content: (str/concat "Your estimate: " (math/round @entity.estimate 2) " " @entity.unit) },
238
+ { type: range-slider, min: @config.sliderMin, max: @config.sliderMax, step: @config.sliderStep, value: @entity.estimate, showTooltip: true, action: "SET_ESTIMATE" }
239
+ ] },
240
+ { type: stack, direction: horizontal, gap: sm, children: [
241
+ { type: button, action: LOCK_IN, label: @config.lockLabel, variant: primary, disabled: (if @entity.locked true false) },
242
+ { type: button, action: NEXT, label: @config.nextLabel, variant: secondary, disabled: (if @entity.locked false true) }
243
+ ] },
244
+ { type: stack, direction: horizontal, gap: xs, children: [
245
+ { type: typography, variant: caption, content: @entity.feedback }
246
+ ] },
247
+ { type: stat-display, label: "Score", value: @entity.score, max: (* @entity.totalPrompts @config.exactPoints) }
248
+ ])))
249
+ )
250
+ (render-ui main {
251
+ type: box
252
+ padding: md
253
+ children: [
254
+ { type: stack, direction: vertical, gap: md, children: [
255
+ { type: typography, variant: h4, content: @entity.title },
256
+ { type: progress-bar, value: (+ @entity.promptIndex 1), max: @entity.totalPrompts, showPercentage: false, label: (str/concat "Prompt " (str/concat "" (+ @entity.promptIndex 1)) " of " (str/concat "" @entity.totalPrompts)) },
257
+ { type: stack, direction: vertical, gap: md, children: @entity.view }
258
+ ] }
259
+ ]
260
+ })
261
+ (emit PROMPT_ADVANCED { promptIndex: @entity.promptIndex, done: @entity.done, score: @entity.score })
262
+
263
+ RETRY -> idle when (and (== @entity.active true) (== @entity.done true))
264
+ (let (
265
+ (first (array/nth @config.prompts 0))
266
+ )
267
+ (do
268
+ (set @entity.promptIndex 0)
269
+ (set @entity.estimate @config.sliderDefault)
270
+ (set @entity.locked false)
271
+ (set @entity.band "")
272
+ (set @entity.score 0)
273
+ (set @entity.done false)
274
+ (set @entity.promptText (object/get @first prompt))
275
+ (set @entity.promptHint (object/get @first hint ""))
276
+ (set @entity.answer (object/get @first answer))
277
+ (set @entity.unit (object/get @first unit ""))
278
+ (set @entity.feedback "")
279
+ (set @entity.view [
280
+ { type: card, variant: bordered, padding: md, children: [
281
+ { type: typography, variant: body, content: @entity.promptText },
282
+ { type: typography, variant: caption, color: muted, content: @entity.promptHint }
283
+ ] },
284
+ { type: stack, direction: vertical, gap: xs, children: [
285
+ { type: typography, variant: caption, content: (str/concat "Your estimate: " (math/round @entity.estimate 2) " " @entity.unit) },
286
+ { type: range-slider, min: @config.sliderMin, max: @config.sliderMax, step: @config.sliderStep, value: @entity.estimate, showTooltip: true, action: "SET_ESTIMATE" }
287
+ ] },
288
+ { type: stack, direction: horizontal, gap: sm, children: [
289
+ { type: button, action: LOCK_IN, label: @config.lockLabel, variant: primary, disabled: (if @entity.locked true false) },
290
+ { type: button, action: NEXT, label: @config.nextLabel, variant: secondary, disabled: (if @entity.locked false true) }
291
+ ] },
292
+ { type: stack, direction: horizontal, gap: xs, children: [
293
+ { type: typography, variant: caption, content: @entity.feedback }
294
+ ] },
295
+ { type: stat-display, label: "Score", value: @entity.score, max: (* @entity.totalPrompts @config.exactPoints) }
296
+ ])))
297
+ (render-ui main {
298
+ type: box
299
+ padding: md
300
+ children: [
301
+ { type: stack, direction: vertical, gap: md, children: [
302
+ { type: typography, variant: h4, content: @entity.title },
303
+ { type: progress-bar, value: (+ @entity.promptIndex 1), max: @entity.totalPrompts, showPercentage: false, label: (str/concat "Prompt " (str/concat "" (+ @entity.promptIndex 1)) " of " (str/concat "" @entity.totalPrompts)) },
304
+ { type: stack, direction: vertical, gap: md, children: @entity.view }
305
+ ] }
306
+ ]
307
+ })
308
+ (emit ROUND_RESTARTED { totalPrompts: @entity.totalPrompts })
309
+ }
310
+
311
+ listens {
312
+ MODE_SELECTED {
313
+ mode : string
314
+ }
315
+ @description "Lab router broadcast naming the active mode; this instrument renders when the mode equals matchMode, otherwise renders null."
316
+ @tier "domain"
317
+ SET_ESTIMATE {
318
+ value : number
319
+ }
320
+ @description "Learner moved the estimate slider — value is the current guess, not yet graded."
321
+ @tier "domain"
322
+ LOCK_IN {
323
+ }
324
+ @description "Learner committed the current estimate; it is graded against the true answer by relative-error band."
325
+ @tier "domain"
326
+ NEXT {
327
+ }
328
+ @description "Learner advanced to the next prompt after a lock-in; past the last prompt this completes the round."
329
+ @tier "domain"
330
+ RETRY {
331
+ }
332
+ @description "Learner restarted the round from the first prompt with a cleared score."
333
+ @tier "domain"
334
+ }
335
+
336
+ emits {
337
+ ESTIMATE_JUDGED -> external {
338
+ band : string
339
+ estimate : number
340
+ answer : number
341
+ score : number
342
+ }
343
+ @description "The verdict of a lock-in: which error band the estimate landed in (exact, close, off), the guess, the truth, and the running score — a composed listener (coach, grader) can subscribe; a harmless no-op when the atom runs standalone."
344
+ @synonyms "estimation, order of magnitude, guess the number, error band, quantitative intuition"
345
+ @tier "domain"
346
+ PROMPT_ADVANCED -> external {
347
+ promptIndex : number
348
+ done : boolean
349
+ score : number
350
+ }
351
+ @description "The learner moved to the next prompt (or completed the round) with the running score."
352
+ @tier "domain"
353
+ ROUND_RESTARTED -> external {
354
+ totalPrompts : number
355
+ }
356
+ @description "The learner restarted the round from scratch."
357
+ @tier "domain"
358
+ }
359
+
360
+ config {
361
+ matchMode : string = ""
362
+ @label "Match Mode"
363
+ @description "When composed behind a lab router, the MODE_SELECTED mode value this instrument responds to. Empty string means standalone — render immediately on INIT."
364
+ @tier "presentation"
365
+ title : string = "Estimate It"
366
+ @label "Title"
367
+ @description "Title shown above the drill."
368
+ @tier "presentation"
369
+ prompts : [EstimatePrompt] = [
370
+ { prompt: "How many meters does light travel in one microsecond?", answer: 300, unit: "m", hint: "Light covers 300,000 km every second." },
371
+ { prompt: "What is the boiling point of water at sea level, in Fahrenheit?", answer: 212, unit: "°F", hint: "It is 100 °C." },
372
+ { prompt: "Roughly how many days is one million seconds?", answer: 11.6, unit: "days", hint: "A day is 86,400 seconds." }
373
+ ]
374
+ @label "Prompts"
375
+ @description "The question roster; each prompt carries the true numeric answer, an optional unit, and an optional hint. Realizations declare their own subject's quantities here."
376
+ @tier "domain"
377
+ sliderMin : number = 0
378
+ @label "Slider Min"
379
+ @description "Lower bound of the estimate slider."
380
+ @tier "domain"
381
+ sliderMax : number = 500
382
+ @label "Slider Max"
383
+ @description "Upper bound of the estimate slider."
384
+ @tier "domain"
385
+ sliderStep : number = 0.1
386
+ @label "Slider Step"
387
+ @tier "presentation"
388
+ sliderDefault : number = 100
389
+ @label "Slider Default"
390
+ @description "Starting position of the estimate slider for each prompt."
391
+ @tier "domain"
392
+ exactPct : number = 0.05
393
+ @label "Exact Band"
394
+ @description "Relative error at or below this fraction counts as exact (full points)."
395
+ @tier "domain"
396
+ closePct : number = 0.25
397
+ @label "Close Band"
398
+ @description "Relative error at or below this fraction (but above the exact band) counts as close (partial points)."
399
+ @tier "domain"
400
+ exactPoints : number = 2
401
+ @label "Exact Points"
402
+ @tier "domain"
403
+ closePoints : number = 1
404
+ @label "Close Points"
405
+ @tier "domain"
406
+ lockLabel : string = "Lock In"
407
+ @label "Lock Label"
408
+ @tier "presentation"
409
+ nextLabel : string = "Next"
410
+ @label "Next Label"
411
+ @tier "presentation"
412
+ retryLabel : string = "Try Again"
413
+ @label "Retry Label"
414
+ @tier "presentation"
415
+ }
416
+ }
417
+
418
+ page "/learn-estimate" as EstimatePage -> EstimateSim
419
+ }