familia 2.12.0 → 2.14.0.pre1

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 (237) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +5 -0
  3. data/.github/workflows/ci.yml +86 -0
  4. data/.github/workflows/claude-code-review.yml +9 -10
  5. data/.github/workflows/claude.yml +1 -1
  6. data/.github/workflows/release-gem.yml +1 -1
  7. data/.gitignore +1 -0
  8. data/.rubocop.yml +3 -0
  9. data/AGENTS.md +23 -1
  10. data/CHANGELOG.rst +264 -147
  11. data/Gemfile +8 -3
  12. data/Gemfile.lock +28 -28
  13. data/README.md +3 -0
  14. data/changelog.d/README.md +6 -4
  15. data/changelog.d/fragments/.gitkeep +0 -0
  16. data/changelog.d/scriv.ini +1 -0
  17. data/docs/guides/datatype-collections.md +60 -2
  18. data/docs/guides/encryption.md +3 -2
  19. data/docs/guides/feature-encrypted-fields.md +31 -6
  20. data/docs/guides/feature-external-identifiers.md +4 -0
  21. data/docs/guides/feature-relationships-indexing.md +254 -3
  22. data/docs/guides/feature-relationships-participation.md +6 -0
  23. data/docs/guides/feature-relationships.md +6 -0
  24. data/docs/guides/getting-started.md +8 -3
  25. data/docs/guides/index.md +18 -1
  26. data/docs/guides/optimized-loading.md +1 -1
  27. data/docs/{schema-validation.md → guides/schema-validation.md} +14 -6
  28. data/docs/investigation/memory-audit.md +34 -0
  29. data/docs/investigation/rebuild-memory-incident.md +136 -0
  30. data/docs/investigation/v2-passphrase-not-bound-to-ciphertext.md +163 -0
  31. data/docs/migrating/dbkey-encoding.md +233 -0
  32. data/docs/migrating/identifier-secret.md +36 -0
  33. data/docs/migrating/key-patterns-and-index-rebuilds.md +303 -0
  34. data/docs/migrating/refresh.md +187 -0
  35. data/docs/migrating/runtime-dependencies.md +175 -0
  36. data/docs/migrating/transaction-replies.md +350 -0
  37. data/docs/overview.md +39 -25
  38. data/docs/reference/api-technical.md +252 -21
  39. data/docs/reference/migrations-specification.md +704 -0
  40. data/docs/reference/transaction_safety.md +371 -0
  41. data/docs/security/2026-07-19-audit.md +61 -34
  42. data/docs/security/2026-07-26-audit.md +113 -0
  43. data/docs/security/2026-07-30-audit.md +38 -10
  44. data/docs/security/2026-08-06-audit.md +110 -0
  45. data/docs/security/2026-09-04-audit.md +106 -0
  46. data/docs/security/README.md +25 -0
  47. data/examples/encrypted_fields.rb +9 -8
  48. data/examples/encryption_upgrade_proof/README.md +6 -3
  49. data/examples/encryption_upgrade_proof/phase1_gem_upgrade_no_libsodium.rb +4 -1
  50. data/examples/encryption_upgrade_proof/phase2_libsodium_enabled.rb +11 -7
  51. data/examples/json_usage_patterns.rb +3 -2
  52. data/familia.gemspec +3 -4
  53. data/lib/familia/atomic_operations.rb +410 -36
  54. data/lib/familia/connection/behavior.rb +22 -0
  55. data/lib/familia/connection/handlers.rb +39 -0
  56. data/lib/familia/connection/operations.rb +13 -3
  57. data/lib/familia/connection/scope.rb +299 -0
  58. data/lib/familia/connection/transaction_core.rb +12 -3
  59. data/lib/familia/connection.rb +113 -0
  60. data/lib/familia/data_type/class_methods.rb +33 -0
  61. data/lib/familia/data_type/collection_base.rb +1 -1
  62. data/lib/familia/data_type/connection.rb +5 -0
  63. data/lib/familia/data_type/serialization.rb +35 -12
  64. data/lib/familia/data_type/types/counter.rb +21 -2
  65. data/lib/familia/data_type/types/hashkey.rb +153 -60
  66. data/lib/familia/data_type/types/json_stringkey.rb +75 -26
  67. data/lib/familia/data_type/types/listkey.rb +75 -16
  68. data/lib/familia/data_type/types/lock.rb +54 -2
  69. data/lib/familia/data_type/types/sorted_set.rb +193 -97
  70. data/lib/familia/data_type/types/stringkey.rb +30 -5
  71. data/lib/familia/data_type/types/unsorted_set.rb +54 -18
  72. data/lib/familia/data_type.rb +122 -22
  73. data/lib/familia/encryption/encrypted_data.rb +40 -10
  74. data/lib/familia/encryption/manager.rb +15 -8
  75. data/lib/familia/encryption/stored_envelope.rb +28 -0
  76. data/lib/familia/encryption/strict_base64.rb +41 -0
  77. data/lib/familia/encryption.rb +11 -8
  78. data/lib/familia/errors.rb +141 -9
  79. data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +66 -14
  80. data/lib/familia/features/expiration/extensions.rb +7 -1
  81. data/lib/familia/features/expiration.rb +70 -27
  82. data/lib/familia/features/external_identifier.rb +31 -10
  83. data/lib/familia/features/housekeeping/enforce_collection_caps.rb +4 -0
  84. data/lib/familia/features/housekeeping.rb +4 -0
  85. data/lib/familia/features/object_identifier.rb +7 -0
  86. data/lib/familia/features/relationships/indexing/multi_index_generators.rb +442 -65
  87. data/lib/familia/features/relationships/indexing/rebuild_strategies.rb +113 -99
  88. data/lib/familia/features/relationships/indexing/record_key_ownership.rb +501 -0
  89. data/lib/familia/features/relationships/indexing/unique_index_generators.rb +97 -20
  90. data/lib/familia/features/relationships/indexing.rb +71 -13
  91. data/lib/familia/features/relationships/participation/participant_methods.rb +22 -6
  92. data/lib/familia/features/relationships/participation/staged_operations.rb +10 -0
  93. data/lib/familia/features/relationships/participation/target_methods.rb +33 -8
  94. data/lib/familia/features/relationships/participation/through_model_operations.rb +23 -0
  95. data/lib/familia/features/relationships/participation.rb +41 -10
  96. data/lib/familia/features/relationships.rb +14 -0
  97. data/lib/familia/features/schema_validation.rb +8 -0
  98. data/lib/familia/field_type.rb +10 -2
  99. data/lib/familia/horreum/atomic_write.rb +8 -4
  100. data/lib/familia/horreum/connection.rb +4 -1
  101. data/lib/familia/horreum/database_commands.rb +28 -7
  102. data/lib/familia/horreum/definition.rb +80 -0
  103. data/lib/familia/horreum/management/audit.rb +443 -73
  104. data/lib/familia/horreum/management/audit_report.rb +22 -4
  105. data/lib/familia/horreum/management/repair.rb +89 -35
  106. data/lib/familia/horreum/management.rb +235 -69
  107. data/lib/familia/horreum/persistence.rb +335 -56
  108. data/lib/familia/horreum/related_fields.rb +248 -29
  109. data/lib/familia/horreum/serialization.rb +102 -15
  110. data/lib/familia/horreum.rb +211 -49
  111. data/lib/familia/index_descriptor.rb +28 -2
  112. data/lib/familia/logging.rb +8 -4
  113. data/lib/familia/migration/base.rb +22 -4
  114. data/lib/familia/migration/model.rb +77 -5
  115. data/lib/familia/migration/pipeline.rb +18 -1
  116. data/lib/familia/migration/rake_tasks.rb +4 -1
  117. data/lib/familia/migration/registry.rb +135 -43
  118. data/lib/familia/migration/runner.rb +26 -1
  119. data/lib/familia/schema_registry.rb +22 -1
  120. data/lib/familia/thread_safety/instrumented_mutex.rb +5 -2
  121. data/lib/familia/utils.rb +193 -1
  122. data/lib/familia/verifiable_identifier.rb +60 -25
  123. data/lib/familia/version.rb +1 -1
  124. data/lib/familia.rb +0 -1
  125. data/lib/middleware/database_logger.rb +29 -0
  126. data/try/bug_fixes/binary_dbkey_log_messages_try.rb +194 -0
  127. data/try/bug_fixes/binary_dbkey_update_expiration_try.rb +135 -0
  128. data/try/bug_fixes/binary_dbkey_watch_abort_message_try.rb +66 -0
  129. data/try/bug_fixes/binary_identifier_non_ascii_prefix_try.rb +152 -0
  130. data/try/bug_fixes/binary_identifier_serialize_value_debug_try.rb +98 -0
  131. data/try/bug_fixes/binary_scope_id_instance_scoped_audit_try.rb +88 -0
  132. data/try/bug_fixes/glob_prefix_key_patterns_try.rb +262 -0
  133. data/try/bug_fixes/hashkey_refresh_read_only_try.rb +104 -0
  134. data/try/bug_fixes/horreum_refresh_absent_fields_try.rb +124 -0
  135. data/try/bug_fixes/horreum_refresh_aliased_identifier_try.rb +120 -0
  136. data/try/bug_fixes/horreum_refresh_exception_safety_try.rb +140 -0
  137. data/try/bug_fixes/horreum_refresh_identifier_forms_try.rb +226 -0
  138. data/try/bug_fixes/horreum_refresh_identity_try.rb +254 -0
  139. data/try/bug_fixes/index_bucket_key_audits_try.rb +268 -0
  140. data/try/bug_fixes/invalid_scope_id_index_tracker_try.rb +108 -0
  141. data/try/bug_fixes/invalid_scope_id_nested_scope_audit_try.rb +85 -0
  142. data/try/bug_fixes/invalid_scope_id_non_ascii_value_audit_try.rb +92 -0
  143. data/try/bug_fixes/invalid_utf8_field_value_index_try.rb +115 -0
  144. data/try/bug_fixes/invalid_utf8_long_field_value_warning_try.rb +71 -0
  145. data/try/bug_fixes/multi_byte_delimiter_ownership_try.rb +90 -0
  146. data/try/bug_fixes/multi_index_blank_value_buckets_try.rb +341 -0
  147. data/try/bug_fixes/multi_index_blank_value_other_index_try.rb +109 -0
  148. data/try/bug_fixes/multi_index_rebuild_glob_scope_try.rb +370 -0
  149. data/try/bug_fixes/multi_index_record_ownership_try.rb +540 -0
  150. data/try/bug_fixes/multi_index_tail_index_name_ownership_try.rb +87 -0
  151. data/try/bug_fixes/object_key_type_scans_try.rb +223 -0
  152. data/try/bug_fixes/partial_write_index_maintenance_try.rb +19 -4
  153. data/try/bug_fixes/participation_entry_invalid_utf8_try.rb +118 -0
  154. data/try/bug_fixes/refresh_missing_key_try.rb +160 -0
  155. data/try/bug_fixes/refresh_operation_mode_try.rb +60 -0
  156. data/try/bug_fixes/unique_index_guard_identifier_bytes_try.rb +136 -0
  157. data/try/bug_fixes/unique_index_integer_identifier_try.rb +95 -0
  158. data/try/edge_cases/legacy_data_detection/deserialization_edge_cases_try.rb +2 -1
  159. data/try/edge_cases/legacy_data_detection/deserialization_log_identifier_try.rb +197 -0
  160. data/try/edge_cases/legacy_data_detection/deserialization_log_redaction_try.rb +144 -0
  161. data/try/edge_cases/legacy_data_detection/deserialize_value_override_try.rb +211 -0
  162. data/try/edge_cases/legacy_data_detection/find_by_id_legacy_string_try.rb +76 -0
  163. data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +1 -0
  164. data/try/features/encrypted_fields/envelope_provenance_try.rb +151 -0
  165. data/try/features/encrypted_fields/identifier_precondition_try.rb +80 -0
  166. data/try/features/encryption/algorithm_upgrade_try.rb +5 -3
  167. data/try/features/encryption/bundled_gem_independence_try.rb +99 -0
  168. data/try/features/encryption/encrypted_data_valid_logging_try.rb +145 -0
  169. data/try/features/encryption/envelope_encoding_validation_try.rb +135 -0
  170. data/try/features/expiration/long_ttl_try.rb +196 -0
  171. data/try/features/external_identifier/external_identifier_try.rb +24 -5
  172. data/try/features/relationships/indexing_rebuild_try.rb +60 -0
  173. data/try/features/relationships/multi_index_ownership_concurrent_declaration_try.rb +115 -0
  174. data/try/features/relationships/rebuild_via_scan_try.rb +115 -0
  175. data/try/features/relationships/relationships_performance_try.rb +13 -8
  176. data/try/features/relationships/unique_index_fallback_try.rb +132 -0
  177. data/try/features/schema_registry_try.rb +63 -0
  178. data/try/integration/connection/connection_scope_try.rb +594 -0
  179. data/try/integration/familia_extended_try.rb +1 -1
  180. data/try/integration/futures/admin_futures_try.rb +82 -0
  181. data/try/integration/futures/conditional_write_scripting_try.rb +100 -0
  182. data/try/integration/futures/expiration_futures_try.rb +113 -0
  183. data/try/integration/futures/features_futures_try.rb +70 -0
  184. data/try/integration/futures/hashkey_futures_try.rb +353 -0
  185. data/try/integration/futures/horreum_management_futures_try.rb +149 -0
  186. data/try/integration/futures/horreum_persistence_futures_try.rb +177 -0
  187. data/try/integration/futures/listkey_futures_try.rb +264 -0
  188. data/try/integration/futures/migration_futures_try.rb +166 -0
  189. data/try/integration/futures/related_field_predicates_futures_try.rb +101 -0
  190. data/try/integration/futures/relationships_futures_try.rb +469 -0
  191. data/try/integration/futures/scalar_futures_try.rb +416 -0
  192. data/try/integration/futures/sorted_set_futures_try.rb +320 -0
  193. data/try/integration/futures/subsecond_expiration_futures_try.rb +145 -0
  194. data/try/integration/futures/unsorted_set_futures_try.rb +187 -0
  195. data/try/integration/persistence_operations_try.rb +1 -0
  196. data/try/integration/transaction_safety_core_try.rb +6 -5
  197. data/try/integration/transaction_safety_workflow_try.rb +8 -7
  198. data/try/integration/verifiable_identifier_try.rb +255 -0
  199. data/try/investigation/memory_leak_proof.rb +20 -13
  200. data/try/migration/model_try.rb +44 -0
  201. data/try/migration/schema_validation_try.rb +217 -0
  202. data/try/performance/transaction_safety_benchmark_try.rb +51 -27
  203. data/try/support/debugging/debug_aad_process.rb +3 -2
  204. data/try/support/debugging/debug_concealed_internal.rb +1 -0
  205. data/try/support/debugging/debug_concealed_reveal.rb +1 -0
  206. data/try/support/debugging/debug_context_aad.rb +1 -0
  207. data/try/support/debugging/debug_context_simple.rb +1 -0
  208. data/try/support/debugging/debug_cross_context.rb +1 -0
  209. data/try/support/debugging/debug_database_load.rb +1 -0
  210. data/try/support/debugging/debug_encrypted_json_check.rb +1 -0
  211. data/try/support/debugging/debug_encrypted_json_step_by_step.rb +1 -0
  212. data/try/support/debugging/debug_exists_lifecycle.rb +1 -0
  213. data/try/support/debugging/debug_field_decrypt.rb +1 -0
  214. data/try/support/debugging/debug_fresh_cross_context.rb +1 -0
  215. data/try/support/debugging/debug_load_path.rb +1 -0
  216. data/try/support/debugging/debug_method_resolution.rb +1 -0
  217. data/try/support/debugging/debug_provider.rb +1 -0
  218. data/try/support/debugging/debug_secure_behavior.rb +1 -0
  219. data/try/support/debugging/debug_test_design.rb +1 -0
  220. data/try/support/helpers/fresh_ruby.rb +28 -0
  221. data/try/support/helpers/test_helpers.rb +5 -4
  222. data/try/thread_safety/instrumented_mutex_exclusion_try.rb +88 -0
  223. data/try/unit/atomic_operations_try.rb +523 -3
  224. data/try/unit/core/escape_glob_try.rb +107 -0
  225. data/try/unit/core/runtime_dependencies_try.rb +56 -0
  226. data/try/unit/horreum/base_try.rb +8 -5
  227. data/try/unit/horreum/related_field_inheritance_snapshot_try.rb +122 -0
  228. data/try/unit/horreum/related_field_lifecycle_try.rb +1362 -0
  229. data/try/unit/horreum/serialization_try.rb +7 -0
  230. data/try/unit/utils/future_aware_helpers_try.rb +95 -2
  231. metadata +98 -32
  232. data/changelog.d/fragments/20260725_202500_delano_282_unsaved_index_guard.md +0 -7
  233. data/changelog.d/fragments/20260725_213000_delano_282_index_scope_tracker.md +0 -18
  234. data/changelog.d/fragments/20260728_120000_delano_365_stale_tracker_prune.rst +0 -30
  235. data/docs/qodo-merge-compliance.md +0 -96
  236. data/docs/transaction_safety.md +0 -215
  237. /data/docs/{1106-participates_in-bidirectional-solution.md → investigation/participates_in-bidirectional-solution.md} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d860c29966392e82cf54d842d457353d6a7268c3bf5378e25af9cb850f59d37c
4
- data.tar.gz: 87fc36560a6cd68ffb614ef6b3ab11625300ebed8433508739f1ab4633f5b9ff
3
+ metadata.gz: 78abdfef8c91211092845604967187b510a3b01f8b00772340cfb1c6ff081819
4
+ data.tar.gz: 8e982398843fb0c227be798af2c3b6de60b2daf40a6d9e8791ac4c122e586f55
5
5
  SHA512:
6
- metadata.gz: 15b5c9028503566db28d179052982d3a38617463753ea360f22ea49eeb86d3fc896352f18c73a703fe62d3fd5a6cdcf65f254dab284a7671f3b9a0b9db413acb
7
- data.tar.gz: 633e8ae2bab11aaf362791f23f68ea7f0287e1388c38850200809c5b43ed79ae59039492258927023ea91821d39243a18c9eaa5a63d8c068fb011edc99120468
6
+ metadata.gz: 0d612da7f16d268eb3b214a43cfa8f53c26e7766e70294ce3dabd134e2ca1c065726811f87c0e4dccb2aaacb463aba05a3e13148c7d8b6578933361c1c62c9e8
7
+ data.tar.gz: 39a032c23215875127fb97cdcbb7501ee28a9e624df60e81ab5feab700feeb1fdeae98df28bfbf660271d622aa77a74a3004ea9a4b8061345e0972e40ecb4094
@@ -13,3 +13,8 @@ updates:
13
13
  directory: "/" # Location of package manifests
14
14
  schedule:
15
15
  interval: "weekly"
16
+ ignore:
17
+ # dry-configurable 1.4.0 requires Ruby >= 3.3. Remove with Ruby 3.2
18
+ # support (see the Gemfile).
19
+ - dependency-name: "dry-configurable"
20
+ versions: [">= 1.4"]
@@ -13,6 +13,92 @@ permissions:
13
13
  contents: read
14
14
 
15
15
  jobs:
16
+ # The repo's own bundle includes development and test gems, which can supply
17
+ # a library that familia requires but does not declare (base64 arrived this
18
+ # way, through ruby-prof). This job bundles familia alone, as an application
19
+ # does, and fails if it cannot be required or if Ruby warns that a required
20
+ # library is leaving the default gems.
21
+ consumer-load:
22
+ timeout-minutes: 10
23
+
24
+ runs-on: ubuntu-24.04
25
+
26
+ strategy:
27
+ fail-fast: false
28
+ matrix:
29
+ ruby: ["3.2", "3.3", "3.4", "4.0"]
30
+
31
+ steps:
32
+ - uses: actions/checkout@v7
33
+ - name: Set up Ruby
34
+ uses: ruby/setup-ruby@v1
35
+ with:
36
+ ruby-version: ${{ matrix.ruby }}
37
+
38
+ - name: Require familia from a bundle that contains only familia
39
+ run: |
40
+ consumer="$RUNNER_TEMP/consumer"
41
+ mkdir -p "$consumer"
42
+ cd "$consumer"
43
+ printf "source 'https://rubygems.org'\ngem 'familia', path: '%s'\n" "$GITHUB_WORKSPACE" > Gemfile
44
+ bundle install
45
+ if ! out=$(bundle exec ruby -e 'require "familia"; puts "familia #{Familia::VERSION} loaded"' 2>&1); then
46
+ echo "$out"
47
+ echo "::error::require 'familia' failed in a bundle that contains only familia"
48
+ exit 1
49
+ fi
50
+ echo "$out"
51
+ if grep -q "loaded from the standard library" <<<"$out"; then
52
+ echo "::error::familia requires a library that is leaving Ruby's default gems without declaring it in familia.gemspec"
53
+ exit 1
54
+ fi
55
+
56
+ # An application can resolve any release familia.gemspec allows, not only
57
+ # the newest one consumer-load gets. This job pins each runtime dependency
58
+ # to the lowest release the gemspec allows and fails if familia, or
59
+ # json_schemer (which familia requires on first schema validation), cannot
60
+ # be required. Ruby 3.4 is the first release that raises LoadError under
61
+ # Bundler for libraries that left the default gems (base64, bigdecimal).
62
+ # Warnings are not checked here: oj 3.16.2 to 3.16.4 warn about ostruct
63
+ # but load, and consumer-load checks warnings with the newest releases.
64
+ consumer-load-lowest:
65
+ timeout-minutes: 10
66
+
67
+ runs-on: ubuntu-24.04
68
+
69
+ steps:
70
+ - uses: actions/checkout@v7
71
+ - name: Set up Ruby
72
+ uses: ruby/setup-ruby@v1
73
+ with:
74
+ ruby-version: "3.4"
75
+
76
+ - name: Require familia with the lowest dependency releases it allows
77
+ run: |
78
+ consumer="$RUNNER_TEMP/consumer-lowest"
79
+ mkdir -p "$consumer"
80
+ cd "$consumer"
81
+ ruby - "$GITHUB_WORKSPACE" > Gemfile <<'RUBY'
82
+ workspace = ARGV.fetch(0)
83
+ spec = Dir.chdir(workspace) { Gem::Specification.load('familia.gemspec') }
84
+ puts "source 'https://rubygems.org'"
85
+ puts "gem 'familia', path: #{workspace.dump}"
86
+ spec.runtime_dependencies.each do |dep|
87
+ found, = Gem::SpecFetcher.fetcher.spec_for_dependency(dep)
88
+ lowest = found.map { |s, _source| s.version }.min or abort "no release satisfies #{dep}"
89
+ puts "gem #{dep.name.dump}, #{lowest.to_s.dump}"
90
+ end
91
+ RUBY
92
+ cat Gemfile
93
+ bundle install
94
+ probe='require "familia"; require "json_schemer"; puts "familia #{Familia::VERSION} and json_schemer #{JSONSchemer::VERSION} loaded"'
95
+ if ! out=$(bundle exec ruby -e "$probe" 2>&1); then
96
+ echo "$out"
97
+ echo "::error::familia or json_schemer failed to load with the lowest dependency releases familia.gemspec allows"
98
+ exit 1
99
+ fi
100
+ echo "$out"
101
+
16
102
  build:
17
103
  timeout-minutes: 10
18
104
 
@@ -48,7 +48,7 @@ jobs:
48
48
 
49
49
  - name: Run Claude Code Review
50
50
  id: claude-review
51
- uses: anthropics/claude-code-action@be7b93b1907a4abad570368f3c74b6fe3807510b # v1.0.183
51
+ uses: anthropics/claude-code-action@d70510b174a1244958df0b03166a54912811f3e6 # v1.0.264
52
52
  with:
53
53
  claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
54
54
 
@@ -62,17 +62,18 @@ jobs:
62
62
  claude_args: |
63
63
  --model ${{ inputs.model || vars.CLAUDE_MODEL || 'claude-opus-4-6' }}
64
64
  --fallback-model ${{ vars.CLAUDE_FALLBACK_MODEL || 'claude-sonnet-4-6' }}
65
- --allowedTools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"
65
+ --allowedTools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"
66
66
 
67
- # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
67
+ # A bare `prompt` puts the action in agent mode, which creates no tracking
68
+ # comment, so use_sticky_comment alone did nothing and every push got a
69
+ # fresh `gh pr comment`. track_progress forces tag mode: the action owns
70
+ # one tracking comment, use_sticky_comment finds and reuses it on later
71
+ # pushes, and Claude writes the review into it via the action's built-in
72
+ # comment tool. The prompt becomes <custom_instructions> in tag mode.
73
+ track_progress: true
68
74
  use_sticky_comment: true
69
75
 
70
- # v1 renamed direct_prompt -> prompt. The REPO/PR NUMBER header is the
71
- # format the migration guide calls for so Claude reviews the right PR.
72
76
  prompt: |
73
- REPO: ${{ github.repository }}
74
- PR NUMBER: ${{ github.event.pull_request.number }}
75
-
76
77
  Please review this pull request and provide feedback on:
77
78
  - Code quality and best practices
78
79
  - Potential bugs or issues
@@ -81,5 +82,3 @@ jobs:
81
82
  - Test coverage
82
83
 
83
84
  Use the repository's AGENTS.md for guidance on style and conventions. Be constructive and helpful in your feedback.
84
-
85
- Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
@@ -32,7 +32,7 @@ jobs:
32
32
 
33
33
  - name: Run Claude Code
34
34
  id: claude
35
- uses: anthropics/claude-code-action@be7b93b1907a4abad570368f3c74b6fe3807510b # v1.0.183
35
+ uses: anthropics/claude-code-action@d70510b174a1244958df0b03166a54912811f3e6 # v1.0.264
36
36
  with:
37
37
  claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
38
 
@@ -158,4 +158,4 @@ jobs:
158
158
  echo "Releasing familia ${gem_version} from tag ${RELEASE_TAG}"
159
159
 
160
160
  - name: Build and push gem to RubyGems
161
- uses: rubygems/release-gem@052cc82692552de3ef2b81fd670e41d13cba8092 # v1.4.0
161
+ uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1
data/.gitignore CHANGED
@@ -18,6 +18,7 @@
18
18
  dump.rdb
19
19
  appendonlydir
20
20
  data
21
+ doc
21
22
  log
22
23
  tmp
23
24
  vendor
data/.rubocop.yml CHANGED
@@ -30,6 +30,9 @@ AllCops:
30
30
  - "rspec/**/*.rb"
31
31
  - "tmp/**/*.rb"
32
32
  - "try/**/*.rb"
33
+ # Setting Exclude here replaces RuboCop's default list, which excludes
34
+ # vendor/. CI installs gems into vendor/bundle inside the checkout.
35
+ - "vendor/**/*"
33
36
 
34
37
  #
35
38
  # Trailing commas
data/AGENTS.md CHANGED
@@ -11,6 +11,8 @@ Guidance for AI coding agents working in this repository.
11
11
 
12
12
  ### Testing (Tryouts v3)
13
13
 
14
+ Use `valkey-server try/valkey.conf` to start the test redis.
15
+
14
16
  Each file has optional setup, testcases, and optional teardown. A testcase is a
15
17
  `##` description line, Ruby code, then one or more expectation comments
16
18
  (`#=>`, `#==>`, `#=:>`, `#=!>`, ...). The last expression is the result.
@@ -171,8 +173,9 @@ in one MULTI/EXEC; collection mutations auto-route into the open transaction via
171
173
  `Fiber[:familia_transaction]`. Constraints:
172
174
 
173
175
  - All related DataTypes must share the parent's `logical_database`, else `Familia::CrossDatabaseError` (fall back to `save_with_collections`). MULTI/EXEC is single-database only.
174
- - Cannot nest inside another `transaction`/`atomic_write` (`Familia::OperationModeError`).
176
+ - Cannot nest inside another `transaction`/`atomic_write` or run inside a `pipelined` block (`Familia::OperationModeError`).
175
177
  - Collection return values inside the block are `Redis::Future` — do not inspect before EXEC.
178
+ - Methods that need a reply to continue (iterators, finders and loaders, `fetch`, `refresh!`, the partial writers) raise `Familia::OperationModeError` inside the block. The policy and method lists are in docs/reference/transaction_safety.md, rule 4.
176
179
 
177
180
  **Factory — `build` for create-and-populate:**
178
181
 
@@ -203,3 +206,22 @@ last-write timestamps (ZADD score), not a registry.
203
206
  DataType instances are frozen (immutable). Configure module-level settings once
204
207
  at startup, before threads spawn. `Familia.start_monitoring!` tracks contention.
205
208
  Tests and contention patterns live in `try/thread_safety/`.
209
+
210
+ ## Project claims and source authority
211
+
212
+ ### Attribution
213
+
214
+ Do not infer project terminology or guarantees from repetition. Before attributing a claim to the project, locate an authoritative primary source and provide its exact wording. Treat delivery notes, commit messages, agent output, and documents created or modified during the current task as leads, not evidence. If the wording is absent, call it an interpretation or proposal. Never place paraphrases in quotation marks.
215
+
216
+ ### Authoritative sources
217
+
218
+ Authoritative sources must be identified explicitly; repository presence alone does not confer authority. Accepted specifications and ADRs may establish project claims only within their stated scope. Delivery notes, commit messages, issue discussions, summaries, and agent-authored text are non-authoritative unless an authoritative source incorporates them explicitly.
219
+
220
+ ### Normative claims
221
+
222
+ For normative claims concerning security, privacy, compatibility, persistence, or data loss:
223
+
224
+ 1. Cite the authoritative source and its exact wording.
225
+ 2. Distinguish quotations, paraphrases, interpretations, and proposals.
226
+ 3. Do not use material created or modified during the current task to validate that task’s claims.
227
+ 4. If no authoritative wording exists, report the claim as unsupported.