kairos-chain 3.26.0 → 3.27.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: efb171bcb7680f795a7132e8d2d68ffb5ca4574d298ca1ea47ac7d44b42398e8
4
- data.tar.gz: da787664c3683e38f960da502a395bdde91285550a9af8003b59c2cc5cd5cfef
3
+ metadata.gz: 0eb600b698a295c1d826f77fd01e7b557608b8771b1d40593406d6027b345d51
4
+ data.tar.gz: 6428da295ba73bcb338cfd545510cb14980288d381eac0e64eabaca9941ee354
5
5
  SHA512:
6
- metadata.gz: 1ed8251d8184beed84b8b3d424a32d5e81c667d30f304e90767aa7d80f279291ef2ce18ed129bd1ddc5c527d2ae03b153854c400f1d929f7acc17c50b43e930c
7
- data.tar.gz: f386544999d14dff7298ecbfcb2c5939adc593767d2dc10843bc09e2e143bc003f2616dc8f01f463bf22f8b75b3571007c7a4e389477e4401dd486377cab0f18
6
+ metadata.gz: 492d3c12ed01371fa093b1504fc137499a4ad1e9fac6168e3ccff8d9c3bbdc5c8b4bdf127bc8bfa6dae70f87f8bf4e8fa94a7ee8c6ecb9acd805193efede861d
7
+ data.tar.gz: 923e4189b8b60e1d313296513187143b63ea96ae9099e944b4ccb15ee72ec1dca82d6117bc235093dcac57a92eba82f4b6c15921992674edf57ffde2c2aa7a48
data/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@ 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.27.0] - 2026-05-19
8
+
9
+ ### Added — L1 frontmatter `relations.informed_by` on L2→L1 promotion (design v0.2)
10
+
11
+ `skills_promote` now auto-attaches an `informed_by` edge to the L1 frontmatter
12
+ `relations` list when promoting from L2, pointing to the source L2 context
13
+ (`v1:<session_id>/<source_name>`). Existing edges of any type are preserved
14
+ verbatim; the edge is omitted (field absent) when ancestor identification is
15
+ not possible. Design: `docs/drafts/l1_informed_by_field_design_v0.2_draft.md`
16
+ (multi-LLM review round 2: 4/5 APPROVE, philosophy-aligned).
17
+
18
+ - Backward compatible: legacy L1 entries without `relations` continue to load.
19
+ - Idempotent: re-promoting the same source does not duplicate the edge.
20
+ - No backfill of existing L1 entries (Inv 5 — forward-only).
21
+ - Read-side traversal of `informed_by` is deferred to a separate PR.
22
+
23
+ Tests: `test_informed_by_promotion.rb` (15/15). Regression
24
+ `test_dream_scan_promotion.rb` (30/30).
25
+
7
26
  ## [3.26.0] - 2026-05-12
8
27
 
9
28
  ### Added — consumer_project_root separation (design v0.2)
@@ -194,11 +194,18 @@ module KairosMcp
194
194
  target_name = args['target_name'] || args['source_name']
195
195
  reason = args['reason'] || "Promoted from #{from_layer} to #{to_layer}"
196
196
 
197
+ # Inv 3 (design v0.2): attach informed_by edge for identifiable L2→L1 promotion
198
+ content_to_write = source_content[:content]
199
+ if from_layer == 'L2' && to_layer == 'L1'
200
+ ancestor = build_l2_ancestor_ref(args['session_id'], args['source_name'])
201
+ content_to_write = inject_informed_by(content_to_write, ancestor) if ancestor
202
+ end
203
+
197
204
  case to_layer
198
205
  when 'L1'
199
- promote_to_l1(target_name, source_content[:content], reason)
206
+ promote_to_l1(target_name, content_to_write, reason)
200
207
  when 'L0'
201
- promote_to_l0(target_name, source_content[:content], reason)
208
+ promote_to_l0(target_name, content_to_write, reason)
202
209
  end
203
210
  end
204
211
 
@@ -334,6 +341,38 @@ module KairosMcp
334
341
  VALID_TRANSITIONS[from]&.include?(to) || false
335
342
  end
336
343
 
344
+ # Build a v1-tagged L2 ancestor reference from session + source name.
345
+ # Returns nil if either component is missing (Inv 3: identify 不能時は field 不在).
346
+ def build_l2_ancestor_ref(session_id, source_name)
347
+ return nil if session_id.nil? || session_id.to_s.empty?
348
+ return nil if source_name.nil? || source_name.to_s.empty?
349
+ "v1:#{session_id}/#{source_name}"
350
+ end
351
+
352
+ # Inject an informed_by edge into the frontmatter's `relations` list.
353
+ # Idempotent: if the same edge already exists, content is returned unchanged.
354
+ # Preserves any other existing edges and unknown edge types verbatim (Inv 2).
355
+ def inject_informed_by(content, ancestor_ref)
356
+ require_relative '../anthropic_skill_parser'
357
+ frontmatter, body = AnthropicSkillParser.extract_frontmatter(content)
358
+
359
+ relations = frontmatter['relations']
360
+ relations = [] unless relations.is_a?(Array)
361
+
362
+ new_edge = { 'type' => 'informed_by', 'target' => ancestor_ref }
363
+ already_present = relations.any? do |e|
364
+ e.is_a?(Hash) && e['type'] == 'informed_by' && e['target'] == ancestor_ref
365
+ end
366
+ return content if already_present
367
+
368
+ frontmatter['relations'] = relations + [new_edge]
369
+ AnthropicSkillParser.generate_content(frontmatter, body)
370
+ rescue StandardError => e
371
+ # Inv 1: absence is valid — never block promotion on a frontmatter mishap.
372
+ warn "[SkillsPromote] informed_by injection skipped: #{e.message}"
373
+ content
374
+ end
375
+
337
376
  def fetch_source_content(args)
338
377
  from_layer = args['from_layer']
339
378
  source_name = args['source_name']
@@ -1,4 +1,4 @@
1
1
  module KairosMcp
2
- VERSION = "3.26.0"
2
+ VERSION = "3.27.0"
3
3
  CHANGELOG_URL = "https://github.com/masaomi/KairosChain_2026/blob/main/CHANGELOG.md"
4
4
  end
@@ -29,6 +29,39 @@ Projection runs automatically:
29
29
 
30
30
  Run `/reload-plugins` after projection to activate new skills in Claude Code.
31
31
 
32
+ ## Cross-Project Projection (`kairos-chain mode project`)
33
+
34
+ Project an instruction mode from one KairosChain data directory into a *different* consumer project root.
35
+
36
+ ### Command shape
37
+
38
+ ```
39
+ kairos-chain mode project \
40
+ --data-dir /path/to/source/.kairos \
41
+ --project-root /path/to/consumer_project
42
+ ```
43
+
44
+ - `--data-dir`: where the mode body is read from (`<data-dir>/skills/<active_mode>.md`).
45
+ - `--project-root`: where `CLAUDE.md` and `.claude/kairos/instruction_mode.md` are written.
46
+ - When `--data-dir` points outside the consumer workspace, `--project-root` is **required** (no plausible cwd default). `data_dir == project_root` is refused (`CoincidenceRefused`, v3.26.0).
47
+
48
+ ### Which mode gets projected
49
+
50
+ The active mode is **not** chosen by the CLI — it is read from `instructions_mode` in `<data-dir>/skills/config.yml`. If that says `tutorial`, tutorial is projected even when `masa.md` exists in the same `skills/` directory.
51
+
52
+ To switch the active mode before projecting:
53
+
54
+ - Preferred: `instructions_update(mode: "masa")` MCP tool (records to blockchain).
55
+ - Direct: edit `instructions_mode:` in `<data-dir>/skills/config.yml`, then re-run `mode project`.
56
+
57
+ ### Drift between config and artifact
58
+
59
+ `<data-dir>/skills/config.yml` (`instructions_mode`) and `<consumer>/.claude/kairos/instruction_mode.md` can diverge silently if `mode project` is not re-run after a config change. The CLI output line `mode : <name> v<ver>` is the authoritative record of what was last projected — compare it against `instructions_mode` to detect drift.
60
+
61
+ ### After projection
62
+
63
+ Restart Claude Code in the consumer project. CLAUDE.md `@-imports` resolve only at session start; mid-session edits to the projected artifact do **not** reach Agent tool sub-agents.
64
+
32
65
  ## Available Tools
33
66
 
34
67
  <!-- AUTO_TOOLS -->
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kairos-chain
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.26.0
4
+ version: 3.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaomi Hatakeyama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-12 00:00:00.000000000 Z
11
+ date: 2026-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest