@spilno/herald-mcp 1.34.3 → 1.34.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.
package/README.md CHANGED
@@ -30,11 +30,31 @@ herald.gotStuck('What failed');
30
30
 
31
31
  ## Quick Start
32
32
 
33
+ ### MCP Server (for AI agents like Claude)
34
+
33
35
  ```bash
34
36
  cd your-project
35
37
  npx @spilno/herald-mcp init
36
38
  ```
37
39
 
40
+ ### SDK (for programmatic access)
41
+
42
+ ```typescript
43
+ import { herald } from '@spilno/herald-mcp';
44
+
45
+ // Capture a pattern (something that worked)
46
+ await herald.learned('Always run tests before committing');
47
+
48
+ // Capture an antipattern (something that failed)
49
+ await herald.gotStuck('Forgot to check existing tests before refactoring');
50
+
51
+ // Query patterns
52
+ const patterns = await herald.recall();
53
+
54
+ // Configure (optional - uses git context by default)
55
+ herald.configure({ baseUrl: 'https://custom.ceda.com', token: 'your-token' });
56
+ ```
57
+
38
58
  **What this does:**
39
59
  1. Creates `.mcp.json` with Herald MCP configuration
40
60
  2. Fetches learned patterns from CEDA (if any exist)
@@ -223,6 +243,82 @@ CEDA (Cognitive Event-Driven Architecture) is pattern memory for AI:
223
243
 
224
244
  Unlike RAG (retrieves content), CEDA retrieves **what worked**.
225
245
 
246
+ ## SDK API
247
+
248
+ The SDK provides programmatic access to CEDA pattern memory for use in your own applications.
249
+
250
+ ### Installation
251
+
252
+ ```bash
253
+ npm install @spilno/herald-mcp
254
+ ```
255
+
256
+ ### API Reference
257
+
258
+ #### `herald.learned(insight, context?)`
259
+
260
+ Capture a pattern (something that worked).
261
+
262
+ ```typescript
263
+ await herald.learned('Always run tests before committing');
264
+ await herald.learned('Use feature flags for gradual rollouts', 'deployment pipeline');
265
+ ```
266
+
267
+ #### `herald.gotStuck(insight, context?)`
268
+
269
+ Capture an antipattern (something that failed).
270
+
271
+ ```typescript
272
+ await herald.gotStuck('Forgot to check existing tests before refactoring');
273
+ await herald.gotStuck('Deployed without running migrations', 'production incident');
274
+ ```
275
+
276
+ #### `herald.recall(topic?)`
277
+
278
+ Query learned patterns and antipatterns.
279
+
280
+ ```typescript
281
+ const patterns = await herald.recall();
282
+ const deployPatterns = await herald.recall('deployment');
283
+ ```
284
+
285
+ Returns an array of `Pattern` objects:
286
+
287
+ ```typescript
288
+ interface Pattern {
289
+ insight: string;
290
+ feeling: 'success' | 'stuck';
291
+ signal?: string;
292
+ reinforcement?: string;
293
+ warning?: string;
294
+ scope?: string;
295
+ }
296
+ ```
297
+
298
+ #### `herald.configure(opts)`
299
+
300
+ Configure the SDK (optional - uses git context by default).
301
+
302
+ ```typescript
303
+ herald.configure({
304
+ baseUrl: 'https://custom.ceda.com',
305
+ token: 'your-api-token',
306
+ company: 'acme',
307
+ project: 'backend',
308
+ user: 'developer'
309
+ });
310
+ ```
311
+
312
+ ### Context Detection
313
+
314
+ By default, the SDK automatically derives context from:
315
+
316
+ 1. **Git remote** - Organization and repository name from git origin
317
+ 2. **Git user** - User name from git config
318
+ 3. **Path** - Falls back to folder names if not in a git repo
319
+
320
+ This means you can use the SDK without any configuration in most projects.
321
+
226
322
  ## Links
227
323
 
228
324
  - **CEDA**: https://getceda.com
@@ -235,4 +331,4 @@ MIT
235
331
 
236
332
  ---
237
333
 
238
- *Herald v1.25.0 — Pattern memory for AI agents*
334
+ *Herald v1.33.0 — Pattern memory for AI agents*
package/dist/cli.js CHANGED
@@ -134,9 +134,11 @@ function hashTag(input) {
134
134
  }
135
135
  function deriveTagSet() {
136
136
  // 1. Check env vars (explicit override)
137
- if (process.env.HERALD_COMPANY) {
137
+ // HERALD_ORG is primary, HERALD_COMPANY for backwards compat
138
+ const envOrg = process.env.HERALD_ORG || process.env.HERALD_COMPANY;
139
+ if (envOrg) {
138
140
  return {
139
- tags: [process.env.HERALD_COMPANY, process.env.HERALD_PROJECT].filter(Boolean),
141
+ tags: [envOrg, process.env.HERALD_PROJECT].filter(Boolean),
140
142
  trust: 'LOW', // Env vars can be set by anyone
141
143
  source: 'env',
142
144
  propagates: false
@@ -213,9 +215,11 @@ function persistContext(tagSet, user) {
213
215
  function loadOrDeriveContext() {
214
216
  const user = process.env.HERALD_USER || deriveUser();
215
217
  // 1. Check env vars (explicit override - highest priority, but LOW trust)
216
- if (process.env.HERALD_COMPANY) {
218
+ // HERALD_ORG is primary, HERALD_COMPANY for backwards compat
219
+ const envOrg = process.env.HERALD_ORG || process.env.HERALD_COMPANY;
220
+ if (envOrg) {
217
221
  return {
218
- tags: [process.env.HERALD_COMPANY, process.env.HERALD_PROJECT].filter(Boolean),
222
+ tags: [envOrg, process.env.HERALD_PROJECT].filter(Boolean),
219
223
  user,
220
224
  trust: 'LOW',
221
225
  source: 'env',
@@ -261,7 +265,7 @@ const LOADED_CONTEXT = loadOrDeriveContext();
261
265
  let HERALD_USER = LOADED_CONTEXT.user;
262
266
  // Tags from context (env > stored > git > path) - can be refreshed
263
267
  let HERALD_TAGS = LOADED_CONTEXT.tags;
264
- let HERALD_COMPANY = HERALD_TAGS[0] || "";
268
+ let HERALD_ORG = HERALD_TAGS[0] || "";
265
269
  let HERALD_PROJECT = HERALD_TAGS[1] || HERALD_TAGS[0] || "";
266
270
  // ADR-001: Trust level determines pattern propagation
267
271
  // These are mutable - verification with CEDA may upgrade/downgrade trust
@@ -307,7 +311,7 @@ const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "";
307
311
  const OPENAI_API_KEY = process.env.OPENAI_API_KEY || "";
308
312
  // Session persistence - context-isolated paths
309
313
  function getHeraldDir() {
310
- return join(homedir(), ".herald", HERALD_COMPANY, HERALD_PROJECT, HERALD_USER);
314
+ return join(homedir(), ".herald", HERALD_ORG, HERALD_PROJECT, HERALD_USER);
311
315
  }
312
316
  function getSessionFile() {
313
317
  return join(getHeraldDir(), "session");
@@ -424,7 +428,7 @@ function clearSession() {
424
428
  }
425
429
  }
426
430
  function getContextString() {
427
- return `${HERALD_COMPANY}:${HERALD_PROJECT}:${HERALD_USER}`;
431
+ return `${HERALD_ORG}:${HERALD_PROJECT}:${HERALD_USER}`;
428
432
  }
429
433
  const HERALD_SYSTEM_PROMPT = `You are Herald, the voice of CEDA (Cognitive Event-Driven Architecture).
430
434
  You help humans design module structures through natural conversation.
@@ -672,7 +676,7 @@ async function callCedaAPI(endpoint, method = "GET", body) {
672
676
  endpoint.startsWith("/api/observations");
673
677
  if (method === "GET" && needsTenantParams) {
674
678
  const separator = endpoint.includes("?") ? "&" : "?";
675
- url += `${separator}company=${HERALD_COMPANY}&project=${HERALD_PROJECT}&user=${HERALD_USER}`;
679
+ url += `${separator}org=${HERALD_ORG}&project=${HERALD_PROJECT}&user=${HERALD_USER}`;
676
680
  }
677
681
  const headers = {
678
682
  "Content-Type": "application/json",
@@ -685,7 +689,7 @@ async function callCedaAPI(endpoint, method = "GET", body) {
685
689
  if (method === "POST" && body && typeof body === "object") {
686
690
  enrichedBody = {
687
691
  ...body,
688
- company: HERALD_COMPANY,
692
+ org: HERALD_ORG,
689
693
  project: HERALD_PROJECT,
690
694
  user: HERALD_USER,
691
695
  };
@@ -1077,7 +1081,7 @@ Example flow:
1077
1081
  inputSchema: {
1078
1082
  type: "object",
1079
1083
  properties: {
1080
- company: { type: "string", description: "Filter by company (optional, defaults to HERALD_COMPANY)" },
1084
+ org: { type: "string", description: "Filter by org (optional, defaults to HERALD_ORG)" },
1081
1085
  project: { type: "string", description: "Filter by project (optional)" },
1082
1086
  user: { type: "string", description: "Filter by user (optional)" },
1083
1087
  status: { type: "string", description: "Filter by status: active, archived, or expired (optional)" },
@@ -1412,9 +1416,9 @@ async function fetchPatternsWithCascade() {
1412
1416
  const patterns = [];
1413
1417
  const antipatterns = [];
1414
1418
  const queries = [
1415
- { scope: "user", url: `/api/herald/reflections?company=${HERALD_COMPANY}&project=${HERALD_PROJECT}&user=${HERALD_USER}&limit=100` },
1416
- { scope: "project", url: `/api/herald/reflections?company=${HERALD_COMPANY}&project=${HERALD_PROJECT}&limit=100` },
1417
- { scope: "company", url: `/api/herald/reflections?company=${HERALD_COMPANY}&limit=100` },
1419
+ { scope: "user", url: `/api/herald/reflections?org=${HERALD_ORG}&project=${HERALD_PROJECT}&user=${HERALD_USER}&limit=100` },
1420
+ { scope: "project", url: `/api/herald/reflections?org=${HERALD_ORG}&project=${HERALD_PROJECT}&limit=100` },
1421
+ { scope: "org", url: `/api/herald/reflections?org=${HERALD_ORG}&limit=100` },
1418
1422
  ];
1419
1423
  for (const { scope, url } of queries) {
1420
1424
  try {
@@ -1440,14 +1444,14 @@ async function fetchPatternsWithCascade() {
1440
1444
  // Continue if a level fails
1441
1445
  }
1442
1446
  }
1443
- return { patterns, antipatterns, context: `${HERALD_USER}→${HERALD_PROJECT}→${HERALD_COMPANY}` };
1447
+ return { patterns, antipatterns, context: `${HERALD_USER}→${HERALD_PROJECT}→${HERALD_ORG}` };
1444
1448
  }
1445
1449
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
1446
1450
  const resources = [
1447
1451
  {
1448
1452
  uri: "herald://patterns",
1449
1453
  name: "Herald Learned Patterns",
1450
- description: `Patterns and antipatterns learned from past sessions for ${HERALD_USER}→${HERALD_PROJECT}→${HERALD_COMPANY}. READ THIS AT SESSION START.`,
1454
+ description: `Patterns and antipatterns learned from past sessions for ${HERALD_USER}→${HERALD_PROJECT}→${HERALD_ORG}. READ THIS AT SESSION START.`,
1451
1455
  mimeType: "text/plain",
1452
1456
  },
1453
1457
  {
@@ -1504,7 +1508,7 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
1504
1508
  }
1505
1509
  if (uri === "herald://context") {
1506
1510
  const context = {
1507
- company: HERALD_COMPANY,
1511
+ org: HERALD_ORG,
1508
1512
  project: HERALD_PROJECT,
1509
1513
  user: HERALD_USER,
1510
1514
  vault: HERALD_VAULT || null,
@@ -1536,7 +1540,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1536
1540
  Welcome to Herald - your AI-native interface to CEDA (Cognitive Event-Driven Architecture).
1537
1541
 
1538
1542
  ## Current Context
1539
- - Company: ${HERALD_COMPANY}
1543
+ - Company: ${HERALD_ORG}
1540
1544
  - Project: ${HERALD_PROJECT}
1541
1545
  - User: ${HERALD_USER}
1542
1546
 
@@ -1597,7 +1601,7 @@ Herald will:
1597
1601
  const cloudAvailable = !cedaHealth.error;
1598
1602
  const config = {
1599
1603
  cedaUrl: CEDA_API_URL,
1600
- company: HERALD_COMPANY,
1604
+ org: HERALD_ORG,
1601
1605
  project: HERALD_PROJECT,
1602
1606
  user: HERALD_USER,
1603
1607
  vault: HERALD_VAULT || "(not set)",
@@ -1642,7 +1646,7 @@ Herald will:
1642
1646
  // Update module-level variables directly
1643
1647
  HERALD_USER = newContext.user;
1644
1648
  HERALD_TAGS = newContext.tags;
1645
- HERALD_COMPANY = newContext.tags[0] || "";
1649
+ HERALD_ORG = newContext.tags[0] || "";
1646
1650
  HERALD_PROJECT = newContext.tags[1] || newContext.tags[0] || "";
1647
1651
  TRUST_LEVEL = newContext.trust;
1648
1652
  CONTEXT_SOURCE = newContext.source;
@@ -1653,7 +1657,7 @@ Herald will:
1653
1657
  text: JSON.stringify({
1654
1658
  refreshed: true,
1655
1659
  context: {
1656
- company: HERALD_COMPANY,
1660
+ org: HERALD_ORG,
1657
1661
  project: HERALD_PROJECT,
1658
1662
  user: HERALD_USER,
1659
1663
  tags: HERALD_TAGS,
@@ -1675,7 +1679,7 @@ Herald will:
1675
1679
  type: "text",
1676
1680
  text: JSON.stringify({
1677
1681
  context: {
1678
- company: HERALD_COMPANY,
1682
+ org: HERALD_ORG,
1679
1683
  project: HERALD_PROJECT,
1680
1684
  user: HERALD_USER,
1681
1685
  tags: HERALD_TAGS,
@@ -1823,7 +1827,7 @@ Herald will:
1823
1827
  topic,
1824
1828
  targetVault,
1825
1829
  sourceVault: HERALD_VAULT || undefined,
1826
- company: HERALD_COMPANY,
1830
+ org: HERALD_ORG,
1827
1831
  project: HERALD_PROJECT,
1828
1832
  user: HERALD_USER,
1829
1833
  };
@@ -1835,7 +1839,7 @@ Herald will:
1835
1839
  insight,
1836
1840
  toContext: targetVault || "all", // Required by CEDA, default to broadcast
1837
1841
  topic,
1838
- fromContext: HERALD_VAULT || `${HERALD_COMPANY}/${HERALD_PROJECT}`,
1842
+ fromContext: HERALD_VAULT || `${HERALD_ORG}/${HERALD_PROJECT}`,
1839
1843
  });
1840
1844
  // Check if API returned an error
1841
1845
  if (result.error) {
@@ -1916,12 +1920,29 @@ Herald will:
1916
1920
  const failed = [];
1917
1921
  for (const item of buffer) {
1918
1922
  try {
1919
- const result = await callCedaAPI("/api/herald/insight", "POST", {
1920
- insight: item.insight,
1921
- topic: item.topic,
1922
- toContext: item.targetVault || "all", // CEDA expects toContext, default to "all"
1923
- fromContext: item.sourceVault, // CEDA expects fromContext
1924
- });
1923
+ let result;
1924
+ // CEDA-100: Route based on buffer item type
1925
+ if (item.type === "reflection") {
1926
+ // Reflections go to /api/herald/reflect (stored in PlanetScale, shown in dashboard)
1927
+ result = await callCedaAPI("/api/herald/reflect", "POST", {
1928
+ session: item.session || item.insight,
1929
+ feeling: item.feeling || "success",
1930
+ insight: item.insight,
1931
+ method: item.method || "direct",
1932
+ org: item.org,
1933
+ project: item.project,
1934
+ user: item.user,
1935
+ });
1936
+ }
1937
+ else {
1938
+ // Insights (default) go to /api/herald/insight (legacy behavior)
1939
+ result = await callCedaAPI("/api/herald/insight", "POST", {
1940
+ insight: item.insight,
1941
+ topic: item.topic,
1942
+ toContext: item.targetVault || "all",
1943
+ fromContext: item.sourceVault,
1944
+ });
1945
+ }
1925
1946
  if (result.error) {
1926
1947
  failed.push(item);
1927
1948
  }
@@ -1972,7 +1993,7 @@ Herald will:
1972
1993
  const status = args?.status;
1973
1994
  const limit = args?.limit;
1974
1995
  const params = new URLSearchParams();
1975
- params.set("company", company || HERALD_COMPANY);
1996
+ params.set("company", company || HERALD_ORG);
1976
1997
  if (project)
1977
1998
  params.set("project", project);
1978
1999
  if (user)
@@ -2097,17 +2118,22 @@ Herald will:
2097
2118
  feeling,
2098
2119
  insight: sanitizedInsight, // Sanitized - no PII/secrets transmitted
2099
2120
  method: "direct", // Track capture method for meta-learning
2100
- company: HERALD_COMPANY,
2121
+ org: HERALD_ORG,
2101
2122
  project: HERALD_PROJECT,
2102
2123
  user: HERALD_USER,
2103
2124
  vault: HERALD_VAULT || undefined,
2104
2125
  });
2105
2126
  if (result.error) {
2106
2127
  // If cloud fails, store locally for later processing (also sanitized)
2128
+ // CEDA-100: Mark as reflection type for proper sync routing
2107
2129
  bufferInsight({
2108
- insight: `[REFLECT:${feeling}] ${sanitizedInsight} | Context: ${sanitizedSession}`,
2130
+ insight: sanitizedInsight,
2131
+ session: sanitizedSession,
2132
+ feeling,
2133
+ method: "direct",
2134
+ type: "reflection",
2109
2135
  topic: feeling === "stuck" ? "antipattern" : "pattern",
2110
- company: HERALD_COMPANY,
2136
+ org: HERALD_ORG,
2111
2137
  project: HERALD_PROJECT,
2112
2138
  user: HERALD_USER,
2113
2139
  });
@@ -2139,7 +2165,7 @@ Herald will:
2139
2165
  ? `Antipattern captured: "${insight}"`
2140
2166
  : `Pattern captured: "${insight}"`,
2141
2167
  context: {
2142
- company: HERALD_COMPANY,
2168
+ org: HERALD_ORG,
2143
2169
  project: HERALD_PROJECT,
2144
2170
  tags: HERALD_TAGS,
2145
2171
  trust: TRUST_LEVEL,
@@ -2152,10 +2178,15 @@ Herald will:
2152
2178
  }
2153
2179
  catch (error) {
2154
2180
  // Network error - buffer locally (sanitized)
2181
+ // CEDA-100: Mark as reflection type for proper sync routing
2155
2182
  bufferInsight({
2156
- insight: `[REFLECT:${feeling}] ${sanitizedInsight} | Context: ${sanitizedSession}`,
2183
+ insight: sanitizedInsight,
2184
+ session: sanitizedSession,
2185
+ feeling,
2186
+ method: "direct",
2187
+ type: "reflection",
2157
2188
  topic: feeling === "stuck" ? "antipattern" : "pattern",
2158
- company: HERALD_COMPANY,
2189
+ org: HERALD_ORG,
2159
2190
  project: HERALD_PROJECT,
2160
2191
  user: HERALD_USER,
2161
2192
  });
@@ -2191,11 +2222,12 @@ Herald will:
2191
2222
  return true;
2192
2223
  }).map(item => ({ ...item, scope }));
2193
2224
  };
2194
- // Cascade queries: user (most specific) project company (broadest)
2225
+ // CEDA-95: Cascade queries with minLevel=1 to only return graduated patterns (not observations)
2226
+ // Observations (level 0) are raw captures; patterns (level 1+) are validated
2195
2227
  const queries = [
2196
- { scope: "user", url: `/api/herald/reflections?company=${HERALD_COMPANY}&project=${HERALD_PROJECT}&user=${HERALD_USER}&limit=100` },
2197
- { scope: "project", url: `/api/herald/reflections?company=${HERALD_COMPANY}&project=${HERALD_PROJECT}&limit=100` },
2198
- { scope: "company", url: `/api/herald/reflections?company=${HERALD_COMPANY}&limit=100` },
2228
+ { scope: "user", url: `/api/herald/reflections?org=${HERALD_ORG}&project=${HERALD_PROJECT}&user=${HERALD_USER}&limit=100&minLevel=1` },
2229
+ { scope: "project", url: `/api/herald/reflections?org=${HERALD_ORG}&project=${HERALD_PROJECT}&limit=100&minLevel=1` },
2230
+ { scope: "org", url: `/api/herald/reflections?org=${HERALD_ORG}&limit=100&minLevel=1` },
2199
2231
  ];
2200
2232
  const patterns = [];
2201
2233
  const antipatterns = [];
@@ -2215,7 +2247,7 @@ Herald will:
2215
2247
  const metaResult = await callCedaAPI("/api/herald/meta-patterns");
2216
2248
  const metaPatterns = metaResult.metaPatterns || [];
2217
2249
  // Build readable summary with scope indicators
2218
- let summary = `## Learned Patterns for ${HERALD_USER}→${HERALD_PROJECT}→${HERALD_COMPANY}\n\n`;
2250
+ let summary = `## Learned Patterns for ${HERALD_USER}→${HERALD_PROJECT}→${HERALD_ORG}\n\n`;
2219
2251
  if (antipatterns.length > 0) {
2220
2252
  summary += `### ⚠️ Antipatterns (avoid these)\n`;
2221
2253
  antipatterns.forEach((ap, i) => {
@@ -2244,7 +2276,7 @@ Herald will:
2244
2276
  summary += `Recommended capture method: ${meta.recommendedMethod} (${(meta.confidence * 100).toFixed(0)}% confidence)\n`;
2245
2277
  }
2246
2278
  if (patterns.length === 0 && antipatterns.length === 0) {
2247
- summary = `No patterns learned yet for ${HERALD_USER}→${HERALD_PROJECT}→${HERALD_COMPANY}.\n\nCapture patterns with "herald reflect" or "herald simulate" when you notice friction or flow.`;
2279
+ summary = `No patterns learned yet for ${HERALD_USER}→${HERALD_PROJECT}→${HERALD_ORG}.\n\nCapture patterns with "herald reflect" or "herald simulate" when you notice friction or flow.`;
2248
2280
  }
2249
2281
  return {
2250
2282
  content: [{
@@ -2328,17 +2360,22 @@ Herald will:
2328
2360
  outcome: extracted.outcome,
2329
2361
  reinforcement: sanitizedReinforcement,
2330
2362
  warning: sanitizedWarning,
2331
- company: HERALD_COMPANY,
2363
+ org: HERALD_ORG,
2332
2364
  project: HERALD_PROJECT,
2333
2365
  user: HERALD_USER,
2334
2366
  vault: HERALD_VAULT || undefined,
2335
2367
  });
2336
2368
  if (result.error) {
2337
2369
  // Cloud failed but we have AI extraction - buffer with enriched data (sanitized)
2370
+ // CEDA-100: Mark as reflection type for proper sync routing
2338
2371
  bufferInsight({
2339
- insight: `[SIMULATE:${feeling}] Signal: ${sanitizedSignal} | Insight: ${simSanitizedInsight} | ${extracted.outcome === "pattern" ? `Reinforce: ${sanitizedReinforcement}` : `Warn: ${sanitizedWarning}`}`,
2372
+ insight: simSanitizedInsight,
2373
+ session: simSanitizedSession,
2374
+ feeling,
2375
+ method: "simulation",
2376
+ type: "reflection",
2340
2377
  topic: extracted.outcome,
2341
- company: HERALD_COMPANY,
2378
+ org: HERALD_ORG,
2342
2379
  project: HERALD_PROJECT,
2343
2380
  user: HERALD_USER,
2344
2381
  });
@@ -2446,7 +2483,7 @@ Herald will:
2446
2483
  patternText,
2447
2484
  outcome,
2448
2485
  helped: outcome === "helped",
2449
- company: HERALD_COMPANY,
2486
+ org: HERALD_ORG,
2450
2487
  project: HERALD_PROJECT,
2451
2488
  user: HERALD_USER,
2452
2489
  });
@@ -2497,7 +2534,7 @@ Herald will:
2497
2534
  insight,
2498
2535
  scope,
2499
2536
  topic,
2500
- sourceCompany: HERALD_COMPANY,
2537
+ sourceCompany: HERALD_ORG,
2501
2538
  sourceProject: HERALD_PROJECT,
2502
2539
  sourceUser: HERALD_USER,
2503
2540
  sourceVault: HERALD_VAULT || undefined,
@@ -2568,7 +2605,7 @@ Herald will:
2568
2605
  patternId,
2569
2606
  sessionId,
2570
2607
  all: deleteAll,
2571
- company: HERALD_COMPANY,
2608
+ org: HERALD_ORG,
2572
2609
  project: HERALD_PROJECT,
2573
2610
  user: HERALD_USER,
2574
2611
  });
@@ -2592,7 +2629,7 @@ Herald will:
2592
2629
  message = `All patterns from session ${sessionId} deleted`;
2593
2630
  }
2594
2631
  else if (deleteAll) {
2595
- message = `All patterns for ${HERALD_COMPANY}/${HERALD_PROJECT}/${HERALD_USER} deleted`;
2632
+ message = `All patterns for ${HERALD_ORG}/${HERALD_PROJECT}/${HERALD_USER} deleted`;
2596
2633
  }
2597
2634
  return {
2598
2635
  content: [{
@@ -2622,7 +2659,7 @@ Herald will:
2622
2659
  case "herald_export": {
2623
2660
  const format = args?.format || "json";
2624
2661
  try {
2625
- const result = await callCedaAPI(`/api/herald/export?company=${HERALD_COMPANY}&project=${HERALD_PROJECT}&user=${HERALD_USER}&format=${format}`);
2662
+ const result = await callCedaAPI(`/api/herald/export?org=${HERALD_ORG}&project=${HERALD_PROJECT}&user=${HERALD_USER}&format=${format}`);
2626
2663
  if (result.error) {
2627
2664
  return {
2628
2665
  content: [{
@@ -2643,7 +2680,7 @@ Herald will:
2643
2680
  message: `Data exported in ${format.toUpperCase()} format (GDPR Art. 20)`,
2644
2681
  gdprArticle: "Article 20 - Right to Data Portability",
2645
2682
  format,
2646
- context: `${HERALD_COMPANY}/${HERALD_PROJECT}/${HERALD_USER}`,
2683
+ context: `${HERALD_ORG}/${HERALD_PROJECT}/${HERALD_USER}`,
2647
2684
  ...result,
2648
2685
  }, null, 2)
2649
2686
  }],
@@ -2734,7 +2771,7 @@ async function verifyWithCeda() {
2734
2771
  const ctx = result.context;
2735
2772
  VERIFIED_CONTEXT = {
2736
2773
  verified: true,
2737
- company: ctx.company,
2774
+ org: (ctx.org || ctx.company),
2738
2775
  project: ctx.project,
2739
2776
  trust: ctx.trust,
2740
2777
  tags: ctx.tags,
@@ -2743,7 +2780,7 @@ async function verifyWithCeda() {
2743
2780
  TRUST_LEVEL = VERIFIED_CONTEXT.trust || 'HIGH';
2744
2781
  PROPAGATES = true;
2745
2782
  CONTEXT_SOURCE = 'verified';
2746
- console.error(`[Herald] Verified with CEDA: ${VERIFIED_CONTEXT.company}/${VERIFIED_CONTEXT.project} (trust: HIGH)`);
2783
+ console.error(`[Herald] Verified with CEDA: ${VERIFIED_CONTEXT.org}/${VERIFIED_CONTEXT.project} (trust: HIGH)`);
2747
2784
  }
2748
2785
  else {
2749
2786
  // Not verified - user not registered or no access to this repo
@@ -2794,7 +2831,7 @@ async function runMCP() {
2794
2831
  console.error(`User: ${HERALD_USER} | Tags: [${HERALD_TAGS.join(", ")}]`);
2795
2832
  console.error(`Trust: ${TRUST_LEVEL} (${CONTEXT_SOURCE})${PROPAGATES ? " | Propagates: YES" : ""}`);
2796
2833
  if (VERIFIED_CONTEXT?.verified) {
2797
- console.error(`Context: ${VERIFIED_CONTEXT.company}/${VERIFIED_CONTEXT.project} (server-verified)`);
2834
+ console.error(`Context: ${VERIFIED_CONTEXT.org}/${VERIFIED_CONTEXT.project} (server-verified)`);
2798
2835
  }
2799
2836
  // Send startup heartbeat for visibility (non-blocking)
2800
2837
  sendStartupHeartbeat();