@yottagraph-app/aether-instructions 1.1.21 → 1.1.22

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 (2) hide show
  1. package/package.json +1 -1
  2. package/rules/api.mdc +109 -49
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yottagraph-app/aether-instructions",
3
- "version": "1.1.21",
3
+ "version": "1.1.22",
4
4
  "description": "Cursor rules, commands, and skills for Aether development",
5
5
  "files": [
6
6
  "rules",
package/rules/api.mdc CHANGED
@@ -28,13 +28,32 @@ For Lovelace **entity types, properties, relationships, and per-source schemas**
28
28
 
29
29
  ## Test Before You Build
30
30
 
31
- **ALWAYS test API calls via curl before writing code that depends on them.**
32
- This is not optional — the Elemental API has response shapes that differ from
33
- what the TypeScript types suggest, and assumptions about nesting, property
34
- formats, and field names will be wrong without testing. This applies doubly
35
- to server-side code, where you can't inspect responses in the browser console.
31
+ **ALWAYS test data access before writing application code.** The Elemental
32
+ API has response shapes that differ from what the TypeScript types suggest,
33
+ and assumptions about nesting, property formats, and field names will be
34
+ wrong without testing.
36
35
 
37
- ### How to test
36
+ ### Step 1: MCP tools (interactive exploration)
37
+
38
+ **If MCP tools appear in your tool list, start here.** MCP handles entity
39
+ resolution, PID lookups, and NEID formatting automatically — use it to
40
+ verify what data exists and how it's structured.
41
+
42
+ ```
43
+ elemental_get_schema() → list all entity types
44
+ elemental_get_schema(flavor="article") → properties for a type
45
+ elemental_get_entity(entity="Apple") → resolve + fetch entity
46
+ elemental_get_related(entity="Apple",
47
+ related_flavor="person") → follow relationships
48
+ ```
49
+
50
+ MCP tells you the correct flavor IDs, property IDs, and data shapes. Use
51
+ these to inform your REST implementation.
52
+
53
+ ### Step 2: curl (verify exact request/response shapes)
54
+
55
+ MCP doesn't cover every REST endpoint (e.g. `/elemental/find` expressions).
56
+ Test those with curl before implementing them in code.
38
57
 
39
58
  The gateway proxy authenticates on your behalf — no Auth0 tokens needed.
40
59
  Read `broadchurch.yaml` for the three values you need:
@@ -48,8 +67,6 @@ Read `broadchurch.yaml` for the three values you need:
48
67
  Build the request URL as `{gateway.url}/api/qs/{tenant.org_id}/{endpoint}`
49
68
  and include the header `X-Api-Key: {gateway.qs_api_key}`.
50
69
 
51
- ### Example calls
52
-
53
70
  ```bash
54
71
  # Variables — read these from broadchurch.yaml
55
72
  GW="https://broadchurch-portal-194773164895.us-central1.run.app"
@@ -62,6 +79,13 @@ curl -s "$GW/api/qs/$ORG/entities/search" \
62
79
  -H "X-Api-Key: $KEY" \
63
80
  -d '{"queries":[{"queryId":1,"query":"Microsoft"}],"maxResults":3}'
64
81
 
82
+ # Test a find expression
83
+ curl -s -X POST "$GW/api/qs/$ORG/elemental/find" \
84
+ -H "X-Api-Key: $KEY" \
85
+ -H "Content-Type: application/x-www-form-urlencoded" \
86
+ --data-urlencode 'expression={"type":"is_type","is_type":{"fid":12}}' \
87
+ --data-urlencode 'limit=5'
88
+
65
89
  # Get entity properties (form-encoded)
66
90
  curl -s -X POST "$GW/api/qs/$ORG/elemental/entities/properties" \
67
91
  -H "X-Api-Key: $KEY" \
@@ -74,6 +98,14 @@ curl -s -X POST "$GW/api/qs/$ORG/elemental/entities/properties" \
74
98
  `application/x-www-form-urlencoded` with JSON-stringified parameter values.
75
99
  All other endpoints accept `application/json`.
76
100
 
101
+ **Interpreting errors:** 400 = expression syntax is wrong. 500 = expression
102
+ is valid but the query failed (wrong PID, unsupported operator for that
103
+ property type). 200 + empty `eids` = query worked but no results match.
104
+
105
+ ### Step 3: Implement with confidence
106
+
107
+ Now write your composable or server route, knowing the exact API shapes.
108
+
77
109
  ## Client Usage
78
110
 
79
111
  All API calls go through `useElementalClient()` from `@yottagraph-app/elemental-api/client`.
@@ -163,26 +195,46 @@ knowledge of what's in the graph.
163
195
 
164
196
  ## API Gotchas
165
197
 
166
- ### `getSchema()` response is nested WILL crash if you don't handle it
198
+ ### `getSchema()` response structure differs by endpoint
167
199
 
168
- The generated TypeScript types suggest `response.properties` and
169
- `response.flavors` exist at the top level. **They don't.** The API nests
170
- them under `response.schema`. This mismatch between types and reality
171
- causes `Cannot read properties of undefined` every time.
200
+ There are two schema endpoints with **different response shapes**:
201
+
202
+ | Endpoint | Flavors at | Flavor ID field | Detail level |
203
+ |----------|-----------|-----------------|--------------|
204
+ | `GET /schema` | top-level (`res.flavors`) | `findex` | Rich (display names, units, domains) |
205
+ | `GET /elemental/metadata/schema` | nested (`res.schema.flavors`) | `fid` | Basic (name + type only) |
206
+
207
+ The TypeScript client's `getSchema()` calls `/elemental/metadata/schema`,
208
+ so the response nests data under `.schema`. The generated types may suggest
209
+ top-level access, but it won't work at runtime.
172
210
 
173
211
  ```typescript
174
- // WRONG — will crash at runtime despite TypeScript compiling fine:
212
+ // WRONG — will crash (data is nested under .schema):
175
213
  const res = await client.getSchema();
176
214
  const props = res.properties; // undefined!
177
215
 
178
- // CORRECT — always access through .schema:
216
+ // CORRECT — always use fallback to handle both shapes:
179
217
  const res = await client.getSchema();
180
218
  const properties = res.schema?.properties ?? (res as any).properties ?? [];
181
219
  const flavors = res.schema?.flavors ?? (res as any).flavors ?? [];
182
220
  ```
183
221
 
184
- The `(res as any).properties` fallback is there in case the API is ever
185
- fixed to match the types. Use this pattern every time.
222
+ ### Flavor ID field: `fid` vs `findex`
223
+
224
+ The flavor identifier has **different field names** depending on the endpoint:
225
+ `GET /schema` returns `findex`, `/elemental/metadata/schema` returns `fid`.
226
+ Same value, different key. Always use a fallback:
227
+
228
+ ```typescript
229
+ const articleFlavor = flavors.find(f => f.name === 'article');
230
+ const articleFid = articleFlavor?.fid ?? articleFlavor?.findex ?? null;
231
+
232
+ // When building a FID lookup map:
233
+ const fidMap = new Map(flavors.map(f => [f.fid ?? f.findex, f.name]));
234
+ ```
235
+
236
+ The `is_type` expression in `/elemental/find` always uses the `fid` key
237
+ regardless of which schema endpoint provided the value.
186
238
 
187
239
  ### Relationship property values need zero-padding to form valid NEIDs
188
240
 
@@ -273,6 +325,23 @@ const docNeids = (res.values ?? []).map((v) => String(v.value).padStart(20, '0')
273
325
 
274
326
  See the **cookbook** rule for a full "Get filings for a company" recipe.
275
327
 
328
+ ### Expression language pitfalls
329
+
330
+ These mistakes come up repeatedly when building `/elemental/find` queries:
331
+
332
+ - **Entity type filtering**: Use `is_type` (not `comparison` with pid=0).
333
+ `comparison` requires `pid != 0`.
334
+ - **`string_like` is name-only**: Only works on the name property (PID 8).
335
+ Use `eq` for exact matches on other string properties.
336
+ - **Boolean combinators**: Use `{"type": "and", "and": [...]}` — not
337
+ `conjunction` or any other name.
338
+ - **`lt`/`gt` are numeric-only**: Only work on `data_int` and `data_float`
339
+ properties.
340
+ - **`regex` is not implemented**: Will return an error.
341
+
342
+ Read the "Common Mistakes" section in the **elemental-api skill** (`find.md`)
343
+ for examples of each.
344
+
276
345
  ### Entity Search
277
346
 
278
347
  Use `client.findEntities()` (`POST /elemental/find`) for entity search.
@@ -327,17 +396,13 @@ const response = await getArticle(artid);
327
396
  if (response.status === 404) { /* handle not found */ }
328
397
  ```
329
398
 
330
- ## Lovelace MCP Servers (Optional)
331
-
332
- Four MCP servers **may** be configured in `.cursor/mcp.json` for interactive
333
- data exploration. They are NOT required — the REST client
334
- (`useElementalClient()`) and skill docs cover the same data and are the
335
- primary path for building features.
399
+ ## Lovelace MCP Servers
336
400
 
337
- **Before referencing MCP tools, check your available tool list.** If tools
338
- like `elemental_get_schema` don't appear in your MCP server list, the
339
- servers aren't connected just use the REST client and skill docs instead.
340
- Do not report this as a problem; it's a normal configuration state.
401
+ Four MCP servers may be configured in `.cursor/mcp.json` for interactive
402
+ data exploration. **Check your tool list** if tools like
403
+ `elemental_get_schema` appear, use them as your primary testing and
404
+ exploration interface before writing code. If they don't appear, the
405
+ servers aren't connected; use curl and the skill docs instead.
341
406
 
342
407
  | Server | What it provides |
343
408
  |---|---|
@@ -346,6 +411,23 @@ Do not report this as a problem; it's a normal configuration state.
346
411
  | `lovelace-wiki` | Wikipedia entity enrichment |
347
412
  | `lovelace-polymarket` | Prediction market data |
348
413
 
414
+ ### MCP Tool Quick Reference
415
+
416
+ | Tool | Purpose | Use to verify... |
417
+ |---|---|---|
418
+ | `elemental_get_schema` | Discover entity types (flavors), properties, and relationships | Flavor IDs, property IDs, data types |
419
+ | `elemental_get_entity` | Look up entity by name or NEID; returns properties | Entity resolution, property shapes |
420
+ | `elemental_get_related` | Related entities with type/relationship filters | Relationship types and traversal |
421
+ | `elemental_get_relationships` | Relationship types and counts between two entities | Edge types between specific entities |
422
+ | `elemental_graph_neighborhood` | Most influential neighbors of an entity | Graph connectivity |
423
+ | `elemental_graph_sentiment` | Sentiment analysis from news articles | Sentiment data availability |
424
+ | `elemental_get_events` | Events for an entity or by search query | Event categories and shapes |
425
+ | `elemental_health` | Health check | Server connectivity |
426
+
427
+ MCP tools handle entity resolution, PID lookups, and NEID formatting
428
+ automatically. Use them to discover IDs and verify data exists before
429
+ building REST-based features with `useElementalClient()`.
430
+
349
431
  ### Setup
350
432
 
351
433
  `.cursor/mcp.json` is auto-generated by `init-project.js`. If it's missing,
@@ -353,25 +435,3 @@ run `node init-project.js --local` to regenerate it. For provisioned projects,
353
435
  the servers route through the Portal Gateway proxy (no credentials needed).
354
436
  For local development without a gateway, the servers require an
355
437
  `AUTH0_M2M_DEV_TOKEN` environment variable.
356
-
357
- These servers are also accessible from the browser through the Portal
358
- Gateway, so you can build MCP tool exploration UIs if needed.
359
-
360
- ### When MCP Servers Are Available
361
-
362
- If the MCP tools appear in your tool list, you can use them for interactive
363
- exploration alongside the REST client:
364
-
365
- | Tool | Purpose |
366
- |---|---|
367
- | `elemental_get_schema` | Discover entity types (flavors), properties, and relationships |
368
- | `elemental_get_entity` | Look up entity by name or NEID; returns properties |
369
- | `elemental_get_related` | Related entities with type/relationship filters |
370
- | `elemental_get_relationships` | Relationship types and counts between two entities |
371
- | `elemental_graph_neighborhood` | Most influential neighbors of an entity |
372
- | `elemental_graph_sentiment` | Sentiment analysis from news articles |
373
- | `elemental_get_events` | Events for an entity or by search query |
374
- | `elemental_health` | Health check |
375
-
376
- MCP is convenient for schema discovery and entity resolution during planning.
377
- For building UI features, always use the REST client (`useElementalClient()`).