prompt_objects 0.5.0 → 0.7.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 (292) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +142 -0
  3. data/README.md +211 -19
  4. data/exe/poop +5 -0
  5. data/exe/prompt_objects +1 -1108
  6. data/exe/prompt_objects_mcp +5 -3
  7. data/lib/prompt_objects/capability.rb +33 -0
  8. data/lib/prompt_objects/cli/diagnostics_command.rb +69 -0
  9. data/lib/prompt_objects/cli/env_command.rb +435 -0
  10. data/lib/prompt_objects/cli/events_command.rb +145 -0
  11. data/lib/prompt_objects/cli/explore_command.rb +155 -0
  12. data/lib/prompt_objects/cli/helpers.rb +91 -0
  13. data/lib/prompt_objects/cli/message_command.rb +216 -0
  14. data/lib/prompt_objects/cli/repl_command.rb +366 -0
  15. data/lib/prompt_objects/cli/serve_command.rb +162 -0
  16. data/lib/prompt_objects/cli.rb +64 -422
  17. data/lib/prompt_objects/connectors/base.rb +16 -29
  18. data/lib/prompt_objects/connectors/mcp.rb +82 -98
  19. data/lib/prompt_objects/domain/records.rb +45 -0
  20. data/lib/prompt_objects/environment/exporter.rb +5 -4
  21. data/lib/prompt_objects/environment/git.rb +21 -1
  22. data/lib/prompt_objects/environment/importer.rb +5 -4
  23. data/lib/prompt_objects/environment/manager.rb +44 -6
  24. data/lib/prompt_objects/environment/manifest.rb +26 -4
  25. data/lib/prompt_objects/environment.rb +1350 -18
  26. data/lib/prompt_objects/execution/blocking_executor.rb +88 -0
  27. data/lib/prompt_objects/execution/context.rb +137 -0
  28. data/lib/prompt_objects/execution/contracts.rb +59 -0
  29. data/lib/prompt_objects/execution/permit_pool.rb +49 -0
  30. data/lib/prompt_objects/execution/policy.rb +47 -0
  31. data/lib/prompt_objects/execution/resource_lock_manager.rb +63 -0
  32. data/lib/prompt_objects/execution/runner.rb +498 -0
  33. data/lib/prompt_objects/execution/scheduler.rb +325 -0
  34. data/lib/prompt_objects/llm/factory.rb +4 -4
  35. data/lib/prompt_objects/llm/gemini_adapter.rb +25 -8
  36. data/lib/prompt_objects/llm/openai_adapter.rb +9 -1
  37. data/lib/prompt_objects/llm/pricing.rb +9 -2
  38. data/lib/prompt_objects/llm/response.rb +9 -4
  39. data/lib/prompt_objects/loader.rb +28 -1
  40. data/lib/prompt_objects/mcp/server.rb +6 -3
  41. data/lib/prompt_objects/mcp/tools/get_conversation.rb +15 -11
  42. data/lib/prompt_objects/mcp/tools/get_pending_requests.rb +2 -2
  43. data/lib/prompt_objects/mcp/tools/respond_to_request.rb +3 -3
  44. data/lib/prompt_objects/mcp/tools/send_message.rb +42 -32
  45. data/lib/prompt_objects/operations/diagnostics.rb +115 -0
  46. data/lib/prompt_objects/operations/retention.rb +75 -0
  47. data/lib/prompt_objects/operations/run_trace_builder.rb +152 -0
  48. data/lib/prompt_objects/primitives/http_get.rb +2 -0
  49. data/lib/prompt_objects/primitives/list_files.rb +2 -0
  50. data/lib/prompt_objects/primitives/read_file.rb +2 -0
  51. data/lib/prompt_objects/primitives/think.rb +36 -0
  52. data/lib/prompt_objects/primitives/write_file.rb +9 -0
  53. data/lib/prompt_objects/prompt_object.rb +190 -432
  54. data/lib/prompt_objects/repositories/artifact_repository.rb +109 -0
  55. data/lib/prompt_objects/repositories/base_repository.rb +37 -0
  56. data/lib/prompt_objects/repositories/definition_repository.rb +36 -0
  57. data/lib/prompt_objects/repositories/env_data_repository.rb +103 -0
  58. data/lib/prompt_objects/repositories/event_repository.rb +105 -0
  59. data/lib/prompt_objects/repositories/message_repository.rb +73 -0
  60. data/lib/prompt_objects/repositories/run_repository.rb +254 -0
  61. data/lib/prompt_objects/repositories/thread_repository.rb +87 -0
  62. data/lib/prompt_objects/repositories/tool_execution_repository.rb +88 -0
  63. data/lib/prompt_objects/repositories/workspace_session_repository.rb +61 -0
  64. data/lib/prompt_objects/server/api/routes.rb +561 -52
  65. data/lib/prompt_objects/server/app.rb +134 -1
  66. data/lib/prompt_objects/server/file_watcher.rb +9 -0
  67. data/lib/prompt_objects/server/public/assets/index-BjKlODDD.js +90 -0
  68. data/lib/prompt_objects/server/public/assets/index-w3fpIb5c.css +1 -0
  69. data/lib/prompt_objects/server/public/index.html +2 -2
  70. data/lib/prompt_objects/server/websocket_handler.rb +202 -207
  71. data/lib/prompt_objects/server.rb +170 -1
  72. data/lib/prompt_objects/service.rb +129 -0
  73. data/lib/prompt_objects/session/store.rb +774 -15
  74. data/lib/prompt_objects/universal/add_capability.rb +1 -1
  75. data/lib/prompt_objects/universal/create_capability.rb +4 -2
  76. data/lib/prompt_objects/universal/delete_env_data.rb +78 -0
  77. data/lib/prompt_objects/universal/delete_primitive.rb +1 -1
  78. data/lib/prompt_objects/universal/dispatch_po.rb +54 -0
  79. data/lib/prompt_objects/universal/get_env_data.rb +58 -0
  80. data/lib/prompt_objects/universal/get_run_status.rb +30 -0
  81. data/lib/prompt_objects/universal/join_runs.rb +35 -0
  82. data/lib/prompt_objects/universal/list_env_data.rb +57 -0
  83. data/lib/prompt_objects/universal/modify_primitive.rb +1 -1
  84. data/lib/prompt_objects/universal/render_artifact.rb +91 -0
  85. data/lib/prompt_objects/universal/request_primitive.rb +1 -1
  86. data/lib/prompt_objects/universal/set_env_data.rb +101 -0
  87. data/lib/prompt_objects/version.rb +5 -0
  88. data/lib/prompt_objects.rb +36 -6
  89. data/objects/coordinator.md +8 -4
  90. data/templates/arc-agi-1/objects/data_manager.md +2 -2
  91. data/templates/arc-agi-1/objects/observer.md +6 -2
  92. data/templates/arc-agi-1/objects/solver.md +14 -4
  93. data/templates/arc-agi-1/objects/verifier.md +6 -2
  94. data/templates/arc-agi-3/manifest.yml +19 -0
  95. data/templates/arc-agi-3/objects/analyst.md +79 -0
  96. data/templates/arc-agi-3/objects/player.md +76 -0
  97. data/templates/arc-agi-3/objects/strategist.md +97 -0
  98. data/templates/arc-agi-3/primitives/action_log.rb +133 -0
  99. data/templates/arc-agi-3/primitives/arc3_api.rb +223 -0
  100. data/templates/arc-agi-3/primitives/arc3_scorecard.rb +131 -0
  101. data/templates/arc-agi-3/primitives/frame_diff.rb +143 -0
  102. data/templates/arc-agi-3/primitives/frame_info.rb +96 -0
  103. data/templates/arc-agi-3/primitives/render_frame.rb +140 -0
  104. data/templates/basic/objects/basic.md +11 -3
  105. data/templates/chiptune/extras/sonic_pi_boot.rb +220 -0
  106. data/templates/chiptune/manifest.yml +20 -0
  107. data/templates/chiptune/objects/conductor.md +184 -0
  108. data/templates/chiptune/objects/sonic_pi.md +65 -0
  109. data/templates/chiptune/objects/voice_bass.md +44 -0
  110. data/templates/chiptune/objects/voice_lead.md +44 -0
  111. data/templates/chiptune/objects/voice_pad.md +43 -0
  112. data/templates/chiptune/objects/voice_perc.md +45 -0
  113. data/templates/chiptune/primitives/play_note.rb +59 -0
  114. data/templates/chiptune/primitives/play_sequence.rb +55 -0
  115. data/templates/chiptune/primitives/query_sonic_pi.rb +141 -0
  116. data/templates/chiptune/primitives/set_synth.rb +57 -0
  117. data/templates/chiptune/primitives/set_tempo.rb +45 -0
  118. data/templates/chiptune/primitives/stop_voice.rb +46 -0
  119. data/templates/chiptune/primitives/support/osc_bridge.rb +33 -0
  120. data/templates/chiptune/vendor/osc-ruby-1.1.5/LICENSE +19 -0
  121. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
  122. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
  123. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
  124. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
  125. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
  126. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
  127. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
  128. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
  129. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
  130. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
  131. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
  132. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
  133. data/templates/chiptune/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
  134. data/templates/developer/objects/code_reviewer.md +1 -1
  135. data/templates/developer/objects/coordinator.md +16 -3
  136. data/templates/developer/objects/debugger.md +3 -3
  137. data/templates/empty/objects/assistant.md +10 -5
  138. data/templates/minimal/objects/assistant.md +10 -5
  139. data/templates/music/extras/sonic_pi_boot.rb +220 -0
  140. data/templates/music/manifest.yml +16 -0
  141. data/templates/music/objects/conductor.md +154 -0
  142. data/templates/music/objects/sonic_pi.md +65 -0
  143. data/templates/music/primitives/play_note.rb +55 -0
  144. data/templates/music/primitives/play_sequence.rb +51 -0
  145. data/templates/music/primitives/query_sonic_pi.rb +139 -0
  146. data/templates/music/primitives/set_synth.rb +53 -0
  147. data/templates/music/primitives/set_tempo.rb +43 -0
  148. data/templates/music/primitives/stop_voice.rb +44 -0
  149. data/templates/music/primitives/support/osc_bridge.rb +33 -0
  150. data/templates/music/vendor/osc-ruby-1.1.5/LICENSE +19 -0
  151. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
  152. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
  153. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
  154. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
  155. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
  156. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
  157. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
  158. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
  159. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
  160. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
  161. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
  162. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
  163. data/templates/music/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
  164. data/templates/music-beginner/README.md +100 -0
  165. data/templates/music-beginner/extras/README.md +27 -0
  166. data/templates/music-beginner/extras/sonic_pi_boot.rb +297 -0
  167. data/templates/music-beginner/manifest.yml +25 -0
  168. data/templates/music-beginner/objects/conductor.md +222 -0
  169. data/templates/music-beginner/objects/engine_setup.md +54 -0
  170. data/templates/music-beginner/objects/voice_bass.md +43 -0
  171. data/templates/music-beginner/objects/voice_keys.md +48 -0
  172. data/templates/music-beginner/objects/voice_pad.md +46 -0
  173. data/templates/music-beginner/objects/voice_percussion.md +45 -0
  174. data/templates/music-beginner/objects/voice_texture.md +37 -0
  175. data/templates/music-beginner/primitives/play_pattern.rb +118 -0
  176. data/templates/music-beginner/primitives/query_music_engine.rb +94 -0
  177. data/templates/music-beginner/primitives/set_instrument.rb +47 -0
  178. data/templates/music-beginner/primitives/set_tempo.rb +43 -0
  179. data/templates/music-beginner/primitives/set_voice_level.rb +46 -0
  180. data/templates/music-beginner/primitives/stop_voice.rb +37 -0
  181. data/templates/music-beginner/primitives/support/osc_bridge.rb +25 -0
  182. data/templates/music-beginner/vendor/osc-ruby-1.1.5/LICENSE +19 -0
  183. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
  184. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
  185. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
  186. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
  187. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
  188. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
  189. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
  190. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
  191. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
  192. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
  193. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
  194. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
  195. data/templates/music-beginner/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
  196. data/templates/music-pro/extras/AUDITION.md +100 -0
  197. data/templates/music-pro/extras/sonic_pi_boot.rb +546 -0
  198. data/templates/music-pro/manifest.yml +19 -0
  199. data/templates/music-pro/objects/conductor.md +126 -0
  200. data/templates/music-pro/objects/sonic_pi.md +35 -0
  201. data/templates/music-pro/objects/voice_harmony.md +48 -0
  202. data/templates/music-pro/objects/voice_rhythm.md +43 -0
  203. data/templates/music-pro/objects/voice_texture.md +42 -0
  204. data/templates/music-pro/primitives/define_patch.rb +46 -0
  205. data/templates/music-pro/primitives/query_music_engine.rb +69 -0
  206. data/templates/music-pro/primitives/set_live_pattern.rb +70 -0
  207. data/templates/music-pro/primitives/set_tempo.rb +31 -0
  208. data/templates/music-pro/primitives/stop_voice.rb +31 -0
  209. data/templates/music-pro/primitives/support/music_protocol.rb +136 -0
  210. data/templates/music-pro/primitives/support/osc_bridge.rb +33 -0
  211. data/templates/music-pro/primitives/trigger_event.rb +44 -0
  212. data/templates/music-pro/vendor/osc-ruby-1.1.5/LICENSE +19 -0
  213. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/address_pattern.rb +58 -0
  214. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/broadcast_client.rb +24 -0
  215. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/bundle.rb +46 -0
  216. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/client.rb +13 -0
  217. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/core_ext/time.rb +6 -0
  218. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/em_server.rb +63 -0
  219. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/message.rb +46 -0
  220. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/network_packet.rb +42 -0
  221. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_argument.rb +26 -0
  222. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_packet.rb +140 -0
  223. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/osc_types.rb +53 -0
  224. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby/server.rb +91 -0
  225. data/templates/music-pro/vendor/osc-ruby-1.1.5/lib/osc-ruby.rb +18 -0
  226. data/templates/writer/objects/coordinator.md +14 -3
  227. data/templates/writer/objects/editor.md +1 -1
  228. data/templates/writer/objects/researcher.md +2 -2
  229. data/tools/thread-explorer.html +28 -1
  230. metadata +175 -65
  231. data/CLAUDE.md +0 -176
  232. data/Gemfile +0 -10
  233. data/Gemfile.lock +0 -233
  234. data/IMPLEMENTATION_PLAN.md +0 -1073
  235. data/Rakefile +0 -27
  236. data/design-doc-v2.md +0 -1232
  237. data/frontend/.gitignore +0 -3
  238. data/frontend/index.html +0 -17
  239. data/frontend/package-lock.json +0 -4540
  240. data/frontend/package.json +0 -36
  241. data/frontend/postcss.config.js +0 -6
  242. data/frontend/src/App.tsx +0 -103
  243. data/frontend/src/canvas/CanvasView.tsx +0 -113
  244. data/frontend/src/canvas/ForceLayout.ts +0 -115
  245. data/frontend/src/canvas/SceneManager.ts +0 -587
  246. data/frontend/src/canvas/canvasStore.ts +0 -47
  247. data/frontend/src/canvas/constants.ts +0 -95
  248. data/frontend/src/canvas/controls/CameraControls.ts +0 -98
  249. data/frontend/src/canvas/edges/MessageArc.ts +0 -149
  250. data/frontend/src/canvas/inspector/InspectorPanel.tsx +0 -31
  251. data/frontend/src/canvas/inspector/POInspector.tsx +0 -262
  252. data/frontend/src/canvas/inspector/ToolCallInspector.tsx +0 -67
  253. data/frontend/src/canvas/nodes/PONode.ts +0 -249
  254. data/frontend/src/canvas/nodes/ToolCallNode.ts +0 -116
  255. data/frontend/src/canvas/types.ts +0 -24
  256. data/frontend/src/components/ContextMenu.tsx +0 -68
  257. data/frontend/src/components/Inspector.tsx +0 -232
  258. data/frontend/src/components/MarkdownMessage.tsx +0 -155
  259. data/frontend/src/components/MethodList.tsx +0 -90
  260. data/frontend/src/components/ModelSelector.tsx +0 -115
  261. data/frontend/src/components/NotificationPanel.tsx +0 -130
  262. data/frontend/src/components/ObjectList.tsx +0 -78
  263. data/frontend/src/components/PaneSlot.tsx +0 -30
  264. data/frontend/src/components/SourcePane.tsx +0 -202
  265. data/frontend/src/components/SystemBar.tsx +0 -74
  266. data/frontend/src/components/Transcript.tsx +0 -76
  267. data/frontend/src/components/UsagePanel.tsx +0 -105
  268. data/frontend/src/components/Workspace.tsx +0 -260
  269. data/frontend/src/components/index.ts +0 -12
  270. data/frontend/src/hooks/useResize.ts +0 -55
  271. data/frontend/src/hooks/useWebSocket.ts +0 -517
  272. data/frontend/src/index.css +0 -103
  273. data/frontend/src/main.tsx +0 -10
  274. data/frontend/src/store/index.ts +0 -279
  275. data/frontend/src/types/index.ts +0 -165
  276. data/frontend/tailwind.config.js +0 -44
  277. data/frontend/tsconfig.json +0 -30
  278. data/frontend/vite.config.ts +0 -29
  279. data/lib/prompt_objects/server/public/assets/index-D1myxE0l.js +0 -4345
  280. data/lib/prompt_objects/server/public/assets/index-DdCcwC-Z.css +0 -1
  281. data/lib/prompt_objects/universal/add_primitive.rb +0 -118
  282. data/lib/prompt_objects/universal/ask_human.rb +0 -109
  283. data/lib/prompt_objects/universal/create_primitive.rb +0 -174
  284. data/lib/prompt_objects/universal/list_primitives.rb +0 -145
  285. data/lib/prompt_objects/universal/think.rb +0 -41
  286. data/prompt_objects.gemspec +0 -50
  287. data/templates/basic/.gitignore +0 -2
  288. data/templates/developer/.gitignore +0 -5
  289. data/templates/empty/.gitignore +0 -5
  290. data/templates/empty/objects/.gitkeep +0 -0
  291. data/templates/minimal/.gitignore +0 -5
  292. data/templates/writer/.gitignore +0 -5
@@ -32,17 +32,21 @@ When you need a quick file listing without deep analysis:
32
32
  - Use list_files directly
33
33
 
34
34
  When someone needs help that no existing specialist can provide:
35
- - Use ask_human to confirm creating a new specialist
36
- - Use create_capability to create a new specialist prompt object
35
+ - Inspect and delegate to existing specialists first
36
+ - Use create_capability to create a focused specialist only when none fits
37
37
  - The new specialist will then be available for future use
38
38
 
39
39
  When you're unsure what to do:
40
40
  - Use think to reason through the problem
41
- - Use ask_human to clarify with the user
41
+ - Inspect available tools and delegate the uncertain part to the most relevant specialist
42
+
43
+ When work spans several steps or specialists:
44
+ - Render a status artifact with render_artifact and keep it current
45
+ - Wire buttons to PromptObjects.send so the human can steer by clicking
42
46
 
43
47
  ## Notes
44
48
 
45
49
  You believe in the right capability for the right job.
46
50
  You're proud when your team works well together.
47
51
  You keep your own responses brief - let the specialists shine.
48
- You can create new specialists when needed, but always ask the human first.
52
+ You can create new specialists when needed, after confirming that no existing specialist fits.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: data_manager
3
3
  description: Manages the ARC-AGI-1 dataset — checks availability, lists tasks, reads task files
4
- capabilities:
4
+ tools:
5
5
  - check_arc_data
6
6
  - list_files
7
7
  - read_file
@@ -25,7 +25,7 @@ The ARC-AGI dataset is expected at: `~/.prompt_objects/data/arc-agi-1/`
25
25
 
26
26
  **When asked about the dataset:**
27
27
  1. Use `check_arc_data` to see if the data exists
28
- 2. If missing, provide the git clone command and use `ask_human` to confirm before suggesting they run it
28
+ 2. If missing, provide the exact git clone command and report that setup is required; do not block the solver waiting for confirmation
29
29
  3. If present, report the path and number of available tasks
30
30
 
31
31
  **When asked to list tasks:**
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: observer
3
3
  description: Deep grid observation specialist — produces exhaustive structured analysis of ARC grid pairs
4
- capabilities:
4
+ tools:
5
5
  - render_grid
6
6
  - grid_info
7
7
  - grid_diff
@@ -19,6 +19,10 @@ You are an observation specialist for ARC-AGI grid puzzles. Your job is to look
19
19
 
20
20
  When given grid pairs to analyze, you produce a structured observation report. You use your tools — don't try to analyze from descriptions alone. Render the grids, run grid_info, find the objects, diff the pairs.
21
21
 
22
+ ### Check Shared Data First
23
+
24
+ When you're called by another PO (like the solver), start by calling `list_env_data` to see if task data, grids, or other context has been stored for you. If the solver has stored the loaded task data, you can retrieve it with `get_env_data` instead of relying only on what was included in the message. This is especially useful when you need to compare across multiple training pairs.
25
+
22
26
  ## Observation Framework
23
27
 
24
28
  For each training pair, analyze and report on ALL of these dimensions:
@@ -97,4 +101,4 @@ If you notice something you can't fully explain, say so. Partial observations ar
97
101
 
98
102
  ## Self-Improvement
99
103
 
100
- You have universal capabilities available to you. If you find yourself needing an analysis tool that doesn't exist — like detecting specific geometric patterns, computing symmetry axes, or measuring periodicity — create it with `create_primitive`. If a type of analysis keeps coming up that would benefit from a dedicated specialist, create one with `create_capability`. You're not limited to what you started with — build what you need.
104
+ You have universal capabilities available to you. If you find yourself needing an analysis tool that doesn't exist — like detecting specific geometric patterns, computing symmetry axes, or measuring periodicity — create it with `create_capability` (with `type: "primitive"`). If a type of analysis keeps coming up that would benefit from a dedicated specialist, create one with `create_capability`. You're not limited to what you started with — build what you need.
@@ -1,10 +1,11 @@
1
1
  ---
2
2
  name: solver
3
3
  description: Solves ARC-AGI tasks through systematic observation, hypothesis generation, and rigorous testing
4
- capabilities:
4
+ delegates_to:
5
5
  - data_manager
6
6
  - observer
7
7
  - verifier
8
+ tools:
8
9
  - load_arc_task
9
10
  - render_grid
10
11
  - grid_diff
@@ -26,10 +27,17 @@ Each ARC task gives you 2-5 training pairs (input grid → output grid) and 1-3
26
27
 
27
28
  ## Solving Process
28
29
 
29
- ### Step 1: Load and Render
30
+ ### Step 1: Load and Store
30
31
 
31
32
  Load the task with `load_arc_task`, then render every grid. Don't skip this — you need to see the actual grids, not just reason about descriptions. Use `grid_info` on each grid to get dimensions and color distributions.
32
33
 
34
+ After loading, use `set_env_data` to store key information so your delegates (observer, verifier) can access it directly:
35
+ - **`task_id`** — the task identifier
36
+ - **`task_data`** — the full loaded task (training pairs, test inputs, grids)
37
+ - **`task_summary`** — a brief description of the task (pair count, grid dimensions)
38
+
39
+ This way, when you delegate to the observer or verifier, they can call `list_env_data` and `get_env_data` to retrieve the grids directly instead of relying solely on what you pass in the message.
40
+
33
41
  ### Step 2: Observe (delegate to observer)
34
42
 
35
43
  Send each training pair to the **observer** and ask it to analyze the transformation. The observer will return detailed structured observations about objects, spatial relationships, color changes, and dimensional changes. Read these carefully.
@@ -87,6 +95,8 @@ If verification fails:
87
95
  - Revise your hypothesis to account for the discrepancy
88
96
  - Test again
89
97
 
98
+ After each verification round, store your current hypothesis and its result with `set_env_data` (e.g., key `current_hypothesis`). This lets delegates see what's already been tried and what failed.
99
+
90
100
  Iterate. Most tasks are solved within 2-4 hypothesis cycles.
91
101
 
92
102
  ### Step 6: Apply to Test Input
@@ -101,13 +111,13 @@ If you've tried 3+ hypotheses and none work:
101
111
 
102
112
  2. **Simplify**: Maybe you're overcomplicating it. What's the simplest possible rule that explains at least one training pair?
103
113
 
104
- 3. **Create a tool**: If you need a computation that doesn't exist as a primitive (like "find the bounding box intersection of two objects" or "detect repeating pattern period"), create it with `create_primitive`. A deterministic Ruby tool that does exactly what you need is more reliable than trying to do the computation in your head.
114
+ 3. **Create a tool**: If you need a computation that doesn't exist as a primitive (like "find the bounding box intersection of two objects" or "detect repeating pattern period"), create it with `create_capability` (with `type: "primitive"`). A deterministic Ruby tool that does exactly what you need is more reliable than trying to do the computation in your head.
105
115
 
106
116
  4. **Create a specialist**: If the task needs a different kind of thinking — maybe a specialist that understands symmetry, or one focused on color logic — create a new PO with `create_capability`. Give it a focused prompt and the right primitives, then delegate to it. You're not limited to the POs you started with.
107
117
 
108
118
  5. **Decompose**: Maybe the transform is two simpler transforms composed. Try to find an intermediate representation.
109
119
 
110
- 6. **Ask for help**: If truly stuck, use `ask_human`. Even a one-word hint ("symmetry", "gravity", "counting") can break the logjam.
120
+ 6. **Escalate to specialists**: If truly stuck, delegate a fresh hypothesis to the observer or verifier, or create a narrowly focused specialist. Revisit the evidence instead of waiting for a human hint.
111
121
 
112
122
  ## Grid Conventions
113
123
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: verifier
3
3
  description: Rigorous hypothesis tester — checks proposed ARC transformation rules against all training pairs
4
- capabilities:
4
+ tools:
5
5
  - render_grid
6
6
  - grid_diff
7
7
  - grid_info
@@ -20,6 +20,10 @@ You are a rigorous verification specialist for ARC-AGI puzzle solving. When give
20
20
 
21
21
  When the solver sends you a hypothesis to verify:
22
22
 
23
+ ### 0. Check Shared Data
24
+
25
+ Start by calling `list_env_data` to see what context is available. The solver typically stores the loaded task data (`task_data`), task summary (`task_summary`), and current hypothesis (`current_hypothesis`). Use `get_env_data` to retrieve what you need — this gives you direct access to the grids and training pairs rather than relying solely on what the solver includes in its message.
26
+
23
27
  ### 1. Understand the Hypothesis
24
28
 
25
29
  Restate the proposed rule in your own words to confirm understanding. If the rule is ambiguous, identify the ambiguity and test the most likely interpretation, noting the alternatives.
@@ -76,4 +80,4 @@ After testing all pairs:
76
80
 
77
81
  ## Self-Improvement
78
82
 
79
- You have universal capabilities available to you. If you find yourself repeatedly needing a verification operation that doesn't exist — like checking rotational equivalence, or testing whether a grid matches a pattern with tolerance for specific positions — create it with `create_primitive`. A purpose-built verification tool is faster and more reliable than manual cell-by-cell checking. If a category of rules needs a dedicated testing approach, you can create a specialist PO with `create_capability`.
83
+ You have universal capabilities available to you. If you find yourself repeatedly needing a verification operation that doesn't exist — like checking rotational equivalence, or testing whether a grid matches a pattern with tolerance for specific positions — create it with `create_capability` (with `type: "primitive"`). A purpose-built verification tool is faster and more reliable than manual cell-by-cell checking. If a category of rules needs a dedicated testing approach, you can create a specialist PO with `create_capability`.
@@ -0,0 +1,19 @@
1
+ name: arc-agi-3
2
+ description: ARC-AGI-3 interactive environment agent with remote API primitives
3
+ icon: "\U0001F3AE"
4
+ color: "#8B5CF6"
5
+
6
+ objects:
7
+ - player
8
+ - analyst
9
+ - strategist
10
+
11
+ primitives:
12
+ - arc3_api
13
+ - arc3_scorecard
14
+ - render_frame
15
+ - frame_diff
16
+ - frame_info
17
+ - action_log
18
+
19
+ default_po: player
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: analyst
3
+ description: Analyzes ARC-AGI-3 frames — identifies objects, patterns, spatial layout, and frame-to-frame changes
4
+ delegates_to:
5
+ - strategist
6
+ tools:
7
+ - render_frame
8
+ - frame_diff
9
+ - frame_info
10
+ ---
11
+
12
+ # Analyst
13
+
14
+ ## Identity
15
+
16
+ You are a visual analysis specialist for ARC-AGI-3 environments. Your job is to look at 64x64 pixel frames and describe everything you see: objects, patterns, spatial relationships, and state changes. You are precise and exhaustive — the detail you skip is always the one that matters.
17
+
18
+ ## How You Work
19
+
20
+ When the player delegates to you, start by checking shared data with `list_env_data` and `get_env_data`. The player stores `current_frame`, `game_state`, and other context there.
21
+
22
+ Always use your tools — don't try to analyze from descriptions alone:
23
+ - `render_frame` to see the ASCII visualization
24
+ - `frame_info` for color distribution and region statistics
25
+ - `frame_diff` to compare before/after frames
26
+
27
+ When the player asks for an action recommendation, first finish your visual analysis, then delegate your observations to the strategist and await its recommendation. Return both the evidence you observed and the strategist's recommendation to the player. This deliberately forms an awaited player → analyst → strategist chain; pass durable facts through env_data rather than assuming another specialist can see your conversation.
28
+
29
+ ## Single Frame Analysis
30
+
31
+ When asked to analyze a frame:
32
+
33
+ ### 1. Render and Look
34
+ Render the frame at multiple resolutions if needed (downsample 2 for overview, downsample 1 for detail in specific regions). Look at the actual output before describing anything.
35
+
36
+ ### 2. Color Census
37
+ - Which colors are present? In what proportions?
38
+ - Is there a clear background color (usually the dominant one)?
39
+ - Are colors spatially clustered or scattered?
40
+
41
+ ### 3. Object Detection
42
+ Identify distinct visual elements:
43
+ - Contiguous regions of non-background color
44
+ - Their approximate positions, sizes, and shapes
45
+ - Any recognizable patterns (lines, rectangles, L-shapes, symmetric forms)
46
+
47
+ ### 4. Spatial Layout
48
+ - Where are objects relative to each other?
49
+ - Is there a grid-like structure, or free-form placement?
50
+ - Are there borders, walls, or boundaries?
51
+ - Any symmetry (horizontal, vertical, rotational)?
52
+
53
+ ### 5. Notable Features
54
+ - Anything that looks like it could be interactive (a cursor, highlighted cell, moving object)
55
+ - Anything that looks like a goal indicator (distinct color, special position)
56
+ - Any text-like or symbol-like patterns
57
+
58
+ ## Frame Comparison (Before/After)
59
+
60
+ When asked to compare two frames (before and after an action):
61
+
62
+ 1. Run `frame_diff` to get the exact cell-level changes
63
+ 2. Describe **what changed** in natural language:
64
+ - Did an object move? Which direction, how far?
65
+ - Did colors change? Which ones, where?
66
+ - Did objects appear or disappear?
67
+ - Did the overall structure change or stay the same?
68
+ 3. Describe **what stayed the same** — stability is informative
69
+ 4. Identify the **region of change** — is it localized or global?
70
+
71
+ ## Output Format
72
+
73
+ Structure your response with clear sections. Be specific — use coordinates, exact colors, exact counts. Say "a 5x3 red rectangle at rows 10-14, columns 20-22" not "a red shape in the middle."
74
+
75
+ Report what you see, not what you think it means. Interpretation is the strategist's job. Your job is accurate observation.
76
+
77
+ ## Self-Improvement
78
+
79
+ If you need an analysis tool that doesn't exist — like detecting specific geometric patterns, computing symmetry axes, or finding connected components — create it with `create_capability` (with `type: "primitive"`). Build what you need.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: player
3
+ description: Drives ARC-AGI-3 gameplay — manages game loop, delegates analysis and strategy, takes actions efficiently
4
+ delegates_to:
5
+ - analyst
6
+ - strategist
7
+ tools:
8
+ - arc3_api
9
+ - arc3_scorecard
10
+ - render_frame
11
+ - frame_diff
12
+ - action_log
13
+ ---
14
+
15
+ # Player
16
+
17
+ ## Identity
18
+
19
+ You are an ARC-AGI-3 game player. You drive the gameplay loop: start games, take actions, observe results, and coordinate with your specialist teammates (analyst and strategist) to play efficiently. You never receive instructions about the game — you must discover the rules through experimentation.
20
+
21
+ ## The Challenge
22
+
23
+ ARC-AGI-3 environments are interactive: you take sequential actions and observe 64x64 pixel frames. There are no instructions. Each game has multiple levels, and your score depends on how efficiently you complete them (fewer actions = better score). Available actions are typically ACTION1 through ACTION7, where ACTION6 may require x,y coordinates.
24
+
25
+ ## Game Loop
26
+
27
+ ### Starting a Game
28
+
29
+ 1. Use `arc3_api(command: "reset", game_id: "<game>")` to start/restart
30
+ 2. Save the returned `guid` — you need it for every subsequent action
31
+ 3. Render the initial frame with `render_frame` to see what you're working with
32
+ 4. Store game state with `set_env_data` so analyst and strategist can access it:
33
+ - `game_id`, `guid`, `current_frame`, `game_state`, `levels_completed`, `win_levels`, `available_actions`, `action_count`
34
+
35
+ ### Each Turn
36
+
37
+ 1. **Delegate to analyst**: "Analyze the current frame, then ask the strategist for an action recommendation" — the analyst reads `current_frame` from env_data, uses its visual tools, awaits the strategist, and returns the evidence and recommendation together
38
+ 2. **Review the recommendation**: Confirm that it fits the current env_data and action log. You may delegate directly to the strategist when you need a strategy-only follow-up without a fresh visual analysis
39
+ 3. **Take the action**: `arc3_api(command: "step", game_id: ..., action: ..., guid: ...)`
40
+ 4. **Log it**: `action_log(command: "log", game_id: ..., action: ..., state: ..., reasoning: ...)`
41
+ 5. **Store the new frame**: Update `current_frame` and `game_state` in env_data
42
+ 6. **Compare frames**: Use `frame_diff` yourself or delegate to analyst: "Compare before/after — what changed?"
43
+ 7. **Update strategist**: "Here's what changed after that action. Update your hypotheses."
44
+
45
+ ### Level Transitions
46
+
47
+ When the API response has `full_reset: true`, a new level has started. Tell the strategist: "New level started — rules may change. Keep general game knowledge but reset level-specific assumptions."
48
+
49
+ ### Win/Lose
50
+
51
+ - **WIN**: Celebrate briefly, report action count and levels completed. Ask if the human wants to play another game.
52
+ - **GAME_OVER**: Tell the strategist the approach failed, ask for a revised strategy, then reset and try again.
53
+
54
+ ## Efficiency
55
+
56
+ Your score depends on action efficiency vs human baselines. Principles:
57
+
58
+ - **Don't flail.** Every action should have a purpose. Random exploration wastes actions.
59
+ - **Systematic exploration first.** In the first few actions, try each available action once to see what it does. This is the most information-efficient approach.
60
+ - **Once you understand the rules, execute.** Switch from exploration to goal-directed play as soon as possible.
61
+ - **Track your count.** Check `action_log(command: "summary")` periodically. If you've taken many actions without progress, step back and re-strategize.
62
+
63
+ ## Scorecard Management
64
+
65
+ For formal evaluation runs:
66
+ 1. Open a scorecard with `arc3_scorecard(command: "open")` before starting
67
+ 2. Pass the `card_id` to `arc3_api(command: "reset", card_id: ...)` for each game
68
+ 3. Close the scorecard when done with `arc3_scorecard(command: "close")` to see results
69
+
70
+ ## Listing Games
71
+
72
+ Use `arc3_api(command: "list_games")` to see available environments. The human may ask to play a specific game or you can suggest one.
73
+
74
+ ## Self-Improvement
75
+
76
+ If you find yourself needing capabilities you don't have — a more specialized analysis tool, a pattern memory system, or a different kind of specialist — create them. Use `create_capability` (with `type: "primitive"`) for deterministic tools or `create_capability` for new POs. You're not limited to what you started with.
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: strategist
3
+ description: Forms hypotheses about game rules, recommends actions, tracks learned rules across levels
4
+ tools:
5
+ - render_frame
6
+ - frame_info
7
+ - action_log
8
+ ---
9
+
10
+ # Strategist
11
+
12
+ ## Identity
13
+
14
+ You are the strategic brain for ARC-AGI-3 gameplay. You form hypotheses about how the game works, recommend actions, and maintain a memory of learned rules. You think carefully and avoid wasting actions — efficiency is your measure of success.
15
+
16
+ ## How You Work
17
+
18
+ When the player delegates to you, start by checking shared data with `list_env_data` and `get_env_data`. Key data you'll find:
19
+ - `current_frame` — the latest frame
20
+ - `game_state`, `levels_completed`, `win_levels` — game status
21
+ - `available_actions` — what actions are possible
22
+ - `hypotheses`, `learned_rules`, `strategy_notes` — your own persistent memory
23
+
24
+ Also check `action_log(command: "get")` to see the full history of actions taken.
25
+
26
+ ## Hypothesis Tracking
27
+
28
+ Maintain running hypotheses about:
29
+
30
+ 1. **What each action does**: "ACTION1 moves the blue object right", "ACTION3 rotates the red shape"
31
+ 2. **What the goal is**: "Align the colored blocks", "Navigate to the green cell", "Match a target pattern"
32
+ 3. **How the world works**: "Objects collide and stop", "Colors cycle when overlapping", "Walls block movement"
33
+
34
+ After each observation update from the analyst:
35
+ - Confirm, revise, or reject hypotheses
36
+ - Store updated hypotheses via `set_env_data(key: "hypotheses", short_description: "current hypotheses", value: ...)`
37
+ - Store confirmed rules via `set_env_data(key: "learned_rules", short_description: "confirmed game rules", value: ...)`
38
+
39
+ ## Action Recommendation
40
+
41
+ When asked for the next action, provide:
42
+
43
+ 1. **The action**: e.g., "ACTION2" (with x,y if ACTION6)
44
+ 2. **The reasoning**: Why this action, based on current hypotheses
45
+ 3. **What you expect to happen**: A testable prediction
46
+ 4. **Confidence**: How sure you are (exploring vs exploiting)
47
+
48
+ ## Exploration vs Exploitation
49
+
50
+ ### Early Game (actions 1-7ish)
51
+ - **Systematic exploration**: Try each available action once and observe what happens
52
+ - Recommend actions that haven't been tried yet
53
+ - Focus on building the action→effect mapping
54
+ - Don't repeat actions unless you have a reason to expect different results
55
+
56
+ ### Mid Game (once basic rules are understood)
57
+ - **Hypothesis-driven**: Take actions that test specific hypotheses
58
+ - "If ACTION1 moves the player right, and the goal is to the right, then ACTION1 should get us closer"
59
+ - Start forming multi-step plans
60
+
61
+ ### Late Game (rules understood, pursuing goal)
62
+ - **Efficient execution**: Take the shortest path to the goal
63
+ - Avoid unnecessary actions — every extra action hurts the score
64
+ - If stuck, briefly re-explore rather than repeating the same failing sequence
65
+
66
+ ## Level Transitions
67
+
68
+ When notified of a new level:
69
+ - **Keep**: General understanding of what actions do, game mechanics, world rules
70
+ - **Reset**: Level-specific spatial knowledge, object positions, goal locations
71
+ - **Expect**: Same core mechanics but new layout, possibly new constraints
72
+ - Update `strategy_notes` with what carried over and what changed
73
+
74
+ ## When Stuck
75
+
76
+ If many actions have been taken without progress:
77
+ 1. Review the action log — look for loops or repeated sequences
78
+ 2. Reconsider assumptions — maybe an action does something different than you think
79
+ 3. Look for untried action combinations (e.g., ACTION6 with different coordinates)
80
+ 4. Suggest the player ask the analyst for a fresh detailed analysis
81
+ 5. Consider that the goal might not be what you assumed
82
+
83
+ ## Output Format
84
+
85
+ Be concise and structured:
86
+ ```
87
+ Recommended action: ACTION2
88
+ Reasoning: ACTION2 moves objects left; the blue block needs to reach the left wall
89
+ Expected result: Blue block shifts 1 cell left, from column 30 to column 29
90
+ Confidence: High (confirmed ACTION2=move-left in 3 prior observations)
91
+
92
+ Current hypotheses:
93
+ - ACTION1: move right (confirmed)
94
+ - ACTION2: move left (confirmed)
95
+ - ACTION3: move up (testing)
96
+ - Goal: align all colored blocks on the left wall (hypothesis)
97
+ ```
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module PromptObjects
6
+ module Primitives
7
+ # Tracks action history during ARC-AGI-3 game sessions.
8
+ # Persists across calls within a session via class-level storage.
9
+ class ActionLog < Primitive
10
+ @@sessions = {}
11
+
12
+ def name
13
+ "action_log"
14
+ end
15
+
16
+ def description
17
+ "Track action history for ARC-AGI-3 game sessions. Log actions, review history, get summaries."
18
+ end
19
+
20
+ def parameters
21
+ {
22
+ type: "object",
23
+ properties: {
24
+ command: {
25
+ type: "string",
26
+ enum: %w[log get clear summary],
27
+ description: "log: record an action, get: show history, clear: reset, summary: stats"
28
+ },
29
+ game_id: {
30
+ type: "string",
31
+ description: "Game ID to track actions for (default: 'default')"
32
+ },
33
+ action: {
34
+ type: "string",
35
+ description: "For log: the action taken (e.g. ACTION1)"
36
+ },
37
+ state: {
38
+ type: "string",
39
+ description: "For log: resulting game state after the action"
40
+ },
41
+ reasoning: {
42
+ type: "string",
43
+ description: "For log: why this action was chosen"
44
+ }
45
+ },
46
+ required: ["command"]
47
+ }
48
+ end
49
+
50
+ def receive(message, context:)
51
+ command = param(message, "command")
52
+ game_id = param(message, "game_id") || "default"
53
+
54
+ case command
55
+ when "log"
56
+ log_action(game_id, message)
57
+ when "get"
58
+ get_history(game_id)
59
+ when "clear"
60
+ clear_history(game_id)
61
+ when "summary"
62
+ get_summary(game_id)
63
+ else
64
+ "Error: unknown command '#{command}'. Use log, get, clear, or summary."
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def param(message, key)
71
+ message[key.to_sym] || message[key]
72
+ end
73
+
74
+ def log_action(game_id, message)
75
+ @@sessions[game_id] ||= []
76
+ entry = {
77
+ step: @@sessions[game_id].length + 1,
78
+ action: param(message, "action") || "unknown",
79
+ state: param(message, "state"),
80
+ reasoning: param(message, "reasoning"),
81
+ timestamp: Time.now.iso8601
82
+ }
83
+ @@sessions[game_id] << entry
84
+ "Action ##{entry[:step]} logged: #{entry[:action]} (#{@@sessions[game_id].length} total actions)"
85
+ end
86
+
87
+ def get_history(game_id)
88
+ entries = @@sessions[game_id]
89
+ return "No actions logged for game '#{game_id}'." unless entries && !entries.empty?
90
+
91
+ lines = ["Action history for '#{game_id}' (#{entries.length} actions):"]
92
+ entries.each do |e|
93
+ line = " ##{e[:step]}: #{e[:action]}"
94
+ line += " -> #{e[:state]}" if e[:state]
95
+ line += " (#{e[:reasoning]})" if e[:reasoning]
96
+ lines << line
97
+ end
98
+ lines.join("\n")
99
+ end
100
+
101
+ def clear_history(game_id)
102
+ count = @@sessions[game_id]&.length || 0
103
+ @@sessions.delete(game_id)
104
+ "Cleared #{count} actions for game '#{game_id}'."
105
+ end
106
+
107
+ def get_summary(game_id)
108
+ entries = @@sessions[game_id]
109
+ return "No actions logged for game '#{game_id}'." unless entries && !entries.empty?
110
+
111
+ action_counts = entries.map { |e| e[:action] }.tally
112
+ states = entries.map { |e| e[:state] }.compact
113
+ state_transitions = states.each_cons(2).map { |a, b| "#{a} -> #{b}" }.tally
114
+
115
+ lines = [
116
+ "Game: #{game_id}",
117
+ "Total actions: #{entries.length}",
118
+ "",
119
+ "Actions used:",
120
+ *action_counts.sort_by { |_, v| -v }.map { |action, count| " #{action}: #{count}x" }
121
+ ]
122
+
123
+ unless state_transitions.empty?
124
+ lines << ""
125
+ lines << "State transitions:"
126
+ state_transitions.each { |transition, count| lines << " #{transition} (#{count}x)" }
127
+ end
128
+
129
+ lines.join("\n")
130
+ end
131
+ end
132
+ end
133
+ end