@elevasis/sdk 1.44.3 → 1.45.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 (246) hide show
  1. package/dist/cli.cjs +991 -650
  2. package/dist/index.d.ts +1045 -509
  3. package/dist/index.js +738 -688
  4. package/dist/node/index.d.ts +105 -97
  5. package/dist/test-utils/index.d.ts +42 -28
  6. package/dist/test-utils/index.js +514 -783
  7. package/dist/worker/index.d.ts +12112 -0
  8. package/dist/worker/index.js +121 -182
  9. package/package.json +6 -9
  10. package/reference/_navigation.md +151 -21
  11. package/reference/_reference-manifest.json +186 -4
  12. package/reference/claude-config.md +8 -0
  13. package/reference/core/index.mdx +3 -3
  14. package/reference/examples/organization-model.ts +117 -111
  15. package/reference/index.mdx +4 -4
  16. package/reference/rules/active-change-index.md +40 -54
  17. package/reference/rules/agent-runtime.md +81 -0
  18. package/reference/rules/agent-start-here.md +71 -163
  19. package/reference/rules/deployment.md +33 -10
  20. package/reference/rules/error-handling.md +26 -0
  21. package/reference/rules/execution.md +13 -0
  22. package/reference/rules/frontend.md +10 -3
  23. package/reference/rules/observability.md +9 -1
  24. package/reference/rules/operations.md +26 -17
  25. package/reference/rules/organization-model.md +74 -88
  26. package/reference/rules/organization-os.md +71 -88
  27. package/reference/rules/package-taxonomy.md +11 -2
  28. package/reference/rules/platform.md +13 -7
  29. package/reference/rules/shared-types.md +15 -0
  30. package/reference/rules/task-tracking.md +30 -5
  31. package/reference/rules/ui.md +145 -3
  32. package/reference/rules/vibe-intents.md +271 -0
  33. package/reference/rules/vibe.md +17 -243
  34. package/reference/scaffold/core/organization-graph.mdx +111 -97
  35. package/reference/scaffold/core/organization-model.mdx +234 -214
  36. package/reference/scaffold/operations/propagation-pipeline.md +1 -1
  37. package/reference/scaffold/operations/scaffold-maintenance.md +19 -18
  38. package/reference/scaffold/operations/workflow-recipes.md +71 -19
  39. package/reference/scaffold/recipes/add-a-feature.md +156 -146
  40. package/reference/scaffold/recipes/add-a-resource.md +123 -117
  41. package/reference/scaffold/recipes/customize-crm-actions.md +25 -10
  42. package/reference/scaffold/recipes/customize-knowledge-browser.md +52 -117
  43. package/reference/scaffold/recipes/customize-organization-model.md +161 -149
  44. package/reference/scaffold/recipes/extend-a-base-entity.md +156 -140
  45. package/reference/scaffold/recipes/extend-crm.md +16 -11
  46. package/reference/scaffold/recipes/extend-lead-gen.md +25 -7
  47. package/reference/scaffold/recipes/gate-by-feature-or-admin.md +160 -118
  48. package/reference/scaffold/recipes/index.md +2 -2
  49. package/reference/scaffold/recipes/query-the-knowledge-graph.md +23 -23
  50. package/reference/scaffold/reference/contracts.md +12 -1
  51. package/reference/scaffold/reference/glossary.md +3 -3
  52. package/reference/scaffold/reference/system-interface-capabilities.md +5 -4
  53. package/reference/scaffold/ui/composition-extensibility.mdx +271 -232
  54. package/reference/scaffold/ui/feature-flags-and-gating.md +14 -6
  55. package/reference/scaffold/ui/feature-shell.mdx +279 -62
  56. package/reference/scaffold/ui/recipes.md +229 -197
  57. package/reference/sdk/cli-management.mdx +77 -29
  58. package/reference/sdk/concepts.mdx +2 -0
  59. package/reference/sdk/define-builders.mdx +76 -0
  60. package/reference/sdk/deployment/command-center.mdx +6 -2
  61. package/reference/sdk/deployment/execution-reference.mdx +64 -186
  62. package/reference/sdk/deployment/index.mdx +2 -0
  63. package/reference/sdk/exports.mdx +4 -4
  64. package/reference/sdk/framework/agent.mdx +49 -119
  65. package/reference/sdk/framework/index.mdx +46 -65
  66. package/reference/sdk/framework/project-structure.mdx +150 -205
  67. package/reference/sdk/framework/tutorial-system.mdx +2 -2
  68. package/reference/sdk/human-in-the-loop.mdx +152 -0
  69. package/reference/sdk/index.mdx +6 -7
  70. package/reference/sdk/platform-tools/index.mdx +12 -0
  71. package/reference/sdk/platform-tools/type-safety.mdx +4 -0
  72. package/reference/sdk/project-deployment-spec.mdx +131 -0
  73. package/reference/sdk/resources/index.mdx +21 -7
  74. package/reference/sdk/resources/patterns.mdx +54 -24
  75. package/reference/sdk/resources/types.mdx +7 -4
  76. package/reference/sdk/templates/data-enrichment.mdx +7 -3
  77. package/reference/sdk/templates/email-sender.mdx +139 -135
  78. package/reference/sdk/templates/lead-scorer.mdx +5 -1
  79. package/reference/sdk/templates/pdf-generator.mdx +155 -151
  80. package/reference/sdk/templates/recurring-job.mdx +195 -189
  81. package/reference/sdk/templates/text-classifier.mdx +4 -0
  82. package/reference/sdk/templates/web-scraper.mdx +139 -135
  83. package/reference/spine/spine-primer.md +135 -96
  84. package/reference/ui/index.mdx +14 -7
  85. package/dist/types/worker/adapters/anymailfinder.d.ts +0 -14
  86. package/dist/types/worker/adapters/apify.d.ts +0 -14
  87. package/dist/types/worker/adapters/approval.d.ts +0 -23
  88. package/dist/types/worker/adapters/attio.d.ts +0 -22
  89. package/dist/types/worker/adapters/clickup.d.ts +0 -22
  90. package/dist/types/worker/adapters/create-adapter.d.ts +0 -41
  91. package/dist/types/worker/adapters/crm.d.ts +0 -20
  92. package/dist/types/worker/adapters/dropbox.d.ts +0 -14
  93. package/dist/types/worker/adapters/email.d.ts +0 -25
  94. package/dist/types/worker/adapters/execution.d.ts +0 -22
  95. package/dist/types/worker/adapters/gmail.d.ts +0 -14
  96. package/dist/types/worker/adapters/google-sheets.d.ts +0 -14
  97. package/dist/types/worker/adapters/index.d.ts +0 -33
  98. package/dist/types/worker/adapters/instantly.d.ts +0 -14
  99. package/dist/types/worker/adapters/lead.d.ts +0 -28
  100. package/dist/types/worker/adapters/list.d.ts +0 -9
  101. package/dist/types/worker/adapters/llm.d.ts +0 -45
  102. package/dist/types/worker/adapters/millionverifier.d.ts +0 -14
  103. package/dist/types/worker/adapters/notification.d.ts +0 -28
  104. package/dist/types/worker/adapters/pdf.d.ts +0 -22
  105. package/dist/types/worker/adapters/projects.d.ts +0 -20
  106. package/dist/types/worker/adapters/resend.d.ts +0 -14
  107. package/dist/types/worker/adapters/scheduler.d.ts +0 -25
  108. package/dist/types/worker/adapters/signature-api.d.ts +0 -14
  109. package/dist/types/worker/adapters/storage.d.ts +0 -33
  110. package/dist/types/worker/adapters/stripe.d.ts +0 -14
  111. package/dist/types/worker/adapters/tomba.d.ts +0 -14
  112. package/dist/types/worker/index.d.ts +0 -60
  113. package/dist/types/worker/platform.d.ts +0 -90
  114. package/dist/types/worker/utils.d.ts +0 -9
  115. package/reference/claude-config/Overview.md +0 -230
  116. package/reference/claude-config/hooks/post-edit-validate.mjs +0 -98
  117. package/reference/claude-config/hooks/scaffold-registry-reminder.mjs +0 -187
  118. package/reference/claude-config/hooks/tool-failure-recovery.mjs +0 -73
  119. package/reference/claude-config/registries/graph-skills.json +0 -4
  120. package/reference/claude-config/registries/knowledge-flags.json +0 -154
  121. package/reference/claude-config/registries/skill-coverage.json +0 -20
  122. package/reference/claude-config/rules/active-change-index.md +0 -22
  123. package/reference/claude-config/rules/agent-start-here.md +0 -22
  124. package/reference/claude-config/rules/deployment.md +0 -22
  125. package/reference/claude-config/rules/error-handling.md +0 -22
  126. package/reference/claude-config/rules/execution.md +0 -22
  127. package/reference/claude-config/rules/frontend.md +0 -22
  128. package/reference/claude-config/rules/observability.md +0 -22
  129. package/reference/claude-config/rules/operations.md +0 -22
  130. package/reference/claude-config/rules/organization-model.md +0 -22
  131. package/reference/claude-config/rules/organization-os.md +0 -22
  132. package/reference/claude-config/rules/package-taxonomy.md +0 -22
  133. package/reference/claude-config/rules/platform.md +0 -22
  134. package/reference/claude-config/rules/shared-types.md +0 -22
  135. package/reference/claude-config/rules/task-tracking.md +0 -22
  136. package/reference/claude-config/rules/topbar-actions.md +0 -70
  137. package/reference/claude-config/rules/ui.md +0 -22
  138. package/reference/claude-config/rules/vibe.md +0 -22
  139. package/reference/claude-config/scripts/statusline-command.js +0 -18
  140. package/reference/claude-config/settings.json +0 -30
  141. package/reference/claude-config/skills/client/SKILL.md +0 -201
  142. package/reference/claude-config/skills/deploy/SKILL.md +0 -159
  143. package/reference/claude-config/skills/dsp/SKILL.md +0 -66
  144. package/reference/claude-config/skills/elevasis/SKILL.md +0 -251
  145. package/reference/claude-config/skills/explore/SKILL.md +0 -78
  146. package/reference/claude-config/skills/git-sync/SKILL.md +0 -166
  147. package/reference/claude-config/skills/om/SKILL.md +0 -475
  148. package/reference/claude-config/skills/om/operations/build.md +0 -237
  149. package/reference/claude-config/skills/om/operations/codify-level-a.md +0 -109
  150. package/reference/claude-config/skills/om/operations/codify-level-b.md +0 -159
  151. package/reference/claude-config/skills/om/operations/customers.md +0 -114
  152. package/reference/claude-config/skills/om/operations/features.md +0 -88
  153. package/reference/claude-config/skills/om/operations/goals.md +0 -123
  154. package/reference/claude-config/skills/om/operations/identity.md +0 -97
  155. package/reference/claude-config/skills/om/operations/labels.md +0 -110
  156. package/reference/claude-config/skills/om/operations/offerings.md +0 -114
  157. package/reference/claude-config/skills/om/operations/roles.md +0 -104
  158. package/reference/claude-config/skills/om/operations/scaffold.md +0 -163
  159. package/reference/claude-config/skills/om/operations/techStack.md +0 -38
  160. package/reference/claude-config/skills/project/SKILL.md +0 -1114
  161. package/reference/claude-config/skills/run-ui/SKILL.md +0 -73
  162. package/reference/claude-config/skills/save/SKILL.md +0 -183
  163. package/reference/claude-config/skills/setup/SKILL.md +0 -290
  164. package/reference/claude-config/skills/status/SKILL.md +0 -59
  165. package/reference/claude-config/skills/submit-request/SKILL.md +0 -180
  166. package/reference/claude-config/skills/sync/SKILL.md +0 -47
  167. package/reference/claude-config/skills/tutorial/SKILL.md +0 -259
  168. package/reference/claude-config/skills/tutorial/progress-template.md +0 -74
  169. package/reference/claude-config/skills/tutorial/technical.md +0 -1303
  170. package/reference/claude-config/skills/tutorial/vibe-coder.md +0 -890
  171. package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +0 -27
  172. package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +0 -30
  173. package/reference/claude-config/sync-notes/2026-04-24-test-utils-and-template-tests.md +0 -73
  174. package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +0 -86
  175. package/reference/claude-config/sync-notes/2026-04-25-auth-role-system-and-settings-roles.md +0 -55
  176. package/reference/claude-config/sync-notes/2026-04-27-crm-hitl-action-layer-cutover.md +0 -97
  177. package/reference/claude-config/sync-notes/2026-04-27-lead-gen-substrate-train.md +0 -112
  178. package/reference/claude-config/sync-notes/2026-04-29-crm-state-and-lead-gen-processing-status.md +0 -93
  179. package/reference/claude-config/sync-notes/2026-05-02-crm-ownership-next-action.md +0 -58
  180. package/reference/claude-config/sync-notes/2026-05-02-template-hardcode-workos-config.md +0 -56
  181. package/reference/claude-config/sync-notes/2026-05-04-elevasis-workspace.md +0 -71
  182. package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +0 -83
  183. package/reference/claude-config/sync-notes/2026-05-04-template-skills-run-ui-and-tutorial.md +0 -59
  184. package/reference/claude-config/sync-notes/2026-05-05-list-builder.md +0 -42
  185. package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +0 -60
  186. package/reference/claude-config/sync-notes/2026-05-06-sdk-changes-release-train.md +0 -37
  187. package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +0 -34
  188. package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +0 -38
  189. package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +0 -32
  190. package/reference/claude-config/sync-notes/2026-05-09-command-system.md +0 -33
  191. package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +0 -69
  192. package/reference/claude-config/sync-notes/2026-05-12-sdk-ready-release-train.md +0 -30
  193. package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +0 -45
  194. package/reference/claude-config/sync-notes/2026-05-15-om-skill-rename-and-write-family.md +0 -52
  195. package/reference/claude-config/sync-notes/2026-05-17-sdk-boundary-consolidation.md +0 -33
  196. package/reference/claude-config/sync-notes/2026-05-20-om-define-helpers.md +0 -32
  197. package/reference/claude-config/sync-notes/2026-05-22-access-model-and-right-panel.md +0 -43
  198. package/reference/claude-config/sync-notes/2026-05-22-lead-gen-tenant-config.md +0 -40
  199. package/reference/claude-config/sync-notes/2026-05-22-org-model-multi-file-split.md +0 -61
  200. package/reference/claude-config/sync-notes/2026-05-23-branding-names-to-identity.md +0 -49
  201. package/reference/claude-config/sync-notes/2026-05-23-lead-gen-manage-access.md +0 -31
  202. package/reference/claude-config/sync-notes/2026-05-23-om-deployment-drift-detection.md +0 -42
  203. package/reference/claude-config/sync-notes/2026-05-23-om-full-model-deploy-contract.md +0 -33
  204. package/reference/claude-config/sync-notes/2026-05-23-ui-sdk-package-fixes.md +0 -37
  205. package/reference/claude-config/sync-notes/2026-05-24-platform-invite-router-core-baseline.md +0 -28
  206. package/reference/claude-config/sync-notes/2026-05-24-system-interface-readiness.md +0 -43
  207. package/reference/claude-config/sync-notes/2026-05-25-invitation-login-loader.md +0 -26
  208. package/reference/claude-config/sync-notes/2026-05-25-om-topbar-requests.md +0 -33
  209. package/reference/claude-config/sync-notes/2026-05-25-system-interface-profile-registry-and-substrate.md +0 -35
  210. package/reference/claude-config/sync-notes/2026-05-25-tenant-om-scaffold-cli.md +0 -49
  211. package/reference/claude-config/sync-notes/2026-05-25-vibe-operate-intent.md +0 -47
  212. package/reference/claude-config/sync-notes/2026-05-28-om-snapshot-sdk-workflow-config.md +0 -33
  213. package/reference/claude-config/sync-notes/2026-05-30-client-source-and-om-profiles.md +0 -39
  214. package/reference/claude-config/sync-notes/2026-06-02-knowledge-nested-group-routing.md +0 -27
  215. package/reference/claude-config/sync-notes/2026-06-02-nest-projects-under-platform.md +0 -45
  216. package/reference/claude-config/sync-notes/2026-06-03-skill-autogen-and-client-skill.md +0 -34
  217. package/reference/claude-config/sync-notes/2026-06-04-scaffold-registry-lane-severity.md +0 -34
  218. package/reference/claude-config/sync-notes/2026-06-05-appearance-app-mode-decouple.md +0 -29
  219. package/reference/claude-config/sync-notes/2026-06-05-ontology-endpoint-rename-and-knowledge-browser-ui.md +0 -86
  220. package/reference/claude-config/sync-notes/2026-06-06-om-build-systems-scaffold.md +0 -47
  221. package/reference/claude-config/sync-notes/2026-06-06-om-item-copy-references.md +0 -50
  222. package/reference/claude-config/sync-notes/2026-06-08-knowledge-base-page-not-found-fix.md +0 -76
  223. package/reference/claude-config/sync-notes/2026-06-09-agent-sessions-public-agent-chat-route.md +0 -75
  224. package/reference/claude-config/sync-notes/2026-06-09-sdk-cli-load-org-model-resolution.md +0 -42
  225. package/reference/claude-config/sync-notes/2026-06-12-agent-grants-visualizer-operations.md +0 -30
  226. package/reference/claude-config/sync-notes/2026-06-14-session-ux-and-project-cli-json.md +0 -33
  227. package/reference/claude-config/sync-notes/2026-06-14-shared-session-conversation-view.md +0 -26
  228. package/reference/claude-config/sync-notes/2026-06-15-session-chat-zero-wiring.md +0 -46
  229. package/reference/claude-config/sync-notes/2026-06-17-agent-session-ux-features.md +0 -34
  230. package/reference/claude-config/sync-notes/2026-06-25-shared-page-scroll-contract-guard.md +0 -52
  231. package/reference/claude-config/sync-notes/2026-06-26-leadgen-overview-om-telemetry.md +0 -47
  232. package/reference/claude-config/sync-notes/2026-07-21-agent-scaffold-hardening.md +0 -75
  233. package/reference/claude-config/sync-notes/2026-07-23-agent-session-memory.md +0 -49
  234. package/reference/claude-config/sync-notes/2026-07-23-workos-org-marker.md +0 -50
  235. package/reference/claude-config/sync-notes/2026-07-24-claude-5-models-and-session-surface-fixes.md +0 -116
  236. package/reference/claude-config/sync-notes/2026-07-27-agent-strict-output-and-turn-drift.md +0 -73
  237. package/reference/claude-config/sync-notes/2026-07-28-agent-reply-is-its-own-field.md +0 -84
  238. package/reference/claude-config/sync-notes/2026-07-30-login-screen-and-member-provisioning-state.md +0 -114
  239. package/reference/claude-config/sync-notes/2026-08-02-auth-guard-defaults-and-truncation-fix.md +0 -122
  240. package/reference/claude-config/sync-notes/2026-08-03-agent-prose-escape-normalization.md +0 -88
  241. package/reference/claude-config/sync-notes/2026-08-03-cli-gateway-errors-and-request-timeout.md +0 -120
  242. package/reference/claude-config/sync-notes/README.md +0 -43
  243. package/reference/sdk/framework/interaction-guidance.mdx +0 -182
  244. package/reference/sdk/framework/memory.mdx +0 -326
  245. package/reference/sdk/framework/resource-documentation.mdx +0 -90
  246. package/reference/sdk/roadmap.mdx +0 -164
@@ -4343,6 +4343,23 @@ var Workflow = class {
4343
4343
 
4344
4344
  // ../core/src/execution/engine/agent/observability/logging.ts
4345
4345
  function createAgentLogger(logger, agentId, sessionId) {
4346
+ function emitAction(actionType, message, iteration, startTime, endTime, duration) {
4347
+ const event = {
4348
+ type: "agent",
4349
+ agentId,
4350
+ lifecycle: "iteration",
4351
+ eventType: "action",
4352
+ iteration,
4353
+ actionType,
4354
+ startTime,
4355
+ endTime,
4356
+ duration,
4357
+ data: { message },
4358
+ ...sessionId && { sessionId }
4359
+ // Include sessionId if present
4360
+ };
4361
+ logger.info("action", event);
4362
+ }
4346
4363
  return {
4347
4364
  lifecycle(lifecycle, stage, data) {
4348
4365
  let event;
@@ -4409,21 +4426,15 @@ function createAgentLogger(logger, agentId, sessionId) {
4409
4426
  logger.info("reasoning", event);
4410
4427
  },
4411
4428
  action(actionType, message, iteration, startTime, endTime, duration) {
4412
- const event = {
4413
- type: "agent",
4414
- agentId,
4415
- lifecycle: "iteration",
4416
- eventType: "action",
4417
- iteration,
4418
- actionType,
4419
- startTime,
4420
- endTime,
4421
- duration,
4422
- data: { message },
4423
- ...sessionId && { sessionId }
4424
- // Include sessionId if present
4425
- };
4426
- logger.info("action", event);
4429
+ emitAction(actionType, message, iteration, startTime, endTime, duration);
4430
+ },
4431
+ async timed(actionType, iteration, work, message) {
4432
+ const startTime = Date.now();
4433
+ const result = await work();
4434
+ const endTime = Date.now();
4435
+ const resolvedActionType = typeof actionType === "function" ? actionType(result) : actionType;
4436
+ emitAction(resolvedActionType, message(result), iteration, startTime, endTime, endTime - startTime);
4437
+ return result;
4427
4438
  },
4428
4439
  toolCall(toolName, iteration, startTime, endTime, duration, success, error, input, output) {
4429
4440
  const event = {
@@ -5351,66 +5362,21 @@ async function processReasoning(iterationContext) {
5351
5362
  reasoning: response.reasoning
5352
5363
  });
5353
5364
  iterationContext.logger.reasoning(response.reasoning, iterationContext.iteration, startTime, endTime, duration);
5354
- const memoryStartTime = Date.now();
5355
- iterationContext.memoryManager.addToHistory({
5356
- type: "reasoning",
5357
- content: response.reasoning,
5358
- turnNumber: iterationContext.executionContext.sessionTurnNumber ?? null,
5359
- iterationNumber: iterationContext.iteration,
5360
- source: "model"
5361
- });
5362
- const memoryEndTime = Date.now();
5363
- const memoryDuration = memoryEndTime - memoryStartTime;
5364
- iterationContext.logger.action(
5365
+ await iterationContext.logger.timed(
5365
5366
  "memory-reasoning",
5366
- `Stored reasoning (${response.reasoning.length} chars), history size: ${iterationContext.memoryManager.getHistoryLength()}, actions: ${response.nextActions.map((a3) => a3.type).join(", ")}`,
5367
5367
  iterationContext.iteration,
5368
- memoryStartTime,
5369
- memoryEndTime,
5370
- memoryDuration
5368
+ () => iterationContext.memoryManager.addToHistory({
5369
+ type: "reasoning",
5370
+ content: response.reasoning,
5371
+ turnNumber: iterationContext.executionContext.sessionTurnNumber ?? null,
5372
+ iterationNumber: iterationContext.iteration,
5373
+ source: "model"
5374
+ }),
5375
+ () => `Stored reasoning (${response.reasoning.length} chars), history size: ${iterationContext.memoryManager.getHistoryLength()}, actions: ${response.nextActions.map((a3) => a3.type).join(", ")}`
5371
5376
  );
5372
5377
  return response;
5373
5378
  }
5374
5379
 
5375
- // ../core/src/execution/engine/agent/memory/domains.ts
5376
- var MEMORY_DOMAINS = {
5377
- /**
5378
- * Tool-owned keys
5379
- * Updated automatically by tools as side effects
5380
- * LLM cannot modify these via memoryOps
5381
- *
5382
- * Tools manage complex structured data (caches, indexes, etc.)
5383
- * that would be error-prone for LLM to update via JSON strings.
5384
- *
5385
- * No tool currently writes these three keys, so in practice the guard reserves the names
5386
- * against the LLM rather than arbitrating a live conflict. That is still enforcement --
5387
- * see `validateMemoryKeyOwnership` in `./utils` -- not dead code.
5388
- */
5389
- TOOL_OWNED: [
5390
- "notion-pages-cache",
5391
- // Notion tools manage page hierarchy
5392
- "github-repo-cache",
5393
- // GitHub tools manage repository structure
5394
- "slack-channel-cache"
5395
- // Slack tools manage channel data
5396
- ]
5397
- /**
5398
- * LLM-owned keys
5399
- * All keys NOT in TOOL_OWNED
5400
- * Managed via memoryOps by agent reasoning
5401
- *
5402
- * LLM manages semantic memory (business context, decisions, etc.)
5403
- * that requires understanding and judgment.
5404
- */
5405
- };
5406
- function isToolOwnedKey(key) {
5407
- return MEMORY_DOMAINS.TOOL_OWNED.includes(key);
5408
- }
5409
- function getKeyOwner(key) {
5410
- if (isToolOwnedKey(key)) return "tool";
5411
- return "llm";
5412
- }
5413
-
5414
5380
  // ../core/src/execution/engine/agent/memory/utils.ts
5415
5381
  function addToolError(memoryManager, action, errorMessage, iteration, turnNumber = null, metadata) {
5416
5382
  memoryManager.addToHistory({
@@ -5434,11 +5400,10 @@ function addToolError(memoryManager, action, errorMessage, iteration, turnNumber
5434
5400
  });
5435
5401
  }
5436
5402
  function validateMemoryKeyOwnership(key, logger, iteration) {
5437
- if (isToolOwnedKey(key)) {
5438
- const owner = getKeyOwner(key);
5403
+ if (key.startsWith("_")) {
5439
5404
  logger.action(
5440
5405
  "memory-set-rejected",
5441
- `Rejected LLM update to ${owner}-managed key: ${key}`,
5406
+ `Rejected LLM update to framework-reserved key: ${key}`,
5442
5407
  iteration,
5443
5408
  Date.now(),
5444
5409
  Date.now(),
@@ -5680,25 +5645,19 @@ async function executeToolCall(iterationContext, action) {
5680
5645
  action.input,
5681
5646
  boundedResult
5682
5647
  );
5683
- const memoryStartTime = Date.now();
5684
5648
  const memoryContent = typeof boundedResult === "string" ? boundedResult : JSON.stringify(boundedResult);
5685
- iterationContext.memoryManager.addToHistory({
5686
- type: "tool-result",
5687
- content: memoryContent,
5688
- toolName: action.name,
5689
- turnNumber: iterationContext.executionContext.sessionTurnNumber ?? null,
5690
- iterationNumber: iterationContext.iteration,
5691
- source: "tool"
5692
- });
5693
- const memoryEndTime = Date.now();
5694
- const memoryDuration = memoryEndTime - memoryStartTime;
5695
- iterationContext.logger.action(
5649
+ await iterationContext.logger.timed(
5696
5650
  "memory-tool-result",
5697
- `Stored tool-result for ${action.name} (${memoryContent.length} chars), history size: ${iterationContext.memoryManager.getHistoryLength()}`,
5698
5651
  iterationContext.iteration,
5699
- memoryStartTime,
5700
- memoryEndTime,
5701
- memoryDuration
5652
+ () => iterationContext.memoryManager.addToHistory({
5653
+ type: "tool-result",
5654
+ content: memoryContent,
5655
+ toolName: action.name,
5656
+ turnNumber: iterationContext.executionContext.sessionTurnNumber ?? null,
5657
+ iterationNumber: iterationContext.iteration,
5658
+ source: "tool"
5659
+ }),
5660
+ () => `Stored tool-result for ${action.name} (${memoryContent.length} chars), history size: ${iterationContext.memoryManager.getHistoryLength()}`
5702
5661
  );
5703
5662
  } catch (error) {
5704
5663
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -5721,29 +5680,25 @@ async function executeToolCall(iterationContext, action) {
5721
5680
  action.input,
5722
5681
  void 0
5723
5682
  );
5724
- const memoryStartTime = Date.now();
5725
- const metadata = error instanceof ToolingError ? {
5726
- errorType: error.errorType,
5727
- severity: error.severity,
5728
- isRetryable: error.isRetryable()
5729
- } : void 0;
5730
- addToolError(
5731
- iterationContext.memoryManager,
5732
- action,
5733
- errorMessage,
5734
- iterationContext.iteration,
5735
- iterationContext.executionContext.sessionTurnNumber ?? null,
5736
- metadata
5737
- );
5738
- const memoryEndTime = Date.now();
5739
- const memoryDuration = memoryEndTime - memoryStartTime;
5740
- iterationContext.logger.action(
5683
+ await iterationContext.logger.timed(
5741
5684
  "memory-tool-error",
5742
- `Stored error for ${action.name}: ${errorMessage}, history size: ${iterationContext.memoryManager.getHistoryLength()}`,
5743
5685
  iterationContext.iteration,
5744
- memoryStartTime,
5745
- memoryEndTime,
5746
- memoryDuration
5686
+ () => {
5687
+ const metadata = error instanceof ToolingError ? {
5688
+ errorType: error.errorType,
5689
+ severity: error.severity,
5690
+ isRetryable: error.isRetryable()
5691
+ } : void 0;
5692
+ addToolError(
5693
+ iterationContext.memoryManager,
5694
+ action,
5695
+ errorMessage,
5696
+ iterationContext.iteration,
5697
+ iterationContext.executionContext.sessionTurnNumber ?? null,
5698
+ metadata
5699
+ );
5700
+ },
5701
+ () => `Stored error for ${action.name}: ${errorMessage}, history size: ${iterationContext.memoryManager.getHistoryLength()}`
5747
5702
  );
5748
5703
  }
5749
5704
  }
@@ -5981,11 +5936,13 @@ async function processMemory(memoryManager, response, logger, iteration) {
5981
5936
  if (!validateMemoryKeyOwnership(key, logger, iteration)) {
5982
5937
  continue;
5983
5938
  }
5984
- const startTime = Date.now();
5985
- const stringValue2 = typeof content === "string" ? content : JSON.stringify(content);
5986
- memoryManager.set(key, stringValue2);
5987
- const endTime = Date.now();
5988
- logger.action("memory-set", `Set: ${key}`, iteration, startTime, endTime, endTime - startTime);
5939
+ await logger.timed(
5940
+ "memory-set",
5941
+ iteration,
5942
+ // Auto-stringify non-string values (arrays, objects, etc.)
5943
+ () => memoryManager.set(key, typeof content === "string" ? content : JSON.stringify(content)),
5944
+ () => `Set: ${key}`
5945
+ );
5989
5946
  }
5990
5947
  }
5991
5948
  if (memoryOps.delete) {
@@ -5993,21 +5950,12 @@ async function processMemory(memoryManager, response, logger, iteration) {
5993
5950
  if (!validateMemoryKeyOwnership(key, logger, iteration)) {
5994
5951
  continue;
5995
5952
  }
5996
- const startTime = Date.now();
5997
- const deleted = memoryManager.delete(key);
5998
- const endTime = Date.now();
5999
- if (deleted) {
6000
- logger.action("memory-delete", `Deleted: ${key}`, iteration, startTime, endTime, endTime - startTime);
6001
- } else {
6002
- logger.action(
6003
- "memory-delete-missing",
6004
- `Attempted to delete non-existent key: ${key}`,
6005
- iteration,
6006
- startTime,
6007
- endTime,
6008
- endTime - startTime
6009
- );
6010
- }
5953
+ await logger.timed(
5954
+ (deleted) => deleted ? "memory-delete" : "memory-delete-missing",
5955
+ iteration,
5956
+ () => memoryManager.delete(key),
5957
+ (deleted) => deleted ? `Deleted: ${key}` : `Attempted to delete non-existent key: ${key}`
5958
+ );
6011
5959
  }
6012
5960
  }
6013
5961
  }
@@ -6134,7 +6082,6 @@ var MemoryManager = class {
6134
6082
  this.constraints = constraints;
6135
6083
  this.logger = logger;
6136
6084
  }
6137
- cachedSnapshot;
6138
6085
  /**
6139
6086
  * Rolling correction for `estimateTokens`'s bias, learned from real provider usage.
6140
6087
  * `undefined` until the first `recordActualUsage` call -- the cold-start state, where
@@ -6423,21 +6370,15 @@ var MemoryManager = class {
6423
6370
  };
6424
6371
  }
6425
6372
  /**
6426
- * Create memory snapshot for persistence
6427
- * Caches snapshot internally for later retrieval
6373
+ * Create a memory snapshot for persistence.
6374
+ *
6375
+ * Stateless: every call returns a fresh `structuredClone` of the current memory, so the caller
6376
+ * owns caching if it needs to hold onto the result across calls (see `Agent.memorySnapshot`).
6377
+ *
6428
6378
  * @returns Deep copy of current memory state
6429
6379
  */
6430
- toSnapshot() {
6431
- this.cachedSnapshot = structuredClone(this.memory);
6432
- return this.cachedSnapshot;
6433
- }
6434
- /**
6435
- * Get cached memory snapshot
6436
- * Returns snapshot created by toSnapshot()
6437
- * @returns Cached snapshot (undefined if toSnapshot() not called yet)
6438
- */
6439
- getSnapshot() {
6440
- return this.cachedSnapshot;
6380
+ snapshot() {
6381
+ return structuredClone(this.memory);
6441
6382
  }
6442
6383
  /**
6443
6384
  * Build the framework framing and the untrusted data envelope for an LLM call.
@@ -6569,6 +6510,12 @@ var Agent = class {
6569
6510
  * reading memory history after the fact, because the emit is the user-visible event and memory
6570
6511
  * can be compacted or restructured without changing whether the turn spoke. */
6571
6512
  spokeThisTurn = false;
6513
+ /** Cached result of `memoryManager.snapshot()` -- `MemoryManager.snapshot()` itself is stateless
6514
+ * (a fresh `structuredClone` every call), so caching the LAST one taken is this class's job. Set
6515
+ * once, in the `finally` around `iterate()` and again in `complete()` -- see `getMemorySnapshot()`
6516
+ * for why `undefined`-before-first-iteration is a contract other callers (`session.ts`, the SDK
6517
+ * worker) depend on. */
6518
+ memorySnapshot;
6572
6519
  /**
6573
6520
  * Create a new agent instance from definition
6574
6521
  * Memory will be initialized during execution
@@ -6609,7 +6556,7 @@ var Agent = class {
6609
6556
  try {
6610
6557
  await this.iterate(this.executionContext);
6611
6558
  } finally {
6612
- this.memoryManager.toSnapshot();
6559
+ this.memorySnapshot = this.memoryManager.snapshot();
6613
6560
  }
6614
6561
  }
6615
6562
  const output = await this.complete();
@@ -6722,22 +6669,21 @@ var Agent = class {
6722
6669
  async initializeMemoryManager(context) {
6723
6670
  const memory = await this.resolveInitialMemory(context);
6724
6671
  const memoryManager = new MemoryManager(memory, this.config.constraints, this.logger);
6725
- const inputStartTime = Date.now();
6726
- memoryManager.addToHistory({
6727
- type: "input",
6728
- content: this.currentInput,
6729
- turnNumber: context.sessionTurnNumber ?? null,
6730
- iterationNumber: 0,
6731
- source: "user"
6732
- });
6733
- const inputEndTime = Date.now();
6734
- this.logger.action(
6672
+ await this.logger.timed(
6735
6673
  "memory-input",
6736
- `Added input entry to history`,
6737
6674
  0,
6738
- inputStartTime,
6739
- inputEndTime,
6740
- inputEndTime - inputStartTime
6675
+ // Kept in history even though the input also travels as its own message: history is what
6676
+ // later iterations and later turns read, and `autoCompact` anchors on `history[0]` as the
6677
+ // original input. `toContextParts` excludes this entry from the current turn's envelope so
6678
+ // the model does not see the same text twice.
6679
+ () => memoryManager.addToHistory({
6680
+ type: "input",
6681
+ content: this.currentInput,
6682
+ turnNumber: context.sessionTurnNumber ?? null,
6683
+ iterationNumber: 0,
6684
+ source: "user"
6685
+ }),
6686
+ () => `Added input entry to history`
6741
6687
  );
6742
6688
  flowLog("agent.initialize", {
6743
6689
  resourceId: this.config.resourceId,
@@ -6759,32 +6705,20 @@ var Agent = class {
6759
6705
  */
6760
6706
  async resolveInitialMemory(context) {
6761
6707
  if (this.initialMemory) {
6762
- const restoreStartTime = Date.now();
6763
- const memory = structuredClone(this.initialMemory);
6764
- const restoreEndTime = Date.now();
6765
- this.logger.action(
6708
+ return this.logger.timed(
6766
6709
  "memory-restore",
6767
- `Restored ${Object.keys(memory.sessionMemory).length} session memory entries`,
6768
6710
  0,
6769
- restoreStartTime,
6770
- restoreEndTime,
6771
- restoreEndTime - restoreStartTime
6711
+ () => structuredClone(this.initialMemory),
6712
+ (memory) => `Restored ${Object.keys(memory.sessionMemory).length} session memory entries`
6772
6713
  );
6773
- return memory;
6774
6714
  }
6775
6715
  if (this.definition.preloadMemory) {
6776
- const preloadStartTime = Date.now();
6777
- const memory = await this.definition.preloadMemory(context);
6778
- const preloadEndTime = Date.now();
6779
- this.logger.action(
6716
+ return this.logger.timed(
6780
6717
  "memory-preload",
6781
- `Preloaded ${Object.keys(memory.sessionMemory).length} session memory entries`,
6782
6718
  0,
6783
- preloadStartTime,
6784
- preloadEndTime,
6785
- preloadEndTime - preloadStartTime
6719
+ () => this.definition.preloadMemory(context),
6720
+ (memory) => `Preloaded ${Object.keys(memory.sessionMemory).length} session memory entries`
6786
6721
  );
6787
- return memory;
6788
6722
  }
6789
6723
  return { sessionMemory: {}, history: [] };
6790
6724
  }
@@ -6918,8 +6852,8 @@ var Agent = class {
6918
6852
  0
6919
6853
  );
6920
6854
  }
6921
- this.memoryManager.toSnapshot();
6922
- const snapshot = this.memoryManager.getSnapshot();
6855
+ const snapshot = this.memoryManager.snapshot();
6856
+ this.memorySnapshot = snapshot;
6923
6857
  const completionEndTime = Date.now();
6924
6858
  this.logger.lifecycle("completion", "completed", {
6925
6859
  startTime: completionStartTime,
@@ -7135,12 +7069,17 @@ Fix the errors and generate a valid output.
7135
7069
  `.trim();
7136
7070
  }
7137
7071
  /**
7138
- * Get memory snapshot after execution
7139
- * Delegates to MemoryManager.getSnapshot()
7140
- * @returns Memory snapshot (only available after execute() completes)
7072
+ * Get memory snapshot after execution.
7073
+ *
7074
+ * `undefined` until the `finally` around `iterate()` (or `complete()`) takes the first snapshot --
7075
+ * `session.ts` and the SDK worker both rely on this to distinguish "no memory produced yet" (a
7076
+ * throw during `initialize()`, before any iteration ran) from "memory exists".
7077
+ *
7078
+ * @returns Memory snapshot (only available after execute() completes, or after a mid-turn throw
7079
+ * past the point `iterate()` began)
7141
7080
  */
7142
7081
  getMemorySnapshot() {
7143
- return this.memoryManager.getSnapshot();
7082
+ return this.memorySnapshot;
7144
7083
  }
7145
7084
  /**
7146
7085
  * How the just-finished turn ended -- see `AgentStopReason`. Set once `iterate()` returns,
@@ -9067,17 +9006,23 @@ var SystemInterfaceResourceScopeSchema = z.array(ModelIdSchema).default([]);
9067
9006
  var SystemApiInterfaceReadinessContractSchema = z.object({
9068
9007
  /** Ontology IDs of object types the interface depends on. */
9069
9008
  requiredObjects: z.array(z.string().trim().min(1)).default([]),
9070
- /** Ontology IDs of catalog types the interface requires (must be non-empty). */
9071
- requiredCatalogs: z.array(z.string().trim().min(1)).default([]),
9072
- /** Optional ontology kind filters (reserved for future profile extensions). */
9073
- requiredKinds: z.array(z.string().trim().min(1)).optional()
9009
+ /**
9010
+ * Ontology IDs of catalog types the interface requires. Must declare at least one
9011
+ * entry a `readinessContract` with no `requiredCatalogs` asserts nothing at all,
9012
+ * so it has no `.default([])`; omitting the field is rejected the same as an
9013
+ * explicit empty array.
9014
+ */
9015
+ requiredCatalogs: z.array(z.string().trim().min(1)).min(1)
9074
9016
  }).strict();
9075
9017
  var SystemApiInterfaceSchema = z.object({
9076
9018
  lifecycle: SystemInterfaceLifecycleSchema.default("active"),
9077
9019
  /**
9078
9020
  * Open-string profile id. Built-in platform presets are looked up through
9079
9021
  * the profile registry; custom ids are validated structurally via
9080
- * `readinessContract`. Optional `profileForInterface` provides a default.
9022
+ * `readinessContract`. Optional at the schema layer, but readiness
9023
+ * computation rejects an interface that omits it with a
9024
+ * `missing-readiness-profile` diagnostic — there is no positional
9025
+ * fallback to `${systemPath}.${interfaceKey}`.
9081
9026
  */
9082
9027
  readinessProfile: SystemInterfaceReadinessProfileSchema.optional(),
9083
9028
  /**
@@ -9098,9 +9043,6 @@ var _profileRegistry = new Map(
9098
9043
  { profileId, kind: "built-in" }
9099
9044
  ])
9100
9045
  );
9101
- function profileForInterface(systemPath, interfaceKey, readinessProfile) {
9102
- return readinessProfile ?? `${systemPath}.${interfaceKey}`;
9103
- }
9104
9046
  function isBuiltInReadinessProfile(profileId) {
9105
9047
  return _profileRegistry.get(profileId)?.kind === "built-in";
9106
9048
  }
@@ -9197,469 +9139,137 @@ z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record
9197
9139
  message: "Each system entry id must match its map key"
9198
9140
  }).default({});
9199
9141
 
9200
- // ../core/src/organization-model/migration-helpers.ts
9201
- function catalogRecords(model) {
9202
- return Object.values(compileOrganizationOntology(model).ontology.catalogTypes);
9142
+ // ../core/src/organization-model/readiness/profile-registry.ts
9143
+ var _builtInProfileValidators = /* @__PURE__ */ new Map();
9144
+ function getBuiltInReadinessProfile(profileId) {
9145
+ return _builtInProfileValidators.get(profileId);
9203
9146
  }
9204
- function systemScope(id, fallback) {
9205
- return parseOntologyId(id).scope || fallback || "";
9147
+ var _interfaceMarkerResolvers = /* @__PURE__ */ new Map();
9148
+ function interfaceMarkerKey(systemPath, interfaceKey) {
9149
+ return `${systemPath}::${interfaceKey}`;
9206
9150
  }
9207
- function entriesOf(catalog) {
9208
- return Object.entries(catalog.entries ?? {}).map(([id, value]) => [
9209
- id,
9210
- value && typeof value === "object" && !Array.isArray(value) ? value : {}
9211
- ]);
9151
+ function resolveReadinessInterfaceMarker(model, systemPath, interfaceKey) {
9152
+ return _interfaceMarkerResolvers.get(interfaceMarkerKey(systemPath, interfaceKey))?.(model);
9212
9153
  }
9213
- function stringValue(value) {
9214
- return typeof value === "string" ? value : void 0;
9154
+
9155
+ // ../core/src/organization-model/readiness/engine.ts
9156
+ function addReadinessIssue(issues, family, code, message, details = {}) {
9157
+ issues.push({
9158
+ family,
9159
+ code,
9160
+ message,
9161
+ ...details
9162
+ });
9215
9163
  }
9216
- function stringArray(value) {
9217
- return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
9164
+ function formatInterfaceIdentity(systemPath, interfaceKey) {
9165
+ return `${systemPath}/${interfaceKey}`;
9218
9166
  }
9219
- function numberValue(value, fallback = 0) {
9220
- return typeof value === "number" ? value : fallback;
9167
+ function readinessMarkerPath(context) {
9168
+ return context.interfaceKey === "api" ? `systems.${context.systemPath}.apiInterface` : void 0;
9221
9169
  }
9222
- function appliesToLocalId(catalog) {
9223
- const appliesTo = catalog.appliesTo;
9224
- if (appliesTo === void 0) return void 0;
9225
- return parseOntologyId(appliesTo).localId;
9170
+ function readinessMarkerFieldPath(context, suffix) {
9171
+ const base = readinessMarkerPath(context);
9172
+ return base === void 0 ? void 0 : `${base}${suffix}`;
9226
9173
  }
9227
- function appliesToEntityKind(catalog) {
9228
- const id = appliesToLocalId(catalog);
9229
- if (id === "company" || id === "contact" || id === "project" || id === "milestone" || id === "task") return id;
9230
- if (id === "deal") return void 0;
9231
- return void 0;
9174
+ function formatSupportedReadinessProfiles() {
9175
+ return SYSTEM_INTERFACE_PROFILES.map((p3) => `"${p3.readinessProfile}"`).join(", ");
9176
+ }
9177
+ function isPlainRecord(value) {
9178
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
9232
9179
  }
9233
- function getLeadGenStageCatalog(model) {
9234
- const results = {};
9235
- for (const catalog of catalogRecords(model).filter(
9236
- (record) => record.kind === "stage" && (record.ownerSystemId ?? systemScope(record.id)) === "sales.lead-gen"
9237
- )) {
9238
- const catalogEntity = appliesToEntityKind(catalog);
9239
- if (catalogEntity !== "company" && catalogEntity !== "contact") continue;
9240
- for (const [entryId, entry] of entriesOf(catalog)) {
9241
- const entity = entry.entity === "contact" ? "contact" : entry.entity === "company" ? "company" : catalogEntity;
9242
- const additionalEntities = stringArray(entry.additionalEntities).filter(
9243
- (item) => item === "company" || item === "contact"
9180
+ function getCatalogEntries(catalog) {
9181
+ return isPlainRecord(catalog.entries) ? catalog.entries : {};
9182
+ }
9183
+ function getActiveScopedResources(model, resourceIds, issues, context) {
9184
+ const resources = [];
9185
+ for (const [index2, resourceId] of resourceIds.entries()) {
9186
+ const resource = model.resources?.[resourceId];
9187
+ const path = readinessMarkerFieldPath(context, `.resourceIds.${index2}`);
9188
+ if (resource === void 0) {
9189
+ addReadinessIssue(
9190
+ issues,
9191
+ "SYSTEM_INTERFACE_NOT_READY",
9192
+ "missing-resource",
9193
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes missing resource "${resourceId}".`,
9194
+ { path, ref: resourceId }
9244
9195
  );
9245
- const recordEntity = entry.recordEntity === "company" || entry.recordEntity === "contact" ? entry.recordEntity : void 0;
9246
- const recordStageKey = stringValue(entry.recordStageKey);
9247
- const readinessTarget = entry.readinessTarget === true ? true : void 0;
9248
- results[entryId] = {
9249
- key: entryId,
9250
- label: stringValue(entry.label) ?? entryId,
9251
- description: stringValue(entry.description) ?? "",
9252
- order: numberValue(entry.order),
9253
- entity,
9254
- ...additionalEntities.length > 0 ? { additionalEntities } : {},
9255
- ...recordEntity ? { recordEntity } : {},
9256
- ...recordStageKey ? { recordStageKey } : {},
9257
- ...readinessTarget ? { readinessTarget } : {}
9258
- };
9196
+ continue;
9197
+ }
9198
+ if (resource.systemPath !== context.systemPath) {
9199
+ addReadinessIssue(
9200
+ issues,
9201
+ "SYSTEM_INTERFACE_INVALID",
9202
+ "resource-system-mismatch",
9203
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes resource "${resourceId}" from system "${resource.systemPath}".`,
9204
+ { path, ref: resourceId }
9205
+ );
9206
+ continue;
9207
+ }
9208
+ if (resource.status !== "active") {
9209
+ addReadinessIssue(
9210
+ issues,
9211
+ "SYSTEM_INTERFACE_NOT_READY",
9212
+ "inactive-resource",
9213
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes inactive resource "${resourceId}".`,
9214
+ { path, ref: resourceId }
9215
+ );
9216
+ continue;
9259
9217
  }
9218
+ resources.push(resource);
9260
9219
  }
9261
- return Object.fromEntries(
9262
- Object.entries(results).sort(([, a3], [, b2]) => a3.order - b2.order || a3.key.localeCompare(b2.key))
9220
+ return resources;
9221
+ }
9222
+ function resourceBindingIds(resources, key) {
9223
+ return new Set(resources.flatMap((resource) => resource.ontology?.[key] ?? []));
9224
+ }
9225
+ function requireScopedBinding(issues, boundIds, bindingKey, ontologyId, context) {
9226
+ if (boundIds.has(ontologyId)) return;
9227
+ addReadinessIssue(
9228
+ issues,
9229
+ "SYSTEM_INTERFACE_NOT_READY",
9230
+ "missing-resource-binding",
9231
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" has no active scoped resource with ontology.${bindingKey} binding "${ontologyId}".`,
9232
+ { path: readinessMarkerFieldPath(context, ".resourceIds"), ref: ontologyId }
9263
9233
  );
9264
9234
  }
9265
- z.object({
9266
- success: z.boolean(),
9267
- tool: z.string(),
9268
- method: z.string(),
9269
- result: z.unknown().optional(),
9270
- error: z.string().optional(),
9271
- durationMs: z.number().optional()
9272
- });
9273
- z.object({
9274
- credential: z.string().describe("Credential name registered for this integration")
9275
- });
9276
-
9277
- // ../core/src/execution/engine/llm/schema/compile.ts
9278
- function isPlainObject(value) {
9279
- return typeof value === "object" && value !== null && !Array.isArray(value);
9235
+ function ontologyOwnerMatches(ontologyId, expectedSystemPath, catalog) {
9236
+ if (catalog?.ownerSystemId !== void 0) return catalog.ownerSystemId === expectedSystemPath;
9237
+ return parseOntologyId(ontologyId).scope === expectedSystemPath;
9280
9238
  }
9281
- var UNSUPPORTED_KEYWORDS = /* @__PURE__ */ new Set([
9282
- "minimum",
9283
- "maximum",
9284
- "exclusiveMinimum",
9285
- "exclusiveMaximum",
9286
- "multipleOf",
9287
- "minLength",
9288
- "maxLength",
9289
- "pattern",
9290
- "maxItems",
9291
- "uniqueItems",
9292
- "minProperties",
9293
- "maxProperties",
9294
- "patternProperties",
9295
- "propertyNames",
9296
- "contains",
9297
- "minContains",
9298
- "maxContains",
9299
- "dependentRequired",
9300
- "dependentSchemas",
9301
- "if",
9302
- "then",
9303
- "else",
9304
- "not",
9305
- "$id",
9306
- "$anchor"
9307
- ]);
9308
- var SUPPORTED_FORMATS = /* @__PURE__ */ new Set([
9309
- "date-time",
9310
- "time",
9311
- "date",
9312
- "duration",
9313
- "email",
9314
- "hostname",
9315
- "uri",
9316
- "ipv4",
9317
- "ipv6",
9318
- "uuid"
9319
- ]);
9320
- var MAX_SCHEMA_DEPTH = 32;
9321
- function convertNode(node, state, depth) {
9322
- if (depth > MAX_SCHEMA_DEPTH && state.dialect.strict !== "unsupported") {
9323
- state.blockers.push("depth>32");
9324
- return node;
9239
+ function requireObjectReadiness(issues, index2, objectId, context) {
9240
+ const object2 = index2.ontology.objectTypes[objectId];
9241
+ if (object2 === void 0) {
9242
+ addReadinessIssue(
9243
+ issues,
9244
+ "SYSTEM_INTERFACE_NOT_READY",
9245
+ "missing-object",
9246
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing required object type "${objectId}".`,
9247
+ { ref: objectId }
9248
+ );
9249
+ return;
9325
9250
  }
9326
- if (Array.isArray(node)) {
9327
- return node.map((item) => convertNode(item, state, depth + 1));
9251
+ const ownerSystemId = object2.ownerSystemId ?? parseOntologyId(objectId).scope;
9252
+ if (ownerSystemId !== context.systemPath) {
9253
+ addReadinessIssue(
9254
+ issues,
9255
+ "SYSTEM_INTERFACE_INVALID",
9256
+ "foreign-object",
9257
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" requires object "${objectId}" owned by "${ownerSystemId}".`,
9258
+ { ref: objectId }
9259
+ );
9328
9260
  }
9329
- if (!isPlainObject(node)) {
9330
- return node;
9331
- }
9332
- const strictEngaged = state.dialect.strict !== "unsupported";
9333
- const out = {};
9334
- for (const [key, value] of Object.entries(node)) {
9335
- if (key === "$ref" || key === "$defs" || key === "definitions") {
9336
- if (state.dialect.refs === "refuse") {
9337
- state.blockers.push(`unsupported:${key}`);
9338
- out[key] = value;
9339
- continue;
9340
- }
9341
- out[key] = value;
9342
- continue;
9343
- }
9344
- if (key === "$schema") {
9345
- if (!state.dialect.allowsSchemaKeyword) {
9346
- continue;
9347
- }
9348
- out.$schema = value;
9349
- continue;
9350
- }
9351
- if (key === "properties") {
9352
- if (!isPlainObject(value)) {
9353
- out.properties = value;
9354
- continue;
9355
- }
9356
- const properties = {};
9357
- for (const [propertyName, propertySchema] of Object.entries(value)) {
9358
- properties[propertyName] = convertNode(propertySchema, state, depth + 1);
9359
- }
9360
- out.properties = properties;
9361
- continue;
9362
- }
9363
- if (key === "items") {
9364
- out.items = convertNode(value, state, depth + 1);
9365
- continue;
9366
- }
9367
- if (strictEngaged) {
9368
- if (UNSUPPORTED_KEYWORDS.has(key)) {
9369
- continue;
9370
- }
9371
- if (key === "oneOf") {
9372
- out.anyOf = convertNode(value, state, depth + 1);
9373
- continue;
9374
- }
9375
- if (key === "format") {
9376
- if (typeof value === "string" && SUPPORTED_FORMATS.has(value)) {
9377
- out.format = value;
9378
- }
9379
- continue;
9380
- }
9381
- if (key === "minItems") {
9382
- const n2 = typeof value === "number" ? value : 0;
9383
- out.minItems = n2 > 1 ? 1 : n2;
9384
- continue;
9385
- }
9386
- if (key === "type" && Array.isArray(value)) {
9387
- out.anyOf = value.map((t) => ({ type: t }));
9388
- continue;
9389
- }
9390
- if (key === "additionalProperties") {
9391
- continue;
9392
- }
9393
- }
9394
- out[key] = convertNode(value, state, depth + 1);
9395
- }
9396
- const isObjectNode = out.type === "object" || isPlainObject(out.properties);
9397
- if (isObjectNode) {
9398
- const properties = isPlainObject(out.properties) ? out.properties : void 0;
9399
- const originalAdditionalProperties = node.additionalProperties;
9400
- if (strictEngaged) {
9401
- if (properties) {
9402
- const declared = Object.keys(properties);
9403
- const required = Array.isArray(out.required) ? out.required : [];
9404
- const optional = declared.filter((k2) => !required.includes(k2));
9405
- if (state.dialect.strict === "allRequired" && optional.length > 0) {
9406
- state.blockers.push(`optionalProperty:${optional[0]}`);
9407
- }
9408
- state.optionalProperties += optional.length;
9409
- }
9410
- if (originalAdditionalProperties !== void 0 && originalAdditionalProperties !== false && (!properties || Object.keys(properties).length === 0)) {
9411
- state.blockers.push("freeFormObject");
9412
- }
9413
- out.additionalProperties = false;
9414
- }
9415
- if (strictEngaged && (!properties || Object.keys(properties).length === 0)) {
9416
- out.properties = {};
9417
- }
9418
- }
9419
- return out;
9420
- }
9421
- function dedupe(values) {
9422
- return [...new Set(values)];
9423
- }
9424
- function compileSchema(schema, dialect) {
9425
- if (!isPlainObject(schema)) {
9426
- const strictEngaged = dialect.strict !== "unsupported";
9427
- return {
9428
- schema,
9429
- sendStrict: false,
9430
- status: strictEngaged ? "refused" : "notAttempted",
9431
- refusalReasons: strictEngaged ? ["notAnObject"] : []
9432
- };
9433
- }
9434
- const state = { dialect, blockers: [], optionalProperties: 0 };
9435
- const compiled = convertNode(schema, state, 0);
9436
- if (state.blockers.length === 0 && dialect.maxOptionalProperties !== void 0 && state.optionalProperties > dialect.maxOptionalProperties) {
9437
- state.blockers.push(`optionalPropertyLimit:${state.optionalProperties}>${dialect.maxOptionalProperties}`);
9438
- }
9439
- if (dialect.strict === "unsupported") {
9440
- return {
9441
- schema: compiled,
9442
- sendStrict: false,
9443
- status: "notAttempted",
9444
- refusalReasons: []
9445
- };
9446
- }
9447
- if (state.blockers.length > 0) {
9448
- return {
9449
- schema,
9450
- sendStrict: false,
9451
- status: "refused",
9452
- refusalReasons: dedupe(state.blockers)
9453
- };
9454
- }
9455
- return { schema: compiled, sendStrict: true, status: "applied", refusalReasons: [] };
9456
- }
9457
-
9458
- // ../core/src/execution/engine/llm/schema/dialect.ts
9459
- var ANTHROPIC_DIALECT = {
9460
- strict: "optionalAllowed",
9461
- // No placeholder of its own: an empty or absent `properties` becomes a bare `properties: {}`,
9462
- // synthesized directly by the walk for any dialect engaging strict.
9463
- // Refuses rather than inlining: detecting recursion through `$defs` is more machinery than the
9464
- // payoff justifies for a tool-input schema.
9465
- refs: "refuse",
9466
- allowsSchemaKeyword: false,
9467
- // Anthropic's published ceiling. Measured live before this was added: the Command Center
9468
- // assistant's iteration schema declares 33, so 8 of 8 iterations across a 3-turn session were
9469
- // 400'd and retried unstrict. `optionalAllowed` is still correct -- an optional property is
9470
- // representable in this grammar, there is just a cap on how many.
9471
- maxOptionalProperties: 24
9472
- };
9473
- var OPENAI_DIALECT = {
9474
- strict: "allRequired",
9475
- refs: "passthrough",
9476
- allowsSchemaKeyword: false
9477
- };
9478
- var OPENROUTER_DIALECT = {
9479
- strict: "allRequired",
9480
- refs: "refuse",
9481
- allowsSchemaKeyword: false
9482
- };
9483
- var PROVIDER_DIALECTS = {
9484
- anthropic: ANTHROPIC_DIALECT,
9485
- openai: OPENAI_DIALECT,
9486
- openrouter: OPENROUTER_DIALECT
9487
- };
9488
-
9489
- // ../core/src/business/acquisition/ontology-validation.ts
9490
- var LEAD_GEN_API_INTERFACE = SYSTEM_INTERFACE_PROFILES[0];
9491
- var CRM_API_INTERFACE = SYSTEM_INTERFACE_PROFILES[1];
9492
- var LEAD_GEN_CRM_HANDOFF_INTERFACE = SYSTEM_INTERFACE_PROFILES[2];
9493
- LEAD_GEN_API_INTERFACE.readinessProfile;
9494
- CRM_API_INTERFACE.readinessProfile;
9495
- LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile;
9496
- var LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID = formatOntologyId({
9497
- scope: "sales.lead-gen",
9498
- kind: "object",
9499
- localId: "list"
9500
- });
9501
- var LEAD_GEN_COMPANY_OBJECT_ONTOLOGY_ID = formatOntologyId({
9502
- scope: "sales.lead-gen",
9503
- kind: "object",
9504
- localId: "company"
9505
- });
9506
- var LEAD_GEN_CONTACT_OBJECT_ONTOLOGY_ID = formatOntologyId({
9507
- scope: "sales.lead-gen",
9508
- kind: "object",
9509
- localId: "contact"
9510
- });
9511
- var LEAD_GEN_BUILD_TEMPLATE_CATALOG_ONTOLOGY_ID = formatOntologyId({
9512
- scope: "sales.lead-gen",
9513
- kind: "catalog",
9514
- localId: "build-template"
9515
- });
9516
- var LEAD_GEN_COMPANY_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
9517
- scope: "sales.lead-gen",
9518
- kind: "catalog",
9519
- localId: "company-stage"
9520
- });
9521
- var LEAD_GEN_CONTACT_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
9522
- scope: "sales.lead-gen",
9523
- kind: "catalog",
9524
- localId: "contact-stage"
9525
- });
9526
- var CRM_PIPELINE_CATALOG_ONTOLOGY_ID = formatOntologyId({
9527
- scope: "sales.crm",
9528
- kind: "catalog",
9529
- localId: "crm.pipeline"
9530
- });
9531
- var LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
9532
- scope: "sales.lead-gen",
9533
- kind: "catalog",
9534
- localId: "lead-gen.stage-catalog"
9535
- });
9536
- function createLeadGenStageCatalog(model) {
9537
- return {
9538
- id: LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID,
9539
- label: "Lead Gen Processing Stages",
9540
- ownerSystemId: "sales.lead-gen",
9541
- kind: "processing-stage-catalog",
9542
- entries: Object.fromEntries(
9543
- Object.entries(getLeadGenStageCatalog(model)).map(([key, entry]) => [
9544
- key,
9545
- {
9546
- ...entry
9547
- }
9548
- ])
9549
- ),
9550
- legacyCatalogKey: "LEAD_GEN_STAGE_CATALOG"
9551
- };
9552
- }
9553
- function isPlainRecord(value) {
9554
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
9555
- }
9556
- function addReadinessIssue(issues, family, code, message, details = {}) {
9557
- issues.push({
9558
- family,
9559
- code,
9560
- message,
9561
- ...details
9562
- });
9563
- }
9564
- function formatInterfaceIdentity(systemPath, interfaceKey) {
9565
- return `${systemPath}/${interfaceKey}`;
9566
- }
9567
- function readinessMarkerPath(context) {
9568
- return context.interfaceKey === "api" ? `systems.${context.systemPath}.apiInterface` : `systems.${context.systemPath}.derivedCrmHandoffReadiness`;
9569
- }
9570
- function formatSupportedReadinessProfiles() {
9571
- return SYSTEM_INTERFACE_PROFILES.map((p3) => `"${p3.readinessProfile}"`).join(", ");
9572
- }
9573
- function getActiveScopedResources(model, resourceIds, issues, context) {
9574
- const resources = [];
9575
- for (const [index2, resourceId] of resourceIds.entries()) {
9576
- const resource = model.resources?.[resourceId];
9577
- const path = `${readinessMarkerPath(context)}.resourceIds.${index2}`;
9578
- if (resource === void 0) {
9579
- addReadinessIssue(
9580
- issues,
9581
- "SYSTEM_INTERFACE_NOT_READY",
9582
- "missing-resource",
9583
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes missing resource "${resourceId}".`,
9584
- { path, ref: resourceId }
9585
- );
9586
- continue;
9587
- }
9588
- if (resource.systemPath !== context.systemPath) {
9589
- addReadinessIssue(
9590
- issues,
9591
- "SYSTEM_INTERFACE_INVALID",
9592
- "resource-system-mismatch",
9593
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes resource "${resourceId}" from system "${resource.systemPath}".`,
9594
- { path, ref: resourceId }
9595
- );
9596
- continue;
9597
- }
9598
- if (resource.status !== "active") {
9599
- addReadinessIssue(
9600
- issues,
9601
- "SYSTEM_INTERFACE_NOT_READY",
9602
- "inactive-resource",
9603
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes inactive resource "${resourceId}".`,
9604
- { path, ref: resourceId }
9605
- );
9606
- continue;
9607
- }
9608
- resources.push(resource);
9609
- }
9610
- return resources;
9611
- }
9612
- function resourceBindingIds(resources, key) {
9613
- return new Set(resources.flatMap((resource) => resource.ontology?.[key] ?? []));
9614
- }
9615
- function requireScopedBinding(issues, boundIds, bindingKey, ontologyId, context) {
9616
- if (boundIds.has(ontologyId)) return;
9617
- addReadinessIssue(
9618
- issues,
9619
- "SYSTEM_INTERFACE_NOT_READY",
9620
- "missing-resource-binding",
9621
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" has no active scoped resource with ontology.${bindingKey} binding "${ontologyId}".`,
9622
- { path: `${readinessMarkerPath(context)}.resourceIds`, ref: ontologyId }
9623
- );
9624
- }
9625
- function ontologyOwnerMatches(ontologyId, expectedSystemPath, catalog) {
9626
- if (catalog?.ownerSystemId !== void 0) return catalog.ownerSystemId === expectedSystemPath;
9627
- return parseOntologyId(ontologyId).scope === expectedSystemPath;
9628
- }
9629
- function requireObjectReadiness(issues, index2, objectId, context) {
9630
- const object2 = index2.ontology.objectTypes[objectId];
9631
- if (object2 === void 0) {
9632
- addReadinessIssue(
9633
- issues,
9634
- "SYSTEM_INTERFACE_NOT_READY",
9635
- "missing-object",
9636
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing required object type "${objectId}".`,
9637
- { ref: objectId }
9638
- );
9639
- return;
9640
- }
9641
- const ownerSystemId = object2.ownerSystemId ?? parseOntologyId(objectId).scope;
9642
- if (ownerSystemId !== context.systemPath) {
9643
- addReadinessIssue(
9644
- issues,
9645
- "SYSTEM_INTERFACE_INVALID",
9646
- "foreign-object",
9647
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" requires object "${objectId}" owned by "${ownerSystemId}".`,
9648
- { ref: objectId }
9649
- );
9650
- }
9651
- }
9652
- function requireCatalogReadiness(issues, index2, catalogId, context) {
9653
- const catalog = index2.ontology.catalogTypes[catalogId];
9654
- if (catalog === void 0) {
9655
- addReadinessIssue(
9656
- issues,
9657
- "SYSTEM_INTERFACE_NOT_READY",
9658
- "missing-catalog",
9659
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing required catalog "${catalogId}".`,
9660
- { ref: catalogId }
9661
- );
9662
- return void 0;
9261
+ }
9262
+ function requireCatalogReadiness(issues, index2, catalogId, context) {
9263
+ const catalog = index2.ontology.catalogTypes[catalogId];
9264
+ if (catalog === void 0) {
9265
+ addReadinessIssue(
9266
+ issues,
9267
+ "SYSTEM_INTERFACE_NOT_READY",
9268
+ "missing-catalog",
9269
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing required catalog "${catalogId}".`,
9270
+ { ref: catalogId }
9271
+ );
9272
+ return void 0;
9663
9273
  }
9664
9274
  if (context.allowForeignOwner !== true && !ontologyOwnerMatches(catalogId, context.systemPath, catalog)) {
9665
9275
  addReadinessIssue(
@@ -9681,129 +9291,40 @@ function requireCatalogReadiness(issues, index2, catalogId, context) {
9681
9291
  }
9682
9292
  return catalog;
9683
9293
  }
9684
- function requireLeadGenInterfaceReadiness(issues, index2, resources, context) {
9294
+ function requireContractReadiness(issues, index2, resources, contract, context) {
9685
9295
  const reads = resourceBindingIds(resources, "reads");
9686
9296
  const catalogs = resourceBindingIds(resources, "usesCatalogs");
9687
- for (const objectId of [
9688
- LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID,
9689
- LEAD_GEN_COMPANY_OBJECT_ONTOLOGY_ID,
9690
- LEAD_GEN_CONTACT_OBJECT_ONTOLOGY_ID
9691
- ]) {
9297
+ for (const objectId of contract.requiredObjects) {
9692
9298
  requireObjectReadiness(issues, index2, objectId, context);
9693
9299
  requireScopedBinding(issues, reads, "reads", objectId, context);
9694
9300
  }
9695
- for (const catalogId of [
9696
- LEAD_GEN_BUILD_TEMPLATE_CATALOG_ONTOLOGY_ID,
9697
- LEAD_GEN_COMPANY_STAGE_CATALOG_ONTOLOGY_ID,
9698
- LEAD_GEN_CONTACT_STAGE_CATALOG_ONTOLOGY_ID
9699
- ]) {
9301
+ for (const catalogId of contract.requiredCatalogs) {
9700
9302
  requireCatalogReadiness(issues, index2, catalogId, context);
9701
9303
  requireScopedBinding(issues, catalogs, "usesCatalogs", catalogId, context);
9702
9304
  }
9703
- const templateStepCatalog = findLeadGenTemplateStepCatalog(index2);
9704
- if (templateStepCatalog === void 0) {
9705
- addReadinessIssue(
9706
- issues,
9707
- "SYSTEM_INTERFACE_NOT_READY",
9708
- "missing-template-step-catalog",
9709
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing a lead-gen template-step catalog.`
9710
- );
9711
- } else {
9712
- requireCatalogReadiness(issues, index2, templateStepCatalog.id, context);
9713
- requireScopedBinding(issues, catalogs, "usesCatalogs", templateStepCatalog.id, context);
9714
- }
9715
- const leadGenStageCatalog = requireCatalogReadiness(issues, index2, LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID, context);
9716
- return leadGenStageCatalog;
9717
- }
9718
- function requireCrmInterfaceReadiness(issues, index2, resources, context) {
9719
- const catalogs = resourceBindingIds(resources, "usesCatalogs");
9720
- const crmPipelineCatalog = requireCatalogReadiness(issues, index2, CRM_PIPELINE_CATALOG_ONTOLOGY_ID, context);
9721
- requireScopedBinding(issues, catalogs, "usesCatalogs", CRM_PIPELINE_CATALOG_ONTOLOGY_ID, context);
9722
- return crmPipelineCatalog;
9723
- }
9724
- function findSystemInterfaceGrant(model, consumer, provider) {
9725
- return Object.values(model.topology?.relationships ?? {}).find((relationship) => {
9726
- const grant = relationship.metadata?.["systemInterfaceGrant"];
9727
- if (!isPlainRecord(grant) || !isPlainRecord(grant.consumer) || !isPlainRecord(grant.provider)) return false;
9728
- return grant.consumer.systemPath === consumer.systemPath && grant.consumer.interfaceKey === consumer.interfaceKey && grant.provider.systemPath === provider.systemPath && grant.provider.interfaceKey === provider.interfaceKey;
9729
- });
9730
- }
9731
- function requireHandoffBridgeReadiness(issues, model, context) {
9732
- const crmResult = computeInterfaceReadiness(model, CRM_API_INTERFACE);
9733
- if (!crmResult.ready) {
9734
- for (const issue of crmResult.issues) {
9735
- addReadinessIssue(
9736
- issues,
9737
- "SYSTEM_BRIDGE_NOT_READY",
9738
- issue.code,
9739
- `Provider interface ${formatInterfaceIdentity(CRM_API_INTERFACE.systemPath, CRM_API_INTERFACE.interfaceKey)} is not ready: ${issue.message}`,
9740
- { path: issue.path, ref: issue.ref }
9741
- );
9742
- }
9743
- }
9744
- const bridgeGrant = findSystemInterfaceGrant(model, context, CRM_API_INTERFACE);
9745
- if (bridgeGrant === void 0) {
9746
- addReadinessIssue(
9747
- issues,
9748
- "SYSTEM_BRIDGE_NOT_READY",
9749
- "missing-topology-grant",
9750
- `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" requires a scoped topology grant to "${formatInterfaceIdentity(CRM_API_INTERFACE.systemPath, CRM_API_INTERFACE.interfaceKey)}".`
9751
- );
9752
- }
9753
- return bridgeGrant;
9754
- }
9755
- function getLeadGenCrmHandoffResourceIds(model) {
9756
- return Object.values(model.resources ?? {}).filter(
9757
- (resource) => resource.systemPath === LEAD_GEN_CRM_HANDOFF_INTERFACE.systemPath && resource.ontology?.usesCatalogs?.includes(CRM_PIPELINE_CATALOG_ONTOLOGY_ID) === true
9758
- ).map((resource) => resource.id);
9759
9305
  }
9760
9306
  function getSystemInterfaceReadinessMarker(model, request) {
9761
9307
  const system = getSystem(model, request.systemPath);
9762
9308
  if (system === void 0) return void 0;
9763
- if (request.systemPath === LEAD_GEN_CRM_HANDOFF_INTERFACE.systemPath && request.interfaceKey === LEAD_GEN_CRM_HANDOFF_INTERFACE.interfaceKey) {
9764
- return {
9765
- lifecycle: "active",
9766
- readinessProfile: LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile,
9767
- resourceIds: getLeadGenCrmHandoffResourceIds(model)
9768
- };
9769
- }
9309
+ const registeredMarker = resolveReadinessInterfaceMarker(model, request.systemPath, request.interfaceKey);
9310
+ if (registeredMarker !== void 0) return registeredMarker;
9770
9311
  if (request.interfaceKey === "api" && system.apiInterface !== void 0) {
9771
9312
  return system.apiInterface;
9772
9313
  }
9773
- return void 0;
9774
- }
9775
- function mergeLeadGenDerivedCatalogs(model) {
9776
- const baseCatalogTypes = model.ontology?.catalogTypes ?? {};
9777
- const derivedCatalogTypes = {};
9778
- if (baseCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] === void 0) {
9779
- derivedCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] = createLeadGenStageCatalog(model);
9780
- }
9781
- if (Object.keys(derivedCatalogTypes).length === 0) return model;
9782
- return {
9783
- ...model,
9784
- ontology: {
9785
- ...model.ontology ?? {},
9786
- catalogTypes: {
9787
- ...baseCatalogTypes,
9788
- ...derivedCatalogTypes
9789
- }
9790
- }
9791
- };
9314
+ return void 0;
9792
9315
  }
9793
- function compileBusinessOntology(model, contractId) {
9794
- const compilation = compileOrganizationOntology(mergeLeadGenDerivedCatalogs(model));
9316
+ function compileReadinessOntology(model, readinessProfile, prepareModel) {
9317
+ const preparedModel = prepareModel !== void 0 ? prepareModel(model) : model;
9318
+ const compilation = compileOrganizationOntology(preparedModel);
9795
9319
  if (compilation.diagnostics.length > 0) {
9796
9320
  const summary = compilation.diagnostics.map((diagnostic) => diagnostic.message).join("; ");
9797
- throw new Error(`${contractId} ontology validation index failed to compile: ${summary}`);
9321
+ throw new Error(`${readinessProfile} ontology validation index failed to compile: ${summary}`);
9798
9322
  }
9799
- return {
9800
- ontology: compilation.ontology,
9801
- actionTypesByLegacyId: indexActionTypesByLegacyId(compilation.ontology.actionTypes)
9802
- };
9323
+ return { ontology: compilation.ontology };
9803
9324
  }
9804
- function tryCompileBusinessOntology(model, readinessProfile, issues) {
9325
+ function tryCompileReadinessOntology(model, readinessProfile, prepareModel, issues) {
9805
9326
  try {
9806
- return compileBusinessOntology(model, readinessProfile);
9327
+ return compileReadinessOntology(model, readinessProfile, prepareModel);
9807
9328
  } catch (error) {
9808
9329
  addReadinessIssue(
9809
9330
  issues,
@@ -9814,23 +9335,11 @@ function tryCompileBusinessOntology(model, readinessProfile, issues) {
9814
9335
  return void 0;
9815
9336
  }
9816
9337
  }
9817
- function requireContractReadiness(issues, index2, resources, contract, context) {
9818
- const reads = resourceBindingIds(resources, "reads");
9819
- const catalogs = resourceBindingIds(resources, "usesCatalogs");
9820
- for (const objectId of contract.requiredObjects) {
9821
- requireObjectReadiness(issues, index2, objectId, context);
9822
- requireScopedBinding(issues, reads, "reads", objectId, context);
9823
- }
9824
- for (const catalogId of contract.requiredCatalogs) {
9825
- requireCatalogReadiness(issues, index2, catalogId, context);
9826
- requireScopedBinding(issues, catalogs, "usesCatalogs", catalogId, context);
9827
- }
9828
- }
9829
9338
  function computeInterfaceReadiness(model, request) {
9830
9339
  const issues = [];
9831
9340
  const system = getSystem(model, request.systemPath);
9832
9341
  const systemInterface = getSystemInterfaceReadinessMarker(model, request);
9833
- const readinessProfile = systemInterface === void 0 ? void 0 : profileForInterface(request.systemPath, request.interfaceKey, systemInterface.readinessProfile);
9342
+ const readinessProfile = systemInterface?.readinessProfile;
9834
9343
  const scopedResourceIds = systemInterface?.resourceIds ?? [];
9835
9344
  if (system === void 0) {
9836
9345
  addReadinessIssue(
@@ -9870,25 +9379,48 @@ function computeInterfaceReadiness(model, request) {
9870
9379
  "SYSTEM_INTERFACE_DISABLED",
9871
9380
  "inactive-interface",
9872
9381
  `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" lifecycle is "${systemInterface.lifecycle}".`,
9873
- { path: `${readinessMarkerPath(request)}.lifecycle` }
9382
+ { path: readinessMarkerFieldPath(request, ".lifecycle") }
9383
+ );
9384
+ return {
9385
+ ready: false,
9386
+ systemPath: request.systemPath,
9387
+ interfaceKey: request.interfaceKey,
9388
+ readinessProfile,
9389
+ scopedResourceIds,
9390
+ issues
9391
+ };
9392
+ }
9393
+ if (readinessProfile === void 0) {
9394
+ addReadinessIssue(
9395
+ issues,
9396
+ "SYSTEM_INTERFACE_INVALID",
9397
+ "missing-readiness-profile",
9398
+ `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" declares an apiInterface but no readinessProfile. Declare a built-in profile (${formatSupportedReadinessProfiles()}) or a custom id paired with a readinessContract.`,
9399
+ { path: readinessMarkerFieldPath(request, ".readinessProfile") }
9874
9400
  );
9401
+ return {
9402
+ ready: false,
9403
+ systemPath: request.systemPath,
9404
+ interfaceKey: request.interfaceKey,
9405
+ scopedResourceIds,
9406
+ issues
9407
+ };
9875
9408
  }
9876
- const checkedReadinessProfile = readinessProfile ?? profileForInterface(request.systemPath, request.interfaceKey);
9877
- const isBuiltIn = isBuiltInReadinessProfile(checkedReadinessProfile);
9409
+ const isBuiltIn = isBuiltInReadinessProfile(readinessProfile);
9878
9410
  const readinessContract = systemInterface.readinessContract;
9879
9411
  if (!isBuiltIn && readinessContract === void 0) {
9880
9412
  addReadinessIssue(
9881
9413
  issues,
9882
9414
  "SYSTEM_INTERFACE_INVALID",
9883
9415
  "missing-readiness-contract",
9884
- `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" uses custom readiness profile "${checkedReadinessProfile}" but declares no readinessContract. Built-in profiles: ${formatSupportedReadinessProfiles()}.`,
9885
- { path: `${readinessMarkerPath(request)}.readinessContract`, ref: checkedReadinessProfile }
9416
+ `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" uses custom readiness profile "${readinessProfile}" but declares no readinessContract. Built-in profiles: ${formatSupportedReadinessProfiles()}.`,
9417
+ { path: readinessMarkerFieldPath(request, ".readinessContract"), ref: readinessProfile }
9886
9418
  );
9887
9419
  return {
9888
9420
  ready: false,
9889
9421
  systemPath: request.systemPath,
9890
9422
  interfaceKey: request.interfaceKey,
9891
- readinessProfile: checkedReadinessProfile,
9423
+ readinessProfile,
9892
9424
  scopedResourceIds,
9893
9425
  issues
9894
9426
  };
@@ -9899,20 +9431,15 @@ function computeInterfaceReadiness(model, request) {
9899
9431
  "SYSTEM_INTERFACE_NOT_READY",
9900
9432
  "missing-scoped-resources",
9901
9433
  `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" must scope at least one active resource.`,
9902
- { path: `${readinessMarkerPath(request)}.resourceIds` }
9434
+ { path: readinessMarkerFieldPath(request, ".resourceIds") }
9903
9435
  );
9904
9436
  }
9905
9437
  const resources = getActiveScopedResources(model, scopedResourceIds, issues, request);
9906
- const index2 = tryCompileBusinessOntology(model, checkedReadinessProfile, issues);
9438
+ const registration = getBuiltInReadinessProfile(readinessProfile);
9439
+ const index2 = tryCompileReadinessOntology(model, readinessProfile, registration?.prepareModel, issues);
9907
9440
  if (index2 !== void 0) {
9908
- if (checkedReadinessProfile === LEAD_GEN_API_INTERFACE.readinessProfile) {
9909
- requireLeadGenInterfaceReadiness(issues, index2, resources, request);
9910
- } else if (checkedReadinessProfile === CRM_API_INTERFACE.readinessProfile) {
9911
- requireCrmInterfaceReadiness(issues, index2, resources, request);
9912
- } else if (checkedReadinessProfile === LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile) {
9913
- requireLeadGenInterfaceReadiness(issues, index2, resources, request);
9914
- requireCrmInterfaceReadiness(issues, index2, resources, { ...request, allowForeignOwner: true });
9915
- requireHandoffBridgeReadiness(issues, model, request);
9441
+ if (registration !== void 0) {
9442
+ registration.validate(issues, index2, resources, model, request);
9916
9443
  } else if (readinessContract !== void 0) {
9917
9444
  requireContractReadiness(issues, index2, resources, readinessContract, request);
9918
9445
  }
@@ -9921,30 +9448,235 @@ function computeInterfaceReadiness(model, request) {
9921
9448
  ready: issues.length === 0,
9922
9449
  systemPath: request.systemPath,
9923
9450
  interfaceKey: request.interfaceKey,
9924
- readinessProfile: checkedReadinessProfile,
9451
+ readinessProfile,
9925
9452
  scopedResourceIds,
9926
9453
  issues
9927
9454
  };
9928
9455
  }
9929
- function findLeadGenTemplateStepCatalog(index2) {
9930
- return Object.values(index2.ontology.catalogTypes).find(
9931
- (catalog) => catalog.ownerSystemId === "sales.lead-gen" && catalog.kind === "template-step" && catalog.appliesTo === LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID
9932
- );
9456
+ z.object({
9457
+ success: z.boolean(),
9458
+ tool: z.string(),
9459
+ method: z.string(),
9460
+ result: z.unknown().optional(),
9461
+ error: z.string().optional(),
9462
+ durationMs: z.number().optional()
9463
+ });
9464
+ z.object({
9465
+ credential: z.string().describe("Credential name registered for this integration")
9466
+ });
9467
+
9468
+ // ../core/src/execution/engine/llm/schema/compile.ts
9469
+ function isPlainObject(value) {
9470
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9933
9471
  }
9934
- function indexActionTypesByLegacyId(actionTypes) {
9935
- const byLegacyId = {};
9936
- for (const actionType of Object.values(actionTypes)) {
9937
- const legacyActionId = actionType["legacyActionId"];
9938
- if (typeof legacyActionId === "string") {
9939
- byLegacyId[legacyActionId] = actionType;
9472
+ var UNSUPPORTED_KEYWORDS = /* @__PURE__ */ new Set([
9473
+ "minimum",
9474
+ "maximum",
9475
+ "exclusiveMinimum",
9476
+ "exclusiveMaximum",
9477
+ "multipleOf",
9478
+ "minLength",
9479
+ "maxLength",
9480
+ "pattern",
9481
+ "maxItems",
9482
+ "uniqueItems",
9483
+ "minProperties",
9484
+ "maxProperties",
9485
+ "patternProperties",
9486
+ "propertyNames",
9487
+ "contains",
9488
+ "minContains",
9489
+ "maxContains",
9490
+ "dependentRequired",
9491
+ "dependentSchemas",
9492
+ "if",
9493
+ "then",
9494
+ "else",
9495
+ "not",
9496
+ "$id",
9497
+ "$anchor"
9498
+ ]);
9499
+ var SUPPORTED_FORMATS = /* @__PURE__ */ new Set([
9500
+ "date-time",
9501
+ "time",
9502
+ "date",
9503
+ "duration",
9504
+ "email",
9505
+ "hostname",
9506
+ "uri",
9507
+ "ipv4",
9508
+ "ipv6",
9509
+ "uuid"
9510
+ ]);
9511
+ var MAX_SCHEMA_DEPTH = 32;
9512
+ function convertNode(node, state, depth) {
9513
+ if (depth > MAX_SCHEMA_DEPTH && state.dialect.strict !== "unsupported") {
9514
+ state.blockers.push("depth>32");
9515
+ return node;
9516
+ }
9517
+ if (Array.isArray(node)) {
9518
+ return node.map((item) => convertNode(item, state, depth + 1));
9519
+ }
9520
+ if (!isPlainObject(node)) {
9521
+ return node;
9522
+ }
9523
+ const strictEngaged = state.dialect.strict !== "unsupported";
9524
+ const out = {};
9525
+ for (const [key, value] of Object.entries(node)) {
9526
+ if (key === "$ref" || key === "$defs" || key === "definitions") {
9527
+ if (state.dialect.refs === "refuse") {
9528
+ state.blockers.push(`unsupported:${key}`);
9529
+ out[key] = value;
9530
+ continue;
9531
+ }
9532
+ out[key] = value;
9533
+ continue;
9534
+ }
9535
+ if (key === "$schema") {
9536
+ if (!state.dialect.allowsSchemaKeyword) {
9537
+ continue;
9538
+ }
9539
+ out.$schema = value;
9540
+ continue;
9541
+ }
9542
+ if (key === "properties") {
9543
+ if (!isPlainObject(value)) {
9544
+ out.properties = value;
9545
+ continue;
9546
+ }
9547
+ const properties = {};
9548
+ for (const [propertyName, propertySchema] of Object.entries(value)) {
9549
+ properties[propertyName] = convertNode(propertySchema, state, depth + 1);
9550
+ }
9551
+ out.properties = properties;
9552
+ continue;
9553
+ }
9554
+ if (key === "items") {
9555
+ out.items = convertNode(value, state, depth + 1);
9556
+ continue;
9557
+ }
9558
+ if (strictEngaged) {
9559
+ if (UNSUPPORTED_KEYWORDS.has(key)) {
9560
+ continue;
9561
+ }
9562
+ if (key === "oneOf") {
9563
+ out.anyOf = convertNode(value, state, depth + 1);
9564
+ continue;
9565
+ }
9566
+ if (key === "format") {
9567
+ if (typeof value === "string" && SUPPORTED_FORMATS.has(value)) {
9568
+ out.format = value;
9569
+ }
9570
+ continue;
9571
+ }
9572
+ if (key === "minItems") {
9573
+ const n2 = typeof value === "number" ? value : 0;
9574
+ out.minItems = n2 > 1 ? 1 : n2;
9575
+ continue;
9576
+ }
9577
+ if (key === "type" && Array.isArray(value)) {
9578
+ out.anyOf = value.map((t) => ({ type: t }));
9579
+ continue;
9580
+ }
9581
+ if (key === "additionalProperties") {
9582
+ continue;
9583
+ }
9584
+ }
9585
+ out[key] = convertNode(value, state, depth + 1);
9586
+ }
9587
+ const isObjectNode = out.type === "object" || isPlainObject(out.properties);
9588
+ if (isObjectNode) {
9589
+ const properties = isPlainObject(out.properties) ? out.properties : void 0;
9590
+ const originalAdditionalProperties = node.additionalProperties;
9591
+ if (strictEngaged) {
9592
+ if (properties) {
9593
+ const declared = Object.keys(properties);
9594
+ const required = Array.isArray(out.required) ? out.required : [];
9595
+ const optional = declared.filter((k2) => !required.includes(k2));
9596
+ if (state.dialect.strict === "allRequired" && optional.length > 0) {
9597
+ state.blockers.push(`optionalProperty:${optional[0]}`);
9598
+ }
9599
+ state.optionalProperties += optional.length;
9600
+ }
9601
+ if (originalAdditionalProperties !== void 0 && originalAdditionalProperties !== false && (!properties || Object.keys(properties).length === 0)) {
9602
+ state.blockers.push("freeFormObject");
9603
+ }
9604
+ out.additionalProperties = false;
9605
+ }
9606
+ if (strictEngaged && (!properties || Object.keys(properties).length === 0)) {
9607
+ out.properties = {};
9940
9608
  }
9941
9609
  }
9942
- return byLegacyId;
9610
+ return out;
9943
9611
  }
9944
- function getCatalogEntries(catalog) {
9945
- return isPlainRecord(catalog.entries) ? catalog.entries : {};
9612
+ function dedupe(values) {
9613
+ return [...new Set(values)];
9614
+ }
9615
+ function compileSchema(schema, dialect) {
9616
+ if (!isPlainObject(schema)) {
9617
+ const strictEngaged = dialect.strict !== "unsupported";
9618
+ return {
9619
+ schema,
9620
+ sendStrict: false,
9621
+ status: strictEngaged ? "refused" : "notAttempted",
9622
+ refusalReasons: strictEngaged ? ["notAnObject"] : []
9623
+ };
9624
+ }
9625
+ const state = { dialect, blockers: [], optionalProperties: 0 };
9626
+ const compiled = convertNode(schema, state, 0);
9627
+ if (state.blockers.length === 0 && dialect.maxOptionalProperties !== void 0 && state.optionalProperties > dialect.maxOptionalProperties) {
9628
+ state.blockers.push(`optionalPropertyLimit:${state.optionalProperties}>${dialect.maxOptionalProperties}`);
9629
+ }
9630
+ if (dialect.strict === "unsupported") {
9631
+ return {
9632
+ schema: compiled,
9633
+ sendStrict: false,
9634
+ status: "notAttempted",
9635
+ refusalReasons: []
9636
+ };
9637
+ }
9638
+ if (state.blockers.length > 0) {
9639
+ return {
9640
+ schema,
9641
+ sendStrict: false,
9642
+ status: "refused",
9643
+ refusalReasons: dedupe(state.blockers)
9644
+ };
9645
+ }
9646
+ return { schema: compiled, sendStrict: true, status: "applied", refusalReasons: [] };
9946
9647
  }
9947
9648
 
9649
+ // ../core/src/execution/engine/llm/schema/dialect.ts
9650
+ var ANTHROPIC_DIALECT = {
9651
+ strict: "optionalAllowed",
9652
+ // No placeholder of its own: an empty or absent `properties` becomes a bare `properties: {}`,
9653
+ // synthesized directly by the walk for any dialect engaging strict.
9654
+ // Refuses rather than inlining: detecting recursion through `$defs` is more machinery than the
9655
+ // payoff justifies for a tool-input schema.
9656
+ refs: "refuse",
9657
+ allowsSchemaKeyword: false,
9658
+ // Anthropic's published ceiling. Measured live before this was added: the Command Center
9659
+ // assistant's iteration schema declares 33, so 8 of 8 iterations across a 3-turn session were
9660
+ // 400'd and retried unstrict. `optionalAllowed` is still correct -- an optional property is
9661
+ // representable in this grammar, there is just a cap on how many.
9662
+ maxOptionalProperties: 24
9663
+ };
9664
+ var OPENAI_DIALECT = {
9665
+ strict: "allRequired",
9666
+ refs: "passthrough",
9667
+ allowsSchemaKeyword: false
9668
+ };
9669
+ var OPENROUTER_DIALECT = {
9670
+ strict: "allRequired",
9671
+ refs: "refuse",
9672
+ allowsSchemaKeyword: false
9673
+ };
9674
+ var PROVIDER_DIALECTS = {
9675
+ anthropic: ANTHROPIC_DIALECT,
9676
+ openai: OPENAI_DIALECT,
9677
+ openrouter: OPENROUTER_DIALECT
9678
+ };
9679
+
9948
9680
  // ../core/src/platform/registry/validation.ts
9949
9681
  var RegistryValidationError = class extends Error {
9950
9682
  constructor(orgName, resourceId, field, message) {
@@ -10312,7 +10044,6 @@ function validateDeclaredSystemInterfaceReadiness(orgName, organizationModel) {
10312
10044
  message: `System Interface "${path}/${interfaceKey}" references unknown readiness profile "${readinessProfile}".`
10313
10045
  });
10314
10046
  }
10315
- continue;
10316
10047
  }
10317
10048
  const result = computeInterfaceReadiness(model, { systemPath: path, interfaceKey });
10318
10049
  for (const issue of result.issues) {