@elevasis/sdk 1.19.0 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/cli.cjs +1718 -72
  2. package/dist/index.d.ts +661 -7
  3. package/dist/index.js +565 -42
  4. package/dist/node/index.d.ts +2 -0
  5. package/dist/node/index.js +219 -2
  6. package/dist/test-utils/index.d.ts +459 -4
  7. package/dist/test-utils/index.js +509 -37
  8. package/dist/types/worker/platform.d.ts +15 -1
  9. package/dist/worker/index.js +365 -37
  10. package/package.json +2 -2
  11. package/reference/_navigation.md +2 -1
  12. package/reference/_reference-manifest.json +14 -0
  13. package/reference/claude-config/registries/knowledge-flags.json +156 -0
  14. package/reference/claude-config/rules/agent-start-here.md +5 -5
  15. package/reference/claude-config/rules/deployment.md +4 -3
  16. package/reference/claude-config/rules/frontend.md +2 -2
  17. package/reference/claude-config/rules/operations.md +17 -13
  18. package/reference/claude-config/rules/organization-model.md +7 -5
  19. package/reference/claude-config/rules/organization-os.md +13 -11
  20. package/reference/claude-config/rules/ui.md +3 -3
  21. package/reference/claude-config/rules/vibe.md +4 -4
  22. package/reference/claude-config/skills/explore/SKILL.md +4 -4
  23. package/reference/claude-config/skills/knowledge/SKILL.md +8 -8
  24. package/reference/claude-config/skills/knowledge/operations/codify-level-a.md +7 -7
  25. package/reference/claude-config/skills/knowledge/operations/codify-level-b.md +13 -13
  26. package/reference/claude-config/skills/knowledge/operations/customers.md +1 -1
  27. package/reference/claude-config/skills/knowledge/operations/goals.md +1 -1
  28. package/reference/claude-config/skills/knowledge/operations/identity.md +1 -1
  29. package/reference/claude-config/skills/knowledge/operations/offerings.md +1 -1
  30. package/reference/claude-config/skills/knowledge/operations/roles.md +1 -1
  31. package/reference/claude-config/skills/knowledge/operations/techStack.md +19 -91
  32. package/reference/claude-config/skills/project/SKILL.md +73 -13
  33. package/reference/claude-config/skills/save/SKILL.md +5 -5
  34. package/reference/claude-config/skills/tutorial/technical.md +5 -6
  35. package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +34 -0
  36. package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +38 -0
  37. package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +32 -0
  38. package/reference/claude-config/sync-notes/2026-05-09-command-system.md +33 -0
  39. package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +69 -0
  40. package/reference/examples/organization-model.ts +17 -5
  41. package/reference/framework/index.mdx +1 -1
  42. package/reference/framework/project-structure.mdx +10 -8
  43. package/reference/packages/core/src/business/README.md +2 -2
  44. package/reference/packages/core/src/organization-model/README.md +10 -3
  45. package/reference/resources/index.mdx +27 -17
  46. package/reference/scaffold/core/organization-model.mdx +33 -14
  47. package/reference/scaffold/operations/workflow-recipes.md +35 -29
  48. package/reference/scaffold/recipes/add-a-feature.md +18 -3
  49. package/reference/scaffold/recipes/add-a-resource.md +50 -10
  50. package/reference/scaffold/recipes/customize-crm-actions.md +12 -6
  51. package/reference/scaffold/recipes/customize-organization-model.md +18 -3
  52. package/reference/scaffold/recipes/extend-crm.md +17 -19
  53. package/reference/scaffold/recipes/extend-lead-gen.md +31 -31
  54. package/reference/scaffold/recipes/index.md +1 -1
  55. package/reference/scaffold/reference/contracts.md +501 -303
  56. package/reference/scaffold/reference/feature-registry.md +1 -1
  57. package/reference/scaffold/reference/glossary.md +8 -3
  58. package/reference/scaffold/ui/recipes.md +21 -6
package/dist/cli.cjs CHANGED
@@ -36630,6 +36630,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
36630
36630
  "knowledge.reference",
36631
36631
  "feature.dashboard",
36632
36632
  "feature.calendar",
36633
+ "feature.business",
36633
36634
  "feature.sales",
36634
36635
  "feature.crm",
36635
36636
  "feature.finance",
@@ -36869,6 +36870,13 @@ var LEAD_GEN_STAGE_CATALOG = {
36869
36870
  order: 2,
36870
36871
  entity: "company"
36871
36872
  },
36873
+ crawled: {
36874
+ key: "crawled",
36875
+ label: "Websites crawled",
36876
+ description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
36877
+ order: 2.5,
36878
+ entity: "company"
36879
+ },
36872
36880
  extracted: {
36873
36881
  key: "extracted",
36874
36882
  label: "Websites analyzed",
@@ -36888,7 +36896,9 @@ var LEAD_GEN_STAGE_CATALOG = {
36888
36896
  label: "Decision-makers found",
36889
36897
  description: "Decision-maker contacts discovered and attached to a qualified company.",
36890
36898
  order: 6,
36891
- entity: "company"
36899
+ entity: "company",
36900
+ recordEntity: "contact",
36901
+ recordStageKey: "discovered"
36892
36902
  },
36893
36903
  // Prospecting — contact discovery
36894
36904
  discovered: {
@@ -36926,7 +36936,8 @@ var LEAD_GEN_STAGE_CATALOG = {
36926
36936
  label: "Reviewed and exported",
36927
36937
  description: "Approved records have been reviewed and exported for handoff.",
36928
36938
  order: 10,
36929
- entity: "contact"
36939
+ entity: "company",
36940
+ additionalEntities: ["contact"]
36930
36941
  },
36931
36942
  interested: {
36932
36943
  key: "interested",
@@ -36985,18 +36996,47 @@ var DEFAULT_ORGANIZATION_MODEL_PROJECTS = {
36985
36996
  // ../core/src/organization-model/domains/prospecting.ts
36986
36997
  var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
36987
36998
  id: ModelIdSchema,
36988
- order: external_exports.number().int().min(0)
36999
+ order: external_exports.number().min(0)
37000
+ });
37001
+ var RecordColumnConfigSchema = external_exports.object({
37002
+ key: ModelIdSchema,
37003
+ label: external_exports.string().trim().min(1).max(120),
37004
+ path: external_exports.string().trim().min(1).max(500),
37005
+ width: external_exports.union([external_exports.number().positive(), external_exports.string().trim().min(1).max(100)]).optional(),
37006
+ renderType: external_exports.enum(["text", "badge", "datetime", "count", "json"]).optional(),
37007
+ badgeColor: external_exports.string().trim().min(1).max(40).optional()
37008
+ });
37009
+ var RecordColumnsConfigSchema = external_exports.object({
37010
+ company: external_exports.array(RecordColumnConfigSchema).optional(),
37011
+ contact: external_exports.array(RecordColumnConfigSchema).optional()
37012
+ }).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
37013
+ message: "recordColumns must include at least one entity column set"
37014
+ });
37015
+ var CredentialRequirementSchema = external_exports.object({
37016
+ key: ModelIdSchema,
37017
+ provider: ModelIdSchema,
37018
+ credentialType: external_exports.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
37019
+ label: external_exports.string().trim().min(1).max(120),
37020
+ required: external_exports.boolean(),
37021
+ selectionMode: external_exports.enum(["single", "multiple"]).optional(),
37022
+ inputPath: external_exports.string().trim().min(1).max(500),
37023
+ verifyOnRun: external_exports.boolean().optional()
36989
37024
  });
36990
37025
  var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
36991
37026
  id: ModelIdSchema,
36992
37027
  primaryEntity: external_exports.enum(["company", "contact"]),
36993
37028
  outputs: external_exports.array(external_exports.enum(["company", "contact", "export"])).min(1),
36994
37029
  stageKey: ModelIdSchema,
37030
+ recordEntity: external_exports.enum(["company", "contact"]).optional(),
37031
+ recordsStageKey: ModelIdSchema.optional(),
37032
+ recordSourceStageKey: ModelIdSchema.optional(),
36995
37033
  dependsOn: external_exports.array(ModelIdSchema).optional(),
36996
37034
  dependencyMode: external_exports.literal("per-record-eligibility"),
36997
37035
  capabilityKey: ModelIdSchema,
36998
37036
  defaultBatchSize: external_exports.number().int().positive(),
36999
- maxBatchSize: external_exports.number().int().positive()
37037
+ maxBatchSize: external_exports.number().int().positive(),
37038
+ recordColumns: RecordColumnsConfigSchema.optional(),
37039
+ credentialRequirements: external_exports.array(CredentialRequirementSchema).optional()
37000
37040
  }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
37001
37041
  message: "defaultBatchSize must be less than or equal to maxBatchSize",
37002
37042
  path: ["defaultBatchSize"]
@@ -37005,6 +37045,62 @@ var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
37005
37045
  id: ModelIdSchema,
37006
37046
  steps: external_exports.array(ProspectingBuildTemplateStepSchema).min(1)
37007
37047
  });
37048
+ var DTC_RECORD_COLUMNS = {
37049
+ populated: {
37050
+ company: [
37051
+ { key: "name", label: "Company", path: "company.name" },
37052
+ { key: "domain", label: "Domain", path: "company.domain" },
37053
+ { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
37054
+ { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
37055
+ { key: "location", label: "Location", path: "company.locationState" }
37056
+ ]
37057
+ },
37058
+ crawled: {
37059
+ company: [
37060
+ { key: "name", label: "Company", path: "company.name" },
37061
+ { key: "domain", label: "Domain", path: "company.domain" },
37062
+ { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
37063
+ { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
37064
+ ]
37065
+ },
37066
+ extracted: {
37067
+ company: [
37068
+ { key: "name", label: "Company", path: "company.name" },
37069
+ { key: "domain", label: "Domain", path: "company.domain" },
37070
+ { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
37071
+ { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
37072
+ { key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
37073
+ { key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
37074
+ ]
37075
+ },
37076
+ qualified: {
37077
+ company: [
37078
+ { key: "name", label: "Company", path: "company.name" },
37079
+ { key: "domain", label: "Domain", path: "company.domain" },
37080
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
37081
+ { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
37082
+ { key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
37083
+ ]
37084
+ },
37085
+ decisionMakers: {
37086
+ contact: [
37087
+ { key: "name", label: "Name", path: "contact.name" },
37088
+ { key: "title", label: "Title", path: "contact.title" },
37089
+ { key: "email", label: "Email", path: "contact.email" },
37090
+ { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
37091
+ { key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
37092
+ ]
37093
+ },
37094
+ uploaded: {
37095
+ company: [
37096
+ { key: "name", label: "Company", path: "company.name" },
37097
+ { key: "domain", label: "Domain", path: "company.domain" },
37098
+ { key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
37099
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
37100
+ { key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
37101
+ ]
37102
+ }
37103
+ };
37008
37104
  var CapabilitySchema = external_exports.object({
37009
37105
  id: ModelIdSchema,
37010
37106
  label: external_exports.string(),
@@ -37036,6 +37132,12 @@ var CAPABILITY_REGISTRY = [
37036
37132
  description: "Check email deliverability before outreach.",
37037
37133
  resourceId: "lgn-05-email-verification-workflow"
37038
37134
  },
37135
+ {
37136
+ id: "lead-gen.company.apify-crawl",
37137
+ label: "Crawl websites",
37138
+ description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.",
37139
+ resourceId: "lgn-02a-apify-website-crawl-workflow"
37140
+ },
37039
37141
  {
37040
37142
  id: "lead-gen.company.website-extract",
37041
37143
  label: "Extract website signals",
@@ -37182,7 +37284,45 @@ var PROSPECTING_STEPS = {
37182
37284
  dependencyMode: "per-record-eligibility",
37183
37285
  capabilityKey: "lead-gen.company.apollo-import",
37184
37286
  defaultBatchSize: 250,
37185
- maxBatchSize: 1e3
37287
+ maxBatchSize: 1e3,
37288
+ recordColumns: DTC_RECORD_COLUMNS.populated,
37289
+ credentialRequirements: [
37290
+ {
37291
+ key: "apollo",
37292
+ provider: "apollo",
37293
+ credentialType: "api-key-secret",
37294
+ label: "Apollo API key",
37295
+ required: true,
37296
+ selectionMode: "single",
37297
+ inputPath: "credential"
37298
+ }
37299
+ ]
37300
+ },
37301
+ apifyCrawl: {
37302
+ id: "apify-crawl",
37303
+ label: "Websites crawled",
37304
+ description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.",
37305
+ primaryEntity: "company",
37306
+ outputs: ["company"],
37307
+ stageKey: "crawled",
37308
+ dependsOn: ["import-apollo-search"],
37309
+ dependencyMode: "per-record-eligibility",
37310
+ capabilityKey: "lead-gen.company.apify-crawl",
37311
+ defaultBatchSize: 50,
37312
+ maxBatchSize: 100,
37313
+ recordColumns: DTC_RECORD_COLUMNS.crawled,
37314
+ credentialRequirements: [
37315
+ {
37316
+ key: "apify",
37317
+ provider: "apify",
37318
+ credentialType: "api-key-secret",
37319
+ label: "Apify API token",
37320
+ required: true,
37321
+ selectionMode: "single",
37322
+ inputPath: "credential",
37323
+ verifyOnRun: true
37324
+ }
37325
+ ]
37186
37326
  },
37187
37327
  analyzeWebsites: {
37188
37328
  id: "analyze-websites",
@@ -37191,11 +37331,12 @@ var PROSPECTING_STEPS = {
37191
37331
  primaryEntity: "company",
37192
37332
  outputs: ["company"],
37193
37333
  stageKey: "extracted",
37194
- dependsOn: ["import-apollo-search"],
37334
+ dependsOn: ["apify-crawl"],
37195
37335
  dependencyMode: "per-record-eligibility",
37196
37336
  capabilityKey: "lead-gen.company.website-extract",
37197
37337
  defaultBatchSize: 50,
37198
- maxBatchSize: 100
37338
+ maxBatchSize: 100,
37339
+ recordColumns: DTC_RECORD_COLUMNS.extracted
37199
37340
  },
37200
37341
  scoreDtcFit: {
37201
37342
  id: "score-dtc-fit",
@@ -37208,7 +37349,8 @@ var PROSPECTING_STEPS = {
37208
37349
  dependencyMode: "per-record-eligibility",
37209
37350
  capabilityKey: "lead-gen.company.dtc-subscription-qualify",
37210
37351
  defaultBatchSize: 100,
37211
- maxBatchSize: 250
37352
+ maxBatchSize: 250,
37353
+ recordColumns: DTC_RECORD_COLUMNS.qualified
37212
37354
  },
37213
37355
  enrichDecisionMakers: {
37214
37356
  id: "enrich-decision-makers",
@@ -37217,37 +37359,52 @@ var PROSPECTING_STEPS = {
37217
37359
  primaryEntity: "company",
37218
37360
  outputs: ["contact"],
37219
37361
  stageKey: "decision-makers-enriched",
37362
+ recordEntity: "contact",
37220
37363
  dependsOn: ["score-dtc-fit"],
37221
37364
  dependencyMode: "per-record-eligibility",
37222
37365
  capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
37223
37366
  defaultBatchSize: 100,
37224
- maxBatchSize: 250
37225
- },
37226
- verifyEmails: {
37227
- id: "verify-emails",
37228
- label: "Emails verified",
37229
- description: "Verify deliverability before the QC and handoff step.",
37230
- primaryEntity: "contact",
37231
- outputs: ["contact"],
37232
- stageKey: "verified",
37233
- dependsOn: ["enrich-decision-makers"],
37234
- dependencyMode: "per-record-eligibility",
37235
- capabilityKey: "lead-gen.contact.verify-email",
37236
- defaultBatchSize: 250,
37237
- maxBatchSize: 500
37367
+ maxBatchSize: 250,
37368
+ recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
37369
+ credentialRequirements: [
37370
+ {
37371
+ key: "apollo",
37372
+ provider: "apollo",
37373
+ credentialType: "api-key-secret",
37374
+ label: "Apollo API key",
37375
+ required: true,
37376
+ selectionMode: "single",
37377
+ inputPath: "credential"
37378
+ }
37379
+ ]
37238
37380
  },
37239
37381
  reviewAndExport: {
37240
37382
  id: "review-and-export",
37241
37383
  label: "Reviewed and exported",
37242
- description: "Operator QC approves or rejects leads, then approved records are exported as a lead list.",
37384
+ description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
37243
37385
  primaryEntity: "company",
37244
37386
  outputs: ["export"],
37245
37387
  stageKey: "uploaded",
37246
- dependsOn: ["verify-emails"],
37388
+ recordsStageKey: "uploaded",
37389
+ recordSourceStageKey: "qualified",
37390
+ dependsOn: ["enrich-decision-makers"],
37247
37391
  dependencyMode: "per-record-eligibility",
37248
37392
  capabilityKey: "lead-gen.export.list",
37249
37393
  defaultBatchSize: 100,
37250
- maxBatchSize: 250
37394
+ maxBatchSize: 250,
37395
+ recordColumns: DTC_RECORD_COLUMNS.uploaded,
37396
+ credentialRequirements: [
37397
+ {
37398
+ key: "clickup",
37399
+ provider: "clickup",
37400
+ credentialType: "api-key-secret",
37401
+ label: "ClickUp API token",
37402
+ required: true,
37403
+ selectionMode: "single",
37404
+ inputPath: "clickupCredential",
37405
+ verifyOnRun: true
37406
+ }
37407
+ ]
37251
37408
  }
37252
37409
  }
37253
37410
  };
@@ -37269,7 +37426,7 @@ function toProspectingLifecycleStage(stage) {
37269
37426
  };
37270
37427
  }
37271
37428
  function leadGenStagesForEntity(entity) {
37272
- return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity).sort((a, b) => a.order - b.order).map(toProspectingLifecycleStage);
37429
+ return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity || stage.additionalEntities?.includes(entity)).sort((a, b) => a.order - b.order).map(toProspectingLifecycleStage);
37273
37430
  }
37274
37431
  var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
37275
37432
  listEntityId: "leadgen.list",
@@ -37299,10 +37456,10 @@ var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
37299
37456
  description: "Prospecting pipeline for DTC subscription or subscription-ready brands where Apollo is the source and contact-enrichment layer, Elevasis handles company research and fit scoring, and approved leads export as an approved lead list.",
37300
37457
  steps: [
37301
37458
  PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
37459
+ PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
37302
37460
  PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
37303
37461
  PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
37304
37462
  PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
37305
- PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
37306
37463
  PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
37307
37464
  ]
37308
37465
  }
@@ -37503,14 +37660,105 @@ var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {
37503
37660
  products: []
37504
37661
  };
37505
37662
 
37663
+ // ../core/src/organization-model/domains/systems.ts
37664
+ var SystemKindSchema = external_exports.enum(["product", "operational", "platform", "diagnostic"]);
37665
+ var SystemStatusSchema = external_exports.enum(["active", "deprecated", "archived"]);
37666
+ var SystemIdSchema = ModelIdSchema;
37667
+ var SystemEntrySchema = external_exports.object({
37668
+ /** Stable tenant-defined system id (e.g. "sys.lead-gen"). */
37669
+ id: SystemIdSchema,
37670
+ /** Human-readable system title shown in governance and operations UI. */
37671
+ title: LabelSchema,
37672
+ /** One-paragraph purpose statement for the bounded context. */
37673
+ description: DescriptionSchema,
37674
+ /** Closed system shape enum; catalog values remain tenant-defined. */
37675
+ kind: SystemKindSchema,
37676
+ /** Optional role responsible for this system. */
37677
+ responsibleRoleId: ModelIdSchema.optional(),
37678
+ /** Optional knowledge nodes that govern this system. */
37679
+ governedByKnowledge: ReferenceIdsSchema,
37680
+ /** Optional goals this system contributes to. */
37681
+ drivesGoals: ReferenceIdsSchema,
37682
+ status: SystemStatusSchema
37683
+ });
37684
+ var SystemsDomainSchema = external_exports.object({
37685
+ systems: external_exports.array(SystemEntrySchema).default([])
37686
+ });
37687
+ var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {
37688
+ systems: []
37689
+ };
37690
+
37691
+ // ../core/src/organization-model/domains/resources.ts
37692
+ var ResourceKindSchema = external_exports.enum(["workflow", "agent", "integration"]);
37693
+ var ResourceGovernanceStatusSchema = external_exports.enum(["active", "deprecated", "archived"]);
37694
+ var AgentKindSchema = external_exports.enum(["orchestrator", "specialist", "utility", "system"]);
37695
+ var ResourceIdSchema = external_exports.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
37696
+ var ResourceEntryBaseSchema = external_exports.object({
37697
+ /** Canonical resource id; runtime resourceId derives from this value. */
37698
+ id: ResourceIdSchema,
37699
+ /** Required single System membership. */
37700
+ systemId: SystemIdSchema,
37701
+ /** Optional role responsible for maintaining this resource. */
37702
+ ownerRoleId: ModelIdSchema.optional(),
37703
+ status: ResourceGovernanceStatusSchema
37704
+ });
37705
+ var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
37706
+ kind: external_exports.literal("workflow"),
37707
+ /** Mirrors WorkflowConfig.capabilityKey when the runtime workflow has one. */
37708
+ capabilityKey: external_exports.string().trim().min(1).max(255).optional()
37709
+ });
37710
+ var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
37711
+ kind: external_exports.literal("agent"),
37712
+ /** Mirrors code-side AgentConfig.kind. */
37713
+ agentKind: AgentKindSchema,
37714
+ /** Role this agent embodies, if any. */
37715
+ actsAsRoleId: ModelIdSchema.optional(),
37716
+ /** Mirrors AgentConfig.sessionCapable. */
37717
+ sessionCapable: external_exports.boolean()
37718
+ });
37719
+ var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
37720
+ kind: external_exports.literal("integration"),
37721
+ provider: external_exports.string().trim().min(1).max(100)
37722
+ });
37723
+ var ResourceEntrySchema = external_exports.discriminatedUnion("kind", [
37724
+ WorkflowResourceEntrySchema,
37725
+ AgentResourceEntrySchema,
37726
+ IntegrationResourceEntrySchema
37727
+ ]);
37728
+ var ResourcesDomainSchema = external_exports.object({
37729
+ entries: external_exports.array(ResourceEntrySchema).default([])
37730
+ });
37731
+ var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {
37732
+ entries: []
37733
+ };
37734
+
37506
37735
  // ../core/src/organization-model/domains/roles.ts
37736
+ var RoleIdSchema = ModelIdSchema;
37737
+ var HumanRoleHolderSchema = external_exports.object({
37738
+ kind: external_exports.literal("human"),
37739
+ userId: external_exports.string().trim().min(1).max(200)
37740
+ });
37741
+ var AgentRoleHolderSchema = external_exports.object({
37742
+ kind: external_exports.literal("agent"),
37743
+ agentId: ResourceIdSchema
37744
+ });
37745
+ var TeamRoleHolderSchema = external_exports.object({
37746
+ kind: external_exports.literal("team"),
37747
+ memberIds: external_exports.array(external_exports.string().trim().min(1).max(200)).min(1)
37748
+ });
37749
+ var RoleHolderSchema = external_exports.discriminatedUnion("kind", [
37750
+ HumanRoleHolderSchema,
37751
+ AgentRoleHolderSchema,
37752
+ TeamRoleHolderSchema
37753
+ ]);
37754
+ var RoleHoldersSchema = external_exports.union([RoleHolderSchema, external_exports.array(RoleHolderSchema).min(1)]);
37507
37755
  var RoleSchema = external_exports.object({
37508
37756
  /** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
37509
- id: external_exports.string().trim().min(1).max(100),
37757
+ id: RoleIdSchema,
37510
37758
  /** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
37511
37759
  title: external_exports.string().trim().min(1).max(200),
37512
37760
  /**
37513
- * List of responsibilities this role owns plain-language descriptions of
37761
+ * List of responsibilities this role owns - plain-language descriptions of
37514
37762
  * what the person in this role is accountable for delivering.
37515
37763
  * Defaults to empty array so minimal role definitions stay concise.
37516
37764
  */
@@ -37518,16 +37766,18 @@ var RoleSchema = external_exports.object({
37518
37766
  /**
37519
37767
  * Optional: ID of another role this role reports to.
37520
37768
  * When present, must reference another `roles[].id` in the same organization.
37521
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
37522
- * Absence indicates a top-level role (no reporting line).
37523
37769
  */
37524
- reportsToId: external_exports.string().trim().min(1).max(100).optional(),
37770
+ reportsToId: RoleIdSchema.optional(),
37771
+ /**
37772
+ * Optional: human, agent, or team holder currently filling this role.
37773
+ * Agent holders reference OM Resource IDs and are validated at the model level.
37774
+ */
37775
+ heldBy: RoleHoldersSchema.optional(),
37525
37776
  /**
37526
- * Optional: name or email of the person currently holding this role.
37527
- * Free-form string supports "Alice Johnson", "alice@example.com", or
37528
- * any human-readable identifier. Not validated against any user registry.
37777
+ * Optional Systems this role is accountable for.
37778
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
37529
37779
  */
37530
- heldBy: external_exports.string().trim().max(200).optional()
37780
+ responsibleFor: external_exports.array(SystemIdSchema).optional()
37531
37781
  });
37532
37782
  var RolesDomainSchema = external_exports.object({
37533
37783
  roles: external_exports.array(RoleSchema).default([])
@@ -37770,8 +38020,8 @@ var OrgKnowledgeNodeSchema = external_exports.object({
37770
38020
  skills: external_exports.array(KnowledgeSkillBindingSchema).optional(),
37771
38021
  /** Domain key used to derive fast graph->skill registries. */
37772
38022
  domain: KnowledgeDomainBindingSchema.optional(),
37773
- /** Identifiers of the roles or members who own this knowledge node. */
37774
- ownerIds: external_exports.array(ModelIdSchema).default([]),
38023
+ /** Role identifiers that own this knowledge node. */
38024
+ ownerIds: external_exports.array(RoleIdSchema).default([]),
37775
38025
  /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
37776
38026
  updatedAt: external_exports.string().trim().min(1).max(50)
37777
38027
  });
@@ -37793,6 +38043,8 @@ var OrganizationModelSchemaBase = external_exports.object({
37793
38043
  offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
37794
38044
  roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
37795
38045
  goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
38046
+ systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
38047
+ resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
37796
38048
  statuses: StatusesDomainSchema.default({ entries: [] }),
37797
38049
  operations: OperationsDomainSchema.default({ entries: [] }),
37798
38050
  knowledge: KnowledgeDomainSchema.default({ nodes: [] })
@@ -37826,6 +38078,9 @@ function hasFeature(featuresById, featureId) {
37826
38078
  function defaultFeaturePathFor(id) {
37827
38079
  return `/${id.replaceAll(".", "/")}`;
37828
38080
  }
38081
+ function asRoleHolderArray(heldBy) {
38082
+ return Array.isArray(heldBy) ? heldBy : [heldBy];
38083
+ }
37829
38084
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
37830
38085
  const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
37831
38086
  const featureIdsByEffectivePath = /* @__PURE__ */ new Map();
@@ -37936,6 +38191,8 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
37936
38191
  );
37937
38192
  }
37938
38193
  });
38194
+ const goalsById = new Map(model.goals.objectives.map((objective) => [objective.id, objective]));
38195
+ const knowledgeById = new Map(model.knowledge.nodes.map((node) => [node.id, node]));
37939
38196
  const rolesById = new Map(model.roles.roles.map((role) => [role.id, role]));
37940
38197
  model.roles.roles.forEach((role, roleIndex) => {
37941
38198
  if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
@@ -37946,6 +38203,102 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
37946
38203
  );
37947
38204
  }
37948
38205
  });
38206
+ const systemsById = collectIds(model.systems.systems, ctx, ["systems", "systems"], "System");
38207
+ model.roles.roles.forEach((role, roleIndex) => {
38208
+ role.responsibleFor?.forEach((systemId, systemIndex) => {
38209
+ if (!systemsById.has(systemId)) {
38210
+ addIssue(
38211
+ ctx,
38212
+ ["roles", "roles", roleIndex, "responsibleFor", systemIndex],
38213
+ `Role "${role.id}" references unknown responsibleFor system "${systemId}"`
38214
+ );
38215
+ }
38216
+ });
38217
+ });
38218
+ model.systems.systems.forEach((system, systemIndex) => {
38219
+ if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
38220
+ addIssue(
38221
+ ctx,
38222
+ ["systems", "systems", systemIndex, "responsibleRoleId"],
38223
+ `System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
38224
+ );
38225
+ }
38226
+ system.governedByKnowledge.forEach((nodeId2, nodeIndex) => {
38227
+ if (!knowledgeById.has(nodeId2)) {
38228
+ addIssue(
38229
+ ctx,
38230
+ ["systems", "systems", systemIndex, "governedByKnowledge", nodeIndex],
38231
+ `System "${system.id}" references unknown knowledge node "${nodeId2}"`
38232
+ );
38233
+ }
38234
+ });
38235
+ system.drivesGoals.forEach((goalId, goalIndex) => {
38236
+ if (!goalsById.has(goalId)) {
38237
+ addIssue(
38238
+ ctx,
38239
+ ["systems", "systems", systemIndex, "drivesGoals", goalIndex],
38240
+ `System "${system.id}" references unknown goal "${goalId}"`
38241
+ );
38242
+ }
38243
+ });
38244
+ });
38245
+ const resourcesById = collectIds(model.resources.entries, ctx, ["resources", "entries"], "Resource");
38246
+ model.resources.entries.forEach((resource, resourceIndex) => {
38247
+ if (!systemsById.has(resource.systemId)) {
38248
+ addIssue(
38249
+ ctx,
38250
+ ["resources", "entries", resourceIndex, "systemId"],
38251
+ `Resource "${resource.id}" references unknown systemId "${resource.systemId}"`
38252
+ );
38253
+ }
38254
+ if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
38255
+ addIssue(
38256
+ ctx,
38257
+ ["resources", "entries", resourceIndex, "ownerRoleId"],
38258
+ `Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
38259
+ );
38260
+ }
38261
+ if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
38262
+ addIssue(
38263
+ ctx,
38264
+ ["resources", "entries", resourceIndex, "actsAsRoleId"],
38265
+ `Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
38266
+ );
38267
+ }
38268
+ });
38269
+ model.roles.roles.forEach((role, roleIndex) => {
38270
+ if (role.heldBy === void 0) return;
38271
+ asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
38272
+ if (holder.kind !== "agent") return;
38273
+ const resource = resourcesById.get(holder.agentId);
38274
+ if (resource === void 0) {
38275
+ addIssue(
38276
+ ctx,
38277
+ ["roles", "roles", roleIndex, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
38278
+ `Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
38279
+ );
38280
+ return;
38281
+ }
38282
+ if (resource.kind !== "agent") {
38283
+ addIssue(
38284
+ ctx,
38285
+ ["roles", "roles", roleIndex, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
38286
+ `Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
38287
+ );
38288
+ }
38289
+ });
38290
+ });
38291
+ model.knowledge.nodes.forEach((node, nodeIndex) => {
38292
+ node.ownerIds.forEach((roleId, ownerIndex) => {
38293
+ if (!rolesById.has(roleId)) {
38294
+ addIssue(
38295
+ ctx,
38296
+ ["knowledge", "nodes", nodeIndex, "ownerIds", ownerIndex],
38297
+ `Knowledge node "${node.id}" references unknown owner role "${roleId}"`
38298
+ );
38299
+ }
38300
+ });
38301
+ });
37949
38302
  });
37950
38303
 
37951
38304
  // ../core/src/organization-model/graph/schema.ts
@@ -38268,6 +38621,149 @@ var RegistryValidationError = class extends Error {
38268
38621
  this.name = "RegistryValidationError";
38269
38622
  }
38270
38623
  };
38624
+ function getResourceValidatorMode(explicitMode) {
38625
+ if (explicitMode) return explicitMode;
38626
+ const env2 = globalThis.process?.env;
38627
+ return env2?.ELEVASIS_RESOURCE_VALIDATOR === "warn-only" ? "warn-only" : "strict";
38628
+ }
38629
+ function addGovernanceIssue(issues, type, orgName, resourceId, message) {
38630
+ issues.push({
38631
+ type,
38632
+ orgName,
38633
+ resourceId,
38634
+ message
38635
+ });
38636
+ }
38637
+ function emitGovernanceIssues(issues, mode, onWarning) {
38638
+ if (issues.length === 0) return;
38639
+ if (mode === "strict") {
38640
+ const first = issues[0];
38641
+ throw new RegistryValidationError(first.orgName, first.resourceId, "organizationModel.resources", first.message);
38642
+ }
38643
+ const warn2 = onWarning ?? ((issue2) => console.warn(issue2.message));
38644
+ for (const issue2 of issues) {
38645
+ warn2(issue2);
38646
+ }
38647
+ }
38648
+ function getRuntimeResources(resources) {
38649
+ return [
38650
+ ...(resources.workflows ?? []).map((workflow) => ({
38651
+ resourceId: workflow.config.resourceId,
38652
+ type: workflow.config.type,
38653
+ descriptor: workflow.config.resource
38654
+ })),
38655
+ ...(resources.agents ?? []).map((agent) => ({
38656
+ resourceId: agent.config.resourceId,
38657
+ type: agent.config.type,
38658
+ descriptor: agent.config.resource
38659
+ })),
38660
+ ...(resources.integrations ?? []).map((integration) => ({
38661
+ resourceId: integration.resourceId,
38662
+ type: integration.type,
38663
+ descriptor: integration.resource
38664
+ }))
38665
+ ];
38666
+ }
38667
+ function validateResourceGovernance(orgName, deployment, organizationModel = deployment.organizationModel, options = {}) {
38668
+ const mode = getResourceValidatorMode(options.mode);
38669
+ const omResources = organizationModel?.resources?.entries;
38670
+ const omSystems = organizationModel?.systems?.systems;
38671
+ const issues = [];
38672
+ if (!omResources || !omSystems) {
38673
+ return { valid: true, mode, issues };
38674
+ }
38675
+ const systemsById = new Map(omSystems.map((system) => [system.id, system]));
38676
+ const activeOmResources = omResources.filter((resource) => resource.status === "active");
38677
+ const omResourcesById = new Map(activeOmResources.map((resource) => [resource.id, resource]));
38678
+ const runtimeResources = getRuntimeResources(deployment);
38679
+ const runtimeResourcesById = new Map(runtimeResources.map((resource) => [resource.resourceId, resource]));
38680
+ for (const resource of activeOmResources) {
38681
+ if (!systemsById.has(resource.systemId)) {
38682
+ addGovernanceIssue(
38683
+ issues,
38684
+ "missing-om-system",
38685
+ orgName,
38686
+ resource.id,
38687
+ `[${orgName}] OM resource '${resource.id}' references missing System '${resource.systemId}'.`
38688
+ );
38689
+ }
38690
+ const runtimeResource = runtimeResourcesById.get(resource.id);
38691
+ if (!runtimeResource) {
38692
+ addGovernanceIssue(
38693
+ issues,
38694
+ "missing-code-resource",
38695
+ orgName,
38696
+ resource.id,
38697
+ `[${orgName}] OM resource '${resource.id}' has no matching code-side resource.`
38698
+ );
38699
+ continue;
38700
+ }
38701
+ if (runtimeResource.type !== resource.kind) {
38702
+ addGovernanceIssue(
38703
+ issues,
38704
+ "type-mismatch",
38705
+ orgName,
38706
+ resource.id,
38707
+ `[${orgName}] Resource '${resource.id}' type mismatch: code has '${runtimeResource.type}', OM has '${resource.kind}'.`
38708
+ );
38709
+ }
38710
+ if (runtimeResource.descriptor && runtimeResource.descriptor.systemId !== resource.systemId) {
38711
+ addGovernanceIssue(
38712
+ issues,
38713
+ "system-mismatch",
38714
+ orgName,
38715
+ resource.id,
38716
+ `[${orgName}] Resource '${resource.id}' system mismatch: code descriptor has '${runtimeResource.descriptor.systemId}', OM has '${resource.systemId}'.`
38717
+ );
38718
+ }
38719
+ }
38720
+ for (const runtimeResource of runtimeResources) {
38721
+ const omResource = omResourcesById.get(runtimeResource.resourceId);
38722
+ if (!omResource) {
38723
+ addGovernanceIssue(
38724
+ issues,
38725
+ "missing-om-resource",
38726
+ orgName,
38727
+ runtimeResource.resourceId,
38728
+ `[${orgName}] Code-side resource '${runtimeResource.resourceId}' has no active OM Resource descriptor.`
38729
+ );
38730
+ }
38731
+ if (!runtimeResource.descriptor) {
38732
+ addGovernanceIssue(
38733
+ issues,
38734
+ "raw-resource-id",
38735
+ orgName,
38736
+ runtimeResource.resourceId,
38737
+ `[${orgName}] Code-side resource '${runtimeResource.resourceId}' authors raw resourceId/type values. Use an OM Resource descriptor and bindResourceDescriptor().`
38738
+ );
38739
+ continue;
38740
+ }
38741
+ if (runtimeResource.descriptor.id !== runtimeResource.resourceId) {
38742
+ addGovernanceIssue(
38743
+ issues,
38744
+ "raw-resource-id",
38745
+ orgName,
38746
+ runtimeResource.resourceId,
38747
+ `[${orgName}] Code-side resource '${runtimeResource.resourceId}' does not derive identity from its OM descriptor '${runtimeResource.descriptor.id}'.`
38748
+ );
38749
+ }
38750
+ if (runtimeResource.descriptor.kind !== runtimeResource.type) {
38751
+ addGovernanceIssue(
38752
+ issues,
38753
+ "type-mismatch",
38754
+ orgName,
38755
+ runtimeResource.resourceId,
38756
+ `[${orgName}] Code-side resource '${runtimeResource.resourceId}' descriptor kind '${runtimeResource.descriptor.kind}' does not match runtime type '${runtimeResource.type}'.`
38757
+ );
38758
+ }
38759
+ }
38760
+ emitGovernanceIssues(issues, mode, options.onWarning);
38761
+ return {
38762
+ valid: issues.length === 0,
38763
+ mode,
38764
+ issues
38765
+ };
38766
+ }
38271
38767
  function validateDeploymentSpec(orgName, resources) {
38272
38768
  const seenIds = /* @__PURE__ */ new Set();
38273
38769
  resources.workflows?.forEach((workflow) => {
@@ -38304,6 +38800,7 @@ function validateDeploymentSpec(orgName, resources) {
38304
38800
  validateExecutionInterface(orgName, id, agent.interface, agent.contract.inputSchema);
38305
38801
  }
38306
38802
  });
38803
+ validateResourceGovernance(orgName, resources);
38307
38804
  }
38308
38805
  function validateResourceModelConfig(orgName, resourceId, modelConfig) {
38309
38806
  try {
@@ -40831,6 +41328,29 @@ function redactSecret(value) {
40831
41328
  }
40832
41329
 
40833
41330
  // ../core/src/platform/registry/serialization.ts
41331
+ function summarizeSystem(system) {
41332
+ if (!system) return void 0;
41333
+ return {
41334
+ id: system.id,
41335
+ title: system.title,
41336
+ description: system.description,
41337
+ kind: system.kind,
41338
+ status: system.status
41339
+ };
41340
+ }
41341
+ function createGovernanceMetadataResolver(resources) {
41342
+ const resourcesById = new Map((resources.organizationModel?.resources?.entries ?? []).map((r) => [r.id, r]));
41343
+ const systemsById = new Map((resources.organizationModel?.systems?.systems ?? []).map((s) => [s.id, s]));
41344
+ return (resourceId, descriptor) => {
41345
+ const resource = descriptor ?? resourcesById.get(resourceId);
41346
+ if (!resource) return {};
41347
+ return {
41348
+ systemId: resource.systemId,
41349
+ system: summarizeSystem(systemsById.get(resource.systemId)),
41350
+ governanceStatus: resource.status
41351
+ };
41352
+ };
41353
+ }
40834
41354
  function serializeAllOrganizations(registry2) {
40835
41355
  const cache = /* @__PURE__ */ new Map();
40836
41356
  for (const [orgName, resources] of Object.entries(registry2)) {
@@ -40839,6 +41359,7 @@ function serializeAllOrganizations(registry2) {
40839
41359
  return cache;
40840
41360
  }
40841
41361
  function serializeOrganization(resources) {
41362
+ const getGovernanceMetadata = createGovernanceMetadataResolver(resources);
40842
41363
  const workflowDefinitions = /* @__PURE__ */ new Map();
40843
41364
  const workflowResources = [];
40844
41365
  const commandViewWorkflows = [];
@@ -40854,7 +41375,8 @@ function serializeOrganization(resources) {
40854
41375
  type: "workflow",
40855
41376
  status: workflow.config.status,
40856
41377
  links: workflow.config.links,
40857
- category: workflow.config.category
41378
+ category: workflow.config.category,
41379
+ ...getGovernanceMetadata(resourceId, workflow.config.resource)
40858
41380
  });
40859
41381
  commandViewWorkflows.push({
40860
41382
  resourceId,
@@ -40865,6 +41387,7 @@ function serializeOrganization(resources) {
40865
41387
  status: workflow.config.status,
40866
41388
  links: workflow.config.links,
40867
41389
  category: workflow.config.category,
41390
+ ...getGovernanceMetadata(resourceId, workflow.config.resource),
40868
41391
  stepCount: Object.keys(workflow.steps).length,
40869
41392
  entryPoint: workflow.entryPoint
40870
41393
  });
@@ -40884,7 +41407,8 @@ function serializeOrganization(resources) {
40884
41407
  type: "agent",
40885
41408
  status: agent.config.status,
40886
41409
  links: agent.config.links,
40887
- category: agent.config.category
41410
+ category: agent.config.category,
41411
+ ...getGovernanceMetadata(resourceId, agent.config.resource)
40888
41412
  });
40889
41413
  commandViewAgents.push({
40890
41414
  resourceId,
@@ -40895,6 +41419,7 @@ function serializeOrganization(resources) {
40895
41419
  status: agent.config.status,
40896
41420
  links: agent.config.links,
40897
41421
  category: agent.config.category,
41422
+ ...getGovernanceMetadata(resourceId, agent.config.resource),
40898
41423
  modelProvider: agent.modelConfig.provider,
40899
41424
  modelId: agent.modelConfig.model,
40900
41425
  toolCount: agent.tools.length,
@@ -41039,6 +41564,16 @@ function filterArchived(org) {
41039
41564
  humanCheckpoints: org.humanCheckpoints?.filter((h) => !h.archived)
41040
41565
  };
41041
41566
  }
41567
+ function summarizeSystem2(system) {
41568
+ if (!system) return void 0;
41569
+ return {
41570
+ id: system.id,
41571
+ title: system.title,
41572
+ description: system.description,
41573
+ kind: system.kind,
41574
+ status: system.status
41575
+ };
41576
+ }
41042
41577
  var ResourceRegistry = class {
41043
41578
  constructor(registry2) {
41044
41579
  this.registry = registry2;
@@ -41185,6 +41720,17 @@ var ResourceRegistry = class {
41185
41720
  environment
41186
41721
  };
41187
41722
  }
41723
+ const resourcesById = new Map((orgResources.organizationModel?.resources?.entries ?? []).map((r) => [r.id, r]));
41724
+ const systemsById = new Map((orgResources.organizationModel?.systems?.systems ?? []).map((s) => [s.id, s]));
41725
+ const getGovernanceMetadata = (resourceId, descriptor) => {
41726
+ const resource = descriptor ?? resourcesById.get(resourceId);
41727
+ if (!resource) return {};
41728
+ return {
41729
+ systemId: resource.systemId,
41730
+ system: summarizeSystem2(systemsById.get(resource.systemId)),
41731
+ governanceStatus: resource.status
41732
+ };
41733
+ };
41188
41734
  const workflows = (orgResources.workflows || []).map((def) => ({
41189
41735
  resourceId: def.config.resourceId,
41190
41736
  name: def.config.name,
@@ -41194,7 +41740,8 @@ var ResourceRegistry = class {
41194
41740
  status: def.config.status,
41195
41741
  links: def.config.links,
41196
41742
  category: def.config.category,
41197
- origin: this.remoteResources.has(`${organizationName}/${def.config.resourceId}`) ? "remote" : "local"
41743
+ origin: this.remoteResources.has(`${organizationName}/${def.config.resourceId}`) ? "remote" : "local",
41744
+ ...getGovernanceMetadata(def.config.resourceId, def.config.resource)
41198
41745
  })).filter((resource) => !environment || resource.status === environment);
41199
41746
  const agents = (orgResources.agents || []).map((def) => ({
41200
41747
  resourceId: def.config.resourceId,
@@ -41206,7 +41753,8 @@ var ResourceRegistry = class {
41206
41753
  links: def.config.links,
41207
41754
  category: def.config.category,
41208
41755
  sessionCapable: def.config.sessionCapable ?? false,
41209
- origin: this.remoteResources.has(`${organizationName}/${def.config.resourceId}`) ? "remote" : "local"
41756
+ origin: this.remoteResources.has(`${organizationName}/${def.config.resourceId}`) ? "remote" : "local",
41757
+ ...getGovernanceMetadata(def.config.resourceId, def.config.resource)
41210
41758
  })).filter((resource) => !environment || resource.status === environment);
41211
41759
  return {
41212
41760
  workflows,
@@ -41669,6 +42217,15 @@ var DEFAULT_ORGANIZATION_MODEL = {
41669
42217
  color: "green",
41670
42218
  icon: "feature.finance"
41671
42219
  },
42220
+ {
42221
+ id: "business",
42222
+ label: "Business",
42223
+ description: "Revenue, client relationships, and project delivery",
42224
+ enabled: true,
42225
+ color: "blue",
42226
+ icon: "feature.business",
42227
+ uiPosition: "sidebar-primary"
42228
+ },
41672
42229
  {
41673
42230
  id: "sales",
41674
42231
  label: "Sales",
@@ -41676,7 +42233,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
41676
42233
  enabled: true,
41677
42234
  color: "blue",
41678
42235
  icon: "feature.sales",
41679
- uiPosition: "sidebar-primary"
42236
+ path: "/sales"
41680
42237
  },
41681
42238
  {
41682
42239
  id: "sales.crm",
@@ -41703,8 +42260,16 @@ var DEFAULT_ORGANIZATION_MODEL = {
41703
42260
  enabled: true,
41704
42261
  color: "orange",
41705
42262
  icon: "feature.projects",
41706
- path: "/projects",
41707
- uiPosition: "sidebar-primary"
42263
+ path: "/projects"
42264
+ },
42265
+ {
42266
+ id: "clients",
42267
+ label: "Clients",
42268
+ description: "Client relationships, accounts, and business context",
42269
+ enabled: true,
42270
+ color: "orange",
42271
+ icon: "feature.projects",
42272
+ path: "/business/clients"
41708
42273
  },
41709
42274
  {
41710
42275
  id: "operations",
@@ -41949,6 +42514,8 @@ var DEFAULT_ORGANIZATION_MODEL = {
41949
42514
  offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
41950
42515
  roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
41951
42516
  goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
42517
+ systems: DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
42518
+ resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
41952
42519
  statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
41953
42520
  operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
41954
42521
  knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
@@ -42418,7 +42985,7 @@ function wrapAction(commandName, fn) {
42418
42985
  // package.json
42419
42986
  var package_default = {
42420
42987
  name: "@elevasis/sdk",
42421
- version: "1.19.0",
42988
+ version: "1.20.1",
42422
42989
  description: "SDK for building Elevasis organization resources",
42423
42990
  type: "module",
42424
42991
  bin: {
@@ -42624,6 +43191,10 @@ function bumpVersion(current, type) {
42624
43191
  return `${major}.${minor}.${patch + 1}`;
42625
43192
  }
42626
43193
  }
43194
+ function validateResourceGovernancePreflight(orgName, org) {
43195
+ if (process.env.ELEVASIS_RESOURCE_VALIDATOR === "warn-only") return;
43196
+ validateResourceGovernance(orgName, org, org.organizationModel, { mode: "strict" });
43197
+ }
42627
43198
  function registerDeployCommand(program3) {
42628
43199
  program3.command("deploy").description(
42629
43200
  "Validate, bundle, upload, and deploy project resources\n Example: elevasis-sdk deploy --api-url http://localhost:5170"
@@ -42668,6 +43239,7 @@ function registerDeployCommand(program3) {
42668
43239
  console.error(source_default.gray(` Entry file: ${resolvePackageRelative(entryPath)}`));
42669
43240
  throw new Error("Invalid entry: no default export found");
42670
43241
  }
43242
+ validateResourceGovernancePreflight(orgName, org);
42671
43243
  new ResourceRegistry({ [orgName]: org });
42672
43244
  activeWorkflows = (org.workflows ?? []).filter((w) => !w.config.archived);
42673
43245
  activeAgents = (org.agents ?? []).filter((a) => !a.config.archived);
@@ -42866,6 +43438,7 @@ function registerCheckCommand(program3) {
42866
43438
  console.error(source_default.gray(" Expected: export default { workflows: [...], agents: [...] }"));
42867
43439
  throw new Error("Invalid entry");
42868
43440
  }
43441
+ validateResourceGovernancePreflight("_check", org);
42869
43442
  new ResourceRegistry({ _check: org });
42870
43443
  const workflowCount = org.workflows?.length ?? 0;
42871
43444
  const agentCount = org.agents?.length ?? 0;
@@ -43933,32 +44506,194 @@ function renderProjectWorkBrief(brief) {
43933
44506
  return lines.join("\n");
43934
44507
  }
43935
44508
 
43936
- // src/cli/commands/project/projects.ts
43937
- function registerProjectList(program3) {
43938
- program3.command("project:list").description("List projects\n Example: elevasis-sdk project:list --search alpha").option("--kind <kind>", "Filter by kind: client_engagement | internal | research | other").option("--status <status>", "Filter by status: active | on_track | at_risk | blocked | completed | paused").option("--search <query>", "Search by project name or description").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
44509
+ // src/cli/commands/client/client.ts
44510
+ function isUuid2(value) {
44511
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
44512
+ }
44513
+ function normalizeStr(value) {
44514
+ return value.trim().toLowerCase();
44515
+ }
44516
+ function formatClientCandidates(clients) {
44517
+ return clients.slice(0, 5).map((c) => `${c.name} (${c.id})`).join(", ");
44518
+ }
44519
+ async function resolveClient(query, apiUrlOverride) {
44520
+ const trimmedQuery = query.trim();
44521
+ if (!trimmedQuery) {
44522
+ throw new Error("Client query is required");
44523
+ }
44524
+ const apiUrl = resolveApiUrl(apiUrlOverride);
44525
+ if (isUuid2(trimmedQuery)) {
44526
+ try {
44527
+ const result2 = await apiGet(`/api/external/clients/${trimmedQuery}`, apiUrl);
44528
+ return result2;
44529
+ } catch (error46) {
44530
+ if (!(error46 instanceof Error) || !error46.message.includes("(404)")) {
44531
+ throw error46;
44532
+ }
44533
+ }
44534
+ }
44535
+ const params = new URLSearchParams({ search: trimmedQuery });
44536
+ const result = await apiGet(`/api/external/clients?${params.toString()}`, apiUrl);
44537
+ const clients = result.data;
44538
+ if (clients.length === 0) {
44539
+ throw new Error(`No client matched "${trimmedQuery}"`);
44540
+ }
44541
+ const normalizedQuery = normalizeStr(trimmedQuery);
44542
+ const exactNameMatches = clients.filter((c) => normalizeStr(c.name) === normalizedQuery);
44543
+ if (exactNameMatches.length === 1) {
44544
+ return exactNameMatches[0];
44545
+ }
44546
+ if (exactNameMatches.length > 1) {
44547
+ throw new Error(`Multiple clients matched "${trimmedQuery}": ${formatClientCandidates(exactNameMatches)}`);
44548
+ }
44549
+ if (clients.length === 1) {
44550
+ return clients[0];
44551
+ }
44552
+ const prefixMatches = clients.filter((c) => normalizeStr(c.name).startsWith(normalizedQuery));
44553
+ if (prefixMatches.length === 1) {
44554
+ return prefixMatches[0];
44555
+ }
44556
+ throw new Error(`Multiple clients matched "${trimmedQuery}": ${formatClientCandidates(clients)}`);
44557
+ }
44558
+ function printJson(value) {
44559
+ console.log(JSON.stringify(value, null, 2));
44560
+ }
44561
+ function appendQuery(params, key, value) {
44562
+ if (value === void 0 || value === null || value === "") return;
44563
+ params.set(key, String(value));
44564
+ }
44565
+ function endpointWithQuery(endpoint, params) {
44566
+ const query = params.toString();
44567
+ return query ? `${endpoint}?${query}` : endpoint;
44568
+ }
44569
+ function registerClientList(program3) {
44570
+ program3.command("client:list").description("List clients\n Example: elevasis-sdk client:list --status active").option("--status <status>", "Filter by status: active | onboarding | paused | completed | churned").option("--search <query>", "Search by client name").option("--limit <limit>", "Maximum number of clients to return").option("--offset <offset>", "Number of clients to skip").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
43939
44571
  wrapAction(
43940
- "project:list",
44572
+ "client:list",
43941
44573
  async (options) => {
43942
44574
  const apiUrl = resolveApiUrl(options.apiUrl);
43943
44575
  const params = new URLSearchParams();
43944
- if (options.kind) params.set("kind", options.kind);
43945
- if (options.status) params.set("status", options.status);
43946
- if (options.search) params.set("search", options.search);
43947
- const qs = params.toString();
43948
- const endpoint = `/api/external/projects${qs ? `?${qs}` : ""}`;
43949
- const result = await apiGet(endpoint, apiUrl);
43950
- if (options.pretty) {
43951
- const projects = result.projects;
43952
- if (projects.length === 0) {
43953
- console.log(source_default.yellow("No projects found."));
43954
- return;
43955
- }
43956
- console.log(source_default.cyan(`
43957
- Projects (${projects.length}):
44576
+ appendQuery(params, "status", options.status);
44577
+ appendQuery(params, "search", options.search);
44578
+ appendQuery(params, "limit", options.limit);
44579
+ appendQuery(params, "offset", options.offset);
44580
+ const result = await apiGet(endpointWithQuery("/api/external/clients", params), apiUrl);
44581
+ if (!options.pretty) {
44582
+ printJson(result);
44583
+ return;
44584
+ }
44585
+ if (result.data.length === 0) {
44586
+ console.log(source_default.yellow("No clients found."));
44587
+ return;
44588
+ }
44589
+ console.log(source_default.cyan(`
44590
+ Clients (${result.data.length} of ${result.total}):
43958
44591
  `));
43959
- for (const p of projects) {
43960
- console.log(` ${source_default.bold(p.name)} ${source_default.dim(p.kind)} ${source_default.gray(p.status)}`);
43961
- console.log(source_default.gray(` ID: ${p.id}`));
44592
+ for (const client of result.data) {
44593
+ console.log(` ${source_default.bold(client.name)} ${source_default.gray(client.status)}`);
44594
+ console.log(source_default.gray(` ID: ${client.id}`));
44595
+ if (client.sourceDealId) console.log(source_default.gray(` Source deal: ${client.sourceDealId}`));
44596
+ }
44597
+ console.log();
44598
+ }
44599
+ )
44600
+ );
44601
+ }
44602
+ function registerClientGet(program3) {
44603
+ program3.command("client:get <id>").description("Get a client by ID\n Example: elevasis-sdk client:get <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
44604
+ wrapAction("client:get", async (id, options) => {
44605
+ const apiUrl = resolveApiUrl(options.apiUrl);
44606
+ const result = await apiGet(`/api/external/clients/${id}`, apiUrl);
44607
+ if (!options.pretty) {
44608
+ printJson(result);
44609
+ return;
44610
+ }
44611
+ console.log(source_default.cyan(`
44612
+ Client: ${result.name}`));
44613
+ console.log(source_default.gray(` ID: ${result.id}`));
44614
+ console.log(source_default.gray(` Status: ${result.status}`));
44615
+ if (result.sourceDealId) console.log(source_default.gray(` Deal: ${result.sourceDealId}`));
44616
+ if (result.lineage) console.log(source_default.gray(" Lineage: included"));
44617
+ console.log();
44618
+ })
44619
+ );
44620
+ }
44621
+ function registerClientStatus(program3) {
44622
+ program3.command("client:status").description("Show client portfolio status").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
44623
+ wrapAction("client:status", async (options) => {
44624
+ const apiUrl = resolveApiUrl(options.apiUrl);
44625
+ const result = await apiGet("/api/external/clients/status", apiUrl);
44626
+ if (!options.pretty) {
44627
+ printJson(result);
44628
+ return;
44629
+ }
44630
+ console.log(source_default.cyan("\nClient status"));
44631
+ console.log(source_default.gray(` Total: ${result.totalClients}`));
44632
+ console.log(
44633
+ source_default.gray(
44634
+ ` Statuses: ${Object.entries(result.byStatus).map(([k, v]) => `${k}=${v}`).join(", ")}`
44635
+ )
44636
+ );
44637
+ console.log(
44638
+ source_default.gray(
44639
+ ` Links: deals=${result.linkedDeals}, projects=${result.linkedProjects}, companies=${result.linkedCompanies}, contacts=${result.linkedContacts}`
44640
+ )
44641
+ );
44642
+ console.log();
44643
+ })
44644
+ );
44645
+ }
44646
+ function registerClientResolve(program3) {
44647
+ program3.command("client:resolve <query>").description(
44648
+ 'Resolve a client ID from a name, UUID, or search query\n Example: elevasis-sdk client:resolve "Acme"'
44649
+ ).option("--api-url <url>", "API base URL").option("--pretty", "Render client details instead of only the resolved ID").action(
44650
+ wrapAction("client:resolve", async (query, options) => {
44651
+ const client = await resolveClient(query, options.apiUrl);
44652
+ if (options.pretty) {
44653
+ console.log(source_default.cyan(`
44654
+ Resolved client: ${client.name}`));
44655
+ console.log(source_default.gray(` ID: ${client.id}`));
44656
+ console.log(source_default.gray(` Status: ${client.status}`));
44657
+ console.log();
44658
+ } else {
44659
+ console.log(client.id);
44660
+ }
44661
+ })
44662
+ );
44663
+ }
44664
+
44665
+ // src/cli/commands/project/projects.ts
44666
+ function registerProjectList(program3) {
44667
+ program3.command("project:list").description("List projects\n Example: elevasis-sdk project:list --search alpha").option("--kind <kind>", "Filter by kind: client_engagement | internal | research | other").option("--status <status>", "Filter by status: active | on_track | at_risk | blocked | completed | paused").option("--search <query>", "Search by project name or description").option("--client <id-or-name>", "Filter by client hub record (UUID or fuzzy name)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
44668
+ wrapAction(
44669
+ "project:list",
44670
+ async (options) => {
44671
+ const apiUrl = resolveApiUrl(options.apiUrl);
44672
+ let clientId;
44673
+ if (options.client) {
44674
+ const resolved = await resolveClient(options.client, options.apiUrl);
44675
+ clientId = resolved.id;
44676
+ }
44677
+ const params = new URLSearchParams();
44678
+ if (options.kind) params.set("kind", options.kind);
44679
+ if (options.status) params.set("status", options.status);
44680
+ if (options.search) params.set("search", options.search);
44681
+ if (clientId) params.set("client_id", clientId);
44682
+ const qs = params.toString();
44683
+ const endpoint = `/api/external/projects${qs ? `?${qs}` : ""}`;
44684
+ const result = await apiGet(endpoint, apiUrl);
44685
+ if (options.pretty) {
44686
+ const projects = result.projects;
44687
+ if (projects.length === 0) {
44688
+ console.log(source_default.yellow("No projects found."));
44689
+ return;
44690
+ }
44691
+ console.log(source_default.cyan(`
44692
+ Projects (${projects.length}):
44693
+ `));
44694
+ for (const p of projects) {
44695
+ console.log(` ${source_default.bold(p.name)} ${source_default.dim(p.kind)} ${source_default.gray(p.status)}`);
44696
+ console.log(source_default.gray(` ID: ${p.id}`));
43962
44697
  if (p.description) console.log(source_default.gray(` ${p.description}`));
43963
44698
  }
43964
44699
  console.log();
@@ -44032,11 +44767,16 @@ Project: ${p.name}`));
44032
44767
  );
44033
44768
  }
44034
44769
  function registerProjectCreate(program3) {
44035
- program3.command("project:create").description('Create a new project\n Example: elevasis-sdk project:create --name "My Project" --kind internal').requiredOption("--name <name>", "Project name").requiredOption("--kind <kind>", "Project kind: client_engagement | internal | research | other").option("--status <status>", "Project status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "Project description").option("--deal-id <uuid>", "Link to a deal (UUID)").option("--client-company-id <uuid>", "Link to a client company (UUID)").option("--start-date <date>", "Start date (ISO 8601, e.g. 2026-06-01)").option("--target-end-date <date>", "Target end date (ISO 8601, e.g. 2026-12-31)").option("--contract-value <amount>", "Contract value (number)", parseFloat).option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
44770
+ program3.command("project:create").description('Create a new project\n Example: elevasis-sdk project:create --name "My Project" --kind internal').requiredOption("--name <name>", "Project name").requiredOption("--kind <kind>", "Project kind: client_engagement | internal | research | other").option("--status <status>", "Project status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "Project description").option("--deal-id <uuid>", "Link to a deal (UUID)").option("--client <id-or-name>", "Link to a client hub record (UUID or fuzzy name)").option("--client-company-id <uuid>", "Link to a client company (UUID)").option("--start-date <date>", "Start date (ISO 8601, e.g. 2026-06-01)").option("--target-end-date <date>", "Target end date (ISO 8601, e.g. 2026-12-31)").option("--contract-value <amount>", "Contract value (number)", parseFloat).option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
44036
44771
  wrapAction(
44037
44772
  "project:create",
44038
44773
  async (options) => {
44039
44774
  const apiUrl = resolveApiUrl(options.apiUrl);
44775
+ let clientId;
44776
+ if (options.client) {
44777
+ const resolved = await resolveClient(options.client, options.apiUrl);
44778
+ clientId = resolved.id;
44779
+ }
44040
44780
  const body = {
44041
44781
  name: options.name,
44042
44782
  kind: options.kind
@@ -44044,6 +44784,7 @@ function registerProjectCreate(program3) {
44044
44784
  if (options.status) body.status = options.status;
44045
44785
  if (options.description) body.description = options.description;
44046
44786
  if (options.dealId) body.deal_id = options.dealId;
44787
+ if (clientId) body.client_id = clientId;
44047
44788
  if (options.clientCompanyId) body.client_company_id = options.clientCompanyId;
44048
44789
  if (options.startDate) body.start_date = options.startDate;
44049
44790
  if (options.targetEndDate) body.target_end_date = options.targetEndDate;
@@ -44066,15 +44807,32 @@ Project created: ${p.name}`));
44066
44807
  );
44067
44808
  }
44068
44809
  function registerProjectUpdate(program3) {
44069
- program3.command("project:update <id>").description("Update a project\n Example: elevasis-sdk project:update <uuid> --status completed").option("--name <name>", "New project name").option("--status <status>", "New status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "New description").option("--deal-id <uuid>", "Link to a deal (UUID)").option("--client-company-id <uuid>", "Link to a client company (UUID)").option("--start-date <date>", "Start date (ISO 8601, e.g. 2026-06-01)").option("--target-end-date <date>", "Target end date (ISO 8601, e.g. 2026-12-31)").option("--actual-end-date <date>", "Actual end date (ISO 8601)").option("--contract-value <amount>", "Contract value (number)", parseFloat).option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
44810
+ program3.command("project:update <id>").description("Update a project\n Example: elevasis-sdk project:update <uuid> --status completed").option("--name <name>", "New project name").option("--status <status>", "New status: active | on_track | at_risk | blocked | completed | paused").option("--description <description>", "New description").option("--deal-id <uuid>", "Link to a deal (UUID)").option("--client <id-or-name>", "Link to a client hub record (UUID or fuzzy name)").option("--clear-client", "Remove the client hub link (sets client_id to null)").option("--client-company-id <uuid>", "Link to a client company (UUID)").option("--start-date <date>", "Start date (ISO 8601, e.g. 2026-06-01)").option("--target-end-date <date>", "Target end date (ISO 8601, e.g. 2026-12-31)").option("--actual-end-date <date>", "Actual end date (ISO 8601)").option("--contract-value <amount>", "Contract value (number)", parseFloat).option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
44070
44811
  wrapAction(
44071
44812
  "project:update",
44072
44813
  async (id, options) => {
44814
+ if (options.client && options.clearClient) {
44815
+ process.stderr.write(
44816
+ JSON.stringify({
44817
+ error: "--client and --clear-client are mutually exclusive",
44818
+ code: "CONFLICTING_FLAGS"
44819
+ }) + "\n"
44820
+ );
44821
+ process.exit(1);
44822
+ }
44823
+ let clientId;
44824
+ if (options.clearClient) {
44825
+ clientId = null;
44826
+ } else if (options.client) {
44827
+ const resolved = await resolveClient(options.client, options.apiUrl);
44828
+ clientId = resolved.id;
44829
+ }
44073
44830
  const body = {};
44074
44831
  if (options.name !== void 0) body.name = options.name;
44075
44832
  if (options.status !== void 0) body.status = options.status;
44076
44833
  if (options.description !== void 0) body.description = options.description;
44077
44834
  if (options.dealId !== void 0) body.deal_id = options.dealId;
44835
+ if (clientId !== void 0) body.client_id = clientId;
44078
44836
  if (options.clientCompanyId !== void 0) body.client_company_id = options.clientCompanyId;
44079
44837
  if (options.startDate !== void 0) body.start_date = options.startDate;
44080
44838
  if (options.targetEndDate !== void 0) body.target_end_date = options.targetEndDate;
@@ -44084,7 +44842,7 @@ function registerProjectUpdate(program3) {
44084
44842
  if (Object.keys(body).length === 0) {
44085
44843
  process.stderr.write(
44086
44844
  JSON.stringify({
44087
- error: "At least one field must be provided (--name, --status, --description, --deal-id, --client-company-id, --start-date, --target-end-date, --actual-end-date, --contract-value, --metadata)",
44845
+ error: "At least one field must be provided (--name, --status, --description, --deal-id, --client, --clear-client, --client-company-id, --start-date, --target-end-date, --actual-end-date, --contract-value, --metadata)",
44088
44846
  code: "MISSING_FIELDS"
44089
44847
  }) + "\n"
44090
44848
  );
@@ -44559,6 +45317,7 @@ var CreateProjectRequestSchema = external_exports.object({
44559
45317
  status: ProjectStatusSchema.optional(),
44560
45318
  description: external_exports.string().nullable().optional(),
44561
45319
  deal_id: UuidSchema.nullable().optional(),
45320
+ client_id: UuidSchema.nullable().optional(),
44562
45321
  client_company_id: UuidSchema.nullable().optional(),
44563
45322
  start_date: external_exports.string().nullable().optional(),
44564
45323
  target_end_date: external_exports.string().nullable().optional(),
@@ -44571,6 +45330,7 @@ var UpdateProjectRequestSchema = external_exports.object({
44571
45330
  status: ProjectStatusSchema.optional(),
44572
45331
  description: external_exports.string().nullable().optional(),
44573
45332
  deal_id: UuidSchema.nullable().optional(),
45333
+ client_id: UuidSchema.nullable().optional(),
44574
45334
  client_company_id: UuidSchema.nullable().optional(),
44575
45335
  start_date: external_exports.string().nullable().optional(),
44576
45336
  target_end_date: external_exports.string().nullable().optional(),
@@ -44581,9 +45341,24 @@ var UpdateProjectRequestSchema = external_exports.object({
44581
45341
  var GetProjectsQuerySchema = external_exports.object({
44582
45342
  kind: ProjectKindSchema.optional(),
44583
45343
  status: ProjectStatusSchema.optional(),
44584
- search: external_exports.string().trim().min(1).max(255).optional()
45344
+ search: external_exports.string().trim().min(1).max(255).optional(),
45345
+ client_id: UuidSchema.optional()
44585
45346
  }).strict();
44586
45347
  var ProjectIdParamsSchema = external_exports.object({ id: UuidSchema });
45348
+ var ProjectSourceDealRefSchema = external_exports.object({
45349
+ id: external_exports.string(),
45350
+ clientId: external_exports.string().nullable().optional(),
45351
+ contactEmail: external_exports.string(),
45352
+ stageKey: external_exports.string().nullable(),
45353
+ stateKey: external_exports.string().nullable(),
45354
+ sourceListId: external_exports.string().nullable(),
45355
+ updatedAt: external_exports.string()
45356
+ });
45357
+ var ProjectClientRefSchema = external_exports.object({
45358
+ id: external_exports.string(),
45359
+ name: external_exports.string(),
45360
+ status: external_exports.string()
45361
+ });
44587
45362
  var CreateMilestoneRequestSchema = external_exports.object({
44588
45363
  name: external_exports.string().trim().min(1).max(255),
44589
45364
  status: MilestoneStatusSchema.optional(),
@@ -45245,6 +46020,132 @@ function optionalStringArray(frontmatter, key, filePath) {
45245
46020
  }
45246
46021
  return value.map((entry) => entry.trim()).filter(Boolean);
45247
46022
  }
46023
+ var ROUTING_STOPWORDS = /* @__PURE__ */ new Set([
46024
+ "about",
46025
+ "after",
46026
+ "again",
46027
+ "against",
46028
+ "all",
46029
+ "also",
46030
+ "and",
46031
+ "any",
46032
+ "are",
46033
+ "before",
46034
+ "but",
46035
+ "can",
46036
+ "cannot",
46037
+ "could",
46038
+ "for",
46039
+ "from",
46040
+ "has",
46041
+ "have",
46042
+ "how",
46043
+ "into",
46044
+ "its",
46045
+ "may",
46046
+ "more",
46047
+ "must",
46048
+ "not",
46049
+ "now",
46050
+ "off",
46051
+ "one",
46052
+ "only",
46053
+ "our",
46054
+ "out",
46055
+ "over",
46056
+ "per",
46057
+ "run",
46058
+ "same",
46059
+ "should",
46060
+ "than",
46061
+ "that",
46062
+ "the",
46063
+ "their",
46064
+ "then",
46065
+ "there",
46066
+ "this",
46067
+ "through",
46068
+ "use",
46069
+ "uses",
46070
+ "using",
46071
+ "when",
46072
+ "where",
46073
+ "with",
46074
+ "workflow",
46075
+ "workflows",
46076
+ "would",
46077
+ "you",
46078
+ "your"
46079
+ ]);
46080
+ function toRegistryPath(path3) {
46081
+ return path3.replace(/\\/g, "/");
46082
+ }
46083
+ function slugify(value) {
46084
+ return value.trim().toLowerCase().replace(/['"]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
46085
+ }
46086
+ function toTitle(value) {
46087
+ return value.split(/[-:\s]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
46088
+ }
46089
+ function tokenizeRoutingText(...values) {
46090
+ return values.join(" ").toLowerCase().replace(/```[\s\S]*?```/g, " ").replace(/[\\/]/g, " ").match(/[a-z0-9]+(?:[.-][a-z0-9]+)*/g)?.flatMap((token) => {
46091
+ const expanded = token.includes(".") ? [token, ...token.split(".")] : [token];
46092
+ return expanded.flatMap((entry) => entry.includes("-") ? [entry, ...entry.split("-")] : [entry]);
46093
+ }) ?? [];
46094
+ }
46095
+ function rankedTerms(values, limit) {
46096
+ const counts = /* @__PURE__ */ new Map();
46097
+ for (const value of values) {
46098
+ const token = slugify(value);
46099
+ if (!token || ROUTING_STOPWORDS.has(token)) continue;
46100
+ if (token.length < 3 && token !== "ai") continue;
46101
+ counts.set(token, (counts.get(token) ?? 0) + 1);
46102
+ }
46103
+ return [...counts.entries()].sort(([termA, countA], [termB, countB]) => countB - countA || termA.localeCompare(termB)).slice(0, limit).map(([term]) => term);
46104
+ }
46105
+ function uniqueSorted(values) {
46106
+ return [...new Set(values.filter(Boolean))].sort((a, b) => a.localeCompare(b));
46107
+ }
46108
+ function nodeRoutingTerms(node, sourcePath, limit) {
46109
+ return rankedTerms(
46110
+ tokenizeRoutingText(
46111
+ node.id,
46112
+ node.kind,
46113
+ node.title,
46114
+ node.summary,
46115
+ node.body,
46116
+ node.domain ?? "",
46117
+ sourcePath,
46118
+ ...node.links.map((link) => link.nodeId),
46119
+ ...node.skills
46120
+ ),
46121
+ limit
46122
+ );
46123
+ }
46124
+ function nodeTags(node, sourcePath) {
46125
+ return uniqueSorted([
46126
+ ...node.domain ? [node.domain] : [],
46127
+ node.kind,
46128
+ ...tokenizeRoutingText(
46129
+ node.title,
46130
+ node.summary,
46131
+ sourcePath,
46132
+ ...node.links.map((link) => link.nodeId),
46133
+ ...node.skills
46134
+ ).map(slugify).filter((term) => term && !ROUTING_STOPWORDS.has(term) && (term.length >= 3 || term === "ai")).slice(0, 20)
46135
+ ]);
46136
+ }
46137
+ function readCommandForNode(node, cliCommand = "elevasis") {
46138
+ return [
46139
+ {
46140
+ command: `pnpm exec ${cliCommand} knowledge:cat ${node.id}`,
46141
+ description: `Read ${node.title}`
46142
+ },
46143
+ {
46144
+ command: `pnpm exec ${cliCommand} knowledge:ls /by-kind/${node.kind}`,
46145
+ description: `List ${node.kind} knowledge nodes`
46146
+ }
46147
+ ];
46148
+ }
45248
46149
  function readKnowledgeNodeMdx(filePath) {
45249
46150
  const raw = (0, import_node_fs2.readFileSync)(filePath, "utf8");
45250
46151
  const { frontmatter, body } = parseFrontmatter(raw, filePath);
@@ -45285,6 +46186,79 @@ function generateGraphSkillsRegistry(nodes) {
45285
46186
  domains: Object.fromEntries(Object.entries(domains).sort(([a], [b]) => a.localeCompare(b)))
45286
46187
  };
45287
46188
  }
46189
+ function generateKnowledgeFlagRegistry(nodes, sourcePaths = {}, options = {}) {
46190
+ const routes = /* @__PURE__ */ new Map();
46191
+ for (const node of nodes) {
46192
+ const routeKey = node.domain ?? `kind-${node.kind}`;
46193
+ const flag = `--${slugify(routeKey)}`;
46194
+ const sourcePath = toRegistryPath(sourcePaths[node.id] ?? "");
46195
+ const routingTerms = nodeRoutingTerms(node, sourcePath, 24);
46196
+ const tags = nodeTags(node, sourcePath);
46197
+ const skills = uniqueSorted(node.skills);
46198
+ const cliBindings = readCommandForNode(node, options.cliCommand);
46199
+ const route = routes.get(flag) ?? {
46200
+ flag,
46201
+ label: toTitle(routeKey),
46202
+ ...node.domain ? { domain: node.domain } : { kind: node.kind },
46203
+ tags: [],
46204
+ queryTerms: [],
46205
+ skills: [],
46206
+ cliBindings: [],
46207
+ nodes: []
46208
+ };
46209
+ route.tags = uniqueSorted([...route.tags, ...tags]);
46210
+ route.queryTerms = rankedTerms([...route.queryTerms, ...routingTerms], 40);
46211
+ route.skills = uniqueSorted([...route.skills, ...skills]);
46212
+ route.cliBindings = [...route.cliBindings, ...cliBindings].filter(
46213
+ (binding, index, bindings) => bindings.findIndex((candidate) => candidate.command === binding.command) === index
46214
+ );
46215
+ route.nodes.push({
46216
+ id: node.id,
46217
+ title: node.title,
46218
+ kind: node.kind,
46219
+ ...node.domain ? { domain: node.domain } : {},
46220
+ sourcePath,
46221
+ tags,
46222
+ routingTerms,
46223
+ links: node.links.map((link) => link.nodeId),
46224
+ skills,
46225
+ cliBindings
46226
+ });
46227
+ routes.set(flag, route);
46228
+ }
46229
+ const sortedRoutes = [...routes.values()].sort((a, b) => a.flag.localeCompare(b.flag));
46230
+ const aliasCandidates = sortedRoutes.flatMap((route) => {
46231
+ const aliasTerms = uniqueSorted([
46232
+ route.flag.replace(/^--/, ""),
46233
+ route.label.toLowerCase(),
46234
+ ...route.tags.slice(0, 12),
46235
+ ...route.queryTerms.slice(0, 12)
46236
+ ]);
46237
+ return aliasTerms.map((alias) => [alias, route.flag]);
46238
+ });
46239
+ const aliasCounts = aliasCandidates.reduce((counts, [alias]) => {
46240
+ counts.set(alias, (counts.get(alias) ?? 0) + 1);
46241
+ return counts;
46242
+ }, /* @__PURE__ */ new Map());
46243
+ const aliases = Object.fromEntries(
46244
+ aliasCandidates.filter(([alias]) => aliasCounts.get(alias) === 1).sort(([aliasA], [aliasB]) => aliasA.localeCompare(aliasB))
46245
+ );
46246
+ return {
46247
+ generatedBy: "generate-knowledge-nodes",
46248
+ routingMode: "deterministic-keyword",
46249
+ flags: Object.fromEntries(
46250
+ sortedRoutes.map((route) => [
46251
+ route.flag,
46252
+ {
46253
+ ...route,
46254
+ cliBindings: route.cliBindings.sort((a, b) => a.command.localeCompare(b.command)),
46255
+ nodes: route.nodes.sort((a, b) => a.id.localeCompare(b.id))
46256
+ }
46257
+ ])
46258
+ ),
46259
+ aliases
46260
+ };
46261
+ }
45288
46262
  function generateKnowledgeNodesTs(options) {
45289
46263
  const exportedName = options.exportedName ?? "mdxKnowledgeNodes";
45290
46264
  const typeImport = options.typeImportPath ? [`import type { OrgKnowledgeNode } from '${options.typeImportPath}'`, ""] : [];
@@ -45304,6 +46278,9 @@ function generateKnowledgeNodes(options) {
45304
46278
  (a, b) => (0, import_node_path2.relative)(options.sourceDir, a).localeCompare((0, import_node_path2.relative)(options.sourceDir, b))
45305
46279
  );
45306
46280
  const nodes = files.map(readKnowledgeNodeMdx);
46281
+ const sourcePaths = Object.fromEntries(
46282
+ files.map((file2, index) => [nodes[index].id, toRegistryPath((0, import_node_path2.relative)(options.sourceDir, file2))])
46283
+ );
45307
46284
  const ids = /* @__PURE__ */ new Set();
45308
46285
  for (const node of nodes) {
45309
46286
  if (ids.has(node.id)) throw new Error(`[knowledge-node-codegen] Duplicate knowledge node id: ${node.id}`);
@@ -45325,6 +46302,21 @@ function generateKnowledgeNodes(options) {
45325
46302
  (0, import_node_fs2.writeFileSync)(
45326
46303
  options.graphSkillsOutputPath,
45327
46304
  `${JSON.stringify(generateGraphSkillsRegistry(nodes), null, 2)}
46305
+ `,
46306
+ "utf8"
46307
+ );
46308
+ }
46309
+ if (options.knowledgeFlagsOutputPath) {
46310
+ (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(options.knowledgeFlagsOutputPath), { recursive: true });
46311
+ (0, import_node_fs2.writeFileSync)(
46312
+ options.knowledgeFlagsOutputPath,
46313
+ `${JSON.stringify(
46314
+ generateKnowledgeFlagRegistry(nodes, sourcePaths, {
46315
+ cliCommand: options.knowledgeFlagsCliCommand ?? "elevasis-sdk"
46316
+ }),
46317
+ null,
46318
+ 2
46319
+ )}
45328
46320
  `,
45329
46321
  "utf8"
45330
46322
  );
@@ -45336,7 +46328,19 @@ function generateKnowledgeNodes(options) {
45336
46328
  function registerKnowledgeGenerate(program3) {
45337
46329
  program3.command("knowledge:generate").description(
45338
46330
  "Generate OrganizationModel knowledge nodes from MDX source files\n Example: elevasis-sdk knowledge:generate"
45339
- ).option("--source <path>", "MDX source directory relative to project root", "core/config/knowledge/nodes").option("--output <path>", "Generated TS file relative to project root", "core/config/knowledge/_generated/nodes.ts").option("--skills-output <path>", "Generated graph skill registry relative to project root", ".claude/registries/graph-skills.json").action(
46331
+ ).option("--source <path>", "MDX source directory relative to project root", "core/config/knowledge/nodes").option(
46332
+ "--output <path>",
46333
+ "Generated TS file relative to project root",
46334
+ "core/config/knowledge/_generated/nodes.ts"
46335
+ ).option(
46336
+ "--skills-output <path>",
46337
+ "Generated graph skill registry relative to project root",
46338
+ ".claude/registries/graph-skills.json"
46339
+ ).option(
46340
+ "--flags-output <path>",
46341
+ "Generated knowledge flag registry relative to project root",
46342
+ ".claude/registries/knowledge-flags.json"
46343
+ ).action(
45340
46344
  wrapAction("knowledge:generate", async (options) => {
45341
46345
  const projectRoot = getProjectRoot();
45342
46346
  const sourceDir = (0, import_node_path3.resolve)(projectRoot, options.source ?? "core/config/knowledge/nodes");
@@ -45345,6 +46349,10 @@ function registerKnowledgeGenerate(program3) {
45345
46349
  projectRoot,
45346
46350
  options.skillsOutput ?? ".claude/registries/graph-skills.json"
45347
46351
  );
46352
+ const knowledgeFlagsOutputPath = (0, import_node_path3.resolve)(
46353
+ projectRoot,
46354
+ options.flagsOutput ?? ".claude/registries/knowledge-flags.json"
46355
+ );
45348
46356
  if (!(0, import_node_fs3.existsSync)(sourceDir)) {
45349
46357
  process.stderr.write(`knowledge:generate: source directory not found: ${sourceDir}
45350
46358
  `);
@@ -45355,11 +46363,14 @@ function registerKnowledgeGenerate(program3) {
45355
46363
  sourceDir,
45356
46364
  outputPath,
45357
46365
  graphSkillsOutputPath,
46366
+ knowledgeFlagsOutputPath,
45358
46367
  sourceLabel: options.source ?? "core/config/knowledge/nodes"
45359
46368
  });
45360
46369
  process.stdout.write(`Generated ${result.nodes.length} knowledge node(s): ${result.outputPath}
45361
46370
  `);
45362
46371
  process.stdout.write(`Generated graph skill registry: ${graphSkillsOutputPath}
46372
+ `);
46373
+ process.stdout.write(`Generated knowledge flag registry: ${knowledgeFlagsOutputPath}
45363
46374
  `);
45364
46375
  })
45365
46376
  );
@@ -45743,12 +46754,631 @@ function printSummary(failCount) {
45743
46754
  }
45744
46755
  }
45745
46756
 
46757
+ // src/cli/commands/cli/catalog.ts
46758
+ function buildCliCatalogFromProgram(program3, options = {}) {
46759
+ const commands = program3.commands.flatMap((command) => collectRuntimeCommands(command));
46760
+ return groupCommands(commands, "registered Commander commands", options.domain);
46761
+ }
46762
+ function groupCommands(commands, sourceRoot, domain2) {
46763
+ const filtered = domain2 ? commands.filter((command) => command.domain === domain2) : commands;
46764
+ const sorted = filtered.sort((a, b) => a.domain.localeCompare(b.domain) || a.syntax.localeCompare(b.syntax));
46765
+ const domainNames = [...new Set(sorted.map((command) => command.domain))];
46766
+ return {
46767
+ sourceRoot,
46768
+ domains: domainNames.map((name) => ({
46769
+ name,
46770
+ commands: sorted.filter((command) => command.domain === name)
46771
+ }))
46772
+ };
46773
+ }
46774
+ function collectRuntimeCommands(command, parent) {
46775
+ const commandName = command.name();
46776
+ const argSuffix = formatRuntimeArguments(command.registeredArguments);
46777
+ const syntaxSegment = argSuffix ? `${commandName} ${argSuffix}` : commandName;
46778
+ const syntax = parent ? `${parent.syntax} ${syntaxSegment}` : syntaxSegment;
46779
+ const domain2 = parent?.domain ?? domainFromCommand(commandName);
46780
+ const current = {
46781
+ command: commandName,
46782
+ syntax,
46783
+ domain: domain2
46784
+ };
46785
+ const aliases = command.aliases().map((alias) => parent ? `${parent.syntax} ${alias}` : alias);
46786
+ return [
46787
+ {
46788
+ syntax,
46789
+ command: commandName,
46790
+ domain: domain2,
46791
+ description: firstLine(command.description()),
46792
+ aliases,
46793
+ options: command.options.map((option) => ({
46794
+ flags: option.flags,
46795
+ description: option.description,
46796
+ required: option.mandatory
46797
+ })),
46798
+ source: "runtime"
46799
+ },
46800
+ ...command.commands.flatMap((child) => collectRuntimeCommands(child, current))
46801
+ ];
46802
+ }
46803
+ function formatRuntimeArguments(args) {
46804
+ return args.map((arg) => {
46805
+ const name = `${arg.name()}${arg.variadic ? "..." : ""}`;
46806
+ return arg.required ? `<${name}>` : `[${name}]`;
46807
+ }).join(" ");
46808
+ }
46809
+ function renderCliCatalogMarkdown(catalog) {
46810
+ const lines = [
46811
+ "# elevasis-sdk CLI Catalog",
46812
+ "",
46813
+ `Source: \`${catalog.sourceRoot}\``,
46814
+ ""
46815
+ ];
46816
+ if (catalog.domains.length === 0) {
46817
+ lines.push("No commands found.");
46818
+ return lines.join("\n");
46819
+ }
46820
+ for (const domain2 of catalog.domains) {
46821
+ lines.push(`## ${domain2.name}`, "");
46822
+ lines.push("| Command | Description | Aliases | Options | Source |");
46823
+ lines.push("| --- | --- | --- | --- | --- |");
46824
+ for (const command of domain2.commands) {
46825
+ const aliases = command.aliases.length > 0 ? command.aliases.map((alias) => `\`${alias}\``).join(", ") : "-";
46826
+ const options = command.options.length > 0 ? command.options.map((option) => `${option.required ? "required " : ""}\`${option.flags}\``).join("<br>") : "-";
46827
+ lines.push(
46828
+ `| \`elevasis-sdk ${command.syntax}\` | ${escapeMarkdownTable(command.description || "-")} | ${aliases} | ${options} | \`${command.source}\` |`
46829
+ );
46830
+ }
46831
+ lines.push("");
46832
+ }
46833
+ return lines.join("\n").trimEnd();
46834
+ }
46835
+ function renderCliCatalogJson(catalog) {
46836
+ return JSON.stringify(catalog, null, 2);
46837
+ }
46838
+ function domainFromCommand(command) {
46839
+ if (command.includes(":")) return command.split(":")[0];
46840
+ return "platform";
46841
+ }
46842
+ function firstLine(value) {
46843
+ return value.split("\n")[0]?.trim() ?? "";
46844
+ }
46845
+ function escapeMarkdownTable(value) {
46846
+ return value.replace(/\|/g, "\\|").replace(/\r?\n/g, "<br>");
46847
+ }
46848
+ function knownDomains(catalog) {
46849
+ return catalog.domains.map((domain2) => domain2.name);
46850
+ }
46851
+
46852
+ // src/cli/commands/cli/cli.ts
46853
+ var FORMATS = /* @__PURE__ */ new Set(["markdown", "json"]);
46854
+ function registerCliCatalogCommand(program3) {
46855
+ program3.command("cli [domain]").description("Generate a catalog of registered elevasis-sdk commands").option("--domain <domain>", "Filter to one domain, e.g. project, knowledge, platform").option("--format <format>", "Output format: markdown | json", "markdown").action(
46856
+ wrapAction("cli", async (domainArg, options) => {
46857
+ const format = options.format ?? "markdown";
46858
+ if (!FORMATS.has(format)) {
46859
+ throw new Error(`Unsupported format "${format}". Expected markdown or json.`);
46860
+ }
46861
+ const domain2 = options.domain ?? domainArg;
46862
+ const catalog = buildCliCatalogFromProgram(program3, { domain: domain2 });
46863
+ if (domain2 && catalog.domains.length === 0) {
46864
+ const fullCatalog = buildCliCatalogFromProgram(program3);
46865
+ throw new Error(`No CLI domain "${domain2}" found. Known domains: ${knownDomains(fullCatalog).join(", ")}`);
46866
+ }
46867
+ console.log(format === "json" ? renderCliCatalogJson(catalog) : renderCliCatalogMarkdown(catalog));
46868
+ })
46869
+ );
46870
+ }
46871
+
46872
+ // src/cli/commands/acquisition/deals.ts
46873
+ function appendQuery2(params, key, value) {
46874
+ if (value === void 0 || value === null || value === "") return;
46875
+ params.set(key, String(value));
46876
+ }
46877
+ function endpointWithQuery2(endpoint, params) {
46878
+ const query = params.toString();
46879
+ return query ? `${endpoint}?${query}` : endpoint;
46880
+ }
46881
+ function printJson2(value) {
46882
+ console.log(JSON.stringify(value, null, 2));
46883
+ }
46884
+ function dealEmail(deal) {
46885
+ return deal.contactEmail ?? deal.contact_email ?? "unknown contact";
46886
+ }
46887
+ function dealStage(deal) {
46888
+ return deal.stageKey ?? deal.stage_key ?? "unknown";
46889
+ }
46890
+ function dealState(deal) {
46891
+ return deal.stateKey ?? deal.state_key ?? null;
46892
+ }
46893
+ function dealListId(deal) {
46894
+ return deal.sourceListId ?? deal.source_list_id ?? null;
46895
+ }
46896
+ function registerAcquisitionDealList(program3) {
46897
+ program3.command("acquisition:deal:list").description("List acquisition deals\n Example: elevasis-sdk acquisition:deal:list --stage discovery").option("--stage <stage>", "Filter by CRM stage").option("--list <id>", "Filter by source acquisition list ID").option("--batch <batch>", "Filter by source batch ID").option("--stale-since <datetime>", "Filter to deals stale since an ISO datetime").option("--search <query>", "Search by contact, company, or deal label").option("--limit <limit>", "Maximum number of deals to return").option("--offset <offset>", "Number of deals to skip").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
46898
+ wrapAction(
46899
+ "acquisition:deal:list",
46900
+ async (options) => {
46901
+ const apiUrl = resolveApiUrl(options.apiUrl);
46902
+ const params = new URLSearchParams();
46903
+ appendQuery2(params, "stage", options.stage);
46904
+ appendQuery2(params, "list", options.list);
46905
+ appendQuery2(params, "batch", options.batch);
46906
+ appendQuery2(params, "staleSince", options.staleSince);
46907
+ appendQuery2(params, "search", options.search);
46908
+ appendQuery2(params, "limit", options.limit);
46909
+ appendQuery2(params, "offset", options.offset);
46910
+ const result = await apiGet(endpointWithQuery2("/api/external/deals", params), apiUrl);
46911
+ if (!options.pretty) {
46912
+ printJson2(result);
46913
+ return;
46914
+ }
46915
+ if (result.data.length === 0) {
46916
+ console.log(source_default.yellow("No acquisition deals found."));
46917
+ return;
46918
+ }
46919
+ console.log(source_default.cyan(`
46920
+ Acquisition deals (${result.data.length} of ${result.total}):
46921
+ `));
46922
+ for (const deal of result.data) {
46923
+ const state = dealState(deal);
46924
+ console.log(` ${source_default.bold(dealEmail(deal))} ${source_default.gray(dealStage(deal))}${state ? `/${state}` : ""}`);
46925
+ console.log(source_default.gray(` ID: ${deal.id}`));
46926
+ const listId = dealListId(deal);
46927
+ if (listId) console.log(source_default.gray(` List: ${listId}`));
46928
+ }
46929
+ console.log();
46930
+ }
46931
+ )
46932
+ );
46933
+ }
46934
+ function registerAcquisitionDealGet(program3) {
46935
+ program3.command("acquisition:deal:get <id>").description("Get an acquisition deal by ID\n Example: elevasis-sdk acquisition:deal:get <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
46936
+ wrapAction("acquisition:deal:get", async (id, options) => {
46937
+ const apiUrl = resolveApiUrl(options.apiUrl);
46938
+ const result = await apiGet("/api/external/deals/" + id, apiUrl);
46939
+ if (!options.pretty) {
46940
+ printJson2(result);
46941
+ return;
46942
+ }
46943
+ console.log(source_default.cyan(`
46944
+ Acquisition deal: ${dealEmail(result)}`));
46945
+ console.log(source_default.gray(` ID: ${result.id}`));
46946
+ console.log(source_default.gray(` Stage: ${dealStage(result)}`));
46947
+ const state = dealState(result);
46948
+ if (state) console.log(source_default.gray(` State: ${state}`));
46949
+ const listId = dealListId(result);
46950
+ if (listId) console.log(source_default.gray(` List: ${listId}`));
46951
+ if (result.lineage) console.log(source_default.gray(" Lineage: included"));
46952
+ console.log();
46953
+ })
46954
+ );
46955
+ }
46956
+ function registerAcquisitionDealStatus(program3) {
46957
+ program3.command("acquisition:deal:status").description("Show CRM funnel status for acquisition deals").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
46958
+ wrapAction("acquisition:deal:status", async (options) => {
46959
+ const apiUrl = resolveApiUrl(options.apiUrl);
46960
+ const result = await apiGet("/api/external/deals/summary", apiUrl);
46961
+ if (!options.pretty) {
46962
+ printJson2(result);
46963
+ return;
46964
+ }
46965
+ console.log(source_default.cyan("\nAcquisition deal status"));
46966
+ console.log(source_default.gray(` Total: ${result.totalDeals}`));
46967
+ console.log(source_default.gray(` Open: ${result.openDeals}`));
46968
+ console.log(source_default.gray(` Won: ${result.wonDeals}`));
46969
+ console.log(source_default.gray(` Lost: ${result.lostDeals}`));
46970
+ console.log(source_default.gray(` Win rate: ${result.winRate}`));
46971
+ if (result.stageSummary.length > 0) {
46972
+ console.log(
46973
+ source_default.gray(` Stages: ${result.stageSummary.map((stage) => `${stage.stage}=${stage.count}`).join(", ")}`)
46974
+ );
46975
+ }
46976
+ console.log();
46977
+ })
46978
+ );
46979
+ }
46980
+
46981
+ // src/cli/commands/acquisition/lists.ts
46982
+ function appendQuery3(params, key, value) {
46983
+ if (value === void 0 || value === null || value === "") return;
46984
+ params.set(key, String(value));
46985
+ }
46986
+ function endpointWithQuery3(endpoint, params) {
46987
+ const query = params.toString();
46988
+ return query ? `${endpoint}?${query}` : endpoint;
46989
+ }
46990
+ function printJson3(value) {
46991
+ console.log(JSON.stringify(value, null, 2));
46992
+ }
46993
+ function renderListSummary(list) {
46994
+ const batches = list.batchIds?.length ? `${list.batchIds.length} batch(es)` : "no batches";
46995
+ const vertical = typeof list.scrapingConfig?.vertical === "string" ? ` ${list.scrapingConfig.vertical}` : "";
46996
+ console.log(` ${source_default.bold(list.name)} ${source_default.gray(list.status ?? "unknown")}${vertical}`);
46997
+ console.log(source_default.gray(` ID: ${list.id}`));
46998
+ console.log(source_default.gray(` ${batches}`));
46999
+ if (list.description) console.log(source_default.gray(` ${list.description}`));
47000
+ }
47001
+ function registerAcquisitionListList(program3) {
47002
+ program3.command("acquisition:list:list").description("List acquisition lists\n Example: elevasis-sdk acquisition:list:list --status launched").option("--status <status>", "Filter by status: draft | enriching | launched | closing | archived").option("--batch <batch>", "Filter by batch ID").option("--vertical <vertical>", "Filter by scraping vertical").option("--limit <limit>", "Maximum number of lists to return").option("--offset <offset>", "Number of lists to skip").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47003
+ wrapAction(
47004
+ "acquisition:list:list",
47005
+ async (options) => {
47006
+ const apiUrl = resolveApiUrl(options.apiUrl);
47007
+ const params = new URLSearchParams();
47008
+ appendQuery3(params, "status", options.status);
47009
+ appendQuery3(params, "batch", options.batch);
47010
+ appendQuery3(params, "vertical", options.vertical);
47011
+ appendQuery3(params, "limit", options.limit);
47012
+ appendQuery3(params, "offset", options.offset);
47013
+ const result = await apiGet(
47014
+ endpointWithQuery3("/api/external/acquisition/lists", params),
47015
+ apiUrl
47016
+ );
47017
+ if (!options.pretty) {
47018
+ printJson3(result);
47019
+ return;
47020
+ }
47021
+ if (result.length === 0) {
47022
+ console.log(source_default.yellow("No acquisition lists found."));
47023
+ return;
47024
+ }
47025
+ console.log(source_default.cyan(`
47026
+ Acquisition lists (${result.length}):
47027
+ `));
47028
+ for (const list of result) renderListSummary(list);
47029
+ console.log();
47030
+ }
47031
+ )
47032
+ );
47033
+ }
47034
+ function registerAcquisitionListGet(program3) {
47035
+ program3.command("acquisition:list:get <id>").description("Get an acquisition list by ID\n Example: elevasis-sdk acquisition:list:get <uuid>").option("--no-include-deals", "Exclude thin deal lineage refs").option("--deal-limit <limit>", "Maximum number of thin deal refs to include").option("--include-progress", "Include processing progress aggregates").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47036
+ wrapAction(
47037
+ "acquisition:list:get",
47038
+ async (id, options) => {
47039
+ const apiUrl = resolveApiUrl(options.apiUrl);
47040
+ const params = new URLSearchParams();
47041
+ if (options.includeDeals === false) appendQuery3(params, "includeDeals", false);
47042
+ appendQuery3(params, "dealLimit", options.dealLimit);
47043
+ if (options.includeProgress) appendQuery3(params, "includeProgress", true);
47044
+ const result = await apiGet(
47045
+ endpointWithQuery3(`/api/external/acquisition/lists/${id}`, params),
47046
+ apiUrl
47047
+ );
47048
+ if (!options.pretty) {
47049
+ printJson3(result);
47050
+ return;
47051
+ }
47052
+ console.log(source_default.cyan(`
47053
+ Acquisition list: ${result.name}`));
47054
+ console.log(source_default.gray(` ID: ${result.id}`));
47055
+ console.log(source_default.gray(` Status: ${result.status ?? "unknown"}`));
47056
+ if (result.description) console.log(source_default.gray(` Summary: ${result.description}`));
47057
+ if (result.batchIds?.length) console.log(source_default.gray(` Batches: ${result.batchIds.join(", ")}`));
47058
+ if (result.lineage) console.log(source_default.gray(" Lineage: included"));
47059
+ if (result.progress) console.log(source_default.gray(" Progress: included"));
47060
+ console.log();
47061
+ }
47062
+ )
47063
+ );
47064
+ }
47065
+ function registerAcquisitionListStatus(program3) {
47066
+ program3.command("acquisition:list:status").description("Show portfolio status across acquisition lists").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47067
+ wrapAction("acquisition:list:status", async (options) => {
47068
+ const apiUrl = resolveApiUrl(options.apiUrl);
47069
+ const result = await apiGet("/api/external/acquisition/lists/status", apiUrl);
47070
+ if (!options.pretty) {
47071
+ printJson3(result);
47072
+ return;
47073
+ }
47074
+ console.log(source_default.cyan("\nAcquisition list status"));
47075
+ console.log(source_default.gray(` Lists: ${result.totalLists}`));
47076
+ console.log(source_default.gray(` Companies: ${result.totalCompanies}`));
47077
+ console.log(source_default.gray(` Contacts: ${result.totalContacts}`));
47078
+ console.log(source_default.gray(` Deals: ${result.totalDeals}`));
47079
+ const statusEntries = Object.entries(result.byStatus);
47080
+ if (statusEntries.length > 0) {
47081
+ console.log(source_default.gray(` By status: ${statusEntries.map(([key, count]) => `${key}=${count}`).join(", ")}`));
47082
+ }
47083
+ console.log();
47084
+ })
47085
+ );
47086
+ }
47087
+
47088
+ // src/cli/commands/acquisition/index.ts
47089
+ function registerAcquisitionCommands(program3) {
47090
+ registerAcquisitionListList(program3);
47091
+ registerAcquisitionListGet(program3);
47092
+ registerAcquisitionListStatus(program3);
47093
+ registerAcquisitionDealList(program3);
47094
+ registerAcquisitionDealGet(program3);
47095
+ registerAcquisitionDealStatus(program3);
47096
+ }
47097
+
47098
+ // src/cli/commands/client/client-write.ts
47099
+ function registerClientCreate(program3) {
47100
+ program3.command("client:create").description('Create a new client\n Example: elevasis-sdk client:create --name "Acme Corp"').requiredOption("--name <name>", "Client name").option("--status <status>", "Client status: active | onboarding | paused | completed | churned").option("--source-deal-id <uuid>", "UUID of the source deal").option("--primary-company-id <uuid>", "UUID of the primary company").option("--primary-contact-id <uuid>", "UUID of the primary contact").option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47101
+ wrapAction(
47102
+ "client:create",
47103
+ async (options) => {
47104
+ const apiUrl = resolveApiUrl(options.apiUrl);
47105
+ const body = { name: options.name };
47106
+ if (options.status !== void 0) body.status = options.status;
47107
+ if (options.sourceDealId !== void 0) body.sourceDealId = options.sourceDealId;
47108
+ if (options.primaryCompanyId !== void 0) body.primaryCompanyId = options.primaryCompanyId;
47109
+ if (options.primaryContactId !== void 0) body.primaryContactId = options.primaryContactId;
47110
+ if (options.metadata !== void 0) body.metadata = JSON.parse(options.metadata);
47111
+ const result = await apiPost("/api/external/clients", body, apiUrl);
47112
+ if (options.pretty) {
47113
+ console.log(source_default.green(`
47114
+ Client created: ${result.name}`));
47115
+ console.log(source_default.gray(` ID: ${result.id}`));
47116
+ console.log(source_default.gray(` Status: ${result.status}`));
47117
+ console.log();
47118
+ } else {
47119
+ console.log(JSON.stringify(result, null, 2));
47120
+ }
47121
+ }
47122
+ )
47123
+ );
47124
+ }
47125
+ function registerClientUpdate(program3) {
47126
+ program3.command("client:update <id>").description("Update a client\n Example: elevasis-sdk client:update <uuid> --status active").option("--name <name>", "New client name").option("--status <status>", "New status: active | onboarding | paused | completed | churned").option("--source-deal-id <uuid>", "Set source deal (UUID)").option("--clear-source-deal", "Remove the source deal link (sets sourceDealId to null)").option("--primary-company-id <uuid>", "Set primary company (UUID)").option("--clear-primary-company", "Remove the primary company link (sets primaryCompanyId to null)").option("--primary-contact-id <uuid>", "Set primary contact (UUID)").option("--clear-primary-contact", "Remove the primary contact link (sets primaryContactId to null)").option("--metadata <json>", "Arbitrary metadata (JSON string)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47127
+ wrapAction(
47128
+ "client:update",
47129
+ async (id, options) => {
47130
+ if (options.sourceDealId && options.clearSourceDeal) {
47131
+ process.stderr.write(
47132
+ JSON.stringify({
47133
+ error: "--source-deal-id and --clear-source-deal are mutually exclusive",
47134
+ code: "CONFLICTING_FLAGS"
47135
+ }) + "\n"
47136
+ );
47137
+ process.exit(1);
47138
+ }
47139
+ if (options.primaryCompanyId && options.clearPrimaryCompany) {
47140
+ process.stderr.write(
47141
+ JSON.stringify({
47142
+ error: "--primary-company-id and --clear-primary-company are mutually exclusive",
47143
+ code: "CONFLICTING_FLAGS"
47144
+ }) + "\n"
47145
+ );
47146
+ process.exit(1);
47147
+ }
47148
+ if (options.primaryContactId && options.clearPrimaryContact) {
47149
+ process.stderr.write(
47150
+ JSON.stringify({
47151
+ error: "--primary-contact-id and --clear-primary-contact are mutually exclusive",
47152
+ code: "CONFLICTING_FLAGS"
47153
+ }) + "\n"
47154
+ );
47155
+ process.exit(1);
47156
+ }
47157
+ const client = await resolveClient(id, options.apiUrl);
47158
+ const body = {};
47159
+ if (options.name !== void 0) body.name = options.name;
47160
+ if (options.status !== void 0) body.status = options.status;
47161
+ if (options.clearSourceDeal) {
47162
+ body.sourceDealId = null;
47163
+ } else if (options.sourceDealId !== void 0) {
47164
+ body.sourceDealId = options.sourceDealId;
47165
+ }
47166
+ if (options.clearPrimaryCompany) {
47167
+ body.primaryCompanyId = null;
47168
+ } else if (options.primaryCompanyId !== void 0) {
47169
+ body.primaryCompanyId = options.primaryCompanyId;
47170
+ }
47171
+ if (options.clearPrimaryContact) {
47172
+ body.primaryContactId = null;
47173
+ } else if (options.primaryContactId !== void 0) {
47174
+ body.primaryContactId = options.primaryContactId;
47175
+ }
47176
+ if (options.metadata !== void 0) body.metadata = JSON.parse(options.metadata);
47177
+ if (Object.keys(body).length === 0) {
47178
+ process.stderr.write(
47179
+ JSON.stringify({
47180
+ error: "At least one field must be provided (--name, --status, --source-deal-id, --clear-source-deal, --primary-company-id, --clear-primary-company, --primary-contact-id, --clear-primary-contact, --metadata)",
47181
+ code: "MISSING_FIELDS"
47182
+ }) + "\n"
47183
+ );
47184
+ process.exit(1);
47185
+ }
47186
+ const apiUrl = resolveApiUrl(options.apiUrl);
47187
+ const result = await apiPatch(`/api/external/clients/${client.id}`, body, apiUrl);
47188
+ if (options.pretty) {
47189
+ console.log(source_default.green(`
47190
+ Client updated: ${result.name}`));
47191
+ console.log(source_default.gray(` ID: ${result.id}`));
47192
+ console.log(source_default.gray(` Status: ${result.status}`));
47193
+ console.log();
47194
+ } else {
47195
+ console.log(JSON.stringify(result, null, 2));
47196
+ }
47197
+ }
47198
+ )
47199
+ );
47200
+ }
47201
+ function registerClientDelete(program3) {
47202
+ program3.command("client:delete <id>").description("Delete a client\n Example: elevasis-sdk client:delete <uuid>").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
47203
+ wrapAction("client:delete", async (id, options) => {
47204
+ const client = await resolveClient(id, options.apiUrl);
47205
+ const apiUrl = resolveApiUrl(options.apiUrl);
47206
+ await apiDelete(`/api/external/clients/${client.id}`, apiUrl);
47207
+ if (options.pretty) {
47208
+ console.log(source_default.green(`
47209
+ Client ${client.id} deleted.`));
47210
+ console.log();
47211
+ } else {
47212
+ console.log(JSON.stringify({ success: true, id: client.id }, null, 2));
47213
+ }
47214
+ })
47215
+ );
47216
+ }
47217
+
47218
+ // src/cli/commands/client/index.ts
47219
+ function registerClientCommands(program3) {
47220
+ registerClientList(program3);
47221
+ registerClientGet(program3);
47222
+ registerClientStatus(program3);
47223
+ registerClientResolve(program3);
47224
+ registerClientCreate(program3);
47225
+ registerClientUpdate(program3);
47226
+ registerClientDelete(program3);
47227
+ }
47228
+
47229
+ // src/cli/commands/agent/agent.ts
47230
+ function printJson4(value) {
47231
+ console.log(JSON.stringify(value, null, 2));
47232
+ }
47233
+ function registerAgentList(program3) {
47234
+ program3.command("agent:list").description("List deployed agents for your organization").option("--api-url <url>", "API base URL").option("--json", "Output as JSON").action(
47235
+ wrapAction("agent:list", async (options) => {
47236
+ const apiUrl = resolveApiUrl(options.apiUrl);
47237
+ const result = await apiGet("/api/external/resources", apiUrl);
47238
+ const agents = result.resources.filter((resource) => resource.resourceType === "agent");
47239
+ if (options.json) {
47240
+ printJson4({ agents, total: agents.length });
47241
+ return;
47242
+ }
47243
+ if (agents.length === 0) {
47244
+ console.log(source_default.yellow("No deployed agents found."));
47245
+ return;
47246
+ }
47247
+ console.log(source_default.magenta(`Agents (${agents.length}):`));
47248
+ for (const agent of agents) {
47249
+ console.log(source_default.white(` ${source_default.bold(agent.resourceId)}`));
47250
+ if (agent.name) console.log(source_default.gray(` Name: ${agent.name}`));
47251
+ if (agent.description) console.log(source_default.gray(` Description: ${agent.description}`));
47252
+ if (agent.agentKind) console.log(source_default.gray(` Kind: ${agent.agentKind}`));
47253
+ if (agent.systemId) console.log(source_default.gray(` System: ${agent.systemId}`));
47254
+ if (agent.actsAsRoleId) console.log(source_default.gray(` Acts as role: ${agent.actsAsRoleId}`));
47255
+ console.log(source_default.gray(` Session capable: ${agent.sessionCapable ? "yes" : "no"}`));
47256
+ if (agent.status) console.log(source_default.gray(` Status: ${agent.status}`));
47257
+ console.log();
47258
+ }
47259
+ })
47260
+ );
47261
+ }
47262
+ function registerAgentGet(program3) {
47263
+ program3.command("agent:get <id>").description("Get full agent metadata and organization model linkage").option("--api-url <url>", "API base URL").option("--json", "Output as JSON").action(
47264
+ wrapAction("agent:get", async (id, options) => {
47265
+ const apiUrl = resolveApiUrl(options.apiUrl);
47266
+ const definition = await apiGet(`/api/external/resources/${id}/definition`, apiUrl);
47267
+ if (options.json) {
47268
+ printJson4(definition);
47269
+ return;
47270
+ }
47271
+ console.log(source_default.magenta(`Agent: ${definition.name ?? definition.resourceId ?? id}`));
47272
+ console.log(source_default.gray(` ID: ${definition.resourceId ?? id}`));
47273
+ console.log(source_default.gray(` Type: ${definition.type ?? "agent"}`));
47274
+ if (definition.description) console.log(source_default.gray(` Description: ${definition.description}`));
47275
+ if (definition.agentKind) console.log(source_default.gray(` Kind: ${definition.agentKind}`));
47276
+ if (definition.systemId) console.log(source_default.gray(` System: ${definition.systemId}`));
47277
+ if (definition.actsAsRoleId) console.log(source_default.gray(` Acts as role: ${definition.actsAsRoleId}`));
47278
+ console.log(source_default.gray(` Session capable: ${definition.sessionCapable ? "yes" : "no"}`));
47279
+ if (definition.status) console.log(source_default.gray(` Status: ${definition.status}`));
47280
+ })
47281
+ );
47282
+ }
47283
+
47284
+ // src/cli/commands/agent/index.ts
47285
+ function registerAgentCommands(program3) {
47286
+ registerAgentList(program3);
47287
+ registerAgentGet(program3);
47288
+ }
47289
+
47290
+ // src/cli/commands/session/session.ts
47291
+ function printJson5(value) {
47292
+ console.log(JSON.stringify(value, null, 2));
47293
+ }
47294
+ function appendQuery4(params, key, value) {
47295
+ if (value === void 0 || value === null || value === "") return;
47296
+ params.set(key, String(value));
47297
+ }
47298
+ function endpointWithQuery4(endpoint, params) {
47299
+ const query = params.toString();
47300
+ return query ? `${endpoint}?${query}` : endpoint;
47301
+ }
47302
+ function registerSessionList(program3) {
47303
+ program3.command("session:list").description("List active multi-turn agent sessions").option("--resource-id <id>", "Filter by agent resource ID").option("--user-id <id>", "Filter by user ID").option("--limit <limit>", "Maximum number of sessions to return").option("--api-url <url>", "API base URL").option("--json", "Output as JSON").action(
47304
+ wrapAction("session:list", async (options) => {
47305
+ const apiUrl = resolveApiUrl(options.apiUrl);
47306
+ const params = new URLSearchParams();
47307
+ appendQuery4(params, "resourceId", options.resourceId);
47308
+ appendQuery4(params, "userId", options.userId);
47309
+ appendQuery4(params, "limit", options.limit);
47310
+ const result = await apiGet(endpointWithQuery4("/api/external/sessions", params), apiUrl);
47311
+ if (options.json) {
47312
+ printJson5(result);
47313
+ return;
47314
+ }
47315
+ const activeSessions = result.sessions.filter((session) => !session.isEnded);
47316
+ if (activeSessions.length === 0) {
47317
+ console.log(source_default.yellow("No active sessions found."));
47318
+ return;
47319
+ }
47320
+ console.log(source_default.cyan(`Sessions (${activeSessions.length} active of ${result.total}):`));
47321
+ for (const session of activeSessions) {
47322
+ console.log(source_default.white(` ${source_default.bold(session.sessionId)}`));
47323
+ if (session.title) console.log(source_default.gray(` Title: ${session.title}`));
47324
+ console.log(source_default.gray(` Agent: ${session.resourceId}`));
47325
+ console.log(source_default.gray(` Turns: ${session.turnCount}`));
47326
+ console.log(source_default.gray(` Updated: ${new Date(session.updatedAt).toLocaleString()}`));
47327
+ console.log();
47328
+ }
47329
+ })
47330
+ );
47331
+ }
47332
+ function registerSessionGet(program3) {
47333
+ program3.command("session:get <id>").description("Get session details and transcript").option("--api-url <url>", "API base URL").option("--json", "Output as JSON").action(
47334
+ wrapAction("session:get", async (id, options) => {
47335
+ const apiUrl = resolveApiUrl(options.apiUrl);
47336
+ const session = await apiGet(`/api/external/sessions/${id}`, apiUrl);
47337
+ if (options.json) {
47338
+ printJson5(session);
47339
+ return;
47340
+ }
47341
+ console.log(source_default.cyan(`Session: ${session.title ?? session.sessionId}`));
47342
+ console.log(source_default.gray(` ID: ${session.sessionId}`));
47343
+ console.log(source_default.gray(` Agent: ${session.resourceId}`));
47344
+ console.log(source_default.gray(` Status: ${session.isEnded ? "ended" : "active"}`));
47345
+ console.log(source_default.gray(` Turns: ${session.turnCount}`));
47346
+ console.log(source_default.gray(` Created: ${new Date(session.createdAt).toLocaleString()}`));
47347
+ console.log(source_default.gray(` Updated: ${new Date(session.updatedAt).toLocaleString()}`));
47348
+ if (session.endedAt) console.log(source_default.gray(` Ended: ${new Date(session.endedAt).toLocaleString()}`));
47349
+ if (session.messages) console.log(source_default.gray(` Transcript messages: ${session.messages.length}`));
47350
+ })
47351
+ );
47352
+ }
47353
+ function registerSessionEnd(program3) {
47354
+ program3.command("session:end <id>").description("Terminate an active agent session").option("--api-url <url>", "API base URL").option("--json", "Output as JSON").action(
47355
+ wrapAction("session:end", async (id, options) => {
47356
+ const apiUrl = resolveApiUrl(options.apiUrl);
47357
+ const result = await apiDelete(`/api/external/sessions/${id}`, apiUrl);
47358
+ if (options.json) {
47359
+ printJson5(result);
47360
+ return;
47361
+ }
47362
+ console.log(source_default.green(`Ended session ${result.sessionId ?? id}.`));
47363
+ })
47364
+ );
47365
+ }
47366
+
47367
+ // src/cli/commands/session/index.ts
47368
+ function registerSessionCommands(program3) {
47369
+ registerSessionList(program3);
47370
+ registerSessionGet(program3);
47371
+ registerSessionEnd(program3);
47372
+ }
47373
+
45746
47374
  // src/cli/index.ts
45747
47375
  var PREFLIGHT_SKIP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h", "--version", "-V"]);
47376
+ var PREFLIGHT_SKIP_COMMANDS = /* @__PURE__ */ new Set(["cli"]);
45748
47377
  var LOCAL_PROJECT_COMMANDS = /* @__PURE__ */ new Set(["ui:use-local", "ui:use-published", "knowledge:generate"]);
45749
47378
  function shouldSkipPreflight() {
45750
47379
  const args = process.argv.slice(2);
45751
47380
  if (args.length === 0) return true;
47381
+ if (PREFLIGHT_SKIP_COMMANDS.has(args[0] ?? "")) return true;
45752
47382
  return args.every((a) => PREFLIGHT_SKIP_FLAGS.has(a));
45753
47383
  }
45754
47384
  function isLocalProjectCommand() {
@@ -45807,6 +47437,16 @@ Commands:
45807
47437
  elevasis-sdk project:list [--search <query>] List projects with optional search
45808
47438
  elevasis-sdk project:resolve <query> Resolve a project ID from a name or UUID
45809
47439
  elevasis-sdk project:work <query> Open a lifecycle-aware project work brief
47440
+ elevasis-sdk client:list [--search <query>] List clients with optional search
47441
+ elevasis-sdk client:get <id> Get client detail and lineage
47442
+ elevasis-sdk client:status Show client portfolio status
47443
+ elevasis-sdk agent:list List deployed agents
47444
+ elevasis-sdk agent:get <id> Get agent metadata and OM linkage
47445
+ elevasis-sdk session:list List active agent sessions
47446
+ elevasis-sdk session:get <id> Get session details and transcript
47447
+ elevasis-sdk session:end <id> Terminate an active agent session
47448
+ elevasis-sdk acquisition:list:list List acquisition lists
47449
+ elevasis-sdk acquisition:deal:list List acquisition deals
45810
47450
  elevasis-sdk knowledge:generate Generate knowledge nodes from MDX files
45811
47451
  elevasis-sdk knowledge:ls <path> List knowledge nodes for a path
45812
47452
  elevasis-sdk knowledge:cat <id> Print raw MDX body of a knowledge node
@@ -45814,6 +47454,7 @@ Commands:
45814
47454
  elevasis-sdk request:submit -f <path> Submit a structured request report
45815
47455
  elevasis-sdk ui:use-local Use a local @elevasis/ui tarball
45816
47456
  elevasis-sdk ui:use-published Restore published @elevasis/ui
47457
+ elevasis-sdk cli [domain] Generate a registered command catalog
45817
47458
  elevasis-sdk rename <id> --to <newId> [--prod] Rename resource across platform tables
45818
47459
  elevasis-sdk doctor [--verbose] Check project environment and API connectivity
45819
47460
 
@@ -45834,10 +47475,15 @@ registerCredsCommand(program2);
45834
47475
  registerErrorCommand(program2);
45835
47476
  registerRenameCommand(program2);
45836
47477
  registerProjectCommands(program2);
47478
+ registerClientCommands(program2);
47479
+ registerAgentCommands(program2);
47480
+ registerSessionCommands(program2);
47481
+ registerAcquisitionCommands(program2);
45837
47482
  registerKnowledgeCommands(program2);
45838
47483
  registerRequestCommands(program2);
45839
47484
  registerUiCommands(program2);
45840
47485
  registerDoctorCommand(program2);
47486
+ registerCliCatalogCommand(program2);
45841
47487
  program2.parse();
45842
47488
  // Annotate the CommonJS export names for ESM import in node:
45843
47489
  0 && (module.exports = {