assistant 0.1.0 → 1.0.0.rc1

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +39 -0
  3. data/.github/workflows/ci.yml +99 -0
  4. data/.github/workflows/docs.yml +64 -0
  5. data/.github/workflows/release.yml +1 -1
  6. data/.gitignore +5 -1
  7. data/.opencode/.gitignore +4 -0
  8. data/.opencode/opencode.json +13 -0
  9. data/.opencode/skills/create-pr/SKILL.md +138 -0
  10. data/.opencode/skills/ruby-services/SKILL.md +81 -0
  11. data/.rubocop.yml +14 -4
  12. data/.yardopts +17 -0
  13. data/CHANGELOG.md +378 -0
  14. data/CONTRIBUTING.md +131 -0
  15. data/Gemfile +10 -0
  16. data/Gemfile.lock +196 -29
  17. data/README.md +125 -16
  18. data/Rakefile +45 -0
  19. data/SECURITY.md +50 -0
  20. data/Steepfile +49 -0
  21. data/_config.yml +87 -0
  22. data/assistant.gemspec +24 -7
  23. data/docs/api-reference.md +264 -0
  24. data/docs/changelog.md +26 -0
  25. data/docs/deprecations.md +86 -0
  26. data/docs/examples/cli-handler.md +17 -0
  27. data/docs/examples/composing-services.md +17 -0
  28. data/docs/examples/execute-callbacks.md +17 -0
  29. data/docs/examples/index.md +29 -0
  30. data/docs/examples/instrumentation-notifier.md +17 -0
  31. data/docs/examples/rails-service.md +17 -0
  32. data/docs/examples/rbs-generator.md +17 -0
  33. data/docs/examples/sidekiq-worker.md +17 -0
  34. data/docs/getting-started.md +136 -0
  35. data/docs/guides/composing-services.md +222 -0
  36. data/docs/guides/index.md +25 -0
  37. data/docs/guides/inputs.md +333 -0
  38. data/docs/guides/logging-and-results.md +202 -0
  39. data/docs/guides/rbs-and-types.md +16 -0
  40. data/docs/guides/validation.md +180 -0
  41. data/docs/index.md +69 -0
  42. data/docs/roadmap.md +33 -0
  43. data/exe/assistant-rbs +7 -0
  44. data/lib/assistant/execute_callbacks.rb +103 -0
  45. data/lib/assistant/execute_callbacks.rbs +30 -0
  46. data/lib/assistant/input_builder/accessors.rb +36 -0
  47. data/lib/assistant/input_builder/accessors.rbs +10 -0
  48. data/lib/assistant/input_builder/default_option.rb +41 -0
  49. data/lib/assistant/input_builder/default_option.rbs +11 -0
  50. data/lib/assistant/input_builder/dsl.rb +37 -0
  51. data/lib/assistant/input_builder/dsl.rbs +12 -0
  52. data/lib/assistant/input_builder/optional_option.rb +45 -0
  53. data/lib/assistant/input_builder/optional_option.rbs +10 -0
  54. data/lib/assistant/input_builder/registry.rb +27 -0
  55. data/lib/assistant/input_builder/registry.rbs +13 -0
  56. data/lib/assistant/input_builder/require_validator.rb +104 -0
  57. data/lib/assistant/input_builder/require_validator.rbs +24 -0
  58. data/lib/assistant/input_builder/type_validator.rb +47 -0
  59. data/lib/assistant/input_builder/type_validator.rbs +18 -0
  60. data/lib/assistant/input_builder.rb +25 -81
  61. data/lib/assistant/input_builder.rbs +15 -0
  62. data/lib/assistant/log_item.rb +74 -16
  63. data/lib/assistant/log_item.rbs +40 -0
  64. data/lib/assistant/log_list.rb +43 -17
  65. data/lib/assistant/log_list.rbs +48 -0
  66. data/lib/assistant/rbs_generator/cli.rb +109 -0
  67. data/lib/assistant/rbs_generator/cli.rbs +24 -0
  68. data/lib/assistant/rbs_generator/renderer.rb +67 -0
  69. data/lib/assistant/rbs_generator/renderer.rbs +11 -0
  70. data/lib/assistant/rbs_generator/writer.rb +65 -0
  71. data/lib/assistant/rbs_generator/writer.rbs +24 -0
  72. data/lib/assistant/rbs_generator.rb +38 -0
  73. data/lib/assistant/rbs_generator.rbs +5 -0
  74. data/lib/assistant/refinements/string_blankness.rb +9 -13
  75. data/lib/assistant/refinements/string_blankness.rbs +6 -0
  76. data/lib/assistant/service.rb +300 -11
  77. data/lib/assistant/service.rbs +82 -1
  78. data/lib/assistant/version.rb +5 -1
  79. data/lib/assistant/version.rbs +5 -0
  80. data/lib/assistant.rb +54 -4
  81. data/lib/assistant.rbs +25 -0
  82. data/mise.toml +2 -0
  83. data/sig/examples/greeter.rbs +14 -0
  84. metadata +142 -38
  85. data/.fasterer.yml +0 -19
  86. data/.rubocop_todo.yml +0 -7
data/Gemfile.lock CHANGED
@@ -1,36 +1,117 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- assistant (0.1.0)
4
+ assistant (1.0.0.rc1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ addressable (2.9.0)
10
+ public_suffix (>= 2.0.2, < 8.0)
9
11
  ast (2.4.3)
10
- brakeman (8.0.4)
11
- racc
12
+ base64 (0.3.0)
13
+ bigdecimal (4.1.2)
12
14
  byebug (13.0.0)
13
15
  reline (>= 0.6.0)
16
+ colorator (1.1.0)
14
17
  colorize (1.1.0)
15
- fasterer (0.11.0)
16
- ruby_parser (>= 3.19.1)
18
+ concurrent-ruby (1.3.6)
19
+ csv (3.3.5)
20
+ docile (1.4.1)
21
+ drb (2.2.3)
22
+ em-websocket (0.5.3)
23
+ eventmachine (>= 0.12.9)
24
+ http_parser.rb (~> 0)
25
+ eventmachine (1.2.7)
26
+ ffi (1.17.4)
27
+ ffi (1.17.4-arm64-darwin)
28
+ fileutils (1.8.0)
29
+ forwardable-extended (2.6.0)
30
+ google-protobuf (4.35.1)
31
+ bigdecimal
32
+ rake (~> 13.3)
33
+ google-protobuf (4.35.1-arm64-darwin)
34
+ bigdecimal
35
+ rake (~> 13.3)
36
+ http_parser.rb (0.8.1)
37
+ i18n (1.14.8)
38
+ concurrent-ruby (~> 1.0)
17
39
  io-console (0.8.2)
18
- json (2.19.5)
40
+ jekyll (4.4.1)
41
+ addressable (~> 2.4)
42
+ base64 (~> 0.2)
43
+ colorator (~> 1.0)
44
+ csv (~> 3.0)
45
+ em-websocket (~> 0.5)
46
+ i18n (~> 1.0)
47
+ jekyll-sass-converter (>= 2.0, < 4.0)
48
+ jekyll-watch (~> 2.0)
49
+ json (~> 2.6)
50
+ kramdown (~> 2.3, >= 2.3.1)
51
+ kramdown-parser-gfm (~> 1.0)
52
+ liquid (~> 4.0)
53
+ mercenary (~> 0.3, >= 0.3.6)
54
+ pathutil (~> 0.9)
55
+ rouge (>= 3.0, < 5.0)
56
+ safe_yaml (~> 1.0)
57
+ terminal-table (>= 1.8, < 4.0)
58
+ webrick (~> 1.7)
59
+ jekyll-include-cache (0.2.1)
60
+ jekyll (>= 3.7, < 5.0)
61
+ jekyll-relative-links (0.7.0)
62
+ jekyll (>= 3.3, < 5.0)
63
+ jekyll-sass-converter (3.1.0)
64
+ sass-embedded (~> 1.75)
65
+ jekyll-seo-tag (2.9.0)
66
+ jekyll (>= 3.8, < 5.0)
67
+ jekyll-watch (2.2.1)
68
+ listen (~> 3.0)
69
+ json (2.19.9)
70
+ just-the-docs (0.12.0)
71
+ jekyll (>= 3.8.5)
72
+ jekyll-include-cache
73
+ jekyll-seo-tag (>= 2.0)
74
+ rake (>= 12.3.1)
75
+ kramdown (2.5.2)
76
+ rexml (>= 3.4.4)
77
+ kramdown-parser-gfm (1.1.0)
78
+ kramdown (~> 2.0)
19
79
  language_server-protocol (3.17.0.5)
20
80
  lint_roller (1.1.0)
21
- minitest (5.27.0)
81
+ liquid (4.0.4)
82
+ listen (3.10.0)
83
+ logger
84
+ rb-fsevent (~> 0.10, >= 0.10.3)
85
+ rb-inotify (~> 0.9, >= 0.9.10)
86
+ logger (1.7.0)
87
+ mercenary (0.4.0)
88
+ minitest (6.0.6)
89
+ drb (~> 2.0)
90
+ prism (~> 1.5)
22
91
  parallel (2.1.0)
23
92
  parser (3.3.11.1)
24
93
  ast (~> 2.4.1)
25
94
  racc
95
+ pathutil (0.16.2)
96
+ forwardable-extended (~> 2.6)
26
97
  prism (1.9.0)
98
+ public_suffix (7.0.5)
27
99
  racc (1.8.1)
28
100
  rainbow (3.1.1)
29
101
  rake (13.4.2)
102
+ rb-fsevent (0.11.2)
103
+ rb-inotify (0.11.1)
104
+ ffi (~> 1.0)
105
+ rbs (4.0.2)
106
+ logger
107
+ prism (>= 1.6.0)
108
+ tsort
30
109
  regexp_parser (2.12.0)
31
110
  reline (0.6.3)
32
111
  io-console (~> 0.5)
33
- rubocop (1.86.1)
112
+ rexml (3.4.4)
113
+ rouge (4.7.0)
114
+ rubocop (1.86.2)
34
115
  json (~> 2.3)
35
116
  language_server-protocol (~> 3.17.0.2)
36
117
  lint_roller (~> 1.1.0)
@@ -55,14 +136,47 @@ GEM
55
136
  rubocop-rake (0.7.1)
56
137
  lint_roller (~> 1.1)
57
138
  rubocop (>= 1.72.1)
139
+ rubocop-style-compact_nesting (0.1.2)
140
+ lint_roller (~> 1.1)
141
+ rubocop (>= 1.72, < 2.0)
58
142
  ruby-progressbar (1.13.0)
59
- ruby_parser (3.22.0)
60
- racc (~> 1.5)
61
- sexp_processor (~> 4.16)
62
- sexp_processor (4.17.5)
63
- unicode-display_width (3.2.0)
64
- unicode-emoji (~> 4.1)
65
- unicode-emoji (4.2.0)
143
+ safe_yaml (1.0.5)
144
+ sass-embedded (1.101.0)
145
+ google-protobuf (~> 4.31)
146
+ rake (>= 13)
147
+ sass-embedded (1.101.0-arm64-darwin)
148
+ google-protobuf (~> 4.31)
149
+ securerandom (0.4.1)
150
+ simplecov (0.22.0)
151
+ docile (~> 1.1)
152
+ simplecov-html (~> 0.11)
153
+ simplecov_json_formatter (~> 0.1)
154
+ simplecov-html (0.13.2)
155
+ simplecov_json_formatter (0.1.4)
156
+ steep (2.0.0)
157
+ concurrent-ruby (>= 1.1.10)
158
+ csv (>= 3.0.9)
159
+ fileutils (>= 1.1.0)
160
+ json (>= 2.1.0)
161
+ language_server-protocol (>= 3.17.0.4, < 4.0)
162
+ listen (~> 3.0)
163
+ logger (>= 1.3.0)
164
+ parser (>= 3.2)
165
+ prism (>= 0.25.0)
166
+ rainbow (>= 2.2.2, < 4.0)
167
+ rbs (~> 4.0)
168
+ securerandom (>= 0.1)
169
+ strscan (>= 1.0.0)
170
+ terminal-table (>= 2, < 5)
171
+ uri (>= 0.12.0)
172
+ strscan (3.1.8)
173
+ terminal-table (3.0.2)
174
+ unicode-display_width (>= 1.1.1, < 3)
175
+ tsort (0.2.0)
176
+ unicode-display_width (2.6.0)
177
+ uri (1.1.1)
178
+ webrick (1.9.2)
179
+ yard (0.9.44)
66
180
 
67
181
  PLATFORMS
68
182
  arm64-darwin-25
@@ -70,49 +184,102 @@ PLATFORMS
70
184
 
71
185
  DEPENDENCIES
72
186
  assistant!
73
- brakeman (~> 8.0)
74
187
  bundler (~> 4.0)
75
188
  byebug (~> 13.0)
76
189
  colorize (~> 1.1)
77
- fasterer (~> 0.11.0)
78
- minitest (~> 5.25)
190
+ jekyll (~> 4.3)
191
+ jekyll-relative-links (~> 0.7)
192
+ just-the-docs (~> 0.10)
193
+ minitest (~> 6.0)
79
194
  rake (~> 13.4)
80
- rubocop (~> 1.86)
195
+ rubocop (~> 1.86, >= 1.86.2)
81
196
  rubocop-minitest (~> 0.39)
82
197
  rubocop-performance (~> 1.26)
83
198
  rubocop-rake (~> 0.7)
199
+ rubocop-style-compact_nesting (~> 0.1)
200
+ simplecov (~> 0.22)
201
+ steep (~> 2.0)
202
+ yard (~> 0.9)
84
203
 
85
204
  CHECKSUMS
86
- assistant (0.1.0)
205
+ addressable (2.9.0) sha256=7fdf6ac3660f7f4e867a0838be3f6cf722ace541dd97767fa42bc6cfa980c7af
206
+ assistant (1.0.0.rc1)
87
207
  ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
88
- brakeman (8.0.4) sha256=7bf921fa9638544835df9aa7b3e720a9a72c0267f34f92135955edd80d4dcf6f
208
+ base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
209
+ bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
89
210
  bundler (4.0.11) sha256=5bcec0fb78302e48d02ee46f10ee6e6942be647ba5b44a6d1ddfda9a240ce785
90
211
  byebug (13.0.0) sha256=d2263efe751941ca520fa29744b71972d39cbc41839496706f5d9b22e92ae05d
212
+ colorator (1.1.0) sha256=e2f85daf57af47d740db2a32191d1bdfb0f6503a0dfbc8327d0c9154d5ddfc38
91
213
  colorize (1.1.0) sha256=30b5237f0603f6662ab8d1fc2bd4a96142b806c6415d79e45ef5fdc6a0cfc837
92
- fasterer (0.11.0) sha256=9c38b77583584f3339a729eb077fd8f2856a317abe747528f6563d7c23e9dda8
214
+ concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab
215
+ csv (3.3.5) sha256=6e5134ac3383ef728b7f02725d9872934f523cb40b961479f69cf3afa6c8e73f
216
+ docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
217
+ drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
218
+ em-websocket (0.5.3) sha256=f56a92bde4e6cb879256d58ee31f124181f68f8887bd14d53d5d9a292758c6a8
219
+ eventmachine (1.2.7) sha256=994016e42aa041477ba9cff45cbe50de2047f25dd418eba003e84f0d16560972
220
+ ffi (1.17.4) sha256=bcd1642e06f0d16fc9e09ac6d49c3a7298b9789bcb58127302f934e437d60acf
221
+ ffi (1.17.4-arm64-darwin) sha256=19071aaf1419251b0a46852abf960e77330a3b334d13a4ab51d58b31a937001b
222
+ fileutils (1.8.0) sha256=8c6b1df54e2540bdb2f39258f08af78853aa70bad52b4d394bbc6424593c6e02
223
+ forwardable-extended (2.6.0) sha256=1bec948c469bbddfadeb3bd90eb8c85f6e627a412a3e852acfd7eaedbac3ec97
224
+ google-protobuf (4.35.1) sha256=a3a6471331d918f58dfa4d014a8f6286f0af2cf4840216bde52fcf2ea3fe3726
225
+ google-protobuf (4.35.1-arm64-darwin) sha256=d9c957df04fa89c749fa9a72a7b383eb4296efc9b2303dc6fd6fbe39c698ad6b
226
+ http_parser.rb (0.8.1) sha256=9ae8df145b39aa5398b2f90090d651c67bd8e2ebfe4507c966579f641e11097a
227
+ i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5
93
228
  io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
94
- json (2.19.5) sha256=218a18553e4801d579ca7e0f5bc72bafd776d7397238a1fb4e74db5b0a812c59
229
+ jekyll (4.4.1) sha256=4c1144d857a5b2b80d45b8cf5138289579a9f8136aadfa6dd684b31fe2bc18c1
230
+ jekyll-include-cache (0.2.1) sha256=c7d4b9e551732a27442cb2ce853ba36a2f69c66603694b8c1184c99ab1a1a205
231
+ jekyll-relative-links (0.7.0) sha256=831e54c348eeae751845c0d4ac4b244bd73b664341f0e8c9f1803b16f4570835
232
+ jekyll-sass-converter (3.1.0) sha256=83925d84f1d134410c11d0c6643b0093e82e3a3cf127e90757a85294a3862443
233
+ jekyll-seo-tag (2.9.0) sha256=0260015a8e1df9bf195cdfb0c675b7b2883fd8cbf12556e1c1cbe36a831c6852
234
+ jekyll-watch (2.2.1) sha256=bc44ed43f5e0a552836245a54dbff3ea7421ecc2856707e8a1ee203a8387a7e1
235
+ json (2.19.9) sha256=9b9025b7cdddafa38d316eca0b2358488e42d417045c1b90d216a9fefe46b79a
236
+ just-the-docs (0.12.0) sha256=15f2839ac9082898d60f33b978aa6f8e46fc50ba8fac20ae7a7f0e1fb295523e
237
+ kramdown (2.5.2) sha256=1ba542204c66b6f9111ff00dcc26075b95b220b07f2905d8261740c82f7f02fa
238
+ kramdown-parser-gfm (1.1.0) sha256=fb39745516427d2988543bf01fc4cf0ab1149476382393e0e9c48592f6581729
95
239
  language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
96
240
  lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
97
- minitest (5.27.0) sha256=2d3b17f8a36fe7801c1adcffdbc38233b938eb0b4966e97a6739055a45fa77d5
241
+ liquid (4.0.4) sha256=4fcfebb1a045e47918388dbb7a0925e7c3893e58d2bd6c3b3c73ec17a2d8fdb3
242
+ listen (3.10.0) sha256=c6e182db62143aeccc2e1960033bebe7445309c7272061979bb098d03760c9d2
243
+ logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
244
+ mercenary (0.4.0) sha256=b25a1e4a59adca88665e08e24acf0af30da5b5d859f7d8f38fba52c28f405138
245
+ minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
98
246
  parallel (2.1.0) sha256=b35258865c2e31134c5ecb708beaaf6772adf9d5efae28e93e99260877b09356
99
247
  parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54
248
+ pathutil (0.16.2) sha256=e43b74365631cab4f6d5e4228f812927efc9cb2c71e62976edcb252ee948d589
100
249
  prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
250
+ public_suffix (7.0.5) sha256=1a8bb08f1bbea19228d3bed6e5ed908d1cb4f7c2726d18bd9cadf60bc676f623
101
251
  racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
102
252
  rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
103
253
  rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
254
+ rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
255
+ rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e
256
+ rbs (4.0.2) sha256=af75671e66cd03434cc546622741ebf83f6197ec4328375805306330bf78ef25
104
257
  regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb
105
258
  reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
106
- rubocop (1.86.1) sha256=44415f3f01d01a21e01132248d2fd0867572475b566ca188a0a42133a08d4531
259
+ rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142
260
+ rouge (4.7.0) sha256=dba5896715c0325c362e895460a6d350803dbf6427454f49a47500f3193ea739
261
+ rubocop (1.86.2) sha256=bb2e97f635eda42c448f2588f4a6ff78f221b8bdfdf65b1e9b07fbd57521b45d
107
262
  rubocop-ast (1.49.1) sha256=4412f3ee70f6fe4546cc489548e0f6fcf76cafcfa80fa03af67098ffed755035
108
263
  rubocop-minitest (0.39.1) sha256=998398d6da4026d297f0f9bf709a1eac5f2b6947c24431f94af08138510cf7ed
109
264
  rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834
110
265
  rubocop-rake (0.7.1) sha256=3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d
266
+ rubocop-style-compact_nesting (0.1.2) sha256=cbe155ec7230dcea32925d34a435b40c2fc666ea9b45755f92102dd1a73b739b
111
267
  ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
112
- ruby_parser (3.22.0) sha256=1eb4937cd9eb220aa2d194e352a24dba90aef00751e24c8dfffdb14000f15d23
113
- sexp_processor (4.17.5) sha256=ae2b48ba98353d5d465ce8759836b7a05f2e12c5879fcd14d7815b026de32f0e
114
- unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
115
- unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
268
+ safe_yaml (1.0.5) sha256=a6ac2d64b7eb027bdeeca1851fe7e7af0d668e133e8a88066a0c6f7087d9f848
269
+ sass-embedded (1.101.0) sha256=57dbc3409e2c0a2c581a4c9945c2bd72ec88e71ec98017bd02dd1da8a76b22f4
270
+ sass-embedded (1.101.0-arm64-darwin) sha256=9fed684380b49499dfc856aba0d026a0748f924bd78044ffff2bae1537aea73e
271
+ securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
272
+ simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
273
+ simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246
274
+ simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
275
+ steep (2.0.0) sha256=6eb0ecc09637bbb54f0a5f2cf63daea6d3208ccace64b4f1107d976333605c30
276
+ strscan (3.1.8) sha256=aae2db611a225559f21ffbb71765c9a4e60fd262534a9ea84f4f11c7f32f679e
277
+ terminal-table (3.0.2) sha256=f951b6af5f3e00203fb290a669e0a85c5dd5b051b3b023392ccfd67ba5abae91
278
+ tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
279
+ unicode-display_width (2.6.0) sha256=12279874bba6d5e4d2728cef814b19197dbb10d7a7837a869bab65da943b7f5a
280
+ uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
281
+ webrick (1.9.2) sha256=beb4a15fc474defed24a3bda4ffd88a490d517c9e4e6118c3edce59e45864131
282
+ yard (0.9.44) sha256=eb087e9b631ccd887b049f303d489963945452d5e2a7eb49a5a74a7cf6887f28
116
283
 
117
284
  BUNDLED WITH
118
285
  4.0.11
data/README.md CHANGED
@@ -1,43 +1,152 @@
1
1
  # Assistant
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/assistant`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [![CI](https://github.com/ramongr/assistant/actions/workflows/ci.yml/badge.svg)](https://github.com/ramongr/assistant/actions/workflows/ci.yml)
4
+ [![Gem Version](https://img.shields.io/gem/v/assistant.svg)](https://rubygems.org/gems/assistant)
5
+ [![Downloads](https://img.shields.io/gem/dt/assistant.svg)](https://rubygems.org/gems/assistant)
6
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.4-ruby.svg)](https://www.ruby-lang.org/)
7
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://opensource.org/licenses/MIT)
4
8
 
5
- TODO: Delete this and the text above, and describe your gem
9
+ A tiny, dependency-free Ruby library for writing **soft-fail, composable
10
+ service objects**. A service declares its inputs, validates them, runs its
11
+ body, and returns a uniform result that always carries either a value plus
12
+ warnings or a list of errors — it never raises for expected failures.
6
13
 
7
14
  ## Installation
8
15
 
9
- Add this line to your application's Gemfile:
16
+ ```sh
17
+ bundle add assistant
18
+ ```
10
19
 
11
- ```ruby
12
- gem 'assistant'
20
+ Or without Bundler:
21
+
22
+ ```sh
23
+ gem install assistant
13
24
  ```
14
25
 
15
- And then execute:
26
+ Ruby `>= 3.4` is required.
27
+
28
+ ## 60-second example
29
+
30
+ ```ruby
31
+ require 'assistant'
32
+
33
+ class CreateUser < Assistant::Service
34
+ input :email, type: String, required: true
35
+ input :name, type: String, required: true
36
+ input :age, type: Integer, allow_nil: true, default: nil
37
+
38
+ def validate
39
+ return if email.include?('@')
40
+
41
+ log_item_error(source: :validate, detail: :email, message: 'must contain @')
42
+ end
16
43
 
17
- $ bundle
44
+ def execute
45
+ log_item_warning(source: :execute, detail: :age, message: 'age missing') if age.nil?
18
46
 
19
- Or install it yourself as:
47
+ User.create!(email:, name:, age:)
48
+ end
49
+ end
20
50
 
21
- $ gem install assistant
51
+ CreateUser.run(email: 'ada@example.com', name: 'Ada')
52
+ # => { result: #<User …>, status: :with_warnings, warnings: [#<Assistant::LogItem …>] }
22
53
 
23
- ## Usage
54
+ CreateUser.run(email: 'nope', name: 'Ada')
55
+ # => { errors: [#<Assistant::LogItem …>], result: nil, status: :with_errors }
56
+ ```
57
+
58
+ The result hash is always one of two shapes:
24
59
 
25
- TODO: Write usage instructions here
60
+ ```ruby
61
+ # Success — status is :ok or :with_warnings
62
+ { result: <Object>, status: :ok | :with_warnings, warnings: Array<Assistant::LogItem> }
63
+
64
+ # Failure — any error was logged before or during execute
65
+ { errors: Array<Assistant::LogItem>, result: nil, status: :with_errors }
66
+ ```
67
+
68
+ Use `#success?`, `#failure?`, and `#status` on a service instance, or
69
+ pattern-match the hash returned by `.run` directly.
70
+
71
+ ## Why another service-object gem?
72
+
73
+ - **No runtime dependencies.** `assistant` is one require away; it does not
74
+ pull in ActiveSupport, dry-rb, or anything else. It runs in plain Ruby,
75
+ Rails, Hanami, Sidekiq workers, and Rake tasks alike.
76
+ - **Soft-fail by design.** Validation problems and recoverable failures are
77
+ surfaced as `LogItem`s on the result, not exceptions. Callers
78
+ pattern-match a hash; they don't write `rescue` blocks for expected
79
+ outcomes.
80
+ - **Tiny, frozen surface.** The public API documented in
81
+ [`docs/v1/01-api-surface.md`](docs/v1/01-api-surface.md) is everything
82
+ there is. No DSL gymnastics, no plug-in registry, no opinionated
83
+ serialization. Compose services with the plain `#call_service` primitive.
84
+
85
+ Compared to [Interactor](https://github.com/collectiveidea/interactor) and
86
+ [dry-transaction](https://dry-rb.org/gems/dry-transaction/), `assistant`
87
+ keeps a single result shape regardless of success or failure, distinguishes
88
+ warnings from errors at the log-item level, and ships RBS signatures plus
89
+ a per-class generator (`bin/assistant-rbs`) out of the box.
90
+
91
+ ## Documentation
92
+
93
+ - **Getting started** — [`docs/getting-started.md`](docs/getting-started.md)
94
+ walks from `gem install` to a first working service.
95
+ - **API reference** — [`docs/api-reference.md`](docs/api-reference.md)
96
+ is the hand-written, curated reference for every Frozen symbol; the
97
+ source of truth for stability labels stays in
98
+ [`docs/v1/01-api-surface.md`](docs/v1/01-api-surface.md).
99
+ - **Feature catalogue and rationale** —
100
+ [`docs/v1/02-features.md`](docs/v1/02-features.md).
101
+ - **Upgrading from 0.x** —
102
+ [`docs/v1/06-migration-0x-to-1.md`](docs/v1/06-migration-0x-to-1.md).
103
+ - **Deprecations** — [`docs/deprecations.md`](docs/deprecations.md).
104
+ - **Runnable sample** — [`examples/greeter.rb`](examples/greeter.rb).
105
+ - **Changelog** — [`CHANGELOG.md`](CHANGELOG.md).
106
+
107
+ The deeper guides (`docs/guides/inputs.md`,
108
+ `docs/guides/validation.md`, `docs/guides/logging-and-results.md`,
109
+ `docs/guides/composing-services.md`) are tracked in
110
+ [`docs/v1/03-documentation.md`](docs/v1/03-documentation.md) and land
111
+ in follow-up PRs.
112
+
113
+ ## Roadmap
114
+
115
+ The plan for the 1.0 release lives under
116
+ [`docs/v1/`](docs/v1/README.md). Every "must" item is shipped; remaining
117
+ work is documentation and release-checklist tasks.
26
118
 
27
119
  ## Development
28
120
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
121
+ ```sh
122
+ bin/setup # install dependencies
123
+ bundle exec rake test # Minitest
124
+ bundle exec rubocop # style
125
+ bundle exec steep check --jobs=1 # type-check RBS signatures
126
+ bin/console # IRB session with the gem loaded
127
+ ```
128
+
129
+ To install the gem locally for ad-hoc experimentation:
30
130
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
131
+ ```sh
132
+ bundle exec rake install
133
+ ```
32
134
 
33
135
  ## Contributing
34
136
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/assistant. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
137
+ Bug reports and pull requests are welcome at
138
+ <https://github.com/ramongr/assistant>. This project is intended to be a
139
+ safe, welcoming space for collaboration, and contributors are expected to
140
+ adhere to the [Contributor Covenant](http://contributor-covenant.org) code
141
+ of conduct.
36
142
 
37
143
  ## License
38
144
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
145
+ The gem is released under the terms of the
146
+ [MIT License](https://opensource.org/licenses/MIT).
40
147
 
41
148
  ## Code of Conduct
42
149
 
43
- Everyone interacting in the Assistant projects codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/assistant/blob/master/CODE_OF_CONDUCT.md).
150
+ Everyone interacting in the Assistant project's codebases, issue trackers,
151
+ chat rooms, and mailing lists is expected to follow the
152
+ [code of conduct](https://github.com/ramongr/assistant/blob/main/CODE_OF_CONDUCT.md).
data/Rakefile CHANGED
@@ -10,4 +10,49 @@ Rake::TestTask.new(:test) do |t|
10
10
  t.warning = false
11
11
  end
12
12
 
13
+ begin
14
+ require 'rubocop/rake_task'
15
+ RuboCop::RakeTask.new
16
+ rescue LoadError
17
+ # rubocop is a development-only dependency; the rubocop task is unavailable
18
+ # in environments (e.g. release builds) where it isn't installed.
19
+ end
20
+
21
+ desc 'Run Steep type-check (matches the required CI job)'
22
+ task :steep do
23
+ sh 'bundle exec steep check --jobs=1'
24
+ end
25
+
26
+ desc 'YARD: build docs into doc/ and enforce 100% public-method coverage'
27
+ task :yard do
28
+ sh 'bundle exec yard doc --quiet'
29
+ stats = `bundle exec yard stats --list-undoc 2>&1`
30
+ match = stats.match(/([\d.]+)% documented/)
31
+ abort "yard: could not parse stats output:\n#{stats}" unless match
32
+
33
+ percentage = match[1].to_f
34
+ abort "yard: only #{format('%.2f', percentage)}% documented; full output:\n#{stats}" if percentage < 100.0
35
+ puts "yard: #{format('%.2f', percentage)}% documented"
36
+ end
37
+
38
+ desc 'Run the full local CI pipeline: test + rubocop + steep + yard'
39
+ task ci: %i[test rubocop steep yard]
40
+
41
+ namespace :docs do
42
+ desc 'Install the Jekyll docs toolchain (Bundler :docs group)'
43
+ task :install do
44
+ sh 'bundle install --with docs'
45
+ end
46
+
47
+ desc 'Build the Jekyll site into ./_site (mirrors the CI Pages build)'
48
+ task :build do
49
+ sh 'bundle exec jekyll build --strict_front_matter'
50
+ end
51
+
52
+ desc 'Serve the Jekyll site on http://127.0.0.1:4000 with live reload'
53
+ task :serve do
54
+ sh 'bundle exec jekyll serve --livereload'
55
+ end
56
+ end
57
+
13
58
  task default: :test
data/SECURITY.md ADDED
@@ -0,0 +1,50 @@
1
+ <!-- markdownlint-disable MD013 -->
2
+ # Security Policy
3
+
4
+ `assistant` is a small Ruby gem with no runtime dependencies and a tiny
5
+ surface area, but security reports are still very welcome.
6
+
7
+ ## Supported versions
8
+
9
+ | Version | Status |
10
+ |---------|-----------------------------------------------------------------|
11
+ | 1.x | **Supported.** Security fixes land on `main` and ship promptly. |
12
+ | 0.x | **End of life** on the `1.0.0` release. No further fixes. |
13
+
14
+ The supported branch will always be the current `1.x` release line. There is
15
+ no intention to backport security fixes to `0.x` once `1.0.0` ships; users on
16
+ `0.x` should upgrade. The migration guide lives at
17
+ [`docs/v1/06-migration-0x-to-1.md`](./docs/v1/06-migration-0x-to-1.md).
18
+
19
+ ## Reporting a vulnerability
20
+
21
+ **Do not open a public GitHub issue or pull request for a security report.**
22
+
23
+ Email <cerberus.ramon@gmail.com> with:
24
+
25
+ - A description of the issue.
26
+ - The version of `assistant` (and Ruby) you reproduced it on.
27
+ - A minimal proof-of-concept or runnable reproduction.
28
+ - Any suggested mitigation, if you have one.
29
+
30
+ If the report involves dependencies pulled in by a downstream Rails or Sinatra
31
+ application, please mention that too — `assistant` itself has zero runtime
32
+ dependencies, so the issue may need to be routed upstream.
33
+
34
+ ## Response SLA
35
+
36
+ We aim for the following turnaround on a best-effort basis:
37
+
38
+ - **First response:** within **7 days** of receiving the email.
39
+ - **Fix or mitigation plan:** within **30 days** of triage, depending on
40
+ severity. Critical issues are fast-tracked.
41
+
42
+ You will be kept in the loop on the timeline and credited in the
43
+ `CHANGELOG.md` entry once the fix ships, unless you ask to remain anonymous.
44
+
45
+ ## Coordinated disclosure
46
+
47
+ We follow a coordinated-disclosure model: the fix is released first, the
48
+ CHANGELOG entry calls out the affected versions and the reporter, and any
49
+ CVE / GHSA advisory is filed afterwards. Please do not publish details
50
+ publicly until the fixed release is out.
data/Steepfile ADDED
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Steep configuration for the `assistant` gem (docs/v1 M8).
4
+ #
5
+ # A single `:lib` target type-checks the gem's Ruby code against the
6
+ # sibling `lib/**/*.rbs` declarations.
7
+ #
8
+ # Steep is intentionally restricted to files that do **not** rely on
9
+ # metaprogramming Steep cannot model:
10
+ #
11
+ # * `Module#define_method` (used by InputBuilder to install the
12
+ # per-input `valid_type_*?`, `valid_required_*?`, etc. methods);
13
+ # * `Kernel#send` to one of those generated methods;
14
+ # * Ruby refinements (`Assistant::Refinements::StringBlankness`);
15
+ # * cross-module helper lookups that only resolve once every
16
+ # `InputBuilder` submodule has been mixed into the same singleton.
17
+ #
18
+ # Signatures for the excluded files still live in `lib/**/*.rbs` so
19
+ # downstream consumers (and the included files) can name the modules
20
+ # and call the helpers. The full per-input surface generated by
21
+ # `Service.input` is the subject of M11 (`bin/assistant-rbs`).
22
+ target :lib do
23
+ signature 'lib'
24
+
25
+ library 'fileutils'
26
+ library 'optparse'
27
+
28
+ check 'lib/assistant.rb'
29
+ check 'lib/assistant/version.rb'
30
+ check 'lib/assistant/input_builder.rb'
31
+ check 'lib/assistant/input_builder/registry.rb'
32
+ check 'lib/assistant/input_builder/default_option.rb'
33
+ check 'lib/assistant/input_builder/optional_option.rb'
34
+ check 'lib/assistant/rbs_generator.rb'
35
+ check 'lib/assistant/rbs_generator/renderer.rb'
36
+ check 'lib/assistant/rbs_generator/writer.rb'
37
+ check 'lib/assistant/rbs_generator/cli.rb'
38
+ end
39
+
40
+ # Type-checks the sample service in `examples/` against the .rbs
41
+ # generated by `exe/assistant-rbs` and shipped in `sig/examples/`.
42
+ # Doubles as the M11 regression that the generator's output is in fact
43
+ # accepted by Steep.
44
+ target :examples do
45
+ signature 'lib'
46
+ signature 'sig'
47
+
48
+ check 'examples'
49
+ end