robot_lab 0.2.1 → 0.2.7

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 (236) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +1 -0
  3. data/.loki +60 -0
  4. data/.quality/reek_baseline.txt +43 -0
  5. data/.rubocop.yml +5 -167
  6. data/CHANGELOG.md +54 -0
  7. data/README.md +185 -64
  8. data/Rakefile +28 -12
  9. data/docs/api/core/index.md +41 -14
  10. data/docs/api/core/memory.md +247 -29
  11. data/docs/api/core/network.md +285 -33
  12. data/docs/api/core/result.md +120 -32
  13. data/docs/api/core/robot.md +636 -60
  14. data/docs/api/core/state.md +87 -197
  15. data/docs/api/core/tool.md +165 -20
  16. data/docs/api/errors.md +152 -14
  17. data/docs/api/hooks.md +469 -0
  18. data/docs/api/index.md +83 -7
  19. data/docs/api/mcp/client.md +129 -35
  20. data/docs/api/mcp/index.md +164 -23
  21. data/docs/api/mcp/server.md +27 -3
  22. data/docs/api/mcp/transports.md +94 -22
  23. data/docs/api/messages/index.md +26 -3
  24. data/docs/api/messages/text-message.md +33 -11
  25. data/docs/api/messages/tool-call-message.md +27 -4
  26. data/docs/api/messages/tool-result-message.md +23 -4
  27. data/docs/api/messages/user-message.md +45 -8
  28. data/docs/api/skills.md +519 -0
  29. data/docs/api/streaming/context.md +28 -5
  30. data/docs/api/streaming/index.md +57 -11
  31. data/docs/api/support.md +846 -0
  32. data/docs/architecture/core-concepts.md +118 -30
  33. data/docs/architecture/index.md +86 -11
  34. data/docs/architecture/message-flow.md +66 -29
  35. data/docs/architecture/network-orchestration.md +153 -38
  36. data/docs/architecture/robot-execution.md +173 -91
  37. data/docs/architecture/state-management.md +31 -12
  38. data/docs/concepts.md +176 -21
  39. data/docs/examples/basic-chat.md +72 -19
  40. data/docs/examples/index.md +117 -31
  41. data/docs/examples/mcp-server.md +154 -45
  42. data/docs/examples/multi-robot-network.md +91 -21
  43. data/docs/examples/tool-usage.md +104 -37
  44. data/docs/getting-started/configuration.md +299 -93
  45. data/docs/getting-started/installation.md +53 -41
  46. data/docs/getting-started/quick-start.md +51 -6
  47. data/docs/guides/building-robots.md +296 -50
  48. data/docs/guides/creating-networks.md +220 -31
  49. data/docs/guides/hooks.md +1084 -0
  50. data/docs/guides/index.md +5 -0
  51. data/docs/guides/knowledge.md +37 -6
  52. data/docs/guides/mcp-integration.md +211 -44
  53. data/docs/guides/memory.md +103 -12
  54. data/docs/guides/observability.md +166 -51
  55. data/docs/guides/streaming.md +184 -125
  56. data/docs/guides/using-tools.md +300 -11
  57. data/docs/index.md +37 -5
  58. data/examples/01_simple_robot.rb +2 -2
  59. data/examples/02_tools.rb +14 -4
  60. data/examples/03_network.rb +23 -9
  61. data/examples/04_mcp.rb +11 -4
  62. data/examples/05_streaming.rb +8 -5
  63. data/examples/06_prompt_templates.rb +13 -9
  64. data/examples/07_network_memory.rb +5 -5
  65. data/examples/08_llm_config.rb +20 -15
  66. data/examples/09_chaining.rb +4 -4
  67. data/examples/11_network_introspection.rb +4 -4
  68. data/examples/12_message_bus.rb +2 -2
  69. data/examples/13_spawn.rb +2 -2
  70. data/examples/14_rusty_circuit/README.md +1 -0
  71. data/examples/14_rusty_circuit/comic.rb +7 -3
  72. data/examples/14_rusty_circuit/display.rb +14 -0
  73. data/examples/14_rusty_circuit/heckler.rb +8 -6
  74. data/examples/14_rusty_circuit/open_mic.rb +17 -6
  75. data/examples/14_rusty_circuit/scout.rb +17 -10
  76. data/examples/15_memory_network_and_bus/editorial_pipeline.rb +14 -10
  77. data/examples/15_memory_network_and_bus/linux_writer.rb +2 -2
  78. data/examples/15_memory_network_and_bus/os_editor.rb +3 -1
  79. data/examples/15_memory_network_and_bus/os_writer.rb +4 -1
  80. data/examples/16_writers_room/writer.rb +22 -22
  81. data/examples/16_writers_room/writers_room.rb +2 -0
  82. data/examples/17_skills.rb +14 -13
  83. data/examples/18_rails/README.md +20 -1
  84. data/examples/18_rails/app/controllers/chat_controller.rb +5 -1
  85. data/examples/18_rails/app/jobs/robot_run_job.rb +11 -5
  86. data/examples/18_rails/app/robots/chat_robot.rb +11 -0
  87. data/examples/18_rails/config/initializers/robot_lab.rb +8 -0
  88. data/examples/19_token_tracking.rb +25 -9
  89. data/examples/20_circuit_breaker.rb +10 -7
  90. data/examples/21_learning_loop.rb +42 -16
  91. data/examples/22_context_compression.rb +23 -23
  92. data/examples/23_convergence.rb +24 -17
  93. data/examples/24_structured_delegation.rb +13 -8
  94. data/examples/25_history_search.rb +12 -8
  95. data/examples/27_incident_response/incident_response.rb +31 -13
  96. data/examples/28_mcp_discovery.rb +17 -13
  97. data/examples/29_ractor_tools.rb +4 -2
  98. data/examples/30_ractor_network.rb +22 -17
  99. data/examples/31_launch_assessment.rb +20 -9
  100. data/examples/32_newsletter_reader.rb +7 -2
  101. data/examples/33_stock_predictor.rb +34 -13
  102. data/examples/34_agentskills.rb +7 -3
  103. data/examples/35_hooks.rb +266 -0
  104. data/examples/README.md +203 -42
  105. data/examples/common.rb +79 -7
  106. data/examples/xyzzy.rb +97 -0
  107. data/lib/robot_lab/agent_skill.rb +5 -4
  108. data/lib/robot_lab/budget/ledger.rb +98 -0
  109. data/lib/robot_lab/capabilities.rb +84 -0
  110. data/lib/robot_lab/config/defaults.yml +10 -0
  111. data/lib/robot_lab/config.rb +14 -9
  112. data/lib/robot_lab/error.rb +34 -4
  113. data/lib/robot_lab/errors.rb +45 -0
  114. data/lib/robot_lab/hook.rb +79 -0
  115. data/lib/robot_lab/hook_context.rb +194 -0
  116. data/lib/robot_lab/hook_registry.rb +55 -0
  117. data/lib/robot_lab/hooks.rb +87 -0
  118. data/lib/robot_lab/mcp/connection_poller.rb +2 -2
  119. data/lib/robot_lab/names.rb +402 -0
  120. data/lib/robot_lab/narrator.rb +87 -0
  121. data/lib/robot_lab/network.rb +77 -20
  122. data/lib/robot_lab/robot/agent_skill_matching.rb +1 -3
  123. data/lib/robot_lab/robot/budget.rb +89 -0
  124. data/lib/robot_lab/robot/bus_messaging.rb +90 -18
  125. data/lib/robot_lab/robot/hooking.rb +56 -0
  126. data/lib/robot_lab/robot/mcp_management.rb +8 -2
  127. data/lib/robot_lab/robot/template_rendering.rb +18 -5
  128. data/lib/robot_lab/robot.rb +233 -89
  129. data/lib/robot_lab/run_config.rb +24 -5
  130. data/lib/robot_lab/runnable.rb +51 -0
  131. data/lib/robot_lab/sandbox/null.rb +13 -0
  132. data/lib/robot_lab/sandbox/seatbelt.rb +104 -0
  133. data/lib/robot_lab/sandbox.rb +52 -0
  134. data/lib/robot_lab/script_tool.rb +60 -2
  135. data/lib/robot_lab/task.rb +26 -20
  136. data/lib/robot_lab/tool.rb +52 -11
  137. data/lib/robot_lab/version.rb +1 -1
  138. data/lib/robot_lab.rb +70 -15
  139. data/mkdocs.yml +7 -1
  140. metadata +41 -99
  141. data/examples/temp.md +0 -51
  142. data/site/404.html +0 -2300
  143. data/site/api/core/index.html +0 -2706
  144. data/site/api/core/memory/index.html +0 -3793
  145. data/site/api/core/network/index.html +0 -3500
  146. data/site/api/core/robot/index.html +0 -4566
  147. data/site/api/core/state/index.html +0 -3390
  148. data/site/api/core/tool/index.html +0 -3843
  149. data/site/api/index.html +0 -2635
  150. data/site/api/mcp/client/index.html +0 -3435
  151. data/site/api/mcp/index.html +0 -2783
  152. data/site/api/mcp/server/index.html +0 -3252
  153. data/site/api/mcp/transports/index.html +0 -3352
  154. data/site/api/messages/index.html +0 -2641
  155. data/site/api/messages/text-message/index.html +0 -3087
  156. data/site/api/messages/tool-call-message/index.html +0 -3159
  157. data/site/api/messages/tool-result-message/index.html +0 -3252
  158. data/site/api/messages/user-message/index.html +0 -3212
  159. data/site/api/streaming/context/index.html +0 -3282
  160. data/site/api/streaming/events/index.html +0 -3347
  161. data/site/api/streaming/index.html +0 -2738
  162. data/site/architecture/core-concepts/index.html +0 -3757
  163. data/site/architecture/index.html +0 -2797
  164. data/site/architecture/message-flow/index.html +0 -3238
  165. data/site/architecture/network-orchestration/index.html +0 -3433
  166. data/site/architecture/robot-execution/index.html +0 -3140
  167. data/site/architecture/state-management/index.html +0 -3498
  168. data/site/assets/css/custom.css +0 -56
  169. data/site/assets/images/favicon.png +0 -0
  170. data/site/assets/images/robot_lab.jpg +0 -0
  171. data/site/assets/javascripts/bundle.79ae519e.min.js +0 -16
  172. data/site/assets/javascripts/bundle.79ae519e.min.js.map +0 -7
  173. data/site/assets/javascripts/lunr/min/lunr.ar.min.js +0 -1
  174. data/site/assets/javascripts/lunr/min/lunr.da.min.js +0 -18
  175. data/site/assets/javascripts/lunr/min/lunr.de.min.js +0 -18
  176. data/site/assets/javascripts/lunr/min/lunr.du.min.js +0 -18
  177. data/site/assets/javascripts/lunr/min/lunr.el.min.js +0 -1
  178. data/site/assets/javascripts/lunr/min/lunr.es.min.js +0 -18
  179. data/site/assets/javascripts/lunr/min/lunr.fi.min.js +0 -18
  180. data/site/assets/javascripts/lunr/min/lunr.fr.min.js +0 -18
  181. data/site/assets/javascripts/lunr/min/lunr.he.min.js +0 -1
  182. data/site/assets/javascripts/lunr/min/lunr.hi.min.js +0 -1
  183. data/site/assets/javascripts/lunr/min/lunr.hu.min.js +0 -18
  184. data/site/assets/javascripts/lunr/min/lunr.hy.min.js +0 -1
  185. data/site/assets/javascripts/lunr/min/lunr.it.min.js +0 -18
  186. data/site/assets/javascripts/lunr/min/lunr.ja.min.js +0 -1
  187. data/site/assets/javascripts/lunr/min/lunr.jp.min.js +0 -1
  188. data/site/assets/javascripts/lunr/min/lunr.kn.min.js +0 -1
  189. data/site/assets/javascripts/lunr/min/lunr.ko.min.js +0 -1
  190. data/site/assets/javascripts/lunr/min/lunr.multi.min.js +0 -1
  191. data/site/assets/javascripts/lunr/min/lunr.nl.min.js +0 -18
  192. data/site/assets/javascripts/lunr/min/lunr.no.min.js +0 -18
  193. data/site/assets/javascripts/lunr/min/lunr.pt.min.js +0 -18
  194. data/site/assets/javascripts/lunr/min/lunr.ro.min.js +0 -18
  195. data/site/assets/javascripts/lunr/min/lunr.ru.min.js +0 -18
  196. data/site/assets/javascripts/lunr/min/lunr.sa.min.js +0 -1
  197. data/site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +0 -1
  198. data/site/assets/javascripts/lunr/min/lunr.sv.min.js +0 -18
  199. data/site/assets/javascripts/lunr/min/lunr.ta.min.js +0 -1
  200. data/site/assets/javascripts/lunr/min/lunr.te.min.js +0 -1
  201. data/site/assets/javascripts/lunr/min/lunr.th.min.js +0 -1
  202. data/site/assets/javascripts/lunr/min/lunr.tr.min.js +0 -18
  203. data/site/assets/javascripts/lunr/min/lunr.vi.min.js +0 -1
  204. data/site/assets/javascripts/lunr/min/lunr.zh.min.js +0 -1
  205. data/site/assets/javascripts/lunr/tinyseg.js +0 -206
  206. data/site/assets/javascripts/lunr/wordcut.js +0 -6708
  207. data/site/assets/javascripts/workers/search.2c215733.min.js +0 -42
  208. data/site/assets/javascripts/workers/search.2c215733.min.js.map +0 -7
  209. data/site/assets/stylesheets/main.484c7ddc.min.css +0 -1
  210. data/site/assets/stylesheets/main.484c7ddc.min.css.map +0 -1
  211. data/site/assets/stylesheets/palette.ab4e12ef.min.css +0 -1
  212. data/site/assets/stylesheets/palette.ab4e12ef.min.css.map +0 -1
  213. data/site/concepts/index.html +0 -3455
  214. data/site/examples/basic-chat/index.html +0 -2880
  215. data/site/examples/index.html +0 -2907
  216. data/site/examples/mcp-server/index.html +0 -3018
  217. data/site/examples/multi-robot-network/index.html +0 -3131
  218. data/site/examples/rails-application/index.html +0 -3329
  219. data/site/examples/tool-usage/index.html +0 -3085
  220. data/site/getting-started/configuration/index.html +0 -3745
  221. data/site/getting-started/index.html +0 -2572
  222. data/site/getting-started/installation/index.html +0 -2981
  223. data/site/getting-started/quick-start/index.html +0 -2942
  224. data/site/guides/building-robots/index.html +0 -4290
  225. data/site/guides/creating-networks/index.html +0 -3858
  226. data/site/guides/index.html +0 -2586
  227. data/site/guides/mcp-integration/index.html +0 -3581
  228. data/site/guides/memory/index.html +0 -3586
  229. data/site/guides/rails-integration/index.html +0 -4019
  230. data/site/guides/streaming/index.html +0 -3157
  231. data/site/guides/using-tools/index.html +0 -3802
  232. data/site/index.html +0 -2671
  233. data/site/search/search_index.json +0 -1
  234. data/site/sitemap.xml +0 -183
  235. data/site/sitemap.xml.gz +0 -0
  236. data/site/tags.json +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '020282572c5c4eca7e0c44d60920752df53043df99aa54a2018b68e049404945'
4
- data.tar.gz: 2f0d0e92ff91a8eb24ff73065e1b91091c57cb6abcf3a0c3349c2370ab877973
3
+ metadata.gz: 36b770d963e004a951cdf35d07a2e867e4e661a9e342e8047184cfd9dafd6e15
4
+ data.tar.gz: f53bb5c52efcd6169bf36afc69306a9c03e9cfcabdaf5b0a94871802e2909f55
5
5
  SHA512:
6
- metadata.gz: 7d99549cbb526071e48e2d66e9771553491404ec437f21465190517fc4451418a48024cd5e1fc8482ae96ea061492fb632f8f264048d8941e20090faa1213d22
7
- data.tar.gz: 0fe87b21e72c03a65e3809dfab01d3d6735919101ab8f2f8d9cd9d64a52394c06fc12f9fc9b648cb9350568c56ac8da111d8a6db9ba841738cbb72ce682708d6
6
+ metadata.gz: 850bde0e9ac1b7d65176bd067f42751d6d9db64517ca665d4765837fc5493e204f9b333cac08019cb451962d4d95789f986dee2ff08e55ae5e6a0d3d034f4f50
7
+ data.tar.gz: 97eb4dc66458a9a43f861e3f9c927eb6cfa63d33ddfff150b4181a45dc2c0db9570095f2e71d1182b76b4ee85e7086a6014b5536e805d9956f0860f9b4a03f50
data/.envrc CHANGED
@@ -1 +1,2 @@
1
1
  export RR=`pwd`
2
+ export BUNDLE_GEMFILE=Gemfile
data/.loki ADDED
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+ # robot_lab core — development tasks.
3
+
4
+ import_up "repo_dev.loki"
5
+
6
+ class Tasks
7
+ @@gem_name ||= "robot_lab".freeze
8
+
9
+ header "robot_lab v#{gem_version} — core multi-robot LLM framework"
10
+
11
+ desc "Run integration tests only"
12
+ def integration
13
+ sh "bundle exec rake integration"
14
+ end
15
+
16
+ desc "Run a single test file (e.g. asgard test_file test/robot_test.rb)"
17
+ def test_file(path)
18
+ sh "ruby -Ilib:test \"#{path}\""
19
+ end
20
+
21
+ class DocsCommands < Tasks
22
+ desc "Build YARD + MkDocs documentation"
23
+ def build
24
+ sh "bundle exec rake docs:build"
25
+ end
26
+
27
+ desc "Serve MkDocs documentation at http://localhost:8000"
28
+ def serve
29
+ sh "mkdocs serve"
30
+ end
31
+
32
+ desc "Serve YARD documentation locally"
33
+ def yard
34
+ sh "yard server --reload"
35
+ end
36
+ end
37
+
38
+ class ExamplesCommands < Tasks
39
+ desc "Run all examples (skips standalone apps and external-service examples)"
40
+ def all
41
+ sh "bundle exec rake examples:all"
42
+ end
43
+
44
+ desc "exec N", "Run a specific example by number (e.g. asgard examples exec 3)"
45
+ def exec(num)
46
+ sh "bundle exec rake examples:run[#{num}]"
47
+ end
48
+
49
+ desc "Start the Rails demo app (example 18)"
50
+ def rails
51
+ sh "bundle exec rake examples:rails"
52
+ end
53
+ end
54
+
55
+ desc "docs SUBCOMMAND", "Documentation tasks (build, serve, yard)"
56
+ subcommand "docs", DocsCommands
57
+
58
+ desc "examples SUBCOMMAND", "Example tasks (all, exec N, rails)"
59
+ subcommand "examples", ExamplesCommands
60
+ end
@@ -0,0 +1,43 @@
1
+ 4 lib/robot_lab.rb
2
+ 1 lib/robot_lab/agent_skill_catalog.rb
3
+ 2 lib/robot_lab/ask_user.rb
4
+ 2 lib/robot_lab/bus_poller.rb
5
+ 4 lib/robot_lab/capabilities.rb
6
+ 8 lib/robot_lab/config.rb
7
+ 3 lib/robot_lab/doom_loop_detector.rb
8
+ 6 lib/robot_lab/history_compressor.rb
9
+ 1 lib/robot_lab/hook.rb
10
+ 4 lib/robot_lab/hook_context.rb
11
+ 1 lib/robot_lab/hook_registry.rb
12
+ 4 lib/robot_lab/hooks.rb
13
+ 3 lib/robot_lab/mcp/client.rb
14
+ 6 lib/robot_lab/mcp/connection_poller.rb
15
+ 1 lib/robot_lab/mcp/server_discovery.rb
16
+ 3 lib/robot_lab/mcp/transports/sse.rb
17
+ 6 lib/robot_lab/mcp/transports/stdio.rb
18
+ 4 lib/robot_lab/mcp/transports/streamable_http.rb
19
+ 3 lib/robot_lab/mcp/transports/websocket.rb
20
+ 16 lib/robot_lab/memory.rb
21
+ 1 lib/robot_lab/memory_change.rb
22
+ 3 lib/robot_lab/message.rb
23
+ 8 lib/robot_lab/network.rb
24
+ 70 lib/robot_lab/robot.rb
25
+ 2 lib/robot_lab/robot/agent_skill_matching.rb
26
+ 4 lib/robot_lab/robot/bus_messaging.rb
27
+ 2 lib/robot_lab/robot/history_search.rb
28
+ 2 lib/robot_lab/robot/hooking.rb
29
+ 9 lib/robot_lab/robot/mcp_management.rb
30
+ 8 lib/robot_lab/robot/template_rendering.rb
31
+ 4 lib/robot_lab/robot_result.rb
32
+ 5 lib/robot_lab/run_config.rb
33
+ 1 lib/robot_lab/sandbox.rb
34
+ 1 lib/robot_lab/sandbox/seatbelt.rb
35
+ 3 lib/robot_lab/script_tool.rb
36
+ 1 lib/robot_lab/state_proxy.rb
37
+ 1 lib/robot_lab/streaming/context.rb
38
+ 1 lib/robot_lab/streaming/events.rb
39
+ 2 lib/robot_lab/task.rb
40
+ 6 lib/robot_lab/tool.rb
41
+ 2 lib/robot_lab/user_message.rb
42
+ 2 lib/robot_lab/utils.rb
43
+ 2 lib/robot_lab/waiter.rb
data/.rubocop.yml CHANGED
@@ -1,172 +1,10 @@
1
+ inherit_from: ../.rubocop-base.yml
2
+
3
+ # Core-only overrides. Exclude patterns here are relative to this repo and
4
+ # merge with the shared base's excludes.
1
5
  AllCops:
2
- NewCops: enable
3
- SuggestExtensions: false
4
- TargetRubyVersion: 4.0
5
6
  Exclude:
6
- - 'examples/**/*'
7
- - 'vendor/**/*'
8
- - 'dead_code/**/*'
9
7
  - '_notes/**/*'
10
8
 
11
- # ── Style: disabled cops ───────────────────────────────────────────────────
12
- Style/StringLiterals:
13
- Enabled: false
14
-
15
- Style/StringLiteralsInInterpolation:
16
- Enabled: false
17
-
18
- Style/Documentation:
19
- Enabled: false
20
-
21
- # Ruby 4.0 freezes string literals by default
22
- Style/FrozenStringLiteralComment:
23
- Enabled: false
24
-
25
- Style/IfUnlessModifier:
26
- Enabled: false
27
-
28
- Style/RescueModifier:
29
- Enabled: false
30
-
31
- Style/TrivialAccessors:
32
- Enabled: false
33
-
34
- Style/MultilineTernaryOperator:
35
- Enabled: false
36
-
37
- Style/SafeNavigation:
38
- Enabled: false
39
-
40
- Style/EmptyClassDefinition:
41
- Enabled: false
42
-
43
- Style/ClassAndModuleChildren:
44
- Enabled: false
45
-
46
- Style/RescueStandardError:
47
- Enabled: false
48
-
49
- Style/OneClassPerFile:
50
- Enabled: false
51
-
52
- # Both % and format/sprintf are acceptable
53
- Style/FormatString:
54
- Enabled: false
55
-
56
- # String concatenation and interpolation are both acceptable
57
- Style/StringConcatenation:
58
- Enabled: false
59
-
60
- # ── Layout ─────────────────────────────────────────────────────────────────
61
- Layout/LineLength:
62
- Max: 140
63
-
64
- Layout/ExtraSpacing:
65
- Enabled: false
66
-
67
- Layout/HashAlignment:
68
- Enabled: false
69
-
70
- Layout/FirstHashElementIndentation:
71
- Enabled: false
72
-
73
- Layout/EmptyLineAfterGuardClause:
74
- Enabled: false
75
-
76
- # ── Naming ─────────────────────────────────────────────────────────────────
77
- # Single-char params (c, e, n) are acceptable throughout
78
- Naming/MethodParameterName:
79
- Enabled: false
80
-
81
- Naming/VariableNumber:
82
- Exclude:
83
- - 'test/**/*'
84
-
85
- Naming/RescuedExceptionsVariableName:
86
- Enabled: false
87
-
88
- # set_results and similar explicit setters are clear and conventional
89
- Naming/AccessorMethodName:
90
- Enabled: false
91
-
92
- # has_tool_calls? and similar are clear and conventional
93
- Naming/PredicatePrefix:
94
- Enabled: false
95
-
96
- # Test helper methods don't need to follow predicate naming rules
97
- Naming/PredicateMethod:
98
- Exclude:
99
- - 'test/**/*'
100
-
101
- # ── Lint: relax noisy cops on intentional patterns ─────────────────────────
102
- Lint/EmptyBlock:
103
- Exclude:
104
- - 'test/**/*'
105
-
106
- # Library and framework methods commonly accept args for API/documentation purposes
107
- Lint/UnusedMethodArgument:
108
- Enabled: false
109
-
110
- Lint/ConstantDefinitionInBlock:
111
- Exclude:
112
- - 'Rakefile'
113
- - 'test/**/*'
114
-
115
- # ── Gemspec ────────────────────────────────────────────────────────────────
116
- Gemspec/DevelopmentDependencies:
117
- EnforcedStyle: Gemfile
118
-
119
- Gemspec/RequiredRubyVersion:
120
- Enabled: false
121
-
122
- Gemspec/OrderedDependencies:
123
- Enabled: false
124
-
125
- # ── Metrics ────────────────────────────────────────────────────────────────
126
- # Framework-level code (routers, parsers, orchestrators) is inherently complex.
127
- # Flog is the primary complexity gate — these RuboCop thresholds catch only
128
- # egregious outliers without false-positiving every dispatch method.
129
-
130
- Metrics/MethodLength:
131
- Max: 35
132
- CountAsOne:
133
- - heredoc
134
- - array
135
- - hash
136
- Exclude:
137
- - 'test/**/*'
138
-
139
- Metrics/AbcSize:
140
- Max: 40
141
- Exclude:
142
- - 'test/**/*'
143
-
144
9
  Metrics/ClassLength:
145
- Max: 600
146
- Exclude:
147
- - 'test/**/*'
148
-
149
- Metrics/ModuleLength:
150
- Max: 200
151
- Exclude:
152
- - 'test/**/*'
153
-
154
- Metrics/CyclomaticComplexity:
155
- Max: 20
156
- Exclude:
157
- - 'test/**/*'
158
-
159
- Metrics/PerceivedComplexity:
160
- Max: 20
161
- Exclude:
162
- - 'test/**/*'
163
-
164
- # Long method signatures with keyword args are a Ruby framework idiom
165
- Metrics/ParameterLists:
166
- Enabled: false
167
-
168
- Metrics/BlockLength:
169
- Exclude:
170
- - 'Rakefile'
171
- - '*.gemspec'
172
- - 'test/**/*'
10
+ Max: 650 # Robot is the central class; a future refactor could split it further
data/CHANGELOG.md CHANGED
@@ -8,6 +8,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ### Added
12
+ - `BusMessaging#respond_to_tasks` and `#serve` — a member auto-answers inbound
13
+ (non-reply) bus tasks and replies to the sender. `serve` runs each task through
14
+ `#run`; `respond_to_tasks { |m| ... }` is the generic form. Makes a Robot a
15
+ first-class bus responder (symmetric with how a Cyborg answers its human)
16
+ without hand-wiring `on_message`.
17
+ - `.loki` Asgard task file: `test`, `rubocop`, `rubocop_fix`, `flog`, `flay`, `quality`, `build`, `install`, `release`, `integration`, `docs`, and `examples` tasks via the Asgard task runner
18
+
19
+ ### Fixed
20
+ - `BusMessaging` now synchronizes its message counter and outbox with a mutex, so
21
+ concurrent sends and poller-thread reply correlation can't clobber each other.
22
+ - `flay_check` Rake task: structural code duplication gate (mass threshold 50); integrated into the `quality` Rake task
23
+ - `flay` gem added to development dependencies
24
+ - `test_output.txt`, `flay_output.txt`, `flog_output.txt`, and `rubocop_output.txt` added to `.gitignore`
25
+
26
+ ### Changed
27
+ - `test/test_helper.rb`: test output redirected to `test_output.txt` via `$stdout` reassignment; `TerminalSummaryReporter` prints a single PASS/FAIL summary line to the terminal
28
+ - `Rakefile`: `rubocop` and `rubocop_fix` tasks removed (now owned by Asgard); `flay_check` integrated into the `quality` gate
29
+
30
+ ## [0.2.6] - 2026-05-23
31
+
32
+ ### Added
33
+
34
+ - **`:compaction` hook family** — fires when `maybe_compact` determines that conversation history should be compressed. Provides `before_compaction`, `around_compaction`, `after_compaction`, and `on_compaction` callbacks.
35
+ - `on_compaction` allows an extension to supply a complete replacement message set via `ctx.compacted_messages`; when set, the core skips its own compaction strategy entirely (`ctx.handled?` returns true).
36
+ - `CompactionHookContext` — carries `robot`, `messages_before` (frozen snapshot), `config`, `strategy` (`:context_window`, `:custom`, or other symbol), `compacted_messages`, and `handled?`.
37
+ - **`:learn` hook family** — fires on every `robot.learn(text)` call with non-empty text. Provides `before_learn`, `around_learn`, `after_learn`, and `on_learn` callbacks.
38
+ - `on_learn` fires after the text has been stored and `ctx.stored = true`, giving extensions a reliable hook point for cross-session persistence.
39
+ - `LearnHookContext` — carries `robot`, `text`, `learnings_before` (frozen snapshot), and `stored`.
40
+ - **`over_compact_threshold?`** private predicate extracted from `compact_if_over_context_window` for independent testability.
41
+ - Hook tests for both new families added to `test/robot_lab/hooks_test.rb` (18 new tests across `RobotLabCompactionHooksTest` and `RobotLabLearnHooksTest`).
42
+ - Documentation for `:compaction` and `:learn` hook families added to `docs/guides/hooks.md`.
43
+
44
+ ### Changed
45
+
46
+ - **`Robot#on`** now accepts and forwards `context:` to `HookRegistry#on`, allowing extensions to pass per-registration domain config at registration time (e.g. `robot.on(MyHook, context: { domain: "finance" })`). Previously `context:` was silently dropped.
47
+ - **`maybe_compact`** refactored to dispatch through the `:compaction` hook family and delegate to `on_compaction` before falling back to the built-in strategy.
48
+ - **`Robot#learn`** refactored to dispatch through the `:learn` hook family; `on_learn` fires after deduplication with `ctx.stored` reflecting whether the text was actually added.
49
+
50
+ ### Added
51
+
52
+ - **`RobotLab::Hook` base class** (`lib/robot_lab/hook.rb`) — all hook handlers inherit from this class. Subclasses define lifecycle callbacks as `class << self` methods (`before_run`, `after_run`, etc.). Namespace is auto-derived from the class name via snake_case conversion of the final class name segment (e.g. `AuditHook` → `:audit_hook`); override with `self.namespace = :custom`. Ractor-safe by design: handler classes are Ruby constants, not Procs, so registrations are natively serializable across Ractor boundaries.
53
+ - **Hook system** — lifecycle hooks across all execution boundaries. Register handler classes with `RobotLab.on`, `network.on`, or `robot.on` for five families: `:run`, `:llm_generation`, `:tool_call`, `:network_run`, and `:task`, each with `before_*`, `around_*`, `after_*`, and (where applicable) `on_error` variants.
54
+ - `HookRegistry::Registration` — `Data.define(:handler_class, :context)`; stores a handler class reference and optional per-registration default `DotState` values. No Proc, no namespace field — namespace is read from the handler class.
55
+ - `HookContext` and five typed subclasses: `RunHookContext`, `LlmGenerationHookContext`, `ToolCallHookContext`, `NetworkRunHookContext`, `TaskHookContext` — unchanged
56
+ - `DotState` / `ExtensionState` — namespace-isolated dot-access state carried on every context object; `ctx.local` reads/writes state for the active handler's namespace
57
+ - `context:` parameter on `on(handler_class, context: {...})` — sets per-registration default `DotState` values merged in before each callback fires
58
+ - Around hooks chain correctly across handler class registrations; return value is propagated up the chain
59
+ - Per-run hooks via `robot.run("msg", hooks: MyHook)` or `robot.run("msg", hooks: [MyHook, OtherHook])`
60
+ - `on_error` fires for `:run`, `:network_run`, and `:task` families; exception is re-raised after all error handlers complete
61
+ - **`examples/xyzzy.rb`** — updated reference extension: `RobotLab::Xyzzy < RobotLab::Hook` with `class << self` methods for every hook family; logs each callback with a timestamped stdout tagline and a structured logger context snapshot; registered globally with `RobotLab.on(RobotLab::Xyzzy)`
62
+ - **Example 35** (`examples/35_hooks.rb`) — updated full hook pipeline demo: xyzzy extension tracing all hooks, `around_run` perf timer handler class, `around_llm_generation` response cache handler class (cache hits skip the LLM entirely), `before/after_llm_generation` tracer, tool call hooks, network/task hooks, and `on_error`
63
+ - **`examples/common.rb`** — added explicit `openai_api_key`, `openai_organization_id`, and `openai_project_id` to `RubyLLM.configure` to match provider configurator expectations; updated default model to `gpt-4.1-mini`
64
+
11
65
  ## [0.2.1] - 2026-05-19
12
66
 
13
67
  ### Added