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 +4 -4
- data/CHANGELOG.md +11 -0
- data/lib/kairos_mcp/state_commit/pending_changes.rb +55 -41
- data/lib/kairos_mcp/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7256c06e2fd204672e04f33e2b88bed3f302188b6d97cb5fe736e142b84580bd
|
|
4
|
+
data.tar.gz: c95abbd55c084474595a81e257eee4a5ad08168b47c2d069669dfe8ca49c7ed7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
162
|
-
|
|
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') &&
|
|
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') &&
|
|
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
|
|
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
|
|
196
|
+
if @changes.size >= total_threshold
|
|
183
197
|
return { should_commit: true, trigger: 'total_threshold' }
|
|
184
198
|
end
|
|
185
199
|
end
|
data/lib/kairos_mcp/version.rb
CHANGED