@elevasis/sdk 1.44.3 → 1.46.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 (259) hide show
  1. package/dist/cli.cjs +35026 -30226
  2. package/dist/index.d.ts +1786 -808
  3. package/dist/index.js +789 -739
  4. package/dist/node/index.d.ts +105 -181
  5. package/dist/node/index.js +2 -2
  6. package/dist/test-utils/index.d.ts +901 -359
  7. package/dist/test-utils/index.js +587 -824
  8. package/dist/worker/index.d.ts +12685 -0
  9. package/dist/worker/index.js +188 -216
  10. package/package.json +4 -7
  11. package/reference/_navigation.md +161 -22
  12. package/reference/_reference-manifest.json +228 -4
  13. package/reference/claude-config.md +8 -0
  14. package/reference/core/exports.mdx +2 -0
  15. package/reference/core/index.mdx +3 -3
  16. package/reference/examples/organization-model.ts +117 -111
  17. package/reference/index.mdx +4 -4
  18. package/reference/packages/core/src/business/README.md +4 -1
  19. package/reference/packages/core/src/content/README.md +19 -0
  20. package/reference/packages/core/src/organization-model/README.md +148 -149
  21. package/reference/packages/core/src/organization-model/readiness/README.md +42 -0
  22. package/reference/packages/ui/src/features/README.md +28 -28
  23. package/reference/rules/active-change-index.md +40 -54
  24. package/reference/rules/agent-runtime.md +81 -0
  25. package/reference/rules/agent-start-here.md +71 -163
  26. package/reference/rules/deployment.md +33 -10
  27. package/reference/rules/error-handling.md +26 -0
  28. package/reference/rules/execution.md +13 -0
  29. package/reference/rules/frontend.md +10 -3
  30. package/reference/rules/observability.md +9 -1
  31. package/reference/rules/operations.md +26 -17
  32. package/reference/rules/organization-model.md +74 -88
  33. package/reference/rules/organization-os.md +71 -88
  34. package/reference/rules/package-taxonomy.md +11 -2
  35. package/reference/rules/platform.md +13 -7
  36. package/reference/rules/shared-types.md +36 -0
  37. package/reference/rules/task-tracking.md +30 -5
  38. package/reference/rules/ui.md +145 -3
  39. package/reference/rules/vibe-intents.md +271 -0
  40. package/reference/rules/vibe.md +17 -243
  41. package/reference/scaffold/core/organization-graph.mdx +112 -99
  42. package/reference/scaffold/core/organization-model.mdx +231 -215
  43. package/reference/scaffold/operations/propagation-pipeline.md +16 -17
  44. package/reference/scaffold/operations/scaffold-maintenance.md +22 -20
  45. package/reference/scaffold/operations/workflow-recipes.md +72 -20
  46. package/reference/scaffold/recipes/add-a-feature.md +156 -146
  47. package/reference/scaffold/recipes/add-a-resource.md +123 -117
  48. package/reference/scaffold/recipes/customize-crm-actions.md +28 -13
  49. package/reference/scaffold/recipes/customize-knowledge-browser.md +52 -117
  50. package/reference/scaffold/recipes/customize-organization-model.md +161 -149
  51. package/reference/scaffold/recipes/extend-a-base-entity.md +156 -140
  52. package/reference/scaffold/recipes/extend-content.md +265 -0
  53. package/reference/scaffold/recipes/extend-crm.md +16 -11
  54. package/reference/scaffold/recipes/extend-lead-gen.md +37 -21
  55. package/reference/scaffold/recipes/gate-by-feature-or-admin.md +160 -118
  56. package/reference/scaffold/recipes/index.md +6 -3
  57. package/reference/scaffold/recipes/query-the-knowledge-graph.md +23 -23
  58. package/reference/scaffold/reference/contracts.md +30 -56
  59. package/reference/scaffold/reference/feature-registry.md +3 -0
  60. package/reference/scaffold/reference/glossary.md +4 -4
  61. package/reference/scaffold/reference/system-interface-capabilities.md +5 -4
  62. package/reference/scaffold/ui/composition-extensibility.mdx +271 -232
  63. package/reference/scaffold/ui/customization.md +2 -2
  64. package/reference/scaffold/ui/feature-flags-and-gating.md +14 -6
  65. package/reference/scaffold/ui/feature-shell.mdx +277 -62
  66. package/reference/scaffold/ui/recipes.md +229 -197
  67. package/reference/sdk/cli-management.mdx +166 -33
  68. package/reference/sdk/cli.mdx +90 -13
  69. package/reference/sdk/concepts.mdx +2 -0
  70. package/reference/sdk/define-builders.mdx +76 -0
  71. package/reference/sdk/deployment/command-center.mdx +6 -2
  72. package/reference/sdk/deployment/execution-reference.mdx +64 -186
  73. package/reference/sdk/deployment/index.mdx +2 -0
  74. package/reference/sdk/exports.mdx +4 -4
  75. package/reference/sdk/framework/agent.mdx +52 -116
  76. package/reference/sdk/framework/index.mdx +46 -65
  77. package/reference/sdk/framework/project-structure.mdx +150 -205
  78. package/reference/sdk/framework/tutorial-system.mdx +2 -2
  79. package/reference/sdk/human-in-the-loop.mdx +152 -0
  80. package/reference/sdk/index.mdx +6 -7
  81. package/reference/sdk/platform-tools/adapters-platform.mdx +3 -1
  82. package/reference/sdk/platform-tools/index.mdx +12 -0
  83. package/reference/sdk/platform-tools/type-safety.mdx +4 -0
  84. package/reference/sdk/project-deployment-spec.mdx +131 -0
  85. package/reference/sdk/resources/index.mdx +21 -7
  86. package/reference/sdk/resources/patterns.mdx +54 -24
  87. package/reference/sdk/resources/types.mdx +7 -4
  88. package/reference/sdk/templates/data-enrichment.mdx +7 -3
  89. package/reference/sdk/templates/email-sender.mdx +139 -135
  90. package/reference/sdk/templates/lead-scorer.mdx +5 -1
  91. package/reference/sdk/templates/pdf-generator.mdx +155 -151
  92. package/reference/sdk/templates/recurring-job.mdx +195 -189
  93. package/reference/sdk/templates/text-classifier.mdx +4 -0
  94. package/reference/sdk/templates/web-scraper.mdx +139 -135
  95. package/reference/spine/spine-primer.md +135 -96
  96. package/reference/ui/exports.mdx +1 -0
  97. package/reference/ui/index.mdx +14 -7
  98. package/dist/types/worker/adapters/anymailfinder.d.ts +0 -14
  99. package/dist/types/worker/adapters/apify.d.ts +0 -14
  100. package/dist/types/worker/adapters/approval.d.ts +0 -23
  101. package/dist/types/worker/adapters/attio.d.ts +0 -22
  102. package/dist/types/worker/adapters/clickup.d.ts +0 -22
  103. package/dist/types/worker/adapters/create-adapter.d.ts +0 -41
  104. package/dist/types/worker/adapters/crm.d.ts +0 -20
  105. package/dist/types/worker/adapters/dropbox.d.ts +0 -14
  106. package/dist/types/worker/adapters/email.d.ts +0 -25
  107. package/dist/types/worker/adapters/execution.d.ts +0 -22
  108. package/dist/types/worker/adapters/gmail.d.ts +0 -14
  109. package/dist/types/worker/adapters/google-sheets.d.ts +0 -14
  110. package/dist/types/worker/adapters/index.d.ts +0 -33
  111. package/dist/types/worker/adapters/instantly.d.ts +0 -14
  112. package/dist/types/worker/adapters/lead.d.ts +0 -28
  113. package/dist/types/worker/adapters/list.d.ts +0 -9
  114. package/dist/types/worker/adapters/llm.d.ts +0 -45
  115. package/dist/types/worker/adapters/millionverifier.d.ts +0 -14
  116. package/dist/types/worker/adapters/notification.d.ts +0 -28
  117. package/dist/types/worker/adapters/pdf.d.ts +0 -22
  118. package/dist/types/worker/adapters/projects.d.ts +0 -20
  119. package/dist/types/worker/adapters/resend.d.ts +0 -14
  120. package/dist/types/worker/adapters/scheduler.d.ts +0 -25
  121. package/dist/types/worker/adapters/signature-api.d.ts +0 -14
  122. package/dist/types/worker/adapters/storage.d.ts +0 -33
  123. package/dist/types/worker/adapters/stripe.d.ts +0 -14
  124. package/dist/types/worker/adapters/tomba.d.ts +0 -14
  125. package/dist/types/worker/index.d.ts +0 -60
  126. package/dist/types/worker/platform.d.ts +0 -90
  127. package/dist/types/worker/utils.d.ts +0 -9
  128. package/reference/claude-config/Overview.md +0 -230
  129. package/reference/claude-config/hooks/post-edit-validate.mjs +0 -98
  130. package/reference/claude-config/hooks/scaffold-registry-reminder.mjs +0 -187
  131. package/reference/claude-config/hooks/tool-failure-recovery.mjs +0 -73
  132. package/reference/claude-config/registries/graph-skills.json +0 -4
  133. package/reference/claude-config/registries/knowledge-flags.json +0 -154
  134. package/reference/claude-config/registries/skill-coverage.json +0 -20
  135. package/reference/claude-config/rules/active-change-index.md +0 -22
  136. package/reference/claude-config/rules/agent-start-here.md +0 -22
  137. package/reference/claude-config/rules/deployment.md +0 -22
  138. package/reference/claude-config/rules/error-handling.md +0 -22
  139. package/reference/claude-config/rules/execution.md +0 -22
  140. package/reference/claude-config/rules/frontend.md +0 -22
  141. package/reference/claude-config/rules/observability.md +0 -22
  142. package/reference/claude-config/rules/operations.md +0 -22
  143. package/reference/claude-config/rules/organization-model.md +0 -22
  144. package/reference/claude-config/rules/organization-os.md +0 -22
  145. package/reference/claude-config/rules/package-taxonomy.md +0 -22
  146. package/reference/claude-config/rules/platform.md +0 -22
  147. package/reference/claude-config/rules/shared-types.md +0 -22
  148. package/reference/claude-config/rules/task-tracking.md +0 -22
  149. package/reference/claude-config/rules/topbar-actions.md +0 -70
  150. package/reference/claude-config/rules/ui.md +0 -22
  151. package/reference/claude-config/rules/vibe.md +0 -22
  152. package/reference/claude-config/scripts/statusline-command.js +0 -18
  153. package/reference/claude-config/settings.json +0 -30
  154. package/reference/claude-config/skills/client/SKILL.md +0 -201
  155. package/reference/claude-config/skills/deploy/SKILL.md +0 -159
  156. package/reference/claude-config/skills/dsp/SKILL.md +0 -66
  157. package/reference/claude-config/skills/elevasis/SKILL.md +0 -251
  158. package/reference/claude-config/skills/explore/SKILL.md +0 -78
  159. package/reference/claude-config/skills/git-sync/SKILL.md +0 -166
  160. package/reference/claude-config/skills/om/SKILL.md +0 -475
  161. package/reference/claude-config/skills/om/operations/build.md +0 -237
  162. package/reference/claude-config/skills/om/operations/codify-level-a.md +0 -109
  163. package/reference/claude-config/skills/om/operations/codify-level-b.md +0 -159
  164. package/reference/claude-config/skills/om/operations/customers.md +0 -114
  165. package/reference/claude-config/skills/om/operations/features.md +0 -88
  166. package/reference/claude-config/skills/om/operations/goals.md +0 -123
  167. package/reference/claude-config/skills/om/operations/identity.md +0 -97
  168. package/reference/claude-config/skills/om/operations/labels.md +0 -110
  169. package/reference/claude-config/skills/om/operations/offerings.md +0 -114
  170. package/reference/claude-config/skills/om/operations/roles.md +0 -104
  171. package/reference/claude-config/skills/om/operations/scaffold.md +0 -163
  172. package/reference/claude-config/skills/om/operations/techStack.md +0 -38
  173. package/reference/claude-config/skills/project/SKILL.md +0 -1114
  174. package/reference/claude-config/skills/run-ui/SKILL.md +0 -73
  175. package/reference/claude-config/skills/save/SKILL.md +0 -183
  176. package/reference/claude-config/skills/setup/SKILL.md +0 -290
  177. package/reference/claude-config/skills/status/SKILL.md +0 -59
  178. package/reference/claude-config/skills/submit-request/SKILL.md +0 -180
  179. package/reference/claude-config/skills/sync/SKILL.md +0 -47
  180. package/reference/claude-config/skills/tutorial/SKILL.md +0 -259
  181. package/reference/claude-config/skills/tutorial/progress-template.md +0 -74
  182. package/reference/claude-config/skills/tutorial/technical.md +0 -1303
  183. package/reference/claude-config/skills/tutorial/vibe-coder.md +0 -890
  184. package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +0 -27
  185. package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +0 -30
  186. package/reference/claude-config/sync-notes/2026-04-24-test-utils-and-template-tests.md +0 -73
  187. package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +0 -86
  188. package/reference/claude-config/sync-notes/2026-04-25-auth-role-system-and-settings-roles.md +0 -55
  189. package/reference/claude-config/sync-notes/2026-04-27-crm-hitl-action-layer-cutover.md +0 -97
  190. package/reference/claude-config/sync-notes/2026-04-27-lead-gen-substrate-train.md +0 -112
  191. package/reference/claude-config/sync-notes/2026-04-29-crm-state-and-lead-gen-processing-status.md +0 -93
  192. package/reference/claude-config/sync-notes/2026-05-02-crm-ownership-next-action.md +0 -58
  193. package/reference/claude-config/sync-notes/2026-05-02-template-hardcode-workos-config.md +0 -56
  194. package/reference/claude-config/sync-notes/2026-05-04-elevasis-workspace.md +0 -71
  195. package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +0 -83
  196. package/reference/claude-config/sync-notes/2026-05-04-template-skills-run-ui-and-tutorial.md +0 -59
  197. package/reference/claude-config/sync-notes/2026-05-05-list-builder.md +0 -42
  198. package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +0 -60
  199. package/reference/claude-config/sync-notes/2026-05-06-sdk-changes-release-train.md +0 -37
  200. package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +0 -34
  201. package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +0 -38
  202. package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +0 -32
  203. package/reference/claude-config/sync-notes/2026-05-09-command-system.md +0 -33
  204. package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +0 -69
  205. package/reference/claude-config/sync-notes/2026-05-12-sdk-ready-release-train.md +0 -30
  206. package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +0 -45
  207. package/reference/claude-config/sync-notes/2026-05-15-om-skill-rename-and-write-family.md +0 -52
  208. package/reference/claude-config/sync-notes/2026-05-17-sdk-boundary-consolidation.md +0 -33
  209. package/reference/claude-config/sync-notes/2026-05-20-om-define-helpers.md +0 -32
  210. package/reference/claude-config/sync-notes/2026-05-22-access-model-and-right-panel.md +0 -43
  211. package/reference/claude-config/sync-notes/2026-05-22-lead-gen-tenant-config.md +0 -40
  212. package/reference/claude-config/sync-notes/2026-05-22-org-model-multi-file-split.md +0 -61
  213. package/reference/claude-config/sync-notes/2026-05-23-branding-names-to-identity.md +0 -49
  214. package/reference/claude-config/sync-notes/2026-05-23-lead-gen-manage-access.md +0 -31
  215. package/reference/claude-config/sync-notes/2026-05-23-om-deployment-drift-detection.md +0 -42
  216. package/reference/claude-config/sync-notes/2026-05-23-om-full-model-deploy-contract.md +0 -33
  217. package/reference/claude-config/sync-notes/2026-05-23-ui-sdk-package-fixes.md +0 -37
  218. package/reference/claude-config/sync-notes/2026-05-24-platform-invite-router-core-baseline.md +0 -28
  219. package/reference/claude-config/sync-notes/2026-05-24-system-interface-readiness.md +0 -43
  220. package/reference/claude-config/sync-notes/2026-05-25-invitation-login-loader.md +0 -26
  221. package/reference/claude-config/sync-notes/2026-05-25-om-topbar-requests.md +0 -33
  222. package/reference/claude-config/sync-notes/2026-05-25-system-interface-profile-registry-and-substrate.md +0 -35
  223. package/reference/claude-config/sync-notes/2026-05-25-tenant-om-scaffold-cli.md +0 -49
  224. package/reference/claude-config/sync-notes/2026-05-25-vibe-operate-intent.md +0 -47
  225. package/reference/claude-config/sync-notes/2026-05-28-om-snapshot-sdk-workflow-config.md +0 -33
  226. package/reference/claude-config/sync-notes/2026-05-30-client-source-and-om-profiles.md +0 -39
  227. package/reference/claude-config/sync-notes/2026-06-02-knowledge-nested-group-routing.md +0 -27
  228. package/reference/claude-config/sync-notes/2026-06-02-nest-projects-under-platform.md +0 -45
  229. package/reference/claude-config/sync-notes/2026-06-03-skill-autogen-and-client-skill.md +0 -34
  230. package/reference/claude-config/sync-notes/2026-06-04-scaffold-registry-lane-severity.md +0 -34
  231. package/reference/claude-config/sync-notes/2026-06-05-appearance-app-mode-decouple.md +0 -29
  232. package/reference/claude-config/sync-notes/2026-06-05-ontology-endpoint-rename-and-knowledge-browser-ui.md +0 -86
  233. package/reference/claude-config/sync-notes/2026-06-06-om-build-systems-scaffold.md +0 -47
  234. package/reference/claude-config/sync-notes/2026-06-06-om-item-copy-references.md +0 -50
  235. package/reference/claude-config/sync-notes/2026-06-08-knowledge-base-page-not-found-fix.md +0 -76
  236. package/reference/claude-config/sync-notes/2026-06-09-agent-sessions-public-agent-chat-route.md +0 -75
  237. package/reference/claude-config/sync-notes/2026-06-09-sdk-cli-load-org-model-resolution.md +0 -42
  238. package/reference/claude-config/sync-notes/2026-06-12-agent-grants-visualizer-operations.md +0 -30
  239. package/reference/claude-config/sync-notes/2026-06-14-session-ux-and-project-cli-json.md +0 -33
  240. package/reference/claude-config/sync-notes/2026-06-14-shared-session-conversation-view.md +0 -26
  241. package/reference/claude-config/sync-notes/2026-06-15-session-chat-zero-wiring.md +0 -46
  242. package/reference/claude-config/sync-notes/2026-06-17-agent-session-ux-features.md +0 -34
  243. package/reference/claude-config/sync-notes/2026-06-25-shared-page-scroll-contract-guard.md +0 -52
  244. package/reference/claude-config/sync-notes/2026-06-26-leadgen-overview-om-telemetry.md +0 -47
  245. package/reference/claude-config/sync-notes/2026-07-21-agent-scaffold-hardening.md +0 -75
  246. package/reference/claude-config/sync-notes/2026-07-23-agent-session-memory.md +0 -49
  247. package/reference/claude-config/sync-notes/2026-07-23-workos-org-marker.md +0 -50
  248. package/reference/claude-config/sync-notes/2026-07-24-claude-5-models-and-session-surface-fixes.md +0 -116
  249. package/reference/claude-config/sync-notes/2026-07-27-agent-strict-output-and-turn-drift.md +0 -73
  250. package/reference/claude-config/sync-notes/2026-07-28-agent-reply-is-its-own-field.md +0 -84
  251. package/reference/claude-config/sync-notes/2026-07-30-login-screen-and-member-provisioning-state.md +0 -114
  252. package/reference/claude-config/sync-notes/2026-08-02-auth-guard-defaults-and-truncation-fix.md +0 -122
  253. package/reference/claude-config/sync-notes/2026-08-03-agent-prose-escape-normalization.md +0 -88
  254. package/reference/claude-config/sync-notes/2026-08-03-cli-gateway-errors-and-request-timeout.md +0 -120
  255. package/reference/claude-config/sync-notes/README.md +0 -43
  256. package/reference/sdk/framework/interaction-guidance.mdx +0 -182
  257. package/reference/sdk/framework/memory.mdx +0 -326
  258. package/reference/sdk/framework/resource-documentation.mdx +0 -90
  259. 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
@@ -0,0 +1,265 @@
1
+ ---
2
+ title: Build and Extend Content
3
+ description: Map the content platform primitives available to SDK projects: pipeline and step catalogs, shared review/pipeline/distribution pages, data hooks, the content workflow adapter, artifacts as rules documents, and org-model extension boundaries.
4
+ ---
5
+ <!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
6
+ <!-- Regenerate: pnpm scaffold:sync -->
7
+
8
+
9
+ # Build and Extend Content
10
+
11
+ Use this recipe when a downstream project wants to build on the shared content system instead of forking it.
12
+
13
+ Good trigger phrases:
14
+
15
+ - "Add a content pipeline for our podcast."
16
+ - "Change the review screen for clip proposals."
17
+ - "Write a workflow that produces the next step of a content item."
18
+ - "Store our style guide so producers read the same rules."
19
+ - "Track where each piece got published."
20
+
21
+ Content is a layered platform surface, not one component:
22
+
23
+ - **Organization OS:** pipelines, steps, statuses, pillars, and platforms are **catalogs** in the content System's ontology, not hardcoded enums. `content.config.defaultPipelineId` names the pipeline the UI opens by default.
24
+ - **Shared UI:** overview, items list, item review, pipelines, pipeline workspace, distributions, and rules-and-artifacts pages live in `@elevasis/ui/features/content`.
25
+ - **Headless hooks:** item, attempt, distribution, artifact, and pipeline-summary hooks live under `@elevasis/ui/hooks`.
26
+ - **Workflow adapter:** `content` from `@elevasis/sdk/worker` lets workflows create items, record attempts, and open distributions through platform tools.
27
+ - **Rules documents:** governing documents (idea banks, ICP docs, style guides, selection briefs) are **artifacts**, reached through the `artifacts` adapter, not a content-specific table.
28
+ - **System API Interface:** `content` uses the flat `system.apiInterface` marker. Readiness is derived from scoped resources, ontology bindings, and required catalogs — `content:object/item` plus the pipeline, step, and status catalogs.
29
+
30
+ ## The one thing to understand first: a pipeline is data
31
+
32
+ Every other system in this scaffold has its structure in code. Content does not. A pipeline is a catalog record, its steps are a second catalog record, and a workflow claims a step **by step key**. Adding a pipeline is therefore an org-model edit plus one workflow per step — no changes to shared UI, no new routes, no fork.
33
+
34
+ ```
35
+ content:catalog/pipeline which pipelines exist
36
+ content:catalog/{pipeline}-steps the ordered steps of one pipeline
37
+ content:catalog/status item lifecycle statuses
38
+ content:catalog/pillar editorial pillars (optional)
39
+ content:catalog/platform distribution targets
40
+ ```
41
+
42
+ A pipeline's step catalog is named `content:catalog/{pipelineId}-steps` and referenced from the pipeline record's `stepCatalog`. Get that name wrong and the workspace renders an empty pipeline with no error — the binding is by string.
43
+
44
+ ## Decision Table
45
+
46
+ | User wants | Start here | Notes |
47
+ | ------------------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
48
+ | Add a pipeline, step, status, pillar, or platform | `core/config/organization-model.ts` — the content System's `ontology` | Catalog edit. Add the step catalog **and** point the pipeline record's `stepCatalog` at it. |
49
+ | Produce the next step of an item from a workflow | `content` from `@elevasis/sdk/worker` | One workflow per step. Claim the step with `stepKey`; return the next step key. |
50
+ | Change the review screen | `ContentItemReviewPage` slots, or compose `ContentReviewCard` yourself | Prefer slots. The card, action bar, alternates panel, and processing strip are all exported individually. |
51
+ | Add content nav or a content route | `CONTENT_ITEMS`, `ContentSidebar`, `ContentSidebarMiddle` | Same manifest/sidebar composition pattern as CRM and lead-gen. |
52
+ | Store a governing document producers should read | `artifacts` from `@elevasis/sdk/worker` | `kind` MUST start with `content:` or RLS rejects an org-owned write. Pass `pipelineId` or `getActive` never finds it. |
53
+ | Track where a piece was published | `createDistribution` / `updateDistribution` | One distribution row per platform per item. |
54
+ | Add a new persisted content column or table | Platform/API migration work, not just scaffold work | DB, core schemas/types, API service/handlers, hooks, docs, and scaffold contracts move together. |
55
+
56
+ ## Published Content Surfaces
57
+
58
+ | Surface | Import from | Use for |
59
+ | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------- |
60
+ | `contentManifest`, `CONTENT_ITEMS`, `ContentSidebar`, `ContentSidebarTop`, `ContentSidebarMiddle`, `MyReviewQueuePanel` | `@elevasis/ui/features/content` | Feature registration and sidebar composition |
61
+ | `ContentOverviewPage`, `ContentItemsPage`, `ContentItemReviewPage`, `ContentPipelinesPage`, `ContentPipelineWorkspacePage` | `@elevasis/ui/features/content` | Shared pages you can route to or wrap |
62
+ | `ContentSettingsPage`, `ContentDistributionsPage`, `ContentDistributionDetailPage` | `@elevasis/ui/features/content` | Rules-and-artifacts and distribution surfaces |
63
+ | `ContentReviewCard`, `ReviewActionBar`, `PayloadBody`, `AlternatesPanel`, `ProcessingStateStrip` | `@elevasis/ui/features/content` | Review UI primitives for a custom review screen |
64
+ | `useContentConfig`, `resolveContentStepResource` | `@elevasis/ui/features/content` | Read the resolved pipeline/step catalogs from OM |
65
+ | `useContentItems`, `useContentItem`, `useContentItemAttempts`, `useUpdateContentItem`, `useReviewContentItem` | `@elevasis/ui/hooks` | Item data access and review mutations |
66
+ | `useContentDistributions`, `useContentDistribution`, `useUpdateContentDistribution` | `@elevasis/ui/hooks` | Distribution data access |
67
+ | `useContentArtifacts`, `filterContentArtifacts`, `useContentPipelineSummary` | `@elevasis/ui/hooks` | Rules documents and pipeline roll-ups |
68
+ | `content`, `artifacts` | `@elevasis/sdk/worker` | Workflow-side content and rules-document adapters |
69
+
70
+ Read the generated contracts before changing typed boundaries:
71
+
72
+ `operations/node_modules/@elevasis/sdk/reference/scaffold/reference/contracts.md`
73
+
74
+ Look for the **Content Platform Primitives** section: item/attempt/distribution rows, review decisions, the status and pillar vocabularies, and the `ContentToolMap` adapter map.
75
+
76
+ ## 1. Add a Pipeline
77
+
78
+ A pipeline is two catalog records plus the workflows that claim its steps.
79
+
80
+ <!-- doc-snippet:skip: illustrative excerpt -- catalog shape, not a compilable module -->
81
+
82
+ ```ts
83
+ // core/config/organization-model.ts -- inside the content System's `ontology.catalogTypes`
84
+ 'content:catalog/pipeline': {
85
+ entries: {
86
+ 'podcast-to-clips': {
87
+ label: 'Podcast to Clips',
88
+ stepCatalog: 'content:catalog/podcast-to-clips-steps'
89
+ }
90
+ }
91
+ },
92
+ 'content:catalog/podcast-to-clips-steps': {
93
+ entries: {
94
+ 'transcript': { label: 'Transcript', order: 1 },
95
+ 'clip-selection': { label: 'Clip Selection', order: 2 },
96
+ 'publish': { label: 'Publish', order: 3 }
97
+ }
98
+ }
99
+ ```
100
+
101
+ Then set `content.config.defaultPipelineId` if this should be the pipeline the UI opens first.
102
+
103
+ **The step catalog name is load-bearing.** `content:catalog/{pipelineId}-steps` must match the pipeline record's `stepCatalog` exactly. Nothing type-checks that string.
104
+
105
+ ## 2. Produce a Step in a Workflow
106
+
107
+ One workflow per step. The workflow records an **attempt** against the item, tagged with the step it satisfies:
108
+
109
+ <!-- doc-snippet:skip: illustrative excerpt -- `resourceDescriptors` names the project's own resource-descriptors export -->
110
+
111
+ ```ts
112
+ // operations/src/content/clip-selection.ts
113
+ import type { WorkflowDefinition } from '@elevasis/sdk'
114
+ import { content } from '@elevasis/sdk/worker'
115
+ import { resourceDescriptors } from '@core/config/organization-model'
116
+ import { z } from 'zod'
117
+
118
+ const inputSchema = z.object({ contentItemId: z.string().uuid() })
119
+ const outputSchema = z.object({ attemptId: z.string(), nextStepKey: z.string().nullable() })
120
+
121
+ export const clipSelectionWorkflow: WorkflowDefinition = {
122
+ config: {
123
+ resource: resourceDescriptors.clipSelection,
124
+ resourceId: resourceDescriptors.clipSelection.id,
125
+ name: 'Clip Selection',
126
+ description: 'Chooses clip candidates for a podcast episode.',
127
+ type: resourceDescriptors.clipSelection.kind,
128
+ version: '1.0.0',
129
+ status: 'dev'
130
+ },
131
+ contract: { inputSchema, outputSchema },
132
+ steps: {
133
+ select: {
134
+ id: 'select',
135
+ name: 'Select Clips',
136
+ description: 'Records a clip-selection attempt against the item.',
137
+ inputSchema,
138
+ outputSchema,
139
+ next: null,
140
+ handler: async (rawInput, context) => {
141
+ const input = rawInput as z.infer<typeof inputSchema>
142
+ const item = await content.getItem({ contentItemId: input.contentItemId })
143
+
144
+ const attempt = await content.createAttempt({
145
+ contentItemId: item.id,
146
+ // Tags the attempt with the step it satisfies. Omit it and the
147
+ // attempt is stored with a null step -- the review UI's Step column
148
+ // renders "--" and nothing tells you which step produced the row.
149
+ stepKey: 'clip-selection',
150
+ payload: { clips: [] },
151
+ sourceExecutionId: context.executionId
152
+ })
153
+
154
+ return { attemptId: attempt.id, nextStepKey: 'publish' }
155
+ }
156
+ }
157
+ },
158
+ entryPoint: 'select'
159
+ }
160
+ ```
161
+
162
+ `ContentToolMap` is the full surface: `createItem`, `getItem`, `listItems`, `updateItem`, `createAttempt`, `listAttempts`, `createDistribution`, `updateDistribution`. `organizationId` is injected server-side — never pass it from workflow code.
163
+
164
+ ## 3. Store Rules Documents
165
+
166
+ Governing documents are artifacts, not a content table. Two rules decide whether a write is reachable at all:
167
+
168
+ ```ts
169
+ import { artifacts } from '@elevasis/sdk/worker'
170
+
171
+ // `kind` MUST be `content:`-prefixed. The artifacts_manage_content RLS policy
172
+ // grants org-owned writes only for `kind LIKE 'content:%'` -- a non-prefixed
173
+ // kind is rejected server-side with no compile-time warning.
174
+ //
175
+ // `pipelineId` MUST be supplied. getActive filters on
176
+ // (organizationId, pipelineId, kind); an artifact written without one can
177
+ // never be read back by the lookup every consumer uses.
178
+ await artifacts.createArtifact({
179
+ ownerKind: 'organization',
180
+ ownerId: null,
181
+ kind: 'content:style-guide',
182
+ pipelineId: 'podcast-to-clips',
183
+ content: { tone: 'direct', bannedPhrases: ['synergy'] }
184
+ })
185
+
186
+ const { artifact } = await artifacts.getActive({
187
+ pipelineId: 'podcast-to-clips',
188
+ kind: 'content:style-guide'
189
+ })
190
+ ```
191
+
192
+ Writing again for the same `(pipelineId, kind)` supersedes the previous version rather than colliding: the platform deactivates the predecessor and stores the new row at the next version number, atomically. `getActive` always returns the current one, and `ContentSettingsPage` renders the version history.
193
+
194
+ `ContentSettingsPage` scopes its browser to **declared** pipelines. An artifact written under a `pipelineId` that is not in `content:catalog/pipeline` is stored correctly and is invisible in that UI.
195
+
196
+ ## 4. Customize the Review Screen
197
+
198
+ Start with slots on the shared page:
199
+
200
+ ```tsx
201
+ // ui/src/routes/content/items.$itemId.tsx
202
+ import { createFileRoute } from '@tanstack/react-router'
203
+ import { ContentItemReviewPage } from '@elevasis/ui/features/content'
204
+ import { Button } from '@mantine/core'
205
+
206
+ export const Route = createFileRoute('/content/items/$itemId')({ component: ReviewRoute })
207
+
208
+ function ReviewRoute() {
209
+ const { itemId } = Route.useParams()
210
+ return <ContentItemReviewPage itemId={itemId} headerActions={<Button>Send to Legal</Button>} />
211
+ }
212
+ ```
213
+
214
+ When the layout itself has to change, compose the primitives — `ContentReviewCard`, `ReviewActionBar`, `PayloadBody`, `AlternatesPanel`, `ProcessingStateStrip` — with `useContentItem`, `useContentItemAttempts`, and `useReviewContentItem`. Read the pipeline's steps through `useContentConfig` rather than hardcoding them, or a new step silently fails to render.
215
+
216
+ ## 5. Extend Navigation
217
+
218
+ Same pattern as the other systems:
219
+
220
+ ```tsx
221
+ import { contentManifest, CONTENT_ITEMS, ContentSidebar, ContentSidebarMiddle } from '@elevasis/ui/features/content'
222
+ import type { SystemModule } from '@elevasis/ui/provider'
223
+ import type { NavItem } from '@elevasis/ui/layout'
224
+ import { IconChartBar } from '@tabler/icons-react'
225
+
226
+ const customItems: NavItem[] = [
227
+ ...CONTENT_ITEMS,
228
+ { label: 'Performance', to: '/content/performance', icon: IconChartBar, exact: false }
229
+ ]
230
+
231
+ export const customContentManifest: SystemModule = {
232
+ ...contentManifest,
233
+ sidebar: () => (
234
+ <ContentSidebar>
235
+ <ContentSidebarMiddle items={customItems} />
236
+ </ContentSidebar>
237
+ )
238
+ }
239
+ ```
240
+
241
+ Replace `contentManifest` with `customContentManifest` in the local `SYSTEM_MANIFESTS` array and add the matching route under `ui/src/routes/content/`.
242
+
243
+ ## 6. Mark the System API-Ready
244
+
245
+ `content.apiInterface.lifecycle` goes `active` only when the System's scoped resources, `content:object/item`, and the pipeline/step/status catalogs are all in place. Two failure modes are worth knowing before you flip it:
246
+
247
+ - An **empty** `apiInterface.resourceIds` array throws rather than opting out. Omitting the whole `apiInterface` block is the opt-out; a `resourceIds: []` stub is the anomaly.
248
+ - Readiness is derived from a **deployed** snapshot. A model edit that has not been redeployed produces a stale-snapshot 503 that looks like a code bug. Redeploy before debugging.
249
+
250
+ ## Verify
251
+
252
+ Run the checks for the surfaces you touched:
253
+
254
+ ```bash
255
+ pnpm -C ui run check-types
256
+ pnpm -C operations run check
257
+ pnpm -C operations exec elevasis-sdk check
258
+ ```
259
+
260
+ If you changed platform-level content contracts in the monorepo, the platform maintainer must also regenerate and verify scaffold output:
261
+
262
+ ```bash
263
+ pnpm scaffold:sync
264
+ pnpm scaffold:verify
265
+ ```
@@ -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
  ```