feelings 0.0.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.
data/lib/feelings.rb ADDED
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ruby_decision_model"
4
+
5
+ require_relative "feelings/version"
6
+ require_relative "feelings/errors"
7
+ require_relative "feelings/registry"
8
+ require_relative "feelings/distribution"
9
+ require_relative "feelings/labels"
10
+ require_relative "feelings/state"
11
+ require_relative "feelings/questions"
12
+ require_relative "feelings/mood"
13
+ require_relative "feelings/pick"
14
+ require_relative "feelings/tape"
15
+ require_relative "feelings/match_builder"
16
+ require_relative "feelings/engine"
17
+ require_relative "feelings/about"
18
+ require_relative "feelings/judges/stub"
19
+ require_relative "feelings/judges/decision_model"
20
+
21
+ # feelings brings the `feels` construct from the Probably language to Ruby.
22
+ # A decision model judges how well a description fits a value, and
23
+ # feelings turns that into conditionals, semantic match, bounded loops,
24
+ # chaos sampling, and replayable tapes.
25
+ module Feelings
26
+ class << self
27
+ def judge=(judge)
28
+ @judge = judge
29
+ @judge_set = true
30
+ end
31
+
32
+ def judge
33
+ return @judge if @judge_set
34
+
35
+ @judge = Judges::DecisionModel.new(RubyDecisionModel.client)
36
+ @judge_set = true
37
+ @judge
38
+ end
39
+
40
+ def with_judge(judge)
41
+ previous = Thread.current[:feelings_judge_override]
42
+ Thread.current[:feelings_judge_override] = judge
43
+ yield
44
+ ensure
45
+ Thread.current[:feelings_judge_override] = previous
46
+ end
47
+
48
+ def current_judge
49
+ Thread.current[:feelings_judge_override] || judge
50
+ end
51
+
52
+ def random=(source)
53
+ @random = source
54
+ end
55
+
56
+ def random
57
+ @random ||= -> { Kernel.rand }
58
+ end
59
+
60
+ def load(path)
61
+ registry.load(path)
62
+ registry.to_h
63
+ end
64
+
65
+ def register(hash)
66
+ registry.register(hash)
67
+ registry.to_h
68
+ end
69
+
70
+ def [](key)
71
+ registry[key]
72
+ end
73
+
74
+ def registry
75
+ @registry ||= Registry.new
76
+ end
77
+
78
+ def reset!
79
+ @registry = Registry.new
80
+ @judge = nil
81
+ @judge_set = false
82
+ @random = nil
83
+ self
84
+ end
85
+
86
+ def chaos
87
+ previous = Thread.current[:feelings_chaos]
88
+ Thread.current[:feelings_chaos] = true
89
+ yield
90
+ ensure
91
+ Thread.current[:feelings_chaos] = previous
92
+ end
93
+
94
+ def chaos?
95
+ !!Thread.current[:feelings_chaos]
96
+ end
97
+
98
+ def record
99
+ tape = Tape.new
100
+ previous = Thread.current[:feelings_tape]
101
+ Thread.current[:feelings_tape] = tape
102
+ yield
103
+ tape
104
+ ensure
105
+ Thread.current[:feelings_tape] = previous
106
+ end
107
+
108
+ def current_tape
109
+ Thread.current[:feelings_tape]
110
+ end
111
+
112
+ def replay(tape)
113
+ queue = tape.entries.dup
114
+ previous = Thread.current[:feelings_replay]
115
+ Thread.current[:feelings_replay] = queue
116
+ result = yield
117
+ raise ReplayMismatch, "tape has #{queue.size} unused entries" unless queue.empty?
118
+
119
+ result
120
+ ensure
121
+ Thread.current[:feelings_replay] = previous
122
+ end
123
+
124
+ def current_replay
125
+ Thread.current[:feelings_replay]
126
+ end
127
+
128
+ def while(initial, description, max: 5)
129
+ raise ArgumentError, "max must be between 1 and 50" unless (1..50).cover?(max)
130
+
131
+ current = initial
132
+ max.times do
133
+ mood = About.new(current).like(description)
134
+ return current if mood.no?
135
+
136
+ current = yield(current)
137
+ end
138
+ raise LoopLimit, "Loop still feels true after #{max} iterations."
139
+ end
140
+
141
+ def like?(value, *args, **kwargs)
142
+ About.new(value).like?(*args, **kwargs)
143
+ end
144
+
145
+ def like(value, *args, **kwargs, &block)
146
+ About.new(value).like(*args, **kwargs, &block)
147
+ end
148
+
149
+ def most_like(value, *args, **kwargs)
150
+ About.new(value).most_like(*args, **kwargs)
151
+ end
152
+
153
+ def match(value, *args, **kwargs, &block)
154
+ About.new(value).match(*args, **kwargs, &block)
155
+ end
156
+ end
157
+ end
158
+
159
+ module Kernel
160
+ def Feelings(value)
161
+ Feelings::About.new(value)
162
+ end
163
+ private :Feelings
164
+ end
165
+
166
+ require_relative "feelings/railtie" if defined?(Rails::Railtie)
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: feelings
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Obie Fernandez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-09-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby_decision_model
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ description: feelings brings the feels construct from the Probably language to Ruby.
56
+ A decision model judges how well a description fits a value, and feelings turns
57
+ that into conditionals, semantic match, bounded loops, chaos sampling, and replayable
58
+ tapes. Descriptions and label sets can live in YAML. Works with any judge; ruby_decision_model
59
+ is the default.
60
+ email:
61
+ - obiefernandez@gmail.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - ".ruby-version"
67
+ - CHANGELOG.md
68
+ - LICENSE.txt
69
+ - README.md
70
+ - Rakefile
71
+ - feelings.gemspec
72
+ - lib/feelings.rb
73
+ - lib/feelings/about.rb
74
+ - lib/feelings/core_ext.rb
75
+ - lib/feelings/distribution.rb
76
+ - lib/feelings/engine.rb
77
+ - lib/feelings/errors.rb
78
+ - lib/feelings/judges/decision_model.rb
79
+ - lib/feelings/judges/stub.rb
80
+ - lib/feelings/labels.rb
81
+ - lib/feelings/match_builder.rb
82
+ - lib/feelings/mood.rb
83
+ - lib/feelings/pick.rb
84
+ - lib/feelings/questions.rb
85
+ - lib/feelings/railtie.rb
86
+ - lib/feelings/registry.rb
87
+ - lib/feelings/state.rb
88
+ - lib/feelings/tape.rb
89
+ - lib/feelings/version.rb
90
+ homepage: https://github.com/obie/feelings
91
+ licenses:
92
+ - MIT
93
+ metadata:
94
+ source_code_uri: https://github.com/obie/feelings
95
+ rubygems_mfa_required: 'true'
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '3.2'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.5.11
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: 'Probabilistic conditionals for Ruby: Feelings(message).like?("genuinely
115
+ urgent")'
116
+ test_files: []