0xray 4.0.40 → 4.0.41

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 (129) hide show
  1. package/.grok-plugin/plugin.json +1 -1
  2. package/.opencode/agents/api-design.yml +31 -0
  3. package/.opencode/agents/architect.yml +15 -0
  4. package/.opencode/agents/architecture-patterns.yml +14 -0
  5. package/.opencode/agents/auto-format.yml +14 -0
  6. package/.opencode/agents/backend-engineer.yml +12 -0
  7. package/.opencode/agents/boot-orchestrator.yml +14 -0
  8. package/.opencode/agents/bug-triage-specialist.yml +15 -0
  9. package/.opencode/agents/code-analyzer.yml +12 -0
  10. package/.opencode/agents/code-reviewer.yml +14 -0
  11. package/.opencode/agents/content-creator.yml +12 -0
  12. package/.opencode/agents/database-engineer.yml +12 -0
  13. package/.opencode/agents/devops-engineer.yml +12 -0
  14. package/.opencode/agents/framework-compliance-audit.yml +14 -0
  15. package/.opencode/agents/frontend-engineer.yml +12 -0
  16. package/.opencode/agents/frontend-ui-ux-engineer.yml +12 -0
  17. package/.opencode/agents/git-workflow.yml +15 -0
  18. package/.opencode/agents/growth-strategist.yml +12 -0
  19. package/.opencode/agents/hermes-agent.yml +12 -0
  20. package/.opencode/agents/inference-improve.yml +12 -0
  21. package/.opencode/agents/lint.yml +14 -0
  22. package/.opencode/agents/log-monitor.yml +12 -0
  23. package/.opencode/agents/mobile-developer.yml +12 -0
  24. package/.opencode/agents/model-health-check.yml +12 -0
  25. package/.opencode/agents/multimodal-looker.yml +12 -0
  26. package/.opencode/agents/performance-analysis.yml +12 -0
  27. package/.opencode/agents/performance-engineer.yml +12 -0
  28. package/.opencode/agents/performance-optimization.yml +12 -0
  29. package/.opencode/agents/processor-pipeline.yml +14 -0
  30. package/.opencode/agents/project-analysis.yml +12 -0
  31. package/.opencode/agents/refactorer.yml +12 -0
  32. package/.opencode/agents/researcher.yml +12 -0
  33. package/.opencode/agents/security-auditor.yml +12 -0
  34. package/.opencode/agents/security-scan.yml +12 -0
  35. package/.opencode/agents/seo-consultant.yml +12 -0
  36. package/.opencode/agents/session-management.yml +12 -0
  37. package/.opencode/agents/state-manager.yml +12 -0
  38. package/.opencode/agents/storyteller.yml +12 -0
  39. package/.opencode/agents/strategist.yml +12 -0
  40. package/.opencode/agents/tech-writer.yml +12 -0
  41. package/.opencode/agents/testing-best-practices.yml +12 -0
  42. package/.opencode/agents/testing-lead.yml +12 -0
  43. package/.opencode/agents/ui-ux-design.yml +12 -0
  44. package/.opencode/codex.codex +8 -0
  45. package/.opencode/commands/auto-format.md +99 -0
  46. package/.opencode/commands/auto-summary-capture.md +90 -0
  47. package/.opencode/commands/dependency-audit.md +184 -0
  48. package/.opencode/commands/enforcer-daily-scan.md +137 -0
  49. package/.opencode/commands/framework-compliance-audit.md +205 -0
  50. package/.opencode/commands/interactive-validator.md +75 -0
  51. package/.opencode/commands/job-summary-logger.md +68 -0
  52. package/.opencode/commands/lint.md +11 -0
  53. package/.opencode/commands/mode-switch.md +95 -0
  54. package/.opencode/commands/model-health-check.md +186 -0
  55. package/.opencode/commands/performance-analysis.md +144 -0
  56. package/.opencode/commands/pre-commit-introspection.md +185 -0
  57. package/.opencode/commands/pre-commit-introspection.sh +133 -0
  58. package/.opencode/commands/security-scan.md +157 -0
  59. package/.opencode/commands/sisyphus-validation.md +128 -0
  60. package/.opencode/commands/summary-logger.md +83 -0
  61. package/.opencode/enforcer-config.json +282 -0
  62. package/.opencode/workflows/post-deployment-audit.yml +123 -0
  63. package/.xray/features.json +1 -1
  64. package/dist/CHANGELOG.md +16 -0
  65. package/dist/integrations/grok/hooks/grok-hook-utils.js +21 -1
  66. package/dist/integrations/grok/hooks/session-start.js +2 -20
  67. package/dist/integrations/hooks/goggles-mcp.mjs +36 -4
  68. package/dist/integrations/hooks/goggles-pipeline.mjs +55 -15
  69. package/dist/integrations/hooks/goggles-planes.json +9 -3
  70. package/dist/integrations/hooks/plates.cjs +22 -0
  71. package/dist/integrations/hooks/session-note-index.cjs +298 -0
  72. package/dist/integrations/hooks/session-note-index.mjs +22 -0
  73. package/dist/integrations/hooks/sleeve.cjs +335 -0
  74. package/dist/integrations/hooks/sleeve.mjs +18 -0
  75. package/dist/integrations/hooks/station-hook-runtime.cjs +205 -9
  76. package/dist/integrations/hooks/wake-cascade.cjs +102 -0
  77. package/dist/integrations/hooks/wake-cascade.mjs +16 -0
  78. package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  79. package/dist/memory-routing/plates.d.ts +1 -1
  80. package/dist/memory-routing/plates.js +1 -0
  81. package/docs-site/docs/plates/activity-log.md +1 -1
  82. package/docs-site/docs/plates/boot.md +2 -0
  83. package/docs-site/docs/plates/centrifuge.md +30 -0
  84. package/docs-site/docs/plates/cursor-compact.md +1 -1
  85. package/docs-site/docs/plates/glossary.md +1 -2
  86. package/docs-site/docs/plates/goggles.md +4 -0
  87. package/docs-site/docs/plates/governance.md +2 -0
  88. package/docs-site/docs/plates/grok-compact.md +1 -1
  89. package/docs-site/docs/plates/grokbot.md +1 -1
  90. package/docs-site/docs/plates/host-pack.md +2 -0
  91. package/docs-site/docs/plates/house.md +1 -1
  92. package/docs-site/docs/plates/index.md +3 -1
  93. package/docs-site/docs/plates/inference-files.md +1 -1
  94. package/docs-site/docs/plates/kept-line.md +1 -1
  95. package/docs-site/docs/plates/kits.md +2 -0
  96. package/docs-site/docs/plates/lens-gate.md +1 -1
  97. package/docs-site/docs/plates/lens-page.md +1 -1
  98. package/docs-site/docs/plates/live-mesh.md +1 -1
  99. package/docs-site/docs/plates/memory-recall.md +4 -0
  100. package/docs-site/docs/plates/notes-page.md +2 -1
  101. package/docs-site/docs/plates/orchestration.md +2 -0
  102. package/docs-site/docs/plates/package-face.md +1 -1
  103. package/docs-site/docs/plates/payload-heat.md +1 -1
  104. package/docs-site/docs/plates/pickup-stamp.md +1 -1
  105. package/docs-site/docs/plates/pre-tool.md +1 -1
  106. package/docs-site/docs/plates/processor.md +2 -0
  107. package/docs-site/docs/plates/record-map.md +2 -1
  108. package/docs-site/docs/plates/reflection-page.md +1 -1
  109. package/docs-site/docs/plates/reporting.md +2 -0
  110. package/docs-site/docs/plates/review.md +1 -1
  111. package/docs-site/docs/plates/routing.md +2 -0
  112. package/docs-site/docs/plates/session-capture.md +1 -1
  113. package/docs-site/docs/plates/site-manual.md +1 -1
  114. package/docs-site/docs/plates/stamp-plate.md +1 -1
  115. package/docs-site/docs/plates/station-card.md +4 -1
  116. package/docs-site/docs/plates/station-heat.md +1 -1
  117. package/docs-site/docs/plates/suit-organs.md +1 -1
  118. package/docs-site/docs/plates/suit-settings.md +1 -1
  119. package/docs-site/docs/plates/suit-wear.md +3 -1
  120. package/docs-site/docs/plates/suit.md +2 -0
  121. package/docs-site/docs/plates/trail-state.md +1 -1
  122. package/docs-site/docs/plates/work-fresh.md +1 -1
  123. package/docs-site/docs/plates/write-home.md +1 -1
  124. package/package.json +1 -1
  125. package/scripts/node/bridge-mcp-wiring.cjs +37 -4
  126. package/scripts/node/install-bridges.cjs +172 -19
  127. package/scripts/node/setup.cjs +2 -46
  128. package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
  129. package/xray/features.json +1 -1
@@ -32,6 +32,7 @@ const {
32
32
  maybeWriteOpenClawCliBackend,
33
33
  isEphemeralInstallRoot,
34
34
  enableMemoryRoutingIfResolves,
35
+ pinLauncherPackageRoot,
35
36
  XRAY_MCP_SERVERS,
36
37
  } = require("./bridge-mcp-wiring.cjs");
37
38
 
@@ -334,6 +335,34 @@ function mergeOpencodeJson(targetDir, packageRoot, log) {
334
335
  }
335
336
  }
336
337
 
338
+ function settlePackageRoot(packageRoot, targetDir) {
339
+ const resolved = path.resolve(packageRoot || ".");
340
+ if (!targetDir || !isEphemeralInstallRoot(resolved) || isEphemeralInstallRoot(path.resolve(targetDir))) {
341
+ return resolved;
342
+ }
343
+ const dest = path.join(machineHome(), ".grok", "wears", "0xray");
344
+ if (resolved === dest) return dest;
345
+ // Copy beside the live wear. A hook pointed at dest keeps loading until the swap.
346
+ const staging = `${dest}.next`;
347
+ const backup = `${dest}.prev`;
348
+ fs.rmSync(staging, { recursive: true, force: true });
349
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
350
+ fs.cpSync(resolved, staging, {
351
+ recursive: true,
352
+ filter(src) {
353
+ const rel = path.relative(resolved, src);
354
+ if (!rel) return true;
355
+ const top = rel.split(path.sep)[0];
356
+ return top !== "node_modules" && top !== ".git";
357
+ },
358
+ });
359
+ fs.rmSync(backup, { recursive: true, force: true });
360
+ if (fs.existsSync(dest)) fs.renameSync(dest, backup);
361
+ fs.renameSync(staging, dest);
362
+ fs.rmSync(backup, { recursive: true, force: true });
363
+ return dest;
364
+ }
365
+
337
366
  function grokHookShellCommand(packageRoot, scriptName, extraArgs) {
338
367
  const script = path.join(packageRoot, "scripts", "mjs", "run-grok-hook.mjs");
339
368
  const extra = extraArgs ? ` ${extraArgs}` : "";
@@ -365,6 +394,7 @@ function ensureGrokHookEvent(hooks, eventName) {
365
394
  }
366
395
 
367
396
  function patchGrokHooks(pluginDir, packageRoot, targetDir, log, label) {
397
+ packageRoot = settlePackageRoot(packageRoot, targetDir);
368
398
  const hooksDir = path.join(pluginDir, "hooks");
369
399
  const hooksPath = path.join(hooksDir, "hooks.json");
370
400
  const hookScript = path.join(packageRoot, "scripts", "mjs", "run-grok-hook.mjs");
@@ -580,6 +610,83 @@ function grokPluginSettled(sourceDir, dest, packageRoot, targetDir) {
580
610
  return true;
581
611
  }
582
612
 
613
+ /** Absolute paths under a temp checkout. Longest match wins so a script path is retargeted before its root. */
614
+ function retargetEphemeralText(text, durableRoot) {
615
+ if (typeof text !== "string" || !isEphemeralInstallRoot(text)) return text;
616
+ const re = /(?:\/private\/var\/folders\/|\/var\/folders\/|\/private\/tmp\/|\/tmp\/|\/Temp\/)[^\s"']*/g;
617
+ const tokens = [...new Set(text.match(re) || [])].sort((a, b) => b.length - a.length);
618
+ let out = text;
619
+ for (const token of tokens) {
620
+ const scriptsAt = token.indexOf("/scripts/");
621
+ if (scriptsAt > 0) {
622
+ const repl = path.join(durableRoot, token.slice(scriptsAt + 1));
623
+ if (fs.existsSync(repl)) out = out.split(token).join(repl);
624
+ continue;
625
+ }
626
+ const runner = path.join(durableRoot, "scripts", "mjs", "run-grok-hook.mjs");
627
+ if (
628
+ !fs.existsSync(token) &&
629
+ fs.existsSync(runner) &&
630
+ (out.includes("run-grok-hook") || out.includes("mcp-launch.cjs"))
631
+ ) {
632
+ out = out.split(token).join(durableRoot);
633
+ }
634
+ }
635
+ return out;
636
+ }
637
+
638
+ function scrubEphemeralPins(node, durableRoot) {
639
+ if (Array.isArray(node)) return node.map((item) => scrubEphemeralPins(item, durableRoot));
640
+ if (!node || typeof node !== "object") {
641
+ return typeof node === "string" ? retargetEphemeralText(node, durableRoot) : node;
642
+ }
643
+ const out = {};
644
+ for (const [key, value] of Object.entries(node)) {
645
+ if ((key === "env" || key === "environment") && value && typeof value === "object" && !Array.isArray(value)) {
646
+ const env = {};
647
+ for (const [envKey, envValue] of Object.entries(value)) {
648
+ if (typeof envValue === "string" && isEphemeralInstallRoot(envValue)) {
649
+ if (envKey === "XRAY_AI_PATH") env[envKey] = durableRoot;
650
+ continue;
651
+ }
652
+ env[envKey] = scrubEphemeralPins(envValue, durableRoot);
653
+ }
654
+ out[key] = env;
655
+ continue;
656
+ }
657
+ out[key] = scrubEphemeralPins(value, durableRoot);
658
+ }
659
+ return out;
660
+ }
661
+
662
+ /**
663
+ * Shared HOME does not wear the machine plugin, but Grok still loads a stale
664
+ * `~/.grok/plugins/0xray`. Drop temp XRAY_ROOT pins and retarget dead launch
665
+ * paths onto the durable wear. A real project root on that plugin is left alone.
666
+ */
667
+ function scrubEphemeralMachineGrokPins(machine, durablePackageRoot) {
668
+ if (!machine || !durablePackageRoot) return 0;
669
+ const runner = path.join(durablePackageRoot, "scripts", "mjs", "run-grok-hook.mjs");
670
+ if (!fs.existsSync(runner)) return 0;
671
+ const plugin = path.join(machine, ".grok", "plugins", "0xray");
672
+ const files = [path.join(plugin, "hooks", "hooks.json"), path.join(plugin, ".mcp.json")];
673
+ let changed = 0;
674
+ for (const file of files) {
675
+ if (!fs.existsSync(file)) continue;
676
+ let data;
677
+ try {
678
+ data = JSON.parse(fs.readFileSync(file, "utf8"));
679
+ } catch {
680
+ continue;
681
+ }
682
+ const next = scrubEphemeralPins(data, durablePackageRoot);
683
+ if (JSON.stringify(data) === JSON.stringify(next)) continue;
684
+ writeFileIfChanged(file, `${JSON.stringify(next, null, 2)}\n`);
685
+ changed += 1;
686
+ }
687
+ return changed;
688
+ }
689
+
583
690
  function installGrokBridge(targetDir, packageRoot, log, opts) {
584
691
  const sourceDir = findGrokPluginSource(packageRoot);
585
692
  if (!sourceDir) {
@@ -599,6 +706,7 @@ function installGrokBridge(targetDir, packageRoot, log, opts) {
599
706
  log("grok-bridge", "skip machine ~/.grok plugin — isolated HOME", "info");
600
707
  } else {
601
708
  log("grok-bridge", "skip machine ~/.grok plugin — project-scoped wear", "info");
709
+ scrubEphemeralMachineGrokPins(machine, settlePackageRoot(packageRoot, targetDir));
602
710
  }
603
711
 
604
712
  for (const dest of targets) {
@@ -1846,26 +1954,29 @@ function syncSetupSkillsAndRootLinks(packageRoot, targetDir) {
1846
1954
  require("./setup.cjs").syncSetupSkillsAndRootLinks(packageRoot, targetDir);
1847
1955
  }
1848
1956
 
1849
- function setupSkillMirrorNames(packageRoot) {
1850
- const skillsSource = fs.existsSync(path.join(packageRoot, "src", "skills"))
1957
+ /** A byte-identical package skill is the old mirror. A different body still throws. */
1958
+ function wornSkillMatchesPackage(packageRoot, targetDir, name) {
1959
+ const source = fs.existsSync(path.join(packageRoot, "src", "skills"))
1851
1960
  ? path.join(packageRoot, "src", "skills")
1852
1961
  : path.join(packageRoot, "dist", "skills");
1853
- if (!fs.existsSync(skillsSource)) return new Set();
1854
- const names = new Set();
1855
- for (const entry of fs.readdirSync(skillsSource, { withFileTypes: true })) {
1856
- if (!entry.isDirectory()) continue;
1857
- if (fs.existsSync(path.join(skillsSource, entry.name, "SKILL.md"))) names.add(entry.name);
1962
+ const packaged = path.join(source, name, "SKILL.md");
1963
+ if (!fs.existsSync(packaged)) return false;
1964
+ const packagedBytes = fs.readFileSync(packaged);
1965
+ let saw = false;
1966
+ for (const parts of ROLE_SKILL_DIRS) {
1967
+ const worn = path.join(targetDir, ...parts, name, "SKILL.md");
1968
+ if (!fs.existsSync(worn)) continue;
1969
+ saw = true;
1970
+ if (!packagedBytes.equals(fs.readFileSync(worn))) return false;
1858
1971
  }
1859
- return names;
1972
+ return saw;
1860
1973
  }
1861
1974
 
1862
- /** The 4.0.28 skill mirror is not a consumer costume. Any other extra name still throws. */
1863
- function isSetupSkillMirrorDump(err, packageRoot) {
1975
+ function isSetupSkillMirrorDump(err, packageRoot, targetDir) {
1864
1976
  if (!err || err.code !== "FOUNDRY_COSTUME_DUMP") return false;
1865
1977
  if (!Array.isArray(err.extraSkills) || err.extraSkills.length === 0) return false;
1866
1978
  if (Array.isArray(err.extraAgents) && err.extraAgents.length > 0) return false;
1867
- const mirrored = setupSkillMirrorNames(packageRoot);
1868
- return err.extraSkills.every((name) => mirrored.has(name));
1979
+ return err.extraSkills.every((name) => wornSkillMatchesPackage(packageRoot, targetDir, name));
1869
1980
  }
1870
1981
 
1871
1982
  function packageShipsConsumerSuit(packageRoot) {
@@ -1873,11 +1984,41 @@ function packageShipsConsumerSuit(packageRoot) {
1873
1984
  }
1874
1985
 
1875
1986
  /**
1876
- * 4.0.28 consumer postinstall files: AGENTS.md, .gitignore, repertoire link,
1877
- * .xray config, bridges, mill plant, then the setup.cjs skill mirror and
1878
- * dist/scripts links. Does not install Cursor hooks or git hooks.
1987
+ * Consumer wear files: AGENTS.md, .gitignore, repertoire link, .xray config,
1988
+ * bridges, mill plant (mill + inspect), and the scripts and dist links.
1989
+ * The role-skill mirror stays in the package.
1990
+ * Does not install Cursor hooks or git hooks.
1879
1991
  * Existing user files follow the 4.0.28 guards inside those functions.
1880
1992
  */
1993
+
1994
+ const ROLE_SKILL_KEEP = new Set(["mill", "inspect"]);
1995
+ const ROLE_SKILL_DIRS = [
1996
+ [".opencode", "skills"],
1997
+ [".grok", "plugins", "0xray", "skills"],
1998
+ [".hermes", "plugins", "xray-hermes", "skills"],
1999
+ [".openclaw", "skills"],
2000
+ ];
2001
+
2002
+ function removeCopiedRoleSkills(packageRoot, targetDir) {
2003
+ const source = fs.existsSync(path.join(packageRoot, "src", "skills"))
2004
+ ? path.join(packageRoot, "src", "skills")
2005
+ : path.join(packageRoot, "dist", "skills");
2006
+ if (!fs.existsSync(source)) return;
2007
+ for (const parts of ROLE_SKILL_DIRS) {
2008
+ const dir = path.join(targetDir, ...parts);
2009
+ if (!fs.existsSync(dir)) continue;
2010
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
2011
+ if (!entry.isDirectory() || ROLE_SKILL_KEEP.has(entry.name)) continue;
2012
+ const packaged = path.join(source, entry.name, "SKILL.md");
2013
+ const worn = path.join(dir, entry.name, "SKILL.md");
2014
+ if (!fs.existsSync(packaged) || !fs.existsSync(worn)) continue;
2015
+ const same = fs.readFileSync(packaged).equals(fs.readFileSync(worn));
2016
+ if (!same) continue;
2017
+ fs.rmSync(path.join(dir, entry.name), { recursive: true, force: true });
2018
+ }
2019
+ }
2020
+ }
2021
+
1881
2022
  function installConsumerProjectFiles(packageRoot, targetDir, log) {
1882
2023
  const write = typeof log === "function" ? log : () => {};
1883
2024
  if (!isConsumerInstall(packageRoot, targetDir) || !packageShipsConsumerSuit(packageRoot)) {
@@ -1896,10 +2037,11 @@ function installConsumerProjectFiles(packageRoot, targetDir, log) {
1896
2037
  installGrokBridge(targetDir, packageRoot, write);
1897
2038
  installHermesBridge(targetDir, packageRoot, write);
1898
2039
  installOpenclawBridge(targetDir, packageRoot, write);
2040
+ removeCopiedRoleSkills(packageRoot, targetDir);
1899
2041
  try {
1900
2042
  mintConsumerSuit(packageRoot, targetDir, write);
1901
2043
  } catch (err) {
1902
- if (!isSetupSkillMirrorDump(err, packageRoot)) throw err;
2044
+ if (!isSetupSkillMirrorDump(err, packageRoot, targetDir)) throw err;
1903
2045
  }
1904
2046
  syncSetupSkillsAndRootLinks(packageRoot, targetDir);
1905
2047
  return true;
@@ -2085,7 +2227,9 @@ function wearCursorHooks(targetDir, packageRoot, log, opts) {
2085
2227
  const write = typeof log === "function" ? log : () => {};
2086
2228
  const options = opts || {};
2087
2229
  const resolvedTarget = path.resolve(targetDir);
2088
- const resolvedPackage = path.resolve(packageRoot);
2230
+ const resolvedPackage = settlePackageRoot(path.resolve(packageRoot), resolvedTarget);
2231
+ pinLauncherPackageRoot(resolvedPackage);
2232
+ try {
2089
2233
  if (classifyCursorWearGit(resolvedTarget) === "not-work-tree") {
2090
2234
  wearSuitSkippingCursorHooks(resolvedPackage, resolvedTarget, write);
2091
2235
  return;
@@ -2137,6 +2281,9 @@ function wearCursorHooks(targetDir, packageRoot, log, opts) {
2137
2281
  }
2138
2282
  write("cursor-bridge", "hooks.json wired to installed dist", "info", { path: hooksPath });
2139
2283
  return hooksPath;
2284
+ } finally {
2285
+ pinLauncherPackageRoot("");
2286
+ }
2140
2287
  }
2141
2288
 
2142
2289
  /**
@@ -2344,15 +2491,16 @@ function installFrameworkDogfoodWear(packageRoot, log) {
2344
2491
  * @param {{ targetDir: string, packageRoot: string, log?: Function }} opts
2345
2492
  */
2346
2493
  function installAllBridges(opts) {
2347
- const packageRoot = path.resolve(opts.packageRoot);
2348
2494
  const targetDir = path.resolve(opts.targetDir);
2495
+ const packageRoot = settlePackageRoot(path.resolve(opts.packageRoot), targetDir);
2496
+ pinLauncherPackageRoot(packageRoot);
2349
2497
  const logFn = opts.log;
2350
2498
  const log =
2351
2499
  logFn ||
2352
2500
  ((_component, _action, _status, _details) => {
2353
2501
  /* noop */
2354
2502
  });
2355
-
2503
+ try {
2356
2504
  wearVendoredRepertoire(packageRoot, targetDir, log);
2357
2505
 
2358
2506
  if (!isConsumerInstall(packageRoot, targetDir)) {
@@ -2373,6 +2521,9 @@ function installAllBridges(opts) {
2373
2521
  installCursorBridge(targetDir, packageRoot, log);
2374
2522
 
2375
2523
  log("install-bridges", "4-platform + cursor wear complete", "success");
2524
+ } finally {
2525
+ pinLauncherPackageRoot("");
2526
+ }
2376
2527
  }
2377
2528
 
2378
2529
  module.exports = {
@@ -2393,6 +2544,8 @@ module.exports = {
2393
2544
  MERGE_CONFIG_FILES,
2394
2545
  patchGrokHooks,
2395
2546
  grokHookShellCommand,
2547
+ settlePackageRoot,
2548
+ scrubEphemeralMachineGrokPins,
2396
2549
  writeGrokDiscoveredHooks,
2397
2550
  isEphemeralInstallRoot,
2398
2551
  isIsolatedHome,
@@ -4,37 +4,7 @@ const fs = require("fs");
4
4
  const path = require("path");
5
5
 
6
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
- }
7
+ // Mint fastens mill and inspect. The role-skill mirror stays in the package.
38
8
 
39
9
  // 4. Create scripts symlink
40
10
  const scriptsSource = path.join(packageRoot, "scripts");
@@ -106,21 +76,7 @@ if (hasHermes) {
106
76
  console.log("🔍 Hermes Agent detected");
107
77
  }
108
78
 
109
- /**
110
- * P3-SKILLS-DE-DUP-SCOPE-AND-EXEC-01 (supporting header in sync owner) — Small-Batch Surgical Skills Deduplication (one package: orchestrator).
111
- * This file (scripts/node/setup.cjs) is the canonical sync owner enforcing src/skills/ (or dist/skills/) → .opencode/skills/ mirror for framework core skills.
112
- * Rich CGT + ties modeled on paired edit in src/cli/commands/status.ts + P3-YML-AGENT-SURFACES-UNIFICATION-01 + P3-7TH-GAP-DEEPER-01 + deep ref 2026-05-26 + Phase 3 Pivot + Term 61 + user's "create a todo list. spawn subagents..." + 6/6+7/7 + YML live.
113
- * Highly modular header only (no behavior change). Fully reversible (delete header). fw discipline + AGENTS org. 2 files total for this micro-slice (status.ts primary with fw guard + this header).
114
- * Governance-visible: documents the SSOT ownership for orchestrator package dedup at the build/install layer.
115
- * The box contains its builders. Term 61 held. Pure momentum.
116
- *
117
- * P3-SKILLS-DE-DUP-RESEARCHER-FOLLOW-01 (follow-on small-batch per deep ref "parallel small batches on skills deduplication (one package)" + YML @ "skills follow-on" + playbook P3-SKILLS-FOLLOW-01 + YML @ harness-codex verification 16982–17045 + FORCE + codex 100/60/0 + 3 subagents tracked + 0 hot + 3-hot re-establish + all prior completions + user's spawn command + deep ref 2026-05-26 + Phase 3 Pivot + Term 61 + 6/6+7/7 + YML):
118
- * Extended header for next high-value package (researcher). src/skills/researcher/SKILL.md canonical SSOT; .opencode/skills/researcher/ built mirror of this sync logic. See paired guarded fw log "P3-SKILLS-DE-DUP-RESEARCHER-FOLLOW-01-researcher-ssot-preferred" in status.ts getSkillsList + rich append docs/reflections/p3-skills-dedup-researcher-follow-01-2026-05-27.md + CGT/Governance-visible for YML @ harness-codex verification + 0 hot + 3-hot + all ties. 2 files max total for this follow-on. Highly modular. Fully reversible. fw/echo discipline. AGENTS org (scripts/ for sh/cjs). Term 61 surgical forward motion held. "the box contains its builders". Green + ready.
119
- *
120
- * P3-SKILLS-FOLLOW-02 (follow-on small-batch per deep ref "parallel small batches on skills deduplication (one package)" + @architect scoping rec 2 + YML @ "Ready for next" + this execution on user's "create a todo list. spawn subagents to complete todos. maintain todo list. do not ask questions. do not stop. you have the full plan."; modeled exactly on "orchestrator" + researcher precedent):
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.
122
- */
123
-
79
+ // Mint fastens mill and inspect. The links below are scripts and dist.
124
80
  syncSetupSkillsAndRootLinks(packageRoot, targetDir);
125
81
 
126
82
  // 2. Handle opencode.json merge
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray-pre-tool",
3
- "version": "4.0.40",
3
+ "version": "4.0.41",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "0xRay constitution + temperament PreToolUse for OpenClaw",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./features.schema.json",
3
- "version": "4.0.40",
3
+ "version": "4.0.41",
4
4
  "description": "0xRay Framework - Unified Feature Configuration",
5
5
  "suit_temperament": {
6
6
  "profile": "auto",