kairos-chain 2.4.0 → 2.5.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 +24 -0
- data/lib/kairos_mcp/tools/skills_audit.rb +233 -3
- data/lib/kairos_mcp/version.rb +1 -1
- data/templates/knowledge/hestiachain_meeting_place/hestiachain_meeting_place.md +27 -5
- data/templates/knowledge/hestiachain_meeting_place_jp/hestiachain_meeting_place_jp.md +27 -5
- data/templates/knowledge/kairoschain_operations/kairoschain_operations.md +5 -2
- data/templates/knowledge/kairoschain_operations_jp/kairoschain_operations_jp.md +4 -1
- data/templates/knowledge/kairoschain_usage/kairoschain_usage.md +3 -1
- data/templates/knowledge/kairoschain_usage_jp/kairoschain_usage_jp.md +2 -0
- data/templates/knowledge/persona_definitions/persona_definitions.md +10 -1
- data/templates/skills/kairos_tutorial.md +51 -0
- data/templates/skillsets/hestia/lib/hestia/place_router.rb +51 -0
- data/templates/skillsets/hestia/lib/hestia/skill_board.rb +42 -0
- data/templates/skillsets/hestia/skillset.json +2 -1
- data/templates/skillsets/hestia/tools/meeting_publish_needs.rb +171 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4bb1a479485b0eeb8315806b9cb6b657aab0999da825b028c1bd164d29d7683a
|
|
4
|
+
data.tar.gz: f0c41de78a0b1a83bd0826b71e7847a80549f5f3ce91673acaefcafd322b9c23
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 86afd61254c72f559565196bf3caa53f547b5f3483ae5562cbedac0ddaa9d56970ec19aa54eaed3278f338e2ca930ab5c7dcd9d6acbe681f61b0bc0d197ae706
|
|
7
|
+
data.tar.gz: d8de0bb6abda6c4e1837c3976a1e85a4b2784d8e8619afda40434c64b1365733ca69666b5de981c87ec3f296667192e9b7a3d573a0301108c2fd7c3408e55b7e
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,29 @@ 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
|
+
## [2.5.0] - 2026-03-03
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Cross-Instance Knowledge Discovery**: KairosChain instances connected to a Meeting Place can now publish knowledge gaps as "needs" to the SkillBoard. Other agents browsing the board can discover these needs and offer relevant knowledge.
|
|
12
|
+
- `skills_audit(command: "export_needs")`: New audit command to package knowledge gaps for cross-instance sharing
|
|
13
|
+
- `meeting_publish_needs`: New Hestia MCP tool to publish needs to the Meeting Place board (requires explicit `opt_in: true`)
|
|
14
|
+
- `SkillBoard#post_need` / `remove_needs`: In-memory need entries (session-only, no persistence — DEE compliant)
|
|
15
|
+
- `POST /place/v1/board/needs`: New HTTP endpoint to publish knowledge needs
|
|
16
|
+
- `DELETE /place/v1/board/needs`: New HTTP endpoint to remove published needs
|
|
17
|
+
- `browse(type: 'need')`: Filter board entries to show only knowledge needs
|
|
18
|
+
- Needs are automatically cleaned up on agent unregister
|
|
19
|
+
|
|
20
|
+
- **Knowledge Acquisition Policy — Cross-Instance Extension**: Tutorial template Acquisition Behavior now includes opt-in cross-instance knowledge needs publishing guidance
|
|
21
|
+
|
|
22
|
+
- **L1 Knowledge Updates**: Updated `hestiachain_meeting_place` (EN/JP), `kairoschain_usage` (EN/JP), `kairoschain_operations` (EN/JP), `persona_definitions` with cross-instance discovery, proactive tool usage, and dynamic persona suggestion documentation
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **PlaceRouter query string parsing**: Added missing `require 'uri'` — `parse_query` was silently failing due to `NameError` on `URI.decode_www_form`, causing all browse query parameters (`type`, `search`, `limit`) to be ignored
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
7
30
|
## [2.4.0] - 2026-03-03
|
|
8
31
|
|
|
9
32
|
### Added
|
|
@@ -284,6 +307,7 @@ This project follows [Semantic Versioning](https://semver.org/).
|
|
|
284
307
|
- Skill promotion with Persona Assembly
|
|
285
308
|
- Tool guide and metadata system
|
|
286
309
|
|
|
310
|
+
[2.5.0]: https://github.com/masaomi/KairosChain_2026/compare/v2.4.0...v2.5.0
|
|
287
311
|
[2.4.0]: https://github.com/masaomi/KairosChain_2026/compare/v2.3.1...v2.4.0
|
|
288
312
|
[2.3.1]: https://github.com/masaomi/KairosChain_2026/compare/v2.3.0...v2.3.1
|
|
289
313
|
[2.3.0]: https://github.com/masaomi/KairosChain_2026/compare/v2.2.0...v2.3.0
|
|
@@ -4,6 +4,7 @@ require_relative 'base_tool'
|
|
|
4
4
|
require_relative '../knowledge_provider'
|
|
5
5
|
require_relative '../context_manager'
|
|
6
6
|
require_relative '../dsl_skills_provider'
|
|
7
|
+
require_relative '../skills_config'
|
|
7
8
|
require_relative '../kairos'
|
|
8
9
|
|
|
9
10
|
module KairosMcp
|
|
@@ -38,7 +39,7 @@ module KairosMcp
|
|
|
38
39
|
}
|
|
39
40
|
}.freeze
|
|
40
41
|
|
|
41
|
-
READONLY_COMMANDS = %w[check conflicts stale dangerous recommend].freeze
|
|
42
|
+
READONLY_COMMANDS = %w[check conflicts stale dangerous recommend gaps export_needs].freeze
|
|
42
43
|
WRITE_COMMANDS = %w[archive unarchive].freeze
|
|
43
44
|
|
|
44
45
|
def name
|
|
@@ -47,7 +48,8 @@ module KairosMcp
|
|
|
47
48
|
|
|
48
49
|
def description
|
|
49
50
|
'Audit knowledge health across L0/L1/L2 layers. Check for conflicts, staleness, ' \
|
|
50
|
-
'dangerous patterns,
|
|
51
|
+
'dangerous patterns, get promotion/archive recommendations, and detect knowledge gaps ' \
|
|
52
|
+
'defined by custom instruction mode policies. ' \
|
|
51
53
|
'Archive operations require human approval (approved: true).'
|
|
52
54
|
end
|
|
53
55
|
|
|
@@ -56,7 +58,7 @@ module KairosMcp
|
|
|
56
58
|
end
|
|
57
59
|
|
|
58
60
|
def usecase_tags
|
|
59
|
-
%w[audit health check recommend archive stale dangerous L0 L1 L2]
|
|
61
|
+
%w[audit health check recommend archive stale dangerous gaps needs meeting knowledge-policy L0 L1 L2]
|
|
60
62
|
end
|
|
61
63
|
|
|
62
64
|
def examples
|
|
@@ -76,6 +78,18 @@ module KairosMcp
|
|
|
76
78
|
{
|
|
77
79
|
title: 'Archive stale knowledge',
|
|
78
80
|
code: 'skills_audit(command: "archive", target: "old_guide", reason: "No longer relevant", approved: true)'
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
title: 'Check knowledge gaps for current mode',
|
|
84
|
+
code: 'skills_audit(command: "gaps")'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
title: 'Check knowledge gaps for specific mode',
|
|
88
|
+
code: 'skills_audit(command: "gaps", mode_name: "genomics_expert")'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
title: 'Export knowledge needs for Meeting Place sharing',
|
|
92
|
+
code: 'skills_audit(command: "export_needs")'
|
|
79
93
|
}
|
|
80
94
|
]
|
|
81
95
|
end
|
|
@@ -143,6 +157,10 @@ module KairosMcp
|
|
|
143
157
|
include_archived: {
|
|
144
158
|
type: 'boolean',
|
|
145
159
|
description: 'Include archived items in results (default: false)'
|
|
160
|
+
},
|
|
161
|
+
mode_name: {
|
|
162
|
+
type: 'string',
|
|
163
|
+
description: 'Instruction mode name (for gaps command). Defaults to current active mode.'
|
|
146
164
|
}
|
|
147
165
|
},
|
|
148
166
|
required: ['command']
|
|
@@ -192,6 +210,10 @@ module KairosMcp
|
|
|
192
210
|
run_dangerous_check(layer, args)
|
|
193
211
|
when 'recommend'
|
|
194
212
|
run_recommendations(layer, args)
|
|
213
|
+
when 'gaps'
|
|
214
|
+
run_gaps_check(args)
|
|
215
|
+
when 'export_needs'
|
|
216
|
+
run_export_needs(args)
|
|
195
217
|
end
|
|
196
218
|
|
|
197
219
|
output << result
|
|
@@ -895,6 +917,214 @@ module KairosMcp
|
|
|
895
917
|
end
|
|
896
918
|
end
|
|
897
919
|
|
|
920
|
+
# =========================================================================
|
|
921
|
+
# Knowledge Gaps
|
|
922
|
+
# =========================================================================
|
|
923
|
+
|
|
924
|
+
def run_gaps_check(args)
|
|
925
|
+
mode = args['mode_name'] || current_mode_name
|
|
926
|
+
content = load_instruction_content(mode)
|
|
927
|
+
|
|
928
|
+
unless content
|
|
929
|
+
return "## Knowledge Gaps Report\n\n" \
|
|
930
|
+
"Could not load instruction file for mode `#{mode}`.\n" \
|
|
931
|
+
"Ensure the mode exists and has a corresponding `.md` file in the skills directory."
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
baseline = parse_baseline_knowledge(content)
|
|
935
|
+
|
|
936
|
+
unless baseline && !baseline.empty?
|
|
937
|
+
return "## Knowledge Gaps Report\n\n" \
|
|
938
|
+
"**Mode**: `#{mode}`\n\n" \
|
|
939
|
+
"No Knowledge Acquisition Policy found in this mode's instructions.\n\n" \
|
|
940
|
+
"To add one, include a `## Knowledge Acquisition Policy` section with a " \
|
|
941
|
+
"`### Baseline Knowledge` subsection listing required L1 entries:\n\n" \
|
|
942
|
+
"```markdown\n" \
|
|
943
|
+
"## Knowledge Acquisition Policy\n\n" \
|
|
944
|
+
"### Baseline Knowledge\n\n" \
|
|
945
|
+
"Required L1 knowledge entries for this mode.\n\n" \
|
|
946
|
+
"- `entry_name` — Description of what this knowledge covers\n" \
|
|
947
|
+
"```"
|
|
948
|
+
end
|
|
949
|
+
|
|
950
|
+
# Compare against existing L1 knowledge
|
|
951
|
+
provider = KnowledgeProvider.new
|
|
952
|
+
existing = provider.list.map { |item| item[:name] }
|
|
953
|
+
|
|
954
|
+
present = []
|
|
955
|
+
missing = []
|
|
956
|
+
baseline.each do |entry|
|
|
957
|
+
if existing.include?(entry[:name])
|
|
958
|
+
present << entry
|
|
959
|
+
else
|
|
960
|
+
missing << entry
|
|
961
|
+
end
|
|
962
|
+
end
|
|
963
|
+
|
|
964
|
+
output = ["## Knowledge Gaps Report\n"]
|
|
965
|
+
output << "**Mode**: `#{mode}`"
|
|
966
|
+
output << "**Baseline entries**: #{baseline.size}"
|
|
967
|
+
output << "**Present**: #{present.size}"
|
|
968
|
+
output << "**Missing**: #{missing.size}\n"
|
|
969
|
+
|
|
970
|
+
if missing.empty?
|
|
971
|
+
output << "### All Baseline Knowledge Present\n"
|
|
972
|
+
output << "All required L1 knowledge entries for this mode are available."
|
|
973
|
+
else
|
|
974
|
+
output << "### Missing Entries\n"
|
|
975
|
+
missing.each do |entry|
|
|
976
|
+
output << "- `#{entry[:name]}` — #{entry[:description]}"
|
|
977
|
+
end
|
|
978
|
+
|
|
979
|
+
output << "\n### Suggested Actions\n"
|
|
980
|
+
output << "Create the missing entries using `knowledge_update`:\n"
|
|
981
|
+
missing.each do |entry|
|
|
982
|
+
output << "```"
|
|
983
|
+
output << "knowledge_update(command: \"create\", name: \"#{entry[:name]}\", " \
|
|
984
|
+
"description: \"#{entry[:description]}\", " \
|
|
985
|
+
"content: \"# #{entry[:name]}\\n\\nTODO: Add content\", " \
|
|
986
|
+
"tags: [\"baseline\"])"
|
|
987
|
+
output << "```\n"
|
|
988
|
+
end
|
|
989
|
+
end
|
|
990
|
+
|
|
991
|
+
if present.any?
|
|
992
|
+
output << "### Present Entries\n"
|
|
993
|
+
present.each do |entry|
|
|
994
|
+
output << "- `#{entry[:name]}` — #{entry[:description]}"
|
|
995
|
+
end
|
|
996
|
+
end
|
|
997
|
+
|
|
998
|
+
output.join("\n")
|
|
999
|
+
end
|
|
1000
|
+
|
|
1001
|
+
def parse_baseline_knowledge(content)
|
|
1002
|
+
# Find the Knowledge Acquisition Policy section
|
|
1003
|
+
policy_match = content.match(/^##\s+Knowledge Acquisition Policy\s*$/i)
|
|
1004
|
+
return nil unless policy_match
|
|
1005
|
+
|
|
1006
|
+
# Extract from ### Baseline Knowledge subsection
|
|
1007
|
+
baseline_match = content.match(/^###\s+Baseline Knowledge\s*\n(.*?)(?=^###|\z)/im)
|
|
1008
|
+
return nil unless baseline_match
|
|
1009
|
+
|
|
1010
|
+
baseline_text = baseline_match[1]
|
|
1011
|
+
entries = []
|
|
1012
|
+
|
|
1013
|
+
# Parse lines matching: - `name` — description (supports —, --, :, -)
|
|
1014
|
+
baseline_text.scan(/^-\s+`([^`]+)`\s*(?:—|--|:|-)\s*(.+)$/) do |name, description|
|
|
1015
|
+
entries << { name: name.strip, description: description.strip }
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1018
|
+
entries
|
|
1019
|
+
end
|
|
1020
|
+
|
|
1021
|
+
def current_mode_name
|
|
1022
|
+
SkillsConfig.load['instructions_mode'] || 'tutorial'
|
|
1023
|
+
end
|
|
1024
|
+
|
|
1025
|
+
def load_instruction_content(mode_name)
|
|
1026
|
+
path = case mode_name
|
|
1027
|
+
when 'developer'
|
|
1028
|
+
KairosMcp.md_path
|
|
1029
|
+
when 'user'
|
|
1030
|
+
KairosMcp.quickguide_path
|
|
1031
|
+
when 'tutorial'
|
|
1032
|
+
KairosMcp.tutorial_path
|
|
1033
|
+
when 'none'
|
|
1034
|
+
nil
|
|
1035
|
+
else
|
|
1036
|
+
File.join(KairosMcp.skills_dir, "#{mode_name}.md")
|
|
1037
|
+
end
|
|
1038
|
+
|
|
1039
|
+
return nil unless path && File.exist?(path)
|
|
1040
|
+
|
|
1041
|
+
File.read(path)
|
|
1042
|
+
end
|
|
1043
|
+
|
|
1044
|
+
# =========================================================================
|
|
1045
|
+
# Export Needs (Cross-Instance Knowledge Discovery)
|
|
1046
|
+
# =========================================================================
|
|
1047
|
+
|
|
1048
|
+
def run_export_needs(args)
|
|
1049
|
+
mode = args['mode_name'] || current_mode_name
|
|
1050
|
+
content = load_instruction_content(mode)
|
|
1051
|
+
|
|
1052
|
+
unless content
|
|
1053
|
+
return "## Export Needs Report\n\n" \
|
|
1054
|
+
"Could not load instruction file for mode `#{mode}`.\n" \
|
|
1055
|
+
"No knowledge needs to export."
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
baseline = parse_baseline_knowledge(content)
|
|
1059
|
+
|
|
1060
|
+
unless baseline && !baseline.empty?
|
|
1061
|
+
return "## Export Needs Report\n\n" \
|
|
1062
|
+
"**Mode**: `#{mode}`\n\n" \
|
|
1063
|
+
"No Knowledge Acquisition Policy found — no needs to export."
|
|
1064
|
+
end
|
|
1065
|
+
|
|
1066
|
+
# Find missing entries (gaps)
|
|
1067
|
+
provider = KnowledgeProvider.new
|
|
1068
|
+
existing = provider.list.map { |item| item[:name] }
|
|
1069
|
+
missing = baseline.reject { |entry| existing.include?(entry[:name]) }
|
|
1070
|
+
|
|
1071
|
+
if missing.empty?
|
|
1072
|
+
return "## Export Needs Report\n\n" \
|
|
1073
|
+
"**Mode**: `#{mode}`\n\n" \
|
|
1074
|
+
"All baseline knowledge is present. No needs to export."
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
# Build exportable needs structure
|
|
1078
|
+
needs_data = build_knowledge_needs(mode, missing)
|
|
1079
|
+
|
|
1080
|
+
# Check Meeting Place connection
|
|
1081
|
+
connection_file = File.join(KairosMcp.storage_dir, 'meeting_connection.json')
|
|
1082
|
+
connected = File.exist?(connection_file)
|
|
1083
|
+
|
|
1084
|
+
output = ["## Export Needs Report\n"]
|
|
1085
|
+
output << "**Mode**: `#{mode}`"
|
|
1086
|
+
output << "**Missing entries**: #{missing.size}"
|
|
1087
|
+
output << "**Meeting Place connected**: #{connected}\n"
|
|
1088
|
+
|
|
1089
|
+
output << "### Exportable Needs\n"
|
|
1090
|
+
needs_data[:needs].each do |need|
|
|
1091
|
+
output << "- `#{need[:name]}` — #{need[:description]}"
|
|
1092
|
+
end
|
|
1093
|
+
|
|
1094
|
+
if connected
|
|
1095
|
+
output << "\n### Next Step\n"
|
|
1096
|
+
output << "Publish these needs to the Meeting Place board:\n"
|
|
1097
|
+
output << "```"
|
|
1098
|
+
output << "meeting_publish_needs(opt_in: true)"
|
|
1099
|
+
output << "```"
|
|
1100
|
+
else
|
|
1101
|
+
output << "\n### Not Connected\n"
|
|
1102
|
+
output << "Connect to a Meeting Place first using `meeting_connect(url: \"...\")`, "
|
|
1103
|
+
output << "then use `meeting_publish_needs(opt_in: true)` to publish."
|
|
1104
|
+
end
|
|
1105
|
+
|
|
1106
|
+
output.join("\n")
|
|
1107
|
+
end
|
|
1108
|
+
|
|
1109
|
+
def build_knowledge_needs(mode_name, missing_entries = nil)
|
|
1110
|
+
if missing_entries.nil?
|
|
1111
|
+
content = load_instruction_content(mode_name)
|
|
1112
|
+
return { agent_mode: mode_name, needs: [], published_at: nil, session_only: true } unless content
|
|
1113
|
+
|
|
1114
|
+
baseline = parse_baseline_knowledge(content) || []
|
|
1115
|
+
provider = KnowledgeProvider.new
|
|
1116
|
+
existing = provider.list.map { |item| item[:name] }
|
|
1117
|
+
missing_entries = baseline.reject { |entry| existing.include?(entry[:name]) }
|
|
1118
|
+
end
|
|
1119
|
+
|
|
1120
|
+
{
|
|
1121
|
+
agent_mode: mode_name,
|
|
1122
|
+
needs: missing_entries.map { |entry| { name: entry[:name], description: entry[:description] } },
|
|
1123
|
+
published_at: Time.now.utc.iso8601,
|
|
1124
|
+
session_only: true
|
|
1125
|
+
}
|
|
1126
|
+
end
|
|
1127
|
+
|
|
898
1128
|
# =========================================================================
|
|
899
1129
|
# Helpers
|
|
900
1130
|
# =========================================================================
|
data/lib/kairos_mcp/version.rb
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hestiachain_meeting_place
|
|
3
3
|
description: "HestiaChain Meeting Place — user guide for agent discovery, skill exchange, and trust anchoring"
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1
|
|
5
5
|
layer: L1
|
|
6
6
|
tags: [documentation, readme, hestia, meeting-place, p2p, deployment, trust-anchor]
|
|
7
7
|
readme_order: 4.5
|
|
8
8
|
readme_lang: en
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
## HestiaChain Meeting Place (v2.
|
|
11
|
+
## HestiaChain Meeting Place (v2.5.0)
|
|
12
12
|
|
|
13
13
|
### What is HestiaChain?
|
|
14
14
|
|
|
@@ -29,9 +29,9 @@ KairosChain (MCP Server)
|
|
|
29
29
|
├── chain/ ← Trust anchor (self-contained, no external gem dependency)
|
|
30
30
|
├── PlaceRouter ← /place/v1/* HTTP endpoints
|
|
31
31
|
├── AgentRegistry ← Agent registration with JSON persistence
|
|
32
|
-
├── SkillBoard ← Skill discovery (random sampling, no ranking)
|
|
32
|
+
├── SkillBoard ← Skill + knowledge needs discovery (random sampling, no ranking)
|
|
33
33
|
├── HeartbeatManager ← TTL-based liveness with fadeout recording
|
|
34
|
-
└── tools/ ←
|
|
34
|
+
└── tools/ ← 7 MCP tools
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
A KairosChain instance with the hestia SkillSet is simultaneously an MCP server, a P2P agent, a Meeting Place host, and a participant in other Meeting Places. This embodies the DEE principle of subject-object undifferentiation (主客未分).
|
|
@@ -85,6 +85,8 @@ curl -s -H "Authorization: Bearer $TOKEN" \
|
|
|
85
85
|
| POST | `/place/v1/unregister` | Bearer | Unregister an agent |
|
|
86
86
|
| GET | `/place/v1/agents` | Bearer | List registered agents |
|
|
87
87
|
| GET | `/place/v1/board/browse` | Bearer | Browse skill board (random order) |
|
|
88
|
+
| POST | `/place/v1/board/needs` | Bearer | Publish knowledge needs to board |
|
|
89
|
+
| DELETE | `/place/v1/board/needs` | Bearer | Remove published knowledge needs |
|
|
88
90
|
| GET | `/place/v1/keys/:id` | Bearer | Retrieve agent's public key |
|
|
89
91
|
|
|
90
92
|
### MCP Tools
|
|
@@ -97,6 +99,26 @@ curl -s -H "Authorization: Bearer $TOKEN" \
|
|
|
97
99
|
| `record_observation` | Record subjective observation of interaction |
|
|
98
100
|
| `meeting_place_start` | Start the Meeting Place, initialize components |
|
|
99
101
|
| `meeting_place_status` | Show Meeting Place configuration and status |
|
|
102
|
+
| `meeting_publish_needs` | Publish knowledge gaps to board (explicit opt-in required) |
|
|
103
|
+
|
|
104
|
+
### Cross-Instance Knowledge Discovery
|
|
105
|
+
|
|
106
|
+
Agents can publish their knowledge gaps (needs) to the Meeting Place board, enabling other agents to discover and offer relevant knowledge.
|
|
107
|
+
|
|
108
|
+
**Workflow:**
|
|
109
|
+
|
|
110
|
+
1. Run `skills_audit(command: "gaps")` to detect missing baseline knowledge
|
|
111
|
+
2. Run `skills_audit(command: "export_needs")` to preview exportable needs
|
|
112
|
+
3. Run `meeting_publish_needs(opt_in: true)` to publish needs to the board
|
|
113
|
+
4. Other agents browsing with `browse(type: 'need')` can discover these needs
|
|
114
|
+
5. Agents decide locally whether to offer knowledge (no automated matching)
|
|
115
|
+
|
|
116
|
+
**DEE Compliance:**
|
|
117
|
+
- Needs are session-only (in-memory, no persistence)
|
|
118
|
+
- No aggregation, ranking, or popularity metrics
|
|
119
|
+
- Explicit opt-in required (`opt_in: true`)
|
|
120
|
+
- Random sampling for browse results (D3)
|
|
121
|
+
- Each agent decides independently whether to respond (D5)
|
|
100
122
|
|
|
101
123
|
### Trust Anchor: Chain Migration
|
|
102
124
|
|
|
@@ -118,7 +140,7 @@ HestiaChain implements the Decentralized Event Exchange (DEE) protocol:
|
|
|
118
140
|
- **PhilosophyDeclaration**: Agents declare their exchange philosophy (observable, not enforceable). Only the hash is recorded on chain.
|
|
119
141
|
- **ObservationLog**: Agents record subjective observations. Multiple agents can have different observations of the same interaction — "meaning coexists."
|
|
120
142
|
- **Fadeout**: When an agent's heartbeat expires, this is recorded as a first-class event (not an error). Silent departure is a natural part of the protocol.
|
|
121
|
-
- **Random Sampling**: The SkillBoard returns skills in random order. There is no ranking, no scoring, no popularity metric.
|
|
143
|
+
- **Random Sampling**: The SkillBoard returns skills and knowledge needs in random order. There is no ranking, no scoring, no popularity metric.
|
|
122
144
|
|
|
123
145
|
### EC2 Deployment
|
|
124
146
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hestiachain_meeting_place_jp
|
|
3
3
|
description: "HestiaChain Meeting Place — エージェント探索・スキル交換・信頼アンカーのユーザーガイド"
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.1
|
|
5
5
|
layer: L1
|
|
6
6
|
tags: [documentation, readme, hestia, meeting-place, p2p, deployment, trust-anchor]
|
|
7
7
|
readme_order: 4.5
|
|
8
8
|
readme_lang: jp
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
## HestiaChain Meeting Place (v2.
|
|
11
|
+
## HestiaChain Meeting Place (v2.5.0)
|
|
12
12
|
|
|
13
13
|
### HestiaChain とは
|
|
14
14
|
|
|
@@ -29,9 +29,9 @@ KairosChain (MCP Server)
|
|
|
29
29
|
├── chain/ ← 信頼アンカー(自己完結型、外部 gem 依存なし)
|
|
30
30
|
├── PlaceRouter ← /place/v1/* HTTP エンドポイント
|
|
31
31
|
├── AgentRegistry ← JSON 永続化によるエージェント登録
|
|
32
|
-
├── SkillBoard ←
|
|
32
|
+
├── SkillBoard ← スキル+知識ニーズ発見(ランダムサンプリング、ランキングなし)
|
|
33
33
|
├── HeartbeatManager ← TTL ベースの生存確認と退場記録
|
|
34
|
-
└── tools/ ←
|
|
34
|
+
└── tools/ ← 7 MCP ツール
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
hestia SkillSet を持つ KairosChain インスタンスは、MCP サーバー、P2P エージェント、Meeting Place ホスト、他の Meeting Place の参加者を同時に兼ねます。これは DEE プロトコルの「主客未分」原則を体現しています。
|
|
@@ -85,6 +85,8 @@ curl -s -H "Authorization: Bearer $TOKEN" \
|
|
|
85
85
|
| POST | `/place/v1/unregister` | Bearer | エージェント登録解除 |
|
|
86
86
|
| GET | `/place/v1/agents` | Bearer | 登録エージェント一覧 |
|
|
87
87
|
| GET | `/place/v1/board/browse` | Bearer | スキルボード閲覧(ランダム順) |
|
|
88
|
+
| POST | `/place/v1/board/needs` | Bearer | 知識ニーズをボードに公開 |
|
|
89
|
+
| DELETE | `/place/v1/board/needs` | Bearer | 公開した知識ニーズを削除 |
|
|
88
90
|
| GET | `/place/v1/keys/:id` | Bearer | エージェントの公開鍵取得 |
|
|
89
91
|
|
|
90
92
|
### MCP ツール
|
|
@@ -97,6 +99,26 @@ curl -s -H "Authorization: Bearer $TOKEN" \
|
|
|
97
99
|
| `record_observation` | インタラクションの主観的観察を記録 |
|
|
98
100
|
| `meeting_place_start` | Meeting Place を起動、コンポーネント初期化 |
|
|
99
101
|
| `meeting_place_status` | Meeting Place の設定とステータスを表示 |
|
|
102
|
+
| `meeting_publish_needs` | 知識ギャップをボードに公開(明示的 opt-in 必須) |
|
|
103
|
+
|
|
104
|
+
### クロスインスタンス知識発見
|
|
105
|
+
|
|
106
|
+
エージェントは自身の知識ギャップ(ニーズ)を Meeting Place ボードに公開できます。他のエージェントがブラウズ中にニーズを発見し、関連知識を提供できます。
|
|
107
|
+
|
|
108
|
+
**ワークフロー:**
|
|
109
|
+
|
|
110
|
+
1. `skills_audit(command: "gaps")` でベースライン知識の不足を検出
|
|
111
|
+
2. `skills_audit(command: "export_needs")` でエクスポート可能なニーズをプレビュー
|
|
112
|
+
3. `meeting_publish_needs(opt_in: true)` でニーズをボードに公開
|
|
113
|
+
4. 他のエージェントが `browse(type: 'need')` でニーズを発見
|
|
114
|
+
5. 各エージェントがローカルに知識提供の判断を行う(自動マッチングなし)
|
|
115
|
+
|
|
116
|
+
**DEE 準拠:**
|
|
117
|
+
- ニーズはセッション限り(インメモリ、永続化なし)
|
|
118
|
+
- 集計・ランキング・人気指標なし
|
|
119
|
+
- 明示的 opt-in 必須(`opt_in: true`)
|
|
120
|
+
- ブラウズ結果はランダムサンプリング(D3)
|
|
121
|
+
- 各エージェントが独立に判断(D5)
|
|
100
122
|
|
|
101
123
|
### 信頼アンカー:チェーン移行
|
|
102
124
|
|
|
@@ -118,7 +140,7 @@ HestiaChain は Decentralized Event Exchange(DEE)プロトコルを実装し
|
|
|
118
140
|
- **PhilosophyDeclaration**: エージェントが交換哲学を宣言(観察可能、強制不可)。ハッシュのみチェーンに記録
|
|
119
141
|
- **ObservationLog**: エージェントが主観的観察を記録。同じインタラクションに対して複数のエージェントが異なる観察を持てる —「意味は合意されない。意味は共存する」
|
|
120
142
|
- **Fadeout**: エージェントの心拍が期限切れになると、これはエラーではなく第一級イベントとして記録される。静かな退場はプロトコルの自然な一部
|
|
121
|
-
- **ランダムサンプリング**: SkillBoard
|
|
143
|
+
- **ランダムサンプリング**: SkillBoard はスキルと知識ニーズをランダム順で返す。ランキング、スコアリング、人気指標は存在しない
|
|
122
144
|
|
|
123
145
|
### EC2 デプロイ
|
|
124
146
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kairoschain_operations
|
|
3
3
|
description: "Future roadmap, deployment, and operations guide"
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2
|
|
5
5
|
layer: L1
|
|
6
6
|
tags: [documentation, readme, operations, deployment, roadmap, backup]
|
|
7
7
|
readme_order: 5
|
|
@@ -26,8 +26,11 @@ The following development phases have been completed on the `feature/skillset-pl
|
|
|
26
26
|
| **Phase 4.pre** | Authentication + Hardening | Admin token rotation, session-based auth for P2P endpoints |
|
|
27
27
|
| **Phase 4A** | HestiaChain Foundation | Self-contained trust anchor SkillSet, DEE protocol (PhilosophyDeclaration, ObservationLog), chain migration (4 stages), 4 MCP tools, 77 test assertions |
|
|
28
28
|
| **Phase 4B** | Meeting Place Server | PlaceRouter, AgentRegistry, SkillBoard, HeartbeatManager, 6 HTTP endpoints, 2 MCP tools, 70 test assertions |
|
|
29
|
+
| **v2.3.0** | Tutorial Mode + Proactive Tools | Behavioral gradient instruction mode, existing project fast-track, Knowledge Acquisition Policy |
|
|
30
|
+
| **v2.4.0** | Dynamic Persona Suggestion | 2-step suggest→assembly workflow, custom persona names, improved unknown persona handling |
|
|
31
|
+
| **v2.5.0** | Cross-Instance Knowledge Discovery | SkillBoard knowledge needs, `meeting_publish_needs` tool, `export_needs` audit command, DEE-compliant session-only needs |
|
|
29
32
|
|
|
30
|
-
Test results: 356 passed, 0 failed (v2.
|
|
33
|
+
Test results: 356+ passed, 0 failed (v2.5.0).
|
|
31
34
|
|
|
32
35
|
### Near-term
|
|
33
36
|
|
|
@@ -26,8 +26,11 @@ readme_lang: jp
|
|
|
26
26
|
| **Phase 4.pre** | 認証 + 堅牢化 | Admin トークンローテーション、P2Pエンドポイントのセッションベース認証 |
|
|
27
27
|
| **Phase 4A** | HestiaChain Foundation | 自己完結型信頼アンカーSkillSet、DEEプロトコル(PhilosophyDeclaration、ObservationLog)、チェーン移行(4ステージ)、4 MCPツール、77テストアサーション |
|
|
28
28
|
| **Phase 4B** | Meeting Placeサーバー | PlaceRouter、AgentRegistry、SkillBoard、HeartbeatManager、6 HTTPエンドポイント、2 MCPツール、70テストアサーション |
|
|
29
|
+
| **v2.3.0** | チュートリアルモード + プロアクティブツール | 行動勾配インストラクションモード、既存プロジェクト高速トラック、Knowledge Acquisition Policy |
|
|
30
|
+
| **v2.4.0** | 動的ペルソナ提案 | 2ステップ suggest→assembly ワークフロー、カスタムペルソナ名、未知ペルソナハンドリング改善 |
|
|
31
|
+
| **v2.5.0** | クロスインスタンス知識発見 | SkillBoard知識ニーズ、`meeting_publish_needs`ツール、`export_needs`監査コマンド、DEE準拠セッション限りニーズ |
|
|
29
32
|
|
|
30
|
-
テスト結果: 356
|
|
33
|
+
テスト結果: 356+テスト通過、0失敗(v2.5.0)。
|
|
31
34
|
|
|
32
35
|
### 近期
|
|
33
36
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kairoschain_usage
|
|
3
3
|
description: "KairosChain tools reference, usage patterns, and evolution workflow"
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2
|
|
5
5
|
layer: L1
|
|
6
6
|
tags: [documentation, readme, usage, tools, workflow, examples]
|
|
7
7
|
readme_order: 3
|
|
@@ -252,6 +252,8 @@ Commands:
|
|
|
252
252
|
- `conflicts`: Detect potential contradictions between knowledge
|
|
253
253
|
- `dangerous`: Detect patterns conflicting with L0 safety
|
|
254
254
|
- `recommend`: Get promotion and archive recommendations
|
|
255
|
+
- `gaps`: Check knowledge gaps defined by Knowledge Acquisition Policy in instruction modes
|
|
256
|
+
- `export_needs`: Package knowledge gaps as shareable needs for cross-instance discovery via Meeting Place
|
|
255
257
|
- `archive`: Archive L1 knowledge (human approval required)
|
|
256
258
|
- `unarchive`: Restore from archive (human approval required)
|
|
257
259
|
|
|
@@ -252,6 +252,8 @@ cp -r skills/versions skills/backups/versions_$(date +%Y%m%d)
|
|
|
252
252
|
- `conflicts`: 知識間の潜在的矛盾を検出
|
|
253
253
|
- `dangerous`: L0安全性と矛盾するパターンを検出
|
|
254
254
|
- `recommend`: 昇格とアーカイブの推奨を取得
|
|
255
|
+
- `gaps`: Knowledge Acquisition Policyで定義された知識ギャップを検出
|
|
256
|
+
- `export_needs`: 知識ギャップをMeeting Placeでの共有用にパッケージ化
|
|
255
257
|
- `archive`: L1知識をアーカイブ(人間の承認が必要)
|
|
256
258
|
- `unarchive`: アーカイブから復元(人間の承認が必要)
|
|
257
259
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: persona_definitions
|
|
3
3
|
description: Default persona definitions for Persona Assembly during skill promotion and audit decisions
|
|
4
|
-
version: "1.
|
|
4
|
+
version: "1.3"
|
|
5
5
|
layer: L1
|
|
6
6
|
tags: [meta, personas, assembly, promotion, audit, decision-making, facilitator]
|
|
7
7
|
---
|
|
@@ -242,6 +242,15 @@ The assembly produces a discussion summary with:
|
|
|
242
242
|
|
|
243
243
|
**Important:** The assembly output is advisory only. Human judgment remains the final authority, especially for L0 promotions.
|
|
244
244
|
|
|
245
|
+
### Dynamic Persona Suggestion (v2.4.0+)
|
|
246
|
+
|
|
247
|
+
Use `skills_promote(command: "suggest")` to have the LLM analyze source content and suggest optimal personas before running Persona Assembly. The 2-step workflow:
|
|
248
|
+
|
|
249
|
+
1. **Suggest**: LLM analyzes the content and recommends persona types and count
|
|
250
|
+
2. **Assembly**: Run the assembly with the suggested (or modified) persona set
|
|
251
|
+
|
|
252
|
+
Custom persona names are fully supported — the LLM infers the role from the name and context when no pre-defined definition exists.
|
|
253
|
+
|
|
245
254
|
### Customizing Personas
|
|
246
255
|
|
|
247
256
|
Users can modify this knowledge to:
|
|
@@ -73,6 +73,10 @@ them as naturally as you would use a notebook.
|
|
|
73
73
|
to check if relevant L1 knowledge exists before answering from scratch.
|
|
74
74
|
- **When the user asks about capabilities**: Call `tool_guide(command: "catalog")`
|
|
75
75
|
to give accurate, current information.
|
|
76
|
+
- **Knowledge gaps (custom modes only)**: If the active mode has a Knowledge
|
|
77
|
+
Acquisition Policy, call `skills_audit(command: "gaps")` silently to check
|
|
78
|
+
for missing baseline knowledge. If gaps are found, inform the user briefly
|
|
79
|
+
and offer to create the missing entries.
|
|
76
80
|
|
|
77
81
|
### When Few or No L2 Contexts Exist
|
|
78
82
|
|
|
@@ -183,6 +187,53 @@ Minimum requirements for L1 knowledge (kept intentionally low):
|
|
|
183
187
|
Quality improves over time through audit suggestions. Do not block initial promotion
|
|
184
188
|
for perfectionism.
|
|
185
189
|
|
|
190
|
+
## Knowledge Acquisition Policy (Custom Modes)
|
|
191
|
+
|
|
192
|
+
When creating a custom instruction mode (including via fast-track), include a
|
|
193
|
+
Knowledge Acquisition Policy section to define what L1 knowledge the mode requires.
|
|
194
|
+
This enables automatic gap detection at session start.
|
|
195
|
+
|
|
196
|
+
### Template
|
|
197
|
+
|
|
198
|
+
```markdown
|
|
199
|
+
## Knowledge Acquisition Policy
|
|
200
|
+
|
|
201
|
+
### Baseline Knowledge
|
|
202
|
+
|
|
203
|
+
Required L1 knowledge entries for this mode.
|
|
204
|
+
|
|
205
|
+
- `entry_name` — Description of what this knowledge covers
|
|
206
|
+
- `another_entry` — Description of another required knowledge area
|
|
207
|
+
|
|
208
|
+
### Active Monitoring
|
|
209
|
+
|
|
210
|
+
Topics and sources to track for knowledge updates.
|
|
211
|
+
|
|
212
|
+
- Source or topic to monitor (frequency)
|
|
213
|
+
|
|
214
|
+
### Acquisition Behavior
|
|
215
|
+
|
|
216
|
+
- **On session start**: Check baseline entries against L1 knowledge. Report gaps.
|
|
217
|
+
- **On gap found**: Propose creating the missing L1 entry with a draft outline.
|
|
218
|
+
- **Frequency**: Check baseline every session.
|
|
219
|
+
- **Cross-instance (opt-in)**: When connected to a Meeting Place, you may
|
|
220
|
+
publish knowledge needs to the board using `meeting_publish_needs(opt_in: true)`.
|
|
221
|
+
Other agents browsing the board may discover and offer relevant knowledge.
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Format Rules
|
|
225
|
+
|
|
226
|
+
- Start the section with `## Knowledge Acquisition Policy`
|
|
227
|
+
- List baseline entries under `### Baseline Knowledge` using: `` - `name` — description ``
|
|
228
|
+
- Separators between name and description: `—`, `--`, `:`, or `-` are all accepted
|
|
229
|
+
- `### Active Monitoring` and `### Acquisition Behavior` are LLM-facing guidance
|
|
230
|
+
(not parsed programmatically)
|
|
231
|
+
|
|
232
|
+
### Usage
|
|
233
|
+
|
|
234
|
+
Run `skills_audit(command: "gaps")` to check the current mode's baseline against
|
|
235
|
+
existing L1 knowledge. Missing entries are reported with suggested creation commands.
|
|
236
|
+
|
|
186
237
|
## Progressive Concept Introduction
|
|
187
238
|
|
|
188
239
|
Introduce KairosChain concepts only when they become relevant:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
|
+
require 'uri'
|
|
4
5
|
|
|
5
6
|
module Hestia
|
|
6
7
|
# PlaceRouter handles Meeting Place HTTP endpoints under /place/v1/*.
|
|
@@ -102,6 +103,10 @@ module Hestia
|
|
|
102
103
|
handle_list_agents(env)
|
|
103
104
|
when ['GET', '/place/v1/board/browse']
|
|
104
105
|
handle_browse(env)
|
|
106
|
+
when ['POST', '/place/v1/board/needs']
|
|
107
|
+
handle_post_needs(env)
|
|
108
|
+
when ['DELETE', '/place/v1/board/needs']
|
|
109
|
+
handle_delete_needs(env)
|
|
105
110
|
else
|
|
106
111
|
# Check for /place/v1/keys/:id pattern
|
|
107
112
|
if request_method == 'GET' && path.start_with?('/place/v1/keys/')
|
|
@@ -215,6 +220,9 @@ module Hestia
|
|
|
215
220
|
|
|
216
221
|
result = @registry.unregister(agent_id)
|
|
217
222
|
|
|
223
|
+
# Clean up any posted needs for this agent
|
|
224
|
+
@skill_board.remove_needs(agent_id)
|
|
225
|
+
|
|
218
226
|
# Record fade-out observation if trust anchor available
|
|
219
227
|
# (agent explicitly leaving = graceful fadeout)
|
|
220
228
|
|
|
@@ -241,6 +249,49 @@ module Hestia
|
|
|
241
249
|
json_response(200, result)
|
|
242
250
|
end
|
|
243
251
|
|
|
252
|
+
# POST /place/v1/board/needs — Bearer token required
|
|
253
|
+
# Publish knowledge needs to the board (session-only, in-memory)
|
|
254
|
+
def handle_post_needs(env)
|
|
255
|
+
body = parse_body(env)
|
|
256
|
+
agent_id = body['agent_id']
|
|
257
|
+
agent_name = body['agent_name'] || 'Unknown Agent'
|
|
258
|
+
agent_mode = body['agent_mode'] || 'unknown'
|
|
259
|
+
needs = body['needs'] || []
|
|
260
|
+
|
|
261
|
+
unless agent_id
|
|
262
|
+
return json_response(400, { error: 'missing_agent_id', message: 'agent_id is required' })
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
@skill_board.post_need(
|
|
266
|
+
agent_id: agent_id,
|
|
267
|
+
agent_name: agent_name,
|
|
268
|
+
agent_mode: agent_mode,
|
|
269
|
+
needs: needs.map { |n| { name: n['name'], description: n['description'] } }
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
json_response(200, {
|
|
273
|
+
status: 'published',
|
|
274
|
+
agent_id: agent_id,
|
|
275
|
+
needs_count: needs.size,
|
|
276
|
+
session_only: true
|
|
277
|
+
})
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# DELETE /place/v1/board/needs — Bearer token required
|
|
281
|
+
# Remove all needs posted by an agent
|
|
282
|
+
def handle_delete_needs(env)
|
|
283
|
+
body = parse_body(env)
|
|
284
|
+
agent_id = body['agent_id']
|
|
285
|
+
|
|
286
|
+
unless agent_id
|
|
287
|
+
return json_response(400, { error: 'missing_agent_id', message: 'agent_id is required' })
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
@skill_board.remove_needs(agent_id)
|
|
291
|
+
|
|
292
|
+
json_response(200, { status: 'removed', agent_id: agent_id })
|
|
293
|
+
end
|
|
294
|
+
|
|
244
295
|
# GET /place/v1/keys/:id — Bearer token required
|
|
245
296
|
def handle_get_key(path)
|
|
246
297
|
agent_id = path.sub('/place/v1/keys/', '')
|
|
@@ -13,6 +13,32 @@ module Hestia
|
|
|
13
13
|
|
|
14
14
|
def initialize(registry:)
|
|
15
15
|
@registry = registry
|
|
16
|
+
@posted_needs = []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Post knowledge needs for an agent (session-only, no persistence — DEE compliant).
|
|
20
|
+
# Overwrites existing needs for the same agent_id.
|
|
21
|
+
#
|
|
22
|
+
# @param agent_id [String] The agent's unique identifier
|
|
23
|
+
# @param agent_name [String] Human-readable agent name
|
|
24
|
+
# @param agent_mode [String] The agent's instruction mode
|
|
25
|
+
# @param needs [Array<Hash>] List of { name:, description: } hashes
|
|
26
|
+
def post_need(agent_id:, agent_name:, agent_mode:, needs:)
|
|
27
|
+
@posted_needs.reject! { |n| n[:agent_id] == agent_id }
|
|
28
|
+
@posted_needs << {
|
|
29
|
+
agent_id: agent_id,
|
|
30
|
+
agent_name: agent_name,
|
|
31
|
+
agent_mode: agent_mode,
|
|
32
|
+
needs: needs,
|
|
33
|
+
published_at: Time.now.utc.iso8601
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Remove all needs posted by an agent (called on unregister cleanup).
|
|
38
|
+
#
|
|
39
|
+
# @param agent_id [String] The agent's unique identifier
|
|
40
|
+
def remove_needs(agent_id)
|
|
41
|
+
@posted_needs.reject! { |n| n[:agent_id] == agent_id }
|
|
16
42
|
end
|
|
17
43
|
|
|
18
44
|
# Browse available skills across all registered agents.
|
|
@@ -79,6 +105,22 @@ module Hestia
|
|
|
79
105
|
}
|
|
80
106
|
end
|
|
81
107
|
|
|
108
|
+
# Add need entries from posted needs (session-only, in-memory)
|
|
109
|
+
@posted_needs.each do |posted|
|
|
110
|
+
posted[:needs].each do |need|
|
|
111
|
+
entries << {
|
|
112
|
+
agent_id: posted[:agent_id],
|
|
113
|
+
agent_name: posted[:agent_name],
|
|
114
|
+
name: need[:name],
|
|
115
|
+
format: 'need',
|
|
116
|
+
description: need[:description],
|
|
117
|
+
agent_mode: posted[:agent_mode],
|
|
118
|
+
tags: ['knowledge_need'],
|
|
119
|
+
published_at: posted[:published_at]
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
82
124
|
entries
|
|
83
125
|
end
|
|
84
126
|
end
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"KairosMcp::SkillSets::Hestia::Tools::PhilosophyAnchor",
|
|
13
13
|
"KairosMcp::SkillSets::Hestia::Tools::RecordObservation",
|
|
14
14
|
"KairosMcp::SkillSets::Hestia::Tools::MeetingPlaceStart",
|
|
15
|
-
"KairosMcp::SkillSets::Hestia::Tools::MeetingPlaceStatus"
|
|
15
|
+
"KairosMcp::SkillSets::Hestia::Tools::MeetingPlaceStatus",
|
|
16
|
+
"KairosMcp::SkillSets::Hestia::Tools::MeetingPublishNeeds"
|
|
16
17
|
],
|
|
17
18
|
"config_files": ["config/hestia.yml"],
|
|
18
19
|
"knowledge_dirs": ["knowledge/hestia_meeting_place"]
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'json'
|
|
6
|
+
|
|
7
|
+
module KairosMcp
|
|
8
|
+
module SkillSets
|
|
9
|
+
module Hestia
|
|
10
|
+
module Tools
|
|
11
|
+
# Publish knowledge needs to a Meeting Place board.
|
|
12
|
+
#
|
|
13
|
+
# DEE compliance:
|
|
14
|
+
# - Requires explicit opt_in: true (no silent publishing)
|
|
15
|
+
# - Needs are session-only (in-memory on the Place, no persistence)
|
|
16
|
+
# - No aggregation or ranking of needs (D3, D5)
|
|
17
|
+
class MeetingPublishNeeds < KairosMcp::Tools::BaseTool
|
|
18
|
+
def name
|
|
19
|
+
'meeting_publish_needs'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def description
|
|
23
|
+
'Publish knowledge needs (gaps) to a Meeting Place board. ' \
|
|
24
|
+
'Other agents browsing the board can discover and offer relevant knowledge. ' \
|
|
25
|
+
'Requires explicit opt-in and an active Meeting Place connection.'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def category
|
|
29
|
+
:meeting_place
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def usecase_tags
|
|
33
|
+
%w[hestia meeting needs knowledge gaps cross-instance board publish]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def related_tools
|
|
37
|
+
%w[skills_audit meeting_connect meeting_place_status]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def input_schema
|
|
41
|
+
{
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
opt_in: {
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
description: 'Explicit opt-in to publish knowledge needs. Must be true.'
|
|
47
|
+
},
|
|
48
|
+
mode_name: {
|
|
49
|
+
type: 'string',
|
|
50
|
+
description: 'Instruction mode name to check gaps for (defaults to current active mode)'
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
required: ['opt_in']
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def call(arguments)
|
|
58
|
+
unless arguments['opt_in'] == true
|
|
59
|
+
return text_content(JSON.pretty_generate({
|
|
60
|
+
error: 'opt_in_required',
|
|
61
|
+
message: 'Publishing knowledge needs requires explicit opt-in. ' \
|
|
62
|
+
'Call with opt_in: true to confirm.'
|
|
63
|
+
}))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Load connection state
|
|
67
|
+
connection_file = File.join(KairosMcp.storage_dir, 'meeting_connection.json')
|
|
68
|
+
unless File.exist?(connection_file)
|
|
69
|
+
return text_content(JSON.pretty_generate({
|
|
70
|
+
error: 'not_connected',
|
|
71
|
+
message: 'No active Meeting Place connection. Use meeting_connect first.'
|
|
72
|
+
}))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
connection = JSON.parse(File.read(connection_file), symbolize_names: true)
|
|
76
|
+
unless connection[:connected]
|
|
77
|
+
return text_content(JSON.pretty_generate({
|
|
78
|
+
error: 'not_connected',
|
|
79
|
+
message: 'Meeting Place connection is not active. Reconnect using meeting_connect.'
|
|
80
|
+
}))
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
place_url = connection[:url] || connection.dig(:meeting_place, :url)
|
|
84
|
+
agent_id = connection[:self_agent_id]
|
|
85
|
+
|
|
86
|
+
unless place_url && agent_id
|
|
87
|
+
return text_content(JSON.pretty_generate({
|
|
88
|
+
error: 'invalid_connection',
|
|
89
|
+
message: 'Connection state is missing url or agent_id. Reconnect using meeting_connect.'
|
|
90
|
+
}))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Compute knowledge needs using skills_audit logic
|
|
94
|
+
audit_tool = KairosMcp::Tools::SkillsAudit.new
|
|
95
|
+
mode_name = arguments['mode_name'] || audit_tool.send(:current_mode_name)
|
|
96
|
+
needs_data = audit_tool.send(:build_knowledge_needs, mode_name)
|
|
97
|
+
|
|
98
|
+
if needs_data[:needs].empty?
|
|
99
|
+
return text_content(JSON.pretty_generate({
|
|
100
|
+
status: 'no_needs',
|
|
101
|
+
mode: mode_name,
|
|
102
|
+
message: 'All baseline knowledge is present. Nothing to publish.'
|
|
103
|
+
}))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Read session token from connection state
|
|
107
|
+
session_token = connection[:session_token]
|
|
108
|
+
|
|
109
|
+
# POST needs to the Meeting Place board
|
|
110
|
+
mmp_config = ::MMP.load_config rescue {}
|
|
111
|
+
agent_name = mmp_config.dig('identity', 'name') || 'KairosChain Instance'
|
|
112
|
+
|
|
113
|
+
post_body = {
|
|
114
|
+
agent_id: agent_id,
|
|
115
|
+
agent_name: agent_name,
|
|
116
|
+
agent_mode: mode_name,
|
|
117
|
+
needs: needs_data[:needs]
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
result = http_post(
|
|
121
|
+
"#{place_url}/place/v1/board/needs",
|
|
122
|
+
post_body,
|
|
123
|
+
session_token
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
if result
|
|
127
|
+
text_content(JSON.pretty_generate({
|
|
128
|
+
status: 'published',
|
|
129
|
+
mode: mode_name,
|
|
130
|
+
needs_count: needs_data[:needs].size,
|
|
131
|
+
needs: needs_data[:needs],
|
|
132
|
+
place_url: place_url,
|
|
133
|
+
session_only: true,
|
|
134
|
+
hint: 'Needs are visible to other agents browsing the board. ' \
|
|
135
|
+
'They will be removed when you disconnect.'
|
|
136
|
+
}))
|
|
137
|
+
else
|
|
138
|
+
text_content(JSON.pretty_generate({
|
|
139
|
+
error: 'publish_failed',
|
|
140
|
+
message: 'Failed to publish needs to Meeting Place. ' \
|
|
141
|
+
'The Place may be unreachable or the session may have expired.',
|
|
142
|
+
place_url: place_url
|
|
143
|
+
}))
|
|
144
|
+
end
|
|
145
|
+
rescue StandardError => e
|
|
146
|
+
text_content(JSON.pretty_generate({
|
|
147
|
+
error: 'unexpected_error',
|
|
148
|
+
message: e.message
|
|
149
|
+
}))
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
private
|
|
153
|
+
|
|
154
|
+
def http_post(url, body, token = nil)
|
|
155
|
+
uri = URI.parse(url)
|
|
156
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
157
|
+
http.use_ssl = uri.scheme == 'https'
|
|
158
|
+
req = Net::HTTP::Post.new(uri.path)
|
|
159
|
+
req['Content-Type'] = 'application/json'
|
|
160
|
+
req['Authorization'] = "Bearer #{token}" if token
|
|
161
|
+
req.body = JSON.generate(body)
|
|
162
|
+
response = http.request(req)
|
|
163
|
+
response.is_a?(Net::HTTPSuccess) ? JSON.parse(response.body, symbolize_names: true) : nil
|
|
164
|
+
rescue StandardError
|
|
165
|
+
nil
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kairos-chain
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Masa Hatakeyama
|
|
@@ -221,6 +221,7 @@ files:
|
|
|
221
221
|
- templates/skillsets/hestia/tools/chain_migrate_status.rb
|
|
222
222
|
- templates/skillsets/hestia/tools/meeting_place_start.rb
|
|
223
223
|
- templates/skillsets/hestia/tools/meeting_place_status.rb
|
|
224
|
+
- templates/skillsets/hestia/tools/meeting_publish_needs.rb
|
|
224
225
|
- templates/skillsets/hestia/tools/philosophy_anchor.rb
|
|
225
226
|
- templates/skillsets/hestia/tools/record_observation.rb
|
|
226
227
|
- templates/skillsets/mmp/config/meeting.yml
|
|
@@ -269,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
269
270
|
- !ruby/object:Gem::Version
|
|
270
271
|
version: '0'
|
|
271
272
|
requirements: []
|
|
272
|
-
rubygems_version: 3.
|
|
273
|
+
rubygems_version: 3.5.22
|
|
273
274
|
signing_key:
|
|
274
275
|
specification_version: 4
|
|
275
276
|
summary: KairosChain - Memory-driven agent framework with blockchain auditability
|