@elevasis/sdk 1.22.0 → 1.23.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 (41) hide show
  1. package/dist/cli.cjs +980 -42
  2. package/dist/index.d.ts +1221 -220
  3. package/dist/index.js +390 -15
  4. package/dist/test-utils/index.d.ts +964 -211
  5. package/dist/test-utils/index.js +257 -14
  6. package/dist/worker/index.js +122 -14
  7. package/package.json +3 -3
  8. package/reference/claude-config/rules/operations.md +3 -3
  9. package/reference/claude-config/rules/organization-model.md +88 -85
  10. package/reference/claude-config/rules/organization-os.md +104 -104
  11. package/reference/claude-config/rules/vibe.md +235 -235
  12. package/reference/claude-config/skills/om/SKILL.md +324 -0
  13. package/reference/claude-config/skills/{knowledge → om}/operations/customers.md +110 -109
  14. package/reference/claude-config/skills/{knowledge → om}/operations/features.md +77 -76
  15. package/reference/claude-config/skills/{knowledge → om}/operations/goals.md +119 -118
  16. package/reference/claude-config/skills/{knowledge → om}/operations/identity.md +94 -93
  17. package/reference/claude-config/skills/{knowledge → om}/operations/labels.md +94 -94
  18. package/reference/claude-config/skills/{knowledge → om}/operations/offerings.md +110 -109
  19. package/reference/claude-config/skills/{knowledge → om}/operations/roles.md +100 -99
  20. package/reference/claude-config/skills/{knowledge → om}/operations/techStack.md +30 -30
  21. package/reference/claude-config/skills/project/SKILL.md +1088 -1088
  22. package/reference/claude-config/skills/setup/SKILL.md +275 -275
  23. package/reference/claude-config/skills/tutorial/SKILL.md +259 -259
  24. package/reference/claude-config/skills/tutorial/progress-template.md +74 -74
  25. package/reference/claude-config/skills/tutorial/technical.md +1303 -1303
  26. package/reference/claude-config/skills/tutorial/vibe-coder.md +890 -890
  27. package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +7 -4
  28. package/reference/claude-config/sync-notes/2026-05-15-om-skill-rename-and-write-family.md +52 -0
  29. package/reference/examples/organization-model.ts +26 -2
  30. package/reference/scaffold/core/organization-model.mdx +16 -11
  31. package/reference/scaffold/recipes/add-a-feature.md +28 -26
  32. package/reference/scaffold/recipes/add-a-resource.md +26 -16
  33. package/reference/scaffold/recipes/customize-organization-model.md +5 -3
  34. package/reference/scaffold/recipes/extend-lead-gen.md +9 -9
  35. package/reference/scaffold/recipes/index.md +1 -1
  36. package/reference/scaffold/recipes/query-the-knowledge-graph.md +189 -185
  37. package/reference/scaffold/reference/contracts.md +139 -101
  38. package/reference/scaffold/reference/glossary.md +74 -72
  39. package/reference/claude-config/skills/knowledge/SKILL.md +0 -345
  40. /package/reference/claude-config/skills/{knowledge → om}/operations/codify-level-a.md +0 -0
  41. /package/reference/claude-config/skills/{knowledge → om}/operations/codify-level-b.md +0 -0
@@ -6519,6 +6519,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
6519
6519
  "crm",
6520
6520
  "lead-gen",
6521
6521
  "projects",
6522
+ "clients",
6522
6523
  "operations",
6523
6524
  "monitoring",
6524
6525
  "knowledge",
@@ -8075,7 +8076,6 @@ function addLegacyEntityProjections(index2, diagnostics, sourcesById, entities)
8075
8076
  table: entity.table
8076
8077
  }
8077
8078
  } : {},
8078
- legacyEntityId: entity.id,
8079
8079
  ...entity.rowSchema !== void 0 ? { rowSchema: entity.rowSchema } : {},
8080
8080
  ...entity.stateCatalogId !== void 0 ? { stateCatalogId: entity.stateCatalogId } : {}
8081
8081
  };
@@ -8100,8 +8100,7 @@ function addLegacyEntityProjections(index2, diagnostics, sourcesById, entities)
8100
8100
  from: legacyObjectId(entity),
8101
8101
  to: legacyObjectId(targetEntity),
8102
8102
  cardinality: link.kind,
8103
- ...link.via !== void 0 ? { via: link.via } : {},
8104
- legacyEntityId: entity.id
8103
+ ...link.via !== void 0 ? { via: link.via } : {}
8105
8104
  };
8106
8105
  addRecord(index2, diagnostics, sourcesById, "linkTypes", linkType, {
8107
8106
  source: "legacy.entities.links",
@@ -8159,8 +8158,7 @@ function addSystemContentProjections(index2, diagnostics, sourcesById, systemPat
8159
8158
  kind: node.type,
8160
8159
  ...typeof node.data?.["entityId"] === "string" ? { appliesTo: formatOntologyId({ scope: systemPath, kind: "object", localId: node.data["entityId"] }) } : {},
8161
8160
  ...Object.keys(entries).length > 0 ? { entries } : {},
8162
- ...node.data !== void 0 ? { data: node.data } : {},
8163
- legacyContentId: `${systemPath}:${localId}`
8161
+ ...node.data !== void 0 ? { data: node.data } : {}
8164
8162
  };
8165
8163
  addRecord(index2, diagnostics, sourcesById, "catalogTypes", catalogType, {
8166
8164
  source: "legacy.system.content",
@@ -8338,11 +8336,20 @@ EventEmissionDescriptorSchema.extend({
8338
8336
  ownerKind: z.enum(["resource", "entity"]).meta({ label: "Owner kind" })
8339
8337
  });
8340
8338
  var ResourceOntologyBindingSchema = z.object({
8341
- implements: z.array(OntologyIdSchema).optional(),
8339
+ actions: z.array(OntologyIdSchema).optional(),
8340
+ primaryAction: OntologyIdSchema.optional(),
8342
8341
  reads: z.array(OntologyIdSchema).optional(),
8343
8342
  writes: z.array(OntologyIdSchema).optional(),
8344
8343
  usesCatalogs: z.array(OntologyIdSchema).optional(),
8345
8344
  emits: z.array(OntologyIdSchema).optional()
8345
+ }).superRefine((binding, ctx) => {
8346
+ if (binding.primaryAction === void 0) return;
8347
+ if (binding.actions?.includes(binding.primaryAction)) return;
8348
+ ctx.addIssue({
8349
+ code: z.ZodIssueCode.custom,
8350
+ path: ["primaryAction"],
8351
+ message: "Resource ontology primaryAction must be included in actions"
8352
+ });
8346
8353
  });
8347
8354
  var CodeReferenceSchema = z.object({
8348
8355
  path: z.string().trim().min(1).max(500).regex(/^[A-Za-z0-9_./$@()[\] -]+$/, "Code reference paths must be repo-relative paths"),
@@ -8357,6 +8364,10 @@ var ResourceEntryBaseSchema = z.object({
8357
8364
  order: z.number().default(0),
8358
8365
  /** Required single System membership — value is a dot-separated system path (e.g. "sales.lead-gen"). */
8359
8366
  systemPath: SystemPathSchema.meta({ ref: "system" }),
8367
+ /** Executable display title owned by the OM Resource descriptor. */
8368
+ title: LabelSchema.optional(),
8369
+ /** Executable display description owned by the OM Resource descriptor. */
8370
+ description: DescriptionSchema.optional(),
8360
8371
  /** Optional role responsible for maintaining this resource. */
8361
8372
  ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
8362
8373
  status: ResourceGovernanceStatusSchema,
@@ -8371,8 +8382,6 @@ var ResourceEntryBaseSchema = z.object({
8371
8382
  });
8372
8383
  var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
8373
8384
  kind: z.literal("workflow"),
8374
- /** Mirrors WorkflowConfig.actionKey when the runtime workflow has one. */
8375
- actionKey: z.string().trim().min(1).max(255).optional(),
8376
8385
  emits: z.array(EventEmissionDescriptorSchema).optional()
8377
8386
  });
8378
8387
  var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
@@ -8514,6 +8523,73 @@ var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) =>
8514
8523
  message: "Each objective entry id must match its map key"
8515
8524
  }).default({});
8516
8525
  var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
8526
+ var SecretLikeMetadataKeySchema = /(?:secret|password|passwd|token|api[-_]?key|credential|private[-_]?key)/i;
8527
+ var SecretLikeMetadataValueSchema = /(?:sk-[A-Za-z0-9_-]{12,}|pk_live_[A-Za-z0-9_-]{12,}|eyJ[A-Za-z0-9_-]{20,}|-----BEGIN (?:RSA |OPENSSH |EC )?PRIVATE KEY-----)/;
8528
+ z.enum([
8529
+ "system",
8530
+ "resource",
8531
+ "ontology",
8532
+ "policy",
8533
+ "role",
8534
+ "trigger",
8535
+ "humanCheckpoint",
8536
+ "externalResource"
8537
+ ]);
8538
+ var OmTopologyRelationshipKindSchema = z.enum(["triggers", "uses", "approval"]);
8539
+ var OmTopologyNodeRefSchema = z.discriminatedUnion("kind", [
8540
+ z.object({ kind: z.literal("system"), id: ModelIdSchema }),
8541
+ z.object({ kind: z.literal("resource"), id: ResourceIdSchema }),
8542
+ z.object({ kind: z.literal("ontology"), id: OntologyIdSchema }),
8543
+ z.object({ kind: z.literal("policy"), id: ModelIdSchema }),
8544
+ z.object({ kind: z.literal("role"), id: ModelIdSchema }),
8545
+ z.object({ kind: z.literal("trigger"), id: ResourceIdSchema }),
8546
+ z.object({ kind: z.literal("humanCheckpoint"), id: ResourceIdSchema }),
8547
+ z.object({ kind: z.literal("externalResource"), id: ResourceIdSchema })
8548
+ ]);
8549
+ var OmTopologyMetadataSchema = z.record(z.string().trim().min(1).max(120), JsonValueSchema).superRefine((metadata, ctx) => {
8550
+ function visit(value, path) {
8551
+ if (typeof value === "string" && SecretLikeMetadataValueSchema.test(value)) {
8552
+ ctx.addIssue({
8553
+ code: z.ZodIssueCode.custom,
8554
+ path,
8555
+ message: "Topology metadata must not contain secret-like values"
8556
+ });
8557
+ return;
8558
+ }
8559
+ if (Array.isArray(value)) {
8560
+ value.forEach((entry, index2) => visit(entry, [...path, index2]));
8561
+ return;
8562
+ }
8563
+ if (typeof value !== "object" || value === null) return;
8564
+ Object.entries(value).forEach(([key, entry]) => {
8565
+ if (SecretLikeMetadataKeySchema.test(key)) {
8566
+ ctx.addIssue({
8567
+ code: z.ZodIssueCode.custom,
8568
+ path: [...path, key],
8569
+ message: `Topology metadata key "${key}" looks secret-like`
8570
+ });
8571
+ }
8572
+ visit(entry, [...path, key]);
8573
+ });
8574
+ }
8575
+ visit(metadata, []);
8576
+ });
8577
+ var OmTopologyRelationshipSchema = z.object({
8578
+ from: OmTopologyNodeRefSchema,
8579
+ kind: OmTopologyRelationshipKindSchema,
8580
+ to: OmTopologyNodeRefSchema,
8581
+ systemPath: SystemPathSchema.optional(),
8582
+ required: z.boolean().optional(),
8583
+ metadata: OmTopologyMetadataSchema.optional()
8584
+ });
8585
+ var OmTopologyDomainSchema = z.object({
8586
+ version: z.literal(1).default(1),
8587
+ relationships: z.record(z.string().trim().min(1).max(255), OmTopologyRelationshipSchema).default({})
8588
+ }).default({ version: 1, relationships: {} });
8589
+ var DEFAULT_ORGANIZATION_MODEL_TOPOLOGY = {
8590
+ version: 1,
8591
+ relationships: {}
8592
+ };
8517
8593
  var PolicyIdSchema = ModelIdSchema;
8518
8594
  var PolicyApplicabilitySchema = z.object({
8519
8595
  systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
@@ -8886,6 +8962,7 @@ z.enum([
8886
8962
  "systems",
8887
8963
  "ontology",
8888
8964
  "resources",
8965
+ "topology",
8889
8966
  "actions",
8890
8967
  "entities",
8891
8968
  "policies",
@@ -8905,6 +8982,7 @@ var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
8905
8982
  systems: { version: 1, lastModified: "2026-05-10" },
8906
8983
  ontology: { version: 1, lastModified: "2026-05-14" },
8907
8984
  resources: { version: 1, lastModified: "2026-05-10" },
8985
+ topology: { version: 1, lastModified: "2026-05-14" },
8908
8986
  actions: { version: 1, lastModified: "2026-05-10" },
8909
8987
  entities: { version: 1, lastModified: "2026-05-10" },
8910
8988
  policies: { version: 1, lastModified: "2026-05-10" },
@@ -8920,6 +8998,7 @@ var OrganizationModelDomainMetadataByDomainSchema = z.object({
8920
8998
  systems: OrganizationModelDomainMetadataSchema,
8921
8999
  ontology: OrganizationModelDomainMetadataSchema,
8922
9000
  resources: OrganizationModelDomainMetadataSchema,
9001
+ topology: OrganizationModelDomainMetadataSchema,
8923
9002
  actions: OrganizationModelDomainMetadataSchema,
8924
9003
  entities: OrganizationModelDomainMetadataSchema,
8925
9004
  policies: OrganizationModelDomainMetadataSchema,
@@ -8938,6 +9017,7 @@ var OrganizationModelSchemaBase = z.object({
8938
9017
  systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
8939
9018
  ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
8940
9019
  resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
9020
+ topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
8941
9021
  actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
8942
9022
  entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
8943
9023
  policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
@@ -9280,6 +9360,25 @@ OrganizationModelSchemaBase.superRefine((model, ctx) => {
9280
9360
  surface: ontologyCompilation.ontology.surfaces
9281
9361
  };
9282
9362
  const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index2) => Object.keys(index2)));
9363
+ function topologyTargetExists(ref) {
9364
+ if (ref.kind === "system") return systemsById.has(ref.id);
9365
+ if (ref.kind === "resource") return resourcesById.has(ref.id);
9366
+ if (ref.kind === "ontology") return ontologyIds.has(ref.id);
9367
+ if (ref.kind === "policy") return policiesById.has(ref.id);
9368
+ if (ref.kind === "role") return rolesById.has(ref.id);
9369
+ return true;
9370
+ }
9371
+ Object.entries(model.topology.relationships).forEach(([relationshipId, relationship]) => {
9372
+ ["from", "to"].forEach((side) => {
9373
+ const ref = relationship[side];
9374
+ if (topologyTargetExists(ref)) return;
9375
+ addIssue(
9376
+ ctx,
9377
+ ["topology", "relationships", relationshipId, side],
9378
+ `Topology relationship "${relationshipId}" ${side} references unknown ${ref.kind} "${ref.id}"`
9379
+ );
9380
+ });
9381
+ });
9283
9382
  const ontologyReferenceKeyKinds = {
9284
9383
  valueType: "value-type",
9285
9384
  catalogType: "catalog",
@@ -9418,11 +9517,18 @@ OrganizationModelSchemaBase.superRefine((model, ctx) => {
9418
9517
  }
9419
9518
  });
9420
9519
  function validateResourceOntologyBinding(resourceId, bindingKey, expectedKind, ids) {
9421
- ids?.forEach((ontologyId, ontologyIndex) => {
9520
+ const ontologyIds2 = ids === void 0 ? [] : Array.isArray(ids) ? ids : [ids];
9521
+ ontologyIds2.forEach((ontologyId, ontologyIndex) => {
9422
9522
  if (ontologyIndexByKind[expectedKind][ontologyId] === void 0) {
9423
9523
  addIssue(
9424
9524
  ctx,
9425
- ["resources", resourceId, "ontology", bindingKey, ontologyIndex],
9525
+ [
9526
+ "resources",
9527
+ resourceId,
9528
+ "ontology",
9529
+ bindingKey,
9530
+ ...Array.isArray(ids) ? [ontologyIndex] : []
9531
+ ],
9426
9532
  `Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
9427
9533
  );
9428
9534
  }
@@ -9431,7 +9537,8 @@ OrganizationModelSchemaBase.superRefine((model, ctx) => {
9431
9537
  Object.values(model.resources).forEach((resource) => {
9432
9538
  const binding = resource.ontology;
9433
9539
  if (binding === void 0) return;
9434
- validateResourceOntologyBinding(resource.id, "implements", "action", binding.implements);
9540
+ validateResourceOntologyBinding(resource.id, "actions", "action", binding.actions);
9541
+ validateResourceOntologyBinding(resource.id, "primaryAction", "action", binding.primaryAction);
9435
9542
  validateResourceOntologyBinding(resource.id, "reads", "object", binding.reads);
9436
9543
  validateResourceOntologyBinding(resource.id, "writes", "object", binding.writes);
9437
9544
  validateResourceOntologyBinding(resource.id, "usesCatalogs", "catalog", binding.usesCatalogs);
@@ -9565,7 +9672,7 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
9565
9672
  business: {
9566
9673
  type: "group",
9567
9674
  label: "Business",
9568
- icon: "business",
9675
+ icon: "briefcase",
9569
9676
  order: 20,
9570
9677
  children: {
9571
9678
  sales: {
@@ -9582,7 +9689,7 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
9582
9689
  label: "Clients",
9583
9690
  path: "/clients",
9584
9691
  surfaceType: "list",
9585
- icon: "projects",
9692
+ icon: "clients",
9586
9693
  order: 20,
9587
9694
  targets: { systems: ["clients"] }
9588
9695
  },
@@ -9956,7 +10063,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
9956
10063
  enabled: true,
9957
10064
  lifecycle: "active",
9958
10065
  color: "orange",
9959
- icon: "projects",
10066
+ icon: "clients",
9960
10067
  path: "/clients"
9961
10068
  },
9962
10069
  operations: {
@@ -10260,6 +10367,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
10260
10367
  },
10261
10368
  ontology: DEFAULT_ONTOLOGY_SCOPE,
10262
10369
  resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
10370
+ topology: DEFAULT_ORGANIZATION_MODEL_TOPOLOGY,
10263
10371
  actions: DEFAULT_ORGANIZATION_MODEL_ACTIONS,
10264
10372
  entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
10265
10373
  policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
@@ -11731,6 +11839,119 @@ function getRuntimeResources(resources) {
11731
11839
  }))
11732
11840
  ];
11733
11841
  }
11842
+ function hasOntologySources(organizationModel) {
11843
+ return organizationModel.ontology !== void 0 || organizationModel.entities !== void 0 || organizationModel.actions !== void 0 || Object.values(organizationModel.systems ?? {}).some(systemHasOntologySource);
11844
+ }
11845
+ function systemHasOntologySource(system) {
11846
+ if (system.ontology !== void 0 || system.content !== void 0 && Object.keys(system.content).length > 0) return true;
11847
+ return Object.values(system.systems ?? system.subsystems ?? {}).some(systemHasOntologySource);
11848
+ }
11849
+ function ontologyIndexForKind(index2, kind) {
11850
+ switch (kind) {
11851
+ case "object":
11852
+ return index2.objectTypes;
11853
+ case "link":
11854
+ return index2.linkTypes;
11855
+ case "action":
11856
+ return index2.actionTypes;
11857
+ case "catalog":
11858
+ return index2.catalogTypes;
11859
+ case "event":
11860
+ return index2.eventTypes;
11861
+ case "interface":
11862
+ return index2.interfaceTypes;
11863
+ case "value-type":
11864
+ return index2.valueTypes;
11865
+ case "property":
11866
+ return index2.sharedProperties;
11867
+ case "group":
11868
+ return index2.groups;
11869
+ case "surface":
11870
+ return index2.surfaces;
11871
+ }
11872
+ }
11873
+ function sameJson(left, right) {
11874
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
11875
+ }
11876
+ function addOntologyBindingIssues(issues, orgName, resource, ontologyIndex) {
11877
+ const binding = resource.ontology;
11878
+ if (binding === void 0) return;
11879
+ if ((resource.kind === "workflow" || resource.kind === "agent") && (binding.actions?.length ?? 0) === 0) {
11880
+ addGovernanceIssue(
11881
+ issues,
11882
+ "missing-ontology-actions",
11883
+ orgName,
11884
+ resource.id,
11885
+ `[${orgName}] Resource '${resource.id}' declares ontology bindings but no ontology actions.`
11886
+ );
11887
+ }
11888
+ if (binding.primaryAction !== void 0 && !binding.actions?.includes(binding.primaryAction)) {
11889
+ addGovernanceIssue(
11890
+ issues,
11891
+ "primary-action-mismatch",
11892
+ orgName,
11893
+ resource.id,
11894
+ `[${orgName}] Resource '${resource.id}' primaryAction '${binding.primaryAction}' must be included in ontology.actions.`
11895
+ );
11896
+ }
11897
+ if (ontologyIndex === void 0) return;
11898
+ const validateRefs = (bindingKey, expectedKind, refs) => {
11899
+ const values = refs === void 0 ? [] : Array.isArray(refs) ? refs : [refs];
11900
+ const index2 = ontologyIndexForKind(ontologyIndex, expectedKind);
11901
+ for (const ref of values) {
11902
+ if (index2[ref] !== void 0) continue;
11903
+ addGovernanceIssue(
11904
+ issues,
11905
+ "ontology-reference-missing",
11906
+ orgName,
11907
+ resource.id,
11908
+ `[${orgName}] Resource '${resource.id}' ontology.${bindingKey} references missing ${expectedKind} ontology record '${ref}'.`
11909
+ );
11910
+ }
11911
+ };
11912
+ validateRefs("actions", "action", binding.actions);
11913
+ validateRefs("primaryAction", "action", binding.primaryAction);
11914
+ validateRefs("reads", "object", binding.reads);
11915
+ validateRefs("writes", "object", binding.writes);
11916
+ validateRefs("usesCatalogs", "catalog", binding.usesCatalogs);
11917
+ validateRefs("emits", "event", binding.emits);
11918
+ }
11919
+ function addTopologyIssues(issues, orgName, deployment, organizationModel, systemsById, omResourcesById, ontologyIndex) {
11920
+ const relationships = organizationModel.topology?.relationships;
11921
+ if (relationships === void 0) return;
11922
+ const rolesById = new Set(Object.keys(organizationModel.roles ?? {}));
11923
+ const policiesById = new Set(Object.keys(organizationModel.policies ?? {}));
11924
+ const triggerIds = new Set(deployment.triggers?.map((trigger) => trigger.resourceId) ?? []);
11925
+ const humanCheckpointIds = new Set(deployment.humanCheckpoints?.map((checkpoint) => checkpoint.resourceId) ?? []);
11926
+ const externalResourceIds = new Set(deployment.externalResources?.map((external) => external.resourceId) ?? []);
11927
+ const topologyRefExists = (ref) => {
11928
+ if (ref.kind === "system") return systemsById.has(ref.id);
11929
+ if (ref.kind === "resource") return omResourcesById.has(ref.id);
11930
+ if (ref.kind === "policy") return policiesById.has(ref.id);
11931
+ if (ref.kind === "role") return rolesById.has(ref.id);
11932
+ if (ref.kind === "trigger") return triggerIds.has(ref.id);
11933
+ if (ref.kind === "humanCheckpoint") return humanCheckpointIds.has(ref.id);
11934
+ if (ref.kind === "externalResource") return externalResourceIds.has(ref.id);
11935
+ if (ref.kind === "ontology") {
11936
+ if (ontologyIndex === void 0) return true;
11937
+ return Object.values(ontologyIndex).some((records) => records[ref.id] !== void 0);
11938
+ }
11939
+ return false;
11940
+ };
11941
+ for (const [relationshipId, relationship] of Object.entries(relationships)) {
11942
+ ["from", "to"].forEach((side) => {
11943
+ const ref = relationship[side];
11944
+ if (topologyRefExists(ref)) return;
11945
+ addGovernanceIssue(
11946
+ issues,
11947
+ "topology-reference-missing",
11948
+ orgName,
11949
+ ref.id,
11950
+ `[${orgName}] Topology relationship '${relationshipId}' ${side} references missing ${ref.kind} '${ref.id}'.`
11951
+ );
11952
+ });
11953
+ }
11954
+ }
11734
11955
  function validateResourceGovernance(orgName, deployment, organizationModel = deployment.organizationModel, options = {}) {
11735
11956
  const mode = getResourceValidatorMode(options.mode);
11736
11957
  const omResourcesMap = organizationModel?.resources;
@@ -11746,6 +11967,17 @@ function validateResourceGovernance(orgName, deployment, organizationModel = dep
11746
11967
  const omResourcesById = new Map(activeOmResources.map((resource) => [resource.id, resource]));
11747
11968
  const runtimeResources = getRuntimeResources(deployment);
11748
11969
  const runtimeResourcesById = new Map(runtimeResources.map((resource) => [resource.resourceId, resource]));
11970
+ const ontologyCompilation = hasOntologySources(organizationModel) ? compileOrganizationOntology(organizationModel) : void 0;
11971
+ const ontologyIndex = ontologyCompilation?.ontology;
11972
+ for (const diagnostic of ontologyCompilation?.diagnostics ?? []) {
11973
+ addGovernanceIssue(
11974
+ issues,
11975
+ "ontology-reference-missing",
11976
+ orgName,
11977
+ diagnostic.id,
11978
+ `[${orgName}] ${diagnostic.message}`
11979
+ );
11980
+ }
11749
11981
  for (const resource of activeOmResources) {
11750
11982
  if (!systemsById.has(resource.systemPath)) {
11751
11983
  addGovernanceIssue(
@@ -11785,6 +12017,16 @@ function validateResourceGovernance(orgName, deployment, organizationModel = dep
11785
12017
  `[${orgName}] Resource '${resource.id}' system mismatch: code descriptor has '${runtimeResource.descriptor.systemPath}', OM has '${resource.systemPath}'.`
11786
12018
  );
11787
12019
  }
12020
+ if (runtimeResource.descriptor && !sameJson(runtimeResource.descriptor.ontology, resource.ontology)) {
12021
+ addGovernanceIssue(
12022
+ issues,
12023
+ "descriptor-mismatch",
12024
+ orgName,
12025
+ resource.id,
12026
+ `[${orgName}] Resource '${resource.id}' ontology descriptor mismatch between code and OM.`
12027
+ );
12028
+ }
12029
+ addOntologyBindingIssues(issues, orgName, resource, ontologyIndex);
11788
12030
  }
11789
12031
  for (const runtimeResource of runtimeResources) {
11790
12032
  const omResource = omResourcesById.get(runtimeResource.resourceId);
@@ -11826,6 +12068,7 @@ function validateResourceGovernance(orgName, deployment, organizationModel = dep
11826
12068
  );
11827
12069
  }
11828
12070
  }
12071
+ addTopologyIssues(issues, orgName, deployment, organizationModel, systemsById, omResourcesById, ontologyIndex);
11829
12072
  emitGovernanceIssues(issues, mode, options.onWarning);
11830
12073
  return {
11831
12074
  valid: issues.length === 0,