0xray 4.0.29 → 4.0.30
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/.xray/features.json +1 -1
- package/README.md +1 -0
- package/dist/CHANGELOG.md +8 -0
- package/dist/README.md +1 -0
- package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/llms.txt +1 -0
- package/package.json +2 -2
- package/scripts/node/install-bridges.cjs +120 -12
- package/scripts/node/setup.cjs +80 -71
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/xray/features.json +1 -1
package/.grok-plugin/plugin.json
CHANGED
package/.xray/features.json
CHANGED
package/README.md
CHANGED
|
@@ -52,6 +52,7 @@ Docs: [guides/autonomy-command](docs-site/docs/guides/autonomy-command.md) · Sk
|
|
|
52
52
|
| Version | Highlights |
|
|
53
53
|
|---------|------------|
|
|
54
54
|
| **Unreleased** | Fasten is **foundry-plant/0**: builtin plant is mill+inspect only. `foundry.json` `"plant": "@0xray/blip"` (aliases `"plant": "blip"` / `"plant": "sound"`) fastens whatever that mill declares (looker / vibe / mixer live in the mill). Nested mill `@0xray/foundry@0.1.12`. CLI shims `foundry blip\|sound` remain (0.1.11+). Shop plant first-class (`shop-extract`, `shop-witness`, `shop-pin` + `foundry.json` `shopPlant`). |
|
|
55
|
+
| **4.0.30** | Fixes 4.0.29: `npx 0xray wear` and `setup` work outside a git checkout again. They write the 4.0.28 project setup, skip only Cursor hooks, and print one warning. Inside a git checkout they restore the 4.0.28 project setup, and `wear` adds Cursor hooks plus the unwear snapshot. Companion `@0xray/grok-bot` 0.1.8. Released 2026-09-28. |
|
|
55
56
|
| **4.0.29** | `npm install` only creates the relative `node_modules/@0xray/repertoire` link to the vendored repertoire and prints `npx 0xray wear`. Run `npx 0xray wear` after install. Wear writes only the consumer project's `.cursor/hooks.json` (installed dist hooks, beside user entries); `npx 0xray unwear` restores the snapshot. Companion `@0xray/grok-bot` 0.1.8. Released 2026-09-28. |
|
|
56
57
|
| **4.0.28** | MCP servers start through `scripts/node/mcp-launch.cjs` and only see PATH, HOME, XRAY_ROOT, plus names on their keep list. Tokens such as NPM_TOKEN are not inherited. User env values stay out of argv. Postinstall keeps user edits to AGENTS.md, .mcp.json, and opencode.json. `house init` does not copy EXAMPLE.md; doctor FAILs while `house/EXAMPLE.md` exists. Inspect adds a machinePlugin check. The Cursor hook defaults XRAY_ROOT to the suit. Companion `@0xray/grok-bot` 0.1.7. Released 2026-09-27. |
|
|
57
58
|
| **4.0.27** | Host compact proof needs a generation id and a numeric usage percent, and the same preCompact receipt is mirrored to nested consumer wear roots. Memory scoring: [docs/memory-scoring.md](docs/memory-scoring.md) (orchestrator links it). Companion `@0xray/grok-bot` 0.1.6: general page vs `house/` overlay, `templates/house/`, `grok-bot house init`, doctor `GROK_BOT_HOUSE` or walk-up. Released 2026-09-26. |
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -41,6 +41,14 @@ The format is based on [Conventional Commits](https://www.conventionalcommits.or
|
|
|
41
41
|
- Archive root `integrations/` costume SKILL dump → `docs/archive/integrations-costume/`. Live wear is `src/integrations`.
|
|
42
42
|
- Archive root `commands/` stale copy → `docs/archive/commands-copy/`. Live wear is `src/opencode/commands`.
|
|
43
43
|
|
|
44
|
+
## [4.0.30] - 2026-09-28
|
|
45
|
+
|
|
46
|
+
Next patch after npm `4.0.29`. Released 2026-09-28.
|
|
47
|
+
|
|
48
|
+
Fixes the 4.0.29 regression where `npx 0xray wear` and `npx 0xray setup` exited 1 with `cursor-wear: not a git work tree` outside a git checkout (#147). Outside a git checkout, both commands again write the 4.0.28 consumer project setup and skip only Cursor hooks, with one stderr line: `cursor-wear: hooks skipped because this folder is not a git checkout`. Inside a git checkout, `wear` and `setup` restore the 4.0.28 project setup that 4.0.29 had dropped: managed `AGENTS.md`, `.gitignore` entries, `.xray` config, the `node_modules/@0xray/repertoire` link, the mill/inspect plant, chat bridges, the `.opencode/skills` sync, and the `dist` / `scripts` links. `wear` then adds the Cursor hooks, including the six hook scripts, and the `.xray/state/cursor-hook-wear/` snapshot. Postinstall is unchanged: it links the vendored repertoire and prints `npx 0xray wear`. Companion package `@0xray/grok-bot` is unchanged at 0.1.8.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
44
52
|
## [4.0.29] - 2026-09-28
|
|
45
53
|
|
|
46
54
|
Next patch after npm `4.0.28`. Released 2026-09-28.
|
package/dist/README.md
CHANGED
|
@@ -52,6 +52,7 @@ Docs: [guides/autonomy-command](docs-site/docs/guides/autonomy-command.md) · Sk
|
|
|
52
52
|
| Version | Highlights |
|
|
53
53
|
|---------|------------|
|
|
54
54
|
| **Unreleased** | Fasten is **foundry-plant/0**: builtin plant is mill+inspect only. `foundry.json` `"plant": "@0xray/blip"` (aliases `"plant": "blip"` / `"plant": "sound"`) fastens whatever that mill declares (looker / vibe / mixer live in the mill). Nested mill `@0xray/foundry@0.1.12`. CLI shims `foundry blip\|sound` remain (0.1.11+). Shop plant first-class (`shop-extract`, `shop-witness`, `shop-pin` + `foundry.json` `shopPlant`). |
|
|
55
|
+
| **4.0.30** | Fixes 4.0.29: `npx 0xray wear` and `setup` work outside a git checkout again. They write the 4.0.28 project setup, skip only Cursor hooks, and print one warning. Inside a git checkout they restore the 4.0.28 project setup, and `wear` adds Cursor hooks plus the unwear snapshot. Companion `@0xray/grok-bot` 0.1.8. Released 2026-09-28. |
|
|
55
56
|
| **4.0.29** | `npm install` only creates the relative `node_modules/@0xray/repertoire` link to the vendored repertoire and prints `npx 0xray wear`. Run `npx 0xray wear` after install. Wear writes only the consumer project's `.cursor/hooks.json` (installed dist hooks, beside user entries); `npx 0xray unwear` restores the snapshot. Companion `@0xray/grok-bot` 0.1.8. Released 2026-09-28. |
|
|
56
57
|
| **4.0.28** | MCP servers start through `scripts/node/mcp-launch.cjs` and only see PATH, HOME, XRAY_ROOT, plus names on their keep list. Tokens such as NPM_TOKEN are not inherited. User env values stay out of argv. Postinstall keeps user edits to AGENTS.md, .mcp.json, and opencode.json. `house init` does not copy EXAMPLE.md; doctor FAILs while `house/EXAMPLE.md` exists. Inspect adds a machinePlugin check. The Cursor hook defaults XRAY_ROOT to the suit. Companion `@0xray/grok-bot` 0.1.7. Released 2026-09-27. |
|
|
57
58
|
| **4.0.27** | Host compact proof needs a generation id and a numeric usage percent, and the same preCompact receipt is mirrored to nested consumer wear roots. Memory scoring: [docs/memory-scoring.md](docs/memory-scoring.md) (orchestrator links it). Companion `@0xray/grok-bot` 0.1.6: general page vs `house/` overlay, `templates/house/`, `grok-bot house init`, doctor `GROK_BOT_HOUSE` or walk-up. Released 2026-09-26. |
|
package/llms.txt
CHANGED
|
@@ -14,6 +14,7 @@ Default consumer wear is **mill plant** (`mill` + `inspect`), not a 45-skill / 4
|
|
|
14
14
|
- `@0xray/grok-bot`: the general page is `grok-bot/OP-PROC.md`. The team overlay is `house/` and is not in that npm pack. `templates/house/` ships. `grok-bot house init` copies the template and refuses to overwrite. Doctor uses `GROK_BOT_HOUSE` when set, otherwise walks up from the working directory for `house/HOUSE.md`.
|
|
15
15
|
- MCP servers start through `scripts/node/mcp-launch.cjs`. They see PATH, HOME, and XRAY_ROOT, plus the names on their keep list. Tokens such as NPM_TOKEN are not inherited. User env values stay out of argv. Postinstall keeps user edits to AGENTS.md, `.mcp.json`, and `opencode.json`. `house init` does not copy EXAMPLE.md. Doctor FAILs while `house/EXAMPLE.md` exists. Inspect has a machinePlugin check. The Cursor hook defaults XRAY_ROOT to the suit directory.
|
|
16
16
|
- `npm install` only creates the relative `node_modules/@0xray/repertoire` link to the vendored repertoire and prints `npx 0xray wear`. Run `npx 0xray wear` after install; it writes only the consumer project's `.cursor/hooks.json`. `npx 0xray unwear` restores the pre-wear snapshot.
|
|
17
|
+
- 4.0.30: `npx 0xray wear` and `setup` also work outside a git checkout. They write the 4.0.28 project setup and skip only Cursor hooks, with one warning. In a git checkout they write the 4.0.28 project setup plus Cursor hooks.
|
|
17
18
|
|
|
18
19
|
- `npx @0xray/foundry mint --skip-live` — re-fasten mill plant, then inspect.
|
|
19
20
|
- `npx @0xray/foundry inspect --skip-live` — plant-vs-worn, receipt, CI. Chat is not a receipt.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "0xray",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.30",
|
|
4
4
|
"description": "Multi-agent orchestration and Codex governance for OpenCode, Hermes, Grok Build, and OpenClaw",
|
|
5
5
|
"readme": "README.md",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"test:miscellaneous": "npm test -- src/__tests__/unit/blocked-test.test.ts",
|
|
83
83
|
"test:grok-bot": "npm test -- src/__tests__/unit/grok-bot-seat-doctor.test.ts src/__tests__/unit/grok-bot-op-proc-map.test.ts src/__tests__/unit/lead-cadence.test.ts src/__tests__/unit/grok-bot-auto-review-policy.test.ts",
|
|
84
84
|
"test:quick": "npm test -- src/__tests__/integration/boot-orchestrator.integration.test.ts src/__tests__/unit/config-loader.test.ts src/__tests__/unit/state-manager.test.ts",
|
|
85
|
-
"test:comprehensive": "npm run typecheck && npm run test:unit && npm run test:core-framework && npm run test:security && npm run test:performance && npm run test:session-management && npm run test:code-analysis && npm run test:processors && npm run test:miscellaneous && npm test -- src/__tests__/unit/llm-governance-provider.test.ts src/__tests__/unit/mcp-server-smoke.test.ts src/__tests__/unit/cursor-hooks.test.ts src/__tests__/unit/host-vs-mill-score.test.ts && npm run test:grok-bot",
|
|
85
|
+
"test:comprehensive": "npm run typecheck && npm run test:unit && npm run test:core-framework && npm run test:security && npm run test:performance && npm run test:session-management && npm run test:code-analysis && npm run test:processors && npm run test:miscellaneous && npm test -- src/__tests__/unit/llm-governance-provider.test.ts src/__tests__/unit/mcp-server-smoke.test.ts src/__tests__/unit/cursor-hooks.test.ts src/__tests__/unit/host-vs-mill-score.test.ts src/__tests__/unit/wear-pack-file-list.test.ts && npm run test:grok-bot",
|
|
86
86
|
"test:integration-all": "npm test -- src/__tests__/integration/",
|
|
87
87
|
"test:performance-all": "npm test -- src/__tests__/performance/ src/__tests__/unit/performance-system.test.ts src/__tests__/unit/benchmark.test.ts src/__tests__/unit/analytics.test.ts",
|
|
88
88
|
"test:agents-all": "echo 'Legacy agents test entry retired'",
|
|
@@ -1615,11 +1615,11 @@ function userBytesBeforeWear(previousText) {
|
|
|
1615
1615
|
return stripOwnedHookEntries(previousText);
|
|
1616
1616
|
}
|
|
1617
1617
|
|
|
1618
|
-
function
|
|
1618
|
+
function classifyCursorWearGit(targetDir) {
|
|
1619
1619
|
try {
|
|
1620
1620
|
execFileSync("git", ["--version"], { stdio: "ignore" });
|
|
1621
1621
|
} catch {
|
|
1622
|
-
|
|
1622
|
+
return "missing";
|
|
1623
1623
|
}
|
|
1624
1624
|
let bare = "";
|
|
1625
1625
|
try {
|
|
@@ -1629,9 +1629,9 @@ function assertCursorWearGit(targetDir) {
|
|
|
1629
1629
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1630
1630
|
}).trim();
|
|
1631
1631
|
} catch {
|
|
1632
|
-
|
|
1632
|
+
return "not-work-tree";
|
|
1633
1633
|
}
|
|
1634
|
-
if (bare === "true")
|
|
1634
|
+
if (bare === "true") return "bare";
|
|
1635
1635
|
let inside = "";
|
|
1636
1636
|
try {
|
|
1637
1637
|
inside = execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
@@ -1640,9 +1640,98 @@ function assertCursorWearGit(targetDir) {
|
|
|
1640
1640
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1641
1641
|
}).trim();
|
|
1642
1642
|
} catch {
|
|
1643
|
-
|
|
1643
|
+
return "not-work-tree";
|
|
1644
|
+
}
|
|
1645
|
+
if (inside !== "true") return "not-work-tree";
|
|
1646
|
+
return "ok";
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
function assertCursorWearGit(targetDir) {
|
|
1650
|
+
const kind = classifyCursorWearGit(targetDir);
|
|
1651
|
+
if (kind === "missing") throw new Error("cursor-wear: git is missing");
|
|
1652
|
+
if (kind === "bare") throw new Error("cursor-wear: bare repository");
|
|
1653
|
+
if (kind === "not-work-tree") throw new Error("cursor-wear: not a git work tree");
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
const CURSOR_HOOKS_SKIPPED_LINE =
|
|
1657
|
+
"cursor-wear: hooks skipped because this folder is not a git checkout\n";
|
|
1658
|
+
|
|
1659
|
+
function syncSetupSkillsAndRootLinks(packageRoot, targetDir) {
|
|
1660
|
+
require("./setup.cjs").syncSetupSkillsAndRootLinks(packageRoot, targetDir);
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
function setupSkillMirrorNames(packageRoot) {
|
|
1664
|
+
const skillsSource = fs.existsSync(path.join(packageRoot, "src", "skills"))
|
|
1665
|
+
? path.join(packageRoot, "src", "skills")
|
|
1666
|
+
: path.join(packageRoot, "dist", "skills");
|
|
1667
|
+
if (!fs.existsSync(skillsSource)) return new Set();
|
|
1668
|
+
const names = new Set();
|
|
1669
|
+
for (const entry of fs.readdirSync(skillsSource, { withFileTypes: true })) {
|
|
1670
|
+
if (!entry.isDirectory()) continue;
|
|
1671
|
+
if (fs.existsSync(path.join(skillsSource, entry.name, "SKILL.md"))) names.add(entry.name);
|
|
1644
1672
|
}
|
|
1645
|
-
|
|
1673
|
+
return names;
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
/** The 4.0.28 skill mirror is not a consumer costume. Any other extra name still throws. */
|
|
1677
|
+
function isSetupSkillMirrorDump(err, packageRoot) {
|
|
1678
|
+
if (!err || err.code !== "FOUNDRY_COSTUME_DUMP") return false;
|
|
1679
|
+
if (!Array.isArray(err.extraSkills) || err.extraSkills.length === 0) return false;
|
|
1680
|
+
if (Array.isArray(err.extraAgents) && err.extraAgents.length > 0) return false;
|
|
1681
|
+
const mirrored = setupSkillMirrorNames(packageRoot);
|
|
1682
|
+
return err.extraSkills.every((name) => mirrored.has(name));
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
function packageShipsConsumerSuit(packageRoot) {
|
|
1686
|
+
return fs.existsSync(path.join(packageRoot, "AGENTS-consumer.md"));
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
/**
|
|
1690
|
+
* 4.0.28 consumer postinstall files: AGENTS.md, .gitignore, repertoire link,
|
|
1691
|
+
* .xray config, bridges, mill plant, then the setup.cjs skill mirror and
|
|
1692
|
+
* dist/scripts links. Does not install Cursor hooks or git hooks.
|
|
1693
|
+
* Existing user files follow the 4.0.28 guards inside those functions.
|
|
1694
|
+
*/
|
|
1695
|
+
function installConsumerProjectFiles(packageRoot, targetDir, log) {
|
|
1696
|
+
const write = typeof log === "function" ? log : () => {};
|
|
1697
|
+
if (!isConsumerInstall(packageRoot, targetDir) || !packageShipsConsumerSuit(packageRoot)) {
|
|
1698
|
+
return false;
|
|
1699
|
+
}
|
|
1700
|
+
const { deployManagedAgents } = require("./postinstall.cjs");
|
|
1701
|
+
const { applyConsumerGitignore } = require("./consumer-gitignore.cjs");
|
|
1702
|
+
const { mintConsumerSuit } = require("../foundry/mint-suit.cjs");
|
|
1703
|
+
deployManagedAgents(packageRoot, targetDir, write);
|
|
1704
|
+
applyConsumerGitignore(targetDir, packageRoot);
|
|
1705
|
+
wearVendoredRepertoire(packageRoot, targetDir, write);
|
|
1706
|
+
deployXrayConfig(targetDir, packageRoot, write);
|
|
1707
|
+
deployProjectMcpJson(targetDir, write);
|
|
1708
|
+
mergeOpencodeJson(targetDir, packageRoot, write);
|
|
1709
|
+
installOpencodeBridge(targetDir, packageRoot, write);
|
|
1710
|
+
installGrokBridge(targetDir, packageRoot, write);
|
|
1711
|
+
installHermesBridge(targetDir, packageRoot, write);
|
|
1712
|
+
installOpenclawBridge(targetDir, packageRoot, write);
|
|
1713
|
+
try {
|
|
1714
|
+
mintConsumerSuit(packageRoot, targetDir, write);
|
|
1715
|
+
} catch (err) {
|
|
1716
|
+
if (!isSetupSkillMirrorDump(err, packageRoot)) throw err;
|
|
1717
|
+
}
|
|
1718
|
+
syncSetupSkillsAndRootLinks(packageRoot, targetDir);
|
|
1719
|
+
return true;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
/**
|
|
1723
|
+
* 4.0.28 consumer postinstall, minus Cursor hooks and git hooks.
|
|
1724
|
+
* Used only when the folder is not a git work tree.
|
|
1725
|
+
*/
|
|
1726
|
+
function wearSuitSkippingCursorHooks(packageRoot, targetDir, log) {
|
|
1727
|
+
const write = typeof log === "function" ? log : () => {};
|
|
1728
|
+
if (!installConsumerProjectFiles(packageRoot, targetDir, write)) {
|
|
1729
|
+
if (!isConsumerInstall(packageRoot, targetDir)) {
|
|
1730
|
+
wearVendoredRepertoire(packageRoot, targetDir, write);
|
|
1731
|
+
}
|
|
1732
|
+
syncSetupSkillsAndRootLinks(packageRoot, targetDir);
|
|
1733
|
+
}
|
|
1734
|
+
process.stderr.write(CURSOR_HOOKS_SKIPPED_LINE);
|
|
1646
1735
|
}
|
|
1647
1736
|
|
|
1648
1737
|
function isGitTracked(targetDir, rel) {
|
|
@@ -1794,7 +1883,16 @@ function wearCursorHooks(targetDir, packageRoot, log, opts) {
|
|
|
1794
1883
|
const options = opts || {};
|
|
1795
1884
|
const resolvedTarget = path.resolve(targetDir);
|
|
1796
1885
|
const resolvedPackage = path.resolve(packageRoot);
|
|
1886
|
+
if (classifyCursorWearGit(resolvedTarget) === "not-work-tree") {
|
|
1887
|
+
wearSuitSkippingCursorHooks(resolvedPackage, resolvedTarget, write);
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1797
1890
|
assertCursorWearGit(resolvedTarget);
|
|
1891
|
+
if (options.suit !== false) {
|
|
1892
|
+
if (!installConsumerProjectFiles(resolvedPackage, resolvedTarget, write)) {
|
|
1893
|
+
syncSetupSkillsAndRootLinks(resolvedPackage, resolvedTarget);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1798
1896
|
if (!isConsumerInstall(resolvedPackage, resolvedTarget) || !consumerDistHooksReady(resolvedPackage)) {
|
|
1799
1897
|
return fastenCursorHooksAt(resolvedTarget, resolvedPackage, write);
|
|
1800
1898
|
}
|
|
@@ -1826,11 +1924,14 @@ function wearCursorHooks(targetDir, packageRoot, log, opts) {
|
|
|
1826
1924
|
snap.meta.also = linkedWearRoots(resolvedTarget);
|
|
1827
1925
|
saveWearState(snap.paths, snap.meta);
|
|
1828
1926
|
for (const extra of snap.meta.also) {
|
|
1829
|
-
wearCursorHooks(extra, resolvedPackage, write, { outerRoots: false });
|
|
1927
|
+
wearCursorHooks(extra, resolvedPackage, write, { outerRoots: false, suit: false });
|
|
1830
1928
|
process.stdout.write(`cursor-wear: wrote outer hooks at ${extra}\n`);
|
|
1831
1929
|
}
|
|
1832
1930
|
saveWearState(snap.paths, snap.meta);
|
|
1833
1931
|
}
|
|
1932
|
+
if (options.suit !== false && packageShipsConsumerSuit(resolvedPackage)) {
|
|
1933
|
+
fastenCursorHookScripts(resolvedTarget, resolvedPackage, write);
|
|
1934
|
+
}
|
|
1834
1935
|
write("cursor-bridge", "hooks.json wired to installed dist", "info", { path: hooksPath });
|
|
1835
1936
|
return hooksPath;
|
|
1836
1937
|
}
|
|
@@ -1959,12 +2060,19 @@ function setupProjectBridges(opts) {
|
|
|
1959
2060
|
: () => {
|
|
1960
2061
|
/* noop */
|
|
1961
2062
|
};
|
|
2063
|
+
if (classifyCursorWearGit(targetDir) === "not-work-tree") {
|
|
2064
|
+
wearSuitSkippingCursorHooks(packageRoot, targetDir, log);
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
1962
2067
|
assertSetupGit(targetDir);
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
2068
|
+
if (!installConsumerProjectFiles(packageRoot, targetDir, log)) {
|
|
2069
|
+
syncSetupSkillsAndRootLinks(packageRoot, targetDir);
|
|
2070
|
+
deployProjectMcpJson(targetDir, log);
|
|
2071
|
+
installOpencodeBridge(targetDir, packageRoot, log);
|
|
2072
|
+
installGrokBridge(targetDir, packageRoot, log);
|
|
2073
|
+
installHermesBridge(targetDir, packageRoot, log);
|
|
2074
|
+
installOpenclawBridge(targetDir, packageRoot, log);
|
|
2075
|
+
}
|
|
1968
2076
|
if (opts.gitHooks === true) installGitHooks(packageRoot, log, targetDir);
|
|
1969
2077
|
}
|
|
1970
2078
|
|
package/scripts/node/setup.cjs
CHANGED
|
@@ -3,6 +3,84 @@
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
|
|
6
|
+
function syncSetupSkillsAndRootLinks(packageRoot, targetDir) {
|
|
7
|
+
/* 1. Sync core skills from src/skills/ (dev) or dist/skills/ (consumer) → .opencode/skills/ [P3-SKILLS-DE-DUP-SCOPE-AND-EXEC-01: orchestrator package SSOT canonical src/skills/orchestrator/SKILL.md; mirror .opencode/skills/orchestrator/ is built output of this logic; see paired guarded fw in status.ts getSkillsList + mapping append + deep ref 2026-05-26 authority for one-package dedup under pivoted surgical plan]
|
|
8
|
+
[P3-SKILLS-DE-DUP-RESEARCHER-FOLLOW-01: researcher package SSOT canonical src/skills/researcher/SKILL.md (high-value per deep ref + YML precedent + playbook P3-SKILLS-FOLLOW-01); mirror .opencode/skills/researcher/ is built output of this logic; see paired guarded fw in status.ts + rich append + YML @ harness-codex verification (FORCE exercised P3-YML + codex-enforcement + 100/60/0 + 3 subagents tracked + 0 hot + 3-hot re-establish + all prior green) + deep ref 2026-05-26 + Phase 3 Pivot + Term 61 + user's "create a todo list. spawn subagents..." + 6/6+7/7 + YML. Governance-visible hook for skills SSOT at install layer. Silent, additive, reversible, no behavior change, fw/echo only.]
|
|
9
|
+
[P3-SKILLS-FOLLOW-02: code-review package SSOT canonical src/skills/code-review/SKILL.md (next high-value per deep ref "parallel small batches" + @architect scoping rec 2 + YML @ "Ready for next" + this P3-SKILLS-FOLLOW-02 on user's spawn command); mirror .opencode/skills/code-review/ is built output of this logic; see paired guarded fw "P3-SKILLS-FOLLOW-02-code-review-ssot-preferred" in status.ts (after researcher) + rich append docs/reflections/p3-skills-follow-02-code-review-2026-05-27.md + YML @ harness-codex verification + 0 hot + 3-hot + all ties + ps 0 + this work (2-file surgical edit, harness post, mapping append after latest ~17099+, todo advance 1, spawn replacement, self-audit 100%, green + ready) + deep ref 2026-05-26 + Phase 3 Pivot + Term 61 + 6/6+7/7 + YML. Governance-visible hook for skills SSOT at install layer for code-review. Silent, additive, reversible, no behavior change, fw/echo only. "The box contains its builders. The relay is hot."] */
|
|
10
|
+
const skillsSource = fs.existsSync(path.join(packageRoot, "src", "skills"))
|
|
11
|
+
? path.join(packageRoot, "src", "skills")
|
|
12
|
+
: path.join(packageRoot, "dist", "skills");
|
|
13
|
+
const skillsDest = path.join(targetDir, ".opencode", "skills");
|
|
14
|
+
|
|
15
|
+
if (fs.existsSync(skillsSource)) {
|
|
16
|
+
try {
|
|
17
|
+
if (!fs.existsSync(skillsDest)) fs.mkdirSync(skillsDest, { recursive: true });
|
|
18
|
+
const skillDirs = fs.readdirSync(skillsSource, { withFileTypes: true });
|
|
19
|
+
let copied = 0, skipped = 0;
|
|
20
|
+
for (const entry of skillDirs) {
|
|
21
|
+
if (!entry.isDirectory()) continue;
|
|
22
|
+
const skillMd = path.join(skillsSource, entry.name, "SKILL.md");
|
|
23
|
+
if (!fs.existsSync(skillMd)) continue;
|
|
24
|
+
const destMd = path.join(skillsDest, entry.name, "SKILL.md");
|
|
25
|
+
const destDir = path.dirname(destMd);
|
|
26
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
27
|
+
if (fs.existsSync(destMd)) {
|
|
28
|
+
const destContent = fs.readFileSync(destMd, "utf8");
|
|
29
|
+
if (destContent.includes("source: community")) { skipped++; continue; }
|
|
30
|
+
if (fs.statSync(skillMd).mtime <= fs.statSync(destMd).mtime) continue;
|
|
31
|
+
}
|
|
32
|
+
fs.copyFileSync(skillMd, destMd);
|
|
33
|
+
copied++;
|
|
34
|
+
}
|
|
35
|
+
console.log(`✅ Skills: ${copied} updated, ${skipped} community skills preserved`);
|
|
36
|
+
} catch (e) { console.warn(`⚠️ Skills sync: ${e.message}`); }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 4. Create scripts symlink
|
|
40
|
+
const scriptsSource = path.join(packageRoot, "scripts");
|
|
41
|
+
const scriptsDest = path.join(targetDir, "scripts");
|
|
42
|
+
|
|
43
|
+
if (fs.existsSync(scriptsSource)) {
|
|
44
|
+
try {
|
|
45
|
+
if (fs.existsSync(scriptsDest)) {
|
|
46
|
+
const stats = fs.lstatSync(scriptsDest);
|
|
47
|
+
if (stats.isSymbolicLink()) {
|
|
48
|
+
console.log("ℹ️ Scripts symlink: exists");
|
|
49
|
+
} else {
|
|
50
|
+
console.log("⚠️ Scripts dir exists but is not a symlink");
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
fs.symlinkSync(scriptsSource, scriptsDest, "dir");
|
|
54
|
+
console.log("✅ Scripts symlink: created");
|
|
55
|
+
}
|
|
56
|
+
} catch (e) { console.warn(`⚠️ Scripts symlink: ${e.message}`); }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 5. Create dist symlink
|
|
60
|
+
const distSource = path.join(packageRoot, "dist");
|
|
61
|
+
const distDest = path.join(targetDir, "dist");
|
|
62
|
+
|
|
63
|
+
if (fs.existsSync(distSource)) {
|
|
64
|
+
try {
|
|
65
|
+
if (fs.existsSync(distDest)) {
|
|
66
|
+
const stats = fs.lstatSync(distDest);
|
|
67
|
+
if (stats.isSymbolicLink()) {
|
|
68
|
+
console.log("ℹ️ Dist symlink: exists");
|
|
69
|
+
} else {
|
|
70
|
+
console.log("⚠️ Dist exists but is not a symlink");
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
fs.symlinkSync(distSource, distDest, "dir");
|
|
74
|
+
console.log("✅ Dist symlink: created");
|
|
75
|
+
}
|
|
76
|
+
} catch (e) { console.warn(`⚠️ Dist symlink: ${e.message}`); }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = { syncSetupSkillsAndRootLinks };
|
|
82
|
+
|
|
83
|
+
if (require.main === module) {
|
|
6
84
|
const packageRoot = path.join(__dirname, "..", "..");
|
|
7
85
|
const homeDir = require("os").homedir();
|
|
8
86
|
|
|
@@ -43,37 +121,7 @@ if (hasHermes) {
|
|
|
43
121
|
* Extended header for next high-value package (code-review). src/skills/code-review/SKILL.md canonical SSOT; .opencode/skills/code-review/ built mirror of this sync logic. See paired guarded fw log "P3-SKILLS-FOLLOW-02-code-review-ssot-preferred" in status.ts getSkillsList (inserted after researcher block) + rich append docs/reflections/p3-skills-follow-02-code-review-2026-05-27.md (per AGENTS) + CGT/Governance-visible for YML @ harness-codex verification + 0 hot + 3-hot re-establish + all ties to spawn command + deep ref + pivot + Term 61 + 6/6+7/7 + YML + ps 0 + this P3-SKILLS-FOLLOW-02 full work (2-file surgical, harness post green tsc 0 new on touched, mapping append after latest, todo advance exactly 1, spawn replacement to maintain 3-hot, self-audit 100%) + verification + "the box contains its builders. The relay is hot.". 2 files max total for this follow-02. Highly modular (100% prior P3-SKILLS/YML/7th pattern reuse exactly inside existing sync logic). Fully reversible (targeted delete of notes restores exact prior). fw/echo discipline. AGENTS org (scripts/ for sh/cjs). Term 61 surgical forward motion held (no bloat, pure on actual dedup). "the box contains its builders". Green + ready. Subagent ID for resume.
|
|
44
122
|
*/
|
|
45
123
|
|
|
46
|
-
|
|
47
|
-
[P3-SKILLS-DE-DUP-RESEARCHER-FOLLOW-01: researcher package SSOT canonical src/skills/researcher/SKILL.md (high-value per deep ref + YML precedent + playbook P3-SKILLS-FOLLOW-01); mirror .opencode/skills/researcher/ is built output of this logic; see paired guarded fw in status.ts + rich append + YML @ harness-codex verification (FORCE exercised P3-YML + codex-enforcement + 100/60/0 + 3 subagents tracked + 0 hot + 3-hot re-establish + all prior green) + deep ref 2026-05-26 + Phase 3 Pivot + Term 61 + user's "create a todo list. spawn subagents..." + 6/6+7/7 + YML. Governance-visible hook for skills SSOT at install layer. Silent, additive, reversible, no behavior change, fw/echo only.]
|
|
48
|
-
[P3-SKILLS-FOLLOW-02: code-review package SSOT canonical src/skills/code-review/SKILL.md (next high-value per deep ref "parallel small batches" + @architect scoping rec 2 + YML @ "Ready for next" + this P3-SKILLS-FOLLOW-02 on user's spawn command); mirror .opencode/skills/code-review/ is built output of this logic; see paired guarded fw "P3-SKILLS-FOLLOW-02-code-review-ssot-preferred" in status.ts (after researcher) + rich append docs/reflections/p3-skills-follow-02-code-review-2026-05-27.md + YML @ harness-codex verification + 0 hot + 3-hot + all ties + ps 0 + this work (2-file surgical edit, harness post, mapping append after latest ~17099+, todo advance 1, spawn replacement, self-audit 100%, green + ready) + deep ref 2026-05-26 + Phase 3 Pivot + Term 61 + 6/6+7/7 + YML. Governance-visible hook for skills SSOT at install layer for code-review. Silent, additive, reversible, no behavior change, fw/echo only. "The box contains its builders. The relay is hot."] */
|
|
49
|
-
const skillsSource = fs.existsSync(path.join(packageRoot, "src", "skills"))
|
|
50
|
-
? path.join(packageRoot, "src", "skills")
|
|
51
|
-
: path.join(packageRoot, "dist", "skills");
|
|
52
|
-
const skillsDest = path.join(targetDir, ".opencode", "skills");
|
|
53
|
-
|
|
54
|
-
if (fs.existsSync(skillsSource)) {
|
|
55
|
-
try {
|
|
56
|
-
if (!fs.existsSync(skillsDest)) fs.mkdirSync(skillsDest, { recursive: true });
|
|
57
|
-
const skillDirs = fs.readdirSync(skillsSource, { withFileTypes: true });
|
|
58
|
-
let copied = 0, skipped = 0;
|
|
59
|
-
for (const entry of skillDirs) {
|
|
60
|
-
if (!entry.isDirectory()) continue;
|
|
61
|
-
const skillMd = path.join(skillsSource, entry.name, "SKILL.md");
|
|
62
|
-
if (!fs.existsSync(skillMd)) continue;
|
|
63
|
-
const destMd = path.join(skillsDest, entry.name, "SKILL.md");
|
|
64
|
-
const destDir = path.dirname(destMd);
|
|
65
|
-
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
66
|
-
if (fs.existsSync(destMd)) {
|
|
67
|
-
const destContent = fs.readFileSync(destMd, "utf8");
|
|
68
|
-
if (destContent.includes("source: community")) { skipped++; continue; }
|
|
69
|
-
if (fs.statSync(skillMd).mtime <= fs.statSync(destMd).mtime) continue;
|
|
70
|
-
}
|
|
71
|
-
fs.copyFileSync(skillMd, destMd);
|
|
72
|
-
copied++;
|
|
73
|
-
}
|
|
74
|
-
console.log(`✅ Skills: ${copied} updated, ${skipped} community skills preserved`);
|
|
75
|
-
} catch (e) { console.warn(`⚠️ Skills sync: ${e.message}`); }
|
|
76
|
-
}
|
|
124
|
+
syncSetupSkillsAndRootLinks(packageRoot, targetDir);
|
|
77
125
|
|
|
78
126
|
// 2. Handle opencode.json merge
|
|
79
127
|
const rootOpencodeJson = path.join(packageRoot, "opencode.json");
|
|
@@ -121,46 +169,6 @@ if (fs.existsSync(pluginSource)) {
|
|
|
121
169
|
console.log("ℹ️ Plugin source not found (build may be needed)");
|
|
122
170
|
}
|
|
123
171
|
|
|
124
|
-
// 4. Create scripts symlink
|
|
125
|
-
const scriptsSource = path.join(packageRoot, "scripts");
|
|
126
|
-
const scriptsDest = path.join(targetDir, "scripts");
|
|
127
|
-
|
|
128
|
-
if (fs.existsSync(scriptsSource)) {
|
|
129
|
-
try {
|
|
130
|
-
if (fs.existsSync(scriptsDest)) {
|
|
131
|
-
const stats = fs.lstatSync(scriptsDest);
|
|
132
|
-
if (stats.isSymbolicLink()) {
|
|
133
|
-
console.log("ℹ️ Scripts symlink: exists");
|
|
134
|
-
} else {
|
|
135
|
-
console.log("⚠️ Scripts dir exists but is not a symlink");
|
|
136
|
-
}
|
|
137
|
-
} else {
|
|
138
|
-
fs.symlinkSync(scriptsSource, scriptsDest, "dir");
|
|
139
|
-
console.log("✅ Scripts symlink: created");
|
|
140
|
-
}
|
|
141
|
-
} catch (e) { console.warn(`⚠️ Scripts symlink: ${e.message}`); }
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// 5. Create dist symlink
|
|
145
|
-
const distSource = path.join(packageRoot, "dist");
|
|
146
|
-
const distDest = path.join(targetDir, "dist");
|
|
147
|
-
|
|
148
|
-
if (fs.existsSync(distSource)) {
|
|
149
|
-
try {
|
|
150
|
-
if (fs.existsSync(distDest)) {
|
|
151
|
-
const stats = fs.lstatSync(distDest);
|
|
152
|
-
if (stats.isSymbolicLink()) {
|
|
153
|
-
console.log("ℹ️ Dist symlink: exists");
|
|
154
|
-
} else {
|
|
155
|
-
console.log("⚠️ Dist exists but is not a symlink");
|
|
156
|
-
}
|
|
157
|
-
} else {
|
|
158
|
-
fs.symlinkSync(distSource, distDest, "dir");
|
|
159
|
-
console.log("✅ Dist symlink: created");
|
|
160
|
-
}
|
|
161
|
-
} catch (e) { console.warn(`⚠️ Dist symlink: ${e.message}`); }
|
|
162
|
-
}
|
|
163
|
-
|
|
164
172
|
// 6. Convert MCP paths in consumer opencode.json
|
|
165
173
|
const isConsumer = isConsumerInstall(packageRoot, targetDir);
|
|
166
174
|
const consumerPkgName = isConsumer
|
|
@@ -234,3 +242,4 @@ if (resolvedPackage !== resolvedTarget) {
|
|
|
234
242
|
}
|
|
235
243
|
|
|
236
244
|
console.log("\n✅ xray setup complete.\n");
|
|
245
|
+
}
|