0xray 3.4.9 → 3.4.10
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/AGENTS-consumer.md +1 -1
- package/AGENTS.md +1 -1
- package/README.md +1 -1
- package/SKILLS.md +1 -1
- package/dist/AGENTS.md +1 -1
- package/dist/CHANGELOG.md +12 -0
- package/dist/README.md +1 -1
- package/dist/SKILLS.md +1 -1
- package/dist/mcps/orchestrator/config/agent-capabilities.d.ts +1 -1
- package/dist/mcps/orchestrator/config/agent-capabilities.js +23 -1
- package/dist/mcps/orchestrator/execution/execution-planner.js +2 -2
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +1 -1
- package/dist/nucleus/autonomy-kernel.d.ts +1 -1
- package/dist/nucleus/autonomy-kernel.js +5 -2
- package/package.json +4 -2
- package/scripts/mjs/verify-orchestrator-behavior.mjs +122 -0
- package/src/mcps/orchestrator/config/agent-capabilities.ts +26 -0
- package/src/mcps/orchestrator/execution/execution-planner.ts +2 -0
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +1 -0
package/AGENTS-consumer.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Quick reference for the 0xRay AI orchestration framework (shipped to your project on `npm install 0xray`).
|
|
6
6
|
|
|
7
|
-
**v3.4.
|
|
7
|
+
**v3.4.10** — 7 MCP servers · 45 skills · 68 codex terms · 4 platform bridges
|
|
8
8
|
|
|
9
9
|
## Postinstall (automatic)
|
|
10
10
|
|
package/AGENTS.md
CHANGED
package/README.md
CHANGED
package/SKILLS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0xray Skills
|
|
2
2
|
|
|
3
|
-
**v3.4.
|
|
3
|
+
**v3.4.10** — **45 skills** · invoked via `xray-skills` MCP · synced on postinstall
|
|
4
4
|
|
|
5
5
|
xray ships 45 knowledge skills (`src/skills/<name>/SKILL.md`) across the full software lifecycle. Lead-dev operating model lives in **`orchestrator`** skill + `multi_agent_orchestration.lead_dev_mode` in features.json. Skills load on demand via the **xray-skills** MCP server (`npx -y 0xray mcp skills`), agent `@mentions`, or platform skill directories after postinstall.
|
|
6
6
|
|
package/dist/AGENTS.md
CHANGED
package/dist/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ 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.4.10] - 2026-06-19
|
|
8
|
+
|
|
9
|
+
### 🐛 Bug Fixes
|
|
10
|
+
- **Routing SSOT** — `selectAgentForTask` checks `routeSubagent(taskType)` before capability scoring or memory routing; `type: implement` → `backend-engineer` (not `code-reviewer`)
|
|
11
|
+
- **Unified complexity** — `buildLeadDevPlan` uses `max(thin-dispatch, MCP overallComplexity)`; `dependencyCount: 8` at complexity 70 forces phased plan
|
|
12
|
+
|
|
13
|
+
### ✅ Tests
|
|
14
|
+
- `verify-orchestrator-behavior.mjs` ships in tarball — 5 behavior assertions (NaN, multi-task todos, implement routing, phased plan, honest deferral)
|
|
15
|
+
- Unit coverage: `agent-capabilities-routing`, extended `autonomy-kernel` + `execution-planner-dependencies`
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
7
19
|
## [3.4.9] - 2026-06-19
|
|
8
20
|
|
|
9
21
|
### ⚠️ Breaking Changes
|
package/dist/README.md
CHANGED
package/dist/SKILLS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0xray Skills
|
|
2
2
|
|
|
3
|
-
**v3.4.
|
|
3
|
+
**v3.4.10** — **45 skills** · invoked via `xray-skills` MCP · synced on postinstall
|
|
4
4
|
|
|
5
5
|
xray ships 45 knowledge skills (`src/skills/<name>/SKILL.md`) across the full software lifecycle. Lead-dev operating model lives in **`orchestrator`** skill + `multi_agent_orchestration.lead_dev_mode` in features.json. Skills load on demand via the **xray-skills** MCP server (`npx -y 0xray mcp skills`), agent `@mentions`, or platform skill directories after postinstall.
|
|
6
6
|
|
|
@@ -29,7 +29,7 @@ export declare class AgentCapabilitiesManager {
|
|
|
29
29
|
/**
|
|
30
30
|
* Select the best agent for a task based on complexity, capabilities, and memory routing.
|
|
31
31
|
*/
|
|
32
|
-
selectAgentForTask(requiredCapabilities: string[], complexity: number, operationDescription?: string): string | null;
|
|
32
|
+
selectAgentForTask(requiredCapabilities: string[], complexity: number, operationDescription?: string, taskType?: string): string | null;
|
|
33
33
|
/**
|
|
34
34
|
* Get all available agents for a given complexity level
|
|
35
35
|
*/
|
|
@@ -7,6 +7,22 @@
|
|
|
7
7
|
import { AGENT_REGISTRY } from "../../../agents/registry.js";
|
|
8
8
|
import { initializeMemoryRouting } from '../../../memory-routing/index.js';
|
|
9
9
|
import { getProvider, toMemoryCapabilityMap, fromMemoryCapabilityMap, } from './memory-routing-bridge.js';
|
|
10
|
+
import { routeSubagent } from '../../../nucleus/autonomy-kernel.js';
|
|
11
|
+
/** routeSubagent names → AGENT_REGISTRY keys */
|
|
12
|
+
const ROUTE_AGENT_ALIASES = {
|
|
13
|
+
'code-review': 'code-reviewer',
|
|
14
|
+
'security-audit': 'security-auditor',
|
|
15
|
+
'bug-triage': 'bug-triage-specialist',
|
|
16
|
+
'architect-tools': 'architect',
|
|
17
|
+
};
|
|
18
|
+
function resolveRoutedAgent(routed, capabilities) {
|
|
19
|
+
const candidate = ROUTE_AGENT_ALIASES[routed] ?? routed;
|
|
20
|
+
if (capabilities.has(candidate))
|
|
21
|
+
return candidate;
|
|
22
|
+
if (capabilities.has(routed))
|
|
23
|
+
return routed;
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
10
26
|
const DEFAULT_AGENT_CAPABILITIES = Object.fromEntries(Object.entries(AGENT_REGISTRY).map(([name, entry]) => [
|
|
11
27
|
name,
|
|
12
28
|
{
|
|
@@ -61,7 +77,13 @@ export class AgentCapabilitiesManager {
|
|
|
61
77
|
/**
|
|
62
78
|
* Select the best agent for a task based on complexity, capabilities, and memory routing.
|
|
63
79
|
*/
|
|
64
|
-
selectAgentForTask(requiredCapabilities, complexity, operationDescription = '') {
|
|
80
|
+
selectAgentForTask(requiredCapabilities, complexity, operationDescription = '', taskType = '') {
|
|
81
|
+
if (taskType.trim()) {
|
|
82
|
+
const routed = routeSubagent(taskType);
|
|
83
|
+
const resolved = resolveRoutedAgent(routed, this.capabilities);
|
|
84
|
+
if (resolved)
|
|
85
|
+
return resolved;
|
|
86
|
+
}
|
|
65
87
|
const provider = getProvider();
|
|
66
88
|
if (provider.id !== 'null' && operationDescription) {
|
|
67
89
|
const memoryCaps = toMemoryCapabilityMap(this.getAllCapabilities());
|
|
@@ -181,7 +181,7 @@ export class ExecutionPlanner {
|
|
|
181
181
|
const operationDescription = task.metadata?.memoryHighConfidenceTrap
|
|
182
182
|
? `${task.description} TYPE: ontological-trap`
|
|
183
183
|
: task.description;
|
|
184
|
-
const agent = this.capabilitiesManager.selectAgentForTask(requiredCaps, complexity, operationDescription) || 'orchestrator';
|
|
184
|
+
const agent = this.capabilitiesManager.selectAgentForTask(requiredCaps, complexity, operationDescription, task.type) || 'orchestrator';
|
|
185
185
|
if (!agentAssignments.has(agent)) {
|
|
186
186
|
agentAssignments.set(agent, []);
|
|
187
187
|
}
|
|
@@ -223,7 +223,7 @@ export class ExecutionPlanner {
|
|
|
223
223
|
task.type,
|
|
224
224
|
...(task.metadata?.memorySignals ?? []),
|
|
225
225
|
];
|
|
226
|
-
const agent = this.capabilitiesManager.selectAgentForTask(requiredCaps, complexity, task.description) || 'orchestrator';
|
|
226
|
+
const agent = this.capabilitiesManager.selectAgentForTask(requiredCaps, complexity, task.description, task.type) || 'orchestrator';
|
|
227
227
|
if (!assignments.has(agent)) {
|
|
228
228
|
assignments.set(agent, []);
|
|
229
229
|
}
|
|
@@ -59,7 +59,7 @@ export class ComplexityHandler {
|
|
|
59
59
|
.filter((t) => t.description?.trim())
|
|
60
60
|
.map((t) => ({ description: t.description, type: t.type }));
|
|
61
61
|
const leadDevPlan = isLeadDevModeActive() && (primaryDescription || planTaskInputs.length > 0)
|
|
62
|
-
? buildLeadDevPlan(primaryDescription, taskTypes.length ? taskTypes : ['implement'], planTaskInputs)
|
|
62
|
+
? buildLeadDevPlan(primaryDescription, taskTypes.length ? taskTypes : ['implement'], planTaskInputs, analysis.overallComplexity)
|
|
63
63
|
: null;
|
|
64
64
|
if (leadDevPlan) {
|
|
65
65
|
try {
|
|
@@ -41,7 +41,7 @@ export interface LeadDevPlan {
|
|
|
41
41
|
export declare function isLeadDevModeActive(): boolean;
|
|
42
42
|
export declare function routeSubagent(taskType: string): SubagentRoute;
|
|
43
43
|
export declare function shouldFlagFullTestSuite(command: string): boolean;
|
|
44
|
-
export declare function buildLeadDevPlan(description: string, taskTypes?: string[], taskInputs?: LeadDevPlanTaskInput[]): LeadDevPlan | null;
|
|
44
|
+
export declare function buildLeadDevPlan(description: string, taskTypes?: string[], taskInputs?: LeadDevPlanTaskInput[], mcpOverallComplexity?: number): LeadDevPlan | null;
|
|
45
45
|
export declare function buildSessionBootContext(): Record<string, unknown>;
|
|
46
46
|
/** Persist plan for PreToolUse spawn_subagent gate */
|
|
47
47
|
export declare function persistLeadDevPlan(plan: LeadDevPlan, projectRoot?: string): string;
|
|
@@ -73,13 +73,16 @@ function buildImplementationTodos(description, taskTypes, taskInputs, idPrefix)
|
|
|
73
73
|
status: 'pending',
|
|
74
74
|
}));
|
|
75
75
|
}
|
|
76
|
-
export function buildLeadDevPlan(description, taskTypes = ['implement'], taskInputs = []) {
|
|
76
|
+
export function buildLeadDevPlan(description, taskTypes = ['implement'], taskInputs = [], mcpOverallComplexity) {
|
|
77
77
|
if (!isLeadDevModeActive())
|
|
78
78
|
return null;
|
|
79
79
|
const cfg = orchestrationConfig();
|
|
80
80
|
const threshold = cfg.phased_plan_threshold ?? 25;
|
|
81
81
|
const score = scoreComplexity(description, { taskTypes });
|
|
82
|
-
const
|
|
82
|
+
const mcpScore = mcpOverallComplexity !== undefined && Number.isFinite(mcpOverallComplexity)
|
|
83
|
+
? Math.round(mcpOverallComplexity)
|
|
84
|
+
: 0;
|
|
85
|
+
const complexity = Math.max(score.score, mcpScore);
|
|
83
86
|
const requiresPhasedPlan = complexity > threshold || taskInputs.length > 1;
|
|
84
87
|
const mandatoryConsults = cfg.auto_consult_major_work !== false && requiresPhasedPlan
|
|
85
88
|
? [...MANDATORY_MAJOR_CONSULTS]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "0xray",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.10",
|
|
4
4
|
"description": "Multi-agent orchestration and Codex governance for OpenCode, Hermes, Grok Build, and OpenClaw",
|
|
5
5
|
"readme": "README.md",
|
|
6
6
|
"license": "MIT",
|
|
@@ -125,7 +125,8 @@
|
|
|
125
125
|
"pre-publish-guard": "node scripts/node/pre-publish-guard.js",
|
|
126
126
|
"safe-publish": "npm run prepare-consumer && npm run build",
|
|
127
127
|
"publish": "npm run release:gate && npm run safe-publish && npm publish --access public",
|
|
128
|
-
"release:patch": "node scripts/node/release.mjs patch"
|
|
128
|
+
"release:patch": "node scripts/node/release.mjs patch",
|
|
129
|
+
"verify:orchestrator-behavior": "npm run build && node scripts/mjs/verify-orchestrator-behavior.mjs"
|
|
129
130
|
},
|
|
130
131
|
"files": [
|
|
131
132
|
"dist/",
|
|
@@ -137,6 +138,7 @@
|
|
|
137
138
|
"scripts/mjs/test-mcp-functionality.mjs",
|
|
138
139
|
"scripts/mjs/validate-mcp-connectivity.cjs",
|
|
139
140
|
"scripts/mjs/validate-postinstall-config.mjs",
|
|
141
|
+
"scripts/mjs/verify-orchestrator-behavior.mjs",
|
|
140
142
|
"src/opencode/",
|
|
141
143
|
"src/opencode/codex.codex",
|
|
142
144
|
"src/opencode/commands/",
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Consumer behavior verify — orchestrator honesty (ships in 0xray tarball).
|
|
4
|
+
* Run: node node_modules/0xray/scripts/mjs/verify-orchestrator-behavior.mjs
|
|
5
|
+
*/
|
|
6
|
+
import { dirname, join } from 'path';
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
8
|
+
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const packageRoot = join(__dirname, '../..');
|
|
11
|
+
const dist = (rel) => pathToFileURL(join(packageRoot, 'dist', rel)).href;
|
|
12
|
+
|
|
13
|
+
let failed = 0;
|
|
14
|
+
|
|
15
|
+
function pass(name) {
|
|
16
|
+
console.log(`✅ ${name}`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function fail(name, detail = '') {
|
|
20
|
+
failed++;
|
|
21
|
+
console.error(`❌ ${name}${detail ? ` — ${detail}` : ''}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { dependencyCount, getExecutionPlanner } = await import(
|
|
25
|
+
dist('mcps/orchestrator/execution/execution-planner.js')
|
|
26
|
+
);
|
|
27
|
+
const { buildLeadDevPlan } = await import(dist('nucleus/autonomy-kernel.js'));
|
|
28
|
+
const { TaskHandler } = await import(
|
|
29
|
+
dist('mcps/orchestrator/handlers/task-handler.js')
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const planner = getExecutionPlanner();
|
|
33
|
+
|
|
34
|
+
// 1. numeric deps ≠ NaN
|
|
35
|
+
const analysis = await planner.analyzeTaskComplexity([
|
|
36
|
+
{
|
|
37
|
+
id: 't1',
|
|
38
|
+
description: 'Jelly migration',
|
|
39
|
+
type: 'implement',
|
|
40
|
+
dependencies: 8,
|
|
41
|
+
},
|
|
42
|
+
]);
|
|
43
|
+
if (Number.isFinite(analysis.overallComplexity) && analysis.overallComplexity > 0) {
|
|
44
|
+
pass('numeric dependencyCount produces finite MCP complexity');
|
|
45
|
+
} else {
|
|
46
|
+
fail('NaN guard', `overallComplexity=${analysis.overallComplexity}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 2. multi-task → ≥3 todos
|
|
50
|
+
const multiPlan = buildLeadDevPlan(
|
|
51
|
+
'G0 J1 J2',
|
|
52
|
+
['implement'],
|
|
53
|
+
[
|
|
54
|
+
{ description: 'Publish 0xray', type: 'release' },
|
|
55
|
+
{ description: 'Jelly swap', type: 'migration' },
|
|
56
|
+
{ description: 'Wire tests', type: 'test' },
|
|
57
|
+
],
|
|
58
|
+
70,
|
|
59
|
+
);
|
|
60
|
+
const todoCount =
|
|
61
|
+
multiPlan?.phases.reduce((n, p) => n + p.todos.length, 0) ?? 0;
|
|
62
|
+
if (multiPlan?.requiresPhasedPlan && todoCount >= 3) {
|
|
63
|
+
pass(`multi-task phased plan (${todoCount} todos)`);
|
|
64
|
+
} else {
|
|
65
|
+
fail('multi-task plan', `requiresPhasedPlan=${multiPlan?.requiresPhasedPlan} todos=${todoCount}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 3. implement → backend-engineer
|
|
69
|
+
const implAnalysis = await planner.analyzeTaskComplexity([
|
|
70
|
+
{ id: 'impl-1', description: 'swap deps', type: 'implement' },
|
|
71
|
+
]);
|
|
72
|
+
const implAgent = implAnalysis.agentAssignments[0]?.agent;
|
|
73
|
+
if (implAgent === 'backend-engineer') {
|
|
74
|
+
pass('implement routes to backend-engineer');
|
|
75
|
+
} else {
|
|
76
|
+
fail('implement routing', `got ${implAgent}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 4. MCP complexity drives phased plan (single task, high MCP score)
|
|
80
|
+
const singleHigh = buildLeadDevPlan(
|
|
81
|
+
'single complex migration',
|
|
82
|
+
['implement'],
|
|
83
|
+
[{ description: 'single complex migration', type: 'implement' }],
|
|
84
|
+
70,
|
|
85
|
+
);
|
|
86
|
+
if (singleHigh?.requiresPhasedPlan && (singleHigh.phases.length ?? 0) > 1) {
|
|
87
|
+
pass('MCP overallComplexity 70 forces phased plan');
|
|
88
|
+
} else {
|
|
89
|
+
fail('MCP phased plan', `requiresPhasedPlan=${singleHigh?.requiresPhasedPlan}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 5. orchestrate-task defers implement (not fake-complete)
|
|
93
|
+
const handler = new TaskHandler();
|
|
94
|
+
const orch = await handler.handleOrchestrateTask(
|
|
95
|
+
{
|
|
96
|
+
description: 'implement feature',
|
|
97
|
+
sessionId: 'verify-behavior',
|
|
98
|
+
tasks: [
|
|
99
|
+
{
|
|
100
|
+
id: 'be-1',
|
|
101
|
+
description: 'implementation work',
|
|
102
|
+
type: 'implement',
|
|
103
|
+
estimatedComplexity: 40,
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{ taskHistory: [], activeTasks: new Map() },
|
|
108
|
+
);
|
|
109
|
+
const text = orch.content[0]?.text ?? '';
|
|
110
|
+
if (text.includes('Deferred') && text.includes('❌ FAILED')) {
|
|
111
|
+
pass('orchestrate-task defers implement (success: false)');
|
|
112
|
+
} else {
|
|
113
|
+
fail('defer honesty', text.slice(0, 200));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
console.log(
|
|
117
|
+
'\n' +
|
|
118
|
+
(failed === 0
|
|
119
|
+
? '🎉 Orchestrator behavior verify passed (5/5).'
|
|
120
|
+
: `⚠️ ${failed} behavior check(s) failed.`),
|
|
121
|
+
);
|
|
122
|
+
process.exit(failed === 0 ? 0 : 1);
|
|
@@ -13,6 +13,25 @@ import {
|
|
|
13
13
|
toMemoryCapabilityMap,
|
|
14
14
|
fromMemoryCapabilityMap,
|
|
15
15
|
} from './memory-routing-bridge.js';
|
|
16
|
+
import { routeSubagent } from '../../../nucleus/autonomy-kernel.js';
|
|
17
|
+
|
|
18
|
+
/** routeSubagent names → AGENT_REGISTRY keys */
|
|
19
|
+
const ROUTE_AGENT_ALIASES: Record<string, string> = {
|
|
20
|
+
'code-review': 'code-reviewer',
|
|
21
|
+
'security-audit': 'security-auditor',
|
|
22
|
+
'bug-triage': 'bug-triage-specialist',
|
|
23
|
+
'architect-tools': 'architect',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function resolveRoutedAgent(
|
|
27
|
+
routed: string,
|
|
28
|
+
capabilities: Map<string, AgentCapability>,
|
|
29
|
+
): string | null {
|
|
30
|
+
const candidate = ROUTE_AGENT_ALIASES[routed] ?? routed;
|
|
31
|
+
if (capabilities.has(candidate)) return candidate;
|
|
32
|
+
if (capabilities.has(routed)) return routed;
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
16
35
|
|
|
17
36
|
const DEFAULT_AGENT_CAPABILITIES: Record<string, AgentCapability> = Object.fromEntries(
|
|
18
37
|
Object.entries(AGENT_REGISTRY).map(([name, entry]) => [
|
|
@@ -81,7 +100,14 @@ export class AgentCapabilitiesManager {
|
|
|
81
100
|
requiredCapabilities: string[],
|
|
82
101
|
complexity: number,
|
|
83
102
|
operationDescription = '',
|
|
103
|
+
taskType = '',
|
|
84
104
|
): string | null {
|
|
105
|
+
if (taskType.trim()) {
|
|
106
|
+
const routed = routeSubagent(taskType);
|
|
107
|
+
const resolved = resolveRoutedAgent(routed, this.capabilities);
|
|
108
|
+
if (resolved) return resolved;
|
|
109
|
+
}
|
|
110
|
+
|
|
85
111
|
const provider = getProvider();
|
|
86
112
|
|
|
87
113
|
if (provider.id !== 'null' && operationDescription) {
|
|
@@ -243,6 +243,7 @@ export class ExecutionPlanner {
|
|
|
243
243
|
requiredCaps,
|
|
244
244
|
complexity,
|
|
245
245
|
operationDescription,
|
|
246
|
+
task.type,
|
|
246
247
|
) || 'orchestrator';
|
|
247
248
|
|
|
248
249
|
if (!agentAssignments.has(agent)) {
|
|
@@ -298,6 +299,7 @@ export class ExecutionPlanner {
|
|
|
298
299
|
requiredCaps,
|
|
299
300
|
complexity,
|
|
300
301
|
task.description,
|
|
302
|
+
task.type,
|
|
301
303
|
) || 'orchestrator';
|
|
302
304
|
|
|
303
305
|
if (!assignments.has(agent)) {
|