0xray 3.3.0 → 3.3.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.
- package/.opencode/codex.codex +1 -1
- package/dist/CHANGELOG.md +10 -0
- package/dist/integrations/grok/grok-cli.js +6 -0
- package/dist/mcps/index.js +1 -0
- package/dist/mcps/knowledge-skills/skill-invocation.server.js +3 -2
- package/dist/mcps/knowledge-skills/storyteller.server.js +167 -0
- package/dist/mcps/orchestrator/execution/execution-planner.js +14 -2
- package/dist/mcps/researcher-confidence.js +92 -0
- package/dist/mcps/researcher.server.js +19 -3
- package/dist/memory-routing/null-provider.js +12 -0
- package/package.json +1 -1
- package/scripts/node/install-bridges.cjs +364 -0
- package/scripts/node/postinstall.cjs +24 -83
- package/scripts/node/setup.cjs +2 -6
- package/scripts/node/universal-version-manager.js +2 -2
- package/src/mcps/index.ts +1 -0
- package/src/mcps/knowledge-skills/skill-invocation.server.ts +3 -2
- package/src/mcps/knowledge-skills/storyteller.server.ts +206 -0
- package/src/mcps/orchestrator/execution/execution-planner.ts +14 -2
- package/src/mcps/orchestrator/types.ts +4 -0
- package/src/mcps/researcher-confidence.ts +144 -0
- package/src/mcps/researcher.server.ts +28 -3
- package/src/opencode/codex.codex +1 -1
package/.opencode/codex.codex
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.3.
|
|
2
|
+
"version": "3.3.1",
|
|
3
3
|
"terms": [
|
|
4
4
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60
|
|
5
5
|
],
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Conventional Commits](https://www.conventionalcommits.org/).
|
|
6
6
|
|
|
7
|
+
## [3.3.0] - 2026-06-18
|
|
8
|
+
|
|
9
|
+
### 🔄 Changes
|
|
10
|
+
|
|
11
|
+
### 🔎 Other Changes
|
|
12
|
+
- Wire orchestrator confidence gate into execution planning (d7910b610)
|
|
13
|
+
- tweet: v3.3.0 release tweet — Pluggable Memory Routing (7fb6c9f70)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
7
17
|
## [3.2.0] - 2026-06-17
|
|
8
18
|
|
|
9
19
|
### 🔄 Changes
|
|
@@ -55,6 +55,12 @@ export async function installForGrokCLI(options = {}) {
|
|
|
55
55
|
console.log(`\x1b[32m✓ Synced ${skillsCopied} builtin skills to Grok plugin\x1b[0m`);
|
|
56
56
|
}
|
|
57
57
|
frameworkLogger.log('grok-integration', 'skills-synced', 'info', { count: skillsCopied });
|
|
58
|
+
// Grok Build / Cursor also reads ~/.grok/skills/ for agent_skills
|
|
59
|
+
const globalSkillsDir = path.join(home, '.grok', 'skills');
|
|
60
|
+
const globalCopied = syncBuiltinSkills(globalSkillsDir);
|
|
61
|
+
if (globalCopied > 0) {
|
|
62
|
+
console.log(`\x1b[32m✓ Synced ${globalCopied} builtin skills to ~/.grok/skills/\x1b[0m`);
|
|
63
|
+
}
|
|
58
64
|
// Attempt auto-trust (best effort)
|
|
59
65
|
try {
|
|
60
66
|
execSync(`grok plugins trust "${targetPluginDir}"`, { stdio: 'ignore' });
|
package/dist/mcps/index.js
CHANGED
|
@@ -40,6 +40,7 @@ export const MCP_SERVERS = [
|
|
|
40
40
|
{ serverName: "refactoring-strategies", sourceFile: "mcps/knowledge-skills/refactoring-strategies.server.ts", type: "knowledge-skill", registered: true, description: "Refactoring strategies" },
|
|
41
41
|
{ serverName: "security-audit", sourceFile: "mcps/knowledge-skills/security-audit.server.ts", type: "knowledge-skill", registered: true, description: "Security auditing" },
|
|
42
42
|
{ serverName: "seo-consultant", sourceFile: "mcps/knowledge-skills/seo-consultant.server.ts", type: "knowledge-skill", registered: false, description: "SEO consulting" },
|
|
43
|
+
{ serverName: "storyteller", sourceFile: "mcps/knowledge-skills/storyteller.server.ts", type: "knowledge-skill", registered: false, description: "Reflections, sagas, and technical narratives" },
|
|
43
44
|
{ serverName: "session-management", sourceFile: "mcps/knowledge-skills/session-management.server.ts", type: "knowledge-skill", registered: true, description: "Session management" },
|
|
44
45
|
{ serverName: "skill-invocation", sourceFile: "mcps/knowledge-skills/skill-invocation.server.ts", type: "knowledge-skill", registered: true, description: "Skill invocation" },
|
|
45
46
|
{ serverName: "strategist", sourceFile: "mcps/knowledge-skills/strategist.server.ts", type: "knowledge-skill", registered: false, description: "Strategic planning" },
|
|
@@ -87,7 +87,7 @@ class SkillInvocationServer extends XrayKnowledgeSkillBase {
|
|
|
87
87
|
"strategist", "skill-invocation",
|
|
88
88
|
];
|
|
89
89
|
const knowledgeSkills = [
|
|
90
|
-
"architecture-patterns", "strategist", "tech-writer",
|
|
90
|
+
"architecture-patterns", "strategist", "tech-writer", "storyteller",
|
|
91
91
|
"seo-consultant", "content-creator", "growth-strategist",
|
|
92
92
|
"bug-triage-specialist", "log-monitor",
|
|
93
93
|
"mobile-development", "git-workflow", "session-management",
|
|
@@ -132,6 +132,7 @@ class SkillInvocationServer extends XrayKnowledgeSkillBase {
|
|
|
132
132
|
"tech-writer": "documentation-generation",
|
|
133
133
|
"frontend-ui-ux-engineer": "ui-ux-design",
|
|
134
134
|
"frontend-engineer": "project-analysis",
|
|
135
|
+
"storyteller": "storyteller",
|
|
135
136
|
};
|
|
136
137
|
const resolvedSkill = skillAliases[skillName] || skillName;
|
|
137
138
|
const availableServers = [
|
|
@@ -147,7 +148,7 @@ class SkillInvocationServer extends XrayKnowledgeSkillBase {
|
|
|
147
148
|
"git-workflow", "content-creator", "ui-ux-design",
|
|
148
149
|
"multimodal-looker", "refactoring-strategies",
|
|
149
150
|
"project-analysis", "testing-best-practices",
|
|
150
|
-
"architecture-patterns",
|
|
151
|
+
"architecture-patterns", "storyteller",
|
|
151
152
|
];
|
|
152
153
|
if (!availableServers.includes(resolvedSkill)) {
|
|
153
154
|
return {
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storyteller MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Returns storyteller SKILL.md guidance plus a session-aware writing prompt.
|
|
5
|
+
* The host LLM writes the story; this server supplies the contract.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { dirname, join } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { XrayKnowledgeSkillBase } from '../shared/knowledge-skill-base.js';
|
|
12
|
+
const STORY_TYPES = ['reflection', 'saga', 'journey', 'narrative'];
|
|
13
|
+
function resolveSkillMd() {
|
|
14
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const candidates = [
|
|
16
|
+
join(here, '../../../skills/storyteller/SKILL.md'),
|
|
17
|
+
join(here, '../../skills/storyteller/SKILL.md'),
|
|
18
|
+
join(process.cwd(), 'node_modules/0xray/dist/skills/storyteller/SKILL.md'),
|
|
19
|
+
join(process.cwd(), 'node_modules/xray/dist/skills/storyteller/SKILL.md'),
|
|
20
|
+
];
|
|
21
|
+
for (const path of candidates) {
|
|
22
|
+
if (existsSync(path)) {
|
|
23
|
+
return readFileSync(path, 'utf-8');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return '# Storyteller\n\nWrite warmly candid technical reflections with scene-first openings.';
|
|
27
|
+
}
|
|
28
|
+
function getStoryMeta(storyType) {
|
|
29
|
+
const defaults = {
|
|
30
|
+
reflection: {
|
|
31
|
+
location: 'docs/reflections/',
|
|
32
|
+
min_words: 2000,
|
|
33
|
+
ideal_words: 5000,
|
|
34
|
+
framework: 'three_act_structure',
|
|
35
|
+
},
|
|
36
|
+
saga: {
|
|
37
|
+
location: 'docs/reflections/deep/',
|
|
38
|
+
min_words: 5000,
|
|
39
|
+
ideal_words: 15000,
|
|
40
|
+
framework: 'hero_journey',
|
|
41
|
+
},
|
|
42
|
+
journey: {
|
|
43
|
+
location: 'docs/reflections/deep/',
|
|
44
|
+
min_words: 1500,
|
|
45
|
+
ideal_words: 4000,
|
|
46
|
+
framework: 'three_act_structure',
|
|
47
|
+
},
|
|
48
|
+
narrative: {
|
|
49
|
+
location: 'docs/reflections/',
|
|
50
|
+
min_words: 1000,
|
|
51
|
+
ideal_words: 3000,
|
|
52
|
+
framework: 'three_act_structure',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
return defaults[storyType];
|
|
56
|
+
}
|
|
57
|
+
function gitContext() {
|
|
58
|
+
try {
|
|
59
|
+
const commits = execSync('git log --oneline -20 2>/dev/null', { encoding: 'utf-8' });
|
|
60
|
+
const files = execSync('git diff --name-only HEAD~10 2>/dev/null || git ls-files 2>/dev/null | head -50', { encoding: 'utf-8' });
|
|
61
|
+
return `Recent commits:\n${commits}\n\nRecent files:\n${files}`;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return 'No git context available in this workspace.';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function buildPrompt(storyType, title, meta, extraContext) {
|
|
68
|
+
const contextBlock = extraContext
|
|
69
|
+
? `\n## Provided context\n${JSON.stringify(extraContext, null, 2)}\n`
|
|
70
|
+
: '';
|
|
71
|
+
return `Write a ${storyType} titled "${title}".
|
|
72
|
+
|
|
73
|
+
## Requirements
|
|
74
|
+
- Framework: ${meta.framework}
|
|
75
|
+
- Target length: ${meta.ideal_words} words (minimum: ${meta.min_words})
|
|
76
|
+
- Save to: ${meta.location}
|
|
77
|
+
- Follow storyteller SKILL.md voice (warmly candid, scene-first, no executive summary)
|
|
78
|
+
- Include Key Takeaways and What Next sections
|
|
79
|
+
|
|
80
|
+
## Session / repo context
|
|
81
|
+
${gitContext()}
|
|
82
|
+
${contextBlock}
|
|
83
|
+
|
|
84
|
+
Write the complete ${storyType} now.`;
|
|
85
|
+
}
|
|
86
|
+
function writeStoryTool(storyType, args) {
|
|
87
|
+
const meta = getStoryMeta(storyType);
|
|
88
|
+
if (args.framework)
|
|
89
|
+
meta.framework = args.framework;
|
|
90
|
+
const title = args.title ??
|
|
91
|
+
`${storyType.charAt(0).toUpperCase() + storyType.slice(1)} - ${new Date().toISOString().split('T')[0]}`;
|
|
92
|
+
const skillMd = resolveSkillMd();
|
|
93
|
+
const prompt = buildPrompt(storyType, title, meta, args.context);
|
|
94
|
+
const slug = title
|
|
95
|
+
.toLowerCase()
|
|
96
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
97
|
+
.replace(/^-|-$/g, '');
|
|
98
|
+
const filename = `${storyType}-${slug}-${new Date().toISOString().split('T')[0]}.md`;
|
|
99
|
+
const outputPath = args.output ?? join(meta.location, filename);
|
|
100
|
+
const outputDir = join(process.cwd(), dirname(outputPath));
|
|
101
|
+
if (!existsSync(outputDir))
|
|
102
|
+
mkdirSync(outputDir, { recursive: true });
|
|
103
|
+
const fullPath = join(process.cwd(), outputPath);
|
|
104
|
+
const frontmatter = `---
|
|
105
|
+
story_type: ${storyType}
|
|
106
|
+
title: "${title}"
|
|
107
|
+
framework: ${meta.framework}
|
|
108
|
+
target_words: ${meta.ideal_words}
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
`;
|
|
112
|
+
writeFileSync(fullPath, `${frontmatter}\n${prompt}\n`, 'utf-8');
|
|
113
|
+
return {
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: 'text',
|
|
117
|
+
text: [
|
|
118
|
+
`Storyteller ${storyType} brief prepared.`,
|
|
119
|
+
`Output template: ${outputPath}`,
|
|
120
|
+
'',
|
|
121
|
+
'--- SKILL (excerpt) ---',
|
|
122
|
+
skillMd.slice(0, 4000),
|
|
123
|
+
skillMd.length > 4000 ? '\n...(truncated; full SKILL.md on disk)' : '',
|
|
124
|
+
'',
|
|
125
|
+
'--- WRITING PROMPT ---',
|
|
126
|
+
prompt,
|
|
127
|
+
'',
|
|
128
|
+
'Host LLM: write the full story into the output path using the prompt above.',
|
|
129
|
+
].join('\n'),
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
class StorytellerServer extends XrayKnowledgeSkillBase {
|
|
135
|
+
constructor() {
|
|
136
|
+
super('storyteller', '1.0.0');
|
|
137
|
+
const writeSchema = {
|
|
138
|
+
type: 'object',
|
|
139
|
+
properties: {
|
|
140
|
+
title: { type: 'string', description: 'Story title' },
|
|
141
|
+
context: { type: 'object', description: 'Session context (commits, changes, notes)' },
|
|
142
|
+
framework: { type: 'string', description: 'Storytelling framework override' },
|
|
143
|
+
output: { type: 'string', description: 'Relative output path' },
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
this.tools = STORY_TYPES.map((storyType) => ({
|
|
147
|
+
name: `write_${storyType}`,
|
|
148
|
+
description: `Prepare ${storyType} story brief using storyteller SKILL.md`,
|
|
149
|
+
inputSchema: writeSchema,
|
|
150
|
+
}));
|
|
151
|
+
this.handlers = {
|
|
152
|
+
write_reflection: async (args) => writeStoryTool('reflection', args),
|
|
153
|
+
write_saga: async (args) => writeStoryTool('saga', args),
|
|
154
|
+
write_journey: async (args) => writeStoryTool('journey', args),
|
|
155
|
+
write_narrative: async (args) => writeStoryTool('narrative', args),
|
|
156
|
+
};
|
|
157
|
+
this.setupToolHandlers();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (import.meta.url === `file://${fileURLToPath(import.meta.url)}`) {
|
|
161
|
+
const server = new StorytellerServer();
|
|
162
|
+
server.run().catch((error) => {
|
|
163
|
+
process.stderr.write(`FATAL: ${String(error)}\n`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
export { StorytellerServer };
|
|
@@ -159,12 +159,15 @@ export class ExecutionPlanner {
|
|
|
159
159
|
*/
|
|
160
160
|
assignTasksToAgents(tasks, agentAssignments) {
|
|
161
161
|
for (const task of tasks) {
|
|
162
|
-
const complexity = task
|
|
162
|
+
const complexity = this.calculateTaskComplexity(task);
|
|
163
163
|
const requiredCaps = [
|
|
164
164
|
task.type,
|
|
165
165
|
...(task.metadata?.memorySignals ?? []),
|
|
166
166
|
];
|
|
167
|
-
const
|
|
167
|
+
const operationDescription = task.metadata?.memoryHighConfidenceTrap
|
|
168
|
+
? `${task.description} TYPE: ontological-trap`
|
|
169
|
+
: task.description;
|
|
170
|
+
const agent = this.capabilitiesManager.selectAgentForTask(requiredCaps, complexity, operationDescription) || 'orchestrator';
|
|
168
171
|
if (!agentAssignments.has(agent)) {
|
|
169
172
|
agentAssignments.set(agent, []);
|
|
170
173
|
}
|
|
@@ -264,6 +267,15 @@ export class ExecutionPlanner {
|
|
|
264
267
|
if (task.dependencies) {
|
|
265
268
|
complexity += task.dependencies.length * 5;
|
|
266
269
|
}
|
|
270
|
+
if (task.metadata?.memoryComplexityBoost !== undefined) {
|
|
271
|
+
complexity += task.metadata.memoryComplexityBoost;
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
const provider = getProvider();
|
|
275
|
+
if (provider.id !== 'null' && provider.getTaskConfidence) {
|
|
276
|
+
complexity += provider.getTaskConfidence(toMemoryTask(task)).complexityBoost;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
267
279
|
return Math.min(Math.max(Math.round(complexity), 1), 100);
|
|
268
280
|
}
|
|
269
281
|
/**
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { frameworkLogger } from '../core/framework-logger.js';
|
|
2
|
+
import { getMemoryRoutingProviderSync } from '../memory-routing/index.js';
|
|
3
|
+
const TRAP_LANGUAGE = /TYPE:\s*ontological-trap|ontological[- ]trap/i;
|
|
4
|
+
const DEFAULT_MIN_CONFIDENCE_GATE = 0.55;
|
|
5
|
+
export function shouldQueryRepertoireConfidence(description, proposalType = '') {
|
|
6
|
+
const text = `${description} ${proposalType}`.trim();
|
|
7
|
+
return TRAP_LANGUAGE.test(text);
|
|
8
|
+
}
|
|
9
|
+
export function hasHighConfidencePrimitiveMatch(routingContext, minConfidence = DEFAULT_MIN_CONFIDENCE_GATE) {
|
|
10
|
+
const confidences = routingContext.signalConfidences ?? {};
|
|
11
|
+
return Object.values(confidences).some((confidence) => confidence >= minConfidence);
|
|
12
|
+
}
|
|
13
|
+
function buildTaskText(proposalTitle, proposalDescription, proposalType) {
|
|
14
|
+
return [proposalTitle, proposalDescription, proposalType].filter(Boolean).join('\n');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Resolve Repertoire task confidence for researcher proposal analysis.
|
|
18
|
+
* Triggered by ontological-trap language or high-confidence primitive matches.
|
|
19
|
+
*/
|
|
20
|
+
export function resolveResearcherMemoryContext(input) {
|
|
21
|
+
const proposalTitle = input.proposalTitle ?? '';
|
|
22
|
+
const proposalDescription = input.proposalDescription ?? '';
|
|
23
|
+
const proposalType = input.proposalType ?? '';
|
|
24
|
+
const taskText = buildTaskText(proposalTitle, proposalDescription, proposalType);
|
|
25
|
+
const provider = getMemoryRoutingProviderSync();
|
|
26
|
+
if (provider.id === 'null' || !provider.getTaskConfidence) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const trapLanguageDetected = shouldQueryRepertoireConfidence(proposalDescription, proposalType);
|
|
30
|
+
const routingContext = provider.buildRoutingContext(taskText);
|
|
31
|
+
const primitiveMatchDetected = hasHighConfidencePrimitiveMatch(routingContext);
|
|
32
|
+
if (!trapLanguageDetected && !primitiveMatchDetected) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const confidence = provider.getTaskConfidence({
|
|
36
|
+
id: 'researcher-proposal',
|
|
37
|
+
description: taskText,
|
|
38
|
+
type: proposalType || 'governance',
|
|
39
|
+
});
|
|
40
|
+
const matchedSignals = confidence.matchedSignals.length > 0
|
|
41
|
+
? confidence.matchedSignals
|
|
42
|
+
: routingContext.matchedSignals;
|
|
43
|
+
const context = {
|
|
44
|
+
providerId: provider.id,
|
|
45
|
+
confidence,
|
|
46
|
+
matchedSignals,
|
|
47
|
+
recommendedAgent: confidence.recommendedAgent,
|
|
48
|
+
triggeredBy: trapLanguageDetected ? 'trap-language' : 'high-confidence-primitives',
|
|
49
|
+
};
|
|
50
|
+
if (confidence.highConfidenceTrapPresent) {
|
|
51
|
+
frameworkLogger.log('mcps/researcher', 'repertoire-trap-detected', 'info', {
|
|
52
|
+
providerId: provider.id,
|
|
53
|
+
matchedSignals,
|
|
54
|
+
complexityBoost: confidence.complexityBoost,
|
|
55
|
+
recommendedAgent: confidence.recommendedAgent,
|
|
56
|
+
triggeredBy: context.triggeredBy,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return context;
|
|
60
|
+
}
|
|
61
|
+
export function buildMemoryRoutingEvidence(context) {
|
|
62
|
+
const { confidence, matchedSignals, recommendedAgent } = context;
|
|
63
|
+
const signalSummary = confidence.signals
|
|
64
|
+
.map((entry) => `${entry.name} (${entry.confidence.toFixed(2)})`)
|
|
65
|
+
.join(', ');
|
|
66
|
+
const lines = [
|
|
67
|
+
`Repertoire memory routing (${context.providerId}, trigger: ${context.triggeredBy})`,
|
|
68
|
+
`Matched signals: ${matchedSignals.join(', ') || 'none'}`,
|
|
69
|
+
`Signal confidences: ${signalSummary || 'none'}`,
|
|
70
|
+
`High-confidence trap present: ${confidence.highConfidenceTrapPresent}`,
|
|
71
|
+
`Complexity boost: ${confidence.complexityBoost}`,
|
|
72
|
+
];
|
|
73
|
+
if (recommendedAgent) {
|
|
74
|
+
lines.push(`Recommended agent for trap handling: ${recommendedAgent}`);
|
|
75
|
+
}
|
|
76
|
+
return lines;
|
|
77
|
+
}
|
|
78
|
+
export function formatMemoryRoutingBlock(context) {
|
|
79
|
+
const { confidence, matchedSignals, recommendedAgent } = context;
|
|
80
|
+
const lines = [
|
|
81
|
+
'MEMORY_ROUTING:',
|
|
82
|
+
` provider: ${context.providerId}`,
|
|
83
|
+
` trigger: ${context.triggeredBy}`,
|
|
84
|
+
` matchedSignals: ${matchedSignals.join(', ') || 'none'}`,
|
|
85
|
+
` highConfidenceTrapPresent: ${confidence.highConfidenceTrapPresent}`,
|
|
86
|
+
` complexityBoost: ${confidence.complexityBoost}`,
|
|
87
|
+
];
|
|
88
|
+
if (recommendedAgent) {
|
|
89
|
+
lines.push(` recommendedAgent: ${recommendedAgent}`);
|
|
90
|
+
}
|
|
91
|
+
return lines.join('\n');
|
|
92
|
+
}
|
|
@@ -11,6 +11,7 @@ import * as fs from "fs";
|
|
|
11
11
|
import * as path from "path";
|
|
12
12
|
import { frameworkLogger } from "../core/framework-logger.js";
|
|
13
13
|
import { tryLLMGovernance } from "../governance/llm-governance-provider.js";
|
|
14
|
+
import { buildMemoryRoutingEvidence, formatMemoryRoutingBlock, resolveResearcherMemoryContext, } from "./researcher-confidence.js";
|
|
14
15
|
import { XrayKnowledgeSkillBase } from "./shared/knowledge-skill-base.js";
|
|
15
16
|
class XrayLibrarianServer extends XrayKnowledgeSkillBase {
|
|
16
17
|
constructor() {
|
|
@@ -377,13 +378,28 @@ class XrayLibrarianServer extends XrayKnowledgeSkillBase {
|
|
|
377
378
|
*/
|
|
378
379
|
async analyzeProposal(args) {
|
|
379
380
|
const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args || {};
|
|
380
|
-
const
|
|
381
|
+
const memoryContext = resolveResearcherMemoryContext({
|
|
382
|
+
proposalTitle,
|
|
383
|
+
proposalDescription,
|
|
384
|
+
proposalType,
|
|
385
|
+
});
|
|
386
|
+
const enrichedEvidence = [...(evidence || [])];
|
|
387
|
+
if (memoryContext?.confidence.highConfidenceTrapPresent) {
|
|
388
|
+
enrichedEvidence.push(...buildMemoryRoutingEvidence(memoryContext));
|
|
389
|
+
}
|
|
390
|
+
const vote = await tryLLMGovernance("researcher", proposalTitle || "", proposalDescription || "", enrichedEvidence, proposalType || "");
|
|
391
|
+
const memoryRoutingBlock = memoryContext?.confidence.highConfidenceTrapPresent
|
|
392
|
+
? `\n${formatMemoryRoutingBlock(memoryContext)}`
|
|
393
|
+
: "";
|
|
381
394
|
if (!vote) {
|
|
395
|
+
const abstainReason = memoryContext?.confidence.highConfidenceTrapPresent
|
|
396
|
+
? "No LLM governance provider configured. Repertoire detected a high-confidence ontological trap — route to the recommended agent before proceeding."
|
|
397
|
+
: "No LLM governance provider configured. Set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT, or install Hermes and run: hermes auth add xai-oauth --no-browser";
|
|
382
398
|
return {
|
|
383
399
|
content: [
|
|
384
400
|
{
|
|
385
401
|
type: "text",
|
|
386
|
-
text:
|
|
402
|
+
text: `DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: ${abstainReason}${memoryRoutingBlock}`,
|
|
387
403
|
},
|
|
388
404
|
],
|
|
389
405
|
};
|
|
@@ -392,7 +408,7 @@ class XrayLibrarianServer extends XrayKnowledgeSkillBase {
|
|
|
392
408
|
content: [
|
|
393
409
|
{
|
|
394
410
|
type: "text",
|
|
395
|
-
text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
|
|
411
|
+
text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}${memoryRoutingBlock}`,
|
|
396
412
|
},
|
|
397
413
|
],
|
|
398
414
|
};
|
|
@@ -45,6 +45,18 @@ export class NullMemoryRoutingProvider {
|
|
|
45
45
|
context: { ...EMPTY_CONTEXT },
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
+
getTaskConfidence() {
|
|
49
|
+
return {
|
|
50
|
+
signals: [],
|
|
51
|
+
matchedSignals: [],
|
|
52
|
+
avgConfidence: 0,
|
|
53
|
+
maxConfidence: 0,
|
|
54
|
+
highConfidenceTrapPresent: false,
|
|
55
|
+
ontologicalTrapDetected: false,
|
|
56
|
+
complexityBoost: 0,
|
|
57
|
+
recommendedAgent: null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
48
60
|
}
|
|
49
61
|
export function createMemoryRoutingProvider() {
|
|
50
62
|
return new NullMemoryRoutingProvider();
|