@rubytech/create-maxy-code 0.1.567 → 0.1.568

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/__tests__/brand-agent-root.test.js +91 -0
  2. package/dist/brand-agent-root.js +58 -0
  3. package/dist/index.js +25 -28
  4. package/package.json +1 -1
  5. package/payload/platform/plugins/admin/mcp/dist/index.js +7 -1
  6. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  7. package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.d.ts +10 -1
  8. package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.d.ts.map +1 -1
  9. package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.js +6 -1
  10. package/payload/platform/plugins/admin/mcp/dist/lib/roster-census.js.map +1 -1
  11. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts +9 -0
  12. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.d.ts.map +1 -1
  13. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js +1 -1
  14. package/payload/platform/plugins/admin/mcp/dist/tools/capabilities-here.js.map +1 -1
  15. package/payload/platform/plugins/admin/skills/capabilities-here/SKILL.md +1 -1
  16. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +44 -1
  17. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +7 -0
  18. package/payload/platform/plugins/docs/references/channel-wake-and-prompt.md +43 -0
  19. package/payload/platform/scripts/lib/provision-account-dir.sh +0 -2
  20. package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts +19 -0
  21. package/payload/platform/services/claude-session-manager/dist/account-agent-registry.d.ts.map +1 -0
  22. package/payload/platform/services/claude-session-manager/dist/account-agent-registry.js +146 -0
  23. package/payload/platform/services/claude-session-manager/dist/account-agent-registry.js.map +1 -0
  24. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +5 -0
  25. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
  26. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +5 -5
  27. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
  28. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +11 -1
  29. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  30. package/payload/platform/services/claude-session-manager/dist/http-server.js +58 -12
  31. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  32. package/payload/platform/services/claude-session-manager/dist/index.js +25 -13
  33. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  34. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts +6 -1
  35. package/payload/platform/services/claude-session-manager/dist/pty-census.d.ts.map +1 -1
  36. package/payload/platform/services/claude-session-manager/dist/pty-census.js +6 -3
  37. package/payload/platform/services/claude-session-manager/dist/pty-census.js.map +1 -1
  38. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +21 -8
  39. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  40. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +38 -15
  41. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  42. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +2 -0
  43. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  44. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +4 -1
  45. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  46. package/payload/platform/services/claude-session-manager/dist/reaper.d.ts +3 -0
  47. package/payload/platform/services/claude-session-manager/dist/reaper.d.ts.map +1 -1
  48. package/payload/platform/services/claude-session-manager/dist/reaper.js +2 -1
  49. package/payload/platform/services/claude-session-manager/dist/reaper.js.map +1 -1
  50. package/payload/platform/services/claude-session-manager/dist/session-cap-audit.d.ts +2 -0
  51. package/payload/platform/services/claude-session-manager/dist/session-cap-audit.d.ts.map +1 -1
  52. package/payload/platform/services/claude-session-manager/dist/session-cap-audit.js +5 -2
  53. package/payload/platform/services/claude-session-manager/dist/session-cap-audit.js.map +1 -1
  54. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts +2 -0
  55. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.d.ts.map +1 -1
  56. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js +5 -3
  57. package/payload/platform/services/claude-session-manager/dist/slice-memory-policy.js.map +1 -1
  58. package/payload/platform/services/claude-session-manager/dist/systemd-scope.d.ts +26 -16
  59. package/payload/platform/services/claude-session-manager/dist/systemd-scope.d.ts.map +1 -1
  60. package/payload/platform/services/claude-session-manager/dist/systemd-scope.js +84 -31
  61. package/payload/platform/services/claude-session-manager/dist/systemd-scope.js.map +1 -1
  62. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts +7 -0
  63. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.d.ts.map +1 -1
  64. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js +6 -0
  65. package/payload/platform/services/claude-session-manager/dist/wa-channel-mcp.js.map +1 -1
  66. package/payload/platform/services/telegram-channel/dist/notification.d.ts +10 -2
  67. package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
  68. package/payload/platform/services/telegram-channel/dist/notification.js +15 -3
  69. package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
  70. package/payload/platform/services/telegram-channel/dist/server.d.ts.map +1 -1
  71. package/payload/platform/services/telegram-channel/dist/server.js +35 -3
  72. package/payload/platform/services/telegram-channel/dist/server.js.map +1 -1
  73. package/payload/platform/services/telegram-channel/dist/turn-follow.d.ts +10 -0
  74. package/payload/platform/services/telegram-channel/dist/turn-follow.d.ts.map +1 -1
  75. package/payload/platform/services/telegram-channel/dist/turn-follow.js +38 -1
  76. package/payload/platform/services/telegram-channel/dist/turn-follow.js.map +1 -1
  77. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  78. package/payload/platform/services/webchat-channel/dist/server.js +31 -2
  79. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  80. package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts +10 -0
  81. package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts.map +1 -1
  82. package/payload/platform/services/webchat-channel/dist/turn-follow.js +38 -1
  83. package/payload/platform/services/webchat-channel/dist/turn-follow.js.map +1 -1
  84. package/payload/platform/services/whatsapp-channel/dist/instructions.d.ts +9 -0
  85. package/payload/platform/services/whatsapp-channel/dist/instructions.d.ts.map +1 -0
  86. package/payload/platform/services/whatsapp-channel/dist/instructions.js +22 -0
  87. package/payload/platform/services/whatsapp-channel/dist/instructions.js.map +1 -0
  88. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +3 -1
  89. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  90. package/payload/platform/services/whatsapp-channel/dist/notification.js +10 -2
  91. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  92. package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
  93. package/payload/platform/services/whatsapp-channel/dist/server.js +26 -2
  94. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
  95. package/payload/server/server.js +254 -96
@@ -0,0 +1,91 @@
1
+ // Task 2460 — the brand root is no longer a registration surface. It was
2
+ // written once at install and never pruned, so a retired template stayed
3
+ // registered forever: clare-craig carries `archive-ingest-operator.md` as a
4
+ // dangling symlink into a template that no longer exists, and Task 2416 had to
5
+ // strip its roster line by hand on five installs while the link survived.
6
+ // Ceasing to write it is not enough, because every existing install already
7
+ // carries the links.
8
+ import test from "node:test";
9
+ import assert from "node:assert/strict";
10
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, symlinkSync, readdirSync, existsSync } from "node:fs";
11
+ import { tmpdir } from "node:os";
12
+ import { join } from "node:path";
13
+ import { clearBrandAgentRoot } from "../brand-agent-root.js";
14
+ /** A temp brand root with an empty `agents/` under it, plus a collector for the
15
+ * one line the function emits. */
16
+ function makeRoot() {
17
+ const root = mkdtempSync(join(tmpdir(), "t2460-brand-root-"));
18
+ const agentsDir = join(root, "agents");
19
+ mkdirSync(agentsDir, { recursive: true });
20
+ const lines = [];
21
+ return { root, agentsDir, lines, log: (l) => lines.push(l) };
22
+ }
23
+ test("removes every markdown symlink and counts them", () => {
24
+ const { root, agentsDir, lines, log } = makeRoot();
25
+ try {
26
+ const target = join(root, "database-operator.md");
27
+ writeFileSync(target, "---\n");
28
+ symlinkSync(target, join(agentsDir, "database-operator.md"));
29
+ // The dangling case, which is what clare-craig actually carries.
30
+ symlinkSync(join(root, "gone.md"), join(agentsDir, "archive-ingest-operator.md"));
31
+ const result = clearBrandAgentRoot(agentsDir, log);
32
+ assert.deepEqual(result, { removed: 2, kept: [] });
33
+ assert.deepEqual(readdirSync(agentsDir), []);
34
+ // The link goes, never the template it pointed at.
35
+ assert.ok(existsSync(target));
36
+ assert.deepEqual(lines, [" [brand-agent-root] op=brand-agent-root-cleared removed=2 kept="]);
37
+ }
38
+ finally {
39
+ rmSync(root, { recursive: true, force: true });
40
+ }
41
+ });
42
+ test("keeps a regular file and names it", () => {
43
+ const { root, agentsDir, lines, log } = makeRoot();
44
+ try {
45
+ writeFileSync(join(agentsDir, "hand-written.md"), "---\n");
46
+ const result = clearBrandAgentRoot(agentsDir, log);
47
+ assert.deepEqual(result, { removed: 0, kept: ["hand-written.md"] });
48
+ assert.ok(existsSync(join(agentsDir, "hand-written.md")));
49
+ assert.deepEqual(lines, [" [brand-agent-root] op=brand-agent-root-cleared removed=0 kept=hand-written.md"]);
50
+ }
51
+ finally {
52
+ rmSync(root, { recursive: true, force: true });
53
+ }
54
+ });
55
+ test("leaves non-markdown entries alone", () => {
56
+ const { root, agentsDir, log } = makeRoot();
57
+ try {
58
+ writeFileSync(join(agentsDir, "notes.txt"), "scratch");
59
+ assert.deepEqual(clearBrandAgentRoot(agentsDir, log), { removed: 0, kept: [] });
60
+ assert.ok(existsSync(join(agentsDir, "notes.txt")));
61
+ }
62
+ finally {
63
+ rmSync(root, { recursive: true, force: true });
64
+ }
65
+ });
66
+ test("reports removed=0 on a directory that does not exist", () => {
67
+ const { root, agentsDir, lines, log } = makeRoot();
68
+ try {
69
+ rmSync(agentsDir, { recursive: true, force: true });
70
+ assert.deepEqual(clearBrandAgentRoot(agentsDir, log), { removed: 0, kept: [] });
71
+ assert.deepEqual(lines, [" [brand-agent-root] op=brand-agent-root-cleared removed=0 kept="]);
72
+ }
73
+ finally {
74
+ rmSync(root, { recursive: true, force: true });
75
+ }
76
+ });
77
+ test("is idempotent: a second run reports removed=0", () => {
78
+ const { root, agentsDir, lines, log } = makeRoot();
79
+ try {
80
+ const target = join(root, "database-operator.md");
81
+ writeFileSync(target, "---\n");
82
+ symlinkSync(target, join(agentsDir, "database-operator.md"));
83
+ clearBrandAgentRoot(agentsDir, log);
84
+ lines.length = 0;
85
+ assert.deepEqual(clearBrandAgentRoot(agentsDir, log), { removed: 0, kept: [] });
86
+ assert.deepEqual(lines, [" [brand-agent-root] op=brand-agent-root-cleared removed=0 kept="]);
87
+ }
88
+ finally {
89
+ rmSync(root, { recursive: true, force: true });
90
+ }
91
+ });
@@ -0,0 +1,58 @@
1
+ // Task 2460 — the brand-wide agent root is retired.
2
+ //
3
+ // `$CLAUDE_CONFIG_DIR/agents/` was written once, by the installer, from
4
+ // `platform/templates/specialists/agents/`, and never pruned. Three things
5
+ // followed. A retired template stayed registered forever: on clare-craig,
6
+ // `archive-ingest-operator.md` is a dangling symlink into a template that no
7
+ // longer exists, and Task 2416 had to strip its roster line by hand on five
8
+ // installs while the link survived. A specialist disabled on one account stayed
9
+ // resolvable by name in that account and in every other account on the install,
10
+ // because disabling touches only `<accountDir>/specialists/agents/`. And an
11
+ // authored specialist could never be registered here at all without becoming
12
+ // dispatchable inside every other account on the box.
13
+ //
14
+ // The replacement is one registry per account, mirrored at spawn by
15
+ // `syncAccountAgentRegistry`. Dispatch is unaffected by emptying this root:
16
+ // provisioning copies every template specialist into each account's
17
+ // `specialists/agents/`, which that registry mirrors, and cwd at every spawn is
18
+ // the account whose source is mirrored.
19
+ //
20
+ // This function removes what the old surface left behind. Removal rather than
21
+ // merely ceasing to write, because every existing install already carries the
22
+ // links.
23
+ import { existsSync, lstatSync, readdirSync, unlinkSync } from "node:fs";
24
+ import { join } from "node:path";
25
+ /** Remove every `*.md` symlink under `agentsDir`. A regular file is the
26
+ * operator's own and is kept and named, never deleted. Returns the counts and
27
+ * logs `op=brand-agent-root-cleared removed=<N> kept=<names>` once, which is
28
+ * the per-box record the fleet remediation is tracked against. */
29
+ export function clearBrandAgentRoot(agentsDir, log = () => { }) {
30
+ let removed = 0;
31
+ const kept = [];
32
+ // A missing directory is an install that never had the old surface. Nothing
33
+ // to clear is a real result, not an error, so it still logs its zero.
34
+ if (existsSync(agentsDir)) {
35
+ for (const entry of readdirSync(agentsDir).sort()) {
36
+ if (!entry.endsWith(".md"))
37
+ continue;
38
+ const path = join(agentsDir, entry);
39
+ let stat;
40
+ try {
41
+ // lstat, not stat: the links this clears are frequently dangling, which
42
+ // is the whole of symptom 2, and stat would throw on exactly those.
43
+ stat = lstatSync(path);
44
+ }
45
+ catch {
46
+ continue;
47
+ }
48
+ if (!stat.isSymbolicLink()) {
49
+ kept.push(entry);
50
+ continue;
51
+ }
52
+ unlinkSync(path);
53
+ removed++;
54
+ }
55
+ }
56
+ log(` [brand-agent-root] op=brand-agent-root-cleared removed=${removed} kept=${kept.join(",")}`);
57
+ return { removed, kept };
58
+ }
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { execFileSync, spawn, spawnSync } from "node:child_process";
3
3
  import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync, accessSync, constants as fsConstants } from "node:fs";
4
- import { registerSpecialistAgentsAt, SpecialistSymlinkCollision } from "./specialist-registration.js";
4
+ import { clearBrandAgentRoot } from "./brand-agent-root.js";
5
5
  import { seedBypassPermissionsSettings, assertBypassPermissionsSeed } from "./permissions-seed.js";
6
6
  import { resolve, join, dirname } from "node:path";
7
7
  import { randomBytes } from "node:crypto";
@@ -3419,14 +3419,13 @@ function setupAccount() {
3419
3419
  env: { ...neo4jEnv, PLATFORM_ROOT: join(INSTALL_DIR, "platform") },
3420
3420
  });
3421
3421
  }
3422
- // Task 165register every bundled specialist subagent at
3423
- // $CLAUDE_CONFIG_DIR/agents/<name>.md. Claude Code's `--agent <name>`
3424
- // discovery only resolves under this path; without these symlinks,
3425
- // every `--agent database-operator` etc. silently runs as the admin
3426
- // agent on admin IDENTITY/SOUL scaffolding. Symlinks (not copies) so
3427
- // a `npx -y @rubytech/create-maxy-code` upgrade picks up template
3428
- // changes without a second seed run.
3429
- registerSpecialistAgents();
3422
+ // Task 2460clear the brand-wide agent root this step used to write.
3423
+ // Every bundled specialist now reaches a session through the per-account
3424
+ // registry that `syncAccountAgentRegistry` mirrors at spawn from
3425
+ // `<accountDir>/specialists/agents/`, which provisioning fills from the same
3426
+ // templates. Runs on every install, so an upgrade removes the links an
3427
+ // earlier install left behind.
3428
+ clearBrandAgentRegistrations();
3430
3429
  // install-time defaults. Stamp `account.json` with the
3431
3430
  // brand's default plugin set + default outputStyle / thinkingView, and
3432
3431
  // write a minimal admin SOUL.md. The agent boots into a working state
@@ -3595,25 +3594,23 @@ function writeEntitlementFromFlag(payload) {
3595
3594
  console.log(line);
3596
3595
  logFile(line);
3597
3596
  }
3598
- // Task 394premium-bundle agents register through the native Claude Code
3599
- // subagent registry via `.claude-plugin/plugin.json` manifests emitted by
3600
- // scripts/generate-plugin-manifests.mjs at bundle time, not through a
3601
- // parallel symlink channel. This function still wires the bundled platform
3602
- // specialists (database-operator, project-manager, …) under
3603
- // platform/templates/specialists/agents/, which are not part of a
3604
- // registered plugin and rely on $CLAUDE_CONFIG_DIR/agents/ resolution.
3605
- function registerSpecialistAgents() {
3606
- try {
3607
- registerSpecialistAgentsAt(join(INSTALL_DIR, "platform/templates/specialists/agents"), join(CLAUDE_CONFIG_DIR, "agents"), (line) => { console.log(line); logFile(line); });
3608
- }
3609
- catch (err) {
3610
- if (err instanceof SpecialistSymlinkCollision) {
3611
- console.error(`Setup failed: ${err.message}`);
3612
- console.error(` Remove the file and re-run.`);
3613
- process.exit(1);
3614
- }
3615
- throw err;
3616
- }
3597
+ // Task 2460the brand root is no longer a registration surface. It was
3598
+ // written once and never pruned, which left retired templates registered
3599
+ // forever and left a specialist disabled on one account dispatchable in every
3600
+ // other account on the install. Bundled platform specialists reach a session
3601
+ // through the per-account registry instead; this step removes the links the old
3602
+ // surface left behind, which is what closes those two symptoms on an existing
3603
+ // install rather than only on a fresh one.
3604
+ //
3605
+ // Task 394 — premium-bundle agents were never registered here. They resolve
3606
+ // through the native Claude Code subagent registry via `.claude-plugin/plugin.json`
3607
+ // manifests emitted by scripts/generate-plugin-manifests.mjs at bundle time, so
3608
+ // clearing this directory does not touch them.
3609
+ function clearBrandAgentRegistrations() {
3610
+ clearBrandAgentRoot(join(CLAUDE_CONFIG_DIR, "agents"), (line) => {
3611
+ console.log(line);
3612
+ logFile(line);
3613
+ });
3617
3614
  }
3618
3615
  // ---------------------------------------------------------------------------
3619
3616
  // Account discovery (shared by installService + the post-install summary)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.567",
3
+ "version": "0.1.568",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -203,6 +203,9 @@ if (ACCOUNT_ID) {
203
203
  const roster = runRosterCensus({
204
204
  agentsMdPath: resolve(accountDir, "agents", "admin", "AGENTS.md"),
205
205
  specialistsAgentsDir: resolve(accountDir, "specialists", "agents"),
206
+ // Task 2460 — the one directory the CLI resolves a subagent name from,
207
+ // written at every spawn by syncAccountAgentRegistry.
208
+ registryDir: resolve(accountDir, ".claude", "agents"),
206
209
  durableDirs: [resolve(PLATFORM_ROOT, "templates", "specialists", "agents")],
207
210
  durablePluginRoots: [
208
211
  resolve(accountDir, "plugins"),
@@ -727,7 +730,7 @@ eagerTool(server, "account-manage", "Read the account configuration (tier, domai
727
730
  };
728
731
  }
729
732
  });
730
- eagerTool(server, "capabilities-here", "Returns the live install set on the current account as a single JSON object: enabledPlugins (account config), tier, adminModel, publicModel, installedPlatformSpecialists (disk), installedPremiumSpecialists (disk, gated by brand.shipsPremiumBundles), registeredAgentTypes (Claude Code agent registry under $CLAUDE_CONFIG_DIR/agents/), claudeAiConnectors (the claude.ai account connectors loaded for this client, each with an auth state of connected, needs-auth, or unreachable), and the brand block. Call this whenever you are about to make a claim about what this account can do, what is enabled, or what specialists are dispatchable. A connector listed here exists and is usable: do not deny a connector-backed request (Zoom, Dropbox, Microsoft 365, Cloudflare, Google) just because there is no skill or plugin for it — reach the connector tool, and authenticate it if its state is needs-auth. Do not infer install state from the platform-architecture skill — that skill is the catalogue of what the platform can ship, not what is enabled here.", {}, async () => {
733
+ eagerTool(server, "capabilities-here", "Returns the live install set on the current account as a single JSON object: enabledPlugins (account config), tier, adminModel, publicModel, installedPlatformSpecialists (disk), installedPremiumSpecialists (disk, gated by brand.shipsPremiumBundles), registeredAgentTypes (this account's Claude Code agent registry, <accountDir>/.claude/agents/), claudeAiConnectors (the claude.ai account connectors loaded for this client, each with an auth state of connected, needs-auth, or unreachable), and the brand block. Call this whenever you are about to make a claim about what this account can do, what is enabled, or what specialists are dispatchable. A connector listed here exists and is usable: do not deny a connector-backed request (Zoom, Dropbox, Microsoft 365, Cloudflare, Google) just because there is no skill or plugin for it — reach the connector tool, and authenticate it if its state is needs-auth. Do not infer install state from the platform-architecture skill — that skill is the catalogue of what the platform can ship, not what is enabled here.", {}, async () => {
731
734
  if (!ACCOUNT_ID)
732
735
  return refuseNoAccount("capabilities-here");
733
736
  const requestId = randomUUID();
@@ -745,6 +748,9 @@ eagerTool(server, "capabilities-here", "Returns the live install set on the curr
745
748
  platformRoot: PLATFORM_ROOT,
746
749
  premiumPluginsRoot,
747
750
  claudeConfigDir,
751
+ // Task 2460 — the account's own agent registry. The brand-wide root
752
+ // this used to read is retired and cleared on upgrade.
753
+ agentRegistryDir: resolve(getAccountDir(), ".claude", "agents"),
748
754
  // Task 1160 — enumerate the brand client's claude.ai connectors via
749
755
  // `claude mcp list`. Never rejects: resolves with whatever output the CLI
750
756
  // produced (empty on a missing binary, non-zero exit, or the 12s timeout