rubik 0.4.2 → 0.6.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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/ATTRIBUTION.md +1 -1
  3. data/CHANGELOG.md +125 -1
  4. data/lib/rubik/ast/cache_store.rb +33 -0
  5. data/lib/rubik/ast/graph.rb +2 -1
  6. data/lib/rubik/benchmark/runner.rb +14 -0
  7. data/lib/rubik/benchmark/vakanuvis_adoption.rb +439 -0
  8. data/lib/rubik/config/defaults.rb +7 -1
  9. data/lib/rubik/log.rb +4 -3
  10. data/lib/rubik/orchestrator/budget_manager.rb +2 -0
  11. data/lib/rubik/orchestrator/loop.rb +1 -0
  12. data/lib/rubik/orchestrator/shell_deps.rb +4 -0
  13. data/lib/rubik/orchestrator/step_executor.rb +3 -3
  14. data/lib/rubik/orchestrator/subagent/tool_dispatch.rb +31 -11
  15. data/lib/rubik/orchestrator/turn_executor/user_channel.rb +2 -0
  16. data/lib/rubik/prompt/doctrine.rb +10 -15
  17. data/lib/rubik/prompt/emergency_compactor.rb +7 -3
  18. data/lib/rubik/prompt/tool_teachings.rb +29 -35
  19. data/lib/rubik/repl/commands/agent_context.rb +1 -0
  20. data/lib/rubik/repl/commands/agent_execution.rb +7 -0
  21. data/lib/rubik/repl/commands/system.rb +2 -0
  22. data/lib/rubik/repl/input_execution.rb +5 -1
  23. data/lib/rubik/repl/turn_recorder.rb +3 -0
  24. data/lib/rubik/security/redactor.rb +13 -9
  25. data/lib/rubik/storage/vakanuvis/annal_writer.rb +51 -4
  26. data/lib/rubik/storage/vakanuvis/distill_gate.rb +14 -2
  27. data/lib/rubik/storage/vakanuvis/gate.rb +23 -15
  28. data/lib/rubik/storage/vakanuvis/harness.rb +149 -121
  29. data/lib/rubik/storage/vakanuvis/job.rb +25 -0
  30. data/lib/rubik/storage/vakanuvis/orientation.rb +277 -0
  31. data/lib/rubik/storage/vakanuvis/service.rb +5 -1
  32. data/lib/rubik/storage/vakanuvis.rb +20 -1
  33. data/lib/rubik/tools/builtins/vakanuvis.rb +13 -15
  34. data/lib/rubik/tools/truncator.rb +53 -0
  35. data/lib/rubik/version.rb +1 -1
  36. metadata +4 -1
@@ -0,0 +1,277 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../layout"
4
+
5
+ module Rubik
6
+ module Storage
7
+ module Vakanuvis
8
+ # Soğuk-başlangıç ve sıkıştırma sonrası yönelim enjeksiyonu (issue #340):
9
+ # Sistem istemi (system prompt) hiç şişirilmeden, oturumun ilk model
10
+ # çağrısından önce ve her bağlam sıkıştırması / budaması tamamlandığında
11
+ # kök konuşma geçmişine kısa, deterministik bir `role: "user"` yönelim
12
+ # iletisi eklenir. Kart yoksa (N == 0), kronikçi kapalıysa veya
13
+ # `subagents.vakanuvis.orientation == false` ise hiçbir şey enjekte
14
+ # edilmez. Kanca `ctx` içine tersiyle (`on_dispose`) kaydedilir (§1A).
15
+ module Orientation
16
+ DEFAULT_MAX_TOPICS = 10
17
+ HOOK_KEY = :vakanuvis_orientation_hook
18
+ TAG_OPEN = "<vakanuvis_orientation>"
19
+ TAG_CLOSE = "</vakanuvis_orientation>"
20
+ DEPTH_HINT = "Ask `vakanuvis(action: 'recall', query: '<2-3 terms>')` for depth."
21
+
22
+ # Oturum-içi durum ve terslenebilir kanca taşıyıcısı.
23
+ class Hook
24
+ attr_reader :harness
25
+
26
+ def initialize(harness, config: nil)
27
+ @harness = harness
28
+ @config = config
29
+ @session_oriented = false
30
+ @disposed = false
31
+ end
32
+
33
+ def dispose!
34
+ @disposed = true
35
+ @session_oriented = false
36
+ end
37
+
38
+ def disposed?
39
+ @disposed
40
+ end
41
+
42
+ def reset_session!
43
+ @session_oriented = false
44
+ end
45
+
46
+ def enabled?(override_config = nil)
47
+ return false if @disposed || @harness.nil? || @harness.stopped?
48
+
49
+ cfg = override_config || @config || @harness.config
50
+ return false unless Service.enabled?(cfg)
51
+
52
+ Layout.config_get(cfg, "subagents.vakanuvis.orientation", true) != false
53
+ end
54
+
55
+ def max_topics(override_config = nil)
56
+ cfg = override_config || @config || @harness.config
57
+ raw = Layout.config_get(cfg, "subagents.vakanuvis.orientation_max_topics", DEFAULT_MAX_TOPICS)
58
+ val = raw.to_i
59
+ val.positive? ? val : DEFAULT_MAX_TOPICS
60
+ end
61
+
62
+ def build_message(override_config = nil)
63
+ return nil unless enabled?(override_config)
64
+
65
+ excerpt = Orientation.format_excerpt(@harness, limit: max_topics(override_config))
66
+ return nil unless excerpt
67
+
68
+ { role: "user", content: excerpt }
69
+ end
70
+
71
+ def inject_session_start!(history, config: nil)
72
+ return nil unless history.is_a?(Array)
73
+
74
+ if history.any? { |m| Orientation.orientation_message?(m) }
75
+ @session_oriented = true
76
+ return nil
77
+ end
78
+ return nil if @session_oriented
79
+ return nil unless enabled?(config)
80
+
81
+ msg = build_message(config)
82
+ return nil unless msg
83
+
84
+ @session_oriented = true
85
+ Orientation.deduplicate_and_insert_start!(history, msg)
86
+ end
87
+
88
+ def inject_after_compaction!(history, config: nil)
89
+ return nil unless history.is_a?(Array)
90
+
91
+ Orientation.strip_orientation_messages!(history)
92
+ return nil unless enabled?(config)
93
+
94
+ msg = build_message(config)
95
+ return nil unless msg
96
+
97
+ @session_oriented = true
98
+ Orientation.insert_after_compaction!(history, msg)
99
+ end
100
+ end
101
+
102
+ module_function
103
+
104
+ # Kancayı `ctx` (veya child sub-context) içine tersiyle kaydeder (§1A).
105
+ # Kronikçi devre dışı bırakıldığında veya child dispose edildiğinde
106
+ # kanca otomatik olarak sökülür; reload döngülerinde yetim kanca kalmaz.
107
+ def register_hook(ctx, harness, config: nil, inverse_ctx: nil)
108
+ return nil unless ctx.respond_to?(:provide) && harness
109
+
110
+ cfg = config || harness.config
111
+ hook = Hook.new(harness, config: cfg)
112
+ ctx.provide(HOOK_KEY, hook)
113
+ target_ctx = inverse_ctx || ctx
114
+ cfg_inverse = wire_config_observer(ctx, hook, cfg)
115
+ if target_ctx.respond_to?(:on_dispose)
116
+ target_ctx.on_dispose do
117
+ cfg_inverse&.call
118
+ hook.dispose!
119
+ ctx.unprovide(HOOK_KEY) if ctx.respond_to?(:unprovide) && ctx.get(HOOK_KEY).equal?(hook)
120
+ end
121
+ end
122
+ hook
123
+ end
124
+
125
+ def wire_config_observer(ctx, hook, cfg)
126
+ return nil unless cfg.respond_to?(:on_change)
127
+
128
+ cfg.on_change("subagents.vakanuvis") do |_key, _val, _old|
129
+ next if hook.disposed?
130
+
131
+ if hook.enabled?(cfg)
132
+ ctx.provide(HOOK_KEY, hook) unless ctx.get(HOOK_KEY).equal?(hook)
133
+ elsif ctx.respond_to?(:unprovide) && ctx.get(HOOK_KEY).equal?(hook)
134
+ ctx.unprovide(HOOK_KEY)
135
+ end
136
+ end
137
+ end
138
+
139
+ # Coeffect üzerinden kancayı veya doğrudan VAKANUIS harness'ini çözer.
140
+ # VAKANUIS coeffect'i karşılanmamışsa nil döner.
141
+ def resolve_hook(context_or_manager, config: nil)
142
+ ctx = extract_context(context_or_manager)
143
+ return nil unless ctx
144
+
145
+ harness = Rubik::Coeffects.get(ctx, Rubik::Coeffects::VAKANUIS)
146
+ return nil unless harness.is_a?(Harness) && !harness.stopped?
147
+
148
+ cfg = config || harness.config
149
+ return nil unless Service.enabled?(cfg)
150
+ return nil if Layout.config_get(cfg, "subagents.vakanuvis.orientation", true) == false
151
+
152
+ hook = Rubik::Coeffects.get(ctx, HOOK_KEY)
153
+ return hook if hook.is_a?(Hook) && !hook.disposed? && hook.harness.equal?(harness)
154
+
155
+ register_hook(ctx, harness, config: cfg)
156
+ end
157
+
158
+ def reset_session!(context_or_manager)
159
+ ctx = extract_context(context_or_manager)
160
+ return false unless ctx
161
+
162
+ hook = Rubik::Coeffects.get(ctx, HOOK_KEY)
163
+ hook.reset_session! if hook.is_a?(Hook)
164
+ true
165
+ end
166
+
167
+ def inject_session_start!(history, context_or_manager, config: nil)
168
+ hook = resolve_hook(context_or_manager, config: config)
169
+ return nil unless hook
170
+
171
+ hook.inject_session_start!(history, config: config)
172
+ end
173
+
174
+ def inject_after_compaction!(history, context_or_manager, config: nil)
175
+ strip_orientation_messages!(history) if history.is_a?(Array)
176
+ hook = resolve_hook(context_or_manager, config: config)
177
+ return nil unless hook
178
+
179
+ hook.inject_after_compaction!(history, config: config)
180
+ end
181
+
182
+ # Aktif mem.* kartlarını [ref, row] sırasıyla listeler.
183
+ # Dönen çift: [lines_array, total_active_cards_count].
184
+ def topic_lines(store, limit: nil)
185
+ return [[], 0] unless store
186
+
187
+ bound = store.refs.select { |ref, _| Vocabulary.memory_ref?(ref) }
188
+ cards = store.list(type: "memory").select do |s|
189
+ s.status == Vocabulary::STATUS_ACTIVE && bound.value?(s.id)
190
+ end
191
+ return [[], 0] if cards.empty?
192
+
193
+ all_lines = cards.sort_by { |s| [bound.key(s.id), s.row] }.filter_map do |s|
194
+ record = store.get(type: "memory", id: s.id)
195
+ next unless record # list→get arası silme yarışı (review L2)
196
+
197
+ "- #{bound.key(s.id)} — #{s.title} — #{first_body_line(record)} — #{store.uri_for('memory', s.id)}"
198
+ end
199
+ total = all_lines.size
200
+ shown = limit ? all_lines.first(limit.to_i) : all_lines
201
+ [shown, total]
202
+ end
203
+
204
+ def first_body_line(record)
205
+ slice = record["body"].to_s.lines.map(&:strip).reject(&:empty?).first.to_s.slice(0, Harness::RECALL_BODY_SLICE)
206
+ slice.empty? ? "(no body)" : slice
207
+ end
208
+
209
+ # Aktif mem.* kartlarından deterministik [ref, row] sırasıyla en fazla
210
+ # `limit` satır üretir. Aktif kart yoksa (N == 0) nil döner.
211
+ def format_excerpt(harness, limit: DEFAULT_MAX_TOPICS)
212
+ store = harness.respond_to?(:store) ? harness.store : nil
213
+ lines, total = topic_lines(store, limit: limit)
214
+ return nil if lines.empty?
215
+
216
+ count_label = total > lines.size ? "#{lines.size} of #{total}" : lines.size.to_s
217
+ "#{TAG_OPEN}\nRecorded topics (#{count_label}):\n#{lines.join("\n")}\n#{DEPTH_HINT}\n#{TAG_CLOSE}"
218
+ end
219
+
220
+ def orientation_message?(msg)
221
+ return false unless msg.is_a?(Hash)
222
+
223
+ role = (msg[:role] || msg["role"]).to_s
224
+ return false unless role == "user"
225
+
226
+ content = (msg[:content] || msg["content"]).to_s
227
+ content.include?(TAG_OPEN) && content.include?(DEPTH_HINT)
228
+ end
229
+
230
+ def strip_orientation_messages!(history)
231
+ return history unless history.is_a?(Array)
232
+
233
+ history.reject! { |msg| orientation_message?(msg) }
234
+ history
235
+ end
236
+
237
+ # Oturum başında: sistem mesajı varsa hemen ardına (ilk user mesajından
238
+ # önce), yoksa dizinin başına yerleştirir. Eski kopyaları temizler.
239
+ def deduplicate_and_insert_start!(history, msg)
240
+ strip_orientation_messages!(history)
241
+ idx = first_non_system_index(history)
242
+ history.insert(idx, msg)
243
+ msg
244
+ end
245
+
246
+ # Sıkıştırma sonrasında: eski yönelim iletilerini siler ve yeni yönelim
247
+ # iletisini sistem mesajlarının hemen ardına deterministik olarak ekler.
248
+ def insert_after_compaction!(history, msg)
249
+ strip_orientation_messages!(history)
250
+ idx = first_non_system_index(history)
251
+ history.insert(idx, msg)
252
+ msg
253
+ end
254
+
255
+ def first_non_system_index(history)
256
+ idx = history.index do |m|
257
+ role = m.is_a?(Hash) ? (m[:role] || m["role"]).to_s : ""
258
+ role != "system"
259
+ end
260
+ idx || history.size
261
+ end
262
+
263
+ def extract_context(context_or_manager)
264
+ return nil unless context_or_manager
265
+
266
+ if context_or_manager.respond_to?(:context)
267
+ context_or_manager.context
268
+ elsif context_or_manager.respond_to?(:runtime_manager) && context_or_manager.runtime_manager.respond_to?(:context)
269
+ context_or_manager.runtime_manager.context
270
+ else
271
+ context_or_manager
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
277
+ end
@@ -57,7 +57,11 @@ module Rubik
57
57
  )
58
58
  # Ömür (§2.7): child ctx'in cascade inverse'i worker'ı kapatır;
59
59
  # kuyruk FIFO'su drain olur, yarım kronik kalmaz.
60
- child&.on_dispose { harness.shutdown }
60
+ child&.on_dispose do
61
+ harness.shutdown
62
+ ctx.unprovide(Rubik::Coeffects::VAKANUIS) if ctx.respond_to?(:unprovide) && ctx.get(Rubik::Coeffects::VAKANUIS).equal?(harness)
63
+ end
64
+ Orientation.register_hook(ctx, harness, config: config, inverse_ctx: child)
61
65
  harness.start!
62
66
  ctx.provide(Rubik::Coeffects::VAKANUIS, harness)
63
67
  context_or_manager.reconcile_all if context_or_manager.respond_to?(:reconcile_all)
@@ -50,10 +50,16 @@ module Rubik
50
50
  # gereği notice YOK — sadece dmesg/stderr düzlemi.
51
51
  SUBSYSTEM = :storage
52
52
 
53
+ # Konu-adlı uyarıların SON İZİ buradır: iki havuz da patlarsa bile
54
+ # mesaj stderr'e düşer — kayıp iz yok (review #346 F2).
53
55
  def log_via(dmesg, level, message)
54
56
  dmesg.respond_to?(:log) ? dmesg.log(SUBSYSTEM, level, message) : Rubik::Log.send(level, SUBSYSTEM, message)
55
57
  rescue StandardError
56
- Rubik::Log.warn(SUBSYSTEM, message)
58
+ begin
59
+ Rubik::Log.warn(SUBSYSTEM, message)
60
+ rescue StandardError
61
+ warn("[vakanuvis] #{message}")
62
+ end
57
63
  end
58
64
 
59
65
  def content_unchanged?(existing, title, body, tags, links, status)
@@ -63,6 +69,17 @@ module Rubik
63
69
  existing["links"] == links.to_h { |k, v| [k.to_s, v.to_s] }.sort.to_h &&
64
70
  existing["status"] == status.to_s
65
71
  end
72
+
73
+ # Mükerrer otomatik-damıtım kabulü (issue #351 F9): "already queued"
74
+ # sessiz başarı sayılmaz — mevcut iş değişmez, bu goal kaydına
75
+ # bağlanmaz; iz satırı düşer. Dönen true çağrı yerindeki kısa-devre
76
+ # koşuluna hizmet eder (mükerrer stranded DEĞİLDİR, yeniden kuyruğa
77
+ # girmez — var olan iş hedefi zaten derliyor).
78
+ def log_duplicate_digest(dmesg, topic, goal_ordinal)
79
+ note = goal_ordinal ? "goal record ##{goal_ordinal} not attached; " : ""
80
+ log_via(dmesg, :warn, "auto-digest duplicate for '#{topic}' — #{note}existing job keeps its own context")
81
+ true
82
+ end
66
83
  end
67
84
  end
68
85
  end
@@ -72,6 +89,8 @@ require_relative "vakanuvis/annal_writer"
72
89
  require_relative "vakanuvis/memory_steward"
73
90
  require_relative "vakanuvis/wiki_skeleton"
74
91
  require_relative "vakanuvis/distill_gate"
92
+ require_relative "vakanuvis/job"
75
93
  require_relative "vakanuvis/gate"
76
94
  require_relative "vakanuvis/harness"
95
+ require_relative "vakanuvis/orientation"
77
96
  require_relative "vakanuvis/service"
@@ -24,15 +24,12 @@ module Rubik
24
24
  DECLARATION = Declaration.new(
25
25
  name: "vakanuvis", aliases: ["chronicler"],
26
26
  description: "Ask the background chronicler (compiled knowledge in rubik://storage): " \
27
- "'recall' (deterministic digest over memory+wiki with source links — ask at task start " \
28
- "and after compaction), 'record' (persist durable knowledge as a memory card; the ONE " \
29
- "path for memory writes), 'forget' (supersede/purge a mem.* card or a note), 'digest' (queue an " \
30
- "async wiki compilation; returns a deterministic receipt, never blocks on the LLM), " \
31
- "'topics' (list recorded memory topics — orient before the first query), 'digest_status' " \
32
- "(is my queued digest pending, in flight, or done?). Notes (annal.*) are the chronicler's " \
33
- "evidence layer; memory cards are the durable conclusions you want recalled by default. " \
34
- "Hygiene: same topic, same session = one note — update it (or retire it with forget; " \
35
- "superseded rows keep a trace).",
27
+ "'recall' (deterministic digest over memory+wiki with source links — ask at task start), " \
28
+ "'record' (persist durable knowledge as a memory card; the ONE path for memory writes), " \
29
+ "'forget' (supersede/purge a mem.* card or a note), 'digest' (queue an async wiki compilation; " \
30
+ "returns a deterministic receipt, never blocks on the LLM), 'topics' (list recorded memory topics " \
31
+ "— orient before the first query), 'digest_status' (is my queued digest pending, in flight, or done?). " \
32
+ "Notes (annal.*) are the chronicler's evidence layer; memory cards are the durable conclusions you want recalled by default.",
36
33
  risk: :write, archetypes: [], write_grant: false,
37
34
  maestro_blocked: false, # storage emsali: kronikçi düzlemi kökte doğrudan
38
35
  params_schema: {
@@ -42,9 +39,11 @@ module Rubik
42
39
  type: "string", enum: ["recall", "record", "forget", "digest", "topics", "digest_status"],
43
40
  description: "Operation (default: 'recall')."
44
41
  },
45
- query: { type: "string",
46
- description: "recall/digest: knowledge query. Recall is keyword-AND — every space-separated " \
47
- "term must literally appear; retry with other-language synonyms when empty." },
42
+ query: {
43
+ type: "string",
44
+ description: "recall/digest: knowledge query. Recall is keyword-AND — use 2-3 core terms (every " \
45
+ "space-separated term must literally appear); retry with other-language synonyms when empty."
46
+ },
48
47
  types: {
49
48
  type: "array", items: { type: "string", enum: ["memory", "wiki", "note"] },
50
49
  description: "recall: entity scopes to search (default: memory + wiki)."
@@ -52,9 +51,8 @@ module Rubik
52
51
  topic: { type: "string", description: "record: card topic — mints ref mem.<topic-slug> (upsert by topic)." },
53
52
  body: {
54
53
  type: "string",
55
- description: "record: card body (markdown; end it with a Keywords: line of 5-10 TR+EN synonyms so " \
56
- "keyword-AND recall can find the card — a missing Keywords: line is auto-extracted " \
57
- "from the body at write time)."
54
+ description: "record: card body (markdown; end it with a Keywords: line of 5-10 TR+EN synonyms if you " \
55
+ "can — a missing Keywords: line is auto-extracted from the body at write time)."
58
56
  },
59
57
  tags: {
60
58
  type: "array", items: { type: "string" },
@@ -5,6 +5,59 @@ module Rubik
5
5
  module Truncator
6
6
  DEFAULT_MAX_CHARS = 12_000
7
7
  DEFAULT_MAX_LINES = 300
8
+ # The strategy knob's default lives here (arch scan card 5, 2026-11-01):
9
+ # both orchestrator planes read tools.truncation_strategy with this
10
+ # fallback — one literal for the whole repo instead of restated copies.
11
+ DEFAULT_STRATEGY = :head_tail
12
+ # Known-strategy set (issue #349): a typo'd config value used to die
13
+ # silently into the head_tail `else` branch in both planes. This set
14
+ # is the honest frontier — resolve_strategy warns against it, and a
15
+ # new strategy added to #truncate must register here to be reachable.
16
+ STRATEGIES = [:head_tail, :head_only, :tail_only].freeze
17
+
18
+ class << self
19
+ # Configured-value resolver for the strategy fetch sites (root
20
+ # StepExecutor + subagent ToolDispatch + prompt EmergencyCompactor).
21
+ # nil/false/empty/missing fall back to the default SILENTLY (that
22
+ # path is correct today); a non-empty value outside STRATEGIES warns
23
+ # ONCE per distinct knob+value pair, then keeps the default — the
24
+ # operator "tuning" truncation with a typo must not get
25
+ # byte-identical old behavior in silence. `key:` names the config
26
+ # knob in the warn so each caller's message points at its own
27
+ # setting, and the frontier dedups on the pair: the same typo under
28
+ # two different knobs must warn twice, or fixing one knob leaves
29
+ # the other misconfigured in silence.
30
+ def resolve_strategy(value, key: "tools.truncation_strategy")
31
+ return DEFAULT_STRATEGY if value.nil? || value == false || value.to_s.strip.empty?
32
+
33
+ sym = value.to_s.downcase.to_sym
34
+ return sym if STRATEGIES.include?(sym)
35
+
36
+ warn_unknown_strategy(value, key)
37
+ DEFAULT_STRATEGY
38
+ end
39
+
40
+ private
41
+
42
+ # One-time-per-knob-and-value warn (UI::Theme#paint precedent):
43
+ # the first bad value speaks, re-occurrences (every tool result
44
+ # would re-resolve) stay quiet. Warn level, not debug: a config
45
+ # typo is operator-visible in normal operation. The value is
46
+ # forced to UTF-8 and scrubbed BEFORE interpolation — scrub alone
47
+ # is a no-op on BINARY strings — because Log.warn's rescue cannot
48
+ # reach a message that fails to build, and a binary-encoding
49
+ # config value must never turn tool results into errors.
50
+ def warn_unknown_strategy(value, key)
51
+ shown = value.to_s.dup.force_encoding(Encoding::UTF_8).scrub
52
+ return unless unknown_strategies.add?([key, shown])
53
+
54
+ Rubik::Log.warn(:tools, "#{key}='#{shown}' is not a known strategy (#{STRATEGIES.join('/')}) — using #{DEFAULT_STRATEGY}")
55
+ end
56
+
57
+ def unknown_strategies
58
+ @unknown_strategies ||= Set.new
59
+ end
60
+ end
8
61
 
9
62
  def self.truncate(text, max_chars: DEFAULT_MAX_CHARS, max_lines: DEFAULT_MAX_LINES, strategy: :head_tail, separator: "\n")
10
63
  str = text.to_s
data/lib/rubik/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubik
4
- VERSION = "0.4.2"
4
+ VERSION = "0.6.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubik
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Özgür Ulukır
@@ -267,6 +267,7 @@ files:
267
267
  - lib/rubik/benchmark.rb
268
268
  - lib/rubik/benchmark/runner.rb
269
269
  - lib/rubik/benchmark/synth_repo.rb
270
+ - lib/rubik/benchmark/vakanuvis_adoption.rb
270
271
  - lib/rubik/buffer.rb
271
272
  - lib/rubik/buffer/apply_contract.rb
272
273
  - lib/rubik/buffer/diff.rb
@@ -720,7 +721,9 @@ files:
720
721
  - lib/rubik/storage/vakanuvis/distill_gate.rb
721
722
  - lib/rubik/storage/vakanuvis/gate.rb
722
723
  - lib/rubik/storage/vakanuvis/harness.rb
724
+ - lib/rubik/storage/vakanuvis/job.rb
723
725
  - lib/rubik/storage/vakanuvis/memory_steward.rb
726
+ - lib/rubik/storage/vakanuvis/orientation.rb
724
727
  - lib/rubik/storage/vakanuvis/service.rb
725
728
  - lib/rubik/storage/vakanuvis/vocabulary.rb
726
729
  - lib/rubik/storage/vakanuvis/wiki_skeleton.rb