familia 2.0.0.pre16 → 2.0.0.pre18

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 (250) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -2
  3. data/.github/workflows/{code-smellage.yml → code-smells.yml} +3 -63
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +6 -0
  6. data/CHANGELOG.rst +82 -0
  7. data/CLAUDE.md +47 -2
  8. data/Gemfile.lock +1 -1
  9. data/README.md +13 -0
  10. data/bin/irb +1 -1
  11. data/docs/archive/FAMILIA_TECHNICAL.md +1 -1
  12. data/docs/guides/core-field-system.md +48 -26
  13. data/docs/migrating/v2.0.0-pre18.md +58 -0
  14. data/docs/overview.md +2 -2
  15. data/docs/qodo-merge-compliance.md +96 -0
  16. data/docs/reference/api-technical.md +1 -1
  17. data/examples/encrypted_fields.rb +1 -1
  18. data/examples/safe_dump.rb +1 -1
  19. data/lib/familia/base.rb +6 -6
  20. data/lib/familia/connection/middleware.rb +58 -4
  21. data/lib/familia/connection.rb +1 -1
  22. data/lib/familia/data_type/class_methods.rb +63 -0
  23. data/lib/familia/data_type/connection.rb +83 -0
  24. data/lib/familia/data_type/{commands.rb → database_commands.rb} +2 -2
  25. data/lib/familia/data_type/serialization.rb +5 -5
  26. data/lib/familia/data_type/settings.rb +96 -0
  27. data/lib/familia/data_type/types/hashkey.rb +2 -1
  28. data/lib/familia/data_type/types/sorted_set.rb +113 -10
  29. data/lib/familia/data_type/types/stringkey.rb +0 -4
  30. data/lib/familia/data_type.rb +8 -195
  31. data/lib/familia/encryption/encrypted_data.rb +12 -2
  32. data/lib/familia/encryption/manager.rb +11 -4
  33. data/lib/familia/features/autoloader.rb +3 -1
  34. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +11 -3
  35. data/lib/familia/features/encrypted_fields.rb +5 -2
  36. data/lib/familia/features/external_identifier.rb +49 -8
  37. data/lib/familia/features/object_identifier.rb +84 -12
  38. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +9 -9
  39. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +45 -26
  40. data/lib/familia/features/relationships/indexing.rb +7 -1
  41. data/lib/familia/features/relationships/participation/participant_methods.rb +6 -2
  42. data/lib/familia/features/safe_dump.rb +2 -3
  43. data/lib/familia/features/transient_fields.rb +7 -2
  44. data/lib/familia/features.rb +6 -1
  45. data/lib/familia/field_type.rb +0 -18
  46. data/lib/familia/horreum/{core/connection.rb → connection.rb} +21 -0
  47. data/lib/familia/horreum/{core/database_commands.rb → database_commands.rb} +1 -1
  48. data/lib/familia/horreum/{subclass/definition.rb → definition.rb} +102 -56
  49. data/lib/familia/horreum/{subclass/management.rb → management.rb} +18 -15
  50. data/lib/familia/horreum/{core/serialization.rb → persistence.rb} +73 -170
  51. data/lib/familia/horreum/{subclass/related_fields_management.rb → related_fields.rb} +22 -2
  52. data/lib/familia/horreum/serialization.rb +190 -0
  53. data/lib/familia/horreum.rb +39 -14
  54. data/lib/familia/identifier_extractor.rb +60 -0
  55. data/lib/familia/logging.rb +271 -112
  56. data/lib/familia/refinements.rb +0 -1
  57. data/lib/familia/version.rb +1 -1
  58. data/lib/familia.rb +2 -2
  59. data/lib/middleware/{database_middleware.rb → database_logger.rb} +47 -14
  60. data/pr_agent.toml +31 -0
  61. data/pr_compliance_checklist.yaml +45 -0
  62. data/try/edge_cases/empty_identifiers_try.rb +1 -1
  63. data/try/edge_cases/hash_symbolization_try.rb +31 -31
  64. data/try/edge_cases/json_serialization_try.rb +2 -2
  65. data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +170 -0
  66. data/try/edge_cases/race_conditions_try.rb +1 -1
  67. data/try/edge_cases/reserved_keywords_try.rb +1 -1
  68. data/try/edge_cases/string_coercion_try.rb +1 -1
  69. data/try/edge_cases/ttl_side_effects_try.rb +1 -1
  70. data/try/features/encrypted_fields/aad_protection_try.rb +1 -1
  71. data/try/features/encrypted_fields/concealed_string_core_try.rb +1 -1
  72. data/try/features/encrypted_fields/context_isolation_try.rb +1 -1
  73. data/try/features/encrypted_fields/encrypted_fields_core_try.rb +1 -1
  74. data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +1 -1
  75. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +1 -1
  76. data/try/features/encrypted_fields/encrypted_fields_security_try.rb +1 -1
  77. data/try/features/encrypted_fields/error_conditions_try.rb +1 -1
  78. data/try/features/encrypted_fields/fresh_key_derivation_try.rb +1 -1
  79. data/try/features/encrypted_fields/fresh_key_try.rb +1 -1
  80. data/try/features/encrypted_fields/key_rotation_try.rb +1 -1
  81. data/try/features/encrypted_fields/memory_security_try.rb +1 -1
  82. data/try/features/encrypted_fields/missing_current_key_version_try.rb +1 -1
  83. data/try/features/encrypted_fields/nonce_uniqueness_try.rb +1 -1
  84. data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +1 -1
  85. data/try/features/encrypted_fields/thread_safety_try.rb +1 -1
  86. data/try/features/encrypted_fields/universal_serialization_safety_try.rb +1 -1
  87. data/try/{encryption → features/encryption}/config_persistence_try.rb +1 -1
  88. data/try/{encryption/encryption_core_try.rb → features/encryption/core_try.rb} +2 -2
  89. data/try/{encryption → features/encryption}/instance_variable_scope_try.rb +1 -1
  90. data/try/{encryption → features/encryption}/module_loading_try.rb +1 -1
  91. data/try/{encryption → features/encryption}/providers/aes_gcm_provider_try.rb +1 -1
  92. data/try/{encryption → features/encryption}/providers/xchacha20_poly1305_provider_try.rb +1 -1
  93. data/try/{encryption → features/encryption}/roundtrip_validation_try.rb +1 -1
  94. data/try/{encryption → features/encryption}/secure_memory_handling_try.rb +2 -2
  95. data/try/features/expiration/expiration_try.rb +1 -1
  96. data/try/features/external_identifier/external_identifier_try.rb +1 -1
  97. data/try/features/feature_dependencies_try.rb +1 -1
  98. data/try/features/feature_improvements_try.rb +1 -1
  99. data/try/features/field_groups_try.rb +244 -0
  100. data/try/features/object_identifier/object_identifier_integration_try.rb +1 -1
  101. data/try/features/object_identifier/object_identifier_try.rb +1 -1
  102. data/try/features/quantization/quantization_try.rb +1 -1
  103. data/try/features/real_feature_integration_try.rb +17 -14
  104. data/try/features/relationships/indexing_commands_verification_try.rb +8 -3
  105. data/try/features/relationships/indexing_try.rb +16 -1
  106. data/try/features/relationships/participation_commands_verification_spec.rb +1 -1
  107. data/try/features/relationships/participation_commands_verification_try.rb +4 -4
  108. data/try/features/relationships/participation_performance_improvements_try.rb +1 -1
  109. data/try/features/relationships/participation_reverse_index_try.rb +1 -1
  110. data/try/features/relationships/relationships_api_changes_try.rb +1 -1
  111. data/try/features/relationships/relationships_edge_cases_try.rb +3 -3
  112. data/try/features/relationships/relationships_performance_minimal_try.rb +1 -1
  113. data/try/features/relationships/relationships_performance_simple_try.rb +1 -1
  114. data/try/features/relationships/relationships_performance_try.rb +1 -1
  115. data/try/features/relationships/relationships_performance_working_try.rb +1 -1
  116. data/try/features/relationships/relationships_try.rb +1 -1
  117. data/try/features/safe_dump/safe_dump_advanced_try.rb +1 -1
  118. data/try/features/safe_dump/safe_dump_try.rb +1 -1
  119. data/try/features/transient_fields/redacted_string_try.rb +1 -1
  120. data/try/features/transient_fields/refresh_reset_try.rb +3 -1
  121. data/try/features/transient_fields/single_use_redacted_string_try.rb +1 -1
  122. data/try/features/transient_fields/transient_fields_core_try.rb +1 -1
  123. data/try/features/transient_fields/transient_fields_integration_try.rb +1 -1
  124. data/try/{connection → integration/connection}/fiber_context_preservation_try.rb +1 -1
  125. data/try/{connection → integration/connection}/handler_constraints_try.rb +1 -1
  126. data/try/{core → integration/connection}/isolated_dbclient_try.rb +3 -3
  127. data/try/integration/connection/middleware_reconnect_try.rb +87 -0
  128. data/try/{connection → integration/connection}/operation_mode_guards_try.rb +1 -1
  129. data/try/{connection → integration/connection}/pipeline_fallback_integration_try.rb +1 -1
  130. data/try/{core → integration/connection}/pools_try.rb +1 -1
  131. data/try/{connection → integration/connection}/responsibility_chain_tracking_try.rb +1 -1
  132. data/try/{connection → integration/connection}/transaction_fallback_integration_try.rb +1 -1
  133. data/try/{connection → integration/connection}/transaction_mode_permissive_try.rb +1 -1
  134. data/try/{connection → integration/connection}/transaction_mode_strict_try.rb +1 -1
  135. data/try/{connection → integration/connection}/transaction_mode_warn_try.rb +1 -1
  136. data/try/{connection → integration/connection}/transaction_modes_try.rb +1 -1
  137. data/try/{core → integration}/conventional_inheritance_try.rb +1 -1
  138. data/try/{core → integration}/create_method_try.rb +1 -1
  139. data/try/integration/cross_component_try.rb +1 -1
  140. data/try/{core → integration}/database_consistency_try.rb +12 -8
  141. data/try/{core → integration}/familia_extended_try.rb +1 -1
  142. data/try/{core → integration}/familia_members_methods_try.rb +1 -1
  143. data/try/{models → integration/models}/customer_safe_dump_try.rb +1 -1
  144. data/try/{models → integration/models}/customer_try.rb +6 -6
  145. data/try/{models → integration/models}/datatype_base_try.rb +1 -1
  146. data/try/{models → integration/models}/familia_object_try.rb +1 -1
  147. data/try/{core → integration}/persistence_operations_try.rb +1 -1
  148. data/try/integration/relationships_persistence_round_trip_try.rb +441 -0
  149. data/try/{configuration → integration}/scenarios_try.rb +2 -2
  150. data/try/{core → integration}/secure_identifier_try.rb +1 -1
  151. data/try/{core → integration}/verifiable_identifier_try.rb +1 -1
  152. data/try/performance/benchmarks_try.rb +2 -2
  153. data/try/support/benchmarks/deserialization_benchmark.rb +180 -0
  154. data/try/support/benchmarks/deserialization_correctness_test.rb +237 -0
  155. data/try/{helpers → support/helpers}/test_helpers.rb +15 -7
  156. data/try/{memory → support/memory}/memory_docker_ruby_dump.sh +1 -1
  157. data/try/{core → unit/core}/autoloader_try.rb +1 -1
  158. data/try/{core → unit/core}/base_enhancements_try.rb +1 -9
  159. data/try/{core → unit/core}/connection_try.rb +5 -5
  160. data/try/{core → unit/core}/errors_try.rb +4 -4
  161. data/try/{core → unit/core}/extensions_try.rb +1 -1
  162. data/try/unit/core/familia_logger_try.rb +110 -0
  163. data/try/{core → unit/core}/familia_try.rb +2 -2
  164. data/try/{core → unit/core}/middleware_try.rb +41 -1
  165. data/try/{core → unit/core}/settings_try.rb +1 -1
  166. data/try/{core → unit/core}/time_utils_try.rb +1 -1
  167. data/try/{core → unit/core}/tools_try.rb +3 -3
  168. data/try/{core → unit/core}/utils_try.rb +17 -14
  169. data/try/{data_types → unit/data_types}/boolean_try.rb +1 -1
  170. data/try/{data_types → unit/data_types}/counter_try.rb +1 -1
  171. data/try/{data_types → unit/data_types}/datatype_base_try.rb +1 -1
  172. data/try/{data_types → unit/data_types}/hash_try.rb +1 -1
  173. data/try/{data_types → unit/data_types}/list_try.rb +1 -1
  174. data/try/{data_types → unit/data_types}/lock_try.rb +1 -1
  175. data/try/{data_types → unit/data_types}/sorted_set_try.rb +1 -1
  176. data/try/unit/data_types/sorted_set_zadd_options_try.rb +625 -0
  177. data/try/{data_types → unit/data_types}/string_try.rb +1 -1
  178. data/try/{data_types → unit/data_types}/unsortedset_try.rb +1 -1
  179. data/try/unit/horreum/auto_indexing_on_save_try.rb +212 -0
  180. data/try/{horreum → unit/horreum}/base_try.rb +3 -3
  181. data/try/{horreum → unit/horreum}/class_methods_try.rb +1 -1
  182. data/try/{horreum → unit/horreum}/commands_try.rb +3 -1
  183. data/try/unit/horreum/defensive_initialization_try.rb +86 -0
  184. data/try/{horreum → unit/horreum}/destroy_related_fields_cleanup_try.rb +3 -1
  185. data/try/{horreum → unit/horreum}/enhanced_conflict_handling_try.rb +1 -1
  186. data/try/{horreum → unit/horreum}/field_categories_try.rb +27 -18
  187. data/try/{horreum → unit/horreum}/field_definition_try.rb +1 -1
  188. data/try/{horreum → unit/horreum}/initialization_try.rb +2 -2
  189. data/try/unit/horreum/json_type_preservation_try.rb +248 -0
  190. data/try/{horreum → unit/horreum}/relations_try.rb +1 -1
  191. data/try/{horreum → unit/horreum}/serialization_persistent_fields_try.rb +24 -18
  192. data/try/{horreum → unit/horreum}/serialization_try.rb +4 -4
  193. data/try/{horreum → unit/horreum}/settings_try.rb +3 -1
  194. data/try/{refinements → unit/refinements}/dear_json_array_methods_try.rb +1 -1
  195. data/try/{refinements → unit/refinements}/dear_json_hash_methods_try.rb +1 -1
  196. data/try/{refinements → unit/refinements}/time_literals_numeric_methods_try.rb +1 -1
  197. data/try/{refinements → unit/refinements}/time_literals_string_methods_try.rb +1 -1
  198. data/try/valkey.conf +26 -0
  199. metadata +149 -132
  200. data/lib/familia/distinguisher.rb +0 -85
  201. data/lib/familia/horreum/core.rb +0 -21
  202. data/lib/familia/refinements/logger_trace.rb +0 -60
  203. data/try/refinements/logger_trace_methods_try.rb +0 -44
  204. /data/lib/familia/horreum/{shared/settings.rb → settings.rb} +0 -0
  205. /data/lib/familia/horreum/{core/utils.rb → utils.rb} +0 -0
  206. /data/try/{debugging → support/debugging}/README.md +0 -0
  207. /data/try/{debugging → support/debugging}/cache_behavior_tracer.rb +0 -0
  208. /data/try/{debugging → support/debugging}/debug_aad_process.rb +0 -0
  209. /data/try/{debugging → support/debugging}/debug_concealed_internal.rb +0 -0
  210. /data/try/{debugging → support/debugging}/debug_concealed_reveal.rb +0 -0
  211. /data/try/{debugging → support/debugging}/debug_context_aad.rb +0 -0
  212. /data/try/{debugging → support/debugging}/debug_context_simple.rb +0 -0
  213. /data/try/{debugging → support/debugging}/debug_cross_context.rb +0 -0
  214. /data/try/{debugging → support/debugging}/debug_database_load.rb +0 -0
  215. /data/try/{debugging → support/debugging}/debug_encrypted_json_check.rb +0 -0
  216. /data/try/{debugging → support/debugging}/debug_encrypted_json_step_by_step.rb +0 -0
  217. /data/try/{debugging → support/debugging}/debug_exists_lifecycle.rb +0 -0
  218. /data/try/{debugging → support/debugging}/debug_field_decrypt.rb +0 -0
  219. /data/try/{debugging → support/debugging}/debug_fresh_cross_context.rb +0 -0
  220. /data/try/{debugging → support/debugging}/debug_load_path.rb +0 -0
  221. /data/try/{debugging → support/debugging}/debug_method_definition.rb +0 -0
  222. /data/try/{debugging → support/debugging}/debug_method_resolution.rb +0 -0
  223. /data/try/{debugging → support/debugging}/debug_minimal.rb +0 -0
  224. /data/try/{debugging → support/debugging}/debug_provider.rb +0 -0
  225. /data/try/{debugging → support/debugging}/debug_secure_behavior.rb +0 -0
  226. /data/try/{debugging → support/debugging}/debug_string_class.rb +0 -0
  227. /data/try/{debugging → support/debugging}/debug_test.rb +0 -0
  228. /data/try/{debugging → support/debugging}/debug_test_design.rb +0 -0
  229. /data/try/{debugging → support/debugging}/encryption_method_tracer.rb +0 -0
  230. /data/try/{debugging → support/debugging}/provider_diagnostics.rb +0 -0
  231. /data/try/{helpers → support/helpers}/test_cleanup.rb +0 -0
  232. /data/try/{memory → support/memory}/memory_basic_test.rb +0 -0
  233. /data/try/{memory → support/memory}/memory_detailed_test.rb +0 -0
  234. /data/try/{memory → support/memory}/memory_search_for_string.rb +0 -0
  235. /data/try/{memory → support/memory}/test_actual_redactedstring_protection.rb +0 -0
  236. /data/try/{prototypes → support/prototypes}/atomic_saves_v1_context_proxy.rb +0 -0
  237. /data/try/{prototypes → support/prototypes}/atomic_saves_v2_connection_switching.rb +0 -0
  238. /data/try/{prototypes → support/prototypes}/atomic_saves_v3_connection_pool.rb +0 -0
  239. /data/try/{prototypes → support/prototypes}/atomic_saves_v4.rb +0 -0
  240. /data/try/{prototypes → support/prototypes}/lib/atomic_saves_v2_connection_switching_helpers.rb +0 -0
  241. /data/try/{prototypes → support/prototypes}/lib/atomic_saves_v3_connection_pool_helpers.rb +0 -0
  242. /data/try/{prototypes → support/prototypes}/pooling/README.md +0 -0
  243. /data/try/{prototypes → support/prototypes}/pooling/configurable_stress_test.rb +0 -0
  244. /data/try/{prototypes → support/prototypes}/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +0 -0
  245. /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_metrics.rb +0 -0
  246. /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_stress_test.rb +0 -0
  247. /data/try/{prototypes → support/prototypes}/pooling/lib/connection_pool_threading_models.rb +0 -0
  248. /data/try/{prototypes → support/prototypes}/pooling/lib/visualize_stress_results.rb +0 -0
  249. /data/try/{prototypes → support/prototypes}/pooling/pool_siege.rb +0 -0
  250. /data/try/{prototypes → support/prototypes}/pooling/run_stress_tests.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebaf394ebbccf9d096e87da84c693040c71d963860002a9d970d9b04edc11b6c
4
- data.tar.gz: 4862991d1b2a1538876089030657986eb1b56f5551c7e5e9978a1009c77e86f9
3
+ metadata.gz: e5bbf0ac2fc6a1243d74f679c7027040be00783af625dd90d376637e32417394
4
+ data.tar.gz: 4b354347a0c2403490dc20fdc12f93b3e71b826cf0b2b08638f6fd884a883630
5
5
  SHA512:
6
- metadata.gz: 533af9a33a115e8a59c87ae35e5b82401e1d72edbe43fd4a2963a3ca25a2c1ac259e5aaf02e68945d9d2f576393c6f77e9843ec87c4ed92696ca41d0b06e4d4c
7
- data.tar.gz: b74dca7e415cbd0d6933beb77185e7738d33b3c10a704569120892fa9062fe92874fe2b879439f8d9508b8d02ba0e8154c79cb1546b029ac9e6bbdde442fd5e1
6
+ metadata.gz: 221116e1aa14bc7114cb51164727587dcb0e8435dd8b85bb7d14618393ef446446376fd7febf6dbc9993098e2c819b3b0aa6f3c8bedce1c965b99ec4c8832a7b
7
+ data.tar.gz: 457b0e5bfef1f203c8f2edf934d1ee37915df04c49b0cb8b097ab9732738186ba9e8e92496851699f0952426971d2d3d244e61e594719439672996a0ccde2050
@@ -35,8 +35,8 @@ jobs:
35
35
  --health-retries 5
36
36
  ports:
37
37
  # https://docs.github.com/en/actions/using-containerized-services/creating-redis-service-containers#running-jobs-in-containers
38
- # Maps port 6379 on service container to the host
39
- - 6379:6379
38
+ # Maps port 6379 on service container to 2525 on the host
39
+ - 2525:6379
40
40
 
41
41
  steps:
42
42
  - uses: actions/checkout@v4
@@ -1,4 +1,6 @@
1
- name: Any Code Smellage?
1
+ # ..github/workflows/code-smells.yml
2
+ ---
3
+ name: Code Smells
2
4
 
3
5
  on:
4
6
  pull_request:
@@ -81,65 +83,3 @@ jobs:
81
83
  reek-report.html
82
84
  if-no-files-found: ignore
83
85
  retention-days: 30
84
-
85
- # Add other code quality checks here
86
- additional-quality-checks:
87
- name: Additional Quality Checks
88
- runs-on: ubuntu-24.04
89
- timeout-minutes: 5
90
-
91
- steps:
92
- - name: Checkout code
93
- uses: actions/checkout@v4
94
-
95
- - name: Set up Ruby
96
- uses: ruby/setup-ruby@v1
97
- with:
98
- ruby-version: 3.4
99
- bundler-cache: true
100
-
101
- - name: Configure Bundler for secure gem installation
102
- run: |
103
- bundle config set --local path 'vendor/bundle'
104
- bundle config set --local deployment 'false'
105
-
106
- - name: Install dependencies
107
- run: bundle install --jobs 4 --retry 3
108
-
109
- - name: Check for TODO/FIXME comments
110
- run: |
111
- echo "=== Scanning for TODO/FIXME comments ==="
112
- echo "This helps track technical debt and action items."
113
- echo ""
114
-
115
- # Find TODO/FIXME comments (excluding this workflow file)
116
- find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
117
- xargs grep -Hn -i -E "(TODO|FIXME|HACK|XXX|NOTE):" 2>/dev/null | \
118
- head -20 || echo "No TODO/FIXME comments found"
119
- continue-on-error: true
120
-
121
- - name: Check Ruby file syntax
122
- run: |
123
- echo "=== Checking Ruby syntax ==="
124
- echo "Validates that all Ruby files have correct syntax."
125
- echo ""
126
-
127
- find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
128
- while read -r file; do
129
- if ! ruby -c "$file" > /dev/null 2>&1; then
130
- echo "Syntax error in: $file"
131
- ruby -c "$file"
132
- fi
133
- done
134
- continue-on-error: true
135
-
136
- - name: Check for long lines
137
- run: |
138
- echo "=== Checking for long lines (>120 characters) ==="
139
- echo "Identifies potentially hard-to-read code lines."
140
- echo ""
141
-
142
- find . -name "*.rb" -not -path "./vendor/*" -not -path "./tmp/*" | \
143
- xargs grep -Hn "^.\{121,\}$" | \
144
- head -10 || echo "No overly long lines found"
145
- continue-on-error: true
data/.gitignore CHANGED
@@ -14,7 +14,9 @@
14
14
  *.log
15
15
  *.txt
16
16
  .ruby-version
17
+ dump.rdb
17
18
  appendonlydir
19
+ data
18
20
  log
19
21
  tmp
20
22
  vendor
data/.rubocop.yml CHANGED
@@ -124,6 +124,9 @@ Style/NegatedIfElseCondition:
124
124
  Naming/AsciiIdentifiers:
125
125
  Enabled: false
126
126
 
127
+ Naming/PredicateMethod:
128
+ Enabled: false
129
+
127
130
  Style/StringLiterals:
128
131
  Enabled: true
129
132
  EnforcedStyle: single_quotes
@@ -135,6 +138,9 @@ Style/FrozenStringLiteralComment:
135
138
  Naming/MemoizedInstanceVariableName:
136
139
  Enabled: false
137
140
 
141
+ ThreadSafety/ClassAndModuleAttributes:
142
+ Enabled: false
143
+
138
144
  ThreadSafety/ClassInstanceVariable:
139
145
  Enabled: false
140
146
 
data/CHANGELOG.rst CHANGED
@@ -12,6 +12,88 @@ Versioning <https://semver.org/spec/v2.0.0.html>`__.
12
12
 
13
13
  <!--scriv-insert-here-->
14
14
 
15
+ .. _changelog-2.0.0.pre18:
16
+
17
+ 2.0.0.pre18 — 2025-10-05
18
+ ========================
19
+
20
+ Added
21
+ -----
22
+
23
+ - Added ``Familia.reconnect!`` method to refresh connection pools with current middleware configuration. This solves issues in test suites where middleware (like DatabaseLogger) is enabled after connection pools are created. The method clears the connection chain, increments the middleware version, and clears fiber-local connections, ensuring new connections include the latest middleware. See ``lib/familia/connection/middleware.rb:81-117``.
24
+
25
+ Changed
26
+ -------
27
+
28
+ - **BREAKING**: Implemented type-preserving JSON serialization for Horreum field values. Non-string values (Integer, Boolean, Float, nil, Hash, Array) are JSON-encoded for storage and JSON-decoded on retrieval. **Strings are stored as-is without JSON encoding** to avoid double-quoting and maintain Redis baseline simplicity. Type preservation is achieved through smart deserialization: values that parse as JSON restore to their original types, otherwise remain as strings.
29
+
30
+ - **BREAKING**: Changed default Hash key format from symbols to strings throughout the codebase (``symbolize: false`` default). This eliminates ambiguity with HTTP request parameters and IndifferentHash-style implementations, providing strict adherence to JSON parsing rules and avoiding key duplication issues.
31
+
32
+ - **BREAKING**: Fixed ``initialize_with_keyword_args`` to properly handle ``false`` and ``0`` values during object initialization. Previously, falsy values were incorrectly skipped due to truthiness checks. Now uses explicit nil checking with ``fetch`` to preserve all non-nil values including ``false`` and ``0``.
33
+
34
+ - **String serialization now uses JSON encoding**: All string values are JSON-encoded during storage (wrapped in quotes) for consistent type preservation. The lenient deserializer handles both new JSON-encoded strings and legacy plain strings automatically. PR #152
35
+
36
+ Removed
37
+ -------
38
+
39
+ - **BREAKING**: Removed ``dump_method`` and ``load_method`` configuration options from ``Familia::Base`` and ``Familia::Horreum::Definition``. JSON serialization is now hard-coded for consistency and type safety. Custom serialization methods are no longer supported.
40
+
41
+ Fixed
42
+ -----
43
+
44
+ - Fixed type coercion bugs where Integer fields (e.g., ``age: 35``) became Strings (``"35"``) and Boolean fields (e.g., ``active: true``) became Strings (``"true"``) after database round-trips. All primitive types now maintain their original types through ``find_by_dbkey``, ``refresh!``, and ``batch_update`` operations.
45
+
46
+ - Fixed ``deserialize_value`` to return all JSON-parsed types instead of filtering to Hash/Array only. This enables proper deserialization of primitive types (Integer, Boolean, Float, String) from Redis storage.
47
+
48
+ - Added JSON deserialization in ``find_by_dbkey`` using existing ``initialize_with_keyword_args_deserialize_value`` helper method to maintain DRY principles and ensure loaded objects receive properly typed field values rather than raw Redis strings.
49
+
50
+ - Optimized serialization to avoid double-encoding strings - strings stored directly in Redis as-is, only non-string types use JSON encoding. This reduces storage overhead and maintains Redis's string baseline semantics.
51
+
52
+ - Fixed encrypted fields with ``category: :encrypted`` appearing in ``to_h()`` output. These fields now correctly set ``loggable: false`` to prevent accidental exposure in logs, APIs, or external interfaces. PR #152
53
+
54
+ - Fixed middleware registration to only set ``@middleware_registered`` flag when middleware is actually enabled and registered. Previously, calling ``create_dbclient`` before enabling middleware would set the flag to ``true`` without registering anything, preventing later middleware enablement from working. The fix ensures ``register_middleware_once`` only sets the flag after successful registration. See ``lib/familia/connection/middleware.rb:124-146``.
55
+
56
+ Security
57
+ --------
58
+
59
+ - Encrypted fields defined via ``field :name, category: :encrypted`` now properly excluded from ``to_h()`` serialization, matching the security behavior of ``encrypted_field``. PR #152
60
+
61
+ Documentation
62
+ -------------
63
+
64
+ - Added comprehensive type preservation test suite (``try/unit/horreum/json_type_preservation_try.rb``) with 30 test cases covering Integer, Boolean, String, Float, Hash, Array, nested structures, nil handling, empty strings, zero values, round-trip consistency, ``batch_update``, and ``refresh!`` operations.
65
+
66
+ AI Assistance
67
+ -------------
68
+
69
+ - Claude Code (claude-sonnet-4-5) provided implementation guidance, identified the ``initialize_with_keyword_args`` falsy value bug, wrote comprehensive test suite, and coordinated multi-file changes across serialization, management, and base modules.
70
+
71
+ - Issue analysis, implementation guidance, test verification, and documentation for JSON serialization changes and encrypted field security fix.
72
+
73
+ - Claude Code (Sonnet 4.5) provided architecture analysis, implementation design, and identified critical issues through the second-opinion agent. Key contributions included recommending the simplified approach without pool shutdown lifecycle management, identifying the race condition risk in clearing ``@middleware_registered``, and suggesting the use of natural pool aging instead of explicit shutdown.
74
+
75
+ .. _changelog-2.0.0.pre17:
76
+
77
+ 2.0.0.pre17 — 2025-10-03
78
+ ========================
79
+
80
+ Added
81
+ -----
82
+
83
+ - **SortedSet#add**: Full ZADD option support (NX, XX, GT, LT, CH) for atomic conditional operations and accurate change tracking. This enables proper index management with timestamp preservation, update-only operations, conditional score updates, and analytics tracking. Closes issue #135.
84
+
85
+ Fixed
86
+ -----
87
+
88
+ - Restored objid provenance tracking when loading objects from Redis. The ``ObjectIdentifier`` feature now infers the generator type (:uuid_v7, :uuid_v4, :hex) from the objid format, enabling dependent features like ``ExternalIdentifier`` to derive external identifiers from loaded objects. PR #131
89
+
90
+ AI Assistance
91
+ -------------
92
+
93
+ - Claude Code assisted with implementing the ``infer_objid_generator`` method and updating the setter logic in ``lib/familia/features/object_identifier.rb``.
94
+
95
+ - Claude Code assisted with Redis ZADD option semantics research, mutual exclusivity validation design, comprehensive test case matrix creation (50+ test cases), and YAML documentation examples.
96
+
15
97
  .. _changelog-2.0.0.pre16:
16
98
 
17
99
  2.0.0.pre16 — 2025-09-30
data/CLAUDE.md CHANGED
@@ -92,6 +92,44 @@ Familia uses a modular feature system where features are mixed into classes:
92
92
 
93
93
  **Inheritance Chain**: `MyClass < Familia::Horreum` automatically extends `ClassMethods` and `Features`
94
94
 
95
+ **Common Pitfall: Overriding initialize**
96
+
97
+ ⚠️ **Do NOT override `initialize` without calling `super`** - this breaks related field initialization.
98
+
99
+ **Bad - will cause crashes:**
100
+ ```ruby
101
+ class User < Familia::Horreum
102
+ def initialize(email)
103
+ @email = email # Missing super! Related fields won't work
104
+ end
105
+ end
106
+ ```
107
+
108
+ **Good - use the `init` hook instead:**
109
+ ```ruby
110
+ class User < Familia::Horreum
111
+ def init(email = nil)
112
+ @email = email # Called after super, related fields work
113
+ end
114
+ end
115
+ ```
116
+
117
+ **Good - call super explicitly:**
118
+ ```ruby
119
+ class User < Familia::Horreum
120
+ def initialize(email = nil, **kwargs)
121
+ super(**kwargs) # ✓ Related fields initialized
122
+ @email = email
123
+ end
124
+ end
125
+ ```
126
+
127
+ **Why this matters**: Familia's `initialize` method calls `initialize_relatives` to set up DataType objects (lists, sets, etc.). Without calling `super`, these objects remain nil and you'll get helpful errors pointing to the missing super call.
128
+
129
+ **When to use each approach:**
130
+ - **Use `init` hook** (preferred): For simple initialization logic that doesn't need to intercept constructor arguments. The `init` method is called automatically after `super` with the same arguments passed to `new`.
131
+ - **Use explicit `super`**: When you need full control over initialization order or need to transform arguments before passing to parent. Remember to pass `**kwargs` to preserve keyword argument handling.
132
+
95
133
  **DataType Definition**: Use class methods to define keystore database-backed attributes:
96
134
  ```ruby
97
135
  class User < Familia::Horreum
@@ -116,8 +154,15 @@ end
116
154
 
117
155
  ### Important Implementation Notes
118
156
 
119
- **Field Initialization**: Objects can be initialized with positional args (brittle) or keyword args (robust). Keyword args are recommended.
120
- **Serialization**: Uses JSON by default but supports custom `serialize_value`/`deserialize_value` methods.
157
+ **Field Initialization**: Objects can be initialized with positional args (brittle) or keyword args (robust). Keyword args are recommended. All non-nil values including `false` and `0` are preserved during initialization.
158
+
159
+ **Serialization**: All field values are JSON-encoded for storage and JSON-decoded on retrieval to preserve Ruby types (Integer, Boolean, String, Float, Hash, Array, nil). This ensures type preservation across the Redis storage boundary. For example:
160
+ - `age: 35` (Integer) stores as `"35"` in Redis and loads back as Integer `35`
161
+ - `active: true` (Boolean) stores as `"true"` in Redis and loads back as Boolean `true`
162
+ - `metadata: {key: "value"}` (Hash) stores as JSON and loads back as Hash with proper types
163
+
121
164
  **Database Key Generation**: Automatic key generation using class name, identifier, and field/type names (aka dbkey). Pattern: `classname:identifier:fieldname`
165
+
122
166
  **Memory Efficiency**: Only non-nil values are stored in keystore database to optimize memory usage.
167
+
123
168
  **Thread Safety**: Data types are frozen after instantiation to ensure immutability.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- familia (2.0.0.pre16)
4
+ familia (2.0.0.pre18)
5
5
  benchmark (~> 0.4)
6
6
  connection_pool (~> 2.5)
7
7
  csv (~> 3.3)
data/README.md CHANGED
@@ -438,6 +438,19 @@ Contributions are welcome! Please feel free to submit a Pull Request.
438
438
  4. Push to the branch (`git push origin feature/amazing-feature`)
439
439
  5. Open a Pull Request
440
440
 
441
+ ### PR Compliance Checks
442
+
443
+ Pull requests are automatically reviewed by [Qodo Merge](https://qodo.ai) with compliance checks for:
444
+ - **Error Handling** - External API calls and database operations must have proper error handling
445
+ - **Test Coverage** - New features must include tests using the Tryouts framework
446
+ - **Changelog Fragments** - User-facing changes should include a changelog entry
447
+ - **Documentation** - API changes must update documentation
448
+ - **Backward Compatibility** - Breaking changes must be documented
449
+ - **Thread Safety** - Shared state must be properly synchronized
450
+ - **Database Key Naming** - Keys must follow Familia conventions
451
+
452
+ See [docs/qodo-merge-compliance.md](docs/qodo-merge-compliance.md) for details.
453
+
441
454
  ## License
442
455
 
443
456
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
data/bin/irb CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/bin/bash
2
2
 
3
- irb -Ilib -r familia -Itry -r helpers/test_helpers
3
+ irb -Ilib -r familia -Itry -r support/helpers/test_helpers
@@ -722,7 +722,7 @@ require 'familia'
722
722
 
723
723
  # Use separate Valkey/Redis database for tests
724
724
  Familia.configure do |config|
725
- config.redis_uri = ENV.fetch('REDIS_TEST_URI', 'redis://localhost:6379/15')
725
+ config.redis_uri = ENV.fetch('REDIS_TEST_URI', 'redis://localhost:2525/3')
726
726
  end
727
727
 
728
728
  module TestHelpers
@@ -50,17 +50,20 @@ customer.email = "admin@acme.com" # Custom method name
50
50
  customer.name!("Updated Corp") # Fast writer (immediate DB persistence)
51
51
  ```
52
52
 
53
- ### Field Categories
53
+ ### Special Field Types
54
54
 
55
- Fields can be categorized for special processing by features:
55
+ Use dedicated field methods provided by features for special field behaviors:
56
56
 
57
57
  ```ruby
58
58
  class Document < Familia::Horreum
59
- field :title # Regular field
60
- field :content, category: :encrypted # Will be processed by encrypted_fields feature
61
- field :api_key, category: :transient # Non-persistent field
62
- field :tags, category: :indexed # Custom category for indexing
63
- field :metadata, category: :json # Custom JSON serialization
59
+ feature :encrypted_fields
60
+ feature :transient_fields
61
+
62
+ field :title # Regular persistent field
63
+ encrypted_field :content # Encrypted storage
64
+ transient_field :api_key # Non-persistent (memory only)
65
+ field :tags # Regular field
66
+ field :metadata # Regular field
64
67
  end
65
68
  ```
66
69
 
@@ -285,27 +288,28 @@ order.priority_urgent? # => false
285
288
 
286
289
  ```ruby
287
290
  class Product < Familia::Horreum
288
- field :name, category: :searchable
289
- field :price, category: :numeric
290
- field :description, category: :text
291
- field :secret_key, category: :encrypted
291
+ feature :transient_fields
292
+
293
+ field :name
294
+ field :price
295
+ field :description
292
296
  transient_field :temp_data
293
297
  end
294
298
 
295
299
  # Get all field names
296
300
  Product.fields
297
- # => [:name, :price, :description, :secret_key, :temp_data]
301
+ # => [:name, :price, :description, :temp_data]
298
302
 
299
303
  # Get field types registry
300
304
  Product.field_types
301
305
  # => { name: #<FieldType...>, price: #<FieldType...>, ... }
302
306
 
303
- # Get fields by category
304
- Product.fields.select { |f| Product.field_types[f].category == :searchable }
305
- # => [:name]
307
+ # Get fields by category (read-only introspection)
308
+ Product.fields.select { |f| Product.field_types[f].category == :transient }
309
+ # => [:temp_data]
306
310
 
307
311
  # Get persistent vs transient fields
308
- Product.persistent_fields # => [:name, :price, :description, :secret_key]
312
+ Product.persistent_fields # => [:name, :price, :description]
309
313
  Product.transient_fields # => [:temp_data]
310
314
 
311
315
  # Field method mapping (for backward compatibility)
@@ -313,15 +317,24 @@ Product.field_method_map
313
317
  # => { name: :name, price: :price, secret_key: :secret_key, temp_data: :temp_data }
314
318
  ```
315
319
 
316
- ### Field Categories for Feature Processing
320
+ ### Using Field Type Category for Introspection
321
+
322
+ The `category` method on FieldType provides read-only metadata for introspection:
317
323
 
318
324
  ```ruby
319
- # Features can process fields by category
325
+ # Custom field type with category metadata
326
+ class SearchableFieldType < Familia::FieldType
327
+ def category
328
+ :searchable
329
+ end
330
+ end
331
+
332
+ # Features can process fields by inspecting their category
320
333
  module SearchableFieldsFeature
321
334
  def self.included(base)
322
335
  base.extend ClassMethods
323
336
 
324
- # Process all searchable fields
337
+ # Find all searchable fields by inspecting field type category
325
338
  searchable_fields = base.fields.select do |field|
326
339
  base.field_types[field].category == :searchable
327
340
  end
@@ -348,11 +361,17 @@ module SearchableFieldsFeature
348
361
  end
349
362
 
350
363
  class Product < Familia::Horreum
351
- feature :searchable_fields # Processes all :searchable category fields
364
+ feature :searchable_fields
352
365
 
353
- field :name, category: :searchable
354
- field :description, category: :searchable
355
- field :internal_id, category: :system
366
+ # Use custom field type with searchable category
367
+ def self.searchable_field(name, **options)
368
+ field_type = SearchableFieldType.new(name, **options)
369
+ register_field_type(field_type)
370
+ end
371
+
372
+ searchable_field :name
373
+ searchable_field :description
374
+ field :internal_id
356
375
  end
357
376
 
358
377
  # Auto-generated search methods available
@@ -733,10 +752,13 @@ end
733
752
  ### 1. Choose Appropriate Field Types
734
753
 
735
754
  ```ruby
736
- # Use built-in field types when possible
755
+ # Use dedicated field methods provided by features
737
756
  class User < Familia::Horreum
738
- field :name # Simple string field
739
- field :metadata, category: :json # For complex data
757
+ feature :transient_fields
758
+ feature :encrypted_fields
759
+
760
+ field :name # Simple persistent field
761
+ field :metadata # For complex data
740
762
  transient_field :temp_token # For runtime-only data
741
763
  encrypted_field :api_key # For sensitive data
742
764
  end
@@ -0,0 +1,58 @@
1
+ # Migrating Guide: v2.0.0-pre18
2
+
3
+ This version completes the JSON serialization implementation by removing the string-as-is optimization and fixes encrypted field visibility in serialization.
4
+
5
+ ## JSON Serialization for All Types
6
+
7
+ **What Changed:**
8
+
9
+ All field values (including strings) are now JSON-encoded during storage for consistent type preservation.
10
+
11
+ **Storage Format:**
12
+
13
+ ```ruby
14
+ # Before (v2.0.0-pre14):
15
+ HGET user:123 name
16
+ "John Doe" # Plain string
17
+
18
+ # After (v2.0.0-pre18):
19
+ HGET user:123 name
20
+ "\"John Doe\"" # JSON-encoded string
21
+ ```
22
+
23
+ **Migration:**
24
+
25
+ No migration needed. The deserializer automatically handles:
26
+ - **New format**: `"\"value\""` → `"value"`
27
+ - **Legacy format**: `"value"` → `"value"`
28
+
29
+ **Why This Matters:**
30
+
31
+ Prevents data corruption for edge cases:
32
+ - Badge `"007"` stays `"007"` (not converted to integer `7`)
33
+ - String `"true"` stays `"true"` (not converted to boolean)
34
+ - String `"null"` stays `"null"` (not converted to `nil`)
35
+
36
+ ## Encrypted Field Security Fix
37
+
38
+ **What Changed:**
39
+
40
+ Fields defined with `category: :encrypted` now correctly exclude encrypted data from `to_h()` output.
41
+
42
+ **Before:**
43
+ ```ruby
44
+ field :secret, category: :encrypted
45
+ user.to_h # => {"id" => "123", "secret" => {...}} # ❌ Exposed!
46
+ ```
47
+
48
+ **After:**
49
+ ```ruby
50
+ field :secret, category: :encrypted
51
+ user.to_h # => {"id" => "123"} # ✅ Secure
52
+ ```
53
+
54
+ Both `encrypted_field` and `field :name, category: :encrypted` now behave identically for security.
55
+
56
+ **Migration:**
57
+
58
+ No code changes needed. Review any code relying on encrypted fields appearing in `to_h()` output.
data/docs/overview.md CHANGED
@@ -708,7 +708,7 @@ when 'production'
708
708
  when 'development'
709
709
  Familia.uri = 'redis://localhost:6379/0'
710
710
  when 'test'
711
- Familia.uri = 'redis://localhost:6379/15'
711
+ Familia.uri = 'redis://localhost:2525/3'
712
712
  end
713
713
  ```
714
714
 
@@ -868,7 +868,7 @@ Familia.redis.keys('*') # List all keys (use carefully in production)
868
868
  require 'familia'
869
869
 
870
870
  # Use separate test database
871
- Familia.uri = 'redis://localhost:6379/15'
871
+ Familia.uri = 'redis://localhost:2525/3'
872
872
 
873
873
  # Setup encryption for tests
874
874
  test_keys = {
@@ -0,0 +1,96 @@
1
+ # Qodo Merge Compliance Configuration
2
+
3
+ This document describes the Qodo Merge (formerly PR-Agent) configuration for the Familia project.
4
+
5
+ ## Overview
6
+
7
+ Qodo Merge provides automated PR analysis, code reviews, and compliance checks. Our configuration enables two key compliance features:
8
+
9
+ 1. **Codebase Duplication Compliance** - Uses RAG (Retrieval-Augmented Generation) to check for duplicate code across related repositories
10
+ 2. **Custom Compliance** - Project-specific rules tailored to Familia's development practices
11
+
12
+ ## Configuration Files
13
+
14
+ ### pr_agent.toml
15
+
16
+ The main Qodo Merge configuration file located in the repository root. It includes:
17
+
18
+ - **Response Language**: Set to English for consistency
19
+ - **RAG Context Enrichment**: Enabled with related repositories (`delano/familia`, `delano/tryouts`, `delano/otto`)
20
+ - **Custom Compliance Path**: References our custom compliance checklist
21
+ - **Ignore Rules**: Excludes generated files and build artifacts from analysis
22
+
23
+ ### pr_compliance_checklist.yaml
24
+
25
+ Custom compliance rules specific to Familia development:
26
+
27
+ #### ErrorHandling
28
+ All external API calls and database operations must have proper error handling with try-catch blocks or appropriate error handling mechanisms.
29
+
30
+ #### TestCoverage
31
+ New features must include tests using the Tryouts framework. Test files should be in the `try/` directory following the `*_try.rb` or `*.try.rb` naming convention.
32
+
33
+ #### ChangelogFragment
34
+ User-facing changes must include a changelog fragment in the `changelog.d/` directory following RST format, or provide explicit justification for omission.
35
+
36
+ #### DocumentationUpdates
37
+ API changes must be reflected in documentation, including YARD comments for new public methods or updates to the `docs/` directory.
38
+
39
+ #### BackwardCompatibility
40
+ Changes must maintain backward compatibility or document breaking changes in migration guides with deprecation warnings.
41
+
42
+ #### ThreadSafety
43
+ Code handling shared state must be thread-safe with proper synchronization or clear documentation of thread-safety assumptions.
44
+
45
+ #### DatabaseKeyNaming
46
+ Database key generation must follow Familia conventions:
47
+ - Use the configured `delim` separator (default `:`)
48
+ - Avoid reserved keywords: `ttl`, `db`, `valkey`, `redis`
49
+ - Handle empty identifiers to prevent stack overflow
50
+
51
+ ## Interactive Commands
52
+
53
+ Team members can trigger on-demand Qodo Merge analysis in PR comments:
54
+
55
+ - `/analyze --review` - Run code review
56
+ - `/analyze --test` - Generate test suggestions
57
+ - `/improve` - Get improvement suggestions
58
+ - `/ask` - Ask questions about the PR
59
+
60
+ ## Compliance Status
61
+
62
+ In PR comments from `@qodo-merge-pro`, you'll see:
63
+
64
+ - 🟢 Green circle - Compliance check passed
65
+ - 🔴 Red circle - Compliance check failed with details
66
+ - ⚪ White circle - Compliance check not configured (should not appear with proper configuration)
67
+
68
+ ## References
69
+
70
+ - [Qodo Merge Configuration Options](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/)
71
+ - [RAG Context Enrichment Guide](https://qodo-merge-docs.qodo.ai/core-abilities/rag_context_enrichment/)
72
+ - [Compliance Guide](https://qodo-merge-docs.qodo.ai/tools/compliance/)
73
+ - [Best Practices](https://docs.qodo.ai/qodo-documentation/qodo-merge/features/best-practices)
74
+
75
+ ## Maintenance
76
+
77
+ ### Updating Compliance Rules
78
+
79
+ To add or modify compliance rules:
80
+
81
+ 1. Edit `pr_compliance_checklist.yaml`
82
+ 2. Ensure YAML syntax is valid: `ruby -r yaml -e "YAML.load_file('pr_compliance_checklist.yaml')"`
83
+ 3. Commit changes - they take effect immediately on new PRs
84
+
85
+ ### Updating Ignore Rules
86
+
87
+ To exclude additional files from analysis:
88
+
89
+ 1. Edit the `[ignore]` section in `pr_agent.toml`
90
+ 2. Use glob patterns to match file paths
91
+ 3. Test with new PRs to verify exclusions work as expected
92
+
93
+ ## Future Improvements (Optional)
94
+
95
+ - **Centralized Configuration**: Create a `pr-agent-settings` repository with `metadata.yaml` to share configuration across all repos
96
+ - **Wiki Configuration**: Enable repo wiki and create `.pr_agent.toml` page (wiki config takes precedence over local files)
@@ -1167,7 +1167,7 @@ require 'familia'
1167
1167
 
1168
1168
  # Use separate Valkey/Redis database for tests
1169
1169
  Familia.configure do |config|
1170
- config.redis_uri = ENV.fetch('REDIS_TEST_URI', 'redis://localhost:6379/15')
1170
+ config.redis_uri = ENV.fetch('REDIS_TEST_URI', 'redis://localhost:2525/3')
1171
1171
  end
1172
1172
 
1173
1173
  module TestHelpers
@@ -10,7 +10,7 @@ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
10
10
  require 'familia'
11
11
 
12
12
  # Configure connection
13
- Familia.uri = 'redis://localhost:6379/15'
13
+ Familia.uri = 'redis://localhost:2525/3'
14
14
 
15
15
  puts '=== Encrypted Fields Feature Examples ==='
16
16
  puts
@@ -10,7 +10,7 @@ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
10
10
  require 'familia'
11
11
 
12
12
  # Configure connection
13
- Familia.uri = 'redis://localhost:6379/15'
13
+ Familia.uri = 'redis://localhost:2525/3'
14
14
 
15
15
  puts '=== SafeDump Feature Examples ==='
16
16
  puts