0xray 4.0.21 → 4.0.22

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 (56) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.opencode/skills/hermes-agent/SKILL.md +1 -1
  3. package/.opencode/skills/orchestrator/SKILL.md +22 -0
  4. package/.xray/features.json +1 -1
  5. package/AGENTS-consumer.md +11 -11
  6. package/AGENTS.md +8 -8
  7. package/README.md +27 -27
  8. package/SKILLS.md +1 -1
  9. package/dist/AGENTS.md +8 -8
  10. package/dist/CHANGELOG.md +75 -0
  11. package/dist/README.md +27 -27
  12. package/dist/SKILLS.md +1 -1
  13. package/dist/governance/governance-core.d.ts +2 -1
  14. package/dist/governance/governance-core.js +20 -11
  15. package/dist/governance/governance-service.js +9 -7
  16. package/dist/inference/inference-cycle.js +22 -5
  17. package/dist/integrations/cursor/README.md +1 -1
  18. package/dist/integrations/cursor/hooks/cursor-hook-utils.js +19 -0
  19. package/dist/integrations/cursor/hooks/pre-tool-use.js +2 -1
  20. package/dist/integrations/hooks/station-hook-runtime.cjs +90 -30
  21. package/dist/integrations/hooks/station-hook-runtime.mjs +1 -0
  22. package/dist/integrations/hooks/station-memory-ingest.mjs +4 -2
  23. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  24. package/dist/memory-routing/provider-loader.d.ts +3 -1
  25. package/dist/memory-routing/provider-loader.js +3 -1
  26. package/dist/nucleus/thin-dispatch.js +11 -2
  27. package/dist/processors/implementations/agents-md-validation-processor.js +1 -1
  28. package/dist/skills/hermes-agent/SKILL.md +1 -1
  29. package/dist/skills/orchestrator/SKILL.md +22 -0
  30. package/package.json +2 -2
  31. package/scripts/foundry/CHANGELOG.md +2 -0
  32. package/scripts/foundry/README.md +2 -2
  33. package/scripts/foundry/cli.mjs +1 -1
  34. package/scripts/foundry/inspect.mjs +160 -5
  35. package/scripts/foundry/plant/skills/inspect/SKILL.md +2 -0
  36. package/scripts/foundry/validate-release-docs.mjs +24 -20
  37. package/scripts/foundry/version-manager.mjs +127 -7
  38. package/scripts/mjs/test-consumer-readiness.mjs +10 -3
  39. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  40. package/src/skills/hermes-agent/SKILL.md +1 -1
  41. package/src/skills/orchestrator/SKILL.md +22 -0
  42. package/vendor/@0xray/repertoire/data/stack-overlay.json +154 -1
  43. package/vendor/@0xray/repertoire/dist/RepertoireService.js +7 -6
  44. package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js +10 -11
  45. package/vendor/@0xray/repertoire/dist/paths.js +66 -4
  46. package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js +54 -14
  47. package/xray/agents_template.md +10 -5
  48. package/xray/features.json +1 -1
  49. package/dist/mcps/shared/prompt-security-validator.d.ts +0 -44
  50. package/dist/mcps/shared/prompt-security-validator.js +0 -148
  51. package/dist/mcps/shared/security-scanner.d.ts +0 -119
  52. package/dist/mcps/shared/security-scanner.js +0 -429
  53. package/dist/scripts/activate-kernel-pipeline.d.ts +0 -7
  54. package/dist/scripts/activate-kernel-pipeline.js +0 -101
  55. package/src/mcps/shared/prompt-security-validator.ts +0 -199
  56. package/src/mcps/shared/security-scanner.ts +0 -599
@@ -70,6 +70,65 @@ export function resolveWritableConfigPath(configured, cwd, fallback) {
70
70
  return configured;
71
71
  return resolve(cwd, configured);
72
72
  }
73
+ const STACK_LAW_FIELDS = [
74
+ 'definition',
75
+ 'tags',
76
+ 'priority',
77
+ 'evaluation_criteria',
78
+ 'validation_experiment',
79
+ 'example_inference_snippet',
80
+ 'implementation_notes',
81
+ ];
82
+ function assignStackLawField(existing, field, next) {
83
+ switch (field) {
84
+ case 'definition':
85
+ if (typeof next === 'string')
86
+ existing.definition = next;
87
+ break;
88
+ case 'tags':
89
+ if (Array.isArray(next))
90
+ existing.tags = [...next];
91
+ break;
92
+ case 'priority':
93
+ if (typeof next === 'string')
94
+ existing.priority = next;
95
+ break;
96
+ case 'evaluation_criteria':
97
+ if (typeof next === 'string')
98
+ existing.evaluation_criteria = next;
99
+ break;
100
+ case 'validation_experiment':
101
+ if (typeof next === 'string')
102
+ existing.validation_experiment = next;
103
+ break;
104
+ case 'example_inference_snippet':
105
+ if (typeof next === 'string')
106
+ existing.example_inference_snippet = next;
107
+ break;
108
+ case 'implementation_notes':
109
+ if (typeof next === 'string')
110
+ existing.implementation_notes = next;
111
+ break;
112
+ default: {
113
+ const unexpected = field;
114
+ throw new Error(`unknown stack law field ${String(unexpected)}`);
115
+ }
116
+ }
117
+ }
118
+ /** Copy changed stack law text onto an existing project name. Observation stats stay. */
119
+ function refreshStackLaw(existing, signal) {
120
+ let dirty = false;
121
+ for (const field of STACK_LAW_FIELDS) {
122
+ const next = signal[field];
123
+ if (next == null)
124
+ continue;
125
+ if (JSON.stringify(existing[field]) === JSON.stringify(next))
126
+ continue;
127
+ assignStackLawField(existing, field, next);
128
+ dirty = true;
129
+ }
130
+ return dirty;
131
+ }
73
132
  export function isGenericFieldObservedDefinition(definition) {
74
133
  return definition.includes('Field-observed domain primitive');
75
134
  }
@@ -104,6 +163,9 @@ function mergeOverlaySignals(destPath, overlayPath, options = {}) {
104
163
  changed += 1;
105
164
  continue;
106
165
  }
166
+ if (options.refreshLaws && refreshStackLaw(existing, signal)) {
167
+ changed += 1;
168
+ }
107
169
  if (options.fleshGeneric && isGenericFieldObservedDefinition(existing.definition)) {
108
170
  existing.definition = signal.definition;
109
171
  if (signal.tags)
@@ -127,12 +189,12 @@ function mergeOverlaySignals(destPath, overlayPath, options = {}) {
127
189
  return changed;
128
190
  }
129
191
  /**
130
- * Additive merge of `data/stack-overlay.json` into a project copy.
131
- * Existing names keep their stats. Missing overlay names are appended.
132
- * Refuses the factory tarball path.
192
+ * Merge `data/stack-overlay.json` into a project copy.
193
+ * Missing names are appended. A changed stack law field is refreshed.
194
+ * Observation stats on existing names stay. Refuses the factory tarball path.
133
195
  */
134
196
  export function mergeStackOverlay(destPath, overlayPath = DEFAULT_STACK_OVERLAY_PATH) {
135
- return mergeOverlaySignals(destPath, overlayPath);
197
+ return mergeOverlaySignals(destPath, overlayPath, { refreshLaws: true });
136
198
  }
137
199
  /**
138
200
  * Additive merge of `data/subject-overlay.json` — product/repo flesh.
@@ -7,6 +7,21 @@ export const FEEDBACK_SUCCESS_CONFIDENCE_BOOST = 0.002;
7
7
  export const FEEDBACK_FAILURE_CONFIDENCE_PENALTY = 0.005;
8
8
  export const FEEDBACK_MIN_CONFIDENCE = DEFAULT_PROMOTION_MIN_CONFIDENCE;
9
9
  const FIELD_PRIMITIVE_NAME = /^[A-Za-z][A-Za-z0-9_-]{2,119}$/;
10
+ /**
11
+ * The diary names a law only when it contains the signal id, or the id with
12
+ * hyphens read as spaces. A repo tail, leftover tokens, and two definition
13
+ * words are not the name.
14
+ */
15
+ export function signalNameInText(text, name) {
16
+ const normalized = text.toLowerCase();
17
+ const id = name.toLowerCase();
18
+ if (!id)
19
+ return false;
20
+ if (normalized.includes(id))
21
+ return true;
22
+ const spaced = id.replace(/-/g, ' ');
23
+ return spaced !== id && normalized.includes(spaced);
24
+ }
10
25
  const GROOVER_EXPERIMENT_NAMES = new Set([
11
26
  'criteria_selection_gap',
12
27
  'external_norm_smuggling_risk',
@@ -119,25 +134,17 @@ export class CuratedSignalsManager {
119
134
  return this.load().signals.filter((s) => s.priority === priority);
120
135
  }
121
136
  /**
122
- * Score text against all signals using name, tags, definition, criteria, and snippet.
137
+ * Score text against signals. A hit requires the signal id, or the id with
138
+ * hyphens read as spaces. Two definition words are not a match.
123
139
  */
124
140
  matchByText(text, minScore = 2) {
125
141
  const normalized = text.toLowerCase();
126
142
  const matches = [];
127
143
  for (const signal of this.load().signals) {
128
- const matchedOn = [];
129
- let score = 0;
130
- if (normalized.includes(signal.name.replace(/-/g, ' ')) || normalized.includes(signal.name)) {
131
- score += 5;
132
- matchedOn.push('name');
133
- }
134
- else if (signal.name.startsWith('repo-')) {
135
- const tail = signal.name.slice(5);
136
- if (tail.length >= 3 && new RegExp(`\\b${tail}\\b`, 'i').test(normalized)) {
137
- score += 5;
138
- matchedOn.push('name');
139
- }
140
- }
144
+ if (!signalNameInText(text, signal.name))
145
+ continue;
146
+ const matchedOn = ['name'];
147
+ let score = 5;
141
148
  for (const tag of signal.tags) {
142
149
  if (normalized.includes(tag.toLowerCase())) {
143
150
  score += 3;
@@ -191,6 +198,39 @@ export class CuratedSignalsManager {
191
198
  }
192
199
  return matches.sort((a, b) => b.score - a.score);
193
200
  }
201
+ /**
202
+ * Mark names the diary already matched. Does not append a confidence sample.
203
+ * Missing names are left absent. Heat must not mint a law.
204
+ */
205
+ touchLastSeen(names) {
206
+ const data = this.load();
207
+ const now = new Date().toISOString();
208
+ const updated = [];
209
+ const seen = new Set();
210
+ for (const name of names) {
211
+ if (!name || seen.has(name))
212
+ continue;
213
+ seen.add(name);
214
+ const signal = data.signals.find((entry) => entry.name === name);
215
+ if (!signal)
216
+ continue;
217
+ const previous = signal.observation_stats;
218
+ signal.observation_stats = previous
219
+ ? { ...previous, last_seen: now }
220
+ : {
221
+ observation_count: 0,
222
+ avg_confidence: 0,
223
+ max_confidence: 0,
224
+ last_seen: now,
225
+ governance_forced_count: 0,
226
+ };
227
+ updated.push(signal.name);
228
+ }
229
+ if (updated.length > 0) {
230
+ this.save(data);
231
+ }
232
+ return updated;
233
+ }
194
234
  recordPrimitiveObservations(matches, options = {}) {
195
235
  const minConfidence = options.minConfidence ?? DEFAULT_PROMOTION_MIN_CONFIDENCE;
196
236
  const data = this.load();
@@ -1,22 +1,27 @@
1
1
  # 0xRay AI Agents
2
2
 
3
- Quick reference for the 0xRay AI orchestration framework (v16 MCPs-centric three-subsystem).
3
+ Quick reference for the 0xRay AI orchestration framework (**4.0** — 7 consumer MCP servers).
4
4
 
5
5
  ## Available MCP Servers
6
6
 
7
+ All seven use `npx -y 0xray mcp <cmd>`:
8
+
7
9
  | Server | Role |
8
10
  |--------|------|
9
11
  | `xray-governance` | Proposal governance, codex snapshot, quality gates |
10
- | `xray-skills` | Skill invocation, agent-specific knowledge servers |
12
+ | `xray-skills` | Skill invocation, 45 knowledge skills |
13
+ | `xray-orchestrator` | thinDispatch routing, AsideContext, confidence gate |
11
14
  | `xray-enforcer` | Codex compliance enforcement, rule validation |
12
- | `xray-orchestrator` | Multi-agent workflow coordination, task delegation |
15
+ | `xray-researcher` | Codebase exploration, memory-routing enrichment |
16
+ | `xray-code-review` | Proposal quality, code review deliberation |
17
+ | `xray-architect-tools` | System design, architecture decisions |
13
18
 
14
19
  ## CLI Commands
15
20
 
16
21
  | Command | Description |
17
22
  |---------|-------------|
18
23
  | `xray setup` | Full framework setup (hooks, Hermes, symlinks) |
19
- | `xray validate` | Validate codex compliance |
24
+ | `xray validate` | Wear check (pack paths, Cursor hooks, mill) — not leftover init.sh |
20
25
  | `xray codex check` | Check codex rules |
21
26
  | `xray health` | Framework health check |
22
27
  | `xray hooks` | Manage lifecycle hooks |
@@ -25,7 +30,7 @@ Quick reference for the 0xRay AI orchestration framework (v16 MCPs-centric three
25
30
 
26
31
  xray operates under the three-subsystem model: Inference + External Governance (Dynamo Solar SSOT) + Autonomous Engine (thinDispatch 7-flow in MCP orchestrator). All actions are validated against the Universal Development Codex before execution.
27
32
 
28
- **Codex**: The codex lives in `.xray/codex.json` and enforces 60 terms across all agent interactions.
33
+ **Codex**: `.xray/codex.json` — **69 terms** across all agent interactions.
29
34
 
30
35
  ## thinDispatch Routing
31
36
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./features.schema.json",
3
- "version": "4.0.21",
3
+ "version": "4.0.22",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",
@@ -1,44 +0,0 @@
1
- /**
2
- * 0xRay Framework - AI Prompt Security Validator
3
- *
4
- * Specialized security validation for AI agent prompts and responses
5
- * Prevents prompt injection, system prompt override, and malicious inputs
6
- */
7
- export interface PromptSecurityConfig {
8
- enabled: boolean;
9
- maxPromptLength: number;
10
- allowedPatterns: RegExp[];
11
- blockedPatterns: RegExp[];
12
- sanitizeLevel: "basic" | "strict" | "paranoid";
13
- }
14
- export interface SecurityValidationResult {
15
- isSafe: boolean;
16
- violations: string[];
17
- sanitizedPrompt?: string | undefined;
18
- riskLevel: "low" | "medium" | "high" | "critical";
19
- }
20
- export declare class PromptSecurityValidator {
21
- private config;
22
- constructor(config?: Partial<PromptSecurityConfig>);
23
- /**
24
- * Validate AI prompt for security issues
25
- */
26
- validatePrompt(prompt: string): SecurityValidationResult;
27
- /**
28
- * Check for system prompt override attempts
29
- */
30
- private containsSystemPromptOverride;
31
- /**
32
- * Check for prompt injection attempts
33
- */
34
- private containsInjectionAttempts;
35
- /**
36
- * Sanitize prompt by removing dangerous patterns
37
- */
38
- private sanitizePrompt;
39
- /**
40
- * Validate agent response for safety
41
- */
42
- validateResponse(response: string): SecurityValidationResult;
43
- }
44
- export declare const promptSecurityValidator: PromptSecurityValidator;
@@ -1,148 +0,0 @@
1
- /**
2
- * 0xRay Framework - AI Prompt Security Validator
3
- *
4
- * Specialized security validation for AI agent prompts and responses
5
- * Prevents prompt injection, system prompt override, and malicious inputs
6
- */
7
- export class PromptSecurityValidator {
8
- config;
9
- constructor(config = {}) {
10
- this.config = {
11
- enabled: true,
12
- maxPromptLength: 10000,
13
- allowedPatterns: [],
14
- blockedPatterns: [
15
- /system\s+prompt\s*[:=]/gi,
16
- /ignore\s+previous\s+instructions/gi,
17
- /you\s+are\s+now\s+/gi,
18
- /forget\s+your\s+previous\s+/gi,
19
- /override\s+(your\s+)?instructions/gi,
20
- /jailbreak/gi,
21
- /dan.*mode/gi,
22
- ],
23
- sanitizeLevel: "strict",
24
- ...config,
25
- };
26
- }
27
- /**
28
- * Validate AI prompt for security issues
29
- */
30
- validatePrompt(prompt) {
31
- if (!this.config.enabled) {
32
- return { isSafe: true, violations: [], riskLevel: "low" };
33
- }
34
- const violations = [];
35
- let riskLevel = "low";
36
- // Length check
37
- if (prompt.length > this.config.maxPromptLength) {
38
- violations.push(`Prompt too long: ${prompt.length} > ${this.config.maxPromptLength}`);
39
- riskLevel = "medium";
40
- }
41
- // Blocked pattern check
42
- for (const pattern of this.config.blockedPatterns) {
43
- if (pattern.test(prompt)) {
44
- violations.push(`Blocked pattern detected: ${pattern.source}`);
45
- riskLevel = "high";
46
- }
47
- }
48
- // Advanced pattern analysis
49
- if (this.containsSystemPromptOverride(prompt)) {
50
- violations.push("Potential system prompt override attempt");
51
- riskLevel = "critical";
52
- }
53
- if (this.containsInjectionAttempts(prompt)) {
54
- violations.push("Potential prompt injection detected");
55
- riskLevel = "high";
56
- }
57
- const isSafe = violations.length === 0;
58
- const sanitizedPrompt = isSafe ? undefined : this.sanitizePrompt(prompt);
59
- return {
60
- isSafe,
61
- violations,
62
- sanitizedPrompt,
63
- riskLevel,
64
- };
65
- }
66
- /**
67
- * Check for system prompt override attempts
68
- */
69
- containsSystemPromptOverride(prompt) {
70
- const overrideIndicators = [
71
- "you are now",
72
- "act as if",
73
- "pretend to be",
74
- "role-play as",
75
- "from now on you are",
76
- "ignore your system",
77
- "override your",
78
- "new personality",
79
- "different role",
80
- ];
81
- const lowerPrompt = prompt.toLowerCase();
82
- return overrideIndicators.some((indicator) => lowerPrompt.includes(indicator));
83
- }
84
- /**
85
- * Check for prompt injection attempts
86
- */
87
- containsInjectionAttempts(prompt) {
88
- const injectionIndicators = [
89
- "ignore previous",
90
- "forget instructions",
91
- "start over",
92
- "new conversation",
93
- "reset context",
94
- "clear memory",
95
- "delete history",
96
- ];
97
- const lowerPrompt = prompt.toLowerCase();
98
- return injectionIndicators.some((indicator) => lowerPrompt.includes(indicator));
99
- }
100
- /**
101
- * Sanitize prompt by removing dangerous patterns
102
- */
103
- sanitizePrompt(prompt) {
104
- let sanitized = prompt;
105
- // Remove blocked patterns
106
- for (const pattern of this.config.blockedPatterns) {
107
- sanitized = sanitized.replace(pattern, "[REDACTED]");
108
- }
109
- // Additional sanitization based on level
110
- if (this.config.sanitizeLevel === "strict" ||
111
- this.config.sanitizeLevel === "paranoid") {
112
- // Remove potential code execution
113
- sanitized = sanitized.replace(/```[\s\S]*?```/g, "[CODE_BLOCK_REMOVED]");
114
- // Remove potential file system access
115
- sanitized = sanitized.replace(/(?:\/|\\)\.\.(?:\/|\\)/g, "/");
116
- // Remove potential command injection
117
- sanitized = sanitized.replace(/[;&|`$()]/g, "");
118
- }
119
- if (this.config.sanitizeLevel === "paranoid") {
120
- // Extreme sanitization - only allow alphanumeric, spaces, and basic punctuation
121
- sanitized = sanitized.replace(/[^a-zA-Z0-9\s.,!?-]/g, "");
122
- }
123
- return sanitized;
124
- }
125
- /**
126
- * Validate agent response for safety
127
- */
128
- validateResponse(response) {
129
- // Similar validation but focused on response safety
130
- const violations = [];
131
- // Check for potentially harmful content
132
- if (response.includes("system prompt") ||
133
- response.includes("internal instructions")) {
134
- violations.push("Response contains sensitive system information");
135
- }
136
- // Check for code execution attempts
137
- if (/eval\s*\(|Function\s*\(/.test(response)) {
138
- violations.push("Response contains potential code execution");
139
- }
140
- return {
141
- isSafe: violations.length === 0,
142
- violations,
143
- riskLevel: violations.length > 0 ? "medium" : "low",
144
- };
145
- }
146
- }
147
- // Export singleton instance
148
- export const promptSecurityValidator = new PromptSecurityValidator();
@@ -1,119 +0,0 @@
1
- /**
2
- * 0xRay Framework - Security Scanner
3
- *
4
- * Automated security vulnerability scanning and compliance validation
5
- * Integrates with security tools and provides comprehensive security reports
6
- */
7
- export interface SecurityScanConfig {
8
- enabled: boolean;
9
- tools: {
10
- npmAudit: boolean;
11
- trivy: boolean;
12
- eslintSecurity: boolean;
13
- dependencyCheck: boolean;
14
- };
15
- severityThreshold: "low" | "moderate" | "high" | "critical";
16
- reportPath: string;
17
- failOnVulnerabilities: boolean;
18
- }
19
- export interface SecurityVulnerability {
20
- id: string;
21
- title: string;
22
- description: string;
23
- severity: "low" | "moderate" | "high" | "critical";
24
- package?: string;
25
- version?: string;
26
- cve?: string;
27
- url?: string;
28
- recommendation: string;
29
- }
30
- export interface SecurityReport {
31
- timestamp: string;
32
- duration: number;
33
- tools: {
34
- npmAudit: SecurityVulnerability[];
35
- trivy: SecurityVulnerability[];
36
- eslintSecurity: SecurityVulnerability[];
37
- dependencyCheck: SecurityVulnerability[];
38
- };
39
- summary: {
40
- totalVulnerabilities: number;
41
- bySeverity: Record<string, number>;
42
- byTool: Record<string, number>;
43
- };
44
- recommendations: string[];
45
- compliant: boolean;
46
- }
47
- export declare class SecurityScanner {
48
- private config;
49
- constructor(config?: Partial<SecurityScanConfig>);
50
- /**
51
- * Run comprehensive security scan
52
- */
53
- runSecurityScan(): Promise<SecurityReport>;
54
- /**
55
- * Run npm audit
56
- */
57
- private runNpmAudit;
58
- /**
59
- * Run Trivy security scan
60
- */
61
- private runTrivyScan;
62
- /**
63
- * Run ESLint security rules
64
- */
65
- private runEslintSecurity;
66
- /**
67
- * Run OWASP Dependency Check
68
- */
69
- private runDependencyCheck;
70
- /**
71
- * Generate comprehensive security report
72
- */
73
- private generateReport;
74
- /**
75
- * Generate security recommendations
76
- */
77
- private generateRecommendations;
78
- /**
79
- * Save report to file
80
- */
81
- private saveReport;
82
- /**
83
- * Log security scan results
84
- */
85
- private logResults;
86
- /**
87
- * Map npm audit severity levels
88
- */
89
- private mapNpmSeverity;
90
- /**
91
- * Map Trivy severity levels
92
- */
93
- private mapTrivySeverity;
94
- /**
95
- * Map Dependency Check severity levels
96
- */
97
- private mapDependencyCheckSeverity;
98
- /**
99
- * Validate AI prompt security
100
- */
101
- validatePrompt(prompt: string): Promise<{
102
- isSafe: boolean;
103
- violations: string[];
104
- riskLevel: string;
105
- }>;
106
- /**
107
- * Validate AI response security
108
- */
109
- validateResponse(response: string): Promise<{
110
- isSafe: boolean;
111
- violations: string[];
112
- riskLevel: string;
113
- }>;
114
- /**
115
- * Create empty report when scanning is disabled
116
- */
117
- private createEmptyReport;
118
- }
119
- export declare const securityScanner: SecurityScanner;