kairos-chain 3.95.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -0
  3. data/lib/kairos_mcp/capability.rb +20 -4
  4. data/lib/kairos_mcp/tools/capability_status.rb +3 -1
  5. data/lib/kairos_mcp/version.rb +1 -1
  6. data/templates/knowledge/multi_llm_review_workflow/multi_llm_review_workflow.md +116 -27
  7. data/templates/skillsets/agent/bin/agent_policy_report.rb +26 -0
  8. data/templates/skillsets/agent/config/policies/default_2026_10_20.rb +34 -0
  9. data/templates/skillsets/agent/lib/agent/policy_report.rb +665 -0
  10. data/templates/skillsets/agent/lib/agent/precedents.rb +5 -2
  11. data/templates/skillsets/agent/plugin/SKILL.md +16 -4
  12. data/templates/skillsets/agent/skillset.json +2 -2
  13. data/templates/skillsets/agent/test/test_agent1_dsl.rb +5 -5
  14. data/templates/skillsets/agent/test/test_agent1_policy_report.rb +475 -0
  15. data/templates/skillsets/agent/test/test_agent1_r1_words.rb +39 -39
  16. data/templates/skillsets/agent/test/test_agent1_r3_words.rb +11 -11
  17. data/templates/skillsets/agent/test/test_agent1_r3v_guardwords.rb +11 -11
  18. data/templates/skillsets/agent/test/test_agent1_r3v_lifecycle.rb +1 -1
  19. data/templates/skillsets/agent/test/test_agent1_stand_in_precedents.rb +5 -5
  20. data/templates/skillsets/agent/test/test_agent1_v06.rb +28 -3
  21. data/templates/skillsets/llm_client/lib/llm_client/adapter.rb +7 -2
  22. data/templates/skillsets/llm_client/lib/llm_client/call_router.rb +1 -1
  23. data/templates/skillsets/llm_client/lib/llm_client/claude_code_adapter.rb +9 -3
  24. data/templates/skillsets/llm_client/lib/llm_client/cli_failure.rb +123 -0
  25. data/templates/skillsets/llm_client/lib/llm_client/codex_adapter.rb +6 -3
  26. data/templates/skillsets/llm_client/lib/llm_client/cursor_adapter.rb +5 -3
  27. data/templates/skillsets/llm_client/skillset.json +1 -1
  28. data/templates/skillsets/llm_client/test/test_cli_failure.rb +263 -0
  29. data/templates/skillsets/llm_client/tools/llm_call.rb +1 -1
  30. data/templates/skillsets/multi_llm_review/config/multi_llm_review.yml +19 -0
  31. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/build_review_bundle.rb +8 -1
  32. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/consensus.rb +20 -4
  33. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/dispatcher.rb +5 -1
  34. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/feedback_formatter.rb +119 -1
  35. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/observer_set.rb +7 -3
  36. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/persona_assembly.rb +26 -7
  37. data/templates/skillsets/multi_llm_review/lib/multi_llm_review/roster_health.rb +127 -0
  38. data/templates/skillsets/multi_llm_review/skillset.json +3 -3
  39. data/templates/skillsets/multi_llm_review/test/test_feedback_formatter.rb +1 -1
  40. data/templates/skillsets/multi_llm_review/test/test_non_claude_host.rb +455 -0
  41. data/templates/skillsets/multi_llm_review/test/test_tool_wiring.rb +1 -1
  42. data/templates/skillsets/multi_llm_review/tools/multi_llm_review.rb +103 -34
  43. data/templates/skillsets/multi_llm_review/tools/multi_llm_review_collect.rb +16 -11
  44. data/templates/skillsets/multi_llm_review/tools/multi_llm_review_wait.rb +24 -4
  45. metadata +9 -2
  46. data/templates/skillsets/agent/config/policies/masa_2026_10_20.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bce3f299f0bb91ecbb6199e464a2ea24602ede6e9d4e972c1a7b5905ec447c5
4
- data.tar.gz: 4986b9e4f8c87ff233b67586791d8b3068aed4decaecb1319f5c0553b4a5445c
3
+ metadata.gz: d9378e59ddbeb6127f907b009d5c74f362932d3ded7669e75975d9e4e000285b
4
+ data.tar.gz: f5153b3a2034f5ad9f68d1ee5d31f4a7295e8b4e1cdf48cf90283744886d0355
5
5
  SHA512:
6
- metadata.gz: a4af517774c9e5e90299d4877190d83659932acf7851bf04275d5c3066298411ca628084a490cfef6348b327d550c05d5cc4f96cab086e5c297e2a169e1f72b3
7
- data.tar.gz: ba67dc90461e4350615a4ba9e232702efc27b241fa853a2934a80714bb5753c2aa1ebba06921ebe58e4db7145d8f3fb5d747be4ab37f8ad5da25150ab8c7ce8d
6
+ metadata.gz: 2a9ca012c529a7523e68bb0dde4fd08b20bda1e08a540d98714ae169efc1268946faeb6d16ad1a0926382a480177c60c736a383f8747b2dbcf0225bac5ad522a
7
+ data.tar.gz: 9e39c4801fef0169431db7c23e6f1e45099b11b0a482b12254fef0a90cf7de7787f6d3b6414824fddb86c0f04c246a2b488cda4741e450366841ee7d2f706b52
data/CHANGELOG.md CHANGED
@@ -6,6 +6,88 @@ 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
+
9
91
  ## [3.95.0] - 2026-10-21
10
92
 
11
93
  ### Changed — the `agent` SkillSet is rebuilt (1.0): long runs in the host session, a stand-in instead of terminal approvals
@@ -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
@@ -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)
@@ -1,4 +1,4 @@
1
1
  module KairosMcp
2
- VERSION = "3.95.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: multi_llm_review_workflow
3
3
  description: "Multi-LLM review methodology and execution — workflow pattern, CLI tooling, consensus analysis, Persona Assembly. Applicable to design, implementation, documentation, or any artifact."
4
- version: "3.16.0"
4
+ version: "3.17.0"
5
5
  tags:
6
6
  - workflow
7
7
  - review
@@ -24,7 +24,7 @@ and integrated. The user (or primary LLM) acts as orchestrator.
24
24
 
25
25
  This skill covers:
26
26
  - **WHAT/WHEN**: When to use multi-LLM review, review types, convergence criteria
27
- - **HOW**: CLI commands, prompt generation, auto/manual execution, consensus analysis
27
+ - **HOW**: CLI commands, prompt generation, Path A (manual) and Path B (MCP) execution, consensus analysis
28
28
 
29
29
  For **WHO** (which LLM is good at what), see: `multi_llm_reviewer_evaluation`
30
30
  For **development lifecycle** (design → implement → verify), see: `design_to_implementation_workflow`
@@ -861,20 +861,87 @@ Save to L2 context at these moments:
861
861
 
862
862
  # Execution
863
863
 
864
- ## Auto Mode vs Manual Mode
864
+ ## Execution Environment
865
865
 
866
- ### Mode Detection
866
+ ### Reduced rosters and non-Claude hosts
867
867
 
868
- ```bash
869
- which codex 2>/dev/null && echo "codex: available" || echo "codex: NOT FOUND"
870
- which agent 2>/dev/null && echo "agent: available" || echo "agent: NOT FOUND"
871
- which claude 2>/dev/null && echo "claude: available" || echo "claude: NOT FOUND"
868
+ The roster is whatever `config/multi_llm_review.yml` names (Path B), and the tool
869
+ never drops a seat because its CLI is missing. Every seat runs only on its own
870
+ provider (no fallback to another). A seat that cannot run fails, leaves the count,
871
+ and is recorded with the cause its transport established — never with a cause read
872
+ out of text the CLI printed, because codex prints the prompt and the files it read:
873
+
874
+ | Reason | What happened | What restores the seat |
875
+ |---|---|---|
876
+ | `cli_missing` | the CLI's binary is not on the PATH the server searched | install it, or put its directory on that PATH (the result shows it) |
877
+ | `cli_unauthenticated` | the CLI, asked after the failure, said it is not logged in | log in with that CLI (`codex login`, `agent login`, `claude` then `/login`); the seat reads the login under HOME |
878
+ | `workspace_refused` | codex refused the server's working directory (no git repository, not trusted) | make that directory (named in the result) lie inside a git repository; how a host sets the server's directory is the host's |
879
+ | `cli_timeout` | the CLI call's own timer (llm_client `timeout_seconds`) fired | raise llm_client's and multi_llm_review's `timeout_seconds` together |
880
+ | `dispatch_timeout` | the dispatch window (multi_llm_review `timeout_seconds`) closed with the seat still running or still queued; with both at 600 s this fires first | as for `cli_timeout`; `collect_deadline_seconds` (1800 shipped) bounds how far that helps |
881
+ | `transport` | anything else; the seat's error message says what was seen | read the seat's row (an API-key seat whose key is unset lands here) |
882
+
883
+ Asking a failed CLI whether it is logged in costs one status command after the
884
+ failure (its own 10 s timer; up to about 19 s with the kill grace and reader joins),
885
+ and every other llm_client caller sees the same pause after a failed CLI call. It is
886
+ never run when the dispatcher itself ended the call.
887
+
888
+ Whenever a seat did not count, or the counted seats are not known to come from two
889
+ different makers, the result carries one roster line, on APPROVE too:
890
+
891
+ ```
892
+ Roster: 2 of 4 seats counted (1 caller-declared) — not counted: cli_missing: codex_gpt6-astra, cursor_composer2.5; maker diversity not established.
872
893
  ```
873
894
 
874
- - All three available → Auto mode (the configured roster, currently 5 reviewers)
875
- - Codex + Agent only → Auto mode (legacy, reduced roster — apply "Legacy 3-reviewer mode: 2/3 APPROVE" from Convergence Rules)
876
- - Any of codex/agent missing → Manual mode
877
- - User override: `mode: manual` or `mode: auto`
895
+ A counted seat's maker is observed (the seat reported its model), configured (the
896
+ roster pins the model and the seat ran on its own provider — this holds while the
897
+ CLI's own configuration does not route that name to another maker), or
898
+ caller-declared (a persona seat that was not observed). Only the first two
899
+ establish diversity. Two kinds of round always carry the line: an `exclude` round
900
+ whose caller names a slot (that slot does not count), and an agent SkillSet round
901
+ (it submits no personas). None of this changes the verdict or the quorum
902
+ (`min_quorum`, 2 shipped). An INSUFFICIENT result also says how many seats counted
903
+ and how many were needed, that a seat can be added in config, and the restoring
904
+ action for each reason in the table above.
905
+
906
+ **Claude Code without codex or cursor.** Nothing to configure. The persona team and
907
+ the Sonnet seat count, APPROVE is reachable, and every result says "2 of 4 seats
908
+ counted … maker diversity not established".
909
+
910
+ **A host other than Claude Code.** Pass `orchestrator_host` (`codex_cli`, `cursor`
911
+ or `other`; `claude_code` or nothing keeps `claude_team_<model>`), and the persona
912
+ seat is recorded as `codex_team_<model>` and so on, beside the server's own
913
+ detection of its host. Run the personas as separate sub-agents of your host (Codex:
914
+ multi-agent). Nothing in the system can observe that, so the persona seat is always
915
+ recorded as your declaration. A Codex session can still run the `claude` seats:
916
+ Codex's sandbox does not confine kairos-chain's MCP server.
917
+
918
+ **A machine with only the codex CLI.** One seat can answer, below the quorum, so
919
+ every review is INSUFFICIENT until a second codex seat is added on another model —
920
+ the commented recipe in `config/multi_llm_review.yml`. Upgrades never rewrite an
921
+ instance's config, so an existing instance adds it by hand: a slot naming
922
+ `provider`, `model` and `role_label`, on a model the roster does not already name.
923
+ With orchestrator_model `gpt-6-astra` and a `gpt-6-sol` seat:
924
+
925
+ | Strategy | Counted seats | What it costs |
926
+ |---|---|---|
927
+ | `delegate` (default) | 2: `gpt-6-sol` and your persona team | the persona seat rests on your declaration |
928
+ | `subprocess`, no `persona_model` | 2: `gpt-6-astra` and `gpt-6-sol`, both fresh processes | one call that returns only when every seat has finished; your own slot runs only if your model names one |
929
+ | `exclude` | 1: your slot leaves (`exclude_orchestrator_model: true`, shipped) | below the quorum |
930
+
931
+ **A host with a per-call time limit** (Codex: `tool_timeout_sec` per MCP server;
932
+ documented default 60 s, not verified here). A `subprocess` review is one call that
933
+ lasts as long as the slowest seat, so first raise the limit for kairos-chain above
934
+ both configured `timeout_seconds`, with a margin. A cut single-phase call leaves its
935
+ record only in the run's `completed.json`. On the delegate path the first call
936
+ returns at once, but waiting in short calls is no substitute: three consecutive
937
+ `still_pending` replies from `multi_llm_review_wait` end in `crashed` /
938
+ `wait_exhausted` while the worker is still healthy. Raise the host's limit instead.
939
+ `multi_llm_review_collect` waits at most `collect_max_wait_seconds` (420 shipped)
940
+ before reaping a live worker, so call collect after wait has said `ready`.
941
+
942
+ **Path A (manual Bash).** Run `which codex`, `which agent`, `which claude`; leave
943
+ out the line of a CLI that is not found, and read the result by the same rules: the
944
+ quorum stays 2, and the report says which seats did not count and why.
878
945
 
879
946
  ### CLI Tool Matrix (tested 2026-03-28; model flags made mandatory 2026-07-27)
880
947
 
@@ -1069,7 +1136,7 @@ multi_llm_review(
1069
1136
  `orchestrator_strategy: "subprocess"`.
1070
1137
  - If `orchestrator_model` is `null` or unmatched, full roster runs (back-compat).
1071
1138
 
1072
- **Manual-mode equivalent**: When orchestrating by hand, do not assign yourself
1139
+ **Path A equivalent**: When orchestrating by hand, do not assign yourself
1073
1140
  as a subprocess reviewer. Run the Claude CLI subprocess reviewers (Sonnet 5.5, plus
1074
1141
  any frontier roster slot you are not); if your own model matches one of them,
1075
1142
  skip that entry and use the after-exclusion convergence rule.
@@ -1094,19 +1161,21 @@ cross-model subprocess reviewers give epistemic diversity. The two are complemen
1094
1161
 
1095
1162
  **Call 1**: `multi_llm_review(orchestrator_strategy: "delegate", orchestrator_model: "...")`
1096
1163
  - SkillSet drops the orchestrator-matching reviewer from dispatch
1097
- - Subprocess reviewers run synchronously (no background threads)
1098
- - Subprocess results persisted to `.kairos/multi_llm_review/pending/<uuid>.json`
1164
+ - Subprocess reviewers run in a detached worker (default `parallel: true`), or
1165
+ synchronously with `parallel: false`
1166
+ - Subprocess results persisted under `.kairos/multi_llm_review/pending/<token>/`
1099
1167
  - Returns `status: "delegation_pending"`, `collect_token`, `persona_count_min/max`
1100
1168
 
1101
1169
  **Orchestrator's obligation** (between calls):
1102
1170
  - Recognize the `delegation_pending` status
1103
- - Spawn 2-4 parallel `Agent` tool calls with self-chosen personas appropriate to
1171
+ - Run 2-4 personas as separate sub-agents of your host (Claude Code: parallel
1172
+ `Agent` tool calls; Codex: multi-agent), self-chosen and appropriate to
1104
1173
  the artifact (e.g. design → architect/security/operability; code → correctness/
1105
1174
  performance/api-design; doc → ontologist/skeptic/integration)
1106
1175
  - Collect persona results: each as `{persona, verdict (APPROVE|REVISE|REJECT),
1107
1176
  reasoning, findings: [{severity, issue}, ...]}`
1108
- - Bind each persona to its subagent: add `agent_id` — the id the Agent tool
1109
- returned for that persona's subagent — to its entry. With the model_provenance
1177
+ - Bind each persona to its subagent (Claude Code): add `agent_id` — the id the
1178
+ Agent tool returned for that persona's subagent — to its entry. With the model_provenance
1110
1179
  SkillSet installed, the seat then records the model the harness observed
1111
1180
  answering, not only the declared one: a safety-classifier fallback inside a
1112
1181
  persona (Opus 5.5 → Opus 5 on biology, → Opus 4.8 on cyber) otherwise leaves
@@ -1120,7 +1189,8 @@ cross-model subprocess reviewers give epistemic diversity. The two are complemen
1120
1189
 
1121
1190
  **Call 2**: `multi_llm_review_collect(collect_token, orchestrator_reviews: [...])`
1122
1191
  - Persona Assembly: any REJECT → REJECT; else any REVISE → REVISE; else APPROVE
1123
- - Assembled into one synthetic reviewer entry `claude_team_<orchestrator_model>`
1192
+ - Assembled into one synthetic reviewer entry `<host>_team_<model>`
1193
+ (`claude_team_` for `orchestrator_host` claude_code or none; § Reduced rosters)
1124
1194
  - Combined with persisted subprocess results, run Consensus, return final verdict
1125
1195
  - Idempotent: repeated calls with the same token return the cached result
1126
1196
 
@@ -1128,9 +1198,12 @@ cross-model subprocess reviewers give epistemic diversity. The two are complemen
1128
1198
  - `expired_or_unknown_token`: orchestrator missed `must_collect_by` deadline
1129
1199
  (default 1800s since v3.23.2; was 600s), or token never existed. The pending
1130
1200
  review is gone; call `multi_llm_review` again from scratch.
1131
- - `error: invalid orchestrator_reviews`: persona count outside 2-4 or missing
1132
- required fields. Fix and retry collect with the same token.
1133
- - All-subprocess-failed at Call 1: returns error immediately; no token issued.
1201
+ - `error: invalid orchestrator_reviews`: more than 4 personas, or missing
1202
+ required fields. Fix and retry collect with the same token. 0–4 are accepted;
1203
+ fewer than convened is recorded as a shortfall.
1204
+ - All subprocess seats failed at Call 1: with `parallel: false` it returns an
1205
+ error at once and issues no token; on the default parallel path the failures
1206
+ surface at collect, as INSUFFICIENT with each seat's reason.
1134
1207
 
1135
1208
  **Default**: `orchestrator_strategy` defaults to `"delegate"` (config key
1136
1209
  `default_orchestrator_strategy`). `"exclude"` remains available as the legacy
@@ -1554,7 +1627,8 @@ Step 3: Execute the configured roster in parallel (currently 4 slots, one of
1554
1627
  Step 4: Collect and validate
1555
1628
  - Wait for all to complete (background task notifications)
1556
1629
  - Verify each output file exists and contains structured review
1557
- - Failed tool → offer manual fallback
1630
+ - Failed tool → record it as not counted, with its cause (§ Reduced rosters
1631
+ and non-Claude hosts)
1558
1632
 
1559
1633
  Step 5: Consensus analysis
1560
1634
  - Read all review files
@@ -1571,10 +1645,11 @@ Step 6: Report to user
1571
1645
 
1572
1646
  | Error | Detection | Recovery |
1573
1647
  |-------|-----------|----------|
1574
- | CLI not found | `which` non-zero | Manual mode fallback |
1575
- | Auth expired | Non-zero exit, auth error | Prompt re-login |
1576
- | Timeout (>5 min) | Background task timeout | Kill, report partial, retry |
1577
- | Empty output | Missing verdict | Report failure, manual retry |
1648
+ | CLI not found | `cli_missing` (Path A: `which` non-zero) | Install, or fix the server's PATH |
1649
+ | Not logged in | `cli_unauthenticated` | Log in with that CLI |
1650
+ | codex refuses the directory | `workspace_refused` | Run from inside a git repository |
1651
+ | Timeout | `cli_timeout` / `dispatch_timeout` | Raise both `timeout_seconds`; mind `collect_deadline_seconds` |
1652
+ | Empty output | `no_verdict` / `insubstantial` | Report failure, retry |
1578
1653
  | Trust prompt | Agent hangs | `--trust` flag |
1579
1654
  | Usage limit | "usage limit" in output | Alternate tool fallback |
1580
1655
 
@@ -2028,6 +2103,20 @@ Compression ratio: parallel agent raw → Assembly ≈ 2:1
2028
2103
  Step 0.25 guard-track sentence and § Convergence Rules. Source: design
2029
2104
  `log/agent_skillset_rebuild_design_v0.5.1_20261020.md` §2 and its delta v0.6.6.
2030
2105
 
2106
+ - Reduced rosters and non-Claude hosts (v3.17.0, 2026-10-21, operator request:
2107
+ 「MLRのdefaultがclaude codeでない場合の処理について…修正しようと思います」,
2108
+ rulings 1–9 in L2 `decision_mlr_non_claude_host_four_rulings_20261021`).
2109
+ § Auto Mode vs Manual Mode, which sent a missing CLI to a "Manual mode" it never
2110
+ described and counted 5 reviewers, is replaced by § Execution Environment /
2111
+ Reduced rosters and non-Claude hosts: what each failure cause means and what
2112
+ restores the seat, the roster line results now carry, what a Claude-only,
2113
+ non-Claude-host or codex-only setup counts under each strategy, and a host's
2114
+ per-call limit. The delegation protocol now names sub-agents of any host,
2115
+ `<host>_team_<model>`, the 0–4 persona range and where an all-failed Call 1
2116
+ surfaces; the Error Handling table maps the new reason tokens. Ships with
2117
+ multi_llm_review 0.12.0 and llm_client 0.4.0. Design
2118
+ `log/mlr_non_claude_host_design_v0.3.3_20261021.md`, frozen after four rounds.
2119
+
2031
2120
  **Key insight**: Design reviews and implementation reviews find
2032
2121
  **categorically different bugs**. Both phases are necessary. The corollary that
2033
2122
  cost eight rounds to learn: **which of the two you are in is readable from the
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The policy report (design v0.7.2 INV-8): for each rule of the adopted
4
+ # policy, what the runs the chain records as ended hold against it — counts
5
+ # with their denominators and the operator's words of each act. The operator
6
+ # runs it outside runs. It reads the data directory, calls no model,
7
+ # evaluates no file from a run directory, writes one file under
8
+ # storage/agent/policy_reports (and storage/agent/.gitignore when absent), and
9
+ # changes no policy.
10
+ #
11
+ # ruby .kairos/skillsets/agent/bin/agent_policy_report.rb [--data-dir DIR]
12
+
13
+ require_relative '../lib/agent/policy_report'
14
+
15
+ def arg(name)
16
+ i = ARGV.index(name)
17
+ i && ARGV[i + 1]
18
+ end
19
+
20
+ data_dir = arg('--data-dir') || ENV['KAIROS_DATA_DIR'] || File.join(ENV['CLAUDE_PROJECT_DIR'] || Dir.pwd, '.kairos')
21
+ paths = KairosMcp::SkillSets::Agent::Paths.new(data_dir)
22
+ begin
23
+ puts KairosMcp::SkillSets::Agent::PolicyReport.new(paths).write
24
+ rescue ArgumentError, IOError, SystemCallError => e
25
+ abort e.message
26
+ end
@@ -0,0 +1,34 @@
1
+ # A sample policy for agent runs: an operator's mandate, shipped with the agent
2
+ # SkillSet. It binds no one until an operator adopts it by typing
3
+ # "adopt policy default_2026_10_20 <first 8 hex digits of its digest>"; any
4
+ # edit changes the digest and needs a new adoption. A changed policy takes a
5
+ # new name in its policy line. The stand-in reads this whole file, comments
6
+ # included, as part of its instructions.
7
+ #
8
+ # stand_in may: the decision points the stand-in answers instead of the
9
+ # operator (questions, plan approval and parameters, pinned-test changes).
10
+ # :precedent answers from the operator's own recorded words;
11
+ # :instruction_mode answers from the active instruction mode;
12
+ # :novel_reversible answers a reversible question no recorded word covers,
13
+ # by the model's own judgment (with an empty precedent store, that is most
14
+ # questions). Leaving out :precedent or :instruction_mode while keeping
15
+ # :novel_reversible answers the same questions, labelled novel; leaving out
16
+ # all three sends those decision points to the operator. These classes do
17
+ # not govern the stand-in's readings: it still checks review bundles for
18
+ # personal data, labels review findings and rules on hazards.
19
+ # consent review: a run may send its artifacts to the reviewers configured in
20
+ # multi_llm_review. The value and scope are recorded, not enforced.
21
+ # free_of_personal_data: projects whose review bundles skip the stand-in's
22
+ # check for personal or third-party data, unless a bundle carries findings
23
+ # from an earlier round. None here.
24
+ # spend: review_rounds caps each review, counted apart; at the cap the review
25
+ # waits for the operator. stand_in_calls caps the stand-in's model calls in a
26
+ # run; past it decision points and readings go to the operator, and a hazard
27
+ # cannot be ruled, which ends the run.
28
+
29
+ policy "default_2026_10_20" do
30
+ stand_in may: [:precedent, :instruction_mode, :novel_reversible]
31
+ consent review: :configured_providers, of: :project_artifacts
32
+ free_of_personal_data projects: []
33
+ spend default: { review_rounds: 10, stand_in_calls: 300 }
34
+ end