0xray 4.0.26 → 4.0.28

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 (35) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.opencode/skills/orchestrator/SKILL.md +5 -5
  3. package/.opencode/skills/storyteller/SKILL.md +1 -1
  4. package/.xray/features.json +1 -1
  5. package/AGENTS.md +1 -1
  6. package/README.md +2 -0
  7. package/SKILLS.md +1 -1
  8. package/dist/AGENTS.md +1 -1
  9. package/dist/CHANGELOG.md +34 -0
  10. package/dist/README.md +2 -0
  11. package/dist/SKILLS.md +1 -1
  12. package/dist/integrations/cursor/README.md +3 -1
  13. package/dist/integrations/cursor/hooks/cursor-hook-utils.js +77 -7
  14. package/dist/integrations/cursor/hooks/pre-compact.js +22 -16
  15. package/dist/integrations/cursor/hooks/xray-cloud-hook.sh +1 -1
  16. package/dist/integrations/hooks/plates.cjs +7 -0
  17. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  18. package/dist/memory-routing/plates.d.ts +1 -1
  19. package/dist/memory-routing/plates.js +1 -0
  20. package/dist/skills/orchestrator/SKILL.md +5 -5
  21. package/dist/skills/storyteller/SKILL.md +1 -1
  22. package/docs-site/docs/plates/house.md +50 -0
  23. package/docs-site/docs/plates/index.md +1 -1
  24. package/llms.txt +6 -1
  25. package/package.json +3 -2
  26. package/scripts/foundry/inspect.mjs +47 -2
  27. package/scripts/node/bridge-mcp-wiring.cjs +320 -29
  28. package/scripts/node/consumer-install-smoke.mjs +37 -3
  29. package/scripts/node/install-bridges.cjs +34 -19
  30. package/scripts/node/mcp-launch.cjs +70 -0
  31. package/scripts/node/postinstall.cjs +42 -13
  32. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  33. package/src/skills/orchestrator/SKILL.md +5 -5
  34. package/src/skills/storyteller/SKILL.md +1 -1
  35. package/xray/features.json +1 -1
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Start an MCP server with an allowlisted environment.
5
+ *
6
+ * node mcp-launch.cjs --keep PATH,HOME,XRAY_ROOT[,NAME...] -- <cmd> [args...]
7
+ *
8
+ * argv carries names only. The host merges the config `env` block onto this
9
+ * process, so values come from the live environment. The child receives
10
+ * process.env filtered to those names. stdio is inherited. Signals and the
11
+ * exit code are forwarded.
12
+ */
13
+ const { spawn } = require("child_process");
14
+
15
+ function fail(message) {
16
+ process.stderr.write(`mcp-launch: ${message}\n`);
17
+ process.exit(1);
18
+ }
19
+
20
+ function parseArgs(argv) {
21
+ const keepIdx = argv.indexOf("--keep");
22
+ const dash = argv.indexOf("--");
23
+ if (keepIdx < 0 || dash < 0 || dash !== keepIdx + 2 || dash >= argv.length - 1) {
24
+ fail("usage: node mcp-launch.cjs --keep NAME[,NAME...] -- <cmd> [args...]");
25
+ }
26
+ const keep = argv[keepIdx + 1]
27
+ .split(",")
28
+ .map((name) => name.trim())
29
+ .filter(Boolean);
30
+ if (keep.length === 0) fail("--keep needs at least one name");
31
+ for (const name of keep) {
32
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) fail(`refusing keep name ${name}`);
33
+ }
34
+ return { keep, command: argv[dash + 1], args: argv.slice(dash + 2) };
35
+ }
36
+
37
+ function childEnv(keep) {
38
+ const env = {};
39
+ for (const name of keep) {
40
+ if (process.env[name] != null) env[name] = process.env[name];
41
+ }
42
+ return env;
43
+ }
44
+
45
+ function main() {
46
+ const { keep, command, args } = parseArgs(process.argv.slice(2));
47
+ const child = spawn(command, args, { env: childEnv(keep), stdio: "inherit" });
48
+ const forward = (signal) => {
49
+ if (!child.pid) return;
50
+ try {
51
+ child.kill(signal);
52
+ } catch {
53
+ /* child already exited */
54
+ }
55
+ };
56
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
57
+ process.on(signal, () => forward(signal));
58
+ }
59
+ child.on("error", (err) => fail(err.message));
60
+ child.on("exit", (code, signal) => {
61
+ if (signal) {
62
+ process.removeAllListeners(signal);
63
+ process.kill(process.pid, signal);
64
+ return;
65
+ }
66
+ process.exit(code == null ? 1 : code);
67
+ });
68
+ }
69
+
70
+ main();
@@ -25,6 +25,8 @@ function structuredLog(component, action, status, details) {
25
25
  }
26
26
 
27
27
  const XRAY_MANAGED_AGENTS_MARKER = "<!-- 0xray-managed -->";
28
+ const XRAY_MANAGED_AGENTS_BEGIN = "<!-- 0xray-managed:begin -->";
29
+ const XRAY_MANAGED_AGENTS_END = "<!-- 0xray-managed:end -->";
28
30
 
29
31
  function fillConsumerPlaceholders(content, consumer) {
30
32
  const name = consumer.name || "this project";
@@ -36,24 +38,51 @@ function fillConsumerPlaceholders(content, consumer) {
36
38
  .join(versionParen);
37
39
  }
38
40
 
41
+ function renderManagedAgents(packageRoot, targetDir) {
42
+ let content = fs.readFileSync(path.join(packageRoot, "AGENTS-consumer.md"), "utf8");
43
+ const consumer = readPackageIdentity(path.join(targetDir, "package.json"));
44
+ content = fillConsumerPlaceholders(content, consumer).trim();
45
+ if (!content.includes(XRAY_MANAGED_AGENTS_MARKER)) {
46
+ content = `${content}\n\n${XRAY_MANAGED_AGENTS_MARKER}`;
47
+ }
48
+ return `${XRAY_MANAGED_AGENTS_BEGIN}\n${content}\n${XRAY_MANAGED_AGENTS_END}\n`;
49
+ }
50
+
51
+ function managedRegion(text) {
52
+ const beginAt = text.indexOf(XRAY_MANAGED_AGENTS_BEGIN);
53
+ const endAt = text.indexOf(XRAY_MANAGED_AGENTS_END);
54
+ if (beginAt === -1 || endAt === -1 || endAt < beginAt) return null;
55
+ return {
56
+ before: text.slice(0, beginAt),
57
+ after: text.slice(endAt + XRAY_MANAGED_AGENTS_END.length),
58
+ };
59
+ }
60
+
61
+ function outsideRegionEdited(parts) {
62
+ return parts.before.trim() !== "" || parts.after.trim() !== "";
63
+ }
64
+
39
65
  function deployManagedAgents(packageRoot, targetDir, log) {
40
66
  const agentsConsumer = path.join(packageRoot, "AGENTS-consumer.md");
41
67
  const agentsDest = path.join(targetDir, "AGENTS.md");
42
68
  if (!fs.existsSync(agentsConsumer)) return;
43
- const shouldDeployAgents =
44
- !fs.existsSync(agentsDest) ||
45
- fs.readFileSync(agentsDest, "utf8").includes(XRAY_MANAGED_AGENTS_MARKER);
46
- if (shouldDeployAgents) {
47
- let content = fs.readFileSync(agentsConsumer, "utf8");
48
- const consumer = readPackageIdentity(path.join(targetDir, "package.json"));
49
- content = fillConsumerPlaceholders(content, consumer);
50
- if (!content.includes(XRAY_MANAGED_AGENTS_MARKER)) {
51
- content = `${content.trimEnd()}\n\n${XRAY_MANAGED_AGENTS_MARKER}\n`;
52
- }
53
- fs.writeFileSync(agentsDest, content);
54
- } else {
55
- log("postinstall", "Skipped AGENTS.md (consumer-customized)", "info");
69
+ const next = renderManagedAgents(packageRoot, targetDir);
70
+ if (!fs.existsSync(agentsDest)) {
71
+ fs.writeFileSync(agentsDest, next);
72
+ return;
73
+ }
74
+ const current = fs.readFileSync(agentsDest, "utf8");
75
+ const parts = managedRegion(current);
76
+ if (!parts || outsideRegionEdited(parts)) {
77
+ fs.writeFileSync(path.join(targetDir, "AGENTS.md.0xray-new"), next);
78
+ log("postinstall", "AGENTS.md left in place; wrote AGENTS.md.0xray-new", "info");
79
+ return;
56
80
  }
81
+ const beginAt = next.indexOf(XRAY_MANAGED_AGENTS_BEGIN);
82
+ const endAt = next.indexOf(XRAY_MANAGED_AGENTS_END);
83
+ const interior = next.slice(beginAt, endAt + XRAY_MANAGED_AGENTS_END.length);
84
+ const updated = `${parts.before}${interior}${parts.after}`;
85
+ if (updated !== current) fs.writeFileSync(agentsDest, updated);
57
86
  }
58
87
 
59
88
  function deployConsumerGitignore(packageRoot, targetDir, log) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray-pre-tool",
3
- "version": "4.0.26",
3
+ "version": "4.0.28",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
@@ -62,7 +62,7 @@ Config: `features.json` → `multi_agent_orchestration.lead_dev_mode`
62
62
 
63
63
  ## Lead cadence (syncopation)
64
64
 
65
- The seven rules are the engine. The cadence is the time signature. Disk SSOT: `grok-bot/ops/LEAD-CADENCE.md`.
65
+ The seven rules are the engine. The cadence is the time signature. Disk SSOT: `grok-bot/OP-PROC.md` (team specifics live in `house/`).
66
66
 
67
67
  Jargon is not the job. Review and cadence ask whether the change works. Do not spend the loop reciting dest names, mill liturgy, or host mantras.
68
68
 
@@ -76,8 +76,8 @@ Jargon is not the job. Review and cadence ask whether the change works. Do not s
76
76
  - **Peer boot:** four-line dispatch. They Read Station + this cadence and install without a command novel. Not a twin critic.
77
77
  - **Live tick, not pacer:** `/loop` runs work now. Keep workstreams moving. Do not idle-wait 12 minutes. **Clean ticks every cycle** — unsubscribe then resubscribe so the prompt matches metal. Name-dedupe does not rewrite. A stale prompt (waiting URL after live, Hold after strip) is dirty: rewrite, do not act. **If the card and WAVEBOARD are idle, unsubscribe and do not resubscribe.**
78
78
  - **Board clock:** PR events + resume the same critic. Not two idle pacers. Merge after PASS+CI (gate A). Publish only after mill-gate D + `foundry gate`.
79
- - **Dispatch:** ticket + PR URLs + “Wear, then review.” The critic Reads `SEATS.md` Reviewer. Do not paste a command novel. When a law is spoken twice, encode it this wake.
80
- - **Cascade:** Chat is not the brain. A cascade that must survive compaction is a named repertoire signal on the stack overlay, hydrated onto the project law list. NOTES holds the same cascade for the second Read. Station stays the ticket. A reflection is not this capture. Capture priority: a law is an invariant you would otherwise re-read the source to relearn. One law per subsystem bone. Heat touches last_seen and does not append a confidence sample, so more hits do not raise conviction. Heat touches last_seen when the diary contains that signal's name or a local clause of four definition content words; two definition words are not a hit; the same words scattered through a long diary are not a hit; a weak session score is not lifted to 0.55 and a sample below 0.55 is not recorded. Constructing the organ does not append workspace samples. Hero names: `heat-is-not-conviction`, `inference-cycle-invariant`, `governance-vote-invariant`, `thin-dispatch-invariant`. Repertoire mergeStackOverlay refreshes a changed stack definition and keeps observation stats. A floor observation count does not change a route. Feedback moves conviction by a tenth, and a failure can leave 0.55. learned-conviction.json beside dest restores that average when a wake flattens it to 0.55. It does not store the observation count.
79
+ - **Dispatch:** ticket + PR URLs + “Wear, then review.” The critic Reads `grok-bot/OP-PROC.md` (team specifics live in `house/`). Do not paste a command novel. When a law is spoken twice, encode it this wake.
80
+ - **Cascade:** Chat is not the brain. A cascade that must survive compaction is a named repertoire signal on the stack overlay, hydrated onto the project law list. NOTES holds the same cascade for the second Read. Station stays the ticket. A reflection is not this capture. Memory scoring rules: [docs/memory-scoring.md](https://github.com/0xRayAI/xray/blob/main/docs/memory-scoring.md).
81
81
  - **Cold brief:** a new critic or any new subagent that does not already have this thread gets the latest commit SHA on the branch under review (fetch it; do not reuse an earlier SHA from a previous pass) and the Station card (`.xray/state/STATION.md`: intent, plan, git). If the card is missing, give branch + HEAD + what just changed. If the branch moves after you brief them, send the new SHA before they verdict.
82
82
  - **Control:** The lead keeps control. Do not assume the subagent has the context. Give the duty, the latest SHA, the Station card, and the laws that apply. The subagent wears the applicable 0xRay suit before it works: the tree under review, built and installed. An older published package is not that suit. The lead checks the result.
83
83
 
@@ -96,7 +96,7 @@ This suite is the engine that builds the engine. When a seat sees OP-PROC, write
96
96
 
97
97
  Operating planes: code, OP-PROC, model, suit, mill, host, and test/ship. Test/ship is the critical OP-PROC plane. Test then ship is the hero. Ship without that proof is the catastrophe. Long-term memory is the project law list. Each wake refreshes a changed stack definition and keeps observation stats. Heat writes the matched names onto Station, the short-term card that survives compaction. Reactive decisions move out of TypeScript into OP-PROC as the model improves. That move is why the mill and the suit exist. It is not fully proved. Once a version is live, the stamper strips every present-tense patch pin from shipped guides and shipped OP-PROC, or reconcile advances the next cut. The stamper does not edit Station, NOTES, dest, or node_modules. It does not publish. Do not freeze the live cut.
98
98
  - **Close:** loop until Station is done. Compact: Station survives the cut. Overlay dest names are OP-PROC — reload `repertoire-working.json` `opProcNames`, not Station.
99
- - **Board:** critic Strict comments; forge implements; lead stays main thread.
99
+ - **Board:** critic Strict comments; the implementer implements; lead stays main thread.
100
100
  - **Codex 69:** rewire this skill and existing ops. Do not add a new `SKILL.md` to hold the cadence.
101
- - **Ship matrix:** `LEAD-CADENCE.md` Decision matrix — A PR+CI · B pack · C `release:docs-check` (`reconcile --check`; no patch stamps on guides) · D `foundry release --i-mean-it`. Green CI is not ship. Spend / credentials stay Ask-first. Patch number lives in `package.json` + CHANGELOG.
101
+ - **Ship matrix:** `grok-bot/OP-PROC.md` Decision matrix (team specifics live in `house/`) — A PR+CI · B pack · C `release:docs-check` (`reconcile --check`; no patch stamps on guides) · D `foundry release --i-mean-it`. Green CI is not ship. Spend / credentials stay Ask-first. Patch number lives in `package.json` + CHANGELOG.
102
102
  - **Metamorphosis:** LLM → OP-PROC is in-context worn seats (same critic, same dummy, resume only). Not more bots.
@@ -96,7 +96,7 @@ codex_terms: [5, 7, 32] # Related Codex term numbers
96
96
  ```markdown
97
97
  ## What Next?
98
98
 
99
- - Related Codex terms: [codex.json](../../../../.xray/codex.json)
99
+ - Related Codex terms: [codex.json](../../../.xray/codex.json)
100
100
  - Next story to write: [suggestion]
101
101
  ```
102
102
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./features.schema.json",
3
- "version": "4.0.26",
3
+ "version": "4.0.28",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",