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.
- package/.grok-plugin/plugin.json +1 -1
- package/.opencode/skills/orchestrator/SKILL.md +5 -5
- package/.opencode/skills/storyteller/SKILL.md +1 -1
- package/.xray/features.json +1 -1
- package/AGENTS.md +1 -1
- package/README.md +2 -0
- package/SKILLS.md +1 -1
- package/dist/AGENTS.md +1 -1
- package/dist/CHANGELOG.md +34 -0
- package/dist/README.md +2 -0
- package/dist/SKILLS.md +1 -1
- package/dist/integrations/cursor/README.md +3 -1
- package/dist/integrations/cursor/hooks/cursor-hook-utils.js +77 -7
- package/dist/integrations/cursor/hooks/pre-compact.js +22 -16
- package/dist/integrations/cursor/hooks/xray-cloud-hook.sh +1 -1
- package/dist/integrations/hooks/plates.cjs +7 -0
- package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/dist/memory-routing/plates.d.ts +1 -1
- package/dist/memory-routing/plates.js +1 -0
- package/dist/skills/orchestrator/SKILL.md +5 -5
- package/dist/skills/storyteller/SKILL.md +1 -1
- package/docs-site/docs/plates/house.md +50 -0
- package/docs-site/docs/plates/index.md +1 -1
- package/llms.txt +6 -1
- package/package.json +3 -2
- package/scripts/foundry/inspect.mjs +47 -2
- package/scripts/node/bridge-mcp-wiring.cjs +320 -29
- package/scripts/node/consumer-install-smoke.mjs +37 -3
- package/scripts/node/install-bridges.cjs +34 -19
- package/scripts/node/mcp-launch.cjs +70 -0
- package/scripts/node/postinstall.cjs +42 -13
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/src/skills/orchestrator/SKILL.md +5 -5
- package/src/skills/storyteller/SKILL.md +1 -1
- 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
|
|
44
|
-
|
|
45
|
-
fs.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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) {
|
|
@@ -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/
|
|
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 `
|
|
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.
|
|
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;
|
|
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:** `
|
|
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](
|
|
99
|
+
- Related Codex terms: [codex.json](../../../.xray/codex.json)
|
|
100
100
|
- Next story to write: [suggestion]
|
|
101
101
|
```
|
|
102
102
|
|