0xray 2.1.4 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/.opencode/codex.codex +1 -1
  2. package/.opencode/commands/dependency-audit.md +3 -3
  3. package/.opencode/enforcer-config.json +2 -2
  4. package/.opencode/init.sh +1 -1
  5. package/AGENTS.md +6 -6
  6. package/README.md +4 -4
  7. package/dist/AGENTS.md +6 -6
  8. package/dist/CHANGELOG.md +39 -0
  9. package/dist/README.md +4 -4
  10. package/dist/agents/code-reviewer.js +1 -1
  11. package/dist/analytics/routing-refiner.js +1 -1
  12. package/dist/cli/commands/govern.d.ts +29 -0
  13. package/dist/cli/commands/govern.js +152 -0
  14. package/dist/cli/index.js +29 -216
  15. package/dist/core/boot-orchestrator.js +2 -2
  16. package/dist/core/features-config.js +1 -1
  17. package/dist/core/framework-logger.d.ts +1 -0
  18. package/dist/core/framework-logger.js +57 -2
  19. package/dist/delegation/index.d.ts +1 -2
  20. package/dist/delegation/index.js +1 -2
  21. package/dist/enforcement/enforcer-tools.js +1 -1
  22. package/dist/execution/proposal-applier.d.ts +1 -9
  23. package/dist/execution/proposal-applier.js +18 -173
  24. package/dist/governance/codex-policy.service.d.ts +7 -25
  25. package/dist/governance/codex-policy.service.js +8 -26
  26. package/dist/governance/governance-core.d.ts +22 -28
  27. package/dist/governance/governance-core.js +31 -101
  28. package/dist/governance/governance-service.d.ts +1 -0
  29. package/dist/governance/governance-service.js +67 -4
  30. package/dist/governance/governance-types.d.ts +5 -2
  31. package/dist/inference/index.d.ts +3 -4
  32. package/dist/inference/inference-accumulator.js +1 -1
  33. package/dist/inference/inference-cycle.d.ts +12 -18
  34. package/dist/inference/inference-cycle.js +120 -335
  35. package/dist/integrations/base/index.d.ts +0 -1
  36. package/dist/integrations/base/index.js +0 -2
  37. package/dist/integrations/grok/hooks/pre-tool-use.js +4 -18
  38. package/dist/integrations/hermes-agent/bridge.mjs +9 -0
  39. package/dist/mcps/config/server-config-registry.js +1 -1
  40. package/dist/mcps/governance.server.js +4 -5
  41. package/dist/mcps/knowledge-skills/api-design.server.js +10 -0
  42. package/dist/mcps/knowledge-skills/architecture-patterns.server.js +10 -0
  43. package/dist/mcps/knowledge-skills/bug-triage-specialist.server.js +10 -0
  44. package/dist/mcps/knowledge-skills/code-analyzer.server.js +10 -0
  45. package/dist/mcps/knowledge-skills/code-review.server.js +10 -0
  46. package/dist/mcps/knowledge-skills/content-creator.server.js +10 -0
  47. package/dist/mcps/knowledge-skills/database-design.server.js +10 -0
  48. package/dist/mcps/knowledge-skills/devops-deployment.server.js +10 -0
  49. package/dist/mcps/knowledge-skills/git-workflow.server.js +10 -0
  50. package/dist/mcps/knowledge-skills/growth-strategist.server.js +10 -0
  51. package/dist/mcps/knowledge-skills/log-monitor.server.js +10 -0
  52. package/dist/mcps/knowledge-skills/mobile-development.server.js +10 -0
  53. package/dist/mcps/knowledge-skills/multimodal-looker.server.js +10 -0
  54. package/dist/mcps/knowledge-skills/performance-optimization.server.js +10 -0
  55. package/dist/mcps/knowledge-skills/project-analysis.server.js +10 -0
  56. package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +10 -0
  57. package/dist/mcps/knowledge-skills/security-audit.server.js +10 -0
  58. package/dist/mcps/knowledge-skills/seo-consultant.server.js +10 -0
  59. package/dist/mcps/knowledge-skills/skill-invocation.server.d.ts +4 -0
  60. package/dist/mcps/knowledge-skills/skill-invocation.server.js +33 -14
  61. package/dist/mcps/knowledge-skills/strategist.server.js +10 -0
  62. package/dist/mcps/knowledge-skills/tech-writer.server.js +11 -1
  63. package/dist/mcps/knowledge-skills/testing-strategy.server.js +10 -0
  64. package/dist/mcps/knowledge-skills/ui-ux-design.server.js +10 -0
  65. package/dist/mcps/registry.json +1 -1
  66. package/dist/mcps/simulation/server-simulations.js +1 -1
  67. package/dist/metrics/agent-metrics.d.ts +2 -1
  68. package/dist/nucleus/govern-http.d.ts +59 -0
  69. package/dist/nucleus/govern-http.js +172 -0
  70. package/dist/nucleus/index.d.ts +14 -0
  71. package/dist/nucleus/index.js +9 -0
  72. package/dist/nucleus/kernel.d.ts +51 -0
  73. package/dist/nucleus/kernel.js +62 -0
  74. package/dist/nucleus/plugin-registry.d.ts +104 -0
  75. package/dist/nucleus/plugin-registry.js +147 -0
  76. package/dist/orchestrator/orchestrator.d.ts +0 -1
  77. package/dist/orchestrator/orchestrator.js +0 -21
  78. package/dist/postprocessor/PostProcessor.d.ts +13 -1
  79. package/dist/postprocessor/PostProcessor.js +41 -1
  80. package/dist/postprocessor/autofix/AutoFixEngine.d.ts +0 -8
  81. package/dist/postprocessor/autofix/AutoFixEngine.js +0 -54
  82. package/dist/postprocessor/metamorphosis/MetamorphosisEngine.d.ts +25 -0
  83. package/dist/postprocessor/metamorphosis/MetamorphosisEngine.js +10 -0
  84. package/dist/postprocessor/metamorphosis/SelfProposalEngine.d.ts +68 -0
  85. package/dist/postprocessor/metamorphosis/SelfProposalEngine.js +371 -0
  86. package/dist/skills/orchestrator/SKILL.md +1 -1
  87. package/dist/skills/registry.json +1 -1
  88. package/dist/state/index.d.ts +0 -2
  89. package/package.json +4 -3
  90. package/scripts/node/universal-version-manager.js +9 -9
  91. package/scripts/node/validate-mcp-connectivity.js +1 -1
  92. package/src/mcps/config/__tests__/server-config-registry.test.ts +6 -15
  93. package/src/mcps/config/server-config-registry.ts +1 -1
  94. package/src/mcps/governance.server.ts +4 -6
  95. package/src/mcps/knowledge-skills/api-design.server.ts +9 -0
  96. package/src/mcps/knowledge-skills/architecture-patterns.server.ts +9 -0
  97. package/src/mcps/knowledge-skills/bug-triage-specialist.server.ts +9 -0
  98. package/src/mcps/knowledge-skills/code-analyzer.server.ts +9 -0
  99. package/src/mcps/knowledge-skills/code-review.server.ts +9 -0
  100. package/src/mcps/knowledge-skills/content-creator.server.ts +9 -0
  101. package/src/mcps/knowledge-skills/database-design.server.ts +9 -0
  102. package/src/mcps/knowledge-skills/devops-deployment.server.ts +9 -0
  103. package/src/mcps/knowledge-skills/git-workflow.server.ts +9 -0
  104. package/src/mcps/knowledge-skills/growth-strategist.server.ts +9 -0
  105. package/src/mcps/knowledge-skills/log-monitor.server.ts +9 -0
  106. package/src/mcps/knowledge-skills/mobile-development.server.ts +9 -0
  107. package/src/mcps/knowledge-skills/multimodal-looker.server.ts +9 -0
  108. package/src/mcps/knowledge-skills/performance-optimization.server.ts +9 -0
  109. package/src/mcps/knowledge-skills/project-analysis.server.ts +9 -0
  110. package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +9 -0
  111. package/src/mcps/knowledge-skills/security-audit.server.ts +9 -0
  112. package/src/mcps/knowledge-skills/seo-consultant.server.ts +9 -0
  113. package/src/mcps/knowledge-skills/session-management.server.ts +1 -0
  114. package/src/mcps/knowledge-skills/skill-invocation.server.ts +44 -29
  115. package/src/mcps/knowledge-skills/strategist.server.ts +9 -0
  116. package/src/mcps/knowledge-skills/tech-writer.server.ts +10 -1
  117. package/src/mcps/knowledge-skills/testing-strategy.server.ts +9 -0
  118. package/src/mcps/knowledge-skills/ui-ux-design.server.ts +9 -0
  119. package/src/mcps/registry.json +1 -1
  120. package/src/mcps/simulation/server-simulations.ts +1 -1
  121. package/src/opencode/codex.codex +1 -1
  122. package/src/opencode/commands/dependency-audit.md +3 -3
  123. package/src/opencode/enforcer-config.json +2 -2
  124. package/src/skills/orchestrator/SKILL.md +1 -1
  125. package/src/skills/registry.json +1 -1
  126. package/xray/codex.json +1 -1
  127. package/xray/config.json +1 -1
  128. package/xray/features.json +1 -1
  129. package/xray/integrations.json +3 -3
  130. package/.opencode/agents/testing-best-practices.yml +0 -12
  131. package/dist/analytics/consent-manager.d.ts +0 -93
  132. package/dist/analytics/consent-manager.js +0 -258
  133. package/dist/analytics/simple-pattern-analyzer.d.ts +0 -80
  134. package/dist/analytics/simple-pattern-analyzer.js +0 -297
  135. package/dist/cli/commands/analytics-disable.d.ts +0 -9
  136. package/dist/cli/commands/analytics-disable.js +0 -72
  137. package/dist/cli/commands/analytics-enable-action.d.ts +0 -8
  138. package/dist/cli/commands/analytics-enable-action.js +0 -82
  139. package/dist/cli/commands/analytics-preview.d.ts +0 -9
  140. package/dist/cli/commands/analytics-preview.js +0 -106
  141. package/dist/cli/commands/analytics-status.d.ts +0 -9
  142. package/dist/cli/commands/analytics-status.js +0 -68
  143. package/dist/cli/server.d.ts +0 -1
  144. package/dist/cli/server.js +0 -147
  145. package/dist/core/errors.d.ts +0 -3
  146. package/dist/core/errors.js +0 -10
  147. package/dist/core/logging-config.d.ts +0 -11
  148. package/dist/core/logging-config.js +0 -43
  149. package/dist/core/trace-context.d.ts +0 -12
  150. package/dist/core/trace-context.js +0 -33
  151. package/dist/delegation/voting-coordinator.d.ts +0 -49
  152. package/dist/delegation/voting-coordinator.js +0 -375
  153. package/dist/enforcement/test-auto-healing.d.ts +0 -83
  154. package/dist/enforcement/test-auto-healing.js +0 -325
  155. package/dist/integrations/base/ExampleIntegration.d.ts +0 -47
  156. package/dist/integrations/base/ExampleIntegration.js +0 -181
  157. package/dist/mcps/knowledge-skills/testing-best-practices.server.d.ts +0 -34
  158. package/dist/mcps/knowledge-skills/testing-best-practices.server.js +0 -831
  159. package/dist/mcps/orchestrator.server.d.ts +0 -10
  160. package/dist/mcps/orchestrator.server.js +0 -19
  161. package/dist/orchestrator/self-direction-activation.d.ts +0 -109
  162. package/dist/orchestrator/self-direction-activation.js +0 -245
  163. package/dist/orchestrator/universal-librarian-consultation.d.ts +0 -98
  164. package/dist/orchestrator/universal-librarian-consultation.js +0 -216
  165. package/dist/orchestrator/universal-registry-bridge.d.ts +0 -85
  166. package/dist/orchestrator/universal-registry-bridge.js +0 -247
  167. package/dist/performance/performance-budget-enforcer.d.ts +0 -158
  168. package/dist/performance/performance-budget-enforcer.js +0 -434
  169. package/dist/performance/performance-regression-tester.d.ts +0 -108
  170. package/dist/performance/performance-regression-tester.js +0 -342
  171. package/dist/skills/testing-best-practices/SKILL.md +0 -37
  172. package/dist/state/context-providers.d.ts +0 -4
  173. package/dist/state/context-providers.js +0 -1
  174. package/dist/state/state-types.d.ts +0 -5
  175. package/dist/state/state-types.js +0 -1
  176. package/dist/utils/batch-operations.d.ts +0 -25
  177. package/dist/utils/batch-operations.js +0 -292
  178. package/dist/utils/test-template-generator.d.ts +0 -25
  179. package/dist/utils/test-template-generator.js +0 -178
  180. package/dist/utils/token-manager.d.ts +0 -48
  181. package/dist/utils/token-manager.js +0 -163
  182. package/src/mcps/knowledge-skills/testing-best-practices.server.test.ts +0 -136
  183. package/src/mcps/knowledge-skills/testing-best-practices.server.ts +0 -1183
  184. package/src/mcps/orchestrator.server.ts +0 -34
  185. package/src/opencode/agents/testing-best-practices.yml +0 -12
  186. package/src/skills/testing-best-practices/SKILL.md +0 -37
@@ -2,31 +2,20 @@ import * as fs from "fs";
2
2
  import * as path from "path";
3
3
  import { shouldTriggerCycle, accumulateCorpus } from "./inference-accumulator.js";
4
4
  import { DeployVerifier } from "./deploy-verifier.js";
5
- import { VotingCoordinator } from "../delegation/voting-coordinator.js";
6
5
  import { XrayStateManager } from "../state/state-manager.js";
7
6
  import { frameworkLogger } from "../core/framework-logger.js";
8
- import { getGovernanceIntegration } from "../integrations/governance/index.js";
9
7
  import { featuresConfigLoader } from "../core/features-config.js";
10
8
  import { mcpClientManager } from "../mcps/mcp-client.js";
11
9
  import { getConfigDir } from "../core/config-paths.js";
12
10
  import { invokeViaOpencode as invokeOpencodeFromEngine } from "../execution/opencode-cli-invoker.js";
13
11
  import { ProposalApplier } from "../execution/proposal-applier.js";
14
- const CYCLE_STATE_FILE = "inference-cycle-state.json";
15
- const CYCLE_HISTORY_FILE = "inference-cycle-history.json";
16
- const GOVERNANCE_AGENTS = {
17
- // Real individual knowledge-skill MCP servers (have analyze_proposal handlers)
18
- fix: ["code-review", "security-audit", "researcher"],
19
- refactor: ["code-review", "security-audit", "researcher"],
20
- guard: ["code-review", "security-audit", "researcher"],
21
- automate: ["code-review", "security-audit", "researcher"],
22
- codify: ["code-review", "security-audit", "researcher"],
23
- };
12
+ import { handleGovernRequest } from "../nucleus/govern-http.js";
13
+ const CONSOLIDATED_STATE_FILE = "inference-state.json";
24
14
  export class InferenceCycle {
25
15
  // Singleton registry + state management to prevent recursive agent spawning
26
16
  static instances = new Map();
27
17
  static reEntryLock = false;
28
18
  static governedProposalIds = new Set();
29
- static votingCoordinator = null;
30
19
  static getInstance(projectRoot, options) {
31
20
  const root = path.resolve(projectRoot || process.cwd());
32
21
  if (!InferenceCycle.instances.has(root)) {
@@ -38,7 +27,6 @@ export class InferenceCycle {
38
27
  InferenceCycle.instances.clear();
39
28
  InferenceCycle.reEntryLock = false;
40
29
  InferenceCycle.governedProposalIds.clear();
41
- InferenceCycle.votingCoordinator = null;
42
30
  }
43
31
  inferenceDir;
44
32
  stateDir;
@@ -98,7 +86,6 @@ export class InferenceCycle {
98
86
  InferenceCycle.governedProposalIds.add(p.id);
99
87
  this.setPhase("complete");
100
88
  this.saveCycleState(cycleId);
101
- this.saveGovernanceState(this.getCoordinator());
102
89
  const result = this.buildResult(cycleId, true, "external proposals", startTime, undefined, proposals, votes);
103
90
  this.appendHistory(result);
104
91
  frameworkLogger.log("inference-cycle", "external-governance-complete", "info", {
@@ -124,7 +111,7 @@ export class InferenceCycle {
124
111
  const cycleId = `cycle-${Date.now()}`;
125
112
  try {
126
113
  this.setPhase("collecting");
127
- const lastCycleFile = path.join(this.stateDir, CYCLE_STATE_FILE);
114
+ const lastCycleFile = path.join(this.stateDir, CONSOLIDATED_STATE_FILE);
128
115
  const threshold = this.options.force ? { trigger: true, reason: "force flag set" } : shouldTriggerCycle(this.inferenceDir, lastCycleFile);
129
116
  if (!threshold.trigger) {
130
117
  this.setPhase("idle");
@@ -188,7 +175,6 @@ export class InferenceCycle {
188
175
  }
189
176
  this.setPhase("complete");
190
177
  this.saveCycleState(cycleId);
191
- this.saveGovernanceState(this.getCoordinator());
192
178
  this.appendHistory(this.buildResult(cycleId, true, threshold.reason, startTime, corpus, proposals, votes, deployResult));
193
179
  return this.buildResult(cycleId, true, threshold.reason, startTime, corpus, proposals, votes, deployResult);
194
180
  }
@@ -270,19 +256,8 @@ export class InferenceCycle {
270
256
  this.adjustConfidenceFromHistory(proposals);
271
257
  proposals.sort((a, b) => b.confidence - a.confidence);
272
258
  }
273
- getCoordinator() {
274
- if (!InferenceCycle.votingCoordinator) {
275
- const stateManager = this.getGovernanceStateManager();
276
- InferenceCycle.votingCoordinator = new VotingCoordinator(stateManager);
277
- }
278
- return InferenceCycle.votingCoordinator;
279
- }
280
259
  async applyProposals(proposals) {
281
- const applier = new ProposalApplier(this.projectRoot, async (p) => this.applyProposalWork(p), async (p, prUrl) => {
282
- if (this.options.skipResearcherReview)
283
- return "go";
284
- return this.researcherReview(p, prUrl);
285
- });
260
+ const applier = new ProposalApplier(this.projectRoot);
286
261
  const results = await applier.applyProposals(proposals);
287
262
  for (const r of results) {
288
263
  const p = proposals.find(pr => pr.id === r.proposalId);
@@ -453,9 +428,36 @@ Respond with EXACTLY one of:
453
428
  }
454
429
  }
455
430
  async governProposals(proposals) {
456
- // Primary path: Use the first-class Governance MCP (real skill servers + required Dynamo)
457
- // This is the clean, centralized path (governance.server.ts + GovernanceService)
458
- const useGovernanceMcp = (process.env.XRAY_FORCE_MCP_GOVERNANCE) === 'true' ||
431
+ // v3: Primary path through the nucleus kernel (handleGovernRequest)
432
+ // This gives ALL proposals the same contract: 3-agent + Dynamo governance,
433
+ // metamorphosis scoring, dynamic skills, and structured logging.
434
+ // The MCP governance server remains the standard external surface; this is the
435
+ // internal uniform path that the MCP server also delegates to.
436
+ try {
437
+ const governanceResponse = await this.governViaNucleus(proposals);
438
+ frameworkLogger.log("inference-cycle", "governance-nucleus-success", "info", {
439
+ proposalCount: proposals.length,
440
+ overall: governanceResponse.overallDecision,
441
+ });
442
+ return this.convertNucleusResponse(governanceResponse, proposals);
443
+ }
444
+ catch (err) {
445
+ frameworkLogger.log("inference-cycle", "governance-nucleus-failed", "warning", {
446
+ error: err instanceof Error ? err.message : String(err),
447
+ stack: err instanceof Error ? err.stack : undefined,
448
+ });
449
+ // In forced pure MCP mode we must not silently fall back
450
+ if (process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true') {
451
+ throw err;
452
+ }
453
+ // Fallback: try the Governance MCP directly (the standard external surface)
454
+ frameworkLogger.log("inference-cycle", "governance-mcp-fallback", "warning", {
455
+ message: "Nucleus path failed; falling back to Governance MCP.",
456
+ originalError: err instanceof Error ? err.message : String(err),
457
+ });
458
+ }
459
+ // Fallback: MCP governance server
460
+ const useGovernanceMcp = process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true' ||
459
461
  this.isGovernanceMcpPreferred();
460
462
  if (useGovernanceMcp) {
461
463
  try {
@@ -477,35 +479,79 @@ Respond with EXACTLY one of:
477
479
  ]);
478
480
  const text = result?.content?.[0]?.text || "";
479
481
  const parsed = this.parseGovernanceMcpResponse(text, proposals);
480
- frameworkLogger.log("inference-cycle", "governance-mcp-primary-path", "info", {
482
+ frameworkLogger.log("inference-cycle", "governance-mcp-fallback-success", "info", {
481
483
  proposalCount: proposals.length,
482
484
  overall: parsed.overallDecision,
483
485
  });
484
486
  return parsed.votes;
485
487
  }
486
488
  catch (err) {
487
- frameworkLogger.log("inference-cycle", "governance-mcp-failed", "error", {
489
+ frameworkLogger.log("inference-cycle", "governance-mcp-fallback-failed", "error", {
488
490
  error: err instanceof Error ? err.message : String(err),
489
491
  });
490
- // In forced pure MCP mode we must not silently fall back
491
- if (process.env.XRAY_FORCE_MCP_GOVERNANCE === 'true') {
492
- throw err;
493
- }
494
- // In normal mode, fall back to legacy path with deprecation warning.
495
- // The legacy path will be removed once all consumers have migrated to the Governance MCP + Dynamo Solar SSOT model.
496
- frameworkLogger.log("inference-cycle", "governance-legacy-fallback", "warning", {
497
- message: "Falling back to legacy governance path. This path is deprecated and will be removed in a future version.",
498
- });
499
492
  }
500
493
  }
501
- // Legacy internal path (deprecated)
502
- const internalVotes = await this.governProposalsInternal(proposals);
503
- const governanceIntegration = getGovernanceIntegration();
504
- if (governanceIntegration?.isAvailable()) {
505
- const externalVotes = await this.governProposalsExternal(proposals);
506
- return this.mergeGovernanceVotes(internalVotes, externalVotes, proposals);
507
- }
508
- return internalVotes;
494
+ throw new Error("All governance paths exhausted: nucleus and MCP fallback both failed");
495
+ }
496
+ /**
497
+ * Map InferenceProposal.source to GovernanceProposal.source.
498
+ * Inference-specific sources (recurring_problem, recurring_pattern, wrong_turn)
499
+ * all normalize to 'inference'. Future tuning/mod-specific sources can be added here.
500
+ */
501
+ static SOURCE_MAP = {
502
+ 'recurring_problem': 'inference',
503
+ 'recurring_pattern': 'inference',
504
+ 'wrong_turn': 'inference',
505
+ };
506
+ /**
507
+ * Convert InferenceProposal[] to GovernanceRequest and route through
508
+ * the nucleus kernel (handleGovernRequest). This is the v3 uniform path.
509
+ */
510
+ async governViaNucleus(proposals) {
511
+ const governanceRequest = {
512
+ proposals: proposals.map(p => ({
513
+ id: p.id,
514
+ type: p.type,
515
+ title: p.title,
516
+ description: p.description,
517
+ evidence: p.evidence,
518
+ source: InferenceCycle.SOURCE_MAP[p.source] || 'inference',
519
+ confidence: p.confidence,
520
+ })),
521
+ context: {
522
+ project: 'xray',
523
+ phase: 'inference-cycle',
524
+ source: 'inference-cycle',
525
+ },
526
+ options: {
527
+ requireExternalDynamo: true,
528
+ },
529
+ };
530
+ return handleGovernRequest(governanceRequest);
531
+ }
532
+ /**
533
+ * Convert a GovernanceResponse (nucleus kernel format) back to the
534
+ * InferenceCycleResult["votes"] format that the rest of the cycle expects.
535
+ */
536
+ convertNucleusResponse(response, proposals) {
537
+ return proposals.map((p, i) => {
538
+ const result = response.results[i];
539
+ if (!result) {
540
+ return {
541
+ proposalId: p.id,
542
+ decision: 'reject',
543
+ confidence: 0,
544
+ details: ['nucleus: no result returned'],
545
+ };
546
+ }
547
+ const decision = result.finalDecision === 'approve' ? 'approve' : result.finalDecision === 'reject' ? 'reject' : 'abstain';
548
+ return {
549
+ proposalId: p.id,
550
+ decision,
551
+ confidence: result.averageConfidence,
552
+ details: result.votes?.map((v) => `${v.server || v.agentName || 'agent'}: ${v.decision} (${v.confidence})`) || [result.reasoningSummary],
553
+ };
554
+ });
509
555
  }
510
556
  isGovernanceMcpPreferred() {
511
557
  try {
@@ -547,230 +593,6 @@ Respond with EXACTLY one of:
547
593
  return { votes, overallDecision: "needs_revision" };
548
594
  }
549
595
  }
550
- /**
551
- * Oscillator 1: Internal VotingCoordinator-based governance
552
- */
553
- async governProposalsInternal(proposals) {
554
- // Defensive: if pure MCP mode is forced, use individual skill servers only
555
- if ((process.env.XRAY_FORCE_MCP_GOVERNANCE) === 'true') {
556
- return this.governProposalsWithIndividualSkills(proposals);
557
- }
558
- const coordinator = this.getCoordinator();
559
- const sessionId = `inference-governance-${Date.now()}`;
560
- const results = [];
561
- const todoPrompt = [
562
- `Vote on ${proposals.length} inference proposals. Output EXACTLY one PROPOSAL block per proposal.`,
563
- ``,
564
- `FORMAT (exact, no extra text, no markdown):`,
565
- `PROPOSAL: <number>`,
566
- ` AGENT: architect`,
567
- ` DECISION: approve|reject|abstain`,
568
- ` CONFIDENCE: 0.XX`,
569
- ` REASONING: <brief reason>`,
570
- ``,
571
- `Example:`,
572
- `PROPOSAL: 1`,
573
- ` AGENT: architect`,
574
- ` DECISION: approve`,
575
- ` CONFIDENCE: 0.85`,
576
- ` REASONING: Cleanup reduces maintenance burden`,
577
- ``,
578
- `PROPOSALS:`,
579
- ];
580
- for (let i = 0; i < proposals.length; i++) {
581
- const p = proposals[i];
582
- todoPrompt.push(`${i + 1}. [${p.type}] "${p.title}"`);
583
- }
584
- try {
585
- const jsonOutput = await this.invokeAgentInternal("architect", todoPrompt.join("\n"));
586
- const allVotes = this.parseSubagentVotes(jsonOutput, proposals);
587
- for (const proposal of proposals) {
588
- const agents = GOVERNANCE_AGENTS[proposal.type] ?? ["code-reviewer"];
589
- const participants = ["architect", ...agents];
590
- const voteId = await coordinator.initiateVoting(sessionId, proposal.title, proposal.description, participants, {
591
- complexity: Math.min(50, 10 + proposal.evidence.length * 5 + (proposal.confidence > 0.8 ? 10 : 0)),
592
- riskLevel: proposal.type === "fix" ? "low" : proposal.type === "guard" ? "high" : "medium",
593
- hasSecurityConcerns: proposal.type === "guard" || proposal.type === "fix",
594
- hasArchitecturalImpact: proposal.type === "codify" || proposal.type === "automate",
595
- participantCount: participants.length,
596
- });
597
- const proposalVotes = allVotes.filter((v) => v.proposalId === proposal.id);
598
- for (const v of proposalVotes) {
599
- coordinator.submitVote(voteId, v.agentName, v.decision, v.confidence, v.reasoning);
600
- }
601
- const resolved = coordinator.resolveVoting(voteId);
602
- if (resolved) {
603
- results.push({
604
- proposalId: proposal.id,
605
- decision: resolved.decision === "approve" ? "approve" : "reject",
606
- confidence: resolved.confidence,
607
- details: resolved.details?.map((d) => `${d.agentName}: vote=${d.vote}, weight=${d.weight.toFixed(2)}`) || [],
608
- });
609
- if (resolved.details) {
610
- for (const detail of resolved.details) {
611
- this.getCoordinator().getAggregator().updateAgentPerformance(detail.agentName, resolved.decision, detail.vote, detail.vote === resolved.decision, proposal.confidence);
612
- }
613
- }
614
- }
615
- else {
616
- results.push(this.rejectNoQuorum(proposal, "agents did not vote (no quorum)"));
617
- }
618
- }
619
- }
620
- catch (error) {
621
- frameworkLogger.log("inference-cycle", "architect-governance-failed", "error", { error: String(error) });
622
- for (const proposal of proposals) {
623
- results.push(this.rejectNoQuorum(proposal, `agent invocation failed: ${error instanceof Error ? error.message : String(error)}`));
624
- }
625
- }
626
- const metrics = coordinator.getMetrics();
627
- frameworkLogger.log("inference-cycle", "governance-metrics", "info", {
628
- totalVotes: metrics.totalVotes,
629
- avgConfidence: metrics.averageConfidence.toFixed(2),
630
- strategyUsage: metrics.strategyUsage,
631
- });
632
- return results;
633
- }
634
- /**
635
- * Pure individual knowledge-skill MCP path for governance.
636
- * Used when XRAY_FORCE_MCP_GOVERNANCE=true.
637
- * Each proposal is evaluated directly by the relevant skill servers using analyze_proposal.
638
- */
639
- async governProposalsWithIndividualSkills(proposals) {
640
- const results = [];
641
- const GOVERNANCE_AGENTS = {
642
- fix: ["code-review", "security-audit", "researcher"],
643
- refactor: ["code-review", "security-audit", "researcher"],
644
- guard: ["code-review", "security-audit", "researcher"],
645
- automate: ["code-review", "security-audit", "researcher"],
646
- codify: ["code-review", "security-audit", "researcher"],
647
- };
648
- for (const proposal of proposals) {
649
- const agents = GOVERNANCE_AGENTS[proposal.type] ?? ["code-review", "security-audit"];
650
- const skillVotes = [];
651
- for (const agent of agents) {
652
- try {
653
- const skillResult = await mcpClientManager.callServerTool(agent, "analyze_proposal", {
654
- proposalTitle: proposal.title,
655
- proposalDescription: proposal.description,
656
- evidence: proposal.evidence,
657
- proposalType: proposal.type,
658
- });
659
- let structured = "";
660
- const contents = skillResult?.content || [];
661
- for (const c of contents) {
662
- if (c?.text && c.text.includes("DECISION:")) {
663
- structured = c.text.trim();
664
- break;
665
- }
666
- }
667
- if (!structured) {
668
- const full = JSON.stringify(skillResult);
669
- const m = full.match(/DECISION:\s*(approve|reject|abstain)[\s\S]{0,300}?REASONING:[^\n"]*/i);
670
- if (m)
671
- structured = m[0].trim();
672
- }
673
- skillVotes.push({
674
- agent,
675
- toolUsed: "analyze_proposal",
676
- rawResponse: structured || JSON.stringify(skillResult),
677
- structuredVote: structured || null,
678
- });
679
- }
680
- catch (err) {
681
- skillVotes.push({
682
- agent,
683
- toolUsed: "analyze_proposal",
684
- rawResponse: `error: ${err}`,
685
- structuredVote: null,
686
- });
687
- }
688
- }
689
- const approves = skillVotes.filter((v) => v.structuredVote && v.structuredVote.includes("DECISION: approve")).length;
690
- const rejects = skillVotes.filter((v) => v.structuredVote && v.structuredVote.includes("DECISION: reject")).length;
691
- const decision = approves > rejects ? "approve" : (rejects > approves ? "reject" : "abstain");
692
- let avgConf = 0.75;
693
- const confMatches = skillVotes.map((v) => {
694
- if (!v.structuredVote)
695
- return 0.75;
696
- const m = v.structuredVote.match(/CONFIDENCE:\s*([0-9.]+)/);
697
- return m ? parseFloat(m[1]) : 0.75;
698
- });
699
- if (confMatches.length > 0)
700
- avgConf = confMatches.reduce((a, b) => a + b, 0) / confMatches.length;
701
- results.push({
702
- proposalId: proposal.id,
703
- decision: decision,
704
- confidence: Math.round(avgConf * 100) / 100,
705
- details: skillVotes.map((v) => `${v.agent}: ${v.structuredVote?.split('\n')[0] || 'no structured vote'}`),
706
- });
707
- }
708
- return results;
709
- }
710
- /**
711
- * Merge internal and external governance votes.
712
- * A proposal passes both oscillators — must be approved by internal AND external.
713
- */
714
- mergeGovernanceVotes(internalVotes, externalVotes, proposals) {
715
- const merged = [];
716
- for (const proposal of proposals) {
717
- const internal = internalVotes.find((v) => v.proposalId === proposal.id);
718
- const external = externalVotes.find((v) => v.proposalId === proposal.id);
719
- if (!internal) {
720
- merged.push(this.rejectNoQuorum(proposal, "internal governance vote missing"));
721
- continue;
722
- }
723
- const internalApproved = internal.decision === "approve";
724
- const externalApproved = external?.decision === "approve";
725
- const bothApproved = internalApproved && (!external || externalApproved);
726
- merged.push({
727
- proposalId: proposal.id,
728
- decision: bothApproved ? "approve" : "reject",
729
- confidence: internal.confidence * (external ? external.confidence : 1.0),
730
- details: [
731
- ...internal.details,
732
- ...(external ? [`External governance: ${external.decision} (conf: ${external.confidence.toFixed(2)})`, ...external.details] : []),
733
- ],
734
- });
735
- }
736
- return merged;
737
- }
738
- // Removed: buildOrchestratorGovernancePrompt (replaced by inline TODO prompt in governProposals)
739
- /**
740
- * Govern proposals using external chrono-warp-drive Dynamo endpoint
741
- */
742
- async governProposalsExternal(proposals) {
743
- const governanceIntegration = getGovernanceIntegration();
744
- if (!governanceIntegration) {
745
- throw new Error("Governance integration not available");
746
- }
747
- // Build agent reviews from proposal evidence
748
- const agentReviews = proposals.flatMap((p) => p.evidence.slice(0, 2).map((e) => `[${p.type}] ${e}`));
749
- try {
750
- const batchResult = await governanceIntegration.checkProposals(proposals, agentReviews, []);
751
- const votes = batchResult.results.map((result) => ({
752
- proposalId: result.governanceResponse.proposalId,
753
- decision: result.vote.toLowerCase() === "yes" ? "approve" : "reject",
754
- confidence: result.governanceResponse.confidence,
755
- details: [
756
- `Governance: ${result.governanceResponse.recommendation}`,
757
- `Isotope: ${result.governanceResponse.governanceIsotopeId}`,
758
- ...result.governanceResponse.reasons.slice(0, 2),
759
- ],
760
- }));
761
- frameworkLogger.log("inference-cycle", "external-governance-complete", "info", {
762
- proposalCount: proposals.length,
763
- passedCount: batchResult.results.filter((r) => r.passed).length,
764
- });
765
- return votes;
766
- }
767
- catch (error) {
768
- frameworkLogger.log("inference-cycle", "external-governance-failed", "error", {
769
- error: error instanceof Error ? error.message : String(error),
770
- });
771
- return proposals.map((p) => this.rejectNoQuorum(p, "external governance endpoint failed"));
772
- }
773
- }
774
596
  async invokeAgentInternal(agentName, prompt) {
775
597
  frameworkLogger.log("inference-cycle", "invoke-agent-internal", "info", {
776
598
  agentName,
@@ -921,13 +743,15 @@ Respond with EXACTLY one of:
921
743
  if (!fs.existsSync(this.stateDir)) {
922
744
  fs.mkdirSync(this.stateDir, { recursive: true });
923
745
  }
924
- const stateFile = path.join(this.stateDir, "governance-state.json");
746
+ const statePath = path.join(this.stateDir, CONSOLIDATED_STATE_FILE);
925
747
  const stateManager = new XrayStateManager();
926
- if (fs.existsSync(stateFile)) {
748
+ if (fs.existsSync(statePath)) {
927
749
  try {
928
- const data = JSON.parse(fs.readFileSync(stateFile, "utf-8"));
929
- for (const [key, value] of Object.entries(data)) {
930
- stateManager.set(key, value);
750
+ const data = JSON.parse(fs.readFileSync(statePath, "utf-8"));
751
+ if (data.governanceState) {
752
+ for (const [key, value] of Object.entries(data.governanceState)) {
753
+ stateManager.set(key, value);
754
+ }
931
755
  }
932
756
  }
933
757
  catch {
@@ -936,26 +760,6 @@ Respond with EXACTLY one of:
936
760
  }
937
761
  return stateManager;
938
762
  }
939
- saveGovernanceState(coordinator) {
940
- const stateFile = path.join(this.stateDir, "governance-state.json");
941
- try {
942
- // Export the coordinator's internal state (voting history, metrics, etc.)
943
- const history = coordinator.getVotingHistory();
944
- const metrics = coordinator.getMetrics();
945
- const exportData = {
946
- votingHistory: history,
947
- metrics,
948
- exportedAt: new Date().toISOString(),
949
- };
950
- if (!fs.existsSync(this.stateDir)) {
951
- fs.mkdirSync(this.stateDir, { recursive: true });
952
- }
953
- fs.writeFileSync(stateFile, JSON.stringify(exportData, null, 2));
954
- }
955
- catch (error) {
956
- frameworkLogger.log("inference-cycle", "governance-state-save-failed", "warning", { error: String(error) });
957
- }
958
- }
959
763
  extractTextFromNdjson(output) {
960
764
  const texts = [];
961
765
  for (const line of output.split("\n")) {
@@ -975,26 +779,9 @@ Respond with EXACTLY one of:
975
779
  return texts.join("\n").trim();
976
780
  }
977
781
  resolveOpencodeRoot() {
978
- // Use the provider-agnostic config path resolver (prefers .xray/, falls back to .opencode/xray/)
782
+ // Use the provider-agnostic config path resolver (prefers .xray/ over legacy .opencode)
979
783
  const configDir = getConfigDir(this.projectRoot);
980
- // If we resolved to a .xray or custom dir, use its parent as the "root"
981
- if (configDir.includes(".xray") || configDir.includes("xray")) {
982
- return path.dirname(configDir);
983
- }
984
- // Legacy fallback
985
- let dir = this.projectRoot;
986
- for (let i = 0; i < 10; i++) {
987
- if (fs.existsSync(path.join(dir, ".opencode")))
988
- return dir;
989
- const parent = path.dirname(dir);
990
- if (parent === dir)
991
- break;
992
- dir = parent;
993
- }
994
- const cwd = process.cwd();
995
- if (fs.existsSync(path.join(cwd, ".opencode")))
996
- return cwd;
997
- return this.projectRoot;
784
+ return path.dirname(configDir);
998
785
  }
999
786
  rejectNoQuorum(proposal, reason) {
1000
787
  return {
@@ -1062,37 +849,35 @@ Respond with EXACTLY one of:
1062
849
  if (!fs.existsSync(this.stateDir)) {
1063
850
  fs.mkdirSync(this.stateDir, { recursive: true });
1064
851
  }
1065
- fs.writeFileSync(path.join(this.stateDir, CYCLE_STATE_FILE), JSON.stringify({
852
+ const statePath = path.join(this.stateDir, CONSOLIDATED_STATE_FILE);
853
+ const existing = fs.existsSync(statePath) ? JSON.parse(fs.readFileSync(statePath, "utf-8")) : {};
854
+ existing.cycleState = {
1066
855
  cycleId,
1067
856
  completedAt: new Date().toISOString(),
1068
857
  phase: this.phase,
1069
- }));
858
+ };
859
+ fs.writeFileSync(statePath, JSON.stringify(existing, null, 2));
1070
860
  }
1071
861
  appendHistory(result) {
1072
862
  if (!fs.existsSync(this.stateDir)) {
1073
863
  fs.mkdirSync(this.stateDir, { recursive: true });
1074
864
  }
1075
- const historyPath = path.join(this.stateDir, CYCLE_HISTORY_FILE);
1076
- let history = [];
1077
- if (fs.existsSync(historyPath)) {
1078
- try {
1079
- history = JSON.parse(fs.readFileSync(historyPath, "utf-8"));
1080
- }
1081
- catch {
1082
- history = [];
1083
- }
1084
- }
865
+ const statePath = path.join(this.stateDir, CONSOLIDATED_STATE_FILE);
866
+ const existing = fs.existsSync(statePath) ? JSON.parse(fs.readFileSync(statePath, "utf-8")) : {};
867
+ let history = existing.history || [];
1085
868
  history.push(result);
1086
869
  if (history.length > 50)
1087
870
  history = history.slice(-50);
1088
- fs.writeFileSync(historyPath, JSON.stringify(history, null, 2));
871
+ existing.history = history;
872
+ fs.writeFileSync(statePath, JSON.stringify(existing, null, 2));
1089
873
  }
1090
874
  loadHistory() {
1091
- const historyPath = path.join(this.stateDir, CYCLE_HISTORY_FILE);
1092
- if (!fs.existsSync(historyPath))
875
+ const statePath = path.join(this.stateDir, CONSOLIDATED_STATE_FILE);
876
+ if (!fs.existsSync(statePath))
1093
877
  return [];
1094
878
  try {
1095
- return JSON.parse(fs.readFileSync(historyPath, "utf-8"));
879
+ const data = JSON.parse(fs.readFileSync(statePath, "utf-8"));
880
+ return data.history || [];
1096
881
  }
1097
882
  catch {
1098
883
  return [];
@@ -9,4 +9,3 @@
9
9
  export * from "./types.js";
10
10
  export * from "./Integration.js";
11
11
  export * from "./registry.js";
12
- export * from "./ExampleIntegration.js";
@@ -12,5 +12,3 @@ export * from "./types.js";
12
12
  export * from "./Integration.js";
13
13
  // Re-export registry
14
14
  export * from "./registry.js";
15
- // Re-export example (for documentation/testing)
16
- export * from "./ExampleIntegration.js";
@@ -16,7 +16,7 @@ function findGovernanceCore() {
16
16
  const here = path.dirname(new URL(import.meta.url).pathname);
17
17
 
18
18
  // Priority: explicit dev root
19
- const devRoot = ;
19
+ const devRoot = process.env.XRAY_DEV_ROOT || '';
20
20
  if (devRoot) {
21
21
  const devCandidate = path.resolve(devRoot, 'dist/governance/governance-core.js');
22
22
  if (fs.existsSync(devCandidate)) return devCandidate;
@@ -92,23 +92,9 @@ async function main() {
92
92
  let govDetails = null;
93
93
 
94
94
  if (corePath) {
95
- try {
96
- const core = await import(`file://${corePath}`);
97
- if (typeof core.applyDecisionMatrix === 'function') {
98
- const result = core.applyDecisionMatrix({
99
- resonance,
100
- isotopicRatio: resonance > 0.8 ? 0.96 : 0.7,
101
- vortexVolume: 1_000_000,
102
- historicalCoherence: 0.82,
103
- solarActivity: 'active',
104
- });
105
- govDetails = result;
106
- recommendation = result.recommendation || 'NEEDS_REVISION';
107
- log(`Solar decision: ${recommendation} (resonance=${resonance.toFixed(2)})`);
108
- }
109
- } catch (e) {
110
- log(`Governance core error: ${e.message}`);
111
- }
95
+ // Governance core no longer exposes the legacy PHI/TAU matrix (purged in v3).
96
+ // Resonance is still derived locally for logging/decision notes.
97
+ log(`Using local resonance derivation (core matrix purged)`);
112
98
  } else {
113
99
  log('Governance core not located — using safe default');
114
100
  }
@@ -42,6 +42,15 @@ import { homedir } from "os";
42
42
 
43
43
  const __dirname = dirname(fileURLToPath(import.meta.url));
44
44
 
45
+ // Redirect console methods to stderr so only the final JSON result goes to stdout.
46
+ // Any dynamically loaded module using console.log/info/debug/warn will then
47
+ // write diagnostic output to stderr, keeping stdout clean for JSON.parse.
48
+ const _stderrWrite = process.stderr.write.bind(process.stderr);
49
+ console.log = (...args) => { _stderrWrite(args.join(' ') + '\n'); };
50
+ console.info = (...args) => { _stderrWrite('[INFO] ' + args.join(' ') + '\n'); };
51
+ console.debug = (...args) => { _stderrWrite('[DEBUG] ' + args.join(' ') + '\n'); };
52
+ console.warn = (...args) => { _stderrWrite('[WARN] ' + args.join(' ') + '\n'); };
53
+
45
54
  // ── Framework components (lazy-loaded) ───────────────────────
46
55
  let ProcessorManager = null;
47
56
  let StrRayStateManager = null;
@@ -160,7 +160,7 @@ export class ServerConfigRegistry {
160
160
  this.register({
161
161
  serverName: 'orchestrator',
162
162
  command: 'node',
163
- args: [`${basePath}/orchestrator.server.js`],
163
+ args: [`${basePath}/orchestrator/server.js`],
164
164
  timeout: 60000,
165
165
  });
166
166
  // Estimation Validator Server