insika 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -3
  3. data/README.md +1 -1
  4. data/bin/insika +22 -7
  5. data/docs/AGENTS.md +129 -5
  6. data/docs/CHANNELS.md +1 -1
  7. data/docs/CONTEXT.md +22 -5
  8. data/docs/DEPLOY.md +30 -10
  9. data/docs/EMBEDDING.md +11 -7
  10. data/docs/EVALS.md +1 -1
  11. data/docs/LOADTEST.md +3 -2
  12. data/docs/OBSERVABILITY.md +11 -2
  13. data/docs/REFINEMENT.md +6 -6
  14. data/docs/RELEASING.md +7 -7
  15. data/docs/RUNNING-LOCAL.md +1 -1
  16. data/docs/SECURITY.md +24 -11
  17. data/docs/SKILLS.md +189 -3
  18. data/docs/WHY.md +1 -1
  19. data/docs/WORKFLOWS.md +2 -2
  20. data/docs/index.md +1 -1
  21. data/docs/onboarding/start.md +1 -1
  22. data/lib/insika/agent_profile.rb +89 -22
  23. data/lib/insika/alert_dispatcher.rb +139 -0
  24. data/lib/insika/baseline_store.rb +2 -2
  25. data/lib/insika/budget_ledger.rb +135 -0
  26. data/lib/insika/channel_delivery.rb +14 -11
  27. data/lib/insika/channel_registry.rb +1 -1
  28. data/lib/insika/channels/relay.rb +3 -3
  29. data/lib/insika/channels/web/widget.js +2 -2
  30. data/lib/insika/channels/web.rb +7 -7
  31. data/lib/insika/channels/webhook.rb +58 -0
  32. data/lib/insika/chat_builder.rb +62 -13
  33. data/lib/insika/circuit_state.rb +114 -0
  34. data/lib/insika/coercion.rb +8 -0
  35. data/lib/insika/commands/agent_payload.rb +5 -3
  36. data/lib/insika/commands/create_agent.rb +2 -2
  37. data/lib/insika/commands/create_session.rb +1 -1
  38. data/lib/insika/commands/delete_llm_provider.rb +1 -1
  39. data/lib/insika/commands/delete_skill.rb +43 -0
  40. data/lib/insika/commands/gate_refinement.rb +12 -12
  41. data/lib/insika/commands/import_mcp_tools.rb +1 -1
  42. data/lib/insika/commands/import_tools.rb +4 -4
  43. data/lib/insika/commands/issue_tenant_token.rb +41 -0
  44. data/lib/insika/commands/resolve_refinement.rb +1 -1
  45. data/lib/insika/commands/revoke_token.rb +39 -0
  46. data/lib/insika/commands/rotate_tenant_token.rb +43 -0
  47. data/lib/insika/commands/run_refinement.rb +5 -5
  48. data/lib/insika/commands/send_message.rb +9 -9
  49. data/lib/insika/commands/set_agent_tools.rb +1 -1
  50. data/lib/insika/commands/set_skill_agents.rb +60 -19
  51. data/lib/insika/commands/trigger_workflow.rb +1 -1
  52. data/lib/insika/commands/update_agent.rb +1 -1
  53. data/lib/insika/commands/write_data_tool.rb +1 -1
  54. data/lib/insika/commands/write_golden.rb +1 -1
  55. data/lib/insika/commands/write_skill.rb +19 -9
  56. data/lib/insika/config_store.rb +8 -4
  57. data/lib/insika/context/builder.rb +2 -2
  58. data/lib/insika/context/fragment.rb +27 -3
  59. data/lib/insika/context/priority.rb +3 -2
  60. data/lib/insika/context/providers/memory.rb +1 -1
  61. data/lib/insika/context/providers/request.rb +1 -1
  62. data/lib/insika/context/providers/session.rb +17 -2
  63. data/lib/insika/context/providers/skill.rb +5 -1
  64. data/lib/insika/context/providers/skill_trigger.rb +128 -0
  65. data/lib/insika/context_trace_store.rb +92 -0
  66. data/lib/insika/delegation_store.rb +2 -2
  67. data/lib/insika/doctor.rb +250 -5
  68. data/lib/insika/dsl/runtime.rb +12 -9
  69. data/lib/insika/dsl/server_boot.rb +4 -3
  70. data/lib/insika/dsl/system.rb +1 -1
  71. data/lib/insika/dsl.rb +72 -15
  72. data/lib/insika/edge_limiter.rb +144 -6
  73. data/lib/insika/egress_guard.rb +3 -3
  74. data/lib/insika/env_schema.rb +13 -10
  75. data/lib/insika/errors.rb +61 -5
  76. data/lib/insika/evals/assertions.rb +12 -12
  77. data/lib/insika/evals/baseline.rb +3 -3
  78. data/lib/insika/evals/golden.rb +8 -8
  79. data/lib/insika/evals/judge.rb +7 -7
  80. data/lib/insika/evals/pairwise.rb +3 -3
  81. data/lib/insika/evals/report.rb +2 -2
  82. data/lib/insika/evals/runner.rb +6 -6
  83. data/lib/insika/evals/transport.rb +2 -2
  84. data/lib/insika/event_stream.rb +23 -5
  85. data/lib/insika/executor.rb +423 -108
  86. data/lib/insika/frontmatter.rb +1 -1
  87. data/lib/insika/golden_store.rb +2 -2
  88. data/lib/insika/http_client.rb +3 -3
  89. data/lib/insika/inbound_log.rb +1 -1
  90. data/lib/insika/llm_configurator.rb +3 -3
  91. data/lib/insika/loop_detector.rb +143 -0
  92. data/lib/insika/mcp_http_client.rb +4 -4
  93. data/lib/insika/mcp_tool_ingestor.rb +6 -6
  94. data/lib/insika/message_origin.rb +2 -2
  95. data/lib/insika/model_resolver.rb +1 -1
  96. data/lib/insika/model_selection.rb +5 -4
  97. data/lib/insika/onboarding.rb +2 -2
  98. data/lib/insika/outbox_store.rb +2 -2
  99. data/lib/insika/overlay_tool_registry.rb +3 -4
  100. data/lib/insika/pack.rb +3 -3
  101. data/lib/insika/pack_importer.rb +17 -15
  102. data/lib/insika/pending_action_store.rb +1 -1
  103. data/lib/insika/plugin/loader.rb +2 -2
  104. data/lib/insika/policy/policy.rb +1 -1
  105. data/lib/insika/profile_source.rb +12 -6
  106. data/lib/insika/provider_error_classifier.rb +160 -0
  107. data/lib/insika/queue_policy.rb +2 -2
  108. data/lib/insika/recovery.rb +47 -6
  109. data/lib/insika/refinement/candidate.rb +4 -4
  110. data/lib/insika/refinement/evidence_collector.rb +6 -6
  111. data/lib/insika/refinement/gate.rb +7 -7
  112. data/lib/insika/refinement/panel.rb +7 -7
  113. data/lib/insika/refinement/proposer.rb +9 -9
  114. data/lib/insika/refinement_store.rb +12 -12
  115. data/lib/insika/reliability.rb +185 -0
  116. data/lib/insika/safety/config.rb +2 -2
  117. data/lib/insika/safety/detectors.rb +5 -5
  118. data/lib/insika/safety/factory.rb +3 -3
  119. data/lib/insika/safety/input_guardrail.rb +19 -4
  120. data/lib/insika/safety/moderator.rb +19 -11
  121. data/lib/insika/safety/output_filter.rb +2 -2
  122. data/lib/insika/safety/output_validator.rb +2 -2
  123. data/lib/insika/safety/safe_responses.rb +1 -1
  124. data/lib/insika/sandbox/boundary.rb +2 -2
  125. data/lib/insika/sandbox.rb +1 -1
  126. data/lib/insika/server/app.rb +223 -51
  127. data/lib/insika/server/boot.rb +4 -4
  128. data/lib/insika/server/rack_app.rb +15 -7
  129. data/lib/insika/server/responses.rb +18 -8
  130. data/lib/insika/server/tenant_auth.rb +61 -0
  131. data/lib/insika/session_actor.rb +3 -3
  132. data/lib/insika/session_store.rb +1 -1
  133. data/lib/insika/settings_store.rb +5 -5
  134. data/lib/insika/shutdown.rb +4 -4
  135. data/lib/insika/skill_catalog.rb +127 -20
  136. data/lib/insika/skill_store.rb +70 -22
  137. data/lib/insika/steer_injector.rb +1 -1
  138. data/lib/insika/store.rb +1 -1
  139. data/lib/insika/studio/app.rb +183 -61
  140. data/lib/insika/studio/assets/dist/application.js +25 -24
  141. data/lib/insika/studio/forms.rb +13 -18
  142. data/lib/insika/studio/nav_icons.rb +1 -1
  143. data/lib/insika/studio/views/_message.erb +2 -2
  144. data/lib/insika/studio/views/agent_detail.erb +2 -2
  145. data/lib/insika/studio/views/agents.erb +1 -1
  146. data/lib/insika/studio/views/refinement.erb +4 -4
  147. data/lib/insika/studio/views/session.erb +78 -3
  148. data/lib/insika/studio/views/settings.erb +7 -12
  149. data/lib/insika/studio/views/skills.erb +67 -12
  150. data/lib/insika/subagent_graph.rb +3 -3
  151. data/lib/insika/task_actor.rb +3 -3
  152. data/lib/insika/task_store.rb +1 -1
  153. data/lib/insika/telemetry/pricing.rb +3 -3
  154. data/lib/insika/telemetry/recorder.rb +1 -1
  155. data/lib/insika/telemetry.rb +2 -2
  156. data/lib/insika/testing/store_contract.rb +27 -27
  157. data/lib/insika/tick.rb +122 -0
  158. data/lib/insika/token_store.rb +168 -0
  159. data/lib/insika/tool_assembly.rb +5 -5
  160. data/lib/insika/tool_definition.rb +8 -8
  161. data/lib/insika/tool_envelope.rb +1 -1
  162. data/lib/insika/tool_manifest.rb +6 -6
  163. data/lib/insika/tool_output_compressor.rb +100 -0
  164. data/lib/insika/tool_store.rb +1 -1
  165. data/lib/insika/tool_trace_store.rb +1 -1
  166. data/lib/insika/tools/concurrency.rb +2 -2
  167. data/lib/insika/tools/data_defined_tool.rb +4 -5
  168. data/lib/insika/tools/load_skill.rb +61 -3
  169. data/lib/insika/tools/stuck_signal.rb +44 -0
  170. data/lib/insika/tools/subagent.rb +4 -4
  171. data/lib/insika/tools/subagents.rb +1 -1
  172. data/lib/insika/turn_output.rb +2 -2
  173. data/lib/insika/turn_state.rb +17 -13
  174. data/lib/insika/turn_timing.rb +2 -2
  175. data/lib/insika/usage_ledger.rb +1 -1
  176. data/lib/insika/version.rb +1 -1
  177. data/lib/insika/wiring/graph.rb +77 -26
  178. data/lib/insika/workflow.rb +1 -1
  179. data/lib/insika/workflow_registry.rb +1 -1
  180. data/lib/insika.rb +32 -15
  181. metadata +19 -2
  182. data/lib/insika/server/admin_auth.rb +0 -29
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Insika
4
4
  module Wiring
5
- # SHARED composition core for both roots (§12 G4 / §11.2 B4): the minimal wiring
5
+ # SHARED composition core for both roots: the minimal wiring
6
6
  # (config/wiring.rb) and the concrete deployment (config/deployment.rb) were two
7
7
  # near-identical composition roots. The duplication — backend→stores, event
8
8
  # stream, registries + policy builtins, capability registry, hooks, the Executor,
@@ -28,7 +28,14 @@ module Insika
28
28
  db && !db.empty? ? Insika::Stores::SQLite.new(path: db) : Insika::Stores::Memory.new
29
29
  end
30
30
 
31
- # Phase 1 — the infra spine that is IDENTICAL across roots. `extra_policy_
31
+ # an integer tick knob from the env, nil when unset (the caller's
32
+ # default wins). Dual-read honors the deprecated HARNESS_* alias.
33
+ def tick_env(name, env = ENV)
34
+ value = Insika::EnvSchema.read(name, env)
35
+ value&.to_i
36
+ end
37
+
38
+ # the infra spine that is IDENTICAL across roots. `extra_policy_
32
39
  # builtins` covers the one real divergence (the minimal wiring also registers
33
40
  # :workflow_allowlist; the deployment does not expose workflows).
34
41
  def spine(backend:, extra_policy_builtins: {})
@@ -38,14 +45,17 @@ module Insika
38
45
  pending_action_store = Insika::PendingActionStore.new(store: backend)
39
46
  delegation_store = Insika::DelegationStore.new(store: backend)
40
47
  memory_store = Insika::MemoryStore.new(store: backend)
41
- # RFC-0011 §6.4/§6.5: the two durable halves of a Shape B channel — the
48
+ token_store = Insika::TokenStore.new(store: backend)
49
+ budget_ledger = Insika::BudgetLedger.new(store: backend)
50
+ circuit_state = Insika::CircuitState.new(store: backend)
51
+ # the two durable halves of a Shape B channel — the
42
52
  # replies still owed to a platform, and the retry window that stops a
43
53
  # redelivered webhook from becoming a second turn. Built unconditionally
44
54
  # (they are empty and free when no channel is registered) so a deployment
45
55
  # that turns a channel on later finds its state already durable.
46
56
  outbox_store = Insika::OutboxStore.new(store: backend)
47
57
  inbound_log = Insika::InboundLog.new(store: backend)
48
- # RFC-0013 phase A: refinement RUNS (reports over real traffic). Runtime data,
58
+ # refinement RUNS (reports over real traffic). Runtime data,
49
59
  # same backend as sessions/tasks — the collector and the command that write it
50
60
  # are the root's business (deployment-only, like the memory commands).
51
61
  refinement_store = Insika::RefinementStore.new(store: backend)
@@ -65,6 +75,7 @@ module Insika
65
75
  checkpoint_store: checkpoint_store, pending_action_store: pending_action_store,
66
76
  delegation_store: delegation_store,
67
77
  memory_store: memory_store, refinement_store: refinement_store,
78
+ token_store: token_store, budget_ledger: budget_ledger, circuit_state: circuit_state,
68
79
  outbox_store: outbox_store, inbound_log: inbound_log,
69
80
  code_tool_registry: code_tool_registry,
70
81
  workflow_registry: workflow_registry, policy_registry: policy_registry,
@@ -73,16 +84,16 @@ module Insika
73
84
  )
74
85
  end
75
86
 
76
- # Phase 2 — assemble the graph on top of a spine.
87
+ # assemble the graph on top of a spine.
77
88
  #
78
89
  # tool_registry: effective registry the Executor uses (plain REGISTRY at the
79
90
  # base; OverlayToolRegistry in the deployment).
80
91
  # guardrails: a Safety::Factory — its input_guardrail becomes the single
81
92
  # middleware and its output_validator the after-task hook, so
82
- # both wirings compose RFC-0009 identically.
93
+ # both wirings compose identically.
83
94
  # executor_extra: optional Executor kwargs a root adds (deployment passes
84
95
  # settings_store + tool_trace_store; the base passes none).
85
- # edge_limiter: optional EdgeLimiter (item 33 / §12 G7). It goes BEFORE
96
+ # edge_limiter: optional EdgeLimiter. It goes BEFORE
86
97
  # the InputGuardrail so a flood can't spend the LLM
87
98
  # moderator; nil = no edge (parity).
88
99
  def build(spine:, profiles:, tool_registry:, tool_catalog:, skill_catalog:,
@@ -98,7 +109,7 @@ module Insika
98
109
  policy_registry: spine.policy_registry, event_stream: spine.event_stream
99
110
  )
100
111
 
101
- # RFC-0011 §6.5. Always built: the registry starts empty, so `record` finds no
112
+ # Always built: the registry starts empty, so `record` finds no
102
113
  # channel and returns nil on every turn — the cost of wiring it is one nil
103
114
  # check per completed turn, and the alternative is a second wiring path that
104
115
  # only production exercises.
@@ -107,23 +118,49 @@ module Insika
107
118
  session_store: spine.session_store, event_stream: spine.event_stream
108
119
  )
109
120
 
110
- executor = Insika::Executor.new(
111
- context_builder: context_builder, policy_engine: policy_engine,
112
- middleware: middleware, hooks: spine.hooks,
113
- tool_registry: tool_registry, skill_catalog: skill_catalog, profiles: profiles,
114
- session_store: spine.session_store, task_store: spine.task_store,
115
- checkpoint_store: spine.checkpoint_store, event_stream: spine.event_stream,
116
- workflow_registry: spine.workflow_registry, pending_action_store: spine.pending_action_store,
117
- capability_registry: spine.capability_registry, tool_catalog: tool_catalog,
118
- memory_store: spine.memory_store,
119
- content_filter_factory: guardrails.content_filter_factory, # RFC-0009: stream redaction
120
- delegation_store: spine.delegation_store, # RFC-0010 Fase 2: async delegation durability
121
- channel_delivery: channel_delivery, # RFC-0011 §6.5: out-of-band reply delivery
122
- **executor_extra
123
- )
121
+ # WS3 provider reliability (retries/backoff/fallback/breaker) is ALWAYS wired —
122
+ # the profile's `reliability` data gates it, so the bare wiring is unchanged.
123
+ reliability = Insika::Reliability.new(circuit_store: spine.circuit_state,
124
+ event_stream: spine.event_stream)
125
+ executor = Insika::Executor.new(
126
+ context_builder: context_builder, policy_engine: policy_engine,
127
+ middleware: middleware, hooks: spine.hooks,
128
+ tool_registry: tool_registry, skill_catalog: skill_catalog, profiles: profiles,
129
+ session_store: spine.session_store, task_store: spine.task_store,
130
+ checkpoint_store: spine.checkpoint_store, event_stream: spine.event_stream,
131
+ workflow_registry: spine.workflow_registry, pending_action_store: spine.pending_action_store,
132
+ capability_registry: spine.capability_registry, tool_catalog: tool_catalog,
133
+ memory_store: spine.memory_store,
134
+ content_filter_factory: guardrails.content_filter_factory, # stream redaction
135
+ delegation_store: spine.delegation_store, # async delegation durability
136
+ channel_delivery: channel_delivery, # out-of-band reply delivery
137
+ reliability: reliability, # WS3: retries/fallback/breaker (data-gated)
138
+ **executor_extra
139
+ )
124
140
 
125
141
  bus = build_core_bus(spine: spine, profiles: profiles, executor: executor)
126
142
 
143
+ # the periodic tick (outbox drain + stale recovery sweep). Built
144
+ # here, after the bus, because its recovery half dispatches resume_task
145
+ # through it; handed to the Executor, which starts it as a child of the
146
+ # turn supervisor in serving mode. `INSIKA_TICK_INTERVAL=0` disables.
147
+ executor.tick = Insika::Tick.new(
148
+ store: spine.backend, channel_delivery: channel_delivery,
149
+ recovery: Insika::Recovery.new(
150
+ task_store: spine.task_store, checkpoint_store: spine.checkpoint_store, command_bus: bus
151
+ ),
152
+ interval: tick_env("INSIKA_TICK_INTERVAL") || Insika::Tick::DEFAULT_INTERVAL,
153
+ stale_after: tick_env("INSIKA_TICK_STALE_AFTER") || Insika::Tick::DEFAULT_STALE_AFTER
154
+ )
155
+ # WS6 operator alerts: answers budget_warning / breaker_open /
156
+ # delivery_failed per agent (`alerts.webhook`) via the outbox+claim
157
+ # pipeline. Always wired — the per-agent data gates it (parity).
158
+ executor.alert_dispatcher = Insika::AlertDispatcher.new(
159
+ event_stream: spine.event_stream, outbox: spine.outbox_store,
160
+ channels: spine.channel_registry, profiles: profiles,
161
+ task_store: spine.task_store, http: Insika::HttpClient.new
162
+ )
163
+
127
164
  Graph::Result.new(
128
165
  backend: spine.backend, event_stream: spine.event_stream,
129
166
  session_store: spine.session_store, task_store: spine.task_store,
@@ -131,6 +168,8 @@ module Insika
131
168
  delegation_store: spine.delegation_store,
132
169
  memory_store: spine.memory_store, refinement_store: spine.refinement_store,
133
170
  outbox_store: spine.outbox_store, inbound_log: spine.inbound_log,
171
+ token_store: spine.token_store, budget_ledger: spine.budget_ledger,
172
+ circuit_state: spine.circuit_state,
134
173
  channel_registry: spine.channel_registry, channel_delivery: channel_delivery,
135
174
  code_tool_registry: spine.code_tool_registry,
136
175
  tool_registry: tool_registry, workflow_registry: spine.workflow_registry,
@@ -144,7 +183,7 @@ module Insika
144
183
 
145
184
  # The CORE command surface every root needs — turn essentials + the operator
146
185
  # controls (pause/approve) the Studio dispatches. Registering pause_task/
147
- # approve_action HERE is the crux of B4: it retires the config.ru:28-34 patch.
186
+ # approve_action HERE is the crux of: it retires the config.ru:28-34 patch.
148
187
  def build_core_bus(spine:, profiles:, executor:)
149
188
  bus = Insika::CommandBus.new
150
189
  bus.register(:create_session,
@@ -163,6 +202,18 @@ module Insika
163
202
  bus.register(:resume_task,
164
203
  Insika::Commands::ResumeTask.new(profiles: profiles, task_store: spine.task_store,
165
204
  checkpoint_store: spine.checkpoint_store, executor: executor))
205
+ # WS1 multi-tenant credentials: per-tenant + operator tokens, stored as
206
+ # hashes. Operator-only BY CONSTRUCTION — the edge refuses a tenant
207
+ # principal on POST /v1/commands, and the handlers re-check meta.
208
+ bus.register(:issue_tenant_token,
209
+ Insika::Commands::IssueTenantToken.new(token_store: spine.token_store,
210
+ event_stream: spine.event_stream))
211
+ bus.register(:revoke_token,
212
+ Insika::Commands::RevokeToken.new(token_store: spine.token_store,
213
+ event_stream: spine.event_stream))
214
+ bus.register(:rotate_tenant_token,
215
+ Insika::Commands::RotateTenantToken.new(token_store: spine.token_store,
216
+ event_stream: spine.event_stream))
166
217
  bus
167
218
  end
168
219
 
@@ -171,7 +222,7 @@ module Insika
171
222
  Spine = Struct.new(
172
223
  :backend, :event_stream, :session_store, :task_store, :checkpoint_store,
173
224
  :pending_action_store, :delegation_store, :memory_store, :refinement_store,
174
- :outbox_store, :inbound_log, :code_tool_registry,
225
+ :token_store, :budget_ledger, :circuit_state, :outbox_store, :inbound_log, :code_tool_registry,
175
226
  :workflow_registry, :policy_registry, :capability_registry, :hooks,
176
227
  :channel_registry, keyword_init: true
177
228
  )
@@ -182,8 +233,8 @@ module Insika
182
233
  Result = Struct.new(
183
234
  :backend, :event_stream,
184
235
  :session_store, :task_store, :checkpoint_store, :pending_action_store, :delegation_store,
185
- :memory_store, :refinement_store, :outbox_store, :inbound_log,
186
- :channel_registry, :channel_delivery,
236
+ :memory_store, :refinement_store, :outbox_store, :inbound_log, :token_store,
237
+ :budget_ledger, :circuit_state, :channel_registry, :channel_delivery,
187
238
  :code_tool_registry, :tool_registry, :workflow_registry, :policy_registry, :capability_registry,
188
239
  :tool_catalog, :skill_catalog, :prompt_catalog,
189
240
  :hooks, :guardrails, :middleware,
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Insika
4
- # Workflow surface (item 22 / COMPETITIVE-ANALYSIS §4.4). A workflow is a Ruby
4
+ # Workflow surface (COMPETITIVE-ANALYSIS). A workflow is a Ruby
5
5
  # callable orchestrating RubyLLM Agents/Workflows FROM WITHIN (RubyLLM First);
6
6
  # its durable RUN is a Task (checkpointed, recoverable — stronger than Flue's
7
7
  # at-most-once run record). This module adds the EXPOSED surface the consumer
@@ -8,7 +8,7 @@ module Insika
8
8
  # checkpoint at the end. Nothing is validated at registration (the callable may come
9
9
  # via a factory block). Consumed by the TriggerWorkflow handler.
10
10
  #
11
- # Item 22 / §4.4 — the EXPOSED surface: a registration may carry `input_schema:` /
11
+ # — the EXPOSED surface: a registration may carry `input_schema:` /
12
12
  # `output_schema:` (a JSON Schema Hash or any dry-schema-compatible validator) and a
13
13
  # `description:` in its metadata. `definition` bundles them with the factory into a
14
14
  # Workflow::Definition (schemas resolved, factory left lazy); `catalog` is the
data/lib/insika.rb CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  require_relative "insika/version"
4
4
  require_relative "insika/errors"
5
+ require_relative "insika/provider_error_classifier"
6
+ require_relative "insika/token_store"
7
+ require_relative "insika/budget_ledger"
8
+ require_relative "insika/circuit_state"
9
+ require_relative "insika/reliability"
10
+ require_relative "insika/alert_dispatcher"
11
+ require_relative "insika/channels/webhook"
5
12
  require_relative "insika/coercion"
6
13
  require_relative "insika/message_origin"
7
14
  require_relative "insika/env_schema"
@@ -20,12 +27,14 @@ require_relative "insika/checkpoint"
20
27
  require_relative "insika/command"
21
28
  require_relative "insika/hooks"
22
29
  require_relative "insika/middleware"
23
- # Production edge (item 33 / §12 G7): windowed counters + the rate-limit/cost
30
+ # Production edge: windowed counters + the rate-limit/cost
24
31
  # Middleware. Both inert until configured (nil/0 = off).
25
32
  require_relative "insika/usage_ledger"
33
+ require_relative "insika/budget_ledger"
26
34
  require_relative "insika/edge_limiter"
27
- # Content safety / guardrails (RFC-0009). detectors.rb is self-contained (the eval
28
- # requires it directly, D4); the rest hang off Middleware/hooks seams. No ruby_llm
35
+ require_relative "insika/tool_output_compressor"
36
+ # Content safety / guardrails. detectors.rb is self-contained (the eval
37
+ # requires it directly); the rest hang off Middleware/hooks seams. No ruby_llm
29
38
  # at load-time — Factory requires the gem lazily, like the Executor's create_chat.
30
39
  require_relative "insika/safety/detectors"
31
40
  require_relative "insika/safety/safe_responses"
@@ -43,6 +52,7 @@ require_relative "insika/context/builder"
43
52
  require_relative "insika/context/providers/request"
44
53
  require_relative "insika/context/providers/prompt"
45
54
  require_relative "insika/context/providers/skill"
55
+ require_relative "insika/context/providers/skill_trigger"
46
56
  require_relative "insika/context/providers/tool_search"
47
57
  require_relative "insika/context/providers/memory"
48
58
  require_relative "insika/context/providers/session"
@@ -65,7 +75,7 @@ require_relative "insika/task_store"
65
75
  require_relative "insika/checkpoint_store"
66
76
  require_relative "insika/pending_action_store"
67
77
  require_relative "insika/delegation_store"
68
- # Channels (RFC-0011): the outbound record + the inbound retry window. Both are
78
+ # Channels: the outbound record + the inbound retry window. Both are
69
79
  # plain stores; the channel objects themselves come after the HTTP client.
70
80
  require_relative "insika/outbox_store"
71
81
  require_relative "insika/inbound_log"
@@ -77,7 +87,8 @@ require_relative "insika/skill_store"
77
87
  require_relative "insika/secret_masking"
78
88
  require_relative "insika/tool_store"
79
89
  require_relative "insika/tool_trace_store"
80
- # Refinement (RFC-0013 phase A): the run record + the evidence half of the loop.
90
+ require_relative "insika/context_trace_store"
91
+ # Refinement: the run record + the evidence half of the loop.
81
92
  # Reads sessions/tasks/traces above; requires Safety::Detectors (loaded earlier) for
82
93
  # the PII redaction of the snippets it puts in a report.
83
94
  require_relative "insika/refinement_store"
@@ -92,7 +103,7 @@ require_relative "insika/egress_guard"
92
103
  require_relative "insika/schema_guard"
93
104
  require_relative "insika/sandbox"
94
105
  require_relative "insika/http_client"
95
- # Channels (RFC-0011 §4/§6): the registry, the bundled relay adapter and the
106
+ # Channels: the registry, the bundled relay adapter and the
96
107
  # out-of-band dispatcher. After http_client and egress_guard — the relay POSTs
97
108
  # through both — and after registry.rb, which ChannelRegistry extends.
98
109
  require_relative "insika/channel_registry"
@@ -103,11 +114,11 @@ require_relative "insika/overlay_tool_registry"
103
114
  require_relative "insika/settings_store"
104
115
  require_relative "insika/llm_provider_store"
105
116
  require_relative "insika/llm_configurator"
106
- # LLM-first onboarding surface (item 20 / §5.6): serves start.md + models.json + the
117
+ # LLM-first onboarding surface: serves start.md + models.json + the
107
118
  # public docs. Reads the settings/provider stores above at call-time (order is free).
108
119
  require_relative "insika/onboarding"
109
- # Evals (RFC-0008) — the quality harness, moved under lib/ so the engine can call it
110
- # (the RFC-0013 refinement gate scores a candidate agent with the SAME judge the CLI
120
+ # Evals — the quality harness, moved under lib/ so the engine can call it
121
+ # (the refinement gate scores a candidate agent with the SAME judge the CLI
111
122
  # uses; a second copy would be the worst outcome). It stays a CLIENT of the engine:
112
123
  # HttpTransport talks to a running deployment, nothing here reads a store. Pure Ruby +
113
124
  # stdlib; the judge's provider call is injected, so no ruby_llm at load time.
@@ -119,14 +130,14 @@ require_relative "insika/evals/runner"
119
130
  require_relative "insika/evals/report"
120
131
  require_relative "insika/evals/baseline"
121
132
  require_relative "insika/evals/transport"
122
- # Authored eval cases (RFC-0013 §3.7): the corpus becomes editable without a
133
+ # Authored eval cases: the corpus becomes editable without a
123
134
  # checkout. Requires the loader above (it is the one validator).
124
135
  require_relative "insika/golden_store"
125
136
  require_relative "insika/baseline_store"
126
- # RFC-0013 §3.5: scores a candidate by REPLAYING it. After evals (the runner and
137
+ # scores a candidate by REPLAYING it. After evals (the runner and
127
138
  # the baseline comparison) and after the stores it clones an agent through.
128
139
  require_relative "insika/refinement/gate"
129
- # RFC-0013 §3.9 (phase D): the proposer PANEL and the run's token budget. Needs the
140
+ # the proposer PANEL and the run's token budget. Needs the
130
141
  # candidate format and the gate's Report shape, so it loads after both.
131
142
  require_relative "insika/refinement/panel"
132
143
  require_relative "insika/mcp_store"
@@ -151,6 +162,7 @@ require_relative "insika/commands/write_agent_file"
151
162
  require_relative "insika/commands/delete_agent_file"
152
163
  require_relative "insika/commands/restore_agent_file"
153
164
  require_relative "insika/commands/write_skill"
165
+ require_relative "insika/commands/delete_skill"
154
166
  require_relative "insika/commands/set_skill_agents"
155
167
  require_relative "insika/commands/memory_put_fact"
156
168
  require_relative "insika/commands/memory_forget_fact"
@@ -162,6 +174,9 @@ require_relative "insika/commands/write_golden"
162
174
  require_relative "insika/commands/update_settings"
163
175
  require_relative "insika/commands/upsert_llm_provider"
164
176
  require_relative "insika/commands/delete_llm_provider"
177
+ require_relative "insika/commands/issue_tenant_token"
178
+ require_relative "insika/commands/revoke_token"
179
+ require_relative "insika/commands/rotate_tenant_token"
165
180
  require_relative "insika/commands/upsert_mcp"
166
181
  require_relative "insika/commands/delete_mcp"
167
182
  require_relative "insika/commands/write_system_file"
@@ -179,6 +194,7 @@ require_relative "insika/session_actor"
179
194
  require_relative "insika/skill_catalog"
180
195
  require_relative "insika/tool_catalog"
181
196
  require_relative "insika/steer_injector"
197
+ require_relative "insika/loop_detector"
182
198
  require_relative "insika/turn_output"
183
199
  require_relative "insika/turn_state"
184
200
  require_relative "insika/turn_timing"
@@ -188,19 +204,20 @@ require_relative "insika/tool_assembly"
188
204
  require_relative "insika/chat_builder"
189
205
  require_relative "insika/executor"
190
206
  require_relative "insika/shutdown"
207
+ require_relative "insika/tick"
191
208
  require_relative "insika/pack"
192
209
  require_relative "insika/pack_importer"
193
210
  require_relative "insika/telemetry"
194
- # Strict config + diagnosis (item 23 / §8.1). Doctor reads the config stores above;
211
+ # Strict config + diagnosis. Doctor reads the config stores above;
195
212
  # EnvSchema (required at the top) is its env layer.
196
213
  require_relative "insika/doctor"
197
214
  # Shared composition core for both roots (config/wiring.rb + config/deployment.rb).
198
215
  # Only references the classes above at call-time, so require order is unconstrained.
199
216
  require_relative "insika/wiring/graph"
200
- # Public Ruby DSL (item 36): Insika.agent { … }. The Builder is gem-free (it only
217
+ # Public Ruby DSL: Insika.agent { … }. The Builder is gem-free (it only
201
218
  # generates a Pack); the runtime (chat/serve) is required lazily by Definition, so
202
219
  # `require "insika"` stays free of ruby_llm and the HTTP server.
203
220
  require_relative "insika/dsl"
204
221
  # Do NOT require "insika/tools/load_skill" here: it does `require "ruby_llm"` at
205
222
  # the top (inherits from RubyLLM::Tool) and would pull the gem in at load-time. The
206
- # Executor loads it lazily inside create_chat (D9).
223
+ # Executor loads it lazily inside create_chat.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: insika
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guilherme Lages Santos
@@ -179,8 +179,10 @@ files:
179
179
  - lib/insika.rb
180
180
  - lib/insika/agent_file_store.rb
181
181
  - lib/insika/agent_profile.rb
182
+ - lib/insika/alert_dispatcher.rb
182
183
  - lib/insika/allowlist.rb
183
184
  - lib/insika/baseline_store.rb
185
+ - lib/insika/budget_ledger.rb
184
186
  - lib/insika/capability/resolved_tool.rb
185
187
  - lib/insika/capability_registry.rb
186
188
  - lib/insika/channel_delivery.rb
@@ -188,9 +190,11 @@ files:
188
190
  - lib/insika/channels/relay.rb
189
191
  - lib/insika/channels/web.rb
190
192
  - lib/insika/channels/web/widget.js
193
+ - lib/insika/channels/webhook.rb
191
194
  - lib/insika/chat_builder.rb
192
195
  - lib/insika/checkpoint.rb
193
196
  - lib/insika/checkpoint_store.rb
197
+ - lib/insika/circuit_state.rb
194
198
  - lib/insika/coercion.rb
195
199
  - lib/insika/command.rb
196
200
  - lib/insika/command_bus.rb
@@ -204,10 +208,12 @@ files:
204
208
  - lib/insika/commands/delete_data_tool.rb
205
209
  - lib/insika/commands/delete_llm_provider.rb
206
210
  - lib/insika/commands/delete_mcp.rb
211
+ - lib/insika/commands/delete_skill.rb
207
212
  - lib/insika/commands/delete_system_file.rb
208
213
  - lib/insika/commands/gate_refinement.rb
209
214
  - lib/insika/commands/import_mcp_tools.rb
210
215
  - lib/insika/commands/import_tools.rb
216
+ - lib/insika/commands/issue_tenant_token.rb
211
217
  - lib/insika/commands/memory_add_note.rb
212
218
  - lib/insika/commands/memory_forget_fact.rb
213
219
  - lib/insika/commands/memory_put_fact.rb
@@ -217,6 +223,8 @@ files:
217
223
  - lib/insika/commands/restore_data_tool.rb
218
224
  - lib/insika/commands/restore_system_file.rb
219
225
  - lib/insika/commands/resume_task.rb
226
+ - lib/insika/commands/revoke_token.rb
227
+ - lib/insika/commands/rotate_tenant_token.rb
220
228
  - lib/insika/commands/run_refinement.rb
221
229
  - lib/insika/commands/send_message.rb
222
230
  - lib/insika/commands/set_agent_tools.rb
@@ -242,7 +250,9 @@ files:
242
250
  - lib/insika/context/providers/request.rb
243
251
  - lib/insika/context/providers/session.rb
244
252
  - lib/insika/context/providers/skill.rb
253
+ - lib/insika/context/providers/skill_trigger.rb
245
254
  - lib/insika/context/providers/tool_search.rb
255
+ - lib/insika/context_trace_store.rb
246
256
  - lib/insika/delegation_store.rb
247
257
  - lib/insika/doctor.rb
248
258
  - lib/insika/dsl.rb
@@ -273,6 +283,7 @@ files:
273
283
  - lib/insika/inbound_log.rb
274
284
  - lib/insika/llm_configurator.rb
275
285
  - lib/insika/llm_provider_store.rb
286
+ - lib/insika/loop_detector.rb
276
287
  - lib/insika/mcp_http_client.rb
277
288
  - lib/insika/mcp_store.rb
278
289
  - lib/insika/mcp_tool_ingestor.rb
@@ -295,6 +306,7 @@ files:
295
306
  - lib/insika/policy_registry.rb
296
307
  - lib/insika/profile_source.rb
297
308
  - lib/insika/prompt_catalog.rb
309
+ - lib/insika/provider_error_classifier.rb
298
310
  - lib/insika/queue_policy.rb
299
311
  - lib/insika/recovery.rb
300
312
  - lib/insika/refinement/candidate.rb
@@ -304,6 +316,7 @@ files:
304
316
  - lib/insika/refinement/proposer.rb
305
317
  - lib/insika/refinement_store.rb
306
318
  - lib/insika/registry.rb
319
+ - lib/insika/reliability.rb
307
320
  - lib/insika/safety/config.rb
308
321
  - lib/insika/safety/detectors.rb
309
322
  - lib/insika/safety/factory.rb
@@ -328,12 +341,12 @@ files:
328
341
  - lib/insika/server/a2a/protocol.rb
329
342
  - lib/insika/server/a2a/remotes.rb
330
343
  - lib/insika/server/a2a/task_projection.rb
331
- - lib/insika/server/admin_auth.rb
332
344
  - lib/insika/server/app.rb
333
345
  - lib/insika/server/boot.rb
334
346
  - lib/insika/server/rack_app.rb
335
347
  - lib/insika/server/responses.rb
336
348
  - lib/insika/server/sse_body.rb
349
+ - lib/insika/server/tenant_auth.rb
337
350
  - lib/insika/session_actor.rb
338
351
  - lib/insika/session_store.rb
339
352
  - lib/insika/settings_store.rb
@@ -378,12 +391,15 @@ files:
378
391
  - lib/insika/telemetry/pricing.rb
379
392
  - lib/insika/telemetry/recorder.rb
380
393
  - lib/insika/testing/store_contract.rb
394
+ - lib/insika/tick.rb
381
395
  - lib/insika/token_estimator.rb
396
+ - lib/insika/token_store.rb
382
397
  - lib/insika/tool_assembly.rb
383
398
  - lib/insika/tool_catalog.rb
384
399
  - lib/insika/tool_definition.rb
385
400
  - lib/insika/tool_envelope.rb
386
401
  - lib/insika/tool_manifest.rb
402
+ - lib/insika/tool_output_compressor.rb
387
403
  - lib/insika/tool_registry.rb
388
404
  - lib/insika/tool_store.rb
389
405
  - lib/insika/tool_trace_store.rb
@@ -393,6 +409,7 @@ files:
393
409
  - lib/insika/tools/data_defined_tool.rb
394
410
  - lib/insika/tools/load_skill.rb
395
411
  - lib/insika/tools/remember.rb
412
+ - lib/insika/tools/stuck_signal.rb
396
413
  - lib/insika/tools/subagent.rb
397
414
  - lib/insika/tools/subagents.rb
398
415
  - lib/insika/tools/tool_search.rb
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rack"
4
- require "rack/utils"
5
-
6
- module Insika
7
- module Server
8
- # Minimal operator auth. Fail-closed BY CONSTRUCTION: with no
9
- # token configured, /admin does not exist to the world (503) — never open
10
- # by omission. Pure module, testable without a Rack env.
11
- module AdminAuth
12
- module_function
13
-
14
- # config_token: config[:admin_token] (the wiring reads ADMIN_TOKEN).
15
- # header: raw Authorization value.
16
- # -> :disabled | :unauthorized | :ok
17
- def check(config_token, header)
18
- return :disabled if config_token.nil? || config_token.empty?
19
-
20
- provided = header.to_s[/\ABearer (.+)\z/, 1]
21
- return :unauthorized if provided.nil?
22
- # Constant-time comparison: the operator token doesn't leak via timing.
23
- return :unauthorized unless Rack::Utils.secure_compare(config_token, provided)
24
-
25
- :ok
26
- end
27
- end
28
- end
29
- end