@yottagraph-app/aether-instructions 1.1.42 → 1.1.43

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 (37) hide show
  1. package/AGENTS.md +12 -30
  2. package/README.md +13 -9
  3. package/commands/build_my_app.md +7 -8
  4. package/commands/deploy_agent.md +7 -7
  5. package/commands/update_branding.md +1 -1
  6. package/commands/update_instructions.md +25 -17
  7. package/package.json +2 -4
  8. package/skills/aether/SKILL.md +57 -0
  9. package/{rules/agents-data.mdc → skills/aether/agents-data.md} +3 -6
  10. package/{rules/agents.mdc → skills/aether/agents.md} +42 -28
  11. package/{rules/architecture.mdc → skills/aether/architecture.md} +14 -20
  12. package/{rules/branding.mdc → skills/aether/branding.md} +7 -12
  13. package/{rules/cookbook-data.mdc → skills/aether/cookbook-data.md} +13 -28
  14. package/{rules/cookbook.mdc → skills/aether/cookbook.md} +2 -9
  15. package/{rules/cursor-cloud.mdc → skills/aether/cursor-cloud.md} +1 -6
  16. package/{rules/data.mdc → skills/aether/data.md} +80 -70
  17. package/{rules/deployment.mdc → skills/aether/deployment.md} +1 -6
  18. package/{rules/design.mdc → skills/aether/design.md} +1 -6
  19. package/{rules/env.mdc → skills/aether/env.md} +0 -5
  20. package/{rules/git-support.mdc → skills/aether/git-support.md} +4 -9
  21. package/{rules/instructions_warning.mdc → skills/aether/instructions_warning.md} +6 -12
  22. package/{rules/local-setup.mdc → skills/aether/local-setup.md} +1 -6
  23. package/{rules/mcp-servers.mdc → skills/aether/mcp-servers.md} +3 -7
  24. package/{rules/pref.mdc → skills/aether/pref.md} +9 -14
  25. package/skills/aether/server-data.md +48 -0
  26. package/skills/aether/server.md +60 -0
  27. package/{rules/something-broke.mdc → skills/aether/something-broke.md} +3 -7
  28. package/{rules/server.mdc → skills/aether/storage.md} +78 -108
  29. package/{rules/ui.mdc → skills/aether/ui.md} +2 -6
  30. package/skills/elemental-mcp-patterns/SKILL.md +57 -51
  31. package/variants/mcp-only/commands/build_my_app.md +6 -6
  32. package/variants/mcp-only/{rules/agents-data.mdc → skills/aether/agents-data.md} +0 -6
  33. package/variants/mcp-only/{rules/cookbook-data.mdc → skills/aether/cookbook-data.md} +3 -6
  34. package/variants/mcp-only/{rules/data.mdc → skills/aether/data.md} +1 -6
  35. package/variants/mcp-only/{rules/server-data.mdc → skills/aether/server-data.md} +9 -15
  36. package/rules/server-data.mdc +0 -54
  37. package/rules/storage.mdc +0 -54
@@ -1,15 +1,10 @@
1
- ---
2
- description: "Project structure, navigation patterns, data architecture, server routes, agents, MCP servers. Read when adding pages, navigation, or server-side functionality."
3
- alwaysApply: false
4
- ---
5
-
6
1
  # Aether Architecture
7
2
 
8
3
  Aether is an app framework built on Nuxt 3 + Vue 3 + Vuetify 3 + TypeScript. It follows standard Nuxt conventions -- pages in `pages/`, components in `components/`, composables in `composables/`, server routes in `server/api/`.
9
4
 
10
5
  **Tech stack**: Nuxt 3 (SPA), Vue 3 Composition API (`<script setup>`), Vuetify 3, TypeScript (required), Auth0 (automatic).
11
6
 
12
- **Data source**: This app runs on the Lovelace platform (entities, news, filings, sentiment, relationships, events). See the `data` rule for how your app accesses that data. Do not call external APIs for data the platform provides.
7
+ **Data source**: This app runs on the Lovelace platform (entities, news, filings, sentiment, relationships, events). See [data.md](data.md) in this skill for how your app accesses that data. Do not call external APIs for data the platform provides.
13
8
 
14
9
  ## Project Structure
15
10
 
@@ -26,13 +21,13 @@ mcp-servers/ # MCP servers (Python, deploy to Cloud Run)
26
21
 
27
22
  ## Data Architecture
28
23
 
29
- | Store | Purpose | When to use |
30
- |---|---|---|
31
- | Platform data (Query Server / Postgres per your architecture) | Lovelace knowledge graph or synced local data | See the `data` rule |
32
- | KV (Upstash Redis) | User preferences, lightweight state | Settings, watchlists, UI state that should persist |
33
- | Neon Postgres | App-specific relational data | Custom tables, complex queries (if provisioned — see the `storage` rule for how to check) |
24
+ | Store | Purpose | When to use |
25
+ | ------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------- |
26
+ | Platform data (Query Server / Postgres per your architecture) | Lovelace knowledge graph or synced local data | See [data.md](data.md) |
27
+ | KV (Upstash Redis) | User preferences, lightweight state | Settings, watchlists, UI state that should persist |
28
+ | Neon Postgres | App-specific relational data | Custom tables, complex queries (if provisioned — see [storage.md](storage.md) for how to check) |
34
29
 
35
- See the `storage` rule to check which stores are available, then `pref` (client-side KV) and `server` (Neon usage) for detailed patterns.
30
+ See [storage.md](storage.md) for backend selection and server-side usage (both KV and Neon Postgres), plus [pref.md](pref.md) for the client-side `Pref<T>` pattern.
36
31
 
37
32
  ## Adding Pages
38
33
 
@@ -115,8 +110,8 @@ Use server routes when you need to proxy external APIs (avoid CORS), access
115
110
  data server-side, or keep secrets off the client. Call them from client code
116
111
  with `$fetch('/api/my-data/fetch')`.
117
112
 
118
- See the `server` rule for file-routing conventions and Neon Postgres patterns.
119
- See `server-data` when calling the platform Query Server from server routes.
113
+ See [server.md](server.md) for file-routing conventions and [storage.md](storage.md) for Neon Postgres patterns.
114
+ See [server-data.md](server-data.md) when calling the platform Query Server from server routes.
120
115
 
121
116
  ## Beyond the UI: Agents, MCP Servers, and Server Routes
122
117
 
@@ -124,7 +119,7 @@ Aether apps are more than just a Nuxt SPA. The project contains three additional
124
119
 
125
120
  ### `agents/` -- ADK Agents (Python)
126
121
 
127
- Each subdirectory is a self-contained Python agent that deploys to Vertex AI Agent Engine. See the `agents` cursor rule for development patterns. Agents are deployed via the Broadchurch Portal UI or the `/deploy_agent` Cursor command, both of which trigger `deploy-agent.yml`. Use the `useAgentChat` composable to build a chat UI that talks to them.
122
+ Each subdirectory is a self-contained Python agent that deploys to Vertex AI Agent Engine. See [agents.md](agents.md) for development patterns. Agents are deployed via the Broadchurch Portal UI or the `/deploy_agent` Cursor command, both of which trigger `deploy-agent.yml`. Use the `useAgentChat` composable to build a chat UI that talks to them.
128
123
 
129
124
  **Agent query path:** The app talks to Agent Engine directly — the portal is
130
125
  only in the auth path. The flow is:
@@ -142,7 +137,7 @@ project detail page for IAM health status.
142
137
 
143
138
  ### `mcp-servers/` -- MCP Servers (Python)
144
139
 
145
- Each subdirectory is a FastMCP server that deploys to Cloud Run. See the `mcp-servers` cursor rule. Deployed via Portal UI or `/deploy_mcp`, triggering `deploy-mcp.yml`. Agents can connect to MCP servers as tool providers.
140
+ Each subdirectory is a FastMCP server that deploys to Cloud Run. See [mcp-servers.md](mcp-servers.md). Deployed via Portal UI or `/deploy_mcp`, triggering `deploy-mcp.yml`. Agents can connect to MCP servers as tool providers.
146
141
 
147
142
  ### `broadchurch.yaml`
148
143
 
@@ -157,11 +152,10 @@ Use these to build whatever UI fits the app:
157
152
  local Nitro streaming route (`/api/agent/:agentId/stream`) which calls
158
153
  Agent Engine directly with a tenant SA token. Handles streaming, session
159
154
  management, and response parsing. Shows clear error messages when IAM
160
- permissions are missing. See the `agents` cursor rule for details.
155
+ permissions are missing. See [agents.md](agents.md) for details.
161
156
  - **`useTenantConfig()`** -- Fetch the tenant's runtime config (deployed
162
157
  agents, feature flags, MCP servers) from the Portal Gateway.
163
158
  - **`useElementalClient()`** -- When using the Elemental API from the client,
164
- see the `data` rule.
159
+ see [data.md](data.md).
165
160
  - **`usePrefsStore()` / `Pref<T>`** -- KV-backed user preferences. See
166
- the `pref` rule.
167
-
161
+ [pref.md](pref.md).
@@ -1,8 +1,3 @@
1
- ---
2
- description: Apply when working on visual styling, colors, typography, theming, branding, or UI appearance.
3
- alwaysApply: false
4
- ---
5
-
6
1
  # Lovelace Branding
7
2
 
8
3
  The `lovelace-branding` skill (`skills/lovelace-branding/`) is the single source of truth for all brand specifics -- colors, typography, patterns, assets, and usage guidelines. Read the skill before making branding decisions. Start with `SKILL.md` for the file index.
@@ -15,13 +10,13 @@ Single dark theme. No light mode, no theme switching.
15
10
 
16
11
  These files are project-owned. Consult the branding skill for the values and patterns they should implement.
17
12
 
18
- | File | Role |
19
- |------|------|
20
- | `assets/brand-globals.css` | `:root` CSS variables and global typography/layout |
21
- | `assets/fonts.css` | `@font-face` declarations |
22
- | `assets/theme-styles.css` | Theme-aware CSS utility classes |
23
- | `composables/useLovelaceTheme.ts` | Theme color palette and Vuetify theme activation |
24
- | `composables/useThemeClasses.ts` | Theme-aware class combination utilities |
13
+ | File | Role |
14
+ | --------------------------------- | -------------------------------------------------- |
15
+ | `assets/brand-globals.css` | `:root` CSS variables and global typography/layout |
16
+ | `assets/fonts.css` | `@font-face` declarations |
17
+ | `assets/theme-styles.css` | Theme-aware CSS utility classes |
18
+ | `composables/useLovelaceTheme.ts` | Theme color palette and Vuetify theme activation |
19
+ | `composables/useThemeClasses.ts` | Theme-aware class combination utilities |
25
20
 
26
21
  ## Integration
27
22
 
@@ -1,17 +1,12 @@
1
- ---
2
- description: "Data-fetching UI recipes: entity search, news feed, filings, gateway helpers. Read with the `data` rule when building pages that use the Query Server or platform data."
3
- alwaysApply: false
4
- ---
5
-
6
1
  # Data-fetching cookbook
7
2
 
8
- Copy-paste patterns that call the Elemental API, gateway, or helpers. For platform API details see the `data` rule. Pure UI patterns (tables, forms, charts) are in the `cookbook` rule.
3
+ Copy-paste patterns that call the Elemental API, gateway, or helpers. For platform API details see [data.md](data.md) in this skill. Pure UI patterns (tables, forms, charts) are in [cookbook.md](cookbook.md).
9
4
 
10
5
  ## 1. Entity Search Page
11
6
 
12
7
  Search for entities by name and display results. Uses `$fetch` directly
13
8
  because `POST /entities/search` (batch name resolution with scored ranking)
14
- is not wrapped by the generated `useElementalClient()` — see the `data` rule.
9
+ is not wrapped by the generated `useElementalClient()` — see [data.md](data.md).
15
10
 
16
11
  ```vue
17
12
  <template>
@@ -182,8 +177,8 @@ for runtime flavor/PID discovery and `buildGatewayUrl()` for gateway access.
182
177
  const vals = valueMap.get(neid) ?? {};
183
178
  return {
184
179
  neid,
185
- name: namePid ? (vals[namePid] as string) ?? neid : neid,
186
- sentiment: sentimentPid ? (vals[sentimentPid] as number) ?? null : null,
180
+ name: namePid ? ((vals[namePid] as string) ?? neid) : neid,
181
+ sentiment: sentimentPid ? ((vals[sentimentPid] as number) ?? null) : null,
187
182
  };
188
183
  });
189
184
  } catch (e: any) {
@@ -215,12 +210,7 @@ Simpler version of recipe #1 using the pre-built `searchEntities()` helper.
215
210
  {{ error }}
216
211
  </v-alert>
217
212
  <v-list v-if="results.length" class="mt-4">
218
- <v-list-item
219
- v-for="r in results"
220
- :key="r.neid"
221
- :title="r.name"
222
- :subtitle="r.neid"
223
- />
213
+ <v-list-item v-for="r in results" :key="r.neid" :title="r.name" :subtitle="r.neid" />
224
214
  </v-list>
225
215
  <v-empty-state
226
216
  v-else-if="searched && !loading"
@@ -266,7 +256,7 @@ properties are then fetched via `useElementalClient()`.
266
256
  **Important:** For graph-layer entities (person, organization, location),
267
257
  use `findEntities` with a `linked` expression. For property-layer entities
268
258
  (documents, filings, articles), use `getPropertyValues` with the
269
- relationship PID. See the `data` rule for the two-layer architecture.
259
+ relationship PID. See [data.md](data.md) for the two-layer architecture.
270
260
 
271
261
  ```vue
272
262
  <template>
@@ -366,7 +356,7 @@ relationship PID. See the `data` rule for the two-layer architecture.
366
356
  });
367
357
 
368
358
  const docNeids = (propRes.values ?? []).map((v: any) =>
369
- String(v.value).padStart(20, '0'),
359
+ String(v.value).padStart(20, '0')
370
360
  );
371
361
 
372
362
  function getEntityNameUrl(neid: string) {
@@ -379,15 +369,14 @@ relationship PID. See the `data` rule for the two-layer architecture.
379
369
  const names = await Promise.all(
380
370
  docNeids.map(async (neid: string) => {
381
371
  try {
382
- const res = await $fetch<{ name: string }>(
383
- getEntityNameUrl(neid),
384
- { headers: { 'X-Api-Key': getApiKey() } },
385
- );
372
+ const res = await $fetch<{ name: string }>(getEntityNameUrl(neid), {
373
+ headers: { 'X-Api-Key': getApiKey() },
374
+ });
386
375
  return res.name || neid;
387
376
  } catch {
388
377
  return neid;
389
378
  }
390
- }),
379
+ })
391
380
  );
392
381
 
393
382
  filings.value = docNeids.map((neid: string, i: number) => ({
@@ -430,11 +419,7 @@ Type-ahead search that shows results in a dropdown as the user types. Uses
430
419
  @click:clear="onClear"
431
420
  />
432
421
 
433
- <v-card
434
- v-if="showMenu && suggestions.length > 0"
435
- class="search-dropdown"
436
- elevation="8"
437
- >
422
+ <v-card v-if="showMenu && suggestions.length > 0" class="search-dropdown" elevation="8">
438
423
  <v-list density="compact">
439
424
  <v-list-item
440
425
  v-for="item in suggestions"
@@ -457,7 +442,7 @@ Type-ahead search that shows results in a dropdown as the user types. Uses
457
442
  icon?: string;
458
443
  flavors?: string[];
459
444
  }>(),
460
- { label: 'Search', icon: 'mdi-magnify', flavors: undefined },
445
+ { label: 'Search', icon: 'mdi-magnify', flavors: undefined }
461
446
  );
462
447
 
463
448
  const emit = defineEmits<{
@@ -1,13 +1,8 @@
1
- ---
2
- description: "Copy-paste UI patterns for common pages: data table, form, chart, dialog, master-detail. For Query Server / data-fetching recipes see `cookbook-data`."
3
- alwaysApply: false
4
- ---
5
-
6
1
  # UI Pattern Cookbook
7
2
 
8
3
  Copy-paste patterns using the project's actual composables and Vuetify components. Adapt to your needs.
9
4
 
10
- **Data-fetching recipes** (entity search, news feed, filings, gateway helpers) live in the `cookbook-data` rule.
5
+ **Data-fetching recipes** (entity search, news feed, filings, gateway helpers) live in [cookbook-data.md](cookbook-data.md).
11
6
 
12
7
  ## 2. Data Table Page
13
8
 
@@ -98,9 +93,7 @@ Form with field validation, submit handler, and user feedback.
98
93
  variant="outlined"
99
94
  class="mb-3"
100
95
  />
101
- <v-btn type="submit" color="primary" :loading="saving" :disabled="!valid">
102
- Save
103
- </v-btn>
96
+ <v-btn type="submit" color="primary" :loading="saving" :disabled="!valid"> Save </v-btn>
104
97
  </v-form>
105
98
  </v-container>
106
99
  </template>
@@ -1,8 +1,3 @@
1
- ---
2
- description: Cursor Cloud environment quirks (Node managed by env, dev server auto-started, skip browser testing during initial setup). Apply when the environment check in AGENTS.md indicates Cursor Cloud ($HOME under /root or /home/ubuntu, or a dev-server terminal was auto-started), or when the user mentions Cursor Cloud.
3
- alwaysApply: false
4
- ---
5
-
6
1
  If you are in Cursor Cloud, the `environment.json` install step runs
7
2
  `init-project.js` and `npm install` automatically, and starts a dev server
8
3
  on port 3000.
@@ -59,4 +54,4 @@ check) and `npm run format:check` (Prettier). See Verification Commands.
59
54
 
60
55
  **Before committing:** always run `npm run format` — the husky pre-commit
61
56
  hook runs `lint-staged` with `prettier --check` and will reject
62
- unformatted files.
57
+ unformatted files.
@@ -1,7 +1,3 @@
1
- ---
2
- description: "Data access via Elemental API: client usage, schema discovery, entity search, API gotchas, MCP servers. Read when building features that fetch or display data from the Query Server."
3
- alwaysApply: false
4
- ---
5
1
  # Data — Elemental API (platform data source)
6
2
 
7
3
  **This app is built on the Lovelace platform.** The Query Server is the
@@ -81,10 +77,10 @@ Test those with curl before implementing them in code.
81
77
  The gateway proxy authenticates on your behalf — no Auth0 tokens needed.
82
78
  Read `broadchurch.yaml` for the three values you need:
83
79
 
84
- | YAML path | Purpose |
85
- |---|---|
86
- | `gateway.url` | Portal Gateway base URL |
87
- | `tenant.org_id` | Your tenant ID (path segment) |
80
+ | YAML path | Purpose |
81
+ | -------------------- | ------------------------------------ |
82
+ | `gateway.url` | Portal Gateway base URL |
83
+ | `tenant.org_id` | Your tenant ID (path segment) |
88
84
  | `gateway.qs_api_key` | API key (sent as `X-Api-Key` header) |
89
85
 
90
86
  Build the request URL as `{gateway.url}/api/qs/{tenant.org_id}/{endpoint}`
@@ -141,9 +137,9 @@ Elemental API patterns. **Use these instead of writing from scratch:**
141
137
 
142
138
  ```typescript
143
139
  const { flavors, properties, flavorByName, pidByName, refresh } = useElementalSchema();
144
- await refresh(); // fetches once, then cached
145
- const articleFid = flavorByName('article'); // → string | null
146
- const namePid = pidByName('name'); // → string | null
140
+ await refresh(); // fetches once, then cached
141
+ const articleFid = flavorByName('article'); // → string | null
142
+ const namePid = pidByName('name'); // → string | null
147
143
  ```
148
144
 
149
145
  Handles the dual response shapes (`res.schema.flavors` vs `res.flavors`)
@@ -152,14 +148,20 @@ and the `fid`/`findex` naming inconsistency automatically.
152
148
  ### `utils/elementalHelpers` — Gateway URL Helpers
153
149
 
154
150
  ```typescript
155
- import { buildGatewayUrl, getApiKey, padNeid, searchEntities, getEntityName } from '~/utils/elementalHelpers';
156
-
157
- const url = buildGatewayUrl('entities/search'); // full gateway URL
158
- const key = getApiKey(); // from runtimeConfig
159
- const neid = padNeid('4926132345040704022'); // → "04926132345040704022"
151
+ import {
152
+ buildGatewayUrl,
153
+ getApiKey,
154
+ padNeid,
155
+ searchEntities,
156
+ getEntityName,
157
+ } from '~/utils/elementalHelpers';
158
+
159
+ const url = buildGatewayUrl('entities/search'); // full gateway URL
160
+ const key = getApiKey(); // from runtimeConfig
161
+ const neid = padNeid('4926132345040704022'); // → "04926132345040704022"
160
162
 
161
163
  const results = await searchEntities('Microsoft'); // batch name search
162
- const name = await getEntityName(neid); // display name lookup
164
+ const name = await getEntityName(neid); // display name lookup
163
165
  ```
164
166
 
165
167
  ## Client Usage
@@ -174,7 +176,10 @@ const client = useElementalClient();
174
176
 
175
177
  const schema = await client.getSchema();
176
178
  const entities = await client.findEntities({
177
- expression: JSON.stringify({ type: 'comparison', comparison: { operator: 'string_like', pid: 8, value: 'Apple' } }),
179
+ expression: JSON.stringify({
180
+ type: 'comparison',
181
+ comparison: { operator: 'string_like', pid: 8, value: 'Apple' },
182
+ }),
178
183
  limit: 5,
179
184
  });
180
185
  ```
@@ -185,8 +190,8 @@ All methods return data directly and throw on non-2xx responses.
185
190
 
186
191
  **Entity search and lookup:**
187
192
 
188
- | Method | Signature | Purpose |
189
- |---|---|---|
193
+ | Method | Signature | Purpose |
194
+ | -------------- | -------------------------- | --------------------------------------- |
190
195
  | `findEntities` | `(body: FindEntitiesBody)` | Expression-based search (see `find.md`) |
191
196
 
192
197
  > **Entity search**: Use `findEntities()` with `string_like` on the name PID
@@ -201,25 +206,25 @@ All methods return data directly and throw on non-2xx responses.
201
206
 
202
207
  **Properties and schema:**
203
208
 
204
- | Method | Signature | Purpose |
205
- |---|---|---|
206
- | `getSchema` | `()` | All entity types (flavors) and properties (PIDs) |
209
+ | Method | Signature | Purpose |
210
+ | ------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------ |
211
+ | `getSchema` | `()` | All entity types (flavors) and properties (PIDs) |
207
212
  | `getPropertyValues` | `(body: { eids: string, pids: string })` | Property values (eids: JSON array of NEID strings; pids: JSON array of numeric PIDs) |
208
- | `summarizeProperty` | `(pid: number)` | Summary stats for a property |
213
+ | `summarizeProperty` | `(pid: number)` | Summary stats for a property |
209
214
 
210
215
  **Relationships and graph:**
211
216
 
212
- | Method | Signature | Purpose |
213
- |---|---|---|
217
+ | Method | Signature | Purpose |
218
+ | -------------- | -------------------------------- | ------------------------------------------------------------ |
214
219
  | `findEntities` | `(body: { expression, limit? })` | Find linked entities via `linked` expression (see `find.md`) |
215
220
 
216
221
  **Other:**
217
222
 
218
- | Method | Signature | Purpose |
219
- |---|---|---|
220
- | `getHealth` | `()` | Health check |
221
- | `getStatus` | `()` | Server status and capabilities |
222
- | `adaMessage` | `(body: AdaMessageBody)` | Ada AI chat |
223
+ | Method | Signature | Purpose |
224
+ | ------------ | ------------------------ | ------------------------------ |
225
+ | `getHealth` | `()` | Health check |
226
+ | `getStatus` | `()` | Server status and capabilities |
227
+ | `adaMessage` | `(body: AdaMessageBody)` | Ada AI chat |
223
228
 
224
229
  ## Discovery-First Pattern
225
230
 
@@ -230,16 +235,16 @@ types or property names. Instead, discover them at runtime:
230
235
  1. **Get the schema** — `client.getSchema()` returns all entity types (flavors)
231
236
  and properties (PIDs) available in the system. See `schema.md`.
232
237
 
233
- The schema response contains:
234
- - **Flavors** (entity types): Company, Person, GovernmentOrg, etc.
235
- Each flavor has a numeric ID and a human-readable name.
236
- - **PIDs** (properties): name, country, industry, lei_code, etc.
237
- Each PID has a type (`data_str`, `data_int`, `data_nindex`, etc.).
238
- - Properties with type `data_nindex` are references to other entities —
239
- resolve them with another `getPropertyValues` call.
238
+ The schema response contains:
239
+ - **Flavors** (entity types): Company, Person, GovernmentOrg, etc.
240
+ Each flavor has a numeric ID and a human-readable name.
241
+ - **PIDs** (properties): name, country, industry, lei_code, etc.
242
+ Each PID has a type (`data_str`, `data_int`, `data_nindex`, etc.).
243
+ - Properties with type `data_nindex` are references to other entities —
244
+ resolve them with another `getPropertyValues` call.
240
245
 
241
- Use flavor names in `findEntities()` expressions and PID names in
242
- `getPropertyValues()`.
246
+ Use flavor names in `findEntities()` expressions and PID names in
247
+ `getPropertyValues()`.
243
248
 
244
249
  2. **Search with expressions** — `client.findEntities()` uses a JSON expression
245
250
  language to search by type, property value, or relationship. See `find.md`.
@@ -269,10 +274,10 @@ For reliable agent behavior, prefer typed semantics over string heuristics:
269
274
 
270
275
  There are two schema endpoints with **different response shapes**:
271
276
 
272
- | Endpoint | Flavors at | Flavor ID field | Detail level |
273
- |----------|-----------|-----------------|--------------|
274
- | `GET /schema` | top-level (`res.flavors`) | `findex` | Rich (display names, units, domains) |
275
- | `GET /elemental/metadata/schema` | nested (`res.schema.flavors`) | `fid` | Basic (name + type only) |
277
+ | Endpoint | Flavors at | Flavor ID field | Detail level |
278
+ | -------------------------------- | ----------------------------- | --------------- | ------------------------------------ |
279
+ | `GET /schema` | top-level (`res.flavors`) | `findex` | Rich (display names, units, domains) |
280
+ | `GET /elemental/metadata/schema` | nested (`res.schema.flavors`) | `fid` | Basic (name + type only) |
276
281
 
277
282
  The TypeScript client's `getSchema()` calls `/elemental/metadata/schema`,
278
283
  so the response nests data under `.schema`. The generated types may suggest
@@ -296,12 +301,12 @@ The flavor identifier has **different field names** depending on the endpoint:
296
301
  Same value, different key. Always use a fallback:
297
302
 
298
303
  ```typescript
299
- const articleFlavor = flavors.find(f => f.name === 'article');
304
+ const articleFlavor = flavors.find((f) => f.name === 'article');
300
305
  // Always use String() — safe for small IDs (12) and required for large ones
301
306
  const articleFid = String(articleFlavor?.fid ?? articleFlavor?.findex ?? '');
302
307
 
303
308
  // When building a FID lookup map:
304
- const fidMap = new Map(flavors.map(f => [String(f.fid ?? f.findex), f.name]));
309
+ const fidMap = new Map(flavors.map((f) => [String(f.fid ?? f.findex), f.name]));
305
310
  ```
306
311
 
307
312
  The `is_type` expression in `/elemental/find` always uses the `fid` key
@@ -352,14 +357,14 @@ const filingNeid = String(res.values[0].value).padStart(20, '0'); // "0492613234
352
357
  ```typescript
353
358
  // WRONG — PIDs are numbers, not strings:
354
359
  const values = await client.getPropertyValues({
355
- eids: JSON.stringify(['00416400910670863867']),
356
- pids: JSON.stringify(['name', 'country', 'industry']), // FAILS
360
+ eids: JSON.stringify(['00416400910670863867']),
361
+ pids: JSON.stringify(['name', 'country', 'industry']), // FAILS
357
362
  });
358
363
 
359
364
  // CORRECT — use numeric PIDs from getSchema():
360
365
  const values = await client.getPropertyValues({
361
- eids: JSON.stringify(['00416400910670863867']),
362
- pids: JSON.stringify([8, 313]), // 8=name, 313=country (from schema)
366
+ eids: JSON.stringify(['00416400910670863867']),
367
+ pids: JSON.stringify([8, 313]), // 8=name, 313=country (from schema)
363
368
  });
364
369
  ```
365
370
 
@@ -409,7 +414,7 @@ const res = await client.getPropertyValues({
409
414
  const docNeids = (res.values ?? []).map((v) => String(v.value).padStart(20, '0'));
410
415
  ```
411
416
 
412
- See the **cookbook-data** rule for a full "Get filings for a company" recipe.
417
+ See [cookbook-data.md](cookbook-data.md) in this skill for a full "Get filings for a company" recipe.
413
418
 
414
419
  ### Expression language pitfalls
415
420
 
@@ -455,14 +460,17 @@ source-specific schemas.
455
460
  `getPropertyValues()` with the relationship PID. Values are entity IDs
456
461
  that must be zero-padded to 20 characters.
457
462
 
458
- See the **cookbook-data** rule (news feed recipe) for a full example.
463
+ See [cookbook-data.md](cookbook-data.md) (news feed recipe) for a full example.
459
464
 
460
465
  ## Error Handling
461
466
 
462
467
  ```typescript
463
468
  try {
464
469
  const data = await client.findEntities({
465
- expression: JSON.stringify({ type: 'comparison', comparison: { operator: 'string_like', pid: 8, value: 'Apple' } }),
470
+ expression: JSON.stringify({
471
+ type: 'comparison',
472
+ comparison: { operator: 'string_like', pid: 8, value: 'Apple' },
473
+ }),
466
474
  limit: 5,
467
475
  });
468
476
  } catch (error) {
@@ -479,7 +487,9 @@ functions instead:
479
487
  import { getArticle } from '@yottagraph-app/elemental-api/client';
480
488
 
481
489
  const response = await getArticle(artid);
482
- if (response.status === 404) { /* handle not found */ }
490
+ if (response.status === 404) {
491
+ /* handle not found */
492
+ }
483
493
  ```
484
494
 
485
495
  ## Lovelace MCP Servers
@@ -490,25 +500,25 @@ data exploration. **Check your tool list** — if tools like
490
500
  exploration interface before writing code. If they don't appear, the
491
501
  servers aren't connected; use curl and the skill docs instead.
492
502
 
493
- | Server | What it provides |
494
- |---|---|
495
- | `lovelace-elemental` | Knowledge Graph: entities, relationships, events, sentiment, schema discovery |
496
- | `lovelace-stocks` | Stock/financial market data |
497
- | `lovelace-wiki` | Wikipedia entity enrichment |
498
- | `lovelace-polymarket` | Prediction market data |
503
+ | Server | What it provides |
504
+ | --------------------- | ----------------------------------------------------------------------------- |
505
+ | `lovelace-elemental` | Knowledge Graph: entities, relationships, events, sentiment, schema discovery |
506
+ | `lovelace-stocks` | Stock/financial market data |
507
+ | `lovelace-wiki` | Wikipedia entity enrichment |
508
+ | `lovelace-polymarket` | Prediction market data |
499
509
 
500
510
  ### MCP Tool Quick Reference
501
511
 
502
- | Tool | Purpose | Use to verify... |
503
- |---|---|---|
504
- | `elemental_get_schema` | Discover entity types (flavors), properties, and relationships | Flavor IDs, property IDs, data types |
505
- | `elemental_get_entity` | Look up entity by name or NEID; returns properties | Entity resolution, property shapes |
506
- | `elemental_get_related` | Related entities with type/relationship filters | Relationship types and traversal |
507
- | `elemental_get_relationships` | Relationship types and counts between two entities | Edge types between specific entities |
508
- | `elemental_graph_neighborhood` | Most influential neighbors of an entity | Graph connectivity |
509
- | `elemental_graph_sentiment` | Sentiment analysis from news articles | Sentiment data availability |
510
- | `elemental_get_events` | Events for an entity or by search query | Event categories and shapes |
511
- | `elemental_health` | Health check | Server connectivity |
512
+ | Tool | Purpose | Use to verify... |
513
+ | ------------------------------ | -------------------------------------------------------------- | ------------------------------------ |
514
+ | `elemental_get_schema` | Discover entity types (flavors), properties, and relationships | Flavor IDs, property IDs, data types |
515
+ | `elemental_get_entity` | Look up entity by name or NEID; returns properties | Entity resolution, property shapes |
516
+ | `elemental_get_related` | Related entities with type/relationship filters | Relationship types and traversal |
517
+ | `elemental_get_relationships` | Relationship types and counts between two entities | Edge types between specific entities |
518
+ | `elemental_graph_neighborhood` | Most influential neighbors of an entity | Graph connectivity |
519
+ | `elemental_graph_sentiment` | Sentiment analysis from news articles | Sentiment data availability |
520
+ | `elemental_get_events` | Events for an entity or by search query | Event categories and shapes |
521
+ | `elemental_health` | Health check | Server connectivity |
512
522
 
513
523
  MCP tools handle entity resolution, PID lookups, and NEID formatting
514
524
  automatically. Use them to discover IDs and verify data exists before
@@ -1,8 +1,3 @@
1
- ---
2
- description: App, agent, and MCP server deployment targets (Vercel, Vertex AI Agent Engine, Cloud Run). Apply when pushing to main, running /deploy_agent or /deploy_mcp, or explaining how code reaches production.
3
- alwaysApply: false
4
- ---
5
-
6
1
  ### App (Nuxt UI + server routes)
7
2
 
8
3
  Vercel auto-deploys on every push to `main`. Preview deployments are created for
@@ -16,4 +11,4 @@ the Portal UI or `/deploy_agent` in Cursor.
16
11
  ### MCP Servers (`mcp-servers/`)
17
12
 
18
13
  Each subdirectory in `mcp-servers/` is a Python FastMCP server. Deploy via
19
- the Portal UI or `/deploy_mcp` in Cursor.
14
+ the Portal UI or `/deploy_mcp` in Cursor.
@@ -1,8 +1,3 @@
1
- ---
2
- description: "DESIGN.md workflow, feature docs, starter app is placeholder. Read when starting work, planning features, or updating project design."
3
- alwaysApply: false
4
- ---
5
-
6
1
  # Design
7
2
 
8
3
  Read `DESIGN.md` before starting any work. It is the source of truth for project vision, architecture, and current implementation status.
@@ -58,4 +53,4 @@ If the user is implementing a change that has no feature doc, encourage them to
58
53
 
59
54
  **Exception for initial app builds:** When building a new app from scratch via `/build_my_app`, skip per-page feature docs. They add overhead during greenfield builds where the entire app is being created at once. Start using feature docs once the initial app is built and you're iterating on individual features.
60
55
 
61
- It is a good practice to close out one feature doc and start a new one as the focus of the work shifts. It is acceptable to be working with multiple feature docs at once, if the user is working on multiple unconnected or loosely connected features. The sections of the feature doc are flexible and you should add or remove sections to fit the needs of the project.
56
+ It is a good practice to close out one feature doc and start a new one as the focus of the work shifts. It is acceptable to be working with multiple feature docs at once, if the user is working on multiple unconnected or loosely connected features. The sections of the feature doc are flexible and you should add or remove sections to fit the needs of the project.
@@ -1,8 +1,3 @@
1
- ---
2
- description: .env variable reference (APP_ID, USER_NAME, QUERY_SERVER_ADDRESS, etc.). Apply when adding env vars, configuring Auth0 bypass, or inspecting runtime config.
3
- alwaysApply: false
4
- ---
5
-
6
1
  | Variable | Purpose | Default |
7
2
  | ---------------------------------- | -------------------------------- | --------------------------------------- |
8
3
  | `NUXT_PUBLIC_APP_ID` | Unique app identifier | derived from directory name |
@@ -1,11 +1,6 @@
1
- ---
2
- description: "Git commit workflow and conventions. Apply when finishing implementation work, making commits, or troubleshooting git/pre-commit failures."
3
- alwaysApply: false
4
- ---
5
-
6
1
  # Git Workflow
7
2
 
8
- This rule applies both when an agent is committing its own work and when helping a user commit theirs.
3
+ This guidance applies both when an agent is committing its own work and when helping a user commit theirs.
9
4
 
10
5
  ## Committing
11
6
 
@@ -14,9 +9,9 @@ Commit when you finish a meaningful unit of work — a feature, a fix, a refacto
14
9
  ### Steps
15
10
 
16
11
  1. **Run formatting first** — this is required or the commit will fail:
17
- ```bash
18
- npm run format
19
- ```
12
+ ```bash
13
+ npm run format
14
+ ```
20
15
  2. **Stage all files** — always use `git add -A`.
21
16
  3. **Commit** with the message format below.
22
17
  4. **Verify the commit succeeded** with `git status`. If it failed, see Pre-commit Failure Troubleshooting below. Do not proceed until the commit is confirmed.