kairos-chain 3.52.1 → 3.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +251 -0
- data/lib/kairos_mcp/http_server.rb +16 -4
- data/lib/kairos_mcp/knowledge_provider.rb +70 -8
- data/lib/kairos_mcp/skillset_manager.rb +11 -0
- data/lib/kairos_mcp/version.rb +1 -1
- data/templates/knowledge/hestiachain_meeting_place/hestiachain_meeting_place.md +34 -0
- data/templates/knowledge/instance_session_protocol/instance_session_protocol.md +155 -0
- data/templates/knowledge/kairoschain_development_pitfalls/kairoschain_development_pitfalls.md +179 -0
- data/templates/knowledge/multi_llm_review_workflow/multi_llm_review_workflow.md +296 -54
- data/templates/skillsets/hestia/lib/hestia/place_router.rb +186 -3
- data/templates/skillsets/hestia/skillset.json +1 -1
- data/templates/skillsets/llm_client/config/llm_client.yml +6 -3
- data/templates/skillsets/llm_client/lib/llm_client/claude_code_adapter.rb +11 -2
- data/templates/skillsets/multi_llm_review/bin/dispatch_worker.rb +2 -10
- data/templates/skillsets/multi_llm_review/config/multi_llm_review.yml +98 -32
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/build_review_bundle.rb +7 -1
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/consensus.rb +226 -13
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/dispatcher.rb +26 -3
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/observer_set.rb +236 -0
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/persona_assembly.rb +48 -2
- data/templates/skillsets/multi_llm_review/lib/multi_llm_review/review_serializer.rb +59 -0
- data/templates/skillsets/multi_llm_review/skillset.json +2 -2
- data/templates/skillsets/multi_llm_review/test/test_multi_llm_review.rb +69 -120
- data/templates/skillsets/multi_llm_review/test/test_multi_llm_review_bundle.rb +18 -8
- data/templates/skillsets/multi_llm_review/test/test_observer_set.rb +412 -0
- data/templates/skillsets/multi_llm_review/test/test_observer_set_seams.rb +585 -0
- data/templates/skillsets/multi_llm_review/test/test_tool_wiring.rb +599 -0
- data/templates/skillsets/multi_llm_review/tools/multi_llm_review.rb +228 -92
- data/templates/skillsets/multi_llm_review/tools/multi_llm_review_bundle.rb +42 -11
- data/templates/skillsets/multi_llm_review/tools/multi_llm_review_collect.rb +41 -13
- data/templates/skillsets/project_manager/config/pm.yml +11 -0
- data/templates/skillsets/project_manager/knowledge/project_manager_guide/project_manager_guide.md +41 -0
- data/templates/skillsets/project_manager/lib/project_manager/digest.rb +83 -0
- data/templates/skillsets/project_manager/lib/project_manager/store.rb +204 -0
- data/templates/skillsets/project_manager/lib/project_manager/tool_helpers.rb +22 -0
- data/templates/skillsets/project_manager/lib/project_manager.rb +17 -0
- data/templates/skillsets/project_manager/plugin/SKILL.md +71 -0
- data/templates/skillsets/project_manager/plugin/agents/secretary.md +227 -0
- data/templates/skillsets/project_manager/scripts/l2_scan.py +284 -0
- data/templates/skillsets/project_manager/skillset.json +37 -0
- data/templates/skillsets/project_manager/test/test_project_manager.rb +211 -0
- data/templates/skillsets/project_manager/tools/pm_digest.rb +58 -0
- data/templates/skillsets/project_manager/tools/pm_item.rb +121 -0
- data/templates/skillsets/project_manager/tools/pm_project.rb +75 -0
- data/templates/skillsets/project_manager/tools/pm_query.rb +64 -0
- data/templates/skillsets/project_manager/tools/pm_record.rb +127 -0
- data/templates/skillsets/skillset_exchange/lib/skillset_exchange/place_extension.rb +382 -6
- data/templates/skillsets/skillset_exchange/skillset.json +2 -1
- metadata +24 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2291c491a077a0cfdce3d77bdd3709e8e6278fc9eb656a02f3de5508e4f66580
|
|
4
|
+
data.tar.gz: 96fa06b0195df3167b3113c54125a093f31f4bed10955c044a2ef218fe6d9278
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 72064bd0e1bde0516e8dd2b90adcbb9a85f3d079f71507b9f77210985e2f995fc9a1e8af066eee19835dda664a707f09ae8f6420ecfb6135dec62aa92449b756
|
|
7
|
+
data.tar.gz: 2553da41e8590b33c49f8e0d3526d37ac80bc8f742bab79af45cb5798c7a425ad978e66099a47454f9ca1ade3cbce310a798b7a9d1400eedac7a781d3cfdd745
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,257 @@ All notable changes to the `kairos-chain` gem will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project follows [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [3.55.0] - 2026-07-27
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **`project_manager` SkillSet now ships with the gem** (v0.2.0). Previously
|
|
12
|
+
instance-local. Registers projects and work items, answers queries, produces a
|
|
13
|
+
session-start digest with derived dormancy, and records irreversible project
|
|
14
|
+
actions on the attestation chain. Ships a secretary-persona sub-agent under
|
|
15
|
+
`plugin/agents`, so the secretarial disposition runs in its own context under
|
|
16
|
+
any instruction mode rather than replacing the active one.
|
|
17
|
+
- **`scripts/l2_scan.py`** — read-only derivation of activity evidence from the
|
|
18
|
+
L2 context store. Reports, per work item, first and last activity, distinct
|
|
19
|
+
records, distinct active days, the interval against the memo's own marker, and
|
|
20
|
+
the most recent nearby record by name. It matches on a document's name, saved
|
|
21
|
+
path and tags — never its body, which measured roughly 25% precision — and it
|
|
22
|
+
claims no attribution: tags name subjects while items name work that remains,
|
|
23
|
+
so one record sits correctly under several items and the output is evidence for
|
|
24
|
+
the operator to judge. Writes nothing.
|
|
25
|
+
|
|
26
|
+
### Notes
|
|
27
|
+
|
|
28
|
+
- The operator's own data (the work-item store and the item-to-record mapping)
|
|
29
|
+
stays instance-local under `.kairos/pm/` and is not part of the package.
|
|
30
|
+
- Designs: `docs/drafts/project_manager_plugin_projection_draft_v0.7_FROZEN.md`
|
|
31
|
+
(sub-agent and confinement) and
|
|
32
|
+
`docs/drafts/project_manager_l2_derivation_draft_v0.12.md` (derivation).
|
|
33
|
+
Both state that the SkillSet stays instance-local; that is superseded by this
|
|
34
|
+
release on the operator's decision.
|
|
35
|
+
|
|
36
|
+
## [3.54.3] - 2026-07-27
|
|
37
|
+
|
|
38
|
+
### multi_llm_review SkillSet 0.5.2 — the cursor reviewer pins its model
|
|
39
|
+
|
|
40
|
+
The cursor roster entry carried no `model` key, so `cursor_adapter` omitted
|
|
41
|
+
`--model` and the reviewer ran on whatever the cursor CLI had as its default. That
|
|
42
|
+
default lives in `~/.cursor/cli-config.json`, is operator-editable from the
|
|
43
|
+
interactive Cursor client, and had been set to `claude-opus-4-8`.
|
|
44
|
+
|
|
45
|
+
The roster was therefore dispatching three Anthropic slots out of five — the
|
|
46
|
+
orchestrator's own persona team, Opus 4.6 via `claude -p`, and this entry — while
|
|
47
|
+
still labelling this one `cursor_composer2.5`. Both properties the roster exists for
|
|
48
|
+
were lost at once: provider diversity, which is the reason a five-model roster is
|
|
49
|
+
worth its cost, and the correspondence between a recorded `role_label` and the model
|
|
50
|
+
that actually answered, without which per-reviewer calibration accumulates against
|
|
51
|
+
the wrong name. Neither failure is visible from the review output.
|
|
52
|
+
|
|
53
|
+
The entry now names `composer-2.5` explicitly, which makes the roster independent of
|
|
54
|
+
a setting that is not part of this repository. The comment above it records why the
|
|
55
|
+
key is there, so a future edit does not remove it as redundant.
|
|
56
|
+
|
|
57
|
+
Config files stay operator-owned: an instance whose roster is untouched picks the
|
|
58
|
+
pinned model up on upgrade, and an instance that has already tuned its roster keeps
|
|
59
|
+
its own and should apply the same pin by hand.
|
|
60
|
+
|
|
61
|
+
- **`templates/skillsets/multi_llm_review/config/multi_llm_review.yml`**: cursor entry gains `model: composer-2.5`.
|
|
62
|
+
- **`templates/skillsets/multi_llm_review/skillset.json`**: 0.5.1 → 0.5.2.
|
|
63
|
+
|
|
64
|
+
## [3.54.2] - 2026-07-27
|
|
65
|
+
|
|
66
|
+
### multi_llm_review SkillSet 0.5.1 — so 3.54.1's changes actually propagate
|
|
67
|
+
|
|
68
|
+
3.54.1 shipped the roster change without bumping the SkillSet's own version, and
|
|
69
|
+
`skillset upgrade` is gated strictly on `Gem::Version` comparison. An existing
|
|
70
|
+
instance therefore reported `[UNCHANGED] multi_llm_review v0.5.0` and kept its
|
|
71
|
+
`lib/` and `tools/` as they were — the shipped changes reached the gem and stopped
|
|
72
|
+
there.
|
|
73
|
+
|
|
74
|
+
Two things were stranded by that. The `orchestrator_model` description is the one
|
|
75
|
+
that matters: it now states that the identifier must be passed as a bare ID with a
|
|
76
|
+
context suffix such as `[1m]` stripped, because the roster comparison rejects the
|
|
77
|
+
suffixed form and the caller then dispatches a subprocess against itself. That is
|
|
78
|
+
a behavioural instruction an orchestrating model reads at call time, not a comment.
|
|
79
|
+
The dispatcher's per-reviewer effort comment was stranded with it.
|
|
80
|
+
|
|
81
|
+
Nothing about the fix is new content; this release exists so the previous one is
|
|
82
|
+
deliverable. Config files stay operator-owned and are not replaced, so an instance
|
|
83
|
+
that has already tuned its roster keeps it across the upgrade.
|
|
84
|
+
|
|
85
|
+
- **`templates/skillsets/multi_llm_review/skillset.json`**: 0.5.0 → 0.5.1.
|
|
86
|
+
|
|
87
|
+
Lesson recorded for future SkillSet edits: bumping the gem version is not enough.
|
|
88
|
+
A change under `templates/skillsets/<name>/` reaches an existing instance only if
|
|
89
|
+
that SkillSet's own `version` also moves.
|
|
90
|
+
|
|
91
|
+
## [3.54.1] - 2026-07-27
|
|
92
|
+
|
|
93
|
+
### Fable 5 retired from the multi-LLM review roster
|
|
94
|
+
|
|
95
|
+
Five consecutive rounds returned nothing substantive from that slot: 85 to 128
|
|
96
|
+
characters in 5 to 7 seconds, each an opening sentence with no findings and no
|
|
97
|
+
verdict text. A slot that does not produce a review still counts toward the
|
|
98
|
+
denominator, so it lowered the achievable numerator without contributing signal —
|
|
99
|
+
with six configured reviewers and one permanently silent, `4/6` could not be
|
|
100
|
+
reached even when every working reviewer approved.
|
|
101
|
+
|
|
102
|
+
The roster is now five and the convergence rule is `3/5` (`3/4` after
|
|
103
|
+
orchestrator exclusion), keeping the same `ceil(N * 0.6)` majority basis. One
|
|
104
|
+
consequence is worth stating: with Opus 5 as orchestrator its own slot is
|
|
105
|
+
delegated to the persona team, so the Claude CLI side is Opus 4.6 alone.
|
|
106
|
+
|
|
107
|
+
Restoring the entry is a config edit plus widening the rule back to a six-reviewer
|
|
108
|
+
basis; the retirement rationale is recorded inline where the roster lives.
|
|
109
|
+
|
|
110
|
+
- **`templates/skillsets/multi_llm_review/config/multi_llm_review.yml`**: entry
|
|
111
|
+
removed, `convergence_rule` and `convergence_rule_after_exclusion` adjusted,
|
|
112
|
+
roster header and the orchestrator-exclusion example updated.
|
|
113
|
+
- **`templates/knowledge/multi_llm_review_workflow/`**: identifier list, retirement
|
|
114
|
+
history, and the two-frontier-entry rationale corrected.
|
|
115
|
+
|
|
116
|
+
Note for operators of an existing instance: `config/` files are operator-owned and
|
|
117
|
+
are not replaced on upgrade, so an instance that already ran the six-reviewer
|
|
118
|
+
roster keeps it until the config is edited by hand.
|
|
119
|
+
|
|
120
|
+
## [3.54.0] - 2026-07-26
|
|
121
|
+
|
|
122
|
+
### SkillSet-declared knowledge becomes reachable
|
|
123
|
+
|
|
124
|
+
`knowledge_dirs` in `skillset.json` was a declaration nothing read. Knowledge
|
|
125
|
+
bundled with a SkillSet was therefore write-only: present on disk, declared in
|
|
126
|
+
the manifest, and unreachable by name. Two independent causes, either sufficient
|
|
127
|
+
on its own — no core path consumed the field, and `add_external_dir` mutates a
|
|
128
|
+
single provider instance during SkillSet load while `knowledge_get` builds a
|
|
129
|
+
fresh provider per call, discarding the registration.
|
|
130
|
+
|
|
131
|
+
Resolution moved from imperative load-time mutation to declarative manifest
|
|
132
|
+
reading, which puts `knowledge_dirs` on the same footing as `tool_classes` and
|
|
133
|
+
`config_files`: the manifest is what governs. On a representative instance this
|
|
134
|
+
takes SkillSet-derived L1 entries from 0 to 23 across 16 SkillSets.
|
|
135
|
+
|
|
136
|
+
- **`lib/kairos_mcp/knowledge_provider.rb`**: `#initialize` now registers the
|
|
137
|
+
knowledge directories of every *enabled* SkillSet. Opt out with
|
|
138
|
+
`include_skillset_knowledge: false` for a provider scoped strictly to the main
|
|
139
|
+
knowledge dir.
|
|
140
|
+
- **`add_external_dir` gains `only:`**. The method takes a *container* of
|
|
141
|
+
entries, while `knowledge_dirs` declares *entry* directories; declared entries
|
|
142
|
+
are grouped by container and passed as `only:`. Without it, registering the
|
|
143
|
+
container would expose undeclared siblings — proximity on disk would become a
|
|
144
|
+
declaration. Knowledge a SkillSet ships without declaring stays invisible.
|
|
145
|
+
- **`add_external_dir` is idempotent** by absolute path, so the five SkillSets
|
|
146
|
+
that also register themselves do not produce duplicate `list` entries.
|
|
147
|
+
- **Failure is isolated**: a malformed `skillset.json` degrades to "no SkillSet
|
|
148
|
+
knowledge" with a warning on stderr, never to a broken knowledge layer.
|
|
149
|
+
- **`templates/skillsets/hestia/skillset.json`**: declares
|
|
150
|
+
`knowledge/hestia_chain_migration`, which shipped undeclared since its
|
|
151
|
+
introduction — the only declared-vs-actual mismatch across all SkillSets, and
|
|
152
|
+
how the undeclared-knowledge case was found.
|
|
153
|
+
- **`test_skillset_knowledge_registration.rb`** (new, 15 assertions): retrieval
|
|
154
|
+
by name, `list` source/layer tagging, disabled SkillSets contributing nothing,
|
|
155
|
+
opt-out, idempotency, undeclared siblings staying invisible, and survival of a
|
|
156
|
+
malformed manifest.
|
|
157
|
+
|
|
158
|
+
### New L1 knowledge
|
|
159
|
+
|
|
160
|
+
- **`kairoschain_development_pitfalls`**: failure modes that cannot be inferred
|
|
161
|
+
from reading the code being touched — the gem ships only `templates/`, so
|
|
162
|
+
entries under the dev-repo `knowledge/` reach nobody; `.kairos/` resolves
|
|
163
|
+
against the current working directory and silently creates a second data
|
|
164
|
+
directory on a wrong resolution; declared-but-undeclared knowledge; a truthy
|
|
165
|
+
return that is not a success (`PlaceRouter#authenticate!`); and an observed but
|
|
166
|
+
unexplained `instructions_mode` revert after upgrade.
|
|
167
|
+
- **`instance_session_protocol`**: the procedural half of an instance's operating
|
|
168
|
+
discipline — session-start calls, layer-state surfacing, continuity, knowledge
|
|
169
|
+
baseline, during-work and session-end tool discipline. Extracted from the
|
|
170
|
+
`masa` instruction mode so norms stay in the mode and the runbook loads on
|
|
171
|
+
demand. Contains no normative content.
|
|
172
|
+
- **`hestiachain_meeting_place`** gains § Interaction Policy: the outbound
|
|
173
|
+
redaction / inbound review / per-operation gate checklist, likewise extracted
|
|
174
|
+
from instruction-mode text.
|
|
175
|
+
|
|
176
|
+
## [3.53.1] - 2026-07-25
|
|
177
|
+
|
|
178
|
+
### Multi-LLM Review — Opus 5 enters the roster, Opus 4.8 retires (v3.6.2)
|
|
179
|
+
|
|
180
|
+
Both frontier Claude models (Opus 5, Fable 5) now sit in the reviewer roster at
|
|
181
|
+
once. This is not redundancy: whichever one is the session orchestrator matches
|
|
182
|
+
`orchestrator_model` and is taken by the default `delegate` strategy as the
|
|
183
|
+
persona-team slot, so the other is dispatched as a `claude -p` subprocess. The
|
|
184
|
+
Claude side therefore resolves to "orchestrator persona + other frontier model
|
|
185
|
+
via CLI + Opus 4.6 via CLI" under either orchestrator, with no per-orchestrator
|
|
186
|
+
configuration branch and no dispatcher change.
|
|
187
|
+
|
|
188
|
+
Opus 4.8 retires by the same succession logic that retired 4.7 in 3.51.2 (the
|
|
189
|
+
strictness / systematizing register passes to the direct successor). Roster size
|
|
190
|
+
stays 6, so `convergence_rule` (4/6) and `convergence_rule_after_exclusion`
|
|
191
|
+
(3/5) are unchanged.
|
|
192
|
+
|
|
193
|
+
- **`templates/skillsets/multi_llm_review/config/multi_llm_review.yml`**: roster
|
|
194
|
+
is now `claude-opus-5`, `claude-fable-5`, `claude-opus-4-6`, `gpt-5.6-sol`,
|
|
195
|
+
`gpt-5.5`, cursor default. The two frontier entries carry CLI-neutral
|
|
196
|
+
`role_label`s (`claude_cli_opus5`, `claude_cli_fable5`) because either can
|
|
197
|
+
take either path; the delegated one is relabelled `claude_team_<model>` by
|
|
198
|
+
PersonaAssembly at collect.
|
|
199
|
+
- **`templates/skillsets/llm_client/lib/llm_client/claude_code_adapter.rb`**:
|
|
200
|
+
`DEFAULT_MODEL` `claude-opus-4-8` -> `claude-opus-5`. Fallback only — roster
|
|
201
|
+
entries always pass an explicit model; the constant exists so an unspecified
|
|
202
|
+
call cannot be auto-routed to Haiku.
|
|
203
|
+
- **`templates/knowledge/multi_llm_review_workflow/` v3.6.1 -> v3.6.2**: roster,
|
|
204
|
+
CLI matrix, effort table, and orchestrator self-identification section updated
|
|
205
|
+
for the rotating-frontier arrangement.
|
|
206
|
+
|
|
207
|
+
Two corrections folded into the same knowledge revision:
|
|
208
|
+
|
|
209
|
+
- **`--bare` removed from every `claude -p` example.** The flag skips credential
|
|
210
|
+
loading, so the subprocess returns "Not logged in" (established 2026-07-23)
|
|
211
|
+
while the knowledge entry still mandated it. Project-instruction bias is
|
|
212
|
+
suppressed by `review_context: independent` instead.
|
|
213
|
+
- **`orchestrator_model` must be the bare model ID.** Opus 5 reports itself as
|
|
214
|
+
`claude-opus-5[1m]`; the roster compares by exact string and PersonaAssembly's
|
|
215
|
+
validator rejects `[`, so passing the raw self-report silently defeats
|
|
216
|
+
self-exclusion and lets the orchestrator review its own output.
|
|
217
|
+
|
|
218
|
+
Opus 5's reviewer bias profile is uncalibrated — record (a)/(b)/(c) breakdowns
|
|
219
|
+
per round in `multi_llm_reviewer_evaluation` until a profile accumulates.
|
|
220
|
+
|
|
221
|
+
No dispatcher, tool, or schema changes. Existing suite green (multi_llm_review
|
|
222
|
+
skillset tests: 249 runs, 0 failures).
|
|
223
|
+
|
|
224
|
+
## [3.53.0] - 2026-07-24
|
|
225
|
+
|
|
226
|
+
### SkillSet Web Catalog — anonymous public presentation surface for SkillSet deposits
|
|
227
|
+
|
|
228
|
+
Adds an anonymous, read-only web catalog for Meeting Place SkillSet deposits
|
|
229
|
+
(including certified distillates), closing the presentation gap with the
|
|
230
|
+
existing skill catalog: SkillSet deposits were previously reachable only
|
|
231
|
+
through the authenticated agent API and had no browser-visible surface.
|
|
232
|
+
|
|
233
|
+
Design `skillset_web_catalog` v0.3.1 FROZEN (design review 3 rounds, R3 6/6
|
|
234
|
+
APPROVE unanimous; implementation review 3 rounds, R3 8/8 APPROVE unanimous).
|
|
235
|
+
|
|
236
|
+
- **PlaceRouter public-route mechanism (WC-1/WC-2)**: extensions declare
|
|
237
|
+
unauthenticated `/place/web/` routes via `#public_route_prefixes` (the
|
|
238
|
+
capability travels with the extension, so every registration path wires it);
|
|
239
|
+
read-only by construction, dispatched through `#public_call` with no peer
|
|
240
|
+
identity; declarations are recorded and introspectable; the window
|
|
241
|
+
contributes method restriction, per-client rate limiting, and transport
|
|
242
|
+
security headers (CSP `default-src 'none'`, `X-Frame-Options: DENY`,
|
|
243
|
+
`nosniff`).
|
|
244
|
+
- **skillset_exchange catalog (WC-3/WC-4/WC-5)**: anonymous `/place/web/skillsets`
|
|
245
|
+
listing + per-deposit detail views. Certificate summary is projected onto the
|
|
246
|
+
CD-2 checkability vocabulary at the deposit crossing (never on the anonymous
|
|
247
|
+
path); provenance is rendered as a co-equal field with three truthful states
|
|
248
|
+
and no ranking/badge/filter keyed on certificate presence (CD-3); depositor
|
|
249
|
+
text is structurally separated and HTML-escaped; per-deposit-instance
|
|
250
|
+
addresses sever withdrawn/replaced listings; `no-store` caching.
|
|
251
|
+
- **docker/Caddyfile**: `header_up X-Real-IP {remote_host}` on the meeting-place
|
|
252
|
+
reverse-proxy blocks so the per-client rate limit keys on the real client and
|
|
253
|
+
cannot be spoofed or collapsed to the shared proxy IP.
|
|
254
|
+
|
|
255
|
+
New test suite `test_skillset_web_catalog.rb` (68 assertions). Exchange
|
|
256
|
+
interfaces, storage, and the hestia skill catalog are consumed unchanged.
|
|
257
|
+
|
|
7
258
|
## [3.51.3] - 2026-07-23
|
|
8
259
|
|
|
9
260
|
### Multi-LLM Review — knowledge template sync (v3.6.1)
|
|
@@ -374,10 +374,22 @@ module KairosMcp
|
|
|
374
374
|
require_path = File.join(ss.path, ext_def['require'])
|
|
375
375
|
require require_path
|
|
376
376
|
ext_class = Object.const_get(ext_def['class'])
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
)
|
|
377
|
+
# public_routes (skillset web catalog design WC-2): pass only when the
|
|
378
|
+
# installed hestia PlaceRouter supports it, so a newer gem composes
|
|
379
|
+
# with an older hestia SkillSet (and vice versa) without breaking.
|
|
380
|
+
supports_public = router.method(:register_extension).parameters.any? { |_type, name| name == :public_routes }
|
|
381
|
+
if supports_public
|
|
382
|
+
router.register_extension(
|
|
383
|
+
ext_class.new(router),
|
|
384
|
+
route_action_map: ext_def['route_actions'] || {},
|
|
385
|
+
public_routes: ext_def['public_routes'] || []
|
|
386
|
+
)
|
|
387
|
+
else
|
|
388
|
+
router.register_extension(
|
|
389
|
+
ext_class.new(router),
|
|
390
|
+
route_action_map: ext_def['route_actions'] || {}
|
|
391
|
+
)
|
|
392
|
+
end
|
|
381
393
|
rescue StandardError => e
|
|
382
394
|
$stderr.puts "[HttpServer] Failed to load extension '#{ext_def['class']}' " \
|
|
383
395
|
"from SkillSet '#{ss.name}': #{e.message}"
|
|
@@ -4,6 +4,7 @@ require 'digest'
|
|
|
4
4
|
require 'fileutils'
|
|
5
5
|
require 'yaml'
|
|
6
6
|
require_relative 'anthropic_skill_parser'
|
|
7
|
+
require_relative 'skillset_manager'
|
|
7
8
|
require_relative 'kairos_chain/chain'
|
|
8
9
|
require_relative 'vector_search/provider'
|
|
9
10
|
require_relative '../kairos_mcp'
|
|
@@ -39,7 +40,11 @@ module KairosMcp
|
|
|
39
40
|
# @param knowledge_dir [String] Path to knowledge directory
|
|
40
41
|
# @param vector_search_enabled [Boolean] Enable vector search
|
|
41
42
|
# @param storage_backend [Storage::Backend, nil] Storage backend to use
|
|
42
|
-
|
|
43
|
+
# @param include_skillset_knowledge [Boolean] Register knowledge dirs declared
|
|
44
|
+
# by enabled SkillSets. Default true; pass false to build a provider scoped
|
|
45
|
+
# strictly to the main knowledge dir.
|
|
46
|
+
def initialize(knowledge_dir = nil, vector_search_enabled: true, storage_backend: nil,
|
|
47
|
+
user_context: nil, include_skillset_knowledge: true)
|
|
43
48
|
knowledge_dir ||= KairosMcp.knowledge_dir(user_context: user_context)
|
|
44
49
|
@knowledge_dir = knowledge_dir
|
|
45
50
|
@user_context = user_context
|
|
@@ -49,19 +54,34 @@ module KairosMcp
|
|
|
49
54
|
@index_built = false
|
|
50
55
|
@external_dirs = []
|
|
51
56
|
FileUtils.mkdir_p(@knowledge_dir)
|
|
57
|
+
register_skillset_knowledge_dirs if include_skillset_knowledge
|
|
52
58
|
end
|
|
53
59
|
|
|
54
60
|
# Register an external knowledge directory (e.g. from a SkillSet)
|
|
55
61
|
# Knowledge is read-only from external dirs; no merge into the main dir.
|
|
56
62
|
#
|
|
57
|
-
# @param dir [String] Absolute path to the
|
|
63
|
+
# @param dir [String] Absolute path to the container directory holding entry
|
|
64
|
+
# subdirectories (e.g. `<skillset>/knowledge`), not an entry directory itself
|
|
58
65
|
# @param source [String] Identifier for the source (e.g. "skillset:mmp")
|
|
59
66
|
# @param layer [Symbol] Layer governance (:L0, :L1, :L2)
|
|
60
67
|
# @param index [Boolean] Whether to include in vector search index
|
|
61
|
-
|
|
68
|
+
# @param only [Array<String>, nil] Entry names to expose. nil exposes every
|
|
69
|
+
# subdirectory. Passing the declared set keeps undeclared knowledge shipped
|
|
70
|
+
# inside a SkillSet from becoming visible as L1 by proximity alone.
|
|
71
|
+
#
|
|
72
|
+
# Idempotent by directory: registering the same dir twice (e.g. once from the
|
|
73
|
+
# SkillSet manifest at construction, once from a SkillSet that also registers
|
|
74
|
+
# itself) keeps the first registration rather than duplicating list entries.
|
|
75
|
+
def add_external_dir(dir, source:, layer: :L1, index: true, only: nil)
|
|
62
76
|
return unless File.directory?(dir)
|
|
63
77
|
|
|
64
|
-
|
|
78
|
+
absolute = File.expand_path(dir)
|
|
79
|
+
return if @external_dirs.any? { |ext| ext[:dir] == absolute }
|
|
80
|
+
|
|
81
|
+
@external_dirs << {
|
|
82
|
+
dir: absolute, source: source, layer: layer, index: index,
|
|
83
|
+
only: only && Array(only).map { |n| File.basename(n.to_s) }
|
|
84
|
+
}
|
|
65
85
|
@index_built = false if index # Invalidate index when new indexed dir added
|
|
66
86
|
end
|
|
67
87
|
|
|
@@ -92,7 +112,7 @@ module KairosMcp
|
|
|
92
112
|
|
|
93
113
|
# Include knowledge from external directories (SkillSets)
|
|
94
114
|
@external_dirs.each do |ext|
|
|
95
|
-
external_skill_dirs(ext[:dir]).each do |dir|
|
|
115
|
+
external_skill_dirs(ext[:dir], only: ext[:only]).each do |dir|
|
|
96
116
|
skill = AnthropicSkillParser.parse(dir)
|
|
97
117
|
next unless skill
|
|
98
118
|
|
|
@@ -124,6 +144,8 @@ module KairosMcp
|
|
|
124
144
|
|
|
125
145
|
# Search external directories
|
|
126
146
|
@external_dirs.each do |ext|
|
|
147
|
+
next if ext[:only] && !ext[:only].include?(name)
|
|
148
|
+
|
|
127
149
|
ext_skill_dir = File.join(ext[:dir], name)
|
|
128
150
|
return AnthropicSkillParser.parse(ext_skill_dir) if File.directory?(ext_skill_dir)
|
|
129
151
|
end
|
|
@@ -327,7 +349,7 @@ module KairosMcp
|
|
|
327
349
|
|
|
328
350
|
# Include external dirs that have indexing enabled
|
|
329
351
|
@external_dirs.select { |ext| ext[:index] }.each do |ext|
|
|
330
|
-
external_skill_dirs(ext[:dir]).each do |dir|
|
|
352
|
+
external_skill_dirs(ext[:dir], only: ext[:only]).each do |dir|
|
|
331
353
|
skill = AnthropicSkillParser.parse(dir)
|
|
332
354
|
next unless skill
|
|
333
355
|
|
|
@@ -523,6 +545,43 @@ module KairosMcp
|
|
|
523
545
|
|
|
524
546
|
private
|
|
525
547
|
|
|
548
|
+
# Register the knowledge directories declared by every enabled SkillSet.
|
|
549
|
+
#
|
|
550
|
+
# `knowledge_dirs` in skillset.json is the single declaration of what a
|
|
551
|
+
# SkillSet contributes to L1. Resolving it here — instead of relying on each
|
|
552
|
+
# SkillSet to register itself during load! — keeps the declaration
|
|
553
|
+
# load-bearing for every provider instance, including the short-lived ones
|
|
554
|
+
# tools build per call. Without this, knowledge bundled with a SkillSet is
|
|
555
|
+
# write-only: present on disk, declared in the manifest, and unreachable by
|
|
556
|
+
# name.
|
|
557
|
+
#
|
|
558
|
+
# `knowledge_dirs` declares individual entry directories, while an external
|
|
559
|
+
# registration covers a container of entries. Declared entries are therefore
|
|
560
|
+
# grouped by their container and exposed via `only:`, so that knowledge a
|
|
561
|
+
# SkillSet ships but does not declare stays invisible — proximity on disk is
|
|
562
|
+
# not a declaration.
|
|
563
|
+
#
|
|
564
|
+
# Failure is isolated per SkillSet and overall: a malformed manifest or an
|
|
565
|
+
# unreadable directory degrades to "that SkillSet contributes no knowledge",
|
|
566
|
+
# never to a broken knowledge layer.
|
|
567
|
+
def register_skillset_knowledge_dirs
|
|
568
|
+
manager = SkillSetManager.new
|
|
569
|
+
|
|
570
|
+
manager.enabled_skillsets.each do |skillset|
|
|
571
|
+
skillset.knowledge_dirs.group_by { |dir| File.dirname(dir) }.each do |container, entries|
|
|
572
|
+
add_external_dir(container,
|
|
573
|
+
source: "skillset:#{skillset.name}",
|
|
574
|
+
layer: skillset.layer,
|
|
575
|
+
index: skillset.index_knowledge?,
|
|
576
|
+
only: entries.map { |e| File.basename(e) })
|
|
577
|
+
end
|
|
578
|
+
rescue StandardError => e
|
|
579
|
+
warn "[KnowledgeProvider] Skipped knowledge dirs for SkillSet '#{skillset.name}': #{e.message}"
|
|
580
|
+
end
|
|
581
|
+
rescue StandardError => e
|
|
582
|
+
warn "[KnowledgeProvider] SkillSet knowledge registration skipped: #{e.message}"
|
|
583
|
+
end
|
|
584
|
+
|
|
526
585
|
def vector_search
|
|
527
586
|
@vector_search ||= VectorSearch.create(index_path: KairosMcp.knowledge_index_path)
|
|
528
587
|
end
|
|
@@ -609,10 +668,13 @@ module KairosMcp
|
|
|
609
668
|
end
|
|
610
669
|
|
|
611
670
|
# List subdirectories in an external knowledge dir
|
|
612
|
-
def external_skill_dirs(dir)
|
|
671
|
+
def external_skill_dirs(dir, only: nil)
|
|
613
672
|
return [] unless File.directory?(dir)
|
|
614
673
|
|
|
615
|
-
Dir[File.join(dir, '*')].select { |f| File.directory?(f) && !backup_dir?(f) }
|
|
674
|
+
dirs = Dir[File.join(dir, '*')].select { |f| File.directory?(f) && !backup_dir?(f) }
|
|
675
|
+
return dirs unless only
|
|
676
|
+
|
|
677
|
+
dirs.select { |f| only.include?(File.basename(f)) }
|
|
616
678
|
end
|
|
617
679
|
|
|
618
680
|
# Detect upgrade backup directories (`.bak.<timestamp>`, `<name>.bak.<timestamp>`).
|
|
@@ -457,6 +457,17 @@ module KairosMcp
|
|
|
457
457
|
|
|
458
458
|
if !File.exist?(dst)
|
|
459
459
|
changed << rel
|
|
460
|
+
elsif rel.start_with?('config/')
|
|
461
|
+
# An existing config/ file is operator-owned state (activation
|
|
462
|
+
# flags, adopted profiles): a difference from the template is
|
|
463
|
+
# user customization, not a pending upgrade — never listed and
|
|
464
|
+
# therefore never overwritten by upgrade_apply. Parity with
|
|
465
|
+
# install(force:)'s config preservation and the docker
|
|
466
|
+
# entrypoint's config-preserving sync. (Production incident
|
|
467
|
+
# 2026-07-24: upgrade --apply silently reset the confidentiality
|
|
468
|
+
# guard's enabled: true to the template's false.) Absent config
|
|
469
|
+
# files still install above (new shipped config).
|
|
470
|
+
next
|
|
460
471
|
elsif Digest::SHA256.file(src).hexdigest != Digest::SHA256.file(dst).hexdigest
|
|
461
472
|
changed << rel
|
|
462
473
|
end
|
data/lib/kairos_mcp/version.rb
CHANGED
|
@@ -167,3 +167,37 @@ kairos.example.com {
|
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
For detailed DEE protocol internals, install the hestia SkillSet and refer to its bundled knowledge (`hestia_meeting_place`).
|
|
170
|
+
|
|
171
|
+
### Interaction Policy (instance discipline)
|
|
172
|
+
|
|
173
|
+
The procedural checklist an instance follows when interacting with a Meeting
|
|
174
|
+
Place. This is the *how*; whether an instance defaults to openness or to caution
|
|
175
|
+
is a matter for its instruction mode, and a mode that sets a different default
|
|
176
|
+
overrides the outbound bias below without changing the rest.
|
|
177
|
+
|
|
178
|
+
**Outbound (publishing, depositing, sharing)**
|
|
179
|
+
|
|
180
|
+
- Include provenance, version, applicable domain, and intended framing with
|
|
181
|
+
anything shared.
|
|
182
|
+
- Redact user-specific paths, credentials, and institutional details before they
|
|
183
|
+
leave the instance.
|
|
184
|
+
- Never share an L2 session context without explicit operator approval.
|
|
185
|
+
- Flag foreseeable misuse vectors at the moment of sharing, proactively.
|
|
186
|
+
|
|
187
|
+
**Inbound (browsing, acquiring, receiving)**
|
|
188
|
+
|
|
189
|
+
- Treat an external skill as untrusted until reviewed.
|
|
190
|
+
- Review before rejecting: unfamiliar is not the same as unsound.
|
|
191
|
+
- No auto-adoption, and no automatic execution of received code.
|
|
192
|
+
|
|
193
|
+
**Trust boundaries by operation**
|
|
194
|
+
|
|
195
|
+
| Operation | Gate |
|
|
196
|
+
|---|---|
|
|
197
|
+
| Browse, register | low risk — proceed |
|
|
198
|
+
| Deposit, acquire | explicit operator approval |
|
|
199
|
+
| Knowledge-needs publication | explicit opt-in |
|
|
200
|
+
|
|
201
|
+
The asymmetry is deliberate: reading the board changes nothing, while depositing
|
|
202
|
+
publishes to a service where content may be cached or indexed regardless of later
|
|
203
|
+
withdrawal.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Instance Session Protocol
|
|
3
|
+
description: Procedural runbook for an instance's session lifecycle — mandatory session-start tool calls, layer-state surfacing, continuity check, knowledge-gap baseline, during-work tool discipline, and session-end handoff. Retrieved on demand by an instruction mode; contains no normative content.
|
|
4
|
+
version: "0.1.0"
|
|
5
|
+
tags:
|
|
6
|
+
- session
|
|
7
|
+
- runbook
|
|
8
|
+
- layer_awareness
|
|
9
|
+
- tool_usage
|
|
10
|
+
- continuity
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Instance Session Protocol
|
|
14
|
+
|
|
15
|
+
## What this is
|
|
16
|
+
|
|
17
|
+
The procedural half of an instance's operating discipline: *what to call, in what
|
|
18
|
+
order, and what to report*. It was extracted from the `masa` instruction mode so
|
|
19
|
+
that the mode carries only norms and this runbook loads on demand.
|
|
20
|
+
|
|
21
|
+
**This entry contains no norms.** Why an instance should establish ground state,
|
|
22
|
+
what it owes the operator in disclosure, and how it weighs speed against
|
|
23
|
+
deliberation all remain in the active instruction mode. If the two ever conflict,
|
|
24
|
+
the mode wins and this runbook is the thing that gets revised.
|
|
25
|
+
|
|
26
|
+
An instruction mode adopts this protocol by referring to it. A mode that wants a
|
|
27
|
+
different lifecycle should write its own runbook rather than edit this one.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 1. Session start
|
|
32
|
+
|
|
33
|
+
Execute proactively, before responding to the operator's first task. The goal is
|
|
34
|
+
shared ground state, not a diagnostic dump: **report in 4–6 lines total, naming
|
|
35
|
+
issues only if found.**
|
|
36
|
+
|
|
37
|
+
### 1.1 Required tool calls
|
|
38
|
+
|
|
39
|
+
1. `chain_status()` — verify system health: blockchain integrity, layer counts,
|
|
40
|
+
last known good state.
|
|
41
|
+
2. `resource_read(uri: "l0://kairos.md")` — load the propositions into working
|
|
42
|
+
context. They ground every other decision in the session.
|
|
43
|
+
3. `knowledge_get(name: "kairoschain_self_development")` — load the development
|
|
44
|
+
workflow, when the session works on KairosChain itself.
|
|
45
|
+
4. `skills_audit(command: "check", layer: "L1")` — verify knowledge-layer health
|
|
46
|
+
and surface drift.
|
|
47
|
+
|
|
48
|
+
**Why step 4 is scoped to L1 deliberately**: L2 contexts are a growing record, so
|
|
49
|
+
age is their normal condition rather than a defect. An unscoped audit reports
|
|
50
|
+
every context older than 14 days as an issue, and the response outgrows the tool's
|
|
51
|
+
own output limit. When L2 needs attention, ask a *state* question — which handoffs
|
|
52
|
+
are still `pending`? — not an age question.
|
|
53
|
+
|
|
54
|
+
### 1.2 Layer state surface
|
|
55
|
+
|
|
56
|
+
After the calls, surface the operational layer state in 3–5 lines:
|
|
57
|
+
|
|
58
|
+
- Which host features are active this session (hooks, permissions, plugin
|
|
59
|
+
projection, Skill tool, MCP transport).
|
|
60
|
+
- Which MCP server is connected, and its version.
|
|
61
|
+
- How plugin projection has mapped SkillSets to host artefacts — digest from
|
|
62
|
+
`projection_manifest.json`.
|
|
63
|
+
- Any layer-specific constraint in effect: read-only mode, dry-run mode,
|
|
64
|
+
suspended skills.
|
|
65
|
+
|
|
66
|
+
Supplying this is the harness's job, not something the model can obtain by
|
|
67
|
+
introspection. An agent cannot reliably determine which layer it is operating in
|
|
68
|
+
from the inside; the surface exists so that boundary crossings become reasoned
|
|
69
|
+
rather than accidental.
|
|
70
|
+
|
|
71
|
+
### 1.3 Continuity
|
|
72
|
+
|
|
73
|
+
If recent L2 contexts indicate work this session might continue — handoffs tagged
|
|
74
|
+
`pending`, unresolved revision candidates, paused review cycles — name them
|
|
75
|
+
briefly and offer to resume. **Do not auto-resume.**
|
|
76
|
+
|
|
77
|
+
### 1.4 Knowledge-gap baseline
|
|
78
|
+
|
|
79
|
+
Check the baseline entries in § 3 against what the instance actually has. Report
|
|
80
|
+
gaps only when they bear on the current task.
|
|
81
|
+
|
|
82
|
+
### 1.5 Failure mode
|
|
83
|
+
|
|
84
|
+
If any required call fails, surface the failure immediately and pause
|
|
85
|
+
non-essential work. A session whose ground state cannot be confirmed must not
|
|
86
|
+
proceed to autonomous tasks. (Autonomous behaviour lives in dedicated SkillSets
|
|
87
|
+
and is out of scope here.)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 2. During work and at session end
|
|
92
|
+
|
|
93
|
+
Treat KairosChain tools as primary working memory: retrieve before generating.
|
|
94
|
+
|
|
95
|
+
### 2.1 During work
|
|
96
|
+
|
|
97
|
+
- **Before answering**: check L1 for a relevant convention. When one applies, say
|
|
98
|
+
so — "applying your saved convention X here" — rather than applying it silently.
|
|
99
|
+
- **Multi-LLM review**: follow `multi_llm_review_workflow`.
|
|
100
|
+
- **Design work**: prototype while designing; checkpoint the evolution of the
|
|
101
|
+
design, not only its conclusion.
|
|
102
|
+
- **Steady state**: when system health is good, say so. Do not report only
|
|
103
|
+
problems.
|
|
104
|
+
|
|
105
|
+
### 2.2 Session end (with operator consent)
|
|
106
|
+
|
|
107
|
+
- Offer `context_save()`.
|
|
108
|
+
- Extract reusable patterns; propose L1 promotion for recurring ones.
|
|
109
|
+
- When the session included design or philosophical work, save the reasoning
|
|
110
|
+
process, not only the conclusion.
|
|
111
|
+
|
|
112
|
+
### 2.3 Transparency
|
|
113
|
+
|
|
114
|
+
When invoking tools proactively, briefly state what was done and why. Never use a
|
|
115
|
+
tool silently and leave its result unsurfaced.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 3. Knowledge baseline
|
|
120
|
+
|
|
121
|
+
Entries an instance is expected to have available:
|
|
122
|
+
|
|
123
|
+
| Entry | Status |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `multi_llm_review_workflow` | available |
|
|
126
|
+
| `multi_llm_reviewer_evaluation` | available |
|
|
127
|
+
| `design_to_implementation_workflow` | available |
|
|
128
|
+
| `hestiachain_meeting_place` | available |
|
|
129
|
+
| `kairoschain_development_pitfalls` | available |
|
|
130
|
+
| `skillset_implementation_quality_guide` | **not retrievable** — ships only under the dev-repo `knowledge/`, which is absent from the gem |
|
|
131
|
+
| `kairoschain_meta_philosophy` | **not retrievable** — same cause |
|
|
132
|
+
|
|
133
|
+
The two unreachable entries are a known packaging consequence documented in
|
|
134
|
+
`kairoschain_development_pitfalls` § 1. Do not report them as instance-local gaps
|
|
135
|
+
to be authored: the content exists, its distribution path does not. Report them as
|
|
136
|
+
gaps only if a session needs their content, in which case read the file directly
|
|
137
|
+
from the dev repo.
|
|
138
|
+
|
|
139
|
+
`multi_llm_design_review` appears in older mode text as a baseline entry. No such
|
|
140
|
+
entry exists; the correct name is `multi_llm_review_workflow`.
|
|
141
|
+
|
|
142
|
+
### Behaviour on a genuine gap
|
|
143
|
+
|
|
144
|
+
- Propose creating the missing entry, with a draft outline.
|
|
145
|
+
- Cross-instance, opt-in only: publish knowledge needs via
|
|
146
|
+
`meeting_publish_needs(opt_in: true)`.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Maintenance
|
|
151
|
+
|
|
152
|
+
When a step here stops matching what an instance actually does, change this file
|
|
153
|
+
rather than adding a local exception in the instruction mode. The mode's job is to
|
|
154
|
+
say what the instance owes; this file's job is to say how the instance discharges
|
|
155
|
+
it, and it is expected to churn faster than the mode.
|