0xray 4.0.40 → 4.0.42
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/skills/orchestrator/SKILL.md +12 -0
- package/.opencode/workflows/post-deployment-audit.yml +123 -0
- package/.xray/features.json +1 -1
- package/.xray/features.schema.json +1 -1
- package/AGENTS-consumer.md +2 -0
- package/AGENTS.md +2 -0
- package/README.md +52 -12
- package/SKILLS.md +2 -0
- package/dist/AGENTS.md +2 -0
- package/dist/CHANGELOG.md +29 -0
- package/dist/README.md +52 -12
- package/dist/SKILLS.md +2 -0
- package/dist/cli/commands/openclaw-install.js +1 -1
- package/dist/cli/index.js +12 -0
- package/dist/enforcement/index.d.ts +4 -0
- package/dist/enforcement/index.js +4 -0
- package/dist/enforcement/validators/code-quality-validators.js +6 -4
- package/dist/governance/llm-governance-provider.d.ts +7 -1
- package/dist/governance/llm-governance-provider.js +72 -14
- package/dist/governance/local-confer.d.ts +4 -1
- package/dist/governance/local-confer.js +22 -1
- package/dist/integrations/grok/grok-cli.js +10 -37
- package/dist/integrations/grok/hooks/grok-hook-utils.js +29 -2
- package/dist/integrations/grok/hooks/session-start.js +2 -20
- package/dist/integrations/hooks/confer-hook-runtime.mjs +23 -1
- 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 +13 -4
- 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/mcps/architect-tools.server.d.ts +6 -0
- package/dist/mcps/architect-tools.server.js +19 -2
- package/dist/mcps/config/server-config-registry.js +8 -6
- package/dist/mcps/governance.server.d.ts +1 -0
- package/dist/mcps/governance.server.js +46 -0
- package/dist/mcps/knowledge-skills/code-review.server.js +7 -0
- package/dist/mcps/knowledge-skills/security-audit.server.js +5 -3
- package/dist/mcps/mcp-client.js +1 -1
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +2 -2
- package/dist/mcps/researcher.server.js +12 -3
- package/dist/memory-routing/plates.d.ts +1 -1
- package/dist/memory-routing/plates.js +1 -0
- package/dist/nucleus/autonomy-kernel.d.ts +2 -0
- package/dist/nucleus/autonomy-kernel.js +17 -13
- package/dist/nucleus/confer-host.d.ts +35 -0
- package/dist/nucleus/confer-host.js +55 -0
- package/dist/nucleus/confer.d.ts +19 -3
- package/dist/nucleus/confer.js +111 -55
- package/dist/nucleus/lead-dev-plan-persistence.js +4 -2
- package/dist/nucleus/suit-temperament.d.ts +1 -1
- package/dist/nucleus/suit-temperament.js +2 -2
- package/dist/nucleus/synthesis-consult-receipt.d.ts +7 -1
- package/dist/nucleus/synthesis-consult-receipt.js +86 -35
- package/dist/reporting/framework-reporting-system.js +2 -5
- package/dist/reporting/log-parser.d.ts +2 -0
- package/dist/reporting/log-parser.js +7 -6
- package/dist/skills/orchestrator/SKILL.md +12 -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/llms.txt +2 -0
- package/package.json +2 -2
- package/scripts/mjs/verify-confer-core.mjs +153 -29
- package/scripts/mjs/verify-user-aside-core.mjs +3 -4
- package/scripts/node/bridge-mcp-wiring.cjs +273 -9
- package/scripts/node/confer-switch.cjs +66 -0
- package/scripts/node/install-bridges.cjs +188 -60
- package/scripts/node/setup.cjs +2 -46
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/src/mcps/architect-tools.server.ts +26 -2
- package/src/mcps/config/__tests__/server-config-registry.test.ts +15 -6
- package/src/mcps/config/server-config-registry.ts +9 -6
- package/src/mcps/governance.server.ts +49 -0
- package/src/mcps/knowledge-skills/code-review.server.ts +8 -0
- package/src/mcps/knowledge-skills/security-audit.server.ts +11 -12
- package/src/mcps/mcp-client.ts +1 -1
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +2 -1
- package/src/mcps/researcher.server.ts +19 -10
- package/src/skills/orchestrator/SKILL.md +12 -0
- package/vendor/@0xray/repertoire/scripts/run-live-synthesis-checkpoint.mjs +5 -51
- package/xray/features.json +1 -1
- package/xray/features.schema.json +1 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const fs = require("fs");
|
|
9
9
|
const path = require("path");
|
|
10
|
-
const { execFileSync
|
|
10
|
+
const { execFileSync } = require("child_process");
|
|
11
11
|
const {
|
|
12
12
|
wantsCostume,
|
|
13
13
|
isIsolatedHome,
|
|
@@ -22,17 +22,19 @@ const {
|
|
|
22
22
|
wireOpencodeBridge,
|
|
23
23
|
wireOpenClawBridge,
|
|
24
24
|
deployPortableProjectMcpJson,
|
|
25
|
-
scopedMcpLaunch,
|
|
26
25
|
mergeMcpMap,
|
|
27
26
|
mergeNamedRecords,
|
|
28
27
|
jsonDeepEqual,
|
|
29
28
|
copyHermesFindProjectRootHelper,
|
|
30
29
|
copyHermesHookRuntimes,
|
|
31
30
|
installOpenClawHostWear,
|
|
31
|
+
recordOpenClawProjectPlugin,
|
|
32
32
|
maybeWriteOpenClawCliBackend,
|
|
33
33
|
isEphemeralInstallRoot,
|
|
34
34
|
enableMemoryRoutingIfResolves,
|
|
35
|
-
|
|
35
|
+
pinLauncherPackageRoot,
|
|
36
|
+
writeProjectSuitMcp,
|
|
37
|
+
trustGrokFolder,
|
|
36
38
|
} = require("./bridge-mcp-wiring.cjs");
|
|
37
39
|
|
|
38
40
|
const wearIo = { writes: 0, skips: 0 };
|
|
@@ -334,6 +336,34 @@ function mergeOpencodeJson(targetDir, packageRoot, log) {
|
|
|
334
336
|
}
|
|
335
337
|
}
|
|
336
338
|
|
|
339
|
+
function settlePackageRoot(packageRoot, targetDir) {
|
|
340
|
+
const resolved = path.resolve(packageRoot || ".");
|
|
341
|
+
if (!targetDir || !isEphemeralInstallRoot(resolved) || isEphemeralInstallRoot(path.resolve(targetDir))) {
|
|
342
|
+
return resolved;
|
|
343
|
+
}
|
|
344
|
+
const dest = path.join(machineHome(), ".grok", "wears", "0xray");
|
|
345
|
+
if (resolved === dest) return dest;
|
|
346
|
+
// Copy beside the live wear. A hook pointed at dest keeps loading until the swap.
|
|
347
|
+
const staging = `${dest}.next`;
|
|
348
|
+
const backup = `${dest}.prev`;
|
|
349
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
350
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
351
|
+
fs.cpSync(resolved, staging, {
|
|
352
|
+
recursive: true,
|
|
353
|
+
filter(src) {
|
|
354
|
+
const rel = path.relative(resolved, src);
|
|
355
|
+
if (!rel) return true;
|
|
356
|
+
const top = rel.split(path.sep)[0];
|
|
357
|
+
return top !== "node_modules" && top !== ".git";
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
fs.rmSync(backup, { recursive: true, force: true });
|
|
361
|
+
if (fs.existsSync(dest)) fs.renameSync(dest, backup);
|
|
362
|
+
fs.renameSync(staging, dest);
|
|
363
|
+
fs.rmSync(backup, { recursive: true, force: true });
|
|
364
|
+
return dest;
|
|
365
|
+
}
|
|
366
|
+
|
|
337
367
|
function grokHookShellCommand(packageRoot, scriptName, extraArgs) {
|
|
338
368
|
const script = path.join(packageRoot, "scripts", "mjs", "run-grok-hook.mjs");
|
|
339
369
|
const extra = extraArgs ? ` ${extraArgs}` : "";
|
|
@@ -365,6 +395,7 @@ function ensureGrokHookEvent(hooks, eventName) {
|
|
|
365
395
|
}
|
|
366
396
|
|
|
367
397
|
function patchGrokHooks(pluginDir, packageRoot, targetDir, log, label) {
|
|
398
|
+
packageRoot = settlePackageRoot(packageRoot, targetDir);
|
|
368
399
|
const hooksDir = path.join(pluginDir, "hooks");
|
|
369
400
|
const hooksPath = path.join(hooksDir, "hooks.json");
|
|
370
401
|
const hookScript = path.join(packageRoot, "scripts", "mjs", "run-grok-hook.mjs");
|
|
@@ -454,42 +485,11 @@ function findGrokPluginSource(packageRoot) {
|
|
|
454
485
|
return candidates.find((p) => fs.existsSync(p));
|
|
455
486
|
}
|
|
456
487
|
|
|
457
|
-
function registerGrokMcpServers(targetDir, log,
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
for (const s of XRAY_MCP_SERVERS) {
|
|
466
|
-
try {
|
|
467
|
-
const launch = scopedMcpLaunch(targetDir, s.mcpCmd, s.env);
|
|
468
|
-
const argv = ["mcp", "add", s.name, "--command", launch.command, "--args", launch.args[0], ...launch.args.slice(1)];
|
|
469
|
-
for (const [key, value] of Object.entries(launch.env)) {
|
|
470
|
-
argv.push("--env", `${key}=${value}`);
|
|
471
|
-
}
|
|
472
|
-
execFileSync("grok", argv, { stdio: "pipe" });
|
|
473
|
-
log("grok-bridge", `registered ${s.name} (mcp-launch)`, "info");
|
|
474
|
-
} catch {
|
|
475
|
-
// already registered or grok config conflict — non-blocking
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
const dirs =
|
|
480
|
-
Array.isArray(pluginDirs) && pluginDirs.length > 0
|
|
481
|
-
? pluginDirs
|
|
482
|
-
: [path.join(targetDir, ".grok", "plugins", "0xray")];
|
|
483
|
-
for (const pluginDir of dirs) {
|
|
484
|
-
if (!fs.existsSync(pluginDir)) continue;
|
|
485
|
-
try {
|
|
486
|
-
execSync(`grok plugins trust "${pluginDir}"`, { stdio: "ignore" });
|
|
487
|
-
log("grok-bridge", "plugin trusted", "info", { path: pluginDir });
|
|
488
|
-
break;
|
|
489
|
-
} catch {
|
|
490
|
-
// best-effort
|
|
491
|
-
}
|
|
492
|
-
}
|
|
488
|
+
function registerGrokMcpServers(targetDir, log, env) {
|
|
489
|
+
const tomlPath = writeProjectSuitMcp(targetDir);
|
|
490
|
+
log("grok-bridge", "project mcp config written", "info", { path: tomlPath });
|
|
491
|
+
const trustPath = trustGrokFolder(targetDir, env || process.env);
|
|
492
|
+
log("grok-bridge", "folder trusted", "info", { path: trustPath });
|
|
493
493
|
}
|
|
494
494
|
|
|
495
495
|
|
|
@@ -580,6 +580,83 @@ function grokPluginSettled(sourceDir, dest, packageRoot, targetDir) {
|
|
|
580
580
|
return true;
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
+
/** Absolute paths under a temp checkout. Longest match wins so a script path is retargeted before its root. */
|
|
584
|
+
function retargetEphemeralText(text, durableRoot) {
|
|
585
|
+
if (typeof text !== "string" || !isEphemeralInstallRoot(text)) return text;
|
|
586
|
+
const re = /(?:\/private\/var\/folders\/|\/var\/folders\/|\/private\/tmp\/|\/tmp\/|\/Temp\/)[^\s"']*/g;
|
|
587
|
+
const tokens = [...new Set(text.match(re) || [])].sort((a, b) => b.length - a.length);
|
|
588
|
+
let out = text;
|
|
589
|
+
for (const token of tokens) {
|
|
590
|
+
const scriptsAt = token.indexOf("/scripts/");
|
|
591
|
+
if (scriptsAt > 0) {
|
|
592
|
+
const repl = path.join(durableRoot, token.slice(scriptsAt + 1));
|
|
593
|
+
if (fs.existsSync(repl)) out = out.split(token).join(repl);
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
const runner = path.join(durableRoot, "scripts", "mjs", "run-grok-hook.mjs");
|
|
597
|
+
if (
|
|
598
|
+
!fs.existsSync(token) &&
|
|
599
|
+
fs.existsSync(runner) &&
|
|
600
|
+
(out.includes("run-grok-hook") || out.includes("mcp-launch.cjs"))
|
|
601
|
+
) {
|
|
602
|
+
out = out.split(token).join(durableRoot);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
return out;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function scrubEphemeralPins(node, durableRoot) {
|
|
609
|
+
if (Array.isArray(node)) return node.map((item) => scrubEphemeralPins(item, durableRoot));
|
|
610
|
+
if (!node || typeof node !== "object") {
|
|
611
|
+
return typeof node === "string" ? retargetEphemeralText(node, durableRoot) : node;
|
|
612
|
+
}
|
|
613
|
+
const out = {};
|
|
614
|
+
for (const [key, value] of Object.entries(node)) {
|
|
615
|
+
if ((key === "env" || key === "environment") && value && typeof value === "object" && !Array.isArray(value)) {
|
|
616
|
+
const env = {};
|
|
617
|
+
for (const [envKey, envValue] of Object.entries(value)) {
|
|
618
|
+
if (typeof envValue === "string" && isEphemeralInstallRoot(envValue)) {
|
|
619
|
+
if (envKey === "XRAY_AI_PATH") env[envKey] = durableRoot;
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
env[envKey] = scrubEphemeralPins(envValue, durableRoot);
|
|
623
|
+
}
|
|
624
|
+
out[key] = env;
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
out[key] = scrubEphemeralPins(value, durableRoot);
|
|
628
|
+
}
|
|
629
|
+
return out;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Shared HOME does not wear the machine plugin, but Grok still loads a stale
|
|
634
|
+
* `~/.grok/plugins/0xray`. Drop temp XRAY_ROOT pins and retarget dead launch
|
|
635
|
+
* paths onto the durable wear. A real project root on that plugin is left alone.
|
|
636
|
+
*/
|
|
637
|
+
function scrubEphemeralMachineGrokPins(machine, durablePackageRoot) {
|
|
638
|
+
if (!machine || !durablePackageRoot) return 0;
|
|
639
|
+
const runner = path.join(durablePackageRoot, "scripts", "mjs", "run-grok-hook.mjs");
|
|
640
|
+
if (!fs.existsSync(runner)) return 0;
|
|
641
|
+
const plugin = path.join(machine, ".grok", "plugins", "0xray");
|
|
642
|
+
const files = [path.join(plugin, "hooks", "hooks.json"), path.join(plugin, ".mcp.json")];
|
|
643
|
+
let changed = 0;
|
|
644
|
+
for (const file of files) {
|
|
645
|
+
if (!fs.existsSync(file)) continue;
|
|
646
|
+
let data;
|
|
647
|
+
try {
|
|
648
|
+
data = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
649
|
+
} catch {
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
const next = scrubEphemeralPins(data, durablePackageRoot);
|
|
653
|
+
if (JSON.stringify(data) === JSON.stringify(next)) continue;
|
|
654
|
+
writeFileIfChanged(file, `${JSON.stringify(next, null, 2)}\n`);
|
|
655
|
+
changed += 1;
|
|
656
|
+
}
|
|
657
|
+
return changed;
|
|
658
|
+
}
|
|
659
|
+
|
|
583
660
|
function installGrokBridge(targetDir, packageRoot, log, opts) {
|
|
584
661
|
const sourceDir = findGrokPluginSource(packageRoot);
|
|
585
662
|
if (!sourceDir) {
|
|
@@ -599,6 +676,7 @@ function installGrokBridge(targetDir, packageRoot, log, opts) {
|
|
|
599
676
|
log("grok-bridge", "skip machine ~/.grok plugin — isolated HOME", "info");
|
|
600
677
|
} else {
|
|
601
678
|
log("grok-bridge", "skip machine ~/.grok plugin — project-scoped wear", "info");
|
|
679
|
+
scrubEphemeralMachineGrokPins(machine, settlePackageRoot(packageRoot, targetDir));
|
|
602
680
|
}
|
|
603
681
|
|
|
604
682
|
for (const dest of targets) {
|
|
@@ -634,8 +712,8 @@ function installGrokBridge(targetDir, packageRoot, log, opts) {
|
|
|
634
712
|
if (globalCopied > 0) {
|
|
635
713
|
log("grok-bridge", `global skills synced (${globalCopied})`, "info", { path: grokGlobalSkills });
|
|
636
714
|
}
|
|
637
|
-
registerGrokMcpServers(targetDir, log, targets);
|
|
638
715
|
}
|
|
716
|
+
registerGrokMcpServers(targetDir, log, env);
|
|
639
717
|
}
|
|
640
718
|
|
|
641
719
|
function installHermesBridge(targetDir, packageRoot, log) {
|
|
@@ -773,7 +851,7 @@ function installOpenclawBridge(targetDir, packageRoot, log) {
|
|
|
773
851
|
}
|
|
774
852
|
|
|
775
853
|
if (!ephemeralOpenclaw && !isolatedOpenclaw) {
|
|
776
|
-
const hook = installOpenClawHostWear(packageRoot);
|
|
854
|
+
const hook = installOpenClawHostWear(packageRoot, targetDir);
|
|
777
855
|
if (hook) log("openclaw-bridge", "PreToolUse hook installed", "info", { path: hook });
|
|
778
856
|
if (maybeWriteOpenClawCliBackend()) {
|
|
779
857
|
log("openclaw-bridge", "opencode-cli backend written", "info");
|
|
@@ -787,6 +865,11 @@ function installOpenclawBridge(targetDir, packageRoot, log) {
|
|
|
787
865
|
"info",
|
|
788
866
|
);
|
|
789
867
|
}
|
|
868
|
+
|
|
869
|
+
const recorded = recordOpenClawProjectPlugin(targetDir, packageRoot);
|
|
870
|
+
if (recorded) {
|
|
871
|
+
log("openclaw-bridge", "project plugin path recorded", "info", { path: recorded });
|
|
872
|
+
}
|
|
790
873
|
}
|
|
791
874
|
|
|
792
875
|
const XRAY_CONFIG_FILES = ["codex.json", "features.json", "features.schema.json", "config.json"];
|
|
@@ -1846,26 +1929,29 @@ function syncSetupSkillsAndRootLinks(packageRoot, targetDir) {
|
|
|
1846
1929
|
require("./setup.cjs").syncSetupSkillsAndRootLinks(packageRoot, targetDir);
|
|
1847
1930
|
}
|
|
1848
1931
|
|
|
1849
|
-
|
|
1850
|
-
|
|
1932
|
+
/** A byte-identical package skill is the old mirror. A different body still throws. */
|
|
1933
|
+
function wornSkillMatchesPackage(packageRoot, targetDir, name) {
|
|
1934
|
+
const source = fs.existsSync(path.join(packageRoot, "src", "skills"))
|
|
1851
1935
|
? path.join(packageRoot, "src", "skills")
|
|
1852
1936
|
: path.join(packageRoot, "dist", "skills");
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1937
|
+
const packaged = path.join(source, name, "SKILL.md");
|
|
1938
|
+
if (!fs.existsSync(packaged)) return false;
|
|
1939
|
+
const packagedBytes = fs.readFileSync(packaged);
|
|
1940
|
+
let saw = false;
|
|
1941
|
+
for (const parts of ROLE_SKILL_DIRS) {
|
|
1942
|
+
const worn = path.join(targetDir, ...parts, name, "SKILL.md");
|
|
1943
|
+
if (!fs.existsSync(worn)) continue;
|
|
1944
|
+
saw = true;
|
|
1945
|
+
if (!packagedBytes.equals(fs.readFileSync(worn))) return false;
|
|
1858
1946
|
}
|
|
1859
|
-
return
|
|
1947
|
+
return saw;
|
|
1860
1948
|
}
|
|
1861
1949
|
|
|
1862
|
-
|
|
1863
|
-
function isSetupSkillMirrorDump(err, packageRoot) {
|
|
1950
|
+
function isSetupSkillMirrorDump(err, packageRoot, targetDir) {
|
|
1864
1951
|
if (!err || err.code !== "FOUNDRY_COSTUME_DUMP") return false;
|
|
1865
1952
|
if (!Array.isArray(err.extraSkills) || err.extraSkills.length === 0) return false;
|
|
1866
1953
|
if (Array.isArray(err.extraAgents) && err.extraAgents.length > 0) return false;
|
|
1867
|
-
|
|
1868
|
-
return err.extraSkills.every((name) => mirrored.has(name));
|
|
1954
|
+
return err.extraSkills.every((name) => wornSkillMatchesPackage(packageRoot, targetDir, name));
|
|
1869
1955
|
}
|
|
1870
1956
|
|
|
1871
1957
|
function packageShipsConsumerSuit(packageRoot) {
|
|
@@ -1873,11 +1959,41 @@ function packageShipsConsumerSuit(packageRoot) {
|
|
|
1873
1959
|
}
|
|
1874
1960
|
|
|
1875
1961
|
/**
|
|
1876
|
-
*
|
|
1877
|
-
*
|
|
1878
|
-
*
|
|
1962
|
+
* Consumer wear files: AGENTS.md, .gitignore, repertoire link, .xray config,
|
|
1963
|
+
* bridges, mill plant (mill + inspect), and the scripts and dist links.
|
|
1964
|
+
* The role-skill mirror stays in the package.
|
|
1965
|
+
* Does not install Cursor hooks or git hooks.
|
|
1879
1966
|
* Existing user files follow the 4.0.28 guards inside those functions.
|
|
1880
1967
|
*/
|
|
1968
|
+
|
|
1969
|
+
const ROLE_SKILL_KEEP = new Set(["mill", "inspect"]);
|
|
1970
|
+
const ROLE_SKILL_DIRS = [
|
|
1971
|
+
[".opencode", "skills"],
|
|
1972
|
+
[".grok", "plugins", "0xray", "skills"],
|
|
1973
|
+
[".hermes", "plugins", "xray-hermes", "skills"],
|
|
1974
|
+
[".openclaw", "skills"],
|
|
1975
|
+
];
|
|
1976
|
+
|
|
1977
|
+
function removeCopiedRoleSkills(packageRoot, targetDir) {
|
|
1978
|
+
const source = fs.existsSync(path.join(packageRoot, "src", "skills"))
|
|
1979
|
+
? path.join(packageRoot, "src", "skills")
|
|
1980
|
+
: path.join(packageRoot, "dist", "skills");
|
|
1981
|
+
if (!fs.existsSync(source)) return;
|
|
1982
|
+
for (const parts of ROLE_SKILL_DIRS) {
|
|
1983
|
+
const dir = path.join(targetDir, ...parts);
|
|
1984
|
+
if (!fs.existsSync(dir)) continue;
|
|
1985
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
1986
|
+
if (!entry.isDirectory() || ROLE_SKILL_KEEP.has(entry.name)) continue;
|
|
1987
|
+
const packaged = path.join(source, entry.name, "SKILL.md");
|
|
1988
|
+
const worn = path.join(dir, entry.name, "SKILL.md");
|
|
1989
|
+
if (!fs.existsSync(packaged) || !fs.existsSync(worn)) continue;
|
|
1990
|
+
const same = fs.readFileSync(packaged).equals(fs.readFileSync(worn));
|
|
1991
|
+
if (!same) continue;
|
|
1992
|
+
fs.rmSync(path.join(dir, entry.name), { recursive: true, force: true });
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1881
1997
|
function installConsumerProjectFiles(packageRoot, targetDir, log) {
|
|
1882
1998
|
const write = typeof log === "function" ? log : () => {};
|
|
1883
1999
|
if (!isConsumerInstall(packageRoot, targetDir) || !packageShipsConsumerSuit(packageRoot)) {
|
|
@@ -1896,10 +2012,11 @@ function installConsumerProjectFiles(packageRoot, targetDir, log) {
|
|
|
1896
2012
|
installGrokBridge(targetDir, packageRoot, write);
|
|
1897
2013
|
installHermesBridge(targetDir, packageRoot, write);
|
|
1898
2014
|
installOpenclawBridge(targetDir, packageRoot, write);
|
|
2015
|
+
removeCopiedRoleSkills(packageRoot, targetDir);
|
|
1899
2016
|
try {
|
|
1900
2017
|
mintConsumerSuit(packageRoot, targetDir, write);
|
|
1901
2018
|
} catch (err) {
|
|
1902
|
-
if (!isSetupSkillMirrorDump(err, packageRoot)) throw err;
|
|
2019
|
+
if (!isSetupSkillMirrorDump(err, packageRoot, targetDir)) throw err;
|
|
1903
2020
|
}
|
|
1904
2021
|
syncSetupSkillsAndRootLinks(packageRoot, targetDir);
|
|
1905
2022
|
return true;
|
|
@@ -2085,7 +2202,9 @@ function wearCursorHooks(targetDir, packageRoot, log, opts) {
|
|
|
2085
2202
|
const write = typeof log === "function" ? log : () => {};
|
|
2086
2203
|
const options = opts || {};
|
|
2087
2204
|
const resolvedTarget = path.resolve(targetDir);
|
|
2088
|
-
const resolvedPackage = path.resolve(packageRoot);
|
|
2205
|
+
const resolvedPackage = settlePackageRoot(path.resolve(packageRoot), resolvedTarget);
|
|
2206
|
+
pinLauncherPackageRoot(resolvedPackage);
|
|
2207
|
+
try {
|
|
2089
2208
|
if (classifyCursorWearGit(resolvedTarget) === "not-work-tree") {
|
|
2090
2209
|
wearSuitSkippingCursorHooks(resolvedPackage, resolvedTarget, write);
|
|
2091
2210
|
return;
|
|
@@ -2137,6 +2256,9 @@ function wearCursorHooks(targetDir, packageRoot, log, opts) {
|
|
|
2137
2256
|
}
|
|
2138
2257
|
write("cursor-bridge", "hooks.json wired to installed dist", "info", { path: hooksPath });
|
|
2139
2258
|
return hooksPath;
|
|
2259
|
+
} finally {
|
|
2260
|
+
pinLauncherPackageRoot("");
|
|
2261
|
+
}
|
|
2140
2262
|
}
|
|
2141
2263
|
|
|
2142
2264
|
/**
|
|
@@ -2344,15 +2466,16 @@ function installFrameworkDogfoodWear(packageRoot, log) {
|
|
|
2344
2466
|
* @param {{ targetDir: string, packageRoot: string, log?: Function }} opts
|
|
2345
2467
|
*/
|
|
2346
2468
|
function installAllBridges(opts) {
|
|
2347
|
-
const packageRoot = path.resolve(opts.packageRoot);
|
|
2348
2469
|
const targetDir = path.resolve(opts.targetDir);
|
|
2470
|
+
const packageRoot = settlePackageRoot(path.resolve(opts.packageRoot), targetDir);
|
|
2471
|
+
pinLauncherPackageRoot(packageRoot);
|
|
2349
2472
|
const logFn = opts.log;
|
|
2350
2473
|
const log =
|
|
2351
2474
|
logFn ||
|
|
2352
2475
|
((_component, _action, _status, _details) => {
|
|
2353
2476
|
/* noop */
|
|
2354
2477
|
});
|
|
2355
|
-
|
|
2478
|
+
try {
|
|
2356
2479
|
wearVendoredRepertoire(packageRoot, targetDir, log);
|
|
2357
2480
|
|
|
2358
2481
|
if (!isConsumerInstall(packageRoot, targetDir)) {
|
|
@@ -2373,6 +2496,9 @@ function installAllBridges(opts) {
|
|
|
2373
2496
|
installCursorBridge(targetDir, packageRoot, log);
|
|
2374
2497
|
|
|
2375
2498
|
log("install-bridges", "4-platform + cursor wear complete", "success");
|
|
2499
|
+
} finally {
|
|
2500
|
+
pinLauncherPackageRoot("");
|
|
2501
|
+
}
|
|
2376
2502
|
}
|
|
2377
2503
|
|
|
2378
2504
|
module.exports = {
|
|
@@ -2393,6 +2519,8 @@ module.exports = {
|
|
|
2393
2519
|
MERGE_CONFIG_FILES,
|
|
2394
2520
|
patchGrokHooks,
|
|
2395
2521
|
grokHookShellCommand,
|
|
2522
|
+
settlePackageRoot,
|
|
2523
|
+
scrubEphemeralMachineGrokPins,
|
|
2396
2524
|
writeGrokDiscoveredHooks,
|
|
2397
2525
|
isEphemeralInstallRoot,
|
|
2398
2526
|
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
|
|
@@ -10,14 +10,38 @@ import { XrayKnowledgeSkillBase } from "./shared/knowledge-skill-base.js";
|
|
|
10
10
|
import * as fs from "fs";
|
|
11
11
|
import * as path from "path";
|
|
12
12
|
import { frameworkLogger } from "../core/framework-logger.js";
|
|
13
|
+
import { type GovernanceVote } from "../governance/llm-governance-provider.js";
|
|
13
14
|
import {
|
|
14
15
|
contextAnalysis as architectContextAnalysis,
|
|
15
16
|
codebaseStructure as architectCodebaseStructure,
|
|
16
17
|
dependencyAnalysis as architectDependencyAnalysis,
|
|
17
18
|
architectureAssessment as architectArchitectureAssessment,
|
|
18
|
-
|
|
19
|
+
type ArchitectureAssessment,
|
|
19
20
|
} from "../architect/architect-tools.js";
|
|
20
21
|
|
|
22
|
+
export type ConferModelVerdict = "PASS" | "CONDITIONAL" | "FAIL" | "UNREVIEWED";
|
|
23
|
+
|
|
24
|
+
/** A confer verdict counts only when a model vote exists. Metrics alone are UNREVIEWED. */
|
|
25
|
+
export function conferVerdictFromModelVote(
|
|
26
|
+
vote: Pick<GovernanceVote, "decision"> | null,
|
|
27
|
+
): ConferModelVerdict {
|
|
28
|
+
if (!vote) return "UNREVIEWED";
|
|
29
|
+
if (vote.decision === "reject") return "FAIL";
|
|
30
|
+
if (vote.decision === "approve") return "PASS";
|
|
31
|
+
return "CONDITIONAL";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function formatArchitectureAssessmentConferText(
|
|
35
|
+
conferPrompt: string,
|
|
36
|
+
assessment: ArchitectureAssessment,
|
|
37
|
+
verdict: ConferModelVerdict = "UNREVIEWED",
|
|
38
|
+
): string {
|
|
39
|
+
const assessmentJson = JSON.stringify(assessment, null, 2);
|
|
40
|
+
const trimmed = conferPrompt.trim();
|
|
41
|
+
if (!trimmed) return assessmentJson;
|
|
42
|
+
return `${trimmed}\n\n## Architecture assessment\n${assessmentJson}\n\nVerdict: ${verdict}\nTop risks: review assessment metrics above\nHardening: address high-complexity or coupling findings before resuming`;
|
|
43
|
+
}
|
|
44
|
+
|
|
21
45
|
interface DirectoryNode {
|
|
22
46
|
name: string;
|
|
23
47
|
path: string;
|
|
@@ -48,7 +72,7 @@ export async function renderArchitectureAssessment(
|
|
|
48
72
|
content: [
|
|
49
73
|
{
|
|
50
74
|
type: "text",
|
|
51
|
-
text:
|
|
75
|
+
text: formatArchitectureAssessmentConferText(conferPrompt, result, "UNREVIEWED"),
|
|
52
76
|
},
|
|
53
77
|
],
|
|
54
78
|
};
|
|
@@ -83,25 +83,25 @@ describe('ServerConfigRegistry', () => {
|
|
|
83
83
|
expect(registry.has('code-review')).toBe(true);
|
|
84
84
|
const config = registry.get('code-review');
|
|
85
85
|
expect(config?.command).toBe('node');
|
|
86
|
-
expect(config?.timeout).toBe(
|
|
86
|
+
expect(config?.timeout).toBe(150000);
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
it('should have security-audit server registered by default', () => {
|
|
90
90
|
expect(registry.has('security-audit')).toBe(true);
|
|
91
91
|
const config = registry.get('security-audit');
|
|
92
|
-
expect(config?.timeout).toBe(
|
|
92
|
+
expect(config?.timeout).toBe(150000);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
it('should have security-auditor alias registered by default', () => {
|
|
96
96
|
expect(registry.has('security-auditor')).toBe(true);
|
|
97
97
|
const config = registry.get('security-auditor');
|
|
98
|
-
expect(config?.timeout).toBe(
|
|
98
|
+
expect(config?.timeout).toBe(150000);
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
it('should have researcher server registered by default', () => {
|
|
102
102
|
expect(registry.has('researcher')).toBe(true);
|
|
103
103
|
const config = registry.get('researcher');
|
|
104
|
-
expect(config?.timeout).toBe(
|
|
104
|
+
expect(config?.timeout).toBe(150000);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
it('should have framework-help server registered by default', () => {
|
|
@@ -119,7 +119,7 @@ describe('ServerConfigRegistry', () => {
|
|
|
119
119
|
it('should have architect server registered by default', () => {
|
|
120
120
|
expect(registry.has('architect')).toBe(true);
|
|
121
121
|
const config = registry.get('architect');
|
|
122
|
-
expect(config?.timeout).toBe(
|
|
122
|
+
expect(config?.timeout).toBe(150000);
|
|
123
123
|
});
|
|
124
124
|
|
|
125
125
|
it('should have enforcer server registered by default', () => {
|
|
@@ -242,7 +242,16 @@ describe('ServerConfigRegistry', () => {
|
|
|
242
242
|
|
|
243
243
|
// Governance (Dynamo Solar SSOT orchestrator) is allowed higher timeout
|
|
244
244
|
// because it coordinates multiple skill MCPs + required external filter.
|
|
245
|
-
const
|
|
245
|
+
const modelServers = new Set([
|
|
246
|
+
'governance',
|
|
247
|
+
'architect',
|
|
248
|
+
'code-review',
|
|
249
|
+
'code-reviewer',
|
|
250
|
+
'researcher',
|
|
251
|
+
'security-audit',
|
|
252
|
+
'security-auditor',
|
|
253
|
+
]);
|
|
254
|
+
const maxTimeout = modelServers.has(config.serverName) ? 150000 : 60000;
|
|
246
255
|
expect(config.timeout).toBeLessThanOrEqual(maxTimeout);
|
|
247
256
|
}
|
|
248
257
|
});
|
|
@@ -13,6 +13,9 @@ import { fileURLToPath } from 'url';
|
|
|
13
13
|
import { dirname, join, resolve } from 'path';
|
|
14
14
|
import fs from 'fs';
|
|
15
15
|
|
|
16
|
+
/** Must outlast the 120s governance model call so a real approve can return. */
|
|
17
|
+
const GOVERNANCE_MODEL_TIMEOUT_MS = 150_000;
|
|
18
|
+
|
|
16
19
|
/**
|
|
17
20
|
* Registry for managing MCP server configurations
|
|
18
21
|
*/
|
|
@@ -95,7 +98,7 @@ export class ServerConfigRegistry {
|
|
|
95
98
|
serverName: 'code-review',
|
|
96
99
|
command: 'node',
|
|
97
100
|
args: [`${basePath}/knowledge-skills/code-review.server.js`],
|
|
98
|
-
timeout:
|
|
101
|
+
timeout: GOVERNANCE_MODEL_TIMEOUT_MS,
|
|
99
102
|
});
|
|
100
103
|
|
|
101
104
|
// Security Audit Server
|
|
@@ -103,7 +106,7 @@ export class ServerConfigRegistry {
|
|
|
103
106
|
serverName: 'security-audit',
|
|
104
107
|
command: 'node',
|
|
105
108
|
args: [`${basePath}/knowledge-skills/security-audit.server.js`],
|
|
106
|
-
timeout:
|
|
109
|
+
timeout: GOVERNANCE_MODEL_TIMEOUT_MS,
|
|
107
110
|
});
|
|
108
111
|
|
|
109
112
|
// Performance Optimization Server
|
|
@@ -127,7 +130,7 @@ export class ServerConfigRegistry {
|
|
|
127
130
|
serverName: 'researcher',
|
|
128
131
|
command: 'node',
|
|
129
132
|
args: [`${basePath}/researcher.server.js`],
|
|
130
|
-
timeout:
|
|
133
|
+
timeout: GOVERNANCE_MODEL_TIMEOUT_MS,
|
|
131
134
|
});
|
|
132
135
|
|
|
133
136
|
// Governance Service (meta-MCP that orchestrates the three skill servers + required external Dynamo)
|
|
@@ -199,7 +202,7 @@ export class ServerConfigRegistry {
|
|
|
199
202
|
serverName: 'architect',
|
|
200
203
|
command: 'node',
|
|
201
204
|
args: [`${basePath}/architect-tools.server.js`],
|
|
202
|
-
timeout:
|
|
205
|
+
timeout: GOVERNANCE_MODEL_TIMEOUT_MS,
|
|
203
206
|
});
|
|
204
207
|
|
|
205
208
|
// Bug Triage Specialist Server
|
|
@@ -224,7 +227,7 @@ export class ServerConfigRegistry {
|
|
|
224
227
|
serverName: 'code-reviewer',
|
|
225
228
|
command: 'node',
|
|
226
229
|
args: [`${basePath}/knowledge-skills/code-review.server.js`],
|
|
227
|
-
timeout:
|
|
230
|
+
timeout: GOVERNANCE_MODEL_TIMEOUT_MS,
|
|
228
231
|
});
|
|
229
232
|
|
|
230
233
|
// Security Auditor (alias for security-audit)
|
|
@@ -232,7 +235,7 @@ export class ServerConfigRegistry {
|
|
|
232
235
|
serverName: 'security-auditor',
|
|
233
236
|
command: 'node',
|
|
234
237
|
args: [`${basePath}/knowledge-skills/security-audit.server.js`],
|
|
235
|
-
timeout:
|
|
238
|
+
timeout: GOVERNANCE_MODEL_TIMEOUT_MS,
|
|
236
239
|
});
|
|
237
240
|
|
|
238
241
|
// Refactorer Server
|