robot_lab-document_store 0.2.7 → 0.2.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba7995bd1cc8a7136598de913b944988b3e96b12a7717df76321ec92c587fe90
4
- data.tar.gz: 9837c42e6cf67050c3e15b8e5631c053e094253ceaea5012096ad2c9b9b5bec9
3
+ metadata.gz: 28fc49eabc0cc41a494dd3616b80aae598d136ed9ac43701901c1febea570f12
4
+ data.tar.gz: cd3ab07965633d3a7becd7d0c70c668f17b6b5dcb19e0af02cafc82fee5ca6a0
5
5
  SHA512:
6
- metadata.gz: 6a6c101a2a02ca3d8555d11d9b02e6b763d6ed33cf7ad927fad8bb574809d481772591a08023f60569b85e7f03a1edaf31273dd1cc44cab95c2c3a4b23892165
7
- data.tar.gz: 6bb3eefc700cffff70ed42bdddf5d588959a7291bd8346a8a16c7475c413b9977e0f8bc46635a782e7166896ab5103d7f8859fbb13897a86b8e506ec7a41e86c
6
+ metadata.gz: 36fba6cb5abe124767d1f31f0e5f4a411c6a9c2a65ebaf56b3198de271c1be7c61569b0238729a79d1b2c979982af2dd12ca0ca856a7d9274cb99cc73225757e
7
+ data.tar.gz: c39107b2526d209f8a793ecf7d7a77bff3c31dbc8ceef9de79c05e2ce3df65dad0cf0839803e270d5d04a2162d7bfbc1ace853f084acc854b0098cbc8340792a
data/.envrc CHANGED
@@ -1,3 +1,6 @@
1
+ # robot_lab_project/robot_lab-document_store/.envrc
2
+
1
3
  source_up
4
+
2
5
  export RR=`pwd`
3
6
  export BUNDLE_GEMFILE=Gemfile
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.8] - 2026-09-09
4
+
5
+ Released in lockstep with `robot_lab` core v0.2.8: this gem now resolves the released core gem from RubyGems instead of the local sibling checkout (local-path development remains available via `BUNDLE_GEMFILE=Gemfile.local`). Also in this release: `cosine_similarity` split during the reek pass (remaining sites annotated), and gem lifecycle tasks moved to asgard.
6
+
3
7
  ### Added
4
8
  - `.loki` Asgard task file: `test`, `rubocop`, `rubocop_fix`, `flog`, `flay`, `quality`, `build`, `install`, `release`, and `console` tasks via the Asgard task runner
5
9
  - `flay_check` Rake task: structural code duplication gate (mass threshold 50); integrated into the `quality` Rake task
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler/gem_tasks'
4
3
  require 'rake/testtask'
5
4
 
6
5
  Rake::TestTask.new(:test) do |t|
data/_typos.toml ADDED
@@ -0,0 +1,9 @@
1
+ # False-positive suppressions for the typos quality gate (asgard).
2
+ # Everything here was reviewed by hand — see git history for context.
3
+
4
+ [default.extend-identifiers]
5
+ # The Porter-style stemmer strips suffixes and its docs show raw stem
6
+ # output; these are deliberate word fragments, not typos.
7
+ ment = "ment" # the -ment suffix (stemmer regex + docs table)
8
+ activiti = "activiti" # stem of "activities" (docs table)
9
+ runn = "runn" # stem of "running" (docs table)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RobotLab
4
4
  class DocumentStore
5
- VERSION = '0.2.7'
5
+ VERSION = '0.2.8'
6
6
  end
7
7
  end
@@ -29,6 +29,7 @@ module RobotLab
29
29
  # memory.store_document(:readme, File.read("README.md"))
30
30
  # memory.search_documents("how to configure redis", limit: 3)
31
31
  #
32
+ # :reek:RepeatedConditional -- @using_fastembed selects the dense vs sparse embedding path, fixed at construction.
32
33
  class DocumentStore
33
34
  # @api private
34
35
  FASTEMBED_AVAILABLE = begin
@@ -72,6 +73,7 @@ module RobotLab
72
73
  # @param limit [Integer] maximum number of results (default 5)
73
74
  # @return [Array<Hash>] results sorted by score descending.
74
75
  # Each hash contains +:key+, +:text+, and +:score+ (Float 0.0..1.0).
76
+ # :reek:TooManyStatements -- linear embed/score/sort pipeline; the mutex block inflates the count.
75
77
  def search(query, limit: 5)
76
78
  return [] if empty?
77
79
 
@@ -155,32 +157,37 @@ module RobotLab
155
157
  def cosine_similarity(vec_a, vec_b)
156
158
  return 0.0 unless vec_a && vec_b
157
159
 
158
- if @using_fastembed
159
- return 0.0 if vec_a.empty? || vec_b.empty?
160
- return 0.0 if vec_a.length != vec_b.length
161
-
162
- dot = 0.0
163
- norm_a = 0.0
164
- norm_b = 0.0
165
-
166
- vec_a.each_with_index do |a, i|
167
- b = vec_b[i]
168
- dot += a * b
169
- norm_a += a * a
170
- norm_b += b * b
171
- end
160
+ @using_fastembed ? dense_cosine(vec_a, vec_b) : sparse_cosine(vec_a, vec_b)
161
+ end
172
162
 
173
- return 0.0 if norm_a.zero? || norm_b.zero?
163
+ # :reek:FeatureEnvy -- pure vector math over its two arguments; there is no better home than the store that owns both paths.
164
+ # :reek:TooManyStatements -- one guarded dot-product/norm accumulation; splitting the loop would obscure the formula.
165
+ def dense_cosine(vec_a, vec_b)
166
+ return 0.0 if vec_a.empty? || vec_b.empty?
167
+ return 0.0 if vec_a.length != vec_b.length
174
168
 
175
- dot / (Math.sqrt(norm_a) * Math.sqrt(norm_b))
176
- else
177
- sparse_cosine(vec_a, vec_b)
169
+ dot = 0.0
170
+ norm_a = 0.0
171
+ norm_b = 0.0
172
+
173
+ vec_a.each_with_index do |a, i|
174
+ b = vec_b[i]
175
+ dot += a * b
176
+ norm_a += a * a
177
+ norm_b += b * b
178
178
  end
179
+
180
+ return 0.0 if norm_a.zero? || norm_b.zero?
181
+
182
+ dot / (Math.sqrt(norm_a) * Math.sqrt(norm_b))
179
183
  end
180
184
 
181
185
  # ── Fallback TF-IDF word-frequency path ─────────────────────────────────
182
186
 
183
187
  # Returns a sparse Hash{String => Float} L2-normalised term-frequency vector.
188
+ # :reek:FeatureEnvy -- builds and normalises the local counts hash it returns; there is no other object involved.
189
+ # :reek:TooManyStatements -- one count-then-normalise sequence over the local hash.
190
+ # :reek:UncommunicativeVariableName -- single-char block param (w = word) is accepted project convention.
184
191
  def fallback_vector(text)
185
192
  counts = Hash.new(0)
186
193
  text.downcase.scan(/[a-z]+/).each do |w|
@@ -195,6 +202,7 @@ module RobotLab
195
202
  counts.transform_values { |c| c / norm }
196
203
  end
197
204
 
205
+ # :reek:TooManyStatements -- one guarded dot-product/norm accumulation; splitting the loop would obscure the formula.
198
206
  def sparse_cosine(vec_a, vec_b)
199
207
  return 0.0 if vec_a.empty? || vec_b.empty?
200
208
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: robot_lab-document_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
@@ -58,6 +58,7 @@ files:
58
58
  - LICENSE.txt
59
59
  - README.md
60
60
  - Rakefile
61
+ - _typos.toml
61
62
  - docs/api_reference.md
62
63
  - docs/assets/architecture.svg
63
64
  - docs/getting_started.md
@@ -96,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
97
  - !ruby/object:Gem::Version
97
98
  version: '0'
98
99
  requirements: []
99
- rubygems_version: 4.0.19
100
+ rubygems_version: 4.0.20
100
101
  specification_version: 4
101
102
  summary: Embedding-based semantic document store for RobotLab agents
102
103
  test_files: []