@elevasis/sdk 1.49.0 → 1.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -23570,6 +23570,10 @@ var init_profile_registry = __esm({
23570
23570
  });
23571
23571
 
23572
23572
  // ../core/src/organization-model/domains/systems.ts
23573
+ function isSystemLifecycleVisible(lifecycle, enabled) {
23574
+ if (enabled === false) return false;
23575
+ return lifecycle !== "draft" && lifecycle !== "deprecated" && lifecycle !== "archived";
23576
+ }
23573
23577
  function isReservedPlatformProfileId(profileId) {
23574
23578
  return BUILT_IN_VALIDATED_PROFILE_IDS.includes(profileId);
23575
23579
  }
@@ -23586,7 +23590,10 @@ var init_systems = __esm({
23586
23590
  init_ontology();
23587
23591
  init_profile_registry();
23588
23592
  SystemKindSchema = external_exports.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
23589
- SystemLifecycleSchema = external_exports.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
23593
+ SystemLifecycleSchema = external_exports.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({
23594
+ label: "Lifecycle",
23595
+ color: "teal"
23596
+ });
23590
23597
  SystemIdSchema = ModelIdSchema;
23591
23598
  SystemPathSchema = external_exports.string().trim().min(1).regex(
23592
23599
  /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
@@ -23706,8 +23713,13 @@ var init_systems = __esm({
23706
23713
  parentSystemId: SystemIdSchema.optional(),
23707
23714
  /** Optional UI presence. Systems without UI omit this. */
23708
23715
  ui: SystemUiSchema.optional(),
23709
- /** Canonical lifecycle state. `beta` is what gates a System to dev-mode viewers. */
23710
- lifecycle: SystemLifecycleSchema.optional(),
23716
+ /**
23717
+ * Canonical lifecycle state. `beta` is what gates a System to dev-mode
23718
+ * viewers. Defaults to `active` (not `.optional()`) so an omitted field
23719
+ * never reaches a consumer as `undefined` -- see `isSystemLifecycleVisible`
23720
+ * and `systemLifecycleAllowsAccess` above.
23721
+ */
23722
+ lifecycle: SystemLifecycleSchema.default("active"),
23711
23723
  /** Optional role responsible for this system. */
23712
23724
  responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
23713
23725
  /** Optional knowledge nodes that govern this system. */
@@ -24229,10 +24241,6 @@ function addIssue(ctx, path3, message) {
24229
24241
  message
24230
24242
  });
24231
24243
  }
24232
- function isLifecycleEnabled(lifecycle, enabled) {
24233
- if (enabled === false) return false;
24234
- return lifecycle !== "deprecated" && lifecycle !== "archived";
24235
- }
24236
24244
  function defaultSystemPathFor(id) {
24237
24245
  return `/${id.replaceAll(".", "/")}`;
24238
24246
  }
@@ -24303,11 +24311,11 @@ function refineOrganizationModel(model, ctx) {
24303
24311
  systemIdsByEffectivePath.set(effectivePath, path3);
24304
24312
  }
24305
24313
  }
24306
- if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
24314
+ if (hasChildren && isSystemLifecycleVisible(system.lifecycle, system.enabled)) {
24307
24315
  const hasEnabledDescendant = Object.values(system.systems ?? system.subsystems ?? {}).some(
24308
- (candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
24316
+ (candidate) => isSystemLifecycleVisible(candidate.lifecycle, candidate.enabled)
24309
24317
  ) || allSystems.some(
24310
- (candidate) => candidate.path.startsWith(`${path3}.`) && !candidate.path.slice(path3.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
24318
+ (candidate) => candidate.path.startsWith(`${path3}.`) && !candidate.path.slice(path3.length + 1).includes(".") && isSystemLifecycleVisible(candidate.system.lifecycle, candidate.system.enabled)
24311
24319
  );
24312
24320
  if (!hasEnabledDescendant) {
24313
24321
  addIssue(ctx, [...schemaPath, "lifecycle"], `System "${path3}" is active but has no active descendants`);
@@ -24722,6 +24730,7 @@ var init_schema_refinements = __esm({
24722
24730
  "use strict";
24723
24731
  init_zod();
24724
24732
  init_resources();
24733
+ init_systems();
24725
24734
  init_cross_ref();
24726
24735
  init_ontology();
24727
24736
  }
@@ -25054,7 +25063,7 @@ var init_content = __esm({
25054
25063
  "../core/src/organization-model/catalogs/content.ts"() {
25055
25064
  "use strict";
25056
25065
  init_zod();
25057
- ContentPipelineStepActorSchema = external_exports.enum(["workflow", "agent", "vendor"]);
25066
+ ContentPipelineStepActorSchema = external_exports.enum(["workflow", "agent", "vendor", "human"]);
25058
25067
  ContentPipelineStepReviewModeSchema = external_exports.enum(["none", "required"]);
25059
25068
  ContentPayloadFieldTypeSchema = external_exports.enum(["string", "text", "number", "boolean", "url", "string-array"]);
25060
25069
  ContentPayloadFieldDeclarationSchema = external_exports.object({
@@ -26291,6 +26300,13 @@ var init_lead_gen = __esm({
26291
26300
  }
26292
26301
  });
26293
26302
 
26303
+ // ../core/src/organization-model/catalogs/content-producer-factory.ts
26304
+ var init_content_producer_factory = __esm({
26305
+ "../core/src/organization-model/catalogs/content-producer-factory.ts"() {
26306
+ "use strict";
26307
+ }
26308
+ });
26309
+
26294
26310
  // ../core/src/organization-model/catalogs/define-content-pipeline.ts
26295
26311
  var init_define_content_pipeline = __esm({
26296
26312
  "../core/src/organization-model/catalogs/define-content-pipeline.ts"() {
@@ -26298,6 +26314,49 @@ var init_define_content_pipeline = __esm({
26298
26314
  }
26299
26315
  });
26300
26316
 
26317
+ // ../core/src/organization-model/catalogs/define-system-api-interface.ts
26318
+ function formatAdoptableProfiles() {
26319
+ return SYSTEM_INTERFACE_PROFILES.map((profile) => `"${profile.readinessProfile}"`).join(", ");
26320
+ }
26321
+ function defineSystemApiInterface(input) {
26322
+ const interfaceKey = input.interfaceKey ?? "api";
26323
+ const identity = `${input.systemPath}/${interfaceKey}`;
26324
+ const catalogEntry = SYSTEM_INTERFACE_PROFILES.find((profile) => profile.readinessProfile === input.readinessProfile);
26325
+ if (catalogEntry === void 0) {
26326
+ throw new Error(
26327
+ `System Interface "${identity}" declares readinessProfile "${input.readinessProfile}", which is not a member of SYSTEM_INTERFACE_PROFILES. Adoptable profiles: ${formatAdoptableProfiles()}. An uncataloged id names no route platform code actually serves -- it computes as ready and answers every request with a 503. Add an entry to SYSTEM_INTERFACE_PROFILES (packages/core/src/organization-model/domains/systems.ts) before declaring it on System "${input.systemPath}", or use one of the ids above.`
26328
+ );
26329
+ }
26330
+ if (input.resourceIds.length === 0) {
26331
+ throw new Error(
26332
+ `System Interface "${identity}" declares an empty resourceIds list. An interface with no scoped active resource computes as ready and answers every route with a 503 -- scope at least one active resource for System "${input.systemPath}".`
26333
+ );
26334
+ }
26335
+ const isBuiltIn = catalogEntry.validation === "built-in";
26336
+ if (!isBuiltIn && input.readinessContract === void 0) {
26337
+ throw new Error(
26338
+ `System Interface "${identity}" adopts contract-validated profile "${input.readinessProfile}" but declares no readinessContract. Contract-validated profiles have no registered platform validator -- each adopter's structural requirements differ, so System "${input.systemPath}" must pass a readinessContract with at least one requiredCatalogs entry.`
26339
+ );
26340
+ }
26341
+ if (isBuiltIn && input.readinessContract !== void 0) {
26342
+ throw new Error(
26343
+ `System Interface "${identity}" declares a readinessContract against built-in profile "${input.readinessProfile}". Built-in profiles derive their requirements from platform code registered via registerBuiltInReadinessProfile, and the readiness engine never reads an authored contract against one -- it is silently ignored (the "else if (readinessContract)" branch in readiness/engine.ts is unreachable for a built-in profile). Delete the readinessContract on System "${input.systemPath}"; it asserts nothing today.`
26344
+ );
26345
+ }
26346
+ return {
26347
+ lifecycle: input.lifecycle ?? "active",
26348
+ readinessProfile: input.readinessProfile,
26349
+ resourceIds: input.resourceIds,
26350
+ ...input.readinessContract !== void 0 ? { readinessContract: input.readinessContract } : {}
26351
+ };
26352
+ }
26353
+ var init_define_system_api_interface = __esm({
26354
+ "../core/src/organization-model/catalogs/define-system-api-interface.ts"() {
26355
+ "use strict";
26356
+ init_systems();
26357
+ }
26358
+ });
26359
+
26301
26360
  // ../core/src/organization-model/readiness/engine.ts
26302
26361
  function addReadinessIssue(issues, family, code, message, details = {}) {
26303
26362
  issues.push({
@@ -26638,7 +26697,9 @@ var init_organization_model = __esm({
26638
26697
  init_graph();
26639
26698
  init_lead_gen();
26640
26699
  init_content();
26700
+ init_content_producer_factory();
26641
26701
  init_define_content_pipeline();
26702
+ init_define_system_api_interface();
26642
26703
  init_branding();
26643
26704
  init_systems();
26644
26705
  init_resources();
@@ -45276,7 +45337,7 @@ function detectMissingApiInterfaceDeclarations(orgName, organizationModel) {
45276
45337
  for (const resource of Object.values(organizationModel.resources ?? {})) {
45277
45338
  const ontology = resource.ontology;
45278
45339
  if (ontology === void 0) continue;
45279
- const hasOntologyBindings = ontology.actions !== void 0 && ontology.actions.length > 0 || ontology.writes !== void 0 && ontology.writes.length > 0;
45340
+ const hasOntologyBindings = ontology.actions !== void 0 && ontology.actions.length > 0 || ontology.writes !== void 0 && ontology.writes.length > 0 || ontology.reads !== void 0 && ontology.reads.length > 0 || ontology.usesCatalogs !== void 0 && ontology.usesCatalogs.length > 0;
45280
45341
  if (!hasOntologyBindings) continue;
45281
45342
  const existing = apiBoundResourcesBySystemPath.get(resource.systemPath);
45282
45343
  if (existing) {
@@ -45309,18 +45370,15 @@ function validateDeclaredSystemInterfaceReadiness(orgName, organizationModel, op
45309
45370
  for (const { path: path3, system } of listAllSystems(model)) {
45310
45371
  if (system.apiInterface === void 0) continue;
45311
45372
  const interfaceKey = "api";
45312
- const resourceIds = system.apiInterface.resourceIds ?? [];
45313
- if (resourceIds.length === 0) {
45314
- const readinessProfile = system.apiInterface.readinessProfile;
45315
- if (readinessProfile !== void 0 && !SYSTEM_INTERFACE_PROFILES.some((profile) => profile.readinessProfile === readinessProfile)) {
45316
- addSystemInterfaceIssue(issues, orgName, path3, interfaceKey, {
45317
- family: "SYSTEM_INTERFACE_INVALID",
45318
- code: "unknown-readiness-profile",
45319
- path: `systems.${path3}.apiInterface.readinessProfile`,
45320
- ref: readinessProfile,
45321
- message: `System Interface "${path3}/${interfaceKey}" references unknown readiness profile "${readinessProfile}".`
45322
- });
45323
- }
45373
+ const readinessProfile = system.apiInterface.readinessProfile;
45374
+ if (readinessProfile !== void 0 && !SYSTEM_INTERFACE_PROFILES.some((profile) => profile.readinessProfile === readinessProfile)) {
45375
+ addSystemInterfaceIssue(issues, orgName, path3, interfaceKey, {
45376
+ family: "SYSTEM_INTERFACE_INVALID",
45377
+ code: "unknown-readiness-profile",
45378
+ path: `systems.${path3}.apiInterface.readinessProfile`,
45379
+ ref: readinessProfile,
45380
+ message: `System Interface "${path3}/${interfaceKey}" references unknown readiness profile "${readinessProfile}".`
45381
+ });
45324
45382
  }
45325
45383
  const result = computeInterfaceReadiness(model, { systemPath: path3, interfaceKey });
45326
45384
  for (const issue2 of result.issues) {
@@ -47661,6 +47719,13 @@ var init_clickup = __esm({
47661
47719
  }
47662
47720
  });
47663
47721
 
47722
+ // ../core/src/execution/engine/tools/integration/types/instagram.ts
47723
+ var init_instagram = __esm({
47724
+ "../core/src/execution/engine/tools/integration/types/instagram.ts"() {
47725
+ "use strict";
47726
+ }
47727
+ });
47728
+
47664
47729
  // ../core/src/execution/engine/tools/integration/types/index.ts
47665
47730
  var init_types9 = __esm({
47666
47731
  "../core/src/execution/engine/tools/integration/types/index.ts"() {
@@ -47678,6 +47743,7 @@ var init_types9 = __esm({
47678
47743
  init_tomba();
47679
47744
  init_millionverifier();
47680
47745
  init_clickup();
47746
+ init_instagram();
47681
47747
  }
47682
47748
  });
47683
47749
 
@@ -48771,7 +48837,14 @@ var init_api_schemas5 = __esm({
48771
48837
  "use strict";
48772
48838
  init_zod();
48773
48839
  init_validation();
48774
- CredentialTypeSchema = external_exports.enum(["oauth", "api-key", "webhook-secret", "api-key-secret", "clickup"]);
48840
+ CredentialTypeSchema = external_exports.enum([
48841
+ "oauth",
48842
+ "api-key",
48843
+ "webhook-secret",
48844
+ "api-key-secret",
48845
+ "clickup",
48846
+ "instagram"
48847
+ ]);
48775
48848
  CredentialValueSchema = external_exports.record(external_exports.string(), external_exports.unknown()).refine((val) => Object.keys(val).length > 0, { message: "Credential value must not be empty" }).refine((val) => Object.keys(val).length <= 50, { message: "Credential value has too many keys (max 50)" }).refine(
48776
48849
  (val) => {
48777
48850
  for (const v of Object.values(val)) {
@@ -49225,7 +49298,7 @@ var init_package = __esm({
49225
49298
  "package.json"() {
49226
49299
  package_default = {
49227
49300
  name: "@elevasis/sdk",
49228
- version: "1.49.0",
49301
+ version: "1.50.0",
49229
49302
  description: "SDK for building Elevasis organization resources",
49230
49303
  type: "module",
49231
49304
  bin: {
@@ -49257,6 +49330,7 @@ var init_package = __esm({
49257
49330
  "dist/test-utils/index.js",
49258
49331
  "dist/test-utils/index.d.ts",
49259
49332
  "dist/node/",
49333
+ "dist/chunk-*.js",
49260
49334
  "dist/cli.cjs",
49261
49335
  "reference/"
49262
49336
  ],
@@ -49276,8 +49350,14 @@ var init_package = __esm({
49276
49350
  "remark-gfm": "^4.0.1"
49277
49351
  },
49278
49352
  peerDependencies: {
49353
+ vitest: ">=3",
49279
49354
  zod: "^4.1.0"
49280
49355
  },
49356
+ peerDependenciesMeta: {
49357
+ vitest: {
49358
+ optional: true
49359
+ }
49360
+ },
49281
49361
  devDependencies: {
49282
49362
  "@repo/core": "workspace:*",
49283
49363
  "@repo/eslint-config": "workspace:*",
@@ -49292,6 +49372,7 @@ var init_package = __esm({
49292
49372
  "rollup-plugin-dts": "^6.3.0",
49293
49373
  tsup: "^8.0.0",
49294
49374
  typescript: "5.9.2",
49375
+ vitest: "^3.2.4",
49295
49376
  zod: "^4.1.0"
49296
49377
  }
49297
49378
  };
@@ -49992,18 +50073,35 @@ function emitSystemEntry(opts) {
49992
50073
  const order = opts.order ?? 10;
49993
50074
  let apiInterfaceBlock = "";
49994
50075
  let apiInterfaceNote;
50076
+ let importLine;
49995
50077
  if (opts.apiBacked) {
49996
50078
  const cataloged = SYSTEM_INTERFACE_PROFILES.find(
49997
50079
  (profile) => profile.systemPath === opts.id && profile.interfaceKey === "api"
49998
50080
  );
49999
- if (cataloged !== void 0) {
50081
+ const resourceIds = (opts.resourceIds ?? []).filter((id) => id.trim().length > 0);
50082
+ if (cataloged !== void 0 && cataloged.validation === "built-in" && resourceIds.length > 0) {
50083
+ defineSystemApiInterface({
50084
+ systemPath: opts.id,
50085
+ readinessProfile: cataloged.readinessProfile,
50086
+ resourceIds
50087
+ });
50088
+ importLine = `import { defineSystemApiInterface } from '@elevasis/core/organization-model'`;
50089
+ const resourceIdsLines = resourceIds.map((id) => ` '${id}'`).join(",\n");
50000
50090
  apiInterfaceBlock = `
50001
- apiInterface: {
50002
- lifecycle: 'active',
50003
- readinessProfile: '${cataloged.readinessProfile}'
50004
- },`;
50091
+ apiInterface: defineSystemApiInterface({
50092
+ systemPath: '${opts.id}',
50093
+ readinessProfile: '${cataloged.readinessProfile}',
50094
+ resourceIds: [
50095
+ ${resourceIdsLines}
50096
+ ]
50097
+ }),`;
50098
+ } else if (cataloged !== void 0 && cataloged.validation === "built-in") {
50099
+ apiInterfaceNote = `System \`${opts.id}\` is cataloged for readiness profile "${cataloged.readinessProfile}", but a brand-new System has no scoped resources yet to back an \`apiInterface\`. \`apiInterface\` was NOT added. Once real resource ids exist for this system, declare it with \`defineSystemApiInterface\` from '@elevasis/core/organization-model' (or re-run \`om:scaffold:fill\`, which does this for you).`;
50100
+ } else if (cataloged !== void 0) {
50101
+ apiInterfaceNote = `System \`${opts.id}\` adopts contract-validated readiness profile "${cataloged.readinessProfile}". \`apiInterface\` was NOT added \u2014 declare it with \`defineContentSystem\` from '@elevasis/core/organization-model', which derives the readinessContract, content:object/item, and status catalog from your pipelines, item voice, and status vocabulary.`;
50005
50102
  } else {
50006
- apiInterfaceNote = `System \`${opts.id}\` is not on a cataloged readiness profile (only sales.lead-gen and sales.crm ship built-in profiles today). \`apiInterface\` was NOT added. Declare it manually once real resourceIds exist for this system, using either a cataloged profile or a custom \`readinessProfile\` paired with a \`readinessContract\`.`;
50103
+ const adoptable = SYSTEM_INTERFACE_PROFILES.filter((profile) => profile.interfaceKey === "api").map((profile) => `"${profile.systemPath}"`).join(", ");
50104
+ apiInterfaceNote = `System \`${opts.id}\` is not on a cataloged readiness profile (adoptable system paths today: ${adoptable}). \`apiInterface\` was NOT added. A custom System extends behavior through workflows/operations plus ontology, resources, and topology \u2014 omitting apiInterface entirely is the designed opt-out.`;
50007
50105
  }
50008
50106
  }
50009
50107
  const code = ` {
@@ -50019,7 +50117,8 @@ function emitSystemEntry(opts) {
50019
50117
  `;
50020
50118
  const startAnchor = /^(?!\s*(?:\/\/|\*|\/\*)).*\bexport const templateSystems\s*=/m;
50021
50119
  const anchor = /^\] as const\s*$/m;
50022
- return { code, startAnchor, anchor, apiInterfaceNote };
50120
+ const importAnchor = /^\/\/ -{75,}\n\/\/ Feature/m;
50121
+ return { code, startAnchor, anchor, apiInterfaceNote, importLine, importAnchor };
50023
50122
  }
50024
50123
  var init_emit_system = __esm({
50025
50124
  "src/cli/commands/om/emit-system.ts"() {
@@ -50186,10 +50285,20 @@ async function scaffoldSystem(opts) {
50186
50285
  });
50187
50286
  apiBacked = answer.trim().toLowerCase() === "y";
50188
50287
  }
50189
- const { code, anchor, startAnchor, apiInterfaceNote } = emitSystemEntry({ id, title, kind, apiBacked });
50288
+ const { code, anchor, startAnchor, apiInterfaceNote, importLine, importAnchor } = emitSystemEntry({
50289
+ id,
50290
+ title,
50291
+ kind,
50292
+ apiBacked,
50293
+ resourceIds: options.resourceIds
50294
+ });
50190
50295
  const shouldWrite = options.write === true || options.dryRun === false;
50191
50296
  if (!shouldWrite) {
50192
50297
  console.log(source_default.cyan("Dry-run mode (default) \u2014 no files written. Pass --write to apply.\n"));
50298
+ if (importLine !== void 0) {
50299
+ console.log(source_default.gray("Import line to add near the top of core/config/organization-model/systems.ts:"));
50300
+ console.log(importLine);
50301
+ }
50193
50302
  console.log(source_default.gray("Proposed addition to core/config/organization-model/systems.ts:"));
50194
50303
  console.log(code);
50195
50304
  if (apiInterfaceNote !== void 0) {
@@ -50200,6 +50309,9 @@ async function scaffoldSystem(opts) {
50200
50309
  const systemsFilePath = (0, import_node_path13.join)(getOrganizationModelDir(projectDir), "systems.ts");
50201
50310
  try {
50202
50311
  await withSnapshotRollback([systemsFilePath], async () => {
50312
+ if (importLine !== void 0) {
50313
+ await appendBeforeAnchor(systemsFilePath, importLine + "\n", importAnchor);
50314
+ }
50203
50315
  await appendBeforeAnchor(systemsFilePath, code, anchor, startAnchor);
50204
50316
  const validationError = runValidation(projectDir);
50205
50317
  if (validationError !== null) {
@@ -50646,6 +50758,14 @@ var init_scaffold_knowledge = __esm({
50646
50758
  function toConstName(systemPath) {
50647
50759
  return systemPath.split(/[.-]/).map((segment, index) => index === 0 ? segment : segment.charAt(0).toUpperCase() + segment.slice(1)).join("") + "ApiInterface";
50648
50760
  }
50761
+ function buildContentPlaceholderReadinessContract(systemPath) {
50762
+ return {
50763
+ requiredObjects: [`${systemPath}:object/item`],
50764
+ requiredCatalogs: [
50765
+ "TODO -- replace with this System real pipeline, step, and status catalog ids (see defineContentPipeline and defineContentSystem in the organization-model subpath)"
50766
+ ]
50767
+ };
50768
+ }
50649
50769
  function emitApiInterfaceBlock(gap) {
50650
50770
  const constName = toConstName(gap.systemPath);
50651
50771
  const cataloged = SYSTEM_INTERFACE_PROFILES.find(
@@ -50658,17 +50778,44 @@ function emitApiInterfaceBlock(gap) {
50658
50778
  );
50659
50779
  }
50660
50780
  const readinessProfile = cataloged.readinessProfile;
50661
- const resourceIdsField = gap.resourceIds.length === 0 ? "" : `,
50662
- resourceIds: [
50663
- ${gap.resourceIds.map((id) => `'${id}'`).join(",\n ")}
50664
- ]`;
50781
+ if (gap.resourceIds.length === 0) {
50782
+ throw new Error(
50783
+ `Cannot emit an apiInterface for system path "${gap.systemPath}": the gap carries no resourceIds. defineSystemApiInterface requires at least one scoped resource id \u2014 an interface with none computes as ready and answers every route with a 503. Re-run this scaffolder once the system has at least one API-backed resource declared.`
50784
+ );
50785
+ }
50786
+ const resourceIds = gap.resourceIds;
50787
+ const isContractValidated = cataloged.validation === "contract";
50788
+ const readinessContract = isContractValidated ? buildContentPlaceholderReadinessContract(gap.systemPath) : void 0;
50789
+ defineSystemApiInterface({
50790
+ systemPath: gap.systemPath,
50791
+ readinessProfile,
50792
+ resourceIds,
50793
+ ...readinessContract !== void 0 ? { readinessContract } : {}
50794
+ });
50795
+ const resourceIdsLines = resourceIds.map((id) => ` '${id}'`).join(",\n");
50796
+ const readinessContractField = readinessContract === void 0 ? "" : `,
50797
+ // TODO: requiredCatalogs below is a placeholder. Replace it with this System's actual pipeline,
50798
+ // step, and status catalog ids before deploying \u2014 see extend-content.md in the SDK scaffold docs.
50799
+ readinessContract: {
50800
+ requiredObjects: [
50801
+ ${readinessContract.requiredObjects.map((id) => `'${id}'`).join(",\n ")}
50802
+ ],
50803
+ requiredCatalogs: [
50804
+ ${readinessContract.requiredCatalogs.map((id) => `'${id}'`).join(",\n ")}
50805
+ ]
50806
+ }`;
50665
50807
  const constFileCode = `// Auto-generated by om:scaffold:fill \u2014 do not edit manually.
50666
50808
  // Regenerate by running: elevasis-sdk om:scaffold:fill --gaps <path>
50667
50809
 
50668
- export const ${constName} = {
50669
- lifecycle: 'active' as const,
50670
- readinessProfile: '${readinessProfile}'${resourceIdsField}
50671
- }
50810
+ import { defineSystemApiInterface } from '@elevasis/core/organization-model'
50811
+
50812
+ export const ${constName} = defineSystemApiInterface({
50813
+ systemPath: '${gap.systemPath}',
50814
+ readinessProfile: '${readinessProfile}',
50815
+ resourceIds: [
50816
+ ${resourceIdsLines}
50817
+ ]${readinessContractField}
50818
+ })
50672
50819
  `;
50673
50820
  const importLine = `import { ${constName} } from './api-interfaces/${gap.systemPath}'`;
50674
50821
  const fieldLine = ` apiInterface: ${constName},`;
@@ -50769,11 +50916,21 @@ async function scaffoldFill(opts) {
50769
50916
  gap.resourceIds
50770
50917
  ) : gap.resourceId ? [gap.resourceId] : []
50771
50918
  );
50772
- const emitResult = emitApiInterfaceBlock({
50773
- systemPath,
50774
- resourceIds,
50775
- message: gap.reason
50776
- });
50919
+ let emitResult;
50920
+ try {
50921
+ emitResult = emitApiInterfaceBlock({
50922
+ systemPath,
50923
+ resourceIds,
50924
+ message: gap.reason
50925
+ });
50926
+ } catch (err) {
50927
+ skippedGaps.push({
50928
+ field: gap.field,
50929
+ resourceId: gap.resourceId,
50930
+ reason: err instanceof Error ? err.message : String(err)
50931
+ });
50932
+ continue;
50933
+ }
50777
50934
  const constFilePath = (0, import_node_path17.join)(getOrganizationModelDir(projectDir), "api-interfaces", `${systemPath}.ts`);
50778
50935
  touchedFiles.push(constFilePath);
50779
50936
  emitResults.push(emitResult);
@@ -56433,7 +56590,7 @@ function appendQuery4(params, key, value) {
56433
56590
  }
56434
56591
  function registerContentList(program3) {
56435
56592
  program3.command("content:list").description(
56436
- "List content pipeline items\n Example: elevasis-sdk content:list --status queued --pipeline-id short-form-repurpose"
56593
+ 'List content pipeline items\n Example: elevasis-sdk content:list --status <status> --pipeline-id <pipelineId>\n Note: both values come from the org model this project declares, not a platform enum --\n read them from the content:catalog/status catalog and content:pipeline.\n Note: "awaiting review" is not a status -- that read is content:queue.'
56437
56594
  ).option("--status <status>", "Filter by content item status").option("--pillar <pillar>", "Filter by content pillar").option("--pipeline-id <id>", "Filter by pipeline template id").option("--client-id <id>", "Filter by client id").option("--reviewed-by <id>", "Filter by reviewer user id").option("--search <query>", "Search by title").option("--limit <n>", "Maximum number of results").option("--offset <n>", "Pagination offset").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
56438
56595
  wrapAction("content:list", async (options) => {
56439
56596
  const apiUrl = resolveApiUrl(options.apiUrl, options.prod);
@@ -56671,7 +56828,7 @@ function printCards(cards, stepsByKey) {
56671
56828
  }
56672
56829
  function registerContentBoard(program3) {
56673
56830
  program3.command("content:board <pipelineId>").description(
56674
- "Render one pipeline as a board -- columns, review gates, and waiting counts\n Example: elevasis-sdk content:board short-form-repurpose --pretty"
56831
+ "Render one pipeline as a board -- columns, review gates, and waiting counts\n Example: elevasis-sdk content:board <pipelineId> --pretty\n Note: pipeline ids come from the org model this project declares -- list them with content:pipeline."
56675
56832
  ).option("--limit <n>", `Items to pull before deriving (default and API maximum ${DEFAULT_ITEM_LIMIT})`).option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
56676
56833
  wrapAction("content:board", async (pipelineId, options) => {
56677
56834
  const apiUrl = resolveApiUrl(options.apiUrl, options.prod);
@@ -56772,7 +56929,7 @@ Pipeline: ${pipeline.id}`));
56772
56929
  }
56773
56930
  function registerContentPipeline(program3) {
56774
56931
  program3.command("content:pipeline [id]").description(
56775
- "List content pipeline templates, or show one pipeline's step contract\n Example: elevasis-sdk content:pipeline short-form-repurpose"
56932
+ "List content pipeline templates, or show one pipeline's step contract\n Example: elevasis-sdk content:pipeline <pipelineId>\n Note: run without an id to list the pipeline ids this project declares in its org model."
56776
56933
  ).option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
56777
56934
  wrapAction("content:pipeline", async (id, options) => {
56778
56935
  const apiUrl = resolveApiUrl(options.apiUrl, options.prod);
@@ -56817,7 +56974,7 @@ function appendQuery5(params, key, value) {
56817
56974
  }
56818
56975
  function registerContentDistributions(program3) {
56819
56976
  program3.command("content:distributions").description(
56820
- "List content distributions\n Example: elevasis-sdk content:distributions --pipeline-id short-form-repurpose"
56977
+ "List content distributions\n Example: elevasis-sdk content:distributions --pipeline-id <pipelineId>\n Note: pipeline ids come from the org model this project declares -- list them with content:pipeline."
56821
56978
  ).option("--content-item-id <id>", "Filter by content item id").option("--pipeline-id <id>", "Filter by pipeline template id").option("--platform <platform>", "Filter by distribution platform").option("--status <status>", "Filter by distribution status").option("--limit <n>", "Maximum number of results").option("--offset <n>", "Pagination offset").option("--prod", "Target production (overrides NODE_ENV=development)").option("--api-url <url>", "API base URL").option("--pretty", "Render human-readable output instead of raw JSON").action(
56822
56979
  wrapAction("content:distributions", async (options) => {
56823
56980
  const apiUrl = resolveApiUrl(options.apiUrl, options.prod);