0xray 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitignore.default +59 -0
- package/.mcp.json +35 -0
- package/.opencode/codex.codex +1 -1
- package/.opencode/commands/dependency-audit.md +3 -3
- package/.opencode/commands/summary-logger.md +4 -4
- package/.opencode/enforcer-config.json +2 -2
- package/.opencode/hooks/post-commit +1 -1
- package/.opencode/init.sh +6 -0
- package/.plugin/plugin.json +11 -0
- package/AGENTS-consumer.md +46 -0
- package/AGENTS.md +8 -8
- package/LICENSE +1 -1
- package/README.md +8 -8
- package/SKILLS.md +140 -0
- package/dist/.gitignore.default +59 -0
- package/dist/AGENTS.md +8 -8
- package/dist/CHANGELOG.md +25 -0
- package/dist/LICENSE +1 -1
- package/dist/README.md +8 -8
- package/dist/SKILLS.md +140 -0
- package/dist/agents/index.js +3 -1
- package/dist/agents/registry.js +13 -0
- package/dist/analytics/routing-refiner.js +1 -1
- package/dist/architect/architectural-integrity.js +3 -3
- package/dist/benchmark/performance-benchmark.js +1 -2
- package/dist/cli/commands/antigravity-status.js +23 -23
- package/dist/cli/commands/credible-init.js +1 -1
- package/dist/cli/commands/hermes-install.js +8 -0
- package/dist/cli/commands/mcp-install.js +1 -1
- package/dist/cli/commands/openclaw-install.js +9 -0
- package/dist/cli/commands/opencode-install.js +22 -0
- package/dist/cli/commands/skill-install.js +39 -2
- package/dist/cli/commands/status.js +5 -0
- package/dist/cli/commands/storyteller.js +1 -1
- package/dist/cli/index.js +12 -6
- package/dist/core/activity-logger.js +4 -4
- package/dist/core/agent-spawn-gate.js +1 -1
- package/dist/core/boot-orchestrator.js +12 -13
- package/dist/core/bridge.mjs +4 -4
- package/dist/core/codex-formatter.js +1 -2
- package/dist/core/codex-injector.js +3 -3
- package/dist/core/config-loader.js +1 -2
- package/dist/core/config-paths.js +30 -23
- package/dist/core/context-loader.js +0 -3
- package/dist/core/features-config.js +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/logging-config.js +7 -7
- package/dist/core/orchestrator.js +1 -1
- package/dist/core/xray-activation.js +3 -4
- 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/execution/opencode-cli-invoker.js +1 -1
- package/dist/governance/governance-service.js +1 -1
- package/dist/governance/llm-governance-provider.js +14 -1
- package/dist/index.js +3 -5
- package/dist/inference/inference-cycle.js +11 -11
- package/dist/integrations/base/README.md +1 -1
- package/dist/integrations/enforcement-gate.js +2 -2
- package/dist/integrations/governance/index.js +1 -1
- package/dist/integrations/grok/grok-cli.js +20 -6
- package/dist/integrations/grok/hooks/pre-tool-use.js +3 -3
- package/dist/integrations/grok/plugin/0xray/.mcp.json +16 -4
- package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +2 -2
- package/dist/integrations/hermes-agent/__init__.py +25 -14
- package/dist/integrations/hermes-agent/bridge.mjs +39 -4
- package/dist/integrations/hermes-agent/schemas.py +49 -0
- package/dist/integrations/hermes-agent/test_plugin.py +7 -7
- package/dist/integrations/hermes-agent/tools.py +107 -3
- package/dist/integrations/openclaw/README.md +6 -6
- package/dist/integrations/openclaw/config.js +1 -1
- package/dist/integrations/openclaw/index.js +2 -2
- package/dist/integrations/openclaw/types.js +3 -3
- package/dist/integrations/plugins/plugin-integration.js +1 -1
- package/dist/integrations/plugins/plugin-registry.js +1 -1
- package/dist/mcps/architect-tools.server.js +3 -2
- package/dist/mcps/auto-format.server.js +2 -2
- package/dist/mcps/boot-orchestrator.server.js +2 -2
- package/dist/mcps/config/config-loader.js +40 -9
- package/dist/mcps/enforcer-tools.server.js +2 -2
- package/dist/mcps/estimation.server.js +3 -2
- package/dist/mcps/framework-compliance-audit.server.js +2 -2
- package/dist/mcps/framework-help.server.js +3 -2
- package/dist/mcps/governance.server.js +8 -4
- package/dist/mcps/knowledge-skills/api-design.server.js +3 -2
- package/dist/mcps/knowledge-skills/architecture-patterns.server.js +3 -2
- package/dist/mcps/knowledge-skills/bug-triage-specialist.server.js +3 -3
- package/dist/mcps/knowledge-skills/code-analyzer.server.js +2 -2
- package/dist/mcps/knowledge-skills/code-review.server.js +2 -2
- package/dist/mcps/knowledge-skills/content-creator.server.js +3 -3
- package/dist/mcps/knowledge-skills/database-design.server.js +2 -2
- package/dist/mcps/knowledge-skills/devops-deployment.server.js +3 -2
- package/dist/mcps/knowledge-skills/git-workflow.server.js +3 -2
- package/dist/mcps/knowledge-skills/growth-strategist.server.js +3 -3
- package/dist/mcps/knowledge-skills/log-monitor.server.js +3 -3
- package/dist/mcps/knowledge-skills/mobile-development.server.js +3 -3
- package/dist/mcps/knowledge-skills/multimodal-looker.server.js +3 -3
- package/dist/mcps/knowledge-skills/performance-optimization.server.js +2 -2
- package/dist/mcps/knowledge-skills/project-analysis.server.js +2 -2
- package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +3 -2
- package/dist/mcps/knowledge-skills/security-audit.server.js +2 -2
- package/dist/mcps/knowledge-skills/seo-consultant.server.js +3 -2
- package/dist/mcps/knowledge-skills/session-management.server.js +3 -2
- package/dist/mcps/knowledge-skills/skill-invocation.server.js +105 -3
- package/dist/mcps/knowledge-skills/strategist.server.js +3 -3
- package/dist/mcps/knowledge-skills/tech-writer.server.js +3 -3
- package/dist/mcps/knowledge-skills/testing-best-practices.server.js +3 -2
- package/dist/mcps/knowledge-skills/testing-strategy.server.js +2 -2
- package/dist/mcps/knowledge-skills/ui-ux-design.server.js +3 -2
- package/dist/mcps/lint.server.js +2 -2
- package/dist/mcps/model-health-check.server.js +3 -2
- package/dist/mcps/orchestrator/server.js +2 -1
- package/dist/mcps/orchestrator.server.js +2 -1
- package/dist/mcps/performance-analysis.server.js +2 -2
- package/dist/mcps/processor-pipeline.server.js +3 -2
- package/dist/mcps/registry.json +1 -1
- package/dist/mcps/researcher.server.js +2 -2
- package/dist/mcps/security-scan.server.js +2 -2
- package/dist/mcps/state-manager.server.js +5 -5
- package/dist/metrics/agent-metrics.js +1 -1
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +2 -2
- package/dist/orchestrator/intelligent-commit-batcher.js +0 -1
- package/dist/orchestrator/multi-agent-orchestration-coordinator.js +1 -1
- package/dist/orchestrator/orchestrator.js +1 -2
- package/dist/orchestrator/universal-registry-bridge.js +1 -1
- package/dist/postprocessor/PostProcessor.js +5 -5
- package/dist/postprocessor/services/RegressionAnalysisService.js +2 -2
- package/dist/postprocessor/triggers/GitHookTrigger.js +4 -4
- package/dist/processors/implementations/inference-improvement-processor.js +0 -1
- package/dist/processors/implementations/publish-preflight-processor.js +0 -1
- package/dist/processors/implementations/session-summary-processor.js +2 -2
- package/dist/processors/implementations/storytelling-trigger-processor.js +0 -1
- package/dist/public/about.html +6 -6
- package/dist/public/enterprise.html +1 -1
- package/dist/public/features.html +2 -2
- package/dist/public/index.html +4 -4
- package/dist/reporting/report-formatter.js +1 -1
- package/dist/scripts/activate-kernel-pipeline.js +2 -2
- package/dist/scripts/pre-command +1 -1
- package/dist/services/inference-tuner.js +1 -1
- package/dist/skills/api-design/SKILL.md +1 -1
- package/dist/skills/architect-tools/SKILL.md +1 -1
- package/dist/skills/architecture-patterns/SKILL.md +1 -1
- package/dist/skills/auto-format/SKILL.md +1 -1
- package/dist/skills/boot-orchestrator/SKILL.md +1 -1
- package/dist/skills/bug-triage/SKILL.md +1 -1
- package/dist/skills/code-analyzer/SKILL.md +1 -1
- package/dist/skills/code-review/SKILL.md +1 -1
- package/dist/skills/enforcer/SKILL.md +1 -1
- package/dist/skills/framework-compliance-audit/SKILL.md +1 -1
- package/dist/skills/git-workflow/SKILL.md +1 -1
- package/dist/skills/hermes-agent/SKILL.md +2 -2
- package/dist/skills/inference-improve/SKILL.md +1 -1
- package/dist/skills/lint/SKILL.md +1 -1
- package/dist/skills/log-monitor/SKILL.md +1 -1
- package/dist/skills/model-health-check/SKILL.md +1 -1
- package/dist/skills/multimodal-looker/SKILL.md +1 -1
- package/dist/skills/orchestrator/SKILL.md +1 -1
- package/dist/skills/performance-analysis/SKILL.md +1 -1
- package/dist/skills/performance-optimization/SKILL.md +1 -1
- package/dist/skills/processor-pipeline/SKILL.md +1 -1
- package/dist/skills/project-analysis/SKILL.md +1 -1
- package/dist/skills/refactoring-strategies/SKILL.md +1 -1
- package/dist/skills/registry.json +1 -1
- package/dist/skills/researcher/SKILL.md +1 -1
- package/dist/skills/security-audit/SKILL.md +1 -1
- package/dist/skills/security-scan/SKILL.md +1 -1
- package/dist/skills/session-management/SKILL.md +1 -1
- package/dist/skills/state-manager/SKILL.md +1 -1
- package/dist/skills/storyteller/SKILL.md +1 -1
- package/dist/skills/testing-best-practices/SKILL.md +1 -1
- package/dist/skills/testing-strategy/SKILL.md +1 -1
- package/dist/skills/ui-ux-design/SKILL.md +1 -1
- package/dist/state/index.js +0 -1
- package/dist/state/state-manager.js +1 -2
- package/dist/utils/import-resolver.js +1 -1
- package/dist/utils/path-resolver.js +2 -2
- package/package.json +10 -3
- package/scripts/hooks/pre-command +1 -1
- package/scripts/hooks/run-hook.js +2 -2
- package/scripts/node/auto-reflection-generator.mjs +30 -36
- package/scripts/node/govern-reflection.mjs +1 -1
- package/scripts/node/postinstall.cjs +37 -2
- package/scripts/node/setup-xai-oauth.mjs +244 -0
- package/scripts/node/universal-version-manager.js +8 -8
- package/scripts/node/version-manager.mjs +1 -1
- package/src/integrations/grok/plugin/0xray/.mcp.json +16 -4
- package/src/integrations/grok/plugin/0xray/hooks/hooks.json +2 -2
- package/src/mcps/architect-tools.server.ts +2 -2
- package/src/mcps/auto-format.server.ts +2 -2
- package/src/mcps/boot-orchestrator.server.ts +2 -2
- package/src/mcps/config/__tests__/config-loader.test.ts +29 -33
- package/src/mcps/config/config-loader.ts +50 -11
- package/src/mcps/enforcer-tools.server.ts +2 -2
- package/src/mcps/estimation.server.ts +3 -2
- package/src/mcps/framework-compliance-audit.server.ts +2 -2
- package/src/mcps/framework-help.server.ts +3 -2
- package/src/mcps/governance.server.ts +8 -3
- package/src/mcps/knowledge-skills/api-design.server.ts +3 -2
- package/src/mcps/knowledge-skills/architecture-patterns.server.ts +2 -2
- package/src/mcps/knowledge-skills/bug-triage-specialist.server.ts +2 -2
- package/src/mcps/knowledge-skills/code-analyzer.server.ts +2 -2
- package/src/mcps/knowledge-skills/code-review.server.ts +2 -2
- package/src/mcps/knowledge-skills/content-creator.server.ts +3 -3
- package/src/mcps/knowledge-skills/database-design.server.ts +2 -2
- package/src/mcps/knowledge-skills/devops-deployment.server.ts +3 -2
- package/src/mcps/knowledge-skills/git-workflow.server.ts +3 -2
- package/src/mcps/knowledge-skills/growth-strategist.server.ts +3 -3
- package/src/mcps/knowledge-skills/log-monitor.server.ts +3 -3
- package/src/mcps/knowledge-skills/mobile-development.server.ts +3 -3
- package/src/mcps/knowledge-skills/multimodal-looker.server.ts +3 -3
- package/src/mcps/knowledge-skills/performance-optimization.server.ts +2 -2
- package/src/mcps/knowledge-skills/project-analysis.server.ts +2 -2
- package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +3 -2
- package/src/mcps/knowledge-skills/security-audit.server.ts +2 -2
- package/src/mcps/knowledge-skills/seo-consultant.server.ts +3 -2
- package/src/mcps/knowledge-skills/session-management.server.ts +3 -2
- package/src/mcps/knowledge-skills/skill-invocation.server.ts +113 -3
- package/src/mcps/knowledge-skills/strategist.server.ts +3 -3
- package/src/mcps/knowledge-skills/tech-writer.server.ts +3 -3
- package/src/mcps/knowledge-skills/testing-best-practices.server.ts +3 -2
- package/src/mcps/knowledge-skills/testing-strategy.server.ts +2 -2
- package/src/mcps/knowledge-skills/ui-ux-design.server.ts +3 -2
- package/src/mcps/lint.server.ts +2 -2
- package/src/mcps/model-health-check.server.ts +2 -2
- package/src/mcps/orchestrator/server.ts +2 -1
- package/src/mcps/orchestrator.server.ts +2 -1
- package/src/mcps/performance-analysis.server.ts +2 -2
- package/src/mcps/processor-pipeline.server.ts +3 -2
- package/src/mcps/registry.json +1 -1
- package/src/mcps/researcher.server.ts +2 -2
- package/src/mcps/security-scan.server.ts +2 -2
- package/src/mcps/state-manager.server.ts +5 -5
- package/src/opencode/codex.codex +1 -1
- package/src/opencode/commands/dependency-audit.md +3 -3
- package/src/opencode/commands/summary-logger.md +4 -4
- package/src/opencode/enforcer-config.json +2 -2
- package/src/skills/api-design/SKILL.md +1 -1
- package/src/skills/architect-tools/SKILL.md +1 -1
- package/src/skills/architecture-patterns/SKILL.md +1 -1
- package/src/skills/auto-format/SKILL.md +1 -1
- package/src/skills/boot-orchestrator/SKILL.md +1 -1
- package/src/skills/bug-triage/SKILL.md +1 -1
- package/src/skills/code-analyzer/SKILL.md +1 -1
- package/src/skills/code-review/SKILL.md +1 -1
- package/src/skills/enforcer/SKILL.md +1 -1
- package/src/skills/framework-compliance-audit/SKILL.md +1 -1
- package/src/skills/git-workflow/SKILL.md +1 -1
- package/src/skills/hermes-agent/SKILL.md +2 -2
- package/src/skills/inference-improve/SKILL.md +1 -1
- package/src/skills/lint/SKILL.md +1 -1
- package/src/skills/log-monitor/SKILL.md +1 -1
- package/src/skills/model-health-check/SKILL.md +1 -1
- package/src/skills/multimodal-looker/SKILL.md +1 -1
- package/src/skills/orchestrator/SKILL.md +1 -1
- package/src/skills/performance-analysis/SKILL.md +1 -1
- package/src/skills/performance-optimization/SKILL.md +1 -1
- package/src/skills/processor-pipeline/SKILL.md +1 -1
- package/src/skills/project-analysis/SKILL.md +1 -1
- package/src/skills/refactoring-strategies/SKILL.md +1 -1
- package/src/skills/registry.json +1 -1
- package/src/skills/researcher/SKILL.md +1 -1
- package/src/skills/security-audit/SKILL.md +1 -1
- package/src/skills/security-scan/SKILL.md +1 -1
- package/src/skills/session-management/SKILL.md +1 -1
- package/src/skills/state-manager/SKILL.md +1 -1
- package/src/skills/storyteller/SKILL.md +1 -1
- package/src/skills/testing-best-practices/SKILL.md +1 -1
- package/src/skills/testing-strategy/SKILL.md +1 -1
- package/src/skills/ui-ux-design/SKILL.md +1 -1
- package/xray/agents_template.md +46 -0
- package/xray/codex.json +598 -0
- package/dist/plugin/xray-codex-injection.js +0 -857
- /package/dist/integrations/openclaw/hooks/{strray-hooks.js → xray-hooks.js} +0 -0
|
@@ -328,7 +328,7 @@ export class InferenceCycle {
|
|
|
328
328
|
try {
|
|
329
329
|
let agentName = p.type === "refactor" ? "refactorer" : "code-reviewer";
|
|
330
330
|
// In pure MCP mode, use real skill server names so the orchestrator dispatches to actual MCP tools
|
|
331
|
-
if (process.env.
|
|
331
|
+
if (process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true') {
|
|
332
332
|
agentName = p.type === "refactor" ? "refactoring-strategies" : "code-review";
|
|
333
333
|
}
|
|
334
334
|
await this.invokeAgentInternal(agentName, prompt);
|
|
@@ -353,11 +353,11 @@ 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 .
|
|
356
|
+
`3. If this is a codex rule, add the term to .xray/codex.json`,
|
|
357
357
|
`4. Make minimal, surgical changes`,
|
|
358
358
|
].join("\n");
|
|
359
359
|
try {
|
|
360
|
-
const agentName = process.env.
|
|
360
|
+
const agentName = process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true'
|
|
361
361
|
? "code-review"
|
|
362
362
|
: "code-reviewer";
|
|
363
363
|
await this.invokeAgentInternal(agentName, prompt);
|
|
@@ -388,7 +388,7 @@ export class InferenceCycle {
|
|
|
388
388
|
`3. Implement it if straightforward, otherwise describe the design`,
|
|
389
389
|
].join("\n");
|
|
390
390
|
try {
|
|
391
|
-
const agentName = process.env.
|
|
391
|
+
const agentName = process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true'
|
|
392
392
|
? "architecture-patterns"
|
|
393
393
|
: "architect";
|
|
394
394
|
await this.invokeAgentInternal(agentName, prompt);
|
|
@@ -455,7 +455,7 @@ Respond with EXACTLY one of:
|
|
|
455
455
|
async governProposals(proposals) {
|
|
456
456
|
// Primary path: Use the first-class Governance MCP (real skill servers + required Dynamo)
|
|
457
457
|
// This is the clean, centralized path (governance.server.ts + GovernanceService)
|
|
458
|
-
const useGovernanceMcp = process.env.
|
|
458
|
+
const useGovernanceMcp = process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true' ||
|
|
459
459
|
this.isGovernanceMcpPreferred();
|
|
460
460
|
if (useGovernanceMcp) {
|
|
461
461
|
try {
|
|
@@ -488,7 +488,7 @@ Respond with EXACTLY one of:
|
|
|
488
488
|
error: err instanceof Error ? err.message : String(err),
|
|
489
489
|
});
|
|
490
490
|
// In forced pure MCP mode we must not silently fall back
|
|
491
|
-
if (process.env.
|
|
491
|
+
if (process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true') {
|
|
492
492
|
throw err;
|
|
493
493
|
}
|
|
494
494
|
// In normal mode, fall back to legacy path with deprecation warning.
|
|
@@ -552,7 +552,7 @@ Respond with EXACTLY one of:
|
|
|
552
552
|
*/
|
|
553
553
|
async governProposalsInternal(proposals) {
|
|
554
554
|
// Defensive: if pure MCP mode is forced, use individual skill servers only
|
|
555
|
-
if (process.env.
|
|
555
|
+
if (process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true') {
|
|
556
556
|
return this.governProposalsWithIndividualSkills(proposals);
|
|
557
557
|
}
|
|
558
558
|
const coordinator = this.getCoordinator();
|
|
@@ -633,7 +633,7 @@ Respond with EXACTLY one of:
|
|
|
633
633
|
}
|
|
634
634
|
/**
|
|
635
635
|
* Pure individual knowledge-skill MCP path for governance.
|
|
636
|
-
* Used when
|
|
636
|
+
* Used when XRAY_FORCE_MCP_GOVERNANCE=true.
|
|
637
637
|
* Each proposal is evaluated directly by the relevant skill servers using analyze_proposal.
|
|
638
638
|
*/
|
|
639
639
|
async governProposalsWithIndividualSkills(proposals) {
|
|
@@ -801,7 +801,7 @@ Respond with EXACTLY one of:
|
|
|
801
801
|
responseText = JSON.stringify(result);
|
|
802
802
|
}
|
|
803
803
|
// In pure MCP governance mode, trust the orchestrator response (it now does real work)
|
|
804
|
-
const isPureMcp = process.env.
|
|
804
|
+
const isPureMcp = process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true';
|
|
805
805
|
const hasRealContent = /PROPOSAL:\s*\d+/i.test(responseText) ||
|
|
806
806
|
/DECISION:\s*(approve|reject|abstain)/i.test(responseText) ||
|
|
807
807
|
/Agent Outputs \(real MCP responses\):/i.test(responseText);
|
|
@@ -830,7 +830,7 @@ Respond with EXACTLY one of:
|
|
|
830
830
|
return this.agentInvoker(agentName, prompt);
|
|
831
831
|
}
|
|
832
832
|
// Only fall back to OpenCode if not in forced pure MCP mode
|
|
833
|
-
if (process.env.
|
|
833
|
+
if (process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true') {
|
|
834
834
|
throw new Error(`[PURE MCP] Orchestrator returned no usable response for agent "${agentName}" and OpenCode fallback is disabled`);
|
|
835
835
|
}
|
|
836
836
|
return this.invokeViaOpencode(agentName, prompt);
|
|
@@ -975,7 +975,7 @@ 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 .xray
|
|
978
|
+
// Use the provider-agnostic config path resolver (prefers .xray/)
|
|
979
979
|
const configDir = getConfigDir(this.projectRoot);
|
|
980
980
|
// If we resolved to a .xray or custom dir, use its parent as the "root"
|
|
981
981
|
if (configDir.includes(".xray") || configDir.includes("xray")) {
|
|
@@ -21,7 +21,7 @@ src/integrations/
|
|
|
21
21
|
│ ├── ExampleIntegration.ts # Example implementation
|
|
22
22
|
│ └── index.ts # Module exports
|
|
23
23
|
├── core/ # Core framework integrations
|
|
24
|
-
│ └──
|
|
24
|
+
│ └── xray-integration.ts # Cross-framework integration
|
|
25
25
|
└── openclaw/ # External service integrations
|
|
26
26
|
├── index.ts
|
|
27
27
|
├── client.ts
|
|
@@ -48,7 +48,7 @@ async function loadV3PostProcessor() {
|
|
|
48
48
|
if (global.xrayPostProcessor && typeof global.xrayPostProcessor.executePostProcessorLoop === "function") {
|
|
49
49
|
return global.xrayPostProcessor;
|
|
50
50
|
}
|
|
51
|
-
//
|
|
51
|
+
// xrayPostProcessor fallback removed in v2.2
|
|
52
52
|
return null;
|
|
53
53
|
}
|
|
54
54
|
// ── Context Builder ────────────────────────────────────────────
|
|
@@ -302,7 +302,7 @@ async function loadStateManager() {
|
|
|
302
302
|
const global = globalThis;
|
|
303
303
|
if (global.xrayStateManager)
|
|
304
304
|
return global.xrayStateManager;
|
|
305
|
-
//
|
|
305
|
+
// xrayStateManager fallback removed in v2.2
|
|
306
306
|
const candidatePaths = [
|
|
307
307
|
() => import("../state/state-manager.js"),
|
|
308
308
|
() => import("../../node_modules/0xray/dist/state/state-manager.js"),
|
|
@@ -283,7 +283,7 @@ export class InferenceGovernanceIntegration extends BaseIntegration {
|
|
|
283
283
|
*/
|
|
284
284
|
async loadConfig() {
|
|
285
285
|
try {
|
|
286
|
-
const configPath = path.join(process.cwd(), '.
|
|
286
|
+
const configPath = path.join(process.cwd(), '.xray', 'features.json');
|
|
287
287
|
if (!fs.existsSync(configPath)) {
|
|
288
288
|
await this.log('warning', 'features.json not found, using defaults');
|
|
289
289
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Grok CLI Integration for
|
|
2
|
+
* Grok CLI Integration for 0xRay
|
|
3
3
|
*
|
|
4
4
|
* This module provides the integration points for using 0xRay with the official Grok CLI.
|
|
5
5
|
*
|
|
@@ -18,6 +18,7 @@ import { frameworkLogger } from '../../core/framework-logger.js';
|
|
|
18
18
|
import fs from 'fs';
|
|
19
19
|
import path from 'path';
|
|
20
20
|
import { execSync } from 'child_process';
|
|
21
|
+
import { syncBuiltinSkills } from '../../cli/commands/skill-install.js';
|
|
21
22
|
// ESM-compatible __dirname (this file is compiled to ESM)
|
|
22
23
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
23
24
|
export async function installForGrokCLI(options = {}) {
|
|
@@ -47,6 +48,13 @@ export async function installForGrokCLI(options = {}) {
|
|
|
47
48
|
fs.cpSync(sourceDir, targetPluginDir, { recursive: true, force: true });
|
|
48
49
|
frameworkLogger.log('grok-integration', 'plugin-copied', 'info', { destination: targetPluginDir });
|
|
49
50
|
console.log(`\x1b[32m✓ Copied Grok plugin to ${targetPluginDir}\x1b[0m`);
|
|
51
|
+
// Sync builtin skills to Grok plugin skills dir
|
|
52
|
+
const grokSkillsDir = path.join(targetPluginDir, 'skills');
|
|
53
|
+
const skillsCopied = syncBuiltinSkills(grokSkillsDir);
|
|
54
|
+
if (skillsCopied > 0) {
|
|
55
|
+
console.log(`\x1b[32m✓ Synced ${skillsCopied} builtin skills to Grok plugin\x1b[0m`);
|
|
56
|
+
}
|
|
57
|
+
frameworkLogger.log('grok-integration', 'skills-synced', 'info', { count: skillsCopied });
|
|
50
58
|
// Attempt auto-trust (best effort)
|
|
51
59
|
try {
|
|
52
60
|
execSync(`grok plugins trust "${targetPluginDir}"`, { stdio: 'ignore' });
|
|
@@ -59,15 +67,21 @@ export async function installForGrokCLI(options = {}) {
|
|
|
59
67
|
// Register MCP servers via grok mcp add (most reliable mechanism)
|
|
60
68
|
const govMcpPath = path.resolve(__dirname, '..', '..', '..', 'dist/mcps/governance.server.js');
|
|
61
69
|
const skillsMcpPath = path.resolve(__dirname, '..', '..', '..', 'dist/mcps/knowledge-skills/skill-invocation.server.js');
|
|
70
|
+
const orchMcpPath = path.resolve(__dirname, '..', '..', '..', 'dist/mcps/orchestrator.server.js');
|
|
71
|
+
const enforcerMcpPath = path.resolve(__dirname, '..', '..', '..', 'dist/mcps/enforcer-tools.server.js');
|
|
62
72
|
try {
|
|
63
|
-
execSync(`grok mcp add
|
|
64
|
-
execSync(`grok mcp add
|
|
65
|
-
|
|
73
|
+
execSync(`grok mcp add xray-governance --command node --args "${govMcpPath}" --env "XRAY_FORCE_MCP_GOVERNANCE=true" --env "XRAY_ROOT=${process.cwd()}"`, { stdio: 'pipe' });
|
|
74
|
+
execSync(`grok mcp add xray-skills --command node --args "${skillsMcpPath}" --env "XRAY_ROOT=${process.cwd()}"`, { stdio: 'pipe' });
|
|
75
|
+
execSync(`grok mcp add xray-orchestrator --command node --args "${orchMcpPath}" --env "XRAY_ROOT=${process.cwd()}"`, { stdio: 'pipe' });
|
|
76
|
+
execSync(`grok mcp add xray-enforcer --command node --args "${enforcerMcpPath}" --env "XRAY_ROOT=${process.cwd()}"`, { stdio: 'pipe' });
|
|
77
|
+
console.log('\x1b[32m✓ Registered xray MCP servers with Grok CLI\x1b[0m');
|
|
66
78
|
}
|
|
67
79
|
catch {
|
|
68
80
|
console.log('\nCould not auto-register MCP servers. Run manually:');
|
|
69
|
-
console.log(` grok mcp add
|
|
70
|
-
console.log(` grok mcp add
|
|
81
|
+
console.log(` grok mcp add xray-governance --command node --args "${govMcpPath}"`);
|
|
82
|
+
console.log(` grok mcp add xray-skills --command node --args "${skillsMcpPath}"`);
|
|
83
|
+
console.log(` grok mcp add xray-orchestrator --command node --args "${orchMcpPath}"`);
|
|
84
|
+
console.log(` grok mcp add xray-enforcer --command node --args "${enforcerMcpPath}"`);
|
|
71
85
|
}
|
|
72
86
|
console.log('\n✅ 0xRay is now installed as a first-class Grok CLI plugin!');
|
|
73
87
|
console.log('Restart Grok or run `grok` to load the new hooks and MCP servers.');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Grok CLI PreToolUse Hook Handler for
|
|
3
|
+
* Grok CLI PreToolUse Hook Handler for 0xRay — First Class Citizen
|
|
4
4
|
*
|
|
5
5
|
* Real governance enforcement hook.
|
|
6
6
|
* When Grok is about to execute a tool (write_file, edit, terminal cmd, etc.),
|
|
@@ -16,7 +16,7 @@ function findGovernanceCore() {
|
|
|
16
16
|
const here = path.dirname(new URL(import.meta.url).pathname);
|
|
17
17
|
|
|
18
18
|
// Priority: explicit dev root
|
|
19
|
-
const devRoot = process.env.
|
|
19
|
+
const devRoot = process.env.XRAY_ROOT;
|
|
20
20
|
if (devRoot) {
|
|
21
21
|
const devCandidate = path.resolve(devRoot, 'dist/governance/governance-core.js');
|
|
22
22
|
if (fs.existsSync(devCandidate)) return devCandidate;
|
|
@@ -49,7 +49,7 @@ function walkUpForCore(startDir, maxLevels = 8) {
|
|
|
49
49
|
if (fs.existsSync(pkgPath)) {
|
|
50
50
|
try {
|
|
51
51
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
52
|
-
if (pkg.name === '
|
|
52
|
+
if (pkg.name === '0xray') {
|
|
53
53
|
results.push(path.resolve(current, 'dist/governance/governance-core.js'));
|
|
54
54
|
results.push(path.resolve(current, 'governance/governance-core.js'));
|
|
55
55
|
}
|
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mcpServers": {
|
|
3
|
-
"
|
|
3
|
+
"xray-governance": {
|
|
4
4
|
"command": "npx",
|
|
5
5
|
"args": ["-y", "0xray", "mcp", "governance"],
|
|
6
6
|
"env": {
|
|
7
7
|
"XRAY_FORCE_MCP_GOVERNANCE": "true"
|
|
8
8
|
}
|
|
9
9
|
},
|
|
10
|
-
"
|
|
10
|
+
"xray-skills": {
|
|
11
11
|
"command": "npx",
|
|
12
12
|
"args": ["-y", "0xray", "mcp", "skills"]
|
|
13
13
|
},
|
|
14
|
-
"
|
|
14
|
+
"xray-orchestrator": {
|
|
15
15
|
"command": "npx",
|
|
16
16
|
"args": ["-y", "0xray", "mcp", "orchestrator"]
|
|
17
17
|
},
|
|
18
|
-
"
|
|
18
|
+
"xray-enforcer": {
|
|
19
19
|
"command": "npx",
|
|
20
20
|
"args": ["-y", "0xray", "mcp", "enforcer"]
|
|
21
|
+
},
|
|
22
|
+
"xray-researcher": {
|
|
23
|
+
"command": "npx",
|
|
24
|
+
"args": ["-y", "0xray", "mcp", "researcher"]
|
|
25
|
+
},
|
|
26
|
+
"xray-code-review": {
|
|
27
|
+
"command": "npx",
|
|
28
|
+
"args": ["-y", "0xray", "mcp", "code-review"]
|
|
29
|
+
},
|
|
30
|
+
"xray-architect-tools": {
|
|
31
|
+
"command": "npx",
|
|
32
|
+
"args": ["-y", "0xray", "mcp", "architect-tools"]
|
|
21
33
|
}
|
|
22
34
|
}
|
|
23
35
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node",
|
|
10
10
|
"args": [
|
|
11
|
-
"${
|
|
11
|
+
"${XRAY_AI_PATH:-node_modules/0xray}/dist/integrations/grok/hooks/pre-tool-use.js"
|
|
12
12
|
],
|
|
13
13
|
"timeout": 30000
|
|
14
14
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
{
|
|
22
22
|
"type": "command",
|
|
23
23
|
"command": "echo",
|
|
24
|
-
"args": ["[0xRay] Grok session started with
|
|
24
|
+
"args": ["[0xRay] Grok session started with 0xRay governance enabled"]
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
}
|
|
@@ -36,25 +36,24 @@ logger = logging.getLogger("xray-hermes")
|
|
|
36
36
|
PLUGIN_DIR = Path(__file__).resolve().parent
|
|
37
37
|
BRIDGE_PATH = PLUGIN_DIR / "bridge.mjs"
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
def _find_project_root() -> Path:
|
|
40
|
+
"""Walk up from cwd to find project root."""
|
|
41
|
+
cwd = Path.cwd()
|
|
42
|
+
home = Path.home()
|
|
43
|
+
override = os.environ.get("XRAY_PROJECT_ROOT")
|
|
44
|
+
if override:
|
|
45
|
+
return Path(override).resolve()
|
|
46
|
+
d = cwd
|
|
47
|
+
while True:
|
|
48
|
+
if (d / "node_modules" / "0xray" / "package.json").exists():
|
|
47
49
|
return d
|
|
48
|
-
|
|
49
|
-
if (d / ".opencode" / "xray" / "features.json").exists():
|
|
50
|
+
if (d / ".xray" / "features.json").exists():
|
|
50
51
|
return d
|
|
51
|
-
# package.json but not home dir
|
|
52
52
|
if d != home and (d / "package.json").exists():
|
|
53
53
|
return d
|
|
54
54
|
d = d.parent
|
|
55
55
|
if d == d.parent:
|
|
56
56
|
break
|
|
57
|
-
|
|
58
57
|
return cwd
|
|
59
58
|
|
|
60
59
|
PROJECT_ROOT = _find_project_root()
|
|
@@ -682,6 +681,18 @@ def register(ctx):
|
|
|
682
681
|
schema=schemas.XRAY_HOOKS,
|
|
683
682
|
handler=tools.xray_hooks,
|
|
684
683
|
)
|
|
684
|
+
ctx.register_tool(
|
|
685
|
+
name="xray_skill_install",
|
|
686
|
+
toolset="xray-hermes",
|
|
687
|
+
schema=schemas.XRAY_SKILL_INSTALL,
|
|
688
|
+
handler=tools.xray_skill_install,
|
|
689
|
+
)
|
|
690
|
+
ctx.register_tool(
|
|
691
|
+
name="xray_skill_registry",
|
|
692
|
+
toolset="xray-hermes",
|
|
693
|
+
schema=schemas.XRAY_SKILL_REGISTRY,
|
|
694
|
+
handler=tools.xray_skill_registry,
|
|
695
|
+
)
|
|
685
696
|
|
|
686
697
|
# ── Register hooks ────────────────────────────────────────
|
|
687
698
|
ctx.register_hook("pre_tool_call", _on_pre_tool_call)
|
|
@@ -709,10 +720,10 @@ def register(ctx):
|
|
|
709
720
|
_ensure_log_dir()
|
|
710
721
|
_log_to_file("activity.log",
|
|
711
722
|
f"[plugin-loaded] Xray Hermes Plugin v2.2 — "
|
|
712
|
-
f"
|
|
723
|
+
f"6 tools, 2 hooks, subagent enforcement, bridge={BRIDGE_PATH.exists()}")
|
|
713
724
|
|
|
714
725
|
logger.info(
|
|
715
|
-
"[xray] Plugin v2.2 loaded:
|
|
726
|
+
"[xray] Plugin v2.2 loaded: 6 tools, 2 hooks, "
|
|
716
727
|
"subagent enforcement active, bridge=%s",
|
|
717
728
|
BRIDGE_PATH.exists(),
|
|
718
729
|
)
|
|
@@ -58,7 +58,7 @@ function findProjectRoot() {
|
|
|
58
58
|
|
|
59
59
|
const candidates = [
|
|
60
60
|
process.cwd(),
|
|
61
|
-
join(homedir(), "dev", "
|
|
61
|
+
join(homedir(), "dev", "xray"),
|
|
62
62
|
join(dirname(__dirname), "..", "..", "..", ".."), // plugin dir -> project root
|
|
63
63
|
];
|
|
64
64
|
|
|
@@ -582,7 +582,7 @@ function handleHooks(input, projectRoot) {
|
|
|
582
582
|
} else {
|
|
583
583
|
try {
|
|
584
584
|
const content = readFileSync(gitHook, "utf-8");
|
|
585
|
-
if (content.includes("Xray") || content.includes("xray") ||
|
|
585
|
+
if (content.includes("Xray") || content.includes("xray") || false || content.includes("run-hook.js")) {
|
|
586
586
|
result.managed.push(hookName);
|
|
587
587
|
} else {
|
|
588
588
|
result.external.push(hookName);
|
|
@@ -626,7 +626,7 @@ function handleHooks(input, projectRoot) {
|
|
|
626
626
|
// Backup existing non-xray hooks
|
|
627
627
|
if (existsSync(dst)) {
|
|
628
628
|
const content = readFileSync(dst, "utf-8");
|
|
629
|
-
if (!content.includes("Xray") && !content.includes("xray") && !
|
|
629
|
+
if (!content.includes("Xray") && !content.includes("xray") && !false && !content.includes("run-hook.js")) {
|
|
630
630
|
renameSync(dst, `${dst}.xray-backup`);
|
|
631
631
|
} else {
|
|
632
632
|
unlinkSync(dst);
|
|
@@ -665,7 +665,7 @@ function handleHooks(input, projectRoot) {
|
|
|
665
665
|
|
|
666
666
|
try {
|
|
667
667
|
const content = readFileSync(dst, "utf-8");
|
|
668
|
-
const isXray = content.includes("Xray") || content.includes("xray") ||
|
|
668
|
+
const isXray = content.includes("Xray") || content.includes("xray") || false || content.includes("run-hook.js");
|
|
669
669
|
|
|
670
670
|
if (isXray || lstatSync(dst).isSymbolicLink()) {
|
|
671
671
|
unlinkSync(dst);
|
|
@@ -743,8 +743,37 @@ async function handleApply(input, projectRoot, logDir) {
|
|
|
743
743
|
// ── Known commands for positional-arg mode ──────────────────
|
|
744
744
|
const KNOWN_COMMANDS = new Set([
|
|
745
745
|
"health", "stats", "pre-process", "post-process", "validate", "codex-check", "hooks", "govern", "apply",
|
|
746
|
+
"skill-install", "skill-registry",
|
|
746
747
|
]);
|
|
747
748
|
|
|
749
|
+
// ── Skill management ──────────────────────────────────────────
|
|
750
|
+
|
|
751
|
+
async function handleSkillInstall(command, projectRoot, logDir) {
|
|
752
|
+
try {
|
|
753
|
+
const source = command.source;
|
|
754
|
+
if (!source) {
|
|
755
|
+
return { error: "Missing 'source' — specify a source name or git URL" };
|
|
756
|
+
}
|
|
757
|
+
const { execSync } = await import("child_process");
|
|
758
|
+
const output = execSync(`npx 0xray skill:install "${source}"`, { cwd: projectRoot, timeout: 120000 }).toString();
|
|
759
|
+
return { status: "ok", output: output.trim() };
|
|
760
|
+
} catch (error) {
|
|
761
|
+
return { error: `Skill install failed: ${error.message || error}` };
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
async function handleSkillRegistry(command, projectRoot, logDir) {
|
|
766
|
+
try {
|
|
767
|
+
const action = command.action || "list";
|
|
768
|
+
const { execSync } = await import("child_process");
|
|
769
|
+
const args = command.source ? `"${command.source}"` : "";
|
|
770
|
+
const output = execSync(`npx 0xray skill:registry ${action} ${args}`, { cwd: projectRoot, timeout: 30000 }).toString();
|
|
771
|
+
return { status: "ok", output: output.trim() };
|
|
772
|
+
} catch (error) {
|
|
773
|
+
return { error: `Skill registry command failed: ${error.message || error}` };
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
748
777
|
// ── Main ─────────────────────────────────────────────────────
|
|
749
778
|
async function main() {
|
|
750
779
|
// Parse --cwd flag and detect positional command arg
|
|
@@ -836,6 +865,12 @@ async function main() {
|
|
|
836
865
|
case "apply":
|
|
837
866
|
response = await handleApply(command, projectRoot, logDir);
|
|
838
867
|
break;
|
|
868
|
+
case "skill-install":
|
|
869
|
+
response = await handleSkillInstall(command, projectRoot, logDir);
|
|
870
|
+
break;
|
|
871
|
+
case "skill-registry":
|
|
872
|
+
response = await handleSkillRegistry(command, projectRoot, logDir);
|
|
873
|
+
break;
|
|
839
874
|
default:
|
|
840
875
|
response = { error: `Unknown command: ${cmd}` };
|
|
841
876
|
}
|
|
@@ -70,6 +70,55 @@ XRAY_HEALTH = {
|
|
|
70
70
|
},
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
XRAY_SKILL_INSTALL = {
|
|
74
|
+
"name": "xray_skill_install",
|
|
75
|
+
"description": (
|
|
76
|
+
"Install skills from the registry or any git repo. "
|
|
77
|
+
"Downloads skill definitions for specialized capabilities "
|
|
78
|
+
"like UI/UX design, mobile development, security auditing, etc. "
|
|
79
|
+
"Use this to add new skills to your development environment."
|
|
80
|
+
),
|
|
81
|
+
"parameters": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"properties": {
|
|
84
|
+
"source": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"description": "Source name or git URL to install skills from",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
"required": ["source"],
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
XRAY_SKILL_REGISTRY = {
|
|
94
|
+
"name": "xray_skill_registry",
|
|
95
|
+
"description": (
|
|
96
|
+
"Manage the skills registry — list available sources, "
|
|
97
|
+
"add new sources, or remove existing ones. Use 'list' to see "
|
|
98
|
+
"all available skill sources, 'add' to register a new source, "
|
|
99
|
+
"'remove' to unregister an existing source."
|
|
100
|
+
),
|
|
101
|
+
"parameters": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"properties": {
|
|
104
|
+
"action": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"enum": ["list", "add", "remove"],
|
|
107
|
+
"description": "Registry action to perform",
|
|
108
|
+
},
|
|
109
|
+
"name": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"description": "Source name (required for add/remove)",
|
|
112
|
+
},
|
|
113
|
+
"url": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"description": "Repository URL (required for add)",
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
"required": ["action"],
|
|
119
|
+
},
|
|
120
|
+
}
|
|
121
|
+
|
|
73
122
|
XRAY_HOOKS = {
|
|
74
123
|
"name": "xray_hooks",
|
|
75
124
|
"description": (
|
|
@@ -81,7 +81,7 @@ class TestSchemas(unittest.TestCase):
|
|
|
81
81
|
self.assertTrue(len(schema["description"]) > 20, f"{name}")
|
|
82
82
|
|
|
83
83
|
|
|
84
|
-
class
|
|
84
|
+
class TestRunXrayHelper(unittest.TestCase):
|
|
85
85
|
"""Test the CLI fallback helper (still exists for bridge-less environments)."""
|
|
86
86
|
|
|
87
87
|
def test_successful_command(self):
|
|
@@ -143,7 +143,7 @@ class TestBridgeHelper(unittest.TestCase):
|
|
|
143
143
|
self.assertIn("timed out", r["error"])
|
|
144
144
|
|
|
145
145
|
|
|
146
|
-
class
|
|
146
|
+
class TestXrayHealth(unittest.TestCase):
|
|
147
147
|
def test_health_via_bridge(self):
|
|
148
148
|
"""v2: health uses bridge first."""
|
|
149
149
|
with patch.object(tools_mod, "_bridge_call", return_value={"status": "ok", "framework": "loaded", "version": "1.15.0", "components": {}}) as m:
|
|
@@ -165,7 +165,7 @@ class TestStrrayHealth(unittest.TestCase):
|
|
|
165
165
|
self.assertEqual(r["status"], "ok")
|
|
166
166
|
|
|
167
167
|
|
|
168
|
-
class
|
|
168
|
+
class TestXrayValidate(unittest.TestCase):
|
|
169
169
|
def test_with_files_via_bridge(self):
|
|
170
170
|
"""v2: validate uses bridge first."""
|
|
171
171
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": True, "fileResults": []}) as m:
|
|
@@ -208,7 +208,7 @@ class TestStrrayValidate(unittest.TestCase):
|
|
|
208
208
|
self.assertEqual(r["files_checked"], 100)
|
|
209
209
|
|
|
210
210
|
|
|
211
|
-
class
|
|
211
|
+
class TestXrayCodexCheck(unittest.TestCase):
|
|
212
212
|
def test_with_code_via_bridge(self):
|
|
213
213
|
"""v2: codex check uses bridge for real quality gate analysis."""
|
|
214
214
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": True, "violations": [], "checks": []}) as m:
|
|
@@ -656,7 +656,7 @@ class TestLiveBridge(unittest.TestCase):
|
|
|
656
656
|
if not bridge_path.exists():
|
|
657
657
|
self.skipTest("bridge.mjs not built yet")
|
|
658
658
|
|
|
659
|
-
# Use
|
|
659
|
+
# Use xray dev repo as project root (has package.json)
|
|
660
660
|
xray_root = str(Path(PLUGIN_DIR).parent.parent.parent / "dev" / "xray")
|
|
661
661
|
cwd = xray_root if Path(xray_root).exists() else PLUGIN_DIR
|
|
662
662
|
|
|
@@ -945,7 +945,7 @@ class TestBridgeHelperTimeoutDefault(unittest.TestCase):
|
|
|
945
945
|
self.assertEqual(m.call_args[1]["timeout"], 5)
|
|
946
946
|
|
|
947
947
|
|
|
948
|
-
class
|
|
948
|
+
class TestXrayHooksTool(unittest.TestCase):
|
|
949
949
|
"""Tests for the xray_hooks tool."""
|
|
950
950
|
|
|
951
951
|
def test_list_via_bridge(self):
|
|
@@ -1018,7 +1018,7 @@ class TestStrrayHooksTool(unittest.TestCase):
|
|
|
1018
1018
|
self.assertEqual(call_cmd["action"], "list")
|
|
1019
1019
|
|
|
1020
1020
|
|
|
1021
|
-
class
|
|
1021
|
+
class TestXrayHooksSchema(unittest.TestCase):
|
|
1022
1022
|
"""Tests for the XRAY_HOOKS schema."""
|
|
1023
1023
|
|
|
1024
1024
|
def test_schema_has_required_fields(self):
|