igniter 0.4.5 → 0.5.1

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 (638) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -3
  3. data/README.md +164 -409
  4. data/bin/igniter-stack +94 -0
  5. data/docs/README.md +62 -0
  6. data/examples/README.md +74 -312
  7. data/examples/agent_orchestration.rb +76 -0
  8. data/examples/agents.rb +2 -1
  9. data/examples/catalog.rb +412 -0
  10. data/examples/consensus.rb +241 -0
  11. data/examples/dataflow.rb +309 -0
  12. data/examples/distributed_workflow.rb +1 -1
  13. data/examples/effects.rb +10 -9
  14. data/examples/elocal_webhook.rb +1 -0
  15. data/examples/incremental.rb +4 -3
  16. data/examples/introspection.rb +49 -0
  17. data/examples/invariants.rb +4 -3
  18. data/examples/llm_tools.rb +237 -0
  19. data/examples/mesh.rb +241 -0
  20. data/examples/mesh_discovery.rb +287 -0
  21. data/examples/mesh_gossip.rb +164 -0
  22. data/examples/reactive_auditing.rb +50 -0
  23. data/examples/ringcentral_routing.rb +1 -1
  24. data/examples/run.rb +163 -0
  25. data/lib/igniter/monorepo_packages.rb +17 -0
  26. data/lib/igniter/stack.rb +5 -0
  27. data/lib/igniter.rb +48 -15
  28. data/packages/igniter-agents/README.md +22 -0
  29. data/{lib → packages/igniter-agents/lib}/igniter/agent/ref.rb +1 -0
  30. data/{lib → packages/igniter-agents/lib}/igniter/agent/runner.rb +12 -0
  31. data/{lib → packages/igniter-agents/lib}/igniter/agent.rb +6 -0
  32. data/packages/igniter-agents/lib/igniter/agents/observability/metrics_agent.rb +130 -0
  33. data/packages/igniter-agents/lib/igniter/agents/pipeline/batch_processor_agent.rb +131 -0
  34. data/packages/igniter-agents/lib/igniter/agents/proactive/alert_agent.rb +111 -0
  35. data/packages/igniter-agents/lib/igniter/agents/proactive/health_check_agent.rb +122 -0
  36. data/packages/igniter-agents/lib/igniter/agents/proactive_agent.rb +208 -0
  37. data/packages/igniter-agents/lib/igniter/agents/reliability/retry_agent.rb +99 -0
  38. data/packages/igniter-agents/lib/igniter/agents/scheduling/cron_agent.rb +110 -0
  39. data/packages/igniter-agents/lib/igniter/agents.rb +23 -0
  40. data/packages/igniter-agents/lib/igniter/ai/agents/chain_agent.rb +129 -0
  41. data/packages/igniter-agents/lib/igniter/ai/agents/critic_agent.rb +165 -0
  42. data/packages/igniter-agents/lib/igniter/ai/agents/evaluator_agent.rb +195 -0
  43. data/packages/igniter-agents/lib/igniter/ai/agents/evolution_agent.rb +288 -0
  44. data/packages/igniter-agents/lib/igniter/ai/agents/observer_agent.rb +186 -0
  45. data/packages/igniter-agents/lib/igniter/ai/agents/planner_agent.rb +212 -0
  46. data/packages/igniter-agents/lib/igniter/ai/agents/router_agent.rb +133 -0
  47. data/packages/igniter-agents/lib/igniter/ai/agents/self_reflection_agent.rb +177 -0
  48. data/packages/igniter-agents/lib/igniter/ai/agents.rb +25 -0
  49. data/{lib → packages/igniter-agents/lib}/igniter/registry.rb +2 -0
  50. data/packages/igniter-agents/lib/igniter/runtime/registry_agent_adapter.rb +102 -0
  51. data/{lib → packages/igniter-agents/lib}/igniter/supervisor.rb +3 -0
  52. data/packages/igniter-agents/lib/igniter-agents.rb +7 -0
  53. data/packages/igniter-ai/README.md +20 -0
  54. data/packages/igniter-ai/lib/igniter/ai/config.rb +113 -0
  55. data/{lib/igniter/integrations/llm → packages/igniter-ai/lib/igniter/ai}/context.rb +2 -2
  56. data/packages/igniter-ai/lib/igniter/ai/executor.rb +352 -0
  57. data/{lib/igniter/integrations/llm → packages/igniter-ai/lib/igniter/ai}/providers/anthropic.rb +42 -9
  58. data/{lib/igniter/integrations/llm → packages/igniter-ai/lib/igniter/ai}/providers/base.rb +1 -1
  59. data/{lib/igniter/integrations/llm → packages/igniter-ai/lib/igniter/ai}/providers/ollama.rb +4 -4
  60. data/{lib/igniter/integrations/llm → packages/igniter-ai/lib/igniter/ai}/providers/openai.rb +39 -10
  61. data/packages/igniter-ai/lib/igniter/ai/skill/feedback.rb +116 -0
  62. data/packages/igniter-ai/lib/igniter/ai/skill/output_schema.rb +110 -0
  63. data/packages/igniter-ai/lib/igniter/ai/skill/runtime_contract.rb +87 -0
  64. data/packages/igniter-ai/lib/igniter/ai/skill.rb +107 -0
  65. data/packages/igniter-ai/lib/igniter/ai/tool_registry.rb +79 -0
  66. data/packages/igniter-ai/lib/igniter/ai/transcription/providers/assemblyai.rb +200 -0
  67. data/packages/igniter-ai/lib/igniter/ai/transcription/providers/base.rb +122 -0
  68. data/packages/igniter-ai/lib/igniter/ai/transcription/providers/deepgram.rb +162 -0
  69. data/packages/igniter-ai/lib/igniter/ai/transcription/providers/openai.rb +102 -0
  70. data/packages/igniter-ai/lib/igniter/ai/transcription/transcriber.rb +145 -0
  71. data/packages/igniter-ai/lib/igniter/ai/transcription/transcript_result.rb +29 -0
  72. data/packages/igniter-ai/lib/igniter/ai.rb +98 -0
  73. data/packages/igniter-ai/lib/igniter-ai.rb +3 -0
  74. data/packages/igniter-app/README.md +19 -0
  75. data/packages/igniter-app/lib/igniter/app/app_config.rb +43 -0
  76. data/packages/igniter-app/lib/igniter/app/app_host.rb +56 -0
  77. data/packages/igniter-app/lib/igniter/app/app_host_config.rb +27 -0
  78. data/packages/igniter-app/lib/igniter/app/app_host_pack.rb +13 -0
  79. data/packages/igniter-app/lib/igniter/app/autoloader.rb +18 -0
  80. data/packages/igniter-app/lib/igniter/app/cluster_app_host.rb +95 -0
  81. data/packages/igniter-app/lib/igniter/app/cluster_app_host_config.rb +78 -0
  82. data/packages/igniter-app/lib/igniter/app/credentials/config_loader.rb +152 -0
  83. data/packages/igniter-app/lib/igniter/app/credentials/credential.rb +48 -0
  84. data/packages/igniter-app/lib/igniter/app/credentials/credential_policy.rb +38 -0
  85. data/packages/igniter-app/lib/igniter/app/credentials/events/credential_event.rb +179 -0
  86. data/packages/igniter-app/lib/igniter/app/credentials/events.rb +12 -0
  87. data/packages/igniter-app/lib/igniter/app/credentials/lease_request.rb +153 -0
  88. data/packages/igniter-app/lib/igniter/app/credentials/policies/ephemeral_lease_policy.rb +35 -0
  89. data/packages/igniter-app/lib/igniter/app/credentials/policies/local_only_policy.rb +33 -0
  90. data/packages/igniter-app/lib/igniter/app/credentials/policies.rb +13 -0
  91. data/packages/igniter-app/lib/igniter/app/credentials/store.rb +21 -0
  92. data/packages/igniter-app/lib/igniter/app/credentials/stores/file_store.rb +114 -0
  93. data/packages/igniter-app/lib/igniter/app/credentials/trail.rb +254 -0
  94. data/packages/igniter-app/lib/igniter/app/credentials.rb +20 -0
  95. data/packages/igniter-app/lib/igniter/app/dev_output_sync.rb +4 -0
  96. data/packages/igniter-app/lib/igniter/app/diagnostics/app_host_contributor.rb +71 -0
  97. data/packages/igniter-app/lib/igniter/app/diagnostics/cluster_app_host_contributor.rb +97 -0
  98. data/packages/igniter-app/lib/igniter/app/diagnostics/credential_contributor.rb +66 -0
  99. data/packages/igniter-app/lib/igniter/app/diagnostics/evolution_contributor.rb +74 -0
  100. data/packages/igniter-app/lib/igniter/app/diagnostics/ignite_contributor.rb +121 -0
  101. data/packages/igniter-app/lib/igniter/app/diagnostics/loader_contributor.rb +68 -0
  102. data/packages/igniter-app/lib/igniter/app/diagnostics/orchestration_contributor.rb +200 -0
  103. data/packages/igniter-app/lib/igniter/app/diagnostics/runtime_contributor.rb +68 -0
  104. data/packages/igniter-app/lib/igniter/app/diagnostics/scheduler_contributor.rb +72 -0
  105. data/packages/igniter-app/lib/igniter/app/diagnostics/sdk_contributor.rb +284 -0
  106. data/packages/igniter-app/lib/igniter/app/diagnostics.rb +62 -0
  107. data/packages/igniter-app/lib/igniter/app/evolution/approval_decision.rb +115 -0
  108. data/packages/igniter-app/lib/igniter/app/evolution/approval_request.rb +36 -0
  109. data/packages/igniter-app/lib/igniter/app/evolution/plan.rb +72 -0
  110. data/packages/igniter-app/lib/igniter/app/evolution/planner.rb +85 -0
  111. data/packages/igniter-app/lib/igniter/app/evolution/result.rb +45 -0
  112. data/packages/igniter-app/lib/igniter/app/evolution/runner.rb +102 -0
  113. data/packages/igniter-app/lib/igniter/app/evolution/store.rb +21 -0
  114. data/packages/igniter-app/lib/igniter/app/evolution/stores/file_store.rb +241 -0
  115. data/packages/igniter-app/lib/igniter/app/evolution/trail.rb +108 -0
  116. data/packages/igniter-app/lib/igniter/app/evolution.rb +11 -0
  117. data/packages/igniter-app/lib/igniter/app/filesystem_loader_adapter.rb +21 -0
  118. data/packages/igniter-app/lib/igniter/app/generator.rb +636 -0
  119. data/packages/igniter-app/lib/igniter/app/generators/cluster.rb +1367 -0
  120. data/packages/igniter-app/lib/igniter/app/generators/dashboard.rb +152 -0
  121. data/packages/igniter-app/lib/igniter/app/generators/playground.rb +1227 -0
  122. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/README.md.erb +37 -0
  123. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/app.rb.erb +19 -0
  124. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/contexts/home_context.rb.erb +54 -0
  125. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/frontend/application.js.erb +3 -0
  126. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/spec/dashboard_app_spec.rb.erb +79 -0
  127. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/support/stack_overview.rb.erb +23 -0
  128. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/web/handlers/home_handler.rb.erb +27 -0
  129. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/web/views/home_page.arb.erb +44 -0
  130. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/web/views/home_page.rb.erb +56 -0
  131. data/packages/igniter-app/lib/igniter/app/generators/templates/dashboard/web/views/layout.arb.erb +17 -0
  132. data/packages/igniter-app/lib/igniter/app/host_adapter.rb +26 -0
  133. data/packages/igniter-app/lib/igniter/app/host_config.rb +40 -0
  134. data/packages/igniter-app/lib/igniter/app/host_registry.rb +43 -0
  135. data/packages/igniter-app/lib/igniter/app/loader_adapter.rb +15 -0
  136. data/packages/igniter-app/lib/igniter/app/loader_pack.rb +8 -0
  137. data/packages/igniter-app/lib/igniter/app/loader_registry.rb +39 -0
  138. data/packages/igniter-app/lib/igniter/app/observability/operator_action_handler.rb +147 -0
  139. data/packages/igniter-app/lib/igniter/app/observability/operator_console_handler.rb +747 -0
  140. data/packages/igniter-app/lib/igniter/app/observability/operator_overview_handler.rb +350 -0
  141. data/packages/igniter-app/lib/igniter/app/observability.rb +5 -0
  142. data/packages/igniter-app/lib/igniter/app/observability_pack.rb +71 -0
  143. data/packages/igniter-app/lib/igniter/app/operator/dispatcher.rb +40 -0
  144. data/packages/igniter-app/lib/igniter/app/operator/handler_registry.rb +40 -0
  145. data/packages/igniter-app/lib/igniter/app/operator/handler_result.rb +67 -0
  146. data/packages/igniter-app/lib/igniter/app/operator/handlers/base.rb +79 -0
  147. data/packages/igniter-app/lib/igniter/app/operator/handlers/ignite_handler.rb +108 -0
  148. data/packages/igniter-app/lib/igniter/app/operator/handlers/orchestration_handler.rb +33 -0
  149. data/packages/igniter-app/lib/igniter/app/operator/handlers.rb +5 -0
  150. data/packages/igniter-app/lib/igniter/app/operator/lifecycle_contract.rb +55 -0
  151. data/packages/igniter-app/lib/igniter/app/operator/policy.rb +157 -0
  152. data/packages/igniter-app/lib/igniter/app/operator.rb +17 -0
  153. data/packages/igniter-app/lib/igniter/app/orchestration/action_result_builder.rb +65 -0
  154. data/packages/igniter-app/lib/igniter/app/orchestration/followup_request.rb +36 -0
  155. data/packages/igniter-app/lib/igniter/app/orchestration/handler_registry.rb +58 -0
  156. data/packages/igniter-app/lib/igniter/app/orchestration/handlers.rb +106 -0
  157. data/packages/igniter-app/lib/igniter/app/orchestration/inbox.rb +283 -0
  158. data/packages/igniter-app/lib/igniter/app/orchestration/inbox_query.rb +293 -0
  159. data/packages/igniter-app/lib/igniter/app/orchestration/lane_registry.rb +100 -0
  160. data/packages/igniter-app/lib/igniter/app/orchestration/operator_query.rb +449 -0
  161. data/packages/igniter-app/lib/igniter/app/orchestration/plan.rb +68 -0
  162. data/packages/igniter-app/lib/igniter/app/orchestration/planner.rb +89 -0
  163. data/packages/igniter-app/lib/igniter/app/orchestration/policies.rb +125 -0
  164. data/packages/igniter-app/lib/igniter/app/orchestration/policy_registry.rb +63 -0
  165. data/packages/igniter-app/lib/igniter/app/orchestration/result.rb +43 -0
  166. data/packages/igniter-app/lib/igniter/app/orchestration/routing_registry.rb +43 -0
  167. data/packages/igniter-app/lib/igniter/app/orchestration/runner.rb +50 -0
  168. data/packages/igniter-app/lib/igniter/app/orchestration/runtime_event_query.rb +205 -0
  169. data/packages/igniter-app/lib/igniter/app/orchestration/runtime_overview_builder.rb +286 -0
  170. data/packages/igniter-app/lib/igniter/app/orchestration/runtime_query_overview_builder.rb +20 -0
  171. data/packages/igniter-app/lib/igniter/app/orchestration/runtime_result_builder.rb +23 -0
  172. data/packages/igniter-app/lib/igniter/app/orchestration.rb +113 -0
  173. data/packages/igniter-app/lib/igniter/app/runtime.rb +4 -0
  174. data/packages/igniter-app/lib/igniter/app/runtime_context.rb +101 -0
  175. data/packages/igniter-app/lib/igniter/app/runtime_pack.rb +16 -0
  176. data/packages/igniter-app/lib/igniter/app/scaffold_pack.rb +6 -0
  177. data/packages/igniter-app/lib/igniter/app/scheduler.rb +109 -0
  178. data/packages/igniter-app/lib/igniter/app/scheduler_adapter.rb +17 -0
  179. data/packages/igniter-app/lib/igniter/app/scheduler_pack.rb +8 -0
  180. data/packages/igniter-app/lib/igniter/app/scheduler_registry.rb +39 -0
  181. data/packages/igniter-app/lib/igniter/app/stack.rb +1726 -0
  182. data/packages/igniter-app/lib/igniter/app/stack_pack.rb +3 -0
  183. data/packages/igniter-app/lib/igniter/app/threaded_scheduler_adapter.rb +35 -0
  184. data/packages/igniter-app/lib/igniter/app/yml_loader.rb +43 -0
  185. data/packages/igniter-app/lib/igniter/app.rb +2367 -0
  186. data/packages/igniter-app/lib/igniter/ignite/bootstrap_agent.rb +334 -0
  187. data/packages/igniter-app/lib/igniter/ignite/bootstrap_target.rb +79 -0
  188. data/packages/igniter-app/lib/igniter/ignite/deployment_intent.rb +82 -0
  189. data/packages/igniter-app/lib/igniter/ignite/ignition_agent.rb +1011 -0
  190. data/packages/igniter-app/lib/igniter/ignite/ignition_plan.rb +83 -0
  191. data/packages/igniter-app/lib/igniter/ignite/ignition_report.rb +144 -0
  192. data/packages/igniter-app/lib/igniter/ignite/store.rb +19 -0
  193. data/packages/igniter-app/lib/igniter/ignite/stores/file_store.rb +112 -0
  194. data/packages/igniter-app/lib/igniter/ignite/trail.rb +215 -0
  195. data/packages/igniter-app/lib/igniter/ignite.rb +11 -0
  196. data/packages/igniter-app/lib/igniter-app.rb +5 -0
  197. data/packages/igniter-cluster/README.md +9 -0
  198. data/packages/igniter-cluster/lib/igniter/cluster/agent_route_resolver.rb +58 -0
  199. data/packages/igniter-cluster/lib/igniter/cluster/consensus/cluster.rb +187 -0
  200. data/packages/igniter-cluster/lib/igniter/cluster/consensus/errors.rb +16 -0
  201. data/packages/igniter-cluster/lib/igniter/cluster/consensus/executors.rb +45 -0
  202. data/packages/igniter-cluster/lib/igniter/cluster/consensus/node.rb +322 -0
  203. data/packages/igniter-cluster/lib/igniter/cluster/consensus/read_query.rb +32 -0
  204. data/packages/igniter-cluster/lib/igniter/cluster/consensus/state_machine.rb +60 -0
  205. data/packages/igniter-cluster/lib/igniter/cluster/consensus.rb +18 -0
  206. data/packages/igniter-cluster/lib/igniter/cluster/diagnostics/governance_contributor.rb +90 -0
  207. data/packages/igniter-cluster/lib/igniter/cluster/diagnostics/identity_contributor.rb +98 -0
  208. data/packages/igniter-cluster/lib/igniter/cluster/diagnostics/routing_contributor.rb +674 -0
  209. data/packages/igniter-cluster/lib/igniter/cluster/diagnostics.rb +24 -0
  210. data/packages/igniter-cluster/lib/igniter/cluster/events/envelope.rb +136 -0
  211. data/packages/igniter-cluster/lib/igniter/cluster/events/hook_support.rb +33 -0
  212. data/packages/igniter-cluster/lib/igniter/cluster/events/log.rb +102 -0
  213. data/packages/igniter-cluster/lib/igniter/cluster/events/projection_feed.rb +98 -0
  214. data/packages/igniter-cluster/lib/igniter/cluster/events/read_model_projector.rb +32 -0
  215. data/packages/igniter-cluster/lib/igniter/cluster/events.rb +131 -0
  216. data/packages/igniter-cluster/lib/igniter/cluster/governance/admission_decision.rb +41 -0
  217. data/packages/igniter-cluster/lib/igniter/cluster/governance/admission_policy.rb +66 -0
  218. data/packages/igniter-cluster/lib/igniter/cluster/governance/admission_queue.rb +88 -0
  219. data/packages/igniter-cluster/lib/igniter/cluster/governance/admission_request.rb +62 -0
  220. data/packages/igniter-cluster/lib/igniter/cluster/governance/admission_workflow.rb +214 -0
  221. data/packages/igniter-cluster/lib/igniter/cluster/governance/checkpoint.rb +141 -0
  222. data/packages/igniter-cluster/lib/igniter/cluster/governance/compaction_record.rb +33 -0
  223. data/packages/igniter-cluster/lib/igniter/cluster/governance/stores/checkpoint_store.rb +89 -0
  224. data/packages/igniter-cluster/lib/igniter/cluster/governance/stores/file_store.rb +249 -0
  225. data/packages/igniter-cluster/lib/igniter/cluster/governance/trail.rb +164 -0
  226. data/packages/igniter-cluster/lib/igniter/cluster/governance.rb +12 -0
  227. data/packages/igniter-cluster/lib/igniter/cluster/identity/capability_attestation.rb +114 -0
  228. data/packages/igniter-cluster/lib/igniter/cluster/identity/manifest.rb +139 -0
  229. data/packages/igniter-cluster/lib/igniter/cluster/identity/node_identity.rb +106 -0
  230. data/packages/igniter-cluster/lib/igniter/cluster/identity.rb +5 -0
  231. data/packages/igniter-cluster/lib/igniter/cluster/mesh/announcer.rb +88 -0
  232. data/packages/igniter-cluster/lib/igniter/cluster/mesh/checkpoint_gossip.rb +60 -0
  233. data/packages/igniter-cluster/lib/igniter/cluster/mesh/config.rb +146 -0
  234. data/packages/igniter-cluster/lib/igniter/cluster/mesh/discovery.rb +44 -0
  235. data/packages/igniter-cluster/lib/igniter/cluster/mesh/errors.rb +36 -0
  236. data/packages/igniter-cluster/lib/igniter/cluster/mesh/gossip.rb +62 -0
  237. data/packages/igniter-cluster/lib/igniter/cluster/mesh/mesh_ql.rb +470 -0
  238. data/packages/igniter-cluster/lib/igniter/cluster/mesh/node_observation.rb +281 -0
  239. data/packages/igniter-cluster/lib/igniter/cluster/mesh/observation_query.rb +284 -0
  240. data/packages/igniter-cluster/lib/igniter/cluster/mesh/peer.rb +51 -0
  241. data/packages/igniter-cluster/lib/igniter/cluster/mesh/peer_capacity_report.rb +42 -0
  242. data/packages/igniter-cluster/lib/igniter/cluster/mesh/peer_identity_envelope.rb +158 -0
  243. data/packages/igniter-cluster/lib/igniter/cluster/mesh/peer_metadata.rb +122 -0
  244. data/packages/igniter-cluster/lib/igniter/cluster/mesh/peer_registry.rb +81 -0
  245. data/packages/igniter-cluster/lib/igniter/cluster/mesh/placement_decision.rb +64 -0
  246. data/packages/igniter-cluster/lib/igniter/cluster/mesh/placement_planner.rb +154 -0
  247. data/packages/igniter-cluster/lib/igniter/cluster/mesh/placement_policy.rb +103 -0
  248. data/packages/igniter-cluster/lib/igniter/cluster/mesh/poller.rb +92 -0
  249. data/packages/igniter-cluster/lib/igniter/cluster/mesh/rebalance_plan.rb +66 -0
  250. data/packages/igniter-cluster/lib/igniter/cluster/mesh/rebalance_planner.rb +153 -0
  251. data/packages/igniter-cluster/lib/igniter/cluster/mesh/repair_loop.rb +169 -0
  252. data/packages/igniter-cluster/lib/igniter/cluster/mesh/router.rb +306 -0
  253. data/packages/igniter-cluster/lib/igniter/cluster/mesh/workload_signal.rb +46 -0
  254. data/packages/igniter-cluster/lib/igniter/cluster/mesh/workload_tracker.rb +215 -0
  255. data/packages/igniter-cluster/lib/igniter/cluster/mesh.rb +452 -0
  256. data/packages/igniter-cluster/lib/igniter/cluster/ownership/claim.rb +69 -0
  257. data/packages/igniter-cluster/lib/igniter/cluster/ownership/errors.rb +19 -0
  258. data/packages/igniter-cluster/lib/igniter/cluster/ownership/owner_client.rb +76 -0
  259. data/packages/igniter-cluster/lib/igniter/cluster/ownership/registry.rb +98 -0
  260. data/packages/igniter-cluster/lib/igniter/cluster/ownership/resolver.rb +62 -0
  261. data/packages/igniter-cluster/lib/igniter/cluster/ownership.rb +81 -0
  262. data/packages/igniter-cluster/lib/igniter/cluster/projection_store.rb +62 -0
  263. data/packages/igniter-cluster/lib/igniter/cluster/rag/chunk.rb +49 -0
  264. data/packages/igniter-cluster/lib/igniter/cluster/rag/fanout_retriever.rb +93 -0
  265. data/packages/igniter-cluster/lib/igniter/cluster/rag/knowledge_shard.rb +140 -0
  266. data/packages/igniter-cluster/lib/igniter/cluster/rag/net_http_adapter.rb +85 -0
  267. data/packages/igniter-cluster/lib/igniter/cluster/rag/ranker.rb +46 -0
  268. data/packages/igniter-cluster/lib/igniter/cluster/rag/retrieval_query.rb +30 -0
  269. data/packages/igniter-cluster/lib/igniter/cluster/rag/retrieval_result.rb +77 -0
  270. data/packages/igniter-cluster/lib/igniter/cluster/rag.rb +38 -0
  271. data/packages/igniter-cluster/lib/igniter/cluster/remote_adapter.rb +101 -0
  272. data/packages/igniter-cluster/lib/igniter/cluster/replication/bootstrapper.rb +63 -0
  273. data/packages/igniter-cluster/lib/igniter/cluster/replication/bootstrappers/gem.rb +39 -0
  274. data/packages/igniter-cluster/lib/igniter/cluster/replication/bootstrappers/git.rb +46 -0
  275. data/packages/igniter-cluster/lib/igniter/cluster/replication/bootstrappers/tarball.rb +62 -0
  276. data/packages/igniter-cluster/lib/igniter/cluster/replication/capability_query.rb +675 -0
  277. data/packages/igniter-cluster/lib/igniter/cluster/replication/expansion_plan.rb +40 -0
  278. data/packages/igniter-cluster/lib/igniter/cluster/replication/expansion_planner.rb +154 -0
  279. data/packages/igniter-cluster/lib/igniter/cluster/replication/manifest.rb +47 -0
  280. data/packages/igniter-cluster/lib/igniter/cluster/replication/network_topology.rb +150 -0
  281. data/packages/igniter-cluster/lib/igniter/cluster/replication/node_profile.rb +134 -0
  282. data/packages/igniter-cluster/lib/igniter/cluster/replication/reflective_replication_agent.rb +259 -0
  283. data/packages/igniter-cluster/lib/igniter/cluster/replication/replication_agent.rb +89 -0
  284. data/packages/igniter-cluster/lib/igniter/cluster/replication/ssh_session.rb +79 -0
  285. data/packages/igniter-cluster/lib/igniter/cluster/replication.rb +38 -0
  286. data/packages/igniter-cluster/lib/igniter/cluster/routed_agent_adapter.rb +79 -0
  287. data/packages/igniter-cluster/lib/igniter/cluster/routing_plan_executor.rb +427 -0
  288. data/packages/igniter-cluster/lib/igniter/cluster/routing_plan_result.rb +38 -0
  289. data/packages/igniter-cluster/lib/igniter/cluster/trust/admission_plan.rb +34 -0
  290. data/packages/igniter-cluster/lib/igniter/cluster/trust/admission_planner.rb +76 -0
  291. data/packages/igniter-cluster/lib/igniter/cluster/trust/admission_result.rb +34 -0
  292. data/packages/igniter-cluster/lib/igniter/cluster/trust/admission_runner.rb +125 -0
  293. data/packages/igniter-cluster/lib/igniter/cluster/trust/trust_assessment.rb +37 -0
  294. data/packages/igniter-cluster/lib/igniter/cluster/trust/trust_store.rb +58 -0
  295. data/packages/igniter-cluster/lib/igniter/cluster/trust/verifier.rb +80 -0
  296. data/packages/igniter-cluster/lib/igniter/cluster/trust.rb +9 -0
  297. data/packages/igniter-cluster/lib/igniter/cluster.rb +71 -0
  298. data/packages/igniter-cluster/lib/igniter-cluster.rb +3 -0
  299. data/packages/igniter-core/README.md +21 -0
  300. data/packages/igniter-core/lib/igniter/core/capabilities.rb +70 -0
  301. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/compiled_graph.rb +40 -2
  302. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validation_pipeline.rb +1 -0
  303. data/packages/igniter-core/lib/igniter/core/compiler/validators/agent_validator.rb +142 -0
  304. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validators/dependencies_validator.rb +90 -3
  305. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validators/remote_validator.rb +2 -0
  306. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler.rb +1 -0
  307. data/packages/igniter-core/lib/igniter/core/content_addressing.rb +133 -0
  308. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/contract.rb +88 -6
  309. data/packages/igniter-core/lib/igniter/core/dataflow/aggregate_operators.rb +147 -0
  310. data/packages/igniter-core/lib/igniter/core/dataflow/aggregate_state.rb +77 -0
  311. data/packages/igniter-core/lib/igniter/core/dataflow/diff.rb +37 -0
  312. data/packages/igniter-core/lib/igniter/core/dataflow/diff_state.rb +81 -0
  313. data/packages/igniter-core/lib/igniter/core/dataflow/incremental_collection_result.rb +39 -0
  314. data/packages/igniter-core/lib/igniter/core/dataflow/window_filter.rb +48 -0
  315. data/packages/igniter-core/lib/igniter/core/dataflow.rb +65 -0
  316. data/packages/igniter-core/lib/igniter/core/diagnostics/agent_contributor.rb +241 -0
  317. data/packages/igniter-core/lib/igniter/core/diagnostics/capability_contributor.rb +162 -0
  318. data/packages/igniter-core/lib/igniter/core/diagnostics/orchestration_contributor.rb +75 -0
  319. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/diagnostics/report.rb +81 -6
  320. data/packages/igniter-core/lib/igniter/core/diagnostics.rb +58 -0
  321. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/dsl/contract_builder.rb +230 -9
  322. data/packages/igniter-core/lib/igniter/core/dto/record.rb +189 -0
  323. data/packages/igniter-core/lib/igniter/core/dto.rb +8 -0
  324. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/effect.rb +4 -0
  325. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/errors.rb +26 -3
  326. data/packages/igniter-core/lib/igniter/core/executor.rb +134 -0
  327. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/introspection/graph_formatter.rb +32 -1
  328. data/packages/igniter-core/lib/igniter/core/extensions/introspection/plan_formatter.rb +85 -0
  329. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/introspection/runtime_formatter.rb +26 -0
  330. data/packages/igniter-core/lib/igniter/core/extensions/invariants.rb +70 -0
  331. data/packages/igniter-core/lib/igniter/core/fingerprint.rb +43 -0
  332. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/incremental.rb +4 -4
  333. data/packages/igniter-core/lib/igniter/core/memory/agent_memory.rb +104 -0
  334. data/packages/igniter-core/lib/igniter/core/memory/episode.rb +29 -0
  335. data/packages/igniter-core/lib/igniter/core/memory/fact.rb +27 -0
  336. data/packages/igniter-core/lib/igniter/core/memory/memorable.rb +90 -0
  337. data/packages/igniter-core/lib/igniter/core/memory/reflection_cycle.rb +96 -0
  338. data/packages/igniter-core/lib/igniter/core/memory/reflection_record.rb +28 -0
  339. data/packages/igniter-core/lib/igniter/core/memory/store.rb +115 -0
  340. data/packages/igniter-core/lib/igniter/core/memory/stores/in_memory.rb +136 -0
  341. data/packages/igniter-core/lib/igniter/core/memory/stores/sqlite.rb +286 -0
  342. data/packages/igniter-core/lib/igniter/core/memory.rb +80 -0
  343. data/packages/igniter-core/lib/igniter/core/metrics/collector.rb +131 -0
  344. data/packages/igniter-core/lib/igniter/core/metrics/prometheus_exporter.rb +104 -0
  345. data/packages/igniter-core/lib/igniter/core/metrics/snapshot.rb +8 -0
  346. data/packages/igniter-core/lib/igniter/core/metrics.rb +37 -0
  347. data/packages/igniter-core/lib/igniter/core/model/agent_interaction_contract.rb +172 -0
  348. data/packages/igniter-core/lib/igniter/core/model/agent_node.rb +86 -0
  349. data/packages/igniter-core/lib/igniter/core/model/aggregate_node.rb +34 -0
  350. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/branch_node.rb +37 -1
  351. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/collection_node.rb +3 -2
  352. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/compute_node.rb +13 -0
  353. data/packages/igniter-core/lib/igniter/core/model/remote_node.rb +91 -0
  354. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model.rb +2 -0
  355. data/packages/igniter-core/lib/igniter/core/node_cache.rb +231 -0
  356. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/property_testing.rb +8 -8
  357. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/provenance/builder.rb +30 -1
  358. data/packages/igniter-core/lib/igniter/core/runtime/agent_adapter.rb +41 -0
  359. data/packages/igniter-core/lib/igniter/core/runtime/agent_result_contract.rb +91 -0
  360. data/packages/igniter-core/lib/igniter/core/runtime/agent_route.rb +60 -0
  361. data/packages/igniter-core/lib/igniter/core/runtime/agent_route_resolver.rb +26 -0
  362. data/packages/igniter-core/lib/igniter/core/runtime/agent_session.rb +922 -0
  363. data/packages/igniter-core/lib/igniter/core/runtime/agent_session_query.rb +379 -0
  364. data/packages/igniter-core/lib/igniter/core/runtime/agent_transport.rb +30 -0
  365. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/cache.rb +6 -3
  366. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/deferred_result.rb +27 -1
  367. data/packages/igniter-core/lib/igniter/core/runtime/execution.rb +913 -0
  368. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/input_validator.rb +6 -2
  369. data/packages/igniter-core/lib/igniter/core/runtime/job_worker.rb +39 -0
  370. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/node_state.rb +4 -2
  371. data/packages/igniter-core/lib/igniter/core/runtime/orchestration_overview.rb +213 -0
  372. data/packages/igniter-core/lib/igniter/core/runtime/orchestration_runtime_state.rb +176 -0
  373. data/packages/igniter-core/lib/igniter/core/runtime/orchestration_transition_query.rb +208 -0
  374. data/packages/igniter-core/lib/igniter/core/runtime/planner.rb +301 -0
  375. data/packages/igniter-core/lib/igniter/core/runtime/proxy_agent_adapter.rb +124 -0
  376. data/packages/igniter-core/lib/igniter/core/runtime/remote_adapter.rb +26 -0
  377. data/packages/igniter-core/lib/igniter/core/runtime/resolver.rb +951 -0
  378. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/result.rb +2 -0
  379. data/packages/igniter-core/lib/igniter/core/runtime/stores/redis_store.rb +93 -0
  380. data/packages/igniter-core/lib/igniter/core/runtime/stores/sqlite_store.rb +155 -0
  381. data/packages/igniter-core/lib/igniter/core/runtime/stream_result.rb +171 -0
  382. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime.rb +15 -0
  383. data/packages/igniter-core/lib/igniter/core/temporal.rb +84 -0
  384. data/packages/igniter-core/lib/igniter/core/tool/discoverable.rb +151 -0
  385. data/packages/igniter-core/lib/igniter/core/tool.rb +56 -0
  386. data/{lib/igniter → packages/igniter-core/lib/igniter/core}/version.rb +1 -1
  387. data/packages/igniter-core/lib/igniter/core.rb +23 -0
  388. data/packages/igniter-core/lib/igniter-core.rb +3 -0
  389. data/packages/igniter-extensions/README.md +21 -0
  390. data/packages/igniter-extensions/lib/igniter/extensions/auditing.rb +3 -0
  391. data/packages/igniter-extensions/lib/igniter/extensions/capabilities.rb +39 -0
  392. data/packages/igniter-extensions/lib/igniter/extensions/content_addressing.rb +5 -0
  393. data/packages/igniter-extensions/lib/igniter/extensions/dataflow.rb +117 -0
  394. data/{lib → packages/igniter-extensions/lib}/igniter/extensions/differential.rb +1 -1
  395. data/{lib → packages/igniter-extensions/lib}/igniter/extensions/execution_report.rb +1 -1
  396. data/{lib → packages/igniter-extensions/lib}/igniter/extensions/incremental.rb +1 -1
  397. data/packages/igniter-extensions/lib/igniter/extensions/introspection.rb +3 -0
  398. data/packages/igniter-extensions/lib/igniter/extensions/invariants.rb +3 -0
  399. data/{lib → packages/igniter-extensions/lib}/igniter/extensions/provenance.rb +1 -1
  400. data/packages/igniter-extensions/lib/igniter/extensions/reactive.rb +3 -0
  401. data/{lib → packages/igniter-extensions/lib}/igniter/extensions/saga.rb +1 -1
  402. data/packages/igniter-extensions/lib/igniter/extensions.rb +8 -0
  403. data/packages/igniter-extensions/lib/igniter-extensions.rb +3 -0
  404. data/packages/igniter-frontend/README.md +224 -0
  405. data/packages/igniter-frontend/lib/igniter/frontend/app.rb +90 -0
  406. data/packages/igniter-frontend/lib/igniter/frontend/app_access.rb +36 -0
  407. data/packages/igniter-frontend/lib/igniter/frontend/arbre/component.rb +120 -0
  408. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/action_group.rb +53 -0
  409. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/badge.rb +91 -0
  410. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/boolean.rb +53 -0
  411. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/breadcrumbs.rb +71 -0
  412. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/card.rb +114 -0
  413. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/conversation_panel.rb +61 -0
  414. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/datetime.rb +42 -0
  415. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/display_value_support.rb +38 -0
  416. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/empty_state.rb +39 -0
  417. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/event_list.rb +44 -0
  418. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/filters.rb +183 -0
  419. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/indicator.rb +59 -0
  420. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/json_panel.rb +36 -0
  421. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/key_value_list.rb +40 -0
  422. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/loading_state.rb +43 -0
  423. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/metric_grid.rb +37 -0
  424. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/number.rb +53 -0
  425. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/page_header.rb +53 -0
  426. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/pagination.rb +143 -0
  427. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/panel.rb +67 -0
  428. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/percentage.rb +79 -0
  429. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/resource_list.rb +38 -0
  430. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/scenario_card.rb +48 -0
  431. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/shell_columns.rb +67 -0
  432. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/sidebar_shell.rb +106 -0
  433. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/table_with.rb +203 -0
  434. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/tabs.rb +147 -0
  435. data/packages/igniter-frontend/lib/igniter/frontend/arbre/components/viz.rb +185 -0
  436. data/packages/igniter-frontend/lib/igniter/frontend/arbre/page.rb +74 -0
  437. data/packages/igniter-frontend/lib/igniter/frontend/arbre/raw_text_node.rb +40 -0
  438. data/packages/igniter-frontend/lib/igniter/frontend/arbre/template_page.rb +243 -0
  439. data/packages/igniter-frontend/lib/igniter/frontend/arbre.rb +48 -0
  440. data/packages/igniter-frontend/lib/igniter/frontend/arbre_page.rb +7 -0
  441. data/packages/igniter-frontend/lib/igniter/frontend/assets.rb +101 -0
  442. data/packages/igniter-frontend/lib/igniter/frontend/builder.rb +124 -0
  443. data/packages/igniter-frontend/lib/igniter/frontend/component.rb +24 -0
  444. data/packages/igniter-frontend/lib/igniter/frontend/components.rb +7 -0
  445. data/packages/igniter-frontend/lib/igniter/frontend/context.rb +53 -0
  446. data/packages/igniter-frontend/lib/igniter/frontend/form_builder.rb +63 -0
  447. data/packages/igniter-frontend/lib/igniter/frontend/handler.rb +92 -0
  448. data/packages/igniter-frontend/lib/igniter/frontend/javascript.rb +353 -0
  449. data/packages/igniter-frontend/lib/igniter/frontend/page.rb +24 -0
  450. data/packages/igniter-frontend/lib/igniter/frontend/request.rb +61 -0
  451. data/packages/igniter-frontend/lib/igniter/frontend/response.rb +67 -0
  452. data/packages/igniter-frontend/lib/igniter/frontend/tailwind/realtime/adapters.rb +226 -0
  453. data/packages/igniter-frontend/lib/igniter/frontend/tailwind/realtime/presets.rb +147 -0
  454. data/packages/igniter-frontend/lib/igniter/frontend/tailwind/realtime.rb +259 -0
  455. data/packages/igniter-frontend/lib/igniter/frontend/tailwind/surfaces.rb +1074 -0
  456. data/packages/igniter-frontend/lib/igniter/frontend/tailwind/ui.rb +1438 -0
  457. data/packages/igniter-frontend/lib/igniter/frontend/tailwind.rb +180 -0
  458. data/packages/igniter-frontend/lib/igniter/frontend/version.rb +9 -0
  459. data/packages/igniter-frontend/lib/igniter/frontend.rb +35 -0
  460. data/packages/igniter-frontend/lib/igniter-frontend.rb +3 -0
  461. data/packages/igniter-rails/README.md +96 -0
  462. data/packages/igniter-rails/lib/igniter/plugins/rails/generators/contract/templates/contract.rb.tt +22 -0
  463. data/packages/igniter-rails/lib/igniter/plugins/rails/generators/install/templates/igniter.rb.tt +16 -0
  464. data/packages/igniter-rails/lib/igniter-rails.rb +3 -0
  465. data/packages/igniter-schema-rendering/README.md +27 -0
  466. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/page.rb +35 -0
  467. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/patcher.rb +47 -0
  468. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/renderer.rb +268 -0
  469. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/schema.rb +172 -0
  470. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/store.rb +53 -0
  471. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/submission_normalizer.rb +117 -0
  472. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/submission_processor.rb +91 -0
  473. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/submission_validator.rb +62 -0
  474. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering/version.rb +9 -0
  475. data/packages/igniter-schema-rendering/lib/igniter/schema_rendering.rb +20 -0
  476. data/packages/igniter-schema-rendering/lib/igniter-schema-rendering.rb +3 -0
  477. data/packages/igniter-sdk/README.md +25 -0
  478. data/packages/igniter-sdk/lib/igniter/sdk/channels/base.rb +84 -0
  479. data/packages/igniter-sdk/lib/igniter/sdk/channels/delivery_result.rb +61 -0
  480. data/packages/igniter-sdk/lib/igniter/sdk/channels/message.rb +101 -0
  481. data/packages/igniter-sdk/lib/igniter/sdk/channels/telegram.rb +161 -0
  482. data/packages/igniter-sdk/lib/igniter/sdk/channels/webhook.rb +213 -0
  483. data/packages/igniter-sdk/lib/igniter/sdk/channels.rb +17 -0
  484. data/packages/igniter-sdk/lib/igniter/sdk/data/store.rb +31 -0
  485. data/packages/igniter-sdk/lib/igniter/sdk/data/stores/file.rb +113 -0
  486. data/packages/igniter-sdk/lib/igniter/sdk/data/stores/in_memory.rb +63 -0
  487. data/packages/igniter-sdk/lib/igniter/sdk/data/stores/sqlite.rb +144 -0
  488. data/packages/igniter-sdk/lib/igniter/sdk/data.rb +34 -0
  489. data/packages/igniter-sdk/lib/igniter/sdk/tools/agent_bootstrap_tool.rb +151 -0
  490. data/packages/igniter-sdk/lib/igniter/sdk/tools/local_workflow_selector_tool.rb +269 -0
  491. data/packages/igniter-sdk/lib/igniter/sdk/tools/system_discovery_tool.rb +198 -0
  492. data/packages/igniter-sdk/lib/igniter/sdk/tools.rb +9 -0
  493. data/packages/igniter-sdk/lib/igniter/sdk.rb +86 -0
  494. data/packages/igniter-sdk/lib/igniter-sdk.rb +3 -0
  495. data/packages/igniter-server/README.md +9 -0
  496. data/packages/igniter-server/lib/igniter/server/agent_session_store.rb +98 -0
  497. data/packages/igniter-server/lib/igniter/server/agent_transport.rb +95 -0
  498. data/packages/igniter-server/lib/igniter/server/app_host.rb +3 -0
  499. data/packages/igniter-server/lib/igniter/server/client.rb +256 -0
  500. data/packages/igniter-server/lib/igniter/server/config.rb +70 -0
  501. data/packages/igniter-server/lib/igniter/server/handlers/agent_message_handler.rb +107 -0
  502. data/packages/igniter-server/lib/igniter/server/handlers/agent_session_handler.rb +125 -0
  503. data/{lib → packages/igniter-server/lib}/igniter/server/handlers/event_handler.rb +4 -0
  504. data/{lib → packages/igniter-server/lib}/igniter/server/handlers/execute_handler.rb +6 -0
  505. data/packages/igniter-server/lib/igniter/server/handlers/liveness_handler.rb +20 -0
  506. data/packages/igniter-server/lib/igniter/server/handlers/manifest_handler.rb +77 -0
  507. data/packages/igniter-server/lib/igniter/server/handlers/metrics_handler.rb +51 -0
  508. data/packages/igniter-server/lib/igniter/server/handlers/peers_handler.rb +136 -0
  509. data/packages/igniter-server/lib/igniter/server/handlers/readiness_handler.rb +47 -0
  510. data/packages/igniter-server/lib/igniter/server/http_server.rb +222 -0
  511. data/{lib → packages/igniter-server/lib}/igniter/server/rack_app.rb +27 -2
  512. data/packages/igniter-server/lib/igniter/server/remote_adapter.rb +27 -0
  513. data/packages/igniter-server/lib/igniter/server/router.rb +291 -0
  514. data/packages/igniter-server/lib/igniter/server/server_logger.rb +54 -0
  515. data/packages/igniter-server/lib/igniter/server.rb +130 -0
  516. data/packages/igniter-server/lib/igniter-server.rb +3 -0
  517. metadata +638 -168
  518. data/docs/API_V2.md +0 -537
  519. data/docs/ARCHITECTURE_V2.md +0 -317
  520. data/docs/BACKLOG.md +0 -166
  521. data/docs/BRANCHES_V1.md +0 -213
  522. data/docs/COLLECTIONS_V1.md +0 -303
  523. data/docs/DISTRIBUTED_CONTRACTS_V1.md +0 -493
  524. data/docs/EXECUTION_MODEL_V2.md +0 -324
  525. data/docs/IGNITER_CONCEPTS.md +0 -81
  526. data/docs/LLM_V1.md +0 -335
  527. data/docs/PATTERNS.md +0 -411
  528. data/docs/SERVER_V1.md +0 -313
  529. data/docs/STORE_ADAPTERS.md +0 -126
  530. data/lib/igniter/diagnostics.rb +0 -8
  531. data/lib/igniter/executor.rb +0 -74
  532. data/lib/igniter/extensions/introspection/plan_formatter.rb +0 -55
  533. data/lib/igniter/extensions/invariants.rb +0 -116
  534. data/lib/igniter/integrations/agents.rb +0 -18
  535. data/lib/igniter/integrations/llm/config.rb +0 -69
  536. data/lib/igniter/integrations/llm/executor.rb +0 -159
  537. data/lib/igniter/integrations/llm.rb +0 -59
  538. data/lib/igniter/model/remote_node.rb +0 -26
  539. data/lib/igniter/runtime/execution.rb +0 -398
  540. data/lib/igniter/runtime/job_worker.rb +0 -18
  541. data/lib/igniter/runtime/planner.rb +0 -126
  542. data/lib/igniter/runtime/resolver.rb +0 -520
  543. data/lib/igniter/runtime/stores/redis_store.rb +0 -56
  544. data/lib/igniter/server/client.rb +0 -123
  545. data/lib/igniter/server/config.rb +0 -27
  546. data/lib/igniter/server/http_server.rb +0 -109
  547. data/lib/igniter/server/router.rb +0 -75
  548. data/lib/igniter/server.rb +0 -67
  549. /data/{lib → packages/igniter-agents/lib}/igniter/agent/mailbox.rb +0 -0
  550. /data/{lib → packages/igniter-agents/lib}/igniter/agent/message.rb +0 -0
  551. /data/{lib → packages/igniter-agents/lib}/igniter/agent/state_holder.rb +0 -0
  552. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/graph_compiler.rb +0 -0
  553. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/type_resolver.rb +0 -0
  554. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validation_context.rb +0 -0
  555. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validator.rb +0 -0
  556. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validators/await_validator.rb +0 -0
  557. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validators/callable_validator.rb +0 -0
  558. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validators/outputs_validator.rb +0 -0
  559. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validators/type_compatibility_validator.rb +0 -0
  560. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/compiler/validators/uniqueness_validator.rb +0 -0
  561. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/diagnostics/auditing/report/console_formatter.rb +0 -0
  562. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/diagnostics/auditing/report/markdown_formatter.rb +0 -0
  563. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/diagnostics/introspection/formatters/mermaid_formatter.rb +0 -0
  564. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/diagnostics/introspection/formatters/text_tree_formatter.rb +0 -0
  565. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/differential/divergence.rb +0 -0
  566. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/differential/formatter.rb +0 -0
  567. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/differential/report.rb +0 -0
  568. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/differential/runner.rb +0 -0
  569. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/differential.rb +0 -0
  570. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/dsl/schema_builder.rb +0 -0
  571. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/dsl.rb +0 -0
  572. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/effect_registry.rb +0 -0
  573. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/events/bus.rb +0 -0
  574. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/events/event.rb +0 -0
  575. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/events.rb +0 -0
  576. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/execution_report/builder.rb +0 -0
  577. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/execution_report/formatter.rb +0 -0
  578. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/execution_report/node_entry.rb +0 -0
  579. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/execution_report/report.rb +0 -0
  580. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/execution_report.rb +0 -0
  581. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/executor_registry.rb +0 -0
  582. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/auditing/timeline.rb +0 -0
  583. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/auditing.rb +0 -0
  584. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/introspection.rb +0 -0
  585. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/reactive/engine.rb +0 -0
  586. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/reactive/matcher.rb +0 -0
  587. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/reactive/reaction.rb +0 -0
  588. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions/reactive.rb +0 -0
  589. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/extensions.rb +0 -0
  590. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/incremental/formatter.rb +0 -0
  591. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/incremental/result.rb +0 -0
  592. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/incremental/tracker.rb +0 -0
  593. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/invariant.rb +0 -0
  594. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/await_node.rb +0 -0
  595. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/composition_node.rb +0 -0
  596. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/effect_node.rb +0 -0
  597. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/graph.rb +0 -0
  598. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/input_node.rb +0 -0
  599. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/node.rb +0 -0
  600. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/model/output_node.rb +0 -0
  601. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/property_testing/formatter.rb +0 -0
  602. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/property_testing/generators.rb +0 -0
  603. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/property_testing/result.rb +0 -0
  604. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/property_testing/run.rb +0 -0
  605. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/property_testing/runner.rb +0 -0
  606. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/provenance/lineage.rb +0 -0
  607. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/provenance/node_trace.rb +0 -0
  608. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/provenance/text_formatter.rb +0 -0
  609. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/provenance.rb +0 -0
  610. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/collection_result.rb +0 -0
  611. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/invalidator.rb +0 -0
  612. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/runner_factory.rb +0 -0
  613. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/runners/inline_runner.rb +0 -0
  614. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/runners/store_runner.rb +0 -0
  615. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/runners/thread_pool_runner.rb +0 -0
  616. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/stores/active_record_store.rb +0 -0
  617. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/stores/file_store.rb +0 -0
  618. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/runtime/stores/memory_store.rb +0 -0
  619. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/saga/compensation.rb +0 -0
  620. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/saga/compensation_record.rb +0 -0
  621. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/saga/executor.rb +0 -0
  622. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/saga/formatter.rb +0 -0
  623. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/saga/result.rb +0 -0
  624. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/saga.rb +0 -0
  625. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/stream_loop.rb +0 -0
  626. /data/{lib/igniter → packages/igniter-core/lib/igniter/core}/type_system.rb +0 -0
  627. /data/{lib/igniter/integrations → packages/igniter-rails/lib/igniter/plugins}/rails/cable_adapter.rb +0 -0
  628. /data/{lib/igniter/integrations → packages/igniter-rails/lib/igniter/plugins}/rails/contract_job.rb +0 -0
  629. /data/{lib/igniter/integrations → packages/igniter-rails/lib/igniter/plugins}/rails/generators/contract/contract_generator.rb +0 -0
  630. /data/{lib/igniter/integrations → packages/igniter-rails/lib/igniter/plugins}/rails/generators/install/install_generator.rb +0 -0
  631. /data/{lib/igniter/integrations → packages/igniter-rails/lib/igniter/plugins}/rails/railtie.rb +0 -0
  632. /data/{lib/igniter/integrations → packages/igniter-rails/lib/igniter/plugins}/rails/webhook_concern.rb +0 -0
  633. /data/{lib/igniter/integrations → packages/igniter-rails/lib/igniter/plugins}/rails.rb +0 -0
  634. /data/{lib → packages/igniter-server/lib}/igniter/server/handlers/base.rb +0 -0
  635. /data/{lib → packages/igniter-server/lib}/igniter/server/handlers/contracts_handler.rb +0 -0
  636. /data/{lib → packages/igniter-server/lib}/igniter/server/handlers/health_handler.rb +0 -0
  637. /data/{lib → packages/igniter-server/lib}/igniter/server/handlers/status_handler.rb +0 -0
  638. /data/{lib → packages/igniter-server/lib}/igniter/server/registry.rb +0 -0
@@ -36,8 +36,26 @@ module Igniter
36
36
  if node.kind == :composition
37
37
  line += " contract=#{node.contract_class.name || 'AnonymousContract'}"
38
38
  end
39
+ if node.kind == :agent
40
+ interaction = node.interaction_contract
41
+ line += " via=#{node.agent_name.inspect}"
42
+ line += " message=#{node.message_name.inspect}"
43
+ line += " timeout=#{node.timeout}"
44
+ line += " mode=#{interaction.mode}"
45
+ line += " routing=#{interaction.routing_mode}"
46
+ line += " node=#{interaction.node_url.inspect}" if interaction.routing_mode == :static
47
+ line += " capability=#{interaction.capability.inspect}" if interaction.capability
48
+ line += " query=#{interaction.capability_query.inspect}" if interaction.capability_query
49
+ line += " pinned_to=#{interaction.pinned_to.inspect}" if interaction.pinned_to
50
+ line += " reply=#{interaction.reply_mode}"
51
+ line += " finalizer=#{interaction.finalizer.inspect}" if interaction.finalizer
52
+ line += " tool_loop_policy=#{interaction.tool_loop_policy.inspect}" if interaction.tool_loop_policy
53
+ line += " session_policy=#{interaction.session_policy.inspect}" if interaction.session_policy
54
+ end
39
55
  if node.kind == :branch
40
- cases = node.cases.map { |entry| "#{entry[:match].inspect}:#{entry[:contract].name || 'AnonymousContract'}" }
56
+ cases = node.cases.map do |entry|
57
+ "#{format_branch_case(entry)}:#{entry[:contract].name || 'AnonymousContract'}"
58
+ end
41
59
  line += " selector=#{node.selector_dependency}"
42
60
  line += " depends_on=#{node.context_dependencies.join(',')}" if node.context_dependencies.any?
43
61
  line += " cases=#{cases.join('|')}"
@@ -97,6 +115,19 @@ module Igniter
97
115
 
98
116
  "#{node.kind}: #{node.path}\\n#{node.callable_name}"
99
117
  end
118
+
119
+ def format_branch_case(entry)
120
+ case entry[:matcher]
121
+ when :eq
122
+ entry[:value].inspect
123
+ when :in
124
+ "in=#{entry[:value].inspect}"
125
+ when :matches
126
+ "matches=#{entry[:value].inspect}"
127
+ else
128
+ "#{entry[:matcher]}=#{entry[:value].inspect}"
129
+ end
130
+ end
100
131
  end
101
132
  end
102
133
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ module Extensions
5
+ module Introspection
6
+ class PlanFormatter
7
+ def self.to_text(execution, output_names = nil)
8
+ new(execution, output_names).to_text
9
+ end
10
+
11
+ def initialize(execution, output_names = nil)
12
+ @execution = execution
13
+ @plan = execution.plan(output_names)
14
+ end
15
+
16
+ def to_text
17
+ lines = []
18
+ lines << "Plan #{@execution.compiled_graph.name}"
19
+ lines << "Targets: #{format_list(@plan[:targets])}"
20
+ lines << "Ready: #{format_list(@plan[:ready])}"
21
+ lines << "Blocked: #{format_list(@plan[:blocked])}"
22
+ if @plan[:agent_profiles] && @plan[:agent_profiles][:total].positive?
23
+ lines << "Agents: total=#{@plan[:agent_profiles][:total]}, interactive=#{@plan[:agent_profiles][:interactive]}, manual=#{@plan[:agent_profiles][:manual]}, single_turn=#{@plan[:agent_profiles][:single_turn]}, streaming=#{@plan[:agent_profiles][:streaming]}, deferred=#{@plan[:agent_profiles][:deferred]}"
24
+ end
25
+ if @plan[:orchestration] && @plan[:orchestration][:total].positive?
26
+ lines << "Orchestration: attention_required=#{@plan[:orchestration][:attention_required]}, resumable=#{@plan[:orchestration][:resumable]}, interactive_sessions=#{@plan[:orchestration][:interactive_sessions]}, manual_sessions=#{@plan[:orchestration][:manual_sessions]}, single_turn_sessions=#{@plan[:orchestration][:single_turn_sessions]}, deferred_calls=#{@plan[:orchestration][:deferred_calls]}, single_reply_calls=#{@plan[:orchestration][:single_reply_calls]}, delivery_only=#{@plan[:orchestration][:delivery_only]}"
27
+ if @plan[:orchestration][:attention_nodes].any?
28
+ lines << "Attention Nodes: #{format_list(@plan[:orchestration][:attention_nodes])}"
29
+ end
30
+ if @plan[:orchestration][:actions].any?
31
+ lines << "Orchestration Actions: #{@plan[:orchestration][:actions].map { |action| "#{action[:node]}(#{action[:action]})" }.join(', ')}"
32
+ end
33
+ end
34
+ lines << "Nodes:"
35
+
36
+ @plan[:nodes].each_value do |entry|
37
+ lines << format_node(entry)
38
+ end
39
+
40
+ lines.join("\n")
41
+ end
42
+
43
+ private
44
+
45
+ def format_node(entry)
46
+ line = "- #{entry[:kind]} #{entry[:path]} status=#{entry[:status]}"
47
+ line += " ready=true" if entry[:ready]
48
+ line += " blocked=true" if entry[:blocked]
49
+ line += " waiting_on=#{format_list(entry[:waiting_on])}" if entry[:waiting_on].any?
50
+ if entry[:kind] == :agent
51
+ line += " via=#{entry[:via].inspect}"
52
+ line += " message=#{entry[:message].inspect}"
53
+ line += " mode=#{entry[:mode]}"
54
+ line += " reply=#{entry[:reply_mode]}"
55
+ line += " session_policy=#{entry[:session_policy]}" if entry[:session_policy]
56
+ line += " tool_loop_policy=#{entry[:tool_loop_policy]}" if entry[:tool_loop_policy]
57
+ line += " finalizer=#{entry[:finalizer].inspect}" if entry[:finalizer]
58
+ if entry[:orchestration]
59
+ line += " orchestration=#{entry[:orchestration][:interaction]}"
60
+ line += " guidance=#{entry[:orchestration][:guidance].inspect}"
61
+ line += " attention_required=true" if entry[:orchestration][:attention_required]
62
+ line += " resumable=true" if entry[:orchestration][:resumable]
63
+ line += " allows_continuation=true" if entry[:orchestration][:allows_continuation]
64
+ line += " requires_explicit_completion=true" if entry[:orchestration][:requires_explicit_completion]
65
+ line += " auto_finalization=#{entry[:orchestration][:auto_finalization]}"
66
+ end
67
+ end
68
+
69
+ dependency_summary = entry[:dependencies].map do |dependency|
70
+ "#{dependency[:name]}(#{dependency[:status]})"
71
+ end
72
+ line += " deps=#{dependency_summary.join(',')}" if dependency_summary.any?
73
+ line
74
+ end
75
+
76
+ def format_list(values)
77
+ array = Array(values)
78
+ return "none" if array.empty?
79
+
80
+ array.join(",")
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -73,6 +73,7 @@ module Igniter
73
73
  status: state.status,
74
74
  version: state.version,
75
75
  invalidated_by: invalidation_details(state),
76
+ details: state.details,
76
77
  value: serialize_value(state.value),
77
78
  error: state.error&.message
78
79
  }
@@ -91,6 +92,31 @@ module Igniter
91
92
 
92
93
  def serialize_value(value)
93
94
  case value
95
+ when Igniter::Runtime::StreamResult
96
+ {
97
+ type: :stream,
98
+ token: value.token,
99
+ payload: value.payload,
100
+ source_node: value.source_node,
101
+ waiting_on: value.waiting_on,
102
+ phase: value.phase,
103
+ events: value.events,
104
+ event_count: value.events.size,
105
+ status_count: value.status_events.size,
106
+ tool_call_count: value.tool_calls.size,
107
+ tool_result_count: value.tool_results.size,
108
+ tool_interaction_count: value.tool_interactions.size,
109
+ pending_tool_interaction_count: value.pending_tool_interactions.size,
110
+ completed_tool_interaction_count: value.completed_tool_interactions.size,
111
+ orphan_tool_interaction_count: value.orphan_tool_interactions.size,
112
+ tool_loop_status: value.tool_loop_status,
113
+ tool_loop_complete: value.tool_loop_complete?,
114
+ tool_loop_summary: value.tool_loop_summary,
115
+ tool_runtime: value.tool_runtime,
116
+ artifact_count: value.artifacts.size,
117
+ chunks: value.chunks,
118
+ chunk_count: value.chunks.size
119
+ }
94
120
  when Igniter::Runtime::DeferredResult
95
121
  {
96
122
  type: :deferred,
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../contract"
4
+ require_relative "../errors"
5
+ require_relative "../invariant"
6
+
7
+ module Igniter
8
+ module Extensions
9
+ # Patches Igniter::Contract with:
10
+ # - Class method: invariant(name) { |output:, **| condition }
11
+ # - Instance method: check_invariants -> Array<InvariantViolation>
12
+ # - Automatic post-execution check in resolve_all (raises InvariantError)
13
+ module Invariants
14
+ def self.included(base)
15
+ base.extend(ClassMethods)
16
+ base.prepend(InstanceMethods)
17
+ end
18
+
19
+ module ClassMethods
20
+ def invariant(name, &block)
21
+ @_invariants ||= {}
22
+ @_invariants[name.to_sym] = Igniter::Invariant.new(name, &block)
23
+ end
24
+
25
+ def invariants
26
+ @_invariants || {}
27
+ end
28
+ end
29
+
30
+ module InstanceMethods
31
+ def resolve_all(...)
32
+ result = super
33
+ validate_invariants! unless Thread.current[:igniter_skip_invariants]
34
+ result
35
+ end
36
+
37
+ def check_invariants
38
+ return [] if self.class.invariants.empty?
39
+
40
+ resolved = collect_output_values
41
+ self.class.invariants.values.filter_map { |inv| inv.check(resolved) }
42
+ end
43
+
44
+ private
45
+
46
+ def validate_invariants!
47
+ violations = check_invariants
48
+ return if violations.empty?
49
+
50
+ names = violations.map { |v| ":#{v.name}" }.join(", ")
51
+ raise Igniter::InvariantError.new(
52
+ "#{violations.size} invariant(s) violated: #{names}",
53
+ violations: violations,
54
+ context: { contract: self.class.name }
55
+ )
56
+ end
57
+
58
+ def collect_output_values
59
+ cache = execution.cache
60
+ execution.compiled_graph.outputs.each_with_object({}) do |output_node, acc|
61
+ state = cache.fetch(output_node.source_root)
62
+ acc[output_node.name] = state.value if state&.succeeded?
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ Igniter::Contract.include(Igniter::Extensions::Invariants)
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ # Mixin that enables stable cross-execution cache keys for objects used as
5
+ # compute node dependencies (e.g. ActiveRecord models).
6
+ #
7
+ # Include this module in any class whose instances are passed as node deps:
8
+ #
9
+ # class Trade < ApplicationRecord
10
+ # include Igniter::Fingerprint
11
+ # end
12
+ #
13
+ # The Rails Railtie includes this automatically in ApplicationRecord when
14
+ # the igniter-rails integration is loaded.
15
+ #
16
+ # == Custom fingerprints
17
+ #
18
+ # Override #igniter_fingerprint for non-AR objects or custom invalidation logic:
19
+ #
20
+ # class PricingConfig
21
+ # include Igniter::Fingerprint
22
+ #
23
+ # def igniter_fingerprint
24
+ # "PricingConfig:#{version}:#{market}"
25
+ # end
26
+ # end
27
+ module Fingerprint
28
+ # Returns a stable string that uniquely identifies this object's state.
29
+ # Changing the returned value invalidates any NodeCache entry that depends on it.
30
+ #
31
+ # Default: "{ClassName}:{id}:{updated_at_unix}" — works for any AR record.
32
+ # Returns "{ClassName}:{id}" for objects without updated_at.
33
+ def igniter_fingerprint
34
+ if respond_to?(:updated_at) && updated_at
35
+ "#{self.class.name}:#{id}:#{updated_at.to_i}"
36
+ elsif respond_to?(:id)
37
+ "#{self.class.name}:#{id}"
38
+ else
39
+ "#{self.class.name}:#{object_id}"
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "igniter"
4
- require "igniter/incremental/result"
5
- require "igniter/incremental/tracker"
6
- require "igniter/incremental/formatter"
3
+ require_relative "errors"
4
+ require_relative "incremental/result"
5
+ require_relative "incremental/tracker"
6
+ require_relative "incremental/formatter"
7
7
 
8
8
  module Igniter
9
9
  # Incremental computation for Igniter contracts.
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ module Memory
5
+ # Facade that pre-fills +agent_id+ on all Store operations.
6
+ #
7
+ # Callers interact with AgentMemory instead of the raw Store so they never
8
+ # have to pass +agent_id:+ explicitly. An optional +session_id+ groups
9
+ # episodes within a single interaction session.
10
+ #
11
+ # @example
12
+ # store = Igniter::Memory::Stores::InMemory.new
13
+ # memory = Igniter::Memory::AgentMemory.new(store: store, agent_id: "MyAgent:1")
14
+ #
15
+ # memory.record(type: :tool_call, content: "searched web for Ruby docs")
16
+ # memory.recall(query: "Ruby") # => [Episode, ...]
17
+ # memory.remember(:user_tz, "UTC")
18
+ # memory.facts # => { "user_tz" => Fact }
19
+ class AgentMemory
20
+ # @param store [Store] backing store implementation
21
+ # @param agent_id [String] identifier for this agent
22
+ # @param session_id [String, nil] optional session grouping key
23
+ def initialize(store:, agent_id:, session_id: nil)
24
+ @store = store
25
+ @agent_id = agent_id
26
+ @session_id = session_id
27
+ end
28
+
29
+ # Record a new episode.
30
+ #
31
+ # @param type [String, Symbol] category tag
32
+ # @param content [String] textual description of the event
33
+ # @param outcome [String, nil] result label, e.g. "success"/"failure"
34
+ # @param importance [Float] relevance weight 0.0–1.0
35
+ # @return [Episode]
36
+ def record(type:, content:, outcome: nil, importance: 0.5)
37
+ @store.record(
38
+ agent_id: @agent_id,
39
+ type: type,
40
+ content: content,
41
+ session_id: @session_id,
42
+ outcome: outcome,
43
+ importance: importance
44
+ )
45
+ end
46
+
47
+ # Keyword-search episodes for this agent.
48
+ #
49
+ # @param query [String, nil] search term; nil returns most recent
50
+ # @param limit [Integer] maximum results (default 10)
51
+ # @param type [String, Symbol, nil] optional type filter
52
+ # @return [Array<Episode>]
53
+ def recall(query: nil, limit: 10, type: nil)
54
+ @store.retrieve(agent_id: @agent_id, query: query, limit: limit, type: type)
55
+ end
56
+
57
+ # Store or update a named fact.
58
+ #
59
+ # @param key [String, Symbol] fact name
60
+ # @param value [Object] fact value
61
+ # @param confidence [Float] confidence score 0.0–1.0
62
+ # @return [Fact]
63
+ def remember(key, value, confidence: 1.0)
64
+ @store.store_fact(agent_id: @agent_id, key: key, value: value, confidence: confidence)
65
+ end
66
+
67
+ # Returns all stored facts for this agent.
68
+ #
69
+ # @return [Hash{String => Fact}]
70
+ def facts
71
+ @store.facts(agent_id: @agent_id)
72
+ end
73
+
74
+ # Returns recent episodes.
75
+ #
76
+ # @param last [Integer] maximum episodes to return
77
+ # @param type [String, Symbol, nil] optional type filter
78
+ # @return [Array<Episode>]
79
+ def recent(last: 20, type: nil)
80
+ @store.episodes(agent_id: @agent_id, last: last, type: type)
81
+ end
82
+
83
+ # Run a reflection cycle and record the result.
84
+ #
85
+ # @param current_system_prompt [String, nil] current prompt to compare against
86
+ # @return [ReflectionRecord]
87
+ def reflect(current_system_prompt: nil)
88
+ ReflectionCycle.new(store: @store).reflect(
89
+ agent_id: @agent_id,
90
+ current_system_prompt: current_system_prompt
91
+ )
92
+ end
93
+
94
+ # Check whether the agent should run a reflection cycle.
95
+ #
96
+ # Returns true when the recent failure rate exceeds the threshold.
97
+ #
98
+ # @return [Boolean]
99
+ def should_reflect?
100
+ ReflectionCycle.new(store: @store).should_reflect?(agent_id: @agent_id)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ module Memory
5
+ # Immutable value object representing a single recorded event in agent history.
6
+ #
7
+ # @!attribute [r] id
8
+ # @return [Integer] unique identifier within the store
9
+ # @!attribute [r] agent_id
10
+ # @return [String] identifier of the agent that recorded this episode
11
+ # @!attribute [r] session_id
12
+ # @return [String, nil] optional session grouping identifier
13
+ # @!attribute [r] ts
14
+ # @return [Integer] Unix timestamp of when the episode was recorded
15
+ # @!attribute [r] type
16
+ # @return [String, Symbol] category of the episode (e.g. :tool_call, :response)
17
+ # @!attribute [r] content
18
+ # @return [String] textual description of what happened
19
+ # @!attribute [r] outcome
20
+ # @return [String, nil] result descriptor, e.g. "success" or "failure"
21
+ # @!attribute [r] importance
22
+ # @return [Float] relevance weight in [0.0, 1.0], default 0.5
23
+ Episode = Struct.new(
24
+ :id, :agent_id, :session_id, :ts,
25
+ :type, :content, :outcome, :importance,
26
+ keyword_init: true
27
+ )
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ module Memory
5
+ # Immutable value object representing a persisted learned fact for an agent.
6
+ #
7
+ # Facts represent stable knowledge extracted from experience, keyed by a
8
+ # string name and associated with a confidence score.
9
+ #
10
+ # @!attribute [r] id
11
+ # @return [Integer] unique identifier within the store
12
+ # @!attribute [r] agent_id
13
+ # @return [String] identifier of the agent that owns this fact
14
+ # @!attribute [r] key
15
+ # @return [String] fact name (e.g. "user_timezone", "preferred_format")
16
+ # @!attribute [r] value
17
+ # @return [Object] the fact's value
18
+ # @!attribute [r] confidence
19
+ # @return [Float] confidence score in [0.0, 1.0], default 1.0
20
+ # @!attribute [r] updated_at
21
+ # @return [Integer] Unix timestamp of last upsert
22
+ Fact = Struct.new(
23
+ :id, :agent_id, :key, :value, :confidence, :updated_at,
24
+ keyword_init: true
25
+ )
26
+ end
27
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ module Memory
5
+ # Mixin that adds episodic memory capabilities to Igniter::Agent and
6
+ # Igniter::AI::Executor subclasses (or any class that includes it).
7
+ #
8
+ # Including +Memorable+ adds:
9
+ # * A class-level +enable_memory+ DSL method for opt-in activation
10
+ # * A +memory+ instance accessor returning a bound AgentMemory facade
11
+ # * Automatic agent_id derived from the class name and object_id
12
+ #
13
+ # Memory is NOT enabled by default — call +enable_memory+ in the class body.
14
+ #
15
+ # == Example
16
+ #
17
+ # class MyAgent < Igniter::Agent
18
+ # include Igniter::Memory::Memorable
19
+ #
20
+ # enable_memory store: Igniter::Memory::Stores::InMemory.new
21
+ #
22
+ # on :task do |state:, payload:, **|
23
+ # memory.record(type: :task, content: payload[:description])
24
+ # # ... handle task
25
+ # state
26
+ # end
27
+ # end
28
+ #
29
+ # == Inheritance
30
+ #
31
+ # Subclasses inherit +memory_enabled?+ and +memory_store+ from their parent.
32
+ # Each subclass can override them independently.
33
+ module Memorable
34
+ def self.included(base)
35
+ base.extend(ClassMethods)
36
+ base.instance_variable_set(:@memory_store, nil)
37
+ base.instance_variable_set(:@memory_enabled, false)
38
+ end
39
+
40
+ module ClassMethods
41
+ # Enable episodic memory for this class.
42
+ #
43
+ # @param store [Store, nil] backing store; falls back to Igniter::Memory.default_store
44
+ # @return [void]
45
+ def enable_memory(store: nil)
46
+ @memory_enabled = true
47
+ @memory_store = store || Igniter::Memory.default_store
48
+ end
49
+
50
+ # Returns the configured memory store, walking up the inheritance chain
51
+ # if none is set on this class.
52
+ #
53
+ # @return [Store]
54
+ def memory_store
55
+ @memory_store ||
56
+ (superclass.respond_to?(:memory_store) ? superclass.memory_store : Igniter::Memory.default_store)
57
+ end
58
+
59
+ # Returns whether memory has been enabled for this class or any ancestor.
60
+ #
61
+ # @return [Boolean]
62
+ def memory_enabled?
63
+ @memory_enabled ||
64
+ (superclass.respond_to?(:memory_enabled?) && superclass.memory_enabled?)
65
+ end
66
+ end
67
+
68
+ # Returns the AgentMemory facade bound to this instance.
69
+ #
70
+ # Lazily initialised on first access. The agent_id incorporates the class
71
+ # name and object_id to keep instances isolated.
72
+ #
73
+ # @return [AgentMemory]
74
+ def memory
75
+ @memory ||= AgentMemory.new(
76
+ store: self.class.memory_store,
77
+ agent_id: memory_agent_id,
78
+ session_id: respond_to?(:session_id, true) ? session_id : nil
79
+ )
80
+ end
81
+
82
+ private
83
+
84
+ def memory_agent_id
85
+ cls_name = self.class.name || "anonymous"
86
+ "#{cls_name}:#{object_id}"
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ module Memory
5
+ # Evaluates recent episodes and produces a ReflectionRecord.
6
+ #
7
+ # ReflectionCycle can operate in two modes:
8
+ #
9
+ # * **Rule-based** (default) — analyses failure rates using simple heuristics,
10
+ # requiring no LLM. Always available.
11
+ # * **LLM-assisted** — delegates to an LLM executor for a richer summary and
12
+ # an optional system-prompt patch. Enabled by passing an +llm:+ object.
13
+ #
14
+ # @example Rule-based reflection
15
+ # cycle = Igniter::Memory::ReflectionCycle.new(store: store)
16
+ # rec = cycle.reflect(agent_id: "MyAgent:1")
17
+ # # => ReflectionRecord (summary describes failure breakdown)
18
+ #
19
+ # @example With failure threshold check
20
+ # cycle.should_reflect?(agent_id: "MyAgent:1")
21
+ # # => true when recent failures >= DEFAULT_FAILURE_THRESHOLD
22
+ class ReflectionCycle
23
+ DEFAULT_FAILURE_THRESHOLD = 5
24
+ DEFAULT_WINDOW = 50
25
+
26
+ # @param store [Store] backing episode store
27
+ # @param failure_threshold [Integer] minimum failures to trigger reflection
28
+ # @param window [Integer] how many recent episodes to inspect
29
+ # @param llm [#call, nil] optional LLM executor for smart reflection
30
+ def initialize(store:, failure_threshold: DEFAULT_FAILURE_THRESHOLD,
31
+ window: DEFAULT_WINDOW, llm: nil)
32
+ @store = store
33
+ @failure_threshold = failure_threshold
34
+ @window = window
35
+ @llm = llm
36
+ end
37
+
38
+ # Check whether a reflection cycle should be triggered.
39
+ #
40
+ # Returns true when the number of recent "failure" outcomes meets or
41
+ # exceeds the configured +failure_threshold+.
42
+ #
43
+ # @param agent_id [String]
44
+ # @return [Boolean]
45
+ def should_reflect?(agent_id:)
46
+ recent = @store.episodes(agent_id: agent_id, last: @window)
47
+ failures = recent.count { |e| e.outcome == "failure" }
48
+ failures >= @failure_threshold
49
+ end
50
+
51
+ # Run a reflection cycle and persist the result.
52
+ #
53
+ # Analyses the most recent +window+ episodes and produces a
54
+ # ReflectionRecord with a summary (and optional system-prompt patch when
55
+ # an LLM is configured).
56
+ #
57
+ # @param agent_id [String]
58
+ # @param current_system_prompt [String, nil] passed to the LLM if available
59
+ # @return [ReflectionRecord]
60
+ def reflect(agent_id:, current_system_prompt: nil) # rubocop:disable Metrics/MethodLength
61
+ recent = @store.episodes(agent_id: agent_id, last: @window)
62
+ summary, patch = if @llm
63
+ smart_reflect(recent, current_system_prompt)
64
+ else
65
+ rule_based_reflect(recent)
66
+ end
67
+
68
+ @store.record_reflection(
69
+ agent_id: agent_id,
70
+ summary: summary,
71
+ system_patch: patch
72
+ )
73
+ end
74
+
75
+ private
76
+
77
+ def rule_based_reflect(episodes) # rubocop:disable Metrics/CyclomaticComplexity
78
+ failures = episodes.select { |e| e.outcome == "failure" }
79
+ failure_types = failures.group_by(&:type).transform_values(&:count)
80
+ top = failure_types.max_by { |_, v| v }
81
+
82
+ summary = "#{failures.size}/#{episodes.size} failures. " \
83
+ "Top failure type: #{top&.first || "none"} (#{top&.last || 0}\xc3\x97)"
84
+ [summary, nil]
85
+ end
86
+
87
+ def smart_reflect(episodes, current_system_prompt)
88
+ result = @llm.call(
89
+ episodes: episodes.map { |e| { type: e.type, content: e.content, outcome: e.outcome } },
90
+ current_system_prompt: current_system_prompt
91
+ )
92
+ [result[:summary], result[:system_patch]]
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Igniter
4
+ module Memory
5
+ # Immutable value object representing the output of a reflection cycle.
6
+ #
7
+ # A ReflectionRecord captures the summary and optional system-prompt patch
8
+ # produced by a ReflectionCycle run. It can be applied to update an agent's
9
+ # system prompt or used as an audit trail.
10
+ #
11
+ # @!attribute [r] id
12
+ # @return [Integer] unique identifier within the store
13
+ # @!attribute [r] agent_id
14
+ # @return [String] identifier of the agent this reflection belongs to
15
+ # @!attribute [r] ts
16
+ # @return [Integer] Unix timestamp when the reflection was recorded
17
+ # @!attribute [r] summary
18
+ # @return [String] human-readable summary of findings
19
+ # @!attribute [r] system_patch
20
+ # @return [String, nil] optional suggested replacement/patch for system prompt
21
+ # @!attribute [r] applied
22
+ # @return [Boolean] whether this reflection has been applied to the agent
23
+ ReflectionRecord = Struct.new(
24
+ :id, :agent_id, :ts, :summary, :system_patch, :applied,
25
+ keyword_init: true
26
+ )
27
+ end
28
+ end