kairos-chain 3.94.0 → 3.96.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 (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +153 -0
  3. data/bin/kairos-chain +2 -0
  4. data/lib/kairos_mcp/capability.rb +20 -4
  5. data/lib/kairos_mcp/skillset.rb +21 -0
  6. data/lib/kairos_mcp/skillset_manager.rb +58 -13
  7. data/lib/kairos_mcp/tools/capability_status.rb +3 -1
  8. data/lib/kairos_mcp/tools/system_upgrade.rb +2 -0
  9. data/lib/kairos_mcp/version.rb +1 -1
  10. data/templates/knowledge/design_to_implementation_workflow/design_to_implementation_workflow.md +4 -1
  11. data/templates/knowledge/multi_llm_review_workflow/multi_llm_review_workflow.md +155 -31
  12. data/templates/skillsets/agent/bin/agent_harvest.rb +28 -0
  13. data/templates/skillsets/agent/bin/agent_policy_report.rb +26 -0
  14. data/templates/skillsets/agent/config/policies/default_2026_10_20.rb +34 -0
  15. data/templates/skillsets/agent/hooks/agent_hook.rb +139 -0
  16. data/templates/skillsets/agent/lib/agent/confinement.rb +107 -239
  17. data/templates/skillsets/agent/lib/agent/dsl.rb +219 -0
  18. data/templates/skillsets/agent/lib/agent/guard.rb +799 -0
  19. data/templates/skillsets/agent/lib/agent/harvest.rb +145 -0
  20. data/templates/skillsets/agent/lib/agent/hooks.rb +785 -0
  21. data/templates/skillsets/agent/lib/agent/journal.rb +118 -0
  22. data/templates/skillsets/agent/lib/agent/policies.rb +153 -0
  23. data/templates/skillsets/agent/lib/agent/policy_report.rb +665 -0
  24. data/templates/skillsets/agent/lib/agent/precedents.rb +154 -0
  25. data/templates/skillsets/agent/lib/agent/review.rb +507 -0
  26. data/templates/skillsets/agent/lib/agent/run.rb +497 -0
  27. data/templates/skillsets/agent/lib/agent/service.rb +1661 -0
  28. data/templates/skillsets/agent/lib/agent/stand_in.rb +274 -0
  29. data/templates/skillsets/agent/lib/agent/templates.rb +131 -0
  30. data/templates/skillsets/agent/lib/agent/transcript.rb +134 -0
  31. data/templates/skillsets/agent/lib/agent.rb +34 -22
  32. data/templates/skillsets/agent/plugin/SKILL.md +150 -171
  33. data/templates/skillsets/agent/plugin/hooks.json +94 -0
  34. data/templates/skillsets/agent/report_kit/KIT_SHA256.txt +5 -0
  35. data/templates/skillsets/agent/report_kit/check.py +23 -0
  36. data/templates/skillsets/agent/report_kit/kit.py +364 -0
  37. data/templates/skillsets/agent/report_kit/make_report_deck.py +159 -0
  38. data/templates/skillsets/agent/report_kit/render.py +19 -0
  39. data/templates/skillsets/agent/report_kit/viz.py +203 -0
  40. data/templates/skillsets/agent/skillset.json +99 -14
  41. data/templates/skillsets/agent/test/test_agent1_dsl.rb +89 -0
  42. data/templates/skillsets/agent/test/test_agent1_guard.rb +127 -0
  43. data/templates/skillsets/agent/test/test_agent1_hooks_service.rb +401 -0
  44. data/templates/skillsets/agent/test/test_agent1_journal_run.rb +93 -0
  45. data/templates/skillsets/agent/test/test_agent1_policy_report.rb +475 -0
  46. data/templates/skillsets/agent/test/test_agent1_r1_check.rb +571 -0
  47. data/templates/skillsets/agent/test/test_agent1_r1_guard.rb +475 -0
  48. data/templates/skillsets/agent/test/test_agent1_r1_hookscript.rb +410 -0
  49. data/templates/skillsets/agent/test/test_agent1_r1_lifecycle.rb +556 -0
  50. data/templates/skillsets/agent/test/test_agent1_r1_report.rb +588 -0
  51. data/templates/skillsets/agent/test/test_agent1_r1_review.rb +689 -0
  52. data/templates/skillsets/agent/test/test_agent1_r1_words.rb +614 -0
  53. data/templates/skillsets/agent/test/test_agent1_r1b_fixes.rb +258 -0
  54. data/templates/skillsets/agent/test/test_agent1_r2_guard.rb +565 -0
  55. data/templates/skillsets/agent/test/test_agent1_r2_words.rb +349 -0
  56. data/templates/skillsets/agent/test/test_agent1_r2v_checkreview.rb +725 -0
  57. data/templates/skillsets/agent/test/test_agent1_r2v_decisions.rb +756 -0
  58. data/templates/skillsets/agent/test/test_agent1_r2v_progress.rb +539 -0
  59. data/templates/skillsets/agent/test/test_agent1_r2v_sessions.rb +770 -0
  60. data/templates/skillsets/agent/test/test_agent1_r3_guard.rb +354 -0
  61. data/templates/skillsets/agent/test/test_agent1_r3_words.rb +367 -0
  62. data/templates/skillsets/agent/test/test_agent1_r3v_checkreview.rb +854 -0
  63. data/templates/skillsets/agent/test/test_agent1_r3v_guardwords.rb +730 -0
  64. data/templates/skillsets/agent/test/test_agent1_r3v_lifecycle.rb +1096 -0
  65. data/templates/skillsets/agent/test/test_agent1_selfreview_fixes.rb +75 -0
  66. data/templates/skillsets/agent/test/test_agent1_stand_in_precedents.rb +113 -0
  67. data/templates/skillsets/agent/test/test_agent1_v06.rb +1154 -0
  68. data/templates/skillsets/agent/tools/agent_advance.rb +51 -0
  69. data/templates/skillsets/agent/tools/agent_finish.rb +50 -0
  70. data/templates/skillsets/agent/tools/agent_items.rb +56 -0
  71. data/templates/skillsets/agent/tools/agent_start.rb +17 -224
  72. data/templates/skillsets/agent/tools/agent_status.rb +9 -89
  73. data/templates/skillsets/agent/tools/agent_stop.rb +8 -122
  74. data/templates/skillsets/introspection/lib/introspection/safety_inspector.rb +28 -14
  75. data/templates/skillsets/llm_client/lib/llm_client/adapter.rb +7 -2
  76. data/templates/skillsets/llm_client/lib/llm_client/call_router.rb +8 -2
  77. data/templates/skillsets/llm_client/lib/llm_client/claude_code_adapter.rb +30 -5
  78. data/templates/skillsets/llm_client/lib/llm_client/cli_failure.rb +123 -0
  79. data/templates/skillsets/llm_client/lib/llm_client/codex_adapter.rb +6 -3
  80. data/templates/skillsets/llm_client/lib/llm_client/cursor_adapter.rb +5 -3
  81. data/templates/skillsets/llm_client/skillset.json +1 -1
  82. data/templates/skillsets/llm_client/test/test_cli_failure.rb +263 -0
  83. data/templates/skillsets/llm_client/test/test_no_fallback_and_isolation.rb +113 -0
  84. data/templates/skillsets/llm_client/tools/llm_call.rb +21 -3
  85. data/templates/skillsets/multi_llm_review/config/multi_llm_review.yml +19 -0
  86. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/build_review_bundle.rb +8 -1
  87. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/consensus.rb +20 -4
  88. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/dispatcher.rb +5 -1
  89. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/feedback_formatter.rb +119 -1
  90. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/observer_set.rb +7 -3
  91. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/persona_assembly.rb +26 -7
  92. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/roster_health.rb +127 -0
  93. data/templates/skillsets/multi_llm_review/skillset.json +3 -3
  94. data/templates/skillsets/multi_llm_review/test/test_feedback_formatter.rb +1 -1
  95. data/templates/skillsets/multi_llm_review/test/test_non_claude_host.rb +455 -0
  96. data/templates/skillsets/multi_llm_review/test/test_tool_wiring.rb +1 -1
  97. data/templates/skillsets/multi_llm_review/tools/multi_llm_review.rb +103 -34
  98. data/templates/skillsets/multi_llm_review/tools/multi_llm_review_collect.rb +16 -11
  99. data/templates/skillsets/multi_llm_review/tools/multi_llm_review_wait.rb +24 -4
  100. metadata +61 -62
  101. data/templates/skillsets/agent/bin/agent_distill.rb +0 -124
  102. data/templates/skillsets/agent/bin/agent_rule.rb +0 -215
  103. data/templates/skillsets/agent/bin/agent_shadow_judge.rb +0 -70
  104. data/templates/skillsets/agent/bin/agent_step_worker.rb +0 -321
  105. data/templates/skillsets/agent/config/agent.yml +0 -171
  106. data/templates/skillsets/agent/lib/agent/act_classification.rb +0 -336
  107. data/templates/skillsets/agent/lib/agent/act_classification.yml +0 -54
  108. data/templates/skillsets/agent/lib/agent/admission.rb +0 -384
  109. data/templates/skillsets/agent/lib/agent/adoption.rb +0 -340
  110. data/templates/skillsets/agent/lib/agent/advance_gate.rb +0 -357
  111. data/templates/skillsets/agent/lib/agent/answer_ruling.rb +0 -491
  112. data/templates/skillsets/agent/lib/agent/cognitive_loop.rb +0 -452
  113. data/templates/skillsets/agent/lib/agent/delegation.rb +0 -372
  114. data/templates/skillsets/agent/lib/agent/delegation_table.yml +0 -44
  115. data/templates/skillsets/agent/lib/agent/distill_run.rb +0 -197
  116. data/templates/skillsets/agent/lib/agent/distiller.rb +0 -313
  117. data/templates/skillsets/agent/lib/agent/distiller_prompt.rb +0 -130
  118. data/templates/skillsets/agent/lib/agent/mandate_adapter.rb +0 -69
  119. data/templates/skillsets/agent/lib/agent/mediator.rb +0 -211
  120. data/templates/skillsets/agent/lib/agent/message_format.rb +0 -33
  121. data/templates/skillsets/agent/lib/agent/native_body/main.rb +0 -166
  122. data/templates/skillsets/agent/lib/agent/native_body/model_client.rb +0 -135
  123. data/templates/skillsets/agent/lib/agent/native_body/spend_meter.rb +0 -131
  124. data/templates/skillsets/agent/lib/agent/native_body/tool_layer.rb +0 -195
  125. data/templates/skillsets/agent/lib/agent/point_facts.rb +0 -231
  126. data/templates/skillsets/agent/lib/agent/review_hint.rb +0 -84
  127. data/templates/skillsets/agent/lib/agent/session.rb +0 -282
  128. data/templates/skillsets/agent/lib/agent/shadow_judge.rb +0 -564
  129. data/templates/skillsets/agent/lib/agent/staging.rb +0 -267
  130. data/templates/skillsets/agent/lib/agent/step_delegation.rb +0 -450
  131. data/templates/skillsets/agent/lib/agent/trigger_validator.rb +0 -69
  132. data/templates/skillsets/agent/lib/agent/verdict.rb +0 -177
  133. data/templates/skillsets/agent/plugin/agents/monitor.md +0 -24
  134. data/templates/skillsets/agent/test/test_agent_act_hardening.rb +0 -488
  135. data/templates/skillsets/agent/test/test_agent_admission.rb +0 -112
  136. data/templates/skillsets/agent/test/test_agent_allowlist.rb +0 -724
  137. data/templates/skillsets/agent/test/test_agent_answer_rulings.rb +0 -949
  138. data/templates/skillsets/agent/test/test_agent_capability_discovery.rb +0 -307
  139. data/templates/skillsets/agent/test/test_agent_complexity_review.rb +0 -852
  140. data/templates/skillsets/agent/test/test_agent_confinement.rb +0 -184
  141. data/templates/skillsets/agent/test/test_agent_distillation.rb +0 -539
  142. data/templates/skillsets/agent/test/test_agent_guard_integration.rb +0 -218
  143. data/templates/skillsets/agent/test/test_agent_guard_verdict_record.rb +0 -446
  144. data/templates/skillsets/agent/test/test_agent_halt_semantics.rb +0 -370
  145. data/templates/skillsets/agent/test/test_agent_human_mark_gate.rb +0 -486
  146. data/templates/skillsets/agent/test/test_agent_interruption_resilience.rb +0 -729
  147. data/templates/skillsets/agent/test/test_agent_m1.rb +0 -329
  148. data/templates/skillsets/agent/test/test_agent_m2.rb +0 -625
  149. data/templates/skillsets/agent/test/test_agent_m3.rb +0 -719
  150. data/templates/skillsets/agent/test/test_agent_m4.rb +0 -545
  151. data/templates/skillsets/agent/test/test_agent_native_body.rb +0 -788
  152. data/templates/skillsets/agent/test/test_agent_shadow_judge.rb +0 -1233
  153. data/templates/skillsets/agent/test/test_agent_verdict.rb +0 -119
  154. data/templates/skillsets/agent/test/test_agent_worker_exit_and_review_parse.rb +0 -622
  155. data/templates/skillsets/agent/test/test_agent_worker_process.rb +0 -386
  156. data/templates/skillsets/agent/test/test_decide_prompt_contract.rb +0 -158
  157. data/templates/skillsets/agent/test/test_review_hint.rb +0 -168
  158. data/templates/skillsets/agent/tools/agent_execute.rb +0 -627
  159. data/templates/skillsets/agent/tools/agent_step.rb +0 -3909
  160. data/templates/skillsets/agent/tools/agent_wait.rb +0 -195
  161. data/templates/skillsets/agent/tools/operator_report.rb +0 -130
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05055bfa3f7c4377e2e88011754c85d8d87c690e07f19837c4dca5a0c1cd033c
4
- data.tar.gz: 48b9c8a70d27304e21293440f121ec069cb0c7ec47ed41b01573cdd2e3c80505
3
+ metadata.gz: d9378e59ddbeb6127f907b009d5c74f362932d3ded7669e75975d9e4e000285b
4
+ data.tar.gz: f5153b3a2034f5ad9f68d1ee5d31f4a7295e8b4e1cdf48cf90283744886d0355
5
5
  SHA512:
6
- metadata.gz: '08ee4ff5f61407bdcc390eb8c4cda6c286472672a6549ded81d5d0b1c7cf29f8203a472f9cfa5d4cfc811b1b8d923d4ee77ee6746decad1893a33c01187ecc1e'
7
- data.tar.gz: 0b94dde53ddce2444defb9933515dda0d4e754bb0e6053129927d82032bdb9b73383b5d67234a9b57f3e003e82e1b004c17c94f6e551a45ba2fc5dca412bd340
6
+ metadata.gz: 2a9ca012c529a7523e68bb0dde4fd08b20bda1e08a540d98714ae169efc1268946faeb6d16ad1a0926382a480177c60c736a383f8747b2dbcf0225bac5ad522a
7
+ data.tar.gz: 9e39c4801fef0169431db7c23e6f1e45099b11b0a482b12254fef0a90cf7de7787f6d3b6414824fddb86c0f04c246a2b488cda4741e450366841ee7d2f706b52
data/CHANGELOG.md CHANGED
@@ -6,6 +6,159 @@ This project follows [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [3.96.0] - 2026-10-21
10
+
11
+ ### Changed — multi_llm_review says what the roster was when a result is read (multi_llm_review 0.12.0, llm_client 0.4.0)
12
+
13
+ A seat whose reviewer CLI was missing, logged out or refused by codex used to leave the count as `transport`, and
14
+ an APPROVE carried no feedback at all, so a review decided by two Anthropic seats read like one decided by four
15
+ seats from three makers. A Codex host's persona team was recorded as Claude's.
16
+
17
+ - A failed seat's reason is the cause its CLI adapter established: `cli_missing` (the binary is not on the PATH the
18
+ server searched), `cli_unauthenticated` (the CLI, asked after the failure with its own status command, says it
19
+ holds no credential), `workspace_refused` (codex refused a working directory outside a git repository) or
20
+ `cli_timeout`. Anything else stays `transport`, which now means an error with no established cause. Nothing the
21
+ CLI printed is read for this: codex prints the prompt and the files it read.
22
+ - `vote_tally.roster_health` states the seats, how many counted, each seat that did not count with its reason, and
23
+ each counted seat's maker with where it comes from (observed, configured, or declared by the caller). When a seat
24
+ did not count or maker diversity is not established, `feedback_text` starts with one line, on APPROVE too:
25
+ `Roster: 2 of 4 seats counted (1 caller-declared) — not counted: cli_missing: codex_gpt6-astra, cursor_composer2.5; maker diversity not established.`
26
+ - INSUFFICIENT says how many seats counted and how many were needed, that a seat can be added in config, and the
27
+ action that restores each lost seat where one exists. The tool advises no strategy.
28
+ - Every seat is dispatched with `no_fallback`: an API-key seat whose key is unset fails on its own provider instead
29
+ of being re-run on claude_code under its own name.
30
+ - New optional argument `orchestrator_host` (`claude_code`, `codex_cli`, `cursor`, `other`). `claude_code` or none
31
+ keeps `claude_team_<model>`; `codex_cli` records the persona seat as `codex_team_<model>` with provider
32
+ `codex_cli_host`. Records carry `orchestrator_host` and the server's own `host_detected`.
33
+ - `multi_llm_review_wait` reports answered and failed seats separately.
34
+ - The verdict and the quorum are unchanged. VERDICT_SCHEMA_VERSION 3, feedback_text_schema_version 2;
35
+ multi_llm_review's min_core_version is 3.24.9.
36
+ - config gains a commented second codex seat for a machine with only the codex CLI. Upgrades never rewrite an
37
+ instance's config; add it by hand.
38
+ - llm_client 0.4.0: `ApiError` carries the `code`, and `CallRouter` and `llm_call` return it as `error['code']`.
39
+ After a failed CLI call one status command runs (never when the dispatcher ended the call; at most about 19 s).
40
+ The error message and its ErrorTaxonomy type are unchanged, so every other llm_client caller sees only the added
41
+ key and that pause.
42
+
43
+ Design: `log/mlr_non_claude_host_design_v0.3.3_20261021.md`, frozen after four review rounds; implementation
44
+ reviewed in two (records `log/mlr_non_claude_host_*`).
45
+
46
+ ### Changed — L1 `multi_llm_review_workflow` 3.17.0
47
+
48
+ § Auto Mode vs Manual Mode sent a missing CLI to a "Manual mode" the runbook never described. It is replaced by
49
+ § Execution Environment / Reduced rosters and non-Claude hosts: what each failure reason means and what restores
50
+ the seat, the roster line, what a Claude-only, a non-Claude-host and a codex-only setup count under each strategy,
51
+ and how a host's per-call time limit meets a long review call.
52
+
53
+ ### Fixed — `capability_status` reported installed reviewer CLIs as missing
54
+
55
+ It searched PATH for files named `claude_cli`, `codex_cli` and `cursor_cli`. It now probes the binaries the
56
+ adapters spawn (`claude`, `codex`, `agent`), runs `--version` without a shell, and names the binary it searched for.
57
+
58
+ ## [3.95.1] - 2026-10-21
59
+
60
+ ### Changed — the agent SkillSet ships a sample policy, `default_2026_10_20`, instead of `masa_2026_10_20` (agent 1.0.1)
61
+
62
+ `masa_2026_10_20.rb` named its author and cited a record that exists only in the author's instance.
63
+ `default_2026_10_20.rb` carries the same rules (the stand-in may answer from the operator's recorded words, from
64
+ the instruction mode, and reversible questions no recorded word covers; review consent; no project exempt from the
65
+ data check; 10 rounds per review; 300 stand-in calls), with comments that say what each rule does. The stand-in
66
+ reads the policy file, comments included. Adopt it with `adopt policy default_2026_10_20 ac4ae89b`; adopting it
67
+ consents to sending the run's artifacts to the reviewers configured in multi_llm_review.
68
+
69
+ `masa_2026_10_20.rb` is no longer shipped and is not listed in `removed_files`, so upgrade leaves an installed copy
70
+ and a forced reinstall keeps the installed copy: an instance that has it keeps it, and an adoption of it stays valid. It is another operator's sample with the same
71
+ rules: an instance that never adopted it may delete it, and one that did may adopt `default_2026_10_20` instead. A
72
+ shipped policy is never changed in place; a changed rule ships under a new policy name in a new file. Design:
73
+ `log/agent_policy_default_and_proposal_design_v0.7.2_20261021.md`.
74
+
75
+ ### Changed — personal material out of the shipped agent tree
76
+
77
+ Home paths, a person's project and course names, answers typed in a real course and a third party's name are
78
+ replaced by synthetic ones in the agent SkillSet's tests and one code comment. The published 3.95.0 gem and the
79
+ repository history keep them.
80
+
81
+ ### Added — `bin/agent_policy_report.rb`
82
+
83
+ An operator-run script that reports, for each rule of the adopted policy, what the runs the chain records as ended
84
+ hold against it: stand-in answers by class and their corrections, review rounds and cap hits, stand-in calls and
85
+ grants, data checks, with counts, denominators and the operator's words. It moves no rule, evaluates no file
86
+ from a run directory, and writes only its report, under `storage/agent/policy_reports/` (and
87
+ `storage/agent/.gitignore` when absent; no report is written unless that file is a regular file holding exactly the line `*`). Every act it counts is recorded on the actor's reading of the
88
+ operator's words, and the report says so. A policy changes only by the operator's own copy, edit and typed
89
+ adoption.
90
+
91
+ ## [3.95.0] - 2026-10-21
92
+
93
+ ### Changed — the `agent` SkillSet is rebuilt (1.0): long runs in the host session, a stand-in instead of terminal approvals
94
+
95
+ The 0.x agent could not carry the operator's ordinary request (design → design review → implement →
96
+ implementation review): its act route wrote only `docs/drafts/draft_*`, could not reach multi-LLM review or
97
+ tests, and counted only terminal-attested answers (0 counted pairs). Design:
98
+ `log/agent_skillset_rebuild_design_v0.5.1_20261020.md` (five review rounds, frozen as the author's proposal)
99
+ and its delta `log/agent_skillset_rebuild_design_v0.6.3_20261020.md`.
100
+
101
+ - The host session (Claude Code) is the only body. The SkillSet supplies a plan from a Ruby-DSL template, a
102
+ stand-in (isolated `claude -p --safe-mode --tools ""`, Opus 5.5) that answers decision points from the
103
+ operator's own words and the instruction mode, a guard (host hooks: `PreToolUse` on every tool, fail-closed)
104
+ that lets through only what the run created or its worktree and branch hold, a hash-chained journal, and a
105
+ report check. Six tools: `agent_start`, `agent_status`, `agent_advance`, `agent_items`, `agent_finish`,
106
+ `agent_stop`.
107
+ - Runs need an adopted policy (the operator's mandate, `config/policies/*.rb`), adopted by the operator's own
108
+ typed words naming its digest; the adoption is recorded on the chain.
109
+ - Templates: `dev_cycle`, `impl_cycle`, `design_only`, `doc_cycle` (a document kept in git, revised in place,
110
+ optional build check), `survey` (versioned survey files from local sources), `general`.
111
+ - A review closes only when no (a)/(b) P0 is open. Each review may take the policy's `review_rounds`
112
+ (10), counted for that review alone; at the cap it waits for the operator, who grants more rounds or
113
+ freezes it. Revisions follow L1 multi_llm_review_workflow § Revision
114
+ Discipline: each round says which new P0s the actor's last addition drew, and the next step is to undo it.
115
+ Design reviews stay at the design level; implementation-only findings are deferred to the implementation
116
+ review and are operator items at once.
117
+ - Every run ends with a layered-deck report (`report_kit/`, the kit of L1 `layered_visual_pitch_deck`).
118
+ - `bin/agent_harvest.rb` harvests the operator's own answers from host transcripts (hook output, peer
119
+ messages and pasted host output excluded).
120
+ - Removed: the in-server OODA loop, act-route table and terminal rulings, shadow judge, distillation,
121
+ native body, `agent_execute`, `agent_step`, `agent_wait`, `operator_report`, the `agent-monitor` subagent.
122
+ - `agent` is no longer installed automatically in new instances (it needs a policy and projects hooks).
123
+ An installed 0.x agent becomes 1.0 on upgrade. 1.0 needs `multi_llm_review` and `llm_client` >= 0.3.0 in
124
+ the same instance; upgrade does not install a missing one (`kairos-chain skillset install multi_llm_review`).
125
+
126
+ ### Added — `removed_files` in `skillset.json`; `system_upgrade` archives them
127
+
128
+ `upgrade_apply` copied changed files and never deleted one, so a SkillSet that dropped files left them to be
129
+ loaded. A template may now list `removed_files`; upgrade moves each from the installed copy to
130
+ `storage/skillset_removed/<name>/<time>/`, and a forced reinstall no longer restores a retired config file.
131
+
132
+ ### Added — `llm_call` options `no_fallback` and `isolated`
133
+
134
+ `no_fallback` makes an authentication failure on the configured provider a failure instead of a silent switch
135
+ to `claude_code`. `isolated` (claude_code) runs `claude -p --safe-mode --tools ""` in an empty directory, so
136
+ no CLAUDE.md, skills, plugins, hooks, memory or MCP servers reach the call. An isolated call's payload carries
137
+ `isolation` (`safe_mode`, `tools`, `cwd`, as `claude -p` was spawned); llm_client is 0.3.0. The agent's
138
+ stand-in refuses any reply without that evidence (and refuses to call an llm_client too old to isolate), and the
139
+ agent SkillSet declares `llm_client >= 0.3.0`; upgrade both together.
140
+
141
+ ### Added — `user_level_conflicts` in `skillset.json`; install and upgrade report them
142
+
143
+ A SkillSet may list files an earlier version left at user level that it cannot remove itself (e.g. a personal
144
+ skill that shadows the project's). `install`, `upgrade_apply`, `system_upgrade` and `kairos-chain skillset
145
+ install/upgrade` print the ones present as warnings, with a command that moves them to a timestamped backup.
146
+ agent 1.0 lists the 0.x personal skill `~/.claude/skills/agent/SKILL.md` and `~/.claude/agents/agent-monitor.md`.
147
+
148
+ ### Changed — the shipped agent policy needs a new adoption
149
+
150
+ `masa_2026_10_20.rb` sets `review_rounds` to 10 rounds for each review (counted apart, no longer shared by a
151
+ run's reviews) and drops the lookup consent comment (runs never look things up on the web). Its digest
152
+ changed: adopt it with `adopt policy masa_2026_10_20 8846b67e`.
153
+
154
+ ### Changed — L1 `multi_llm_review_workflow` 3.16.0 and `design_to_implementation_workflow` 1.3
155
+
156
+ A new entry-level clause, § Provisional delegation under a mandate: under a pinned, journaled operator policy a
157
+ named delegate — never the context whose work is judged — answers reserved judgments provisionally, and nothing
158
+ resolves, closes, freezes or demotes beyond the run until the operator confirms it in their own words. Pointers
159
+ from INV-U2, INV-U4, INV-U5, Step 0.25 and § Convergence Rules, and from the merge criteria of
160
+ `design_to_implementation_workflow`. An instance's own L1 copy is not rewritten by upgrade.
161
+
9
162
  ## [3.94.0] - 2026-10-20
10
163
 
11
164
  ### Added — L0 changes proposed for later approval, L0 restores on the record, L1 body history
data/bin/kairos-chain CHANGED
@@ -102,6 +102,7 @@ when 'skillset'
102
102
  result = manager.install(source, layer_override: layer_override, force: force)
103
103
  puts "Installed SkillSet '#{result[:name]}' v#{result[:version]} [#{result[:layer]}]"
104
104
  puts "Path: #{result[:path]}"
105
+ manager.user_level_conflicts(KairosMcp::Skillset.new(result[:path])).each { |w| puts " [WARNING] #{w}" }
105
106
 
106
107
  when 'enable'
107
108
  name = ARGV.shift
@@ -162,6 +163,7 @@ when 'skillset'
162
163
  puts "## SkillSets"
163
164
  results.each do |r|
164
165
  puts " [UPGRADED] #{r[:name].ljust(22)} v#{r[:from]} -> v#{r[:to]} (#{r[:files_updated]} files)"
166
+ Array(r[:warnings]).each { |w| puts " [WARNING] #{w}" }
165
167
  end
166
168
  checkable.reject { |ss| upgraded_names.include?(ss.name) }.each do |ss|
167
169
  puts " [UNCHANGED] #{ss.name.ljust(22)} v#{ss.version}"
@@ -98,11 +98,25 @@ module KairosMcp
98
98
  declaration_errors: errors }
99
99
  end
100
100
 
101
+ # The binary each declared external names: the one the llm_client
102
+ # adapter spawns for it (claude_code_adapter, codex_adapter,
103
+ # cursor_adapter). Probing the symbol itself searched PATH for a file
104
+ # called "codex_cli" and reported every installed CLI as missing.
105
+ EXTERNAL_BINARIES = {
106
+ claude_cli: 'claude',
107
+ codex_cli: 'codex',
108
+ cursor_cli: 'agent'
109
+ }.freeze
110
+
111
+ def binary_for(name)
112
+ EXTERNAL_BINARIES.fetch(name.to_s.to_sym, name.to_s)
113
+ end
114
+
101
115
  # which-style PATH check using only filesystem (no subprocess).
102
116
  # Returns true/false.
103
117
  def cli_in_path?(name)
104
118
  return false unless name.is_a?(Symbol) || name.is_a?(String)
105
- bin = name.to_s
119
+ bin = binary_for(name)
106
120
  ENV.fetch('PATH', '').split(File::PATH_SEPARATOR).any? do |dir|
107
121
  full = File.join(dir, bin)
108
122
  File.executable?(full) && !File.directory?(full)
@@ -110,11 +124,13 @@ module KairosMcp
110
124
  end
111
125
 
112
126
  # Get version of a CLI by spawning subprocess (only when probe_versions: true).
113
- # Returns nil on any failure (Honest unknown).
127
+ # Returns nil on any failure (Honest unknown). Spawned as an argv, not
128
+ # through a shell.
114
129
  def cli_version(name)
115
130
  return nil unless cli_in_path?(name)
116
- out = `#{name} --version 2>&1`.strip
117
- $?.success? ? out.lines.first&.strip : nil
131
+ require 'open3'
132
+ out, status = Open3.capture2e(binary_for(name), '--version')
133
+ status.success? ? out.strip.lines.first&.strip : nil
118
134
  rescue StandardError
119
135
  nil
120
136
  end
@@ -87,6 +87,27 @@ module KairosMcp
87
87
  @metadata['config_files'] || []
88
88
  end
89
89
 
90
+ # Files a release takes out of an installed copy (relative paths). An
91
+ # upgrade copies changed files and never deletes; a SkillSet that drops
92
+ # files names them here so system_upgrade archives them instead of
93
+ # leaving them to be loaded (Skillset#load requires every tools/*.rb).
94
+ def removed_files
95
+ Array(@metadata['removed_files']).select do |rel|
96
+ rel.is_a?(String) && !rel.empty? && !rel.start_with?('/') && !rel.split('/').include?('..')
97
+ end
98
+ end
99
+
100
+ # Files outside the instance that an earlier version left at user level
101
+ # and that this version cannot remove itself (e.g. a personal skill that
102
+ # shadows the project's): each { "path": "~/...", "pattern": "regex",
103
+ # "note": "..." }. Upgrade reports the ones present; the operator moves
104
+ # them.
105
+ def user_level_conflicts
106
+ Array(@metadata['user_level_conflicts']).select do |c|
107
+ c.is_a?(Hash) && c['path'].is_a?(String) && c['path'].start_with?('~/') && !c['path'].split('/').include?('..')
108
+ end
109
+ end
110
+
90
111
  # Optional fail-closed activation hook: a fully-qualified class name
91
112
  # whose `activate_on_load!` runs at skillset-load time, independent of
92
113
  # whether any of the SkillSet's tools are instantiated. Used by
@@ -89,12 +89,14 @@ module KairosMcp
89
89
  dest = File.join(@skillsets_dir, temp_skillset.name)
90
90
  if File.directory?(dest)
91
91
  if force
92
- # Preserve user config files before replacing
92
+ # Preserve user config files (subdirectories included) before replacing
93
93
  config_dir = File.join(dest, 'config')
94
94
  saved_configs = {}
95
95
  if File.directory?(config_dir)
96
- Dir.glob(File.join(config_dir, '*')).each do |f|
97
- saved_configs[File.basename(f)] = File.read(f)
96
+ Dir.glob(File.join(config_dir, '**', '*')).each do |f|
97
+ next unless File.file?(f)
98
+
99
+ saved_configs[f.sub("#{config_dir}/", '')] = File.read(f)
98
100
  end
99
101
  end
100
102
 
@@ -103,12 +105,13 @@ module KairosMcp
103
105
  # Copy new version
104
106
  FileUtils.cp_r(source_path, dest)
105
107
 
106
- # Restore user configs
107
- unless saved_configs.empty?
108
- FileUtils.mkdir_p(File.join(dest, 'config'))
109
- saved_configs.each do |name, content|
110
- File.write(File.join(dest, 'config', name), content)
111
- end
108
+ # Restore user configs, except those the new version retired
109
+ retired = temp_skillset.removed_files.select { |r| r.start_with?('config/') }.map { |r| r.sub('config/', '') }
110
+ saved_configs.reject! { |rel, _| retired.include?(rel) }
111
+ saved_configs.each do |rel, content|
112
+ path = File.join(dest, 'config', rel)
113
+ FileUtils.mkdir_p(File.dirname(path))
114
+ File.write(path, content)
112
115
  end
113
116
  else
114
117
  raise ArgumentError, "SkillSet '#{temp_skillset.name}' already installed at #{dest}. Use --force to reinstall."
@@ -154,14 +157,16 @@ module KairosMcp
154
157
  template_ver = Gem::Version.new(template_ss.version)
155
158
 
156
159
  changed_files = diff_files(template_path, installed.path)
160
+ removals = template_ss.removed_files.select { |rel| File.exist?(File.join(installed.path, rel)) }
157
161
 
158
- if template_ver > installed_ver || changed_files.any?
162
+ if template_ver > installed_ver || changed_files.any? || removals.any?
159
163
  results << {
160
164
  name: installed.name,
161
165
  installed_version: installed.version,
162
166
  available_version: template_ss.version,
163
167
  version_bump: template_ver > installed_ver,
164
168
  changed_files: changed_files,
169
+ removed_files: removals,
165
170
  new_skillset: false
166
171
  }
167
172
  end
@@ -194,7 +199,7 @@ module KairosMcp
194
199
  # Others (multiuser, service_grant, hestia, mmp, skillset_exchange, mcp_client)
195
200
  # require PostgreSQL or networking and must be installed explicitly.
196
201
  CORE_SKILLSETS = %w[
197
- plugin_projector agent llm_client autoexec autonomos
202
+ plugin_projector llm_client autoexec autonomos
198
203
  skillset_creator knowledge_creator introspection dream
199
204
  document_authoring synoptis
200
205
  ].freeze
@@ -223,7 +228,8 @@ module KairosMcp
223
228
  # Install new SkillSet from template
224
229
  result = install(template_path)
225
230
  results << { name: info[:name], from: nil, to: info[:available_version],
226
- action: 'installed', files_updated: 0 }
231
+ action: 'installed', files_updated: 0,
232
+ warnings: user_level_conflicts(Skillset.new(File.join(@skillsets_dir, info[:name]))) }.reject { |_, v| v == [] }
227
233
  else
228
234
  # Upgrade existing: copy changed files
229
235
  dest = File.join(@skillsets_dir, info[:name])
@@ -233,11 +239,13 @@ module KairosMcp
233
239
  FileUtils.mkdir_p(File.dirname(dst))
234
240
  FileUtils.cp(src, dst) if File.exist?(src)
235
241
  end
242
+ archived = archive_removed_files(info[:name], dest, Array(info[:removed_files]))
236
243
 
237
244
  installed = Skillset.new(dest)
238
245
  record_skillset_event(installed, 'upgrade')
239
246
  results << { name: info[:name], from: info[:installed_version], to: info[:available_version],
240
- action: 'upgraded', files_updated: info[:changed_files].size }
247
+ action: 'upgraded', files_updated: info[:changed_files].size, files_archived: archived.size,
248
+ warnings: user_level_conflicts(installed) }.reject { |_, v| v == [] }
241
249
  end
242
250
  end
243
251
 
@@ -445,8 +453,45 @@ module KairosMcp
445
453
  all_skillsets.find { |ss| ss.name == name.to_s }
446
454
  end
447
455
 
456
+ # The user-level leftovers a SkillSet declares that are present now, as
457
+ # warnings with the command that moves them aside (a timestamped backup,
458
+ # so a second move never overwrites the first).
459
+ def user_level_conflicts(skillset)
460
+ skillset.user_level_conflicts.filter_map do |c|
461
+ path = File.expand_path(c['path'])
462
+ next unless File.exist?(path)
463
+ next if c['pattern'] && !File.read(path, encoding: 'UTF-8').match?(Regexp.new(c['pattern']))
464
+
465
+ backup = File.expand_path("~/.claude/#{skillset.name}_previous_version_backup/#{Time.now.strftime('%Y%m%d_%H%M%S')}")
466
+ "#{path}: #{c['note'] || 'left by an earlier version'} (move it aside: mkdir -p #{backup} && mv #{path} #{backup}/)"
467
+ end
468
+ rescue StandardError
469
+ []
470
+ end
471
+
448
472
  private
449
473
 
474
+ # Move files a release dropped out of the installed copy, into
475
+ # storage/skillset_removed/<name>/<time>/ (kept, not deleted, so the
476
+ # operator can read back what the upgrade took out). Paths are checked to
477
+ # stay inside the installed SkillSet.
478
+ def archive_removed_files(name, dest, rels)
479
+ return [] if rels.empty?
480
+
481
+ root = File.realpath(dest)
482
+ stamp = Time.now.utc.strftime('%Y%m%dT%H%M%SZ')
483
+ archive = File.join(KairosMcp.storage_dir, 'skillset_removed', name.to_s, stamp)
484
+ rels.filter_map do |rel|
485
+ src = File.join(root, rel)
486
+ next unless File.exist?(src) && File.expand_path(src).start_with?("#{root}/")
487
+
488
+ to = File.join(archive, rel)
489
+ FileUtils.mkdir_p(File.dirname(to))
490
+ FileUtils.mv(src, to)
491
+ rel
492
+ end
493
+ end
494
+
450
495
  # Compare files between template and installed SkillSet
451
496
  def diff_files(template_path, installed_path)
452
497
  changed = []
@@ -152,7 +152,9 @@ module KairosMcp
152
152
 
153
153
  externals.each do |ext|
154
154
  present = Capability.cli_in_path?(ext)
155
- entry = { available: present }
155
+ # The binary searched for, so a reader can tell which file was
156
+ # missing (claude_cli is the `claude` binary, and so on).
157
+ entry = { available: present, binary: Capability.binary_for(ext) }
156
158
  entry[:reason] = 'not found in PATH' unless present
157
159
  if present && probe_versions
158
160
  ver = Capability.cli_version(ext)
@@ -361,6 +361,7 @@ module KairosMcp
361
361
  actions[:skillsets_upgraded] = (actions[:skillsets_upgraded] || []) << r[:name]
362
362
  output += " [UPGRADED] #{r[:name]} v#{r[:from]} → v#{r[:to]} (#{r[:files_updated]} files)\n"
363
363
  end
364
+ Array(r[:warnings]).each { |w| output += " [WARNING] #{w}\n" }
364
365
  end
365
366
  end
366
367
  rescue => e
@@ -487,6 +488,7 @@ module KairosMcp
487
488
  else
488
489
  output += " [UPGRADED] #{r[:name]} v#{r[:from]} → v#{r[:to]} (#{r[:files_updated]} files)\n"
489
490
  end
491
+ Array(r[:warnings]).each { |w| output += " [WARNING] #{w}\n" }
490
492
  end
491
493
  output += "\nNo L0 template changes needed.\n"
492
494
  output += "Restart the MCP server to load new SkillSet tools.\n"
@@ -1,4 +1,4 @@
1
1
  module KairosMcp
2
- VERSION = "3.94.0"
2
+ VERSION = "3.96.0"
3
3
  CHANGELOG_URL = "https://github.com/masaomi/KairosChain_2026/blob/main/CHANGELOG.md"
4
4
  end
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: design_to_implementation_workflow
3
3
  description: "Full-lifecycle workflow for complex features: design review, self-review, implementation review, and final merge gate. Derived from Service Grant + Attestation Nudge experiments."
4
- version: "1.2"
4
+ version: "1.3"
5
5
  tags:
6
6
  - workflow
7
7
  - implementation
@@ -157,6 +157,9 @@ Claude Persona Assembly (4 personas):
157
157
  - NOT for intermediate rounds (diminishing returns)
158
158
 
159
159
  **Merge criteria**: new (a)+(b) P0 = 0, with the freeze declared by the operator.
160
+ Inside an agent run a review closes provisionally (`multi_llm_review_workflow`
161
+ § Provisional delegation under a mandate) and only the operator freezes one; the
162
+ operator's word at merge settles the merge and confirms only the closures it names.
160
163
  A Codex APPROVE is the strongest *reference* signal (see
161
164
  `multi_llm_reviewer_evaluation`), and it is not a gate: Codex went 24 of 24
162
165
  reviews without reaching APPROVE on one design loop, so a merge waiting on it