@yottagraph-app/aether-instructions 1.1.41 → 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 +18 -191
  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} +49 -28
  11. package/{rules/architecture.mdc → skills/aether/architecture.md} +14 -21
  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/skills/aether/cursor-cloud.md +57 -0
  16. package/{rules/data.mdc → skills/aether/data.md} +80 -70
  17. package/skills/aether/deployment.md +14 -0
  18. package/{rules/design.mdc → skills/aether/design.md} +1 -6
  19. package/skills/aether/env.md +10 -0
  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/skills/aether/local-setup.md +15 -0
  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/aether.mdc +0 -21
  37. package/rules/server-data.mdc +0 -54
@@ -1,13 +1,14 @@
1
- ---
2
- description: Rules for developing ADK agents in the agents/ directory
3
- globs: agents/**
4
- alwaysApply: false
5
- ---
6
-
7
1
  # Agent Development (Google ADK)
8
2
 
9
3
  This project supports developing and deploying AI agents alongside the UI. Agents live in the `agents/` directory and deploy to Vertex AI Agent Engine via the `/deploy_agent` command.
10
4
 
5
+ ## Starter agent
6
+
7
+ `agents/example_agent/` is a working starter agent that queries the Elemental
8
+ Knowledge Graph. It includes schema discovery, entity search, property lookup,
9
+ and optional MCP server integration. Use it as a starting point — customize the
10
+ instruction, add tools, and follow the patterns described below.
11
+
11
12
  ## Directory Structure
12
13
 
13
14
  Each agent is a self-contained Python package. **Directory names must use underscores, not hyphens** (ADK uses the directory name as a Python identifier).
@@ -42,14 +43,15 @@ root_agent = Agent(
42
43
  ```
43
44
 
44
45
  Key rules:
46
+
45
47
  - The `agent.py` file MUST export a variable named `root_agent`
46
48
  - Tool functions should have detailed docstrings -- the LLM reads these to understand when and how to use each tool
47
49
  - Use `google-adk` for the agent framework, `httpx` for HTTP calls
48
50
  - Pin dependency versions in `requirements.txt` for reproducible deployments
49
51
 
50
52
  For agents that call the **Elemental API** (`broadchurch_auth`, endpoints,
51
- local `ELEMENTAL_*` env vars), see the `agents-data` rule. For agents
52
- using **Elemental MCP tools**, the `agents-data` rule also covers
53
+ local `ELEMENTAL_*` env vars), see [agents-data.md](agents-data.md) in this skill. For agents
54
+ using **Elemental MCP tools**, [agents-data.md](agents-data.md) also covers
53
55
  `McpToolset` wiring — use `StreamableHTTPConnectionParams` (not
54
56
  `SseConnectionParams`) and read the `elemental-mcp-patterns` skill for
55
57
  response handling patterns.
@@ -153,17 +155,18 @@ The response includes an `agents` array:
153
155
 
154
156
  Each agent entry has:
155
157
 
156
- | Field | Type | Description |
157
- |---|---|---|
158
- | `name` | `string` | Agent directory name (e.g. `filing_analyst`) |
159
- | `display_name` | `string` | Human-readable name for the UI |
160
- | `engine_id` | `string` | Vertex AI Agent Engine resource ID — used as `{agentId}` in query/stream URLs |
158
+ | Field | Type | Description |
159
+ | -------------- | -------- | ----------------------------------------------------------------------------- |
160
+ | `name` | `string` | Agent directory name (e.g. `filing_analyst`) |
161
+ | `display_name` | `string` | Human-readable name for the UI |
162
+ | `engine_id` | `string` | Vertex AI Agent Engine resource ID — used as `{agentId}` in query/stream URLs |
161
163
 
162
164
  The `engine_id` is the key value — it becomes the `{agentId}` path
163
165
  parameter in `/api/agent/{agentId}/stream` (the local Nitro route) and
164
166
  the portal's `/authorize` endpoint.
165
167
 
166
168
  **How agents get populated:** The portal discovers agents from two sources:
169
+
167
170
  1. **Firestore** — agents registered by the deploy workflow (`deploy-agent.yml`
168
171
  calls `POST /api/agents/{tenantId}` to register)
169
172
  2. **Agent Engine API** — the portal also queries Vertex AI for reasoning
@@ -219,9 +222,26 @@ A typical stream for an agent that uses a tool:
219
222
 
220
223
  ```json
221
224
  [
222
- { "content": { "parts": [{ "functionCall": { "name": "search", "args": {"q": "AAPL 8-K"} } }], "role": "model" } },
223
- { "content": { "parts": [{ "functionResponse": { "name": "search", "response": {"results": ["..."]} } }], "role": "tool" } },
224
- { "content": { "parts": [{ "text": "Here is the summary of the 8-K filing..." }], "role": "model" } }
225
+ {
226
+ "content": {
227
+ "parts": [{ "functionCall": { "name": "search", "args": { "q": "AAPL 8-K" } } }],
228
+ "role": "model"
229
+ }
230
+ },
231
+ {
232
+ "content": {
233
+ "parts": [
234
+ { "functionResponse": { "name": "search", "response": { "results": ["..."] } } }
235
+ ],
236
+ "role": "tool"
237
+ }
238
+ },
239
+ {
240
+ "content": {
241
+ "parts": [{ "text": "Here is the summary of the 8-K filing..." }],
242
+ "role": "model"
243
+ }
244
+ }
225
245
  ]
226
246
  ```
227
247
 
@@ -252,13 +272,13 @@ automatically.
252
272
 
253
273
  SSE event types:
254
274
 
255
- | Event | Data Shape | Description |
256
- |---|---|---|
257
- | `text` | `{ "text": "..." }` | Agent text output (replaces previous text) |
258
- | `function_call` | `{ "name": "...", "args": {...} }` | Agent is calling a tool |
259
- | `function_response` | `{ "name": "...", "response": {...} }` | Tool returned a result |
260
- | `error` | `{ "message": "...", "code": "..." }` | Error during processing (`code` is `PERMISSION_DENIED` for IAM failures) |
261
- | `done` | `{ "session_id": "...", "text": "..." }` | Stream complete with final text |
275
+ | Event | Data Shape | Description |
276
+ | ------------------- | ---------------------------------------- | ------------------------------------------------------------------------ |
277
+ | `text` | `{ "text": "..." }` | Agent text output (replaces previous text) |
278
+ | `function_call` | `{ "name": "...", "args": {...} }` | Agent is calling a tool |
279
+ | `function_response` | `{ "name": "...", "response": {...} }` | Tool returned a result |
280
+ | `error` | `{ "message": "...", "code": "..." }` | Error during processing (`code` is `PERMISSION_DENIED` for IAM failures) |
281
+ | `done` | `{ "session_id": "...", "text": "..." }` | Stream complete with final text |
262
282
 
263
283
  For custom agent UIs that need streaming, import `readSSE`:
264
284
 
@@ -292,14 +312,14 @@ to the original plain object are invisible to the template.
292
312
  // WRONG — local ref bypasses Vue's reactivity, UI won't update:
293
313
  const msg: ChatMessage = { id: '...', role: 'agent', text: '', streaming: true };
294
314
  messages.value.push(msg);
295
- msg.text = 'hello'; // data changes, but Vue doesn't know
296
- msg.streaming = false; // template still shows typing indicator
315
+ msg.text = 'hello'; // data changes, but Vue doesn't know
316
+ msg.streaming = false; // template still shows typing indicator
297
317
 
298
318
  // CORRECT — access through the reactive array:
299
319
  messages.value.push({ id: '...', role: 'agent', text: '', streaming: true });
300
320
  const idx = messages.value.length - 1;
301
- messages.value[idx].text = 'hello'; // Vue detects this
302
- messages.value[idx].streaming = false; // template re-renders
321
+ messages.value[idx].text = 'hello'; // Vue detects this
322
+ messages.value[idx].streaming = false; // template re-renders
303
323
  ```
304
324
 
305
325
  The `useAgentChat` composable uses the correct pattern internally (via an
@@ -342,7 +362,7 @@ agents (MCP or REST-backed):
342
362
 
343
363
  This applies to ADK agent tools, where the LLM reads tool output directly.
344
364
  MCP server tools follow different conventions (structured dicts/lists) — see
345
- the `mcp-servers` rule.
365
+ [mcp-servers.md](mcp-servers.md).
346
366
 
347
367
  The agent's LLM will try to interpret whatever the tool returns. Raw API
348
368
  responses with nested dicts, numeric IDs, and arrays of unlabeled values
@@ -465,6 +485,7 @@ Passing a raw `McpToolset` as the agent's only tool source and writing a
465
485
  long system prompt does **not** satisfy the spec.
466
486
 
467
487
  `McpToolset` passthrough means:
488
+
468
489
  - The LLM receives raw JSON responses — no Markdown formatting, no
469
490
  human-readable reports
470
491
  - No session-state caching — repeated queries for the same entity make
@@ -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,14 +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 connectedcheck `DATABASE_URL` in `.env`) |
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 provisionedsee [storage.md](storage.md) for how to check) |
34
29
 
35
- Use `Pref<T>` or `usePrefsStore()` for KV (see `pref` rule).
36
- Check `.env` for `DATABASE_URL` before using Neon Postgres (see `server` rule).
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.
37
31
 
38
32
  ## Adding Pages
39
33
 
@@ -116,8 +110,8 @@ Use server routes when you need to proxy external APIs (avoid CORS), access
116
110
  data server-side, or keep secrets off the client. Call them from client code
117
111
  with `$fetch('/api/my-data/fetch')`.
118
112
 
119
- See the `server` rule for file-routing conventions and Neon Postgres patterns.
120
- 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.
121
115
 
122
116
  ## Beyond the UI: Agents, MCP Servers, and Server Routes
123
117
 
@@ -125,7 +119,7 @@ Aether apps are more than just a Nuxt SPA. The project contains three additional
125
119
 
126
120
  ### `agents/` -- ADK Agents (Python)
127
121
 
128
- 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.
129
123
 
130
124
  **Agent query path:** The app talks to Agent Engine directly — the portal is
131
125
  only in the auth path. The flow is:
@@ -143,7 +137,7 @@ project detail page for IAM health status.
143
137
 
144
138
  ### `mcp-servers/` -- MCP Servers (Python)
145
139
 
146
- 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.
147
141
 
148
142
  ### `broadchurch.yaml`
149
143
 
@@ -158,11 +152,10 @@ Use these to build whatever UI fits the app:
158
152
  local Nitro streaming route (`/api/agent/:agentId/stream`) which calls
159
153
  Agent Engine directly with a tenant SA token. Handles streaming, session
160
154
  management, and response parsing. Shows clear error messages when IAM
161
- permissions are missing. See the `agents` cursor rule for details.
155
+ permissions are missing. See [agents.md](agents.md) for details.
162
156
  - **`useTenantConfig()`** -- Fetch the tenant's runtime config (deployed
163
157
  agents, feature flags, MCP servers) from the Portal Gateway.
164
158
  - **`useElementalClient()`** -- When using the Elemental API from the client,
165
- see the `data` rule.
159
+ see [data.md](data.md).
166
160
  - **`usePrefsStore()` / `Pref<T>`** -- KV-backed user preferences. See
167
- the `pref` rule.
168
-
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>
@@ -0,0 +1,57 @@
1
+ If you are in Cursor Cloud, the `environment.json` install step runs
2
+ `init-project.js` and `npm install` automatically, and starts a dev server
3
+ on port 3000.
4
+
5
+ **Verify before starting:** check that `.env` exists and `node_modules/` is
6
+ present. If either is missing, run: `node init-project.js && npm install`
7
+
8
+ **Do NOT** manually run `nvm install` or `nvm use` — Node version is managed
9
+ by the environment.
10
+
11
+ ### Initial environment setup only
12
+
13
+ This subsection applies ONLY when first asked to "set up the development
14
+ environment" or "demonstrate that the environment is working." It does
15
+ **NOT** apply to ongoing development — once the app is built, use the
16
+ browser normally to test and verify UI changes.
17
+
18
+ **During initial setup**, skip browser/UI testing. The starter UI is a
19
+ placeholder template that will be replaced by `/build_my_app`. Do not
20
+ launch a browser, record videos, or take screenshots at this stage.
21
+ Verifying `npm run build` passes is sufficient.
22
+
23
+ 1. Check the "Dev Server" terminal output for a line containing
24
+ `Listening on` or `Local: http://localhost:3000`. If present, the
25
+ environment is working.
26
+ 2. If the dev server is NOT running, start it with `npm run dev` and wait
27
+ for the "Listening on" line.
28
+ 3. Run `npm run build` to verify the project compiles.
29
+ 4. Once confirmed, tell the user the environment is ready, then
30
+ immediately run the `/build_my_app` command.
31
+
32
+ ### MCP tools
33
+
34
+ Lovelace MCP servers (`lovelace-elemental`, `lovelace-stocks`, etc.)
35
+ should be available if configured at the org level. Check your tool list
36
+ for `elemental_*` tools. If they're not available, use the Elemental API
37
+ client (`useElementalClient()`) and the skill docs in
38
+ `.cursor/skills/elemental-api/` and `.cursor/skills/data-model/` for platform data access instead.
39
+
40
+ ### Technical details
41
+
42
+ Node 20 is the baseline (`.nvmrc`). The `environment.json` install step
43
+ handles this via `nvm install 20 && nvm alias default 20`. Newer Node
44
+ versions (22, 25) generally work but may produce `EBADENGINE` warnings
45
+ during install — safe to ignore.
46
+
47
+ The install step runs `node init-project.js --local` (creates `.env` if
48
+ absent) then `npm install` (triggers `postinstall` → `nuxt prepare`).
49
+ Auth0 is bypassed via `NUXT_PUBLIC_USER_NAME=dev-user`
50
+ in the generated `.env`.
51
+
52
+ **No automated test suite.** Verification is `npm run build` (compile
53
+ check) and `npm run format:check` (Prettier). See Verification Commands.
54
+
55
+ **Before committing:** always run `npm run format` — the husky pre-commit
56
+ hook runs `lint-staged` with `prettier --check` and will reject
57
+ unformatted files.