@elevasis/sdk 1.51.0 → 1.52.1

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 (32) hide show
  1. package/dist/{chunk-HIVK54X6.js → chunk-T6DTAP2U.js} +121 -18
  2. package/dist/{chunk-NNRXVYNC.js → chunk-XC57JNMA.js} +79 -19
  3. package/dist/cli.cjs +151 -19
  4. package/dist/index.d.ts +248 -1
  5. package/dist/index.js +1 -1
  6. package/dist/test-utils/index.d.ts +13 -2
  7. package/dist/test-utils/index.js +16 -3
  8. package/dist/worker/index.d.ts +1 -1
  9. package/dist/worker/index.js +2 -2
  10. package/package.json +2 -2
  11. package/reference/_navigation.md +4 -5
  12. package/reference/_reference-manifest.json +0 -14
  13. package/reference/packages/ui/src/hooks/README.md +22 -23
  14. package/reference/rules/content.md +4 -1
  15. package/reference/rules/frontend.md +2 -2
  16. package/reference/rules/organization-os.md +1 -1
  17. package/reference/rules/ui.md +18 -16
  18. package/reference/rules/vibe-intents.md +28 -6
  19. package/reference/rules/vibe.md +3 -2
  20. package/reference/scaffold/operations/propagation-pipeline.md +33 -19
  21. package/reference/scaffold/operations/scaffold-maintenance.md +1 -1
  22. package/reference/scaffold/recipes/customize-crm-actions.md +1 -1
  23. package/reference/scaffold/recipes/extend-content.md +262 -14
  24. package/reference/scaffold/recipes/extend-crm.md +4 -2
  25. package/reference/scaffold/recipes/extend-lead-gen.md +34 -5
  26. package/reference/scaffold/ui/customization.md +5 -5
  27. package/reference/scaffold/ui/recipes.md +11 -15
  28. package/reference/sdk/platform-tools/adapters-integration.mdx +2 -1
  29. package/reference/sdk/platform-tools/adapters-platform.mdx +1 -1
  30. package/reference/sdk/platform-tools/index.mdx +7 -7
  31. package/reference/sdk/resources/index.mdx +8 -8
  32. package/reference/ui/exports.mdx +0 -1
@@ -18,18 +18,20 @@ The template frontend is a React 19 + TanStack Router app that composes a local
18
18
  The main join points are:
19
19
 
20
20
  - `ui/src/main.tsx` -- boots the app with `ElevasisUIProvider`, query client, theme config, WorkOS AuthKit, notifications, and the generated route tree
21
- - `ui/src/routes/__root.tsx` -- composes the authenticated shell with `ElevasisSystemsProvider`, published System modules, app-local dashboard nav, shell runtime dependencies, and `SystemShell`
22
- - `ui/src/config/nav-items.ts` -- keeps the host-local dashboard entry separate from the published feature manifests
21
+ - `ui/src/config/shell.tsx` -- **the file you own for shell composition.** Declares the `SYSTEM_MANIFESTS` array of published System modules the shell mounts. Add, remove, or swap a System module here
22
+ - `ui/src/routes/__root.tsx` -- composes the authenticated shell: imports `SYSTEM_MANIFESTS` from `@/config/shell`, filters it through `selectDeclaredSystems` against `canonicalOrganizationModel`, and passes the result plus shell runtime dependencies into `ElevasisSystemsProvider` / `SystemShell`. This file is sync-managed -- edit `shell.tsx` instead
23
23
  - `core/config/organization-model.ts` -- is the template's semantic source of truth, adapting `@elevasis/core/organization-model` into the preserved branding, dashboard label, quick-access, System labels, resource descriptors, and shell helpers
24
24
 
25
- Published System modules mounted by the template shell:
25
+ Published System modules mounted by the template shell, in `ui/src/config/shell.tsx`'s `SYSTEM_MANIFESTS` order:
26
26
 
27
- - `lead-gen`
28
- - `crm`
29
- - `delivery` at `/projects`
30
- - `operations`
31
- - `monitoring`
32
- - `settings`
27
+ - `leadGenManifest` -- lead-gen
28
+ - `crmManifest` -- CRM
29
+ - `deliveryManifest` -- delivery, at `/projects`
30
+ - `operationsManifest` -- operations
31
+ - `submittedRequestsManifest` -- submitted requests, from `@elevasis/ui/features/monitoring/requests`
32
+ - `knowledgeManifest` -- knowledge
33
+
34
+ There is no `settings` manifest and no top-level `monitoring` manifest; settings routes are template-owned and the monitoring surface reaches the shell only through `submittedRequestsManifest`. Read `shell.tsx` rather than this list if the two disagree -- that file is the source of truth.
33
35
 
34
36
  Important distinction:
35
37
 
@@ -42,7 +44,7 @@ Dashboard remains a host-local route at `/`, not a shared feature manifest.
42
44
  This template should be treated as the downstream reference implementation for this composition:
43
45
 
44
46
  - `core/config/organization-model.ts` owns the organization/runtime semantics
45
- - `ui/src/config/nav-items.ts` preserves the host-local dashboard entry instead of pushing that concern into shared manifests
47
+ - `ui/src/config/shell.tsx` owns which published System modules are mounted, keeping that choice project-local instead of pushing it into `__root.tsx`
46
48
  - `ui/src/routes/__root.tsx` threads `canonicalOrganizationModel` from `@core/config/organization-model` into `ElevasisSystemsProvider` so the shared shell/runtime uses the same semantic source of truth as the local template helpers
47
49
  - host-local customizations still stay local: dashboard remains app-owned nav, branding stays in app config, and quick-access/dashboard UX stays in the template app
48
50
 
@@ -62,7 +64,7 @@ The app uses WorkOS AuthKit through `ElevasisUIProvider`. Authentication is enfo
62
64
 
63
65
  Wrap protected route components with `ProtectedRoute` from `@elevasis/ui/features/auth`. For a **System's top-level route**, use `ProtectedSystemRoute` instead -- it is the canonical shape and is what `ui/src/routes/crm.tsx`, `lead-gen.tsx`, `monitoring.tsx`, `operations.tsx`, `projects.tsx`, `content.tsx`, and `knowledge.tsx` all ship as. See "System route guarding" below. `ProtectedRoute` on its own is for a protected route that gates on authentication alone:
64
66
 
65
- `@elevasis/ui` publishes two components under this name and they behave differently. The one route files want is `@elevasis/ui/features/auth`: it wraps the base guard with an animated full-screen loader that fades out when initialization completes, and supplies a default `AppShellError` fallback so an initialization failure renders a retry surface instead of nothing. `@elevasis/ui/auth` exports the headless base guard, whose `fallback` prop defaults to `null` -- a route that imports it and passes no `fallback` shows a blank screen for the entire initialization window and silently swallows blocking errors. Import the headless one only when the surface deliberately renders its own loading state.
67
+ `@elevasis/ui` publishes two components under this name and they behave differently. The one route files want is `@elevasis/ui/features/auth`: it wraps the base guard with an animated full-screen loader that fades out when initialization completes, and supplies a default `ServiceUnavailableScreen` fallback, which classifies the initialization failure and retries on a backoff instead of rendering nothing. `@elevasis/ui/auth` exports the headless base guard, whose `fallback` prop defaults to `null` -- a route that imports it and passes no `fallback` shows a blank screen for the entire initialization window and silently swallows blocking errors. Import the headless one only when the surface deliberately renders its own loading state.
66
68
 
67
69
  ```tsx
68
70
  import { ProtectedRoute } from '@elevasis/ui/features/auth'
@@ -245,7 +247,7 @@ Section guards currently follow this pattern:
245
247
  - `AccessGuard` on sections that should hard-stop when the backing System is disabled or the role lacks the permission -- `/crm` uses `accessKey="sales.crm"`, `/lead-gen` uses `"sales.lead-gen"`, `/projects` uses `"platform.projects"`, and `/operations` and `/monitoring` both use `AccessKeys.operationsRead`
246
248
  - provider-level shell gating for shared System nav and sub-shell behavior
247
249
 
248
- The app shell in `__root.tsx` derives visible nav from `shellModel.systems` and `getSidebarLinks()`, filters admin-only entries locally using the signed-in profile, and passes `canonicalOrganizationModel` into `ElevasisSystemsProvider` so shared nav labels, paths, and graph runtime behavior resolve from the same organization-model semantic source.
250
+ `__root.tsx` filters `SYSTEM_MANIFESTS` (imported from `@/config/shell`) through `selectDeclaredSystems` against `canonicalOrganizationModel`, so a System module only mounts when the organization model declares it, and passes `canonicalOrganizationModel` into `ElevasisSystemsProvider` so shared nav labels, paths, and graph runtime behavior resolve from the same semantic source. Visible nav is derived inside the shared shell from the declared manifests and the signed-in profile -- the template does not compute it.
249
251
 
250
252
  ## Dashboard and Feature Areas
251
253
 
@@ -280,8 +282,8 @@ The main template-owned customization surfaces are:
280
282
  - `ui/src/config/theme.ts` -- theme presets and defaults
281
283
  - `ui/src/config/background.tsx` -- shared background treatment
282
284
  - `ui/src/config/loader.tsx` -- global loader element
283
- - `ui/src/config/nav-items.ts` -- app-local nav entries, including the preserved dashboard/home entry
284
- - `core/config/organization-model.ts` -- product labels, System availability, resource descriptors, semantic surfaces, canonical-to-legacy surface aliases, and quick-access behavior
285
+ - `ui/src/config/shell.tsx` -- the `SYSTEM_MANIFESTS` array of published System modules the shell mounts
286
+ - `core/config/organization-model/` -- product labels, System availability, resource descriptors, semantic surfaces, canonical-to-legacy surface aliases, and quick-access behavior
285
287
  - `ui/src/config/README.md` -- the deeper guide for those config files
286
288
 
287
289
  ## Customizing a Shared Full-Height Page (never wrap it)
@@ -296,11 +298,11 @@ Wrapping one of these pages in a layout element to bolt on extra UI breaks the h
296
298
 
297
299
  ## Customizing System Sidebars
298
300
 
299
- The template demonstrates one override pattern in `ui/src/routes/__root.tsx`: it extends `CRM_ITEMS` with a template-owned Reports link and replaces `crmManifest` with `customCrmManifest` in the System module array. The backing route lives at `ui/src/routes/crm/reports.tsx` -- delete both the nav item and the route if you don't need them.
301
+ `ui/src/config/shell.tsx` is where sidebar overrides go. The template ships `crmManifest` unmodified in `SYSTEM_MANIFESTS`, so there is no worked override in the template source to copy -- `shell.tsx`'s own doc comment points at `node_modules/@elevasis/sdk/reference/scaffold/ui/customization.md` for the decision tree and patterns. A template-owned `ui/src/routes/crm/reports.tsx` route exists but is not currently surfaced by any nav override; wire it through the `items` prop or a manifest spread below, or delete it.
300
302
 
301
303
  Two customization layers are available for every shared System sidebar:
302
304
 
303
- 1. **Nav-item shortcut (`items` prop)** -- when you just need to swap or extend the nav array, spread the published items constant and pass the result to `*SidebarMiddle`. The template's CRM customization uses this path.
305
+ 1. **Nav-item shortcut (`items` prop)** -- when you just need to swap or extend the nav array, spread the published items constant and pass the result to `*SidebarMiddle`. The template does not use this path today -- it is the shape the unwired `crm/reports.tsx` route would need.
304
306
 
305
307
  ```tsx
306
308
  import { crmManifest, CrmSidebar, CrmSidebarMiddle, CRM_ITEMS } from '@elevasis/ui/features/crm'
@@ -39,7 +39,9 @@ The user wants to record something new -- a task, a note, a piece of information
39
39
 
40
40
  The user wants to know something about current state -- task priorities, what is pending, what is running, what failed.
41
41
 
42
- **Recognize by:** questions about the current list, status, or queue of things. Includes both static-model queries ("what systems are on?") and runtime-entity queries ("what's pending in the queue?"). Route Query to static-model sources (org model, Systems/Actions config) or runtime sources (operations domain) based on the referenced entity.
42
+ **Recognize by:** questions about the current list, status, or queue of things. Includes static-model queries ("which systems are wired up?"), runtime-entity queries ("what's pending in the queue?"), and readiness diagnostics ("is content ready?"). Route Query to static-model sources (org model, Systems/Actions config), runtime sources (operations domain), or the readiness diagnostic (`om:doctor`, `/operations/systems`) based on the referenced entity.
43
+
44
+ **A System being "on" is three fields, not one.** Answering from `systems.ts`'s `enabled` alone gives the wrong answer, and the shipped template proves it: lead-gen, CRM, and `content` all read `enabled: true` while all three carry `lifecycle: 'draft'`, so none is actually reachable. `lifecycle` is the adoption switch — `draft` / `beta` / `active` / `deprecated` / `archived`, defaulting to active when absent. `enabled: false` is a deprecated short-circuit that still wins ahead of the lifecycle check, so read it too. And a System with API-backed actions needs an `apiInterface` before those actions work at all. When the question is whether a System is genuinely usable, run `om:doctor` or point the user at `/operations/systems` rather than narrating a field.
43
45
 
44
46
  **Fixture examples:**
45
47
 
@@ -48,10 +50,21 @@ The user wants to know something about current state -- task priorities, what is
48
50
  | "What should I work on next?" | Asking for prioritized task list |
49
51
  | "What's pending in the HITL queue?" | Runtime-entity query about operations state |
50
52
  | "What runs this week?" | Runtime query about upcoming schedules |
51
- | "What systems are enabled for this project?" | Static-model query about Systems config |
53
+ | "Which systems are actually wired up?" | Static-model query about System adoption |
52
54
  | "What's waiting on review?" | Runtime-entity query about content review-gate state |
55
+ | "Where did this go out?" | Distribution-row query -- which targets were written |
56
+ | "What platforms did this ship to?" | Distribution-row query, phrased by destination |
57
+ | "What are the steps in this pipeline?" | Pipeline step-contract query |
58
+ | "What review gates does this pipeline have?" | Pipeline step-contract query, phrased by gate |
59
+ | "Is the content system ready?" | Readiness diagnosis, not a config read |
60
+
61
+ **Agent action:** read the relevant source and narrate the answer in plain language. Use org model or `project:*` for project state, `elevasis-sdk queue:list --status pending --pretty` and `queue:status --pretty` for HITL queue state, `elevasis-sdk schedule:list --status active --pretty` for upcoming recurring automation, and for the content platform: `elevasis-sdk content:queue --pretty` (open review gates), `content:list --pretty` (item overview), `content:board <pipelineId> --pretty` (pipeline state), `content:get <itemId> --pretty` (one item's attempt/distribution history), `content:distributions --pretty` (distribution rows, one per platform/format target per item), `content:pipeline [id] --pretty` (pipeline templates, or one pipeline's step contract), `content:source-assets --pretty` (list available source assets), or `content:source-asset <id> --pretty` (one source asset's detail). No writes.
62
+
63
+ **`content:distributions` vs `content:get`.** They overlap and the distinction is worth keeping straight: `content:get <itemId>` answers _what happened to this item_; `content:distributions` answers _what went out across the pipeline_ — a filterable cross-item read the per-item command cannot do. It takes `--content-item-id`, `--pipeline-id`, `--platform`, `--status`, `--limit`, and `--offset`.
64
+
65
+ **`content:pipeline` reads the deployed snapshot, not your local model.** With no id it lists pipeline templates; with an id it returns that pipeline's step contract (step keys and review modes). It reads the **deployed** Organization Model snapshot, so a model edit that was never redeployed returns a stale-snapshot **503**. That is a missing redeploy, not a platform failure — do not report it as a bug. `content:pipeline <id>` is also the most direct way to resolve a step key before `content:review --step`; the Transition intent says never to guess `--step`, and this is the second route to getting it right (`content:queue` is the other).
53
66
 
54
- **Agent action:** read the relevant source and narrate the answer in plain language. Use org model or `project:*` for project state, `elevasis-sdk queue:list --status pending --pretty` and `queue:status --pretty` for HITL queue state, `elevasis-sdk schedule:list --status active --pretty` for upcoming recurring automation, and for the content platform: `elevasis-sdk content:queue --pretty` (open review gates), `content:list --pretty` (item overview), `content:board <pipelineId> --pretty` (pipeline state), `content:get <itemId> --pretty` (one item's attempt/distribution history), `content:source-assets --pretty` (list available source assets), or `content:source-asset <id> --pretty` (one source asset's detail). No writes.
67
+ **Readiness is a diagnostic read, and it belongs here.** `elevasis-sdk om:doctor` is the answer to "is this System actually usable" it reports per-issue readiness diagnostics against the deployed snapshot, where plain `doctor` prints only the compact roster. Reach for it whenever a question is about whether something is _wired up_ rather than what the model _says_. A tenant can also read the same picture in the UI at `/operations/systems`, which every project mounts.
55
68
 
56
69
  ### 3. Describe
57
70
 
@@ -97,7 +110,7 @@ The user wants to change the status of a task or entity.
97
110
  | "Pause the Friday report" | Changes schedule state |
98
111
  | "Approve this post" | Clears a named content review gate |
99
112
 
100
- **Agent action:** identify the task, queue item, schedule, or entity being transitioned, confirm the new status/action with the user, then apply it via `elevasis-sdk project:task:save`, `elevasis-sdk queue:select <id> --action-id <id>`, `elevasis-sdk queue:expire <id>`, `elevasis-sdk schedule:pause <id>`, `schedule:resume <id>`, `schedule:cancel <id>`, or `elevasis-sdk content:review <itemId> --step <key> (--approve | --reject) --user <email>` as appropriate. `content:review` always requires resolving the exact `stepKey` from `content:queue` first and confirming the item/decision before executing -- never guess `--step`. Never auto-transition without confirmation if the target entity is ambiguous.
113
+ **Agent action:** identify the task, queue item, schedule, or entity being transitioned, confirm the new status/action with the user, then apply it via `elevasis-sdk project:task:save`, `elevasis-sdk queue:select <id> --action-id <id>`, `elevasis-sdk queue:expire <id>`, `elevasis-sdk schedule:pause <id>`, `schedule:resume <id>`, `schedule:cancel <id>`, or `elevasis-sdk content:review <itemId> --step <key> (--approve | --reject) --user <email>` as appropriate. `content:review` always requires resolving the exact `stepKey` first and confirming the item/decision before executing -- never guess `--step`. Two commands resolve it: `content:queue` (what is currently open) and `content:pipeline <id>` (the pipeline's declared step contract, which is the more direct route when you know the pipeline). Never auto-transition without confirmation if the target entity is ambiguous.
101
114
 
102
115
  ### 5. Navigate
103
116
 
@@ -112,6 +125,7 @@ The user wants to shift focus -- to a different task, project, System, Action, o
112
125
  | "Let's focus on the onboarding flow for now" | "Focus on" + scope target |
113
126
  | "Switch to the Shopify integration project" | "Switch to" = navigate to a different project scope |
114
127
  | "Back to the CRM tasks" | "Back to" = return to a prior scope |
128
+ | "Open the systems page" | "Open" + a real route -- `/operations/systems` |
115
129
 
116
130
  **Agent action:** update the active scope in `prj_tasks.resume_context` (current project + task pointer), then narrate the new scope in plain language so the user knows where they are.
117
131
 
@@ -158,7 +172,9 @@ For "build/extend lead gen" / "campaign creator" / "outbound list state" asks, c
158
172
 
159
173
  For "add a custom CRM action" / "Send Quote button" asks, classify as Codify, then read `operations/node_modules/@elevasis/sdk/reference/scaffold/recipes/customize-crm-actions.md` before editing. Start with the shared `crmActions` provider path for action visibility, labels, ordering, and render-time configuration. In v1, platform-known/default action endpoint behavior is server-constrained; use project-owned UI that calls the workflow directly when a custom key sits outside that server-dispatched set.
160
174
 
161
- For "build/extend content" / "add a content pipeline" / "content review screen" asks, classify the structural org-model portion as Codify, then read `operations/node_modules/@elevasis/sdk/reference/scaffold/recipes/extend-content.md` before editing. A content pipeline is a catalog record, not code -- content work often spans org-model pipeline/step/status/pillar catalogs, the `content` workflow adapter, shared review-page composition, and distribution tracking; do not reduce it to only catalog config or only UI.
175
+ For "build/extend content" / "add a content pipeline" / "content review screen" asks, classify the structural org-model portion as Codify, then read `operations/node_modules/@elevasis/sdk/reference/scaffold/recipes/extend-content.md` before editing. A content pipeline is a catalog record, not code -- content work often spans org-model pipeline/step/status/pillar catalogs, the `content` workflow adapter, the tenant's own Workspace screens, and distribution tracking; do not reduce it to only catalog config or only UI.
176
+
177
+ **Know which side of the line the ask falls on before routing it.** `extend-content.md`'s "Own the Workspace" section draws it: **you own the surfaces where content is operated on; the platform owns the surfaces where it is observed.** Creating a piece and clearing its review gates are yours — authored as the tenant's own Workspace screens, reached through `workspaceRoute` at the pipeline and step level and composed with `ContentWorkspaceShell`. The board, items list, attempt history, distributions, and cross-pipeline review queue are shared, display-only, and do not write. So "build a content review screen" is a **tenant Workspace** build, not a customization of shared review-page composition -- building it on the platform side puts it on the wrong side of a line the recipe now forbids.
162
178
 
163
179
  Heuristics for when to propose codification (passed to `/om` as context):
164
180
 
@@ -183,6 +199,11 @@ The user wants to enable or disable a System.
183
199
 
184
200
  **Agent action:** delegate to `/om systems`. The ceremony (confirm + edit `core/config/organization-model/systems.ts` -- or `core/config/organization-model.ts` in unsplit projects -- + typecheck) belongs to `/om`, not to the ambient rule.
185
201
 
202
+ **Check adoption before flipping anything — `lifecycle` is the switch, not `enabled`.** Run `om:doctor` (or read `/operations/systems`) first and pass what it says to `/om` as context. Two things go wrong without that check:
203
+
204
+ - **"Turn on X" actioned against `enabled`** does nothing when `enabled` is already `true`, which it is for every template System. The field the user means is `lifecycle`.
205
+ - **Flipping `lifecycle: 'draft'` to `'active'` on an unadopted System produces guaranteed 503s.** A System with no scoped resources and no `apiInterface` computes as ready and then fails every request. "On" means adopted — resources, ontology, and an `apiInterface` where API-backed actions are involved — not one edited field. If the readiness check says the System is not adopted, say so in plain language instead of making it look enabled.
206
+
186
207
  **Tenant-local only.** Toggle operates on this project's own `core/config/organization-model/systems.ts` (or `core/config/organization-model.ts` in unsplit projects) — the project's own Systems. The Elevasis platform's own Systems are not in scope; this project cannot toggle them and vibe must not pretend it can. If a user names a platform-only System, surface the boundary in plain language rather than attempting a toggle.
187
208
 
188
209
  ### 8. Operate
@@ -271,4 +292,5 @@ Layers 2 (Public API), 3 (UI Shell Runtime), 5 (Toolkit), and 6 (Graph) require
271
292
  - `operations/node_modules/@elevasis/sdk/reference/scaffold/recipes/extend-lead-gen.md` -- lead-gen build/extend scope
272
293
  - `operations/node_modules/@elevasis/sdk/reference/scaffold/recipes/customize-crm-actions.md` -- custom CRM action keys and the `crmActions` provider
273
294
  - `operations/node_modules/@elevasis/sdk/reference/scaffold/recipes/extend-content.md` -- content build/extend scope
274
- - `core/config/organization-model/systems.ts` -- label vocabulary and System availability (or `core/config/organization-model.ts` in unsplit projects)
295
+ - `core/config/organization-model/systems.ts` -- label vocabulary, and the `lifecycle` / `enabled` / `apiInterface` fields a System's availability is read from (or `core/config/organization-model.ts` in unsplit projects). Read `elevasis-sdk om:doctor` rather than this file when the question is whether a System is genuinely adopted
296
+ - `/operations/systems` -- the readiness page every project mounts, showing which Systems are actually wired up
@@ -21,7 +21,7 @@ Vibe is **ambient and always on**. Every natural-language message is silently cl
21
21
  | Transition | "done", "stuck", "blocked", "finished", "complete", "approve", "pause" | Agent -- confirm + `project:task:save`, `queue:select`, `schedule:*`, or `content:review` |
22
22
  | Navigate | "focus on", "switch to", "back to", "look at" | Agent -- update scope + narrate |
23
23
  | Codify | "we are X", "we track Y", repeated attribute, "add type/field" | Delegate to `/om \<domain>` |
24
- | Toggle | "enable", "disable", "turn on/off" + system | Delegate to `/om systems` (tenant-local only) |
24
+ | Toggle | "enable", "disable", "turn on/off" + system | Check adoption (`om:doctor`), then delegate to `/om systems` (tenant-local only) |
25
25
  | Operate | "run", "execute", "launch", "trigger", "kick off", "start" + deployed resource | Delegate to `/elevasis` -- `elevasis-sdk describe` + confirm + `elevasis-sdk exec` |
26
26
 
27
27
  ## Safety Boundaries
@@ -31,6 +31,7 @@ Vibe is **ambient and always on**. Every natural-language message is silently cl
31
31
  - **Never write the model yourself.** Codify and Toggle detect intent and delegate to `/om <domain>`; the draft-confirm-write-typecheck ceremony belongs to `/om`.
32
32
  - **Never flip public agent exposure.** Making a deployed agent reachable on the public internet (the `agent_access_grants` row behind `/public/agents/:slug`, managed via `grant:create` / `grant:update` / `grant:disable` or the Resource-page public/private toggle) is a security boundary deliberately kept out of ambient routing -- a non-technical user describing their business must never expose an agent by accident. Do NOT classify "make my agent public" / "put the interview online" as Toggle, and do NOT auto-execute. Surface the `grant:*` CLI or the Resource-page toggle in plain language and require explicit confirmation.
33
33
  - **Toggle is tenant-local.** It edits this project's own Systems config -- `core/config/organization-model/systems.ts`, or `core/config/organization-model.ts` in unsplit projects -- only. The Elevasis platform's own Systems cannot be toggled from here; surface that boundary rather than attempting it.
34
+ - **"On" is `lifecycle`, and it is not the whole story.** `enabled` is already `true` on every template System, so actioning "turn on X" against it does nothing; `lifecycle` (`draft` / `beta` / `active` / ...) is the switch. But flipping `lifecycle` to `'active'` on a System with no scoped resources and no `apiInterface` makes it compute as ready and then 503 every request. Run `om:doctor` (or read `/operations/systems`) before delegating, and pass the result to `/om` as context. If the System is not adopted, say so rather than making it look enabled.
34
35
  - **Never guess an ambiguous intent.** Ask one neutral clarifying question presenting the plausible intents. Do not apply a precedence rule and do not route to the "closest" match.
35
36
  - **Never invent vocabulary.** Status, entity, and layer names come from the model's inline `label` fields, read verbatim -- never hardcoded synonyms.
36
37
 
@@ -64,4 +65,4 @@ a required question on every System-shaping change.
64
65
  ## References
65
66
 
66
67
  - `operations/node_modules/@elevasis/sdk/reference/rules/vibe-intents.md` -- per-intent recognition signals, fixture examples, exact agent actions, stage/state sub-routing, the classifier threshold, and phase scope
67
- - `core/config/organization-model/systems.ts` -- label vocabulary and System availability (or `core/config/organization-model.ts` in unsplit projects)
68
+ - `core/config/organization-model/systems.ts` -- label vocabulary, and the `lifecycle` / `enabled` / `apiInterface` fields a System's availability is read from (or `core/config/organization-model.ts` in unsplit projects). Run `elevasis-sdk om:doctor`, or read `/operations/systems`, when the question is whether a System is genuinely adopted rather than what the file says
@@ -101,25 +101,38 @@ The external skill doc (`.claude/skills/external/SKILL.md`) remains the workflow
101
101
 
102
102
  ### Per-Project Checks (auto-discovered)
103
103
 
104
- | Category | What It Checks |
105
- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
106
- | `deps` | `@elevasis/ui`, `@elevasis/sdk`, `@elevasis/core` versions match template |
107
- | `tier1` | registry-backed replace surfaces match template where verification still models them as exact baselines |
108
- | `org-os` | Organization model exists, exports canonical symbols, imports from `@elevasis/core/organization-model`, either calls `createFoundationOrganizationModel` or uses explicit `resolveOrganizationModel(..., { mergeDefaults: false })` canonical assembly, app-config references org model, `__root.tsx` uses `ElevasisAuthenticatedShell` / `ElevasisSystemsProvider` + `canonicalOrganizationModel`, `main.tsx` uses `createElevasisApp`, all 3 CSS subpath imports present |
109
- | `placeholders` | No unresolved `__PROJECT_SLUG__`, `__PROJECT_NAME__`, `__PROJECT_DESCRIPTION__` in key config files |
110
- | `scripts` | `ui` and `operations` `package.json` have required npm scripts |
111
- | `lib` | `ui/src/lib/`, `lib/`, `test-utils/` exist with minimum file counts |
112
- | `tier3` | project-owned preservation boundaries such as `nav-items.ts` remain intact |
113
- | `conflicts` | No merge conflict markers in source files |
114
- | `git` | Working tree is clean |
115
- | `lockfile` | `pnpm-lock.yaml` and `node_modules` exist |
104
+ | Category | What It Checks |
105
+ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
106
+ | `deps` | `@elevasis/ui`, `@elevasis/sdk`, `@elevasis/core` versions match template |
107
+ | `registry-owned` | registry-backed `replace` surfaces match the template byte-for-byte where verification still models them as exact baselines |
108
+ | `org-os` | Organization model exists, exports canonical symbols, imports from `@elevasis/core/organization-model`, either calls `createFoundationOrganizationModel` or uses explicit `resolveOrganizationModel(..., { mergeDefaults: false })` canonical assembly, app-config references org model, `__root.tsx` uses `ElevasisAuthenticatedShell` / `ElevasisSystemsProvider` + `canonicalOrganizationModel`, `main.tsx` uses `createElevasisApp`, all 3 CSS subpath imports present |
109
+ | `placeholders` | No unresolved `__PROJECT_SLUG__`, `__PROJECT_NAME__`, `__PROJECT_DESCRIPTION__` in key config files |
110
+ | `scripts` | `ui` and `operations` `package.json` have required npm scripts |
111
+ | `shared` | Five shared directories exist with minimum file counts: `ui/src/lib` (3), `ui/src/test-utils` (2), `ui/src/config` (3), `ui/src/routes` (5), `ui/src/features` (5) |
112
+ | `sync-plan` | Registry planner drift -- what the planner would write, and whether project-owned paths stay outside its scope |
113
+ | `project-marker` | The project's `.elevasis` marker file is present and well-formed |
114
+ | `claude` | `.claude/` infrastructure -- skills, rules, hooks, and settings the tenant agent loads |
115
+ | `knowledge` | Knowledge scaffold wiring and its generated nodes |
116
+ | `resource-governance` | Resource governance wiring resolves against the project's own OM |
117
+ | `contract-conformance` | Operations-bundle conformance via `detect-conformance-gaps.ts`; passes silently when the bundle is absent |
118
+ | `retired-nav` | Retired nav-item surfaces have not come back |
119
+ | `conflicts` | No merge conflict markers in source files |
120
+ | `git` | Working tree is clean |
121
+ | `lockfile` | `pnpm-lock.yaml` and `node_modules` exist |
122
+
123
+ An org-specific project (one not derived from the template) reports a single `mode` pass and skips the
124
+ dependency and `registry-owned` UI checks entirely.
116
125
 
117
126
  ### Monorepo-Level Checks
118
127
 
119
- | Category | What It Checks |
120
- | ----------- | ----------------------------------------------- |
121
- | `scaffold` | `pnpm scaffold:sync` passes (artifacts current) |
122
- | `artifacts` | 5 generated artifacts exist and have content |
128
+ | Category | What It Checks |
129
+ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
130
+ | `monorepo/artifacts` | Four hardcoded generated artifacts plus every registry-derived `generated` dependent exist and are non-empty |
131
+ | `monorepo/tombstones` | Tombstone lifecycle. A discharged tombstone warns rather than fails -- stale housekeeping should not turn the gate red |
132
+ | `monorepo/template-coverage` | Every file under `external/_template` is claimed by some registry entry |
133
+ | `monorepo/stale-prose-paths` | Prose in managed surfaces does not cite paths that no longer exist |
134
+ | `monorepo/external-registry` | The external registry's own status |
135
+ | `registry-owned/contract` | Every byte-equality-checked path is `replace`-category. Runs once per invocation, not per project |
123
136
 
124
137
  ### Usage
125
138
 
@@ -138,13 +151,14 @@ pnpm sync:verify -- nirvana-marketing # Single project
138
151
 
139
152
  ### Planner Interpretation Note
140
153
 
141
- `pnpm sync:verify` still carries some historical `tier1` / `tier3` labels in its output, but the ownership semantics now come from the registry-backed categories used by the planner:
154
+ `pnpm sync:verify` no longer emits `tier1` / `tier3` labels at all — the categories in the tables above are the real ones, and the ownership semantics come from the registry-backed categories used by the planner:
142
155
 
143
156
  - `.claude/skills/**`, `hooks/**`, `rules/**`, `scripts/**`, and `.claude/settings.json` are managed `replace` surfaces
144
- - `nav-items.ts`, `operations/src/**`, `shared/src/**`, `CLAUDE.md`, and extension files are `never-touch`
157
+ - `.elevasis`, `core/config/organization-model/profile.ts`, `operations/src/**`, `shared/src/**`, `CLAUDE.md`, and extension files are `never-touch`
158
+ - `ui/src/config/shell.tsx` is the project-owned shell seam. It carries no `never-touch` rule -- it is annotated `critical-manual-merge`, which is advisory, so edit it freely and expect a catch-up warning rather than a revert. `ui/src/routes/__root.tsx` and `ui/src/main.tsx` are the sync-managed files it was extracted from; put per-project shell customization in `shell.tsx`, not in those two
145
159
  - generated surfaces are verified for freshness, not copied
146
160
 
147
- Treat the old tier labels as display shorthand inside the verifier, not as the canonical execution contract.
161
+ The old `Tier 1` / `Tier 2` / `Tier 3` vocabulary survives only in this doc's history and in operator memory. Do not expect it in verifier output, and do not reintroduce it as shorthand — the registry categories are the canonical execution contract.
148
162
 
149
163
  ---
150
164
 
@@ -119,7 +119,7 @@ The output lands in `packages/sdk/reference/` which is included in the npm packa
119
119
  - UI patterns: `packages/ui/src/scaffold/...`
120
120
  - Cross-package or SDK-owned: `packages/sdk/docs/scaffold/...`
121
121
 
122
- 2. **Add to `SCAFFOLD_COPIES`** in `packages/sdk/scripts/copy-reference-docs.mjs`:
122
+ 2. **Add to the base `SCAFFOLD_COPIES` list** in `scripts/monorepo/scaffold-copies.js`. Do **not** edit the `SCAFFOLD_COPIES` constant in `packages/sdk/scripts/copy-reference-docs.mjs` -- that one is composed (`[...BASE_SCAFFOLD_COPIES, ...RULE_REFERENCE_COPIES]`) from two imported lists, so an entry added there is lost the next time either source list is edited:
123
123
 
124
124
  ```javascript
125
125
  { source: 'packages/sdk/docs/scaffold/operations/my-doc.md', target: 'scaffold/operations/my-doc.md' }
@@ -12,7 +12,7 @@ CRM deal pages derive their action buttons from an `ActionDef[]` array. The shar
12
12
 
13
13
  For the broader CRM extension map -- pages, sidebars, hooks, workflow adapters, System Interfaces, and org-model boundaries -- start with [Build and Extend CRM](extend-crm.md). This recipe is only the deal-action path.
14
14
 
15
- **Shape reference:** The `ActionDef` flat shape and the consolidation that replaced the old `handler`/`kind` union are documented in `apps/docs/content/docs/in-progress/active-development/_pipeline/crm/crm-current-state-assessment.mdx`.
15
+ **Shape reference:** The `ActionDef` flat shape and the consolidation that replaced the old `handler`/`kind` union are documented in `apps/docs/content/docs/technical/features/operations/crm/index.mdx`.
16
16
 
17
17
  Use this recipe when a user asks for work like:
18
18