Skip to content

Commit 5acae41

Browse files
Skiipy11claude
andcommitted
docs: use generic example names in specs, plans, and tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2de1198 commit 5acae41

7 files changed

Lines changed: 63 additions & 63 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Born from a production setup where [OpenClaw](https://github.com/openclaw/opencl
3737
### What Was New in v2.2
3838

3939
- **Noise-Free Entity Extraction** — v2.2 filters out CSS properties, code identifiers, shell commands, sentence fragments, French prose, and generic phrases. Pattern-based filtering with 50+ generic noun/adjective blocklists. Includes a retroactive cleanup script (`scripts/cleanup-garbage-entities.js`) to purge existing noise.
40-
- **Per-Client Knowledge Base** — Fingerprint-based client identification with accent normalization. One tool call (`brain_client`) returns everything known about a client: brand, strategy, meetings, content, technical details, relationships. Fuzzy name resolution ("JL" resolves to "jetloans").
40+
- **Per-Client Knowledge Base** — Fingerprint-based client identification with accent normalization. One tool call (`brain_client`) returns everything known about a client: brand, strategy, meetings, content, technical details, relationships. Fuzzy name resolution ("AL" resolves to "acme-loans").
4141
- **Gemini Embedding 2** — Task-type-aware embeddings at 3072 dimensions. Uses `RETRIEVAL_DOCUMENT` for storage, `RETRIEVAL_QUERY` for search. Matryoshka support for flexible dimensionality (3072/1536/768).
4242
- **Import/Export** — Full backup and migration support. Export all memories as JSON, import with automatic deduplication. Never lose data when switching embedding providers again.
4343
- **Webhook Notifications** — Real-time dispatch when memories are stored, superseded, or deleted. Fire-and-forget to any HTTP endpoint.

api/tests/client-resolver.test.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,40 @@ describe('ClientResolver', () => {
88
before(() => {
99
resolver = new ClientResolver();
1010
resolver.loadFingerprints([
11-
{ client_id: 'jetloans', fingerprints: { aliases: ['JL', 'Jet Loans'], people: ['Brandon'], domains: ['jetloans.ca'], keywords: ['Granby'] } },
12-
{ client_id: 'credit-instant', fingerprints: { aliases: ['Credit Instant', 'CI'], people: ['Brandon'], domains: ['creditinstant.com'], keywords: ['Quebec City'] } },
13-
{ client_id: 'biolistix', fingerprints: { aliases: ['Bio'], people: ['Dominique'], domains: ['biolistix.ca'], keywords: [] } },
11+
{ client_id: 'acme-loans', fingerprints: { aliases: ['AL', 'Acme Loans'], people: ['Alex'], domains: ['acme-loans.ca'], keywords: ['Springfield'] } },
12+
{ client_id: 'quickcredit', fingerprints: { aliases: ['QuickCredit', 'QC'], people: ['Alex'], domains: ['quickcredit.com'], keywords: ['Riverside'] } },
13+
{ client_id: 'greenlife', fingerprints: { aliases: ['GL'], people: ['Jordan'], domains: ['greenlife.ca'], keywords: [] } },
1414
]);
1515
});
1616

1717
it('should resolve by alias', () => {
18-
assert.strictEqual(resolver.resolve('Talked to JL about their SEO strategy'), 'jetloans');
18+
assert.strictEqual(resolver.resolve('Talked to AL about their SEO strategy'), 'acme-loans');
1919
});
2020

2121
it('should resolve by domain', () => {
22-
assert.strictEqual(resolver.resolve('Updated jetloans.ca homepage'), 'jetloans');
22+
assert.strictEqual(resolver.resolve('Updated acme-loans.ca homepage'), 'acme-loans');
2323
});
2424

2525
it('should resolve by person + context', () => {
26-
assert.strictEqual(resolver.resolve('Brandon called about Granby store'), 'jetloans');
26+
assert.strictEqual(resolver.resolve('Alex called about Springfield store'), 'acme-loans');
2727
});
2828

2929
it('should return null when below threshold', () => {
3030
assert.strictEqual(resolver.resolve('Had a meeting today about loans'), null);
3131
});
3232

3333
it('should return array for multi-client content', () => {
34-
const result = resolver.resolve('Discussed jetloans.ca redesign and Biolistix supplement strategy');
34+
const result = resolver.resolve('Discussed acme-loans.ca redesign and GreenLife supplement strategy');
3535
assert.ok(Array.isArray(result));
36-
assert.ok(result.includes('jetloans'));
37-
assert.ok(result.includes('biolistix'));
36+
assert.ok(result.includes('acme-loans'));
37+
assert.ok(result.includes('greenlife'));
3838
});
3939

4040
it('should be case-insensitive', () => {
41-
assert.strictEqual(resolver.resolve('JETLOANS website is down'), 'jetloans');
41+
assert.strictEqual(resolver.resolve('ACME-LOANS website is down'), 'acme-loans');
4242
});
4343

4444
it('should handle accented characters', () => {
45-
assert.strictEqual(resolver.resolve('Crédit Instant needs new landing page for Québec City'), 'credit-instant');
45+
assert.strictEqual(resolver.resolve('QuickCrédit needs new landing page for Riverside'), 'quickcredit');
4646
});
4747
});

api/tests/entities.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ describe('extractEntities — domains', () => {
8080
});
8181

8282
it('extracts domain names', () => {
83-
const text = 'Deployed to expertlocal.ca and checked acme-corp.com';
83+
const text = 'Deployed to localagency.ca and checked acme-corp.com';
8484
const entities = extractEntities(text, 'global', 'test');
8585
const domains = entities.filter(e => e.type === 'domain');
8686
const names = domains.map(e => e.name);
87-
assert.ok(names.includes('expertlocal.ca'));
87+
assert.ok(names.includes('localagency.ca'));
8888
assert.ok(names.includes('acme-corp.com'));
8989
});
9090

@@ -169,8 +169,8 @@ describe('extractEntities — alias cache', () => {
169169
});
170170

171171
it('addToAliasCache makes new aliases resolvable', () => {
172-
addToAliasCache('morpheus', 99, 'Morpheus Server', 'system');
173-
const text = 'Deployed update to Morpheus overnight';
172+
addToAliasCache('test-server', 99, 'Test Server', 'system');
173+
const text = 'Deployed update to Test Server overnight';
174174
const entities = extractEntities(text, 'global', 'test');
175175
// Morpheus should resolve — check alias cache was used
176176
// (It'll match as technology "Morpheus" since it's not in KNOWN_TECH,

api/tests/notifications.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import { buildNotificationPayload } from '../src/services/notifications.js';
55
describe('notifications', () => {
66
it('should build memory_stored payload with correct structure', () => {
77
const payload = buildNotificationPayload('memory_stored', {
8-
id: 'test-id', type: 'fact', client_id: 'jetloans',
8+
id: 'test-id', type: 'fact', client_id: 'acme-loans',
99
knowledge_category: 'strategy', content: 'x'.repeat(300),
1010
source_agent: 'claude-code', importance: 'high', created_at: '2026-03-20T00:00:00Z',
1111
});
1212
assert.strictEqual(payload.event, 'memory_stored');
1313
assert.strictEqual(payload.memory.id, 'test-id');
1414
assert.strictEqual(payload.memory.type, 'fact');
1515
assert.ok(payload.memory.content_preview.length <= 200);
16-
assert.strictEqual(payload.memory.client_id, 'jetloans');
16+
assert.strictEqual(payload.memory.client_id, 'acme-loans');
1717
});
1818

1919
it('should default missing fields', () => {

docs/superpowers/plans/2026-03-20-shared-brain-v2.md

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -86,42 +86,42 @@ describe('ClientResolver', () => {
8686
before(() => {
8787
resolver = new ClientResolver();
8888
resolver.loadFingerprints([
89-
{ client_id: 'jetloans', fingerprints: { aliases: ['JL', 'Jet Loans'], people: ['Brandon'], domains: ['jetloans.ca'], keywords: ['Granby'] } },
90-
{ client_id: 'credit-instant', fingerprints: { aliases: ['Credit Instant', 'CI'], people: ['Brandon'], domains: ['creditinstant.com'], keywords: ['Quebec City'] } },
91-
{ client_id: 'biolistix', fingerprints: { aliases: ['Bio'], people: ['Dominique'], domains: ['biolistix.ca'], keywords: [] } },
89+
{ client_id: 'acme-loans', fingerprints: { aliases: ['AL', 'Acme Loans'], people: ['Alex'], domains: ['acme-loans.ca'], keywords: ['Springfield'] } },
90+
{ client_id: 'quickcredit', fingerprints: { aliases: ['QuickCredit', 'QC'], people: ['Alex'], domains: ['quickcredit.com'], keywords: ['Riverside'] } },
91+
{ client_id: 'greenlife', fingerprints: { aliases: ['GL'], people: ['Jordan'], domains: ['greenlife.ca'], keywords: [] } },
9292
]);
9393
});
9494

9595
it('should resolve by alias', () => {
96-
assert.strictEqual(resolver.resolve('Talked to JL about their SEO strategy'), 'jetloans');
96+
assert.strictEqual(resolver.resolve('Talked to AL about their SEO strategy'), 'acme-loans');
9797
});
9898

9999
it('should resolve by domain', () => {
100-
assert.strictEqual(resolver.resolve('Updated jetloans.ca homepage'), 'jetloans');
100+
assert.strictEqual(resolver.resolve('Updated acme-loans.ca homepage'), 'acme-loans');
101101
});
102102

103103
it('should resolve by person + context', () => {
104-
// Brandon alone is ambiguous (both jetloans + credit-instant), needs 2nd signal
105-
assert.strictEqual(resolver.resolve('Brandon called about Granby store'), 'jetloans');
104+
// Alex alone is ambiguous (both acme-loans + quickcredit), needs 2nd signal
105+
assert.strictEqual(resolver.resolve('Alex called about Springfield store'), 'acme-loans');
106106
});
107107

108108
it('should return null when below threshold', () => {
109109
assert.strictEqual(resolver.resolve('Had a meeting today about loans'), null);
110110
});
111111

112112
it('should return array for multi-client content', () => {
113-
const result = resolver.resolve('Discussed jetloans.ca redesign and Biolistix supplement strategy');
113+
const result = resolver.resolve('Discussed acme-loans.ca redesign and GreenLife supplement strategy');
114114
assert.ok(Array.isArray(result));
115-
assert.ok(result.includes('jetloans'));
116-
assert.ok(result.includes('biolistix'));
115+
assert.ok(result.includes('acme-loans'));
116+
assert.ok(result.includes('greenlife'));
117117
});
118118

119119
it('should be case-insensitive', () => {
120-
assert.strictEqual(resolver.resolve('JETLOANS website is down'), 'jetloans');
120+
assert.strictEqual(resolver.resolve('ACME-LOANS website is down'), 'acme-loans');
121121
});
122122

123123
it('should handle accented characters', () => {
124-
assert.strictEqual(resolver.resolve('Crédit Instant needs new landing page for Québec City'), 'credit-instant');
124+
assert.strictEqual(resolver.resolve('QuickCrédit needs new landing page for Riverside'), 'quickcredit');
125125
});
126126
});
127127
```
@@ -320,8 +320,8 @@ import assert from 'node:assert';
320320
describe('client route response format', () => {
321321
it('should structure briefing with profile and knowledge sections', () => {
322322
const response = {
323-
client_id: 'jetloans',
324-
profile: { name: 'Jetloans', industry: 'loans' },
323+
client_id: 'acme-loans',
324+
profile: { name: 'Acme Loans', industry: 'loans' },
325325
knowledge: {
326326
brand: [], strategy: [], meeting: [],
327327
content: [], technical: [], relationship: [],
@@ -472,7 +472,7 @@ In `mcp-server/src/index.js`, add to the tools array:
472472
```javascript
473473
{
474474
name: 'brain_client',
475-
description: 'Get everything known about a client — profile, brand, strategy, meetings, content, technical details, relationships. Can also do semantic search within a client\'s memories. Accepts fuzzy names (e.g. "JL" resolves to "jetloans").',
475+
description: 'Get everything known about a client — profile, brand, strategy, meetings, content, technical details, relationships. Can also do semantic search within a client\'s memories. Accepts fuzzy names (e.g. "AL" resolves to "acme-loans").',
476476
inputSchema: {
477477
type: 'object',
478478
properties: {
@@ -668,7 +668,7 @@ import { buildNotificationPayload } from '../src/services/notifications.js';
668668
describe('notifications', () => {
669669
it('should build memory_stored payload', () => {
670670
const payload = buildNotificationPayload('memory_stored', {
671-
id: 'test-id', type: 'fact', client_id: 'jetloans',
671+
id: 'test-id', type: 'fact', client_id: 'acme-loans',
672672
knowledge_category: 'strategy', content: 'Long content here that should be truncated...',
673673
source_agent: 'claude-code', importance: 'high', created_at: '2026-03-20T00:00:00Z',
674674
});
@@ -769,8 +769,8 @@ import assert from 'node:assert';
769769
describe('entity relationships', () => {
770770
it('should detect co-occurring entities', () => {
771771
const entities = [
772-
{ name: 'Jetloans', type: 'client' },
773-
{ name: 'Brandon', type: 'person' },
772+
{ name: 'Acme Loans', type: 'client' },
773+
{ name: 'Alex', type: 'person' },
774774
{ name: 'SEMrush', type: 'technology' },
775775
];
776776
// Each pair should create a relationship
@@ -902,7 +902,7 @@ graphRouter.get('/:entity/html', async (req, res) => {
902902

903903
- [ ] **Step 3: Test manually**
904904

905-
Open `http://192.168.18.40:8084/graph/Jetloans/html` in browser and verify the visualization renders.
905+
Open `http://localhost:8084/graph/Acme Loans/html` in browser and verify the visualization renders.
906906

907907
- [ ] **Step 4: Commit**
908908

@@ -936,7 +936,7 @@ Import `getClientResolver` from `'../services/client-resolver.js'`.
936936

937937
- [ ] **Step 2: Test by storing a memory without client_id that mentions a client**
938938

939-
Use curl or MCP to store a fact with content "Updated Jetloans homepage meta tags for Granby SEO" without providing client_id. Verify it auto-resolves to `jetloans`.
939+
Use curl or MCP to store a fact with content "Updated Acme Loans homepage meta tags for Springfield SEO" without providing client_id. Verify it auto-resolves to `acme-loans`.
940940

941941
- [ ] **Step 3: Commit**
942942

@@ -1045,13 +1045,13 @@ BASEROW_CLIENTS_TABLE_ID=734
10451045
- [ ] **Step 3: Rebuild and restart container**
10461046

10471047
```bash
1048-
ssh beelink "cd ~/shared-brain && docker compose build memory-api && docker compose up -d memory-api"
1048+
ssh server "cd ~/shared-brain && docker compose build memory-api && docker compose up -d memory-api"
10491049
```
10501050

10511051
- [ ] **Step 4: Verify startup logs**
10521052

10531053
```bash
1054-
ssh beelink "docker logs shared-brain-api --tail 20"
1054+
ssh server "docker logs shared-brain-api --tail 20"
10551055
```
10561056
Expected: client resolver loaded, all routes registered, no errors.
10571057

@@ -1061,9 +1061,9 @@ Add `client_fingerprints` field (long text) to table 734 via Baserow UI. Populat
10611061

10621062
- [ ] **Step 6: Test brain_client via MCP**
10631063

1064-
Call `brain_client("jetloans")` — should return a briefing (initially empty knowledge sections until memories are stored with knowledge_category).
1064+
Call `brain_client("acme-loans")` — should return a briefing (initially empty knowledge sections until memories are stored with knowledge_category).
10651065

1066-
Call `brain_client("JL")` — should resolve to jetloans via fingerprints.
1066+
Call `brain_client("AL")` — should resolve to acme-loans via fingerprints.
10671067

10681068
- [ ] **Step 7: Test export/import round-trip**
10691069

@@ -1072,7 +1072,7 @@ Save output, then call `brain_import(data)` — should report all skipped (dupli
10721072

10731073
- [ ] **Step 8: Test graph visualization**
10741074

1075-
Open `http://192.168.18.40:8084/graph/claude-code/html` in browser — should render interactive graph.
1075+
Open `http://localhost:8084/graph/claude-code/html` in browser — should render interactive graph.
10761076

10771077
- [ ] **Step 9: Update local MCP server**
10781078

docs/superpowers/specs/2026-03-20-shared-brain-v2-design.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,20 @@ Each client gets a fingerprint dictionary stored in Baserow table 734 (clients)
2222
**Fingerprint format**:
2323
```json
2424
{
25-
"aliases": ["jetloans", "jet loans", "JL"],
26-
"people": ["Brandon"],
27-
"domains": ["jetloans.ca"],
28-
"keywords": ["Granby", "micro-prets"],
29-
"related_clients": ["credit-instant"]
25+
"aliases": ["acme-loans", "acme loans", "AL"],
26+
"people": ["Alex"],
27+
"domains": ["acme-loans.ca"],
28+
"keywords": ["Springfield", "small-loans"],
29+
"related_clients": ["quickcredit"]
3030
}
3131
```
3232

3333
**Known fingerprints at launch**:
34-
- `jetloans`: aliases [JL, Jet Loans], people [Brandon], domains [jetloans.ca], keywords [Granby]
35-
- `credit-instant`: aliases [Credit Instant, CI], people [Brandon], domains [creditinstant.com], keywords [Quebec City]
36-
- `biolistix`: aliases [Bio], people [Dominique], domains [biolistix.ca]
37-
- `la-canardiere`: aliases [La Canardiere, Canardiere], domains [lacanardiere.com]
38-
- `expert-local`: aliases [EL, Expert Local], people [Steven], domains [expertlocal.ca]
34+
- `acme-loans`: aliases [AL, Acme Loans], people [Alex], domains [acme-loans.ca], keywords [Springfield]
35+
- `quickcredit`: aliases [QuickCredit, QC], people [Alex], domains [quickcredit.com], keywords [Riverside]
36+
- `greenlife`: aliases [GL], people [Jordan], domains [greenlife.ca]
37+
- `riverside-inn`: aliases [Riverside Inn, Riverside], domains [riverside-inn.com]
38+
- `localagency`: aliases [LA, Local Agency], people [Sam], domains [localagency.ca]
3939

4040
**API-side resolver**`resolveClientId(text)`:
4141
1. On startup, fetches all fingerprints from Baserow 734 and caches them
@@ -92,8 +92,8 @@ One-call access to everything known about a client.
9292
4. Return structured response:
9393
```json
9494
{
95-
"client_id": "jetloans",
96-
"profile": { "name": "Jetloans", "industry": "loans", "brand_voice_tone": "helpful", ... },
95+
"client_id": "acme-loans",
96+
"profile": { "name": "Acme Loans", "industry": "loans", "brand_voice_tone": "helpful", ... },
9797
"knowledge": {
9898
"brand": [...],
9999
"strategy": [...],
@@ -119,9 +119,9 @@ The existing Fireflies daily processor workflow (`E:\dev\n8n\fireflies-daily-pro
119119
**A. Fingerprint injection**: Before the LLM extraction node, add a step that fetches fingerprints from the Shared Brain API (new endpoint: `GET /clients/fingerprints`) and formats them into the extraction prompt:
120120
```
121121
Active clients and identifiers:
122-
- jetloans (aliases: JL, Jet Loans | people: Brandon | domains: jetloans.ca)
123-
- credit-instant (aliases: Credit Instant | people: Brandon | domains: creditinstant.com)
124-
- biolistix (aliases: Bio | people: Dominique | domains: biolistix.ca)
122+
- acme-loans (aliases: AL, Acme Loans | people: Alex | domains: acme-loans.ca)
123+
- quickcredit (aliases: QuickCredit | people: Alex | domains: quickcredit.com)
124+
- greenlife (aliases: GL | people: Jordan | domains: greenlife.ca)
125125
...
126126
127127
For each topic/action item, identify which client_id it belongs to.
@@ -148,9 +148,9 @@ If a segment doesn't match any client, use "internal".
148148
"id": "uuid",
149149
"content": "...",
150150
"type": "fact",
151-
"key": "seo-strategy-jetloans",
151+
"key": "seo-strategy-acme-loans",
152152
"subject": null,
153-
"client_id": "jetloans",
153+
"client_id": "acme-loans",
154154
"knowledge_category": "strategy",
155155
"category": "semantic",
156156
"source_agent": "claude-code",
@@ -159,7 +159,7 @@ If a segment doesn't match any client, use "internal".
159159
"access_count": 3,
160160
"active": true,
161161
"superseded_by": null,
162-
"entities": [{"name": "Jetloans", "type": "client"}],
162+
"entities": [{"name": "Acme Loans", "type": "client"}],
163163
"created_at": "2026-03-20T...",
164164
"last_accessed_at": "2026-03-20T..."
165165
}
@@ -213,7 +213,7 @@ WEBHOOK_NOTIFY_URLS=http://n8n.local:5678/webhook/brain-event
213213
"memory": {
214214
"id": "uuid",
215215
"type": "fact",
216-
"client_id": "jetloans",
216+
"client_id": "acme-loans",
217217
"knowledge_category": "strategy",
218218
"content_preview": "First 200 chars...",
219219
"source_agent": "claude-code",

mcp-server/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
286286
},
287287
{
288288
name: 'brain_client',
289-
description: 'Get everything known about a client — brand, strategy, meetings, content, technical details, relationships. Can also do semantic search within a client\'s memories. Accepts fuzzy names (e.g. "JL" resolves to "jetloans").',
289+
description: 'Get everything known about a client — brand, strategy, meetings, content, technical details, relationships. Can also do semantic search within a client\'s memories. Accepts fuzzy names (e.g. "AL" resolves to "acme-loans").',
290290
inputSchema: {
291291
type: 'object',
292292
properties: {

0 commit comments

Comments
 (0)