kairos-chain 2.0.4 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b588bb2644a34f10c7879784f2b9d4e7a61626d5d810d9d6a47289b1325b2c40
4
- data.tar.gz: 19e2b7b74fd32902f23148cda0d81de5b5aacaaadab49b36678fe14518b81037
3
+ metadata.gz: 7256c06e2fd204672e04f33e2b88bed3f302188b6d97cb5fe736e142b84580bd
4
+ data.tar.gz: c95abbd55c084474595a81e257eee4a5ad08168b47c2d069669dfe8ca49c7ed7
5
5
  SHA512:
6
- metadata.gz: 9e9bb0bfd4ccdf847650358cb45478d182c8ad7721c78756aa8fb8b0ccbfeb3cb01c9e9ad38b4d8d192235cd4b2878fcd34161d29aa9abfeabee094d19d940fa
7
- data.tar.gz: cb4f6f5e7f4dc19bd23567b9905e1397d8df510a941c6df5d3f16f68a9265377b584bd7b7a96d28622a29a5e6cb47b794c7723573c23f9a3eaef6df2bfac4c42
6
+ metadata.gz: 9552b83a0ebb90e312837ddad5b0086d620be6c92a2e83fdb93d0cec6eb043dcc6b6f37254e52cb2dc9d6e276d7154a9256360487e45c0cf41c25597bd202e4c
7
+ data.tar.gz: 40636983d68a243b1ba7d7907c59550f6ec15e35ba234f6cd975a6b539f6a416b4da973388310e3bd877cc32ffe25e196ae223aeb736a027330b4a8325eab13a
data/CHANGELOG.md CHANGED
@@ -4,6 +4,15 @@ All notable changes to the `kairos-chain` gem will be documented in this file.
4
4
 
5
5
  This project follows [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## [2.0.5] - 2026-02-25
8
+
9
+ ### Fixed
10
+
11
+ - **Deadlock**: `PendingChanges#summary` caused `deadlock; recursive locking` by calling `includes_l0_change?`, `includes_promotion?`, `includes_demotion?` from within a `@mutex.synchronize` block. Separated lock acquisition (public API) from logic (private `_`-prefixed methods).
12
+ - **Atomicity**: `check_trigger_conditions` now executes within a single lock, preventing race conditions between individual predicate checks.
13
+
14
+ ---
15
+
7
16
  ## [2.0.4] - 2026-02-25
8
17
 
9
18
  ### Fixed
@@ -186,6 +195,8 @@ This project follows [Semantic Versioning](https://semver.org/).
186
195
  - Skill promotion with Persona Assembly
187
196
  - Tool guide and metadata system
188
197
 
198
+ [2.0.5]: https://github.com/masaomi/KairosChain_2026/compare/v2.0.4...v2.0.5
199
+ [2.0.4]: https://github.com/masaomi/KairosChain_2026/compare/v2.0.3...v2.0.4
189
200
  [2.0.3]: https://github.com/masaomi/KairosChain_2026/compare/v2.0.2...v2.0.3
190
201
  [2.0.2]: https://github.com/masaomi/KairosChain_2026/compare/v2.0.1...v2.0.2
191
202
  [2.0.1]: https://github.com/masaomi/KairosChain_2026/compare/v2.0.0...v2.0.1
@@ -57,36 +57,28 @@ module KairosMcp
57
57
  #
58
58
  # @return [Boolean] True if L0 changes exist
59
59
  def includes_l0_change?
60
- @mutex.synchronize do
61
- @changes.any? { |c| c[:layer] == 'L0' }
62
- end
60
+ @mutex.synchronize { _includes_l0_change? }
63
61
  end
64
62
 
65
63
  # Check if there are any promotions
66
64
  #
67
65
  # @return [Boolean] True if promotions exist
68
66
  def includes_promotion?
69
- @mutex.synchronize do
70
- @changes.any? { |c| c[:action] == 'promote' }
71
- end
67
+ @mutex.synchronize { _includes_promotion? }
72
68
  end
73
69
 
74
70
  # Check if there are any demotions
75
71
  #
76
72
  # @return [Boolean] True if demotions exist
77
73
  def includes_demotion?
78
- @mutex.synchronize do
79
- @changes.any? { |c| c[:action] == 'demote' || c[:action] == 'archive' }
80
- end
74
+ @mutex.synchronize { _includes_demotion? }
81
75
  end
82
76
 
83
77
  # Get L1 changes count
84
78
  #
85
79
  # @return [Integer] Number of L1 changes
86
80
  def l1_changes_count
87
- @mutex.synchronize do
88
- @changes.count { |c| c[:layer] == 'L1' }
89
- end
81
+ @mutex.synchronize { _l1_changes_count }
90
82
  end
91
83
 
92
84
  # Get L2 changes count
@@ -127,28 +119,7 @@ module KairosMcp
127
119
  #
128
120
  # @return [Hash] Summary with counts per layer and action
129
121
  def summary
130
- @mutex.synchronize do
131
- {
132
- total: @changes.size,
133
- by_layer: {
134
- L0: @changes.count { |c| c[:layer] == 'L0' },
135
- L1: @changes.count { |c| c[:layer] == 'L1' },
136
- L2: @changes.count { |c| c[:layer] == 'L2' }
137
- },
138
- by_action: {
139
- create: @changes.count { |c| c[:action] == 'create' },
140
- update: @changes.count { |c| c[:action] == 'update' },
141
- delete: @changes.count { |c| c[:action] == 'delete' },
142
- promote: @changes.count { |c| c[:action] == 'promote' },
143
- demote: @changes.count { |c| c[:action] == 'demote' },
144
- archive: @changes.count { |c| c[:action] == 'archive' },
145
- unarchive: @changes.count { |c| c[:action] == 'unarchive' }
146
- },
147
- has_l0_change: includes_l0_change?,
148
- has_promotion: includes_promotion?,
149
- has_demotion: includes_demotion?
150
- }
151
- end
122
+ @mutex.synchronize { _build_summary }
152
123
  end
153
124
 
154
125
  # Check trigger conditions for auto-commit
@@ -158,28 +129,71 @@ module KairosMcp
158
129
  def check_trigger_conditions(config)
159
130
  return { should_commit: false, trigger: nil } unless config
160
131
 
161
- # Check event-based triggers
162
- if config.dig('on_events', 'l0_change') && includes_l0_change?
132
+ @mutex.synchronize { _check_trigger_conditions(config) }
133
+ end
134
+
135
+ private
136
+
137
+ def _includes_l0_change?
138
+ @changes.any? { |c| c[:layer] == 'L0' }
139
+ end
140
+
141
+ def _includes_promotion?
142
+ @changes.any? { |c| c[:action] == 'promote' }
143
+ end
144
+
145
+ def _includes_demotion?
146
+ @changes.any? { |c| c[:action] == 'demote' || c[:action] == 'archive' }
147
+ end
148
+
149
+ def _l1_changes_count
150
+ @changes.count { |c| c[:layer] == 'L1' }
151
+ end
152
+
153
+ def _build_summary
154
+ {
155
+ total: @changes.size,
156
+ by_layer: {
157
+ L0: @changes.count { |c| c[:layer] == 'L0' },
158
+ L1: @changes.count { |c| c[:layer] == 'L1' },
159
+ L2: @changes.count { |c| c[:layer] == 'L2' }
160
+ },
161
+ by_action: {
162
+ create: @changes.count { |c| c[:action] == 'create' },
163
+ update: @changes.count { |c| c[:action] == 'update' },
164
+ delete: @changes.count { |c| c[:action] == 'delete' },
165
+ promote: @changes.count { |c| c[:action] == 'promote' },
166
+ demote: @changes.count { |c| c[:action] == 'demote' },
167
+ archive: @changes.count { |c| c[:action] == 'archive' },
168
+ unarchive: @changes.count { |c| c[:action] == 'unarchive' }
169
+ },
170
+ has_l0_change: _includes_l0_change?,
171
+ has_promotion: _includes_promotion?,
172
+ has_demotion: _includes_demotion?
173
+ }
174
+ end
175
+
176
+ def _check_trigger_conditions(config)
177
+ if config.dig('on_events', 'l0_change') && _includes_l0_change?
163
178
  return { should_commit: true, trigger: 'l0_change' }
164
179
  end
165
180
 
166
- if config.dig('on_events', 'promotion') && includes_promotion?
181
+ if config.dig('on_events', 'promotion') && _includes_promotion?
167
182
  return { should_commit: true, trigger: 'promotion' }
168
183
  end
169
184
 
170
- if config.dig('on_events', 'demotion') && includes_demotion?
185
+ if config.dig('on_events', 'demotion') && _includes_demotion?
171
186
  return { should_commit: true, trigger: 'demotion' }
172
187
  end
173
188
 
174
- # Check threshold-based triggers
175
189
  if config.dig('change_threshold', 'enabled')
176
190
  l1_threshold = config.dig('change_threshold', 'l1_changes') || 5
177
- if l1_changes_count >= l1_threshold
191
+ if _l1_changes_count >= l1_threshold
178
192
  return { should_commit: true, trigger: 'l1_threshold' }
179
193
  end
180
194
 
181
195
  total_threshold = config.dig('change_threshold', 'total_changes') || 10
182
- if total_changes_count >= total_threshold
196
+ if @changes.size >= total_threshold
183
197
  return { should_commit: true, trigger: 'total_threshold' }
184
198
  end
185
199
  end
@@ -1,4 +1,4 @@
1
1
  module KairosMcp
2
- VERSION = "2.0.4"
2
+ VERSION = "2.0.5"
3
3
  CHANGELOG_URL = "https://github.com/masaomi/KairosChain_2026/blob/main/CHANGELOG.md"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kairos-chain
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 2.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masa Hatakeyama