@elevasis/sdk 1.44.3 → 1.45.0

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 (246) hide show
  1. package/dist/cli.cjs +991 -650
  2. package/dist/index.d.ts +1045 -509
  3. package/dist/index.js +738 -688
  4. package/dist/node/index.d.ts +105 -97
  5. package/dist/test-utils/index.d.ts +42 -28
  6. package/dist/test-utils/index.js +514 -783
  7. package/dist/worker/index.d.ts +12112 -0
  8. package/dist/worker/index.js +121 -182
  9. package/package.json +6 -9
  10. package/reference/_navigation.md +151 -21
  11. package/reference/_reference-manifest.json +186 -4
  12. package/reference/claude-config.md +8 -0
  13. package/reference/core/index.mdx +3 -3
  14. package/reference/examples/organization-model.ts +117 -111
  15. package/reference/index.mdx +4 -4
  16. package/reference/rules/active-change-index.md +40 -54
  17. package/reference/rules/agent-runtime.md +81 -0
  18. package/reference/rules/agent-start-here.md +71 -163
  19. package/reference/rules/deployment.md +33 -10
  20. package/reference/rules/error-handling.md +26 -0
  21. package/reference/rules/execution.md +13 -0
  22. package/reference/rules/frontend.md +10 -3
  23. package/reference/rules/observability.md +9 -1
  24. package/reference/rules/operations.md +26 -17
  25. package/reference/rules/organization-model.md +74 -88
  26. package/reference/rules/organization-os.md +71 -88
  27. package/reference/rules/package-taxonomy.md +11 -2
  28. package/reference/rules/platform.md +13 -7
  29. package/reference/rules/shared-types.md +15 -0
  30. package/reference/rules/task-tracking.md +30 -5
  31. package/reference/rules/ui.md +145 -3
  32. package/reference/rules/vibe-intents.md +271 -0
  33. package/reference/rules/vibe.md +17 -243
  34. package/reference/scaffold/core/organization-graph.mdx +111 -97
  35. package/reference/scaffold/core/organization-model.mdx +234 -214
  36. package/reference/scaffold/operations/propagation-pipeline.md +1 -1
  37. package/reference/scaffold/operations/scaffold-maintenance.md +19 -18
  38. package/reference/scaffold/operations/workflow-recipes.md +71 -19
  39. package/reference/scaffold/recipes/add-a-feature.md +156 -146
  40. package/reference/scaffold/recipes/add-a-resource.md +123 -117
  41. package/reference/scaffold/recipes/customize-crm-actions.md +25 -10
  42. package/reference/scaffold/recipes/customize-knowledge-browser.md +52 -117
  43. package/reference/scaffold/recipes/customize-organization-model.md +161 -149
  44. package/reference/scaffold/recipes/extend-a-base-entity.md +156 -140
  45. package/reference/scaffold/recipes/extend-crm.md +16 -11
  46. package/reference/scaffold/recipes/extend-lead-gen.md +25 -7
  47. package/reference/scaffold/recipes/gate-by-feature-or-admin.md +160 -118
  48. package/reference/scaffold/recipes/index.md +2 -2
  49. package/reference/scaffold/recipes/query-the-knowledge-graph.md +23 -23
  50. package/reference/scaffold/reference/contracts.md +12 -1
  51. package/reference/scaffold/reference/glossary.md +3 -3
  52. package/reference/scaffold/reference/system-interface-capabilities.md +5 -4
  53. package/reference/scaffold/ui/composition-extensibility.mdx +271 -232
  54. package/reference/scaffold/ui/feature-flags-and-gating.md +14 -6
  55. package/reference/scaffold/ui/feature-shell.mdx +279 -62
  56. package/reference/scaffold/ui/recipes.md +229 -197
  57. package/reference/sdk/cli-management.mdx +77 -29
  58. package/reference/sdk/concepts.mdx +2 -0
  59. package/reference/sdk/define-builders.mdx +76 -0
  60. package/reference/sdk/deployment/command-center.mdx +6 -2
  61. package/reference/sdk/deployment/execution-reference.mdx +64 -186
  62. package/reference/sdk/deployment/index.mdx +2 -0
  63. package/reference/sdk/exports.mdx +4 -4
  64. package/reference/sdk/framework/agent.mdx +49 -119
  65. package/reference/sdk/framework/index.mdx +46 -65
  66. package/reference/sdk/framework/project-structure.mdx +150 -205
  67. package/reference/sdk/framework/tutorial-system.mdx +2 -2
  68. package/reference/sdk/human-in-the-loop.mdx +152 -0
  69. package/reference/sdk/index.mdx +6 -7
  70. package/reference/sdk/platform-tools/index.mdx +12 -0
  71. package/reference/sdk/platform-tools/type-safety.mdx +4 -0
  72. package/reference/sdk/project-deployment-spec.mdx +131 -0
  73. package/reference/sdk/resources/index.mdx +21 -7
  74. package/reference/sdk/resources/patterns.mdx +54 -24
  75. package/reference/sdk/resources/types.mdx +7 -4
  76. package/reference/sdk/templates/data-enrichment.mdx +7 -3
  77. package/reference/sdk/templates/email-sender.mdx +139 -135
  78. package/reference/sdk/templates/lead-scorer.mdx +5 -1
  79. package/reference/sdk/templates/pdf-generator.mdx +155 -151
  80. package/reference/sdk/templates/recurring-job.mdx +195 -189
  81. package/reference/sdk/templates/text-classifier.mdx +4 -0
  82. package/reference/sdk/templates/web-scraper.mdx +139 -135
  83. package/reference/spine/spine-primer.md +135 -96
  84. package/reference/ui/index.mdx +14 -7
  85. package/dist/types/worker/adapters/anymailfinder.d.ts +0 -14
  86. package/dist/types/worker/adapters/apify.d.ts +0 -14
  87. package/dist/types/worker/adapters/approval.d.ts +0 -23
  88. package/dist/types/worker/adapters/attio.d.ts +0 -22
  89. package/dist/types/worker/adapters/clickup.d.ts +0 -22
  90. package/dist/types/worker/adapters/create-adapter.d.ts +0 -41
  91. package/dist/types/worker/adapters/crm.d.ts +0 -20
  92. package/dist/types/worker/adapters/dropbox.d.ts +0 -14
  93. package/dist/types/worker/adapters/email.d.ts +0 -25
  94. package/dist/types/worker/adapters/execution.d.ts +0 -22
  95. package/dist/types/worker/adapters/gmail.d.ts +0 -14
  96. package/dist/types/worker/adapters/google-sheets.d.ts +0 -14
  97. package/dist/types/worker/adapters/index.d.ts +0 -33
  98. package/dist/types/worker/adapters/instantly.d.ts +0 -14
  99. package/dist/types/worker/adapters/lead.d.ts +0 -28
  100. package/dist/types/worker/adapters/list.d.ts +0 -9
  101. package/dist/types/worker/adapters/llm.d.ts +0 -45
  102. package/dist/types/worker/adapters/millionverifier.d.ts +0 -14
  103. package/dist/types/worker/adapters/notification.d.ts +0 -28
  104. package/dist/types/worker/adapters/pdf.d.ts +0 -22
  105. package/dist/types/worker/adapters/projects.d.ts +0 -20
  106. package/dist/types/worker/adapters/resend.d.ts +0 -14
  107. package/dist/types/worker/adapters/scheduler.d.ts +0 -25
  108. package/dist/types/worker/adapters/signature-api.d.ts +0 -14
  109. package/dist/types/worker/adapters/storage.d.ts +0 -33
  110. package/dist/types/worker/adapters/stripe.d.ts +0 -14
  111. package/dist/types/worker/adapters/tomba.d.ts +0 -14
  112. package/dist/types/worker/index.d.ts +0 -60
  113. package/dist/types/worker/platform.d.ts +0 -90
  114. package/dist/types/worker/utils.d.ts +0 -9
  115. package/reference/claude-config/Overview.md +0 -230
  116. package/reference/claude-config/hooks/post-edit-validate.mjs +0 -98
  117. package/reference/claude-config/hooks/scaffold-registry-reminder.mjs +0 -187
  118. package/reference/claude-config/hooks/tool-failure-recovery.mjs +0 -73
  119. package/reference/claude-config/registries/graph-skills.json +0 -4
  120. package/reference/claude-config/registries/knowledge-flags.json +0 -154
  121. package/reference/claude-config/registries/skill-coverage.json +0 -20
  122. package/reference/claude-config/rules/active-change-index.md +0 -22
  123. package/reference/claude-config/rules/agent-start-here.md +0 -22
  124. package/reference/claude-config/rules/deployment.md +0 -22
  125. package/reference/claude-config/rules/error-handling.md +0 -22
  126. package/reference/claude-config/rules/execution.md +0 -22
  127. package/reference/claude-config/rules/frontend.md +0 -22
  128. package/reference/claude-config/rules/observability.md +0 -22
  129. package/reference/claude-config/rules/operations.md +0 -22
  130. package/reference/claude-config/rules/organization-model.md +0 -22
  131. package/reference/claude-config/rules/organization-os.md +0 -22
  132. package/reference/claude-config/rules/package-taxonomy.md +0 -22
  133. package/reference/claude-config/rules/platform.md +0 -22
  134. package/reference/claude-config/rules/shared-types.md +0 -22
  135. package/reference/claude-config/rules/task-tracking.md +0 -22
  136. package/reference/claude-config/rules/topbar-actions.md +0 -70
  137. package/reference/claude-config/rules/ui.md +0 -22
  138. package/reference/claude-config/rules/vibe.md +0 -22
  139. package/reference/claude-config/scripts/statusline-command.js +0 -18
  140. package/reference/claude-config/settings.json +0 -30
  141. package/reference/claude-config/skills/client/SKILL.md +0 -201
  142. package/reference/claude-config/skills/deploy/SKILL.md +0 -159
  143. package/reference/claude-config/skills/dsp/SKILL.md +0 -66
  144. package/reference/claude-config/skills/elevasis/SKILL.md +0 -251
  145. package/reference/claude-config/skills/explore/SKILL.md +0 -78
  146. package/reference/claude-config/skills/git-sync/SKILL.md +0 -166
  147. package/reference/claude-config/skills/om/SKILL.md +0 -475
  148. package/reference/claude-config/skills/om/operations/build.md +0 -237
  149. package/reference/claude-config/skills/om/operations/codify-level-a.md +0 -109
  150. package/reference/claude-config/skills/om/operations/codify-level-b.md +0 -159
  151. package/reference/claude-config/skills/om/operations/customers.md +0 -114
  152. package/reference/claude-config/skills/om/operations/features.md +0 -88
  153. package/reference/claude-config/skills/om/operations/goals.md +0 -123
  154. package/reference/claude-config/skills/om/operations/identity.md +0 -97
  155. package/reference/claude-config/skills/om/operations/labels.md +0 -110
  156. package/reference/claude-config/skills/om/operations/offerings.md +0 -114
  157. package/reference/claude-config/skills/om/operations/roles.md +0 -104
  158. package/reference/claude-config/skills/om/operations/scaffold.md +0 -163
  159. package/reference/claude-config/skills/om/operations/techStack.md +0 -38
  160. package/reference/claude-config/skills/project/SKILL.md +0 -1114
  161. package/reference/claude-config/skills/run-ui/SKILL.md +0 -73
  162. package/reference/claude-config/skills/save/SKILL.md +0 -183
  163. package/reference/claude-config/skills/setup/SKILL.md +0 -290
  164. package/reference/claude-config/skills/status/SKILL.md +0 -59
  165. package/reference/claude-config/skills/submit-request/SKILL.md +0 -180
  166. package/reference/claude-config/skills/sync/SKILL.md +0 -47
  167. package/reference/claude-config/skills/tutorial/SKILL.md +0 -259
  168. package/reference/claude-config/skills/tutorial/progress-template.md +0 -74
  169. package/reference/claude-config/skills/tutorial/technical.md +0 -1303
  170. package/reference/claude-config/skills/tutorial/vibe-coder.md +0 -890
  171. package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +0 -27
  172. package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +0 -30
  173. package/reference/claude-config/sync-notes/2026-04-24-test-utils-and-template-tests.md +0 -73
  174. package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +0 -86
  175. package/reference/claude-config/sync-notes/2026-04-25-auth-role-system-and-settings-roles.md +0 -55
  176. package/reference/claude-config/sync-notes/2026-04-27-crm-hitl-action-layer-cutover.md +0 -97
  177. package/reference/claude-config/sync-notes/2026-04-27-lead-gen-substrate-train.md +0 -112
  178. package/reference/claude-config/sync-notes/2026-04-29-crm-state-and-lead-gen-processing-status.md +0 -93
  179. package/reference/claude-config/sync-notes/2026-05-02-crm-ownership-next-action.md +0 -58
  180. package/reference/claude-config/sync-notes/2026-05-02-template-hardcode-workos-config.md +0 -56
  181. package/reference/claude-config/sync-notes/2026-05-04-elevasis-workspace.md +0 -71
  182. package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +0 -83
  183. package/reference/claude-config/sync-notes/2026-05-04-template-skills-run-ui-and-tutorial.md +0 -59
  184. package/reference/claude-config/sync-notes/2026-05-05-list-builder.md +0 -42
  185. package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +0 -60
  186. package/reference/claude-config/sync-notes/2026-05-06-sdk-changes-release-train.md +0 -37
  187. package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +0 -34
  188. package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +0 -38
  189. package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +0 -32
  190. package/reference/claude-config/sync-notes/2026-05-09-command-system.md +0 -33
  191. package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +0 -69
  192. package/reference/claude-config/sync-notes/2026-05-12-sdk-ready-release-train.md +0 -30
  193. package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +0 -45
  194. package/reference/claude-config/sync-notes/2026-05-15-om-skill-rename-and-write-family.md +0 -52
  195. package/reference/claude-config/sync-notes/2026-05-17-sdk-boundary-consolidation.md +0 -33
  196. package/reference/claude-config/sync-notes/2026-05-20-om-define-helpers.md +0 -32
  197. package/reference/claude-config/sync-notes/2026-05-22-access-model-and-right-panel.md +0 -43
  198. package/reference/claude-config/sync-notes/2026-05-22-lead-gen-tenant-config.md +0 -40
  199. package/reference/claude-config/sync-notes/2026-05-22-org-model-multi-file-split.md +0 -61
  200. package/reference/claude-config/sync-notes/2026-05-23-branding-names-to-identity.md +0 -49
  201. package/reference/claude-config/sync-notes/2026-05-23-lead-gen-manage-access.md +0 -31
  202. package/reference/claude-config/sync-notes/2026-05-23-om-deployment-drift-detection.md +0 -42
  203. package/reference/claude-config/sync-notes/2026-05-23-om-full-model-deploy-contract.md +0 -33
  204. package/reference/claude-config/sync-notes/2026-05-23-ui-sdk-package-fixes.md +0 -37
  205. package/reference/claude-config/sync-notes/2026-05-24-platform-invite-router-core-baseline.md +0 -28
  206. package/reference/claude-config/sync-notes/2026-05-24-system-interface-readiness.md +0 -43
  207. package/reference/claude-config/sync-notes/2026-05-25-invitation-login-loader.md +0 -26
  208. package/reference/claude-config/sync-notes/2026-05-25-om-topbar-requests.md +0 -33
  209. package/reference/claude-config/sync-notes/2026-05-25-system-interface-profile-registry-and-substrate.md +0 -35
  210. package/reference/claude-config/sync-notes/2026-05-25-tenant-om-scaffold-cli.md +0 -49
  211. package/reference/claude-config/sync-notes/2026-05-25-vibe-operate-intent.md +0 -47
  212. package/reference/claude-config/sync-notes/2026-05-28-om-snapshot-sdk-workflow-config.md +0 -33
  213. package/reference/claude-config/sync-notes/2026-05-30-client-source-and-om-profiles.md +0 -39
  214. package/reference/claude-config/sync-notes/2026-06-02-knowledge-nested-group-routing.md +0 -27
  215. package/reference/claude-config/sync-notes/2026-06-02-nest-projects-under-platform.md +0 -45
  216. package/reference/claude-config/sync-notes/2026-06-03-skill-autogen-and-client-skill.md +0 -34
  217. package/reference/claude-config/sync-notes/2026-06-04-scaffold-registry-lane-severity.md +0 -34
  218. package/reference/claude-config/sync-notes/2026-06-05-appearance-app-mode-decouple.md +0 -29
  219. package/reference/claude-config/sync-notes/2026-06-05-ontology-endpoint-rename-and-knowledge-browser-ui.md +0 -86
  220. package/reference/claude-config/sync-notes/2026-06-06-om-build-systems-scaffold.md +0 -47
  221. package/reference/claude-config/sync-notes/2026-06-06-om-item-copy-references.md +0 -50
  222. package/reference/claude-config/sync-notes/2026-06-08-knowledge-base-page-not-found-fix.md +0 -76
  223. package/reference/claude-config/sync-notes/2026-06-09-agent-sessions-public-agent-chat-route.md +0 -75
  224. package/reference/claude-config/sync-notes/2026-06-09-sdk-cli-load-org-model-resolution.md +0 -42
  225. package/reference/claude-config/sync-notes/2026-06-12-agent-grants-visualizer-operations.md +0 -30
  226. package/reference/claude-config/sync-notes/2026-06-14-session-ux-and-project-cli-json.md +0 -33
  227. package/reference/claude-config/sync-notes/2026-06-14-shared-session-conversation-view.md +0 -26
  228. package/reference/claude-config/sync-notes/2026-06-15-session-chat-zero-wiring.md +0 -46
  229. package/reference/claude-config/sync-notes/2026-06-17-agent-session-ux-features.md +0 -34
  230. package/reference/claude-config/sync-notes/2026-06-25-shared-page-scroll-contract-guard.md +0 -52
  231. package/reference/claude-config/sync-notes/2026-06-26-leadgen-overview-om-telemetry.md +0 -47
  232. package/reference/claude-config/sync-notes/2026-07-21-agent-scaffold-hardening.md +0 -75
  233. package/reference/claude-config/sync-notes/2026-07-23-agent-session-memory.md +0 -49
  234. package/reference/claude-config/sync-notes/2026-07-23-workos-org-marker.md +0 -50
  235. package/reference/claude-config/sync-notes/2026-07-24-claude-5-models-and-session-surface-fixes.md +0 -116
  236. package/reference/claude-config/sync-notes/2026-07-27-agent-strict-output-and-turn-drift.md +0 -73
  237. package/reference/claude-config/sync-notes/2026-07-28-agent-reply-is-its-own-field.md +0 -84
  238. package/reference/claude-config/sync-notes/2026-07-30-login-screen-and-member-provisioning-state.md +0 -114
  239. package/reference/claude-config/sync-notes/2026-08-02-auth-guard-defaults-and-truncation-fix.md +0 -122
  240. package/reference/claude-config/sync-notes/2026-08-03-agent-prose-escape-normalization.md +0 -88
  241. package/reference/claude-config/sync-notes/2026-08-03-cli-gateway-errors-and-request-timeout.md +0 -120
  242. package/reference/claude-config/sync-notes/README.md +0 -43
  243. package/reference/sdk/framework/interaction-guidance.mdx +0 -182
  244. package/reference/sdk/framework/memory.mdx +0 -326
  245. package/reference/sdk/framework/resource-documentation.mdx +0 -90
  246. package/reference/sdk/roadmap.mdx +0 -164
@@ -1,143 +1,159 @@
1
- ---
2
- title: Extend a Base Entity
3
- description: Add project-specific metadata to the canonical entity shapes (Project, Deal, Company, etc.) from @elevasis/core/entities using the TMeta extension slot.
4
- ---
1
+ ---
2
+ title: Extend a Base Entity
3
+ description: Add project-specific metadata to the canonical entity shapes (Project, Deal, Company, etc.) from @elevasis/core/entities using the TMeta extension slot.
4
+ ---
5
5
  <!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
6
6
  <!-- Regenerate: pnpm scaffold:sync -->
7
7
 
8
-
9
- # Extend a Base Entity
10
-
11
- Workflows and UI features often operate on domain entities such as projects, deals, companies, or contacts. Rather than each project declaring its own shape from scratch, `@elevasis/core/entities` provides typed base interfaces generic over a `<TMeta>` slot. External projects extend these to add project-specific fields while keeping the canonical shape stable and interoperable with platform tooling.
12
-
13
- The canonical demo lives in `core/types/entities.ts` of any scaffold project.
14
-
15
- ---
16
-
17
- ## Available Base Entities
18
-
19
- Each entity ships as a TypeScript interface, a Zod schema, and an Input type:
20
-
21
- | Set | Description |
22
- | -------------------------------------------------------------- | ------------------------------------------- |
23
- | `BaseProject` / `BaseProjectSchema` / `BaseProjectInput` | Client or internal project record |
24
- | `BaseMilestone` / `BaseMilestoneSchema` / `BaseMilestoneInput` | Milestone within a project |
25
- | `BaseTask` / `BaseTaskSchema` / `BaseTaskInput` | Discrete task within a project or milestone |
26
- | `BaseDeal` / `BaseDealSchema` / `BaseDealInput` | Sales or partnership deal record |
27
- | `BaseCompany` / `BaseCompanySchema` / `BaseCompanyInput` | Company / account record |
28
- | `BaseContact` / `BaseContactSchema` / `BaseContactInput` | Individual contact record |
29
-
30
- All imports come from `@elevasis/core/entities`.
31
-
32
- ---
33
-
34
- ## Recipe 1 -- Extend a base entity with custom metadata
35
-
36
- Place this in `core/types/entities.ts`. This is the primary pattern -- the scaffold template ships this exact example.
37
-
38
- ```ts
39
- import { z } from 'zod'
40
- import type { BaseProject, BaseDeal } from '@elevasis/core/entities'
41
- import { BaseProjectSchema, BaseDealSchema } from '@elevasis/core/entities'
42
-
43
- // -- Project: extending metadata on a base entity --
44
-
45
- export const ProjectMetaSchema = z.object({
46
- budget: z.number().nonnegative(),
47
- clientPriority: z.enum(['low', 'medium', 'high'])
48
- })
49
-
50
- export type ProjectMeta = z.infer<typeof ProjectMetaSchema>
51
-
52
- export const ProjectSchema = BaseProjectSchema.extend({ metadata: ProjectMetaSchema })
53
-
54
- export type Project = BaseProject<ProjectMeta>
55
- ```
56
-
57
- Key points:
58
-
59
- - `BaseProjectSchema.extend({ metadata: ... })` merges your metadata Zod schema into the validated shape. Zod handles the rest.
60
- - `BaseProject<ProjectMeta>` infers the TypeScript type with your metadata typed correctly.
61
- - Only the `metadata` field is extended -- all other base fields (`id`, `organizationId`, `name`, `status`, `createdAt`, `updatedAt`, etc.) are inherited unchanged.
62
- - This file is the single source of truth for entity shapes across `core/`, `operations/`, and `ui/`.
63
-
64
- ---
65
-
66
- ## Recipe 2 -- Use a base entity as-is
67
-
68
- When the base shape covers everything the project needs, skip the extension entirely:
69
-
70
- ```ts
71
- import type { BaseDeal } from '@elevasis/core/entities'
72
- import { BaseDealSchema } from '@elevasis/core/entities'
73
-
74
- export const DealSchema = BaseDealSchema
75
-
76
- export type Deal = BaseDeal
77
- ```
78
-
79
- `BaseDeal` without a type argument defaults `TMeta` to an empty object (`{}`), which Zod validates as `z.object({})`. Use this path when the project has no per-deal custom fields -- you still get the canonical shape and full Zod validation for free.
80
-
81
- ---
82
-
83
- ## Recipe 3 -- Reference entity types from a workflow input schema
84
-
85
- Workflows that operate on projects or deals should reference the project-local entity types rather than redeclaring the shape. Add this to `operations/src/<workflow>/workflow.ts`:
86
-
87
- ```ts
88
- import { z } from 'zod'
89
- import type { WorkflowDefinition } from '@elevasis/sdk'
90
- import { ProjectSchema } from '@core/types/entities'
91
-
92
- export const myWorkflow: WorkflowDefinition = {
93
- id: 'my-workflow',
94
- inputSchema: z.object({
95
- project: ProjectSchema,
96
- notes: z.string().optional()
97
- }),
98
- // ...
99
- }
100
- ```
101
-
102
- The `@core/*` alias maps to the `core/` workspace package. This keeps entity contracts in one place and ensures the workflow input type matches whatever the UI passes as the execution payload.
103
-
104
- ---
105
-
106
- ## Recipe 4 -- Reference entity types from the UI
107
-
108
- UI components accept entity types directly in props. The entity type flows from the `core` package through the component into the workflow execution payload:
109
-
110
- ```tsx
111
- import type { Project } from '@core/types/entities'
112
-
113
- interface ProjectCardProps {
114
- project: Project
115
- onExecute?: (project: Project) => void
116
- }
117
-
118
- export function ProjectCard({ project, onExecute }: ProjectCardProps) {
119
- return (
120
- <button onClick={() => onExecute?.(project)}>
121
- Run workflow for {project.name}
122
- </button>
123
- )
124
- }
125
- ```
126
-
127
- When wiring this to a `RunResourceButton`, the entity instance becomes the workflow input. See UI Recipes recipe 6 (`Execute a Resource from a Surface`) at `../ui/recipes.md` for the end-to-end pattern where the entity type flows into a resource execution via `RunResourceButton`.
128
-
129
- ---
130
-
131
- ## Verification
132
-
133
- - **Test core contracts:** `pnpm -C core test` runs the Vitest suite. The template ships `core/types/entities.test.ts` as a working smoke-check -- it `safeParse`s a valid project (expects success) and an invalid one (expects failure). Run this after any schema change.
134
- - **Round-trip safeParse:** Call `ProjectSchema.safeParse(candidateObject)` in a test or REPL to confirm the Zod shape accepts the data your workflows and UI will produce.
135
- - **Cross-package type check:** `pnpm -C ui build` will surface any TypeScript errors if a UI component or hook passes a mismatched entity type to a workflow input.
136
-
137
- ---
138
-
139
- ## Cross-references
140
-
141
- - [./add-a-resource.md](./add-a-resource.md) -- resource authoring that consumes entity types in `inputSchema`
142
- - [../ui/recipes.md](../ui/recipes.md) recipe 6 -- execute a resource from a surface, with entity-typed input via `RunResourceButton`
143
- - [../reference/contracts.md](../reference/contracts.md) -- auto-generated TypeScript contract shapes for all Organization OS types
8
+
9
+ # Extend a Base Entity
10
+
11
+ Workflows and UI features often operate on domain entities such as projects, deals, companies, or contacts. Rather than each project declaring its own shape from scratch, `@elevasis/core/entities` provides typed base interfaces generic over a `<TMeta>` slot. External projects extend these to add project-specific fields while keeping the canonical shape stable and interoperable with platform tooling.
12
+
13
+ The canonical demo lives in `core/types/entities.ts` of any scaffold project.
14
+
15
+ ---
16
+
17
+ ## Available Base Entities
18
+
19
+ Each entity ships as a TypeScript interface, a Zod schema, and an Input type:
20
+
21
+ | Set | Description |
22
+ | -------------------------------------------------------------- | ------------------------------------------- |
23
+ | `BaseProject` / `BaseProjectSchema` / `BaseProjectInput` | Client or internal project record |
24
+ | `BaseMilestone` / `BaseMilestoneSchema` / `BaseMilestoneInput` | Milestone within a project |
25
+ | `BaseTask` / `BaseTaskSchema` / `BaseTaskInput` | Discrete task within a project or milestone |
26
+ | `BaseDeal` / `BaseDealSchema` / `BaseDealInput` | Sales or partnership deal record |
27
+ | `BaseCompany` / `BaseCompanySchema` / `BaseCompanyInput` | Company / account record |
28
+ | `BaseContact` / `BaseContactSchema` / `BaseContactInput` | Individual contact record |
29
+
30
+ All imports come from `@elevasis/core/entities`.
31
+
32
+ ---
33
+
34
+ ## Recipe 1 -- Extend a base entity with custom metadata
35
+
36
+ Place this in `core/types/entities.ts`. This is the primary pattern -- the scaffold template ships this exact example.
37
+
38
+ ```ts
39
+ import { z } from 'zod'
40
+ import type { BaseProject, BaseDeal } from '@elevasis/core/entities'
41
+ import { BaseProjectSchema, BaseDealSchema } from '@elevasis/core/entities'
42
+
43
+ // -- Project: extending metadata on a base entity --
44
+
45
+ export const ProjectMetaSchema = z.object({
46
+ budget: z.number().nonnegative(),
47
+ clientPriority: z.enum(['low', 'medium', 'high'])
48
+ })
49
+
50
+ export type ProjectMeta = z.infer<typeof ProjectMetaSchema>
51
+
52
+ export const ProjectSchema = BaseProjectSchema.extend({ metadata: ProjectMetaSchema })
53
+
54
+ export type Project = BaseProject<ProjectMeta>
55
+ ```
56
+
57
+ Key points:
58
+
59
+ - `BaseProjectSchema.extend({ metadata: ... })` merges your metadata Zod schema into the validated shape. Zod handles the rest.
60
+ - `BaseProject<ProjectMeta>` infers the TypeScript type with your metadata typed correctly.
61
+ - Only the `metadata` field is extended -- all other base fields (`id`, `organizationId`, `name`, `status`, `createdAt`, `updatedAt`, etc.) are inherited unchanged.
62
+ - This file is the single source of truth for entity shapes across `core/`, `operations/`, and `ui/`.
63
+
64
+ ---
65
+
66
+ ## Recipe 2 -- Use a base entity as-is
67
+
68
+ When the base shape covers everything the project needs, skip the extension entirely:
69
+
70
+ ```ts
71
+ import type { BaseDeal } from '@elevasis/core/entities'
72
+ import { BaseDealSchema } from '@elevasis/core/entities'
73
+
74
+ export const DealSchema = BaseDealSchema
75
+
76
+ export type Deal = BaseDeal
77
+ ```
78
+
79
+ `BaseDeal` without a type argument defaults `TMeta` to an empty object (`{}`), which Zod validates as `z.object({})`. Use this path when the project has no per-deal custom fields -- you still get the canonical shape and full Zod validation for free.
80
+
81
+ ---
82
+
83
+ ## Recipe 3 -- Reference entity types from a workflow input schema
84
+
85
+ Workflows that operate on projects or deals should reference the project-local entity types rather than redeclaring the shape. Add this to `operations/src/<workflow>/workflow.ts`:
86
+
87
+ <!-- doc-snippet:skip: illustrative excerpt -- `resourceDescriptors` names the project's own resource-descriptors export, and `steps` is shown unimported for readability -->
88
+
89
+ ```ts
90
+ import { z } from 'zod'
91
+ import type { WorkflowDefinition } from '@elevasis/sdk'
92
+ import { ProjectSchema } from '@core/types/entities'
93
+ import { resourceDescriptors } from '@core/config/organization-model'
94
+
95
+ const inputSchema = z.object({
96
+ project: ProjectSchema,
97
+ notes: z.string().optional()
98
+ })
99
+ const outputSchema = z.object({ ok: z.boolean() })
100
+
101
+ export const myWorkflow: WorkflowDefinition = {
102
+ config: {
103
+ resource: resourceDescriptors.myWorkflow,
104
+ resourceId: resourceDescriptors.myWorkflow.id,
105
+ name: 'My Workflow',
106
+ description: 'Runs against a project entity.',
107
+ type: resourceDescriptors.myWorkflow.kind,
108
+ version: '1.0.0',
109
+ status: 'dev',
110
+ category: 'production'
111
+ },
112
+ contract: { inputSchema, outputSchema },
113
+ steps,
114
+ entryPoint: 'run'
115
+ }
116
+ ```
117
+
118
+ The `@core/*` alias maps to the `core/` workspace package. This keeps entity contracts in one place and ensures the workflow input type matches whatever the UI passes as the execution payload.
119
+
120
+ ---
121
+
122
+ ## Recipe 4 -- Reference entity types from the UI
123
+
124
+ UI components accept entity types directly in props. The entity type flows from the `core` package through the component into the workflow execution payload:
125
+
126
+ ```tsx
127
+ import type { Project } from '@core/types/entities'
128
+
129
+ interface ProjectCardProps {
130
+ project: Project
131
+ onExecute?: (project: Project) => void
132
+ }
133
+
134
+ export function ProjectCard({ project, onExecute }: ProjectCardProps) {
135
+ return (
136
+ <button onClick={() => onExecute?.(project)}>
137
+ Run workflow for {project.name}
138
+ </button>
139
+ )
140
+ }
141
+ ```
142
+
143
+ When wiring this to a `RunResourceButton`, the entity instance becomes the workflow input. See UI Recipes recipe 6 (`Execute a Resource from a Surface`) at `../ui/recipes.md` for the end-to-end pattern where the entity type flows into a resource execution via `RunResourceButton`.
144
+
145
+ ---
146
+
147
+ ## Verification
148
+
149
+ - **Test core contracts:** `pnpm -C core test` runs the Vitest suite. The template ships `core/types/entities.test.ts` as a working smoke-check -- it `safeParse`s a valid project (expects success) and an invalid one (expects failure). Run this after any schema change.
150
+ - **Round-trip safeParse:** Call `ProjectSchema.safeParse(candidateObject)` in a test or REPL to confirm the Zod shape accepts the data your workflows and UI will produce.
151
+ - **Cross-package type check:** `pnpm -C ui build` will surface any TypeScript errors if a UI component or hook passes a mismatched entity type to a workflow input.
152
+
153
+ ---
154
+
155
+ ## Cross-references
156
+
157
+ - [./add-a-resource.md](./add-a-resource.md) -- resource authoring that consumes entity types in `inputSchema`
158
+ - [../ui/recipes.md](../ui/recipes.md) recipe 6 -- execute a resource from a surface, with entity-typed input via `RunResourceButton`
159
+ - [../reference/contracts.md](../reference/contracts.md) -- auto-generated TypeScript contract shapes for all Organization OS types
@@ -29,15 +29,15 @@ CRM is a layered platform surface, not one component:
29
29
 
30
30
  ## Decision Table
31
31
 
32
- | User wants | Start here | Notes |
33
- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
34
- | Change CRM System availability, labels, pipeline stages, resource descriptors, or API readiness | `core/config/organization-model.ts` | Treat this as Organization OS work. Mark `sales.crm.apiInterface` active only when scoped CRM resources and ontology are ready for API-backed actions. |
35
- | Add CRM sidebar nav or a CRM route | `@elevasis/ui/features/crm` and `operations/node_modules/@elevasis/sdk/reference/scaffold/ui/customization.md` | Prefer manifest/sidebar composition. Do not fork shared source first. |
36
- | Wrap a shared CRM page with project chrome | `DealsListPage`, `DealDetailPage`, `CrmOverview` from `@elevasis/ui/features/crm` | Keep route files thin and put project-specific logic in local feature modules. |
37
- | Build a custom deal page | `useDealDetail`, `useDealNotes`, `useDealTasks`, `useExecuteAction` from `@elevasis/ui/hooks` | Use hooks for platform data and compose your own UI. |
38
- | Add, hide, or replace deal action buttons | [customize-crm-actions.md](customize-crm-actions.md) | Start with the shared `crmActions` provider path; use project-owned UI when a custom workflow path is outside platform-known/default action dispatch constraints. |
39
- | Read or mutate CRM data inside a workflow | `crm` or `acqDb` from `@elevasis/sdk/worker` | `organizationId` is injected server-side by the platform dispatcher. Do not pass it from workflow code. |
40
- | Add a new persisted CRM column or table | Platform/API migration work, not just scaffold work | Update DB, core schemas/types, API service/handlers, hooks, docs, and scaffold contracts together. |
32
+ | User wants | Start here | Notes |
33
+ | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
34
+ | Change CRM System availability, labels, pipeline stages, resource descriptors, or API readiness | `core/config/organization-model.ts` | Treat this as Organization OS work. Mark `sales.crm.apiInterface` active only when scoped CRM resources and ontology are ready for API-backed actions. |
35
+ | Add CRM sidebar nav or a CRM route | `@elevasis/ui/features/crm` and `operations/node_modules/@elevasis/sdk/reference/scaffold/ui/customization.md` | Prefer manifest/sidebar composition. Do not fork shared source first. |
36
+ | Wrap a shared CRM page with project chrome | `DealsListPage`, `DealDetailPage`, `CrmOverview` from `@elevasis/ui/features/crm` | Keep route files thin and put project-specific logic in local feature modules. |
37
+ | Build a custom deal page | `useDealDetail`, `useDealNotes`, `useDealTasks`, `useExecuteAction` from `@elevasis/ui/hooks` | Use hooks for platform data and compose your own UI. |
38
+ | Add, hide, or replace deal action buttons | [customize-crm-actions.md](customize-crm-actions.md) | Start with the shared `crmActions` provider path; use project-owned UI when a custom workflow path is outside platform-known/default action dispatch constraints. |
39
+ | Read or mutate CRM data inside a workflow | `crm` or `acqDb` from `@elevasis/sdk/worker` | `organizationId` is injected server-side by the platform dispatcher. Do not pass it from workflow code. |
40
+ | Add a new persisted CRM column or table | Platform/API migration work, not just scaffold work | Update DB, core schemas/types, API service/handlers, hooks, docs, and scaffold contracts together. |
41
41
 
42
42
  ## Published CRM Surfaces
43
43
 
@@ -162,6 +162,8 @@ export function CustomDealWorkspace({ dealId }: { dealId: string }) {
162
162
 
163
163
  Inside deployed workflows, use worker adapters instead of browser hooks or direct database access:
164
164
 
165
+ <!-- doc-snippet:skip: illustrative excerpt -- `resourceDescriptors` names the project's own resource-descriptors export -->
166
+
165
167
  ```ts
166
168
  // operations/src/sales/follow-up-stale-deals.ts
167
169
  import type { WorkflowDefinition } from '@elevasis/sdk'
@@ -182,6 +184,7 @@ export const followUpStaleDealsWorkflow: WorkflowDefinition = {
182
184
  resource: resourceDescriptors.followUpStaleDeals,
183
185
  resourceId: resourceDescriptors.followUpStaleDeals.id,
184
186
  name: 'Follow Up Stale Deals',
187
+ description: 'Creates follow-up tasks for deals that have gone stale in a stage.',
185
188
  type: resourceDescriptors.followUpStaleDeals.kind,
186
189
  version: '1.0.0',
187
190
  status: 'dev',
@@ -191,10 +194,12 @@ export const followUpStaleDealsWorkflow: WorkflowDefinition = {
191
194
  followUp: {
192
195
  id: 'followUp',
193
196
  name: 'Follow Up',
197
+ description: 'Lists stale deals in the target stage and creates a follow-up task for each.',
194
198
  inputSchema,
195
199
  outputSchema,
196
200
  next: null,
197
- handler: async (input) => {
201
+ handler: async (rawInput, context) => {
202
+ const input = rawInput as z.infer<typeof inputSchema>
198
203
  const deals = await crm.listDeals({ stage: input.stage })
199
204
 
200
205
  for (const deal of deals) {
@@ -245,7 +250,7 @@ Keep these boundaries straight:
245
250
  Run the checks for the surfaces you touched:
246
251
 
247
252
  ```bash
248
- pnpm -C ui run check
253
+ pnpm -C ui run check-types
249
254
  pnpm -C operations run check
250
255
  pnpm -C operations exec elevasis-sdk check
251
256
  ```
@@ -34,7 +34,7 @@ Lead gen is a layered platform surface, not one component. Shared packages own s
34
34
  | User wants | Start here | Notes |
35
35
  | --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36
36
  | Change lead-gen System availability, labels, quick access, stage catalogs, build templates, workflow actions, resources, topology, or API readiness | `core/config/organization-model.ts` | Treat this as Organization OS work. Tenant projects own these values. Mark `sales.lead-gen.apiInterface` active only when scoped resources and ontology are ready for API-backed lead-gen actions. |
37
- | Add lead-gen sidebar nav or a lead-gen route | `@elevasis/ui/features/lead-gen` and `operations/node_modules/@elevasis/sdk/reference/scaffold/ui/customization.md` | Prefer manifest/sidebar composition. Do not fork shared source first. |
37
+ | Add lead-gen sidebar nav or a lead-gen route | `@elevasis/ui/features/lead-gen` and `operations/node_modules/@elevasis/sdk/reference/scaffold/ui/customization.md` | Prefer manifest/sidebar composition. Do not fork shared source first. |
38
38
  | Wrap a shared lead-gen page with project chrome | `LeadGenOverviewPage`, `LeadGenListsPage`, `LeadGenListDetailPage`, `ListBuilderPage`, `LeadGenCompaniesPage`, `LeadGenContactsPage` | Keep route files thin and put project-specific behavior in local feature modules. |
39
39
  | Build a custom campaign/list workspace | `ListBuilderPage`, `useLists`, `useList`, `useListProgress`, `useListExecutions`, `useWorkflowExecution`, `useExecutionSSE` from `@elevasis/ui` | Use the shared builder when possible; otherwise compose hooks for platform data and workflow execution. |
40
40
  | Add or change list-builder workflow buttons/forms | `ui/src/config/listActions.ts` plus `ElevasisUIProvider listActions={listActions}` / `createElevasisApp({ listActions })` | The shared UI owns the registry contract. The project owns workflow ids, action keys, Zod schemas, layouts, and default inputs. |
@@ -209,7 +209,7 @@ Available field component variants: `textinput`, `textarea`, `numberinput`, `swi
209
209
  ```tsx
210
210
  import * as z from 'zod'
211
211
  import { leadGenManifest, type ListBuilderRegistry } from '@elevasis/ui/features/lead-gen'
212
- import type { StepConfigLayout } from '@elevasis/ui/components/forms'
212
+ import type { StepConfigLayout } from '@elevasis/ui/components'
213
213
  import { ElevasisSystemsProvider, ElevasisUIProvider } from '@elevasis/ui/provider'
214
214
  import { organizationModel, resourceDescriptors } from '@core/config/organization-model'
215
215
 
@@ -351,6 +351,8 @@ Inside deployed workflows, use worker adapters instead of browser hooks or direc
351
351
 
352
352
  External projects should define workflow input/output schemas in `@shared/types`; the example below assumes those shared schemas already exist.
353
353
 
354
+ <!-- doc-snippet:skip: illustrative excerpt -- `@shared/types` is a project-local alias for the reader's own shared schema module, `resourceDescriptors` names the project's own resource-descriptors export, and `z` (zod) is shown unimported -->
355
+
354
356
  ```ts
355
357
  // operations/src/sales/qualify-list.ts
356
358
  import type { WorkflowDefinition } from '@elevasis/sdk'
@@ -363,6 +365,7 @@ export const qualifyListWorkflow: WorkflowDefinition = {
363
365
  resource: resourceDescriptors.qualifyList,
364
366
  resourceId: resourceDescriptors.qualifyList.id,
365
367
  name: 'Qualify List',
368
+ description: 'Marks list contacts as verified based on qualification checks.',
366
369
  type: resourceDescriptors.qualifyList.kind,
367
370
  version: '1.0.0',
368
371
  status: 'dev',
@@ -372,10 +375,12 @@ export const qualifyListWorkflow: WorkflowDefinition = {
372
375
  qualify: {
373
376
  id: 'qualify',
374
377
  name: 'Qualify',
378
+ description: 'Fetches list contacts and marks each verified.',
375
379
  inputSchema: qualifyListInputSchema,
376
380
  outputSchema: qualifyListOutputSchema,
377
381
  next: null,
378
- handler: async (input, context) => {
382
+ handler: async (rawInput, context) => {
383
+ const input = rawInput as z.infer<typeof qualifyListInputSchema>
379
384
  const config = await list.getConfig({ listId: input.listId })
380
385
  const contacts = await acqDb.listContacts({ listId: input.listId, limit: 100, offset: 0 })
381
386
 
@@ -490,7 +495,7 @@ export const organizationModel = {
490
495
  }
491
496
  ```
492
497
 
493
- `readinessContract.requiredObjects` and `requiredCatalogs` are arrays of ontology IDs owned by this system. The platform validates that each declared object type exists in the OM and that each declared catalog type has at least one entry. The `requiredKinds` field is reserved for future profile extensions; omit it today.
498
+ `readinessContract.requiredObjects` and `requiredCatalogs` are arrays of ontology IDs owned by this system. The platform validates that each declared object type exists in the OM and that each declared catalog type has at least one entry. `requiredCatalogs` must declare at least one entry an empty contract asserts nothing and is rejected.
494
499
 
495
500
  Built-in profile ids (`sales.lead-gen.api`, etc.) derive their requirements from platform code. If you use a built-in profile on a custom system, you do not need a `readinessContract`.
496
501
 
@@ -500,17 +505,21 @@ The `lookupReadinessProfile`, `registerReadinessProfile`, and `isBuiltInReadines
500
505
 
501
506
  The export channel — ClickUp, CSV/XLSX file, platform push, or a custom destination — is an action + credential choice declared in your tenant OM. The platform owns the list-builder workflow primitive and the file storage adapters; you own which workflow id handles export and which credential it uses.
502
507
 
508
+ <!-- doc-snippet:skip: illustrative excerpt -- `@shared/types` is a project-local alias for the reader's own shared schema module, and `buildCsvFromContacts` is a tenant-authored helper this recipe does not define -->
509
+
503
510
  ```ts
504
511
  // operations/src/sales/prospecting/export-list.ts
505
512
  import type { WorkflowDefinition } from '@elevasis/sdk'
506
- import { list, storage } from '@elevasis/sdk/worker'
513
+ import { acqDb, list, storage } from '@elevasis/sdk/worker'
507
514
  import { exportListInputSchema, exportListOutputSchema } from '@shared/types'
515
+ import { resourceDescriptors } from '@core/config/organization-model'
508
516
 
509
517
  export const exportListWorkflow: WorkflowDefinition = {
510
518
  config: {
511
519
  resource: resourceDescriptors.exportList,
512
520
  resourceId: resourceDescriptors.exportList.id,
513
521
  name: 'Export List',
522
+ description: 'Exports list contacts to a CSV file in project storage.',
514
523
  type: 'workflow',
515
524
  version: '1.0.0',
516
525
  status: 'prod'
@@ -520,10 +529,13 @@ export const exportListWorkflow: WorkflowDefinition = {
520
529
  export: {
521
530
  id: 'export',
522
531
  name: 'Export',
532
+ description: 'Fetches list contacts, builds a CSV, and uploads it to storage.',
523
533
  inputSchema: exportListInputSchema,
524
534
  outputSchema: exportListOutputSchema,
525
535
  next: null,
526
- handler: async (input, context) => {
536
+ handler: async (rawInput, context) => {
537
+ const input = rawInput as z.infer<typeof exportListInputSchema>
538
+
527
539
  // Fetch contacts from the acquisition substrate
528
540
  const contacts = await acqDb.listContacts({ listId: input.listId, limit: 5000, offset: 0 })
529
541
 
@@ -560,6 +572,8 @@ The `ListTelemetry.stageCounts` field is now a `Record<string, number>` — one
560
572
 
561
573
  To define custom stages, author them in the `catalogTypes` scope of your lead-gen system:
562
574
 
575
+ <!-- doc-snippet:skip: illustrative excerpt, not a standalone compilable file -->
576
+
563
577
  ```ts
564
578
  ontology: {
565
579
  catalogTypes: {
@@ -582,6 +596,8 @@ ontology: {
582
596
 
583
597
  **`readinessTarget` — declaring the pipeline objective.** To tell the platform which stage is the "ready / next-focus" milestone for your pipeline, mark exactly one catalog entry with `readinessTarget: true`:
584
598
 
599
+ <!-- doc-snippet:skip: illustrative excerpt, not a standalone compilable file -->
600
+
585
601
  ```ts
586
602
  entries: {
587
603
  'sourced': { label: 'Sourced', order: 10 },
@@ -597,6 +613,8 @@ The `LeadGenOverviewPage` uses this field to derive a "contacts ready for \<stag
597
613
 
598
614
  Point the `listBuilderWorkflow` factory at your tenant resource and step handlers. The factory validates `stageKey` inputs against your catalog at construction time, not at runtime:
599
615
 
616
+ <!-- doc-snippet:skip: illustrative excerpt -- `resourceDescriptors` names the project's own resource-descriptors export, and `sourceCompaniesStep`/`enrichCompaniesStep`/`qualifyCompaniesStep` are the reader's own step handlers, not defined in this excerpt -->
617
+
600
618
  ```ts
601
619
  // operations/src/sales/prospecting/list-builder.ts
602
620
  import { listBuilderWorkflow } from '@elevasis/sdk/worker'
@@ -619,7 +637,7 @@ Register this workflow in `DeploymentSpec.workflows` alongside the export workfl
619
637
  Run the checks for the surfaces you touched:
620
638
 
621
639
  ```bash
622
- pnpm -C ui run check
640
+ pnpm -C ui run check-types
623
641
  pnpm -C operations run check
624
642
  pnpm -C operations exec elevasis-sdk check
625
643
  ```