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
|
@@ -13,7 +13,7 @@ import { frameworkLogger } from "../core/framework-logger.js";
|
|
|
13
13
|
import { resolveCodexPath } from "./config-paths.js";
|
|
14
14
|
// Dynamic imports for cross-environment compatibility
|
|
15
15
|
let extractCodexMetadata;
|
|
16
|
-
let
|
|
16
|
+
let XrayContextLoaderClass;
|
|
17
17
|
let importsInitialized = false;
|
|
18
18
|
async function initializeImports() {
|
|
19
19
|
if (importsInitialized)
|
|
@@ -22,13 +22,13 @@ async function initializeImports() {
|
|
|
22
22
|
const codexParser = await import("../utils/codex-parser.js");
|
|
23
23
|
const contextLoaderModule = await import("./context-loader.js");
|
|
24
24
|
extractCodexMetadata = codexParser.extractCodexMetadata;
|
|
25
|
-
|
|
25
|
+
XrayContextLoaderClass = contextLoaderModule.XrayContextLoader;
|
|
26
26
|
}
|
|
27
27
|
catch {
|
|
28
28
|
const codexParser = await import("../utils/codex-parser");
|
|
29
29
|
const contextLoaderModule = await import("./context-loader");
|
|
30
30
|
extractCodexMetadata = codexParser.extractCodexMetadata;
|
|
31
|
-
|
|
31
|
+
XrayContextLoaderClass = contextLoaderModule.XrayContextLoader;
|
|
32
32
|
}
|
|
33
33
|
importsInitialized = true;
|
|
34
34
|
}
|
|
@@ -38,7 +38,7 @@ async function initializeImports() {
|
|
|
38
38
|
const codexCache = new Map();
|
|
39
39
|
/**
|
|
40
40
|
* Codex file locations resolved through the standard priority chain.
|
|
41
|
-
* Uses config-paths.ts resolver so STRRAY_CONFIG_DIR and .
|
|
41
|
+
* Uses config-paths.ts resolver so STRRAY_CONFIG_DIR and .xray/ work.
|
|
42
42
|
*/
|
|
43
43
|
function getCodexFileLocations(projectRoot) {
|
|
44
44
|
const root = projectRoot || process.cwd();
|
|
@@ -193,7 +193,7 @@ export function createXrayCodexInjectorHook() {
|
|
|
193
193
|
await frameworkLogger.log("codex-injector", "codex context loaded for validation", "success", { jobId, contextCount: codexContexts.length });
|
|
194
194
|
// Use the initialized context loader
|
|
195
195
|
await initializeImports();
|
|
196
|
-
const ContextLoaderClass =
|
|
196
|
+
const ContextLoaderClass = XrayContextLoaderClass;
|
|
197
197
|
const contextLoader = new ContextLoaderClass();
|
|
198
198
|
const loadResult = await contextLoader.loadCodexContext(sessionId);
|
|
199
199
|
if (!loadResult.success || !loadResult.context) {
|
|
@@ -10,7 +10,7 @@ import * as fs from "fs";
|
|
|
10
10
|
import * as path from "path";
|
|
11
11
|
import { frameworkLogger } from "./framework-logger.js";
|
|
12
12
|
import { getConfigDir, resolveConfigPath } from "./config-paths.js";
|
|
13
|
-
export class
|
|
13
|
+
export class XrayConfigLoader {
|
|
14
14
|
configPath;
|
|
15
15
|
cachedConfig = null;
|
|
16
16
|
cacheExpiry = 30000; // 30 seconds
|
|
@@ -145,4 +145,6 @@ export class StringRayConfigLoader {
|
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
// Export singleton instance
|
|
148
|
-
export const
|
|
148
|
+
export const xrayConfigLoader = new XrayConfigLoader();
|
|
149
|
+
export { XrayConfigLoader as StringRayConfigLoader };
|
|
150
|
+
export { xrayConfigLoader as strRayConfigLoader };
|
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Resolution order (per file type):
|
|
9
9
|
* 1. STRRAY_CONFIG_DIR/<relative_path> (if env var set)
|
|
10
|
-
* 2. .
|
|
11
|
-
* 3. .opencode/
|
|
10
|
+
* 2. .xray/<relative_path> (preferred lightweight root)
|
|
11
|
+
* 3. .opencode/xray/<relative_path> (legacy OpenCode root)
|
|
12
12
|
* 4. null (callers fall back to built-in defaults)
|
|
13
13
|
*
|
|
14
14
|
* For state/data directories, uses:
|
|
15
15
|
* 1. STRRAY_CONFIG_DIR/state (if env var set)
|
|
16
|
-
* 2. .
|
|
16
|
+
* 2. .xray/state
|
|
17
17
|
* 3. .opencode/state (legacy)
|
|
18
|
-
* 4. .
|
|
18
|
+
* 4. .xray/state (default — always writable)
|
|
19
19
|
*/
|
|
20
20
|
import { existsSync } from "fs";
|
|
21
21
|
import { join, resolve } from "path";
|
|
@@ -40,8 +40,8 @@ export function getConfigDir(projectRoot) {
|
|
|
40
40
|
const resolved = resolve(root, envDir);
|
|
41
41
|
candidates.push({ dir: resolved, source: "env" });
|
|
42
42
|
}
|
|
43
|
-
candidates.push({ dir: join(root, ".
|
|
44
|
-
candidates.push({ dir: join(root, ".opencode", "
|
|
43
|
+
candidates.push({ dir: join(root, ".xray"), source: "dot-xray" });
|
|
44
|
+
candidates.push({ dir: join(root, ".opencode", "xray"), source: "dot-opencode" });
|
|
45
45
|
// Return the first that exists, or the highest-priority default
|
|
46
46
|
for (const c of candidates) {
|
|
47
47
|
if (existsSync(c.dir)) {
|
|
@@ -49,7 +49,7 @@ export function getConfigDir(projectRoot) {
|
|
|
49
49
|
return c.dir;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
// Nothing exists — use highest priority default (env > .
|
|
52
|
+
// Nothing exists — use highest priority default (env > .xray > .opencode)
|
|
53
53
|
const defaultDir = candidates[0];
|
|
54
54
|
_resolvedConfigDirs.set(root, defaultDir.dir);
|
|
55
55
|
return defaultDir.dir;
|
|
@@ -68,8 +68,8 @@ export function resolveConfigPath(relativePath, projectRoot) {
|
|
|
68
68
|
if (envDir) {
|
|
69
69
|
candidates.push(resolve(root, envDir, relativePath));
|
|
70
70
|
}
|
|
71
|
-
candidates.push(join(root, ".
|
|
72
|
-
candidates.push(join(root, ".opencode", "
|
|
71
|
+
candidates.push(join(root, ".xray", relativePath));
|
|
72
|
+
candidates.push(join(root, ".opencode", "xray", relativePath));
|
|
73
73
|
for (const candidate of candidates) {
|
|
74
74
|
if (existsSync(candidate)) {
|
|
75
75
|
return candidate;
|
|
@@ -90,7 +90,7 @@ export function resolveStateDir(projectRoot) {
|
|
|
90
90
|
if (envDir) {
|
|
91
91
|
candidates.push(join(root, envDir, "state"));
|
|
92
92
|
}
|
|
93
|
-
candidates.push(join(root, ".
|
|
93
|
+
candidates.push(join(root, ".xray", "state"));
|
|
94
94
|
candidates.push(join(root, ".opencode", "state"));
|
|
95
95
|
for (const candidate of candidates) {
|
|
96
96
|
if (existsSync(candidate)) {
|
|
@@ -117,8 +117,8 @@ export function resolveProfilesDir(projectRoot) {
|
|
|
117
117
|
if (envDir) {
|
|
118
118
|
candidates.push(join(root, envDir, "profiles"));
|
|
119
119
|
}
|
|
120
|
-
candidates.push(join(root, ".
|
|
121
|
-
candidates.push(join(root, ".opencode", "
|
|
120
|
+
candidates.push(join(root, ".xray", "profiles"));
|
|
121
|
+
candidates.push(join(root, ".opencode", "xray", "profiles"));
|
|
122
122
|
for (const candidate of candidates) {
|
|
123
123
|
if (existsSync(candidate)) {
|
|
124
124
|
return candidate;
|
|
@@ -137,9 +137,9 @@ export function resolveCodexPath(projectRoot) {
|
|
|
137
137
|
if (envDir) {
|
|
138
138
|
candidates.push(join(root, envDir, "codex.json"));
|
|
139
139
|
}
|
|
140
|
-
candidates.push(join(root, ".
|
|
140
|
+
candidates.push(join(root, ".xray", "codex.json"));
|
|
141
141
|
candidates.push(join(root, "xray", "codex.json"));
|
|
142
|
-
candidates.push(join(root, ".opencode", "
|
|
142
|
+
candidates.push(join(root, ".opencode", "xray", "codex.json"));
|
|
143
143
|
// Additional fallback locations (for standalone usage)
|
|
144
144
|
candidates.push(join(root, "codex.json"));
|
|
145
145
|
candidates.push(join(root, "src", "codex.json"));
|
|
@@ -22,7 +22,7 @@ function isValidMatch(match, index) {
|
|
|
22
22
|
*
|
|
23
23
|
* Loads and parses the Universal Development Codex v1.2.0 from codex.json
|
|
24
24
|
*/
|
|
25
|
-
export class
|
|
25
|
+
export class XrayContextLoader {
|
|
26
26
|
static instance;
|
|
27
27
|
cachedContext = null;
|
|
28
28
|
codexFilePaths = [];
|
|
@@ -33,10 +33,10 @@ export class StringRayContextLoader {
|
|
|
33
33
|
* Get singleton instance
|
|
34
34
|
*/
|
|
35
35
|
static getInstance() {
|
|
36
|
-
if (!
|
|
37
|
-
|
|
36
|
+
if (!XrayContextLoader.instance) {
|
|
37
|
+
XrayContextLoader.instance = new XrayContextLoader();
|
|
38
38
|
}
|
|
39
|
-
return
|
|
39
|
+
return XrayContextLoader.instance;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Load codex context
|
|
@@ -266,4 +266,7 @@ export class StringRayContextLoader {
|
|
|
266
266
|
/**
|
|
267
267
|
* Export singleton instance
|
|
268
268
|
*/
|
|
269
|
-
export const
|
|
269
|
+
export const xrayContextLoader = XrayContextLoader.getInstance();
|
|
270
|
+
// Backward compat aliases
|
|
271
|
+
export { XrayContextLoader as StringRayContextLoader };
|
|
272
|
+
export { xrayContextLoader as strRayContextLoader };
|
package/dist/core/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { KernelOrchestrator } from "./orchestrator.js";
|
|
2
|
-
export { defaultStringRayConfig } from "./xray-activation.js"; // consumer runtime compat
|
|
2
|
+
export { defaultXrayConfig, defaultXrayConfig as defaultStringRayConfig } from "./xray-activation.js"; // consumer runtime compat
|
|
3
3
|
// Decoupled config path resolution (Layer 1)
|
|
4
4
|
export { getConfigDir, resolveConfigPath, resolveStateDir, resolveProfilesDir, resolveCodexPath, resolveLogDir, resetConfigDirCache, STRRAY_CONFIG_DIR_ENV, } from "./config-paths.js";
|
|
5
5
|
// Standalone codex formatter (Layer 2)
|
|
@@ -267,7 +267,7 @@ export class KernelOrchestrator {
|
|
|
267
267
|
`B) Use a single orchestrator for all dependent tasks\n` +
|
|
268
268
|
`C) Remove the dependency if it's not needed\n\n` +
|
|
269
269
|
`Example of correct usage:\n` +
|
|
270
|
-
` const orch = new
|
|
270
|
+
` const orch = new XrayOrchestrator();\n` +
|
|
271
271
|
` await orch.executeComplexTask("test", [\n` +
|
|
272
272
|
` { id: "task-1" },\n` +
|
|
273
273
|
` { id: "task-2", dependencies: ["task-1"] } // ✅ Same orchestrator\n` +
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @version 1.0.0
|
|
8
8
|
* @since 2026-03-03
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { XrayContextLoader } from "./context-loader.js";
|
|
11
11
|
import { validateContext, preventSystemPromptBloat } from "./context-validator.js";
|
|
12
12
|
import fs from "fs";
|
|
13
13
|
import path from "path";
|
|
@@ -140,7 +140,7 @@ export async function generateLeanSystemPrompt(config = {}) {
|
|
|
140
140
|
let finalPrompt = systemPrompt;
|
|
141
141
|
if (showCodexContext && enableTokenOptimization) {
|
|
142
142
|
try {
|
|
143
|
-
const contextLoader =
|
|
143
|
+
const contextLoader = XrayContextLoader.getInstance();
|
|
144
144
|
const loadResult = await contextLoader.loadCodexContext(process.cwd());
|
|
145
145
|
if (loadResult.success && loadResult.context) {
|
|
146
146
|
const codexSummary = generateCodexSummary(loadResult.context, maxTokenBudget);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Consumer runtime compat shim from prior
|
|
2
|
+
* Consumer runtime compat shim from prior 0xRay releases (1-line min per Scope Rule; primary xray paths + XRAY_||STRRAY_ env + .xray fallbacks).
|
|
3
3
|
*/
|
|
4
4
|
import { frameworkLogger } from "../core/framework-logger.js";
|
|
5
5
|
import { ensureCriticalComponents } from "../architect/architectural-integrity.js";
|
|
6
6
|
import { validateRegistryConsistency } from "../agents/registry.js";
|
|
7
|
-
export const
|
|
7
|
+
export const defaultXrayConfig = {
|
|
8
8
|
enableOrchestrator: true,
|
|
9
9
|
enableBootOrchestrator: true,
|
|
10
10
|
enableStateManagement: true,
|
|
@@ -13,15 +13,15 @@ export const defaultStringRayConfig = {
|
|
|
13
13
|
enableProcessors: true,
|
|
14
14
|
enablePostProcessor: true,
|
|
15
15
|
};
|
|
16
|
-
export async function
|
|
16
|
+
export async function activateXrayFramework(config = {}) {
|
|
17
17
|
const jobId = `activation-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
18
|
-
const activationConfig = { ...
|
|
18
|
+
const activationConfig = { ...defaultXrayConfig, ...config };
|
|
19
19
|
// Banner display moved to init.sh execution in plugin
|
|
20
20
|
// Framework activation proceeds quietly
|
|
21
|
-
frameworkLogger.log("
|
|
21
|
+
frameworkLogger.log("xray-activation", "beginning xray framework activation", "info", { jobId, ...activationConfig });
|
|
22
22
|
const registryValidation = validateRegistryConsistency();
|
|
23
23
|
if (!registryValidation.valid) {
|
|
24
|
-
frameworkLogger.log("
|
|
24
|
+
frameworkLogger.log("xray-activation", "registry-validation-failed", "warning", { errors: registryValidation.errors });
|
|
25
25
|
}
|
|
26
26
|
try {
|
|
27
27
|
if (activationConfig.enableCodexInjection) {
|
|
@@ -48,87 +48,89 @@ export async function activateStringRayFramework(config = {}) {
|
|
|
48
48
|
// Ensure architectural integrity - critical components must always be active
|
|
49
49
|
await ensureCriticalComponents();
|
|
50
50
|
// Loading display moved to init.sh for dramatic line-by-line presentation
|
|
51
|
-
frameworkLogger.log("
|
|
51
|
+
frameworkLogger.log("xray-activation", "xray framework activation completed successfully", "success", { jobId });
|
|
52
52
|
}
|
|
53
53
|
catch (error) {
|
|
54
|
-
await frameworkLogger.log("
|
|
54
|
+
await frameworkLogger.log("xray-activation", "framework-activation-failed", "error", { jobId, error: String(error) });
|
|
55
55
|
throw error;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
async function activateCodexInjection(jobId) {
|
|
59
|
-
frameworkLogger.log("
|
|
59
|
+
frameworkLogger.log("xray-activation", "activating codex injection", "info", { jobId });
|
|
60
60
|
const { createXrayCodexInjectorHook } = await import("./codex-injector.js");
|
|
61
61
|
const hook = createXrayCodexInjectorHook();
|
|
62
|
-
globalThis.
|
|
63
|
-
globalThis.
|
|
64
|
-
frameworkLogger.log("
|
|
62
|
+
globalThis.xrayHooks = globalThis.xrayHooks || [];
|
|
63
|
+
globalThis.xrayHooks.push(hook);
|
|
64
|
+
frameworkLogger.log("xray-activation", "codex injection activated", "success", { jobId, hookName: hook.name });
|
|
65
65
|
}
|
|
66
66
|
async function activateHooks(jobId) {
|
|
67
67
|
try {
|
|
68
|
-
frameworkLogger.log("
|
|
68
|
+
frameworkLogger.log("xray-activation", "activating xray hooks", "info", { jobId });
|
|
69
69
|
// Create and register the Codex injector hook
|
|
70
70
|
const { createXrayCodexInjectorHook } = await import("./codex-injector");
|
|
71
71
|
const hook = createXrayCodexInjectorHook();
|
|
72
72
|
// Store hook globally for OpenCode to pick up
|
|
73
|
-
globalThis.
|
|
74
|
-
globalThis.
|
|
75
|
-
frameworkLogger.log("
|
|
73
|
+
globalThis.xrayHooks = globalThis.xrayHooks || [];
|
|
74
|
+
globalThis.xrayHooks.push(hook);
|
|
75
|
+
frameworkLogger.log("xray-activation", "xray hooks activated", "success", {
|
|
76
76
|
jobId,
|
|
77
77
|
hookName: hook.name,
|
|
78
|
-
hooksRegistered: globalThis.
|
|
78
|
+
hooksRegistered: globalThis.xrayHooks.length
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
catch (error) {
|
|
82
|
-
await frameworkLogger.log("
|
|
82
|
+
await frameworkLogger.log("xray-activation", "hooks activation failed", "error", { jobId, error: String(error) });
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
async function activateBootOrchestrator(jobId) {
|
|
86
|
-
frameworkLogger.log("
|
|
86
|
+
frameworkLogger.log("xray-activation", "activating boot orchestrator", "info", { jobId });
|
|
87
87
|
const { bootOrchestrator } = await import("./boot-orchestrator");
|
|
88
88
|
await bootOrchestrator.executeBootSequence();
|
|
89
|
-
frameworkLogger.log("
|
|
89
|
+
frameworkLogger.log("xray-activation", "boot orchestrator activated", "success", { jobId });
|
|
90
90
|
}
|
|
91
91
|
async function activateStateManagement(jobId) {
|
|
92
|
-
frameworkLogger.log("
|
|
93
|
-
const {
|
|
94
|
-
const stateManager = new
|
|
92
|
+
frameworkLogger.log("xray-activation", "activating state management", "info", { jobId });
|
|
93
|
+
const { XrayStateManager } = await import("../state/state-manager");
|
|
94
|
+
const stateManager = new XrayStateManager();
|
|
95
95
|
// Store the state manager instance globally for framework use
|
|
96
|
-
globalThis.
|
|
97
|
-
frameworkLogger.log("
|
|
96
|
+
globalThis.xrayStateManager = stateManager;
|
|
97
|
+
frameworkLogger.log("xray-activation", "state management activated", "success", { jobId });
|
|
98
98
|
}
|
|
99
99
|
async function activateOrchestrator(jobId) {
|
|
100
|
-
frameworkLogger.log("
|
|
100
|
+
frameworkLogger.log("xray-activation", "activating xray orchestrator", "info", { jobId });
|
|
101
101
|
const { strRayOrchestrator } = await import("./orchestrator");
|
|
102
102
|
// Also activate the multi-agent orchestration coordinator
|
|
103
103
|
const { multiAgentOrchestrationCoordinator } = await import("../orchestrator/multi-agent-orchestration-coordinator");
|
|
104
|
-
frameworkLogger.log("
|
|
104
|
+
frameworkLogger.log("xray-activation", "xray orchestrator and multi-agent coordination activated", "success", { jobId });
|
|
105
105
|
}
|
|
106
106
|
async function activateProcessors(jobId) {
|
|
107
|
-
frameworkLogger.log("
|
|
107
|
+
frameworkLogger.log("xray-activation", "activating processor pipeline", "info", { jobId });
|
|
108
108
|
const { ProcessorManager } = await import("../processors/processor-manager");
|
|
109
|
-
const {
|
|
110
|
-
const stateManager = new
|
|
109
|
+
const { XrayStateManager } = await import("../state/state-manager");
|
|
110
|
+
const stateManager = new XrayStateManager();
|
|
111
111
|
const processorManager = new ProcessorManager(stateManager);
|
|
112
112
|
// Store the processor manager instance globally for framework use
|
|
113
|
-
globalThis.
|
|
114
|
-
frameworkLogger.log("
|
|
113
|
+
globalThis.xrayProcessorManager = processorManager;
|
|
114
|
+
frameworkLogger.log("xray-activation", "processor pipeline activated", "success", { jobId });
|
|
115
115
|
}
|
|
116
116
|
async function activatePostProcessor(jobId) {
|
|
117
|
-
frameworkLogger.log("
|
|
117
|
+
frameworkLogger.log("xray-activation", "activating post-processor system", "info", { jobId });
|
|
118
118
|
const { PostProcessor } = await import("../postprocessor/PostProcessor");
|
|
119
119
|
// Get existing state manager (should be initialized by boot orchestrator)
|
|
120
|
-
const stateManager = globalThis.
|
|
120
|
+
const stateManager = globalThis.xrayStateManager;
|
|
121
121
|
if (!stateManager) {
|
|
122
122
|
throw new Error("State manager not initialized - boot orchestrator must run first");
|
|
123
123
|
}
|
|
124
124
|
const postProcessor = new PostProcessor(stateManager, null, {});
|
|
125
|
-
globalThis.
|
|
126
|
-
frameworkLogger.log("
|
|
125
|
+
globalThis.xrayPostProcessor = postProcessor;
|
|
126
|
+
frameworkLogger.log("xray-activation", "post-processor system activated", "success", { jobId });
|
|
127
127
|
const { pathResolver } = await import("../utils/path-resolver.js");
|
|
128
|
-
globalThis.
|
|
129
|
-
frameworkLogger.log("
|
|
128
|
+
globalThis.xrayPathResolver = pathResolver;
|
|
129
|
+
frameworkLogger.log("xray-activation", "path resolver activated", "success", { jobId });
|
|
130
130
|
const { CodexInjector } = await import("./codex-injector.js");
|
|
131
131
|
const codexInjector = new CodexInjector();
|
|
132
|
-
globalThis.
|
|
133
|
-
frameworkLogger.log("
|
|
132
|
+
globalThis.xrayCodexInjector = codexInjector;
|
|
133
|
+
frameworkLogger.log("xray-activation", "codex injector activated", "success", { jobId });
|
|
134
134
|
}
|
|
135
|
+
export { defaultXrayConfig as defaultStringRayConfig };
|
|
136
|
+
export { activateXrayFramework as activateStringRayFramework };
|
|
@@ -45,9 +45,9 @@ export class AgentDelegator {
|
|
|
45
45
|
*/
|
|
46
46
|
loadRoutingMappings() {
|
|
47
47
|
const candidates = [
|
|
48
|
-
path.resolve(process.cwd(), ".
|
|
48
|
+
path.resolve(process.cwd(), ".xray/routing-mappings.json"),
|
|
49
49
|
path.resolve(process.cwd(), "xray/routing-mappings.json"),
|
|
50
|
-
path.resolve(process.cwd(), ".opencode/
|
|
50
|
+
path.resolve(process.cwd(), ".opencode/xray/routing-mappings.json"),
|
|
51
51
|
path.resolve(process.cwd(), "routing-mappings.json"),
|
|
52
52
|
];
|
|
53
53
|
for (const p of candidates) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { ruleEnforcer, } from "./rule-enforcer.js";
|
|
6
6
|
import { frameworkLogger } from "../core/framework-logger.js";
|
|
7
7
|
import { AgentDelegator } from "../delegation/agent-delegator.js";
|
|
8
|
-
import {
|
|
8
|
+
import { XrayStateManager } from "../state/state-manager.js";
|
|
9
9
|
import { strRayConfigLoader } from "../core/config-loader.js";
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
import * as path from "path";
|
|
@@ -325,7 +325,7 @@ async function executeReleaseWorkflow(operation, context, jobId, routing) {
|
|
|
325
325
|
async function delegateToAgent(agentName, operation, context, jobId) {
|
|
326
326
|
try {
|
|
327
327
|
// Create a minimal state manager and config loader for the delegator
|
|
328
|
-
const stateManager = new
|
|
328
|
+
const stateManager = new XrayStateManager();
|
|
329
329
|
// Create the delegator
|
|
330
330
|
const delegator = new AgentDelegator(stateManager, strRayConfigLoader);
|
|
331
331
|
// Build task description for the delegated agent
|
|
@@ -30,13 +30,13 @@ export class CodexLoader extends BaseLoader {
|
|
|
30
30
|
name = "codex";
|
|
31
31
|
/**
|
|
32
32
|
* Path to the codex.json file.
|
|
33
|
-
* Uses the standard config-paths resolver which checks .
|
|
33
|
+
* Uses the standard config-paths resolver which checks .xray/, .opencode/xray/, etc.
|
|
34
34
|
*/
|
|
35
35
|
get codexPath() {
|
|
36
36
|
const candidates = resolveCodexPath();
|
|
37
37
|
const found = candidates.find((p) => existsSync(p));
|
|
38
38
|
// Fallback to primary path even if not found yet
|
|
39
|
-
return found ?? candidates[0] ?? this.resolvePath(".opencode/
|
|
39
|
+
return found ?? candidates[0] ?? this.resolvePath(".opencode/xray/codex.json");
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Check if codex.json exists.
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { frameworkLogger } from "../core/framework-logger.js";
|
|
5
|
+
const XAI_ENDPOINT = "https://api.x.ai/v1/chat/completions";
|
|
6
|
+
const XAI_MODEL = "grok-4.3";
|
|
7
|
+
const ROLE_PROMPTS = {
|
|
8
|
+
"code-review": `You are a senior code reviewer on a governance committee for a software project. Analyze the following proposal from a code quality, maintainability, readability, and engineering best practices perspective.
|
|
9
|
+
|
|
10
|
+
Consider:
|
|
11
|
+
- Does the proposal improve or degrade code quality?
|
|
12
|
+
- Does it follow established design patterns?
|
|
13
|
+
- Does it introduce technical debt?
|
|
14
|
+
- Are there potential regressions or edge cases?
|
|
15
|
+
|
|
16
|
+
Respond with a structured vote in exactly this format:
|
|
17
|
+
DECISION: approve|reject|abstain
|
|
18
|
+
CONFIDENCE: <0.0-1.0>
|
|
19
|
+
REASONING: <2-4 sentence analysis of the proposal's code quality implications>`,
|
|
20
|
+
"security-audit": `You are a senior security engineer on a governance committee for a software project. Analyze the following proposal from a security, threat modeling, and compliance perspective.
|
|
21
|
+
|
|
22
|
+
Consider:
|
|
23
|
+
- Does the proposal introduce new attack surface?
|
|
24
|
+
- Does it handle authentication, authorization, and data protection properly?
|
|
25
|
+
- Are there compliance implications (GDPR, SOC2, PCI-DSS, etc.)?
|
|
26
|
+
- Does it follow security best practices (input validation, least privilege, defense in depth)?
|
|
27
|
+
|
|
28
|
+
Respond with a structured vote in exactly this format:
|
|
29
|
+
DECISION: approve|reject|abstain
|
|
30
|
+
CONFIDENCE: <0.0-1.0>
|
|
31
|
+
REASONING: <2-4 sentence analysis of the proposal's security implications>`,
|
|
32
|
+
"researcher": `You are a senior architect and researcher on a governance committee for a software project. Analyze the following proposal from a codebase-wide architectural and historical perspective.
|
|
33
|
+
|
|
34
|
+
Consider:
|
|
35
|
+
- Does the proposal align with the project's observed architecture patterns?
|
|
36
|
+
- Does it integrate well with existing systems and data flows?
|
|
37
|
+
- Does it address recurring problems observed in the project history?
|
|
38
|
+
- What is the broader impact on the codebase ecosystem?
|
|
39
|
+
|
|
40
|
+
Respond with a structured vote in exactly this format:
|
|
41
|
+
DECISION: approve|reject|abstain
|
|
42
|
+
CONFIDENCE: <0.0-1.0>
|
|
43
|
+
REASONING: <2-4 sentence analysis of the proposal's broader project impact>`,
|
|
44
|
+
};
|
|
45
|
+
function readHermesOAuthToken() {
|
|
46
|
+
try {
|
|
47
|
+
const authPath = join(homedir(), ".hermes", "auth.json");
|
|
48
|
+
if (!existsSync(authPath))
|
|
49
|
+
return null;
|
|
50
|
+
const raw = readFileSync(authPath, "utf-8");
|
|
51
|
+
const data = JSON.parse(raw);
|
|
52
|
+
let entry;
|
|
53
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
54
|
+
entry = data["xai-oauth"];
|
|
55
|
+
if (!entry?.access_token && data.access_token) {
|
|
56
|
+
entry = data;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!entry?.access_token && Array.isArray(data)) {
|
|
60
|
+
entry = data.find((e) => e.provider === "xai-oauth" || !!e.access_token);
|
|
61
|
+
}
|
|
62
|
+
if (!entry?.access_token)
|
|
63
|
+
return null;
|
|
64
|
+
if (entry.expires_at && Date.now() / 1000 > entry.expires_at) {
|
|
65
|
+
frameworkLogger.log("llm-governance", "hermes-token-expired", "warning", { expiresAt: entry.expires_at });
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return entry.access_token;
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
frameworkLogger.log("llm-governance", "hermes-auth-read-error", "warning", { error: String(err) });
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function getConfig() {
|
|
76
|
+
const directEndpoint = process.env.XRAY_LLM_ENDPOINT ||
|
|
77
|
+
process.env.XRAY_GOVERNANCE_LLM_ENDPOINT ||
|
|
78
|
+
"";
|
|
79
|
+
const directApiKey = process.env.XRAY_LLM_API_KEY ||
|
|
80
|
+
process.env.XRAY_GOVERNANCE_LLM_API_KEY ||
|
|
81
|
+
"";
|
|
82
|
+
const directModel = process.env.XRAY_LLM_MODEL ||
|
|
83
|
+
process.env.XRAY_GOVERNANCE_LLM_MODEL ||
|
|
84
|
+
"gpt-4o";
|
|
85
|
+
const directEnabled = process.env.XRAY_GOVERNANCE_LLM_ENABLED === "true" ||
|
|
86
|
+
process.env.XRAY_LLM_ENABLED === "true";
|
|
87
|
+
if (directEnabled && directEndpoint && directApiKey) {
|
|
88
|
+
return { endpoint: directEndpoint, apiKey: directApiKey, model: directModel };
|
|
89
|
+
}
|
|
90
|
+
const hermesToken = readHermesOAuthToken();
|
|
91
|
+
if (hermesToken) {
|
|
92
|
+
frameworkLogger.log("llm-governance", "using-hermes-oauth", "info", { provider: "xai-oauth", endpoint: XAI_ENDPOINT, model: XAI_MODEL });
|
|
93
|
+
return { endpoint: XAI_ENDPOINT, apiKey: hermesToken, model: XAI_MODEL };
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
function parseVote(text) {
|
|
98
|
+
const decisionMatch = text.match(/DECISION:\s*(approve|reject|abstain)/i);
|
|
99
|
+
const confidenceMatch = text.match(/CONFIDENCE:\s*([0-9.]+)/i);
|
|
100
|
+
const reasoningMatch = text.match(/REASONING:\s*(.+)/is);
|
|
101
|
+
if (!decisionMatch || !decisionMatch[1])
|
|
102
|
+
return null;
|
|
103
|
+
const rawConfidence = confidenceMatch?.[1];
|
|
104
|
+
const confidence = rawConfidence ? parseFloat(rawConfidence) : 0.5;
|
|
105
|
+
return {
|
|
106
|
+
decision: decisionMatch[1].toLowerCase(),
|
|
107
|
+
confidence: isNaN(confidence) ? 0.5 : Math.min(1, Math.max(0, confidence)),
|
|
108
|
+
reasoning: reasoningMatch?.[1]?.trim() || "No reasoning provided",
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export async function tryLLMGovernance(role, proposalTitle, proposalDescription, evidence, proposalType) {
|
|
112
|
+
const config = getConfig();
|
|
113
|
+
if (!config) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const systemPrompt = ROLE_PROMPTS[role];
|
|
117
|
+
const userMessage = `## Proposal
|
|
118
|
+
|
|
119
|
+
**Title:** ${proposalTitle}
|
|
120
|
+
|
|
121
|
+
**Description:** ${proposalDescription}
|
|
122
|
+
|
|
123
|
+
**Type:** ${proposalType}
|
|
124
|
+
|
|
125
|
+
${evidence.length > 0 ? `**Supporting Evidence:**\n${evidence.map((e, i) => `${i + 1}. ${e}`).join("\n")}` : ""}
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
Please provide your structured vote.`;
|
|
130
|
+
try {
|
|
131
|
+
const response = await fetch(config.endpoint, {
|
|
132
|
+
method: "POST",
|
|
133
|
+
headers: {
|
|
134
|
+
"Content-Type": "application/json",
|
|
135
|
+
Authorization: `Bearer ${config.apiKey}`,
|
|
136
|
+
},
|
|
137
|
+
body: JSON.stringify({
|
|
138
|
+
model: config.model,
|
|
139
|
+
messages: [
|
|
140
|
+
{ role: "system", content: systemPrompt },
|
|
141
|
+
{ role: "user", content: userMessage },
|
|
142
|
+
],
|
|
143
|
+
temperature: 0.3,
|
|
144
|
+
max_tokens: 500,
|
|
145
|
+
}),
|
|
146
|
+
});
|
|
147
|
+
if (!response.ok) {
|
|
148
|
+
frameworkLogger.log("llm-governance", "api-call", "error", {
|
|
149
|
+
status: response.status,
|
|
150
|
+
statusText: response.statusText,
|
|
151
|
+
role,
|
|
152
|
+
});
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
const data = (await response.json());
|
|
156
|
+
const choices = data?.choices;
|
|
157
|
+
const message = choices?.[0]?.message;
|
|
158
|
+
const content = message?.content;
|
|
159
|
+
if (!content) {
|
|
160
|
+
frameworkLogger.log("llm-governance", "parse", "warning", {
|
|
161
|
+
issue: "missing content in response",
|
|
162
|
+
role,
|
|
163
|
+
});
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
const vote = parseVote(content);
|
|
167
|
+
if (!vote) {
|
|
168
|
+
frameworkLogger.log("llm-governance", "parse", "warning", {
|
|
169
|
+
issue: "unparseable response",
|
|
170
|
+
snippet: content.slice(0, 200),
|
|
171
|
+
role,
|
|
172
|
+
});
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
frameworkLogger.log("llm-governance", "vote", "success", {
|
|
176
|
+
role,
|
|
177
|
+
decision: vote.decision,
|
|
178
|
+
confidence: vote.confidence,
|
|
179
|
+
});
|
|
180
|
+
return vote;
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
frameworkLogger.log("llm-governance", "error", "error", {
|
|
184
|
+
error: String(error),
|
|
185
|
+
role,
|
|
186
|
+
});
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
export function checkHermesOAuthStatus() {
|
|
191
|
+
const config = getConfig();
|
|
192
|
+
if (!config) {
|
|
193
|
+
const hermesPath = join(homedir(), ".hermes", "auth.json");
|
|
194
|
+
if (existsSync(hermesPath)) {
|
|
195
|
+
return {
|
|
196
|
+
configured: false,
|
|
197
|
+
error: "Hermes auth file found but no valid xai-oauth token. Run: hermes auth add xai-oauth --no-browser",
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
configured: false,
|
|
202
|
+
error: "No Hermes auth file found (~/.hermes/auth.json). Install Hermes and run: hermes auth add xai-oauth --no-browser",
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
configured: true,
|
|
207
|
+
endpoint: XAI_ENDPOINT,
|
|
208
|
+
model: XAI_MODEL,
|
|
209
|
+
};
|
|
210
|
+
}
|