0xray 3.0.14 → 3.1.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.
- package/.opencode/hooks/post-commit +1 -1
- package/.opencode/init.sh +4 -4
- package/AGENTS.md +2 -2
- package/dist/AGENTS.md +2 -2
- package/dist/CHANGELOG.md +9 -0
- package/dist/benchmark/performance-benchmark.js +4 -2
- package/dist/cli/commands/hermes-install.js +4 -4
- package/dist/cli/commands/mcp-install.js +1 -1
- package/dist/cli/commands/openclaw-install.js +1 -1
- package/dist/cli/commands/plugin-commands.js +2 -2
- package/dist/cli/commands/publish-agent.js +5 -5
- package/dist/cli/commands/skill-install.js +1 -1
- package/dist/cli/commands/status.js +3 -3
- package/dist/cli/commands/storyteller.js +1 -1
- package/dist/cli/index.js +6 -6
- package/dist/cli/server.js +4 -4
- package/dist/core/boot-orchestrator.js +24 -24
- package/dist/core/bridge.mjs +22 -22
- package/dist/core/codex-formatter.js +2 -2
- package/dist/core/codex-injector.js +5 -5
- package/dist/core/config-loader.js +4 -2
- package/dist/core/config-paths.js +14 -14
- package/dist/core/context-loader.js +8 -5
- package/dist/core/index.js +1 -1
- package/dist/core/orchestrator.js +1 -1
- package/dist/core/system-prompt-generator.js +2 -2
- package/dist/core/xray-activation.js +42 -40
- package/dist/delegation/agent-delegator.js +2 -2
- package/dist/enforcement/enforcer-tools.js +2 -2
- package/dist/enforcement/loaders/codex-loader.js +2 -2
- package/dist/governance/llm-governance-provider.js +210 -0
- package/dist/index.js +8 -6
- package/dist/inference/deploy-verifier.js +1 -1
- package/dist/inference/inference-cycle.js +7 -7
- package/dist/integrations/hermes-agent/__init__.py +72 -72
- package/dist/integrations/hermes-agent/after-install.md +14 -14
- package/dist/integrations/hermes-agent/bridge.mjs +24 -24
- package/dist/integrations/hermes-agent/plugin.yaml +5 -5
- package/dist/integrations/hermes-agent/schemas.py +12 -12
- package/dist/integrations/hermes-agent/test_plugin.py +117 -117
- package/dist/integrations/hermes-agent/tools.py +25 -25
- package/dist/integrations/plugins/plugin-registry.js +2 -2
- package/dist/mcps/config/server-config-registry.js +10 -10
- package/dist/mcps/connection/mcp-connection.js +1 -1
- package/dist/mcps/framework-help.server.js +6 -6
- package/dist/mcps/knowledge-skills/code-review.server.js +12 -37
- package/dist/mcps/knowledge-skills/security-audit.server.js +12 -42
- package/dist/mcps/knowledge-skills/ui-ux-design.server.js +2 -2
- package/dist/mcps/lint.server.js +2 -2
- package/dist/mcps/mcp-client.js +5 -5
- package/dist/mcps/orchestrator/server.js +2 -2
- package/dist/mcps/researcher.server.js +12 -37
- package/dist/mcps/simulation/server-simulations.js +3 -3
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +2 -2
- package/dist/orchestrator/intelligent-commit-batcher.js +3 -3
- package/dist/orchestrator/multi-agent-orchestration-coordinator.js +9 -9
- package/dist/orchestrator/orchestrator.js +10 -8
- package/dist/orchestrator/universal-registry-bridge.js +3 -3
- package/dist/plugin/xray-codex-injection.js +21 -21
- package/dist/postprocessor/PostProcessor.js +5 -5
- package/dist/postprocessor/services/RegressionAnalysisService.js +2 -2
- package/dist/postprocessor/triggers/GitHookTrigger.js +14 -14
- package/dist/processors/implementations/agents-md-validation-processor.js +2 -2
- package/dist/processors/implementations/inference-improvement-processor.js +1 -1
- package/dist/processors/implementations/log-protection-processor.js +2 -2
- package/dist/processors/implementations/publish-preflight-processor.js +3 -3
- package/dist/processors/implementations/regression-testing-processor.js +2 -2
- package/dist/processors/implementations/session-summary-processor.js +1 -1
- package/dist/processors/implementations/storytelling-trigger-processor.js +1 -1
- package/dist/reporting/report-formatter.js +1 -1
- package/dist/scripts/activate-kernel-pipeline.js +2 -2
- package/dist/services/inference-tuner.js +2 -2
- package/dist/skills/hermes-agent/SKILL.md +42 -42
- package/dist/skills/storyteller/SKILL.md +1 -1
- package/dist/state/index.js +2 -1
- package/dist/state/state-manager.js +3 -3
- package/dist/utils/token-manager.js +1 -1
- package/dist/validation/estimation-validator.js +1 -1
- package/package.json +1 -1
- package/scripts/node/pre-publish-guard.js +13 -9
- package/scripts/node/universal-version-manager.js +2 -2
- package/src/mcps/config/__tests__/server-config-registry.test.ts +12 -12
- package/src/mcps/config/server-config-registry.ts +10 -10
- package/src/mcps/connection/mcp-connection.ts +1 -1
- package/src/mcps/framework-help.server.ts +6 -6
- package/src/mcps/knowledge-skills/code-review.server.ts +19 -34
- package/src/mcps/knowledge-skills/security-audit.server.ts +19 -38
- package/src/mcps/knowledge-skills/ui-ux-design.server.ts +2 -2
- package/src/mcps/lint.server.ts +2 -2
- package/src/mcps/mcp-client.ts +5 -5
- package/src/mcps/orchestrator/server.ts +2 -2
- package/src/mcps/researcher.server.ts +19 -34
- package/src/mcps/simulation/server-simulations.ts +3 -3
- package/src/skills/hermes-agent/SKILL.md +42 -42
- package/src/skills/storyteller/SKILL.md +1 -1
|
@@ -10,9 +10,9 @@ Falls back to CLI (npx 0xray) when bridge is unavailable.
|
|
|
10
10
|
return json.dumps({"error": str(e)})
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
# ── Tool:
|
|
13
|
+
# ── Tool: xray_validate ─────────────────────────────────────
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def xray_validate(args: dict, **kwargs) -> str:
|
|
16
16
|
"""Run pre-commit validation on files using the framework.
|
|
17
17
|
|
|
18
18
|
Uses bridge for real quality gate + processor pipeline.
|
|
@@ -41,7 +41,7 @@ def strray_validate(args: dict, **kwargs) -> str:
|
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
# Fallback to CLI
|
|
44
|
-
result = json.loads(
|
|
44
|
+
result = json.loads(_run_xray(["validate"], timeout=30))
|
|
45
45
|
if "error" in result:
|
|
46
46
|
return json.dumps(result)
|
|
47
47
|
|
|
@@ -54,10 +54,10 @@ def strray_validate(args: dict, **kwargs) -> str:
|
|
|
54
54
|
})
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
# ── Tool:
|
|
57
|
+
# ── Tool: xray_codex_check ──────────────────────────────────
|
|
58
58
|
|
|
59
|
-
def
|
|
60
|
-
"""Check code against
|
|
59
|
+
def xray_codex_check(args: dict, **kwargs) -> str:
|
|
60
|
+
"""Check code against Xray codex rules.
|
|
61
61
|
|
|
62
62
|
Uses bridge for real quality gate codex checks.
|
|
63
63
|
Falls back to CLI if bridge unavailable.
|
|
@@ -93,7 +93,7 @@ def strray_codex_check(args: dict, **kwargs) -> str:
|
|
|
93
93
|
"focus_areas": focus_areas or "all",
|
|
94
94
|
"code_length": len(code),
|
|
95
95
|
"note": "Bridge unavailable — basic analysis only. "
|
|
96
|
-
"Full codex validation available via MCP:
|
|
96
|
+
"Full codex validation available via MCP: mcp_xray_enforcer_codex_enforcement",
|
|
97
97
|
"via": "static",
|
|
98
98
|
})
|
|
99
99
|
|
|
@@ -109,7 +109,7 @@ def strray_codex_check(args: dict, **kwargs) -> str:
|
|
|
109
109
|
"via": "bridge",
|
|
110
110
|
})
|
|
111
111
|
|
|
112
|
-
result = json.loads(
|
|
112
|
+
result = json.loads(_run_xray(["health"], timeout=15))
|
|
113
113
|
if "error" in result:
|
|
114
114
|
return json.dumps(result)
|
|
115
115
|
|
|
@@ -121,10 +121,10 @@ def strray_codex_check(args: dict, **kwargs) -> str:
|
|
|
121
121
|
})
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
# ── Tool:
|
|
124
|
+
# ── Tool: xray_health ───────────────────────────────────────
|
|
125
125
|
|
|
126
|
-
def
|
|
127
|
-
"""Check
|
|
126
|
+
def xray_health(args: dict, **kwargs) -> str:
|
|
127
|
+
"""Check Xray framework health via bridge.
|
|
128
128
|
|
|
129
129
|
Returns framework status, loaded components, version.
|
|
130
130
|
"""
|
|
@@ -141,13 +141,13 @@ def strray_health(args: dict, **kwargs) -> str:
|
|
|
141
141
|
})
|
|
142
142
|
|
|
143
143
|
# Fallback to CLI
|
|
144
|
-
return
|
|
144
|
+
return _run_xray(["health"], timeout=15)
|
|
145
145
|
|
|
146
146
|
|
|
147
|
-
# ── Tool:
|
|
147
|
+
# ── Tool: xray_hooks ───────────────────────────────────────
|
|
148
148
|
|
|
149
|
-
def
|
|
150
|
-
"""Manage
|
|
149
|
+
def xray_hooks(args: dict, **kwargs) -> str:
|
|
150
|
+
"""Manage Xray git hooks.
|
|
151
151
|
|
|
152
152
|
Actions: install, uninstall, list, status
|
|
153
153
|
Uses bridge for hook management when available.
|
|
@@ -174,7 +174,7 @@ def strray_hooks(args: dict, **kwargs) -> str:
|
|
|
174
174
|
|
|
175
175
|
# Fallback: direct file-based hook management
|
|
176
176
|
git_hooks_dir = Path(_get_project_root()) / ".git" / "hooks"
|
|
177
|
-
|
|
177
|
+
xray_hooks_dir = Path(_get_project_root()) / "hooks"
|
|
178
178
|
|
|
179
179
|
if not git_hooks_dir.exists():
|
|
180
180
|
return json.dumps({"error": "Not a git repository", "via": "fallback"})
|
|
@@ -183,19 +183,19 @@ def strray_hooks(args: dict, **kwargs) -> str:
|
|
|
183
183
|
result = {"managed": [], "missing": [], "external": [], "stale": []}
|
|
184
184
|
for hook_name in hooks:
|
|
185
185
|
git_hook = git_hooks_dir / hook_name
|
|
186
|
-
|
|
186
|
+
xray_hook = xray_hooks_dir / hook_name
|
|
187
187
|
if not git_hook.exists():
|
|
188
188
|
result["missing"].append(hook_name)
|
|
189
189
|
else:
|
|
190
190
|
try:
|
|
191
191
|
content = git_hook.read_text()[:500]
|
|
192
|
-
if "
|
|
192
|
+
if "Xray" in content or "xray" in content or "strray" in content or "run-hook.js" in content:
|
|
193
193
|
result["managed"].append(hook_name)
|
|
194
194
|
else:
|
|
195
195
|
result["external"].append(hook_name)
|
|
196
196
|
except OSError:
|
|
197
197
|
result["external"].append(hook_name)
|
|
198
|
-
if not
|
|
198
|
+
if not xray_hook.exists():
|
|
199
199
|
result["stale"].append(hook_name)
|
|
200
200
|
return json.dumps({"status": "ok", "action": action, **result, "via": "fallback"})
|
|
201
201
|
|
|
@@ -203,7 +203,7 @@ def strray_hooks(args: dict, **kwargs) -> str:
|
|
|
203
203
|
installed = []
|
|
204
204
|
skipped = []
|
|
205
205
|
for hook_name in hooks:
|
|
206
|
-
src =
|
|
206
|
+
src = xray_hooks_dir / hook_name
|
|
207
207
|
dst = git_hooks_dir / hook_name
|
|
208
208
|
if not src.exists():
|
|
209
209
|
skipped.append(hook_name)
|
|
@@ -212,8 +212,8 @@ def strray_hooks(args: dict, **kwargs) -> str:
|
|
|
212
212
|
if dst.exists():
|
|
213
213
|
try:
|
|
214
214
|
content = dst.read_text()[:500]
|
|
215
|
-
if "
|
|
216
|
-
dst.rename(dst.with_suffix(".
|
|
215
|
+
if "Xray" not in content and "xray" not in content and "strray" not in content:
|
|
216
|
+
dst.rename(dst.with_suffix(".xray-backup"))
|
|
217
217
|
else:
|
|
218
218
|
dst.unlink()
|
|
219
219
|
except OSError:
|
|
@@ -233,13 +233,13 @@ def strray_hooks(args: dict, **kwargs) -> str:
|
|
|
233
233
|
restored = []
|
|
234
234
|
for hook_name in hooks:
|
|
235
235
|
dst = git_hooks_dir / hook_name
|
|
236
|
-
backup = dst.with_suffix(".
|
|
236
|
+
backup = dst.with_suffix(".xray-backup")
|
|
237
237
|
if not dst.exists():
|
|
238
238
|
continue
|
|
239
239
|
try:
|
|
240
240
|
content = dst.read_text()[:500]
|
|
241
|
-
|
|
242
|
-
if
|
|
241
|
+
is_xray = "Xray" in content or "xray" in content or "strray" in content or "run-hook.js" in content
|
|
242
|
+
if is_xray or dst.is_symlink():
|
|
243
243
|
dst.unlink()
|
|
244
244
|
if backup.exists():
|
|
245
245
|
shutil.move(str(backup), str(dst))
|
|
@@ -46,8 +46,8 @@ export class PluginRegistry extends EventEmitter {
|
|
|
46
46
|
reloadDebounce = new Map();
|
|
47
47
|
constructor(config = {}) {
|
|
48
48
|
super();
|
|
49
|
-
this.pluginsDir = config.pluginsDir || ".
|
|
50
|
-
this.configPath = config.configPath || ".
|
|
49
|
+
this.pluginsDir = config.pluginsDir || ".xray/plugins";
|
|
50
|
+
this.configPath = config.configPath || ".xray/config/plugin-config.json";
|
|
51
51
|
this.autoStart = config.autoStart ?? true;
|
|
52
52
|
this.enableMetrics = config.enableMetrics ?? true;
|
|
53
53
|
this.enableHotReload = config.enableHotReload ?? false;
|
|
@@ -16,20 +16,20 @@ import fs from 'fs';
|
|
|
16
16
|
/**
|
|
17
17
|
* Resolve the correct framework root and MCP servers path.
|
|
18
18
|
* Priority:
|
|
19
|
-
* 1.
|
|
20
|
-
* 2. The "
|
|
19
|
+
* 1. XRAY_DEV_PATH env var (explicit dev override)
|
|
20
|
+
* 2. The "xray" field in the nearest package.json that declares it (works in both source tree and installed package)
|
|
21
21
|
* 3. Safe fallback to node_modules/0xray/dist
|
|
22
22
|
*/
|
|
23
23
|
function resolveFrameworkPaths() {
|
|
24
24
|
// Highest priority: explicit environment override
|
|
25
|
-
if (process.env.
|
|
26
|
-
const devPath = process.env.
|
|
25
|
+
if (process.env.XRAY_DEV_PATH) {
|
|
26
|
+
const devPath = process.env.XRAY_DEV_PATH;
|
|
27
27
|
return {
|
|
28
28
|
frameworkRoot: devPath,
|
|
29
29
|
mcpServersPath: join(devPath, 'mcps'),
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
// Walk upward from this module to find the package that owns the "
|
|
32
|
+
// Walk upward from this module to find the package that owns the "xray" config
|
|
33
33
|
let currentDir = dirname(fileURLToPath(import.meta.url));
|
|
34
34
|
// Safety limit to avoid walking the entire filesystem
|
|
35
35
|
const MAX_LEVELS = 12;
|
|
@@ -38,10 +38,10 @@ function resolveFrameworkPaths() {
|
|
|
38
38
|
if (fs.existsSync(pkgPath)) {
|
|
39
39
|
try {
|
|
40
40
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
41
|
-
if (pkg.name === '0xray' && pkg.
|
|
42
|
-
const
|
|
41
|
+
if (pkg.name === '0xray' && pkg.xray) {
|
|
42
|
+
const xrayCfg = pkg.xray;
|
|
43
43
|
const frameworkRoot = currentDir;
|
|
44
|
-
const declaredMcp =
|
|
44
|
+
const declaredMcp = xrayCfg.mcpServersPath || (xrayCfg.dist ? join(xrayCfg.dist, 'mcps') : 'dist/mcps');
|
|
45
45
|
return {
|
|
46
46
|
frameworkRoot,
|
|
47
47
|
mcpServersPath: join(frameworkRoot, declaredMcp),
|
|
@@ -60,7 +60,7 @@ function resolveFrameworkPaths() {
|
|
|
60
60
|
// Final fallback (should almost never be reached)
|
|
61
61
|
const fallback = 'node_modules/0xray/dist';
|
|
62
62
|
frameworkLogger.log('server-config-registry', 'using-fallback-path', 'warning', {
|
|
63
|
-
reason: 'Could not locate
|
|
63
|
+
reason: 'Could not locate xray package.json with "xray" field',
|
|
64
64
|
fallback,
|
|
65
65
|
});
|
|
66
66
|
return {
|
|
@@ -323,7 +323,7 @@ export class ServerConfigRegistry {
|
|
|
323
323
|
/**
|
|
324
324
|
* Create a dynamic configuration for an unknown server
|
|
325
325
|
* Uses the knowledge-skills directory as default location.
|
|
326
|
-
* Now respects the "
|
|
326
|
+
* Now respects the "xray" field declared in package.json.
|
|
327
327
|
*/
|
|
328
328
|
createDynamicConfig(serverName) {
|
|
329
329
|
// Validate serverName against path traversal attacks
|
|
@@ -21,7 +21,7 @@ class FrameworkHelpServer {
|
|
|
21
21
|
return {
|
|
22
22
|
tools: [
|
|
23
23
|
{
|
|
24
|
-
name: "
|
|
24
|
+
name: "xray_get_capabilities",
|
|
25
25
|
description: "Get comprehensive list of all 0xRay framework capabilities, commands, and available tools",
|
|
26
26
|
inputSchema: {
|
|
27
27
|
type: "object",
|
|
@@ -43,7 +43,7 @@ class FrameworkHelpServer {
|
|
|
43
43
|
},
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
|
-
name: "
|
|
46
|
+
name: "xray_get_commands",
|
|
47
47
|
description: "Get list of available 0xRay commands and their usage",
|
|
48
48
|
inputSchema: {
|
|
49
49
|
type: "object",
|
|
@@ -63,7 +63,7 @@ class FrameworkHelpServer {
|
|
|
63
63
|
},
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
|
-
name: "
|
|
66
|
+
name: "xray_explain_capability",
|
|
67
67
|
description: "Get detailed explanation of a specific 0xRay capability",
|
|
68
68
|
inputSchema: {
|
|
69
69
|
type: "object",
|
|
@@ -84,11 +84,11 @@ class FrameworkHelpServer {
|
|
|
84
84
|
const { name, arguments: args } = request.params;
|
|
85
85
|
try {
|
|
86
86
|
switch (name) {
|
|
87
|
-
case "
|
|
87
|
+
case "xray_get_capabilities":
|
|
88
88
|
return this.handleGetCapabilities(args);
|
|
89
|
-
case "
|
|
89
|
+
case "xray_get_commands":
|
|
90
90
|
return this.handleGetCommands(args);
|
|
91
|
-
case "
|
|
91
|
+
case "xray_explain_capability":
|
|
92
92
|
return this.handleExplainCapability(args);
|
|
93
93
|
default:
|
|
94
94
|
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
@@ -10,6 +10,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextpro
|
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
import * as path from "path";
|
|
12
12
|
import { createGracefulShutdown } from "../../utils/shutdown-handler.js";
|
|
13
|
+
import { tryLLMGovernance } from "../../governance/llm-governance-provider.js";
|
|
13
14
|
class XrayCodeReviewServer {
|
|
14
15
|
server;
|
|
15
16
|
constructor() {
|
|
@@ -339,48 +340,22 @@ class XrayCodeReviewServer {
|
|
|
339
340
|
*/
|
|
340
341
|
async analyzeProposal(args) {
|
|
341
342
|
const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args;
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
decision = "approve";
|
|
353
|
-
confidence = 0.90;
|
|
354
|
-
reasoning = "PSD2 SCA implementation must balance security with user experience. Code should use well-audited MFA libraries, avoid rolling custom authentication, and include comprehensive test coverage for all authentication flows.";
|
|
355
|
-
}
|
|
356
|
-
else if (text.includes("gdpr") || text.includes("right to erasure") || text.includes("data protection")) {
|
|
357
|
-
decision = "approve";
|
|
358
|
-
confidence = 0.92;
|
|
359
|
-
reasoning = "GDPR erasure pipelines require careful code review: cascading deletes must be transactional, audit logs must be preserved, and the 30-day SLA demands observability and monitoring integration.";
|
|
360
|
-
}
|
|
361
|
-
else if (text.includes("extract method")) {
|
|
362
|
-
decision = "approve";
|
|
363
|
-
confidence = 0.93;
|
|
364
|
-
reasoning = "Extract Method is a well-established refactoring pattern that improves readability and reduces cognitive load when applied consistently.";
|
|
365
|
-
}
|
|
366
|
-
else if (text.includes("test coverage")) {
|
|
367
|
-
decision = "approve";
|
|
368
|
-
confidence = 0.90;
|
|
369
|
-
reasoning = "Expanding automated test coverage generally improves long-term code health and reduces regression risk.";
|
|
370
|
-
}
|
|
371
|
-
else if (text.includes("increase timeout") && text.includes("flaky")) {
|
|
372
|
-
decision = "reject";
|
|
373
|
-
confidence = 0.72;
|
|
374
|
-
reasoning = "Repeatedly increasing timeouts to mask flaky tests is an anti-pattern that hides underlying race conditions or timing issues.";
|
|
375
|
-
}
|
|
376
|
-
if (proposalType === "fix" && text.includes("timeout")) {
|
|
377
|
-
confidence = Math.max(0.68, confidence - 0.08);
|
|
343
|
+
const vote = await tryLLMGovernance("code-review", proposalTitle, proposalDescription, evidence, proposalType);
|
|
344
|
+
if (!vote) {
|
|
345
|
+
return {
|
|
346
|
+
content: [
|
|
347
|
+
{
|
|
348
|
+
type: "text",
|
|
349
|
+
text: "DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: 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",
|
|
350
|
+
},
|
|
351
|
+
],
|
|
352
|
+
};
|
|
378
353
|
}
|
|
379
354
|
return {
|
|
380
355
|
content: [
|
|
381
356
|
{
|
|
382
357
|
type: "text",
|
|
383
|
-
text: `DECISION: ${decision}\nCONFIDENCE: ${confidence.toFixed(2)}\nREASONING: ${reasoning}`,
|
|
358
|
+
text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
|
|
384
359
|
},
|
|
385
360
|
],
|
|
386
361
|
};
|
|
@@ -10,6 +10,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextpro
|
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
import * as path from "path";
|
|
12
12
|
import { createGracefulShutdown } from "../../utils/shutdown-handler.js";
|
|
13
|
+
import { tryLLMGovernance } from "../../governance/llm-governance-provider.js";
|
|
13
14
|
class XraySecurityAuditServer {
|
|
14
15
|
server;
|
|
15
16
|
constructor() {
|
|
@@ -777,53 +778,22 @@ class XraySecurityAuditServer {
|
|
|
777
778
|
*/
|
|
778
779
|
async analyzeProposal(args) {
|
|
779
780
|
const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args;
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
decision = "approve";
|
|
791
|
-
confidence = 0.93;
|
|
792
|
-
reasoning = "PSD2 SCA implementation is a mandatory security control for payment services. Multi-factor authentication with dynamic linking reduces unauthorized payment risk and satisfies EBA regulatory technical standards.";
|
|
793
|
-
}
|
|
794
|
-
else if (text.includes("gdpr") || text.includes("right to erasure") || text.includes("data protection")) {
|
|
795
|
-
decision = "approve";
|
|
796
|
-
confidence = 0.94;
|
|
797
|
-
reasoning = "GDPR compliance controls are foundational to data security posture. Automated data erasure pipelines reduce data breach exposure windows and satisfy supervisory authority inspection requirements.";
|
|
798
|
-
}
|
|
799
|
-
else if (text.includes("beneficial ownership") || text.includes("ubo") || text.includes("pep screening")) {
|
|
800
|
-
decision = "approve";
|
|
801
|
-
confidence = 0.87;
|
|
802
|
-
reasoning = "Beneficial ownership transparency and PEP screening are critical AML controls. Verifying ultimate beneficial owners reduces money laundering risk through corporate account structuring.";
|
|
803
|
-
}
|
|
804
|
-
else if (text.includes("extract method")) {
|
|
805
|
-
decision = "approve";
|
|
806
|
-
confidence = 0.88;
|
|
807
|
-
reasoning = "Extract Method refactoring improves security posture by reducing attack surface in large monolithic files and enabling better isolation of sensitive logic.";
|
|
808
|
-
}
|
|
809
|
-
else if (text.includes("test coverage")) {
|
|
810
|
-
decision = "approve";
|
|
811
|
-
confidence = 0.91;
|
|
812
|
-
reasoning = "Expanding test coverage is one of the highest-ROI security controls available — more tests surface regressions and boundary condition vulnerabilities earlier.";
|
|
813
|
-
}
|
|
814
|
-
else if (text.includes("increase timeout") && text.includes("flaky")) {
|
|
815
|
-
decision = "reject";
|
|
816
|
-
confidence = 0.75;
|
|
817
|
-
reasoning = "Repeatedly increasing timeouts to hide flaky tests can mask timing attacks, race conditions, and resource exhaustion vulnerabilities. Root cause remediation is required.";
|
|
818
|
-
}
|
|
819
|
-
if (proposalType === "fix" && text.includes("timeout")) {
|
|
820
|
-
confidence = Math.max(0.65, confidence - 0.10);
|
|
781
|
+
const vote = await tryLLMGovernance("security-audit", proposalTitle, proposalDescription, evidence, proposalType);
|
|
782
|
+
if (!vote) {
|
|
783
|
+
return {
|
|
784
|
+
content: [
|
|
785
|
+
{
|
|
786
|
+
type: "text",
|
|
787
|
+
text: "DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: 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",
|
|
788
|
+
},
|
|
789
|
+
],
|
|
790
|
+
};
|
|
821
791
|
}
|
|
822
792
|
return {
|
|
823
793
|
content: [
|
|
824
794
|
{
|
|
825
795
|
type: "text",
|
|
826
|
-
text: `DECISION: ${decision}\nCONFIDENCE: ${confidence.toFixed(2)}\nREASONING: ${reasoning}`,
|
|
796
|
+
text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
|
|
827
797
|
},
|
|
828
798
|
],
|
|
829
799
|
};
|
|
@@ -1475,7 +1475,7 @@ Available: ${Object.keys(system.components).length} component types
|
|
|
1475
1475
|
async run() {
|
|
1476
1476
|
const transport = new StdioServerTransport();
|
|
1477
1477
|
await this.server.connect(transport);
|
|
1478
|
-
await frameworkLogger.log("ui-ux-design.server", "-
|
|
1478
|
+
await frameworkLogger.log("ui-ux-design.server", "-xray-ui-ux-design-mcp-server-running-", "info", { message: "xray UI/UX Design MCP Server running..." });
|
|
1479
1479
|
const cleanup = async (signal) => {
|
|
1480
1480
|
await frameworkLogger.log("ui-ux-design.server", "-received-signal-shutting-down-gracefully-", "info", { message: `Received ${signal}, shutting down gracefully...` });
|
|
1481
1481
|
// Set a timeout to force exit if graceful shutdown fails
|
|
@@ -1488,7 +1488,7 @@ Available: ${Object.keys(system.components).length} component types
|
|
|
1488
1488
|
await this.server.close();
|
|
1489
1489
|
}
|
|
1490
1490
|
clearTimeout(timeout);
|
|
1491
|
-
await frameworkLogger.log("ui-ux-design.server", "-
|
|
1491
|
+
await frameworkLogger.log("ui-ux-design.server", "-xray-mcp-server-shut-down-gracefully-", "info", { message: "xray MCP Server shut down gracefully" });
|
|
1492
1492
|
process.exit(0);
|
|
1493
1493
|
}
|
|
1494
1494
|
catch (error) {
|
package/dist/mcps/lint.server.js
CHANGED
|
@@ -20,7 +20,7 @@ class XrayLintServer {
|
|
|
20
20
|
},
|
|
21
21
|
});
|
|
22
22
|
this.setupToolHandlers();
|
|
23
|
-
void frameworkLogger.log("lint.server", "-
|
|
23
|
+
void frameworkLogger.log("lint.server", "-xray-lint-mcp-server-initialized-", "info", { message: "0xRay Lint MCP Server initialized" });
|
|
24
24
|
}
|
|
25
25
|
setupToolHandlers() {
|
|
26
26
|
// List available tools
|
|
@@ -370,7 +370,7 @@ ${checkResults.details.map((d) => `• ${d}`).join("\n")}
|
|
|
370
370
|
async run() {
|
|
371
371
|
const transport = new StdioServerTransport();
|
|
372
372
|
await this.server.connect(transport);
|
|
373
|
-
await frameworkLogger.log("lint.server", "-
|
|
373
|
+
await frameworkLogger.log("lint.server", "-xray-lint-mcp-server-started-", "info", { message: "0xRay Lint MCP Server started" });
|
|
374
374
|
}
|
|
375
375
|
}
|
|
376
376
|
// Start the server if run directly
|
package/dist/mcps/mcp-client.js
CHANGED
|
@@ -98,7 +98,7 @@ export class MCPClient extends EventEmitter {
|
|
|
98
98
|
* Pure MCP mode — simulation and generic fallbacks are disabled.
|
|
99
99
|
*/
|
|
100
100
|
get isPureMcpMode() {
|
|
101
|
-
return process.env.
|
|
101
|
+
return process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true';
|
|
102
102
|
}
|
|
103
103
|
/**
|
|
104
104
|
* Register default simulation implementations
|
|
@@ -267,17 +267,17 @@ export class MCPClient extends EventEmitter {
|
|
|
267
267
|
],
|
|
268
268
|
'framework-help': [
|
|
269
269
|
{
|
|
270
|
-
name: '
|
|
270
|
+
name: 'xray_get_capabilities',
|
|
271
271
|
description: 'Get 0xRay framework capabilities',
|
|
272
272
|
inputSchema: { type: 'object', properties: {} },
|
|
273
273
|
},
|
|
274
274
|
{
|
|
275
|
-
name: '
|
|
275
|
+
name: 'xray_get_commands',
|
|
276
276
|
description: 'Get available 0xRay commands',
|
|
277
277
|
inputSchema: { type: 'object', properties: {} },
|
|
278
278
|
},
|
|
279
279
|
{
|
|
280
|
-
name: '
|
|
280
|
+
name: 'xray_explain_capability',
|
|
281
281
|
description: 'Explain a specific capability',
|
|
282
282
|
inputSchema: {
|
|
283
283
|
type: 'object',
|
|
@@ -375,7 +375,7 @@ export class MCPClient extends EventEmitter {
|
|
|
375
375
|
// === LAST RESORT: Generic fallback (disabled in pure mode) ===
|
|
376
376
|
if (this.isPureMcpMode) {
|
|
377
377
|
throw new Error(`[PURE MCP] No real response for ${serverName}/${toolName}. ` +
|
|
378
|
-
`All fallbacks are disabled when
|
|
378
|
+
`All fallbacks are disabled when XRAY_FORCE_MCP_GOVERNANCE=true.`);
|
|
379
379
|
}
|
|
380
380
|
const fallbackResult = {
|
|
381
381
|
content: [
|
|
@@ -8,7 +8,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
|
8
8
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
9
9
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
10
10
|
import { frameworkLogger } from '../../core/framework-logger.js';
|
|
11
|
-
import {
|
|
11
|
+
import { XrayStateManager } from '../../state/state-manager.js';
|
|
12
12
|
import { MultiAgentOrchestrationCoordinator } from '../../orchestrator/multi-agent-orchestration-coordinator.js';
|
|
13
13
|
import { TaskHandler } from './handlers/task-handler.js';
|
|
14
14
|
import { ComplexityHandler } from './handlers/complexity-handler.js';
|
|
@@ -29,7 +29,7 @@ export class OrchestratorServer {
|
|
|
29
29
|
coordinator;
|
|
30
30
|
constructor() {
|
|
31
31
|
// Initialize actual coordinator
|
|
32
|
-
const stateManager = new
|
|
32
|
+
const stateManager = new XrayStateManager();
|
|
33
33
|
this.coordinator = new MultiAgentOrchestrationCoordinator(stateManager);
|
|
34
34
|
// Initialize handlers
|
|
35
35
|
this.taskHandler = new TaskHandler();
|
|
@@ -13,6 +13,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextpro
|
|
|
13
13
|
import * as fs from "fs";
|
|
14
14
|
import * as path from "path";
|
|
15
15
|
import { frameworkLogger } from "../core/framework-logger.js";
|
|
16
|
+
import { tryLLMGovernance } from "../governance/llm-governance-provider.js";
|
|
16
17
|
class XrayLibrarianServer {
|
|
17
18
|
server;
|
|
18
19
|
constructor() {
|
|
@@ -400,48 +401,22 @@ class XrayLibrarianServer {
|
|
|
400
401
|
*/
|
|
401
402
|
async analyzeProposal(args) {
|
|
402
403
|
const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args || {};
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
decision = "approve";
|
|
414
|
-
confidence = 0.88;
|
|
415
|
-
reasoning = "PSD2 SCA patterns are well-established in the corpus across multiple implementations. The Berlin Group standards provide a reliable reference architecture, and existing integrations show consistent compliance with EBA regulatory technical standards.";
|
|
416
|
-
}
|
|
417
|
-
else if (text.includes("gdpr") || text.includes("right to erasure") || text.includes("data protection")) {
|
|
418
|
-
decision = "approve";
|
|
419
|
-
confidence = 0.91;
|
|
420
|
-
reasoning = "GDPR data erasure pipeline patterns appear in approximately 35% of enterprise codebases in the corpus. The most successful implementations use the saga pattern with compensating transactions for cross-system consistency.";
|
|
421
|
-
}
|
|
422
|
-
else if (text.includes("extract method")) {
|
|
423
|
-
decision = "approve";
|
|
424
|
-
confidence = 0.89;
|
|
425
|
-
reasoning = "The Extract Method pattern is a core refactoring technique that improves modularity; the corpus shows consistent positive outcomes when applied to repeated logic across many sessions.";
|
|
426
|
-
}
|
|
427
|
-
else if (text.includes("test coverage")) {
|
|
428
|
-
decision = "approve";
|
|
429
|
-
confidence = 0.94;
|
|
430
|
-
reasoning = "Test coverage expansion is one of the highest-leverage improvements for long-term project health, directly reducing regression incidents across 100+ sessions in the historical data.";
|
|
431
|
-
}
|
|
432
|
-
else if (text.includes("technical debt")) {
|
|
433
|
-
decision = "approve";
|
|
434
|
-
confidence = 0.85;
|
|
435
|
-
reasoning = "Systematic technical debt reduction is strongly supported by historical data showing fewer critical violations and faster feature delivery in low-debt modules.";
|
|
436
|
-
}
|
|
437
|
-
if (proposalType === "fix" && !text.includes("pattern") && !text.includes("recurring")) {
|
|
438
|
-
confidence = Math.max(0.68, confidence - 0.10);
|
|
404
|
+
const vote = await tryLLMGovernance("researcher", proposalTitle || "", proposalDescription || "", evidence || [], proposalType || "");
|
|
405
|
+
if (!vote) {
|
|
406
|
+
return {
|
|
407
|
+
content: [
|
|
408
|
+
{
|
|
409
|
+
type: "text",
|
|
410
|
+
text: "DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: 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",
|
|
411
|
+
},
|
|
412
|
+
],
|
|
413
|
+
};
|
|
439
414
|
}
|
|
440
415
|
return {
|
|
441
416
|
content: [
|
|
442
417
|
{
|
|
443
418
|
type: "text",
|
|
444
|
-
text: `DECISION: ${decision}\nCONFIDENCE: ${confidence.toFixed(2)}\nREASONING: ${reasoning}`,
|
|
419
|
+
text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
|
|
445
420
|
},
|
|
446
421
|
],
|
|
447
422
|
};
|
|
@@ -73,7 +73,7 @@ export const researcherSimulations = {
|
|
|
73
73
|
* Framework Help server simulations
|
|
74
74
|
*/
|
|
75
75
|
export const frameworkHelpSimulations = {
|
|
76
|
-
|
|
76
|
+
xray_get_capabilities: () => ({
|
|
77
77
|
content: [
|
|
78
78
|
{
|
|
79
79
|
type: 'text',
|
|
@@ -104,7 +104,7 @@ export const frameworkHelpSimulations = {
|
|
|
104
104
|
},
|
|
105
105
|
],
|
|
106
106
|
}),
|
|
107
|
-
|
|
107
|
+
xray_get_commands: () => ({
|
|
108
108
|
content: [
|
|
109
109
|
{
|
|
110
110
|
type: 'text',
|
|
@@ -131,7 +131,7 @@ framework-reporting-system - Generate comprehensive framework reports
|
|
|
131
131
|
},
|
|
132
132
|
],
|
|
133
133
|
}),
|
|
134
|
-
|
|
134
|
+
xray_explain_capability: () => ({
|
|
135
135
|
content: [
|
|
136
136
|
{
|
|
137
137
|
type: 'text',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Enhanced Multi-Agent Orchestration with Clickable Monitoring
|
|
3
3
|
* Integrates subagent spawning visibility and lifecycle management
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { XrayStateManager } from "../state/state-manager.js";
|
|
6
6
|
import { frameworkLogger } from "../core/framework-logger.js";
|
|
7
7
|
import { ComplexityAnalyzer, } from "../delegation/complexity-analyzer.js";
|
|
8
8
|
import { createAgentDelegator, } from "../delegation/agent-delegator.js";
|
|
@@ -17,7 +17,7 @@ export class EnhancedMultiAgentOrchestrator {
|
|
|
17
17
|
executionContext;
|
|
18
18
|
cleanupTimer = null;
|
|
19
19
|
constructor(stateManager, isMainOrchestrator = false) {
|
|
20
|
-
this.stateManager = stateManager || new
|
|
20
|
+
this.stateManager = stateManager || new XrayStateManager();
|
|
21
21
|
this.complexityAnalyzer = new ComplexityAnalyzer();
|
|
22
22
|
this.agentDelegator = createAgentDelegator(this.stateManager, strRayConfigLoader);
|
|
23
23
|
this.state = {
|