kairos-chain 3.47.0 → 3.50.0

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +130 -0
  3. data/bin/kairos-chain +30 -7
  4. data/lib/kairos_mcp/skillset.rb +10 -0
  5. data/lib/kairos_mcp/tool_registry.rb +42 -9
  6. data/lib/kairos_mcp/version.rb +1 -1
  7. data/templates/skillsets/chain_distillation/config/chain_distillation.yml +13 -0
  8. data/templates/skillsets/chain_distillation/lib/chain_distillation/canon.rb +44 -0
  9. data/templates/skillsets/chain_distillation/lib/chain_distillation/certificate.rb +308 -0
  10. data/templates/skillsets/chain_distillation/lib/chain_distillation/distiller.rb +305 -0
  11. data/templates/skillsets/chain_distillation/lib/chain_distillation/recorder.rb +144 -0
  12. data/templates/skillsets/chain_distillation/skillset.json +18 -0
  13. data/templates/skillsets/chain_distillation/test/test_chain_distillation.rb +464 -0
  14. data/templates/skillsets/chain_distillation/tools/cd_distill.rb +67 -0
  15. data/templates/skillsets/chain_distillation/tools/cd_revoke.rb +57 -0
  16. data/templates/skillsets/chain_distillation/tools/cd_verify.rb +56 -0
  17. data/templates/skillsets/confidentiality_guard/config/confidentiality_guard.yml +18 -0
  18. data/templates/skillsets/confidentiality_guard/config/profile.example.yml +43 -0
  19. data/templates/skillsets/confidentiality_guard/lib/confidentiality_guard/canon.rb +52 -0
  20. data/templates/skillsets/confidentiality_guard/lib/confidentiality_guard/policy.rb +152 -0
  21. data/templates/skillsets/confidentiality_guard/lib/confidentiality_guard/recorder.rb +117 -0
  22. data/templates/skillsets/confidentiality_guard/lib/confidentiality_guard/regime.rb +321 -0
  23. data/templates/skillsets/confidentiality_guard/lib/confidentiality_guard/surfaces.rb +131 -0
  24. data/templates/skillsets/confidentiality_guard/lib/confidentiality_guard/verdict.rb +100 -0
  25. data/templates/skillsets/confidentiality_guard/skillset.json +20 -0
  26. data/templates/skillsets/confidentiality_guard/test/test_cg_guard.rb +613 -0
  27. data/templates/skillsets/confidentiality_guard/tools/cg_status.rb +51 -0
  28. data/templates/skillsets/synoptis/bin/sda_verify.rb +260 -0
  29. data/templates/skillsets/synoptis/lib/synoptis/anchoring/aggregate_disclosure.rb +221 -0
  30. data/templates/skillsets/synoptis/lib/synoptis/anchoring/ec_group.rb +196 -0
  31. data/templates/skillsets/synoptis/lib/synoptis/anchoring/pedersen.rb +133 -0
  32. data/templates/skillsets/synoptis/lib/synoptis/anchoring/range_proof.rb +266 -0
  33. data/templates/skillsets/synoptis/test/test_sda_aggregate.rb +214 -0
  34. data/templates/skillsets/synoptis/test/test_sda_range_proof.rb +238 -0
  35. metadata +29 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e43541279a3d104b85372574c94f6fdf2d96188fb7de83d5a4d84c3f470634d7
4
- data.tar.gz: 21b58d11561dd6d4177a7aa3d3832bdfe4fbde80ff2da2af198662d655a6fc81
3
+ metadata.gz: 826aabda2632b42bb5e4c688f443616faf29b9b97daba55aa02fa6834bf1629d
4
+ data.tar.gz: 2a743cfa76eb0d56db2220ed40c11ea0cc52f88c9b16ed8dfb84855d54b15981
5
5
  SHA512:
6
- metadata.gz: 41bc6c95594567c2e80ed006ea2bd21e7926361bf3cfb14fdf5a6b0a4aac17b9dca3f65faf17be1a4e86b16ce3fb9285af121d747fcdeac66eca58857d4af0bd
7
- data.tar.gz: 77a5ac53384830598e90b408b4c737eb8549c219dfdeb47c38feb5939c46829c2b53dc9744da1a9914033521ff1fdf126f8d941989fe62857316863a75790e5f
6
+ metadata.gz: 0e0ab6e95d0f527e738053fe45e9899e761820809c0f26ab37dd55eacadf13b387b22737475a8685b894d095aa9ba4529df142ab3809adf917c2ff275b46f403
7
+ data.tar.gz: 1272d3d2ffd8cc80615dc1990346758982cb64cb78d947965d754d3ae5d0e148524044c8197efbb836e0ecf067cfcae69f51aa90a934a71da691525c0b190da2
data/CHANGELOG.md CHANGED
@@ -4,6 +4,136 @@ 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
+ ## [3.50.0] - 2026-07-23
8
+
9
+ ### Chain Distillation SkillSet — slice 1 (CD-1..CD-6)
10
+
11
+ New `chain_distillation` SkillSet implementing design v0.5 (review-converged
12
+ 5/6 APPROVE + persona unanimity): provenance-certified distillation of the
13
+ instance chain into distributable SkillSets.
14
+
15
+ - `cd_distill`: closed-world integer designation (genesis excluded,
16
+ decline-not-coerce), guard-judged distillate and certificate crossings
17
+ (separate, in order, single-encoded presentation), CD-6 constitutive
18
+ record before release (salted sdp-1-style commitments over the distillate
19
+ and the claim core excluding the record citation), content-independent
20
+ pre-assigned certificate identity, attestation-carrier seam
21
+ (`proof_id` = certificate identity), designation-overlap re-issuance
22
+ citation against then-revoked predecessors.
23
+ - `cd_verify`: full-citation positive grounding (claim-core commitment
24
+ opening, identity, designation digest, guard policy sha, distillate
25
+ commitment, predecessors, citation block hash) plus chain-identity /
26
+ head-binding checks; pinned checkability-status table with
27
+ both-direction mislabeling fatal; closed claim-core vocabulary at every
28
+ depth; revocation folds into validity.
29
+ - `cd_revoke`: identity-keyed chain-wide revocation, closed reason
30
+ vocabulary (`superseded|defective|withdrawn|other`).
31
+ - Requires an active confidentiality-guard regime (CD-1: decline, never
32
+ degrade). 60 design-constraint tests incl. production-wiring and
33
+ real-Chain regressions (KAIROS_DATA_DIR-isolated).
34
+
35
+ ### Confidentiality Guard — slice-2 first increment (distillation crossing)
36
+
37
+ - New `:distillation_outward` crossing class (`cd_release_distillate`,
38
+ `cd_release_certificate`): conjunctive per-destination verdict
39
+ (closed-world `distillation_crossings` profile designation AND content
40
+ classes), outward verdicts recorded pass or deny (CG-4); the general
41
+ outward class stays denied wholesale.
42
+ - Certificate-crossing verdict records cite the certificate identity
43
+ (identifier-only, CG-4-compatible).
44
+ - Template-layout require-path parity fix in `regime.rb` / `recorder.rb`.
45
+ - Guard test suite: 75 design-constraint + regression tests.
46
+
47
+ ## [3.49.1] - 2026-07-22
48
+
49
+ ### CLI fix — `skillset upgrade` messaging for non-core new SkillSets
50
+
51
+ `kairos-chain skillset upgrade --apply` always runs with `core_only: true`
52
+ (the plain CLI form has no way to pass explicit `names`), so a new,
53
+ non-core SkillSet (e.g. `confidentiality_guard`, `daemon_runtime`,
54
+ `kairos_hook_projector`) was never installed by `--apply`, regardless of
55
+ how many times it was run — but the check-mode display mislabeled these as
56
+ "files changed" and told the user to run `--apply`, which silently did
57
+ nothing for them.
58
+
59
+ - Detected upgrades are now split into "applicable" (existing-installed
60
+ diffs + core new SkillSets, which `--apply` does handle) and "manual"
61
+ (non-core new SkillSets, which require explicit
62
+ `kairos-chain skillset install <name>`). Both the check-mode listing and
63
+ the post-`--apply` summary report each group accurately.
64
+ - Added the missing `upgrade` line to `kairos-chain skillset -h`.
65
+
66
+ ## [3.49.0] - 2026-07-22
67
+
68
+ ### ZK aggregate reproducibility spike (AUD-L4, Phases 1+2) — KairosChain's first genuine zero-knowledge proof
69
+
70
+ Additive demonstrator in the `synoptis` SkillSet (candidate convention id
71
+ `sda-1` if later promoted). Proves, over a public DOI set, that an auditor's
72
+ published aggregate (mean reproducibility) is honestly computed from
73
+ per-item scores that stay secret — with each hidden score proven in-range
74
+ via a genuine zero-knowledge proof. Pure-Ruby secp256k1; no trusted setup;
75
+ no new runtime dependency (OpenSSL is a test-only oracle).
76
+
77
+ - Phase 1 — `ec_group.rb` (hand-rolled prime-order secp256k1, NUMS second
78
+ generator H), `pedersen.rb` (perfectly-hiding commitments, additive
79
+ homomorphism, aggregate opening + Σr-hiding Schnorr proof),
80
+ `aggregate_disclosure.rb` (SDP-2 dual-commitment score binding to rpr-1
81
+ endorsements, DOI-set commitment, mean verification).
82
+ - Phase 2 — `range_proof.rb` (`Synoptis::Anchoring::RangeProof`):
83
+ bit-decomposition range proof for s ∈ [0, 7] (3-bit band). Per-bit
84
+ Cramer-Damgård-Schoenmakers '94 Schnorr OR proofs (b ∈ {0,1}) plus the
85
+ reconstruction invariant Σ 2^j·B_j = C; Fiat-Shamir (SHA-256) with
86
+ metadata- and index-bound transcripts. Fail-closed verifier admission
87
+ (closed schema, type-strict vmax/bits, point/scalar canonicality,
88
+ identity rejection) closes range-escape and encoding-malleability.
89
+ - CLI: `sda_verify.rb` gains `commit`, `aggregate-verify`,
90
+ `aggregate-schnorr`, `binding`, `doi-set`, `range-verify`,
91
+ `full-audit-verify` (C1 coverage + C3 aggregate + C4 range in one pass).
92
+ - Tests: 93 new (52 Phase 1 + 41 Phase 2) incl. the mandatory forgery
93
+ negatives (an out-of-range 32000 score cannot yield an accepting proof);
94
+ scalar-mul cross-validated against OpenSSL. Existing suites unchanged
95
+ (507 total green).
96
+ - Design memos under `docs/drafts/`; design and implementation each
97
+ converged through philosophy-briefed multi-LLM review (impl round 2:
98
+ 6/6 APPROVE).
99
+
100
+ ## [3.48.0] - 2026-07-22
101
+
102
+ ### Confidentiality Guard SkillSet — slice 1 (CG-1..CG-6)
103
+
104
+ New `confidentiality_guard` SkillSet implementing design v0.3 (FROZEN,
105
+ review-converged). A fail-closed, selectable-off data-confidentiality regime
106
+ for enterprise environments. Slice 1 covers inward (L2/L1 write) and
107
+ restricted-storage-read surfaces; outward crossings and unmapped
108
+ resource-scheme reads are denied wholesale under the CG-1 coverage clause.
109
+
110
+ - `lib/confidentiality_guard/regime.rb`: regime lifecycle + tool-surface
111
+ interception via a `ToolRegistry` gate (verdict precedes effect, CG-2).
112
+ Activation is environment-level (`KAIROS_CONFIDENTIALITY_GUARD` env >
113
+ config), read at load time via the skillset `activation_hook` (independent
114
+ of tool instantiation) with an eager `cg_status` belt-and-suspenders call;
115
+ policy pinned at activation; activation AND cessation recorded; gate
116
+ registered only after the regime is active (no fail-open window).
117
+ - `policy.rb`: pinned, content-addressed policy profile; `File.realpath`-
118
+ matching path resolution (symlink- and `..`-safe, parity with the
119
+ external-tools readers). `surfaces.rb`: crossing classification with a
120
+ release-gated enrollment manifest. `verdict.rb`: deterministic LLM-free
121
+ conjunctive verdict (designation closed-world + content detection),
122
+ versioned verdict basis. `recorder.rb`: constitutive chain records bound
123
+ by salted commitments (sdp-1-aligned), never containing content; read
124
+ records carry the designation id, not the raw path. `canon.rb`: shared
125
+ canonical serialization faithful to false/nil and mixed string/symbol keys.
126
+ - `tools/cg_status.rb`: read-only regime-state tool (CG-1).
127
+ - 67 design-constraint + regression tests (`test/test_cg_guard.rb`); 75 as of the chain_distillation guard slice-2 first increment (distillation crossing).
128
+
129
+ Core (minimal, guard-enabling): `tool_registry.rb` adds `FailClosedError`
130
+ (re-raised by the loader, never swallowed), per-skillset isolated loading,
131
+ and fail-closed `activation_hook` invocation; `skillset.rb` adds the
132
+ `activation_hook` accessor. Impl review: 3 rounds with executable-probe
133
+ personas; every deployment-grounded finding (enabled-but-unguarded start,
134
+ copy source-read bypass, path-resolution parity, symlink+`..` bypass, loader
135
+ fail-closed) resolved.
136
+
7
137
  ## [3.47.0] - 2026-07-22
8
138
 
9
139
  ### Synoptis — selective disclosure sdp-1 (AUD-L4 slice 1)
data/bin/kairos-chain CHANGED
@@ -134,6 +134,12 @@ when 'skillset'
134
134
  when 'upgrade'
135
135
  apply = ARGV.delete('--apply')
136
136
  upgrades = manager.upgrade_check
137
+ # --apply always runs with core_only: true (no way to pass names from this
138
+ # CLI form), so a new, non-core SkillSet is NEVER installed by --apply,
139
+ # no matter how many times it is run. Split the two groups so the
140
+ # displayed guidance matches what --apply will actually do.
141
+ manual = upgrades.select { |u| u[:new_skillset] && !KairosMcp::SkillSetManager::CORE_SKILLSETS.include?(u[:name]) }
142
+ applicable = upgrades - manual
137
143
 
138
144
  if upgrades.empty?
139
145
  puts "All SkillSets are up to date."
@@ -144,6 +150,12 @@ when 'skillset'
144
150
  end
145
151
  puts "Done. #{results.size} SkillSet(s) upgraded."
146
152
 
153
+ if manual.any?
154
+ puts ""
155
+ puts "Not installed (optional, requires explicit approval):"
156
+ manual.each { |u| puts " kairos-chain skillset install #{u[:name]}" }
157
+ end
158
+
147
159
  # Re-project plugin artifacts if any SkillSets changed
148
160
  if results.any?
149
161
  begin
@@ -162,15 +174,25 @@ when 'skillset'
162
174
  end
163
175
  end
164
176
  else
165
- puts "SkillSet upgrades available:"
166
- puts ""
167
- upgrades.each do |u|
168
- label = u[:version_bump] ? "v#{u[:installed_version]} -> v#{u[:available_version]}" : "files changed"
169
- puts " #{u[:name]}: #{label}"
170
- u[:changed_files].each { |f| puts " Modified: #{f}" }
177
+ if applicable.any?
178
+ puts "SkillSet upgrades available:"
179
+ puts ""
180
+ applicable.each do |u|
181
+ label = u[:version_bump] ? "v#{u[:installed_version]} -> v#{u[:available_version]}" : "files changed"
182
+ puts " #{u[:name]}: #{label}"
183
+ u[:changed_files].each { |f| puts " Modified: #{f}" }
184
+ puts ""
185
+ end
186
+ puts "Run 'kairos-chain skillset upgrade --apply' to apply updates."
187
+ end
188
+
189
+ if manual.any?
190
+ puts "" if applicable.any?
191
+ puts "Optional SkillSets available (not auto-installed; require explicit approval):"
192
+ manual.each { |u| puts " #{u[:name]} v#{u[:available_version]} — #{u[:description]}" }
171
193
  puts ""
194
+ puts "Install with: kairos-chain skillset install <name>"
172
195
  end
173
- puts "Run 'kairos-chain skillset upgrade --apply' to apply updates."
174
196
  end
175
197
 
176
198
  when 'remove'
@@ -258,6 +280,7 @@ when 'skillset'
258
280
  puts " install <path> [--layer L0|L1|L2] Install a SkillSet from path"
259
281
  puts " enable <name> Enable a SkillSet"
260
282
  puts " disable <name> Disable a SkillSet"
283
+ puts " upgrade [--apply] Check for/apply SkillSet updates from gem templates"
261
284
  puts " remove <name> Remove a SkillSet"
262
285
  puts " info <name> Show SkillSet details"
263
286
  puts " package <name> Package a knowledge-only SkillSet as JSON archive"
@@ -87,6 +87,16 @@ module KairosMcp
87
87
  @metadata['config_files'] || []
88
88
  end
89
89
 
90
+ # Optional fail-closed activation hook: a fully-qualified class name
91
+ # whose `activate_on_load!` runs at skillset-load time, independent of
92
+ # whether any of the SkillSet's tools are instantiated. Used by
93
+ # fail-closed regimes (confidentiality_guard) so an enabled guard
94
+ # registers its enforcement even if no tool is ever constructed.
95
+ def activation_hook
96
+ name = @metadata['activation_hook']
97
+ name.is_a?(String) && !name.empty? ? name : nil
98
+ end
99
+
90
100
  def knowledge_dir_names
91
101
  @metadata['knowledge_dirs'] || []
92
102
  end
@@ -5,6 +5,12 @@ require_relative 'lifecycle_hook'
5
5
 
6
6
  module KairosMcp
7
7
  class ToolRegistry
8
+ # Raised by SkillSets whose activation must never be swallowed
9
+ # (fail-closed regimes, e.g. confidentiality_guard): the loader
10
+ # re-raises instead of degrading to a warn, so an enabled regime can
11
+ # never be silently skipped and leave the server unguarded.
12
+ class FailClosedError < StandardError; end
13
+
8
14
  # Authorization denial raised by registered gates
9
15
  class GateDeniedError < StandardError
10
16
  attr_reader :tool_name, :role
@@ -273,17 +279,44 @@ module KairosMcp
273
279
 
274
280
  manager = SkillSetManager.new
275
281
  manager.enabled_skillsets.each do |skillset|
276
- skillset.load!
277
- skillset.tool_class_names.each do |cls|
278
- # Phase 1.5: thread source attribution for capability_status manifest
279
- register_if_defined(cls, source: "skillset:#{skillset.name}")
280
- end
281
- # 24/7 v0.4 §2.3 register lifecycle hooks declared by this SkillSet.
282
- skillset.lifecycle_hooks.each do |hook_name, class_name|
283
- register_lifecycle_hook(hook_name, class_name, skillset_name: skillset.name)
282
+ # Per-skillset isolation: one failing SkillSet must not abort the
283
+ # loop and silently skip later ones (a fail-closed regime loaded
284
+ # later would otherwise never register its gate).
285
+ begin
286
+ skillset.load!
287
+ # Fail-closed activation hook (before tool registration): a
288
+ # regime that ships enabled must register its enforcement at load
289
+ # time, not as a side effect of some tool being instantiated.
290
+ # ANY failure to resolve or run the hook is fail-closed: a
291
+ # missing/typo'd hook constant must not degrade to a warn and
292
+ # leave an enabled regime unguarded.
293
+ if (hook = skillset.activation_hook)
294
+ begin
295
+ LifecycleHook.validate_class_name!(hook)
296
+ Object.const_get(hook).activate_on_load!(registry_class: self.class)
297
+ rescue FailClosedError
298
+ raise
299
+ rescue StandardError => e
300
+ raise FailClosedError,
301
+ "activation_hook '#{hook}' (skillset '#{skillset.name}') failed to activate: " \
302
+ "#{e.class}: #{e.message}"
303
+ end
304
+ end
305
+ skillset.tool_class_names.each do |cls|
306
+ # Phase 1.5: thread source attribution for capability_status manifest
307
+ register_if_defined(cls, source: "skillset:#{skillset.name}")
308
+ end
309
+ # 24/7 v0.4 §2.3 — register lifecycle hooks declared by this SkillSet.
310
+ skillset.lifecycle_hooks.each do |hook_name, class_name|
311
+ register_lifecycle_hook(hook_name, class_name, skillset_name: skillset.name)
312
+ end
313
+ rescue LifecycleHook::Conflict, FailClosedError
314
+ raise # never swallow — integrity/fail-closed regimes depend on detection
315
+ rescue StandardError => e
316
+ warn "[ToolRegistry] Failed to load SkillSet '#{skillset.name}': #{e.message}"
284
317
  end
285
318
  end
286
- rescue LifecycleHook::Conflict
319
+ rescue LifecycleHook::Conflict, FailClosedError
287
320
  raise # never swallow — Bootstrap integrity depends on detection
288
321
  rescue StandardError => e
289
322
  warn "[ToolRegistry] Failed to load SkillSet tools: #{e.message}"
@@ -1,4 +1,4 @@
1
1
  module KairosMcp
2
- VERSION = "3.47.0"
2
+ VERSION = "3.50.0"
3
3
  CHANGELOG_URL = "https://github.com/masaomi/KairosChain_2026/blob/main/CHANGELOG.md"
4
4
  end
@@ -0,0 +1,13 @@
1
+ # Chain Distillation SkillSet configuration (design v0.5 slice 1).
2
+ #
3
+ # The distiller carries no activation switch of its own: CD-1 couples
4
+ # certified distillation to the confidentiality guard regime, whose
5
+ # activation is environment-level (KAIROS_CONFIDENTIALITY_GUARD / the
6
+ # guard's own config). With the regime inactive the distiller declines.
7
+ #
8
+ # The guard-side designation for the distillation crossings lives in the
9
+ # GUARD's profile (distillation_crossings key) — the guard track owns
10
+ # that surface; see confidentiality_guard/config/profile.example.yml.
11
+ distillation:
12
+ # Reserved for slice-2 (distribution) settings.
13
+ {}
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module KairosMcp
6
+ module SkillSets
7
+ module ChainDistillation
8
+ # Canonical serialization for commitments and claim-core hashing
9
+ # (design v0.5 CD-2/CD-6). Same faithfulness rules as the guard's
10
+ # Canon (impl review R1 lineage): false/nil preserved distinctly;
11
+ # mixed string/symbol keys both emitted, sorted by stringified key
12
+ # with original order as tiebreak. One encoder for designation
13
+ # digests, artifact commitments, and claim-core commitments so no
14
+ # two bindings can drift apart.
15
+ module Canon
16
+ module_function
17
+
18
+ def canonical(obj)
19
+ case obj
20
+ when Hash
21
+ entries = obj.map.with_index { |(k, v), i| [k.to_s, i, v] }
22
+ entries.sort_by! { |key, i, _| [key, i] }
23
+ "{#{entries.map { |key, _, v| "#{key.to_json}:#{canonical(v)}" }.join(',')}}"
24
+ when Array
25
+ "[#{obj.map { |v| canonical(v) }.join(',')}]"
26
+ else
27
+ obj.to_json
28
+ end
29
+ end
30
+
31
+ def stringify(obj)
32
+ case obj
33
+ when Hash
34
+ obj.each_with_object({}) { |(k, v), acc| acc[k.to_s] = stringify(v) }
35
+ when Array
36
+ obj.map { |v| stringify(v) }
37
+ else
38
+ obj
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end