@rubytech/create-realagent 1.0.838 → 1.0.840

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 (80) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/graph-write/dist/index.js +1 -1
  3. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  4. package/payload/platform/lib/graph-write/src/index.ts +1 -1
  5. package/payload/platform/plugins/admin/PLUGIN.md +2 -0
  6. package/payload/platform/plugins/admin/mcp/dist/index.js +1 -1
  7. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  8. package/payload/platform/plugins/admin/skills/business-profile/SKILL.md +5 -5
  9. package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +11 -11
  10. package/payload/platform/plugins/admin/skills/unzip-attachment/SKILL.md +2 -0
  11. package/payload/platform/plugins/contacts/mcp/dist/index.js +1 -1
  12. package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
  13. package/payload/platform/plugins/docs/references/internals.md +1 -1
  14. package/payload/platform/plugins/docs/references/platform.md +1 -1
  15. package/payload/platform/plugins/docs/references/troubleshooting.md +20 -0
  16. package/payload/platform/plugins/memory/PLUGIN.md +3 -3
  17. package/payload/platform/plugins/memory/mcp/dist/index.js +14 -14
  18. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  19. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts +12 -11
  20. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.d.ts.map +1 -1
  21. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js +22 -10
  22. package/payload/platform/plugins/memory/mcp/dist/lib/graph-write-gate.js.map +1 -1
  23. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js +7 -7
  24. package/payload/platform/plugins/memory/mcp/dist/lib/uuid.js.map +1 -1
  25. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +1 -1
  26. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  27. package/payload/platform/plugins/memory/references/schema-base.md +17 -17
  28. package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +14 -14
  29. package/payload/platform/plugins/tasks/PLUGIN.md +2 -2
  30. package/payload/platform/plugins/tasks/mcp/dist/index.js +11 -11
  31. package/payload/platform/plugins/tasks/mcp/dist/index.js.map +1 -1
  32. package/payload/platform/plugins/tasks/mcp/dist/tools/task-update.js +1 -1
  33. package/payload/platform/plugins/tasks/mcp/dist/tools/task-update.js.map +1 -1
  34. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
  35. package/payload/platform/scripts/seed-neo4j.sh +13 -3
  36. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -0
  37. package/payload/platform/templates/specialists/agents/database-operator.md +1 -1
  38. package/payload/server/adminuser-self-heal-QAWOZ3JV.js +45 -0
  39. package/payload/server/chunk-7PLAT6UR.js +2103 -0
  40. package/payload/server/chunk-CJWFM3WX.js +2098 -0
  41. package/payload/server/chunk-D5U4XQ66.js +656 -0
  42. package/payload/server/chunk-DJXPAH7T.js +1480 -0
  43. package/payload/server/chunk-M6J4JM3D.js +656 -0
  44. package/payload/server/chunk-PZZ3IKUU.js +1116 -0
  45. package/payload/server/chunk-T2MQIKBT.js +10001 -0
  46. package/payload/server/chunk-TSOYVJC4.js +10003 -0
  47. package/payload/server/client-pool-M25CGILI.js +32 -0
  48. package/payload/server/client-pool-OX75YUFD.js +33 -0
  49. package/payload/server/cloudflare-task-tracker-GQFKLY62.js +20 -0
  50. package/payload/server/cloudflare-task-tracker-OQTQWFWK.js +20 -0
  51. package/payload/server/maxy-edge.js +4 -4
  52. package/payload/server/neo4j-migrations-4PG2KB4W.js +665 -0
  53. package/payload/server/public/assets/{Checkbox-Bq6ORjz2.js → Checkbox-aCc0UGp3.js} +1 -1
  54. package/payload/server/public/assets/{admin-CstEkw-G.js → admin-D678VwpH.js} +2 -2
  55. package/payload/server/public/assets/data-DsItQm8c.js +1 -0
  56. package/payload/server/public/assets/graph-C-HOmfmU.js +1 -0
  57. package/payload/server/public/assets/{jsx-runtime-DidQeNoZ.css → jsx-runtime-BKoartnM.css} +1 -1
  58. package/payload/server/public/assets/{page-CFWoVkgV.js → page-D7LchjvY.js} +1 -1
  59. package/payload/server/public/assets/{page-Bpi_jPw6.js → page-DTmTvkNo.js} +1 -1
  60. package/payload/server/public/assets/{public-BWMwq5Jj.js → public-C7mCgRX0.js} +1 -1
  61. package/payload/server/public/assets/{useAdminFetch-B93ig7ef.js → useAdminFetch-BgDL3JGd.js} +1 -1
  62. package/payload/server/public/assets/{useVoiceRecorder-Cb0nAtOo.js → useVoiceRecorder-Bx903Mk1.js} +1 -1
  63. package/payload/server/public/data.html +5 -5
  64. package/payload/server/public/graph.html +6 -6
  65. package/payload/server/public/index.html +8 -8
  66. package/payload/server/public/public.html +5 -5
  67. package/payload/server/server.js +39 -28
  68. package/payload/platform/neo4j/migrations/001-backfill-scope.cypher +0 -30
  69. package/payload/platform/neo4j/migrations/002-project-public-agents.ts +0 -191
  70. package/payload/platform/neo4j/migrations/003-person-name-eradicate.cypher +0 -24
  71. package/payload/platform/neo4j/migrations/004-project-admin-agent.ts +0 -348
  72. package/payload/platform/neo4j/migrations/004-prune-alien-accounts.ts +0 -133
  73. package/payload/platform/neo4j/migrations/005-removed-review-feature.ts +0 -102
  74. package/payload/platform/neo4j/migrations/006-prune-bogus-whatsapp-persons.ts +0 -132
  75. package/payload/platform/neo4j/migrations/007-conversation-archive-source.ts +0 -116
  76. package/payload/platform/neo4j/migrations/008-adminuser-accountid-backfill.ts +0 -85
  77. package/payload/platform/neo4j/migrations/009-conversation-archive-title.ts +0 -197
  78. package/payload/server/public/assets/data-DwZZ7qbH.js +0 -1
  79. package/payload/server/public/assets/graph-DceEv42K.js +0 -1
  80. /package/payload/server/public/assets/{jsx-runtime-DH5S-MwB.js → jsx-runtime-WW3O7tSz.js} +0 -0
@@ -5,13 +5,13 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Real Agent</title>
7
7
  <link rel="icon" href="/favicon.ico">
8
- <script type="module" crossorigin src="/assets/public-BWMwq5Jj.js"></script>
8
+ <script type="module" crossorigin src="/assets/public-C7mCgRX0.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/chunk-DD-I1_y5.js">
10
- <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-DH5S-MwB.js">
10
+ <link rel="modulepreload" crossorigin href="/assets/jsx-runtime-WW3O7tSz.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/preload-helper-qlgyTAkD.js">
12
- <link rel="modulepreload" crossorigin href="/assets/Checkbox-Bq6ORjz2.js">
13
- <link rel="modulepreload" crossorigin href="/assets/useVoiceRecorder-Cb0nAtOo.js">
14
- <link rel="stylesheet" crossorigin href="/assets/jsx-runtime-DidQeNoZ.css">
12
+ <link rel="modulepreload" crossorigin href="/assets/Checkbox-aCc0UGp3.js">
13
+ <link rel="modulepreload" crossorigin href="/assets/useVoiceRecorder-Bx903Mk1.js">
14
+ <link rel="stylesheet" crossorigin href="/assets/jsx-runtime-BKoartnM.css">
15
15
  <link rel="stylesheet" href="/brand-defaults.css">
16
16
  </head>
17
17
  <body>
@@ -45,14 +45,23 @@ import {
45
45
  vncLog,
46
46
  waitForExit,
47
47
  writeChromiumWrapper
48
- } from "./chunk-UXN47TX2.js";
48
+ } from "./chunk-T2MQIKBT.js";
49
49
  import {
50
+ ACCOUNTS_DIR,
51
+ COMMERCIAL_MODE,
52
+ LOG_DIR,
53
+ MAXY_DIR,
54
+ PLATFORM_ROOT,
55
+ TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
56
+ TELEGRAM_WEBHOOK_SECRET_FILE,
57
+ USERS_FILE,
50
58
  agentLogStream,
51
59
  clearSessionHistory,
52
60
  completeGrantSetup,
53
61
  getAccountIdForSession,
54
62
  getAgentNameForSession,
55
63
  getConversationIdForSession,
64
+ getDefaultAccountId,
56
65
  getGrantForSession,
57
66
  getGroupSlugForSession,
58
67
  getRoleForSession,
@@ -60,6 +69,7 @@ import {
60
69
  getUserIdForSession,
61
70
  getUserNameForSession,
62
71
  getVisitorIdForSession,
72
+ hasStubAccountDir,
63
73
  interruptClient,
64
74
  listAdminSessionsInProgress,
65
75
  preConversationLogStream,
@@ -67,30 +77,18 @@ import {
67
77
  registerGrantSession,
68
78
  registerResumedSession,
69
79
  registerSession,
80
+ resolveAccount,
81
+ resolveAgentConfig,
82
+ resolveDefaultAgentSlug,
83
+ resolveUserAccounts,
70
84
  setAgentSessionId,
71
85
  setConversationIdForSession,
72
86
  setGroupContextForSession,
73
87
  sigtermFlushStreamLogs,
74
88
  unregisterSession,
89
+ validateAgentSlug,
75
90
  validateSession
76
- } from "./chunk-BYPWJ4Z6.js";
77
- import {
78
- ACCOUNTS_DIR,
79
- COMMERCIAL_MODE,
80
- LOG_DIR,
81
- MAXY_DIR,
82
- PLATFORM_ROOT,
83
- TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
84
- TELEGRAM_WEBHOOK_SECRET_FILE,
85
- USERS_FILE,
86
- getDefaultAccountId,
87
- hasStubAccountDir,
88
- resolveAccount,
89
- resolveAgentConfig,
90
- resolveDefaultAgentSlug,
91
- resolveUserAccounts,
92
- validateAgentSlug
93
- } from "./chunk-OJZPS4BL.js";
91
+ } from "./chunk-DJXPAH7T.js";
94
92
  import {
95
93
  CLOUDFLARE_TASK_DIAGNOSTICS,
96
94
  appendCloudflareSteps,
@@ -98,12 +96,10 @@ import {
98
96
  openCloudflareTask,
99
97
  readTunnelState,
100
98
  resolveUnitGoneVerdict
101
- } from "./chunk-B43O764H.js";
99
+ } from "./chunk-D5U4XQ66.js";
102
100
  import {
103
101
  GREETING_DIRECTIVE,
104
102
  HAIKU_MODEL,
105
- __commonJS,
106
- __toESM,
107
103
  backfillNullUserIdConversations,
108
104
  bindVisitorToGroup,
109
105
  checkGroupMembership,
@@ -126,11 +122,15 @@ import {
126
122
  loadOnboardingStep,
127
123
  projectAgent,
128
124
  renameConversation,
129
- runBootMigrations,
125
+ runAdminUserSelfHeal,
130
126
  verifyAndGetConversationUpdatedAt,
131
127
  verifyConversationOwnership,
132
128
  writeAdminUserAndPerson
133
- } from "./chunk-TQ6L56KS.js";
129
+ } from "./chunk-CJWFM3WX.js";
130
+ import {
131
+ __commonJS,
132
+ __toESM
133
+ } from "./chunk-JSBRDJBE.js";
134
134
 
135
135
  // ../lib/graph-trash/dist/index.js
136
136
  var require_dist = __commonJS({
@@ -7493,7 +7493,7 @@ var app11 = new Hono();
7493
7493
  app11.post("/cancel", requireAdminSession, async (c) => {
7494
7494
  const session_key = c.var.sessionKey;
7495
7495
  try {
7496
- const { interruptClient: interruptClient2 } = await import("./client-pool-HC6PMV2X.js");
7496
+ const { interruptClient: interruptClient2 } = await import("./client-pool-M25CGILI.js");
7497
7497
  await interruptClient2(session_key);
7498
7498
  return c.json({ ok: true });
7499
7499
  } catch (err) {
@@ -13049,9 +13049,20 @@ try {
13049
13049
  })();
13050
13050
  (async () => {
13051
13051
  try {
13052
- await runBootMigrations();
13052
+ if (!existsSync23(USERS_FILE)) return;
13053
+ const usersRaw = readFileSync17(USERS_FILE, "utf-8").trim();
13054
+ if (!usersRaw) return;
13055
+ const users = JSON.parse(usersRaw);
13056
+ const userId = users[0]?.userId;
13057
+ if (!userId) return;
13058
+ const account = resolveAccount();
13059
+ if (!account) {
13060
+ console.error("[adminuser-self-heal] no account resolved \u2014 skipping (resolveAccount returned null)");
13061
+ return;
13062
+ }
13063
+ await runAdminUserSelfHeal({ userId, accountId: account.accountId });
13053
13064
  } catch (err) {
13054
- console.error(`[migration] runBootMigrations rejected: ${err instanceof Error ? err.message : String(err)}`);
13065
+ console.error(`[adminuser-self-heal] rejected: ${err instanceof Error ? err.message : String(err)}`);
13055
13066
  }
13056
13067
  })();
13057
13068
  startGraphHealthTimer();
@@ -13072,7 +13083,7 @@ autoDeliverPremiumPlugins(bootEntitlement?.purchasedPlugins ?? void 0);
13072
13083
  (async () => {
13073
13084
  if (!bootAccount) return;
13074
13085
  try {
13075
- const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-R35AJT27.js");
13086
+ const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-GQFKLY62.js");
13076
13087
  const result = await recoverRunningCloudflareTasks(
13077
13088
  bootAccount.accountId,
13078
13089
  configDirForWhatsApp,
@@ -1,30 +0,0 @@
1
- // ============================================================
2
- // Migration 001: Backfill scope property on all existing nodes
3
- //
4
- // Sets scope on every node that participates in memory-search.
5
- // Product knowledge → 'public', internal data → 'admin'.
6
- // Safe to re-run: only touches nodes where scope IS NULL.
7
- //
8
- // Run via: cypher-shell -u neo4j -p <password> -f 001-backfill-scope.cypher
9
- // ============================================================
10
-
11
- // --- Product knowledge (public agent can see) ---
12
-
13
- MATCH (n:Question) WHERE n.scope IS NULL SET n.scope = 'public';
14
- MATCH (n:DefinedTerm) WHERE n.scope IS NULL SET n.scope = 'public';
15
- MATCH (n:Service) WHERE n.scope IS NULL SET n.scope = 'public';
16
- MATCH (n:Review) WHERE n.scope IS NULL SET n.scope = 'public';
17
- MATCH (n:PriceSpecification) WHERE n.scope IS NULL SET n.scope = 'public';
18
- MATCH (n:LocalBusiness) WHERE n.scope IS NULL SET n.scope = 'public';
19
- MATCH (n:KnowledgeDocument) WHERE n.scope IS NULL SET n.scope = 'public';
20
- MATCH (n:Section) WHERE n.scope IS NULL SET n.scope = 'public';
21
- MATCH (n:Chunk) WHERE n.scope IS NULL SET n.scope = 'public';
22
- MATCH (n:DigitalDocument) WHERE n.scope IS NULL SET n.scope = 'public';
23
-
24
- // --- Internal data (admin agent only) ---
25
-
26
- MATCH (n:CreativeWork) WHERE n.scope IS NULL SET n.scope = 'admin';
27
- MATCH (n:Task) WHERE n.scope IS NULL SET n.scope = 'admin';
28
- MATCH (n:Person) WHERE n.scope IS NULL SET n.scope = 'admin';
29
- MATCH (n:Event) WHERE n.scope IS NULL SET n.scope = 'admin';
30
- MATCH (n:OnboardingState) WHERE n.scope IS NULL SET n.scope = 'admin';
@@ -1,191 +0,0 @@
1
- /**
2
- * Migration 002 — Project file-based public agents into the graph (Task 837).
3
- *
4
- * Two passes:
5
- *
6
- * 1. Walk every account directory under data/accounts/<accountId>/agents/
7
- * and call projectAgent(accountId, accountDir, slug) for each non-admin
8
- * agent that has a config.json. The projector is idempotent: re-running
9
- * this migration produces no duplicate nodes or edges.
10
- *
11
- * 2. For every existing public Conversation that carries an agentSlug
12
- * property, MATCH the corresponding :Agent and MERGE the
13
- * (:Conversation)-[:HANDLED_BY]->(:Agent) edge. Conversations whose
14
- * slug doesn't resolve to an Agent (orphan slugs from deleted agents,
15
- * or DM-channel public flows that haven't been extended to register a
16
- * slug) are left edge-less; they will gain the edge automatically once
17
- * the slug is registered or a new agent at that slug is projected.
18
- *
19
- * Run via the platform/ui standalone runtime so it picks up the same
20
- * NEO4J_URI / accounts-directory resolution as the server:
21
- *
22
- * cd platform/ui && \
23
- * NEO4J_URI=bolt://… NEO4J_PASSWORD=… \
24
- * npx tsx ../neo4j/migrations/002-project-public-agents.ts
25
- *
26
- * Output: structured `[agent-graph-backfill]` lines per account + a final
27
- * totals line. A non-zero exit code on any per-account failure surfaces to
28
- * the operator; subsequent accounts are still attempted (the migration is
29
- * isolating by account, not all-or-nothing).
30
- */
31
-
32
- import { existsSync, readdirSync } from "node:fs";
33
- import { resolve } from "node:path";
34
- import {
35
- projectAgent,
36
- getSession,
37
- } from "../../ui/app/lib/neo4j-store";
38
- import { ACCOUNTS_DIR } from "../../ui/app/lib/claude-agent/account";
39
-
40
- interface PerAccountStats {
41
- accountId: string;
42
- agents: number;
43
- agentFailures: number;
44
- convEdges: number;
45
- convOrphans: number;
46
- convCandidates: number;
47
- }
48
-
49
- async function projectAccountAgents(
50
- accountId: string,
51
- accountDir: string,
52
- ): Promise<{ agents: number; agentFailures: number }> {
53
- const agentsDir = resolve(accountDir, "agents");
54
- if (!existsSync(agentsDir)) return { agents: 0, agentFailures: 0 };
55
-
56
- let agents = 0;
57
- let agentFailures = 0;
58
- for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
59
- if (!entry.isDirectory()) continue;
60
- if (entry.name === "admin") continue;
61
-
62
- const configPath = resolve(agentsDir, entry.name, "config.json");
63
- if (!existsSync(configPath)) continue;
64
-
65
- try {
66
- await projectAgent(accountId, accountDir, entry.name);
67
- agents++;
68
- } catch (err) {
69
- agentFailures++;
70
- const msg = err instanceof Error ? err.message : String(err);
71
- console.error(
72
- `[agent-graph-backfill] account=${accountId.slice(0, 8)} agent=${entry.name} project FAILED error="${msg}"`,
73
- );
74
- }
75
- }
76
- return { agents, agentFailures };
77
- }
78
-
79
- interface HandledByBackfillStats {
80
- candidates: number;
81
- edges: number;
82
- orphans: number;
83
- }
84
-
85
- /**
86
- * Two-pass: count candidate Conversations (those carrying agentSlug),
87
- * then OPTIONAL MATCH to surface orphans separately from successful merges.
88
- * A hard MATCH-then-MATCH chain would silently filter orphan-slug rows out,
89
- * making `edges=0` indistinguishable from "no public conversations exist"
90
- * vs "every slug is orphaned" — different incidents, different fixes.
91
- */
92
- async function backfillHandledByEdges(accountId: string): Promise<HandledByBackfillStats> {
93
- const session = getSession();
94
- try {
95
- const result = await session.run(
96
- `MATCH (c:Conversation {accountId: $accountId, agentType: 'public'})
97
- WHERE c.agentSlug IS NOT NULL
98
- OPTIONAL MATCH (a:Agent {accountId: $accountId, slug: c.agentSlug})
99
- FOREACH (_ IN CASE WHEN a IS NULL THEN [] ELSE [1] END | MERGE (c)-[:HANDLED_BY]->(a))
100
- RETURN
101
- count(c) AS candidates,
102
- sum(CASE WHEN a IS NULL THEN 0 ELSE 1 END) AS edges,
103
- sum(CASE WHEN a IS NULL THEN 1 ELSE 0 END) AS orphans`,
104
- { accountId },
105
- );
106
- const toNum = (v: unknown): number => {
107
- if (typeof v === "number") return v;
108
- if (v && typeof (v as { toNumber: () => number }).toNumber === "function") {
109
- return (v as { toNumber: () => number }).toNumber();
110
- }
111
- return 0;
112
- };
113
- return {
114
- candidates: toNum(result.records[0]?.get("candidates")),
115
- edges: toNum(result.records[0]?.get("edges")),
116
- orphans: toNum(result.records[0]?.get("orphans")),
117
- };
118
- } finally {
119
- await session.close();
120
- }
121
- }
122
-
123
- async function main(): Promise<void> {
124
- const start = Date.now();
125
-
126
- if (!existsSync(ACCOUNTS_DIR)) {
127
- console.error(`[agent-graph-backfill] ACCOUNTS_DIR missing at ${ACCOUNTS_DIR} — nothing to do`);
128
- process.exit(0);
129
- }
130
-
131
- const accountEntries = readdirSync(ACCOUNTS_DIR, { withFileTypes: true })
132
- .filter((e) => e.isDirectory());
133
-
134
- console.error(`[agent-graph-backfill] start accounts=${accountEntries.length}`);
135
-
136
- let totalAgents = 0;
137
- let totalAgentFailures = 0;
138
- let totalConvEdges = 0;
139
- let totalConvOrphans = 0;
140
- let totalConvCandidates = 0;
141
- const perAccount: PerAccountStats[] = [];
142
-
143
- for (const entry of accountEntries) {
144
- const accountDir = resolve(ACCOUNTS_DIR, entry.name);
145
- const accountId = entry.name;
146
- const accountStart = Date.now();
147
-
148
- const { agents, agentFailures } = await projectAccountAgents(accountId, accountDir);
149
- totalAgents += agents;
150
- totalAgentFailures += agentFailures;
151
-
152
- let convStats: HandledByBackfillStats = { candidates: 0, edges: 0, orphans: 0 };
153
- try {
154
- convStats = await backfillHandledByEdges(accountId);
155
- totalConvEdges += convStats.edges;
156
- totalConvOrphans += convStats.orphans;
157
- totalConvCandidates += convStats.candidates;
158
- } catch (err) {
159
- const msg = err instanceof Error ? err.message : String(err);
160
- console.error(
161
- `[agent-graph-backfill] account=${accountId.slice(0, 8)} handled-by-backfill FAILED error="${msg}"`,
162
- );
163
- }
164
-
165
- perAccount.push({
166
- accountId,
167
- agents,
168
- agentFailures,
169
- convEdges: convStats.edges,
170
- convOrphans: convStats.orphans,
171
- convCandidates: convStats.candidates,
172
- });
173
- const ms = Date.now() - accountStart;
174
- console.error(
175
- `[agent-graph-backfill] account=${accountId.slice(0, 8)} agents=${agents} failures=${agentFailures} conv-candidates=${convStats.candidates} conv-edges=${convStats.edges} conv-orphans=${convStats.orphans} ms=${ms}`,
176
- );
177
- }
178
-
179
- const ms = Date.now() - start;
180
- console.error(
181
- `[agent-graph-backfill] done totals: agents=${totalAgents} agent-failures=${totalAgentFailures} conv-candidates=${totalConvCandidates} conv-edges=${totalConvEdges} conv-orphans=${totalConvOrphans} ms=${ms}`,
182
- );
183
-
184
- process.exit(totalAgentFailures > 0 ? 1 : 0);
185
- }
186
-
187
- main().catch((err) => {
188
- const msg = err instanceof Error ? err.message : String(err);
189
- console.error(`[agent-graph-backfill] fatal error="${msg}"`);
190
- process.exit(2);
191
- });
@@ -1,24 +0,0 @@
1
- // ============================================================
2
- // Migration 003 — Person.name eradication (Task 849)
3
- //
4
- // Removes the denormalised `name` property from every Person node.
5
- // `Person.name` is forbidden by schema-base.md "Forbidden Properties":
6
- // the canonical fields are `givenName` + `familyName`, composed at
7
- // read time by display-helpers.ts. Persisted `name` was a divergence
8
- // trap — LLM extraction emitted `name = givenName` ("Dan") alongside
9
- // the structured pair, so the canvas rendered "Dan" instead of
10
- // "Dan Brett".
11
- //
12
- // Idempotent: subsequent runs find no Persons with `name` set and
13
- // return removed=0.
14
- //
15
- // Applied at boot by platform/ui/app/lib/neo4j-migrations.ts. Safe to
16
- // run manually:
17
- // cypher-shell -u neo4j -p <password> -a $NEO4J_URI \
18
- // -f platform/neo4j/migrations/003-person-name-eradicate.cypher
19
- // ============================================================
20
-
21
- MATCH (p:Person)
22
- WHERE p.name IS NOT NULL
23
- REMOVE p.name
24
- RETURN count(p) AS removed