0xray 3.1.1 → 3.3.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 +1 -1
- package/.opencode/commands/auto-format.md +3 -3
- package/.opencode/commands/auto-summary-capture.md +2 -2
- package/.opencode/commands/enforcer-daily-scan.md +3 -3
- package/.opencode/commands/framework-compliance-audit.md +4 -4
- package/.opencode/commands/interactive-validator.md +2 -2
- package/.opencode/commands/job-summary-logger.md +2 -2
- package/.opencode/commands/mode-switch.md +1 -1
- package/.opencode/commands/model-health-check.md +2 -2
- package/.opencode/commands/performance-analysis.md +2 -2
- package/.opencode/commands/pre-commit-introspection.md +3 -3
- package/.opencode/commands/security-scan.md +3 -3
- package/.opencode/commands/sisyphus-validation.md +3 -3
- package/.opencode/commands/summary-logger.md +2 -2
- package/AGENTS.md +3 -13
- package/README.md +3 -3
- package/dist/AGENTS.md +3 -13
- package/dist/CHANGELOG.md +55 -0
- package/dist/README.md +3 -3
- package/dist/analytics/consent-manager.js +0 -1
- package/dist/analytics/emerging-pattern-detector.js +0 -1
- package/dist/analytics/pattern-learning-engine.js +0 -1
- package/dist/analytics/pattern-performance-tracker.js +0 -1
- package/dist/analytics/predictive-analytics.js +0 -1
- package/dist/analytics/prompt-pattern-analyzer.js +0 -1
- package/dist/analytics/routing-performance-analyzer.js +0 -1
- package/dist/analytics/routing-refiner.js +0 -1
- package/dist/analytics/simple-pattern-analyzer.js +0 -1
- package/dist/cli/commands/archive-logs.js +0 -1
- package/dist/cli/commands/opencode-install.js +13 -0
- package/dist/cli/commands/plugin-commands.js +0 -1
- package/dist/cli/commands/status.js +11 -13
- package/dist/cli/index.js +2 -7
- package/dist/core/activity-logger.js +0 -1
- package/dist/core/adaptive-kernel.js +0 -1
- package/dist/core/boot-orchestrator.js +2 -12
- package/dist/core/bridge.mjs +0 -1
- package/dist/core/codex-formatter.js +0 -1
- package/dist/core/codex-injector.js +0 -1
- package/dist/core/config-loader.js +36 -28
- package/dist/core/context-loader.js +0 -1
- package/dist/core/context-validator.js +0 -1
- package/dist/core/features-config.js +40 -1
- package/dist/core/kernel-patterns.js +0 -1
- package/dist/core/model-router.js +23 -64
- package/dist/core/system-prompt-generator.js +0 -1
- package/dist/delegation/agent-delegator.js +0 -1
- package/dist/delegation/agent-expertise.js +0 -1
- package/dist/delegation/analytics/index.js +0 -1
- package/dist/delegation/analytics/learning-engine.js +0 -1
- package/dist/delegation/analytics/outcome-tracker.js +0 -1
- package/dist/delegation/analytics/routing-analytics.js +0 -1
- package/dist/delegation/ast-code-parser.js +0 -1
- package/dist/delegation/complexity-analyzer.js +0 -1
- package/dist/delegation/dependency-graph-builder.js +0 -1
- package/dist/delegation/index.js +0 -1
- package/dist/delegation/metrics-aggregator.js +0 -1
- package/dist/delegation/session-coordinator.js +0 -1
- package/dist/delegation/strategy-selector.js +0 -1
- package/dist/delegation/voting-coordinator.js +0 -1
- package/dist/delegation/voting-types.js +0 -1
- package/dist/delegation/weighted-voting-aggregator.js +0 -1
- package/dist/enforcement/core/index.js +0 -1
- package/dist/enforcement/core/rule-executor.js +0 -1
- package/dist/enforcement/core/rule-hierarchy.js +0 -1
- package/dist/enforcement/core/rule-registry.js +0 -1
- package/dist/enforcement/core/violation-fixer.js +0 -1
- package/dist/enforcement/index.js +0 -1
- package/dist/enforcement/loaders/agent-triage-loader.js +0 -1
- package/dist/enforcement/loaders/agents-md-validation-loader.js +0 -1
- package/dist/enforcement/loaders/base-loader.js +0 -1
- package/dist/enforcement/loaders/codex-loader.js +0 -1
- package/dist/enforcement/loaders/index.js +0 -1
- package/dist/enforcement/loaders/loader-orchestrator.js +0 -1
- package/dist/enforcement/loaders/processor-loader.js +0 -1
- package/dist/enforcement/types.js +0 -1
- package/dist/enforcement/validators/architecture-validators.js +0 -1
- package/dist/enforcement/validators/base-validator.js +0 -1
- package/dist/enforcement/validators/code-quality-validators.js +0 -1
- package/dist/enforcement/validators/index.js +0 -1
- package/dist/enforcement/validators/security-validators.js +0 -1
- package/dist/enforcement/validators/testing-validators.js +0 -1
- package/dist/enforcement/validators/validator-registry.js +0 -1
- package/dist/governance/codex-policy.service.js +0 -1
- package/dist/inference/inference-agent-invoker.js +67 -0
- package/dist/inference/inference-applier.js +178 -0
- package/dist/inference/inference-cycle.js +51 -827
- package/dist/inference/inference-proposal-generator.js +149 -0
- package/dist/infrastructure/iac-validator.js +465 -0
- package/dist/infrastructure/schemas/cloud-schemas.js +488 -0
- package/dist/integrations/base/ExampleIntegration.js +0 -1
- package/dist/integrations/base/Integration.js +0 -1
- package/dist/integrations/base/index.js +0 -1
- package/dist/integrations/base/registry.js +0 -1
- package/dist/integrations/base/types.js +0 -1
- package/dist/integrations/enforcement-gate.js +3 -3
- package/dist/integrations/governance/governance-client.js +0 -1
- package/dist/integrations/governance/index.js +11 -19
- package/dist/integrations/governance/types.js +0 -1
- package/dist/integrations/hermes-agent/__init__.py +4 -0
- package/dist/integrations/hermes-agent/bridge.mjs +37 -0
- package/dist/integrations/openclaw/api-server.js +0 -1
- package/dist/integrations/openclaw/client.js +0 -1
- package/dist/integrations/openclaw/config.js +0 -1
- package/dist/integrations/openclaw/hooks/xray-hooks.js +0 -1
- package/dist/integrations/openclaw/index.js +0 -1
- package/dist/integrations/openclaw/types.js +0 -1
- package/dist/integrations/plugins/index.js +0 -1
- package/dist/integrations/plugins/plugin-integration.js +0 -1
- package/dist/integrations/plugins/plugin-registry.js +0 -1
- package/dist/mcps/agent-resolver.js +0 -1
- package/dist/mcps/architect-tools.server.js +119 -185
- package/dist/mcps/auto-format.server.js +56 -74
- package/dist/mcps/boot-orchestrator.server.js +67 -85
- package/dist/mcps/config/config-loader.js +6 -0
- package/dist/mcps/config/plugin-server-registry.js +0 -1
- package/dist/mcps/enforcer-tools.server.js +207 -273
- package/dist/mcps/estimation.server.js +63 -107
- package/dist/mcps/framework-compliance-audit.server.js +52 -81
- package/dist/mcps/framework-help.server.js +71 -89
- package/dist/mcps/governance.server.js +97 -149
- package/dist/mcps/knowledge-skills/api-design.server.js +33 -65
- package/dist/mcps/knowledge-skills/architecture-patterns.server.js +33 -65
- package/dist/mcps/knowledge-skills/bug-triage-specialist.server.js +123 -163
- package/dist/mcps/knowledge-skills/code-analyzer.server.js +210 -237
- package/dist/mcps/knowledge-skills/code-review.server.js +108 -142
- package/dist/mcps/knowledge-skills/content-creator.server.js +203 -225
- package/dist/mcps/knowledge-skills/database-design.server.js +116 -150
- package/dist/mcps/knowledge-skills/devops-deployment.server.js +123 -157
- package/dist/mcps/knowledge-skills/git-workflow.server.js +34 -67
- package/dist/mcps/knowledge-skills/growth-strategist.server.js +301 -323
- package/dist/mcps/knowledge-skills/log-monitor.server.js +139 -159
- package/dist/mcps/knowledge-skills/mobile-development.server.js +170 -200
- package/dist/mcps/knowledge-skills/multimodal-looker.server.js +122 -158
- package/dist/mcps/knowledge-skills/performance-optimization.server.js +88 -138
- package/dist/mcps/knowledge-skills/project-analysis.server.js +131 -218
- package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +115 -150
- package/dist/mcps/knowledge-skills/security-audit.server.js +16 -143
- package/dist/mcps/knowledge-skills/seo-consultant.server.js +20 -213
- package/dist/mcps/knowledge-skills/session-management.server.js +13 -90
- package/dist/mcps/knowledge-skills/skill-invocation.server.js +43 -421
- package/dist/mcps/knowledge-skills/strategist.server.js +10 -55
- package/dist/mcps/knowledge-skills/tech-writer.server.js +16 -191
- package/dist/mcps/knowledge-skills/testing-best-practices.server.js +18 -191
- package/dist/mcps/knowledge-skills/testing-strategy.server.js +18 -156
- package/dist/mcps/knowledge-skills/ui-ux-design.server.js +22 -296
- package/dist/mcps/lint.server.js +50 -91
- package/dist/mcps/model-health-check.server.js +32 -60
- package/dist/mcps/orchestrator/aside-context.js +207 -0
- package/dist/mcps/orchestrator/config/agent-capabilities.js +30 -11
- package/dist/mcps/orchestrator/config/memory-routing-bridge.js +70 -0
- package/dist/mcps/orchestrator/execution/execution-planner.js +25 -7
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +5 -1
- package/dist/mcps/orchestrator/handlers/status-handler.js +8 -1
- package/dist/mcps/orchestrator/handlers/task-handler.js +59 -1
- package/dist/mcps/orchestrator/index.js +5 -0
- package/dist/mcps/orchestrator/server.js +63 -8
- package/dist/mcps/performance-analysis.server.js +56 -87
- package/dist/mcps/processor-pipeline.server.js +68 -99
- package/dist/mcps/researcher.server.js +80 -153
- package/dist/mcps/security-scan.server.js +56 -70
- package/dist/mcps/shared/knowledge-skill-base.js +11 -4
- package/dist/mcps/state-manager.server.js +124 -152
- package/dist/memory-routing/index.js +4 -0
- package/dist/memory-routing/null-provider.js +51 -0
- package/dist/memory-routing/provider-loader.js +91 -0
- package/dist/memory-routing/provider-registry.js +40 -0
- package/dist/memory-routing/types.js +7 -0
- package/dist/memory-routing/validate-config.js +32 -0
- package/dist/monitoring/nudge-watchdog.js +0 -1
- package/dist/nucleus/default-plugins.js +13 -19
- package/dist/nucleus/index.js +0 -1
- package/dist/nucleus/thin-dispatch.js +29 -1
- package/dist/orchestrator/agent-spawn-governor.js +0 -1
- package/dist/orchestrator/intelligent-commit-batcher.js +2 -10
- package/dist/orchestrator/multi-agent-orchestration-coordinator.js +0 -1
- package/dist/orchestrator/orchestrator.js +8 -18
- package/dist/orchestrator/self-direction-activation.js +0 -1
- package/dist/orchestrator/universal-registry-bridge.js +0 -1
- package/dist/performance/performance-budget-enforcer.js +0 -1
- package/dist/performance/performance-regression-tester.js +0 -1
- package/dist/plugin/plugin-codex-context.js +87 -0
- package/dist/plugin/plugin-helpers.js +155 -0
- package/dist/plugin/plugin-logger.js +46 -0
- package/dist/plugin/plugin-modules.js +144 -0
- package/dist/plugin/plugin-quality-gate.js +88 -0
- package/dist/plugin/plugin-types.js +1 -0
- package/dist/plugin/xray-codex-injection.js +338 -0
- package/dist/postprocessor/PostProcessor.js +3 -9
- package/dist/postprocessor/analysis/CodeChangeAnalyzer.js +50 -0
- package/dist/postprocessor/config/ProcessorConfigLoader.js +16 -0
- package/dist/postprocessor/integration.js +194 -0
- package/dist/postprocessor/metamorphosis/SelfProposalEngine.js +472 -0
- package/dist/postprocessor/metamorphosis/index.js +1 -0
- package/dist/postprocessor/redeploy/RetryHandler.js +118 -0
- package/dist/postprocessor/services/RegressionAnalysisService.js +0 -1
- package/dist/postprocessor/triggers/APITrigger.js +0 -1
- package/dist/postprocessor/triggers/WebhookTrigger.js +0 -1
- package/dist/processors/implementations/agents-md-validation-processor.js +0 -1
- package/dist/processors/implementations/async-pattern-processor.js +0 -1
- package/dist/processors/implementations/console-log-guard-processor.js +0 -1
- package/dist/processors/implementations/coverage-analysis-processor.js +0 -1
- package/dist/processors/implementations/inference-improvement-processor.js +2 -9
- package/dist/processors/implementations/log-protection-processor.js +0 -1
- package/dist/processors/implementations/nudge-processor.js +0 -1
- package/dist/processors/implementations/performance-budget-processor.js +0 -1
- package/dist/processors/implementations/postprocessor-chain-validator.js +0 -1
- package/dist/processors/implementations/publish-preflight-processor.js +4 -12
- package/dist/processors/implementations/session-summary-processor.js +8 -16
- package/dist/processors/implementations/spawn-governance-processor.js +0 -1
- package/dist/processors/implementations/storytelling-trigger-processor.js +3 -28
- package/dist/processors/implementations/test-auto-creation-processor.js +0 -1
- package/dist/processors/implementations/typescript-compilation-processor.js +0 -1
- package/dist/processors/implementations/version-compliance-processor.js +0 -1
- package/dist/processors/processor-interfaces.js +0 -1
- package/dist/processors/processor-types.js +0 -1
- package/dist/scripts/integration.js +0 -1
- package/dist/security/comprehensive-security-audit.js +0 -1
- package/dist/security/security-agent-coordinator.js +0 -1
- package/dist/security/security-auditor.js +0 -1
- package/dist/security/security-hardener.js +0 -1
- package/dist/security/security-hardening-system.js +0 -1
- package/dist/security/security-headers.js +0 -1
- package/dist/security/security-orchestration-layer.js +0 -1
- package/dist/services/inference-tuner.js +0 -1
- package/dist/session/session-cleanup-manager.js +0 -1
- package/dist/session/session-monitor.js +0 -1
- package/dist/session/session-state-manager.js +0 -1
- package/dist/skills/xray-orchestrator/index.js +0 -1
- package/dist/utils/codex-parser.js +0 -1
- package/dist/utils/language-detector.js +0 -1
- package/dist/utils/shutdown-handler.js +0 -1
- package/dist/validation/agent-config-validator.js +280 -0
- package/dist/validation/orchestration-flow-validator.js +606 -0
- package/package.json +1 -1
- package/scripts/node/release.mjs +2 -2
- package/scripts/node/setup.cjs +28 -0
- package/scripts/node/universal-version-manager.js +1 -1
- package/src/mcps/agent-resolver.ts +0 -1
- package/src/mcps/architect-tools.server.ts +129 -211
- package/src/mcps/auto-format.server.ts +74 -103
- package/src/mcps/boot-orchestrator.server.ts +71 -96
- package/src/mcps/config/__tests__/config-loader.test.ts +6 -6
- package/src/mcps/config/config-loader.ts +7 -0
- package/src/mcps/config/plugin-server-registry.ts +0 -1
- package/src/mcps/enforcer-tools.server.ts +217 -294
- package/src/mcps/estimation.server.ts +62 -122
- package/src/mcps/framework-compliance-audit.server.ts +53 -95
- package/src/mcps/framework-help.server.ts +74 -96
- package/src/mcps/governance.server.ts +97 -162
- package/src/mcps/knowledge-skills/api-design.server.ts +33 -72
- package/src/mcps/knowledge-skills/architecture-patterns.server.ts +33 -72
- package/src/mcps/knowledge-skills/bug-triage-specialist.server.ts +148 -193
- package/src/mcps/knowledge-skills/code-analyzer.server.ts +222 -254
- package/src/mcps/knowledge-skills/code-review.server.ts +115 -157
- package/src/mcps/knowledge-skills/content-creator.server.ts +219 -246
- package/src/mcps/knowledge-skills/database-design.server.ts +119 -160
- package/src/mcps/knowledge-skills/devops-deployment.server.ts +126 -167
- package/src/mcps/knowledge-skills/git-workflow.server.ts +32 -77
- package/src/mcps/knowledge-skills/growth-strategist.server.ts +322 -360
- package/src/mcps/knowledge-skills/log-monitor.server.ts +68 -95
- package/src/mcps/knowledge-skills/mobile-development.server.ts +16 -56
- package/src/mcps/knowledge-skills/multimodal-looker.server.ts +13 -59
- package/src/mcps/knowledge-skills/performance-optimization.server.ts +13 -74
- package/src/mcps/knowledge-skills/project-analysis.server.ts +13 -120
- package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +13 -60
- package/src/mcps/knowledge-skills/security-audit.server.ts +19 -157
- package/src/mcps/knowledge-skills/seo-consultant.server.ts +23 -227
- package/src/mcps/knowledge-skills/session-management.server.ts +17 -106
- package/src/mcps/knowledge-skills/skill-invocation.server.ts +45 -446
- package/src/mcps/knowledge-skills/strategist.server.ts +13 -63
- package/src/mcps/knowledge-skills/tech-writer.server.ts +19 -204
- package/src/mcps/knowledge-skills/testing-best-practices.server.ts +21 -204
- package/src/mcps/knowledge-skills/testing-strategy.server.ts +21 -165
- package/src/mcps/knowledge-skills/ui-ux-design.server.ts +25 -342
- package/src/mcps/lint.server.ts +52 -105
- package/src/mcps/model-health-check.server.ts +34 -70
- package/src/mcps/orchestrator/aside-context.ts +245 -0
- package/src/mcps/orchestrator/config/agent-capabilities.ts +49 -14
- package/src/mcps/orchestrator/config/memory-routing-bridge.ts +80 -0
- package/src/mcps/orchestrator/execution/execution-planner.ts +36 -9
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +9 -3
- package/src/mcps/orchestrator/handlers/status-handler.ts +11 -1
- package/src/mcps/orchestrator/handlers/task-handler.ts +78 -2
- package/src/mcps/orchestrator/index.ts +29 -0
- package/src/mcps/orchestrator/server.ts +79 -24
- package/src/mcps/orchestrator/types.ts +50 -0
- package/src/mcps/performance-analysis.server.ts +59 -102
- package/src/mcps/processor-pipeline.server.ts +70 -108
- package/src/mcps/researcher.server.ts +87 -175
- package/src/mcps/security-scan.server.ts +57 -76
- package/src/mcps/shared/knowledge-skill-base.ts +12 -4
- package/src/mcps/state-manager.server.ts +129 -169
- package/src/opencode/codex.codex +1 -1
- package/src/opencode/commands/auto-format.md +3 -3
- package/src/opencode/commands/auto-summary-capture.md +2 -2
- package/src/opencode/commands/enforcer-daily-scan.md +3 -3
- package/src/opencode/commands/framework-compliance-audit.md +4 -4
- package/src/opencode/commands/interactive-validator.md +2 -2
- package/src/opencode/commands/job-summary-logger.md +2 -2
- package/src/opencode/commands/mode-switch.md +1 -1
- package/src/opencode/commands/model-health-check.md +2 -2
- package/src/opencode/commands/performance-analysis.md +2 -2
- package/src/opencode/commands/pre-commit-introspection.md +3 -3
- package/src/opencode/commands/security-scan.md +3 -3
- package/src/opencode/commands/sisyphus-validation.md +3 -3
- package/src/opencode/commands/summary-logger.md +2 -2
- package/src/skills/xray-orchestrator/index.ts +0 -1
- package/dist/nucleus/orchestrator.js +0 -479
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0xRay Integration Layer
|
|
3
|
+
*
|
|
4
|
+
* Provides generic connectors for integrating 0xRay's PostProcessor
|
|
5
|
+
* with external applications and frameworks.
|
|
6
|
+
*
|
|
7
|
+
* This is framework-agnostic - works with Express, Fastify, Koa, etc.
|
|
8
|
+
*
|
|
9
|
+
* @since 2026-03-08
|
|
10
|
+
*/
|
|
11
|
+
export { WebhookTrigger } from './triggers/WebhookTrigger.js';
|
|
12
|
+
export { APITrigger } from './triggers/APITrigger.js';
|
|
13
|
+
/**
|
|
14
|
+
* Generic 0xRay integration for any external application
|
|
15
|
+
*
|
|
16
|
+
* Provides:
|
|
17
|
+
* - Webhook receivers (GitHub, GitLab, Bitbucket, Stripe)
|
|
18
|
+
* - REST API triggers (manual trigger, retry, status)
|
|
19
|
+
* - Framework-agnostic (works with Express, Fastify, Koa, etc.)
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import { createXrayIntegration } from '0xray/integration';
|
|
24
|
+
*
|
|
25
|
+
* const postProcessor = new PostProcessor(stateManager);
|
|
26
|
+
* const integration = createXrayIntegration(postProcessor);
|
|
27
|
+
*
|
|
28
|
+
* // Get Express app for mounting
|
|
29
|
+
* app.use('/webhooks', integration.getWebhookApp());
|
|
30
|
+
* app.use('/api/post-process', integration.getAPIApp());
|
|
31
|
+
*
|
|
32
|
+
* // Or get raw routers for Fastify/Koa
|
|
33
|
+
* const webhookRouter = integration.getWebhookRouter();
|
|
34
|
+
* const apiRouter = integration.getAPIRouter();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export class XrayIntegration {
|
|
38
|
+
postProcessor;
|
|
39
|
+
webhookTrigger = null;
|
|
40
|
+
apiTrigger = null;
|
|
41
|
+
constructor(postProcessor) {
|
|
42
|
+
this.postProcessor = postProcessor;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Initialize all triggers with default configuration
|
|
46
|
+
*
|
|
47
|
+
* @param config - Optional configuration for triggers
|
|
48
|
+
*/
|
|
49
|
+
async initialize(config) {
|
|
50
|
+
const { WebhookTrigger } = await import('./triggers/WebhookTrigger.js');
|
|
51
|
+
const { APITrigger } = await import('./triggers/APITrigger.js');
|
|
52
|
+
// Initialize webhook trigger with default GitHub config
|
|
53
|
+
this.webhookTrigger = new WebhookTrigger(this.postProcessor, {
|
|
54
|
+
provider: 'github',
|
|
55
|
+
events: ['push', 'pull_request'],
|
|
56
|
+
path: '/webhooks/github',
|
|
57
|
+
verifySignature: true,
|
|
58
|
+
...config?.webhook
|
|
59
|
+
});
|
|
60
|
+
await this.webhookTrigger.initialize();
|
|
61
|
+
// Initialize API trigger with default config
|
|
62
|
+
this.apiTrigger = new APITrigger(this.postProcessor, {
|
|
63
|
+
enabled: true,
|
|
64
|
+
path: '/api/post-process',
|
|
65
|
+
...config?.api
|
|
66
|
+
});
|
|
67
|
+
await this.apiTrigger.initialize();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get webhook app for framework-specific mounting
|
|
71
|
+
*
|
|
72
|
+
* Returns an Express Application. For other frameworks,
|
|
73
|
+
* use getWebhookRouter() to get the router instance.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* // Express
|
|
78
|
+
* app.use('/webhooks', integration.getWebhookApp());
|
|
79
|
+
*
|
|
80
|
+
* // Fastify
|
|
81
|
+
* await fastify.register(integration.getWebhookRouter(), { prefix: '/webhooks' });
|
|
82
|
+
*
|
|
83
|
+
* // Koa
|
|
84
|
+
* app.use(integration.getWebhookRouter().routes());
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
getWebhookApp() {
|
|
88
|
+
return this.webhookTrigger?.getApp() ?? null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get webhook router (raw Express router)
|
|
92
|
+
*
|
|
93
|
+
* Useful for frameworks that need the router instance directly
|
|
94
|
+
* rather than the full Express app.
|
|
95
|
+
*/
|
|
96
|
+
getWebhookRouter() {
|
|
97
|
+
return this.webhookTrigger?.getApp() ?? null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get API trigger app for framework-specific mounting
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* // Express
|
|
105
|
+
* app.use('/api/post-process', integration.getAPIApp());
|
|
106
|
+
*
|
|
107
|
+
* // Fastify
|
|
108
|
+
* await fastify.register(integration.getAPIRouter(), { prefix: '/api/post-process' });
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
getAPIApp() {
|
|
112
|
+
return this.apiTrigger?.getApp() ?? null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get API trigger router (raw Express router)
|
|
116
|
+
*
|
|
117
|
+
* Useful for frameworks that need the router instance directly.
|
|
118
|
+
*/
|
|
119
|
+
getAPIRouter() {
|
|
120
|
+
return this.apiTrigger?.getApp() ?? null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Manually trigger PostProcessor via API
|
|
124
|
+
*
|
|
125
|
+
* Convenience method for programmatic triggering without
|
|
126
|
+
* going through the HTTP endpoint.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* await integration.trigger({
|
|
131
|
+
* tool: 'test',
|
|
132
|
+
* operation: 'run',
|
|
133
|
+
* reason: 'Manual test trigger'
|
|
134
|
+
* });
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
async trigger(options) {
|
|
138
|
+
const context = {
|
|
139
|
+
commitSha: `manual-${Date.now()}`,
|
|
140
|
+
repository: '',
|
|
141
|
+
branch: '',
|
|
142
|
+
author: 'manual',
|
|
143
|
+
files: [],
|
|
144
|
+
trigger: 'manual',
|
|
145
|
+
tool: options.tool,
|
|
146
|
+
operation: options.operation,
|
|
147
|
+
...(options.filePath !== undefined ? { filePath: options.filePath } : {}),
|
|
148
|
+
...(options.directory !== undefined ? { directory: options.directory } : {}),
|
|
149
|
+
};
|
|
150
|
+
await this.postProcessor.executePostProcessorLoop(context);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Shutdown all triggers
|
|
154
|
+
*/
|
|
155
|
+
async shutdown() {
|
|
156
|
+
if (this.webhookTrigger) {
|
|
157
|
+
this.webhookTrigger.shutdown();
|
|
158
|
+
}
|
|
159
|
+
if (this.apiTrigger) {
|
|
160
|
+
this.apiTrigger.shutdown();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Factory function for easy integration setup
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* import { createXrayIntegration } from '0xray/integration';
|
|
170
|
+
*
|
|
171
|
+
* // With default configuration
|
|
172
|
+
* const integration = createXrayIntegration(postProcessor);
|
|
173
|
+
* await integration.initialize();
|
|
174
|
+
*
|
|
175
|
+
* // With custom configuration
|
|
176
|
+
* const integration = createXrayIntegration(postProcessor);
|
|
177
|
+
* await integration.initialize({
|
|
178
|
+
* webhook: {
|
|
179
|
+
* provider: 'gitlab',
|
|
180
|
+
* secret: process.env.GITLAB_WEBHOOK_SECRET,
|
|
181
|
+
* events: ['push', 'merge_request'],
|
|
182
|
+
* path: '/webhooks/gitlab'
|
|
183
|
+
* },
|
|
184
|
+
* api: {
|
|
185
|
+
* path: '/api/stray-trigger',
|
|
186
|
+
* apiKey: process.env.API_KEY
|
|
187
|
+
* }
|
|
188
|
+
* });
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
export function createXrayIntegration(postProcessor) {
|
|
192
|
+
return new XrayIntegration(postProcessor);
|
|
193
|
+
}
|
|
194
|
+
// Backward compat aliases
|
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SelfProposalEngine — Phase 2.2
|
|
3
|
+
*
|
|
4
|
+
* Concrete MetamorphosisEngine that reads activity.log, parses structured
|
|
5
|
+
* log entries, detects semantic patterns, generates governance proposals
|
|
6
|
+
* (type: 'metamorphosis'), and submits them through the full 3-agent +
|
|
7
|
+
* Dynamo governance pipeline.
|
|
8
|
+
*
|
|
9
|
+
* Safety constraints:
|
|
10
|
+
* - Max proposals per hour (default 1, configurable)
|
|
11
|
+
* - Circuit breaker: after N consecutive failures, halt for cooldown (default 3/24h)
|
|
12
|
+
* - Only proposes changes to whitelisted targets
|
|
13
|
+
* - All proposals go through full governance with metamorphosisThreshold (default 0.7)
|
|
14
|
+
* - Detection thresholds are configurable (not hard-coded)
|
|
15
|
+
*
|
|
16
|
+
* Coupling note: currently triggered by PostProcessor.onPhase(). A future
|
|
17
|
+
* refactor should extract log-reading into a dedicated LogReader that can
|
|
18
|
+
* run on its own schedule or fs.watch, decoupling from PostProcessor lifecycle.
|
|
19
|
+
*/
|
|
20
|
+
import { promises as fs, existsSync } from 'fs';
|
|
21
|
+
import { join } from 'path';
|
|
22
|
+
import { frameworkLogger } from '../../core/framework-logger.js';
|
|
23
|
+
import { handleGovernRequest } from '../../nucleus/govern-http.js';
|
|
24
|
+
const DEFAULT_CONFIG = {
|
|
25
|
+
maxProposalsPerHour: 1,
|
|
26
|
+
circuitBreakerThreshold: 3,
|
|
27
|
+
circuitBreakerCooldownHours: 24,
|
|
28
|
+
activityLogPath: 'logs/framework/activity.log',
|
|
29
|
+
whitelistedTargets: ['config/', 'features.json', 'src/processors/'],
|
|
30
|
+
maxLogLines: 100,
|
|
31
|
+
errorThreshold: 5,
|
|
32
|
+
warningThreshold: 10,
|
|
33
|
+
governanceRejectionThreshold: 3,
|
|
34
|
+
proposalConfidence: 0.7,
|
|
35
|
+
metamorphosisThreshold: 0.7,
|
|
36
|
+
projectRoot: process.cwd(),
|
|
37
|
+
};
|
|
38
|
+
const LOG_LINE_PATTERN = /^(\d{4}-\d{2}-\d{2}T[^ ]+)\s+(?:\[([^\]]*)\]\s+)?(?:\[([^\]]*)\]\s+)?\[([^\]]*)\]\s+(\S+)\s+-\s+(\w+)(?:\s+\|(.+))?$/;
|
|
39
|
+
function parseLogEntry(line) {
|
|
40
|
+
const match = line.match(LOG_LINE_PATTERN);
|
|
41
|
+
if (!match) {
|
|
42
|
+
// Fallback: try JSON parse for entangled log entries
|
|
43
|
+
try {
|
|
44
|
+
const json = JSON.parse(line);
|
|
45
|
+
if (json && typeof json === 'object' && json.action) {
|
|
46
|
+
return {
|
|
47
|
+
timestamp: json.timestamp ? new Date(json.timestamp).toISOString() : new Date().toISOString(),
|
|
48
|
+
component: json.component || 'unknown',
|
|
49
|
+
action: json.action,
|
|
50
|
+
status: (json.status || json.level || 'info').toLowerCase(),
|
|
51
|
+
details: json.details || json,
|
|
52
|
+
raw: line,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch { }
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const [, timestamp, , , component, action, status, detailsStr] = match;
|
|
60
|
+
let details;
|
|
61
|
+
if (detailsStr) {
|
|
62
|
+
try {
|
|
63
|
+
details = JSON.parse(detailsStr.trim());
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
details = { rawDetails: detailsStr.trim() };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const entry = {
|
|
70
|
+
timestamp: timestamp ?? new Date().toISOString(),
|
|
71
|
+
component: component || 'unknown',
|
|
72
|
+
action: action ?? 'unknown',
|
|
73
|
+
status: (status ?? 'info').toLowerCase(),
|
|
74
|
+
raw: line,
|
|
75
|
+
};
|
|
76
|
+
if (details !== undefined) {
|
|
77
|
+
entry.details = details;
|
|
78
|
+
}
|
|
79
|
+
return entry;
|
|
80
|
+
}
|
|
81
|
+
export class SelfProposalEngine {
|
|
82
|
+
name = 'self-proposal';
|
|
83
|
+
config;
|
|
84
|
+
proposalHistory = [];
|
|
85
|
+
consecutiveFailures = 0;
|
|
86
|
+
circuitBreakerUntil = 0;
|
|
87
|
+
constructor(config) {
|
|
88
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
89
|
+
}
|
|
90
|
+
async onPhase(phase, context) {
|
|
91
|
+
if (phase !== 'monitoring-complete' && phase !== 'post-process-complete') {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
await frameworkLogger.log('self-proposal', 'phase-hook', 'info', {
|
|
95
|
+
phase,
|
|
96
|
+
message: 'Self-proposal engine triggered by phase',
|
|
97
|
+
});
|
|
98
|
+
if (this.isCircuitBreakerActive()) {
|
|
99
|
+
await frameworkLogger.log('self-proposal', 'circuit-breaker-active', 'warning', {
|
|
100
|
+
message: `Circuit breaker active until ${new Date(this.circuitBreakerUntil).toISOString()}`,
|
|
101
|
+
consecutiveFailures: this.consecutiveFailures,
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (this.isRateLimited()) {
|
|
106
|
+
await frameworkLogger.log('self-proposal', 'rate-limited', 'info', {
|
|
107
|
+
message: 'Max proposals per hour reached',
|
|
108
|
+
});
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
await this.evaluateAndPropose();
|
|
112
|
+
}
|
|
113
|
+
async onProposal(proposal) {
|
|
114
|
+
await frameworkLogger.log('self-proposal', 'external-proposal', 'info', {
|
|
115
|
+
proposalId: proposal.id,
|
|
116
|
+
type: proposal.type,
|
|
117
|
+
target: proposal.target,
|
|
118
|
+
impact: proposal.impact,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
isCircuitBreakerActive() {
|
|
122
|
+
if (this.consecutiveFailures >= this.config.circuitBreakerThreshold) {
|
|
123
|
+
if (Date.now() < this.circuitBreakerUntil) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
this.consecutiveFailures = 0;
|
|
127
|
+
this.circuitBreakerUntil = 0;
|
|
128
|
+
}
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
isRateLimited() {
|
|
132
|
+
const oneHourAgo = Date.now() - 60 * 60 * 1000;
|
|
133
|
+
const recentProposals = this.proposalHistory.filter(a => a.timestamp > oneHourAgo);
|
|
134
|
+
return recentProposals.length >= this.config.maxProposalsPerHour;
|
|
135
|
+
}
|
|
136
|
+
getMetrics() {
|
|
137
|
+
const oneHourAgo = Date.now() - 60 * 60 * 1000;
|
|
138
|
+
const recentProposals = this.proposalHistory.filter(a => a.timestamp > oneHourAgo);
|
|
139
|
+
return {
|
|
140
|
+
totalProposals: this.proposalHistory.length,
|
|
141
|
+
recentProposals: recentProposals.length,
|
|
142
|
+
consecutiveFailures: this.consecutiveFailures,
|
|
143
|
+
circuitBreakerActive: this.isCircuitBreakerActive(),
|
|
144
|
+
circuitBreakerUntil: this.circuitBreakerUntil,
|
|
145
|
+
successRate: this.proposalHistory.length > 0
|
|
146
|
+
? this.proposalHistory.filter(a => a.result === 'approved').length / this.proposalHistory.length
|
|
147
|
+
: 0,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
async evaluateAndPropose() {
|
|
151
|
+
let logEntries = [];
|
|
152
|
+
try {
|
|
153
|
+
const logContent = await fs.readFile(this.config.activityLogPath, 'utf-8');
|
|
154
|
+
const lines = logContent.trim().split('\n');
|
|
155
|
+
logEntries = lines.slice(-this.config.maxLogLines).filter(line => line.trim().length > 0);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
await frameworkLogger.log('self-proposal', 'log-read-error', 'warning', {
|
|
159
|
+
path: this.config.activityLogPath,
|
|
160
|
+
message: 'Activity log not found or unreadable — skipping self-proposal',
|
|
161
|
+
});
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const patterns = this.detectPatterns(logEntries);
|
|
165
|
+
if (patterns.length === 0) {
|
|
166
|
+
await frameworkLogger.log('self-proposal', 'no-patterns', 'info', {
|
|
167
|
+
message: 'No actionable patterns detected in activity log',
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
for (const pattern of patterns) {
|
|
172
|
+
await this.submitProposal(pattern);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Detect actionable patterns from parsed activity log entries.
|
|
177
|
+
* Uses structured parsing instead of raw string matching to handle
|
|
178
|
+
* the actual xray log format:
|
|
179
|
+
* ISO_TIMESTAMP [jobId] [traceId.spanId] [component] action - STATUS | {details}
|
|
180
|
+
*/
|
|
181
|
+
detectPatterns(entries) {
|
|
182
|
+
const parsed = entries.map(parseLogEntry).filter((e) => e !== null);
|
|
183
|
+
const proposals = [];
|
|
184
|
+
const errorEntries = parsed.filter(e => e.status === 'error');
|
|
185
|
+
const warningEntries = parsed.filter(e => e.status === 'warning');
|
|
186
|
+
const rejectedEntries = parsed.filter(e => e.component === 'governance' && (e.status === 'rejected' || e.details?.decision === 'reject'));
|
|
187
|
+
if (errorEntries.length >= this.config.errorThreshold) {
|
|
188
|
+
const components = [...new Set(errorEntries.map(e => e.component))];
|
|
189
|
+
proposals.push({
|
|
190
|
+
id: `meta-errors-${Date.now()}`,
|
|
191
|
+
type: 'modify',
|
|
192
|
+
target: 'config/error-handling',
|
|
193
|
+
description: `Elevated error rate: ${errorEntries.length} errors in last ${this.config.maxLogLines} entries. Components: ${components.join(', ')}. Propose adjusting error handling thresholds.`,
|
|
194
|
+
rationale: `High error count (${errorEntries.length}) across ${components.length} component(s) indicates a systemic issue. Affected components: ${components.join(', ')}. Governance review recommended for self-optimization.`,
|
|
195
|
+
impact: 'medium',
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (warningEntries.length >= this.config.warningThreshold) {
|
|
199
|
+
const components = [...new Set(warningEntries.map(e => e.component))];
|
|
200
|
+
proposals.push({
|
|
201
|
+
id: `meta-warnings-${Date.now()}`,
|
|
202
|
+
type: 'modify',
|
|
203
|
+
target: 'config/monitoring',
|
|
204
|
+
description: `Elevated warning rate: ${warningEntries.length} warnings in last ${this.config.maxLogLines} entries. Components: ${components.join(', ')}. Propose adjusting monitoring sensitivity.`,
|
|
205
|
+
rationale: `Frequent warnings (${warningEntries.length}) across ${components.length} component(s) may indicate configuration drift. Affected: ${components.join(', ')}.`,
|
|
206
|
+
impact: 'low',
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
if (rejectedEntries.length >= this.config.governanceRejectionThreshold) {
|
|
210
|
+
proposals.push({
|
|
211
|
+
id: `meta-governance-rejections-${Date.now()}`,
|
|
212
|
+
type: 'modify',
|
|
213
|
+
target: 'config/governance',
|
|
214
|
+
description: `Repeated governance rejections: ${rejectedEntries.length} in last ${this.config.maxLogLines} entries. Propose reviewing governance thresholds or submission patterns.`,
|
|
215
|
+
rationale: `${rejectedEntries.length} governance rejections suggest a pattern mismatch between proposals and governance criteria. Review recommended.`,
|
|
216
|
+
impact: 'medium',
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
return proposals.filter(p => this.config.whitelistedTargets.some(t => p.target.startsWith(t)));
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Apply an approved self-evolution proposal by recording the change
|
|
223
|
+
* in a state file within the first matching whitelisted target directory.
|
|
224
|
+
* Returns true if the change was written and verified, false otherwise.
|
|
225
|
+
*/
|
|
226
|
+
async applySelfProposal(pattern, score, decision) {
|
|
227
|
+
const matchedTarget = this.config.whitelistedTargets.find(t => pattern.target.startsWith(t));
|
|
228
|
+
if (!matchedTarget) {
|
|
229
|
+
await frameworkLogger.log('self-proposal', 'apply-no-matching-target', 'warning', {
|
|
230
|
+
proposalId: pattern.id,
|
|
231
|
+
target: pattern.target,
|
|
232
|
+
message: 'No whitelisted target matches this proposal — skipping apply',
|
|
233
|
+
});
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
const root = this.config.projectRoot;
|
|
237
|
+
const stateDir = join(root, matchedTarget);
|
|
238
|
+
const statePath = join(stateDir, 'self-evolution-state.json');
|
|
239
|
+
let applied = [];
|
|
240
|
+
try {
|
|
241
|
+
const content = await fs.readFile(statePath, 'utf-8');
|
|
242
|
+
const parsed = JSON.parse(content);
|
|
243
|
+
if (Array.isArray(parsed.applied))
|
|
244
|
+
applied = parsed.applied;
|
|
245
|
+
}
|
|
246
|
+
catch { }
|
|
247
|
+
applied.push({
|
|
248
|
+
proposalId: pattern.id,
|
|
249
|
+
target: pattern.target,
|
|
250
|
+
type: pattern.type,
|
|
251
|
+
description: pattern.description,
|
|
252
|
+
rationale: pattern.rationale,
|
|
253
|
+
impact: pattern.impact,
|
|
254
|
+
metamorphosisScore: score,
|
|
255
|
+
decision: decision,
|
|
256
|
+
appliedAt: new Date().toISOString(),
|
|
257
|
+
});
|
|
258
|
+
try {
|
|
259
|
+
await fs.mkdir(stateDir, { recursive: true });
|
|
260
|
+
// Backup existing state file before overwriting
|
|
261
|
+
const backupDir = join(root, '.xray', 'metamorphosis', 'backups');
|
|
262
|
+
let backupPath = null;
|
|
263
|
+
if (existsSync(statePath)) {
|
|
264
|
+
await fs.mkdir(backupDir, { recursive: true });
|
|
265
|
+
backupPath = join(backupDir, `self-evolution-state-${Date.now()}.json`);
|
|
266
|
+
await fs.copyFile(statePath, backupPath);
|
|
267
|
+
await frameworkLogger.log('self-proposal', 'backup-created', 'info', {
|
|
268
|
+
proposalId: pattern.id,
|
|
269
|
+
backupPath,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
await fs.writeFile(statePath, JSON.stringify({ applied }, null, 2), 'utf-8');
|
|
274
|
+
}
|
|
275
|
+
catch (writeError) {
|
|
276
|
+
// Restore from backup on write failure
|
|
277
|
+
if (backupPath && existsSync(backupPath)) {
|
|
278
|
+
await fs.copyFile(backupPath, statePath);
|
|
279
|
+
await frameworkLogger.log('self-proposal', 'restored-from-backup', 'warning', {
|
|
280
|
+
proposalId: pattern.id,
|
|
281
|
+
backupPath,
|
|
282
|
+
error: writeError instanceof Error ? writeError.message : String(writeError),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
await frameworkLogger.log('self-proposal', 'apply-write-error', 'error', {
|
|
286
|
+
proposalId: pattern.id,
|
|
287
|
+
path: statePath,
|
|
288
|
+
error: writeError instanceof Error ? writeError.message : String(writeError),
|
|
289
|
+
});
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (writeError) {
|
|
294
|
+
await frameworkLogger.log('self-proposal', 'apply-mkdir-error', 'error', {
|
|
295
|
+
proposalId: pattern.id,
|
|
296
|
+
error: writeError instanceof Error ? writeError.message : String(writeError),
|
|
297
|
+
});
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
const verify = await fs.readFile(statePath, 'utf-8');
|
|
302
|
+
const parsed = JSON.parse(verify);
|
|
303
|
+
const found = Array.isArray(parsed.applied) && parsed.applied.some((a) => a.proposalId === pattern.id);
|
|
304
|
+
if (!found) {
|
|
305
|
+
await frameworkLogger.log('self-proposal', 'apply-verify-failed', 'error', {
|
|
306
|
+
proposalId: pattern.id,
|
|
307
|
+
message: 'Applied change not found in state file after write — verification failed',
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
return found;
|
|
311
|
+
}
|
|
312
|
+
catch (verifyError) {
|
|
313
|
+
await frameworkLogger.log('self-proposal', 'apply-verify-error', 'error', {
|
|
314
|
+
proposalId: pattern.id,
|
|
315
|
+
error: verifyError instanceof Error ? verifyError.message : String(verifyError),
|
|
316
|
+
});
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async submitProposal(pattern) {
|
|
321
|
+
const governanceRequest = {
|
|
322
|
+
proposals: [{
|
|
323
|
+
id: pattern.id,
|
|
324
|
+
type: 'metamorphosis',
|
|
325
|
+
title: `Self-proposal: ${pattern.description.slice(0, 80)}`,
|
|
326
|
+
description: pattern.description,
|
|
327
|
+
evidence: [pattern.rationale],
|
|
328
|
+
source: 'metamorphosis',
|
|
329
|
+
confidence: this.config.proposalConfidence,
|
|
330
|
+
tags: ['0xray'],
|
|
331
|
+
}],
|
|
332
|
+
context: {
|
|
333
|
+
project: 'xray-self',
|
|
334
|
+
phase: 'self-evolution',
|
|
335
|
+
source: 'self-proposal-engine',
|
|
336
|
+
tags: ['0xray'],
|
|
337
|
+
},
|
|
338
|
+
options: {
|
|
339
|
+
requireExternalDynamo: true,
|
|
340
|
+
metamorphosisThreshold: this.config.metamorphosisThreshold,
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
await frameworkLogger.log('self-proposal', 'submitting', 'info', {
|
|
344
|
+
proposalId: pattern.id,
|
|
345
|
+
target: pattern.target,
|
|
346
|
+
impact: pattern.impact,
|
|
347
|
+
});
|
|
348
|
+
try {
|
|
349
|
+
const response = await handleGovernRequest(governanceRequest);
|
|
350
|
+
const result = response.results[0];
|
|
351
|
+
if (!result) {
|
|
352
|
+
await frameworkLogger.log('self-proposal', 'no-result', 'warning', {
|
|
353
|
+
proposalId: pattern.id,
|
|
354
|
+
message: 'Governance returned no results',
|
|
355
|
+
});
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const decision = result.finalDecision;
|
|
359
|
+
const attempt = {
|
|
360
|
+
timestamp: Date.now(),
|
|
361
|
+
result: decision === 'approve' ? 'approved' : decision === 'reject' ? 'rejected' : 'needs_revision',
|
|
362
|
+
};
|
|
363
|
+
if (result.metamorphosisScore !== undefined) {
|
|
364
|
+
attempt.metamorphosisScore = result.metamorphosisScore;
|
|
365
|
+
}
|
|
366
|
+
this.proposalHistory.push(attempt);
|
|
367
|
+
if (decision === 'approve' && (result.metamorphosisScore ?? 0) >= this.config.metamorphosisThreshold) {
|
|
368
|
+
this.consecutiveFailures = 0;
|
|
369
|
+
await frameworkLogger.log('self-proposal', 'approved', 'success', {
|
|
370
|
+
proposalId: pattern.id,
|
|
371
|
+
metamorphosisScore: result.metamorphosisScore,
|
|
372
|
+
finalDecision: decision,
|
|
373
|
+
averageConfidence: result.averageConfidence,
|
|
374
|
+
voteSummary: result.votes ? result.votes.map((v) => ({ server: v.server, decision: v.decision })) : undefined,
|
|
375
|
+
message: 'Self-evolution proposal approved by governance — applying change',
|
|
376
|
+
tags: ['0xray'],
|
|
377
|
+
});
|
|
378
|
+
const applied = await this.applySelfProposal(pattern, result.metamorphosisScore, decision);
|
|
379
|
+
if (applied) {
|
|
380
|
+
await frameworkLogger.log('self-proposal', 'applied', 'success', {
|
|
381
|
+
proposalId: pattern.id,
|
|
382
|
+
target: pattern.target,
|
|
383
|
+
metamorphosisScore: result.metamorphosisScore,
|
|
384
|
+
decision,
|
|
385
|
+
message: 'Self-evolution change applied and verified',
|
|
386
|
+
tags: ['0xray'],
|
|
387
|
+
});
|
|
388
|
+
await this.audit0xrayProposalTraceability(pattern.id, decision, result.metamorphosisScore);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
this.consecutiveFailures++;
|
|
392
|
+
if (this.consecutiveFailures >= this.config.circuitBreakerThreshold) {
|
|
393
|
+
this.circuitBreakerUntil = Date.now() + this.config.circuitBreakerCooldownHours * 60 * 60 * 1000;
|
|
394
|
+
}
|
|
395
|
+
await frameworkLogger.log('self-proposal', 'apply-failed', 'error', {
|
|
396
|
+
proposalId: pattern.id,
|
|
397
|
+
target: pattern.target,
|
|
398
|
+
consecutiveFailures: this.consecutiveFailures,
|
|
399
|
+
message: 'Self-evolution change apply failed — circuit breaker may activate',
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
this.consecutiveFailures++;
|
|
405
|
+
if (this.consecutiveFailures >= this.config.circuitBreakerThreshold) {
|
|
406
|
+
this.circuitBreakerUntil = Date.now() + this.config.circuitBreakerCooldownHours * 60 * 60 * 1000;
|
|
407
|
+
}
|
|
408
|
+
await frameworkLogger.log('self-proposal', 'not-approved', 'warning', {
|
|
409
|
+
proposalId: pattern.id,
|
|
410
|
+
decision: decision,
|
|
411
|
+
metamorphosisScore: result.metamorphosisScore,
|
|
412
|
+
consecutiveFailures: this.consecutiveFailures,
|
|
413
|
+
circuitBreakerUntil: this.circuitBreakerUntil || 'not active',
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch (error) {
|
|
418
|
+
this.consecutiveFailures++;
|
|
419
|
+
await frameworkLogger.log('self-proposal', 'submission-error', 'error', {
|
|
420
|
+
proposalId: pattern.id,
|
|
421
|
+
error: error instanceof Error ? error.message : String(error),
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Post-apply audit for Term 72 (Self-Evolution Traceability).
|
|
427
|
+
* For 0xray-tagged proposals (framework self-evolution), asserts that
|
|
428
|
+
* frameworkLogger entries exist with full provenance:
|
|
429
|
+
* - source proposal ID
|
|
430
|
+
* - governance vote results / finalDecision / averageConfidence
|
|
431
|
+
* - metamorphosisScore
|
|
432
|
+
* Logs the audit outcome via frameworkLogger.
|
|
433
|
+
*/
|
|
434
|
+
async audit0xrayProposalTraceability(proposalId, decision, score) {
|
|
435
|
+
if (!proposalId) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
try {
|
|
439
|
+
const logContent = await fs.readFile(this.config.activityLogPath, 'utf-8');
|
|
440
|
+
const lines = logContent.trim().split('\n').filter(l => l.trim().length > 0);
|
|
441
|
+
const recentLines = lines.slice(-this.config.maxLogLines);
|
|
442
|
+
// Look for entries tied to this proposalId that carry the required provenance.
|
|
443
|
+
// We expect 'approved' (with vote info) and 'applied' (with score/decision) for 0xray self-proposals.
|
|
444
|
+
const relevant = recentLines.filter(line => line.includes(proposalId) &&
|
|
445
|
+
(line.includes('approved') || line.includes('applied') || line.includes('submitting')));
|
|
446
|
+
const hasProposalId = relevant.length > 0;
|
|
447
|
+
const hasGovernanceVote = relevant.some(l => l.includes('finalDecision') || l.includes('averageConfidence') || l.includes('voteSummary'));
|
|
448
|
+
const hasMetamorphosisScore = relevant.some(l => l.includes('metamorphosisScore'));
|
|
449
|
+
const has0xrayTag = relevant.some(l => l.includes('0xray') || l.includes('"tags"') && l.includes('0xray'));
|
|
450
|
+
const auditPassed = hasProposalId && hasGovernanceVote && hasMetamorphosisScore && has0xrayTag;
|
|
451
|
+
await frameworkLogger.log('self-proposal', 'post-apply-audit', auditPassed ? 'success' : 'warning', {
|
|
452
|
+
proposalId,
|
|
453
|
+
decision,
|
|
454
|
+
metamorphosisScore: score,
|
|
455
|
+
hasProposalId,
|
|
456
|
+
hasGovernanceVote,
|
|
457
|
+
hasMetamorphosisScore,
|
|
458
|
+
has0xrayTag,
|
|
459
|
+
relevantEntryCount: relevant.length,
|
|
460
|
+
message: auditPassed
|
|
461
|
+
? 'Term 72 traceability audit passed: frameworkLogger entries with full provenance (proposalId, governance votes, metamorphosisScore, 0xray tag) verified for self-evolution proposal.'
|
|
462
|
+
: 'Term 72 traceability audit warning: missing or incomplete frameworkLogger provenance for 0xray-tagged self-evolution proposal.',
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
catch (auditError) {
|
|
466
|
+
await frameworkLogger.log('self-proposal', 'post-apply-audit-error', 'error', {
|
|
467
|
+
proposalId,
|
|
468
|
+
error: auditError instanceof Error ? auditError.message : String(auditError),
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SelfProposalEngine } from './SelfProposalEngine.js';
|