0xray 3.1.1 → 3.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 (296) hide show
  1. package/.opencode/codex.codex +1 -1
  2. package/.opencode/commands/auto-format.md +3 -3
  3. package/.opencode/commands/auto-summary-capture.md +2 -2
  4. package/.opencode/commands/enforcer-daily-scan.md +3 -3
  5. package/.opencode/commands/framework-compliance-audit.md +4 -4
  6. package/.opencode/commands/interactive-validator.md +2 -2
  7. package/.opencode/commands/job-summary-logger.md +2 -2
  8. package/.opencode/commands/mode-switch.md +1 -1
  9. package/.opencode/commands/model-health-check.md +2 -2
  10. package/.opencode/commands/performance-analysis.md +2 -2
  11. package/.opencode/commands/pre-commit-introspection.md +3 -3
  12. package/.opencode/commands/security-scan.md +3 -3
  13. package/.opencode/commands/sisyphus-validation.md +3 -3
  14. package/.opencode/commands/summary-logger.md +2 -2
  15. package/AGENTS.md +3 -13
  16. package/README.md +3 -3
  17. package/dist/AGENTS.md +3 -13
  18. package/dist/CHANGELOG.md +29 -0
  19. package/dist/README.md +3 -3
  20. package/dist/analytics/consent-manager.js +0 -1
  21. package/dist/analytics/emerging-pattern-detector.js +0 -1
  22. package/dist/analytics/pattern-learning-engine.js +0 -1
  23. package/dist/analytics/pattern-performance-tracker.js +0 -1
  24. package/dist/analytics/predictive-analytics.js +0 -1
  25. package/dist/analytics/prompt-pattern-analyzer.js +0 -1
  26. package/dist/analytics/routing-performance-analyzer.js +0 -1
  27. package/dist/analytics/routing-refiner.js +0 -1
  28. package/dist/analytics/simple-pattern-analyzer.js +0 -1
  29. package/dist/cli/commands/archive-logs.js +0 -1
  30. package/dist/cli/commands/opencode-install.js +13 -0
  31. package/dist/cli/commands/plugin-commands.js +0 -1
  32. package/dist/cli/commands/status.js +11 -13
  33. package/dist/cli/index.js +2 -7
  34. package/dist/core/activity-logger.js +0 -1
  35. package/dist/core/adaptive-kernel.js +0 -1
  36. package/dist/core/boot-orchestrator.js +2 -12
  37. package/dist/core/bridge.mjs +0 -1
  38. package/dist/core/codex-formatter.js +0 -1
  39. package/dist/core/codex-injector.js +0 -1
  40. package/dist/core/config-loader.js +36 -28
  41. package/dist/core/context-loader.js +0 -1
  42. package/dist/core/context-validator.js +0 -1
  43. package/dist/core/features-config.js +37 -1
  44. package/dist/core/kernel-patterns.js +0 -1
  45. package/dist/core/model-router.js +23 -64
  46. package/dist/core/system-prompt-generator.js +0 -1
  47. package/dist/delegation/agent-delegator.js +0 -1
  48. package/dist/delegation/agent-expertise.js +0 -1
  49. package/dist/delegation/analytics/index.js +0 -1
  50. package/dist/delegation/analytics/learning-engine.js +0 -1
  51. package/dist/delegation/analytics/outcome-tracker.js +0 -1
  52. package/dist/delegation/analytics/routing-analytics.js +0 -1
  53. package/dist/delegation/ast-code-parser.js +0 -1
  54. package/dist/delegation/complexity-analyzer.js +0 -1
  55. package/dist/delegation/dependency-graph-builder.js +0 -1
  56. package/dist/delegation/index.js +0 -1
  57. package/dist/delegation/metrics-aggregator.js +0 -1
  58. package/dist/delegation/session-coordinator.js +0 -1
  59. package/dist/delegation/strategy-selector.js +0 -1
  60. package/dist/delegation/voting-coordinator.js +0 -1
  61. package/dist/delegation/voting-types.js +0 -1
  62. package/dist/delegation/weighted-voting-aggregator.js +0 -1
  63. package/dist/enforcement/core/index.js +0 -1
  64. package/dist/enforcement/core/rule-executor.js +0 -1
  65. package/dist/enforcement/core/rule-hierarchy.js +0 -1
  66. package/dist/enforcement/core/rule-registry.js +0 -1
  67. package/dist/enforcement/core/violation-fixer.js +0 -1
  68. package/dist/enforcement/index.js +0 -1
  69. package/dist/enforcement/loaders/agent-triage-loader.js +0 -1
  70. package/dist/enforcement/loaders/agents-md-validation-loader.js +0 -1
  71. package/dist/enforcement/loaders/base-loader.js +0 -1
  72. package/dist/enforcement/loaders/codex-loader.js +0 -1
  73. package/dist/enforcement/loaders/index.js +0 -1
  74. package/dist/enforcement/loaders/loader-orchestrator.js +0 -1
  75. package/dist/enforcement/loaders/processor-loader.js +0 -1
  76. package/dist/enforcement/types.js +0 -1
  77. package/dist/enforcement/validators/architecture-validators.js +0 -1
  78. package/dist/enforcement/validators/base-validator.js +0 -1
  79. package/dist/enforcement/validators/code-quality-validators.js +0 -1
  80. package/dist/enforcement/validators/index.js +0 -1
  81. package/dist/enforcement/validators/security-validators.js +0 -1
  82. package/dist/enforcement/validators/testing-validators.js +0 -1
  83. package/dist/enforcement/validators/validator-registry.js +0 -1
  84. package/dist/governance/codex-policy.service.js +0 -1
  85. package/dist/inference/inference-agent-invoker.js +67 -0
  86. package/dist/inference/inference-applier.js +178 -0
  87. package/dist/inference/inference-cycle.js +51 -827
  88. package/dist/inference/inference-proposal-generator.js +149 -0
  89. package/dist/infrastructure/iac-validator.js +465 -0
  90. package/dist/infrastructure/schemas/cloud-schemas.js +488 -0
  91. package/dist/integrations/base/ExampleIntegration.js +0 -1
  92. package/dist/integrations/base/Integration.js +0 -1
  93. package/dist/integrations/base/index.js +0 -1
  94. package/dist/integrations/base/registry.js +0 -1
  95. package/dist/integrations/base/types.js +0 -1
  96. package/dist/integrations/enforcement-gate.js +3 -3
  97. package/dist/integrations/governance/governance-client.js +0 -1
  98. package/dist/integrations/governance/index.js +11 -19
  99. package/dist/integrations/governance/types.js +0 -1
  100. package/dist/integrations/hermes-agent/__init__.py +4 -0
  101. package/dist/integrations/hermes-agent/bridge.mjs +37 -0
  102. package/dist/integrations/openclaw/api-server.js +0 -1
  103. package/dist/integrations/openclaw/client.js +0 -1
  104. package/dist/integrations/openclaw/config.js +0 -1
  105. package/dist/integrations/openclaw/hooks/xray-hooks.js +0 -1
  106. package/dist/integrations/openclaw/index.js +0 -1
  107. package/dist/integrations/openclaw/types.js +0 -1
  108. package/dist/integrations/plugins/index.js +0 -1
  109. package/dist/integrations/plugins/plugin-integration.js +0 -1
  110. package/dist/integrations/plugins/plugin-registry.js +0 -1
  111. package/dist/mcps/agent-resolver.js +0 -1
  112. package/dist/mcps/architect-tools.server.js +119 -185
  113. package/dist/mcps/auto-format.server.js +56 -74
  114. package/dist/mcps/boot-orchestrator.server.js +67 -85
  115. package/dist/mcps/config/config-loader.js +6 -0
  116. package/dist/mcps/config/plugin-server-registry.js +0 -1
  117. package/dist/mcps/enforcer-tools.server.js +207 -273
  118. package/dist/mcps/estimation.server.js +63 -107
  119. package/dist/mcps/framework-compliance-audit.server.js +52 -81
  120. package/dist/mcps/framework-help.server.js +71 -89
  121. package/dist/mcps/governance.server.js +97 -149
  122. package/dist/mcps/knowledge-skills/api-design.server.js +33 -65
  123. package/dist/mcps/knowledge-skills/architecture-patterns.server.js +33 -65
  124. package/dist/mcps/knowledge-skills/bug-triage-specialist.server.js +123 -163
  125. package/dist/mcps/knowledge-skills/code-analyzer.server.js +210 -237
  126. package/dist/mcps/knowledge-skills/code-review.server.js +108 -142
  127. package/dist/mcps/knowledge-skills/content-creator.server.js +203 -225
  128. package/dist/mcps/knowledge-skills/database-design.server.js +116 -150
  129. package/dist/mcps/knowledge-skills/devops-deployment.server.js +123 -157
  130. package/dist/mcps/knowledge-skills/git-workflow.server.js +34 -67
  131. package/dist/mcps/knowledge-skills/growth-strategist.server.js +301 -323
  132. package/dist/mcps/knowledge-skills/log-monitor.server.js +139 -159
  133. package/dist/mcps/knowledge-skills/mobile-development.server.js +170 -200
  134. package/dist/mcps/knowledge-skills/multimodal-looker.server.js +122 -158
  135. package/dist/mcps/knowledge-skills/performance-optimization.server.js +88 -138
  136. package/dist/mcps/knowledge-skills/project-analysis.server.js +131 -218
  137. package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +115 -150
  138. package/dist/mcps/knowledge-skills/security-audit.server.js +16 -143
  139. package/dist/mcps/knowledge-skills/seo-consultant.server.js +20 -213
  140. package/dist/mcps/knowledge-skills/session-management.server.js +13 -90
  141. package/dist/mcps/knowledge-skills/skill-invocation.server.js +43 -421
  142. package/dist/mcps/knowledge-skills/strategist.server.js +10 -55
  143. package/dist/mcps/knowledge-skills/tech-writer.server.js +16 -191
  144. package/dist/mcps/knowledge-skills/testing-best-practices.server.js +18 -191
  145. package/dist/mcps/knowledge-skills/testing-strategy.server.js +18 -156
  146. package/dist/mcps/knowledge-skills/ui-ux-design.server.js +22 -296
  147. package/dist/mcps/lint.server.js +50 -91
  148. package/dist/mcps/model-health-check.server.js +32 -60
  149. package/dist/mcps/orchestrator/aside-context.js +207 -0
  150. package/dist/mcps/orchestrator/handlers/complexity-handler.js +5 -1
  151. package/dist/mcps/orchestrator/handlers/status-handler.js +8 -1
  152. package/dist/mcps/orchestrator/handlers/task-handler.js +5 -0
  153. package/dist/mcps/orchestrator/index.js +5 -0
  154. package/dist/mcps/orchestrator/server.js +63 -8
  155. package/dist/mcps/performance-analysis.server.js +56 -87
  156. package/dist/mcps/processor-pipeline.server.js +68 -99
  157. package/dist/mcps/researcher.server.js +80 -153
  158. package/dist/mcps/security-scan.server.js +56 -70
  159. package/dist/mcps/shared/knowledge-skill-base.js +11 -4
  160. package/dist/mcps/state-manager.server.js +124 -152
  161. package/dist/monitoring/nudge-watchdog.js +0 -1
  162. package/dist/nucleus/default-plugins.js +13 -19
  163. package/dist/nucleus/index.js +0 -1
  164. package/dist/orchestrator/agent-spawn-governor.js +0 -1
  165. package/dist/orchestrator/intelligent-commit-batcher.js +2 -10
  166. package/dist/orchestrator/multi-agent-orchestration-coordinator.js +0 -1
  167. package/dist/orchestrator/orchestrator.js +8 -18
  168. package/dist/orchestrator/self-direction-activation.js +0 -1
  169. package/dist/orchestrator/universal-registry-bridge.js +0 -1
  170. package/dist/performance/performance-budget-enforcer.js +0 -1
  171. package/dist/performance/performance-regression-tester.js +0 -1
  172. package/dist/plugin/plugin-codex-context.js +87 -0
  173. package/dist/plugin/plugin-helpers.js +155 -0
  174. package/dist/plugin/plugin-logger.js +46 -0
  175. package/dist/plugin/plugin-modules.js +144 -0
  176. package/dist/plugin/plugin-quality-gate.js +88 -0
  177. package/dist/plugin/plugin-types.js +1 -0
  178. package/dist/plugin/xray-codex-injection.js +338 -0
  179. package/dist/postprocessor/PostProcessor.js +3 -9
  180. package/dist/postprocessor/analysis/CodeChangeAnalyzer.js +50 -0
  181. package/dist/postprocessor/config/ProcessorConfigLoader.js +16 -0
  182. package/dist/postprocessor/integration.js +194 -0
  183. package/dist/postprocessor/metamorphosis/SelfProposalEngine.js +472 -0
  184. package/dist/postprocessor/metamorphosis/index.js +1 -0
  185. package/dist/postprocessor/redeploy/RetryHandler.js +118 -0
  186. package/dist/postprocessor/services/RegressionAnalysisService.js +0 -1
  187. package/dist/postprocessor/triggers/APITrigger.js +0 -1
  188. package/dist/postprocessor/triggers/WebhookTrigger.js +0 -1
  189. package/dist/processors/implementations/agents-md-validation-processor.js +0 -1
  190. package/dist/processors/implementations/async-pattern-processor.js +0 -1
  191. package/dist/processors/implementations/console-log-guard-processor.js +0 -1
  192. package/dist/processors/implementations/coverage-analysis-processor.js +0 -1
  193. package/dist/processors/implementations/inference-improvement-processor.js +2 -9
  194. package/dist/processors/implementations/log-protection-processor.js +0 -1
  195. package/dist/processors/implementations/nudge-processor.js +0 -1
  196. package/dist/processors/implementations/performance-budget-processor.js +0 -1
  197. package/dist/processors/implementations/postprocessor-chain-validator.js +0 -1
  198. package/dist/processors/implementations/publish-preflight-processor.js +4 -12
  199. package/dist/processors/implementations/session-summary-processor.js +8 -16
  200. package/dist/processors/implementations/spawn-governance-processor.js +0 -1
  201. package/dist/processors/implementations/storytelling-trigger-processor.js +3 -28
  202. package/dist/processors/implementations/test-auto-creation-processor.js +0 -1
  203. package/dist/processors/implementations/typescript-compilation-processor.js +0 -1
  204. package/dist/processors/implementations/version-compliance-processor.js +0 -1
  205. package/dist/processors/processor-interfaces.js +0 -1
  206. package/dist/processors/processor-types.js +0 -1
  207. package/dist/scripts/integration.js +0 -1
  208. package/dist/security/comprehensive-security-audit.js +0 -1
  209. package/dist/security/security-agent-coordinator.js +0 -1
  210. package/dist/security/security-auditor.js +0 -1
  211. package/dist/security/security-hardener.js +0 -1
  212. package/dist/security/security-hardening-system.js +0 -1
  213. package/dist/security/security-headers.js +0 -1
  214. package/dist/security/security-orchestration-layer.js +0 -1
  215. package/dist/services/inference-tuner.js +0 -1
  216. package/dist/session/session-cleanup-manager.js +0 -1
  217. package/dist/session/session-monitor.js +0 -1
  218. package/dist/session/session-state-manager.js +0 -1
  219. package/dist/skills/xray-orchestrator/index.js +0 -1
  220. package/dist/utils/codex-parser.js +0 -1
  221. package/dist/utils/language-detector.js +0 -1
  222. package/dist/utils/shutdown-handler.js +0 -1
  223. package/dist/validation/agent-config-validator.js +280 -0
  224. package/dist/validation/orchestration-flow-validator.js +606 -0
  225. package/package.json +1 -1
  226. package/scripts/node/release.mjs +2 -2
  227. package/scripts/node/setup.cjs +28 -0
  228. package/scripts/node/universal-version-manager.js +1 -1
  229. package/src/mcps/agent-resolver.ts +0 -1
  230. package/src/mcps/architect-tools.server.ts +129 -211
  231. package/src/mcps/auto-format.server.ts +74 -103
  232. package/src/mcps/boot-orchestrator.server.ts +71 -96
  233. package/src/mcps/config/__tests__/config-loader.test.ts +6 -6
  234. package/src/mcps/config/config-loader.ts +7 -0
  235. package/src/mcps/config/plugin-server-registry.ts +0 -1
  236. package/src/mcps/enforcer-tools.server.ts +217 -294
  237. package/src/mcps/estimation.server.ts +62 -122
  238. package/src/mcps/framework-compliance-audit.server.ts +53 -95
  239. package/src/mcps/framework-help.server.ts +74 -96
  240. package/src/mcps/governance.server.ts +97 -162
  241. package/src/mcps/knowledge-skills/api-design.server.ts +33 -72
  242. package/src/mcps/knowledge-skills/architecture-patterns.server.ts +33 -72
  243. package/src/mcps/knowledge-skills/bug-triage-specialist.server.ts +148 -193
  244. package/src/mcps/knowledge-skills/code-analyzer.server.ts +222 -254
  245. package/src/mcps/knowledge-skills/code-review.server.ts +115 -157
  246. package/src/mcps/knowledge-skills/content-creator.server.ts +219 -246
  247. package/src/mcps/knowledge-skills/database-design.server.ts +119 -160
  248. package/src/mcps/knowledge-skills/devops-deployment.server.ts +126 -167
  249. package/src/mcps/knowledge-skills/git-workflow.server.ts +32 -77
  250. package/src/mcps/knowledge-skills/growth-strategist.server.ts +322 -360
  251. package/src/mcps/knowledge-skills/log-monitor.server.ts +68 -95
  252. package/src/mcps/knowledge-skills/mobile-development.server.ts +16 -56
  253. package/src/mcps/knowledge-skills/multimodal-looker.server.ts +13 -59
  254. package/src/mcps/knowledge-skills/performance-optimization.server.ts +13 -74
  255. package/src/mcps/knowledge-skills/project-analysis.server.ts +13 -120
  256. package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +13 -60
  257. package/src/mcps/knowledge-skills/security-audit.server.ts +19 -157
  258. package/src/mcps/knowledge-skills/seo-consultant.server.ts +23 -227
  259. package/src/mcps/knowledge-skills/session-management.server.ts +17 -106
  260. package/src/mcps/knowledge-skills/skill-invocation.server.ts +45 -446
  261. package/src/mcps/knowledge-skills/strategist.server.ts +13 -63
  262. package/src/mcps/knowledge-skills/tech-writer.server.ts +19 -204
  263. package/src/mcps/knowledge-skills/testing-best-practices.server.ts +21 -204
  264. package/src/mcps/knowledge-skills/testing-strategy.server.ts +21 -165
  265. package/src/mcps/knowledge-skills/ui-ux-design.server.ts +25 -342
  266. package/src/mcps/lint.server.ts +52 -105
  267. package/src/mcps/model-health-check.server.ts +34 -70
  268. package/src/mcps/orchestrator/aside-context.ts +245 -0
  269. package/src/mcps/orchestrator/handlers/complexity-handler.ts +9 -3
  270. package/src/mcps/orchestrator/handlers/status-handler.ts +11 -1
  271. package/src/mcps/orchestrator/handlers/task-handler.ts +8 -1
  272. package/src/mcps/orchestrator/index.ts +29 -0
  273. package/src/mcps/orchestrator/server.ts +79 -24
  274. package/src/mcps/orchestrator/types.ts +37 -0
  275. package/src/mcps/performance-analysis.server.ts +59 -102
  276. package/src/mcps/processor-pipeline.server.ts +70 -108
  277. package/src/mcps/researcher.server.ts +87 -175
  278. package/src/mcps/security-scan.server.ts +57 -76
  279. package/src/mcps/shared/knowledge-skill-base.ts +12 -4
  280. package/src/mcps/state-manager.server.ts +129 -169
  281. package/src/opencode/codex.codex +1 -1
  282. package/src/opencode/commands/auto-format.md +3 -3
  283. package/src/opencode/commands/auto-summary-capture.md +2 -2
  284. package/src/opencode/commands/enforcer-daily-scan.md +3 -3
  285. package/src/opencode/commands/framework-compliance-audit.md +4 -4
  286. package/src/opencode/commands/interactive-validator.md +2 -2
  287. package/src/opencode/commands/job-summary-logger.md +2 -2
  288. package/src/opencode/commands/mode-switch.md +1 -1
  289. package/src/opencode/commands/model-health-check.md +2 -2
  290. package/src/opencode/commands/performance-analysis.md +2 -2
  291. package/src/opencode/commands/pre-commit-introspection.md +3 -3
  292. package/src/opencode/commands/security-scan.md +3 -3
  293. package/src/opencode/commands/sisyphus-validation.md +3 -3
  294. package/src/opencode/commands/summary-logger.md +2 -2
  295. package/src/skills/xray-orchestrator/index.ts +0 -1
  296. package/dist/nucleus/orchestrator.js +0 -479
@@ -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';
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Retry Handler for Redeploy Operations
3
+ */
4
+ import { frameworkLogger } from "../../core/framework-logger.js";
5
+ export class RetryHandler {
6
+ config;
7
+ constructor(config = {
8
+ maxRetries: 3,
9
+ baseDelay: 30000,
10
+ backoffStrategy: "exponential",
11
+ }) {
12
+ this.config = config;
13
+ }
14
+ /**
15
+ * Execute an operation with retry logic
16
+ */
17
+ async executeWithRetry(operation, shouldRetry) {
18
+ let lastError = {};
19
+ for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
20
+ try {
21
+ return await operation();
22
+ }
23
+ catch (error) {
24
+ const retryable = error;
25
+ lastError = retryable;
26
+ // Don't retry on the last attempt
27
+ if (attempt === this.config.maxRetries) {
28
+ break;
29
+ }
30
+ // Check if we should retry this error
31
+ if (shouldRetry && !shouldRetry(retryable, attempt)) {
32
+ break;
33
+ }
34
+ // Calculate delay and wait
35
+ const delay = this.calculateDelay(attempt);
36
+ await frameworkLogger.log("-retry-handler", "-operation-failed-attempt-attempt-1-retrying-in-de", "error", {
37
+ message: `⏳ Operation failed (attempt ${attempt + 1}), retrying in ${delay}ms...`,
38
+ });
39
+ await this.wait(delay);
40
+ }
41
+ }
42
+ throw lastError;
43
+ }
44
+ /**
45
+ * Calculate delay based on backoff strategy
46
+ */
47
+ calculateDelay(attempt) {
48
+ const { baseDelay, backoffStrategy } = this.config;
49
+ switch (backoffStrategy) {
50
+ case "exponential":
51
+ return baseDelay * Math.pow(2, attempt);
52
+ case "linear":
53
+ return baseDelay * (attempt + 1);
54
+ default:
55
+ return baseDelay;
56
+ }
57
+ }
58
+ /**
59
+ * Wait for the specified duration
60
+ */
61
+ async wait(duration) {
62
+ return new Promise((resolve) => setTimeout(resolve, duration));
63
+ }
64
+ /**
65
+ * Default retry conditions for deployment operations
66
+ */
67
+ static shouldRetryDeployment(error, attempt) {
68
+ // Don't retry certain types of errors
69
+ const nonRetryableErrors = [
70
+ "authentication_failed",
71
+ "authorization_failed",
72
+ "invalid_configuration",
73
+ "quota_exceeded",
74
+ ];
75
+ if (nonRetryableErrors.some((type) => error.type?.includes(type))) {
76
+ return false;
77
+ }
78
+ // Don't retry after too many attempts for transient errors
79
+ if (attempt >= 2 && error.type === "transient") {
80
+ return false;
81
+ }
82
+ // Retry network and timeout errors
83
+ if (error.code === "ECONNRESET" ||
84
+ error.code === "ETIMEDOUT" ||
85
+ error.code === "ENOTFOUND") {
86
+ return true;
87
+ }
88
+ // Retry 5xx HTTP errors
89
+ if (error.statusCode >= 500 && error.statusCode < 600) {
90
+ return true;
91
+ }
92
+ // Default: retry for most errors
93
+ return true;
94
+ }
95
+ /**
96
+ * Specialized retry handler for deployment operations
97
+ */
98
+ async executeDeploymentWithRetry(deploymentOperation) {
99
+ return this.executeWithRetry(deploymentOperation, RetryHandler.shouldRetryDeployment);
100
+ }
101
+ /**
102
+ * Specialized retry handler for API calls
103
+ */
104
+ async executeApiCallWithRetry(apiCall) {
105
+ return this.executeWithRetry(apiCall, (error, attempt) => {
106
+ // Retry on network errors and 5xx status codes
107
+ return (error.code === "ECONNRESET" ||
108
+ error.code === "ETIMEDOUT" ||
109
+ (error.statusCode >= 500 && error.statusCode < 600));
110
+ });
111
+ }
112
+ /**
113
+ * Get retry statistics
114
+ */
115
+ getStats() {
116
+ return { ...this.config };
117
+ }
118
+ }
@@ -5,7 +5,6 @@
5
5
  * AI code removal attempts, and other critical issues.
6
6
  * Triggers multi-agent conferences when analysis is required.
7
7
  *
8
- * @version 1.0.0
9
8
  * @since 2026-03-08
10
9
  */
11
10
  import { getKernel } from '../../core/kernel-patterns.js';
@@ -5,7 +5,6 @@
5
5
  * operations. Useful for CI/CD pipelines, manual test triggers,
6
6
  * and retry mechanisms.
7
7
  *
8
- * @version 2.0.0
9
8
  * @since 2026-03-08
10
9
  */
11
10
  import express from 'express';
@@ -5,7 +5,6 @@
5
5
  * services (GitHub, GitLab, Bitbucket, Stripe) and routes them
6
6
  * to the PostProcessor for execution.
7
7
  *
8
- * @version 2.0.0
9
8
  * @since 2026-03-08
10
9
  */
11
10
  import express from 'express';
@@ -8,7 +8,6 @@
8
8
  * @priority 90 (high - runs early)
9
9
  * @blocking true (blocks commit if AGENTS.md is invalid)
10
10
  *
11
- * @version 1.0.0
12
11
  * @framework 0xRay 1.3.5
13
12
  */
14
13
  import * as fs from "fs";
@@ -5,7 +5,6 @@
5
5
  * Detects anti-patterns in async code: callback patterns, long promise chains,
6
6
  * missing await inside async functions, and mixed callback/promise styles.
7
7
  *
8
- * @version 1.0.0
9
8
  * @since 2026-03-28
10
9
  */
11
10
  import { frameworkLogger } from "../../core/framework-logger.js";
@@ -5,7 +5,6 @@
5
5
  * Scans code for forbidden console.log/warn/error/info/debug usage,
6
6
  * ensuring all logging goes through frameworkLogger instead.
7
7
  *
8
- * @version 1.0.0
9
8
  * @since 2026-03-28
10
9
  */
11
10
  import { frameworkLogger } from "../../core/framework-logger.js";
@@ -4,7 +4,6 @@
4
4
  * Analyzes test coverage for modified files and reports coverage gaps.
5
5
  *
6
6
  * @module processors/implementations
7
- * @version 1.0.0
8
7
  */
9
8
  import { PostProcessor } from "../processor-interfaces.js";
10
9
  import { frameworkLogger } from "../../core/framework-logger.js";
@@ -12,6 +12,7 @@ import * as path from "path";
12
12
  import { PostProcessor } from "../processor-interfaces.js";
13
13
  import { frameworkLogger } from "../../core/framework-logger.js";
14
14
  import { getConfigDir } from "../../core/config-paths.js";
15
+ import { featuresConfigLoader } from "../../core/features-config.js";
15
16
  export class InferenceImprovementProcessor extends PostProcessor {
16
17
  name = "inferenceImprovement";
17
18
  priority = 5;
@@ -37,15 +38,7 @@ export class InferenceImprovementProcessor extends PostProcessor {
37
38
  }
38
39
  loadInferenceConfig() {
39
40
  try {
40
- const configPaths = [
41
- path.join(process.cwd(), ".xray", "features.json"),
42
- ];
43
- for (const configPath of configPaths) {
44
- if (fs.existsSync(configPath)) {
45
- const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
46
- return config.inference || config;
47
- }
48
- }
41
+ return featuresConfigLoader.loadConfig().inference ?? null;
49
42
  }
50
43
  catch (e) {
51
44
  // ignore - use defaults