@cgh567/agent 2.4.2 → 2.4.4

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 (157) hide show
  1. package/agents/business/talisman-ceo.md +183 -0
  2. package/agents/business/talisman-comms.md +257 -0
  3. package/agents/business/talisman-cto.md +153 -0
  4. package/agents/business/talisman-finance.md +246 -0
  5. package/agents/business/talisman-marketing.md +240 -0
  6. package/agents/business/talisman-sales.md +242 -0
  7. package/agents/business/talisman-support.md +236 -0
  8. package/bin/helios-rpc.js +19 -0
  9. package/daemon/adapters/helios-rpc-adapter.js +5 -12
  10. package/daemon/adapters/tui_wakeup.js +8 -0
  11. package/daemon/context-enrichment.js +27 -0
  12. package/daemon/daemon-manager.js +1 -1
  13. package/daemon/db/email-infrastructure-migrate.js +192 -0
  14. package/daemon/db/hbo-core-migrate.js +189 -0
  15. package/daemon/helios-api.js +863 -64
  16. package/daemon/helios-company-daemon.js +233 -33
  17. package/daemon/lib/blast-radius-analyzer.js +75 -0
  18. package/daemon/lib/domain-bootstrap-orchestrator.js +267 -0
  19. package/daemon/lib/forensic-log.js +113 -0
  20. package/daemon/lib/goal-research-pipeline.js +644 -0
  21. package/daemon/lib/harada/cascade-judge.js +84 -1
  22. package/daemon/lib/harada/cascade-research-dispatcher.js +282 -0
  23. package/daemon/lib/harada/pillar-dispatcher.js +23 -2
  24. package/daemon/lib/hbo-bridge.js +74 -6
  25. package/daemon/lib/headroom-middleware.js +129 -0
  26. package/daemon/lib/headroom-proxy-manager.js +309 -0
  27. package/daemon/lib/hed-engine.js +25 -0
  28. package/daemon/lib/intelligence/department-page-generator.js +46 -1
  29. package/daemon/lib/interpretation-engine.js +92 -0
  30. package/daemon/lib/mental-model-cache.js +96 -0
  31. package/daemon/lib/project-factory.js +47 -0
  32. package/daemon/lib/session-log-reader.js +93 -0
  33. package/daemon/lib/standard-work-bootstrap.js +87 -1
  34. package/daemon/lib/task-completion-processor.js +23 -0
  35. package/daemon/lib/wizard-engine.js +57 -6
  36. package/daemon/package.json +2 -1
  37. package/daemon/routes/agents.js +51 -6
  38. package/daemon/routes/channels.js +116 -2
  39. package/daemon/routes/crm.js +85 -0
  40. package/daemon/routes/dashboard.js +62 -16
  41. package/daemon/routes/dept.js +10 -1
  42. package/daemon/routes/email-triage.js +19 -10
  43. package/daemon/routes/hbo.js +618 -58
  44. package/daemon/routes/hed.js +133 -0
  45. package/daemon/routes/inbox.js +397 -8
  46. package/daemon/routes/project.js +580 -66
  47. package/daemon/routes/routines.js +14 -0
  48. package/daemon/routes/tasks.js +15 -1
  49. package/daemon/schema-apply.js +174 -0
  50. package/daemon/schema-definitions.js +433 -0
  51. package/daemon/schema-migrations-hbo.js +20 -0
  52. package/daemon/schema-migrations-hed.js +18 -0
  53. package/daemon/schema-migrations-proj.js +153 -0
  54. package/extensions/__tests__/codebase-index.test.ts +73 -0
  55. package/extensions/__tests__/extension-command-registration.test.ts +35 -0
  56. package/extensions/__tests__/git-push-guard.test.ts +68 -0
  57. package/extensions/context-compaction.ts +104 -76
  58. package/extensions/cortex/__tests__/cortex-core.test.ts +100 -0
  59. package/extensions/cortex/wal-replay.ts +91 -0
  60. package/extensions/email/actions/draft-response.ts +21 -1
  61. package/extensions/email/auth/accounts.ts +5 -11
  62. package/extensions/email/auth/inbox-dog.ts +5 -2
  63. package/extensions/email/backfill.ts +20 -13
  64. package/extensions/email/providers/gmail.ts +164 -0
  65. package/extensions/email/providers/google-calendar.ts +34 -5
  66. package/extensions/helios-browser/__tests__/browser-routing.test.ts +57 -0
  67. package/extensions/helios-browser/backends/playwright.ts +3 -1
  68. package/extensions/helios-governance/__tests__/governance-gates.test.ts +40 -0
  69. package/extensions/helios-governance/__tests__/tournament-consumer.test.js +66 -0
  70. package/extensions/hema-dispatch-v3/headroom-compress.ts +103 -0
  71. package/extensions/hema-dispatch-v3/index.ts +46 -72
  72. package/extensions/interview/__tests__/server.test.ts +117 -0
  73. package/extensions/lib/helios-root.cjs +46 -0
  74. package/extensions/subagent-mesh/__tests__/handlers.test.ts +98 -0
  75. package/extensions/warm-tick/warm-tick-maintenance.ts +164 -0
  76. package/lib/__tests__/bulk-ingest.live.test.ts +66 -0
  77. package/lib/__tests__/crash-fixes.test.ts +49 -0
  78. package/lib/__tests__/hbo-core-store.test.js +238 -0
  79. package/lib/__tests__/maintenance-mission-wiring.test.ts +35 -0
  80. package/lib/broker/__tests__/jit-subscription.test.js +44 -1
  81. package/lib/broker/__tests__/lifecycle-channels.test.js +25 -1
  82. package/lib/compression/__tests__/ccr-store.test.js +138 -0
  83. package/lib/compression/__tests__/pipeline.test.js +280 -0
  84. package/lib/compression/__tests__/smart-crusher.test.js +242 -0
  85. package/lib/compression/dist/server.js +34 -1
  86. package/lib/compression/dist/start-server.js +77 -0
  87. package/lib/event-bus.mts +1 -1
  88. package/lib/graph/learning/headroom-learn-bridge.js +175 -0
  89. package/lib/graph-availability.js +62 -0
  90. package/lib/hbo-core-store.compiled.js +834 -0
  91. package/lib/hbo-core-store.js +124 -0
  92. package/lib/hbo-core-store.ts +979 -0
  93. package/lib/mission-loop/__tests__/research-handler.test.ts +143 -0
  94. package/lib/skill-sync.js +6 -1
  95. package/lib/startup-integrity.js +9 -2
  96. package/lib/triage-core/__tests__/classifier-fixture.test.ts +254 -0
  97. package/lib/triage-core/__tests__/classifier-post-norm.test.ts +1 -1
  98. package/lib/triage-core/__tests__/classifier.test.ts +45 -7
  99. package/lib/triage-core/__tests__/correction-detector.test.ts +36 -0
  100. package/lib/triage-core/__tests__/d6-dunbar-boost.test.ts +5 -5
  101. package/lib/triage-core/__tests__/orchestrator-pipeline.test.ts +107 -0
  102. package/lib/triage-core/__tests__/orchestrator.test.ts +113 -1
  103. package/lib/triage-core/__tests__/signals.test.ts +357 -0
  104. package/lib/triage-core/__tests__/sql-parity.test.ts +216 -0
  105. package/lib/triage-core/backfill-cost-estimator.ts +91 -0
  106. package/lib/triage-core/backfill-orchestrator.ts +119 -0
  107. package/lib/triage-core/classifier.ts +41 -8
  108. package/lib/triage-core/cos/cross-channel-escalation.ts +2 -3
  109. package/lib/triage-core/cos/response-debt.ts +2 -2
  110. package/lib/triage-core/graph/__tests__/batch-persistence.test.ts +283 -0
  111. package/lib/triage-core/graph/batch-persistence.ts +66 -2
  112. package/lib/triage-core/graph/betweenness-worker.js +75 -0
  113. package/lib/triage-core/graph/graph-rank-sql.ts +67 -0
  114. package/lib/triage-core/graph/persistence.ts +1 -1
  115. package/lib/triage-core/graph/schema-v2.ts +2 -0
  116. package/lib/triage-core/graph/schema.cypher +11 -0
  117. package/lib/triage-core/graph/triage-query.ts +1 -1
  118. package/lib/triage-core/learning.ts +15 -20
  119. package/lib/triage-core/mental-model/bedrock-config.ts +78 -0
  120. package/lib/triage-core/mental-model/cos-integration.ts +1 -1
  121. package/lib/triage-core/mental-model/entity-extractor.ts +51 -4
  122. package/lib/triage-core/mental-model/identity-resolver.ts +5 -5
  123. package/lib/triage-core/mental-model/key-facts.ts +1 -2
  124. package/lib/triage-core/mental-model/model-assembler-sql.ts +200 -0
  125. package/lib/triage-core/mental-model/model-assembler.ts +16 -3
  126. package/lib/triage-core/orchestrator.ts +8 -15
  127. package/lib/triage-core/scheduled-sends.ts +39 -2
  128. package/lib/triage-core/signals/comms-style.ts +1 -1
  129. package/lib/triage-core/signals/cross-channel-escalation.ts +2 -2
  130. package/lib/triage-core/signals/favee-type.ts +6 -1
  131. package/lib/triage-core/signals/goal-relevance.ts +31 -2
  132. package/lib/triage-core/signals/personal-importance.ts +1 -1
  133. package/lib/triage-core/signals/referral-chain.ts +0 -1
  134. package/lib/triage-core/signals/relationship-decay.ts +4 -0
  135. package/lib/triage-core/signals/relationship-health.ts +6 -1
  136. package/lib/triage-core/signals/trajectory-signal.ts +38 -3
  137. package/lib/triage-core/tournament-runner.js +11 -1
  138. package/lib/triage-core/triage-llm-factory.ts +110 -0
  139. package/lib/triage-core/triage-local-llm.ts +145 -0
  140. package/lib/triage-core/triage-sql-store.ts +337 -0
  141. package/lib/triage-core/types.ts +2 -2
  142. package/lib/unified-graph.atomic.test.ts +52 -0
  143. package/lib/unified-graph.failure-categories.test.ts +55 -0
  144. package/package.json +18 -7
  145. package/prebuilds/darwin-arm64/better_sqlite3.node +0 -0
  146. package/prebuilds/linux-x64/better_sqlite3.node +0 -0
  147. package/prebuilds/win32-x64/better_sqlite3.node +0 -0
  148. package/skills/helios-bookkeeping/SKILL.md +321 -0
  149. package/skills/helios-briefer/SKILL.md +44 -0
  150. package/skills/helios-client-relations/SKILL.md +322 -0
  151. package/skills/helios-personal-triager/SKILL.md +45 -0
  152. package/skills/helios-recruitment/SKILL.md +317 -0
  153. package/skills/helios-relationship-nudger/SKILL.md +77 -0
  154. package/skills/helios-researcher/SKILL.md +44 -0
  155. package/skills/helios-scheduler/SKILL.md +58 -0
  156. package/skills/helios-tax-analyst/SKILL.md +280 -0
  157. package/lib/triage-core/orchestrator.ts.bak-r005-r006-r008 +0 -1823
@@ -0,0 +1,192 @@
1
+ #!/usr/bin/env node
2
+ const Database = require("better-sqlite3");
3
+ const path = require("path");
4
+ const fs = require("fs");
5
+ const os = require("os");
6
+
7
+ const DB_PATH = path.join(process.env.HELIOS_ROOT || path.join(os.homedir(), "helios-agent"), "data", "email-infrastructure.db");
8
+ fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
9
+
10
+ const db = new Database(DB_PATH);
11
+ db.pragma("journal_mode = WAL");
12
+ db.pragma("foreign_keys = ON");
13
+
14
+ db.exec(`
15
+ CREATE TABLE IF NOT EXISTS email_domains (
16
+ id TEXT PRIMARY KEY,
17
+ company_id TEXT NOT NULL,
18
+ domain TEXT NOT NULL,
19
+ scenario TEXT NOT NULL DEFAULT 'existing',
20
+ registrar TEXT,
21
+ registrar_account_vault_key TEXT,
22
+ registrar_api_key_vault_key TEXT,
23
+ registered_at TEXT,
24
+ expires_at TEXT,
25
+ auto_renew INTEGER DEFAULT 1,
26
+ registration_cost_cents INTEGER,
27
+ annual_renewal_cents INTEGER,
28
+ porkbun_order_id TEXT,
29
+ mx_records TEXT DEFAULT '[]',
30
+ spf_record TEXT,
31
+ spf_verified INTEGER DEFAULT 0,
32
+ dkim_selectors TEXT DEFAULT '[]',
33
+ dmarc_policy TEXT,
34
+ dmarc_verified INTEGER DEFAULT 0,
35
+ status TEXT DEFAULT 'bootstrapping',
36
+ verified_at TEXT,
37
+ last_verified_at TEXT,
38
+ verification_error TEXT,
39
+ dns_provisioned_at TEXT,
40
+ inbound_provider TEXT,
41
+ outbound_provider TEXT,
42
+ inbound_provider_vault_key TEXT,
43
+ outbound_provider_vault_key TEXT,
44
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
45
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
46
+ UNIQUE(company_id, domain)
47
+ );
48
+ CREATE INDEX IF NOT EXISTS idx_email_domains_company ON email_domains(company_id);
49
+ CREATE INDEX IF NOT EXISTS idx_email_domains_status ON email_domains(status);
50
+ CREATE INDEX IF NOT EXISTS idx_email_domains_expires ON email_domains(expires_at);
51
+
52
+ CREATE TABLE IF NOT EXISTS email_personas (
53
+ id TEXT PRIMARY KEY,
54
+ company_id TEXT NOT NULL,
55
+ slug TEXT NOT NULL,
56
+ first_name TEXT NOT NULL,
57
+ last_name TEXT,
58
+ full_name TEXT NOT NULL,
59
+ title TEXT NOT NULL,
60
+ company_display TEXT,
61
+ bio TEXT,
62
+ avatar_url TEXT,
63
+ persona_type TEXT NOT NULL DEFAULT 'ai_branded',
64
+ tone TEXT DEFAULT 'friendly',
65
+ writing_style TEXT,
66
+ avoid_phrases TEXT DEFAULT '[]',
67
+ signature_html TEXT,
68
+ signature_text TEXT,
69
+ linkedin_url TEXT,
70
+ calendar_url TEXT,
71
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
72
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
73
+ UNIQUE(company_id, slug)
74
+ );
75
+ CREATE INDEX IF NOT EXISTS idx_email_personas_company ON email_personas(company_id);
76
+
77
+ CREATE TABLE IF NOT EXISTS email_channels (
78
+ id TEXT PRIMARY KEY,
79
+ company_id TEXT NOT NULL,
80
+ domain_id TEXT NOT NULL,
81
+ address TEXT NOT NULL,
82
+ local_part TEXT NOT NULL,
83
+ sender_identity_mode TEXT NOT NULL DEFAULT 'branded_ai_agent',
84
+ display_name TEXT NOT NULL,
85
+ agent_persona_name TEXT,
86
+ agent_persona_title TEXT,
87
+ persona_id TEXT,
88
+ ai_disclosure_enabled INTEGER DEFAULT 1,
89
+ ai_disclosure_statement TEXT,
90
+ ai_disclosure_placement TEXT DEFAULT 'footer',
91
+ reply_to TEXT,
92
+ signature_html TEXT,
93
+ signature_text TEXT,
94
+ agent_id TEXT,
95
+ role_pattern TEXT,
96
+ smtp_provider TEXT,
97
+ smtp_vault_key TEXT,
98
+ imap_provider TEXT,
99
+ imap_vault_key TEXT,
100
+ helios_mail_inbox_id TEXT,
101
+ hitl_required INTEGER DEFAULT 0,
102
+ max_daily_outbound INTEGER DEFAULT 50,
103
+ warmup_enabled INTEGER DEFAULT 1,
104
+ warmup_current_limit INTEGER DEFAULT 10,
105
+ warmup_started_at TEXT,
106
+ eu_compliance_acknowledged INTEGER DEFAULT 0,
107
+ can_email_eu_recipients INTEGER DEFAULT 0,
108
+ physical_address TEXT,
109
+ unsubscribe_url TEXT,
110
+ preferred_non_eu_mode TEXT,
111
+ status TEXT DEFAULT 'pending_verification',
112
+ total_sent INTEGER DEFAULT 0,
113
+ sent_today INTEGER DEFAULT 0,
114
+ bounce_rate REAL DEFAULT 0.0,
115
+ complaint_rate REAL DEFAULT 0.0,
116
+ last_sent_at TEXT,
117
+ last_bounce_at TEXT,
118
+ last_error_at TEXT,
119
+ last_error_message TEXT,
120
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
121
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
122
+ UNIQUE(company_id, address)
123
+ );
124
+ CREATE INDEX IF NOT EXISTS idx_email_channels_company ON email_channels(company_id);
125
+ CREATE INDEX IF NOT EXISTS idx_email_channels_agent ON email_channels(agent_id);
126
+ CREATE INDEX IF NOT EXISTS idx_email_channels_status ON email_channels(status);
127
+ CREATE INDEX IF NOT EXISTS idx_email_channels_domain ON email_channels(domain_id);
128
+
129
+ CREATE TABLE IF NOT EXISTS domain_bootstrap_jobs (
130
+ id TEXT PRIMARY KEY,
131
+ company_id TEXT NOT NULL,
132
+ domain_id TEXT,
133
+ triggered_by TEXT NOT NULL,
134
+ approval_id TEXT,
135
+ current_stage TEXT NOT NULL DEFAULT 'domain_search',
136
+ completed_stages TEXT DEFAULT '[]',
137
+ failed_stage TEXT,
138
+ fail_reason TEXT,
139
+ retry_count INTEGER DEFAULT 0,
140
+ max_retries INTEGER DEFAULT 3,
141
+ candidate_domains TEXT DEFAULT '[]',
142
+ selected_domain TEXT,
143
+ estimated_cost_cents INTEGER,
144
+ paid_cost_cents INTEGER,
145
+ porkbun_order_id TEXT,
146
+ porkbun_account_registry_id TEXT,
147
+ resend_account_registry_id TEXT,
148
+ zoho_account_registry_id TEXT,
149
+ zoho_org_id TEXT,
150
+ captcha_solves_attempted INTEGER DEFAULT 0,
151
+ captcha_solves_succeeded INTEGER DEFAULT 0,
152
+ captcha_solve_cost_cents INTEGER DEFAULT 0,
153
+ started_at TEXT NOT NULL DEFAULT (datetime('now')),
154
+ completed_at TEXT,
155
+ last_activity_at TEXT NOT NULL DEFAULT (datetime('now')),
156
+ next_retry_at TEXT,
157
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
158
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
159
+ );
160
+ CREATE INDEX IF NOT EXISTS idx_bootstrap_jobs_company ON domain_bootstrap_jobs(company_id);
161
+ CREATE INDEX IF NOT EXISTS idx_bootstrap_jobs_stage ON domain_bootstrap_jobs(current_stage);
162
+ CREATE INDEX IF NOT EXISTS idx_bootstrap_jobs_domain ON domain_bootstrap_jobs(domain_id);
163
+
164
+ CREATE TABLE IF NOT EXISTS _schema_versions (
165
+ name TEXT PRIMARY KEY,
166
+ version INTEGER NOT NULL DEFAULT 1,
167
+ applied_at TEXT NOT NULL DEFAULT (datetime('now'))
168
+ );
169
+ CREATE TABLE IF NOT EXISTS email_draft_reviews (
170
+ id TEXT PRIMARY KEY,
171
+ company_id TEXT NOT NULL,
172
+ agent_id TEXT NOT NULL,
173
+ channel_id TEXT NOT NULL,
174
+ recipient_email TEXT NOT NULL,
175
+ subject TEXT NOT NULL,
176
+ body_text TEXT NOT NULL,
177
+ body_html TEXT,
178
+ generated_at TEXT NOT NULL DEFAULT (datetime('now')),
179
+ status TEXT NOT NULL DEFAULT 'pending',
180
+ reviewed_by TEXT,
181
+ reviewed_at TEXT,
182
+ review_note TEXT,
183
+ expires_at TEXT NOT NULL,
184
+ send_after_approval INTEGER DEFAULT 1
185
+ );
186
+ CREATE INDEX IF NOT EXISTS idx_drafts_company_pending ON email_draft_reviews(company_id, status);
187
+
188
+ INSERT OR REPLACE INTO _schema_versions(name, version) VALUES('email_infrastructure', 2);
189
+ `);
190
+
191
+ db.close();
192
+ console.log("email-infrastructure.db created/migrated successfully at:", DB_PATH);
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * hbo-core-migrate.js
4
+ * Migrates HBO core entity data from Memgraph → SQLite (hbo-core-store).
5
+ *
6
+ * Entity types: Task, Approval, BudgetPolicy, CostEvent, BusinessAgent,
7
+ * QuarterlyOKR, CompanyGoal, SystemAim, GoalPillar,
8
+ * Lead, CRMContact, Account, Opportunity
9
+ *
10
+ * Design:
11
+ * - Idempotent: safe to run multiple times (INSERT OR REPLACE)
12
+ * - Graceful: catches Memgraph connection errors, logs, exits 0
13
+ * - Reports counts per entity type on completion
14
+ * - Never throws to process for expected errors
15
+ *
16
+ * Phase 1 — TCP probe checks if Memgraph port 7687 is open.
17
+ * If unreachable, logs "Memgraph unavailable" and exits 0.
18
+ * Phase 2 — Loads neo4j-driver and hbo-core-store, runs MATCH queries, upserts.
19
+ */
20
+ 'use strict';
21
+
22
+ process.env.HELIOS_SKIP_BROKER = '1';
23
+ globalThis.__helios_skip_broker = true;
24
+
25
+ const net = require('net');
26
+
27
+ function parseBoltUrl(url) {
28
+ try {
29
+ const u = new URL(url.replace(/^bolt:\/\//, 'tcp://'));
30
+ return { host: u.hostname || '127.0.0.1', port: parseInt(u.port || '7687', 10) };
31
+ } catch {
32
+ return { host: '127.0.0.1', port: 7687 };
33
+ }
34
+ }
35
+
36
+ function probeMemgraph(host, port, timeoutMs) {
37
+ return new Promise((resolve) => {
38
+ const socket = new net.Socket();
39
+ let done = false;
40
+ const finish = (ok) => {
41
+ if (done) return;
42
+ done = true;
43
+ try { socket.destroy(); } catch {}
44
+ resolve(ok);
45
+ };
46
+ socket.setTimeout(timeoutMs);
47
+ socket.once('connect', () => finish(true));
48
+ socket.once('error', () => finish(false));
49
+ socket.once('timeout', () => finish(false));
50
+ socket.connect(port, host);
51
+ });
52
+ }
53
+
54
+ const ENTITY_SPECS = [
55
+ { label: 'Task', cypher: 'MATCH (n:Task) RETURN n', storeMethod: 'createTask' },
56
+ { label: 'Approval', cypher: 'MATCH (n:Approval) RETURN n', storeMethod: 'createApproval' },
57
+ { label: 'BudgetPolicy', cypher: 'MATCH (n:BudgetPolicy) RETURN n', storeMethod: 'upsertBudgetPolicy' },
58
+ { label: 'CostEvent', cypher: 'MATCH (n:CostEvent) RETURN n', storeMethod: 'createCostEvent' },
59
+ { label: 'BusinessAgent', cypher: 'MATCH (n:BusinessAgent) RETURN n', storeMethod: 'upsertBusinessAgent' },
60
+ { label: 'QuarterlyOKR', cypher: 'MATCH (n:QuarterlyOKR) RETURN n', storeMethod: 'upsertOKR', typeOverride: 'quarterly_okr' },
61
+ { label: 'CompanyGoal', cypher: 'MATCH (n:CompanyGoal) RETURN n', storeMethod: 'upsertOKR', typeOverride: 'company_goal' },
62
+ { label: 'SystemAim', cypher: 'MATCH (n:SystemAim) RETURN n', storeMethod: 'upsertOKR', typeOverride: 'system_aim' },
63
+ { label: 'GoalPillar', cypher: 'MATCH (n:GoalPillar) RETURN n', storeMethod: 'upsertOKR', typeOverride: 'goal_pillar' },
64
+ { label: 'Lead', cypher: 'MATCH (n:Lead) RETURN n', storeMethod: 'upsertLead' },
65
+ { label: 'CRMContact', cypher: 'MATCH (n:CRMContact) RETURN n', storeMethod: 'upsertCRMContact' },
66
+ { label: 'Account', cypher: 'MATCH (n:Account) RETURN n', storeMethod: 'upsertAccount' },
67
+ { label: 'Opportunity', cypher: 'MATCH (n:Opportunity) RETURN n', storeMethod: 'upsertOpportunity' },
68
+ ];
69
+
70
+ async function main() {
71
+ console.log('[hbo-core-migrate] Starting HBO core data migration from Memgraph → SQLite');
72
+
73
+ const boltUrl = process.env.MEMGRAPH_BOLT_URL || 'bolt://127.0.0.1:7687';
74
+ const { host, port } = parseBoltUrl(boltUrl);
75
+ const available = await probeMemgraph(host, port, 3000);
76
+
77
+ if (!available) {
78
+ console.log('[hbo-core-migrate] Memgraph unavailable — skipping migration, SQLite will populate on first write');
79
+ process.exit(0);
80
+ }
81
+
82
+ console.log(`[hbo-core-migrate] Memgraph reachable at ${host}:${port} — loading modules`);
83
+
84
+ const neo4j = require('neo4j-driver');
85
+ const store = require('../../lib/hbo-core-store');
86
+
87
+ if (typeof store.createTask !== 'function') {
88
+ console.error('[hbo-core-migrate] ERROR: hbo-core-store failed to load (createTask is not a function).');
89
+ console.error('[hbo-core-migrate] Ensure NODE_OPTIONS=--experimental-sqlite and jiti is available.');
90
+ process.exit(1);
91
+ }
92
+
93
+ const auth = process.env.MEMGRAPH_USER
94
+ ? neo4j.auth.basic(process.env.MEMGRAPH_USER, process.env.MEMGRAPH_PASSWORD || '')
95
+ : neo4j.auth.basic('', '');
96
+
97
+ const driver = neo4j.driver(boltUrl, auth, {
98
+ maxConnectionPoolSize: 4,
99
+ connectionAcquisitionTimeout: 10000,
100
+ connectionTimeout: 8000,
101
+ maxTransactionRetryTime: 0,
102
+ encrypted: 'ENCRYPTION_OFF',
103
+ disableLosslessIntegers: true,
104
+ });
105
+
106
+ async function queryMemgraph(cypher) {
107
+ const session = driver.session({ defaultAccessMode: neo4j.session.READ });
108
+ try {
109
+ const result = await session.run(cypher);
110
+ return result.records.map(r => r.toObject());
111
+ } finally {
112
+ try { await session.close(); } catch {}
113
+ }
114
+ }
115
+
116
+ const counts = {};
117
+ const errors = [];
118
+
119
+ for (const spec of ENTITY_SPECS) {
120
+ let rows;
121
+ try {
122
+ rows = await queryMemgraph(spec.cypher);
123
+ } catch (err) {
124
+ console.warn(`[hbo-core-migrate] Warning: failed to read ${spec.label}: ${err.message}`);
125
+ errors.push({ label: spec.label, error: err.message });
126
+ counts[spec.label] = 0;
127
+ continue;
128
+ }
129
+
130
+ let count = 0;
131
+ const fn = store[spec.storeMethod];
132
+ if (typeof fn !== 'function') {
133
+ console.warn(`[hbo-core-migrate] Warning: store method '${spec.storeMethod}' not found — skipping ${spec.label}`);
134
+ counts[spec.label] = 0;
135
+ continue;
136
+ }
137
+
138
+ for (const row of rows) {
139
+ try {
140
+ const props = row.n && row.n.properties ? row.n.properties : (row.n || {});
141
+ const record = spec.typeOverride ? { ...props, type: spec.typeOverride } : { ...props };
142
+ fn(record);
143
+ count++;
144
+ } catch (writeErr) {
145
+ if (!errors.find(e => e.label === spec.label)) {
146
+ errors.push({ label: spec.label, error: writeErr.message });
147
+ console.warn(`[hbo-core-migrate] Warning: failed to upsert ${spec.label}: ${writeErr.message}`);
148
+ }
149
+ }
150
+ }
151
+ counts[spec.label] = count;
152
+ }
153
+
154
+ try { await driver.close(); } catch {}
155
+
156
+ const tasks = counts['Task'] ?? 0;
157
+ const approvals = counts['Approval'] ?? 0;
158
+ const budgetPols = counts['BudgetPolicy'] ?? 0;
159
+ const costEvts = counts['CostEvent'] ?? 0;
160
+ const bizAgents = counts['BusinessAgent'] ?? 0;
161
+ const qOKRs = counts['QuarterlyOKR'] ?? 0;
162
+ const compGoals = counts['CompanyGoal'] ?? 0;
163
+ const sysAims = counts['SystemAim'] ?? 0;
164
+ const goalPillars = counts['GoalPillar'] ?? 0;
165
+ const leads = counts['Lead'] ?? 0;
166
+ const contacts = counts['CRMContact'] ?? 0;
167
+ const accounts = counts['Account'] ?? 0;
168
+ const opps = counts['Opportunity'] ?? 0;
169
+
170
+ console.log(
171
+ `[hbo-core-migrate] Migrated ${tasks} tasks, ${approvals} approvals, ` +
172
+ `${budgetPols} budget policies, ${costEvts} cost events, ` +
173
+ `${bizAgents} agents, ${qOKRs + compGoals + sysAims + goalPillars} OKRs, ` +
174
+ `${leads} leads, ${contacts} CRM contacts, ${accounts} accounts, ${opps} opportunities`
175
+ );
176
+
177
+ if (errors.length > 0) {
178
+ console.warn(`[hbo-core-migrate] Completed with ${errors.length} warning(s).`);
179
+ } else {
180
+ console.log('[hbo-core-migrate] Migration complete — no errors');
181
+ }
182
+
183
+ process.exit(0);
184
+ }
185
+
186
+ main().catch(err => {
187
+ console.error('[hbo-core-migrate] Unexpected error:', err.message || err);
188
+ process.exit(0);
189
+ });