0xray 2.1.4 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/dist/CHANGELOG.md +31 -0
  2. package/dist/cli/commands/govern.d.ts +29 -0
  3. package/dist/cli/commands/govern.js +152 -0
  4. package/dist/cli/index.js +29 -216
  5. package/dist/core/framework-logger.js +30 -1
  6. package/dist/delegation/index.d.ts +1 -2
  7. package/dist/delegation/index.js +1 -2
  8. package/dist/enforcement/enforcer-tools.js +1 -1
  9. package/dist/execution/proposal-applier.d.ts +1 -9
  10. package/dist/execution/proposal-applier.js +18 -173
  11. package/dist/governance/codex-policy.service.d.ts +7 -25
  12. package/dist/governance/codex-policy.service.js +8 -26
  13. package/dist/governance/governance-core.d.ts +22 -28
  14. package/dist/governance/governance-core.js +31 -101
  15. package/dist/governance/governance-service.d.ts +1 -0
  16. package/dist/governance/governance-service.js +67 -4
  17. package/dist/governance/governance-types.d.ts +5 -2
  18. package/dist/inference/index.d.ts +3 -4
  19. package/dist/inference/inference-accumulator.js +1 -1
  20. package/dist/inference/inference-cycle.d.ts +12 -18
  21. package/dist/inference/inference-cycle.js +120 -335
  22. package/dist/integrations/base/index.d.ts +0 -1
  23. package/dist/integrations/base/index.js +0 -2
  24. package/dist/integrations/grok/hooks/pre-tool-use.js +4 -18
  25. package/dist/integrations/hermes-agent/bridge.mjs +9 -0
  26. package/dist/mcps/config/server-config-registry.js +1 -1
  27. package/dist/mcps/governance.server.js +3 -4
  28. package/dist/mcps/knowledge-skills/api-design.server.js +10 -0
  29. package/dist/mcps/knowledge-skills/architecture-patterns.server.js +10 -0
  30. package/dist/mcps/knowledge-skills/bug-triage-specialist.server.js +10 -0
  31. package/dist/mcps/knowledge-skills/code-analyzer.server.js +10 -0
  32. package/dist/mcps/knowledge-skills/code-review.server.js +10 -0
  33. package/dist/mcps/knowledge-skills/content-creator.server.js +10 -0
  34. package/dist/mcps/knowledge-skills/database-design.server.js +10 -0
  35. package/dist/mcps/knowledge-skills/devops-deployment.server.js +10 -0
  36. package/dist/mcps/knowledge-skills/git-workflow.server.js +10 -0
  37. package/dist/mcps/knowledge-skills/growth-strategist.server.js +10 -0
  38. package/dist/mcps/knowledge-skills/log-monitor.server.js +10 -0
  39. package/dist/mcps/knowledge-skills/mobile-development.server.js +10 -0
  40. package/dist/mcps/knowledge-skills/multimodal-looker.server.js +10 -0
  41. package/dist/mcps/knowledge-skills/performance-optimization.server.js +10 -0
  42. package/dist/mcps/knowledge-skills/project-analysis.server.js +10 -0
  43. package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +10 -0
  44. package/dist/mcps/knowledge-skills/security-audit.server.js +10 -0
  45. package/dist/mcps/knowledge-skills/seo-consultant.server.js +10 -0
  46. package/dist/mcps/knowledge-skills/skill-invocation.server.d.ts +4 -0
  47. package/dist/mcps/knowledge-skills/skill-invocation.server.js +33 -14
  48. package/dist/mcps/knowledge-skills/strategist.server.js +10 -0
  49. package/dist/mcps/knowledge-skills/tech-writer.server.js +10 -0
  50. package/dist/mcps/knowledge-skills/testing-strategy.server.js +10 -0
  51. package/dist/mcps/knowledge-skills/ui-ux-design.server.js +10 -0
  52. package/dist/metrics/agent-metrics.d.ts +2 -1
  53. package/dist/nucleus/govern-http.d.ts +59 -0
  54. package/dist/nucleus/govern-http.js +172 -0
  55. package/dist/nucleus/index.d.ts +14 -0
  56. package/dist/nucleus/index.js +9 -0
  57. package/dist/nucleus/kernel.d.ts +51 -0
  58. package/dist/nucleus/kernel.js +62 -0
  59. package/dist/nucleus/plugin-registry.d.ts +104 -0
  60. package/dist/nucleus/plugin-registry.js +147 -0
  61. package/dist/orchestrator/orchestrator.d.ts +0 -1
  62. package/dist/orchestrator/orchestrator.js +0 -21
  63. package/dist/postprocessor/PostProcessor.d.ts +13 -1
  64. package/dist/postprocessor/PostProcessor.js +41 -1
  65. package/dist/postprocessor/autofix/AutoFixEngine.d.ts +0 -8
  66. package/dist/postprocessor/autofix/AutoFixEngine.js +0 -54
  67. package/dist/postprocessor/metamorphosis/MetamorphosisEngine.d.ts +25 -0
  68. package/dist/postprocessor/metamorphosis/MetamorphosisEngine.js +10 -0
  69. package/dist/postprocessor/metamorphosis/SelfProposalEngine.d.ts +68 -0
  70. package/dist/postprocessor/metamorphosis/SelfProposalEngine.js +371 -0
  71. package/dist/skills/orchestrator/SKILL.md +1 -1
  72. package/dist/state/index.d.ts +0 -2
  73. package/package.json +4 -3
  74. package/scripts/node/universal-version-manager.js +2 -2
  75. package/src/mcps/config/__tests__/server-config-registry.test.ts +6 -15
  76. package/src/mcps/config/server-config-registry.ts +1 -1
  77. package/src/mcps/governance.server.ts +3 -5
  78. package/src/mcps/knowledge-skills/api-design.server.ts +9 -0
  79. package/src/mcps/knowledge-skills/architecture-patterns.server.ts +9 -0
  80. package/src/mcps/knowledge-skills/bug-triage-specialist.server.ts +9 -0
  81. package/src/mcps/knowledge-skills/code-analyzer.server.ts +9 -0
  82. package/src/mcps/knowledge-skills/code-review.server.ts +9 -0
  83. package/src/mcps/knowledge-skills/content-creator.server.ts +9 -0
  84. package/src/mcps/knowledge-skills/database-design.server.ts +9 -0
  85. package/src/mcps/knowledge-skills/devops-deployment.server.ts +9 -0
  86. package/src/mcps/knowledge-skills/git-workflow.server.ts +9 -0
  87. package/src/mcps/knowledge-skills/growth-strategist.server.ts +9 -0
  88. package/src/mcps/knowledge-skills/log-monitor.server.ts +9 -0
  89. package/src/mcps/knowledge-skills/mobile-development.server.ts +9 -0
  90. package/src/mcps/knowledge-skills/multimodal-looker.server.ts +9 -0
  91. package/src/mcps/knowledge-skills/performance-optimization.server.ts +9 -0
  92. package/src/mcps/knowledge-skills/project-analysis.server.ts +9 -0
  93. package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +9 -0
  94. package/src/mcps/knowledge-skills/security-audit.server.ts +9 -0
  95. package/src/mcps/knowledge-skills/seo-consultant.server.ts +9 -0
  96. package/src/mcps/knowledge-skills/session-management.server.ts +1 -0
  97. package/src/mcps/knowledge-skills/skill-invocation.server.ts +44 -29
  98. package/src/mcps/knowledge-skills/strategist.server.ts +9 -0
  99. package/src/mcps/knowledge-skills/tech-writer.server.ts +9 -0
  100. package/src/mcps/knowledge-skills/testing-strategy.server.ts +9 -0
  101. package/src/mcps/knowledge-skills/ui-ux-design.server.ts +9 -0
  102. package/src/skills/orchestrator/SKILL.md +1 -1
  103. package/.opencode/agents/testing-best-practices.yml +0 -12
  104. package/dist/analytics/consent-manager.d.ts +0 -93
  105. package/dist/analytics/consent-manager.js +0 -258
  106. package/dist/analytics/simple-pattern-analyzer.d.ts +0 -80
  107. package/dist/analytics/simple-pattern-analyzer.js +0 -297
  108. package/dist/cli/commands/analytics-disable.d.ts +0 -9
  109. package/dist/cli/commands/analytics-disable.js +0 -72
  110. package/dist/cli/commands/analytics-enable-action.d.ts +0 -8
  111. package/dist/cli/commands/analytics-enable-action.js +0 -82
  112. package/dist/cli/commands/analytics-preview.d.ts +0 -9
  113. package/dist/cli/commands/analytics-preview.js +0 -106
  114. package/dist/cli/commands/analytics-status.d.ts +0 -9
  115. package/dist/cli/commands/analytics-status.js +0 -68
  116. package/dist/cli/server.d.ts +0 -1
  117. package/dist/cli/server.js +0 -147
  118. package/dist/core/errors.d.ts +0 -3
  119. package/dist/core/errors.js +0 -10
  120. package/dist/core/logging-config.d.ts +0 -11
  121. package/dist/core/logging-config.js +0 -43
  122. package/dist/core/trace-context.d.ts +0 -12
  123. package/dist/core/trace-context.js +0 -33
  124. package/dist/delegation/voting-coordinator.d.ts +0 -49
  125. package/dist/delegation/voting-coordinator.js +0 -375
  126. package/dist/enforcement/test-auto-healing.d.ts +0 -83
  127. package/dist/enforcement/test-auto-healing.js +0 -325
  128. package/dist/integrations/base/ExampleIntegration.d.ts +0 -47
  129. package/dist/integrations/base/ExampleIntegration.js +0 -181
  130. package/dist/mcps/knowledge-skills/testing-best-practices.server.d.ts +0 -34
  131. package/dist/mcps/knowledge-skills/testing-best-practices.server.js +0 -831
  132. package/dist/mcps/orchestrator.server.d.ts +0 -10
  133. package/dist/mcps/orchestrator.server.js +0 -19
  134. package/dist/orchestrator/self-direction-activation.d.ts +0 -109
  135. package/dist/orchestrator/self-direction-activation.js +0 -245
  136. package/dist/orchestrator/universal-librarian-consultation.d.ts +0 -98
  137. package/dist/orchestrator/universal-librarian-consultation.js +0 -216
  138. package/dist/orchestrator/universal-registry-bridge.d.ts +0 -85
  139. package/dist/orchestrator/universal-registry-bridge.js +0 -247
  140. package/dist/performance/performance-budget-enforcer.d.ts +0 -158
  141. package/dist/performance/performance-budget-enforcer.js +0 -434
  142. package/dist/performance/performance-regression-tester.d.ts +0 -108
  143. package/dist/performance/performance-regression-tester.js +0 -342
  144. package/dist/skills/testing-best-practices/SKILL.md +0 -37
  145. package/dist/state/context-providers.d.ts +0 -4
  146. package/dist/state/context-providers.js +0 -1
  147. package/dist/state/state-types.d.ts +0 -5
  148. package/dist/state/state-types.js +0 -1
  149. package/dist/utils/batch-operations.d.ts +0 -25
  150. package/dist/utils/batch-operations.js +0 -292
  151. package/dist/utils/test-template-generator.d.ts +0 -25
  152. package/dist/utils/test-template-generator.js +0 -178
  153. package/dist/utils/token-manager.d.ts +0 -48
  154. package/dist/utils/token-manager.js +0 -163
  155. package/src/mcps/knowledge-skills/testing-best-practices.server.test.ts +0 -136
  156. package/src/mcps/knowledge-skills/testing-best-practices.server.ts +0 -1183
  157. package/src/mcps/orchestrator.server.ts +0 -34
  158. package/src/opencode/agents/testing-best-practices.yml +0 -12
  159. package/src/skills/testing-best-practices/SKILL.md +0 -37
@@ -0,0 +1,371 @@
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 } 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
+ async evaluateAndPropose() {
137
+ let logEntries = [];
138
+ try {
139
+ const logContent = await fs.readFile(this.config.activityLogPath, 'utf-8');
140
+ const lines = logContent.trim().split('\n');
141
+ logEntries = lines.slice(-this.config.maxLogLines).filter(line => line.trim().length > 0);
142
+ }
143
+ catch {
144
+ await frameworkLogger.log('self-proposal', 'log-read-error', 'warning', {
145
+ path: this.config.activityLogPath,
146
+ message: 'Activity log not found or unreadable — skipping self-proposal',
147
+ });
148
+ return;
149
+ }
150
+ const patterns = this.detectPatterns(logEntries);
151
+ if (patterns.length === 0) {
152
+ await frameworkLogger.log('self-proposal', 'no-patterns', 'info', {
153
+ message: 'No actionable patterns detected in activity log',
154
+ });
155
+ return;
156
+ }
157
+ for (const pattern of patterns) {
158
+ await this.submitProposal(pattern);
159
+ }
160
+ }
161
+ /**
162
+ * Detect actionable patterns from parsed activity log entries.
163
+ * Uses structured parsing instead of raw string matching to handle
164
+ * the actual xray log format:
165
+ * ISO_TIMESTAMP [jobId] [traceId.spanId] [component] action - STATUS | {details}
166
+ */
167
+ detectPatterns(entries) {
168
+ const parsed = entries.map(parseLogEntry).filter((e) => e !== null);
169
+ const proposals = [];
170
+ const errorEntries = parsed.filter(e => e.status === 'error');
171
+ const warningEntries = parsed.filter(e => e.status === 'warning');
172
+ const rejectedEntries = parsed.filter(e => e.component === 'governance' && (e.status === 'rejected' || e.details?.decision === 'reject'));
173
+ if (errorEntries.length >= this.config.errorThreshold) {
174
+ const components = [...new Set(errorEntries.map(e => e.component))];
175
+ proposals.push({
176
+ id: `meta-errors-${Date.now()}`,
177
+ type: 'modify',
178
+ target: 'config/error-handling',
179
+ description: `Elevated error rate: ${errorEntries.length} errors in last ${this.config.maxLogLines} entries. Components: ${components.join(', ')}. Propose adjusting error handling thresholds.`,
180
+ 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.`,
181
+ impact: 'medium',
182
+ });
183
+ }
184
+ if (warningEntries.length >= this.config.warningThreshold) {
185
+ const components = [...new Set(warningEntries.map(e => e.component))];
186
+ proposals.push({
187
+ id: `meta-warnings-${Date.now()}`,
188
+ type: 'modify',
189
+ target: 'config/monitoring',
190
+ description: `Elevated warning rate: ${warningEntries.length} warnings in last ${this.config.maxLogLines} entries. Components: ${components.join(', ')}. Propose adjusting monitoring sensitivity.`,
191
+ rationale: `Frequent warnings (${warningEntries.length}) across ${components.length} component(s) may indicate configuration drift. Affected: ${components.join(', ')}.`,
192
+ impact: 'low',
193
+ });
194
+ }
195
+ if (rejectedEntries.length >= this.config.governanceRejectionThreshold) {
196
+ proposals.push({
197
+ id: `meta-governance-rejections-${Date.now()}`,
198
+ type: 'modify',
199
+ target: 'config/governance',
200
+ description: `Repeated governance rejections: ${rejectedEntries.length} in last ${this.config.maxLogLines} entries. Propose reviewing governance thresholds or submission patterns.`,
201
+ rationale: `${rejectedEntries.length} governance rejections suggest a pattern mismatch between proposals and governance criteria. Review recommended.`,
202
+ impact: 'medium',
203
+ });
204
+ }
205
+ return proposals.filter(p => this.config.whitelistedTargets.some(t => p.target.startsWith(t)));
206
+ }
207
+ /**
208
+ * Apply an approved self-evolution proposal by recording the change
209
+ * in a state file within the first matching whitelisted target directory.
210
+ * Returns true if the change was written and verified, false otherwise.
211
+ */
212
+ async applySelfProposal(pattern, score, decision) {
213
+ const matchedTarget = this.config.whitelistedTargets.find(t => pattern.target.startsWith(t));
214
+ if (!matchedTarget) {
215
+ await frameworkLogger.log('self-proposal', 'apply-no-matching-target', 'warning', {
216
+ proposalId: pattern.id,
217
+ target: pattern.target,
218
+ message: 'No whitelisted target matches this proposal — skipping apply',
219
+ });
220
+ return false;
221
+ }
222
+ const root = this.config.projectRoot;
223
+ const stateDir = join(root, matchedTarget);
224
+ const statePath = join(stateDir, 'self-evolution-state.json');
225
+ let applied = [];
226
+ try {
227
+ const content = await fs.readFile(statePath, 'utf-8');
228
+ const parsed = JSON.parse(content);
229
+ if (Array.isArray(parsed.applied))
230
+ applied = parsed.applied;
231
+ }
232
+ catch { }
233
+ applied.push({
234
+ proposalId: pattern.id,
235
+ target: pattern.target,
236
+ type: pattern.type,
237
+ description: pattern.description,
238
+ rationale: pattern.rationale,
239
+ impact: pattern.impact,
240
+ metamorphosisScore: score,
241
+ decision: decision,
242
+ appliedAt: new Date().toISOString(),
243
+ });
244
+ try {
245
+ await fs.mkdir(stateDir, { recursive: true });
246
+ await fs.writeFile(statePath, JSON.stringify({ applied }, null, 2), 'utf-8');
247
+ }
248
+ catch (writeError) {
249
+ await frameworkLogger.log('self-proposal', 'apply-write-error', 'error', {
250
+ proposalId: pattern.id,
251
+ path: statePath,
252
+ error: writeError instanceof Error ? writeError.message : String(writeError),
253
+ });
254
+ return false;
255
+ }
256
+ try {
257
+ const verify = await fs.readFile(statePath, 'utf-8');
258
+ const parsed = JSON.parse(verify);
259
+ const found = Array.isArray(parsed.applied) && parsed.applied.some((a) => a.proposalId === pattern.id);
260
+ if (!found) {
261
+ await frameworkLogger.log('self-proposal', 'apply-verify-failed', 'error', {
262
+ proposalId: pattern.id,
263
+ message: 'Applied change not found in state file after write — verification failed',
264
+ });
265
+ }
266
+ return found;
267
+ }
268
+ catch (verifyError) {
269
+ await frameworkLogger.log('self-proposal', 'apply-verify-error', 'error', {
270
+ proposalId: pattern.id,
271
+ error: verifyError instanceof Error ? verifyError.message : String(verifyError),
272
+ });
273
+ return false;
274
+ }
275
+ }
276
+ async submitProposal(pattern) {
277
+ const governanceRequest = {
278
+ proposals: [{
279
+ id: pattern.id,
280
+ type: 'metamorphosis',
281
+ title: `Self-proposal: ${pattern.description.slice(0, 80)}`,
282
+ description: pattern.description,
283
+ evidence: [pattern.rationale],
284
+ source: 'metamorphosis',
285
+ confidence: this.config.proposalConfidence,
286
+ }],
287
+ context: {
288
+ project: 'xray-self',
289
+ phase: 'self-evolution',
290
+ source: 'self-proposal-engine',
291
+ },
292
+ options: {
293
+ requireExternalDynamo: true,
294
+ metamorphosisThreshold: this.config.metamorphosisThreshold,
295
+ },
296
+ };
297
+ await frameworkLogger.log('self-proposal', 'submitting', 'info', {
298
+ proposalId: pattern.id,
299
+ target: pattern.target,
300
+ impact: pattern.impact,
301
+ });
302
+ try {
303
+ const response = await handleGovernRequest(governanceRequest);
304
+ const result = response.results[0];
305
+ if (!result) {
306
+ await frameworkLogger.log('self-proposal', 'no-result', 'warning', {
307
+ proposalId: pattern.id,
308
+ message: 'Governance returned no results',
309
+ });
310
+ return;
311
+ }
312
+ const decision = result.finalDecision;
313
+ const attempt = {
314
+ timestamp: Date.now(),
315
+ result: decision === 'approve' ? 'approved' : decision === 'reject' ? 'rejected' : 'needs_revision',
316
+ };
317
+ if (result.metamorphosisScore !== undefined) {
318
+ attempt.metamorphosisScore = result.metamorphosisScore;
319
+ }
320
+ this.proposalHistory.push(attempt);
321
+ if (decision === 'approve' && (result.metamorphosisScore ?? 0) >= this.config.metamorphosisThreshold) {
322
+ this.consecutiveFailures = 0;
323
+ await frameworkLogger.log('self-proposal', 'approved', 'success', {
324
+ proposalId: pattern.id,
325
+ metamorphosisScore: result.metamorphosisScore,
326
+ message: 'Self-evolution proposal approved by governance — applying change',
327
+ });
328
+ const applied = await this.applySelfProposal(pattern, result.metamorphosisScore, decision);
329
+ if (applied) {
330
+ await frameworkLogger.log('self-proposal', 'applied', 'success', {
331
+ proposalId: pattern.id,
332
+ target: pattern.target,
333
+ message: 'Self-evolution change applied and verified',
334
+ });
335
+ }
336
+ else {
337
+ this.consecutiveFailures++;
338
+ if (this.consecutiveFailures >= this.config.circuitBreakerThreshold) {
339
+ this.circuitBreakerUntil = Date.now() + this.config.circuitBreakerCooldownHours * 60 * 60 * 1000;
340
+ }
341
+ await frameworkLogger.log('self-proposal', 'apply-failed', 'error', {
342
+ proposalId: pattern.id,
343
+ target: pattern.target,
344
+ consecutiveFailures: this.consecutiveFailures,
345
+ message: 'Self-evolution change apply failed — circuit breaker may activate',
346
+ });
347
+ }
348
+ }
349
+ else {
350
+ this.consecutiveFailures++;
351
+ if (this.consecutiveFailures >= this.config.circuitBreakerThreshold) {
352
+ this.circuitBreakerUntil = Date.now() + this.config.circuitBreakerCooldownHours * 60 * 60 * 1000;
353
+ }
354
+ await frameworkLogger.log('self-proposal', 'not-approved', 'warning', {
355
+ proposalId: pattern.id,
356
+ decision: decision,
357
+ metamorphosisScore: result.metamorphosisScore,
358
+ consecutiveFailures: this.consecutiveFailures,
359
+ circuitBreakerUntil: this.circuitBreakerUntil || 'not active',
360
+ });
361
+ }
362
+ }
363
+ catch (error) {
364
+ this.consecutiveFailures++;
365
+ await frameworkLogger.log('self-proposal', 'submission-error', 'error', {
366
+ proposalId: pattern.id,
367
+ error: error instanceof Error ? error.message : String(error),
368
+ });
369
+ }
370
+ }
371
+ }
@@ -15,7 +15,7 @@ dependencies: []
15
15
  mcp:
16
16
  orchestrator:
17
17
  command: node
18
- args: [node_modules/0xray/dist/mcps/orchestrator.server.js]
18
+ args: [node_modules/0xray/dist/mcps/orchestrator/server.js]
19
19
  ---
20
20
 
21
21
  # Orchestrator Skill
@@ -1,3 +1 @@
1
1
  export { StateManager, XrayStateManager, XrayStateManager as StrRayStateManager } from "./state-manager.js";
2
- export type { StateValue, StateTypes } from "./state-types.js";
3
- export type { ContextProviders } from "./context-providers.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "2.1.4",
3
+ "version": "2.2.0",
4
4
  "description": "Multi-agent orchestration and Codex governance for OpenCode, Hermes, Grok Build, and OpenClaw",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -58,10 +58,10 @@
58
58
  "test": "vitest run",
59
59
  "test:batch": "npm test",
60
60
  "test:unit": "npm test -- src/__tests__/unit/config-loader.test.ts src/__tests__/unit/state-manager.test.ts src/__tests__/unit/state-manager-persistence.test.ts src/__tests__/unit/context-loader.test.ts src/__tests__/unit/pattern-analyzer.test.ts src/__tests__/unit/complexity-calibrator.test.ts",
61
- "test:core-framework": "npm test -- src/__tests__/unit/self-direction-activation.test.ts src/__tests__/unit/ast-code-parser.test.ts src/__tests__/unit/v2-deletion-protection.test.ts",
61
+ "test:core-framework": "npm test -- src/__tests__/unit/ast-code-parser.test.ts src/__tests__/unit/v2-deletion-protection.test.ts",
62
62
  "test:security": "npm test -- src/__tests__/unit/security/security-hardener.test.ts src/__tests__/unit/security/security-headers.test.ts",
63
63
  "test:performance": "npm test -- src/__tests__/unit/monitoring.test.ts src/__tests__/unit/benchmark.test.ts src/__tests__/unit/analytics.test.ts",
64
- "test:session-management": "npm test -- src/__tests__/unit/session-state-manager.test.ts src/__tests__/unit/session-security-validator.test.ts src/__tests__/unit/session-coordination-validator.test.ts src/__tests__/unit/session-migration-validator.test.ts src/__tests__/unit/session-migration-logic.test.ts",
64
+ "test:session-management": "npm test -- src/__tests__/unit/session-state-manager.test.ts src/__tests__/unit/session-migration-logic.test.ts",
65
65
  "test:code-analysis": "npm test -- src/__tests__/unit/codebase-context-analyzer.test.ts src/__tests__/unit/dependency-graph-builder.test.ts src/__tests__/unit/rule-enforcer.test.ts src/__tests__/unit/codex-parser.test.ts src/__tests__/unit/codex-injector.test.ts",
66
66
  "test:processors": "npm test -- src/__tests__/unit/processor-activation.test.ts src/__tests__/unit/typescript-compilation-processor.test.ts",
67
67
  "test:miscellaneous": "npm test -- src/__tests__/unit/blocked-test.test.ts",
@@ -87,6 +87,7 @@
87
87
  "test:e2e": "node scripts/node/validate-mcp-connectivity.js && node scripts/node/validate-external-processes.js",
88
88
  "validate": "echo \"[xray] Use 'npm test' or 'npm run test:comprehensive'.\"",
89
89
  "validate:quick": "npm run validate",
90
+ "verify:consumer": "bash scripts/verify-consumer.sh",
90
91
  "debug:inference:force": "STRRAY_FORCE_MCP_GOVERNANCE=true XRAY_DEV_PATH=dist node dist/cli/index.js inference:run --force",
91
92
  "validate:full": "npm run validate",
92
93
  "test:unified": "node scripts/test/test-unified-framework.mjs",
@@ -155,9 +155,9 @@ const detectedCodex = detectCodexInfo();
155
155
  const OFFICIAL_VERSIONS = {
156
156
  // Framework version
157
157
  framework: {
158
- version: "2.1.4",
158
+ version: "2.2.0",
159
159
  displayName: "xray: Self-Healing AI Governance OS",
160
- lastUpdated: "2026-06-09",
160
+ lastUpdated: "2026-06-10",
161
161
  // Counts (auto-calculated, but can be overridden)
162
162
  ...CALCULATED_COUNTS,
163
163
  },
@@ -166,45 +166,36 @@ describe('ServerConfigRegistry', () => {
166
166
 
167
167
  it('should use XRAY_DEV_PATH env var in dynamic config', () => {
168
168
  const originalXrayEnv = process.env.XRAY_DEV_PATH;
169
- const originalStrrayEnv = ;
170
169
  process.env.XRAY_DEV_PATH = 'custom-dist';
171
- = 'custom-dist';
172
-
170
+
173
171
  const config = registry.createDynamicConfig('test-server');
174
172
  expect(config.args[0]).toContain('custom-dist');
175
-
173
+
176
174
  process.env.XRAY_DEV_PATH = originalXrayEnv;
177
- = originalStrrayEnv;
178
175
  });
179
176
  });
180
177
 
181
178
  describe('environment path handling', () => {
182
179
  it('should use resolved framework path when XRAY_DEV_PATH is not set', () => {
183
180
  const originalXrayEnv = process.env.XRAY_DEV_PATH;
184
- const originalStrrayEnv = ;
185
181
  delete process.env.XRAY_DEV_PATH;
186
- delete ;
187
-
182
+
188
183
  const freshRegistry = new ServerConfigRegistry();
189
184
  const config = freshRegistry.get('code-review');
190
185
  expect(config?.args[0]).toContain('.server.js');
191
-
186
+
192
187
  process.env.XRAY_DEV_PATH = originalXrayEnv;
193
- = originalStrrayEnv;
194
188
  });
195
189
 
196
190
  it('should use XRAY_DEV_PATH when set', () => {
197
191
  const originalXrayEnv = process.env.XRAY_DEV_PATH;
198
- const originalStrrayEnv = ;
199
192
  process.env.XRAY_DEV_PATH = 'dist';
200
- = 'dist';
201
-
193
+
202
194
  const freshRegistry = new ServerConfigRegistry();
203
195
  const config = freshRegistry.get('code-review');
204
196
  expect(config?.args[0]).toContain('dist/');
205
-
197
+
206
198
  process.env.XRAY_DEV_PATH = originalXrayEnv;
207
- = originalStrrayEnv;
208
199
  });
209
200
  });
210
201
 
@@ -180,7 +180,7 @@ export class ServerConfigRegistry {
180
180
  this.register({
181
181
  serverName: 'orchestrator',
182
182
  command: 'node',
183
- args: [`${basePath}/orchestrator.server.js`],
183
+ args: [`${basePath}/orchestrator/server.js`],
184
184
  timeout: 60000,
185
185
  });
186
186
 
@@ -28,7 +28,7 @@ import * as fs from "fs";
28
28
  import * as path from "path";
29
29
  import { fileURLToPath } from "url";
30
30
  import { randomUUID } from "crypto";
31
- import { getGovernanceService } from "../governance/governance-service.js";
31
+ import { handleGovernRequest } from "../nucleus/index.js";
32
32
  import { getCodexPolicyService } from "../governance/codex-policy.service.js";
33
33
  import { initializeGovernanceIntegration, shutdownGovernanceIntegration } from "../integrations/governance/index.js";
34
34
  import { featuresConfigLoader } from "../core/features-config.js";
@@ -243,8 +243,6 @@ class GovernanceServer {
243
243
  }
244
244
 
245
245
  private async handleGovernProposals(args: GovernProposalsArgs): Promise<CallToolResult> {
246
- const service = getGovernanceService();
247
-
248
246
  const request: GovernanceRequest = {
249
247
  proposals: args.proposals.map((p, i) => ({
250
248
  id: p.id || `prop-${Date.now()}-${i}`,
@@ -261,11 +259,11 @@ class GovernanceServer {
261
259
  },
262
260
  };
263
261
 
264
- frameworkLogger.log("governance-mcp", "delegating-to-governance-service", "info", {
262
+ frameworkLogger.log("governance-mcp", "delegating-to-kernel", "info", {
265
263
  proposalCount: request.proposals.length,
266
264
  });
267
265
 
268
- const response = await service.govern(request);
266
+ const response = await handleGovernRequest(request);
269
267
 
270
268
  return {
271
269
  content: [
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
9
9
  import { frameworkLogger } from "../../core/framework-logger.js";
10
+ import { pluginRegistry } from "../../nucleus/plugin-registry.js";
10
11
 
11
12
  interface DesignApiEndpointsArgs {
12
13
  resource: string;
@@ -56,6 +57,14 @@ class XrayApiDesignServer extends XrayKnowledgeSkillBase {
56
57
  "validate-api-design": async (args) => this.validateApiDesign(args as unknown as ValidateApiDesignArgs),
57
58
  };
58
59
  this.setupToolHandlers();
60
+ pluginRegistry.registerToolPlugin({
61
+ name: "api-design",
62
+ callTool: async (toolName, args) => {
63
+ const handler = this.handlers[toolName];
64
+ if (!handler) throw new Error(`Unknown tool: ${toolName}`);
65
+ return handler(args);
66
+ },
67
+ });
59
68
  }
60
69
 
61
70
  private async designApiEndpoints(args: DesignApiEndpointsArgs) {
@@ -1,5 +1,6 @@
1
1
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
2
2
  import { frameworkLogger } from "../../core/framework-logger.js";
3
+ import { pluginRegistry } from "../../nucleus/plugin-registry.js";
3
4
  import * as fs from "fs";
4
5
  import * as path from "path";
5
6
 
@@ -49,6 +50,14 @@ class XrayArchitecturePatternsServer extends XrayKnowledgeSkillBase {
49
50
  "recommend-patterns": async (args) => this.recommendPatterns(args as unknown as RecommendPatternsArgs),
50
51
  };
51
52
  this.setupToolHandlers();
53
+ pluginRegistry.registerToolPlugin({
54
+ name: "architecture-patterns",
55
+ callTool: async (toolName, args) => {
56
+ const handler = this.handlers[toolName];
57
+ if (!handler) throw new Error(`Unknown tool: ${toolName}`);
58
+ return handler(args);
59
+ },
60
+ });
52
61
  }
53
62
 
54
63
  private async analyzeArchitecture(args: AnalyzeArchitectureArgs) {
@@ -11,6 +11,7 @@ import * as path from "path";
11
11
  import { fileURLToPath } from "url";
12
12
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
13
13
  import { frameworkLogger } from "../../core/framework-logger.js";
14
+ import { pluginRegistry } from "../../nucleus/plugin-registry.js";
14
15
 
15
16
  interface BugReport {
16
17
  id: string;
@@ -254,6 +255,14 @@ class BugTriageSpecialistServer extends XrayKnowledgeSkillBase {
254
255
  },
255
256
  };
256
257
  this.setupToolHandlers();
258
+ pluginRegistry.registerToolPlugin({
259
+ name: "bug-triage-specialist",
260
+ callTool: async (toolName, args) => {
261
+ const handler = this.handlers[toolName];
262
+ if (!handler) throw new Error(`Unknown tool: ${toolName}`);
263
+ return handler(args);
264
+ },
265
+ });
257
266
  }
258
267
 
259
268
  private triageBugs(errorLogs: string[], context: Record<string, unknown>): TriageResult {
@@ -12,6 +12,7 @@
12
12
 
13
13
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
14
14
  import { frameworkLogger } from "../../core/framework-logger.js";
15
+ import { pluginRegistry } from "../../nucleus/plugin-registry.js";
15
16
  import * as fs from "fs";
16
17
  import * as path from "path";
17
18
 
@@ -310,6 +311,14 @@ class CodeAnalyzerServer extends XrayKnowledgeSkillBase {
310
311
  "find_duplicates": async (args) => this.handleFindDuplicates(args),
311
312
  };
312
313
  this.setupToolHandlers();
314
+ pluginRegistry.registerToolPlugin({
315
+ name: "code-analyzer",
316
+ callTool: async (toolName, args) => {
317
+ const handler = this.handlers[toolName];
318
+ if (!handler) throw new Error(`Unknown tool: ${toolName}`);
319
+ return handler(args);
320
+ },
321
+ });
313
322
  }
314
323
 
315
324
  private handleAnalyzeCode(args: unknown) {
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
9
9
  import { frameworkLogger } from "../../core/framework-logger.js";
10
+ import { pluginRegistry } from "../../nucleus/plugin-registry.js";
10
11
  import * as fs from "fs";
11
12
  import * as path from "path";
12
13
 
@@ -190,6 +191,14 @@ class XrayCodeReviewServer extends XrayKnowledgeSkillBase {
190
191
  "analyze_proposal": async (args) => this.analyzeProposal(args as AnalyzeProposalArgs),
191
192
  };
192
193
  this.setupToolHandlers();
194
+ pluginRegistry.registerToolPlugin({
195
+ name: "code-review",
196
+ callTool: async (toolName, args) => {
197
+ const handler = this.handlers[toolName];
198
+ if (!handler) throw new Error(`Unknown tool: ${toolName}`);
199
+ return handler(args);
200
+ },
201
+ });
193
202
  }
194
203
 
195
204
  private async analyzeCodeQuality(args: AnalyzeCodeQualityArgs) {
@@ -9,6 +9,7 @@ import * as path from "path";
9
9
  import { fileURLToPath } from "url";
10
10
  import { XrayKnowledgeSkillBase } from "../shared/knowledge-skill-base.js";
11
11
  import { frameworkLogger } from "../../core/framework-logger.js";
12
+ import { pluginRegistry } from "../../nucleus/plugin-registry.js";
12
13
 
13
14
  class SEOCopywriterServer extends XrayKnowledgeSkillBase {
14
15
  constructor() {
@@ -251,6 +252,14 @@ class SEOCopywriterServer extends XrayKnowledgeSkillBase {
251
252
  },
252
253
  };
253
254
  this.setupToolHandlers();
255
+ pluginRegistry.registerToolPlugin({
256
+ name: "content-creator",
257
+ callTool: async (toolName, args) => {
258
+ const handler = this.handlers[toolName];
259
+ if (!handler) throw new Error(`Unknown tool: ${toolName}`);
260
+ return handler(args);
261
+ },
262
+ });
254
263
  }
255
264
  }
256
265