0xray 4.0.36 → 4.0.37

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 (169) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.xray/features.json +1 -1
  3. package/dist/CHANGELOG.md +15 -0
  4. package/dist/analytics/emerging-pattern-detector.d.ts +12 -1
  5. package/dist/analytics/emerging-pattern-detector.js +37 -12
  6. package/dist/analytics/pattern-learning-engine.js +1 -9
  7. package/dist/analytics/predictive-analytics.js +51 -33
  8. package/dist/analytics/prompt-pattern-analyzer.d.ts +1 -0
  9. package/dist/analytics/prompt-pattern-analyzer.js +39 -20
  10. package/dist/analytics/routing-performance-analyzer.d.ts +2 -0
  11. package/dist/analytics/routing-performance-analyzer.js +89 -37
  12. package/dist/analytics/simple-pattern-analyzer.d.ts +4 -0
  13. package/dist/analytics/simple-pattern-analyzer.js +66 -28
  14. package/dist/architect/architect-tools.d.ts +3 -0
  15. package/dist/architect/architect-tools.js +22 -0
  16. package/dist/cli/commands/grok-install.js +1 -1
  17. package/dist/cli/commands/hermes-install.js +11 -5
  18. package/dist/cli/commands/openclaw-install.js +13 -7
  19. package/dist/cli/commands/opencode-install.js +7 -4
  20. package/dist/cli/commands/suit-monitor.d.ts +30 -0
  21. package/dist/cli/commands/suit-monitor.js +128 -0
  22. package/dist/cli/index.js +52 -15
  23. package/dist/cli/suit-pulse.d.ts +29 -0
  24. package/dist/cli/suit-pulse.js +270 -0
  25. package/dist/delegation/agent-delegator.d.ts +4 -2
  26. package/dist/delegation/agent-delegator.js +46 -27
  27. package/dist/delegation/agent-expertise.js +2 -1
  28. package/dist/delegation/analytics/outcome-tracker.d.ts +6 -0
  29. package/dist/delegation/analytics/outcome-tracker.js +17 -3
  30. package/dist/delegation/ast-code-parser.d.ts +5 -0
  31. package/dist/delegation/ast-code-parser.js +53 -48
  32. package/dist/delegation/codebase-context-analyzer.d.ts +3 -7
  33. package/dist/delegation/codebase-context-analyzer.js +188 -159
  34. package/dist/delegation/session-coordinator.js +3 -2
  35. package/dist/enforcement/loaders/codex-loader.js +18 -14
  36. package/dist/enforcement/validators/architecture-validators.js +115 -9
  37. package/dist/governance/codex-policy.service.d.ts +12 -2
  38. package/dist/governance/codex-policy.service.js +91 -16
  39. package/dist/integrations/grok/hooks/session-start.js +6 -6
  40. package/dist/integrations/hooks/goggles-pipeline.mjs +169 -28
  41. package/dist/integrations/hooks/goggles-planes.json +172 -8
  42. package/dist/integrations/hooks/plates.cjs +138 -0
  43. package/dist/integrations/hooks/station-hook-runtime.cjs +63 -5
  44. package/dist/integrations/hooks/write-home.cjs +59 -0
  45. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  46. package/dist/mcps/architect-tools.server.d.ts +6 -0
  47. package/dist/mcps/architect-tools.server.js +19 -18
  48. package/dist/mcps/orchestrator/server.d.ts +4 -3
  49. package/dist/mcps/orchestrator/server.js +29 -17
  50. package/dist/memory-routing/lookup-cache.d.ts +8 -0
  51. package/dist/memory-routing/lookup-cache.js +72 -0
  52. package/dist/memory-routing/plates.d.ts +1 -1
  53. package/dist/memory-routing/plates.js +26 -0
  54. package/dist/memory-routing/provider-loader.js +3 -0
  55. package/dist/metrics/agent-metrics.d.ts +14 -5
  56. package/dist/metrics/agent-metrics.js +362 -224
  57. package/dist/nucleus/synthesis-consult-receipt.js +38 -16
  58. package/dist/orchestrator/enhanced-multi-agent-orchestrator.d.ts +5 -0
  59. package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +9 -0
  60. package/dist/orchestrator/multi-agent-orchestration-coordinator.js +1 -2
  61. package/dist/orchestrator/orchestrator.js +1 -2
  62. package/dist/processors/implementations/agents-md-validation-processor.d.ts +0 -1
  63. package/dist/processors/implementations/agents-md-validation-processor.js +0 -11
  64. package/dist/processors/implementations/console-log-guard-processor.js +39 -50
  65. package/dist/processors/implementations/performance-budget-processor.d.ts +0 -5
  66. package/dist/processors/implementations/performance-budget-processor.js +29 -38
  67. package/dist/processors/implementations/storytelling-trigger-processor.d.ts +5 -0
  68. package/dist/processors/implementations/storytelling-trigger-processor.js +69 -16
  69. package/dist/processors/implementations/test-auto-creation-processor.js +39 -36
  70. package/dist/reporting/framework-reporting-system.d.ts +3 -0
  71. package/dist/reporting/framework-reporting-system.js +61 -8
  72. package/dist/reporting/log-parser.js +188 -105
  73. package/dist/reporting/metrics.js +42 -18
  74. package/dist/security/prompt-security-validator.js +8 -7
  75. package/dist/security/security-auditor.d.ts +4 -0
  76. package/dist/security/security-auditor.js +132 -57
  77. package/dist/security/security-hardener.d.ts +2 -0
  78. package/dist/security/security-hardener.js +31 -6
  79. package/dist/security/security-headers.d.ts +2 -0
  80. package/dist/security/security-headers.js +23 -21
  81. package/dist/security/security-scanner.js +18 -4
  82. package/dist/session/session-cleanup-manager.d.ts +2 -0
  83. package/dist/session/session-cleanup-manager.js +29 -8
  84. package/dist/session/session-monitor.d.ts +14 -4
  85. package/dist/session/session-monitor.js +208 -106
  86. package/dist/session/session-state-manager.d.ts +11 -0
  87. package/dist/session/session-state-manager.js +90 -8
  88. package/docs-site/docs/plates/activity-log.md +38 -0
  89. package/docs-site/docs/plates/cursor-compact.md +35 -0
  90. package/docs-site/docs/plates/grok-compact.md +35 -0
  91. package/docs-site/docs/plates/index.md +25 -3
  92. package/docs-site/docs/plates/inference-files.md +35 -0
  93. package/docs-site/docs/plates/kept-line.md +35 -0
  94. package/docs-site/docs/plates/lens-gate.md +35 -0
  95. package/docs-site/docs/plates/lens-page.md +35 -0
  96. package/docs-site/docs/plates/notes-page.md +35 -0
  97. package/docs-site/docs/plates/package-face.md +35 -0
  98. package/docs-site/docs/plates/payload-heat.md +35 -0
  99. package/docs-site/docs/plates/pickup-stamp.md +35 -0
  100. package/docs-site/docs/plates/pre-tool.md +35 -0
  101. package/docs-site/docs/plates/record-map.md +41 -0
  102. package/docs-site/docs/plates/reflection-page.md +35 -0
  103. package/docs-site/docs/plates/review.md +57 -0
  104. package/docs-site/docs/plates/session-capture.md +38 -0
  105. package/docs-site/docs/plates/site-manual.md +35 -0
  106. package/docs-site/docs/plates/stamp-plate.md +35 -0
  107. package/docs-site/docs/plates/station-card.md +35 -0
  108. package/docs-site/docs/plates/station-heat.md +35 -0
  109. package/docs-site/docs/plates/suit-organs.md +38 -0
  110. package/docs-site/docs/plates/suit-settings.md +35 -0
  111. package/docs-site/docs/plates/suit-wear.md +37 -0
  112. package/docs-site/docs/plates/trail-state.md +35 -0
  113. package/docs-site/docs/plates/work-fresh.md +35 -0
  114. package/docs-site/docs/plates/write-home.md +38 -0
  115. package/package.json +3 -2
  116. package/scripts/node/install-bridges.cjs +302 -78
  117. package/scripts/node/postinstall.cjs +14 -3
  118. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  119. package/src/mcps/architect-tools.server.ts +25 -20
  120. package/src/mcps/orchestrator/server.ts +33 -19
  121. package/xray/features.json +1 -1
  122. package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +0 -1
  123. package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +0 -1
  124. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts.map +0 -1
  125. package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js.map +0 -1
  126. package/vendor/@0xray/repertoire/dist/index.d.ts.map +0 -1
  127. package/vendor/@0xray/repertoire/dist/index.js.map +0 -1
  128. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +0 -1
  129. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +0 -1
  130. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts.map +0 -1
  131. package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js.map +0 -1
  132. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts.map +0 -1
  133. package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js.map +0 -1
  134. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +0 -1
  135. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +0 -1
  136. package/vendor/@0xray/repertoire/dist/mcp/server.d.ts.map +0 -1
  137. package/vendor/@0xray/repertoire/dist/mcp/server.js.map +0 -1
  138. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts.map +0 -1
  139. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js.map +0 -1
  140. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts.map +0 -1
  141. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js.map +0 -1
  142. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +0 -1
  143. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +0 -1
  144. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts.map +0 -1
  145. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js.map +0 -1
  146. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +0 -1
  147. package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +0 -1
  148. package/vendor/@0xray/repertoire/dist/paths.d.ts.map +0 -1
  149. package/vendor/@0xray/repertoire/dist/paths.js.map +0 -1
  150. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +0 -1
  151. package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +0 -1
  152. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +0 -1
  153. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +0 -1
  154. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +0 -1
  155. package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +0 -1
  156. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.d.ts.map +0 -1
  157. package/vendor/@0xray/repertoire/dist/registry/confidence-decay.js.map +0 -1
  158. package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts.map +0 -1
  159. package/vendor/@0xray/repertoire/dist/registry/signal-prune.js.map +0 -1
  160. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts.map +0 -1
  161. package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js.map +0 -1
  162. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +0 -1
  163. package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +0 -1
  164. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts.map +0 -1
  165. package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js.map +0 -1
  166. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts.map +0 -1
  167. package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js.map +0 -1
  168. package/vendor/@0xray/repertoire/dist/types.d.ts.map +0 -1
  169. package/vendor/@0xray/repertoire/dist/types.js.map +0 -1
@@ -50,16 +50,22 @@ export class SimplePatternAnalyzer {
50
50
  // Fall back to activity log parsing if no outcomes
51
51
  if (entries.length === 0 && fs.existsSync(this.logPath)) {
52
52
  const content = fs.readFileSync(this.logPath, "utf-8");
53
- const lines = content.split("\n").filter((l) => l.trim());
54
- // Filter to task completion entries
55
- const completionLines = lines.filter((line) => line.includes("complex-task-completed") ||
56
- line.includes("job-completed") ||
57
- line.includes("task-completed"));
53
+ const completionLines = [];
54
+ for (const line of content.split("\n")) {
55
+ if (!line.trim())
56
+ continue;
57
+ if (line.includes("complex-task-completed") ||
58
+ line.includes("job-completed") ||
59
+ line.includes("task-completed")) {
60
+ completionLines.push(line);
61
+ }
62
+ }
58
63
  const entriesToAnalyze = limit ? completionLines.slice(-limit) : completionLines;
59
- const parsedEntries = entriesToAnalyze
60
- .map((line) => this.parseLine(line))
61
- .filter((e) => e !== null);
62
- entries.push(...parsedEntries);
64
+ for (const line of entriesToAnalyze) {
65
+ const parsed = this.parseLine(line);
66
+ if (parsed)
67
+ entries.push(parsed);
68
+ }
63
69
  }
64
70
  if (entries.length === 0) {
65
71
  return this.emptyInsights();
@@ -189,32 +195,64 @@ export class SimplePatternAnalyzer {
189
195
  }
190
196
  }
191
197
  }
192
- // Calculate success rates
193
- for (const [agent, stats] of agentStats) {
194
- if (stats.attempts > 0) {
195
- // We'll calculate in the output
196
- }
198
+ let attempts = 0;
199
+ let successes = 0;
200
+ for (const stats of agentStats.values()) {
201
+ attempts += stats.attempts;
202
+ successes += stats.successes;
197
203
  }
198
- for (const [taskType, stats] of taskTypeStats) {
199
- const agentStatsForTask = Array.from(agentStats.values()).reduce((acc, s) => ({
200
- attempts: acc.attempts + s.attempts,
201
- successes: acc.successes + s.successes,
202
- }), { attempts: 0, successes: 0 });
203
- stats.successRate =
204
- agentStatsForTask.attempts > 0
205
- ? (agentStatsForTask.successes / agentStatsForTask.attempts) * 100
206
- : 0;
204
+ const successRate = attempts > 0 ? (successes / attempts) * 100 : 0;
205
+ for (const stats of taskTypeStats.values()) {
206
+ stats.successRate = successRate;
207
207
  }
208
- const sortedEntries = [...entries].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
209
208
  return {
210
209
  agentStats,
211
210
  taskTypeStats,
212
211
  complexityStats,
213
212
  totalEntries: entries.length,
214
- dateRange: {
215
- start: sortedEntries[0]?.timestamp || "",
216
- end: sortedEntries[sortedEntries.length - 1]?.timestamp || "",
217
- },
213
+ dateRange: this.entryDateRange(entries),
214
+ };
215
+ }
216
+ /**
217
+ * Earliest and latest timestamp. Matches a stable sort on finite times.
218
+ */
219
+ entryDateRange(entries) {
220
+ if (entries.length === 0)
221
+ return { start: "", end: "" };
222
+ const first = entries[0];
223
+ if (!first)
224
+ return { start: "", end: "" };
225
+ let start = first.timestamp;
226
+ let end = start;
227
+ let startTime = new Date(start).getTime();
228
+ let endTime = startTime;
229
+ if (!Number.isNaN(startTime)) {
230
+ let finite = true;
231
+ for (let i = 1; i < entries.length; i++) {
232
+ const entry = entries[i];
233
+ if (!entry)
234
+ continue;
235
+ const time = new Date(entry.timestamp).getTime();
236
+ if (Number.isNaN(time)) {
237
+ finite = false;
238
+ break;
239
+ }
240
+ if (time < startTime) {
241
+ startTime = time;
242
+ start = entry.timestamp;
243
+ }
244
+ if (time >= endTime) {
245
+ endTime = time;
246
+ end = entry.timestamp;
247
+ }
248
+ }
249
+ if (finite)
250
+ return { start, end };
251
+ }
252
+ const sortedEntries = [...entries].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
253
+ return {
254
+ start: sortedEntries[0]?.timestamp || "",
255
+ end: sortedEntries[sortedEntries.length - 1]?.timestamp || "",
218
256
  };
219
257
  }
220
258
  /**
@@ -62,6 +62,9 @@ export declare function dependencyAnalysis(projectRoot: string, focusAreas?: str
62
62
  * Architecture Assessment Tool - Overall architectural health evaluation
63
63
  */
64
64
  export declare function architectureAssessment(projectRoot: string, assessmentType?: "quick" | "comprehensive"): Promise<ArchitectureAssessment>;
65
+ /** Confer text follows the assessment. A critical coupling issue is FAIL. */
66
+ export declare function conferVerdictFromAssessment(assessment: ArchitectureAssessment): "PASS" | "CONDITIONAL" | "FAIL";
67
+ export declare function formatConferArchitectureText(conferPrompt: string, assessment: ArchitectureAssessment): string;
65
68
  export declare const architectTools: {
66
69
  contextAnalysis: typeof contextAnalysis;
67
70
  codebaseStructure: typeof codebaseStructure;
@@ -189,6 +189,28 @@ export async function architectureAssessment(projectRoot, assessmentType = "comp
189
189
  });
190
190
  return result;
191
191
  }
192
+ /** Confer text follows the assessment. A critical coupling issue is FAIL. */
193
+ export function conferVerdictFromAssessment(assessment) {
194
+ const criticalIssue = assessment.issues.some((issue) => issue.type === "critical");
195
+ if (criticalIssue ||
196
+ assessment.overallHealth === "critical" ||
197
+ assessment.overallHealth === "poor") {
198
+ return "FAIL";
199
+ }
200
+ if (assessment.overallHealth === "fair" ||
201
+ assessment.issues.some((issue) => issue.type === "major")) {
202
+ return "CONDITIONAL";
203
+ }
204
+ return "PASS";
205
+ }
206
+ export function formatConferArchitectureText(conferPrompt, assessment) {
207
+ const assessmentJson = JSON.stringify(assessment, null, 2);
208
+ const prompt = conferPrompt.trim();
209
+ if (!prompt)
210
+ return assessmentJson;
211
+ const verdict = conferVerdictFromAssessment(assessment);
212
+ return `${prompt}\n\n## Architecture assessment\n${assessmentJson}\n\nVerdict: ${verdict}\nTop risks: review assessment metrics above\nHardening: address high-complexity or coupling findings before resuming`;
213
+ }
192
214
  // Helper functions
193
215
  function identifyArchitecturalPatterns(codebaseAnalysis, dependencyAnalysis) {
194
216
  const patterns = [];
@@ -3,7 +3,6 @@
3
3
  *
4
4
  * Helps users register 0xRay MCP servers with the Grok CLI.
5
5
  */
6
- import { installForGrokCLI } from '../../integrations/grok/grok-cli.js';
7
6
  export function registerGrokCommands(grokCmd) {
8
7
  grokCmd
9
8
  .command('install')
@@ -11,6 +10,7 @@ export function registerGrokCommands(grokCmd) {
11
10
  .option('--dry-run', 'Show what would be done without making changes')
12
11
  .option('--force', 'Force reinstall even if already present')
13
12
  .action(async (options) => {
13
+ const { installForGrokCLI } = await import('../../integrations/grok/grok-cli.js');
14
14
  await installForGrokCLI({ dryRun: options.dryRun, force: options.force });
15
15
  });
16
16
  }
@@ -2,14 +2,15 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { createRequire } from 'module';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { frameworkLogger } from '../../core/framework-logger.js';
6
- import { syncBuiltinSkills } from './skill-install.js';
7
- import { mintAfterWear } from './foundry-mint-wear.js';
8
5
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
6
  const require = createRequire(import.meta.url);
10
7
  const packageRoot = path.join(__dirname, '..', '..', '..');
11
- const millSuit = require(path.join(packageRoot, 'scripts', 'foundry', 'mint-suit.cjs'));
12
- const wiring = require(path.join(packageRoot, 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
8
+ function loadMillSuit() {
9
+ return require(path.join(packageRoot, 'scripts', 'foundry', 'mint-suit.cjs'));
10
+ }
11
+ function loadWiring() {
12
+ return require(path.join(packageRoot, 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
13
+ }
13
14
  export function registerHermesCommands(hermesCmd) {
14
15
  hermesCmd
15
16
  .command('install')
@@ -21,6 +22,11 @@ export function registerHermesCommands(hermesCmd) {
21
22
  });
22
23
  }
23
24
  async function installForHermes(options = {}) {
25
+ const { frameworkLogger } = await import('../../core/framework-logger.js');
26
+ const { syncBuiltinSkills } = await import('./skill-install.js');
27
+ const { mintAfterWear } = await import('./foundry-mint-wear.js');
28
+ const millSuit = loadMillSuit();
29
+ const wiring = loadWiring();
24
30
  frameworkLogger.log('hermes-integration', 'install-start', 'info', { options });
25
31
  const isolated = millSuit.isIsolatedHome();
26
32
  const targetPluginDir = isolated
@@ -2,15 +2,14 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { createRequire } from 'module';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { frameworkLogger } from '../../core/framework-logger.js';
6
- import { syncBuiltinSkills } from './skill-install.js';
7
- import { mintAfterWear } from './foundry-mint-wear.js';
8
- import { OpenClawConfigLoader } from '../../integrations/openclaw/config.js';
9
- import { writeSuitSessionBoot } from '../../nucleus/suit-temperament.js';
10
5
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
6
  const require = createRequire(import.meta.url);
12
- const millSuit = require(path.join(__dirname, '..', '..', '..', 'scripts', 'foundry', 'mint-suit.cjs'));
13
- const wiring = require(path.join(__dirname, '..', '..', '..', 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
7
+ function loadMillSuit() {
8
+ return require(path.join(__dirname, '..', '..', '..', 'scripts', 'foundry', 'mint-suit.cjs'));
9
+ }
10
+ function loadWiring() {
11
+ return require(path.join(__dirname, '..', '..', '..', 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
12
+ }
14
13
  export function registerOpenClawCommands(openclawCmd) {
15
14
  openclawCmd
16
15
  .command('install')
@@ -22,6 +21,13 @@ export function registerOpenClawCommands(openclawCmd) {
22
21
  });
23
22
  }
24
23
  async function installForOpenClaw(options = {}) {
24
+ const { frameworkLogger } = await import('../../core/framework-logger.js');
25
+ const { syncBuiltinSkills } = await import('./skill-install.js');
26
+ const { mintAfterWear } = await import('./foundry-mint-wear.js');
27
+ const { OpenClawConfigLoader } = await import('../../integrations/openclaw/config.js');
28
+ const { writeSuitSessionBoot } = await import('../../nucleus/suit-temperament.js');
29
+ const millSuit = loadMillSuit();
30
+ const wiring = loadWiring();
25
31
  frameworkLogger.log('openclaw-integration', 'install-start', 'info', { options });
26
32
  const configPath = path.join(process.cwd(), '.xray', 'config', 'openclaw.json');
27
33
  if (options.dryRun) {
@@ -2,12 +2,11 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { createRequire } from 'module';
4
4
  import { fileURLToPath } from 'node:url';
5
- import { frameworkLogger } from '../../core/framework-logger.js';
6
- import { syncBuiltinSkills } from './skill-install.js';
7
- import { mintAfterWear, wantsCostume } from './foundry-mint-wear.js';
8
5
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
6
  const require = createRequire(import.meta.url);
10
- const wiring = require(path.join(__dirname, '..', '..', '..', 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
7
+ function loadWiring() {
8
+ return require(path.join(__dirname, '..', '..', '..', 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
9
+ }
11
10
  export function registerOpencodeCommands(opencodeCmd) {
12
11
  opencodeCmd
13
12
  .command('install')
@@ -74,6 +73,10 @@ function copyDir(src, dest, relPath = "") {
74
73
  }
75
74
  }
76
75
  async function installForOpencode(options = {}) {
76
+ const { frameworkLogger } = await import('../../core/framework-logger.js');
77
+ const { syncBuiltinSkills } = await import('./skill-install.js');
78
+ const { mintAfterWear, wantsCostume } = await import('./foundry-mint-wear.js');
79
+ const wiring = loadWiring();
77
80
  frameworkLogger.log('opencode-integration', 'install-start', 'info', { options });
78
81
  const opencodeSource = path.join(__dirname, '..', '..', '..', '.opencode');
79
82
  const opencodeDest = path.join(process.cwd(), '.opencode');
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Current picture of the worn suit.
3
+ *
4
+ * Inventory, already on disk, not a second store:
5
+ * - logs/framework/activity.log — activity-logger.ts and grok-hook-activity appendHookActivity
6
+ * - inference state — InferenceStateManager.load() from vendored @0xray/repertoire
7
+ * (.xray/state/repertoire/inference-state.json)
8
+ * - repertoire version — that organ's package.json
9
+ * - worn 0xray version — package.json beside this CLI
10
+ * - 0xray report stays the health report; scripts/mjs/goggles-observer.mjs stays the lens check
11
+ */
12
+ export type SuitSources = {
13
+ activityLogPath: string;
14
+ inferenceStatePath: string;
15
+ repertoirePackageJson: string | null;
16
+ xrayPackageJson: string;
17
+ tail?: number;
18
+ };
19
+ export type SuitPicture = {
20
+ activityLines: string[];
21
+ inferenceStatePresent: boolean;
22
+ inferenceLastRun: string | null;
23
+ repertoireVersion: string | null;
24
+ xrayVersion: string | null;
25
+ };
26
+ export declare function resolveRepertoirePackageJson(cwd: string): string | null;
27
+ export declare function defaultSuitSources(cwd: string, xrayPackageJson: string): SuitSources;
28
+ export declare function readSuitPicture(sources: SuitSources): Promise<SuitPicture>;
29
+ export declare function formatSuitPicture(picture: SuitPicture): string;
30
+ export declare function printSuitMonitor(cwd: string, packageRoot: string, lines?: number): Promise<void>;
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Current picture of the worn suit.
3
+ *
4
+ * Inventory, already on disk, not a second store:
5
+ * - logs/framework/activity.log — activity-logger.ts and grok-hook-activity appendHookActivity
6
+ * - inference state — InferenceStateManager.load() from vendored @0xray/repertoire
7
+ * (.xray/state/repertoire/inference-state.json)
8
+ * - repertoire version — that organ's package.json
9
+ * - worn 0xray version — package.json beside this CLI
10
+ * - 0xray report stays the health report; scripts/mjs/goggles-observer.mjs stays the lens check
11
+ */
12
+ import { existsSync, readFileSync } from "node:fs";
13
+ import { pathToFileURL } from "node:url";
14
+ import { dirname, join, resolve } from "node:path";
15
+ const REPERTOIRE_PACKAGE_CANDIDATES = [
16
+ "node_modules/@0xray/repertoire/package.json",
17
+ "vendor/@0xray/repertoire/package.json",
18
+ "node_modules/0xray/vendor/@0xray/repertoire/package.json",
19
+ ];
20
+ function isRecord(value) {
21
+ return typeof value === "object" && value !== null;
22
+ }
23
+ function isConstructor(value) {
24
+ return typeof value === "function";
25
+ }
26
+ export function resolveRepertoirePackageJson(cwd) {
27
+ for (const rel of REPERTOIRE_PACKAGE_CANDIDATES) {
28
+ const abs = resolve(cwd, rel);
29
+ if (existsSync(abs))
30
+ return abs;
31
+ }
32
+ return null;
33
+ }
34
+ export function defaultSuitSources(cwd, xrayPackageJson) {
35
+ return {
36
+ activityLogPath: join(cwd, "logs", "framework", "activity.log"),
37
+ inferenceStatePath: join(cwd, ".xray", "state", "repertoire", "inference-state.json"),
38
+ repertoirePackageJson: resolveRepertoirePackageJson(cwd),
39
+ xrayPackageJson,
40
+ };
41
+ }
42
+ function readPackageVersion(packageJsonPath) {
43
+ try {
44
+ const raw = JSON.parse(readFileSync(packageJsonPath, "utf8"));
45
+ if (!isRecord(raw) || typeof raw.version !== "string")
46
+ return null;
47
+ return raw.version;
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ function readLastActivityLines(logPath, tail) {
54
+ if (!existsSync(logPath) || tail <= 0)
55
+ return [];
56
+ try {
57
+ const lines = readFileSync(logPath, "utf8")
58
+ .split(/\r?\n/)
59
+ .filter((line) => line.length > 0);
60
+ return lines.slice(-tail);
61
+ }
62
+ catch {
63
+ return [];
64
+ }
65
+ }
66
+ function inferenceModuleFromPackage(packageJsonPath) {
67
+ const modulePath = join(dirname(packageJsonPath), "dist", "registry", "InferenceStateManager.js");
68
+ return existsSync(modulePath) ? modulePath : null;
69
+ }
70
+ /** Reuse the organ's read. A missing file stays absent; load() is not a second parser. */
71
+ async function loadLastRun(modulePath, filePath) {
72
+ try {
73
+ const loaded = await import(pathToFileURL(modulePath).href);
74
+ if (!isRecord(loaded) || !isConstructor(loaded.InferenceStateManager))
75
+ return null;
76
+ const instance = new loaded.InferenceStateManager(filePath);
77
+ if (!isRecord(instance) || typeof instance.load !== "function")
78
+ return null;
79
+ const state = instance.load();
80
+ if (!isRecord(state) || typeof state.lastRun !== "string")
81
+ return null;
82
+ return state.lastRun;
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ export async function readSuitPicture(sources) {
89
+ const tail = sources.tail ?? 8;
90
+ const modulePath = sources.repertoirePackageJson
91
+ ? inferenceModuleFromPackage(sources.repertoirePackageJson)
92
+ : null;
93
+ const inferenceStatePresent = existsSync(sources.inferenceStatePath);
94
+ const inferenceLastRun = inferenceStatePresent && modulePath
95
+ ? await loadLastRun(modulePath, sources.inferenceStatePath)
96
+ : null;
97
+ return {
98
+ activityLines: readLastActivityLines(sources.activityLogPath, tail),
99
+ inferenceStatePresent,
100
+ inferenceLastRun,
101
+ repertoireVersion: sources.repertoirePackageJson
102
+ ? readPackageVersion(sources.repertoirePackageJson)
103
+ : null,
104
+ xrayVersion: readPackageVersion(sources.xrayPackageJson),
105
+ };
106
+ }
107
+ export function formatSuitPicture(picture) {
108
+ const inference = picture.inferenceStatePresent
109
+ ? `present${picture.inferenceLastRun ? ` lastRun ${picture.inferenceLastRun}` : ""}`
110
+ : "absent";
111
+ const activity = picture.activityLines.length > 0
112
+ ? picture.activityLines.map((line) => ` ${line}`).join("\n")
113
+ : " (none)";
114
+ return [
115
+ "suit monitor",
116
+ `xray: ${picture.xrayVersion ?? "missing"}`,
117
+ `repertoire: ${picture.repertoireVersion ?? "missing"}`,
118
+ `inference state: ${inference}`,
119
+ "activity:",
120
+ activity,
121
+ ].join("\n");
122
+ }
123
+ export async function printSuitMonitor(cwd, packageRoot, lines = 8) {
124
+ const sources = defaultSuitSources(cwd, join(packageRoot, "package.json"));
125
+ sources.tail = lines;
126
+ const picture = await readSuitPicture(sources);
127
+ process.stdout.write(`${formatSuitPicture(picture)}\n`);
128
+ }
package/dist/cli/index.js CHANGED
@@ -9,9 +9,10 @@ import { execSync, spawn, spawnSync } from "child_process";
9
9
  import { join, resolve } from "path";
10
10
  import { fileURLToPath } from "node:url";
11
11
  import { readFileSync, existsSync } from "fs";
12
- import { getConfigDir } from "../core/config-paths.js";
13
- import { frameworkLogger } from "../core/framework-logger.js";
14
- import { inferenceRunMayEnter } from "../inference/inference-run-gate.js";
12
+ async function loadFrameworkLogger() {
13
+ const { frameworkLogger } = await import("../core/framework-logger.js");
14
+ return frameworkLogger;
15
+ }
15
16
  // Get package root relative to this script location
16
17
  const packageRoot = resolve(fileURLToPath(new URL("../..", import.meta.url)));
17
18
  // Read version dynamically from package.json
@@ -54,7 +55,8 @@ function runNodeScript(scriptName, args = []) {
54
55
  program
55
56
  .command("install")
56
57
  .description("Install xray framework in the current project")
57
- .action(() => {
58
+ .action(async () => {
59
+ const frameworkLogger = await loadFrameworkLogger();
58
60
  frameworkLogger.log('cli', 'install', 'info', { message: 'nothing written' });
59
61
  process.stdout.write("nothing written\n");
60
62
  });
@@ -62,7 +64,7 @@ program
62
64
  .command("setup")
63
65
  .description("Set up .mcp.json and the OpenCode, Grok, Hermes, and OpenClaw bridges")
64
66
  .option("--git-hooks", "also install git hooks")
65
- .action((opts) => {
67
+ .action(async (opts) => {
66
68
  const args = ["setup"];
67
69
  if (opts.gitHooks)
68
70
  args.push("--git-hooks");
@@ -70,6 +72,7 @@ program
70
72
  runNodeScript("install-bridges.cjs", args);
71
73
  }
72
74
  catch (error) {
75
+ const frameworkLogger = await loadFrameworkLogger();
73
76
  frameworkLogger.log("cli", "setup-error", "error", {
74
77
  error: error instanceof Error ? error.message : String(error),
75
78
  });
@@ -116,11 +119,12 @@ program
116
119
  program
117
120
  .command("wear")
118
121
  .description("Wear the 0xray suit in this git checkout")
119
- .action(() => {
122
+ .action(async () => {
120
123
  try {
121
124
  runNodeScript("wear-cursor-hooks.cjs");
122
125
  }
123
126
  catch (error) {
127
+ const frameworkLogger = await loadFrameworkLogger();
124
128
  frameworkLogger.log('cli', 'wear-error', 'error', {
125
129
  error: error instanceof Error ? error.message : String(error),
126
130
  });
@@ -130,11 +134,12 @@ program
130
134
  program
131
135
  .command("unwear")
132
136
  .description("Remove the 0xray suit and restore the pre-wear hooks file")
133
- .action(() => {
137
+ .action(async () => {
134
138
  try {
135
139
  runNodeScript("unwear-cursor-hooks.cjs");
136
140
  }
137
141
  catch (error) {
142
+ const frameworkLogger = await loadFrameworkLogger();
138
143
  frameworkLogger.log('cli', 'unwear-error', 'error', {
139
144
  error: error instanceof Error ? error.message : String(error),
140
145
  });
@@ -154,6 +159,16 @@ program
154
159
  const { statusCommand } = await import("./commands/status.js");
155
160
  await statusCommand(packageRoot);
156
161
  });
162
+ program
163
+ .command("monitor")
164
+ .description("Current picture of the worn suit (activity, inference state, repertoire, version)")
165
+ .option("-n, --lines <count>", "Activity lines to show", "8")
166
+ .action(async (options) => {
167
+ const { printSuitMonitor } = await import("./commands/suit-monitor.js");
168
+ const parsed = Number(options.lines);
169
+ const lines = Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 8;
170
+ await printSuitMonitor(process.cwd(), packageRoot, lines);
171
+ });
157
172
  program
158
173
  .command("validate")
159
174
  .description("Validate consumer wear (pack paths, Cursor hooks, mill plant) — not leftover init.sh")
@@ -391,6 +406,13 @@ program
391
406
  process.exit(1);
392
407
  }
393
408
  });
409
+ program
410
+ .command("pulse")
411
+ .description("Print one line: worn CLI, repertoire, inference age, activity, lens, plant")
412
+ .action(async () => {
413
+ const { readSuitPulse } = await import("./suit-pulse.js");
414
+ process.stdout.write(`${readSuitPulse(process.cwd()).line}\n`);
415
+ });
394
416
  program
395
417
  .command("fix")
396
418
  .description("Automatically fix common framework issues by running the postinstall setup")
@@ -496,6 +518,7 @@ program
496
518
  process.stdout.write("not worn\n");
497
519
  }
498
520
  const opencodeConfigPath = path.join(cwd, "opencode.json");
521
+ const { getConfigDir } = await import("../core/config-paths.js");
499
522
  const xrayDir = getConfigDir(cwd);
500
523
  const opencodeExists = fs.existsSync(opencodeConfigPath);
501
524
  const configDirExists = fs.existsSync(xrayDir);
@@ -727,6 +750,7 @@ program
727
750
  return;
728
751
  }
729
752
  const features = featuresConfigLoader.loadConfig();
753
+ const { inferenceRunMayEnter } = await import('../inference/inference-run-gate.js');
730
754
  if (!inferenceRunMayEnter(features.inference, options.force === true)) {
731
755
  if (options.json) {
732
756
  console.log(JSON.stringify({ triggered: false, reason: 'Inference feature disabled in features.json' }));
@@ -957,22 +981,33 @@ program
957
981
  const child = spawn(process.execPath, [serverPath], { stdio: 'inherit', env });
958
982
  child.on('exit', (code) => process.exit(code ?? 0));
959
983
  });
984
+ function argvSelects(name) {
985
+ return process.argv.slice(2).includes(name);
986
+ }
960
987
  // Grok CLI integration
961
988
  const grokCmd = program.command('grok').description('Grok CLI integration commands');
962
- const { registerGrokCommands } = await import('./commands/grok-install.js');
963
- registerGrokCommands(grokCmd);
989
+ if (argvSelects('grok')) {
990
+ const { registerGrokCommands } = await import('./commands/grok-install.js');
991
+ registerGrokCommands(grokCmd);
992
+ }
964
993
  // Hermes Agent integration
965
994
  const hermesCmd = program.command('hermes').description('Hermes Agent integration commands');
966
- const { registerHermesCommands } = await import('./commands/hermes-install.js');
967
- registerHermesCommands(hermesCmd);
995
+ if (argvSelects('hermes')) {
996
+ const { registerHermesCommands } = await import('./commands/hermes-install.js');
997
+ registerHermesCommands(hermesCmd);
998
+ }
968
999
  // OpenClaw integration
969
1000
  const openclawCmd = program.command('openclaw').description('OpenClaw integration commands');
970
- const { registerOpenClawCommands } = await import('./commands/openclaw-install.js');
971
- registerOpenClawCommands(openclawCmd);
1001
+ if (argvSelects('openclaw')) {
1002
+ const { registerOpenClawCommands } = await import('./commands/openclaw-install.js');
1003
+ registerOpenClawCommands(openclawCmd);
1004
+ }
972
1005
  // OpenCode integration
973
1006
  const opencodeCmd = program.command('opencode').description('OpenCode integration commands');
974
- const { registerOpencodeCommands } = await import('./commands/opencode-install.js');
975
- registerOpencodeCommands(opencodeCmd);
1007
+ if (argvSelects('opencode')) {
1008
+ const { registerOpencodeCommands } = await import('./commands/opencode-install.js');
1009
+ registerOpencodeCommands(opencodeCmd);
1010
+ }
976
1011
  // Analytics enable command
977
1012
  // Plugin subcommands
978
1013
  const pluginCmd = program.command('plugin').description('Manage plugins');
@@ -1029,6 +1064,8 @@ Examples:
1029
1064
  $ npx 0xray capabilities # Show all available capabilities
1030
1065
  $ npx 0xray health # Check framework health and status
1031
1066
  $ npx 0xray report # Generate activity and health reports
1067
+ $ npx 0xray monitor # Current picture of the worn suit
1068
+ $ npx 0xray pulse # One line: worn, repertoire, inference, activity, lens, plant
1032
1069
  $ npx 0xray fix # Automatically restore missing config files
1033
1070
  $ npx 0xray doctor # Diagnose issues (does not fix them)
1034
1071
  $ npx 0xray analytics # Pattern analytics and insights
@@ -0,0 +1,29 @@
1
+ /**
2
+ * One line from streams the suit already writes.
3
+ * Not a doctor, not a second memory.
4
+ */
5
+ export type SuitLens = "none" | "armed" | "spent";
6
+ export interface SuitPulseActivity {
7
+ gate: string | null;
8
+ decision: string;
9
+ tool: string | null;
10
+ }
11
+ export interface SuitPulse {
12
+ worn: {
13
+ version: string;
14
+ directory: string;
15
+ } | null;
16
+ repertoire: string | null;
17
+ inferenceSeconds: number | null;
18
+ activity: SuitPulseActivity | null;
19
+ lens: SuitLens;
20
+ plant: boolean;
21
+ line: string;
22
+ }
23
+ export interface SuitPulseOptions {
24
+ /** Epoch ms. Tests pin this so inference age stays exact. */
25
+ now?: number;
26
+ /** Override the CLI directory. Hooks and node_modules/0xray are the default. */
27
+ wornDir?: string;
28
+ }
29
+ export declare function readSuitPulse(root: string, opts?: SuitPulseOptions): SuitPulse;