@elevasis/sdk 1.8.2 → 1.9.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 (62) hide show
  1. package/dist/cli.cjs +289 -105
  2. package/dist/index.d.ts +90 -39
  3. package/dist/types/worker/adapters/lead.d.ts +1 -1
  4. package/dist/worker/index.js +2 -0
  5. package/package.json +2 -2
  6. package/reference/_navigation.md +7 -1
  7. package/reference/_reference-manifest.json +14 -0
  8. package/reference/claude-config/logs/scaffold-registry-reminder.log +3 -0
  9. package/reference/claude-config/rules/agent-start-here.md +254 -254
  10. package/reference/claude-config/rules/frontend.md +43 -43
  11. package/reference/claude-config/rules/operations.md +64 -64
  12. package/reference/claude-config/rules/organization-model.md +42 -43
  13. package/reference/claude-config/rules/organization-os.md +107 -107
  14. package/reference/claude-config/rules/shared-types.md +2 -2
  15. package/reference/claude-config/rules/task-tracking.md +1 -1
  16. package/reference/claude-config/rules/ui.md +202 -202
  17. package/reference/claude-config/rules/vibe.md +202 -202
  18. package/reference/claude-config/skills/configure/SKILL.md +98 -98
  19. package/reference/claude-config/skills/configure/operations/codify-level-a.md +100 -100
  20. package/reference/claude-config/skills/configure/operations/codify-level-b.md +158 -158
  21. package/reference/claude-config/skills/configure/operations/customers.md +150 -150
  22. package/reference/claude-config/skills/configure/operations/features.md +162 -162
  23. package/reference/claude-config/skills/configure/operations/goals.md +147 -147
  24. package/reference/claude-config/skills/configure/operations/identity.md +133 -133
  25. package/reference/claude-config/skills/configure/operations/labels.md +128 -128
  26. package/reference/claude-config/skills/configure/operations/offerings.md +159 -159
  27. package/reference/claude-config/skills/configure/operations/roles.md +153 -153
  28. package/reference/claude-config/skills/configure/operations/techStack.md +139 -139
  29. package/reference/claude-config/skills/explore/SKILL.md +78 -78
  30. package/reference/claude-config/skills/git-sync/SKILL.md +126 -0
  31. package/reference/claude-config/skills/save/SKILL.md +183 -183
  32. package/reference/claude-config/skills/setup/SKILL.md +275 -275
  33. package/reference/claude-config/skills/sync/SKILL.md +10 -44
  34. package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +27 -0
  35. package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +30 -0
  36. package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +86 -0
  37. package/reference/claude-config/sync-notes/README.md +43 -0
  38. package/reference/deployment/index.mdx +42 -7
  39. package/reference/examples/organization-model.ts +689 -0
  40. package/reference/index.mdx +6 -5
  41. package/reference/packages/core/src/README.md +39 -36
  42. package/reference/packages/core/src/business/README.md +52 -52
  43. package/reference/packages/core/src/organization-model/README.md +97 -97
  44. package/reference/packages/core/src/test-utils/README.md +42 -0
  45. package/reference/scaffold/core/organization-graph.mdx +272 -272
  46. package/reference/scaffold/core/organization-model.mdx +320 -320
  47. package/reference/scaffold/index.mdx +64 -64
  48. package/reference/scaffold/operations/propagation-pipeline.md +125 -104
  49. package/reference/scaffold/operations/scaffold-maintenance.md +122 -122
  50. package/reference/scaffold/operations/workflow-recipes.md +436 -436
  51. package/reference/scaffold/recipes/add-a-feature.md +158 -158
  52. package/reference/scaffold/recipes/add-a-resource.md +158 -158
  53. package/reference/scaffold/recipes/customize-organization-model.md +400 -400
  54. package/reference/scaffold/recipes/extend-a-base-entity.md +140 -140
  55. package/reference/scaffold/recipes/gate-by-feature-or-admin.md +158 -158
  56. package/reference/scaffold/recipes/index.md +32 -32
  57. package/reference/scaffold/reference/contracts.md +608 -607
  58. package/reference/scaffold/reference/feature-registry.md +2 -0
  59. package/reference/scaffold/reference/glossary.md +105 -105
  60. package/reference/scaffold/ui/composition-extensibility.mdx +1 -1
  61. package/reference/scaffold/ui/feature-flags-and-gating.md +1 -1
  62. package/reference/claude-config/commands/submit-request.md +0 -11
@@ -1,158 +1,158 @@
1
- ---
2
- title: Add a Feature
3
- description: End-to-end walkthrough for adding a new shell feature (e.g., analytics) from org-model key through manifest, routes, and gating.
4
- ---
5
-
6
- # Add a Feature
7
-
8
- End-to-end: add a new shell feature such as `analytics`. Steps are sequential.
9
-
10
- See [glossary.md](../reference/glossary.md) for term disambiguation throughout this recipe (Feature has three distinct contexts). See [contracts.md](../reference/contracts.md) for authoritative TypeScript shapes.
11
-
12
- ---
13
-
14
- ## 1. Decide the feature shape
15
-
16
- A shell feature requires a `feature.id` in the org model's `features[]` array to gate it. You have two options:
17
-
18
- - **Reuse an existing feature** (e.g., `operations`, `monitoring`). The new shell module shares the on/off toggle with the existing feature entry. Fine for sub-modules within the same product area.
19
- - **Add a new feature object** -- add an entry to the `features[]` array in `foundations/config/organization-model.ts`. This is always a template-local change; no core package change is required.
20
-
21
- For a genuinely new capability (e.g., `analytics`), you add a feature object to the defaults array and author a matching manifest.
22
-
23
- See [glossary.md](../reference/glossary.md) under **Feature** (three contexts).
24
-
25
- ---
26
-
27
- ## 2. Update the organization model
28
-
29
- File: `foundations/config/organization-model.ts`
30
-
31
- Add a new feature object to the `features[]` array passed to `defineOrganizationModel`.
32
-
33
- ```ts
34
- import { defineOrganizationModel } from '@elevasis/core/organization-model'
35
- ```
36
-
37
- Use typed constants for the 7 platform features (`SALES_FEATURE_ID`, `PROSPECTING_FEATURE_ID`, `PROJECTS_FEATURE_ID`, `OPERATIONS_FEATURE_ID`, `MONITORING_FEATURE_ID`, `SETTINGS_FEATURE_ID`, `SEO_FEATURE_ID`); use string literals for project-specific features you invent.
38
-
39
- ```ts
40
- const foundationOrganizationModelOverride = defineOrganizationModel({
41
- features: [
42
- // ... existing features
43
- {
44
- id: 'analytics',
45
- label: 'Analytics',
46
- enabled: false, // start disabled
47
- entityIds: [],
48
- surfaceIds: [],
49
- resourceIds: [],
50
- capabilityIds: []
51
- }
52
- ],
53
- // ... rest of model
54
- })
55
- ```
56
-
57
- Each field of the feature object:
58
-
59
- - `id` -- unique stable identifier; this is the value `FeatureModule.featureId` must match
60
- - `label` -- display name; used by nav label resolution when no manifest override is provided
61
- - `enabled` -- org-wide default; `MembershipFeatureConfig.features` can override per member
62
- - `entityIds`, `surfaceIds`, `resourceIds`, `capabilityIds` -- semantic references (leave empty to start)
63
-
64
- No domain entry or separate key resolver is needed. The `features[]` array is the sole source of truth.
65
-
66
- **Two-step pattern:** in a template-derived project, the `defineOrganizationModel` output is passed to `createFoundationOrganizationModel(override)` in `foundations/config/organization-model.ts`. The result exposes `.model`, `.canonical`, and `.homeLabel`. See `external/_template/foundations/config/organization-model.ts` for the canonical two-step example.
67
-
68
- ---
69
-
70
- ## 3. Author the FeatureModule
71
-
72
- Create `ui/src/features/analytics/manifest.ts`. Full `FeatureModule` shape is in [contracts.md](../reference/contracts.md#featuremodule) (`@elevasis/ui/provider`).
73
-
74
- ```ts
75
- import type { FeatureModule } from '@elevasis/ui/provider'
76
- import { IconChartBar } from '@tabler/icons-react'
77
- import { AnalyticsSidebar } from './sidebar'
78
-
79
- export const analyticsManifest: FeatureModule = {
80
- key: 'analytics',
81
- featureId: 'analytics', // must match a feature.id in the org model's features[] array
82
- navEntry: {
83
- label: 'Analytics',
84
- icon: IconChartBar,
85
- link: '/analytics'
86
- },
87
- sidebar: AnalyticsSidebar,
88
- subshellRoutes: ['/analytics', '/analytics/reports']
89
- }
90
- ```
91
-
92
- Key fields:
93
-
94
- - `featureId` -- the org-model feature ID that gates the entire feature. The provider throws at startup if this ID is not found in the org model's `features[]` array. See [glossary.md](../reference/glossary.md) under **featureId**.
95
- - `sidebar` -- a component that renders the subshell sidebar. Compose from published primitives. See [customization.md](../ui/customization.md).
96
- - `subshellRoutes` -- every path that should activate this feature's sidebar.
97
-
98
- Register the manifest in `ui/src/routes/__root.tsx` by adding it to the `FEATURE_MANIFESTS` array passed to `ElevasisFeaturesProvider`.
99
-
100
- ---
101
-
102
- ## 4. Add routes under the subshell
103
-
104
- Create the TanStack Router layout and child routes.
105
-
106
- Layout file (`ui/src/routes/analytics.tsx`) owns the subshell guard and renders `<Outlet />`:
107
-
108
- ```tsx
109
- import { createFileRoute, Outlet } from '@tanstack/react-router'
110
- import { ProtectedRoute } from '@/features/auth'
111
- import { FeatureGuard } from '@/features/auth/guards/FeatureGuard'
112
-
113
- export const Route = createFileRoute('/analytics')({
114
- component: AnalyticsLayout
115
- })
116
-
117
- function AnalyticsLayout() {
118
- return (
119
- <ProtectedRoute>
120
- <FeatureGuard featureKey="analytics">
121
- <Outlet />
122
- </FeatureGuard>
123
- </ProtectedRoute>
124
- )
125
- }
126
- ```
127
-
128
- Child pages go under `ui/src/routes/analytics/`. See [UI Recipes](../ui/recipes.md) recipe 2 for the nested page pattern.
129
-
130
- ---
131
-
132
- ## 5. Gate the route
133
-
134
- Two independent mechanisms -- use both:
135
-
136
- - `FeatureGuard` (feature-level): blocks access when the org model has the feature key disabled or when the member's `MembershipFeatureConfig` disables it. Always nest inside `ProtectedRoute`.
137
- - `AdminGuard` (admin-level): blocks access for non-admin members. Add this if the feature should only be accessible to admins.
138
-
139
- Full decision table and import paths are in [gate-by-feature-or-admin.md](gate-by-feature-or-admin.md).
140
-
141
- ---
142
-
143
- ## 6. (Optional) Add operations resources that back the feature
144
-
145
- If the feature drives automation (e.g., an analytics pipeline workflow), create the resources in `operations/src/` and optionally map them into the org model via `resourceMappings`. See [add-a-resource.md](add-a-resource.md).
146
-
147
- ---
148
-
149
- ## 7. Verify
150
-
151
- ```bash
152
- pnpm -C ui dev
153
- ```
154
-
155
- - Feature appears in the nav sidebar.
156
- - Route is accessible and the subshell sidebar renders.
157
- - Toggle `features.enabled.analytics` to `false` in `foundations/config/organization-model.ts` and confirm the nav item disappears and the route redirects.
158
- - Check `FeatureGuard` by navigating directly to `/analytics` with the feature disabled.
1
+ ---
2
+ title: Add a Feature
3
+ description: End-to-end walkthrough for adding a new shell feature (e.g., analytics) from org-model key through manifest, routes, and gating.
4
+ ---
5
+
6
+ # Add a Feature
7
+
8
+ End-to-end: add a new shell feature such as `analytics`. Steps are sequential.
9
+
10
+ See [glossary.md](../reference/glossary.md) for term disambiguation throughout this recipe (Feature has three distinct contexts). See [contracts.md](../reference/contracts.md) for authoritative TypeScript shapes.
11
+
12
+ ---
13
+
14
+ ## 1. Decide the feature shape
15
+
16
+ A shell feature requires a `feature.id` in the org model's `features[]` array to gate it. You have two options:
17
+
18
+ - **Reuse an existing feature** (e.g., `operations`, `monitoring`). The new shell module shares the on/off toggle with the existing feature entry. Fine for sub-modules within the same product area.
19
+ - **Add a new feature object** -- add an entry to the `features[]` array in `foundations/config/organization-model.ts`. This is always a template-local change; no core package change is required.
20
+
21
+ For a genuinely new capability (e.g., `analytics`), you add a feature object to the defaults array and author a matching manifest.
22
+
23
+ See [glossary.md](../reference/glossary.md) under **Feature** (three contexts).
24
+
25
+ ---
26
+
27
+ ## 2. Update the organization model
28
+
29
+ File: `foundations/config/organization-model.ts`
30
+
31
+ Add a new feature object to the `features[]` array passed to `defineOrganizationModel`.
32
+
33
+ ```ts
34
+ import { defineOrganizationModel } from '@elevasis/core/organization-model'
35
+ ```
36
+
37
+ Use typed constants for the 7 platform features (`SALES_FEATURE_ID`, `PROSPECTING_FEATURE_ID`, `PROJECTS_FEATURE_ID`, `OPERATIONS_FEATURE_ID`, `MONITORING_FEATURE_ID`, `SETTINGS_FEATURE_ID`, `SEO_FEATURE_ID`); use string literals for project-specific features you invent.
38
+
39
+ ```ts
40
+ const foundationOrganizationModelOverride = defineOrganizationModel({
41
+ features: [
42
+ // ... existing features
43
+ {
44
+ id: 'analytics',
45
+ label: 'Analytics',
46
+ enabled: false, // start disabled
47
+ entityIds: [],
48
+ surfaceIds: [],
49
+ resourceIds: [],
50
+ capabilityIds: []
51
+ }
52
+ ],
53
+ // ... rest of model
54
+ })
55
+ ```
56
+
57
+ Each field of the feature object:
58
+
59
+ - `id` -- unique stable identifier; this is the value `FeatureModule.featureId` must match
60
+ - `label` -- display name; used by nav label resolution when no manifest override is provided
61
+ - `enabled` -- org-wide default; `MembershipFeatureConfig.features` can override per member
62
+ - `entityIds`, `surfaceIds`, `resourceIds`, `capabilityIds` -- semantic references (leave empty to start)
63
+
64
+ No domain entry or separate key resolver is needed. The `features[]` array is the sole source of truth.
65
+
66
+ **Two-step pattern:** in a template-derived project, the `defineOrganizationModel` output is passed to `createFoundationOrganizationModel(override)` in `foundations/config/organization-model.ts`. The result exposes `.model`, `.canonical`, and `.homeLabel`. See `external/_template/foundations/config/organization-model.ts` for the canonical two-step example.
67
+
68
+ ---
69
+
70
+ ## 3. Author the FeatureModule
71
+
72
+ Create `ui/src/features/analytics/manifest.ts`. Full `FeatureModule` shape is in [contracts.md](../reference/contracts.md#featuremodule) (`@elevasis/ui/provider`).
73
+
74
+ ```ts
75
+ import type { FeatureModule } from '@elevasis/ui/provider'
76
+ import { IconChartBar } from '@tabler/icons-react'
77
+ import { AnalyticsSidebar } from './sidebar'
78
+
79
+ export const analyticsManifest: FeatureModule = {
80
+ key: 'analytics',
81
+ featureId: 'analytics', // must match a feature.id in the org model's features[] array
82
+ navEntry: {
83
+ label: 'Analytics',
84
+ icon: IconChartBar,
85
+ link: '/analytics'
86
+ },
87
+ sidebar: AnalyticsSidebar,
88
+ subshellRoutes: ['/analytics', '/analytics/reports']
89
+ }
90
+ ```
91
+
92
+ Key fields:
93
+
94
+ - `featureId` -- the org-model feature ID that gates the entire feature. The provider throws at startup if this ID is not found in the org model's `features[]` array. See [glossary.md](../reference/glossary.md) under **featureId**.
95
+ - `sidebar` -- a component that renders the subshell sidebar. Compose from published primitives. See [customization.md](../ui/customization.md).
96
+ - `subshellRoutes` -- every path that should activate this feature's sidebar.
97
+
98
+ Register the manifest in `ui/src/routes/__root.tsx` by adding it to the `FEATURE_MANIFESTS` array passed to `ElevasisFeaturesProvider`.
99
+
100
+ ---
101
+
102
+ ## 4. Add routes under the subshell
103
+
104
+ Create the TanStack Router layout and child routes.
105
+
106
+ Layout file (`ui/src/routes/analytics.tsx`) owns the subshell guard and renders `<Outlet />`:
107
+
108
+ ```tsx
109
+ import { createFileRoute, Outlet } from '@tanstack/react-router'
110
+ import { ProtectedRoute } from '@/features/auth'
111
+ import { FeatureGuard } from '@/features/auth/guards/FeatureGuard'
112
+
113
+ export const Route = createFileRoute('/analytics')({
114
+ component: AnalyticsLayout
115
+ })
116
+
117
+ function AnalyticsLayout() {
118
+ return (
119
+ <ProtectedRoute>
120
+ <FeatureGuard featureKey="analytics">
121
+ <Outlet />
122
+ </FeatureGuard>
123
+ </ProtectedRoute>
124
+ )
125
+ }
126
+ ```
127
+
128
+ Child pages go under `ui/src/routes/analytics/`. See [UI Recipes](../ui/recipes.md) recipe 2 for the nested page pattern.
129
+
130
+ ---
131
+
132
+ ## 5. Gate the route
133
+
134
+ Two independent mechanisms -- use both:
135
+
136
+ - `FeatureGuard` (feature-level): blocks access when the org model has the feature key disabled or when the member's `MembershipFeatureConfig` disables it. Always nest inside `ProtectedRoute`.
137
+ - `AdminGuard` (admin-level): blocks access for non-admin members. Add this if the feature should only be accessible to admins.
138
+
139
+ Full decision table and import paths are in [gate-by-feature-or-admin.md](gate-by-feature-or-admin.md).
140
+
141
+ ---
142
+
143
+ ## 6. (Optional) Add operations resources that back the feature
144
+
145
+ If the feature drives automation (e.g., an analytics pipeline workflow), create the resources in `operations/src/` and optionally map them into the org model via `resourceMappings`. See [add-a-resource.md](add-a-resource.md).
146
+
147
+ ---
148
+
149
+ ## 7. Verify
150
+
151
+ ```bash
152
+ pnpm -C ui dev
153
+ ```
154
+
155
+ - Feature appears in the nav sidebar.
156
+ - Route is accessible and the subshell sidebar renders.
157
+ - Toggle `features.enabled.analytics` to `false` in `foundations/config/organization-model.ts` and confirm the nav item disappears and the route redirects.
158
+ - Check `FeatureGuard` by navigating directly to `/analytics` with the feature disabled.
@@ -1,158 +1,158 @@
1
- ---
2
- title: Add a Resource
3
- description: End-to-end walkthrough for adding a new workflow or agent to the deployment spec, declaring relationships, and verifying in the resource inventory.
4
- ---
5
-
6
- # Add a Resource
7
-
8
- End-to-end: add a new workflow or agent to `operations/` and verify it in the platform inventory. Steps are sequential.
9
-
10
- See [glossary.md](../reference/glossary.md) under **Resource**, **DeploymentSpec**, and **Topology**. See [contracts.md](../reference/contracts.md) for `OrganizationModel` and `OrganizationModelResourceMapping` shapes.
11
-
12
- ---
13
-
14
- ## 1. Author the resource
15
-
16
- Create `operations/src/<name>/index.ts`. Follow the anatomy from [workflow-recipes.md](../operations/workflow-recipes.md) recipe 1 for the full `WorkflowDefinition` shape.
17
-
18
- ```ts
19
- import type { WorkflowDefinition } from '@elevasis/sdk'
20
- import { StepType } from '@elevasis/sdk'
21
- import { myInputSchema, myOutputSchema } from '@foundation/types'
22
-
23
- export const myWorkflow: WorkflowDefinition = {
24
- config: {
25
- resourceId: 'my-workflow',
26
- name: 'My Workflow',
27
- type: 'workflow',
28
- version: '1.0.0',
29
- status: 'dev'
30
- },
31
- contract: {
32
- inputSchema: myInputSchema,
33
- outputSchema: myOutputSchema
34
- },
35
- steps: {
36
- run: {
37
- id: 'run',
38
- name: 'Run',
39
- handler: async (rawInput, context) => {
40
- context.logger.info('[run] starting')
41
- // ...
42
- return { result: 'done' }
43
- },
44
- inputSchema: myInputSchema,
45
- outputSchema: myOutputSchema,
46
- next: null
47
- }
48
- },
49
- entryPoint: 'run'
50
- }
51
- ```
52
-
53
- Define input/output schemas in `foundations/types/index.ts`, not inline. Both runtimes import from `@foundation/types`. See [workflow-recipes.md](../operations/workflow-recipes.md) for Zod schema conventions and adapter usage (`llm`, `storage`, `scheduler`, `notifications` from `@elevasis/sdk/worker`).
54
-
55
- **Entity-backed workflows:** if your workflow operates on a domain entity (Project, Deal, Company, etc.), define or reference the entity shape in `foundations/types/entities.ts` rather than declaring an ad-hoc shape here. The entity types extend base contracts from `@elevasis/core/entities` (`BaseProject`, `BaseDeal`, etc.) with project-specific metadata. See [./extend-a-base-entity.md](./extend-a-base-entity.md) for the pattern.
56
-
57
- ---
58
-
59
- ## 2. Register in the DeploymentSpec
60
-
61
- Create an exports barrel at `operations/src/<name>/exports.ts`:
62
-
63
- ```ts
64
- import { myWorkflow } from './index.js'
65
- import type { WorkflowDefinition } from '@elevasis/sdk'
66
-
67
- export const workflows: WorkflowDefinition[] = [myWorkflow]
68
- export const agents: never[] = []
69
- ```
70
-
71
- Then spread into the top-level spec at `operations/src/index.ts`:
72
-
73
- ```ts
74
- import * as myFeature from './my-feature/exports.js'
75
-
76
- const org: DeploymentSpec = {
77
- version: '0.1.0',
78
- workflows: [...existing.workflows, ...myFeature.workflows],
79
- agents: [...existing.agents, ...myFeature.agents]
80
- }
81
- ```
82
-
83
- Use `.js` extensions in imports even though source is TypeScript -- required for ESM interoperability.
84
-
85
- ---
86
-
87
- ## 3. (Optional) Declare relationships
88
-
89
- If the resource triggers another resource, uses a human checkpoint, or depends on an integration, declare those relationships on the `DeploymentSpec`. See [glossary.md](../reference/glossary.md) under **Topology** for the three edge types (`triggers`, `uses`, `approval`).
90
-
91
- ```ts
92
- const org: DeploymentSpec = {
93
- // ...
94
- relationships: {
95
- 'my-workflow': {
96
- triggers: { workflows: ['email-notification'] }
97
- }
98
- },
99
- humanCheckpoints: [
100
- {
101
- resourceId: 'approval-gate',
102
- name: 'Approve before sending',
103
- type: 'human',
104
- version: '1.0.0',
105
- status: 'prod',
106
- routesTo: { workflows: ['my-workflow'] }
107
- }
108
- ]
109
- }
110
- ```
111
-
112
- Full relationship and checkpoint types are defined in `@elevasis/sdk` (`DeploymentSpec`). Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly.
113
-
114
- ---
115
-
116
- ## 4. (Optional) Map to a domain
117
-
118
- To make the resource referenceable from the org model (so the Operations graph and Command View can link to it), add an entry to `resourceMappings` in `foundations/config/organization-model.ts`:
119
-
120
- ```ts
121
- resourceMappings: [
122
- {
123
- id: 'my-workflow',
124
- resourceId: 'my-workflow',
125
- resourceType: 'workflow',
126
- domainIds: ['operations'],
127
- label: 'My Workflow'
128
- }
129
- ]
130
- ```
131
-
132
- See `OrganizationModelResourceMapping` in [contracts.md](../reference/contracts.md) for the full shape.
133
-
134
- ---
135
-
136
- ## 5. Verify resource inventory
137
-
138
- Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly. Confirm the new resource appears with the correct `resourceId`, `version`, and `status`.
139
-
140
- ---
141
-
142
- ## 6. Verify
143
-
144
- Validate and deploy:
145
-
146
- ```bash
147
- pnpm -C operations run check # validate resource definitions
148
- pnpm -C operations run deploy # deploy to dev
149
- ```
150
-
151
- Execute via the platform CLI from the project root:
152
-
153
- ```bash
154
- pnpm exec elevasis describe Elevasis/my-workflow
155
- pnpm exec elevasis exec Elevasis/my-workflow --input '{"field": "value"}'
156
- ```
157
-
158
- Use `--async` for long-running resources. Use `pnpm exec elevasis --prod exec ...` (flag before `exec`) for production. See [workflow-recipes.md](../operations/workflow-recipes.md) recipe 3 for the low-level frontend trigger pattern (`useApiClient` + `useMutation`). For the higher-level UI pattern using `RunResourceButton`, `useExecuteResource`, and `ZodFormRenderer`, see [../ui/recipes.md](../ui/recipes.md) recipe 6.
1
+ ---
2
+ title: Add a Resource
3
+ description: End-to-end walkthrough for adding a new workflow or agent to the deployment spec, declaring relationships, and verifying in the resource inventory.
4
+ ---
5
+
6
+ # Add a Resource
7
+
8
+ End-to-end: add a new workflow or agent to `operations/` and verify it in the platform inventory. Steps are sequential.
9
+
10
+ See [glossary.md](../reference/glossary.md) under **Resource**, **DeploymentSpec**, and **Topology**. See [contracts.md](../reference/contracts.md) for `OrganizationModel` and `OrganizationModelResourceMapping` shapes.
11
+
12
+ ---
13
+
14
+ ## 1. Author the resource
15
+
16
+ Create `operations/src/<name>/index.ts`. Follow the anatomy from [workflow-recipes.md](../operations/workflow-recipes.md) recipe 1 for the full `WorkflowDefinition` shape.
17
+
18
+ ```ts
19
+ import type { WorkflowDefinition } from '@elevasis/sdk'
20
+ import { StepType } from '@elevasis/sdk'
21
+ import { myInputSchema, myOutputSchema } from '@foundation/types'
22
+
23
+ export const myWorkflow: WorkflowDefinition = {
24
+ config: {
25
+ resourceId: 'my-workflow',
26
+ name: 'My Workflow',
27
+ type: 'workflow',
28
+ version: '1.0.0',
29
+ status: 'dev'
30
+ },
31
+ contract: {
32
+ inputSchema: myInputSchema,
33
+ outputSchema: myOutputSchema
34
+ },
35
+ steps: {
36
+ run: {
37
+ id: 'run',
38
+ name: 'Run',
39
+ handler: async (rawInput, context) => {
40
+ context.logger.info('[run] starting')
41
+ // ...
42
+ return { result: 'done' }
43
+ },
44
+ inputSchema: myInputSchema,
45
+ outputSchema: myOutputSchema,
46
+ next: null
47
+ }
48
+ },
49
+ entryPoint: 'run'
50
+ }
51
+ ```
52
+
53
+ Define input/output schemas in `foundations/types/index.ts`, not inline. Both runtimes import from `@foundation/types`. See [workflow-recipes.md](../operations/workflow-recipes.md) for Zod schema conventions and adapter usage (`llm`, `storage`, `scheduler`, `notifications` from `@elevasis/sdk/worker`).
54
+
55
+ **Entity-backed workflows:** if your workflow operates on a domain entity (Project, Deal, Company, etc.), define or reference the entity shape in `foundations/types/entities.ts` rather than declaring an ad-hoc shape here. The entity types extend base contracts from `@elevasis/core/entities` (`BaseProject`, `BaseDeal`, etc.) with project-specific metadata. See [./extend-a-base-entity.md](./extend-a-base-entity.md) for the pattern.
56
+
57
+ ---
58
+
59
+ ## 2. Register in the DeploymentSpec
60
+
61
+ Create an exports barrel at `operations/src/<name>/exports.ts`:
62
+
63
+ ```ts
64
+ import { myWorkflow } from './index.js'
65
+ import type { WorkflowDefinition } from '@elevasis/sdk'
66
+
67
+ export const workflows: WorkflowDefinition[] = [myWorkflow]
68
+ export const agents: never[] = []
69
+ ```
70
+
71
+ Then spread into the top-level spec at `operations/src/index.ts`:
72
+
73
+ ```ts
74
+ import * as myFeature from './my-feature/exports.js'
75
+
76
+ const org: DeploymentSpec = {
77
+ version: '0.1.0',
78
+ workflows: [...existing.workflows, ...myFeature.workflows],
79
+ agents: [...existing.agents, ...myFeature.agents]
80
+ }
81
+ ```
82
+
83
+ Use `.js` extensions in imports even though source is TypeScript -- required for ESM interoperability.
84
+
85
+ ---
86
+
87
+ ## 3. (Optional) Declare relationships
88
+
89
+ If the resource triggers another resource, uses a human checkpoint, or depends on an integration, declare those relationships on the `DeploymentSpec`. See [glossary.md](../reference/glossary.md) under **Topology** for the three edge types (`triggers`, `uses`, `approval`).
90
+
91
+ ```ts
92
+ const org: DeploymentSpec = {
93
+ // ...
94
+ relationships: {
95
+ 'my-workflow': {
96
+ triggers: { workflows: ['email-notification'] }
97
+ }
98
+ },
99
+ humanCheckpoints: [
100
+ {
101
+ resourceId: 'approval-gate',
102
+ name: 'Approve before sending',
103
+ type: 'human',
104
+ version: '1.0.0',
105
+ status: 'prod',
106
+ routesTo: { workflows: ['my-workflow'] }
107
+ }
108
+ ]
109
+ }
110
+ ```
111
+
112
+ Full relationship and checkpoint types are defined in `@elevasis/sdk` (`DeploymentSpec`). Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly.
113
+
114
+ ---
115
+
116
+ ## 4. (Optional) Map to a domain
117
+
118
+ To make the resource referenceable from the org model (so the Operations graph and Command View can link to it), add an entry to `resourceMappings` in `foundations/config/organization-model.ts`:
119
+
120
+ ```ts
121
+ resourceMappings: [
122
+ {
123
+ id: 'my-workflow',
124
+ resourceId: 'my-workflow',
125
+ resourceType: 'workflow',
126
+ featureIds: ['operations'],
127
+ label: 'My Workflow'
128
+ }
129
+ ]
130
+ ```
131
+
132
+ See `OrganizationModelResourceMapping` in [contracts.md](../reference/contracts.md) for the full shape.
133
+
134
+ ---
135
+
136
+ ## 5. Verify resource inventory
137
+
138
+ Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly. Confirm the new resource appears with the correct `resourceId`, `version`, and `status`.
139
+
140
+ ---
141
+
142
+ ## 6. Verify
143
+
144
+ Validate and deploy:
145
+
146
+ ```bash
147
+ pnpm -C operations run check # validate resource definitions
148
+ pnpm -C operations run deploy # deploy to dev
149
+ ```
150
+
151
+ Execute via the platform CLI from the project root:
152
+
153
+ ```bash
154
+ pnpm exec elevasis describe Elevasis/my-workflow
155
+ pnpm exec elevasis exec Elevasis/my-workflow --input '{"field": "value"}'
156
+ ```
157
+
158
+ Use `--async` for long-running resources. Use `pnpm exec elevasis --prod exec ...` (flag before `exec`) for production. See [workflow-recipes.md](../operations/workflow-recipes.md) recipe 3 for the low-level frontend trigger pattern (`useApiClient` + `useMutation`). For the higher-level UI pattern using `RunResourceButton`, `useExecuteResource`, and `ZodFormRenderer`, see [../ui/recipes.md](../ui/recipes.md) recipe 6.