@elevasis/sdk 1.29.0 → 1.30.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 (42) hide show
  1. package/dist/cli.cjs +1610 -594
  2. package/dist/index.d.ts +87 -1
  3. package/dist/index.js +30 -25
  4. package/dist/node/index.d.ts +84 -1
  5. package/dist/test-utils/index.d.ts +84 -1
  6. package/dist/test-utils/index.js +242 -23
  7. package/dist/worker/index.js +1 -0
  8. package/package.json +4 -4
  9. package/reference/claude-config/rules/topbar-actions.md +70 -0
  10. package/reference/claude-config/skills/om/SKILL.md +18 -1
  11. package/reference/claude-config/skills/om/operations/scaffold.md +153 -0
  12. package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +83 -83
  13. package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +45 -45
  14. package/reference/claude-config/sync-notes/2026-05-15-om-skill-rename-and-write-family.md +52 -52
  15. package/reference/claude-config/sync-notes/2026-05-17-sdk-boundary-consolidation.md +33 -33
  16. package/reference/claude-config/sync-notes/2026-05-20-om-define-helpers.md +32 -32
  17. package/reference/claude-config/sync-notes/2026-05-22-access-model-and-right-panel.md +43 -43
  18. package/reference/claude-config/sync-notes/2026-05-22-lead-gen-tenant-config.md +40 -40
  19. package/reference/claude-config/sync-notes/2026-05-22-org-model-multi-file-split.md +61 -61
  20. package/reference/claude-config/sync-notes/2026-05-23-branding-names-to-identity.md +49 -49
  21. package/reference/claude-config/sync-notes/2026-05-23-lead-gen-manage-access.md +31 -31
  22. package/reference/claude-config/sync-notes/2026-05-23-om-deployment-drift-detection.md +42 -42
  23. package/reference/claude-config/sync-notes/2026-05-23-om-full-model-deploy-contract.md +33 -33
  24. package/reference/claude-config/sync-notes/2026-05-23-ui-sdk-package-fixes.md +37 -37
  25. package/reference/claude-config/sync-notes/2026-05-24-platform-invite-router-core-baseline.md +28 -28
  26. package/reference/claude-config/sync-notes/2026-05-24-system-interface-readiness.md +43 -43
  27. package/reference/claude-config/sync-notes/2026-05-25-invitation-login-loader.md +26 -0
  28. package/reference/claude-config/sync-notes/2026-05-25-om-topbar-requests.md +33 -0
  29. package/reference/claude-config/sync-notes/2026-05-25-system-interface-profile-registry-and-substrate.md +35 -0
  30. package/reference/claude-config/sync-notes/2026-05-25-tenant-om-scaffold-cli.md +49 -0
  31. package/reference/claude-config/sync-notes/2026-05-25-vibe-operate-intent.md +47 -0
  32. package/reference/examples/organization-model.ts +18 -0
  33. package/reference/rules/organization-model.md +4 -1
  34. package/reference/rules/organization-os.md +7 -1
  35. package/reference/rules/ui.md +207 -207
  36. package/reference/rules/vibe.md +52 -18
  37. package/reference/scaffold/index.mdx +9 -7
  38. package/reference/scaffold/operations/scaffold-maintenance.md +14 -4
  39. package/reference/scaffold/reference/contracts.md +423 -338
  40. package/reference/scaffold/reference/glossary.md +14 -2
  41. package/reference/scaffold/reference/system-interface-capabilities.md +50 -0
  42. /package/reference/claude-config/skills/deploy/{skill.md → SKILL.md} +0 -0
@@ -6886,6 +6886,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
6886
6886
  "view",
6887
6887
  "launch",
6888
6888
  "message",
6889
+ "message-plus",
6889
6890
  "escalate",
6890
6891
  "promote",
6891
6892
  "submit",
@@ -6923,7 +6924,7 @@ var LabelSchema = z.string().trim().min(1).max(120);
6923
6924
  var DescriptionSchema = z.string().trim().min(1).max(2e3);
6924
6925
  var ColorTokenSchema = z.string().trim().min(1).max(50);
6925
6926
  var IconNameSchema = OrganizationModelIconTokenSchema;
6926
- z.string().trim().startsWith("/").max(300);
6927
+ var PathSchema = z.string().trim().startsWith("/").max(300);
6927
6928
  var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
6928
6929
  var DisplayMetadataSchema = z.object({
6929
6930
  label: LabelSchema,
@@ -6995,6 +6996,89 @@ function listAllSystems(model) {
6995
6996
  return results;
6996
6997
  }
6997
6998
 
6999
+ // ../core/src/organization-model/domains/entities.ts
7000
+ var EntityIdSchema = ModelIdSchema;
7001
+ var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
7002
+ var EntityLinkSchema = z.object({
7003
+ toEntity: EntityIdSchema.meta({ ref: "entity" }),
7004
+ kind: EntityLinkKindSchema,
7005
+ via: z.string().trim().min(1).max(255).optional(),
7006
+ label: LabelSchema.optional()
7007
+ });
7008
+ var EntitySchema = z.object({
7009
+ id: EntityIdSchema,
7010
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
7011
+ order: z.number(),
7012
+ label: LabelSchema,
7013
+ description: DescriptionSchema.optional(),
7014
+ ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
7015
+ table: z.string().trim().min(1).max(255).optional(),
7016
+ rowSchema: ModelIdSchema.optional(),
7017
+ stateCatalogId: ModelIdSchema.optional(),
7018
+ links: z.array(EntityLinkSchema).optional()
7019
+ });
7020
+ z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
7021
+ message: "Each entity entry id must match its map key"
7022
+ }).default({});
7023
+
7024
+ // ../core/src/organization-model/domains/actions.ts
7025
+ var ActionResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
7026
+ z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
7027
+ var ActionIdSchema = ModelIdSchema;
7028
+ var ActionScopeSchema = z.union([
7029
+ z.literal("global"),
7030
+ z.object({
7031
+ domain: ModelIdSchema
7032
+ })
7033
+ ]);
7034
+ var ActionRefSchema = z.object({
7035
+ actionId: ActionIdSchema.meta({ ref: "action" }),
7036
+ intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
7037
+ });
7038
+ var SlashCommandInvocationSchema = z.object({
7039
+ kind: z.literal("slash-command"),
7040
+ command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
7041
+ toolFactory: ModelIdSchema.optional()
7042
+ });
7043
+ var McpToolInvocationSchema = z.object({
7044
+ kind: z.literal("mcp-tool"),
7045
+ server: ModelIdSchema,
7046
+ name: ModelIdSchema
7047
+ });
7048
+ var ApiEndpointInvocationSchema = z.object({
7049
+ kind: z.literal("api-endpoint"),
7050
+ method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
7051
+ path: z.string().trim().startsWith("/").max(500),
7052
+ requestSchema: ModelIdSchema.optional(),
7053
+ responseSchema: ModelIdSchema.optional()
7054
+ });
7055
+ var ScriptExecutionInvocationSchema = z.object({
7056
+ kind: z.literal("script-execution"),
7057
+ resourceId: ActionResourceIdSchema
7058
+ });
7059
+ var ActionInvocationSchema = z.discriminatedUnion("kind", [
7060
+ SlashCommandInvocationSchema,
7061
+ McpToolInvocationSchema,
7062
+ ApiEndpointInvocationSchema,
7063
+ ScriptExecutionInvocationSchema
7064
+ ]);
7065
+ var ActionSchema = z.object({
7066
+ id: ActionIdSchema,
7067
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
7068
+ order: z.number(),
7069
+ label: LabelSchema,
7070
+ description: DescriptionSchema.optional(),
7071
+ scope: ActionScopeSchema.default("global"),
7072
+ resourceId: ActionResourceIdSchema.optional(),
7073
+ affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
7074
+ invocations: z.array(ActionInvocationSchema).default([]),
7075
+ knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
7076
+ lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
7077
+ });
7078
+ z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
7079
+ message: "Each action entry id must match its map key"
7080
+ }).default({});
7081
+
6998
7082
  // ../core/src/organization-model/domains/prospecting.ts
6999
7083
  DisplayMetadataSchema.extend({
7000
7084
  id: ModelIdSchema,
@@ -8316,7 +8400,7 @@ var OntologyGroupSchema = OntologyRecordBaseSchema.extend({
8316
8400
  var OntologySurfaceTypeSchema = OntologyRecordBaseSchema.extend({
8317
8401
  route: z.string().trim().min(1).max(500).optional()
8318
8402
  });
8319
- z.object({
8403
+ var OntologyScopeSchema = z.object({
8320
8404
  objectTypes: z.record(OntologyIdSchema, OntologyObjectTypeSchema).default({}).optional(),
8321
8405
  linkTypes: z.record(OntologyIdSchema, OntologyLinkTypeSchema).default({}).optional(),
8322
8406
  actionTypes: z.record(OntologyIdSchema, OntologyActionTypeSchema).default({}).optional(),
@@ -8549,6 +8633,152 @@ function compileOrganizationOntology(model) {
8549
8633
  addLegacyActionProjections(ontology, diagnostics, sourcesById, model.actions ?? {}, model.entities ?? {});
8550
8634
  return { ontology: sortResolvedOntologyIndex(ontology), diagnostics };
8551
8635
  }
8636
+ var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
8637
+ var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
8638
+ var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Status", color: "teal" });
8639
+ var SystemIdSchema = ModelIdSchema;
8640
+ var SystemPathSchema = z.string().trim().min(1).regex(
8641
+ /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
8642
+ 'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
8643
+ );
8644
+ var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
8645
+ z.string().trim().min(1).max(200).regex(
8646
+ /^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
8647
+ "Node references must use kind:dotted-path (e.g. system:sales.crm or resource:lead-gen.company.qualify)"
8648
+ );
8649
+ var SystemUiSchema = z.object({
8650
+ path: PathSchema,
8651
+ surfaces: ReferenceIdsSchema,
8652
+ icon: IconNameSchema.optional(),
8653
+ order: z.number().int().optional()
8654
+ });
8655
+ var SystemInterfaceKeySchema = ModelIdSchema;
8656
+ var SystemInterfaceLifecycleSchema = z.enum(["draft", "active", "disabled", "deprecated", "archived"]).meta({ label: "System interface lifecycle", color: "teal" });
8657
+ var SYSTEM_INTERFACE_PROFILES = [
8658
+ {
8659
+ systemPath: "sales.lead-gen",
8660
+ interfaceKey: "api",
8661
+ readinessProfile: "sales.lead-gen.api"
8662
+ },
8663
+ {
8664
+ systemPath: "sales.crm",
8665
+ interfaceKey: "api",
8666
+ readinessProfile: "sales.crm.api"
8667
+ },
8668
+ {
8669
+ systemPath: "sales.lead-gen",
8670
+ interfaceKey: "crm-handoff",
8671
+ readinessProfile: "sales.lead-gen.crm-handoff"
8672
+ }
8673
+ ];
8674
+ var SYSTEM_INTERFACE_READINESS_PROFILES = SYSTEM_INTERFACE_PROFILES.map(
8675
+ (profile) => profile.readinessProfile
8676
+ );
8677
+ var SystemInterfaceReadinessProfileSchema = z.enum(SYSTEM_INTERFACE_READINESS_PROFILES);
8678
+ var SystemInterfaceResourceScopeSchema = z.array(ModelIdSchema).default([]);
8679
+ var SystemApiInterfaceSchema = z.object({
8680
+ lifecycle: SystemInterfaceLifecycleSchema.default("active"),
8681
+ readinessProfile: SystemInterfaceReadinessProfileSchema.optional(),
8682
+ /**
8683
+ * Resource ids that participate in this API interface. This scopes readiness
8684
+ * derivation without duplicating authored required/provided contract refs.
8685
+ */
8686
+ resourceIds: SystemInterfaceResourceScopeSchema.optional()
8687
+ }).strict();
8688
+ z.object({
8689
+ systemPath: SystemPathSchema,
8690
+ interfaceKey: SystemInterfaceKeySchema
8691
+ }).strict();
8692
+ var JsonValueSchema = z.lazy(
8693
+ () => z.union([
8694
+ z.string(),
8695
+ z.number(),
8696
+ z.boolean(),
8697
+ z.null(),
8698
+ z.array(JsonValueSchema),
8699
+ z.record(z.string(), JsonValueSchema)
8700
+ ])
8701
+ );
8702
+ var SystemConfigSchema = z.record(z.string().trim().min(1).max(200), JsonValueSchema).default({}).optional();
8703
+ var SystemEntrySchema = z.object({
8704
+ /** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
8705
+ id: SystemIdSchema,
8706
+ /** Human-readable system label shown in UI, governance, and operations surfaces. */
8707
+ label: LabelSchema.optional(),
8708
+ /** @deprecated Use label. Accepted for pre-consolidation System declarations. */
8709
+ title: LabelSchema.optional(),
8710
+ /** One-paragraph purpose statement for the bounded context. */
8711
+ description: DescriptionSchema.optional(),
8712
+ /** Closed system shape enum; catalog values remain tenant-defined. */
8713
+ kind: SystemKindSchema.optional(),
8714
+ /** Optional self-reference for System hierarchy. */
8715
+ parentSystemId: SystemIdSchema.optional(),
8716
+ /** Optional UI presence. Systems without UI omit this. */
8717
+ ui: SystemUiSchema.optional(),
8718
+ /** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
8719
+ lifecycle: SystemLifecycleSchema.optional(),
8720
+ /** Optional role responsible for this system. */
8721
+ responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
8722
+ /** Optional knowledge nodes that govern this system. */
8723
+ governedByKnowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
8724
+ /** Optional actions this system exposes or consumes. */
8725
+ actions: z.array(ActionRefSchema).optional(),
8726
+ /** Optional operational policies that apply to this system. */
8727
+ policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
8728
+ /** Optional goals this system contributes to. */
8729
+ drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
8730
+ /** Thin API runtime-boundary marker. Readiness is derived from scoped resources and topology. */
8731
+ apiInterface: SystemApiInterfaceSchema.optional(),
8732
+ /** @deprecated Use lifecycle. Accepted for one publish cycle. */
8733
+ status: SystemStatusSchema.optional(),
8734
+ /** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
8735
+ path: PathSchema.optional(),
8736
+ /** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
8737
+ icon: IconNameSchema.optional(),
8738
+ /** @deprecated Feature color token, retained for one-cycle compatibility. */
8739
+ color: ColorTokenSchema.optional(),
8740
+ /** @deprecated UI placement hint, retained for one-cycle compatibility. */
8741
+ uiPosition: UiPositionSchema.optional(),
8742
+ /** @deprecated Use lifecycle. */
8743
+ enabled: z.boolean().optional(),
8744
+ /** @deprecated Use lifecycle: "beta". */
8745
+ devOnly: z.boolean().optional(),
8746
+ requiresAdmin: z.boolean().optional(),
8747
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
8748
+ order: z.number(),
8749
+ /**
8750
+ * System-local JSON settings and defaults. Strongly typed OM fields,
8751
+ * secrets, credentials, and runtime state stay outside this bucket.
8752
+ */
8753
+ config: SystemConfigSchema,
8754
+ /**
8755
+ * System-owned ontology declarations. `systems` is now the canonical child
8756
+ * key; this scope holds the object, action, catalog, link, event, and
8757
+ * shared contract records owned by this system.
8758
+ */
8759
+ ontology: OntologyScopeSchema.optional(),
8760
+ /**
8761
+ * Recursive child systems, authored via nesting (per L11).
8762
+ * The key is the local system id; the full path is computed by joining
8763
+ * ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
8764
+ * Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
8765
+ * position-derived paths. Both still exist on this schema for backward compat.
8766
+ */
8767
+ systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
8768
+ /** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
8769
+ subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
8770
+ }).strict().refine((system) => system.label !== void 0 || system.title !== void 0, {
8771
+ path: ["label"],
8772
+ message: "System must provide label or title"
8773
+ }).transform((system) => {
8774
+ const normalizedSystem = system.systems !== void 0 && system.subsystems === void 0 ? { ...system, subsystems: system.systems } : system;
8775
+ if (normalizedSystem.status === void 0) return normalizedSystem;
8776
+ console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
8777
+ return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
8778
+ });
8779
+ z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
8780
+ message: "Each system entry id must match its map key"
8781
+ }).default({});
8552
8782
 
8553
8783
  // ../core/src/organization-model/migration-helpers.ts
8554
8784
  function catalogRecords(model) {
@@ -8626,21 +8856,12 @@ z.object({
8626
8856
  });
8627
8857
 
8628
8858
  // ../core/src/business/acquisition/ontology-validation.ts
8629
- var LEAD_GEN_API_INTERFACE = {
8630
- interfaceKey: "api",
8631
- readinessProfile: "sales.lead-gen.api"
8632
- };
8633
- var CRM_API_INTERFACE = {
8634
- systemPath: "sales.crm",
8635
- interfaceKey: "api",
8636
- readinessProfile: "sales.crm.api"
8637
- };
8638
- var LEAD_GEN_CRM_HANDOFF_INTERFACE = {
8639
- systemPath: "sales.lead-gen",
8640
- interfaceKey: "crm-handoff",
8641
- readinessProfile: "sales.lead-gen.crm-handoff"
8642
- };
8859
+ var LEAD_GEN_API_INTERFACE = SYSTEM_INTERFACE_PROFILES[0];
8860
+ var CRM_API_INTERFACE = SYSTEM_INTERFACE_PROFILES[1];
8861
+ var LEAD_GEN_CRM_HANDOFF_INTERFACE = SYSTEM_INTERFACE_PROFILES[2];
8862
+ LEAD_GEN_API_INTERFACE.readinessProfile;
8643
8863
  CRM_API_INTERFACE.readinessProfile;
8864
+ LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile;
8644
8865
  var LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID = formatOntologyId({
8645
8866
  scope: "sales.lead-gen",
8646
8867
  kind: "object",
@@ -8718,6 +8939,9 @@ function profileForInterface(systemPath, interfaceKey, readinessProfile) {
8718
8939
  function readinessMarkerPath(context) {
8719
8940
  return context.interfaceKey === "api" ? `systems.${context.systemPath}.apiInterface` : `systems.${context.systemPath}.derivedCrmHandoffReadiness`;
8720
8941
  }
8942
+ function formatSupportedReadinessProfiles() {
8943
+ return SYSTEM_INTERFACE_READINESS_PROFILES.map((profile) => `"${profile}"`).join(", ");
8944
+ }
8721
8945
  function getActiveScopedResources(model, resourceIds, issues, context) {
8722
8946
  const resources = [];
8723
8947
  for (const [index2, resourceId] of resourceIds.entries()) {
@@ -8997,18 +9221,13 @@ function computeInterfaceReadiness(model, request) {
8997
9221
  { path: `${readinessMarkerPath(request)}.lifecycle` }
8998
9222
  );
8999
9223
  }
9000
- const supportedProfiles = [
9001
- LEAD_GEN_API_INTERFACE.readinessProfile,
9002
- CRM_API_INTERFACE.readinessProfile,
9003
- LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile
9004
- ];
9005
- const supportedProfile = readinessProfile !== void 0 && supportedProfiles.some((profile) => profile === readinessProfile);
9224
+ const supportedProfile = readinessProfile !== void 0 && SYSTEM_INTERFACE_PROFILES.some((profile) => profile.readinessProfile === readinessProfile);
9006
9225
  if (!supportedProfile) {
9007
9226
  addReadinessIssue(
9008
9227
  issues,
9009
9228
  "SYSTEM_INTERFACE_INVALID",
9010
9229
  "unknown-readiness-profile",
9011
- `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" references unknown readiness profile "${readinessProfile}".`,
9230
+ `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" references unknown readiness profile "${readinessProfile}". Supported profiles: ${formatSupportedReadinessProfiles()}. Custom Systems should not declare apiInterface; route custom behavior through workflows/operations plus ontology, resources, and topology.`,
9012
9231
  { path: `${readinessMarkerPath(request)}.readinessProfile`, ref: readinessProfile }
9013
9232
  );
9014
9233
  return {
@@ -4978,6 +4978,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
4978
4978
  "view",
4979
4979
  "launch",
4980
4980
  "message",
4981
+ "message-plus",
4981
4982
  "escalate",
4982
4983
  "promote",
4983
4984
  "submit",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/sdk",
3
- "version": "1.29.0",
3
+ "version": "1.30.1",
4
4
  "description": "SDK for building Elevasis organization resources",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,9 +58,9 @@
58
58
  "tsup": "^8.0.0",
59
59
  "typescript": "5.9.2",
60
60
  "zod": "^4.1.0",
61
- "@repo/core": "0.36.0",
62
- "@repo/eslint-config": "0.0.0",
63
- "@repo/typescript-config": "0.0.0"
61
+ "@repo/core": "0.38.0",
62
+ "@repo/typescript-config": "0.0.0",
63
+ "@repo/eslint-config": "0.0.0"
64
64
  },
65
65
  "scripts": {
66
66
  "lint": "eslint src --max-warnings 0",
@@ -0,0 +1,70 @@
1
+ ---
2
+ description: OM-declared topbar actions — navigation.topbar field and TOPBAR_ACTION_MANIFESTS registry pattern
3
+ paths:
4
+ - ui/src/lib/components/AppTopbar*
5
+ - ui/src/routes/__root*
6
+ - core/config/organization-model/**
7
+ ---
8
+
9
+ # Topbar Actions (Template Mirror Discipline — Tier 1 Note)
10
+
11
+ > **Scope:** This note documents substrate that has landed in the monorepo but is not yet published
12
+ > to `@elevasis/sdk/reference/rules/`. It will be superseded by the bundled rule once the
13
+ > `@elevasis/ui` minor that carries the topbar substrate ships. Until then, use this file.
14
+
15
+ ## navigation.topbar OM Field
16
+
17
+ The Organization Model now has a `navigation.topbar` region for declaring topbar action items.
18
+ Each entry is a distinct node type — OM owns data and visibility; a registry binds behavior.
19
+
20
+ ```ts
21
+ // core/config/organization-model.ts (navigation section)
22
+ navigation: {
23
+ topbar: {
24
+ request: {
25
+ id: 'request',
26
+ label: 'Request a feature or report an issue',
27
+ tooltip: 'Request a feature or report an issue',
28
+ icon: 'message-plus',
29
+ order: 10,
30
+ enabled: true
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ Topbar items are toggled via `/org-os manage` exactly like sidebar surfaces. The `surfaceType`
37
+ enum (`page | dashboard | list | detail | graph | settings`) does NOT apply to topbar items —
38
+ they are a separate node type, not surfaces.
39
+
40
+ ## TOPBAR_ACTION_MANIFESTS Registry
41
+
42
+ Behavior for each `navigation.topbar` key is bound through a manifest registry in
43
+ `@elevasis/ui`. Each manifest maps a key to a render function:
44
+
45
+ ```ts
46
+ // Registered in packages/ui/src/features/registry/manifests.ts
47
+ TOPBAR_ACTION_MANIFESTS = {
48
+ request: requestTopbarActionManifest
49
+ }
50
+ ```
51
+
52
+ The `requestTopbarActionManifest` renders `<RequestActionIcon />` from
53
+ `@elevasis/ui/features/monitoring/requests`. It owns its own disclosure state and modal —
54
+ no wiring needed at the call site.
55
+
56
+ ## Template Authoring (Tier 2 — Post-Publish)
57
+
58
+ Declaring `navigation.topbar.request` in the template OM and rendering `<TopbarActions />`
59
+ in `AppTopbar` is **Tier 2 post-publish authoring** — it runs after the `@elevasis/ui` minor
60
+ bump lands in `external/_template`. Do NOT edit `core/config/organization-model/**` for this
61
+ until the publish + baseline bump step completes.
62
+
63
+ The requests-page `RequestButton` (entry point C) is a CC-level app-local addition in the
64
+ platform `apps/command-center` routes. Template projects add their own equivalent in
65
+ `ui/src/routes/monitoring/requests.index.tsx` after the surface is present in their navigation.
66
+
67
+ ## Related Rules
68
+
69
+ - `node_modules/@elevasis/sdk/reference/rules/organization-model.md` — OM schema and authoring ceremony
70
+ - `node_modules/@elevasis/sdk/reference/rules/organization-os.md` — `/org-os manage` toggle surface
@@ -47,6 +47,8 @@ metadata:
47
47
  - knowledge graph
48
48
  - knowledge browser
49
49
  - ontology
50
+ - apiInterface
51
+ - interface readiness
50
52
  - by-ontology
51
53
  - list my roles
52
54
  - what is our
@@ -95,7 +97,7 @@ primitive. When two buckets fit, prefer the higher one (more specific → more g
95
97
  | --- | ------------------------------ | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
96
98
  | 1 | Named knowledge/role/policy id | User names `knowledge.<id>`, `role.<id>`, `policy.<id>` directly | `om:cat <id>` for body, `om:describe <id>` for neighborhood |
97
99
  | 2 | Named system | User names a system path (`sales.crm`, `sales.lead-gen`) | `om:describe <id>` |
98
- | 3 | Named ontology id | Id contains `:object/`, `:action/`, `:event/`, `:catalog/`, `:link/`, `:surface/` | `om:describe <id>` (or `om:ls /by-ontology/<id> --ids-only` then `om:cat` each) |
100
+ | 3 | Named ontology id | Id contains `:object/`, `:action/`, `:event/`, `:catalog/`, `:interface/`, `:link/`, `:surface/` | `om:describe <id>` (or `om:ls /by-ontology/<id> --ids-only` then `om:cat` each) |
99
101
  | 4 | Kind keyword | "playbooks", "strategies", "all references", "list policies" | `om:ls /by-kind/<kind> --ids-only` then `om:cat` each |
100
102
  | 5 | Free-text discovery | Anything else ("lead gen", "outreach", "what governs X?") | `om:search "<query>"` then drill into top hit with `om:describe` |
101
103
 
@@ -198,6 +200,7 @@ what adjacent context may matter:
198
200
  | What resources belong to a System? | the id-keyed `organizationModel.resources` map and `getResourcesForSystem(model, systemPath)` | use `{ includeDescendants: true }` only for parent-scope rollups |
199
201
  | What can a System do? | system action refs and the actions domain | `action.resourceId`, invocation metadata, affected entities, policies |
200
202
  | What data does it own? | entities domain | owning System refs, state catalogs, entity links, emitted/projected events |
203
+ | Is a platform API interface ready? | the System's `apiInterface` marker and `node_modules/@elevasis/sdk/reference/scaffold/reference/system-interface-capabilities.md` | matching convention-locked System path, cataloged `readinessProfile`, derived resource ontology bindings, and scoped topology grants |
201
204
  | What UI surface exposes it? | `navigation.sidebar` plus `SystemModule` manifests | route files, surface targets, route-prefix modules, guards |
202
205
  | What knowledge applies? | `om:ls /by-system/<id>` plus graph edges | `om:cat`, `om:graph`, `/graph/<id>/governed-by` |
203
206
 
@@ -207,6 +210,20 @@ follow the relationship that matches the work. Prefer structured helpers from
207
210
 
208
211
  ---
209
212
 
213
+ ## API Interface Readiness
214
+
215
+ `system.apiInterface` is adopt-only in tenant projects. It declares intent to adopt a platform-provided API capability from the installed `@elevasis/core` / `@elevasis/sdk` version; it is not a tenant extension point.
216
+
217
+ Use only readiness profiles listed in `node_modules/@elevasis/sdk/reference/scaffold/reference/system-interface-capabilities.md`. The profile also fixes the required System path, such as `sales.lead-gen` or `sales.crm`. Do not invent a profile, and do not repoint a cataloged profile to a custom System path.
218
+
219
+ Readiness is derived, not hand-authored. After the marker is present, the validator checks ontology object/catalog types, scoped resources and their `resource.ontology` bindings, and any required scoped topology `uses` grants. Lead-gen to CRM handoff is represented as a scoped topology relationship under the cross-System boundary invariant, not as an authored bridge object.
220
+
221
+ Custom Systems should not carry `apiInterface`. Build custom behavior through `System.ontology`, `System.config`, resources, catalogs, topology, navigation, and workflows/operations. Runtime business logic belongs in workflows and agents registered by `operations/src/index.ts`; the tenant project does not add platform API routes.
222
+
223
+ Do not confuse ontology `interface` records with `system.apiInterface`. Ontology ids such as `<system>:interface/<local-id>` describe semantic model records under `System.ontology`; `system.apiInterface` is a flat System-level marker for closed platform API readiness.
224
+
225
+ ---
226
+
210
227
  ## Shared Layering Preview
211
228
 
212
229
  When opening a domain that uses a closed stage, status, or catalog vocabulary -- especially
@@ -0,0 +1,153 @@
1
+ # Scaffold: New OM Entries via `om:scaffold:*` CLI
2
+
3
+ `om:scaffold:*` is the guided-creation surface for adding new entries to the tenant Organization Model. Each command prompts for missing fields, prints the proposed TypeScript / MDX block under `--dry-run`, and (when run without `--dry-run`) writes into the canonical authoring file under `core/config/organization-model/**` or `core/config/knowledge/nodes/`.
4
+
5
+ This operation is invoked by `/om` when intent classifies as **Codify-new-entry** (a net-new System, Resource, Role, Knowledge node, or a fill-pass against a conformance-gap JSON) rather than a Level-A field edit. For existing-field edits, dispatch to `codify-level-a.md` instead.
6
+
7
+ ---
8
+
9
+ ## When to Use
10
+
11
+ | Intent signal | Dispatch |
12
+ | ----------------------------------------------- | -------------------------------- |
13
+ | "Add a new system for …", "we have an X system" | `om:scaffold:system` |
14
+ | "Add a workflow / resource called …" | `om:scaffold:resource` |
15
+ | "Add a role …", "we need a … role" | `om:scaffold:role` |
16
+ | "Add a knowledge node / playbook / strategy …" | `om:scaffold:knowledge` |
17
+ | Conformance gate produced a gap JSON to apply | `om:scaffold:fill --gaps <path>` |
18
+
19
+ For existing-field edits (changing a description, toggling a system, renaming a label), use the Codify Level-A ceremony — do not scaffold.
20
+
21
+ ---
22
+
23
+ ## CLI Surface
24
+
25
+ All commands run from inside `external/<project>/` (or any descendant — `elevasis-sdk` walks up to the `.elevasis` marker). Add `--dry-run` to any command to preview the generated TypeScript / MDX without writing.
26
+
27
+ | Command | Purpose | Writes to |
28
+ | ----------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------- |
29
+ | `om:scaffold:system` | Guide creation of a new System entry. Optional `--api-backed` emits an `apiInterface` block. | `core/config/organization-model/systems.ts` |
30
+ | `om:scaffold:resource` | Add a new workflow Resource descriptor with `systemPath` attachment and an ontology `primaryAction`. | `core/config/organization-model/systems.ts` |
31
+ | `om:scaffold:role` | Add a new Role to the profile domain. | `core/config/organization-model/profile.ts` |
32
+ | `om:scaffold:knowledge` | Create a new MDX knowledge node file under the requested kind / system mount. | `core/config/knowledge/nodes/` |
33
+ | `om:scaffold:fill` | Non-interactive apply of a conformance-gap JSON produced by the conformance gate (Agent 2a). | Per-file as recorded in the JSON. |
34
+
35
+ ---
36
+
37
+ ## Common Options
38
+
39
+ | Flag | Behavior |
40
+ | --------------------------- | ------------------------------------------------------------------------------------ | -------- | --------- | -------- |
41
+ | `--dry-run` | Print proposed block; write nothing. Always run this first when in doubt. |
42
+ | `-h`, `--help` | Print command-specific help. |
43
+ | `--id <id>` | Pre-fill the canonical id (prompted if absent). |
44
+ | `--title <title>` | Pre-fill display title (prompted if absent — `system`, `resource`, `role`). |
45
+ | `--system-path <path>` | Attach Resource or Knowledge to an existing System (prompted if absent). |
46
+ | `--api-backed` | (`system` only) Emit an `apiInterface` block; reminds you to populate `resourceIds`. |
47
+ | `--primary-action <action>` | (`resource` only) Pre-fill ontology primary action id. |
48
+ | `--kind <kind>` | (`knowledge` only) `playbook | strategy | reference | policy`. |
49
+ | `--gaps <path>` | (`fill` only) Required path to the conformance-gap JSON. |
50
+ | `--skipped <path>` | (`fill` only) Output path for gaps that still need manual input. |
51
+
52
+ ---
53
+
54
+ ## Step-by-Step
55
+
56
+ ### Step 1: Pre-flight read
57
+
58
+ Before scaffolding, run a single `om:describe` against the parent System (for Resource / Knowledge scaffolds) or the profile domain (for Role scaffolds). This grounds the proposed id, system path, and ontology references in current model state. Skipping this step routinely produces ids that collide with existing entries.
59
+
60
+ ```bash
61
+ pnpm exec elevasis-sdk om:describe sales.crm
62
+ ```
63
+
64
+ ### Step 2: Dry-run
65
+
66
+ Always preview first. Each command prints the exact TypeScript / MDX block it would write.
67
+
68
+ ```bash
69
+ pnpm exec elevasis-sdk om:scaffold:system --dry-run
70
+ pnpm exec elevasis-sdk om:scaffold:resource --dry-run
71
+ pnpm exec elevasis-sdk om:scaffold:role --dry-run
72
+ pnpm exec elevasis-sdk om:scaffold:knowledge --dry-run
73
+ ```
74
+
75
+ The dry-run output is the diff you would present to the user during a Codify proposal. Show it verbatim before asking for confirmation.
76
+
77
+ ### Step 3: Confirm
78
+
79
+ Pause for explicit user confirmation, exactly like Codify Level-A Step 3. Permission prompts also gate the underlying write.
80
+
81
+ ### Step 4: Write
82
+
83
+ Re-run the command without `--dry-run`. The CLI:
84
+
85
+ 1. Asserts the project is in split layout (`core/config/organization-model/{profile,systems,navigation}.ts`); on monolithic projects it errors with a guidance message rather than guessing where to write.
86
+ 2. Inserts the new block alongside existing entries of the same kind.
87
+ 3. Reports the touched file path.
88
+
89
+ ### Step 5: Validate
90
+
91
+ Always run both gates after a scaffold write:
92
+
93
+ ```bash
94
+ pnpm -C operations check-types # tsc --noEmit
95
+ pnpm -C operations check # elevasis-sdk resource validator (incl. conformance gate)
96
+ ```
97
+
98
+ The new conformance gate (shipped in `@elevasis/sdk@1.30+`) will catch a System that declares API-backed Resources but no `apiInterface`. If it fires after a `system` scaffold, either:
99
+
100
+ - Re-run `om:scaffold:system --api-backed` to add the `apiInterface` block, or
101
+ - Run `om:scaffold:fill --gaps <gaps.json>` against the gate's emitted gaps file.
102
+
103
+ ### Step 6: Rollback on failure
104
+
105
+ If either validation gate fails, restore the touched file from the snapshot captured in Step 1 of the parent `/om` Codify ceremony. The scaffold CLI does not perform its own rollback — the ceremony around it does.
106
+
107
+ ---
108
+
109
+ ## `om:scaffold:fill` — Conformance Gap Pass
110
+
111
+ `om:scaffold:fill` is the non-interactive counterpart to the four guided scaffolders. It consumes a JSON file shaped like the output of the conformance gate (the new deploy preflight introduced alongside `@elevasis/core@0.38` + `@elevasis/sdk@1.30`) and writes the missing fields it can derive without user input. Gaps that require a choice (e.g. picking a `readinessProfile`) land in the `--skipped` output for manual review.
112
+
113
+ ```bash
114
+ # After the conformance gate prints a gaps file:
115
+ pnpm exec elevasis-sdk om:scaffold:fill --gaps .elevasis/conformance-gaps.json --dry-run
116
+ pnpm exec elevasis-sdk om:scaffold:fill --gaps .elevasis/conformance-gaps.json --skipped .elevasis/conformance-skipped.json
117
+ ```
118
+
119
+ `fill` is idempotent for already-applied gaps; it skips entries that no longer match the live model.
120
+
121
+ ---
122
+
123
+ ## Layout Guard
124
+
125
+ Every `om:scaffold:*` command requires the split layout under `core/config/organization-model/`:
126
+
127
+ - `profile.ts` — identity, customers, offerings, roles, goals, techStack, labels
128
+ - `systems.ts` — systems + system-attached resources
129
+ - `navigation.ts` — navigation surfaces and sidebar wiring
130
+
131
+ On a monolithic `core/config/organization-model.ts`, the command errors with a one-line instruction to split first. The split step is owned by an upstream `/om` workflow — do not hand-split during a scaffold.
132
+
133
+ ---
134
+
135
+ ## Related Operations
136
+
137
+ - `codify-level-a.md` — existing-field edits (the default Codify pipeline)
138
+ - `codify-level-b.md` — net-new Zod extension files under `core/config/extensions/`
139
+ - `verify.md` — model-coherence checks (the in-memory doctor)
140
+
141
+ ---
142
+
143
+ ## Caller Contract (when dispatched from `/om`)
144
+
145
+ When `/om` classifies a Codify-new-entry intent, it should:
146
+
147
+ 1. Pick the correct sub-command from the table above.
148
+ 2. Pre-fill any options it can confidently extract from the conversation (`--id`, `--title`, `--system-path`, `--api-backed`, etc.) so the CLI does not re-prompt for them.
149
+ 3. Always pass `--dry-run` on the first invocation and show the output to the user.
150
+ 4. On user confirmation, re-invoke without `--dry-run`.
151
+ 5. Run the Step 5 validators and report the result. Roll back if either fails.
152
+
153
+ Do not skip the dry-run round-trip. The scaffolders write into the authoring source of truth — silent writes erode the trust the `/om` ceremony exists to protect.