kairos-chain 3.95.0 → 3.96.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +119 -0
- data/lib/kairos_mcp/capability.rb +20 -4
- data/lib/kairos_mcp/tools/capability_status.rb +3 -1
- data/lib/kairos_mcp/version.rb +1 -1
- data/templates/knowledge/multi_llm_review_workflow/multi_llm_review_workflow.md +125 -27
- data/templates/skillsets/agent/bin/agent_policy_report.rb +26 -0
- data/templates/skillsets/agent/config/policies/default_2026_10_20.rb +34 -0
- data/templates/skillsets/agent/lib/agent/hooks.rb +178 -4
- data/templates/skillsets/agent/lib/agent/policy_report.rb +665 -0
- data/templates/skillsets/agent/lib/agent/precedents.rb +5 -2
- data/templates/skillsets/agent/lib/agent/review.rb +185 -25
- data/templates/skillsets/agent/lib/agent/run.rb +1 -1
- data/templates/skillsets/agent/lib/agent/seats.rb +634 -0
- data/templates/skillsets/agent/lib/agent/service.rb +37 -4
- data/templates/skillsets/agent/plugin/SKILL.md +27 -5
- data/templates/skillsets/agent/skillset.json +6 -3
- data/templates/skillsets/agent/test/test_agent1_dsl.rb +5 -5
- data/templates/skillsets/agent/test/test_agent1_hooks_service.rb +3 -1
- data/templates/skillsets/agent/test/test_agent1_persona_seats.rb +850 -0
- data/templates/skillsets/agent/test/test_agent1_policy_report.rb +475 -0
- data/templates/skillsets/agent/test/test_agent1_r1_words.rb +39 -39
- data/templates/skillsets/agent/test/test_agent1_r3_words.rb +11 -11
- data/templates/skillsets/agent/test/test_agent1_r3v_guardwords.rb +11 -11
- data/templates/skillsets/agent/test/test_agent1_r3v_lifecycle.rb +1 -1
- data/templates/skillsets/agent/test/test_agent1_stand_in_precedents.rb +5 -5
- data/templates/skillsets/agent/test/test_agent1_v06.rb +28 -3
- data/templates/skillsets/agent/tools/agent_advance.rb +1 -1
- data/templates/skillsets/llm_client/lib/llm_client/adapter.rb +7 -2
- data/templates/skillsets/llm_client/lib/llm_client/call_router.rb +1 -1
- data/templates/skillsets/llm_client/lib/llm_client/claude_code_adapter.rb +9 -3
- data/templates/skillsets/llm_client/lib/llm_client/cli_failure.rb +123 -0
- data/templates/skillsets/llm_client/lib/llm_client/codex_adapter.rb +6 -3
- data/templates/skillsets/llm_client/lib/llm_client/cursor_adapter.rb +5 -3
- data/templates/skillsets/llm_client/skillset.json +1 -1
- data/templates/skillsets/llm_client/test/test_cli_failure.rb +263 -0
- data/templates/skillsets/llm_client/tools/llm_call.rb +1 -1
- data/templates/skillsets/multi_llm_review/config/multi_llm_review.yml +19 -0
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/build_review_bundle.rb +8 -1
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/consensus.rb +20 -4
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/dispatcher.rb +5 -1
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/feedback_formatter.rb +119 -1
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/observer_set.rb +7 -3
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/persona_assembly.rb +26 -7
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/roster_health.rb +127 -0
- data/templates/skillsets/multi_llm_review/skillset.json +3 -3
- data/templates/skillsets/multi_llm_review/test/test_feedback_formatter.rb +1 -1
- data/templates/skillsets/multi_llm_review/test/test_non_claude_host.rb +455 -0
- data/templates/skillsets/multi_llm_review/test/test_tool_wiring.rb +1 -1
- data/templates/skillsets/multi_llm_review/tools/multi_llm_review.rb +103 -34
- data/templates/skillsets/multi_llm_review/tools/multi_llm_review_collect.rb +16 -11
- data/templates/skillsets/multi_llm_review/tools/multi_llm_review_wait.rb +24 -4
- metadata +11 -2
- 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: faa4327412fbbe72c412e3e4cccd41173a346e488366b0d4963023cb389ce97e
|
|
4
|
+
data.tar.gz: 13767304ee185463ac1a1de1293873762c3658f81e8a5c6d007023ca29970377
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 657b3094d640bd4876964d3ffd88f47fd57fda12147c77d882293c68662d66a791c306d8eaae4fd4238041f641c318dc7825bb0ff6c314b2c963086146a7eb17
|
|
7
|
+
data.tar.gz: 2f765af6b6122a2a3627678f3481a410be0bc0f359bb7b479a6e726fe6f1891264c023d42007840d1fd75e03d175109b78a164647d6402f771322fff8a3783d6
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,125 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [3.96.1] - 2026-10-22
|
|
10
|
+
|
|
11
|
+
### Fixed — agent runs convene the persona seat their reviews declared none for (agent 1.0.2)
|
|
12
|
+
|
|
13
|
+
A run review dispatched multi_llm_review with `persona_count_declared: 0` and collected with no persona reviews,
|
|
14
|
+
so every round counted four seats where the operator's roster has five, and the report said so in one line.
|
|
15
|
+
|
|
16
|
+
- Each review round declares three personas (design: architect, security, operability; implementation:
|
|
17
|
+
correctness, performance, api-design; document: ontologist, skeptic, integration) and stores their prompts —
|
|
18
|
+
multi_llm_review's own canonical prompt for the same bundle, under a persona header — in run storage.
|
|
19
|
+
- The actor launches each seat with a one-line marker that the PreToolUse hook replaces with the seat's prompt.
|
|
20
|
+
From then on the subagent is a seat for its whole life, recognised by the host's meta file naming that launch;
|
|
21
|
+
it may read only its prompt file and hand back. Messages and stops aimed at a seat are refused.
|
|
22
|
+
- Each seat is settled at its SubagentStop from the hand-back the hooks kept, before the hazard and question
|
|
23
|
+
readers; agent_advance settles launches the host never started or never stopped. A seat whose transcript
|
|
24
|
+
shows another prompt is not submitted.
|
|
25
|
+
- agent_advance waits about 540 s per call for running seats, submits each settled reply with the verdict and
|
|
26
|
+
findings multi_llm_review's own parser reads from it, one per line the seat wrote, so a finding's severity
|
|
27
|
+
and consequence come from the same line, and gives the stand-in each persona's own reply. A finding whose
|
|
28
|
+
consequence clause (or location) lies past the point where multi_llm_review cuts a persona finding is
|
|
29
|
+
rebuilt with the clause and its location after a shortened body, so the cut does not record a P0 as one
|
|
30
|
+
that stated no consequence. A seat never launched holds the round only until the first reminder; missing
|
|
31
|
+
seats become a shortfall named in the report, and seats launched late or never are named on the review's
|
|
32
|
+
closure item. Until the round collects or its token expires the Stop hook sends the actor back to
|
|
33
|
+
agent_advance (three times without an advance between, and once more after a turn in which a seat started or
|
|
34
|
+
ended, then the run rests), so the round collects before its token expires. From ten minutes before the
|
|
35
|
+
token's end no seat is launched or asked for. Collect closes the round's seats under the lock that admits
|
|
36
|
+
launches and settles its remaining launches, so no launch outlives the round and the seat refusals end with
|
|
37
|
+
it; agent_stop closes the seats of a round that never collected. A close that fails because the seat lock
|
|
38
|
+
cannot be taken is journaled as such (`seats_close_failed`) and the settled replies are still submitted. A settled seat may be stopped; it is
|
|
39
|
+
never messaged.
|
|
40
|
+
- The seats run on the session's own plan; no policy spend counter counts them.
|
|
41
|
+
- `depends_on` pins multi_llm_review >= 0.12.0. L1 multi_llm_review_workflow 3.17.1.
|
|
42
|
+
- Design: `log/agent_persona_seats_design_v0.3_20261022.md` (two design review rounds, four implementation
|
|
43
|
+
review rounds and one falsification check; the P1s of each fixed). Probed live on one host: three seats
|
|
44
|
+
launched through the rewrite, all three submitted, five seats counted.
|
|
45
|
+
|
|
46
|
+
## [3.96.0] - 2026-10-21
|
|
47
|
+
|
|
48
|
+
### 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)
|
|
49
|
+
|
|
50
|
+
A seat whose reviewer CLI was missing, logged out or refused by codex used to leave the count as `transport`, and
|
|
51
|
+
an APPROVE carried no feedback at all, so a review decided by two Anthropic seats read like one decided by four
|
|
52
|
+
seats from three makers. A Codex host's persona team was recorded as Claude's.
|
|
53
|
+
|
|
54
|
+
- A failed seat's reason is the cause its CLI adapter established: `cli_missing` (the binary is not on the PATH the
|
|
55
|
+
server searched), `cli_unauthenticated` (the CLI, asked after the failure with its own status command, says it
|
|
56
|
+
holds no credential), `workspace_refused` (codex refused a working directory outside a git repository) or
|
|
57
|
+
`cli_timeout`. Anything else stays `transport`, which now means an error with no established cause. Nothing the
|
|
58
|
+
CLI printed is read for this: codex prints the prompt and the files it read.
|
|
59
|
+
- `vote_tally.roster_health` states the seats, how many counted, each seat that did not count with its reason, and
|
|
60
|
+
each counted seat's maker with where it comes from (observed, configured, or declared by the caller). When a seat
|
|
61
|
+
did not count or maker diversity is not established, `feedback_text` starts with one line, on APPROVE too:
|
|
62
|
+
`Roster: 2 of 4 seats counted (1 caller-declared) — not counted: cli_missing: codex_gpt6-astra, cursor_composer2.5; maker diversity not established.`
|
|
63
|
+
- INSUFFICIENT says how many seats counted and how many were needed, that a seat can be added in config, and the
|
|
64
|
+
action that restores each lost seat where one exists. The tool advises no strategy.
|
|
65
|
+
- Every seat is dispatched with `no_fallback`: an API-key seat whose key is unset fails on its own provider instead
|
|
66
|
+
of being re-run on claude_code under its own name.
|
|
67
|
+
- New optional argument `orchestrator_host` (`claude_code`, `codex_cli`, `cursor`, `other`). `claude_code` or none
|
|
68
|
+
keeps `claude_team_<model>`; `codex_cli` records the persona seat as `codex_team_<model>` with provider
|
|
69
|
+
`codex_cli_host`. Records carry `orchestrator_host` and the server's own `host_detected`.
|
|
70
|
+
- `multi_llm_review_wait` reports answered and failed seats separately.
|
|
71
|
+
- The verdict and the quorum are unchanged. VERDICT_SCHEMA_VERSION 3, feedback_text_schema_version 2;
|
|
72
|
+
multi_llm_review's min_core_version is 3.24.9.
|
|
73
|
+
- config gains a commented second codex seat for a machine with only the codex CLI. Upgrades never rewrite an
|
|
74
|
+
instance's config; add it by hand.
|
|
75
|
+
- llm_client 0.4.0: `ApiError` carries the `code`, and `CallRouter` and `llm_call` return it as `error['code']`.
|
|
76
|
+
After a failed CLI call one status command runs (never when the dispatcher ended the call; at most about 19 s).
|
|
77
|
+
The error message and its ErrorTaxonomy type are unchanged, so every other llm_client caller sees only the added
|
|
78
|
+
key and that pause.
|
|
79
|
+
|
|
80
|
+
Design: `log/mlr_non_claude_host_design_v0.3.3_20261021.md`, frozen after four review rounds; implementation
|
|
81
|
+
reviewed in two (records `log/mlr_non_claude_host_*`).
|
|
82
|
+
|
|
83
|
+
### Changed — L1 `multi_llm_review_workflow` 3.17.0
|
|
84
|
+
|
|
85
|
+
§ Auto Mode vs Manual Mode sent a missing CLI to a "Manual mode" the runbook never described. It is replaced by
|
|
86
|
+
§ Execution Environment / Reduced rosters and non-Claude hosts: what each failure reason means and what restores
|
|
87
|
+
the seat, the roster line, what a Claude-only, a non-Claude-host and a codex-only setup count under each strategy,
|
|
88
|
+
and how a host's per-call time limit meets a long review call.
|
|
89
|
+
|
|
90
|
+
### Fixed — `capability_status` reported installed reviewer CLIs as missing
|
|
91
|
+
|
|
92
|
+
It searched PATH for files named `claude_cli`, `codex_cli` and `cursor_cli`. It now probes the binaries the
|
|
93
|
+
adapters spawn (`claude`, `codex`, `agent`), runs `--version` without a shell, and names the binary it searched for.
|
|
94
|
+
|
|
95
|
+
## [3.95.1] - 2026-10-21
|
|
96
|
+
|
|
97
|
+
### Changed — the agent SkillSet ships a sample policy, `default_2026_10_20`, instead of `masa_2026_10_20` (agent 1.0.1)
|
|
98
|
+
|
|
99
|
+
`masa_2026_10_20.rb` named its author and cited a record that exists only in the author's instance.
|
|
100
|
+
`default_2026_10_20.rb` carries the same rules (the stand-in may answer from the operator's recorded words, from
|
|
101
|
+
the instruction mode, and reversible questions no recorded word covers; review consent; no project exempt from the
|
|
102
|
+
data check; 10 rounds per review; 300 stand-in calls), with comments that say what each rule does. The stand-in
|
|
103
|
+
reads the policy file, comments included. Adopt it with `adopt policy default_2026_10_20 ac4ae89b`; adopting it
|
|
104
|
+
consents to sending the run's artifacts to the reviewers configured in multi_llm_review.
|
|
105
|
+
|
|
106
|
+
`masa_2026_10_20.rb` is no longer shipped and is not listed in `removed_files`, so upgrade leaves an installed copy
|
|
107
|
+
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
|
|
108
|
+
rules: an instance that never adopted it may delete it, and one that did may adopt `default_2026_10_20` instead. A
|
|
109
|
+
shipped policy is never changed in place; a changed rule ships under a new policy name in a new file. Design:
|
|
110
|
+
`log/agent_policy_default_and_proposal_design_v0.7.2_20261021.md`.
|
|
111
|
+
|
|
112
|
+
### Changed — personal material out of the shipped agent tree
|
|
113
|
+
|
|
114
|
+
Home paths, a person's project and course names, answers typed in a real course and a third party's name are
|
|
115
|
+
replaced by synthetic ones in the agent SkillSet's tests and one code comment. The published 3.95.0 gem and the
|
|
116
|
+
repository history keep them.
|
|
117
|
+
|
|
118
|
+
### Added — `bin/agent_policy_report.rb`
|
|
119
|
+
|
|
120
|
+
An operator-run script that reports, for each rule of the adopted policy, what the runs the chain records as ended
|
|
121
|
+
hold against it: stand-in answers by class and their corrections, review rounds and cap hits, stand-in calls and
|
|
122
|
+
grants, data checks, with counts, denominators and the operator's words. It moves no rule, evaluates no file
|
|
123
|
+
from a run directory, and writes only its report, under `storage/agent/policy_reports/` (and
|
|
124
|
+
`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
|
|
125
|
+
operator's words, and the report says so. A policy changes only by the operator's own copy, edit and typed
|
|
126
|
+
adoption.
|
|
127
|
+
|
|
9
128
|
## [3.95.0] - 2026-10-21
|
|
10
129
|
|
|
11
130
|
### 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
|
|
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
|
-
|
|
117
|
-
|
|
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
|
-
|
|
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)
|
data/lib/kairos_mcp/version.rb
CHANGED
|
@@ -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.
|
|
4
|
+
version: "3.17.1"
|
|
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,
|
|
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,89 @@ Save to L2 context at these moments:
|
|
|
861
861
|
|
|
862
862
|
# Execution
|
|
863
863
|
|
|
864
|
-
##
|
|
864
|
+
## Execution Environment
|
|
865
865
|
|
|
866
|
-
###
|
|
866
|
+
### Reduced rosters and non-Claude hosts
|
|
867
867
|
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
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
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
-
|
|
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. One kind of round always carries the line: an `exclude` round
|
|
900
|
+
whose caller names a slot (that slot does not count). An agent SkillSet round no
|
|
901
|
+
longer always carries it: agent 1.0.2 convenes three personas on the host and
|
|
902
|
+
submits the replies the host handed back, where 1.0.1 submitted none, so its line
|
|
903
|
+
follows the same rule as any other round. None of this changes the verdict or the quorum
|
|
904
|
+
(`min_quorum`, 2 shipped). An INSUFFICIENT result also says how many seats counted
|
|
905
|
+
and how many were needed, that a seat can be added in config, and the restoring
|
|
906
|
+
action for each reason in the table above.
|
|
907
|
+
|
|
908
|
+
**Claude Code without codex or cursor.** Nothing to configure. The persona team and
|
|
909
|
+
the Sonnet seat count, APPROVE is reachable, and every result says "2 of 4 seats
|
|
910
|
+
counted … maker diversity not established".
|
|
911
|
+
|
|
912
|
+
**A host other than Claude Code.** Pass `orchestrator_host` (`codex_cli`, `cursor`
|
|
913
|
+
or `other`; `claude_code` or nothing keeps `claude_team_<model>`), and the persona
|
|
914
|
+
seat is recorded as `codex_team_<model>` and so on, beside the server's own
|
|
915
|
+
detection of its host. Run the personas as separate sub-agents of your host (Codex:
|
|
916
|
+
multi-agent). Nothing in the system can observe that, so the persona seat is always
|
|
917
|
+
recorded as your declaration. A Codex session can still run the `claude` seats:
|
|
918
|
+
Codex's sandbox does not confine kairos-chain's MCP server.
|
|
919
|
+
|
|
920
|
+
**A machine with only the codex CLI.** One seat can answer, below the quorum, so
|
|
921
|
+
every review is INSUFFICIENT until a second codex seat is added on another model —
|
|
922
|
+
the commented recipe in `config/multi_llm_review.yml`. Upgrades never rewrite an
|
|
923
|
+
instance's config, so an existing instance adds it by hand: a slot naming
|
|
924
|
+
`provider`, `model` and `role_label`, on a model the roster does not already name.
|
|
925
|
+
With orchestrator_model `gpt-6-astra` and a `gpt-6-sol` seat:
|
|
926
|
+
|
|
927
|
+
| Strategy | Counted seats | What it costs |
|
|
928
|
+
|---|---|---|
|
|
929
|
+
| `delegate` (default) | 2: `gpt-6-sol` and your persona team | the persona seat rests on your declaration |
|
|
930
|
+
| `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 |
|
|
931
|
+
| `exclude` | 1: your slot leaves (`exclude_orchestrator_model: true`, shipped) | below the quorum |
|
|
932
|
+
|
|
933
|
+
**A host with a per-call time limit** (Codex: `tool_timeout_sec` per MCP server;
|
|
934
|
+
documented default 60 s, not verified here). A `subprocess` review is one call that
|
|
935
|
+
lasts as long as the slowest seat, so first raise the limit for kairos-chain above
|
|
936
|
+
both configured `timeout_seconds`, with a margin. A cut single-phase call leaves its
|
|
937
|
+
record only in the run's `completed.json`. On the delegate path the first call
|
|
938
|
+
returns at once, but waiting in short calls is no substitute: three consecutive
|
|
939
|
+
`still_pending` replies from `multi_llm_review_wait` end in `crashed` /
|
|
940
|
+
`wait_exhausted` while the worker is still healthy. Raise the host's limit instead.
|
|
941
|
+
`multi_llm_review_collect` waits at most `collect_max_wait_seconds` (420 shipped)
|
|
942
|
+
before reaping a live worker, so call collect after wait has said `ready`.
|
|
943
|
+
|
|
944
|
+
**Path A (manual Bash).** Run `which codex`, `which agent`, `which claude`; leave
|
|
945
|
+
out the line of a CLI that is not found, and read the result by the same rules: the
|
|
946
|
+
quorum stays 2, and the report says which seats did not count and why.
|
|
878
947
|
|
|
879
948
|
### CLI Tool Matrix (tested 2026-03-28; model flags made mandatory 2026-07-27)
|
|
880
949
|
|
|
@@ -1069,7 +1138,7 @@ multi_llm_review(
|
|
|
1069
1138
|
`orchestrator_strategy: "subprocess"`.
|
|
1070
1139
|
- If `orchestrator_model` is `null` or unmatched, full roster runs (back-compat).
|
|
1071
1140
|
|
|
1072
|
-
**
|
|
1141
|
+
**Path A equivalent**: When orchestrating by hand, do not assign yourself
|
|
1073
1142
|
as a subprocess reviewer. Run the Claude CLI subprocess reviewers (Sonnet 5.5, plus
|
|
1074
1143
|
any frontier roster slot you are not); if your own model matches one of them,
|
|
1075
1144
|
skip that entry and use the after-exclusion convergence rule.
|
|
@@ -1094,19 +1163,21 @@ cross-model subprocess reviewers give epistemic diversity. The two are complemen
|
|
|
1094
1163
|
|
|
1095
1164
|
**Call 1**: `multi_llm_review(orchestrator_strategy: "delegate", orchestrator_model: "...")`
|
|
1096
1165
|
- SkillSet drops the orchestrator-matching reviewer from dispatch
|
|
1097
|
-
- Subprocess reviewers run
|
|
1098
|
-
|
|
1166
|
+
- Subprocess reviewers run in a detached worker (default `parallel: true`), or
|
|
1167
|
+
synchronously with `parallel: false`
|
|
1168
|
+
- Subprocess results persisted under `.kairos/multi_llm_review/pending/<token>/`
|
|
1099
1169
|
- Returns `status: "delegation_pending"`, `collect_token`, `persona_count_min/max`
|
|
1100
1170
|
|
|
1101
1171
|
**Orchestrator's obligation** (between calls):
|
|
1102
1172
|
- Recognize the `delegation_pending` status
|
|
1103
|
-
-
|
|
1173
|
+
- Run 2-4 personas as separate sub-agents of your host (Claude Code: parallel
|
|
1174
|
+
`Agent` tool calls; Codex: multi-agent), self-chosen and appropriate to
|
|
1104
1175
|
the artifact (e.g. design → architect/security/operability; code → correctness/
|
|
1105
1176
|
performance/api-design; doc → ontologist/skeptic/integration)
|
|
1106
1177
|
- Collect persona results: each as `{persona, verdict (APPROVE|REVISE|REJECT),
|
|
1107
1178
|
reasoning, findings: [{severity, issue}, ...]}`
|
|
1108
|
-
- Bind each persona to its subagent: add `agent_id` — the id the
|
|
1109
|
-
returned for that persona's subagent — to its entry. With the model_provenance
|
|
1179
|
+
- Bind each persona to its subagent (Claude Code): add `agent_id` — the id the
|
|
1180
|
+
Agent tool returned for that persona's subagent — to its entry. With the model_provenance
|
|
1110
1181
|
SkillSet installed, the seat then records the model the harness observed
|
|
1111
1182
|
answering, not only the declared one: a safety-classifier fallback inside a
|
|
1112
1183
|
persona (Opus 5.5 → Opus 5 on biology, → Opus 4.8 on cyber) otherwise leaves
|
|
@@ -1120,7 +1191,8 @@ cross-model subprocess reviewers give epistemic diversity. The two are complemen
|
|
|
1120
1191
|
|
|
1121
1192
|
**Call 2**: `multi_llm_review_collect(collect_token, orchestrator_reviews: [...])`
|
|
1122
1193
|
- Persona Assembly: any REJECT → REJECT; else any REVISE → REVISE; else APPROVE
|
|
1123
|
-
- Assembled into one synthetic reviewer entry
|
|
1194
|
+
- Assembled into one synthetic reviewer entry `<host>_team_<model>`
|
|
1195
|
+
(`claude_team_` for `orchestrator_host` claude_code or none; § Reduced rosters)
|
|
1124
1196
|
- Combined with persisted subprocess results, run Consensus, return final verdict
|
|
1125
1197
|
- Idempotent: repeated calls with the same token return the cached result
|
|
1126
1198
|
|
|
@@ -1128,9 +1200,12 @@ cross-model subprocess reviewers give epistemic diversity. The two are complemen
|
|
|
1128
1200
|
- `expired_or_unknown_token`: orchestrator missed `must_collect_by` deadline
|
|
1129
1201
|
(default 1800s since v3.23.2; was 600s), or token never existed. The pending
|
|
1130
1202
|
review is gone; call `multi_llm_review` again from scratch.
|
|
1131
|
-
- `error: invalid orchestrator_reviews`:
|
|
1132
|
-
required fields. Fix and retry collect with the same token.
|
|
1133
|
-
|
|
1203
|
+
- `error: invalid orchestrator_reviews`: more than 4 personas, or missing
|
|
1204
|
+
required fields. Fix and retry collect with the same token. 0–4 are accepted;
|
|
1205
|
+
fewer than convened is recorded as a shortfall.
|
|
1206
|
+
- All subprocess seats failed at Call 1: with `parallel: false` it returns an
|
|
1207
|
+
error at once and issues no token; on the default parallel path the failures
|
|
1208
|
+
surface at collect, as INSUFFICIENT with each seat's reason.
|
|
1134
1209
|
|
|
1135
1210
|
**Default**: `orchestrator_strategy` defaults to `"delegate"` (config key
|
|
1136
1211
|
`default_orchestrator_strategy`). `"exclude"` remains available as the legacy
|
|
@@ -1554,7 +1629,8 @@ Step 3: Execute the configured roster in parallel (currently 4 slots, one of
|
|
|
1554
1629
|
Step 4: Collect and validate
|
|
1555
1630
|
- Wait for all to complete (background task notifications)
|
|
1556
1631
|
- Verify each output file exists and contains structured review
|
|
1557
|
-
- Failed tool →
|
|
1632
|
+
- Failed tool → record it as not counted, with its cause (§ Reduced rosters
|
|
1633
|
+
and non-Claude hosts)
|
|
1558
1634
|
|
|
1559
1635
|
Step 5: Consensus analysis
|
|
1560
1636
|
- Read all review files
|
|
@@ -1571,10 +1647,11 @@ Step 6: Report to user
|
|
|
1571
1647
|
|
|
1572
1648
|
| Error | Detection | Recovery |
|
|
1573
1649
|
|-------|-----------|----------|
|
|
1574
|
-
| CLI not found | `which` non-zero |
|
|
1575
|
-
|
|
|
1576
|
-
|
|
|
1577
|
-
|
|
|
1650
|
+
| CLI not found | `cli_missing` (Path A: `which` non-zero) | Install, or fix the server's PATH |
|
|
1651
|
+
| Not logged in | `cli_unauthenticated` | Log in with that CLI |
|
|
1652
|
+
| codex refuses the directory | `workspace_refused` | Run from inside a git repository |
|
|
1653
|
+
| Timeout | `cli_timeout` / `dispatch_timeout` | Raise both `timeout_seconds`; mind `collect_deadline_seconds` |
|
|
1654
|
+
| Empty output | `no_verdict` / `insubstantial` | Report failure, retry |
|
|
1578
1655
|
| Trust prompt | Agent hangs | `--trust` flag |
|
|
1579
1656
|
| Usage limit | "usage limit" in output | Alternate tool fallback |
|
|
1580
1657
|
|
|
@@ -2028,6 +2105,27 @@ Compression ratio: parallel agent raw → Assembly ≈ 2:1
|
|
|
2028
2105
|
Step 0.25 guard-track sentence and § Convergence Rules. Source: design
|
|
2029
2106
|
`log/agent_skillset_rebuild_design_v0.5.1_20261020.md` §2 and its delta v0.6.6.
|
|
2030
2107
|
|
|
2108
|
+
- Reduced rosters and non-Claude hosts (v3.17.0, 2026-10-21, operator request:
|
|
2109
|
+
「MLRのdefaultがclaude codeでない場合の処理について…修正しようと思います」,
|
|
2110
|
+
rulings 1–9 in L2 `decision_mlr_non_claude_host_four_rulings_20261021`).
|
|
2111
|
+
§ Auto Mode vs Manual Mode, which sent a missing CLI to a "Manual mode" it never
|
|
2112
|
+
described and counted 5 reviewers, is replaced by § Execution Environment /
|
|
2113
|
+
Reduced rosters and non-Claude hosts: what each failure cause means and what
|
|
2114
|
+
restores the seat, the roster line results now carry, what a Claude-only,
|
|
2115
|
+
non-Claude-host or codex-only setup counts under each strategy, and a host's
|
|
2116
|
+
per-call limit. The delegation protocol now names sub-agents of any host,
|
|
2117
|
+
`<host>_team_<model>`, the 0–4 persona range and where an all-failed Call 1
|
|
2118
|
+
surfaces; the Error Handling table maps the new reason tokens. Ships with
|
|
2119
|
+
multi_llm_review 0.12.0 and llm_client 0.4.0. Design
|
|
2120
|
+
`log/mlr_non_claude_host_design_v0.3.3_20261021.md`, frozen after four rounds.
|
|
2121
|
+
|
|
2122
|
+
- Agent runs convene persona seats (v3.17.1, 2026-10-22, operator request:
|
|
2123
|
+
「Agent SkillSet1.0.1でreview時にpersona数が0に決め打ちされてるそうですが、MLRの設定と異なるので
|
|
2124
|
+
修正して下さい」). § Reduced rosters no longer says an agent SkillSet round always
|
|
2125
|
+
carries the roster line: agent 1.0.2 declares and convenes three personas, launched
|
|
2126
|
+
by the run's actor through a marker the SkillSet's hook rewrites, and submits the
|
|
2127
|
+
replies the host handed back. Design `log/agent_persona_seats_design_v0.3_20261022.md`.
|
|
2128
|
+
|
|
2031
2129
|
**Key insight**: Design reviews and implementation reviews find
|
|
2032
2130
|
**categorically different bugs**. Both phases are necessary. The corollary that
|
|
2033
2131
|
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
|