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.
- package/.grok-plugin/plugin.json +1 -1
- package/.opencode/agents/api-design.yml +31 -0
- package/.opencode/agents/architect.yml +15 -0
- package/.opencode/agents/architecture-patterns.yml +14 -0
- package/.opencode/agents/auto-format.yml +14 -0
- package/.opencode/agents/backend-engineer.yml +12 -0
- package/.opencode/agents/boot-orchestrator.yml +14 -0
- package/.opencode/agents/bug-triage-specialist.yml +15 -0
- package/.opencode/agents/code-analyzer.yml +12 -0
- package/.opencode/agents/code-reviewer.yml +14 -0
- package/.opencode/agents/content-creator.yml +12 -0
- package/.opencode/agents/database-engineer.yml +12 -0
- package/.opencode/agents/devops-engineer.yml +12 -0
- package/.opencode/agents/framework-compliance-audit.yml +14 -0
- package/.opencode/agents/frontend-engineer.yml +12 -0
- package/.opencode/agents/frontend-ui-ux-engineer.yml +12 -0
- package/.opencode/agents/git-workflow.yml +15 -0
- package/.opencode/agents/growth-strategist.yml +12 -0
- package/.opencode/agents/hermes-agent.yml +12 -0
- package/.opencode/agents/inference-improve.yml +12 -0
- package/.opencode/agents/lint.yml +14 -0
- package/.opencode/agents/log-monitor.yml +12 -0
- package/.opencode/agents/mobile-developer.yml +12 -0
- package/.opencode/agents/model-health-check.yml +12 -0
- package/.opencode/agents/multimodal-looker.yml +12 -0
- package/.opencode/agents/performance-analysis.yml +12 -0
- package/.opencode/agents/performance-engineer.yml +12 -0
- package/.opencode/agents/performance-optimization.yml +12 -0
- package/.opencode/agents/processor-pipeline.yml +14 -0
- package/.opencode/agents/project-analysis.yml +12 -0
- package/.opencode/agents/refactorer.yml +12 -0
- package/.opencode/agents/researcher.yml +12 -0
- package/.opencode/agents/security-auditor.yml +12 -0
- package/.opencode/agents/security-scan.yml +12 -0
- package/.opencode/agents/seo-consultant.yml +12 -0
- package/.opencode/agents/session-management.yml +12 -0
- package/.opencode/agents/state-manager.yml +12 -0
- package/.opencode/agents/storyteller.yml +12 -0
- package/.opencode/agents/strategist.yml +12 -0
- package/.opencode/agents/tech-writer.yml +12 -0
- package/.opencode/agents/testing-best-practices.yml +12 -0
- package/.opencode/agents/testing-lead.yml +12 -0
- package/.opencode/agents/ui-ux-design.yml +12 -0
- package/.opencode/codex.codex +8 -0
- package/.opencode/commands/auto-format.md +99 -0
- package/.opencode/commands/auto-summary-capture.md +90 -0
- package/.opencode/commands/dependency-audit.md +184 -0
- package/.opencode/commands/enforcer-daily-scan.md +137 -0
- package/.opencode/commands/framework-compliance-audit.md +205 -0
- package/.opencode/commands/interactive-validator.md +75 -0
- package/.opencode/commands/job-summary-logger.md +68 -0
- package/.opencode/commands/lint.md +11 -0
- package/.opencode/commands/mode-switch.md +95 -0
- package/.opencode/commands/model-health-check.md +186 -0
- package/.opencode/commands/performance-analysis.md +144 -0
- package/.opencode/commands/pre-commit-introspection.md +185 -0
- package/.opencode/commands/pre-commit-introspection.sh +133 -0
- package/.opencode/commands/security-scan.md +157 -0
- package/.opencode/commands/sisyphus-validation.md +128 -0
- package/.opencode/commands/summary-logger.md +83 -0
- package/.opencode/enforcer-config.json +282 -0
- package/.opencode/workflows/post-deployment-audit.yml +123 -0
- package/.xray/features.json +1 -1
- package/dist/CHANGELOG.md +16 -0
- package/dist/integrations/grok/hooks/grok-hook-utils.js +21 -1
- package/dist/integrations/grok/hooks/session-start.js +2 -20
- package/dist/integrations/hooks/goggles-mcp.mjs +36 -4
- package/dist/integrations/hooks/goggles-pipeline.mjs +55 -15
- package/dist/integrations/hooks/goggles-planes.json +9 -3
- package/dist/integrations/hooks/plates.cjs +22 -0
- package/dist/integrations/hooks/session-note-index.cjs +298 -0
- package/dist/integrations/hooks/session-note-index.mjs +22 -0
- package/dist/integrations/hooks/sleeve.cjs +335 -0
- package/dist/integrations/hooks/sleeve.mjs +18 -0
- package/dist/integrations/hooks/station-hook-runtime.cjs +205 -9
- package/dist/integrations/hooks/wake-cascade.cjs +102 -0
- package/dist/integrations/hooks/wake-cascade.mjs +16 -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/docs-site/docs/plates/activity-log.md +1 -1
- package/docs-site/docs/plates/boot.md +2 -0
- package/docs-site/docs/plates/centrifuge.md +30 -0
- package/docs-site/docs/plates/cursor-compact.md +1 -1
- package/docs-site/docs/plates/glossary.md +1 -2
- package/docs-site/docs/plates/goggles.md +4 -0
- package/docs-site/docs/plates/governance.md +2 -0
- package/docs-site/docs/plates/grok-compact.md +1 -1
- package/docs-site/docs/plates/grokbot.md +1 -1
- package/docs-site/docs/plates/host-pack.md +2 -0
- package/docs-site/docs/plates/house.md +1 -1
- package/docs-site/docs/plates/index.md +3 -1
- package/docs-site/docs/plates/inference-files.md +1 -1
- package/docs-site/docs/plates/kept-line.md +1 -1
- package/docs-site/docs/plates/kits.md +2 -0
- package/docs-site/docs/plates/lens-gate.md +1 -1
- package/docs-site/docs/plates/lens-page.md +1 -1
- package/docs-site/docs/plates/live-mesh.md +1 -1
- package/docs-site/docs/plates/memory-recall.md +4 -0
- package/docs-site/docs/plates/notes-page.md +2 -1
- package/docs-site/docs/plates/orchestration.md +2 -0
- package/docs-site/docs/plates/package-face.md +1 -1
- package/docs-site/docs/plates/payload-heat.md +1 -1
- package/docs-site/docs/plates/pickup-stamp.md +1 -1
- package/docs-site/docs/plates/pre-tool.md +1 -1
- package/docs-site/docs/plates/processor.md +2 -0
- package/docs-site/docs/plates/record-map.md +2 -1
- package/docs-site/docs/plates/reflection-page.md +1 -1
- package/docs-site/docs/plates/reporting.md +2 -0
- package/docs-site/docs/plates/review.md +1 -1
- package/docs-site/docs/plates/routing.md +2 -0
- package/docs-site/docs/plates/session-capture.md +1 -1
- package/docs-site/docs/plates/site-manual.md +1 -1
- package/docs-site/docs/plates/stamp-plate.md +1 -1
- package/docs-site/docs/plates/station-card.md +4 -1
- package/docs-site/docs/plates/station-heat.md +1 -1
- package/docs-site/docs/plates/suit-organs.md +1 -1
- package/docs-site/docs/plates/suit-settings.md +1 -1
- package/docs-site/docs/plates/suit-wear.md +3 -1
- package/docs-site/docs/plates/suit.md +2 -0
- package/docs-site/docs/plates/trail-state.md +1 -1
- package/docs-site/docs/plates/work-fresh.md +1 -1
- package/docs-site/docs/plates/write-home.md +1 -1
- package/package.json +1 -1
- package/scripts/node/bridge-mcp-wiring.cjs +37 -4
- package/scripts/node/install-bridges.cjs +172 -19
- package/scripts/node/setup.cjs +2 -46
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- 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
|
-
|
|
1850
|
-
|
|
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
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
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
|
|
1972
|
+
return saw;
|
|
1860
1973
|
}
|
|
1861
1974
|
|
|
1862
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
1877
|
-
*
|
|
1878
|
-
*
|
|
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,
|
package/scripts/node/setup.cjs
CHANGED
|
@@ -4,37 +4,7 @@ const fs = require("fs");
|
|
|
4
4
|
const path = require("path");
|
|
5
5
|
|
|
6
6
|
function syncSetupSkillsAndRootLinks(packageRoot, targetDir) {
|
|
7
|
-
|
|
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
|