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.
Files changed (95) hide show
  1. package/.opencode/hooks/post-commit +1 -1
  2. package/.opencode/init.sh +4 -4
  3. package/AGENTS.md +2 -2
  4. package/dist/AGENTS.md +2 -2
  5. package/dist/CHANGELOG.md +9 -0
  6. package/dist/benchmark/performance-benchmark.js +4 -2
  7. package/dist/cli/commands/hermes-install.js +4 -4
  8. package/dist/cli/commands/mcp-install.js +1 -1
  9. package/dist/cli/commands/openclaw-install.js +1 -1
  10. package/dist/cli/commands/plugin-commands.js +2 -2
  11. package/dist/cli/commands/publish-agent.js +5 -5
  12. package/dist/cli/commands/skill-install.js +1 -1
  13. package/dist/cli/commands/status.js +3 -3
  14. package/dist/cli/commands/storyteller.js +1 -1
  15. package/dist/cli/index.js +6 -6
  16. package/dist/cli/server.js +4 -4
  17. package/dist/core/boot-orchestrator.js +24 -24
  18. package/dist/core/bridge.mjs +22 -22
  19. package/dist/core/codex-formatter.js +2 -2
  20. package/dist/core/codex-injector.js +5 -5
  21. package/dist/core/config-loader.js +4 -2
  22. package/dist/core/config-paths.js +14 -14
  23. package/dist/core/context-loader.js +8 -5
  24. package/dist/core/index.js +1 -1
  25. package/dist/core/orchestrator.js +1 -1
  26. package/dist/core/system-prompt-generator.js +2 -2
  27. package/dist/core/xray-activation.js +42 -40
  28. package/dist/delegation/agent-delegator.js +2 -2
  29. package/dist/enforcement/enforcer-tools.js +2 -2
  30. package/dist/enforcement/loaders/codex-loader.js +2 -2
  31. package/dist/governance/llm-governance-provider.js +210 -0
  32. package/dist/index.js +8 -6
  33. package/dist/inference/deploy-verifier.js +1 -1
  34. package/dist/inference/inference-cycle.js +7 -7
  35. package/dist/integrations/hermes-agent/__init__.py +72 -72
  36. package/dist/integrations/hermes-agent/after-install.md +14 -14
  37. package/dist/integrations/hermes-agent/bridge.mjs +24 -24
  38. package/dist/integrations/hermes-agent/plugin.yaml +5 -5
  39. package/dist/integrations/hermes-agent/schemas.py +12 -12
  40. package/dist/integrations/hermes-agent/test_plugin.py +117 -117
  41. package/dist/integrations/hermes-agent/tools.py +25 -25
  42. package/dist/integrations/plugins/plugin-registry.js +2 -2
  43. package/dist/mcps/config/server-config-registry.js +10 -10
  44. package/dist/mcps/connection/mcp-connection.js +1 -1
  45. package/dist/mcps/framework-help.server.js +6 -6
  46. package/dist/mcps/knowledge-skills/code-review.server.js +12 -37
  47. package/dist/mcps/knowledge-skills/security-audit.server.js +12 -42
  48. package/dist/mcps/knowledge-skills/ui-ux-design.server.js +2 -2
  49. package/dist/mcps/lint.server.js +2 -2
  50. package/dist/mcps/mcp-client.js +5 -5
  51. package/dist/mcps/orchestrator/server.js +2 -2
  52. package/dist/mcps/researcher.server.js +12 -37
  53. package/dist/mcps/simulation/server-simulations.js +3 -3
  54. package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +2 -2
  55. package/dist/orchestrator/intelligent-commit-batcher.js +3 -3
  56. package/dist/orchestrator/multi-agent-orchestration-coordinator.js +9 -9
  57. package/dist/orchestrator/orchestrator.js +10 -8
  58. package/dist/orchestrator/universal-registry-bridge.js +3 -3
  59. package/dist/plugin/xray-codex-injection.js +21 -21
  60. package/dist/postprocessor/PostProcessor.js +5 -5
  61. package/dist/postprocessor/services/RegressionAnalysisService.js +2 -2
  62. package/dist/postprocessor/triggers/GitHookTrigger.js +14 -14
  63. package/dist/processors/implementations/agents-md-validation-processor.js +2 -2
  64. package/dist/processors/implementations/inference-improvement-processor.js +1 -1
  65. package/dist/processors/implementations/log-protection-processor.js +2 -2
  66. package/dist/processors/implementations/publish-preflight-processor.js +3 -3
  67. package/dist/processors/implementations/regression-testing-processor.js +2 -2
  68. package/dist/processors/implementations/session-summary-processor.js +1 -1
  69. package/dist/processors/implementations/storytelling-trigger-processor.js +1 -1
  70. package/dist/reporting/report-formatter.js +1 -1
  71. package/dist/scripts/activate-kernel-pipeline.js +2 -2
  72. package/dist/services/inference-tuner.js +2 -2
  73. package/dist/skills/hermes-agent/SKILL.md +42 -42
  74. package/dist/skills/storyteller/SKILL.md +1 -1
  75. package/dist/state/index.js +2 -1
  76. package/dist/state/state-manager.js +3 -3
  77. package/dist/utils/token-manager.js +1 -1
  78. package/dist/validation/estimation-validator.js +1 -1
  79. package/package.json +1 -1
  80. package/scripts/node/pre-publish-guard.js +13 -9
  81. package/scripts/node/universal-version-manager.js +2 -2
  82. package/src/mcps/config/__tests__/server-config-registry.test.ts +12 -12
  83. package/src/mcps/config/server-config-registry.ts +10 -10
  84. package/src/mcps/connection/mcp-connection.ts +1 -1
  85. package/src/mcps/framework-help.server.ts +6 -6
  86. package/src/mcps/knowledge-skills/code-review.server.ts +19 -34
  87. package/src/mcps/knowledge-skills/security-audit.server.ts +19 -38
  88. package/src/mcps/knowledge-skills/ui-ux-design.server.ts +2 -2
  89. package/src/mcps/lint.server.ts +2 -2
  90. package/src/mcps/mcp-client.ts +5 -5
  91. package/src/mcps/orchestrator/server.ts +2 -2
  92. package/src/mcps/researcher.server.ts +19 -34
  93. package/src/mcps/simulation/server-simulations.ts +3 -3
  94. package/src/skills/hermes-agent/SKILL.md +42 -42
  95. package/src/skills/storyteller/SKILL.md +1 -1
package/dist/index.js CHANGED
@@ -4,17 +4,17 @@
4
4
  * This is the main entry point for the 0xRay framework.
5
5
  * It exports the core initialization function and key components.
6
6
  */
7
- export { StringRayOrchestrator } from "./orchestrator/orchestrator.js";
8
- export { StringRayStateManager } from "./state/index.js";
7
+ export { XrayOrchestrator, StringRayOrchestrator } from "./orchestrator/orchestrator.js";
8
+ export { XrayStateManager, StringRayStateManager } from "./state/index.js";
9
9
  export { AgentDelegator } from "./delegation/index.js";
10
10
  export { frameworkLogger } from "./core/framework-logger.js";
11
11
  export { BUILTIN_CODEX } from "./core/codex-formatter.js";
12
- import { defaultStringRayConfig } from "./core/index.js";
13
- export { defaultStringRayConfig };
12
+ import { defaultXrayConfig } from "./core/index.js";
13
+ export { defaultXrayConfig, defaultXrayConfig as defaultStringRayConfig };
14
14
  export { OpenClawIntegration, initializeOpenClawIntegration, getOpenClawIntegration, shutdownOpenClawIntegration } from "./integrations/openclaw/index.js";
15
15
  // Main initialization function
16
- export function initializeStringRay(config = {}) {
17
- const mergedConfig = { ...defaultStringRayConfig, ...config };
16
+ export function initializeXray(config = {}) {
17
+ const mergedConfig = { ...defaultXrayConfig, ...config };
18
18
  // Return a standardized initialization result
19
19
  return {
20
20
  success: true,
@@ -22,3 +22,5 @@ export function initializeStringRay(config = {}) {
22
22
  message: "0xRay framework initialized successfully",
23
23
  };
24
24
  }
25
+ // Backward compat alias
26
+ export { initializeXray as initializeStringRay };
@@ -43,7 +43,7 @@ export class DeployVerifier {
43
43
  if (!packCheck.passed) {
44
44
  return this.result(false, version, tarballPath, installDir, checks, startTime);
45
45
  }
46
- installDir = fs.mkdtempSync(path.join(os.tmpdir(), "strray-deploy-verify-"));
46
+ installDir = fs.mkdtempSync(path.join(os.tmpdir(), "xray-deploy-verify-"));
47
47
  const installCheck = this.runCheck("npm-install-fresh", () => {
48
48
  this.exec(`npm install ${tarballPath} --no-save`, installDir, 60000);
49
49
  return "Fresh install succeeded";
@@ -3,7 +3,7 @@ import * as path from "path";
3
3
  import { shouldTriggerCycle, accumulateCorpus } from "./inference-accumulator.js";
4
4
  import { DeployVerifier } from "./deploy-verifier.js";
5
5
  import { VotingCoordinator } from "../delegation/voting-coordinator.js";
6
- import { StringRayStateManager } from "../state/state-manager.js";
6
+ import { XrayStateManager } from "../state/state-manager.js";
7
7
  import { frameworkLogger } from "../core/framework-logger.js";
8
8
  import { getGovernanceIntegration } from "../integrations/governance/index.js";
9
9
  import { featuresConfigLoader } from "../core/features-config.js";
@@ -50,7 +50,7 @@ export class InferenceCycle {
50
50
  constructor(projectRoot, agentInvoker, options) {
51
51
  this.projectRoot = projectRoot || process.cwd();
52
52
  this.inferenceDir = path.join(this.projectRoot, "docs", "inference");
53
- this.stateDir = path.join(this.projectRoot, ".strray", "inference");
53
+ this.stateDir = path.join(this.projectRoot, ".xray", "inference");
54
54
  this.agentInvoker = agentInvoker ?? null;
55
55
  this.options = options ?? {};
56
56
  }
@@ -353,7 +353,7 @@ export class InferenceCycle {
353
353
  ``,
354
354
  `1. Read the relevant source files`,
355
355
  `2. Add the missing guard, validation, or edge case handling`,
356
- `3. If this is a codex rule, add the term to .opencode/strray/codex.json`,
356
+ `3. If this is a codex rule, add the term to .opencode/xray/codex.json`,
357
357
  `4. Make minimal, surgical changes`,
358
358
  ].join("\n");
359
359
  try {
@@ -922,7 +922,7 @@ Respond with EXACTLY one of:
922
922
  fs.mkdirSync(this.stateDir, { recursive: true });
923
923
  }
924
924
  const stateFile = path.join(this.stateDir, "governance-state.json");
925
- const stateManager = new StringRayStateManager();
925
+ const stateManager = new XrayStateManager();
926
926
  if (fs.existsSync(stateFile)) {
927
927
  try {
928
928
  const data = JSON.parse(fs.readFileSync(stateFile, "utf-8"));
@@ -975,10 +975,10 @@ Respond with EXACTLY one of:
975
975
  return texts.join("\n").trim();
976
976
  }
977
977
  resolveOpencodeRoot() {
978
- // Use the provider-agnostic config path resolver (prefers .strray/, falls back to .opencode/strray/)
978
+ // Use the provider-agnostic config path resolver (prefers .xray/, falls back to .opencode/xray/)
979
979
  const configDir = getConfigDir(this.projectRoot);
980
- // If we resolved to a .strray or custom dir, use its parent as the "root"
981
- if (configDir.includes(".strray") || configDir.includes("strray")) {
980
+ // If we resolved to a .xray or custom dir, use its parent as the "root"
981
+ if (configDir.includes(".xray") || configDir.includes("xray")) {
982
982
  return path.dirname(configDir);
983
983
  }
984
984
  // Legacy fallback
@@ -1,4 +1,4 @@
1
- """StringRay Hermes Plugin — full framework pipeline integration.
1
+ """Xray Hermes Plugin — full framework pipeline integration.
2
2
 
3
3
  Mirrors the OpenCode xray-codex-injection.ts behavior:
4
4
  1. Captures ALL tool calls and logs to disk
@@ -29,24 +29,24 @@ except ImportError:
29
29
  schemas = importlib.import_module("schemas")
30
30
  tools = importlib.import_module("tools")
31
31
 
32
- logger = logging.getLogger("strray-hermes")
32
+ logger = logging.getLogger("xray-hermes")
33
33
 
34
34
  # ── Paths ─────────────────────────────────────────────────────
35
35
 
36
36
  PLUGIN_DIR = Path(__file__).resolve().parent
37
37
  BRIDGE_PATH = PLUGIN_DIR / "bridge.mjs"
38
38
 
39
- # Project root: find the StringRay project directory
39
+ # Project root: find the Xray project directory
40
40
  # The plugin lives at ~/.hermes/plugins/ which is NOT inside any project tree,
41
41
  # so walking up from PLUGIN_DIR will never find the project. Instead:
42
- # 1. Check STRRAY_PROJECT_ROOT env var (explicit override)
43
- # 2. Walk up from cwd looking for node_modules/0xray or strray-ai (consumer install)
42
+ # 1. Check XRAY_PROJECT_ROOT env var (explicit override)
43
+ # 2. Walk up from cwd looking for node_modules/0xray (consumer install)
44
44
  ...
45
45
  # node_modules/0xray — consumer install marker
46
- if (d / "node_modules" / "0xray" / "package.json").exists() or (d / "node_modules" / "strray-ai" / "package.json").exists():
46
+ if (d / "node_modules" / "0xray" / "package.json").exists() or (d / "node_modules" / "0xray" / "package.json").exists():
47
47
  return d
48
- # .opencode/strray — dev repo marker
49
- if (d / ".opencode" / "strray" / "features.json").exists():
48
+ # .opencode/xray — dev repo marker
49
+ if (d / ".opencode" / "xray" / "features.json").exists():
50
50
  return d
51
51
  # package.json but not home dir
52
52
  if d != home and (d / "package.json").exists():
@@ -79,20 +79,20 @@ _TOOL_AGENT_MAP = {
79
79
  "delegate_task": ("orchestrator", "delegation"),
80
80
  }
81
81
 
82
- # Tools where StringRay has a better alternative
82
+ # Tools where Xray has a better alternative
83
83
  # terminal: only nudge when the command looks lint/security/search related
84
- _BETTER_WITH_STRRAY = {
85
- "search_files": "Use mcp_strray_researcher_search_codebase for code pattern searches",
84
+ _BETTER_WITH_XRAY = {
85
+ "search_files": "Use mcp_xray_researcher_search_codebase for code pattern searches",
86
86
  }
87
87
 
88
88
  # Patterns that suggest the terminal command should use an MCP tool instead
89
89
  _TERMINAL_NUDGE_PATTERNS = {
90
- "grep": "Use mcp_strray_researcher_search_codebase instead of grep",
91
- "rg ": "Use mcp_strray_researcher_search_codebase instead of ripgrep",
92
- "eslint": "Use mcp_strray_lint_lint instead of raw eslint",
93
- "npx eslint": "Use mcp_strray_lint_lint instead of raw eslint",
94
- "npm audit": "Use mcp_strray_security_scan_security_scan instead of npm audit",
95
- "yarn audit": "Use mcp_strray_security_scan_security_scan instead of yarn audit",
90
+ "grep": "Use mcp_xray_researcher_search_codebase instead of grep",
91
+ "rg ": "Use mcp_xray_researcher_search_codebase instead of ripgrep",
92
+ "eslint": "Use mcp_xray_lint_lint instead of raw eslint",
93
+ "npx eslint": "Use mcp_xray_lint_lint instead of raw eslint",
94
+ "npm audit": "Use mcp_xray_security_scan_security_scan instead of npm audit",
95
+ "yarn audit": "Use mcp_xray_security_scan_security_scan instead of yarn audit",
96
96
  "find ": "Use search_files(target='files') instead of find",
97
97
  "sed ": "Use patch tool instead of sed",
98
98
  "awk ": "Use patch tool instead of awk",
@@ -108,7 +108,7 @@ _session_stats = {
108
108
  "session_id": None,
109
109
  "code_operations": 0,
110
110
  "total_tool_calls": 0,
111
- "strray_mcp_calls": 0,
111
+ "xray_mcp_calls": 0,
112
112
  "native_tool_calls": 0,
113
113
  "quality_gate_runs": 0,
114
114
  "quality_gate_blocks": 0,
@@ -184,8 +184,8 @@ def _call_bridge(command: dict, timeout: int = 10) -> dict:
184
184
 
185
185
  # ── Hook: pre_tool_call ───────────────────────────────────────
186
186
 
187
- def _is_strray_mcp(tool_name: str) -> bool:
188
- return tool_name.startswith("mcp_strray_")
187
+ def _is_xray_mcp(tool_name: str) -> bool:
188
+ return tool_name.startswith("mcp_xray_")
189
189
 
190
190
 
191
191
  def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
@@ -195,17 +195,17 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
195
195
  1. Track stats
196
196
  2. Log tool-start event to disk
197
197
  3. For code-producing tools: run quality gate + pre-processors via bridge
198
- 4. For non-code tools: nudge if StringRay alternative exists
198
+ 4. For non-code tools: nudge if Xray alternative exists
199
199
  """
200
200
  _session_stats["total_tool_calls"] += 1
201
201
 
202
202
  # Log start event
203
203
  _log_tool_event("start", tool_name, args)
204
204
 
205
- # StringRay MCP tools — track but don't interfere
206
- if _is_strray_mcp(tool_name):
207
- _session_stats["strray_mcp_calls"] += 1
208
- _log_to_file("activity.log", f"[quality-gate] SKIP (strray-mcp): {tool_name}")
205
+ # Xray MCP tools — track but don't interfere
206
+ if _is_xray_mcp(tool_name):
207
+ _session_stats["xray_mcp_calls"] += 1
208
+ _log_to_file("activity.log", f"[quality-gate] SKIP [xray-mcp]: {tool_name}")
209
209
  return
210
210
 
211
211
  # delegate_task: snapshot working tree so post_hook can validate changes
@@ -252,7 +252,7 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
252
252
  _log_to_file("activity.log",
253
253
  f"[quality-gate] BLOCKED: tool={tool_name} violations={violation_msg}")
254
254
  logger.warning(
255
- "[strray] Quality gate BLOCKED %s: %s",
255
+ "[xray] Quality gate BLOCKED %s: %s",
256
256
  tool_name, violation_msg,
257
257
  )
258
258
  else:
@@ -277,10 +277,10 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
277
277
  f"[bridge] ERROR in pre-process: {bridge_result.get('error', 'unknown')}")
278
278
  return
279
279
 
280
- # Non-code tools: nudge for StringRay alternatives
281
- if tool_name in _BETTER_WITH_STRRAY:
282
- tip = _BETTER_WITH_STRRAY[tool_name]
283
- logger.info("[strray] Tip: %s — %s", tool_name, tip)
280
+ # Non-code tools: nudge for Xray alternatives
281
+ if tool_name in _BETTER_WITH_XRAY:
282
+ tip = _BETTER_WITH_XRAY[tool_name]
283
+ logger.info("[xray] Tip: %s — %s", tool_name, tip)
284
284
  _log_to_file("activity.log",
285
285
  f"[nudge] {tool_name}: {tip}")
286
286
 
@@ -290,7 +290,7 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
290
290
  if isinstance(cmd, str):
291
291
  for pattern, tip in _TERMINAL_NUDGE_PATTERNS.items():
292
292
  if pattern in cmd:
293
- logger.info("[strray] Tip: %s — %s", tool_name, tip)
293
+ logger.info("[xray] Tip: %s — %s", tool_name, tip)
294
294
  _log_to_file("activity.log",
295
295
  f"[nudge] {tool_name}: {tip}")
296
296
  break
@@ -378,14 +378,14 @@ def _on_post_tool_call(tool_name: str, args: dict, result, task_id: str, **kwarg
378
378
  if calls - _last_tune_tool_call_count >= _INFERENCE_TUNE_INTERVAL:
379
379
  _last_tune_tool_call_count = calls
380
380
  logger.info(
381
- "[strray] Triggering inference tuning cycle (tool call #%d)", calls
381
+ "[xray] Triggering inference tuning cycle (tool call #%d)", calls
382
382
  )
383
383
  _log_to_file("activity.log",
384
384
  f"[inference-tune] auto-cycle at tool call #{calls}")
385
385
  try:
386
386
  _run_inference_tune()
387
387
  except Exception as e:
388
- logger.warning("[strray] Inference tuning failed: %s", e)
388
+ logger.warning("[xray] Inference tuning failed: %s", e)
389
389
 
390
390
 
391
391
  # ── Hook: session_start ───────────────────────────────────────
@@ -394,7 +394,7 @@ def _on_session_start(session_id: str, platform: str, **kwargs):
394
394
  """Fires when a new session starts. Resets stats, logs to disk."""
395
395
  _session_stats["started_at"] = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
396
396
  _session_stats["session_id"] = session_id
397
- for key in ("code_operations", "total_tool_calls", "strray_mcp_calls",
397
+ for key in ("code_operations", "total_tool_calls", "xray_mcp_calls",
398
398
  "native_tool_calls", "quality_gate_runs", "quality_gate_blocks",
399
399
  "pre_processor_runs", "post_processor_runs",
400
400
  "bridge_calls", "bridge_errors",
@@ -406,23 +406,23 @@ def _on_session_start(session_id: str, platform: str, **kwargs):
406
406
  _ensure_log_dir()
407
407
  _log_to_file("activity.log",
408
408
  f"[session-start] session={session_id} platform={platform}")
409
- logger.info("[strray] Session %s started on %s", session_id, platform)
409
+ logger.info("[xray] Session %s started on %s", session_id, platform)
410
410
 
411
411
 
412
412
  # ── Slash command ─────────────────────────────────────────────
413
413
 
414
- def _strray_command(args: str) -> str:
415
- """Slash command handler: /strray [status|stats|help]"""
414
+ def _xray_command(args: str) -> str:
415
+ """Slash command handler: /xray [status|stats|help]"""
416
416
  cmd = (args or "status").strip().lower()
417
417
 
418
418
  if cmd == "stats":
419
419
  return (
420
- f"StringRay Session Stats\n"
420
+ f"Xray Session Stats\n"
421
421
  f" Session: {_session_stats['session_id'] or 'N/A'}\n"
422
422
  f" Started: {_session_stats['started_at'] or 'N/A'}\n"
423
423
  f" Tool calls: {_session_stats['total_tool_calls']}\n"
424
424
  f" Code operations: {_session_stats['code_operations']}\n"
425
- f" StringRay MCP: {_session_stats['strray_mcp_calls']}\n"
425
+ f" Xray MCP: {_session_stats['xray_mcp_calls']}\n"
426
426
  f" Native tools: {_session_stats['native_tool_calls']}\n"
427
427
  f" Quality gate runs: {_session_stats['quality_gate_runs']}\n"
428
428
  f" Quality gate blocks: {_session_stats['quality_gate_blocks']}\n"
@@ -437,19 +437,19 @@ def _strray_command(args: str) -> str:
437
437
 
438
438
  if cmd == "help":
439
439
  return (
440
- "StringRay Commands:\n"
441
- " /strray status — Plugin and framework health\n"
442
- " /strray stats — Session pipeline statistics\n"
443
- " /strray help — This message"
440
+ "Xray Commands:\n"
441
+ " /xray status — Plugin and framework health\n"
442
+ " /xray stats — Session pipeline statistics\n"
443
+ " /xray help — This message"
444
444
  )
445
445
 
446
446
  # Default: status (calls bridge health)
447
447
  bridge_result = _call_bridge({"command": "health"}, timeout=10)
448
448
  if "error" in bridge_result:
449
- return f"StringRay plugin loaded. Bridge: {bridge_result['error']}"
449
+ return f"Xray plugin loaded. Bridge: {bridge_result['error']}"
450
450
 
451
451
  return (
452
- f"StringRay Hermes Plugin Status\n"
452
+ f"Xray Hermes Plugin Status\n"
453
453
  f" Framework: {bridge_result.get('framework', 'unknown')}\n"
454
454
  f" Version: {bridge_result.get('version', 'unknown')}\n"
455
455
  f" Quality Gate: {'ready' if bridge_result.get('components', {}).get('qualityGate') else 'not loaded'}\n"
@@ -518,13 +518,13 @@ def _record_tool_outcome(tool_name: str, args: dict, success: bool):
518
518
  with open(_OUTCOMES_PATH, "w") as f:
519
519
  json.dump(outcomes, f, indent=2)
520
520
  except Exception as e:
521
- logger.debug("[strray] outcome recording failed: %s", e)
521
+ logger.debug("[xray] outcome recording failed: %s", e)
522
522
 
523
523
 
524
524
  # ── Inference tuning (auto-calibration) ────────────────────────
525
525
 
526
526
  def _run_inference_tune():
527
- """Shell out to strray-ai inference:tuner --run-once.
527
+ """Shell out to 0xray inference:tuner --run-once.
528
528
 
529
529
  Runs in a background thread so it doesn't block the tool call pipeline.
530
530
  The tuner reads routing outcomes, runs the analytics pipeline, and
@@ -560,7 +560,7 @@ def _run_inference_tune():
560
560
  # ── Registration ──────────────────────────────────────────────
561
561
 
562
562
  # ── Subagent (delegate_task) enforcement ────────────────────
563
- # Subagents bypass all StringRay hooks because they run in isolated
563
+ # Subagents bypass all Xray hooks because they run in isolated
564
564
  # contexts. We enforce by snapshotting the working tree before dispatch
565
565
  # and validating all changed files after return.
566
566
 
@@ -647,7 +647,7 @@ def _validate_subagent_changes(task_id: str, **kwargs):
647
647
  f"[subagent-validate] BLOCKED: {rel_path} "
648
648
  f"violations={'; '.join(str(v) for v in violations[:3])}")
649
649
  logger.warning(
650
- "[strray] Subagent BLOCKED %s: %s",
650
+ "[xray] Subagent BLOCKED %s: %s",
651
651
  rel_path, violations[:3],
652
652
  )
653
653
  else:
@@ -659,28 +659,28 @@ def register(ctx):
659
659
  """Wire schemas to handlers and register lifecycle hooks."""
660
660
  # ── Register tools ────────────────────────────────────────
661
661
  ctx.register_tool(
662
- name="strray_validate",
663
- toolset="strray-hermes",
664
- schema=schemas.STRRAY_VALIDATE,
665
- handler=tools.strray_validate,
662
+ name="xray_validate",
663
+ toolset="xray-hermes",
664
+ schema=schemas.XRAY_VALIDATE,
665
+ handler=tools.xray_validate,
666
666
  )
667
667
  ctx.register_tool(
668
- name="strray_codex_check",
669
- toolset="strray-hermes",
670
- schema=schemas.STRRAY_CODEX_CHECK,
671
- handler=tools.strray_codex_check,
668
+ name="xray_codex_check",
669
+ toolset="xray-hermes",
670
+ schema=schemas.XRAY_CODEX_CHECK,
671
+ handler=tools.xray_codex_check,
672
672
  )
673
673
  ctx.register_tool(
674
- name="strray_health",
675
- toolset="strray-hermes",
676
- schema=schemas.STRRAY_HEALTH,
677
- handler=tools.strray_health,
674
+ name="xray_health",
675
+ toolset="xray-hermes",
676
+ schema=schemas.XRAY_HEALTH,
677
+ handler=tools.xray_health,
678
678
  )
679
679
  ctx.register_tool(
680
- name="strray_hooks",
681
- toolset="strray-hermes",
682
- schema=schemas.STRRAY_HOOKS,
683
- handler=tools.strray_hooks,
680
+ name="xray_hooks",
681
+ toolset="xray-hermes",
682
+ schema=schemas.XRAY_HOOKS,
683
+ handler=tools.xray_hooks,
684
684
  )
685
685
 
686
686
  # ── Register hooks ────────────────────────────────────────
@@ -691,28 +691,28 @@ def register(ctx):
691
691
  try:
692
692
  ctx.register_hook("on_session_start", _on_session_start)
693
693
  except (AttributeError, TypeError):
694
- logger.debug("[strray] on_session_start hook not yet available")
694
+ logger.debug("[xray] on_session_start hook not yet available")
695
695
 
696
696
  # ── Register slash command ────────────────────────────────
697
697
  try:
698
698
  ctx.register_command(
699
- name="strray",
700
- handler=_strray_command,
701
- description="StringRay status, stats, hooks, and enforcement info",
699
+ name="xray",
700
+ handler=_xray_command,
701
+ description="Xray status, stats, hooks, and enforcement info",
702
702
  args_hint="[status|stats|help]",
703
703
  aliases=("sr",),
704
704
  )
705
705
  except (AttributeError, TypeError):
706
- logger.debug("[strray] Slash command registration not yet available")
706
+ logger.debug("[xray] Slash command registration not yet available")
707
707
 
708
708
  # ── Bootstrap ─────────────────────────────────────────────
709
709
  _ensure_log_dir()
710
710
  _log_to_file("activity.log",
711
- f"[plugin-loaded] StringRay Hermes Plugin v2.2 — "
711
+ f"[plugin-loaded] Xray Hermes Plugin v2.2 — "
712
712
  f"4 tools, 2 hooks, subagent enforcement, bridge={BRIDGE_PATH.exists()}")
713
713
 
714
714
  logger.info(
715
- "[strray] Plugin v2.2 loaded: 4 tools, 2 hooks, "
715
+ "[xray] Plugin v2.2 loaded: 4 tools, 2 hooks, "
716
716
  "subagent enforcement active, bridge=%s",
717
717
  BRIDGE_PATH.exists(),
718
718
  )
@@ -1,4 +1,4 @@
1
- # StringRay Hermes Plugin Installed
1
+ # Xray Hermes Plugin Installed
2
2
 
3
3
  **Restart your Hermes session** for the plugin to take effect.
4
4
 
@@ -6,10 +6,10 @@
6
6
 
7
7
  | Component | Description |
8
8
  |-----------|-------------|
9
- | `strray_validate` | Pre-commit validation with quality gates |
10
- | `strray_codex_check` | Code review against 60 Codex error-prevention rules |
11
- | `strray_health` | Framework health check |
12
- | `strray_hooks` | Git hooks management (install, uninstall, list, status) |
9
+ | `xray_validate` | Pre-commit validation with quality gates |
10
+ | `xray_codex_check` | Code review against 60 Codex error-prevention rules |
11
+ | `xray_health` | Framework health check |
12
+ | `xray_hooks` | Git hooks management (install, uninstall, list, status) |
13
13
  | `pre_tool_call` hook | Quality gates + nudges before every tool call |
14
14
  | `post_tool_call` hook | Post-processors after every tool call |
15
15
 
@@ -27,24 +27,24 @@ The plugin can install git hooks for automated validation:
27
27
  ### Install Hooks
28
28
 
29
29
  ```
30
- /strray hooks install
30
+ /xray hooks install
31
31
  ```
32
32
 
33
33
  Or use the tool directly:
34
34
  ```
35
- strray_hooks(action="install")
35
+ xray_hooks(action="install")
36
36
  ```
37
37
 
38
38
  ### Check Hook Status
39
39
 
40
40
  ```
41
- /strray hooks status
41
+ /xray hooks status
42
42
  ```
43
43
 
44
44
  ### Uninstall Hooks
45
45
 
46
46
  ```
47
- /strray hooks uninstall
47
+ /xray hooks uninstall
48
48
  ```
49
49
 
50
50
  ## Quick Test
@@ -52,20 +52,20 @@ strray_hooks(action="install")
52
52
  After restarting Hermes, try:
53
53
 
54
54
  ```
55
- /strray status
56
- /strray stats
55
+ /xray status
56
+ /xray stats
57
57
  ```
58
58
 
59
- Or use the tools directly — `strray_health` will confirm the bridge is connected.
59
+ Or use the tools directly — `xray_health` will confirm the bridge is connected.
60
60
 
61
61
  ## MCP Servers
62
62
 
63
- The plugin works alongside StringRay's MCP servers (if configured in your
63
+ The plugin works alongside Xray's MCP servers (if configured in your
64
64
  Hermes config). The plugin's native tools provide offline/offline-first
65
65
  validation, while MCP servers offer deeper framework integration.
66
66
 
67
67
  ## Files
68
68
 
69
- The plugin lives at `~/.hermes/plugins/strray-hermes/`. It is auto-updated
69
+ The plugin lives at `~/.hermes/plugins/xray-hermes/`. It is auto-updated
70
70
  when you run `npm install` or `npm update` in a project with `0xray`
71
71
  as a dependency.