0xray 2.0.0 → 2.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/codex.codex +2 -2
- package/.opencode/commands/dependency-audit.md +3 -3
- package/.opencode/enforcer-config.json +2 -2
- package/.opencode/init.sh +22 -19
- package/AGENTS.md +6 -6
- package/README.md +276 -76
- package/dist/AGENTS.md +6 -6
- package/dist/CHANGELOG.md +91 -10
- package/dist/README.md +276 -76
- package/dist/agents/architect.d.ts +2 -0
- package/dist/agents/backend-engineer.d.ts +8 -0
- package/dist/agents/bug-triage-specialist.d.ts +2 -0
- package/dist/agents/code-analyzer.d.ts +7 -0
- package/dist/agents/code-reviewer.d.ts +2 -0
- package/dist/agents/code-reviewer.js +1 -1
- package/dist/agents/content-creator.d.ts +9 -0
- package/dist/agents/database-engineer.d.ts +8 -0
- package/dist/agents/devops-engineer.d.ts +8 -0
- package/dist/agents/frontend-engineer.d.ts +8 -0
- package/dist/agents/frontend-ui-ux-engineer.d.ts +8 -0
- package/dist/agents/growth-strategist.d.ts +8 -0
- package/dist/agents/index.d.ts +24 -0
- package/dist/agents/librarian-agents-updater.d.ts +30 -0
- package/dist/agents/log-monitor.d.ts +2 -0
- package/dist/agents/mobile-developer.d.ts +9 -0
- package/dist/agents/multimodal-looker.d.ts +9 -0
- package/dist/agents/performance-engineer.d.ts +8 -0
- package/dist/agents/refactorer.d.ts +2 -0
- package/dist/agents/registry.d.ts +35 -0
- package/dist/agents/researcher.d.ts +2 -0
- package/dist/agents/security-auditor.d.ts +2 -0
- package/dist/agents/seo-consultant.d.ts +8 -0
- package/dist/agents/strategist.d.ts +7 -0
- package/dist/agents/tech-writer.d.ts +8 -0
- package/dist/agents/testing-lead.d.ts +2 -0
- package/dist/agents/types.d.ts +45 -0
- package/dist/analytics/consent-manager.d.ts +93 -0
- package/dist/analytics/emerging-pattern-detector.d.ts +67 -0
- package/dist/analytics/pattern-learning-engine.d.ts +80 -0
- package/dist/analytics/pattern-performance-tracker.d.ts +97 -0
- package/dist/analytics/predictive-analytics.d.ts +41 -0
- package/dist/analytics/prompt-pattern-analyzer.d.ts +99 -0
- package/dist/analytics/routing-performance-analyzer.d.ts +101 -0
- package/dist/analytics/routing-refiner.d.ts +104 -0
- package/dist/analytics/routing-refiner.js +1 -1
- package/dist/analytics/simple-pattern-analyzer.d.ts +80 -0
- package/dist/architect/architect-tools.d.ts +70 -0
- package/dist/architect/architectural-integrity.d.ts +20 -0
- package/dist/benchmark/performance-benchmark.d.ts +103 -0
- package/dist/benchmark/performance-benchmark.js +3 -3
- package/dist/cli/commands/analytics-disable.d.ts +9 -0
- package/dist/cli/commands/analytics-enable-action.d.ts +8 -0
- package/dist/cli/commands/analytics-preview.d.ts +9 -0
- package/dist/cli/commands/analytics-status.d.ts +9 -0
- package/dist/cli/commands/antigravity-status.d.ts +9 -0
- package/dist/cli/commands/archive-logs.d.ts +24 -0
- package/dist/cli/commands/credible-init.d.ts +11 -0
- package/dist/cli/commands/grok-install.d.ts +7 -0
- package/dist/cli/commands/hermes-install.d.ts +2 -0
- package/dist/cli/commands/hermes-install.js +4 -4
- package/dist/cli/commands/mcp-install.d.ts +4 -0
- package/dist/cli/commands/mcp-install.js +1 -1
- package/dist/cli/commands/openclaw-install.d.ts +2 -0
- package/dist/cli/commands/openclaw-install.js +1 -1
- package/dist/cli/commands/opencode-install.d.ts +2 -0
- package/dist/cli/commands/plugin-commands.d.ts +19 -0
- package/dist/cli/commands/plugin-commands.js +2 -2
- package/dist/cli/commands/publish-agent.d.ts +15 -0
- package/dist/cli/commands/publish-agent.js +5 -5
- package/dist/cli/commands/security-audit.d.ts +23 -0
- package/dist/cli/commands/skill-install.d.ts +5 -0
- package/dist/cli/commands/skill-install.js +1 -1
- package/dist/cli/commands/status.d.ts +41 -0
- package/dist/cli/commands/status.js +3 -3
- package/dist/cli/commands/storyteller.d.ts +19 -0
- package/dist/cli/commands/storyteller.js +2 -2
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.js +8 -8
- package/dist/cli/server.d.ts +1 -0
- package/dist/cli/server.js +1 -1
- package/dist/config/default-agents.d.ts +12 -0
- package/dist/core/activity-logger.d.ts +72 -0
- package/dist/core/adaptive-kernel.d.ts +109 -0
- package/dist/core/agent-spawn-gate.d.ts +56 -0
- package/dist/core/agent-spawn-gate.js +1 -1
- package/dist/core/boot-orchestrator.d.ts +99 -0
- package/dist/core/boot-orchestrator.js +28 -28
- package/dist/core/bridge.mjs +22 -22
- package/dist/core/codex-formatter.d.ts +96 -0
- package/dist/core/codex-formatter.js +2 -2
- package/dist/core/codex-injector.d.ts +75 -0
- package/dist/core/codex-injector.js +11 -10
- package/dist/core/config-loader.d.ts +71 -0
- package/dist/core/config-loader.js +4 -2
- package/dist/core/config-paths.d.ts +62 -0
- package/dist/core/config-paths.js +24 -23
- package/dist/core/context-loader.d.ts +122 -0
- package/dist/core/context-loader.js +7 -5
- package/dist/core/context-validator.d.ts +53 -0
- package/dist/core/features-config.d.ts +462 -0
- package/dist/core/features-config.js +1 -1
- package/dist/core/framework-logger.d.ts +76 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +1 -1
- package/dist/core/kernel-patterns.d.ts +130 -0
- package/dist/core/logging-config.d.ts +10 -0
- package/dist/core/model-router.d.ts +61 -0
- package/dist/core/orchestrator.d.ts +72 -0
- package/dist/core/orchestrator.js +3 -2
- package/dist/core/system-prompt-generator.d.ts +35 -0
- package/dist/core/system-prompt-generator.js +2 -2
- package/dist/core/trace-context.d.ts +12 -0
- package/dist/core/xray-activation.d.ts +14 -0
- package/dist/core/xray-activation.js +29 -24
- package/dist/delegation/agent-delegator.d.ts +186 -0
- package/dist/delegation/agent-delegator.js +3 -3
- package/dist/delegation/agent-expertise.d.ts +16 -0
- package/dist/delegation/analytics/index.d.ts +12 -0
- package/dist/delegation/analytics/learning-engine.d.ts +85 -0
- package/dist/delegation/analytics/outcome-tracker.d.ts +118 -0
- package/dist/delegation/analytics/routing-analytics.d.ts +61 -0
- package/dist/delegation/ast-code-parser.d.ts +174 -0
- package/dist/delegation/codebase-context-analyzer.d.ts +164 -0
- package/dist/delegation/complexity-analyzer.d.ts +111 -0
- package/dist/delegation/complexity-core.d.ts +119 -0
- package/dist/delegation/config/types.d.ts +247 -0
- package/dist/delegation/dependency-graph-builder.d.ts +95 -0
- package/dist/delegation/index.d.ts +25 -0
- package/dist/delegation/metrics-aggregator.d.ts +92 -0
- package/dist/delegation/session-coordinator.d.ts +133 -0
- package/dist/delegation/strategy-selector.d.ts +28 -0
- package/dist/delegation/voting-coordinator.d.ts +49 -0
- package/dist/delegation/voting-types.d.ts +155 -0
- package/dist/delegation/weighted-voting-aggregator.d.ts +37 -0
- package/dist/enforcement/core/index.d.ts +15 -0
- package/dist/enforcement/core/rule-executor.d.ts +158 -0
- package/dist/enforcement/core/rule-hierarchy.d.ts +146 -0
- package/dist/enforcement/core/rule-registry.d.ts +197 -0
- package/dist/enforcement/core/violation-fixer.d.ts +106 -0
- package/dist/enforcement/enforcer-tools.d.ts +78 -0
- package/dist/enforcement/enforcer-tools.js +2 -2
- package/dist/enforcement/index.d.ts +23 -0
- package/dist/enforcement/loaders/agent-triage-loader.d.ts +99 -0
- package/dist/enforcement/loaders/agents-md-validation-loader.d.ts +76 -0
- package/dist/enforcement/loaders/base-loader.d.ts +83 -0
- package/dist/enforcement/loaders/codex-loader.d.ts +77 -0
- package/dist/enforcement/loaders/codex-loader.js +2 -2
- package/dist/enforcement/loaders/index.d.ts +37 -0
- package/dist/enforcement/loaders/loader-orchestrator.d.ts +97 -0
- package/dist/enforcement/loaders/processor-loader.d.ts +60 -0
- package/dist/enforcement/rule-enforcer.d.ts +142 -0
- package/dist/enforcement/test-auto-healing.d.ts +83 -0
- package/dist/enforcement/types.d.ts +501 -0
- package/dist/enforcement/validators/architecture-validators.d.ts +155 -0
- package/dist/enforcement/validators/base-validator.d.ts +88 -0
- package/dist/enforcement/validators/code-quality-validators.d.ts +89 -0
- package/dist/enforcement/validators/index.d.ts +15 -0
- package/dist/enforcement/validators/security-validators.d.ts +53 -0
- package/dist/enforcement/validators/testing-validators.d.ts +81 -0
- package/dist/enforcement/validators/validator-registry.d.ts +92 -0
- package/dist/execution/opencode-cli-invoker.d.ts +8 -0
- package/dist/execution/proposal-applier.d.ts +24 -0
- package/dist/governance/codex-policy.service.d.ts +57 -0
- package/dist/governance/governance-core.d.ts +46 -0
- package/dist/governance/governance-service.d.ts +38 -0
- package/dist/governance/governance-types.d.ts +83 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +6 -6
- package/dist/inference/deploy-verifier.d.ts +26 -0
- package/dist/inference/deploy-verifier.js +1 -1
- package/dist/inference/index.d.ts +10 -0
- package/dist/inference/inference-accumulator.d.ts +29 -0
- package/dist/inference/inference-cycle.d.ts +110 -0
- package/dist/inference/inference-cycle.js +7 -7
- package/dist/inference/semantic-patterns.d.ts +7 -0
- package/dist/inference/session-capture.d.ts +32 -0
- package/dist/integrations/base/ExampleIntegration.d.ts +47 -0
- package/dist/integrations/base/Integration.d.ts +267 -0
- package/dist/integrations/base/README.md +2 -2
- package/dist/integrations/base/index.d.ts +12 -0
- package/dist/integrations/base/registry.d.ts +273 -0
- package/dist/integrations/base/types.d.ts +168 -0
- package/dist/integrations/governance/governance-client.d.ts +76 -0
- package/dist/integrations/governance/index.d.ts +99 -0
- package/dist/integrations/governance/index.js +1 -1
- package/dist/integrations/governance/types.d.ts +239 -0
- package/dist/integrations/grok/grok-cli.d.ts +25 -0
- package/dist/integrations/grok/grok-cli.js +6 -6
- package/dist/integrations/grok/hooks/pre-tool-use.js +1 -1
- package/dist/integrations/grok/plugin/0xray/.mcp.json +3 -3
- package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +2 -2
- package/dist/integrations/hermes-agent/__init__.py +78 -72
- package/dist/integrations/hermes-agent/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/schemas.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/test_plugin.cpython-313-pytest-9.0.2.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/test_plugin.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/__pycache__/tools.cpython-313.pyc +0 -0
- package/dist/integrations/hermes-agent/after-install.md +14 -14
- package/dist/integrations/hermes-agent/bridge.mjs +14 -14
- package/dist/integrations/hermes-agent/logs/framework/routing-outcomes.json +1 -0
- 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 +128 -125
- package/dist/integrations/hermes-agent/tools.py +85 -23
- package/dist/integrations/openclaw/README.md +16 -16
- package/dist/integrations/openclaw/api-server.d.ts +87 -0
- package/dist/integrations/openclaw/api-server.js +9 -9
- package/dist/integrations/openclaw/client.d.ts +122 -0
- package/dist/integrations/openclaw/config.d.ts +96 -0
- package/dist/integrations/openclaw/config.js +1 -1
- package/dist/integrations/openclaw/hooks/xray-hooks.d.ts +124 -0
- package/dist/integrations/openclaw/index.d.ts +101 -0
- package/dist/integrations/openclaw/index.js +4 -4
- package/dist/integrations/openclaw/types.d.ts +426 -0
- package/dist/integrations/plugins/index.d.ts +10 -0
- package/dist/integrations/plugins/plugin-integration.d.ts +289 -0
- package/dist/integrations/plugins/plugin-registry.d.ts +224 -0
- package/dist/integrations/plugins/plugin-registry.js +2 -2
- package/dist/mcps/agent-resolver.d.ts +46 -0
- package/dist/mcps/architect-tools.server.d.ts +17 -0
- package/dist/mcps/architect-tools.server.js +4 -4
- package/dist/mcps/auto-format.server.d.ts +19 -0
- package/dist/mcps/auto-format.server.js +4 -4
- package/dist/mcps/boot-orchestrator.server.d.ts +49 -0
- package/dist/mcps/boot-orchestrator.server.js +4 -4
- package/dist/mcps/config/config-loader.d.ts +52 -0
- package/dist/mcps/config/config-validator.d.ts +40 -0
- package/dist/mcps/config/index.d.ts +31 -0
- package/dist/mcps/config/plugin-server-registry.d.ts +127 -0
- package/dist/mcps/config/server-config-registry.d.ts +51 -0
- package/dist/mcps/config/server-config-registry.js +7 -7
- package/dist/mcps/connection/connection-manager.d.ts +39 -0
- package/dist/mcps/connection/connection-pool.d.ts +64 -0
- package/dist/mcps/connection/mcp-connection.d.ts +66 -0
- package/dist/mcps/connection/mcp-connection.js +1 -1
- package/dist/mcps/connection/process-spawner.d.ts +24 -0
- package/dist/mcps/enforcer-tools.server.d.ts +27 -0
- package/dist/mcps/enforcer-tools.server.js +4 -4
- package/dist/mcps/estimation.server.d.ts +21 -0
- package/dist/mcps/estimation.server.js +1 -1
- package/dist/mcps/framework-compliance-audit.server.d.ts +22 -0
- package/dist/mcps/framework-compliance-audit.server.js +4 -4
- package/dist/mcps/framework-help.server.d.ts +14 -0
- package/dist/mcps/framework-help.server.js +7 -7
- package/dist/mcps/governance.server.d.ts +33 -0
- package/dist/mcps/in-process-skill-registry.d.ts +20 -0
- package/dist/mcps/in-process-skill-registry.js +6 -6
- package/dist/mcps/knowledge-skills/api-design.server.d.ts +15 -0
- package/dist/mcps/knowledge-skills/api-design.server.js +4 -4
- package/dist/mcps/knowledge-skills/architecture-patterns.server.d.ts +15 -0
- package/dist/mcps/knowledge-skills/architecture-patterns.server.js +4 -4
- package/dist/mcps/knowledge-skills/bug-triage-specialist.server.d.ts +33 -0
- package/dist/mcps/knowledge-skills/bug-triage-specialist.server.js +1 -1
- package/dist/mcps/knowledge-skills/code-analyzer.server.d.ts +31 -0
- package/dist/mcps/knowledge-skills/code-analyzer.server.js +1 -1
- package/dist/mcps/knowledge-skills/code-review.server.d.ts +46 -0
- package/dist/mcps/knowledge-skills/code-review.server.js +4 -4
- package/dist/mcps/knowledge-skills/content-creator.server.d.ts +13 -0
- package/dist/mcps/knowledge-skills/content-creator.server.js +1 -1
- package/dist/mcps/knowledge-skills/database-design.server.d.ts +43 -0
- package/dist/mcps/knowledge-skills/database-design.server.js +4 -4
- package/dist/mcps/knowledge-skills/devops-deployment.server.d.ts +43 -0
- package/dist/mcps/knowledge-skills/devops-deployment.server.js +4 -4
- package/dist/mcps/knowledge-skills/git-workflow.server.d.ts +15 -0
- package/dist/mcps/knowledge-skills/git-workflow.server.js +4 -4
- package/dist/mcps/knowledge-skills/growth-strategist.server.d.ts +13 -0
- package/dist/mcps/knowledge-skills/growth-strategist.server.js +1 -1
- package/dist/mcps/knowledge-skills/log-monitor.server.d.ts +24 -0
- package/dist/mcps/knowledge-skills/log-monitor.server.js +1 -1
- package/dist/mcps/knowledge-skills/mobile-development.server.d.ts +19 -0
- package/dist/mcps/knowledge-skills/mobile-development.server.js +4 -4
- package/dist/mcps/knowledge-skills/multimodal-looker.server.d.ts +55 -0
- package/dist/mcps/knowledge-skills/multimodal-looker.server.js +3 -2
- package/dist/mcps/knowledge-skills/performance-optimization.server.d.ts +72 -0
- package/dist/mcps/knowledge-skills/performance-optimization.server.js +4 -4
- package/dist/mcps/knowledge-skills/project-analysis.server.d.ts +37 -0
- package/dist/mcps/knowledge-skills/project-analysis.server.js +1 -1
- package/dist/mcps/knowledge-skills/refactoring-strategies.server.d.ts +33 -0
- package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +4 -4
- package/dist/mcps/knowledge-skills/security-audit.server.d.ts +48 -0
- package/dist/mcps/knowledge-skills/security-audit.server.js +4 -4
- package/dist/mcps/knowledge-skills/seo-consultant.server.d.ts +26 -0
- package/dist/mcps/knowledge-skills/seo-consultant.server.js +1 -1
- package/dist/mcps/knowledge-skills/session-management.server.d.ts +23 -0
- package/dist/mcps/knowledge-skills/session-management.server.js +1 -1
- package/dist/mcps/knowledge-skills/skill-invocation.server.d.ts +29 -0
- package/dist/mcps/knowledge-skills/skill-invocation.server.js +1 -1
- package/dist/mcps/knowledge-skills/strategist.server.d.ts +17 -0
- package/dist/mcps/knowledge-skills/strategist.server.js +1 -1
- package/dist/mcps/knowledge-skills/tech-writer.server.d.ts +47 -0
- package/dist/mcps/knowledge-skills/tech-writer.server.js +5 -5
- package/dist/mcps/knowledge-skills/testing-best-practices.server.d.ts +36 -0
- package/dist/mcps/knowledge-skills/testing-best-practices.server.js +4 -4
- package/dist/mcps/knowledge-skills/testing-strategy.server.d.ts +47 -0
- package/dist/mcps/knowledge-skills/testing-strategy.server.js +4 -4
- package/dist/mcps/knowledge-skills/ui-ux-design.server.d.ts +69 -0
- package/dist/mcps/knowledge-skills/ui-ux-design.server.js +6 -6
- package/dist/mcps/lint.server.d.ts +17 -0
- package/dist/mcps/lint.server.js +6 -6
- package/dist/mcps/mcp-client.d.ts +157 -0
- package/dist/mcps/mcp-client.js +3 -3
- package/dist/mcps/model-health-check.server.d.ts +16 -0
- package/dist/mcps/model-health-check.server.js +4 -4
- package/dist/mcps/orchestrator/config/agent-capabilities.d.ts +35 -0
- package/dist/mcps/orchestrator/execution/execution-planner.d.ts +62 -0
- package/dist/mcps/orchestrator/handlers/complexity-handler.d.ts +32 -0
- package/dist/mcps/orchestrator/handlers/status-handler.d.ts +69 -0
- package/dist/mcps/orchestrator/handlers/task-handler.d.ts +52 -0
- package/dist/mcps/orchestrator/server.d.ts +38 -0
- package/dist/mcps/orchestrator/server.js +2 -2
- package/dist/mcps/orchestrator/types.d.ts +79 -0
- package/dist/mcps/orchestrator.server.d.ts +10 -0
- package/dist/mcps/performance-analysis.server.d.ts +27 -0
- package/dist/mcps/performance-analysis.server.js +4 -4
- package/dist/mcps/processor-pipeline.server.d.ts +31 -0
- package/dist/mcps/processor-pipeline.server.js +4 -4
- package/dist/mcps/protocol/protocol-constants.d.ts +46 -0
- package/dist/mcps/registry.json +1 -1
- package/dist/mcps/researcher.server.d.ts +31 -0
- package/dist/mcps/researcher.server.js +5 -5
- package/dist/mcps/security-scan.server.d.ts +20 -0
- package/dist/mcps/security-scan.server.js +4 -4
- package/dist/mcps/simulation/index.d.ts +12 -0
- package/dist/mcps/simulation/server-simulations.d.ts +39 -0
- package/dist/mcps/simulation/server-simulations.js +3 -3
- package/dist/mcps/simulation/simulation-engine.d.ts +51 -0
- package/dist/mcps/state-manager.server.d.ts +28 -0
- package/dist/mcps/state-manager.server.js +1 -1
- package/dist/mcps/tools/index.d.ts +14 -0
- package/dist/mcps/tools/tool-cache.d.ts +53 -0
- package/dist/mcps/tools/tool-discovery.d.ts +27 -0
- package/dist/mcps/tools/tool-executor.d.ts +41 -0
- package/dist/mcps/tools/tool-registry.d.ts +42 -0
- package/dist/mcps/types/index.d.ts +13 -0
- package/dist/mcps/types/json-rpc.types.d.ts +35 -0
- package/dist/mcps/types/mcp.types.d.ts +105 -0
- package/dist/metrics/agent-metrics.d.ts +169 -0
- package/dist/metrics/agent-metrics.js +1 -1
- package/dist/metrics/index.d.ts +6 -0
- package/dist/monitoring/advanced-profiler.d.ts +51 -0
- package/dist/monitoring/memory-monitor.d.ts +113 -0
- package/dist/monitoring/nudge-watchdog.d.ts +88 -0
- package/dist/monitoring/test-auto-generation-monitor.d.ts +64 -0
- package/dist/orchestrator/agent-spawn-governor.d.ts +127 -0
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.d.ts +156 -0
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +2 -2
- package/dist/orchestrator/intelligent-commit-batcher.d.ts +114 -0
- package/dist/orchestrator/intelligent-commit-batcher.js +3 -3
- package/dist/orchestrator/multi-agent-orchestration-coordinator.d.ts +127 -0
- package/dist/orchestrator/multi-agent-orchestration-coordinator.js +9 -9
- package/dist/orchestrator/orchestrator.d.ts +143 -0
- package/dist/orchestrator/orchestrator.js +8 -6
- package/dist/orchestrator/self-direction-activation.d.ts +109 -0
- package/dist/orchestrator/universal-librarian-consultation.d.ts +98 -0
- package/dist/orchestrator/universal-registry-bridge.d.ts +85 -0
- package/dist/orchestrator/universal-registry-bridge.js +1 -1
- package/dist/performance/performance-budget-enforcer.d.ts +158 -0
- package/dist/performance/performance-regression-tester.d.ts +108 -0
- package/dist/plugin/xray-codex-injection.d.ts +55 -0
- package/dist/plugin/xray-codex-injection.js +15 -14
- package/dist/postprocessor/PostProcessor.d.ts +108 -0
- package/dist/postprocessor/PostProcessor.js +1 -1
- package/dist/postprocessor/analysis/FailureAnalysisEngine.d.ts +39 -0
- package/dist/postprocessor/autofix/AutoFixEngine.d.ts +48 -0
- package/dist/postprocessor/autofix/FixValidator.d.ts +23 -0
- package/dist/postprocessor/config.d.ts +6 -0
- package/dist/postprocessor/escalation/EscalationEngine.d.ts +154 -0
- package/dist/postprocessor/monitoring/MonitoringEngine.d.ts +40 -0
- package/dist/postprocessor/redeploy/RedeployCoordinator.d.ts +91 -0
- package/dist/postprocessor/services/RegressionAnalysisService.d.ts +40 -0
- package/dist/postprocessor/services/RegressionAnalysisService.js +2 -2
- package/dist/postprocessor/success/SuccessHandler.d.ts +57 -0
- package/dist/postprocessor/triggers/APITrigger.d.ts +35 -0
- package/dist/postprocessor/triggers/GitHookTrigger.d.ts +38 -0
- package/dist/postprocessor/triggers/GitHookTrigger.js +14 -14
- package/dist/postprocessor/triggers/WebhookTrigger.d.ts +47 -0
- package/dist/postprocessor/types.d.ts +227 -0
- package/dist/processors/doc-write-guard.d.ts +6 -0
- package/dist/processors/implementations/agents-md-validation-processor.d.ts +63 -0
- package/dist/processors/implementations/agents-md-validation-processor.js +2 -2
- package/dist/processors/implementations/async-pattern-processor.d.ts +48 -0
- package/dist/processors/implementations/codex-compliance-processor.d.ts +7 -0
- package/dist/processors/implementations/commit-batcher-processor.d.ts +13 -0
- package/dist/processors/implementations/console-log-guard-processor.d.ts +33 -0
- package/dist/processors/implementations/coverage-analysis-processor.d.ts +20 -0
- package/dist/processors/implementations/error-boundary-processor.d.ts +7 -0
- package/dist/processors/implementations/inference-improvement-processor.d.ts +36 -0
- package/dist/processors/implementations/inference-improvement-processor.js +2 -2
- package/dist/processors/implementations/log-protection-processor.d.ts +30 -0
- package/dist/processors/implementations/log-protection-processor.js +2 -2
- package/dist/processors/implementations/nudge-processor.d.ts +22 -0
- package/dist/processors/implementations/performance-budget-processor.d.ts +50 -0
- package/dist/processors/implementations/postprocessor-chain-validator.d.ts +46 -0
- package/dist/processors/implementations/pre-validate-processor.d.ts +7 -0
- package/dist/processors/implementations/publish-preflight-processor.d.ts +38 -0
- package/dist/processors/implementations/publish-preflight-processor.js +3 -3
- package/dist/processors/implementations/refactoring-logging-processor-wrapper.d.ts +7 -0
- package/dist/processors/implementations/refactoring-logging-processor.d.ts +31 -0
- package/dist/processors/implementations/regression-testing-processor.d.ts +20 -0
- package/dist/processors/implementations/regression-testing-processor.js +2 -2
- package/dist/processors/implementations/session-capture-processor.d.ts +14 -0
- package/dist/processors/implementations/session-summary-processor.d.ts +27 -0
- package/dist/processors/implementations/session-summary-processor.js +2 -2
- package/dist/processors/implementations/spawn-governance-processor.d.ts +58 -0
- package/dist/processors/implementations/state-validation-processor.d.ts +11 -0
- package/dist/processors/implementations/storytelling-trigger-processor.d.ts +42 -0
- package/dist/processors/implementations/storytelling-trigger-processor.js +2 -2
- package/dist/processors/implementations/test-auto-creation-processor.d.ts +17 -0
- package/dist/processors/implementations/test-execution-processor.d.ts +11 -0
- package/dist/processors/implementations/typescript-compilation-processor.d.ts +38 -0
- package/dist/processors/implementations/version-compliance-processor.d.ts +112 -0
- package/dist/processors/processor-interfaces.d.ts +127 -0
- package/dist/processors/processor-manager.d.ts +80 -0
- package/dist/processors/processor-types.d.ts +190 -0
- 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/framework-reporting-system.d.ts +19 -0
- package/dist/reporting/log-parser.d.ts +10 -0
- package/dist/reporting/metrics.d.ts +15 -0
- package/dist/reporting/report-formatter.d.ts +5 -0
- package/dist/reporting/report-formatter.js +1 -1
- package/dist/reporting/types.d.ts +102 -0
- package/dist/scripts/activate-kernel-pipeline.d.ts +7 -0
- package/dist/scripts/activate-kernel-pipeline.js +2 -2
- package/dist/scripts/integration.d.ts +37 -0
- package/dist/scripts/pre-command +1 -1
- package/dist/security/comprehensive-security-audit.d.ts +158 -0
- package/dist/security/index.d.ts +13 -0
- package/dist/security/prompt-security-validator.d.ts +44 -0
- package/dist/security/security-agent-coordinator.d.ts +72 -0
- package/dist/security/security-auditor.d.ts +56 -0
- package/dist/security/security-hardener.d.ts +62 -0
- package/dist/security/security-hardening-system.d.ts +239 -0
- package/dist/security/security-headers.d.ts +64 -0
- package/dist/security/security-orchestration-layer.d.ts +119 -0
- package/dist/security/security-scanner.d.ts +119 -0
- package/dist/services/inference-tuner.d.ts +77 -0
- package/dist/services/inference-tuner.js +2 -2
- package/dist/session/index.d.ts +3 -0
- package/dist/session/session-cleanup-manager.d.ts +118 -0
- package/dist/session/session-monitor.d.ts +133 -0
- package/dist/session/session-state-manager.d.ts +145 -0
- package/dist/skills/hermes-agent/SKILL.md +11 -11
- package/dist/skills/registry.json +1 -1
- package/dist/skills/storyteller/SKILL.md +1 -1
- package/dist/skills/xray-orchestrator/SKILL.md +141 -0
- package/dist/skills/xray-orchestrator/index.d.ts +13 -0
- package/dist/skills/xray-orchestrator/index.js +224 -0
- package/dist/state/context-providers.d.ts +4 -0
- package/dist/state/index.d.ts +5 -0
- package/dist/state/index.js +2 -1
- package/dist/state/state-manager.d.ts +42 -0
- package/dist/state/state-manager.js +5 -4
- package/dist/state/state-types.d.ts +5 -0
- package/dist/testing/memory-regression-suite.d.ts +105 -0
- package/dist/utils/batch-operations.d.ts +25 -0
- package/dist/utils/codex-parser.d.ts +61 -0
- package/dist/utils/command-runner.d.ts +32 -0
- package/dist/utils/import-resolver.d.ts +54 -0
- package/dist/utils/import-resolver.js +1 -1
- package/dist/utils/language-detector.d.ts +44 -0
- package/dist/utils/path-resolver.d.ts +48 -0
- package/dist/utils/path-resolver.js +2 -2
- package/dist/utils/shutdown-handler.d.ts +27 -0
- package/dist/utils/test-template-generator.d.ts +25 -0
- package/dist/utils/token-manager.d.ts +48 -0
- package/dist/utils/token-manager.js +1 -1
- package/dist/validation/estimation-validator.d.ts +61 -0
- package/dist/validation/estimation-validator.js +1 -1
- package/dist/validation/report-content-validator.d.ts +42 -0
- package/package.json +4 -3
- package/scripts/hooks/pre-command +1 -1
- package/scripts/hooks/run-hook.js +2 -2
- package/scripts/node/auto-reflection-generator.mjs +2 -2
- package/scripts/node/postinstall.cjs +1 -1
- package/scripts/node/release.js +6 -6
- package/scripts/node/release.mjs +10 -10
- package/scripts/node/universal-version-manager.js +53 -54
- package/scripts/node/version-manager.mjs +1 -1
- package/src/integrations/grok/plugin/0xray/.mcp.json +3 -3
- package/src/integrations/grok/plugin/0xray/hooks/hooks.json +2 -2
- package/src/mcps/architect-tools.server.ts +4 -4
- package/src/mcps/auto-format.server.ts +4 -4
- package/src/mcps/boot-orchestrator.server.ts +4 -4
- package/src/mcps/config/server-config-registry.ts +7 -7
- package/src/mcps/connection/mcp-connection.ts +1 -1
- package/src/mcps/enforcer-tools.server.ts +4 -4
- package/src/mcps/estimation.server.ts +1 -1
- package/src/mcps/framework-compliance-audit.server.ts +4 -4
- package/src/mcps/framework-help.server.ts +7 -7
- package/src/mcps/in-process-skill-registry.ts +6 -6
- package/src/mcps/knowledge-skills/api-design.server.test.ts +8 -8
- package/src/mcps/knowledge-skills/api-design.server.ts +4 -4
- package/src/mcps/knowledge-skills/architecture-patterns.server.ts +4 -4
- package/src/mcps/knowledge-skills/bug-triage-specialist.server.ts +1 -1
- package/src/mcps/knowledge-skills/code-analyzer.server.ts +1 -1
- package/src/mcps/knowledge-skills/code-review.server.ts +4 -4
- package/src/mcps/knowledge-skills/content-creator.server.ts +1 -1
- package/src/mcps/knowledge-skills/database-design.server.ts +4 -4
- package/src/mcps/knowledge-skills/devops-deployment.server.ts +4 -4
- package/src/mcps/knowledge-skills/git-workflow.server.ts +4 -4
- package/src/mcps/knowledge-skills/growth-strategist.server.ts +1 -1
- package/src/mcps/knowledge-skills/log-monitor.server.ts +1 -1
- package/src/mcps/knowledge-skills/mobile-development.server.ts +4 -4
- package/src/mcps/knowledge-skills/multimodal-looker.server.ts +3 -2
- package/src/mcps/knowledge-skills/performance-optimization.server.ts +4 -4
- package/src/mcps/knowledge-skills/project-analysis.server.ts +1 -1
- package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +4 -4
- package/src/mcps/knowledge-skills/security-audit.server.test.ts +23 -23
- package/src/mcps/knowledge-skills/security-audit.server.ts +4 -4
- package/src/mcps/knowledge-skills/seo-consultant.server.ts +1 -1
- package/src/mcps/knowledge-skills/session-management.server.ts +1 -1
- package/src/mcps/knowledge-skills/skill-invocation.server.ts +1 -1
- package/src/mcps/knowledge-skills/strategist.server.ts +1 -1
- package/src/mcps/knowledge-skills/tech-writer.server.ts +5 -5
- package/src/mcps/knowledge-skills/testing-best-practices.server.test.ts +28 -28
- package/src/mcps/knowledge-skills/testing-best-practices.server.ts +4 -4
- package/src/mcps/knowledge-skills/testing-strategy.server.test.ts +19 -19
- package/src/mcps/knowledge-skills/testing-strategy.server.ts +4 -4
- package/src/mcps/knowledge-skills/ui-ux-design.server.ts +6 -6
- package/src/mcps/lint.server.ts +6 -6
- package/src/mcps/mcp-client.ts +3 -3
- package/src/mcps/model-health-check.server.ts +4 -4
- package/src/mcps/orchestrator/server.ts +2 -2
- package/src/mcps/performance-analysis.server.ts +4 -4
- package/src/mcps/processor-pipeline.server.ts +4 -4
- package/src/mcps/registry.json +1 -1
- package/src/mcps/researcher.server.ts +5 -5
- package/src/mcps/security-scan.server.ts +4 -4
- package/src/mcps/simulation/server-simulations.ts +3 -3
- package/src/mcps/state-manager.server.ts +1 -1
- package/src/opencode/codex.codex +2 -2
- package/src/opencode/commands/dependency-audit.md +3 -3
- package/src/opencode/enforcer-config.json +2 -2
- package/src/skills/hermes-agent/SKILL.md +11 -11
- package/src/skills/registry.json +1 -1
- package/src/skills/storyteller/SKILL.md +1 -1
- package/src/skills/xray-orchestrator/SKILL.md +141 -0
- package/src/skills/xray-orchestrator/index.ts +268 -0
- package/.opencode/hooks/hook-metrics.json +0 -380
- package/.opencode/skills/api-design/SKILL.md +0 -37
- package/.opencode/skills/architect-tools/SKILL.md +0 -37
- package/.opencode/skills/architecture-patterns/SKILL.md +0 -37
- package/.opencode/skills/auto-format/SKILL.md +0 -37
- package/.opencode/skills/backend-engineer/SKILL.md +0 -49
- package/.opencode/skills/boot-orchestrator/SKILL.md +0 -37
- package/.opencode/skills/bug-triage/SKILL.md +0 -43
- package/.opencode/skills/code-analyzer/SKILL.md +0 -45
- package/.opencode/skills/code-review/SKILL.md +0 -52
- package/.opencode/skills/content-creator/SKILL.md +0 -38
- package/.opencode/skills/database-engineer/SKILL.md +0 -46
- package/.opencode/skills/devops-engineer/SKILL.md +0 -49
- package/.opencode/skills/enforcer/SKILL.md +0 -37
- package/.opencode/skills/framework-compliance-audit/SKILL.md +0 -37
- package/.opencode/skills/frontend-engineer/SKILL.md +0 -49
- package/.opencode/skills/frontend-ui-ux-engineer/SKILL.md +0 -41
- package/.opencode/skills/git-workflow/SKILL.md +0 -37
- package/.opencode/skills/growth-strategist/SKILL.md +0 -48
- package/.opencode/skills/hermes-agent/SKILL.md +0 -212
- package/.opencode/skills/inference-improve/SKILL.md +0 -97
- package/.opencode/skills/lint/SKILL.md +0 -37
- package/.opencode/skills/log-monitor/SKILL.md +0 -44
- package/.opencode/skills/mobile-developer/SKILL.md +0 -42
- package/.opencode/skills/model-health-check/SKILL.md +0 -37
- package/.opencode/skills/multimodal-looker/SKILL.md +0 -45
- package/.opencode/skills/orchestrator/SKILL.md +0 -37
- package/.opencode/skills/performance-analysis/SKILL.md +0 -37
- package/.opencode/skills/performance-engineer/SKILL.md +0 -41
- package/.opencode/skills/performance-optimization/SKILL.md +0 -37
- package/.opencode/skills/processor-pipeline/SKILL.md +0 -37
- package/.opencode/skills/project-analysis/SKILL.md +0 -42
- package/.opencode/skills/refactoring-strategies/SKILL.md +0 -37
- package/.opencode/skills/registry.json +0 -66
- package/.opencode/skills/researcher/SKILL.md +0 -37
- package/.opencode/skills/security-audit/SKILL.md +0 -47
- package/.opencode/skills/security-scan/SKILL.md +0 -37
- package/.opencode/skills/seo-consultant/SKILL.md +0 -43
- package/.opencode/skills/session-management/SKILL.md +0 -36
- package/.opencode/skills/state-manager/SKILL.md +0 -37
- package/.opencode/skills/storyteller/SKILL.md +0 -130
- package/.opencode/skills/strategist/SKILL.md +0 -32
- package/.opencode/skills/tech-writer/SKILL.md +0 -37
- package/.opencode/skills/testing-best-practices/SKILL.md +0 -37
- package/.opencode/skills/testing-strategy/SKILL.md +0 -43
- package/.opencode/skills/ui-ux-design/SKILL.md +0 -603
- package/scripts/validate-stringray-comprehensive.js +0 -636
- /package/dist/integrations/openclaw/hooks/{strray-hooks.js → xray-hooks.js} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Comprehensive tests for the
|
|
1
|
+
"""Comprehensive tests for the 0xRay Hermes Plugin v2.
|
|
2
2
|
|
|
3
3
|
Tests all 3 tools, both hooks, the slash command, bridge integration,
|
|
4
4
|
logging to disk, and the full register() wiring.
|
|
@@ -30,18 +30,18 @@ sys.path.insert(0, PLUGIN_DIR)
|
|
|
30
30
|
|
|
31
31
|
# Force reimport
|
|
32
32
|
for mod in list(sys.modules):
|
|
33
|
-
if "
|
|
33
|
+
if "xray" in mod and ("schemas" in mod or "tools" in mod or "plugin" in mod):
|
|
34
34
|
del sys.modules[mod]
|
|
35
35
|
|
|
36
36
|
schemas = importlib.import_module("schemas")
|
|
37
37
|
tools_mod = importlib.import_module("tools")
|
|
38
38
|
|
|
39
39
|
# Create a fake package for __init__.py execution
|
|
40
|
-
pkg = types.ModuleType("
|
|
40
|
+
pkg = types.ModuleType("xray_hermes_pkg")
|
|
41
41
|
pkg.__path__ = [PLUGIN_DIR]
|
|
42
42
|
pkg.__dict__["schemas"] = schemas
|
|
43
43
|
pkg.__dict__["tools"] = tools_mod
|
|
44
|
-
sys.modules["
|
|
44
|
+
sys.modules["xray_hermes_pkg"] = pkg
|
|
45
45
|
|
|
46
46
|
init_path = os.path.join(PLUGIN_DIR, "__init__.py")
|
|
47
47
|
with open(init_path) as f:
|
|
@@ -56,8 +56,8 @@ pi = pkg # plugin init module
|
|
|
56
56
|
|
|
57
57
|
class TestSchemas(unittest.TestCase):
|
|
58
58
|
def test_validate_schema_has_required_fields(self):
|
|
59
|
-
s = schemas.
|
|
60
|
-
self.assertEqual(s["name"], "
|
|
59
|
+
s = schemas.XRAY_VALIDATE
|
|
60
|
+
self.assertEqual(s["name"], "xray_validate")
|
|
61
61
|
params = s["parameters"]
|
|
62
62
|
self.assertEqual(params["type"], "object")
|
|
63
63
|
self.assertIn("files", params["properties"])
|
|
@@ -66,51 +66,51 @@ class TestSchemas(unittest.TestCase):
|
|
|
66
66
|
self.assertEqual(params["properties"]["files"]["type"], "array")
|
|
67
67
|
|
|
68
68
|
def test_codex_check_schema(self):
|
|
69
|
-
s = schemas.
|
|
70
|
-
self.assertEqual(s["name"], "
|
|
69
|
+
s = schemas.XRAY_CODEX_CHECK
|
|
70
|
+
self.assertEqual(s["name"], "xray_codex_check")
|
|
71
71
|
fa = s["parameters"]["properties"]["focus_areas"]
|
|
72
72
|
self.assertIn("enum", fa["items"])
|
|
73
73
|
self.assertIn("error-handling", fa["items"]["enum"])
|
|
74
74
|
|
|
75
75
|
def test_health_schema_no_required(self):
|
|
76
|
-
s = schemas.
|
|
76
|
+
s = schemas.XRAY_HEALTH
|
|
77
77
|
self.assertEqual(len(s["parameters"].get("required", [])), 0)
|
|
78
78
|
|
|
79
79
|
def test_descriptions_non_empty(self):
|
|
80
|
-
for name, schema in [("v", schemas.
|
|
80
|
+
for name, schema in [("v", schemas.XRAY_VALIDATE), ("c", schemas.XRAY_CODEX_CHECK), ("h", schemas.XRAY_HEALTH)]:
|
|
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):
|
|
88
88
|
with patch("subprocess.run") as m:
|
|
89
89
|
m.return_value = MagicMock(returncode=0, stdout="all good", stderr="")
|
|
90
|
-
r = json.loads(tools_mod.
|
|
90
|
+
r = json.loads(tools_mod._run_xray(["health"]))
|
|
91
91
|
self.assertEqual(r["status"], "ok")
|
|
92
92
|
self.assertEqual(m.call_args[0][0], ["npx", "0xray", "health"])
|
|
93
93
|
|
|
94
94
|
def test_command_failure(self):
|
|
95
95
|
with patch("subprocess.run") as m:
|
|
96
96
|
m.return_value = MagicMock(returncode=1, stdout="", stderr="broke")
|
|
97
|
-
r = json.loads(tools_mod.
|
|
97
|
+
r = json.loads(tools_mod._run_xray(["validate"]))
|
|
98
98
|
self.assertEqual(r["status"], "error")
|
|
99
99
|
|
|
100
100
|
def test_file_not_found(self):
|
|
101
101
|
with patch("subprocess.run", side_effect=FileNotFoundError):
|
|
102
|
-
r = json.loads(tools_mod.
|
|
102
|
+
r = json.loads(tools_mod._run_xray(["health"]))
|
|
103
103
|
self.assertIn("not found", r["error"])
|
|
104
104
|
|
|
105
105
|
def test_timeout(self):
|
|
106
106
|
with patch("subprocess.run", side_effect=subprocess.TimeoutExpired("c", 30)):
|
|
107
|
-
r = json.loads(tools_mod.
|
|
107
|
+
r = json.loads(tools_mod._run_xray(["health"], timeout=15))
|
|
108
108
|
self.assertIn("15s", r["error"])
|
|
109
109
|
|
|
110
110
|
def test_custom_timeout(self):
|
|
111
111
|
with patch("subprocess.run") as m:
|
|
112
112
|
m.return_value = MagicMock(returncode=0, stdout="", stderr="")
|
|
113
|
-
tools_mod.
|
|
113
|
+
tools_mod._run_xray(["health"], timeout=60)
|
|
114
114
|
self.assertEqual(m.call_args[1]["timeout"], 60)
|
|
115
115
|
|
|
116
116
|
|
|
@@ -143,11 +143,11 @@ 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:
|
|
150
|
-
r = json.loads(tools_mod.
|
|
150
|
+
r = json.loads(tools_mod.xray_health({}))
|
|
151
151
|
self.assertEqual(r["status"], "ok")
|
|
152
152
|
self.assertEqual(r["via"], "bridge")
|
|
153
153
|
m.assert_called_once_with({"command": "health"}, timeout=10)
|
|
@@ -155,21 +155,21 @@ class TestStrrayHealth(unittest.TestCase):
|
|
|
155
155
|
def test_health_fallback_to_cli(self):
|
|
156
156
|
"""v2: falls back to CLI when bridge fails."""
|
|
157
157
|
with patch.object(tools_mod, "_bridge_call", return_value={"error": "node not found"}):
|
|
158
|
-
with patch.object(tools_mod, "
|
|
159
|
-
r = json.loads(tools_mod.
|
|
158
|
+
with patch.object(tools_mod, "_run_xray", return_value='{"status":"ok","output":"healthy"}') as cli:
|
|
159
|
+
r = json.loads(tools_mod.xray_health({}))
|
|
160
160
|
cli.assert_called_once()
|
|
161
161
|
|
|
162
162
|
def test_health_ignores_extra_args(self):
|
|
163
163
|
with patch.object(tools_mod, "_bridge_call", return_value={"status": "ok", "framework": "loaded", "version": "1.0", "components": {}}):
|
|
164
|
-
r = json.loads(tools_mod.
|
|
164
|
+
r = json.loads(tools_mod.xray_health({"x": 1}))
|
|
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:
|
|
172
|
-
r = json.loads(tools_mod.
|
|
172
|
+
r = json.loads(tools_mod.xray_validate({"files": ["a.ts", "b.ts"], "operation": "commit"}))
|
|
173
173
|
self.assertEqual(r["status"], "passed")
|
|
174
174
|
self.assertEqual(r["files_checked"], 2)
|
|
175
175
|
self.assertEqual(r["via"], "bridge")
|
|
@@ -177,86 +177,86 @@ class TestStrrayValidate(unittest.TestCase):
|
|
|
177
177
|
|
|
178
178
|
def test_bridge_violations(self):
|
|
179
179
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": False, "fileResults": [{"file": "a.ts", "passed": False, "violations": ["tests-required"]}]}) as m:
|
|
180
|
-
r = json.loads(tools_mod.
|
|
180
|
+
r = json.loads(tools_mod.xray_validate({"files": ["a.ts"]}))
|
|
181
181
|
self.assertEqual(r["status"], "violations")
|
|
182
182
|
self.assertEqual(r["file_results"][0]["violations"], ["tests-required"])
|
|
183
183
|
|
|
184
184
|
def test_bridge_error_fallback_to_cli(self):
|
|
185
185
|
with patch.object(tools_mod, "_bridge_call", return_value={"error": "node not found"}):
|
|
186
|
-
with patch.object(tools_mod, "
|
|
187
|
-
r = json.loads(tools_mod.
|
|
186
|
+
with patch.object(tools_mod, "_run_xray", return_value='{"status":"ok","output":"valid"}') as cli:
|
|
187
|
+
r = json.loads(tools_mod.xray_validate({"files": ["a.ts"]}))
|
|
188
188
|
self.assertEqual(r["via"], "cli")
|
|
189
189
|
cli.assert_called_once()
|
|
190
190
|
|
|
191
191
|
def test_no_files_error(self):
|
|
192
|
-
r = json.loads(tools_mod.
|
|
192
|
+
r = json.loads(tools_mod.xray_validate({"files": []}))
|
|
193
193
|
self.assertIn("No files", r["error"])
|
|
194
194
|
|
|
195
195
|
def test_no_files_key_error(self):
|
|
196
|
-
r = json.loads(tools_mod.
|
|
196
|
+
r = json.loads(tools_mod.xray_validate({}))
|
|
197
197
|
self.assertIn("error", r)
|
|
198
198
|
|
|
199
199
|
def test_default_operation(self):
|
|
200
200
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": True, "fileResults": []}):
|
|
201
|
-
r = json.loads(tools_mod.
|
|
201
|
+
r = json.loads(tools_mod.xray_validate({"files": ["a.ts"]}))
|
|
202
202
|
self.assertEqual(r["operation"], "commit")
|
|
203
203
|
|
|
204
204
|
def test_100_files(self):
|
|
205
205
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": True, "fileResults": []}) as m:
|
|
206
206
|
fs = [f"f{i}.ts" for i in range(100)]
|
|
207
|
-
r = json.loads(tools_mod.
|
|
207
|
+
r = json.loads(tools_mod.xray_validate({"files": fs}))
|
|
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:
|
|
215
|
-
r = json.loads(tools_mod.
|
|
215
|
+
r = json.loads(tools_mod.xray_codex_check({"code": "const x = null;", "operation": "create"}))
|
|
216
216
|
self.assertEqual(r["status"], "passed")
|
|
217
217
|
self.assertEqual(r["via"], "bridge")
|
|
218
218
|
m.assert_called_once()
|
|
219
219
|
|
|
220
220
|
def test_with_code_bridge_violations(self):
|
|
221
221
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": False, "violations": ["console.log found"], "checks": []}):
|
|
222
|
-
r = json.loads(tools_mod.
|
|
222
|
+
r = json.loads(tools_mod.xray_codex_check({"code": "console.log(x)", "operation": "create"}))
|
|
223
223
|
self.assertEqual(r["status"], "violations")
|
|
224
224
|
self.assertEqual(r["violations"], ["console.log found"])
|
|
225
225
|
|
|
226
226
|
def test_with_focus_areas(self):
|
|
227
227
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": True, "violations": [], "checks": []}) as m:
|
|
228
|
-
tools_mod.
|
|
228
|
+
tools_mod.xray_codex_check({"code": "eval()", "operation": "modify", "focus_areas": ["security"]})
|
|
229
229
|
self.assertEqual(m.call_args[0][0]["focusAreas"], ["security"])
|
|
230
230
|
|
|
231
231
|
def test_empty_string_code_treated_as_code(self):
|
|
232
232
|
"""BUG FIX: empty string '' should still be treated as code (is not None)."""
|
|
233
233
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": True, "violations": [], "checks": []}) as m:
|
|
234
|
-
r = json.loads(tools_mod.
|
|
234
|
+
r = json.loads(tools_mod.xray_codex_check({"code": "", "operation": "create"}))
|
|
235
235
|
self.assertEqual(r["status"], "passed")
|
|
236
236
|
self.assertEqual(r["code_length"], 0)
|
|
237
237
|
|
|
238
238
|
def test_no_code_bridge_health(self):
|
|
239
239
|
"""No code provided — bridge health check."""
|
|
240
240
|
with patch.object(tools_mod, "_bridge_call", return_value={"framework": "loaded", "version": "1.15.0", "components": {}}) as m:
|
|
241
|
-
r = json.loads(tools_mod.
|
|
241
|
+
r = json.loads(tools_mod.xray_codex_check({"operation": "refactor"}))
|
|
242
242
|
self.assertEqual(r["status"], "ok")
|
|
243
243
|
self.assertIn("Pass", r["note"])
|
|
244
244
|
|
|
245
245
|
def test_no_code_bridge_error_fallback(self):
|
|
246
246
|
with patch.object(tools_mod, "_bridge_call", return_value={"error": "node not found"}):
|
|
247
|
-
with patch.object(tools_mod, "
|
|
248
|
-
r = json.loads(tools_mod.
|
|
247
|
+
with patch.object(tools_mod, "_run_xray", return_value='{"status":"ok","output":"healthy"}') as cli:
|
|
248
|
+
r = json.loads(tools_mod.xray_codex_check({"operation": "create"}))
|
|
249
249
|
cli.assert_called_once()
|
|
250
250
|
|
|
251
251
|
def test_default_operation(self):
|
|
252
252
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": True, "violations": [], "checks": []}):
|
|
253
|
-
r = json.loads(tools_mod.
|
|
253
|
+
r = json.loads(tools_mod.xray_codex_check({"code": "x"}))
|
|
254
254
|
self.assertEqual(r["operation"], "create")
|
|
255
255
|
|
|
256
256
|
def test_multiline_code(self):
|
|
257
257
|
code = "function foo() {\n return null;\n}\n"
|
|
258
258
|
with patch.object(tools_mod, "_bridge_call", return_value={"passed": True, "violations": [], "checks": []}):
|
|
259
|
-
r = json.loads(tools_mod.
|
|
259
|
+
r = json.loads(tools_mod.xray_codex_check({"code": code, "operation": "create"}))
|
|
260
260
|
self.assertEqual(r["code_length"], len(code))
|
|
261
261
|
|
|
262
262
|
|
|
@@ -270,10 +270,10 @@ class TestPreToolCallHook(unittest.TestCase):
|
|
|
270
270
|
pi._session_stats["session_id"] = None
|
|
271
271
|
|
|
272
272
|
@patch.object(pi, "_call_bridge")
|
|
273
|
-
def
|
|
274
|
-
"""
|
|
275
|
-
pi._on_pre_tool_call("
|
|
276
|
-
self.assertEqual(pi._session_stats["
|
|
273
|
+
def test_xray_mcp_no_bridge(self, mock_bridge):
|
|
274
|
+
"""0xRay MCP tools skip bridge entirely."""
|
|
275
|
+
pi._on_pre_tool_call("mcp_xray_lint_lint", {}, "t1")
|
|
276
|
+
self.assertEqual(pi._session_stats["xray_mcp_calls"], 1)
|
|
277
277
|
self.assertEqual(pi._session_stats["native_tool_calls"], 0)
|
|
278
278
|
mock_bridge.assert_not_called()
|
|
279
279
|
|
|
@@ -316,26 +316,26 @@ class TestPreToolCallHook(unittest.TestCase):
|
|
|
316
316
|
"""Terminal nudge only fires when command matches a known pattern."""
|
|
317
317
|
# No command arg — no nudge
|
|
318
318
|
with self.assertRaises(AssertionError):
|
|
319
|
-
with self.assertLogs("
|
|
319
|
+
with self.assertLogs("xray-hermes", level="INFO"):
|
|
320
320
|
pi._on_pre_tool_call("terminal", {}, "t1")
|
|
321
321
|
|
|
322
322
|
# Generic command (git, ls) — no nudge
|
|
323
323
|
with self.assertRaises(AssertionError):
|
|
324
|
-
with self.assertLogs("
|
|
324
|
+
with self.assertLogs("xray-hermes", level="INFO"):
|
|
325
325
|
pi._on_pre_tool_call("terminal", {"command": "git status"}, "t1")
|
|
326
326
|
|
|
327
327
|
# Grep command — should nudge
|
|
328
|
-
with self.assertLogs("
|
|
328
|
+
with self.assertLogs("xray-hermes", level="INFO") as cm:
|
|
329
329
|
pi._on_pre_tool_call("terminal", {"command": "grep -r 'pattern' src/"}, "t1")
|
|
330
330
|
self.assertTrue(any("grep" in m for m in cm.output))
|
|
331
331
|
|
|
332
332
|
# npm audit — should nudge
|
|
333
|
-
with self.assertLogs("
|
|
333
|
+
with self.assertLogs("xray-hermes", level="INFO") as cm:
|
|
334
334
|
pi._on_pre_tool_call("terminal", {"command": "npm audit"}, "t1")
|
|
335
335
|
self.assertTrue(any("audit" in m for m in cm.output))
|
|
336
336
|
|
|
337
337
|
def test_nudge_search_files(self):
|
|
338
|
-
with self.assertLogs("
|
|
338
|
+
with self.assertLogs("xray-hermes", level="INFO") as cm:
|
|
339
339
|
pi._on_pre_tool_call("search_files", {}, "t1")
|
|
340
340
|
self.assertTrue(any("Tip" in m for m in cm.output))
|
|
341
341
|
|
|
@@ -343,7 +343,7 @@ class TestPreToolCallHook(unittest.TestCase):
|
|
|
343
343
|
"""write_file is a code tool — no nudge, gets bridge instead."""
|
|
344
344
|
with patch.object(pi, "_call_bridge", return_value={"passed": True, "qualityGate": {"passed": True}, "processors": {"ran": False}}):
|
|
345
345
|
with self.assertRaises(AssertionError):
|
|
346
|
-
with self.assertLogs("
|
|
346
|
+
with self.assertLogs("xray-hermes", level="INFO"):
|
|
347
347
|
pi._on_pre_tool_call("write_file", {}, "t1")
|
|
348
348
|
|
|
349
349
|
def test_accumulates(self):
|
|
@@ -352,12 +352,12 @@ class TestPreToolCallHook(unittest.TestCase):
|
|
|
352
352
|
pi._on_pre_tool_call("terminal", {}, "t1")
|
|
353
353
|
self.assertEqual(pi._session_stats["total_tool_calls"], 5)
|
|
354
354
|
|
|
355
|
-
def
|
|
356
|
-
self.assertTrue(pi.
|
|
357
|
-
self.assertTrue(pi.
|
|
358
|
-
self.assertFalse(pi.
|
|
359
|
-
self.assertFalse(pi.
|
|
360
|
-
self.assertFalse(pi.
|
|
355
|
+
def test_is_xray_mcp(self):
|
|
356
|
+
self.assertTrue(pi._is_xray_mcp("mcp_xray_lint_lint"))
|
|
357
|
+
self.assertTrue(pi._is_xray_mcp("mcp_xray_enforcer_codex_enforcement"))
|
|
358
|
+
self.assertFalse(pi._is_xray_mcp("terminal"))
|
|
359
|
+
self.assertFalse(pi._is_xray_mcp("xray_validate"))
|
|
360
|
+
self.assertFalse(pi._is_xray_mcp("mcp_other_tool"))
|
|
361
361
|
|
|
362
362
|
|
|
363
363
|
class TestPostToolCallHook(unittest.TestCase):
|
|
@@ -415,7 +415,7 @@ class TestSlashCommand(unittest.TestCase):
|
|
|
415
415
|
"session_id": "test-session",
|
|
416
416
|
"code_operations": 5,
|
|
417
417
|
"total_tool_calls": 20,
|
|
418
|
-
"
|
|
418
|
+
"xray_mcp_calls": 12,
|
|
419
419
|
"native_tool_calls": 8,
|
|
420
420
|
"quality_gate_runs": 10,
|
|
421
421
|
"quality_gate_blocks": 2,
|
|
@@ -429,7 +429,7 @@ class TestSlashCommand(unittest.TestCase):
|
|
|
429
429
|
}
|
|
430
430
|
|
|
431
431
|
def test_stats(self):
|
|
432
|
-
o = pi.
|
|
432
|
+
o = pi._xray_command("stats")
|
|
433
433
|
self.assertIn("20", o)
|
|
434
434
|
self.assertIn("12", o)
|
|
435
435
|
self.assertIn("8", o)
|
|
@@ -440,32 +440,32 @@ class TestSlashCommand(unittest.TestCase):
|
|
|
440
440
|
self.assertIn("15", o) # bridge_calls
|
|
441
441
|
|
|
442
442
|
def test_help(self):
|
|
443
|
-
o = pi.
|
|
443
|
+
o = pi._xray_command("help")
|
|
444
444
|
self.assertIn("status", o)
|
|
445
445
|
self.assertIn("help", o)
|
|
446
446
|
|
|
447
447
|
def test_status_via_bridge(self):
|
|
448
|
-
"""v2: status uses bridge, not tools.
|
|
448
|
+
"""v2: status uses bridge, not tools.xray_health."""
|
|
449
449
|
with patch.object(pi, "_call_bridge", return_value={"framework": "loaded", "version": "1.15.0", "components": {"qualityGate": True, "processorManager": True}}) as m:
|
|
450
|
-
o = pi.
|
|
450
|
+
o = pi._xray_command("status")
|
|
451
451
|
self.assertIn("loaded", o)
|
|
452
452
|
self.assertIn("1.15.0", o)
|
|
453
453
|
m.assert_called_once_with({"command": "health"}, timeout=10)
|
|
454
454
|
|
|
455
455
|
def test_status_bridge_error(self):
|
|
456
456
|
with patch.object(pi, "_call_bridge", return_value={"error": "node not found"}):
|
|
457
|
-
o = pi.
|
|
457
|
+
o = pi._xray_command("status")
|
|
458
458
|
self.assertIn("node not found", o)
|
|
459
459
|
|
|
460
460
|
def test_default_status(self):
|
|
461
461
|
with patch.object(pi, "_call_bridge", return_value={"framework": "loaded", "version": "1.0", "components": {}}):
|
|
462
|
-
o = pi.
|
|
462
|
+
o = pi._xray_command("")
|
|
463
463
|
self.assertIn("loaded", o)
|
|
464
464
|
|
|
465
465
|
def test_stats_null_started_at(self):
|
|
466
466
|
pi._session_stats["started_at"] = None
|
|
467
467
|
pi._session_stats["session_id"] = None
|
|
468
|
-
o = pi.
|
|
468
|
+
o = pi._xray_command("stats")
|
|
469
469
|
self.assertIn("N/A", o)
|
|
470
470
|
|
|
471
471
|
|
|
@@ -484,7 +484,7 @@ class TestSessionStartHook(unittest.TestCase):
|
|
|
484
484
|
self.assertEqual(pi._session_stats["session_id"], "s1")
|
|
485
485
|
|
|
486
486
|
def test_logs(self):
|
|
487
|
-
with self.assertLogs("
|
|
487
|
+
with self.assertLogs("xray-hermes", level="INFO") as cm:
|
|
488
488
|
pi._on_session_start("s1", "telegram")
|
|
489
489
|
self.assertTrue(any("s1" in m for m in cm.output))
|
|
490
490
|
self.assertTrue(any("telegram" in m for m in cm.output))
|
|
@@ -495,29 +495,29 @@ class TestRegisterIntegration(unittest.TestCase):
|
|
|
495
495
|
ctx = MagicMock()
|
|
496
496
|
pi.register(ctx)
|
|
497
497
|
names = [c[1]["name"] for c in ctx.register_tool.call_args_list]
|
|
498
|
-
self.assertEqual(set(names), {"
|
|
498
|
+
self.assertEqual(set(names), {"xray_validate", "xray_codex_check", "xray_health", "xray_hooks"})
|
|
499
499
|
|
|
500
500
|
def test_toolset_name(self):
|
|
501
501
|
ctx = MagicMock()
|
|
502
502
|
pi.register(ctx)
|
|
503
503
|
for c in ctx.register_tool.call_args_list:
|
|
504
|
-
self.assertEqual(c[1]["toolset"], "
|
|
504
|
+
self.assertEqual(c[1]["toolset"], "0xray-hermes")
|
|
505
505
|
|
|
506
506
|
def test_schemas_wired(self):
|
|
507
507
|
ctx = MagicMock()
|
|
508
508
|
pi.register(ctx)
|
|
509
509
|
sm = {c[1]["name"]: c[1]["schema"] for c in ctx.register_tool.call_args_list}
|
|
510
|
-
self.assertIs(sm["
|
|
511
|
-
self.assertIs(sm["
|
|
512
|
-
self.assertIs(sm["
|
|
510
|
+
self.assertIs(sm["xray_validate"], schemas.XRAY_VALIDATE)
|
|
511
|
+
self.assertIs(sm["xray_codex_check"], schemas.XRAY_CODEX_CHECK)
|
|
512
|
+
self.assertIs(sm["xray_health"], schemas.XRAY_HEALTH)
|
|
513
513
|
|
|
514
514
|
def test_handlers_wired(self):
|
|
515
515
|
ctx = MagicMock()
|
|
516
516
|
pi.register(ctx)
|
|
517
517
|
hm = {c[1]["name"]: c[1]["handler"] for c in ctx.register_tool.call_args_list}
|
|
518
|
-
self.assertIs(hm["
|
|
519
|
-
self.assertIs(hm["
|
|
520
|
-
self.assertIs(hm["
|
|
518
|
+
self.assertIs(hm["xray_validate"], tools_mod.xray_validate)
|
|
519
|
+
self.assertIs(hm["xray_codex_check"], tools_mod.xray_codex_check)
|
|
520
|
+
self.assertIs(hm["xray_health"], tools_mod.xray_health)
|
|
521
521
|
|
|
522
522
|
def test_hooks_registered(self):
|
|
523
523
|
ctx = MagicMock()
|
|
@@ -551,7 +551,7 @@ class TestRegisterIntegration(unittest.TestCase):
|
|
|
551
551
|
|
|
552
552
|
def test_logs_on_load(self):
|
|
553
553
|
ctx = MagicMock()
|
|
554
|
-
with self.assertLogs("
|
|
554
|
+
with self.assertLogs("xray-hermes", level="INFO") as cm:
|
|
555
555
|
pi.register(ctx)
|
|
556
556
|
self.assertTrue(any("Plugin" in m and "loaded" in m for m in cm.output))
|
|
557
557
|
|
|
@@ -648,7 +648,10 @@ class TestLiveBridge(unittest.TestCase):
|
|
|
648
648
|
self.assertNotIn("error", r)
|
|
649
649
|
# console.log is a violation
|
|
650
650
|
if r.get("passed") is False:
|
|
651
|
-
self.assertTrue(
|
|
651
|
+
self.assertTrue(
|
|
652
|
+
any("console.log" in v.get("message", "") for v in r.get("violations", [])),
|
|
653
|
+
f"Expected 'console.log' in violations, got: {r.get('violations', [])}",
|
|
654
|
+
)
|
|
652
655
|
|
|
653
656
|
def test_bridge_positional_health(self):
|
|
654
657
|
"""Positional arg mode: node bridge.mjs health --cwd /path (no stdin pipe)."""
|
|
@@ -657,8 +660,8 @@ class TestLiveBridge(unittest.TestCase):
|
|
|
657
660
|
self.skipTest("bridge.mjs not built yet")
|
|
658
661
|
|
|
659
662
|
# Use stringray dev repo as project root (has package.json)
|
|
660
|
-
|
|
661
|
-
cwd =
|
|
663
|
+
xray_root = str(Path(PLUGIN_DIR).parent.parent.parent / "dev" / "stringray")
|
|
664
|
+
cwd = xray_root if Path(xray_root).exists() else PLUGIN_DIR
|
|
662
665
|
|
|
663
666
|
r = subprocess.run(
|
|
664
667
|
["node", str(bridge_path), "health", "--cwd", cwd],
|
|
@@ -675,8 +678,8 @@ class TestLiveBridge(unittest.TestCase):
|
|
|
675
678
|
if not bridge_path.exists():
|
|
676
679
|
self.skipTest("bridge.mjs not built yet")
|
|
677
680
|
|
|
678
|
-
|
|
679
|
-
cwd =
|
|
681
|
+
xray_root = str(Path(PLUGIN_DIR).parent.parent.parent / "dev" / "stringray")
|
|
682
|
+
cwd = xray_root if Path(xray_root).exists() else PLUGIN_DIR
|
|
680
683
|
|
|
681
684
|
r = subprocess.run(
|
|
682
685
|
["node", str(bridge_path), "stats", "--cwd", cwd],
|
|
@@ -692,8 +695,8 @@ class TestLiveBridge(unittest.TestCase):
|
|
|
692
695
|
if not bridge_path.exists():
|
|
693
696
|
self.skipTest("bridge.mjs not built yet")
|
|
694
697
|
|
|
695
|
-
|
|
696
|
-
cwd =
|
|
698
|
+
xray_root = str(Path(PLUGIN_DIR).parent.parent.parent / "dev" / "stringray")
|
|
699
|
+
cwd = xray_root if Path(xray_root).exists() else PLUGIN_DIR
|
|
697
700
|
|
|
698
701
|
r = subprocess.run(
|
|
699
702
|
["node", str(bridge_path), "validate", "--cwd", cwd,
|
|
@@ -710,8 +713,8 @@ class TestLiveBridge(unittest.TestCase):
|
|
|
710
713
|
if not bridge_path.exists():
|
|
711
714
|
self.skipTest("bridge.mjs not built yet")
|
|
712
715
|
|
|
713
|
-
|
|
714
|
-
cwd =
|
|
716
|
+
xray_root = str(Path(PLUGIN_DIR).parent.parent.parent / "dev" / "stringray")
|
|
717
|
+
cwd = xray_root if Path(xray_root).exists() else PLUGIN_DIR
|
|
715
718
|
|
|
716
719
|
r = subprocess.run(
|
|
717
720
|
["node", str(bridge_path), "validate", "--cwd", cwd,
|
|
@@ -739,32 +742,32 @@ class TestBridgeErrorPaths(unittest.TestCase):
|
|
|
739
742
|
r = tools_mod._bridge_call({"command": "health"})
|
|
740
743
|
self.assertIn("error", r)
|
|
741
744
|
|
|
742
|
-
def
|
|
743
|
-
"""
|
|
745
|
+
def test_bridge_generic_exception_in_run_xray(self):
|
|
746
|
+
"""_run_xray catches non-standard exceptions."""
|
|
744
747
|
with patch("subprocess.run", side_effect=RuntimeError("unexpected")):
|
|
745
|
-
r = json.loads(tools_mod.
|
|
748
|
+
r = json.loads(tools_mod._run_xray(["health"]))
|
|
746
749
|
self.assertIn("unexpected", r["error"])
|
|
747
750
|
|
|
748
751
|
def test_validate_cli_fallback_error(self):
|
|
749
|
-
"""
|
|
752
|
+
"""xray_validate CLI fallback when CLI returns an error JSON."""
|
|
750
753
|
with patch.object(tools_mod, "_bridge_call", return_value={"error": "bridge down"}):
|
|
751
|
-
with patch.object(tools_mod, "
|
|
752
|
-
r = json.loads(tools_mod.
|
|
754
|
+
with patch.object(tools_mod, "_run_xray", return_value='{"error": "validation failed"}'):
|
|
755
|
+
r = json.loads(tools_mod.xray_validate({"files": ["a.ts"]}))
|
|
753
756
|
# CLI error path returns raw result without "via" key
|
|
754
757
|
self.assertIn("error", r)
|
|
755
758
|
|
|
756
759
|
def test_codex_check_static_fallback(self):
|
|
757
|
-
"""
|
|
760
|
+
"""xray_codex_check with code but bridge down falls back to static analysis."""
|
|
758
761
|
with patch.object(tools_mod, "_bridge_call", return_value={"error": "bridge down"}):
|
|
759
|
-
r = json.loads(tools_mod.
|
|
762
|
+
r = json.loads(tools_mod.xray_codex_check({"code": "console.log(1)", "operation": "create"}))
|
|
760
763
|
self.assertEqual(r["via"], "static")
|
|
761
764
|
self.assertIn("basic analysis", r["note"])
|
|
762
765
|
|
|
763
766
|
def test_codex_check_cli_health_error(self):
|
|
764
|
-
"""
|
|
767
|
+
"""xray_codex_check no-code path: bridge error + CLI also errors."""
|
|
765
768
|
with patch.object(tools_mod, "_bridge_call", return_value={"error": "no node"}):
|
|
766
|
-
with patch.object(tools_mod, "
|
|
767
|
-
r = json.loads(tools_mod.
|
|
769
|
+
with patch.object(tools_mod, "_run_xray", return_value='{"error": "0xray not found"}'):
|
|
770
|
+
r = json.loads(tools_mod.xray_codex_check({"operation": "create"}))
|
|
768
771
|
self.assertIn("error", r)
|
|
769
772
|
|
|
770
773
|
|
|
@@ -850,17 +853,17 @@ class TestPreToolCallEdgeCases(unittest.TestCase):
|
|
|
850
853
|
self.assertEqual(pi._session_stats["code_operations"], 1, f"{tool} should be a code tool")
|
|
851
854
|
|
|
852
855
|
@patch.object(pi, "_call_bridge")
|
|
853
|
-
def
|
|
856
|
+
def test_unknown_tool_not_xray_mcp(self, mock_bridge):
|
|
854
857
|
"""Unknown tools should be treated as native tools."""
|
|
855
858
|
pi._on_pre_tool_call("some_random_tool", {}, "t1")
|
|
856
859
|
self.assertEqual(pi._session_stats["native_tool_calls"], 1)
|
|
857
860
|
mock_bridge.assert_not_called()
|
|
858
861
|
|
|
859
|
-
def
|
|
860
|
-
"""
|
|
861
|
-
pi._on_pre_tool_call("
|
|
862
|
+
def test_xray_validate_tool_not_treated_as_mcp(self):
|
|
863
|
+
"""xray_validate is a native tool, not an MCP tool."""
|
|
864
|
+
pi._on_pre_tool_call("xray_validate", {}, "t1")
|
|
862
865
|
self.assertEqual(pi._session_stats["native_tool_calls"], 1)
|
|
863
|
-
self.assertEqual(pi._session_stats["
|
|
866
|
+
self.assertEqual(pi._session_stats["xray_mcp_calls"], 0)
|
|
864
867
|
|
|
865
868
|
@patch.object(pi, "_call_bridge", return_value={"passed": True, "qualityGate": {"passed": True, "violations": []}, "processors": {"ran": True, "success": True, "processorCount": 3, "details": [{"name": "p1", "success": True}, {"name": "p2", "success": True}, {"name": "p3", "success": False, "error": "failed"}]}})
|
|
866
869
|
def test_pre_processor_partial_failure(self, mock_bridge):
|
|
@@ -875,12 +878,12 @@ class TestSlashCommandEdgeCases(unittest.TestCase):
|
|
|
875
878
|
def test_unknown_command_defaults_to_status(self):
|
|
876
879
|
"""Unknown args default to status."""
|
|
877
880
|
with patch.object(pi, "_call_bridge", return_value={"framework": "loaded", "version": "1.0", "components": {}}) as m:
|
|
878
|
-
pi.
|
|
881
|
+
pi._xray_command("something-random")
|
|
879
882
|
m.assert_called_once_with({"command": "health"}, timeout=10)
|
|
880
883
|
|
|
881
884
|
def test_case_insensitive(self):
|
|
882
885
|
"""Command arg is lowercased."""
|
|
883
|
-
o = pi.
|
|
886
|
+
o = pi._xray_command(" STATS ")
|
|
884
887
|
self.assertIn("Session", o)
|
|
885
888
|
|
|
886
889
|
|
|
@@ -940,13 +943,13 @@ class TestBridgeHelperTimeoutDefault(unittest.TestCase):
|
|
|
940
943
|
def test_custom_timeout(self):
|
|
941
944
|
"""_bridge_call respects custom timeout."""
|
|
942
945
|
with patch("subprocess.run") as m:
|
|
943
|
-
m.return_value = MagicMock(returncode=0, stdout='{
|
|
946
|
+
m.return_value = MagicMock(returncode=0, stdout='{"ok":true}', stderr="")
|
|
944
947
|
tools_mod._bridge_call({"command": "health"}, timeout=5)
|
|
945
948
|
self.assertEqual(m.call_args[1]["timeout"], 5)
|
|
946
949
|
|
|
947
950
|
|
|
948
|
-
class
|
|
949
|
-
"""Tests for the
|
|
951
|
+
class TestXrayHooksTool(unittest.TestCase):
|
|
952
|
+
"""Tests for the xray_hooks tool."""
|
|
950
953
|
|
|
951
954
|
def test_list_via_bridge(self):
|
|
952
955
|
"""list action uses bridge when available."""
|
|
@@ -954,7 +957,7 @@ class TestStrrayHooksTool(unittest.TestCase):
|
|
|
954
957
|
"status": "ok", "action": "list",
|
|
955
958
|
"hooks": {"managed": ["pre-commit"], "missing": [], "external": [], "stale": []},
|
|
956
959
|
}) as m:
|
|
957
|
-
r = json.loads(tools_mod.
|
|
960
|
+
r = json.loads(tools_mod.xray_hooks({"action": "list"}))
|
|
958
961
|
self.assertEqual(r["status"], "ok")
|
|
959
962
|
self.assertEqual(r["via"], "bridge")
|
|
960
963
|
m.assert_called_once()
|
|
@@ -968,7 +971,7 @@ class TestStrrayHooksTool(unittest.TestCase):
|
|
|
968
971
|
"status": "ok", "action": "install", "installed": ["pre-commit", "post-commit"],
|
|
969
972
|
"skipped": [], "errors": [],
|
|
970
973
|
}) as m:
|
|
971
|
-
r = json.loads(tools_mod.
|
|
974
|
+
r = json.loads(tools_mod.xray_hooks({"action": "install"}))
|
|
972
975
|
self.assertEqual(r["via"], "bridge")
|
|
973
976
|
self.assertEqual(len(r["result"]["installed"]), 2)
|
|
974
977
|
|
|
@@ -977,14 +980,14 @@ class TestStrrayHooksTool(unittest.TestCase):
|
|
|
977
980
|
with patch.object(tools_mod, "_bridge_call", return_value={
|
|
978
981
|
"status": "ok", "action": "uninstall", "removed": ["pre-commit"], "restored": [],
|
|
979
982
|
}) as m:
|
|
980
|
-
r = json.loads(tools_mod.
|
|
983
|
+
r = json.loads(tools_mod.xray_hooks({"action": "uninstall"}))
|
|
981
984
|
self.assertEqual(r["via"], "bridge")
|
|
982
985
|
|
|
983
986
|
def test_bridge_error_fallback(self):
|
|
984
987
|
"""Falls back to file-based when bridge errors."""
|
|
985
988
|
with patch.object(tools_mod, "_bridge_call", return_value={"error": "node not found"}):
|
|
986
989
|
# Without a real git repo, should return error
|
|
987
|
-
r = json.loads(tools_mod.
|
|
990
|
+
r = json.loads(tools_mod.xray_hooks({"action": "list"}))
|
|
988
991
|
self.assertIn("via", r)
|
|
989
992
|
|
|
990
993
|
def test_specific_hooks(self):
|
|
@@ -993,7 +996,7 @@ class TestStrrayHooksTool(unittest.TestCase):
|
|
|
993
996
|
"status": "ok", "action": "list",
|
|
994
997
|
"hooks": {"managed": [], "missing": ["pre-commit"], "external": [], "stale": []},
|
|
995
998
|
}) as m:
|
|
996
|
-
tools_mod.
|
|
999
|
+
tools_mod.xray_hooks({"action": "list", "hooks": ["pre-commit"]})
|
|
997
1000
|
call_cmd = m.call_args[0][0]
|
|
998
1001
|
self.assertEqual(call_cmd["hooks"], ["pre-commit"])
|
|
999
1002
|
|
|
@@ -1003,7 +1006,7 @@ class TestStrrayHooksTool(unittest.TestCase):
|
|
|
1003
1006
|
"status": "ok", "action": "status",
|
|
1004
1007
|
"hooks": {"managed": [], "missing": [], "external": [], "stale": []},
|
|
1005
1008
|
}) as m:
|
|
1006
|
-
r = json.loads(tools_mod.
|
|
1009
|
+
r = json.loads(tools_mod.xray_hooks({"action": "status"}))
|
|
1007
1010
|
self.assertEqual(r["status"], "ok")
|
|
1008
1011
|
m.assert_called_once()
|
|
1009
1012
|
|
|
@@ -1013,23 +1016,23 @@ class TestStrrayHooksTool(unittest.TestCase):
|
|
|
1013
1016
|
"status": "ok", "action": "list",
|
|
1014
1017
|
"hooks": {"managed": [], "missing": [], "external": [], "stale": []},
|
|
1015
1018
|
}) as m:
|
|
1016
|
-
tools_mod.
|
|
1019
|
+
tools_mod.xray_hooks({})
|
|
1017
1020
|
call_cmd = m.call_args[0][0]
|
|
1018
1021
|
self.assertEqual(call_cmd["action"], "list")
|
|
1019
1022
|
|
|
1020
1023
|
|
|
1021
|
-
class
|
|
1022
|
-
"""Tests for the
|
|
1024
|
+
class TestXrayHooksSchema(unittest.TestCase):
|
|
1025
|
+
"""Tests for the XRAY_HOOKS schema."""
|
|
1023
1026
|
|
|
1024
1027
|
def test_schema_has_required_fields(self):
|
|
1025
|
-
s = schemas.
|
|
1026
|
-
self.assertEqual(s["name"], "
|
|
1028
|
+
s = schemas.XRAY_HOOKS
|
|
1029
|
+
self.assertEqual(s["name"], "xray_hooks")
|
|
1027
1030
|
self.assertIn("action", s["parameters"]["properties"])
|
|
1028
1031
|
self.assertIn("hooks", s["parameters"]["properties"])
|
|
1029
1032
|
self.assertIn("action", s["parameters"]["required"])
|
|
1030
1033
|
|
|
1031
1034
|
def test_action_enum(self):
|
|
1032
|
-
s = schemas.
|
|
1035
|
+
s = schemas.XRAY_HOOKS
|
|
1033
1036
|
action = s["parameters"]["properties"]["action"]
|
|
1034
1037
|
self.assertIn("install", action["enum"])
|
|
1035
1038
|
self.assertIn("uninstall", action["enum"])
|
|
@@ -1037,7 +1040,7 @@ class TestStrrayHooksSchema(unittest.TestCase):
|
|
|
1037
1040
|
self.assertIn("status", action["enum"])
|
|
1038
1041
|
|
|
1039
1042
|
def test_hooks_enum(self):
|
|
1040
|
-
s = schemas.
|
|
1043
|
+
s = schemas.XRAY_HOOKS
|
|
1041
1044
|
hooks = s["parameters"]["properties"]["hooks"]
|
|
1042
1045
|
self.assertIn("pre-commit", hooks["items"]["enum"])
|
|
1043
1046
|
self.assertIn("post-commit", hooks["items"]["enum"])
|
|
@@ -1045,7 +1048,7 @@ class TestStrrayHooksSchema(unittest.TestCase):
|
|
|
1045
1048
|
self.assertIn("post-push", hooks["items"]["enum"])
|
|
1046
1049
|
|
|
1047
1050
|
def test_description_mentions_hooks(self):
|
|
1048
|
-
s = schemas.
|
|
1051
|
+
s = schemas.XRAY_HOOKS
|
|
1049
1052
|
self.assertIn("git hooks", s["description"])
|
|
1050
1053
|
|
|
1051
1054
|
|
|
@@ -1057,21 +1060,21 @@ class TestRegisterIntegrationV2_1(unittest.TestCase):
|
|
|
1057
1060
|
pi.register(ctx)
|
|
1058
1061
|
names = [c[1]["name"] for c in ctx.register_tool.call_args_list]
|
|
1059
1062
|
self.assertEqual(set(names), {
|
|
1060
|
-
"
|
|
1061
|
-
"
|
|
1063
|
+
"xray_validate", "xray_codex_check",
|
|
1064
|
+
"xray_health", "xray_hooks",
|
|
1062
1065
|
})
|
|
1063
1066
|
|
|
1064
|
-
def
|
|
1067
|
+
def test_xray_hooks_schema_wired(self):
|
|
1065
1068
|
ctx = MagicMock()
|
|
1066
1069
|
pi.register(ctx)
|
|
1067
1070
|
sm = {c[1]["name"]: c[1]["schema"] for c in ctx.register_tool.call_args_list}
|
|
1068
|
-
self.assertIs(sm["
|
|
1071
|
+
self.assertIs(sm["xray_hooks"], schemas.XRAY_HOOKS)
|
|
1069
1072
|
|
|
1070
|
-
def
|
|
1073
|
+
def test_xray_hooks_handler_wired(self):
|
|
1071
1074
|
ctx = MagicMock()
|
|
1072
1075
|
pi.register(ctx)
|
|
1073
1076
|
hm = {c[1]["name"]: c[1]["handler"] for c in ctx.register_tool.call_args_list}
|
|
1074
|
-
self.assertIs(hm["
|
|
1077
|
+
self.assertIs(hm["xray_hooks"], tools_mod.xray_hooks)
|
|
1075
1078
|
|
|
1076
1079
|
def test_registers_two_hooks(self):
|
|
1077
1080
|
ctx = MagicMock()
|
|
@@ -1090,7 +1093,7 @@ class TestRegisterIntegrationV2_1(unittest.TestCase):
|
|
|
1090
1093
|
|
|
1091
1094
|
def test_v2_2_log_message(self):
|
|
1092
1095
|
ctx = MagicMock()
|
|
1093
|
-
with self.assertLogs("
|
|
1096
|
+
with self.assertLogs("xray-hermes", level="INFO") as cm:
|
|
1094
1097
|
pi.register(ctx)
|
|
1095
1098
|
self.assertTrue(any("v2.2" in m for m in cm.output))
|
|
1096
1099
|
self.assertTrue(any("4 tools" in m for m in cm.output))
|