@rubytech/create-maxy-code 0.1.404 → 0.1.405
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/dist/__tests__/launchd-plist.test.js +13 -1
- package/dist/__tests__/neo4j-darwin-dedicated.test.js +52 -0
- package/dist/__tests__/neo4j-datadir.test.js +8 -7
- package/dist/__tests__/neo4j-teardown.test.js +17 -1
- package/dist/index.js +183 -9
- package/dist/launchd-plist.js +21 -0
- package/dist/neo4j-darwin-dedicated.js +39 -0
- package/dist/neo4j-datadir.js +9 -5
- package/dist/neo4j-teardown.js +15 -0
- package/dist/uninstall.js +34 -8
- package/package.json +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -2
- package/payload/premium-plugins/venture-studio/PLUGIN.md +1 -1
- package/payload/premium-plugins/venture-studio/bin/scan-private-data.sh +61 -0
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/SKILL.md +31 -32
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/business-plan-template.md +5 -5
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/competitor-analysis.md +1 -1
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/compliance-research-checklist.md +2 -2
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/data-room-structure.md +1 -1
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/deck-blueprint-template.md +38 -26
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/design-tokens-application.md +2 -2
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/internal-workings-scrub.md +6 -6
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/strategy-frameworks.md +1 -1
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/references/termsheet-template.md +17 -18
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/templates/prospectus/index.html +156 -234
- package/payload/premium-plugins/venture-studio/skills/investor-data-room/templates/prospectus/term_sheet.html +13 -13
- package/payload/premium-plugins/venture-studio/skills/zero-to-prototype/references/strategy-red-team.md +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-BzErD9Zo.js → AdminLoginScreens-D36zz_SY.js} +1 -1
- package/payload/server/public/assets/{AdminShell-BihejKg_.js → AdminShell-DH6Lcj-d.js} +1 -1
- package/payload/server/public/assets/{Checkbox-Ds004CBE.js → Checkbox-54KtArF3.js} +1 -1
- package/payload/server/public/assets/{Transcript-CgaMQKgY.js → Transcript-BCpiXt4J.js} +1 -1
- package/payload/server/public/assets/{admin-BSuRtMws.js → admin-C0FCHcJj.js} +1 -1
- package/payload/server/public/assets/{browser-BO2eR_YY.js → browser-bKeZ5iLx.js} +1 -1
- package/payload/server/public/assets/{calendar-12QuR_oh.js → calendar-BDPBArFA.js} +1 -1
- package/payload/server/public/assets/chat-Cp_1ebzU.js +1 -0
- package/payload/server/public/assets/chevron-left-S7Nk-se6.js +1 -0
- package/payload/server/public/assets/data-BshlTgIW.js +1 -0
- package/payload/server/public/assets/{graph-CDOJZepc.js → graph-Dvru9CW9.js} +1 -1
- package/payload/server/public/assets/{graph-labels-6HKBjyXX.js → graph-labels-DLhR6Rit.js} +1 -1
- package/payload/server/public/assets/{maximize-2-DWmyXX8h.js → maximize-2-CyPKq7HZ.js} +1 -1
- package/payload/server/public/assets/{operator-D-s7jVnf.js → operator-Ql5iQXB-.js} +1 -1
- package/payload/server/public/assets/page-ClJOW2fk.js +32 -0
- package/payload/server/public/assets/{page-rDhp8G9q.js → page-YsTtZsn6.js} +1 -1
- package/payload/server/public/assets/{public-zK67N3z2.js → public-BlDxwcmS.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-BzBJxqBN.js → rotate-ccw-DSynJPZX.js} +1 -1
- package/payload/server/public/assets/{useSubAccountSwitcher-B-GuP1jj.css → useSubAccountSwitcher-CJelLQK-.css} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +5 -5
- package/payload/server/public/chat.html +9 -9
- package/payload/server/public/data.html +8 -8
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +11 -11
- package/payload/server/public/operator.html +11 -11
- package/payload/server/public/public.html +9 -9
- package/payload/server/server.js +2 -0
- package/payload/server/public/assets/chat-Qpyg5t65.js +0 -1
- package/payload/server/public/assets/chevron-left-DBUeR2CX.js +0 -1
- package/payload/server/public/assets/data-Ch5bne41.js +0 -1
- package/payload/server/public/assets/page-BcxrdxYL.js +0 -32
- /package/payload/server/public/assets/{useSubAccountSwitcher-Bg0RH3Gk.js → useSubAccountSwitcher-DGKQxXDD.js} +0 -0
|
@@ -10,7 +10,19 @@
|
|
|
10
10
|
// package so `node --test dist/__tests__/*.test.js` picks it up after build.
|
|
11
11
|
import test from "node:test";
|
|
12
12
|
import assert from "node:assert/strict";
|
|
13
|
-
import { renderPlist, buildSessionManagerWrapper, buildHeartbeatWrapper } from "../launchd-plist.js";
|
|
13
|
+
import { renderPlist, buildSessionManagerWrapper, buildHeartbeatWrapper, buildNeo4jWrapper } from "../launchd-plist.js";
|
|
14
|
+
test("neo4j wrapper exports NEO4J_CONF, prepends brew bins, execs neo4j console", () => {
|
|
15
|
+
const w = buildNeo4jWrapper({ confDir: "/Users/x/.realagent-code/neo4j/conf", brewPrefix: "/usr/local" });
|
|
16
|
+
assert.match(w, /^#!\/bin\/bash/);
|
|
17
|
+
assert.match(w, /export NEO4J_CONF="\/Users\/x\/\.realagent-code\/neo4j\/conf"/);
|
|
18
|
+
assert.match(w, /export PATH="\/usr\/local\/bin:\/usr\/local\/sbin:\$PATH"/);
|
|
19
|
+
assert.match(w, /exec \/usr\/local\/bin\/neo4j console\n$/);
|
|
20
|
+
});
|
|
21
|
+
test("neo4j wrapper honours the Apple Silicon brew prefix", () => {
|
|
22
|
+
const w = buildNeo4jWrapper({ confDir: "/Users/x/.sitedesk-code/neo4j/conf", brewPrefix: "/opt/homebrew" });
|
|
23
|
+
assert.match(w, /export PATH="\/opt\/homebrew\/bin:\/opt\/homebrew\/sbin:\$PATH"/);
|
|
24
|
+
assert.match(w, /exec \/opt\/homebrew\/bin\/neo4j console\n$/);
|
|
25
|
+
});
|
|
14
26
|
// ---------------------------------------------------------------------------
|
|
15
27
|
// Standard render — every required field present, no escaping needed.
|
|
16
28
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Contract grid for the pure darwin dedicated-Neo4j resolvers. No fs/spawn —
|
|
2
|
+
// the wrapper in index.ts (setupDedicatedNeo4jDarwin / resetNeo4jAuth) owns the
|
|
3
|
+
// mkdir/cp/sed/launchctl. Runs via Node's built-in test runner.
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { resolveDarwinDedicatedNeo4jPaths, resolveDarwinDedicatedNeo4jConfKeys, } from "../neo4j-darwin-dedicated.js";
|
|
7
|
+
test("paths derive the full per-brand neo4j tree + brew source/bins", () => {
|
|
8
|
+
const p = resolveDarwinDedicatedNeo4jPaths({ persistDir: "/Users/x/.realagent-code", brewPrefix: "/usr/local" });
|
|
9
|
+
assert.deepEqual(p, {
|
|
10
|
+
home: "/Users/x/.realagent-code/neo4j",
|
|
11
|
+
dataDir: "/Users/x/.realagent-code/neo4j/data",
|
|
12
|
+
confDir: "/Users/x/.realagent-code/neo4j/conf",
|
|
13
|
+
logsDir: "/Users/x/.realagent-code/neo4j/logs",
|
|
14
|
+
runDir: "/Users/x/.realagent-code/neo4j/run",
|
|
15
|
+
pluginsDir: "/Users/x/.realagent-code/neo4j/plugins",
|
|
16
|
+
importDir: "/Users/x/.realagent-code/neo4j/import",
|
|
17
|
+
srcConfDir: "/usr/local/opt/neo4j/libexec/conf",
|
|
18
|
+
neo4jBin: "/usr/local/bin/neo4j",
|
|
19
|
+
neo4jAdminBin: "/usr/local/bin/neo4j-admin",
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
test("home equals resolveNeo4jDataDir's darwin-dedicated root (reset-auth parity)", () => {
|
|
23
|
+
// resetNeo4jAuth clears `${dataDir}/data/...`, where its dataDir arg is `home`.
|
|
24
|
+
const p = resolveDarwinDedicatedNeo4jPaths({ persistDir: "/Users/x/.realagent-code", brewPrefix: "/usr/local" });
|
|
25
|
+
assert.equal(p.dataDir, `${p.home}/data`);
|
|
26
|
+
});
|
|
27
|
+
test("Apple Silicon prefix flows into src conf + bins", () => {
|
|
28
|
+
const p = resolveDarwinDedicatedNeo4jPaths({ persistDir: "/Users/x/.sitedesk-code", brewPrefix: "/opt/homebrew" });
|
|
29
|
+
assert.equal(p.srcConfDir, "/opt/homebrew/opt/neo4j/libexec/conf");
|
|
30
|
+
assert.equal(p.neo4jBin, "/opt/homebrew/bin/neo4j");
|
|
31
|
+
assert.equal(p.neo4jAdminBin, "/opt/homebrew/bin/neo4j-admin");
|
|
32
|
+
});
|
|
33
|
+
test("conf keys: bolt/http listen + five absolute directories, http = port-213", () => {
|
|
34
|
+
const p = resolveDarwinDedicatedNeo4jPaths({ persistDir: "/Users/x/.realagent-code", brewPrefix: "/usr/local" });
|
|
35
|
+
const keys = resolveDarwinDedicatedNeo4jConfKeys({
|
|
36
|
+
port: 7688, dataDir: p.dataDir, logsDir: p.logsDir, runDir: p.runDir, pluginsDir: p.pluginsDir, importDir: p.importDir,
|
|
37
|
+
});
|
|
38
|
+
assert.deepEqual(keys, [
|
|
39
|
+
["server.bolt.listen_address", ":7688"],
|
|
40
|
+
["server.http.listen_address", ":7475"],
|
|
41
|
+
["server.directories.data", "/Users/x/.realagent-code/neo4j/data"],
|
|
42
|
+
["server.directories.logs", "/Users/x/.realagent-code/neo4j/logs"],
|
|
43
|
+
["server.directories.run", "/Users/x/.realagent-code/neo4j/run"],
|
|
44
|
+
["server.directories.plugins", "/Users/x/.realagent-code/neo4j/plugins"],
|
|
45
|
+
["server.directories.import", "/Users/x/.realagent-code/neo4j/import"],
|
|
46
|
+
]);
|
|
47
|
+
});
|
|
48
|
+
test("sitedesk port maps http to 7476", () => {
|
|
49
|
+
const keys = resolveDarwinDedicatedNeo4jConfKeys({ port: 7689, dataDir: "d", logsDir: "l", runDir: "r", pluginsDir: "p", importDir: "i" });
|
|
50
|
+
assert.equal(keys[0][1], ":7689");
|
|
51
|
+
assert.equal(keys[1][1], ":7476");
|
|
52
|
+
});
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
import { resolveNeo4jDataDir } from "../neo4j-datadir.js";
|
|
4
|
-
test("darwin resolves the Homebrew datadir under the brew prefix (Intel + Apple Silicon)", () => {
|
|
5
|
-
assert.equal(resolveNeo4jDataDir({ platform: "darwin", brewPrefix: "/usr/local", dedicated: false, hostname: "maxy-code" }), "/usr/local/var/neo4j");
|
|
6
|
-
assert.equal(resolveNeo4jDataDir({ platform: "darwin", brewPrefix: "/opt/homebrew", dedicated: false, hostname: "maxy-code" }), "/opt/homebrew/var/neo4j");
|
|
4
|
+
test("darwin shared resolves the Homebrew datadir under the brew prefix (Intel + Apple Silicon)", () => {
|
|
5
|
+
assert.equal(resolveNeo4jDataDir({ platform: "darwin", brewPrefix: "/usr/local", dedicated: false, hostname: "maxy-code", persistDir: "/Users/x/.maxy-code" }), "/usr/local/var/neo4j");
|
|
6
|
+
assert.equal(resolveNeo4jDataDir({ platform: "darwin", brewPrefix: "/opt/homebrew", dedicated: false, hostname: "maxy-code", persistDir: "/Users/x/.maxy-code" }), "/opt/homebrew/var/neo4j");
|
|
7
7
|
});
|
|
8
|
-
test("darwin
|
|
9
|
-
assert.equal(resolveNeo4jDataDir({ platform: "darwin", brewPrefix: "/usr/local", dedicated: true, hostname: "realagent-code" }), "/
|
|
8
|
+
test("darwin dedicated resolves a per-brand datadir under the persist tree", () => {
|
|
9
|
+
assert.equal(resolveNeo4jDataDir({ platform: "darwin", brewPrefix: "/usr/local", dedicated: true, hostname: "realagent-code", persistDir: "/Users/x/.realagent-code" }), "/Users/x/.realagent-code/neo4j");
|
|
10
|
+
assert.equal(resolveNeo4jDataDir({ platform: "darwin", brewPrefix: "/opt/homebrew", dedicated: true, hostname: "sitedesk-code", persistDir: "/Users/x/.sitedesk-code" }), "/Users/x/.sitedesk-code/neo4j");
|
|
10
11
|
});
|
|
11
12
|
test("linux shared and dedicated datadirs are unchanged", () => {
|
|
12
|
-
assert.equal(resolveNeo4jDataDir({ platform: "linux", brewPrefix: "", dedicated: false, hostname: "maxy-code" }), "/var/lib/neo4j");
|
|
13
|
-
assert.equal(resolveNeo4jDataDir({ platform: "linux", brewPrefix: "", dedicated: true, hostname: "realagent" }), "/var/lib/neo4j-realagent");
|
|
13
|
+
assert.equal(resolveNeo4jDataDir({ platform: "linux", brewPrefix: "", dedicated: false, hostname: "maxy-code", persistDir: "/root/.maxy-code" }), "/var/lib/neo4j");
|
|
14
|
+
assert.equal(resolveNeo4jDataDir({ platform: "linux", brewPrefix: "", dedicated: true, hostname: "realagent", persistDir: "/root/.realagent" }), "/var/lib/neo4j-realagent");
|
|
14
15
|
});
|
|
@@ -8,8 +8,24 @@
|
|
|
8
8
|
// convention — see peer-brand-detect.test.ts).
|
|
9
9
|
import test from "node:test";
|
|
10
10
|
import assert from "node:assert/strict";
|
|
11
|
-
import { resolveDedicatedNeo4jTeardown, SHARED_NEO4J_PORT } from "../neo4j-teardown.js";
|
|
11
|
+
import { resolveDedicatedNeo4jTeardown, resolveDarwinDedicatedNeo4jTeardown, SHARED_NEO4J_PORT } from "../neo4j-teardown.js";
|
|
12
12
|
const HOST = "sitedesk-code";
|
|
13
|
+
test("darwin dedicated → label + plist + per-brand datadir", () => {
|
|
14
|
+
const plan = resolveDarwinDedicatedNeo4jTeardown({
|
|
15
|
+
brandHostname: "sitedesk-code", neo4jPort: 7689, home: "/Users/x", persistDir: "/Users/x/.sitedesk-code",
|
|
16
|
+
});
|
|
17
|
+
assert.deepEqual(plan, {
|
|
18
|
+
label: "com.rubytech.sitedesk-code-neo4j",
|
|
19
|
+
plistPath: "/Users/x/Library/LaunchAgents/com.rubytech.sitedesk-code-neo4j.plist",
|
|
20
|
+
dataDir: "/Users/x/.sitedesk-code/neo4j",
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
test("darwin teardown guards: shared 7687 / undefined / empty hostname → null", () => {
|
|
24
|
+
const base = { home: "/Users/x", persistDir: "/Users/x/.maxy-code" };
|
|
25
|
+
assert.equal(resolveDarwinDedicatedNeo4jTeardown({ brandHostname: "maxy-code", neo4jPort: 7687, ...base }), null);
|
|
26
|
+
assert.equal(resolveDarwinDedicatedNeo4jTeardown({ brandHostname: "maxy-code", neo4jPort: undefined, ...base }), null);
|
|
27
|
+
assert.equal(resolveDarwinDedicatedNeo4jTeardown({ brandHostname: "", neo4jPort: 7689, ...base }), null);
|
|
28
|
+
});
|
|
13
29
|
test("dedicated port → full teardown plan with install-parity names", () => {
|
|
14
30
|
const plan = resolveDedicatedNeo4jTeardown({ brandHostname: HOST, neo4jPort: 7689 });
|
|
15
31
|
assert.notEqual(plan, null);
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,8 @@ import { requireSupportedPlatform, detectPlatform } from "./platform-detect.js";
|
|
|
16
16
|
import { decideClaudeUpgradePrivilege } from "./claude-upgrade-privilege.js";
|
|
17
17
|
import { resolveNeo4jDataDir } from "./neo4j-datadir.js";
|
|
18
18
|
import { protectCommands, unprotectCommands, lsattrShowsImmutable } from "./install-immutability.js";
|
|
19
|
-
import { renderPlist, buildSessionManagerWrapper, buildHeartbeatWrapper } from "./launchd-plist.js";
|
|
19
|
+
import { renderPlist, buildSessionManagerWrapper, buildHeartbeatWrapper, buildNeo4jWrapper } from "./launchd-plist.js";
|
|
20
|
+
import { resolveDarwinDedicatedNeo4jPaths, resolveDarwinDedicatedNeo4jConfKeys } from "./neo4j-darwin-dedicated.js";
|
|
20
21
|
import { bootstrapLaunchAgent } from "./launchd-bootstrap.js";
|
|
21
22
|
import { enumerateClaudeCandidates, pickCanonicalClaude } from "./claude-bin.js";
|
|
22
23
|
import { installAllBrewPackages } from "./brew-install.js";
|
|
@@ -1262,14 +1263,51 @@ function resetNeo4jAuth(port = DEFAULT_NEO4J_PORT, dataDir = "/var/lib/neo4j", p
|
|
|
1262
1263
|
`${dataDir}/data/databases/system`,
|
|
1263
1264
|
`${dataDir}/data/transactions/system`,
|
|
1264
1265
|
];
|
|
1265
|
-
if (platform === "darwin") {
|
|
1266
|
-
//
|
|
1267
|
-
//
|
|
1268
|
-
//
|
|
1269
|
-
//
|
|
1270
|
-
//
|
|
1271
|
-
//
|
|
1272
|
-
|
|
1266
|
+
if (platform === "darwin" && dedicated) {
|
|
1267
|
+
// Dedicated darwin brand: the per-brand launchd-supervised instance (Task
|
|
1268
|
+
// 1396). No brew services (that is the shared instance) — bootout the
|
|
1269
|
+
// brand's LaunchAgent, clear its auth db (clearPaths are rooted at the
|
|
1270
|
+
// per-brand dataDir), re-seed the password against the per-brand NEO4J_CONF,
|
|
1271
|
+
// and bootstrap the LaunchAgent back. The trailing bolt-port health loop
|
|
1272
|
+
// below already targets `port`.
|
|
1273
|
+
const brewPrefix = resolveBrewPrefix();
|
|
1274
|
+
const persistDir = resolve(process.env.HOME ?? "/", BRAND.configDir);
|
|
1275
|
+
const p = resolveDarwinDedicatedNeo4jPaths({ persistDir, brewPrefix });
|
|
1276
|
+
const label = `${launchdLabel()}-neo4j`;
|
|
1277
|
+
console.log(" Resetting dedicated Neo4j auth (launchd)...");
|
|
1278
|
+
spawnSync("launchctl", ["bootout", `${gui()}/${label}`], { stdio: "pipe" });
|
|
1279
|
+
// launchctl bootout returns once the job leaves the domain, but neo4j does a
|
|
1280
|
+
// graceful multi-second store flush on SIGTERM — so the JVM can still hold
|
|
1281
|
+
// the port (and the store) after bootout returns. Wait for the bolt port to
|
|
1282
|
+
// free before clearing the auth db and re-seeding: set-initial-password only
|
|
1283
|
+
// takes effect against a stopped store, and rm must not race a live flush.
|
|
1284
|
+
// Unlike the Linux sibling's synchronous `systemctl stop`, darwin needs this
|
|
1285
|
+
// explicit wait. Bounded — after 30s, proceed anyway (loud path continues to
|
|
1286
|
+
// the health check below).
|
|
1287
|
+
for (let i = 0; i < 15; i++) {
|
|
1288
|
+
const c = spawnSync("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN"], { stdio: "pipe", timeout: 5000 });
|
|
1289
|
+
if (!(c.status === 0 && (c.stdout?.toString() ?? "").includes("LISTEN")))
|
|
1290
|
+
break;
|
|
1291
|
+
spawnSync("sleep", ["2"]);
|
|
1292
|
+
}
|
|
1293
|
+
spawnSync("rm", ["-rf", ...clearPaths], { stdio: "inherit" });
|
|
1294
|
+
const setPw = spawnSync(p.neo4jAdminBin, ["dbms", "set-initial-password", "--", password], {
|
|
1295
|
+
stdio: "inherit",
|
|
1296
|
+
env: { ...process.env, NEO4J_CONF: p.confDir },
|
|
1297
|
+
});
|
|
1298
|
+
if (setPw.status !== 0) {
|
|
1299
|
+
throw new Error(`neo4j-admin set-initial-password failed (exit ${setPw.status}) during dedicated darwin auth reset`);
|
|
1300
|
+
}
|
|
1301
|
+
const plistPath = join(launchAgentsDir(), `${label}.plist`);
|
|
1302
|
+
const boot = bootstrapLaunchAgent((a) => { const r = spawnSync("launchctl", a, { stdio: "pipe", encoding: "utf-8", timeout: 15_000 }); return { status: r.status, stderr: (r.stderr ?? "").toString() }; }, { gui: gui(), label, plistPath, logger: (l) => { console.log(` ${l}`); logFile(` ${l}`); } });
|
|
1303
|
+
if (!boot.ok) {
|
|
1304
|
+
throw new Error(`launchctl bootstrap ${label} failed (exit ${boot.bootstrapStatus}) after ${boot.attempts} attempt(s) during dedicated darwin auth reset: ${boot.stderr}`);
|
|
1305
|
+
}
|
|
1306
|
+
logFile(` [neo4j-darwin-auth-reset] dedicated datadir=${dataDir} conf=${p.confDir} label=${label}`);
|
|
1307
|
+
}
|
|
1308
|
+
else if (platform === "darwin") {
|
|
1309
|
+
// Shared (default-brand) darwin instance under brew services — user-owned
|
|
1310
|
+
// datadir, no systemctl, no sudo.
|
|
1273
1311
|
console.log(" Resetting Neo4j auth with fresh password (brew services)...");
|
|
1274
1312
|
spawnSync("brew", ["services", "stop", "neo4j"], { stdio: "inherit" });
|
|
1275
1313
|
spawnSync("rm", ["-rf", ...clearPaths], { stdio: "inherit" });
|
|
@@ -1351,6 +1389,7 @@ function ensureNeo4jPassword() {
|
|
|
1351
1389
|
brewPrefix: platform === "darwin" ? resolveBrewPrefix() : "",
|
|
1352
1390
|
dedicated: NEO4J_DEDICATED,
|
|
1353
1391
|
hostname: BRAND.hostname,
|
|
1392
|
+
persistDir,
|
|
1354
1393
|
});
|
|
1355
1394
|
logFile(`[create-maxy] neo4j-datadir=${dataDir} platform=${platform}`);
|
|
1356
1395
|
// 1. Same-brand check: if our own password file exists and works, done (upgrade path).
|
|
@@ -1408,6 +1447,16 @@ function installNeo4j() {
|
|
|
1408
1447
|
// step ends after `brew install neo4j` + initial-password seeding so the
|
|
1409
1448
|
// payload deploy step finds the shared password file.
|
|
1410
1449
|
installAllBrewPackages(["neo4j"], logFile);
|
|
1450
|
+
if (NEO4J_DEDICATED) {
|
|
1451
|
+
// Dedicated brands get their own launchd-supervised instance in
|
|
1452
|
+
// setupDedicatedNeo4j() (darwin branch, next in the pipeline). Do NOT seed
|
|
1453
|
+
// or start the shared brew instance here — that would bind a pointless
|
|
1454
|
+
// 7687 and seed a shared password the dedicated path never uses. The brew
|
|
1455
|
+
// binary install above is all a dedicated brand needs from this step.
|
|
1456
|
+
logFile(" [neo4j-darwin] dedicated brand — brew binary installed; dedicated instance provisioned in setupDedicatedNeo4j()");
|
|
1457
|
+
console.log(" Neo4j installed (Homebrew). Dedicated instance will be provisioned next.");
|
|
1458
|
+
return;
|
|
1459
|
+
}
|
|
1411
1460
|
// Generate strong random password — stored in persistent location (~/{configDir}/)
|
|
1412
1461
|
const password = randomBytes(24).toString("base64url");
|
|
1413
1462
|
const persistDir = resolve(process.env.HOME ?? "/root", BRAND.configDir);
|
|
@@ -1510,6 +1559,124 @@ function peerBrandUsingSystemUnit() {
|
|
|
1510
1559
|
peerEnvContents,
|
|
1511
1560
|
});
|
|
1512
1561
|
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Darwin dedicated Neo4j (Task 1396): a per-brand launchd-supervised instance
|
|
1564
|
+
* sharing the brew neo4j binary, isolated under `~/.<brand>/neo4j/`. Proven
|
|
1565
|
+
* approach — the brew `neo4j` wrapper force-sets NEO4J_HOME, so isolation is
|
|
1566
|
+
* driven entirely by a per-brand NEO4J_CONF whose server.directories.* are all
|
|
1567
|
+
* absolute (including run, which keeps this instance's pidfile off the shared
|
|
1568
|
+
* one). Copies the brew default conf, delete-then-appends the per-brand keys
|
|
1569
|
+
* (verifying exactly one active line each, the same guard as the Linux path),
|
|
1570
|
+
* seeds the password on first install, writes + bootstraps the LaunchAgent, and
|
|
1571
|
+
* health-checks the brand's bolt port. Idempotent: reruns re-apply conf state and
|
|
1572
|
+
* re-bootstrap without rotating an existing password. Never touches the shared
|
|
1573
|
+
* brew instance on 7687.
|
|
1574
|
+
*/
|
|
1575
|
+
function setupDedicatedNeo4jDarwin() {
|
|
1576
|
+
const brewPrefix = resolveBrewPrefix();
|
|
1577
|
+
const persistDir = resolve(process.env.HOME ?? "/", BRAND.configDir);
|
|
1578
|
+
const p = resolveDarwinDedicatedNeo4jPaths({ persistDir, brewPrefix });
|
|
1579
|
+
const label = `${launchdLabel()}-neo4j`;
|
|
1580
|
+
const confPath = `${p.confDir}/neo4j.conf`;
|
|
1581
|
+
const confExists = existsSync(confPath);
|
|
1582
|
+
for (const dir of [p.dataDir, p.logsDir, p.runDir, p.pluginsDir, p.importDir, p.confDir]) {
|
|
1583
|
+
mkdirSync(dir, { recursive: true });
|
|
1584
|
+
}
|
|
1585
|
+
if (!confExists) {
|
|
1586
|
+
console.log(` Setting up dedicated Neo4j for ${BRAND.productName} on bolt://localhost:${NEO4J_PORT}...`);
|
|
1587
|
+
if (!existsSync(p.srcConfDir)) {
|
|
1588
|
+
throw new Error(`Brew Neo4j default conf not found at ${p.srcConfDir}. Is Neo4j installed via Homebrew?`);
|
|
1589
|
+
}
|
|
1590
|
+
// Seed the per-brand conf from the brew default (neo4j.conf + the logs xml).
|
|
1591
|
+
cpSync(p.srcConfDir, p.confDir, { recursive: true });
|
|
1592
|
+
}
|
|
1593
|
+
else {
|
|
1594
|
+
console.log(` Dedicated Neo4j for ${BRAND.productName} already configured at ${p.confDir} — re-applying per-brand state`);
|
|
1595
|
+
}
|
|
1596
|
+
// Delete-then-append each per-brand key. The brew default ships some directory
|
|
1597
|
+
// keys twice (a commented default plus an active /usr/local/var line), so
|
|
1598
|
+
// delete-all-then-append guarantees exactly one active line. BSD sed needs the
|
|
1599
|
+
// empty in-place suffix argument (`-i ''`).
|
|
1600
|
+
const keys = resolveDarwinDedicatedNeo4jConfKeys({
|
|
1601
|
+
port: NEO4J_PORT, dataDir: p.dataDir, logsDir: p.logsDir, runDir: p.runDir, pluginsDir: p.pluginsDir, importDir: p.importDir,
|
|
1602
|
+
});
|
|
1603
|
+
for (const [key, value] of keys) {
|
|
1604
|
+
const keyRe = key.replace(/\./g, "\\.");
|
|
1605
|
+
spawnSync("sed", ["-i", "", `/^#\\{0,1\\}${keyRe}=/d`, confPath], { stdio: "inherit" });
|
|
1606
|
+
appendFileSync(confPath, `${key}=${value}\n`);
|
|
1607
|
+
}
|
|
1608
|
+
// Verify exactly one active line per key — n!=1 aborts BEFORE bootstrap.
|
|
1609
|
+
const activeCounts = [];
|
|
1610
|
+
for (const [key] of keys) {
|
|
1611
|
+
const r = spawnSync("grep", ["-c", `^${key}=`, confPath], { stdio: "pipe" });
|
|
1612
|
+
const n = parseInt((r.stdout?.toString() ?? "0").trim(), 10) || 0;
|
|
1613
|
+
activeCounts.push(`${key}:${n}`);
|
|
1614
|
+
if (n !== 1) {
|
|
1615
|
+
const msg = `[neo4j-conf] FATAL ${key} active_count=${n} in ${confPath}`;
|
|
1616
|
+
console.error(` ${msg}`);
|
|
1617
|
+
logFile(` ${msg}`);
|
|
1618
|
+
throw new Error(msg);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
logFile(` [neo4j-conf] keys_active=${activeCounts.join(",")}`);
|
|
1622
|
+
if (!confExists) {
|
|
1623
|
+
// Set the initial password before first start (first install only — rotating
|
|
1624
|
+
// on a rerun would brick an existing DB whose password is already stored).
|
|
1625
|
+
const password = randomBytes(24).toString("base64url");
|
|
1626
|
+
mkdirSync(persistDir, { recursive: true });
|
|
1627
|
+
writeFileSync(join(persistDir, ".neo4j-password"), password, { mode: 0o600 });
|
|
1628
|
+
const cfgDir = resolve(INSTALL_DIR, "platform/config");
|
|
1629
|
+
mkdirSync(cfgDir, { recursive: true });
|
|
1630
|
+
writeFileSync(join(cfgDir, ".neo4j-password"), password, { mode: 0o600 });
|
|
1631
|
+
const setPw = spawnSync(p.neo4jAdminBin, ["dbms", "set-initial-password", "--", password], {
|
|
1632
|
+
stdio: "inherit",
|
|
1633
|
+
env: { ...process.env, NEO4J_CONF: p.confDir },
|
|
1634
|
+
});
|
|
1635
|
+
if (setPw.status !== 0) {
|
|
1636
|
+
throw new Error(`neo4j-admin set-initial-password failed (exit ${setPw.status}) for dedicated darwin instance`);
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
// Write the wrapper + plist and bootstrap the LaunchAgent (bounded retry on the
|
|
1640
|
+
// transient launchctl EIO, same helper installServiceDarwin uses).
|
|
1641
|
+
const wrapperPath = join(persistDir, "neo4j-wrapper.sh");
|
|
1642
|
+
writeFileSync(wrapperPath, buildNeo4jWrapper({ confDir: p.confDir, brewPrefix }));
|
|
1643
|
+
chmodSync(wrapperPath, 0o755);
|
|
1644
|
+
const plist = renderPlist({
|
|
1645
|
+
label,
|
|
1646
|
+
programArguments: ["/bin/bash", wrapperPath],
|
|
1647
|
+
stdoutPath: `${p.logsDir}/neo4j-console.log`,
|
|
1648
|
+
stderrPath: `${p.logsDir}/neo4j-console.log`,
|
|
1649
|
+
keepAlive: true,
|
|
1650
|
+
runAtLoad: true,
|
|
1651
|
+
workingDirectory: p.home,
|
|
1652
|
+
});
|
|
1653
|
+
mkdirSync(launchAgentsDir(), { recursive: true });
|
|
1654
|
+
const plistPath = join(launchAgentsDir(), `${label}.plist`);
|
|
1655
|
+
writeFileSync(plistPath, plist);
|
|
1656
|
+
logFile(` ${plistPath} written (${plist.length} bytes)`);
|
|
1657
|
+
const boot = bootstrapLaunchAgent((a) => { const r = spawnSync("launchctl", a, { stdio: "pipe", encoding: "utf-8", timeout: 15_000 }); return { status: r.status, stderr: (r.stderr ?? "").toString() }; }, { gui: gui(), label, plistPath, logger: (l) => { console.log(` ${l}`); logFile(` ${l}`); } });
|
|
1658
|
+
if (!boot.ok) {
|
|
1659
|
+
throw new Error(`launchctl bootstrap ${label} failed (exit ${boot.bootstrapStatus}) after ${boot.attempts} attempt(s): ${boot.stderr}`);
|
|
1660
|
+
}
|
|
1661
|
+
// Health-check the brand's bolt port — loud failure, no silent fallback to the
|
|
1662
|
+
// shared instance (matches the Linux dedicated bind check).
|
|
1663
|
+
console.log(` Waiting for dedicated Neo4j on port ${NEO4J_PORT}...`);
|
|
1664
|
+
let up = false;
|
|
1665
|
+
for (let i = 0; i < 20; i++) {
|
|
1666
|
+
const c = spawnSync("lsof", ["-nP", `-iTCP:${NEO4J_PORT}`, "-sTCP:LISTEN"], { stdio: "pipe", timeout: 5000 });
|
|
1667
|
+
if (c.status === 0 && (c.stdout?.toString() ?? "").includes("LISTEN")) {
|
|
1668
|
+
up = true;
|
|
1669
|
+
break;
|
|
1670
|
+
}
|
|
1671
|
+
spawnSync("sleep", ["2"]);
|
|
1672
|
+
}
|
|
1673
|
+
if (!up) {
|
|
1674
|
+
logFile(` Neo4j dedicated (darwin): failed to bind port ${NEO4J_PORT}`);
|
|
1675
|
+
throw new Error(`Dedicated Neo4j ${label} did not bind bolt://localhost:${NEO4J_PORT} within 40s. Check ${p.logsDir}/neo4j-console.log`);
|
|
1676
|
+
}
|
|
1677
|
+
logFile(` Neo4j dedicated (darwin): conf=${p.confDir} data=${p.dataDir} label=${label} bolt=:${NEO4J_PORT}`);
|
|
1678
|
+
console.log(` Dedicated Neo4j ready on bolt://localhost:${NEO4J_PORT}`);
|
|
1679
|
+
}
|
|
1513
1680
|
/**
|
|
1514
1681
|
* Create a dedicated Neo4j instance for this brand when NEO4J_DEDICATED is true.
|
|
1515
1682
|
* Produces: separate config dir, data dir, log dir, systemd service, and password.
|
|
@@ -1526,6 +1693,13 @@ function peerBrandUsingSystemUnit() {
|
|
|
1526
1693
|
function setupDedicatedNeo4j() {
|
|
1527
1694
|
if (!NEO4J_DEDICATED)
|
|
1528
1695
|
return;
|
|
1696
|
+
// darwin has no systemd/apt neo4j — provision a per-brand launchd-supervised
|
|
1697
|
+
// instance instead (Task 1396). Linux falls through to the systemd body below.
|
|
1698
|
+
const platform = requireSupportedPlatform(process.platform);
|
|
1699
|
+
if (platform === "darwin") {
|
|
1700
|
+
setupDedicatedNeo4jDarwin();
|
|
1701
|
+
return;
|
|
1702
|
+
}
|
|
1529
1703
|
const brandSuffix = BRAND.hostname; // e.g., "realagent"
|
|
1530
1704
|
const confDir = `/etc/neo4j-${brandSuffix}`;
|
|
1531
1705
|
const dataDir = `/var/lib/neo4j-${brandSuffix}`;
|
package/dist/launchd-plist.js
CHANGED
|
@@ -75,6 +75,27 @@ export function buildHeartbeatWrapper(o) {
|
|
|
75
75
|
"",
|
|
76
76
|
].join("\n");
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Bash wrapper for the darwin dedicated-Neo4j LaunchAgent (Task 1396). The
|
|
80
|
+
* launchd analogue of the Linux dedicated neo4j systemd unit. The brew `neo4j`
|
|
81
|
+
* wrapper force-sets NEO4J_HOME to the Cellar, so per-brand isolation is driven
|
|
82
|
+
* entirely by NEO4J_CONF — the per-brand conf's absolute server.directories.*
|
|
83
|
+
* (including run) keep the data and pidfile off the shared instance. PATH gets
|
|
84
|
+
* the brew prefix bins so the neo4j launcher's `java` resolves under the bare
|
|
85
|
+
* launchd PATH.
|
|
86
|
+
*/
|
|
87
|
+
export function buildNeo4jWrapper(o) {
|
|
88
|
+
return [
|
|
89
|
+
"#!/bin/bash",
|
|
90
|
+
"# generated by create-maxy setupDedicatedNeo4jDarwin().",
|
|
91
|
+
"# Exports NEO4J_CONF (per-brand conf → isolated data/run) and prepends the",
|
|
92
|
+
"# brew prefix bins so java resolves, then execs the brew-wrapped neo4j.",
|
|
93
|
+
`export NEO4J_CONF="${o.confDir}"`,
|
|
94
|
+
`export PATH="${o.brewPrefix}/bin:${o.brewPrefix}/sbin:$PATH"`,
|
|
95
|
+
`exec ${o.brewPrefix}/bin/neo4j console`,
|
|
96
|
+
"",
|
|
97
|
+
].join("\n");
|
|
98
|
+
}
|
|
78
99
|
export function renderPlist(spec) {
|
|
79
100
|
const lines = [];
|
|
80
101
|
lines.push(`<?xml version="1.0" encoding="UTF-8"?>`);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Pure path + conf-key resolution for the darwin dedicated Neo4j instance
|
|
2
|
+
// (Task 1396). No fs, no spawn — the caller (setupDedicatedNeo4jDarwin in
|
|
3
|
+
// index.ts) wraps these with mkdir/cp/sed/launchctl. Mirrors neo4j-datadir.ts /
|
|
4
|
+
// launchd-plist.ts: inputs in, decision out.
|
|
5
|
+
//
|
|
6
|
+
// The darwin dedicated instance shares the brew neo4j binary but is isolated by
|
|
7
|
+
// a per-brand NEO4J_CONF whose server.directories.* are ALL absolute (including
|
|
8
|
+
// run, so its pidfile never collides with the shared instance — the brew wrapper
|
|
9
|
+
// force-sets NEO4J_HOME, so the Linux NEO4J_HOME trick is unavailable here).
|
|
10
|
+
export function resolveDarwinDedicatedNeo4jPaths(input) {
|
|
11
|
+
const home = `${input.persistDir}/neo4j`;
|
|
12
|
+
return {
|
|
13
|
+
home,
|
|
14
|
+
dataDir: `${home}/data`,
|
|
15
|
+
confDir: `${home}/conf`,
|
|
16
|
+
logsDir: `${home}/logs`,
|
|
17
|
+
runDir: `${home}/run`,
|
|
18
|
+
pluginsDir: `${home}/plugins`,
|
|
19
|
+
importDir: `${home}/import`,
|
|
20
|
+
srcConfDir: `${input.brewPrefix}/opt/neo4j/libexec/conf`,
|
|
21
|
+
neo4jBin: `${input.brewPrefix}/bin/neo4j`,
|
|
22
|
+
neo4jAdminBin: `${input.brewPrefix}/bin/neo4j-admin`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** The conf keys to delete-then-append into the per-brand neo4j.conf. Order is
|
|
26
|
+
* stable for grep-ability. httpPort = port - 213 preserves the 7687/7474 offset
|
|
27
|
+
* (matching the Linux dedicated path). */
|
|
28
|
+
export function resolveDarwinDedicatedNeo4jConfKeys(input) {
|
|
29
|
+
const httpPort = input.port - 213;
|
|
30
|
+
return [
|
|
31
|
+
["server.bolt.listen_address", `:${input.port}`],
|
|
32
|
+
["server.http.listen_address", `:${httpPort}`],
|
|
33
|
+
["server.directories.data", input.dataDir],
|
|
34
|
+
["server.directories.logs", input.logsDir],
|
|
35
|
+
["server.directories.run", input.runDir],
|
|
36
|
+
["server.directories.plugins", input.pluginsDir],
|
|
37
|
+
["server.directories.import", input.importDir],
|
|
38
|
+
];
|
|
39
|
+
}
|
package/dist/neo4j-datadir.js
CHANGED
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
// No spawnSync, no fs — the caller injects the brew prefix (from `brew --prefix`)
|
|
3
3
|
// on darwin. Peer of the other install decision helpers.
|
|
4
4
|
//
|
|
5
|
-
// darwin: Homebrew installs Neo4j's datadir at `<brew prefix>/var/neo4j`
|
|
6
|
-
// (/usr/local on Intel, /opt/homebrew on Apple Silicon), user-owned.
|
|
7
|
-
//
|
|
8
|
-
//
|
|
5
|
+
// darwin shared: Homebrew installs Neo4j's datadir at `<brew prefix>/var/neo4j`
|
|
6
|
+
// (/usr/local on Intel, /opt/homebrew on Apple Silicon), user-owned.
|
|
7
|
+
// darwin dedicated: a per-brand launchd-supervised instance isolated under the
|
|
8
|
+
// brand persist tree at `<persistDir>/neo4j` (Task 1396). The brew `neo4j`
|
|
9
|
+
// wrapper force-sets NEO4J_HOME, so isolation is driven by a per-brand
|
|
10
|
+
// NEO4J_CONF with absolute server.directories.*; this root is the data home
|
|
11
|
+
// that the conf's `server.directories.data=<root>/data` and resetNeo4jAuth's
|
|
12
|
+
// `${root}/data/...` clear paths both derive from.
|
|
9
13
|
// linux: /var/lib/neo4j (shared) or /var/lib/neo4j-<hostname> (dedicated).
|
|
10
14
|
export function resolveNeo4jDataDir(input) {
|
|
11
15
|
if (input.platform === "darwin") {
|
|
12
|
-
return `${input.brewPrefix}/var/neo4j`;
|
|
16
|
+
return input.dedicated ? `${input.persistDir}/neo4j` : `${input.brewPrefix}/var/neo4j`;
|
|
13
17
|
}
|
|
14
18
|
return input.dedicated ? `/var/lib/neo4j-${input.hostname}` : "/var/lib/neo4j";
|
|
15
19
|
}
|
package/dist/neo4j-teardown.js
CHANGED
|
@@ -43,3 +43,18 @@ export function resolveDedicatedNeo4jTeardown(args) {
|
|
|
43
43
|
logDir: `/var/log/neo4j-${brandHostname}`,
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
+
export function resolveDarwinDedicatedNeo4jTeardown(args) {
|
|
47
|
+
const { brandHostname, neo4jPort, home, persistDir } = args;
|
|
48
|
+
if (neo4jPort === undefined)
|
|
49
|
+
return null;
|
|
50
|
+
if (neo4jPort === SHARED_NEO4J_PORT)
|
|
51
|
+
return null;
|
|
52
|
+
if (!brandHostname)
|
|
53
|
+
return null;
|
|
54
|
+
const label = `com.rubytech.${brandHostname}-neo4j`;
|
|
55
|
+
return {
|
|
56
|
+
label,
|
|
57
|
+
plistPath: `${home}/Library/LaunchAgents/${label}.plist`,
|
|
58
|
+
dataDir: `${persistDir}/neo4j`,
|
|
59
|
+
};
|
|
60
|
+
}
|
package/dist/uninstall.js
CHANGED
|
@@ -5,7 +5,7 @@ import { homedir } from "node:os";
|
|
|
5
5
|
import { createInterface } from "node:readline";
|
|
6
6
|
import { removeBrandStanza, hasAnyBrandStanza } from "./samba-provision.js";
|
|
7
7
|
import { stripCronBlock } from "./cron-registration.js";
|
|
8
|
-
import { resolveDedicatedNeo4jTeardown } from "./neo4j-teardown.js";
|
|
8
|
+
import { resolveDedicatedNeo4jTeardown, resolveDarwinDedicatedNeo4jTeardown, SHARED_NEO4J_PORT } from "./neo4j-teardown.js";
|
|
9
9
|
import { KNOWN_BRAND_HOSTNAMES } from "./known-brands.js";
|
|
10
10
|
const HOME = homedir();
|
|
11
11
|
const PAYLOAD_DIR = resolve(import.meta.dirname, "../payload");
|
|
@@ -80,13 +80,18 @@ function launchdLabel() {
|
|
|
80
80
|
}
|
|
81
81
|
/** Every LaunchAgent label installServiceDarwin() creates for this brand: the
|
|
82
82
|
* main server, the claude-session-manager (Task 1395), and the scheduling
|
|
83
|
-
* heartbeat (Task 1403).
|
|
83
|
+
* heartbeat (Task 1403). A non-default (dedicated) brand also runs the
|
|
84
|
+
* per-brand Neo4j LaunchAgent (Task 1396). Uninstall boots out and removes all. */
|
|
84
85
|
function darwinLaunchdLabels() {
|
|
85
|
-
|
|
86
|
+
const labels = [
|
|
86
87
|
launchdLabel(),
|
|
87
88
|
`${launchdLabel()}-claude-session-manager`,
|
|
88
89
|
`${launchdLabel()}-heartbeat`,
|
|
89
90
|
];
|
|
91
|
+
if ((BRAND.neo4jPort ?? SHARED_NEO4J_PORT) !== SHARED_NEO4J_PORT) {
|
|
92
|
+
labels.push(`${launchdLabel()}-neo4j`);
|
|
93
|
+
}
|
|
94
|
+
return labels;
|
|
90
95
|
}
|
|
91
96
|
function plistPathFor(label) {
|
|
92
97
|
return resolve(HOME, "Library/LaunchAgents", `${label}.plist`);
|
|
@@ -483,12 +488,33 @@ function removeAppDirs() {
|
|
|
483
488
|
// ---------------------------------------------------------------------------
|
|
484
489
|
function removeNeo4jData() {
|
|
485
490
|
log("5", "Removing Neo4j data...");
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
//
|
|
489
|
-
//
|
|
491
|
+
// darwin: a dedicated brand's Neo4j is a per-brand launchd instance under
|
|
492
|
+
// ~/.<brand>/neo4j (Task 1396). Its LaunchAgent was already booted out in
|
|
493
|
+
// stopServices() via darwinLaunchdLabels(); here we remove the plist and the
|
|
494
|
+
// per-brand home. Never touch the shared brew instance under
|
|
495
|
+
// <brewPrefix>/var/neo4j — the teardown resolver returns null for a shared
|
|
496
|
+
// (7687), unreadable, or hostname-less brand.
|
|
497
|
+
if (isDarwin()) {
|
|
498
|
+
const plan = resolveDarwinDedicatedNeo4jTeardown({
|
|
499
|
+
brandHostname: BRAND.hostname,
|
|
500
|
+
neo4jPort: readNeo4jPortFromEnv() ?? BRAND.neo4jPort,
|
|
501
|
+
home: HOME,
|
|
502
|
+
persistDir: resolve(HOME, BRAND.configDir),
|
|
503
|
+
});
|
|
504
|
+
if (plan) {
|
|
505
|
+
rmSync(plan.plistPath, { force: true });
|
|
506
|
+
rmSync(plan.dataDir, { recursive: true, force: true });
|
|
507
|
+
console.log(` Removed dedicated Neo4j (${plan.label}) + datadir`);
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
console.log(" Neo4j: shared instance — left in place.");
|
|
511
|
+
}
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
// Linux teardown below is systemd-shaped (`sudo systemctl daemon-reload`,
|
|
515
|
+
// `sudo rm -rf /var/lib/neo4j*`).
|
|
490
516
|
if (!isLinux()) {
|
|
491
|
-
console.log("
|
|
517
|
+
console.log(" Unsupported platform — skipping.");
|
|
492
518
|
return;
|
|
493
519
|
}
|
|
494
520
|
// Brand isolation: remove only THIS brand's Neo4j data. Shared
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-architecture
|
|
3
3
|
description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
|
|
4
|
-
content-hash: sha256:
|
|
4
|
+
content-hash: sha256:69d2ec47598e75fac6f763994a077fd39ccda77767ddb90404dac2d556f5791c
|
|
5
5
|
brand: maxy-code
|
|
6
6
|
product-name: Maxy
|
|
7
7
|
---
|
|
@@ -605,7 +605,7 @@ To run, for example, `realagent-code` alongside the default install, repeat step
|
|
|
605
605
|
npx -y @rubytech/create-realagent-code@latest
|
|
606
606
|
```
|
|
607
607
|
|
|
608
|
-
The persist directory becomes `$HOME/.realagent-code`, the LaunchAgent becomes `com.rubytech.realagent-code`, and the admin URL switches to `http://realagent-code.local:<port>`. Every brand has its own isolated tree — there is no shared state, and `CLAUDE_CONFIG_DIR` is always `$HOME/.<brand>/.claude` for that brand, never the default `~/.claude`.
|
|
608
|
+
The persist directory becomes `$HOME/.realagent-code`, the LaunchAgent becomes `com.rubytech.realagent-code`, and the admin URL switches to `http://realagent-code.local:<port>`. Because a non-default brand runs its own Neo4j on a dedicated bolt port (`realagent-code` → 7688, `sitedesk-code` → 7689; the default `maxy-code` keeps 7687), the installer provisions a second, isolated Neo4j supervised by its own LaunchAgent `com.rubytech.realagent-code-neo4j`, with data under `$HOME/.realagent-code/neo4j/`. That instance shares the Homebrew `neo4j` binary but reads a per-brand config, so the default brand's shared Neo4j on 7687 is left untouched. Every brand has its own isolated tree — there is no shared state, and `CLAUDE_CONFIG_DIR` is always `$HOME/.<brand>/.claude` for that brand, never the default `~/.claude`.
|
|
609
609
|
|
|
610
610
|
## 3. Confirm the LaunchAgent is up
|
|
611
611
|
|
|
@@ -110,7 +110,7 @@ When the operator's intent matches a row but the scaffold does not yet exist, ru
|
|
|
110
110
|
|
|
111
111
|
## Research routing
|
|
112
112
|
|
|
113
|
-
Every structured-research task — market sizing (TAM/SAM/SOM + CAGR), compliance research (
|
|
113
|
+
Every structured-research task — market sizing (TAM/SAM/SOM + CAGR), compliance research (the vertical's consumer-protection regime, ICO ADM, EU AI Act), competitor scans, comparable rounds and exit comparables, named-acquirer enumeration — routes through the `research-assistant` specialist with the five `deep-research` skills (`deep-research`, `book-mirror`, `strategic-reading`, `academic-verify`, `data-research`). Dispatch the specialist; do not call `WebSearch` or `WebFetch` directly from a venture-studio skill. The specialist returns structured findings with citations the data-room artefacts can quote verbatim.
|
|
114
114
|
|
|
115
115
|
## Tone
|
|
116
116
|
|