@lifeaitools/rdc-skills 0.25.10 → 0.26.0
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/.claude-plugin/plugin.json +1608 -1551
- package/.github/workflows/self-test.yml +34 -34
- package/CHANGELOG.md +332 -319
- package/MANIFEST.md +224 -224
- package/README.md +368 -367
- package/RELEASE.md +50 -45
- package/bin/rdc-skills-mcp.mjs +1 -1
- package/commands/build.md +181 -181
- package/commands/collab.md +180 -180
- package/commands/deploy.md +173 -148
- package/commands/fixit.md +150 -150
- package/commands/handoff.md +173 -173
- package/commands/overnight.md +220 -220
- package/commands/plan.md +158 -158
- package/commands/preplan.md +131 -131
- package/commands/prototype.md +145 -145
- package/commands/report.md +99 -99
- package/commands/review.md +120 -120
- package/commands/status.md +86 -86
- package/commands/workitems.md +127 -127
- package/deploy/install-systemd.sh +16 -0
- package/deploy/systemd/rdc-skills-mcp.service +19 -0
- package/git-sha.json +1 -1
- package/guides/agent-bootstrap.md +195 -195
- package/guides/agents/backend.md +102 -102
- package/guides/agents/content.md +94 -94
- package/guides/agents/cs2.md +56 -56
- package/guides/agents/data.md +86 -86
- package/guides/agents/design.md +77 -77
- package/guides/agents/frontend.md +91 -91
- package/guides/agents/infrastructure.md +81 -81
- package/guides/agents/setup.md +272 -272
- package/guides/agents/verify.md +119 -119
- package/guides/agents/viz.md +106 -106
- package/guides/orchestration-epic.md +17 -0
- package/hooks/check-rdc-environment.js +172 -378
- package/hooks/lib/box-lock.js +4 -5
- package/package.json +1 -2
- package/scripts/install-rdc-skills.js +19 -264
- package/scripts/probe-installed-hooks.mjs +2 -2
- package/scripts/self-test.mjs +1459 -1459
- package/scripts/validate-publish-manifests.js +502 -502
- package/skills/build/SKILL.md +662 -578
- package/skills/channel-formatter/SKILL.md +538 -538
- package/skills/collab/SKILL.md +239 -239
- package/skills/convert/SKILL.md +138 -138
- package/skills/deploy/SKILL.md +583 -541
- package/skills/design/SKILL.md +205 -205
- package/skills/env/SKILL.md +146 -139
- package/skills/fixit/SKILL.md +203 -203
- package/skills/handoff/SKILL.md +236 -236
- package/skills/housekeeping/SKILL.md +189 -189
- package/skills/onramp/SKILL.md +1459 -1459
- package/skills/overnight/SKILL.md +251 -251
- package/skills/plan/SKILL.md +345 -345
- package/skills/preplan/SKILL.md +90 -90
- package/skills/prototype/SKILL.md +150 -150
- package/skills/refactor/SKILL.md +51 -0
- package/skills/regen-media/SKILL.md +94 -94
- package/skills/release/SKILL.md +140 -140
- package/skills/report/SKILL.md +100 -100
- package/skills/review/SKILL.md +151 -151
- package/skills/self-test/SKILL.md +108 -108
- package/skills/status/SKILL.md +99 -99
- package/skills/tests/MATRIX.md +59 -55
- package/skills/tests/README.md +1 -1
- package/skills/tests/onramp.test.json +101 -87
- package/skills/tests/rdc-env.test.json +12 -0
- package/skills/tests/rdc-new-model.test.json +12 -0
- package/skills/tests/rdc-refactor.test.json +29 -0
- package/skills/tests/rdc-regen-media.test.json +29 -29
- package/skills/watch/SKILL.md +84 -84
- package/skills/workitems/SKILL.md +151 -151
- package/tests/no-local-pm2.test.mjs +45 -0
- package/scripts/local-install-with-stop.sh +0 -41
- package/scripts/probe-lock-holders.mjs +0 -36
- package/scripts/rebuild-mcp.mjs +0 -107
|
@@ -30,8 +30,6 @@ const fs = require('fs');
|
|
|
30
30
|
const path = require('path');
|
|
31
31
|
const os = require('os');
|
|
32
32
|
const readline = require('readline');
|
|
33
|
-
const http = require('http');
|
|
34
|
-
const crypto = require('crypto');
|
|
35
33
|
const { execSync } = require('child_process');
|
|
36
34
|
|
|
37
35
|
// ── Args ──────────────────────────────────────────────────────────────────────
|
|
@@ -90,9 +88,7 @@ const projectRoot = projectRootArg || codexRoot || detectedLifeaiRoot;
|
|
|
90
88
|
|
|
91
89
|
const PLUGIN_KEY = 'rdc-skills@rdc-skills';
|
|
92
90
|
const MARKETPLACE = 'rdc-skills';
|
|
93
|
-
const
|
|
94
|
-
const MCP_NAME = 'rdc-skills-mcp';
|
|
95
|
-
const MCP_PORT = '3110';
|
|
91
|
+
const PUBLIC_MCP_URL = 'https://rdc-skills.regendevcorp.com/mcp';
|
|
96
92
|
|
|
97
93
|
// ── Logging ───────────────────────────────────────────────────────────────────
|
|
98
94
|
const ok = msg => console.log(` \x1b[32m✓\x1b[0m ${msg}`);
|
|
@@ -104,12 +100,6 @@ function run(cmd, options = {}) {
|
|
|
104
100
|
return execSync(cmd, { encoding: 'utf8', stdio: 'pipe', ...options }).trim();
|
|
105
101
|
}
|
|
106
102
|
|
|
107
|
-
function shellQuote(s) {
|
|
108
|
-
const raw = String(s);
|
|
109
|
-
if (process.platform === 'win32') return `"${raw.replace(/"/g, '\\"')}"`;
|
|
110
|
-
return `'${raw.replace(/'/g, `'\\''`)}'`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
103
|
function updateCodexMcpToml(toml, mcpUrl) {
|
|
114
104
|
const blockRe = /(^|\n)(\[mcp_servers\.rdc-skills\]\n)([\s\S]*?)(?=\n\[|\s*$)/;
|
|
115
105
|
const desiredLine = `url = '${mcpUrl}'`;
|
|
@@ -218,8 +208,8 @@ function assertHooksLoadable(hooksDst, copiedCount) {
|
|
|
218
208
|
if (res.status !== 0) throw new Error(`installed hook fails to parse: ${combined.trim().slice(0, 300)}`);
|
|
219
209
|
|
|
220
210
|
// RESOLVE the dependency graph without EXECUTING it. `require(entry)` ran the
|
|
221
|
-
// WHOLE hook during install —
|
|
222
|
-
//
|
|
211
|
+
// WHOLE hook during install — including package repair — and on an unhealthy
|
|
212
|
+
// box can create a recursive install -> repair -> install loop.
|
|
223
213
|
// require.resolve answers the only question that matters here ("can it find
|
|
224
214
|
// ./lib/box-lock?") with no side effects.
|
|
225
215
|
const probe = [
|
|
@@ -365,174 +355,6 @@ function buildPluginCache(cacheDir, version, gitSha) {
|
|
|
365
355
|
}
|
|
366
356
|
}
|
|
367
357
|
|
|
368
|
-
function getPm2Process(name) {
|
|
369
|
-
try {
|
|
370
|
-
const list = JSON.parse(run('pm2 jlist'));
|
|
371
|
-
return Array.isArray(list) ? list.find((p) => p.name === name) || null : null;
|
|
372
|
-
} catch {
|
|
373
|
-
return null;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
function isGlobalNpmRdcSkillsPath(scriptPath) {
|
|
378
|
-
if (!scriptPath) return false;
|
|
379
|
-
const normalized = scriptPath.replace(/\\/g, '/').toLowerCase();
|
|
380
|
-
return normalized.includes('/node_modules/@lifeaitools/rdc-skills/');
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
function packageRootFromMcpScript(scriptPath) {
|
|
384
|
-
return scriptPath ? path.resolve(path.dirname(scriptPath), '..') : null;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
function readInstalledPackageVersion(scriptPath) {
|
|
388
|
-
const packageRoot = packageRootFromMcpScript(scriptPath);
|
|
389
|
-
if (!packageRoot) return null;
|
|
390
|
-
return readJson(path.join(packageRoot, 'package.json'), {}).version || null;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
function collectFilesRecursive(baseDir, rel, out) {
|
|
394
|
-
const full = path.join(baseDir, rel);
|
|
395
|
-
if (!fs.existsSync(full)) return;
|
|
396
|
-
const stat = fs.statSync(full);
|
|
397
|
-
if (stat.isDirectory()) {
|
|
398
|
-
for (const entry of fs.readdirSync(full).sort()) {
|
|
399
|
-
collectFilesRecursive(baseDir, path.join(rel, entry), out);
|
|
400
|
-
}
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
if (stat.isFile()) out.push(rel.replace(/\\/g, '/'));
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function hashInstallSurface(root) {
|
|
407
|
-
if (!root || !fs.existsSync(root)) return null;
|
|
408
|
-
const rels = [];
|
|
409
|
-
for (const rel of ['.claude-plugin', 'commands', 'guides', 'skills', 'package.json', 'README.md']) {
|
|
410
|
-
collectFilesRecursive(root, rel, rels);
|
|
411
|
-
}
|
|
412
|
-
const hash = crypto.createHash('sha256');
|
|
413
|
-
for (const rel of rels.sort()) {
|
|
414
|
-
hash.update(rel);
|
|
415
|
-
hash.update('\0');
|
|
416
|
-
hash.update(fs.readFileSync(path.join(root, rel)));
|
|
417
|
-
hash.update('\0');
|
|
418
|
-
}
|
|
419
|
-
return hash.digest('hex');
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
function syncGlobalMcpInstall(version) {
|
|
423
|
-
const proc = getPm2Process(MCP_NAME);
|
|
424
|
-
if (!proc) {
|
|
425
|
-
info('[2.9] MCP pkg — PM2 process not registered yet; start handled below');
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
const scriptPath = proc.pm2_env?.pm_exec_path || proc.pm_exec_path || '';
|
|
430
|
-
if (!isGlobalNpmRdcSkillsPath(scriptPath)) {
|
|
431
|
-
info(`[2.9] MCP pkg — PM2 uses source checkout, not global npm (${scriptPath || 'unknown path'})`);
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
const installedVersion = readInstalledPackageVersion(scriptPath);
|
|
436
|
-
const packageRoot = packageRootFromMcpScript(scriptPath);
|
|
437
|
-
const sourceHash = hashInstallSurface(repoRoot);
|
|
438
|
-
const installedHash = hashInstallSurface(packageRoot);
|
|
439
|
-
if (installedVersion === version && sourceHash && installedHash && sourceHash === installedHash) {
|
|
440
|
-
ok(`[2.9] MCP pkg — global ${NPM_PACKAGE}@${version} already matches source`);
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
let stopped = false;
|
|
445
|
-
let installed = false;
|
|
446
|
-
try {
|
|
447
|
-
const reason = installedVersion === version ? 'same version, source changed' : `${installedVersion || '?'} → ${version}`;
|
|
448
|
-
info(`[2.9] MCP pkg — updating global ${NPM_PACKAGE} (${reason}) from local source`);
|
|
449
|
-
run(`pm2 stop ${MCP_NAME}`);
|
|
450
|
-
stopped = true;
|
|
451
|
-
run(`npm install -g ${shellQuote(repoRoot)}`);
|
|
452
|
-
installed = true;
|
|
453
|
-
ok(`[2.9] MCP pkg — installed global ${NPM_PACKAGE}@${version}`);
|
|
454
|
-
} catch (e) {
|
|
455
|
-
warn(`[2.9] MCP pkg — global install failed (${String(e.message || e).split('\n')[0]})`);
|
|
456
|
-
if (String(e.message || '').includes('EBUSY')) {
|
|
457
|
-
info(' PM2 was stopped first; if EBUSY persists, another Node/npm process still holds the package directory.');
|
|
458
|
-
}
|
|
459
|
-
} finally {
|
|
460
|
-
if (stopped) {
|
|
461
|
-
try {
|
|
462
|
-
run(`pm2 restart ${MCP_NAME} --update-env`, { env: { ...process.env, PORT: MCP_PORT } });
|
|
463
|
-
ok(`[2.9] MCP pkg — pm2 restarted ${MCP_NAME}${installed ? '' : ' (previous install restored)'}`);
|
|
464
|
-
} catch (e) {
|
|
465
|
-
warn(`[2.9] MCP pkg — pm2 restart failed (${String(e.message || e).split('\n')[0]})`);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
function callLocalMcpTool(name, args = {}) {
|
|
472
|
-
return new Promise((resolve, reject) => {
|
|
473
|
-
const payload = JSON.stringify({
|
|
474
|
-
jsonrpc: '2.0',
|
|
475
|
-
id: 1,
|
|
476
|
-
method: 'tools/call',
|
|
477
|
-
params: { name, arguments: args },
|
|
478
|
-
});
|
|
479
|
-
const req = http.request({
|
|
480
|
-
hostname: '127.0.0.1',
|
|
481
|
-
port: Number(MCP_PORT),
|
|
482
|
-
path: '/mcp',
|
|
483
|
-
method: 'POST',
|
|
484
|
-
headers: {
|
|
485
|
-
'Content-Type': 'application/json',
|
|
486
|
-
'Accept': 'application/json, text/event-stream',
|
|
487
|
-
'Content-Length': Buffer.byteLength(payload),
|
|
488
|
-
},
|
|
489
|
-
timeout: 10000,
|
|
490
|
-
}, (res) => {
|
|
491
|
-
let body = '';
|
|
492
|
-
res.setEncoding('utf8');
|
|
493
|
-
res.on('data', (chunk) => { body += chunk; });
|
|
494
|
-
res.on('end', () => {
|
|
495
|
-
try {
|
|
496
|
-
const dataLine = body.split(/\r?\n/).find((line) => line.startsWith('data: '));
|
|
497
|
-
const envelope = JSON.parse(dataLine ? dataLine.slice(6) : body);
|
|
498
|
-
const text = envelope?.result?.content?.[0]?.text;
|
|
499
|
-
resolve(text ? JSON.parse(text) : envelope);
|
|
500
|
-
} catch (e) {
|
|
501
|
-
reject(new Error(`invalid MCP response: ${e.message}`));
|
|
502
|
-
}
|
|
503
|
-
});
|
|
504
|
-
});
|
|
505
|
-
req.on('timeout', () => req.destroy(new Error('MCP request timed out')));
|
|
506
|
-
req.on('error', reject);
|
|
507
|
-
req.write(payload);
|
|
508
|
-
req.end();
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
async function verifyLiveMcpCatalogFresh() {
|
|
513
|
-
const proc = getPm2Process(MCP_NAME);
|
|
514
|
-
if (!proc) {
|
|
515
|
-
warn('[7.5] MCP catalog — skipped (PM2 process not registered)');
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
const sourceSkills = fs.readdirSync(path.join(repoRoot, 'skills'), { withFileTypes: true })
|
|
519
|
-
.filter((entry) => entry.isDirectory() && fs.existsSync(path.join(repoRoot, 'skills', entry.name, 'SKILL.md')))
|
|
520
|
-
.map((entry) => entry.name)
|
|
521
|
-
.sort();
|
|
522
|
-
const catalog = await callLocalMcpTool('rdc_skill_list', {});
|
|
523
|
-
const rows = Array.isArray(catalog)
|
|
524
|
-
? catalog
|
|
525
|
-
: Array.isArray(catalog?.skills) ? catalog.skills
|
|
526
|
-
: Array.isArray(catalog?.results) ? catalog.results
|
|
527
|
-
: [];
|
|
528
|
-
const liveNames = new Set(rows.map((row) => row.name));
|
|
529
|
-
const missing = sourceSkills.filter((name) => !liveNames.has(name));
|
|
530
|
-
if (missing.length > 0 || rows.length < sourceSkills.length) {
|
|
531
|
-
throw new Error(`live MCP catalog stale: source=${sourceSkills.length}, live=${rows.length}, missing=${missing.join(', ') || '(count mismatch)'}`);
|
|
532
|
-
}
|
|
533
|
-
ok(`[7.5] MCP catalog — ${rows.length} live skill(s), source catalog fresh`);
|
|
534
|
-
}
|
|
535
|
-
|
|
536
358
|
// ── User-skills cleanup ───────────────────────────────────────────────────────
|
|
537
359
|
// Older installer versions wrote skill files directly to ~/.claude/skills/user/.
|
|
538
360
|
// Claude Code loads that directory AND the plugin cache, so any rdc skills left
|
|
@@ -814,7 +636,6 @@ function addCodexTarget(targets, label, targetDir) {
|
|
|
814
636
|
// existing clauth/codeflow entries exactly. claude.ai web still needs the one-time
|
|
815
637
|
// connector add in its UI (no programmatic API).
|
|
816
638
|
function registerMcpEndpoints() {
|
|
817
|
-
const MCP_URL = 'https://rdc-skills.regendevcorp.com/mcp';
|
|
818
639
|
const out = [];
|
|
819
640
|
|
|
820
641
|
// Claude Code — user-level ~/.claude.json mcpServers (covers EVERY project).
|
|
@@ -824,8 +645,8 @@ function registerMcpEndpoints() {
|
|
|
824
645
|
const data = readJson(claudeJson);
|
|
825
646
|
if (!data.mcpServers || typeof data.mcpServers !== 'object') data.mcpServers = {};
|
|
826
647
|
const cur = data.mcpServers['rdc-skills'];
|
|
827
|
-
if (!cur || cur.url !==
|
|
828
|
-
data.mcpServers['rdc-skills'] = { type: 'http', url:
|
|
648
|
+
if (!cur || cur.url !== PUBLIC_MCP_URL) {
|
|
649
|
+
data.mcpServers['rdc-skills'] = { type: 'http', url: PUBLIC_MCP_URL };
|
|
829
650
|
writeJson(claudeJson, data, 2);
|
|
830
651
|
out.push('claude(~/.claude.json)');
|
|
831
652
|
}
|
|
@@ -837,7 +658,7 @@ function registerMcpEndpoints() {
|
|
|
837
658
|
const codexToml = path.join(os.homedir(), '.codex', 'config.toml');
|
|
838
659
|
if (fs.existsSync(codexToml)) {
|
|
839
660
|
const toml = fs.readFileSync(codexToml, 'utf8');
|
|
840
|
-
const next = updateCodexMcpToml(toml,
|
|
661
|
+
const next = updateCodexMcpToml(toml, PUBLIC_MCP_URL);
|
|
841
662
|
if (next !== toml) {
|
|
842
663
|
fs.writeFileSync(codexToml, next);
|
|
843
664
|
out.push('codex(~/.codex/config.toml)');
|
|
@@ -958,19 +779,14 @@ function buildZip(version) {
|
|
|
958
779
|
// ── Hook config ───────────────────────────────────────────────────────────────
|
|
959
780
|
|
|
960
781
|
/**
|
|
961
|
-
* SessionStart budget for check-rdc-environment.js,
|
|
962
|
-
*
|
|
963
|
-
* two cannot drift apart.
|
|
782
|
+
* SessionStart budget for check-rdc-environment.js, derived from its two repair
|
|
783
|
+
* steps: global package install and plugin registration.
|
|
964
784
|
*
|
|
965
|
-
* At the harness default (60s) a genuine cold repair
|
|
966
|
-
* leader's own steps alone exceed it — and every follower read that as a crash.
|
|
967
|
-
* The +60s headroom matters: a budget equal to the exact sum kills a leader that
|
|
968
|
-
* legitimately uses its full per-step allowance right at the boundary.
|
|
785
|
+
* At the harness default (60s) a genuine cold repair can be killed mid-install.
|
|
969
786
|
*/
|
|
970
787
|
const REPAIR_NPM_SEC = 120; // npm install -g
|
|
971
788
|
const REPAIR_INSTALL_SEC = 180; // rdc-skills-install
|
|
972
|
-
const
|
|
973
|
-
const RDC_ENV_HOOK_TIMEOUT_SEC = REPAIR_NPM_SEC + REPAIR_INSTALL_SEC + REPAIR_PM2_SEC + 60;
|
|
789
|
+
const RDC_ENV_HOOK_TIMEOUT_SEC = REPAIR_NPM_SEC + REPAIR_INSTALL_SEC + 60;
|
|
974
790
|
|
|
975
791
|
function buildHooksConfig(hooksDir, profile = 'core') {
|
|
976
792
|
const base = hooksDir.replace(/\\/g, '/');
|
|
@@ -1050,62 +866,12 @@ function buildHooksConfig(hooksDir, profile = 'core') {
|
|
|
1050
866
|
return config;
|
|
1051
867
|
}
|
|
1052
868
|
|
|
1053
|
-
// ── MCP
|
|
1054
|
-
//
|
|
1055
|
-
//
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
const connector = 'https://rdc-skills.regendevcorp.com/mcp';
|
|
1060
|
-
|
|
1061
|
-
try {
|
|
1062
|
-
// (a) ensure MCP runtime deps are present (express, @modelcontextprotocol/sdk, yaml, zod)
|
|
1063
|
-
const needDeps = ['express', '@modelcontextprotocol/sdk', 'yaml', 'zod'].some((d) => {
|
|
1064
|
-
try { require.resolve(d, { paths: [repoRoot] }); return false; } catch { return true; }
|
|
1065
|
-
});
|
|
1066
|
-
if (needDeps) {
|
|
1067
|
-
try {
|
|
1068
|
-
execSync('npm install --no-audit --no-fund', { cwd: repoRoot, stdio: 'pipe' });
|
|
1069
|
-
ok('[7/7] MCP deps — installed');
|
|
1070
|
-
} catch (e) {
|
|
1071
|
-
warn(`[7/7] MCP deps — npm install failed (${e.message.split('\n')[0]}); install manually with \`npm install\``);
|
|
1072
|
-
}
|
|
1073
|
-
} else {
|
|
1074
|
-
ok('[7/7] MCP deps — already present');
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
// (b) register/start under PM2 (tolerate pm2 missing)
|
|
1078
|
-
let pm2Ok = false;
|
|
1079
|
-
try { execSync('pm2 -v', { stdio: 'pipe' }); pm2Ok = true; } catch { pm2Ok = false; }
|
|
1080
|
-
|
|
1081
|
-
if (!pm2Ok) {
|
|
1082
|
-
warn('[7/7] MCP server — pm2 not found; start manually:');
|
|
1083
|
-
info(` PORT=${MCP_PORT} pm2 start ${binPath} --name ${MCP_NAME}`);
|
|
1084
|
-
} else {
|
|
1085
|
-
let registered = false;
|
|
1086
|
-
try {
|
|
1087
|
-
const jlist = JSON.parse(execSync('pm2 jlist', { encoding: 'utf8', stdio: 'pipe' }));
|
|
1088
|
-
registered = Array.isArray(jlist) && jlist.some((p) => p.name === MCP_NAME);
|
|
1089
|
-
} catch {}
|
|
1090
|
-
try {
|
|
1091
|
-
if (registered) {
|
|
1092
|
-
execSync(`pm2 restart ${MCP_NAME} --update-env`, { cwd: repoRoot, stdio: 'pipe', env: { ...process.env, PORT: MCP_PORT } });
|
|
1093
|
-
ok(`[7/7] MCP server — pm2 restarted ${MCP_NAME} (PORT=${MCP_PORT})`);
|
|
1094
|
-
} else {
|
|
1095
|
-
execSync(`pm2 start "${binPath}" --name ${MCP_NAME}`, { cwd: repoRoot, stdio: 'pipe', env: { ...process.env, PORT: MCP_PORT } });
|
|
1096
|
-
ok(`[7/7] MCP server — pm2 started ${MCP_NAME} (PORT=${MCP_PORT})`);
|
|
1097
|
-
}
|
|
1098
|
-
} catch (e) {
|
|
1099
|
-
warn(`[7/7] MCP server — pm2 start/restart failed (${e.message.split('\n')[0]})`);
|
|
1100
|
-
info(` PORT=${MCP_PORT} pm2 start ${binPath} --name ${MCP_NAME}`);
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
// (c) print the claude.ai connector line
|
|
1105
|
-
info(` claude.ai connector: ${connector} (Auth: none — URL is the shared secret)`);
|
|
1106
|
-
} catch (e) {
|
|
1107
|
-
warn(`[7/7] MCP server — skipped (${e.message.split('\n')[0]})`);
|
|
1108
|
-
}
|
|
869
|
+
// ── Public MCP connector ──────────────────────────────────────────────────────
|
|
870
|
+
// The MCP is independently hosted. Installation only registers and reports its
|
|
871
|
+
// standard public URL; it never launches a local server or process manager.
|
|
872
|
+
function reportMcpConnector() {
|
|
873
|
+
ok('[7/7] MCP connector — public stateless endpoint registered');
|
|
874
|
+
info(` claude.ai / MCP clients: ${PUBLIC_MCP_URL} (Auth: none)`);
|
|
1109
875
|
}
|
|
1110
876
|
|
|
1111
877
|
// ── Preflight ─────────────────────────────────────────────────────────────────
|
|
@@ -1310,11 +1076,6 @@ async function main() {
|
|
|
1310
1076
|
info('[2.6] MCP — rdc-skills endpoint already registered (claude + codex)');
|
|
1311
1077
|
}
|
|
1312
1078
|
|
|
1313
|
-
// If the live MCP is served from the global npm package, update that exact
|
|
1314
|
-
// install before restarting PM2. Windows otherwise holds the package tree open
|
|
1315
|
-
// and `npm install -g` can fail with EBUSY.
|
|
1316
|
-
syncGlobalMcpInstall(version);
|
|
1317
|
-
|
|
1318
1079
|
// 2.7. Symlinks in regen-root/.claude/skills/ (FS MCP + claude.ai access)
|
|
1319
1080
|
if (codexRoot) {
|
|
1320
1081
|
const skillsLinkDir = path.join(codexRoot, '.claude', 'skills');
|
|
@@ -1443,16 +1204,10 @@ async function main() {
|
|
|
1443
1204
|
process.exit(2);
|
|
1444
1205
|
}
|
|
1445
1206
|
|
|
1446
|
-
// 7. MCP
|
|
1207
|
+
// 7. Public MCP connector registration
|
|
1447
1208
|
console.log('');
|
|
1448
|
-
console.log(' \x1b[36mMCP
|
|
1449
|
-
|
|
1450
|
-
try {
|
|
1451
|
-
await verifyLiveMcpCatalogFresh();
|
|
1452
|
-
} catch (e) {
|
|
1453
|
-
fail(`[7.5] MCP catalog — ${e.message}`);
|
|
1454
|
-
process.exit(2);
|
|
1455
|
-
}
|
|
1209
|
+
console.log(' \x1b[36mMCP connector:\x1b[0m');
|
|
1210
|
+
reportMcpConnector();
|
|
1456
1211
|
|
|
1457
1212
|
// Done
|
|
1458
1213
|
console.log('');
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* The source was fine, the npm tarball was fine, and only the copied result was
|
|
6
6
|
* broken: copyHookFiles() was flat, so hooks/lib/ was never created at the
|
|
7
7
|
* destination and require('./lib/box-lock') died MODULE_NOT_FOUND — a SessionStart
|
|
8
|
-
* hook exiting non-zero with EMPTY stdout on every session, before
|
|
9
|
-
* could run, so its own repair path could never recover it.
|
|
8
|
+
* hook exiting non-zero with EMPTY stdout on every session, before its package
|
|
9
|
+
* verification could run, so its own repair path could never recover it.
|
|
10
10
|
*
|
|
11
11
|
* File-presence checks in the repo would not have caught that. This replays the
|
|
12
12
|
* real copy into a scratch dir and LOADS the result.
|