@odla-ai/cli 0.25.19 → 0.25.21

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.
@@ -17,22 +17,22 @@ function readJsonFile(path) {
17
17
  return null;
18
18
  }
19
19
  }
20
- function writePrivateJson(path, value) {
21
- writePrivateText(path, `${JSON.stringify(value, null, 2)}
20
+ function writePrivateJson(path, value2) {
21
+ writePrivateText(path, `${JSON.stringify(value2, null, 2)}
22
22
  `);
23
23
  }
24
24
  function readCredentials(path) {
25
25
  if (!existsSync(path)) return null;
26
- let value;
26
+ let value2;
27
27
  try {
28
- value = JSON.parse(readFileSync(path, "utf8"));
28
+ value2 = JSON.parse(readFileSync(path, "utf8"));
29
29
  } catch {
30
30
  throw new Error(`credentials file ${path} is not valid JSON; fix or remove it before provisioning`);
31
31
  }
32
- if (!value || typeof value !== "object" || typeof value.appId !== "string" || !value.envs || typeof value.envs !== "object") {
32
+ if (!value2 || typeof value2 !== "object" || typeof value2.appId !== "string" || !value2.envs || typeof value2.envs !== "object") {
33
33
  throw new Error(`credentials file ${path} has an invalid shape; fix or remove it before provisioning`);
34
34
  }
35
- return value;
35
+ return value2;
36
36
  }
37
37
  function mergeCredential(current, update) {
38
38
  const next = current ?? {
@@ -366,8 +366,8 @@ function stillPending(pending, email) {
366
366
  { retryable: true }
367
367
  );
368
368
  }
369
- function handshakeEmail(value, cached) {
370
- const email = (value ?? process4.env.ODLA_USER_EMAIL ?? cached ?? "").trim().toLowerCase();
369
+ function handshakeEmail(value2, cached) {
370
+ const email = (value2 ?? process4.env.ODLA_USER_EMAIL ?? cached ?? "").trim().toLowerCase();
371
371
  if (email.length > 254 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
372
372
  throw new Error("a fresh odla handshake requires --email <account> or ODLA_USER_EMAIL");
373
373
  }
@@ -391,10 +391,10 @@ function handshakeUrl(platformUrl, userCode) {
391
391
  url.searchParams.set("code", userCode);
392
392
  return url.toString();
393
393
  }
394
- function platformAudience(value) {
394
+ function platformAudience(value2) {
395
395
  let url;
396
396
  try {
397
- url = new URL(value);
397
+ url = new URL(value2);
398
398
  } catch {
399
399
  throw new Error("platform must be an absolute URL");
400
400
  }
@@ -436,6 +436,7 @@ function audienceBoundEnvToken(token, platform) {
436
436
  return token;
437
437
  }
438
438
  var SCOPE_PURPOSE = {
439
+ "platform:status:read": "read the platform fleet health and deployment snapshot",
439
440
  "platform:runbook:write": "add or edit odla's operational runbooks",
440
441
  "platform:ai:policy:write": "change System AI model routing",
441
442
  "platform:ai:policy:read": "read System AI model routing",
@@ -499,11 +500,11 @@ var SYSTEM_AI_PURPOSES = [
499
500
  "security.validation",
500
501
  "runbook.answer"
501
502
  ];
502
- function requireSystemAiPurpose(value) {
503
- if (!SYSTEM_AI_PURPOSES.includes(value)) {
503
+ function requireSystemAiPurpose(value2) {
504
+ if (!SYSTEM_AI_PURPOSES.includes(value2)) {
504
505
  throw new Error(`purpose must be one of: ${SYSTEM_AI_PURPOSES.join(", ")}`);
505
506
  }
506
- return value;
507
+ return value2;
507
508
  }
508
509
 
509
510
  // src/admin-ai.ts
@@ -514,22 +515,22 @@ import process6 from "process";
514
515
  var MAX_BYTES = 64 * 1024;
515
516
  async function secretInputValue(options, kind = "credential") {
516
517
  if (options.fromEnv && options.stdin) throw new Error("choose exactly one of --from-env or --stdin");
517
- let value;
518
- if (options.fromEnv) value = process6.env[options.fromEnv];
519
- else if (options.stdin) value = await (options.readStdin ?? (() => readSecretStream(kind)))();
518
+ let value2;
519
+ if (options.fromEnv) value2 = process6.env[options.fromEnv];
520
+ else if (options.stdin) value2 = await (options.readStdin ?? (() => readSecretStream(kind)))();
520
521
  else throw new Error(`${kind} input required: use --from-env <NAME> or --stdin; values are never accepted as arguments`);
521
- value = value?.replace(/[\r\n]+$/, "");
522
- if (!value) throw new Error(options.fromEnv ? `environment variable ${options.fromEnv} is empty or unset` : `stdin ${kind} is empty`);
523
- if (new TextEncoder().encode(value).byteLength > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
524
- return value;
522
+ value2 = value2?.replace(/[\r\n]+$/, "");
523
+ if (!value2) throw new Error(options.fromEnv ? `environment variable ${options.fromEnv} is empty or unset` : `stdin ${kind} is empty`);
524
+ if (new TextEncoder().encode(value2).byteLength > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
525
+ return value2;
525
526
  }
526
527
  async function readSecretStream(kind, stream = process6.stdin) {
527
- let value = "";
528
+ let value2 = "";
528
529
  for await (const chunk of stream) {
529
- value += String(chunk);
530
- if (value.length > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
530
+ value2 += String(chunk);
531
+ if (value2.length > MAX_BYTES) throw new Error(`${kind} exceeds 64 KiB`);
531
532
  }
532
- return value;
533
+ return value2;
533
534
  }
534
535
 
535
536
  // src/admin-ai-audit.ts
@@ -579,13 +580,13 @@ function apiError(status, body) {
579
580
  const message2 = error && typeof error.message === "string" ? error.message : isRecord(body) && typeof body.message === "string" ? body.message : "request failed";
580
581
  return `read System AI admin changes failed (${status}): ${message2}`;
581
582
  }
582
- function timestamp(value) {
583
- if (typeof value !== "number" || !Number.isFinite(value)) return String(value ?? "");
584
- const date = new Date(value);
583
+ function timestamp(value2) {
584
+ if (typeof value2 !== "number" || !Number.isFinite(value2)) return String(value2 ?? "");
585
+ const date = new Date(value2);
585
586
  return Number.isFinite(date.valueOf()) ? date.toISOString() : "";
586
587
  }
587
- function isRecord(value) {
588
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
588
+ function isRecord(value2) {
589
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
589
590
  }
590
591
 
591
592
  // src/admin-ai-usage.ts
@@ -607,11 +608,11 @@ async function readAdminAiUsage(request2) {
607
608
  if (request2.json) request2.stdout.log(JSON.stringify(body, null, 2));
608
609
  else printUsage(body, request2.stdout);
609
610
  }
610
- function usageLimit(value) {
611
- if (!Number.isSafeInteger(value) || value < 1 || value > 500) {
611
+ function usageLimit(value2) {
612
+ if (!Number.isSafeInteger(value2) || value2 < 1 || value2 > 500) {
612
613
  throw new Error("usage limit must be an integer from 1 to 500");
613
614
  }
614
- return value;
615
+ return value2;
615
616
  }
616
617
  function printUsage(body, out) {
617
618
  const aggregates = isRecord2(body) && isRecord2(body.aggregates) && Array.isArray(body.aggregates.byStatus) ? body.aggregates.byStatus.filter(isRecord2) : [];
@@ -647,15 +648,15 @@ when app/env run actor purpose/role route / policy tokens cost status`);
647
648
  ].join(" "));
648
649
  }
649
650
  }
650
- function numeric(value) {
651
- return typeof value === "number" && Number.isFinite(value) ? value : 0;
651
+ function numeric(value2) {
652
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
652
653
  }
653
- function formatMicrousd(value) {
654
- return typeof value === "number" && Number.isFinite(value) ? `$${(value / 1e6).toFixed(6)}` : "unpriced";
654
+ function formatMicrousd(value2) {
655
+ return typeof value2 === "number" && Number.isFinite(value2) ? `$${(value2 / 1e6).toFixed(6)}` : "unpriced";
655
656
  }
656
- function timestamp2(value) {
657
- if (typeof value !== "number" || !Number.isFinite(value)) return String(value ?? "");
658
- const date = new Date(value);
657
+ function timestamp2(value2) {
658
+ if (typeof value2 !== "number" || !Number.isFinite(value2)) return String(value2 ?? "");
659
+ const date = new Date(value2);
659
660
  return Number.isFinite(date.valueOf()) ? date.toISOString() : "";
660
661
  }
661
662
  async function responseBody2(res) {
@@ -672,8 +673,8 @@ function apiError2(action, status, body) {
672
673
  const message2 = error && typeof error.message === "string" ? error.message : isRecord2(body) && typeof body.message === "string" ? body.message : "request failed";
673
674
  return `${action} failed (${status}): ${message2}`;
674
675
  }
675
- function isRecord2(value) {
676
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
676
+ function isRecord2(value2) {
677
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
677
678
  }
678
679
 
679
680
  // src/admin-ai.ts
@@ -718,11 +719,11 @@ async function adminAi(options) {
718
719
  }
719
720
  if (options.action === "credential-set") {
720
721
  const provider = requireProvider(options.credentialProvider);
721
- const value = await secretInputValue(options);
722
+ const value2 = await secretInputValue(options);
722
723
  const res2 = await doFetch(`${platform}/registry/platform/ai-credentials/${encodeURIComponent(provider)}`, {
723
724
  method: "PUT",
724
725
  headers,
725
- body: JSON.stringify({ value })
726
+ body: JSON.stringify({ value: value2 })
726
727
  });
727
728
  const body2 = await responseBody3(res2);
728
729
  if (!res2.ok) throw new Error(apiError3(`store ${provider} platform credential`, res2.status, body2));
@@ -822,11 +823,11 @@ async function adminAi(options) {
822
823
  const policy = isRecord3(response2) && isRecord3(response2.policy) ? response2.policy : isRecord3(response2) ? response2 : {};
823
824
  out.log(options.json ? JSON.stringify({ policy }, null, 2) : `updated ${purpose}: ${String(policy.provider ?? "unchanged")}/${String(policy.model ?? "unchanged")}`);
824
825
  }
825
- function requireProvider(value) {
826
- if (value !== "anthropic" && value !== "openai" && value !== "google") {
826
+ function requireProvider(value2) {
827
+ if (value2 !== "anthropic" && value2 !== "openai" && value2 !== "google") {
827
828
  throw new Error("provider must be one of: anthropic, openai, google");
828
829
  }
829
- return value;
830
+ return value2;
830
831
  }
831
832
  function policyArray(body) {
832
833
  if (isRecord3(body) && Array.isArray(body.policies)) return body.policies.filter(isRecord3);
@@ -837,7 +838,7 @@ function catalogModels(body) {
837
838
  if (!isRecord3(body) || !isRecord3(body.catalog) || !Array.isArray(body.catalog.models)) {
838
839
  throw new Error("platform returned an invalid System AI model catalog");
839
840
  }
840
- return body.catalog.models.filter((value) => isRecord3(value) && typeof value.id === "string" && typeof value.provider === "string");
841
+ return body.catalog.models.filter((value2) => isRecord3(value2) && typeof value2.id === "string" && typeof value2.provider === "string");
841
842
  }
842
843
  async function responseBody3(res) {
843
844
  const text = await res.text();
@@ -853,14 +854,15 @@ function apiError3(action, status, body) {
853
854
  const message2 = error && typeof error.message === "string" ? error.message : isRecord3(body) && typeof body.message === "string" ? body.message : "request failed";
854
855
  return `${action} failed (${status}): ${message2}`;
855
856
  }
856
- function isRecord3(value) {
857
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
857
+ function isRecord3(value2) {
858
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
858
859
  }
859
860
 
860
861
  // src/config.ts
861
862
  import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
862
863
  import { dirname as dirname3, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
863
864
  import { pathToFileURL } from "url";
865
+ import { appServiceDefinition, appServiceIds } from "@odla-ai/apps";
864
866
 
865
867
  // src/integration-validation.ts
866
868
  function validateIntegrations(cfg, path, defaultServices) {
@@ -915,17 +917,17 @@ function validateProbes(integration, at) {
915
917
  }
916
918
  }
917
919
  }
918
- function isRecord4(value) {
919
- return value !== null && typeof value === "object" && !Array.isArray(value);
920
+ function isRecord4(value2) {
921
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
920
922
  }
921
- function safeText(value, max) {
922
- return typeof value === "string" && value.trim().length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
923
+ function safeText(value2, max) {
924
+ return typeof value2 === "string" && value2.trim().length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2);
923
925
  }
924
- function safeProbePath(value) {
925
- return typeof value === "string" && /^\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/.test(value);
926
+ function safeProbePath(value2) {
927
+ return typeof value2 === "string" && /^\/[A-Za-z0-9._~!$&'()*+,;=:@%/-]*$/.test(value2);
926
928
  }
927
- function validId(value) {
928
- return typeof value === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value);
929
+ function validId(value2) {
930
+ return typeof value2 === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value2);
929
931
  }
930
932
  function unique(values) {
931
933
  return [...new Set(values.filter(Boolean))];
@@ -948,6 +950,7 @@ async function loadProjectConfig(configPath = "odla.config.mjs") {
948
950
  const dbEndpoint = trimSlash(process.env.ODLA_DB_ENDPOINT || raw.dbEndpoint || platformUrl);
949
951
  const envs = unique2(raw.envs?.length ? raw.envs : DEFAULT_ENVS);
950
952
  const services = unique2(raw.services?.length ? raw.services : DEFAULT_SERVICES);
953
+ validateServices(services, resolved);
951
954
  validateCalendarConfig(raw, envs, services, resolved);
952
955
  const local = {
953
956
  tokenFile: resolve2(rootDir, raw.local?.tokenFile ?? ".odla/dev-token.json"),
@@ -966,10 +969,10 @@ async function loadProjectConfig(configPath = "odla.config.mjs") {
966
969
  local
967
970
  };
968
971
  }
969
- async function resolveDataExport(cfg, value, names) {
970
- if (value === void 0 || value === null || value === false) return void 0;
971
- if (typeof value !== "string") return value;
972
- const target = isAbsolute2(value) ? value : resolve2(cfg.rootDir, value);
972
+ async function resolveDataExport(cfg, value2, names) {
973
+ if (value2 === void 0 || value2 === null || value2 === false) return void 0;
974
+ if (typeof value2 !== "string") return value2;
975
+ const target = isAbsolute2(value2) ? value2 : resolve2(cfg.rootDir, value2);
973
976
  if (target.endsWith(".json")) {
974
977
  return JSON.parse(readFileSync2(target, "utf8"));
975
978
  }
@@ -978,7 +981,7 @@ async function resolveDataExport(cfg, value, names) {
978
981
  if (mod[name] !== void 0) return mod[name];
979
982
  }
980
983
  if (mod.default !== void 0) return mod.default;
981
- throw new Error(`${value} did not export ${names.join(", ")} or default`);
984
+ throw new Error(`${value2} did not export ${names.join(", ")} or default`);
982
985
  }
983
986
  function buildPlan(cfg) {
984
987
  const integrationSchema = cfg.integrations?.some((integration) => integration.schema) ?? false;
@@ -1012,9 +1015,9 @@ function calendarServiceConfig(cfg, env) {
1012
1015
  };
1013
1016
  }
1014
1017
  function calendarBookingPageUrl(cfg, env) {
1015
- const value = cfg.calendar?.google.bookingPageUrl?.[env];
1016
- if (value === void 0 || value === null) return value;
1017
- return new URL(value).toString();
1018
+ const value2 = cfg.calendar?.google.bookingPageUrl?.[env];
1019
+ if (value2 === void 0 || value2 === null) return value2;
1020
+ return new URL(value2).toString();
1018
1021
  }
1019
1022
  function rulesFromSchema(schema) {
1020
1023
  const entities = serializedEntities(schema);
@@ -1028,10 +1031,10 @@ function serializedEntities(schema) {
1028
1031
  if (!entities || typeof entities !== "object" || Array.isArray(entities)) return [];
1029
1032
  return Object.keys(entities);
1030
1033
  }
1031
- function envValue(value) {
1032
- if (!value) return void 0;
1033
- if (value.startsWith("$")) return process.env[value.slice(1)];
1034
- return value;
1034
+ function envValue(value2) {
1035
+ if (!value2) return void 0;
1036
+ if (value2.startsWith("$")) return process.env[value2.slice(1)];
1037
+ return value2;
1035
1038
  }
1036
1039
  function validateRawConfig(raw, path) {
1037
1040
  if (!raw || typeof raw !== "object") throw new Error(`${path} must export an object`);
@@ -1087,8 +1090,8 @@ function validateCalendarConfig(cfg, envs, services, path) {
1087
1090
  if (!isRecord5(google.bookingCalendar)) throw new Error(`${path}: calendar.google.bookingCalendar must map env names to one calendar id`);
1088
1091
  const unknownBookingEnv = Object.keys(google.bookingCalendar).find((env) => !envs.includes(env));
1089
1092
  if (unknownBookingEnv) throw new Error(`${path}: calendar.google.bookingCalendar.${unknownBookingEnv} is not in config envs`);
1090
- for (const [env, value] of Object.entries(google.bookingCalendar)) {
1091
- if (!safeText2(value, 1024)) {
1093
+ for (const [env, value2] of Object.entries(google.bookingCalendar)) {
1094
+ if (!safeText2(value2, 1024)) {
1092
1095
  throw new Error(`${path}: calendar.google.bookingCalendar.${env} must be a calendar id`);
1093
1096
  }
1094
1097
  }
@@ -1097,45 +1100,57 @@ function validateCalendarConfig(cfg, envs, services, path) {
1097
1100
  if (!isRecord5(google.bookingPageUrl)) throw new Error(`${path}: calendar.google.bookingPageUrl must map env names to HTTPS URLs or null`);
1098
1101
  const unknownBookingEnv = Object.keys(google.bookingPageUrl).find((env) => !envs.includes(env));
1099
1102
  if (unknownBookingEnv) throw new Error(`${path}: calendar.google.bookingPageUrl.${unknownBookingEnv} is not in config envs`);
1100
- for (const [env, value] of Object.entries(google.bookingPageUrl)) {
1101
- if (value !== null && !safeHttpsUrl(value)) {
1103
+ for (const [env, value2] of Object.entries(google.bookingPageUrl)) {
1104
+ if (value2 !== null && !safeHttpsUrl(value2)) {
1102
1105
  throw new Error(`${path}: calendar.google.bookingPageUrl.${env} must be an HTTPS URL without credentials or fragment`);
1103
1106
  }
1104
1107
  }
1105
1108
  }
1106
- if (enabled && !services.includes("db")) throw new Error(`${path}: calendar service requires the db service`);
1107
1109
  }
1108
- function assertOnly(value, allowed, label) {
1109
- const extra = Object.keys(value).find((key) => !allowed.includes(key));
1110
+ function validateServices(services, path) {
1111
+ for (const service of services) {
1112
+ const definition = appServiceDefinition(service);
1113
+ if (!definition) {
1114
+ throw new Error(`${path}: unknown service "${service}" (known: ${appServiceIds().join(", ")})`);
1115
+ }
1116
+ for (const dependency of definition.requires) {
1117
+ if (!services.includes(dependency)) {
1118
+ throw new Error(`${path}: ${service} service requires the ${dependency} service`);
1119
+ }
1120
+ }
1121
+ }
1122
+ }
1123
+ function assertOnly(value2, allowed, label) {
1124
+ const extra = Object.keys(value2).find((key) => !allowed.includes(key));
1110
1125
  if (extra) throw new Error(`${label}.${extra} is not supported`);
1111
1126
  }
1112
- function isRecord5(value) {
1113
- return value !== null && typeof value === "object" && !Array.isArray(value);
1127
+ function isRecord5(value2) {
1128
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
1114
1129
  }
1115
- function safeText2(value, max) {
1116
- return typeof value === "string" && value.trim().length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value);
1130
+ function safeText2(value2, max) {
1131
+ return typeof value2 === "string" && value2.trim().length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2);
1117
1132
  }
1118
- function safeHttpsUrl(value) {
1119
- if (typeof value !== "string" || value.length > 2048) return false;
1133
+ function safeHttpsUrl(value2) {
1134
+ if (typeof value2 !== "string" || value2.length > 2048) return false;
1120
1135
  try {
1121
- const url = new URL(value);
1136
+ const url = new URL(value2);
1122
1137
  return url.protocol === "https:" && !url.username && !url.password && !url.hash;
1123
1138
  } catch {
1124
1139
  return false;
1125
1140
  }
1126
1141
  }
1127
- function validId2(value) {
1128
- return typeof value === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value);
1142
+ function validId2(value2) {
1143
+ return typeof value2 === "string" && /^[a-z0-9][a-z0-9-]*$/.test(value2);
1129
1144
  }
1130
1145
  async function loadConfigModule(path) {
1131
1146
  if (path.endsWith(".json")) return JSON.parse(readFileSync2(path, "utf8"));
1132
1147
  const mod = await import(`${pathToFileURL(path).href}?t=${Date.now()}`);
1133
- const value = mod.default ?? mod.config;
1134
- if (typeof value === "function") return await value();
1135
- return value;
1148
+ const value2 = mod.default ?? mod.config;
1149
+ if (typeof value2 === "function") return await value2();
1150
+ return value2;
1136
1151
  }
1137
- function trimSlash(value) {
1138
- return value.replace(/\/+$/, "");
1152
+ function trimSlash(value2) {
1153
+ return value2.replace(/\/+$/, "");
1139
1154
  }
1140
1155
  function unique2(values) {
1141
1156
  return [...new Set(values.filter(Boolean))];
@@ -1151,44 +1166,44 @@ var REPLACEMENTS = [
1151
1166
  [/\b(ghp|gho|github_pat)_[A-Za-z0-9_]+/g, "$1_[redacted]"],
1152
1167
  [/\bAKIA[A-Z0-9]{12,}/g, "AKIA[redacted]"]
1153
1168
  ];
1154
- function redactSecrets(value) {
1155
- let result = value;
1169
+ function redactSecrets(value2) {
1170
+ let result = value2;
1156
1171
  for (const [pattern, replacement] of REPLACEMENTS) result = result.replace(pattern, replacement);
1157
1172
  return result;
1158
1173
  }
1159
1174
  function redactingOutput(output) {
1160
- const redactArgs = (args) => args.map((value) => redactOutputValue(value, /* @__PURE__ */ new WeakMap()));
1175
+ const redactArgs = (args) => args.map((value2) => redactOutputValue(value2, /* @__PURE__ */ new WeakMap()));
1161
1176
  return {
1162
1177
  log: (...args) => output.log(...redactArgs(args)),
1163
1178
  error: (...args) => output.error(...redactArgs(args))
1164
1179
  };
1165
1180
  }
1166
- function redactOutputValue(value, seen) {
1167
- if (typeof value === "string") return redactSecrets(value);
1168
- if (value instanceof Error) {
1169
- const redacted = new Error(redactSecrets(value.message));
1170
- redacted.name = value.name;
1171
- if (value.stack) redacted.stack = redactSecrets(value.stack);
1181
+ function redactOutputValue(value2, seen) {
1182
+ if (typeof value2 === "string") return redactSecrets(value2);
1183
+ if (value2 instanceof Error) {
1184
+ const redacted = new Error(redactSecrets(value2.message));
1185
+ redacted.name = value2.name;
1186
+ if (value2.stack) redacted.stack = redactSecrets(value2.stack);
1172
1187
  return redacted;
1173
1188
  }
1174
- if (!value || typeof value !== "object") return value;
1175
- const prior = seen.get(value);
1189
+ if (!value2 || typeof value2 !== "object") return value2;
1190
+ const prior = seen.get(value2);
1176
1191
  if (prior) return prior;
1177
- if (Array.isArray(value)) {
1192
+ if (Array.isArray(value2)) {
1178
1193
  const next2 = [];
1179
- seen.set(value, next2);
1180
- for (const item of value) next2.push(redactOutputValue(item, seen));
1194
+ seen.set(value2, next2);
1195
+ for (const item of value2) next2.push(redactOutputValue(item, seen));
1181
1196
  return next2;
1182
1197
  }
1183
- const prototype = Object.getPrototypeOf(value);
1184
- if (prototype !== Object.prototype && prototype !== null) return value;
1198
+ const prototype = Object.getPrototypeOf(value2);
1199
+ if (prototype !== Object.prototype && prototype !== null) return value2;
1185
1200
  const next = {};
1186
- seen.set(value, next);
1187
- for (const [key, item] of Object.entries(value)) next[key] = redactOutputValue(item, seen);
1201
+ seen.set(value2, next);
1202
+ for (const [key, item] of Object.entries(value2)) next[key] = redactOutputValue(item, seen);
1188
1203
  return next;
1189
1204
  }
1190
- function looksSecret(value) {
1191
- return redactSecrets(value) !== value || value.includes("-----BEGIN");
1205
+ function looksSecret(value2) {
1206
+ return redactSecrets(value2) !== value2 || value2.includes("-----BEGIN");
1192
1207
  }
1193
1208
 
1194
1209
  // src/calendar-errors.ts
@@ -1230,9 +1245,9 @@ async function readCalendarStatus(ctx) {
1230
1245
  }
1231
1246
  async function discoverGoogleCalendars(ctx) {
1232
1247
  const raw = await calendarJson(ctx, "/calendars", {});
1233
- const value = record(raw);
1234
- if (!value || !Array.isArray(value.calendars)) throw new Error("calendar discovery returned an invalid response");
1235
- return value.calendars.map((item, index) => {
1248
+ const value2 = record(raw);
1249
+ if (!value2 || !Array.isArray(value2.calendars)) throw new Error("calendar discovery returned an invalid response");
1250
+ return value2.calendars.map((item, index) => {
1236
1251
  const calendar = record(item);
1237
1252
  const id = textField(calendar?.id, 1024);
1238
1253
  if (!calendar || !id) throw new Error(`calendar discovery returned an invalid calendar at index ${index}`);
@@ -1254,10 +1269,10 @@ async function applyCalendarSettings(ctx, bookingPageUrl) {
1254
1269
  }
1255
1270
  async function startCalendarConnection(ctx) {
1256
1271
  const raw = await calendarJson(ctx, "/google/connect", { method: "POST", body: "{}" });
1257
- const value = wrapped(raw, "attempt");
1258
- const attemptId = textField(value.attemptId, 180);
1259
- const consentUrl = textField(value.consentUrl, 4096);
1260
- const expiresAt = timestamp3(value.expiresAt);
1272
+ const value2 = wrapped(raw, "attempt");
1273
+ const attemptId = textField(value2.attemptId, 180);
1274
+ const consentUrl = textField(value2.consentUrl, 4096);
1275
+ const expiresAt = timestamp3(value2.expiresAt);
1261
1276
  if (!attemptId || !consentUrl || expiresAt === void 0) throw new Error("calendar connect returned an invalid attempt");
1262
1277
  return { attemptId, consentUrl, expiresAt };
1263
1278
  }
@@ -1275,42 +1290,42 @@ async function requestCalendarDisconnect(ctx) {
1275
1290
  }
1276
1291
  function parseCalendarStatus(raw, env) {
1277
1292
  const outer = wrapped(raw, "calendar");
1278
- const value = record(outer.attempt) ?? record(outer.status) ?? outer;
1279
- const connection = record(value.connection) ?? {};
1280
- const config = record(value.config) ?? record(outer.config) ?? {};
1293
+ const value2 = record(outer.attempt) ?? record(outer.status) ?? outer;
1294
+ const connection = record(value2.connection) ?? {};
1295
+ const config = record(value2.config) ?? record(outer.config) ?? {};
1281
1296
  const googleConfig = record(config.google) ?? config;
1282
- const stateValue = calendarState(value.status ?? value.state ?? connection.status ?? connection.state);
1297
+ const stateValue = calendarState(value2.status ?? value2.state ?? connection.status ?? connection.state);
1283
1298
  if (!stateValue) {
1284
1299
  throw new Error("calendar status returned an invalid connection state");
1285
1300
  }
1286
- const providerValue = value.provider ?? connection.provider ?? config.provider ?? (config.google ? "google" : void 0);
1301
+ const providerValue = value2.provider ?? connection.provider ?? config.provider ?? (config.google ? "google" : void 0);
1287
1302
  if (providerValue !== void 0 && providerValue !== null && providerValue !== "google") {
1288
1303
  throw new Error("calendar status returned an unsupported provider");
1289
1304
  }
1290
- const accessValue = value.access ?? connection.access ?? config.access ?? googleConfig.access;
1305
+ const accessValue = value2.access ?? connection.access ?? config.access ?? googleConfig.access;
1291
1306
  if (accessValue !== void 0 && accessValue !== "book" && accessValue !== "read") {
1292
1307
  throw new Error("calendar status returned unsupported access");
1293
1308
  }
1294
- const errorValue = record(value.error) ?? record(connection.error);
1295
- const errorCode = textField(value.lastErrorCode, 128);
1296
- const bookingPageValue = Object.hasOwn(value, "bookingPageUrl") ? value.bookingPageUrl : Object.hasOwn(config, "bookingPageUrl") ? config.bookingPageUrl : googleConfig.bookingPageUrl;
1297
- const connected = typeof (value.connected ?? connection.connected) === "boolean" ? Boolean(value.connected ?? connection.connected) : ["healthy", "degraded"].includes(stateValue);
1298
- const bookingCalendarId = textField(value.bookingCalendarId ?? config.bookingCalendarId, 1024);
1309
+ const errorValue = record(value2.error) ?? record(connection.error);
1310
+ const errorCode = textField(value2.lastErrorCode, 128);
1311
+ const bookingPageValue = Object.hasOwn(value2, "bookingPageUrl") ? value2.bookingPageUrl : Object.hasOwn(config, "bookingPageUrl") ? config.bookingPageUrl : googleConfig.bookingPageUrl;
1312
+ const connected = typeof (value2.connected ?? connection.connected) === "boolean" ? Boolean(value2.connected ?? connection.connected) : ["healthy", "degraded"].includes(stateValue);
1313
+ const bookingCalendarId = textField(value2.bookingCalendarId ?? config.bookingCalendarId, 1024);
1299
1314
  return {
1300
1315
  env,
1301
- enabled: typeof value.enabled === "boolean" ? value.enabled : true,
1316
+ enabled: typeof value2.enabled === "boolean" ? value2.enabled : true,
1302
1317
  connected,
1303
- writable: typeof value.writable === "boolean" ? value.writable : stateValue === "healthy",
1318
+ writable: typeof value2.writable === "boolean" ? value2.writable : stateValue === "healthy",
1304
1319
  provider: providerValue === "google" ? "google" : null,
1305
1320
  status: stateValue,
1306
1321
  ...accessValue !== void 0 ? { access: "book" } : {},
1307
1322
  ...bookingCalendarId ? { bookingCalendarId } : {},
1308
1323
  calendars: calendarIds(
1309
- value.availabilityCalendars ?? config.availabilityCalendars ?? value.configuredCalendars ?? value.calendars ?? config.calendars ?? googleConfig.calendars
1324
+ value2.availabilityCalendars ?? config.availabilityCalendars ?? value2.configuredCalendars ?? value2.calendars ?? config.calendars ?? googleConfig.calendars
1310
1325
  ),
1311
1326
  ...optionalNullableUrl("bookingPageUrl", bookingPageValue),
1312
- grantedScopes: stringList(value.grantedScopes ?? connection.grantedScopes ?? connection.scopes),
1313
- ...optionalText("attemptId", value.attemptId ?? connection.attemptId, 180),
1327
+ grantedScopes: stringList(value2.grantedScopes ?? connection.grantedScopes ?? connection.scopes),
1328
+ ...optionalText("attemptId", value2.attemptId ?? connection.attemptId, 180),
1314
1329
  ...errorValue || errorCode ? { error: {
1315
1330
  ...textField(errorValue?.code, 128) ? { code: textField(errorValue?.code, 128) } : {},
1316
1331
  ...textField(errorValue?.message, 500) ? { message: textField(errorValue?.message, 500) } : {},
@@ -1318,9 +1333,9 @@ function parseCalendarStatus(raw, env) {
1318
1333
  } } : {}
1319
1334
  };
1320
1335
  }
1321
- function calendarState(value) {
1322
- if (typeof value !== "string") return null;
1323
- if (CALENDAR_STATES.includes(value)) return value;
1336
+ function calendarState(value2) {
1337
+ if (typeof value2 !== "string") return null;
1338
+ if (CALENDAR_STATES.includes(value2)) return value2;
1324
1339
  const legacy = {
1325
1340
  disabled: "not_connected",
1326
1341
  disconnected: "disconnected",
@@ -1331,7 +1346,7 @@ function calendarState(value) {
1331
1346
  ready: "healthy",
1332
1347
  error: "failed"
1333
1348
  };
1334
- return legacy[value] ?? null;
1349
+ return legacy[value2] ?? null;
1335
1350
  }
1336
1351
  async function calendarJson(ctx, suffix, init) {
1337
1352
  const platform = platformAudience(ctx.platform);
@@ -1365,50 +1380,50 @@ function wrapped(raw, key) {
1365
1380
  if (!outer) throw new Error("calendar returned an invalid response");
1366
1381
  return record(outer[key]) ?? outer;
1367
1382
  }
1368
- function record(value) {
1369
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
1383
+ function record(value2) {
1384
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
1370
1385
  }
1371
- function textField(value, max) {
1372
- return typeof value === "string" && value.length > 0 && value.length <= max && !/[\u0000-\u001f\u007f]/.test(value) ? value : void 0;
1386
+ function textField(value2, max) {
1387
+ return typeof value2 === "string" && value2.length > 0 && value2.length <= max && !/[\u0000-\u001f\u007f]/.test(value2) ? value2 : void 0;
1373
1388
  }
1374
- function stringList(value) {
1375
- return Array.isArray(value) ? [...new Set(value.filter((item) => !!textField(item, 4096)))] : [];
1389
+ function stringList(value2) {
1390
+ return Array.isArray(value2) ? [...new Set(value2.filter((item) => !!textField(item, 4096)))] : [];
1376
1391
  }
1377
- function calendarIds(value) {
1378
- if (!Array.isArray(value)) return [];
1379
- return [...new Set(value.flatMap((item) => {
1392
+ function calendarIds(value2) {
1393
+ if (!Array.isArray(value2)) return [];
1394
+ return [...new Set(value2.flatMap((item) => {
1380
1395
  if (typeof item === "string") return textField(item, 4096) ? [item] : [];
1381
1396
  const calendar = record(item);
1382
1397
  const id = textField(calendar?.id, 4096);
1383
1398
  return id && calendar?.selected !== false ? [id] : [];
1384
1399
  }))];
1385
1400
  }
1386
- function timestamp3(value) {
1387
- if (typeof value === "number" && Number.isFinite(value) && value >= 0) return value;
1388
- if (typeof value === "string") {
1389
- const parsed = Date.parse(value);
1401
+ function timestamp3(value2) {
1402
+ if (typeof value2 === "number" && Number.isFinite(value2) && value2 >= 0) return value2;
1403
+ if (typeof value2 === "string") {
1404
+ const parsed = Date.parse(value2);
1390
1405
  if (Number.isFinite(parsed)) return parsed;
1391
1406
  }
1392
1407
  return void 0;
1393
1408
  }
1394
- function optionalText(key, value, max) {
1395
- const parsed = textField(value, max);
1409
+ function optionalText(key, value2, max) {
1410
+ const parsed = textField(value2, max);
1396
1411
  return parsed ? { [key]: parsed } : {};
1397
1412
  }
1398
- function optionalNullableUrl(key, value) {
1399
- if (value === null) return { [key]: null };
1400
- const parsed = textField(value, 4096);
1413
+ function optionalNullableUrl(key, value2) {
1414
+ if (value2 === null) return { [key]: null };
1415
+ const parsed = textField(value2, 4096);
1401
1416
  return parsed ? { [key]: parsed } : {};
1402
1417
  }
1403
- function identifier(value, name) {
1404
- if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,179}$/.test(value)) throw new Error(`${name} is invalid`);
1405
- return value;
1418
+ function identifier(value2, name) {
1419
+ if (typeof value2 !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,179}$/.test(value2)) throw new Error(`${name} is invalid`);
1420
+ return value2;
1406
1421
  }
1407
- function credential(value) {
1408
- if (typeof value !== "string" || value.length < 8 || value.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value)) {
1422
+ function credential(value2) {
1423
+ if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
1409
1424
  throw new Error("calendar requires an odla developer token");
1410
1425
  }
1411
- return value;
1426
+ return value2;
1412
1427
  }
1413
1428
 
1414
1429
  // src/calendar-poll.ts
@@ -1569,11 +1584,11 @@ async function connectWithContext(ctx, options) {
1569
1584
  }
1570
1585
  throw new Error('Google Calendar consent timed out; run "odla-ai calendar status" and retry connect');
1571
1586
  }
1572
- function trustedCalendarConsentUrl(platform, value) {
1587
+ function trustedCalendarConsentUrl(platform, value2) {
1573
1588
  const origin = platformAudience(platform);
1574
1589
  let url;
1575
1590
  try {
1576
- url = value.startsWith("/") ? new URL(value, origin) : new URL(value);
1591
+ url = value2.startsWith("/") ? new URL(value2, origin) : new URL(value2);
1577
1592
  } catch {
1578
1593
  throw new Error("odla.ai returned an invalid calendar consent URL");
1579
1594
  }
@@ -1584,9 +1599,9 @@ function trustedCalendarConsentUrl(platform, value) {
1584
1599
  }
1585
1600
  return url.toString();
1586
1601
  }
1587
- function pollTimeout(value = 10 * 6e4) {
1588
- if (!Number.isSafeInteger(value) || value < 1e3 || value > 60 * 6e4) throw new Error("calendar poll timeout must be 1000-3600000ms");
1589
- return value;
1602
+ function pollTimeout(value2 = 10 * 6e4) {
1603
+ if (!Number.isSafeInteger(value2) || value2 < 1e3 || value2 > 60 * 6e4) throw new Error("calendar poll timeout must be 1000-3600000ms");
1604
+ return value2;
1590
1605
  }
1591
1606
  function productionConsent(env, yes, action) {
1592
1607
  if ((env === "prod" || env === "production") && !yes) throw new Error(`refusing to ${action} for "${env}" without --yes`);
@@ -1618,6 +1633,7 @@ var CAPABILITIES = {
1618
1633
  "validate integration contracts offline and smoke-test a provisioned db environment plus anonymous capability routes",
1619
1634
  "save and explicitly select non-secret named operator contexts with isolated credential caches; resolve and explain platform, app, environment, and credential provenance without authenticating; then run PM, Discussions, o11y, runbook, and identity operations outside a project checkout",
1620
1635
  "read one versioned o11y status envelope spanning application RED, exact Worker versions and Cloudflare colos observed in traffic, current live-sync freshness/load, the protected commit-to-visible canary, collector ingest/scheduler trust, provider-owned runtime metrics, account-scoped Durable Object, D1, and R2 evidence under odla-db, and a bounded machine verdict",
1636
+ "read one canonical platform fleet snapshot over private service bindings, including release identities, probe latency, Cloudflare load/runtime freshness, explicit unknowns, and stable next actions through a read-only capability",
1621
1637
  "inspect durable agent wakeups as a versioned JSON envelope and explicitly requeue one dead-lettered job with a scoped environment credential",
1622
1638
  "run app-attributed hosted security discovery and independent validation without provider keys",
1623
1639
  "connect/revoke source-read-only GitHub sources and drive commit-pinned hosted security jobs without PATs or provider keys",
@@ -1801,8 +1817,8 @@ function wranglerWarnings(rootDir) {
1801
1817
  }
1802
1818
  const vars = block.vars;
1803
1819
  if (vars && typeof vars === "object") {
1804
- for (const [name, value] of Object.entries(vars)) {
1805
- if (name === "ODLA_API_KEY" || name === "ODLA_O11Y_TOKEN" || typeof value === "string" && looksSecret(value)) {
1820
+ for (const [name, value2] of Object.entries(vars)) {
1821
+ if (name === "ODLA_API_KEY" || name === "ODLA_O11Y_TOKEN" || typeof value2 === "string" && looksSecret(value2)) {
1806
1822
  warnings.push(`wrangler ${label}vars.${name} looks like a secret \u2014 use "odla-ai secrets push" / wrangler secret put, never vars`);
1807
1823
  }
1808
1824
  }
@@ -1970,27 +1986,27 @@ function isUniqueAttr(schema, ns, attr) {
1970
1986
  const definition = entity.attrs[attr];
1971
1987
  return isRecord6(definition) && definition.unique === true;
1972
1988
  }
1973
- function normalizeSchema(value) {
1974
- if (value === void 0 || value === null) return { entities: {}, links: {} };
1975
- if (!isRecord6(value) || !isRecord6(value.entities)) {
1989
+ function normalizeSchema(value2) {
1990
+ if (value2 === void 0 || value2 === null) return { entities: {}, links: {} };
1991
+ if (!isRecord6(value2) || !isRecord6(value2.entities)) {
1976
1992
  throw new Error("db schema must be a serialized schema object with an entities map");
1977
1993
  }
1978
- if (value.links !== void 0 && !isRecord6(value.links)) throw new Error("db schema links must be an object");
1994
+ if (value2.links !== void 0 && !isRecord6(value2.links)) throw new Error("db schema links must be an object");
1979
1995
  return {
1980
- entities: { ...value.entities },
1981
- links: { ...value.links ?? {} }
1996
+ entities: { ...value2.entities },
1997
+ links: { ...value2.links ?? {} }
1982
1998
  };
1983
1999
  }
1984
2000
  function mergeMap(target, fragment, label) {
1985
- for (const [name, value] of Object.entries(fragment)) {
1986
- if (Object.hasOwn(target, name) && !isDeepStrictEqual(target[name], value)) {
2001
+ for (const [name, value2] of Object.entries(fragment)) {
2002
+ if (Object.hasOwn(target, name) && !isDeepStrictEqual(target[name], value2)) {
1987
2003
  throw new Error(`${label} "${name}" conflicts with an existing definition`);
1988
2004
  }
1989
- target[name] = value;
2005
+ target[name] = value2;
1990
2006
  }
1991
2007
  }
1992
- function isRecord6(value) {
1993
- return value !== null && typeof value === "object" && !Array.isArray(value);
2008
+ function isRecord6(value2) {
2009
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
1994
2010
  }
1995
2011
 
1996
2012
  // src/doctor.ts
@@ -2031,9 +2047,9 @@ async function doctor(options) {
2031
2047
  warnings.push(...integrationWarnings(database.integrations, schema, rules));
2032
2048
  if (cfg.services.includes("ai") && !cfg.ai?.provider) warnings.push("ai service is enabled but ai.provider is not set");
2033
2049
  if (cfg.auth?.clerk) {
2034
- for (const [env, value] of Object.entries(cfg.auth.clerk)) {
2035
- if (typeof value === "string" && value.startsWith("$") && !process.env[value.slice(1)]) {
2036
- warnings.push(`auth.clerk.${env} references unset env var ${value}`);
2050
+ for (const [env, value2] of Object.entries(cfg.auth.clerk)) {
2051
+ if (typeof value2 === "string" && value2.startsWith("$") && !process.env[value2.slice(1)]) {
2052
+ warnings.push(`auth.clerk.${env} references unset env var ${value2}`);
2037
2053
  }
2038
2054
  }
2039
2055
  }
@@ -2070,6 +2086,7 @@ async function doctor(options) {
2070
2086
  // src/init.ts
2071
2087
  import { existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
2072
2088
  import { dirname as dirname4, resolve as resolve4 } from "path";
2089
+ import { appServiceDefinition as appServiceDefinition2, appServiceIds as appServiceIds2 } from "@odla-ai/apps";
2073
2090
  function initProject(options) {
2074
2091
  const out = options.stdout ?? console;
2075
2092
  const rootDir = resolve4(options.rootDir ?? process.cwd());
@@ -2082,7 +2099,13 @@ function initProject(options) {
2082
2099
  }
2083
2100
  const envs = options.envs?.length ? options.envs : ["dev"];
2084
2101
  const services = options.services?.length ? options.services : ["db", "ai"];
2085
- if (services.includes("calendar") && !services.includes("db")) throw new Error("--services calendar requires db");
2102
+ for (const service of services) {
2103
+ const definition = appServiceDefinition2(service);
2104
+ if (!definition) throw new Error(`--services contains unknown service "${service}" (known: ${appServiceIds2().join(", ")})`);
2105
+ for (const dependency of definition.requires) {
2106
+ if (!services.includes(dependency)) throw new Error(`--services ${service} requires ${dependency}`);
2107
+ }
2108
+ }
2086
2109
  const aiProvider = options.aiProvider ?? "anthropic";
2087
2110
  mkdirSync2(dirname4(configPath), { recursive: true });
2088
2111
  mkdirSync2(resolve4(rootDir, "src/odla"), { recursive: true });
@@ -2280,38 +2303,38 @@ async function secretsSet(options) {
2280
2303
  if (name.startsWith("$")) {
2281
2304
  throw new Error('"$"-prefixed vault names are platform-reserved; for the Clerk secret key use "odla-ai secrets set-clerk-key"');
2282
2305
  }
2283
- const { cfg, tenantId, value, doFetch, out } = await resolveVaultWrite(options);
2306
+ const { cfg, tenantId, value: value2, doFetch, out } = await resolveVaultWrite(options);
2284
2307
  const token = await getDeveloperToken(cfg, options, doFetch, out);
2285
2308
  try {
2286
- await putSecret({ endpoint: cfg.dbEndpoint, token, fetch: doFetch }, tenantId, name, value);
2309
+ await putSecret({ endpoint: cfg.dbEndpoint, token, fetch: doFetch }, tenantId, name, value2);
2287
2310
  } catch (err) {
2288
- throw new Error(scrubValue(err instanceof Error ? err.message : String(err), value));
2311
+ throw new Error(scrubValue(err instanceof Error ? err.message : String(err), value2));
2289
2312
  }
2290
2313
  out.log(`${name} stored in the ${tenantId} vault (write-only; the value was never echoed and cannot be read back here)`);
2291
2314
  }
2292
2315
  async function secretsSetClerkKey(options) {
2293
- const { cfg, tenantId, value, doFetch, out } = await resolveVaultWrite(options);
2294
- if (!value.startsWith("sk_")) throw new Error("the Clerk secret key must start with sk_ (sk_test_\u2026 or sk_live_\u2026)");
2295
- if (value.startsWith("sk_test_") && PROD_ENV_NAMES2.has(options.env)) {
2316
+ const { cfg, tenantId, value: value2, doFetch, out } = await resolveVaultWrite(options);
2317
+ if (!value2.startsWith("sk_")) throw new Error("the Clerk secret key must start with sk_ (sk_test_\u2026 or sk_live_\u2026)");
2318
+ if (value2.startsWith("sk_test_") && PROD_ENV_NAMES2.has(options.env)) {
2296
2319
  throw new Error(`refusing to store an sk_test_ Clerk key for "${options.env}" \u2014 use the production instance's sk_live_ key`);
2297
2320
  }
2298
- if (value.startsWith("sk_live_") && !PROD_ENV_NAMES2.has(options.env) && !options.yes) {
2321
+ if (value2.startsWith("sk_live_") && !PROD_ENV_NAMES2.has(options.env) && !options.yes) {
2299
2322
  throw new Error(`refusing to store an sk_live_ Clerk key for "${options.env}" without --yes (live users would sync into a non-prod tenant)`);
2300
2323
  }
2301
2324
  const token = await getDeveloperToken(cfg, options, doFetch, out);
2302
2325
  const res = await doFetch(`${cfg.dbEndpoint}/admin/apps/${encodeURIComponent(tenantId)}/clerk-secret`, {
2303
2326
  method: "POST",
2304
2327
  headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
2305
- body: JSON.stringify({ value })
2328
+ body: JSON.stringify({ value: value2 })
2306
2329
  });
2307
2330
  if (!res.ok) {
2308
- const text = scrubValue((await res.text().catch(() => "")).slice(0, 300), value);
2331
+ const text = scrubValue((await res.text().catch(() => "")).slice(0, 300), value2);
2309
2332
  throw new Error(`store Clerk secret key failed (${res.status}): ${text || "request failed"}`);
2310
2333
  }
2311
2334
  out.log(`Clerk secret key stored for ${tenantId} ($clerk_secret, reserved + write-only; the value was never echoed)`);
2312
2335
  }
2313
- function scrubValue(text, value) {
2314
- return redactSecrets(text).split(value).join("[value redacted]");
2336
+ function scrubValue(text, value2) {
2337
+ return redactSecrets(text).split(value2).join("[value redacted]");
2315
2338
  }
2316
2339
  async function resolveVaultWrite(options) {
2317
2340
  const out = options.stdout ?? console;
@@ -2323,8 +2346,8 @@ async function resolveVaultWrite(options) {
2323
2346
  if (PROD_ENV_NAMES2.has(options.env) && !options.yes) {
2324
2347
  throw new Error(`refusing to store a secret for "${options.env}" without --yes`);
2325
2348
  }
2326
- const value = await secretInputValue(options, "secret");
2327
- return { cfg, tenantId: tenantIdFor(cfg.app.id, options.env), value, doFetch, out };
2349
+ const value2 = await secretInputValue(options, "secret");
2350
+ return { cfg, tenantId: tenantIdFor(cfg.app.id, options.env), value: value2, doFetch, out };
2328
2351
  }
2329
2352
 
2330
2353
  // src/skill.ts
@@ -2765,31 +2788,31 @@ async function requestHostedSecurityJson(options, path, init, action) {
2765
2788
  }
2766
2789
  return body;
2767
2790
  }
2768
- function hostedIdentifier(value, name) {
2769
- const result = optionalHostedText(value, name, 180);
2791
+ function hostedIdentifier(value2, name) {
2792
+ const result = optionalHostedText(value2, name, 180);
2770
2793
  if (!result || !/^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(result)) {
2771
2794
  throw new Error(`${name} is invalid`);
2772
2795
  }
2773
2796
  return result;
2774
2797
  }
2775
- function positivePolicyVersion(value, name) {
2776
- if (!Number.isSafeInteger(value) || value < 1) {
2798
+ function positivePolicyVersion(value2, name) {
2799
+ if (!Number.isSafeInteger(value2) || value2 < 1) {
2777
2800
  throw new Error(`${name} is invalid`);
2778
2801
  }
2779
- return value;
2802
+ return value2;
2780
2803
  }
2781
- function optionalHostedText(value, name, maxLength) {
2782
- if (value === void 0 || value === null || value === "") return void 0;
2783
- if (typeof value !== "string" || value.length > maxLength || /[\u0000-\u001f\u007f]/.test(value)) {
2804
+ function optionalHostedText(value2, name, maxLength) {
2805
+ if (value2 === void 0 || value2 === null || value2 === "") return void 0;
2806
+ if (typeof value2 !== "string" || value2.length > maxLength || /[\u0000-\u001f\u007f]/.test(value2)) {
2784
2807
  throw new Error(`${name} is invalid`);
2785
2808
  }
2786
- return value;
2809
+ return value2;
2787
2810
  }
2788
- function githubRepositoryName(value) {
2789
- if (typeof value !== "string" || value.length > 201) {
2811
+ function githubRepositoryName(value2) {
2812
+ if (typeof value2 !== "string" || value2.length > 201) {
2790
2813
  throw new Error("repository must be owner/name");
2791
2814
  }
2792
- const parts = value.split("/");
2815
+ const parts = value2.split("/");
2793
2816
  const owner = parts[0] ?? "";
2794
2817
  const name = (parts[1] ?? "").replace(/\.git$/i, "");
2795
2818
  if (parts.length !== 2 || !/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,98}[A-Za-z0-9])?$/.test(owner) || !/^[A-Za-z0-9_.-]{1,100}$/.test(name) || name === "." || name === "..") {
@@ -2797,10 +2820,10 @@ function githubRepositoryName(value) {
2797
2820
  }
2798
2821
  return `${owner}/${name}`;
2799
2822
  }
2800
- function trustedGitHubInstallUrl(value) {
2823
+ function trustedGitHubInstallUrl(value2) {
2801
2824
  let url;
2802
2825
  try {
2803
- url = new URL(value);
2826
+ url = new URL(value2);
2804
2827
  } catch {
2805
2828
  throw new Error("odla.ai returned an invalid GitHub installation URL");
2806
2829
  }
@@ -2809,17 +2832,17 @@ function trustedGitHubInstallUrl(value) {
2809
2832
  }
2810
2833
  return url.toString();
2811
2834
  }
2812
- function hostedPollInterval(value = 2e3) {
2813
- if (!Number.isSafeInteger(value) || value < 100 || value > 3e4) {
2835
+ function hostedPollInterval(value2 = 2e3) {
2836
+ if (!Number.isSafeInteger(value2) || value2 < 100 || value2 > 3e4) {
2814
2837
  throw new Error("poll interval must be 100-30000ms");
2815
2838
  }
2816
- return value;
2839
+ return value2;
2817
2840
  }
2818
- function hostedPollTimeout(value = 10 * 6e4) {
2819
- if (!Number.isSafeInteger(value) || value < 1e3 || value > 60 * 6e4) {
2841
+ function hostedPollTimeout(value2 = 10 * 6e4) {
2842
+ if (!Number.isSafeInteger(value2) || value2 < 1e3 || value2 > 60 * 6e4) {
2820
2843
  throw new Error("poll timeout must be 1000-3600000ms");
2821
2844
  }
2822
- return value;
2845
+ return value2;
2823
2846
  }
2824
2847
  async function waitForHostedPoll(milliseconds, signal) {
2825
2848
  if (signal?.aborted) throw signal.reason ?? new DOMException("aborted", "AbortError");
@@ -2831,16 +2854,16 @@ async function waitForHostedPoll(milliseconds, signal) {
2831
2854
  }, { once: true });
2832
2855
  });
2833
2856
  }
2834
- function isValidHostedSecurityPlan(value, env) {
2835
- if (!value || value.env !== env || !/^sha256:[a-f0-9]{64}$/.test(value.planDigest) || value.consentContract !== "odla.hosted-security-consent.v1" || value.reportProjection !== "odla.hosted-security-report.v1" || value.redactionContract !== "odla.best-effort-credential-pattern-redaction.v1" || typeof value.promptBundle !== "string" || value.promptBundle.length < 1 || value.promptBundle.length > 100 || typeof value.ready !== "boolean" || typeof value.independent !== "boolean" || value.sourceDisclosure !== "redacted" || value.targetExecution !== false || !Number.isSafeInteger(value.reportRetentionDays) || value.reportRetentionDays < 1) return false;
2857
+ function isValidHostedSecurityPlan(value2, env) {
2858
+ if (!value2 || value2.env !== env || !/^sha256:[a-f0-9]{64}$/.test(value2.planDigest) || value2.consentContract !== "odla.hosted-security-consent.v1" || value2.reportProjection !== "odla.hosted-security-report.v1" || value2.redactionContract !== "odla.best-effort-credential-pattern-redaction.v1" || typeof value2.promptBundle !== "string" || value2.promptBundle.length < 1 || value2.promptBundle.length > 100 || typeof value2.ready !== "boolean" || typeof value2.independent !== "boolean" || value2.sourceDisclosure !== "redacted" || value2.targetExecution !== false || !Number.isSafeInteger(value2.reportRetentionDays) || value2.reportRetentionDays < 1) return false;
2836
2859
  const validRoute = (route2, purpose) => !!route2 && route2.purpose === purpose && typeof route2.enabled === "boolean" && typeof route2.credentialReady === "boolean" && typeof route2.provider === "string" && route2.provider.length > 0 && route2.provider.length <= 100 && typeof route2.model === "string" && route2.model.length > 0 && route2.model.length <= 200 && Number.isSafeInteger(route2.policyVersion) && route2.policyVersion >= 1 && Number.isSafeInteger(route2.maxCallsPerRun) && route2.maxCallsPerRun >= 1 && Number.isSafeInteger(route2.maxInputBytes) && route2.maxInputBytes >= 1 && Number.isSafeInteger(route2.maxOutputTokens) && route2.maxOutputTokens >= 1;
2837
- return validRoute(value.routes?.discovery, "security.discovery") && validRoute(value.routes?.validation, "security.validation");
2860
+ return validRoute(value2.routes?.discovery, "security.discovery") && validRoute(value2.routes?.validation, "security.validation");
2838
2861
  }
2839
- function hostedSecurityCredential(value) {
2840
- if (typeof value !== "string" || value.length < 8 || value.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value)) {
2862
+ function hostedSecurityCredential(value2) {
2863
+ if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
2841
2864
  throw new Error("Hosted security requires an injected odla developer token");
2842
2865
  }
2843
- return value;
2866
+ return value2;
2844
2867
  }
2845
2868
 
2846
2869
  // src/security-hosted-github.ts
@@ -3068,24 +3091,24 @@ var CONTROL = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/;
3068
3091
  var HarnessProtocolError = class extends Error {
3069
3092
  name = "HarnessProtocolError";
3070
3093
  };
3071
- function record2(value) {
3072
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
3094
+ function record2(value2) {
3095
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
3073
3096
  }
3074
- function boundedText(value, label, max) {
3075
- if (typeof value !== "string" || !value || value.length > max || CONTROL.test(value)) {
3097
+ function boundedText(value2, label, max) {
3098
+ if (typeof value2 !== "string" || !value2 || value2.length > max || CONTROL.test(value2)) {
3076
3099
  throw new HarnessProtocolError(`${label} must be a non-empty string of at most ${max} characters`);
3077
3100
  }
3078
- return value;
3101
+ return value2;
3079
3102
  }
3080
3103
  function parseAgentOutput(line) {
3081
3104
  if (Buffer.byteLength(line, "utf8") > 1e6) throw new HarnessProtocolError("agent message exceeds 1 MB");
3082
- let value;
3105
+ let value2;
3083
3106
  try {
3084
- value = JSON.parse(line);
3107
+ value2 = JSON.parse(line);
3085
3108
  } catch {
3086
3109
  throw new HarnessProtocolError("agent emitted invalid JSON");
3087
3110
  }
3088
- const message2 = record2(value);
3111
+ const message2 = record2(value2);
3089
3112
  if (!message2 || message2.protocolVersion !== HARNESS_PROTOCOL_VERSION) {
3090
3113
  throw new HarnessProtocolError(`agent protocolVersion must be ${HARNESS_PROTOCOL_VERSION}`);
3091
3114
  }
@@ -3394,7 +3417,7 @@ async function gitOutput(cwd, args, maxBytes) {
3394
3417
  else stdout.push(chunk);
3395
3418
  });
3396
3419
  child.stderr.on("data", (chunk) => {
3397
- if (stderr.reduce((sum, value) => sum + value.byteLength, 0) < 16384) stderr.push(chunk);
3420
+ if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
3398
3421
  });
3399
3422
  const code = await new Promise((accept, reject) => {
3400
3423
  child.once("error", reject);
@@ -3415,7 +3438,7 @@ async function gitBlobs(cwd, entries, maxBytes) {
3415
3438
  else stdout.push(chunk);
3416
3439
  });
3417
3440
  child.stderr.on("data", (chunk) => {
3418
- if (stderr.reduce((sum, value) => sum + value.byteLength, 0) < 16384) stderr.push(chunk);
3441
+ if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
3419
3442
  });
3420
3443
  child.stdin.end(`${entries.map((entry) => entry.hash).join("\n")}
3421
3444
  `);
@@ -3453,8 +3476,8 @@ async function materializeGitTree(source, commitSha, options = {}) {
3453
3476
  const maxFiles = options.maxFiles ?? 2e4;
3454
3477
  const maxBytes = options.maxBytes ?? 512 * 1024 * 1024;
3455
3478
  const inventory = (await gitOutput(sourceDir, ["ls-tree", "-rz", commitSha], 16 * 1024 * 1024)).toString("utf8").split("\0").filter(Boolean);
3456
- const entries = inventory.flatMap((record7) => {
3457
- const match = /^(100644|100755) blob ([0-9a-f]{40,64})\t([\s\S]+)$/.exec(record7);
3479
+ const entries = inventory.flatMap((record8) => {
3480
+ const match = /^(100644|100755) blob ([0-9a-f]{40,64})\t([\s\S]+)$/.exec(record8);
3458
3481
  return match && allowedWorkspacePath(match[3]) ? [{ mode: match[1], hash: match[2], path: match[3] }] : [];
3459
3482
  });
3460
3483
  if (entries.length > maxFiles) throw new Error(`workspace exceeds ${maxFiles} files`);
@@ -3529,7 +3552,7 @@ async function gitSourceFiles(sourceDir, maxFiles, maxBytes) {
3529
3552
  else stdout.push(chunk);
3530
3553
  });
3531
3554
  child.stderr.on("data", (chunk) => {
3532
- if (stderr.reduce((sum, value) => sum + value.byteLength, 0) < 16384) stderr.push(chunk);
3555
+ if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
3533
3556
  });
3534
3557
  const code = await new Promise((accept, reject) => {
3535
3558
  child.once("error", reject);
@@ -3589,7 +3612,7 @@ async function captureGitDiff(root, maxBytes) {
3589
3612
  else stdout.push(chunk);
3590
3613
  });
3591
3614
  child.stderr.on("data", (chunk) => {
3592
- if (stderr.reduce((sum, value) => sum + value.byteLength, 0) < 16384) stderr.push(chunk);
3615
+ if (stderr.reduce((sum, value2) => sum + value2.byteLength, 0) < 16384) stderr.push(chunk);
3593
3616
  });
3594
3617
  const code = await new Promise((accept, reject) => {
3595
3618
  child.once("error", reject);
@@ -3676,34 +3699,34 @@ var CamelError = class extends Error {
3676
3699
  };
3677
3700
 
3678
3701
  // ../camel/dist/chunk-L5DYU2E2.js
3679
- function canonicalJson(value) {
3680
- return JSON.stringify(normalize(value));
3702
+ function canonicalJson(value2) {
3703
+ return JSON.stringify(normalize(value2));
3681
3704
  }
3682
- async function sha256Hex(value) {
3683
- const bytes = typeof value === "string" ? new TextEncoder().encode(value) : value;
3705
+ async function sha256Hex(value2) {
3706
+ const bytes = typeof value2 === "string" ? new TextEncoder().encode(value2) : value2;
3684
3707
  const digest = await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes).buffer);
3685
3708
  return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
3686
3709
  }
3687
- function utf8Length(value) {
3688
- if (typeof value === "string") return new TextEncoder().encode(value).byteLength;
3689
- if (value instanceof Uint8Array) return value.byteLength;
3710
+ function utf8Length(value2) {
3711
+ if (typeof value2 === "string") return new TextEncoder().encode(value2).byteLength;
3712
+ if (value2 instanceof Uint8Array) return value2.byteLength;
3690
3713
  try {
3691
- return new TextEncoder().encode(canonicalJson(value)).byteLength;
3714
+ return new TextEncoder().encode(canonicalJson(value2)).byteLength;
3692
3715
  } catch {
3693
3716
  throw new CamelError("conversion_rejected", "Unsafe input could not be canonically measured.");
3694
3717
  }
3695
3718
  }
3696
- function normalize(value) {
3697
- if (value === null || typeof value === "string" || typeof value === "boolean") return value;
3698
- if (typeof value === "number") {
3699
- if (!Number.isFinite(value)) throw new CamelError("state_conflict", "Canonical JSON rejects non-finite numbers.");
3700
- return value;
3719
+ function normalize(value2) {
3720
+ if (value2 === null || typeof value2 === "string" || typeof value2 === "boolean") return value2;
3721
+ if (typeof value2 === "number") {
3722
+ if (!Number.isFinite(value2)) throw new CamelError("state_conflict", "Canonical JSON rejects non-finite numbers.");
3723
+ return value2;
3701
3724
  }
3702
- if (Array.isArray(value)) return value.map(normalize);
3703
- if (value instanceof Uint8Array) return { $bytes: [...value] };
3704
- if (typeof value === "object") {
3705
- const record7 = value;
3706
- return Object.fromEntries(Object.keys(record7).filter((key) => record7[key] !== void 0).sort().map((key) => [key, normalize(record7[key])]));
3725
+ if (Array.isArray(value2)) return value2.map(normalize);
3726
+ if (value2 instanceof Uint8Array) return { $bytes: [...value2] };
3727
+ if (typeof value2 === "object") {
3728
+ const record8 = value2;
3729
+ return Object.fromEntries(Object.keys(record8).filter((key) => record8[key] !== void 0).sort().map((key) => [key, normalize(record8[key])]));
3707
3730
  }
3708
3731
  throw new CamelError("state_conflict", "Canonical JSON rejects unsupported values.");
3709
3732
  }
@@ -3712,10 +3735,10 @@ function canRead(readers, readerId) {
3712
3735
  }
3713
3736
  function dependenciesOf(values, influence = "data") {
3714
3737
  const result = [];
3715
- for (const value of values) {
3716
- result.push(...value.label.dependencies);
3717
- for (const ref of value.label.provenance) {
3718
- result.push({ ref, influence, promptSafetyAtUse: value.label.promptSafety });
3738
+ for (const value2 of values) {
3739
+ result.push(...value2.label.dependencies);
3740
+ for (const ref of value2.label.provenance) {
3741
+ result.push({ ref, influence, promptSafetyAtUse: value2.label.promptSafety });
3719
3742
  }
3720
3743
  }
3721
3744
  const unique3 = /* @__PURE__ */ new Map();
@@ -3726,32 +3749,32 @@ function dependenciesOf(values, influence = "data") {
3726
3749
  // ../camel/dist/chunk-S7EVNA2U.js
3727
3750
  var camelValueBrand = /* @__PURE__ */ Symbol("@odla-ai/camel/value");
3728
3751
  var authenticCamelValues = /* @__PURE__ */ new WeakSet();
3729
- function isCamelValue(value) {
3730
- return typeof value === "object" && value !== null && authenticCamelValues.has(value);
3752
+ function isCamelValue(value2) {
3753
+ return typeof value2 === "object" && value2 !== null && authenticCamelValues.has(value2);
3731
3754
  }
3732
- function isSafe(value) {
3733
- return isCamelValue(value) && value.label.promptSafety === "safe";
3755
+ function isSafe(value2) {
3756
+ return isCamelValue(value2) && value2.label.promptSafety === "safe";
3734
3757
  }
3735
- function isUnsafe(value) {
3736
- return isCamelValue(value) && value.label.promptSafety === "unsafe";
3758
+ function isUnsafe(value2) {
3759
+ return isCamelValue(value2) && value2.label.promptSafety === "unsafe";
3737
3760
  }
3738
- function createSafeInternal(value, safeBasis, metadata2) {
3739
- return createValue(value, {
3761
+ function createSafeInternal(value2, safeBasis, metadata2) {
3762
+ return createValue(value2, {
3740
3763
  schemaVersion: 1,
3741
3764
  promptSafety: "safe",
3742
3765
  safeBasis,
3743
3766
  ...copyMetadata(metadata2)
3744
3767
  });
3745
3768
  }
3746
- function createUnsafeInternal(value, metadata2) {
3747
- return createValue(value, {
3769
+ function createUnsafeInternal(value2, metadata2) {
3770
+ return createValue(value2, {
3748
3771
  schemaVersion: 1,
3749
3772
  promptSafety: "unsafe",
3750
3773
  ...copyMetadata(metadata2)
3751
3774
  });
3752
3775
  }
3753
- function createValue(value, label) {
3754
- const result = { value, label: Object.freeze(label) };
3776
+ function createValue(value2, label) {
3777
+ const result = { value: value2, label: Object.freeze(label) };
3755
3778
  Object.defineProperty(result, camelValueBrand, { value: label.promptSafety, enumerable: false });
3756
3779
  authenticCamelValues.add(result);
3757
3780
  return Object.freeze(result);
@@ -3857,8 +3880,8 @@ async function createCodePortableCheckpoint(input) {
3857
3880
  const checkpointDigest = `sha256:${await sha256Hex(canonicalJson(fields))}`;
3858
3881
  return freeze({ ...fields, patch: input.patch, checkpointDigest });
3859
3882
  }
3860
- async function verifyCodePortableCheckpoint(value) {
3861
- const input = object(value, "checkpoint");
3883
+ async function verifyCodePortableCheckpoint(value2) {
3884
+ const input = object(value2, "checkpoint");
3862
3885
  exact2(input, ["schemaVersion", "baseCommitSha", "patch", "patchDigest", "state", "stateDigest", "checkpointDigest"]);
3863
3886
  if (input.schemaVersion !== 1 || typeof input.baseCommitSha !== "string" || typeof input.patch !== "string" || typeof input.patchDigest !== "string" || typeof input.stateDigest !== "string" || typeof input.checkpointDigest !== "string") {
3864
3887
  throw invalid2("Portable checkpoint fields are malformed.");
@@ -3873,8 +3896,8 @@ async function verifyCodePortableCheckpoint(value) {
3873
3896
  }
3874
3897
  return created;
3875
3898
  }
3876
- function normalizeState(value) {
3877
- const state2 = object(value, "state");
3899
+ function normalizeState(value2) {
3900
+ const state2 = object(value2, "state");
3878
3901
  exact2(state2, [
3879
3902
  "planCursor",
3880
3903
  "conversationRefs",
@@ -3932,30 +3955,30 @@ function validateBaseAndPatch(baseCommitSha, patch2) {
3932
3955
  throw invalid2("Portable checkpoint base or patch is malformed or outside its bounds.");
3933
3956
  }
3934
3957
  }
3935
- function strings(value, name, pattern, maximum, sort) {
3936
- if (!Array.isArray(value) || value.length > maximum || value.some((item) => typeof item !== "string" || !pattern.test(item)) || new Set(value).size !== value.length) {
3958
+ function strings(value2, name, pattern, maximum, sort) {
3959
+ if (!Array.isArray(value2) || value2.length > maximum || value2.some((item) => typeof item !== "string" || !pattern.test(item)) || new Set(value2).size !== value2.length) {
3937
3960
  throw invalid2(`Portable checkpoint ${name} is malformed or outside its bounds.`);
3938
3961
  }
3939
- const result = [...value];
3962
+ const result = [...value2];
3940
3963
  return sort ? result.sort() : result;
3941
3964
  }
3942
- function object(value, name) {
3943
- if (!value || typeof value !== "object" || Array.isArray(value)) throw invalid2(`Portable ${name} must be an object.`);
3944
- return value;
3965
+ function object(value2, name) {
3966
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) throw invalid2(`Portable ${name} must be an object.`);
3967
+ return value2;
3945
3968
  }
3946
- function exact2(value, keys) {
3947
- if (Object.keys(value).some((key) => !keys.includes(key)) || keys.some((key) => !(key in value))) {
3969
+ function exact2(value2, keys) {
3970
+ if (Object.keys(value2).some((key) => !keys.includes(key)) || keys.some((key) => !(key in value2))) {
3948
3971
  throw invalid2("Portable checkpoint contains missing or unsupported fields.");
3949
3972
  }
3950
3973
  }
3951
- function freeze(value) {
3974
+ function freeze(value2) {
3952
3975
  return Object.freeze({
3953
- ...value,
3976
+ ...value2,
3954
3977
  state: Object.freeze({
3955
- ...value.state,
3956
- conversationRefs: Object.freeze([...value.state.conversationRefs]),
3957
- completedEffects: Object.freeze(value.state.completedEffects.map((item) => Object.freeze({ ...item }))),
3958
- unresolvedApprovals: Object.freeze([...value.state.unresolvedApprovals])
3978
+ ...value2.state,
3979
+ conversationRefs: Object.freeze([...value2.state.conversationRefs]),
3980
+ completedEffects: Object.freeze(value2.state.completedEffects.map((item) => Object.freeze({ ...item }))),
3981
+ unresolvedApprovals: Object.freeze([...value2.state.unresolvedApprovals])
3959
3982
  })
3960
3983
  });
3961
3984
  }
@@ -4046,61 +4069,61 @@ async function createConversionRegistry(config) {
4046
4069
  if (utf8Length(source.value) > policy.maximumSourceBytes) throw new CamelError("limit_exceeded", "Unsafe conversion input exceeds its byte bound.");
4047
4070
  return policy;
4048
4071
  };
4049
- const emit3 = (source, policy, value) => convert(source, policy, value, outputCounts);
4072
+ const emit3 = (source, policy, value2) => convert(source, policy, value2, outputCounts);
4050
4073
  const operations = Object.freeze({
4051
- boolean: async (value, id) => {
4052
- const policy = checked(value, id, "boolean");
4053
- return emit3(value, policy, requireBoolean(value.value));
4074
+ boolean: async (value2, id) => {
4075
+ const policy = checked(value2, id, "boolean");
4076
+ return emit3(value2, policy, requireBoolean(value2.value));
4054
4077
  },
4055
- integer: async (value, id) => {
4056
- const policy = checked(value, id, "integer");
4057
- return emit3(value, policy, boundedInteger(value.value, policy.output));
4078
+ integer: async (value2, id) => {
4079
+ const policy = checked(value2, id, "integer");
4080
+ return emit3(value2, policy, boundedInteger(value2.value, policy.output));
4058
4081
  },
4059
- finiteNumber: async (value, id) => {
4060
- const policy = checked(value, id, "finite_number");
4061
- return emit3(value, policy, boundedNumber(value.value, policy.output));
4082
+ finiteNumber: async (value2, id) => {
4083
+ const policy = checked(value2, id, "finite_number");
4084
+ return emit3(value2, policy, boundedNumber(value2.value, policy.output));
4062
4085
  },
4063
- enum: async (value, id) => {
4064
- const policy = checked(value, id, "enum");
4065
- return emit3(value, policy, enumMember(value.value, policy.output));
4086
+ enum: async (value2, id) => {
4087
+ const policy = checked(value2, id, "enum");
4088
+ return emit3(value2, policy, enumMember(value2.value, policy.output));
4066
4089
  },
4067
- date: async (value, id) => {
4068
- const policy = checked(value, id, "date");
4069
- return emit3(value, policy, canonicalDate(value.value, policy.output));
4090
+ date: async (value2, id) => {
4091
+ const policy = checked(value2, id, "date");
4092
+ return emit3(value2, policy, canonicalDate(value2.value, policy.output));
4070
4093
  },
4071
- registeredId: async (value, id) => {
4072
- const policy = checked(value, id, "registered_id");
4094
+ registeredId: async (value2, id) => {
4095
+ const policy = checked(value2, id, "registered_id");
4073
4096
  const registry = config.registeredIds?.[policy.output.registryId];
4074
- const output = typeof value.value === "string" ? registry?.values[value.value] : void 0;
4097
+ const output = typeof value2.value === "string" ? registry?.values[value2.value] : void 0;
4075
4098
  if (!output) throw new CamelError("conversion_rejected", "Registered-ID conversion rejected the candidate.");
4076
- return emit3(value, policy, output);
4099
+ return emit3(value2, policy, output);
4077
4100
  },
4078
- digest: async (value, id) => {
4079
- const policy = checked(value, id, "digest");
4080
- if (!(value.value instanceof Uint8Array)) throw new CamelError("conversion_rejected", "Digest conversion requires bytes.");
4081
- return emit3(value, policy, await sha256Hex(value.value));
4101
+ digest: async (value2, id) => {
4102
+ const policy = checked(value2, id, "digest");
4103
+ if (!(value2.value instanceof Uint8Array)) throw new CamelError("conversion_rejected", "Digest conversion requires bytes.");
4104
+ return emit3(value2, policy, await sha256Hex(value2.value));
4082
4105
  },
4083
- measure: async (value, metric, id) => {
4084
- const policy = checked(value, id, "integer");
4085
- const measured = measure(value.value, metric);
4086
- return emit3(value, policy, boundedInteger(measured, policy.output));
4106
+ measure: async (value2, metric, id) => {
4107
+ const policy = checked(value2, id, "integer");
4108
+ const measured = measure(value2.value, metric);
4109
+ return emit3(value2, policy, boundedInteger(measured, policy.output));
4087
4110
  },
4088
- test: async (value, predicateId, id) => {
4089
- const policy = checked(value, id, "boolean");
4111
+ test: async (value2, predicateId, id) => {
4112
+ const policy = checked(value2, id, "boolean");
4090
4113
  const predicate = config.predicates?.[predicateId];
4091
4114
  if (!predicate) throw new CamelError("conversion_rejected", "Predicate is not registered.");
4092
- return emit3(value, policy, evaluatePredicate(value.value, predicate, config.registeredIds));
4115
+ return emit3(value2, policy, evaluatePredicate(value2.value, predicate, config.registeredIds));
4093
4116
  }
4094
4117
  });
4095
4118
  return Object.freeze({ operations, policy: (id) => policies.get(id) ?? missingPolicy() });
4096
4119
  }
4097
- async function convert(source, policy, value, counts) {
4120
+ async function convert(source, policy, value2, counts) {
4098
4121
  const sourceKey = sourceIdentity(source);
4099
4122
  const countKey = `${policy.conversionId}\0${sourceKey}`;
4100
4123
  const count = counts.get(countKey) ?? 0;
4101
4124
  if (count >= policy.maximumOutputsPerArtifact) throw new CamelError("limit_exceeded", "Conversion output count exceeds its per-source bound.");
4102
4125
  counts.set(countKey, count + 1);
4103
- return createSafeInternal(value, "atomic_conversion", {
4126
+ return createSafeInternal(value2, "atomic_conversion", {
4104
4127
  readers: source.label.readers,
4105
4128
  provenance: [...source.label.provenance, { kind: "converter", id: policy.conversionId, digest: policy.digest }],
4106
4129
  dependencies: dependenciesOf([source])
@@ -4112,49 +4135,49 @@ function validatePolicyShape(policy) {
4112
4135
  const output = policy.output;
4113
4136
  if ((output.kind === "integer" || output.kind === "finite_number") && (!Number.isFinite(output.minimum) || !Number.isFinite(output.maximum) || output.minimum > output.maximum)) throw new CamelError("state_conflict", "Numeric conversion bounds are invalid.");
4114
4137
  if (output.kind === "finite_number" && (!Number.isSafeInteger(output.maximumDecimalPlaces) || output.maximumDecimalPlaces < 0 || output.maximumDecimalPlaces > 15)) throw new CamelError("state_conflict", "Decimal-place bound is invalid.");
4115
- if (output.kind === "enum" && (output.values.length === 0 || output.values.some((value) => typeof value !== "string" || !value) || new Set(output.values).size !== output.values.length)) throw new CamelError("state_conflict", "Enum conversion members must be unique and non-empty.");
4138
+ if (output.kind === "enum" && (output.values.length === 0 || output.values.some((value2) => typeof value2 !== "string" || !value2) || new Set(output.values).size !== output.values.length)) throw new CamelError("state_conflict", "Enum conversion members must be unique and non-empty.");
4116
4139
  if (output.kind === "registered_id" && (!output.registryId || !output.registryDigest)) throw new CamelError("state_conflict", "Registered-ID conversion identity is invalid.");
4117
4140
  if (output.kind === "date" && output.format !== "date" && output.format !== "rfc3339") throw new CamelError("state_conflict", "Date conversion format is invalid.");
4118
4141
  if (output.kind === "digest" && output.algorithm !== "sha256") throw new CamelError("state_conflict", "Digest conversion algorithm is invalid.");
4119
4142
  }
4120
- function requireBoolean(value) {
4121
- if (typeof value !== "boolean") throw new CamelError("conversion_rejected", "Boolean conversion requires a structured boolean.");
4122
- return value;
4143
+ function requireBoolean(value2) {
4144
+ if (typeof value2 !== "boolean") throw new CamelError("conversion_rejected", "Boolean conversion requires a structured boolean.");
4145
+ return value2;
4123
4146
  }
4124
- function boundedInteger(value, spec) {
4125
- if (spec.kind !== "integer" || typeof value !== "number" || !Number.isSafeInteger(value) || value < spec.minimum || value > spec.maximum) throw new CamelError("conversion_rejected", "Integer conversion rejected the structured value.");
4126
- return value;
4147
+ function boundedInteger(value2, spec) {
4148
+ if (spec.kind !== "integer" || typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 < spec.minimum || value2 > spec.maximum) throw new CamelError("conversion_rejected", "Integer conversion rejected the structured value.");
4149
+ return value2;
4127
4150
  }
4128
- function boundedNumber(value, spec) {
4129
- if (spec.kind !== "finite_number" || typeof value !== "number" || !Number.isFinite(value) || value < spec.minimum || value > spec.maximum) throw new CamelError("conversion_rejected", "Finite-number conversion rejected the structured value.");
4130
- const text = String(value);
4151
+ function boundedNumber(value2, spec) {
4152
+ if (spec.kind !== "finite_number" || typeof value2 !== "number" || !Number.isFinite(value2) || value2 < spec.minimum || value2 > spec.maximum) throw new CamelError("conversion_rejected", "Finite-number conversion rejected the structured value.");
4153
+ const text = String(value2);
4131
4154
  if (/e/i.test(text) || (text.split(".")[1]?.length ?? 0) > spec.maximumDecimalPlaces) throw new CamelError("conversion_rejected", "Finite-number conversion rejected a non-canonical decimal.");
4132
- return value;
4155
+ return value2;
4133
4156
  }
4134
- function enumMember(value, spec) {
4135
- if (spec.kind !== "enum" || typeof value !== "string") throw new CamelError("conversion_rejected", "Enum conversion requires a structured string member.");
4136
- const member = spec.caseSensitive ? spec.values.find((item) => item === value) : spec.values.find((item) => item.toLocaleLowerCase("en-US") === value.toLocaleLowerCase("en-US"));
4157
+ function enumMember(value2, spec) {
4158
+ if (spec.kind !== "enum" || typeof value2 !== "string") throw new CamelError("conversion_rejected", "Enum conversion requires a structured string member.");
4159
+ const member = spec.caseSensitive ? spec.values.find((item) => item === value2) : spec.values.find((item) => item.toLocaleLowerCase("en-US") === value2.toLocaleLowerCase("en-US"));
4137
4160
  if (member === void 0) throw new CamelError("conversion_rejected", "Enum conversion rejected a non-member.");
4138
4161
  return member;
4139
4162
  }
4140
- function canonicalDate(value, spec) {
4141
- if (spec.kind !== "date" || typeof value !== "string") throw new CamelError("conversion_rejected", "Date conversion requires a canonical structured string.");
4163
+ function canonicalDate(value2, spec) {
4164
+ if (spec.kind !== "date" || typeof value2 !== "string") throw new CamelError("conversion_rejected", "Date conversion requires a canonical structured string.");
4142
4165
  const pattern = spec.format === "date" ? /^\d{4}-\d{2}-\d{2}$/ : /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
4143
- const instant = Date.parse(spec.format === "date" ? `${value}T00:00:00Z` : value);
4144
- if (!pattern.test(value) || !Number.isFinite(instant) || spec.format === "date" && new Date(instant).toISOString().slice(0, 10) !== value) throw new CamelError("conversion_rejected", "Date conversion rejected a non-canonical value.");
4145
- if (spec.earliest && value < spec.earliest || spec.latest && value > spec.latest) throw new CamelError("conversion_rejected", "Date conversion rejected an out-of-range value.");
4146
- return value;
4147
- }
4148
- function measure(value, metric) {
4149
- if (metric === "byte_length" && (typeof value === "string" || value instanceof Uint8Array)) return utf8Length(value);
4150
- if (metric === "codepoint_length" && typeof value === "string") return [...value].length;
4151
- if (metric === "item_count" && Array.isArray(value)) return value.length;
4166
+ const instant = Date.parse(spec.format === "date" ? `${value2}T00:00:00Z` : value2);
4167
+ if (!pattern.test(value2) || !Number.isFinite(instant) || spec.format === "date" && new Date(instant).toISOString().slice(0, 10) !== value2) throw new CamelError("conversion_rejected", "Date conversion rejected a non-canonical value.");
4168
+ if (spec.earliest && value2 < spec.earliest || spec.latest && value2 > spec.latest) throw new CamelError("conversion_rejected", "Date conversion rejected an out-of-range value.");
4169
+ return value2;
4170
+ }
4171
+ function measure(value2, metric) {
4172
+ if (metric === "byte_length" && (typeof value2 === "string" || value2 instanceof Uint8Array)) return utf8Length(value2);
4173
+ if (metric === "codepoint_length" && typeof value2 === "string") return [...value2].length;
4174
+ if (metric === "item_count" && Array.isArray(value2)) return value2.length;
4152
4175
  throw new CamelError("conversion_rejected", "Measurement input does not match the registered metric.");
4153
4176
  }
4154
- function evaluatePredicate(value, predicate, registries) {
4155
- if (predicate.kind === "has_fields") return typeof value === "object" && value !== null && !Array.isArray(value) && predicate.fields.every((field) => Object.hasOwn(value, field));
4156
- if (predicate.kind === "registered_id") return typeof value === "string" && registries?.[predicate.registryId]?.values[value] !== void 0;
4157
- const actual = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
4177
+ function evaluatePredicate(value2, predicate, registries) {
4178
+ if (predicate.kind === "has_fields") return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) && predicate.fields.every((field) => Object.hasOwn(value2, field));
4179
+ if (predicate.kind === "registered_id") return typeof value2 === "string" && registries?.[predicate.registryId]?.values[value2] !== void 0;
4180
+ const actual = value2 === null ? "null" : Array.isArray(value2) ? "array" : typeof value2;
4158
4181
  return actual === predicate.valueType;
4159
4182
  }
4160
4183
  function sourceIdentity(source) {
@@ -4177,17 +4200,17 @@ function createCamelIngress(constants2 = []) {
4177
4200
  byId.set(item.id, item);
4178
4201
  }
4179
4202
  const ingress = {
4180
- userInstruction: (value, input) => createSafeInternal(value, "user_instruction", metadata("user_instruction", input.id, input.readers)),
4181
- systemPolicy: (value, input) => createSafeInternal(value, "system_policy", metadata("system_policy", input.id, input.readers)),
4203
+ userInstruction: (value2, input) => createSafeInternal(value2, "user_instruction", metadata("user_instruction", input.id, input.readers)),
4204
+ systemPolicy: (value2, input) => createSafeInternal(value2, "system_policy", metadata("system_policy", input.id, input.readers)),
4182
4205
  control: (id) => {
4183
4206
  const item = byId.get(id);
4184
4207
  if (!item) throw new CamelError("permission_denied", "Unknown control constant.");
4185
4208
  return createSafeInternal(item.value, "harness_constant", metadata("harness", id, item.readers));
4186
4209
  },
4187
- external: (value, label) => createUnsafeInternal(value, label),
4188
- quarantinedOutput: (value, input) => {
4210
+ external: (value2, label) => createUnsafeInternal(value2, label),
4211
+ quarantinedOutput: (value2, input) => {
4189
4212
  if (!input.runId) throw new CamelError("state_conflict", "Quarantined run IDs must be non-empty.");
4190
- return createUnsafeInternal(value, {
4213
+ return createUnsafeInternal(value2, {
4191
4214
  readers: input.readers,
4192
4215
  dependencies: input.dependencies,
4193
4216
  provenance: [{ kind: "quarantined_llm", id: input.runId, digest: input.digest }]
@@ -4196,15 +4219,15 @@ function createCamelIngress(constants2 = []) {
4196
4219
  };
4197
4220
  return Object.freeze(ingress);
4198
4221
  }
4199
- function assertNoUnsafeConstant(value, seen = /* @__PURE__ */ new WeakSet()) {
4200
- if (typeof value !== "object" || value === null || seen.has(value)) return;
4201
- seen.add(value);
4202
- if (isCamelValue(value)) {
4203
- if (isUnsafe(value)) throw new CamelError("unsafe_privileged_flow", "Control constants cannot contain Prompt-Unsafe values.");
4204
- assertNoUnsafeConstant(value.value, seen);
4222
+ function assertNoUnsafeConstant(value2, seen = /* @__PURE__ */ new WeakSet()) {
4223
+ if (typeof value2 !== "object" || value2 === null || seen.has(value2)) return;
4224
+ seen.add(value2);
4225
+ if (isCamelValue(value2)) {
4226
+ if (isUnsafe(value2)) throw new CamelError("unsafe_privileged_flow", "Control constants cannot contain Prompt-Unsafe values.");
4227
+ assertNoUnsafeConstant(value2.value, seen);
4205
4228
  return;
4206
4229
  }
4207
- for (const child of Object.values(value)) assertNoUnsafeConstant(child, seen);
4230
+ for (const child of Object.values(value2)) assertNoUnsafeConstant(child, seen);
4208
4231
  }
4209
4232
  function metadata(kind, id, readers) {
4210
4233
  if (!id) throw new CamelError("state_conflict", "Provenance IDs must be non-empty.");
@@ -4235,7 +4258,7 @@ async function evaluate(input, registries, approvals) {
4235
4258
  if (invalid3) return deny(invalid3);
4236
4259
  if (arg.role === "selector" && !isSafe(arg.value)) confined.add(arg.value);
4237
4260
  }
4238
- if (input.controlDependencies.some((value) => !isSafe(value) && !confined.has(value))) return deny("unsafe_control_dependency");
4261
+ if (input.controlDependencies.some((value2) => !isSafe(value2) && !confined.has(value2))) return deny("unsafe_control_dependency");
4239
4262
  if (confined.size > 0) {
4240
4263
  const fixed = input.tool.unsafeSelectorPolicy?.fixedProviderIds ?? [];
4241
4264
  const destinations = Object.values(input.args).filter((arg) => arg.role === "destination");
@@ -4262,29 +4285,29 @@ async function validateArgument(path, arg, tool, registries) {
4262
4285
  if (!isSafe(arg.value)) return "unsafe_destination_argument";
4263
4286
  if (!isControlOwned(arg.value)) return "destination_not_control_owned";
4264
4287
  const registry = registries[arg.registryId];
4265
- const validValues = registry && registry.values.length > 0 && registry.values.every((value) => typeof value === "string" && value.length > 0) && new Set(registry.values).size === registry.values.length;
4288
+ const validValues = registry && registry.values.length > 0 && registry.values.every((value2) => typeof value2 === "string" && value2.length > 0) && new Set(registry.values).size === registry.values.length;
4266
4289
  if (!registry || !validValues || registry.digest !== arg.registryDigest || await destinationRegistryDigest(registry.values) !== registry.digest || !registry.values.includes(arg.value.value)) return "destination_not_registered";
4267
4290
  }
4268
4291
  if (arg.role === "selector" && !isSafe(arg.value)) return validateUnsafeSelector(path, arg.value, tool);
4269
4292
  return void 0;
4270
4293
  }
4271
- function isControlOwned(value) {
4272
- return value.label.safeBasis === "system_policy" || value.label.safeBasis === "harness_constant";
4294
+ function isControlOwned(value2) {
4295
+ return value2.label.safeBasis === "system_policy" || value2.label.safeBasis === "harness_constant";
4273
4296
  }
4274
4297
  function copyRegistries(registries) {
4275
4298
  return Object.freeze(Object.fromEntries(Object.entries(registries).map(([id, registry]) => [id, Object.freeze({ digest: registry.digest, values: Object.freeze([...registry.values]) })])));
4276
4299
  }
4277
- function validateUnsafeSelector(path, value, tool) {
4300
+ function validateUnsafeSelector(path, value2, tool) {
4278
4301
  const policy = tool.unsafeSelectorPolicy;
4279
4302
  if (!policy || policy.effect !== tool.effect || !policy.selectorPaths.includes(path)) return "unsafe_selector_not_confined";
4280
4303
  if (!policy.fixedDestination || !policy.unsafeOutput || policy.fixedProviderIds.length === 0) return "unsafe_selector_not_confined";
4281
4304
  if (![policy.maximumCalls, policy.maximumResultsPerCall, policy.maximumOutputBytes, policy.maximumSelectorBytes].every((bound) => Number.isSafeInteger(bound) && bound > 0)) return "unsafe_selector_not_confined";
4282
- if (utf8Length(value.value) > policy.maximumSelectorBytes) return "unsafe_selector_too_large";
4283
- if (typeof value.value === "string" && looksLikeDestination(value.value)) return "unsafe_selector_is_destination";
4305
+ if (utf8Length(value2.value) > policy.maximumSelectorBytes) return "unsafe_selector_too_large";
4306
+ if (typeof value2.value === "string" && looksLikeDestination(value2.value)) return "unsafe_selector_is_destination";
4284
4307
  return void 0;
4285
4308
  }
4286
- function looksLikeDestination(value) {
4287
- const text = value.trim();
4309
+ function looksLikeDestination(value2) {
4310
+ const text = value2.trim();
4288
4311
  return /^(?:[a-z][a-z0-9+.-]*:\/\/|\/|\\\\)/i.test(text) || /^[\w.-]+\.[a-z]{2,}(?:[/:]|$)/i.test(text);
4289
4312
  }
4290
4313
 
@@ -4370,9 +4393,9 @@ var CodeRuntimeReconciler = class {
4370
4393
  }
4371
4394
  }
4372
4395
  };
4373
- function retryableControlFailure(value) {
4374
- if (!value || typeof value !== "object") return false;
4375
- const failure = value;
4396
+ function retryableControlFailure(value2) {
4397
+ if (!value2 || typeof value2 !== "object") return false;
4398
+ const failure = value2;
4376
4399
  if (failure.code === "invalid_response" || typeof failure.status !== "number") return false;
4377
4400
  return failure.status === 408 || failure.status === 425 || failure.status === 429 || failure.status >= 500;
4378
4401
  }
@@ -4424,16 +4447,16 @@ function createCodeRuntimeControlClient(options) {
4424
4447
  if (options.signal?.aborted) throw cause;
4425
4448
  throw new CodeRuntimeControlError("Code runtime control plane is unavailable", 503, "transport_unavailable");
4426
4449
  }
4427
- const value = await response2.json().catch(() => null);
4450
+ const value2 = await response2.json().catch(() => null);
4428
4451
  if (!response2.ok) {
4429
- const problem = record3(record3(value)?.error);
4452
+ const problem = record3(record3(value2)?.error);
4430
4453
  throw new CodeRuntimeControlError(
4431
4454
  typeof problem?.message === "string" ? problem.message : `Code runtime request failed (${response2.status})`,
4432
4455
  response2.status,
4433
4456
  typeof problem?.code === "string" ? problem.code : void 0
4434
4457
  );
4435
4458
  }
4436
- return value;
4459
+ return value2;
4437
4460
  };
4438
4461
  return {
4439
4462
  heartbeat: async (version, capabilities) => {
@@ -4448,15 +4471,15 @@ function createCodeRuntimeControlClient(options) {
4448
4471
  await call2(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/source`, {})
4449
4472
  ),
4450
4473
  infer: async (sessionId, inference) => {
4451
- const value = record3(await call2(
4474
+ const value2 = record3(await call2(
4452
4475
  `/registry/code/runtime/sessions/${validSessionId(sessionId)}/inference`,
4453
4476
  inference,
4454
4477
  modelRequestTimeoutMs
4455
4478
  ));
4456
- if (!value || value.requestId !== inference.requestId || !record3(value.response) || !record3(value.receipt)) {
4479
+ if (!value2 || value2.requestId !== inference.requestId || !record3(value2.response) || !record3(value2.receipt)) {
4457
4480
  throw new CodeRuntimeControlError("invalid Code inference response", 502, "invalid_response");
4458
4481
  }
4459
- return value;
4482
+ return value2;
4460
4483
  },
4461
4484
  review: async (sessionId, review) => parseReview(
4462
4485
  await call2(`/registry/code/runtime/sessions/${validSessionId(sessionId)}/review`, review, modelRequestTimeoutMs)
@@ -4481,8 +4504,8 @@ function createCodeRuntimeControlClient(options) {
4481
4504
  }
4482
4505
  };
4483
4506
  }
4484
- function validatedEndpoint(value) {
4485
- const endpoint = value.replace(/\/+$/, "");
4507
+ function validatedEndpoint(value2) {
4508
+ const endpoint = value2.replace(/\/+$/, "");
4486
4509
  let url;
4487
4510
  try {
4488
4511
  url = new URL(endpoint);
@@ -4495,9 +4518,9 @@ function validatedEndpoint(value) {
4495
4518
  }
4496
4519
  return endpoint;
4497
4520
  }
4498
- function validSessionId(value) {
4499
- if (!/^csess_[0-9a-f]{32}$/.test(value)) throw new TypeError("invalid Code session id");
4500
- return value;
4521
+ function validSessionId(value2) {
4522
+ if (!/^csess_[0-9a-f]{32}$/.test(value2)) throw new TypeError("invalid Code session id");
4523
+ return value2;
4501
4524
  }
4502
4525
  function validateHeartbeat(version, capabilities) {
4503
4526
  if (!version.trim() || version.length > 80) throw new TypeError("runtimeVersion is required and at most 80 characters");
@@ -4510,8 +4533,8 @@ function validateHeartbeat(version, capabilities) {
4510
4533
  throw new TypeError("runtime resources must be positive integers");
4511
4534
  }
4512
4535
  }
4513
- function parseSnapshot(value) {
4514
- const root = record3(value);
4536
+ function parseSnapshot(value2) {
4537
+ const root = record3(value2);
4515
4538
  const host = record3(root?.host);
4516
4539
  if (!host || typeof host.hostId !== "string" || typeof host.runtimeVersion !== "string" || !Number.isSafeInteger(host.lastSeenAt) || host.revokedAt !== null || !Array.isArray(root?.bindings) || root.bindings.length > 1024 || !Array.isArray(root?.commands) || root.commands.length > 64) throw invalid("heartbeat");
4517
4540
  const bindingIds = /* @__PURE__ */ new Set();
@@ -4536,11 +4559,11 @@ function parseSnapshot(value) {
4536
4559
  });
4537
4560
  return { host, bindings, commands };
4538
4561
  }
4539
- async function parseSource(value) {
4540
- const snapshot = record3(record3(value)?.snapshot);
4562
+ async function parseSource(value2) {
4563
+ const snapshot = record3(record3(value2)?.snapshot);
4541
4564
  if (!snapshot || typeof snapshot.repository !== "string" || typeof snapshot.commitSha !== "string" || typeof snapshot.treeDigest !== "string" || !Array.isArray(snapshot.files)) throw invalid("source");
4542
- const files = snapshot.files.map((value2) => {
4543
- const file = record3(value2);
4565
+ const files = snapshot.files.map((value22) => {
4566
+ const file = record3(value22);
4544
4567
  if (!file || typeof file.path !== "string" || typeof file.content !== "string") throw invalid("source file");
4545
4568
  return { path: file.path, content: file.content };
4546
4569
  });
@@ -4567,19 +4590,19 @@ async function parseSource(value) {
4567
4590
  if (digest !== snapshot.treeDigest) throw invalid("source digest");
4568
4591
  return { ...source, treeDigest: digest, ...references.length ? { references } : {} };
4569
4592
  }
4570
- function parseReview(value) {
4571
- const review = record3(record3(value)?.review);
4593
+ function parseReview(value2) {
4594
+ const review = record3(record3(value2)?.review);
4572
4595
  if (!review || !["approved", "rejected"].includes(String(review.verdict)) || typeof review.reviewDigest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(review.reviewDigest) || typeof review.provider !== "string" || !review.provider || typeof review.model !== "string" || !review.model || !Number.isSafeInteger(review.policyVersion) || Number(review.policyVersion) < 1) throw invalid("review");
4573
4596
  return review;
4574
4597
  }
4575
- function parseCandidate(value) {
4576
- const candidate = record3(record3(value)?.candidate);
4598
+ function parseCandidate(value2) {
4599
+ const candidate = record3(record3(value2)?.candidate);
4577
4600
  if (!candidate || typeof candidate.candidateId !== "string" || !/^ccand_[0-9a-f]{32}$/.test(candidate.candidateId) || !["submitted", "approved", "published", "failed"].includes(String(candidate.status))) {
4578
4601
  throw invalid("candidate");
4579
4602
  }
4580
4603
  return { candidateId: candidate.candidateId, status: candidate.status };
4581
4604
  }
4582
- var record3 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
4605
+ var record3 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
4583
4606
  var invalid = (part) => new CodeRuntimeControlError(`invalid Code runtime ${part} response`, 502, "invalid_response");
4584
4607
  var RESERVED = /* @__PURE__ */ new Set([".git", ".odla", ".wrangler", "node_modules", "dist", "coverage"]);
4585
4608
  var SECRET = /^(?:\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json|dev-token(?:\..+)?\.json)$/i;
@@ -4613,8 +4636,8 @@ function validateCodePatch(patch2, maxBytes) {
4613
4636
  if (!paths.length || new Set(paths).size !== paths.length) throw new TypeError("patch has no diffs or repeats a path");
4614
4637
  return paths;
4615
4638
  }
4616
- function validHeaderPath(value, path, prefix) {
4617
- return value === "/dev/null" || value === `${prefix}/${path}`;
4639
+ function validHeaderPath(value2, path, prefix) {
4640
+ return value2 === "/dev/null" || value2 === `${prefix}/${path}`;
4618
4641
  }
4619
4642
  function validateRelativePath(path) {
4620
4643
  const parts = path.split("/");
@@ -4760,8 +4783,8 @@ function assertCodeBuildRecipe(recipe2) {
4760
4783
  throw new TypeError("build recipe is malformed or exceeds its control bounds");
4761
4784
  }
4762
4785
  }
4763
- function parseMemory(value) {
4764
- const match = /^([1-9][0-9]{0,4})([kmg])$/.exec(value.toLowerCase());
4786
+ function parseMemory(value2) {
4787
+ const match = /^([1-9][0-9]{0,4})([kmg])$/.exec(value2.toLowerCase());
4765
4788
  if (!match?.[1] || !match[2]) return 0;
4766
4789
  const scale = match[2] === "k" ? 1024 : match[2] === "m" ? 1024 ** 2 : 1024 ** 3;
4767
4790
  return Number(match[1]) * scale;
@@ -4996,14 +5019,14 @@ function normalizedRecipe(recipe2) {
4996
5019
  expectedArtifacts: [...recipe2.expectedArtifacts ?? []].sort((left, right) => left.id.localeCompare(right.id)).map((artifact) => ({ id: artifact.id, path: artifact.path, maximumBytes: artifact.maximumBytes }))
4997
5020
  };
4998
5021
  }
4999
- function digestJson(value) {
5000
- return digestBytes(JSON.stringify(value));
5022
+ function digestJson(value2) {
5023
+ return digestBytes(JSON.stringify(value2));
5001
5024
  }
5002
- function digestBytes(value) {
5003
- return `sha256:${createHash22("sha256").update(value).digest("hex")}`;
5025
+ function digestBytes(value2) {
5026
+ return `sha256:${createHash22("sha256").update(value2).digest("hex")}`;
5004
5027
  }
5005
- function integer(value, minimum, maximum) {
5006
- return Number.isSafeInteger(value) && value >= minimum && value <= maximum;
5028
+ function integer(value2, minimum, maximum) {
5029
+ return Number.isSafeInteger(value2) && value2 >= minimum && value2 <= maximum;
5007
5030
  }
5008
5031
  async function prepareRuntimeCheckpoint(input) {
5009
5032
  const patch2 = await input.workspace.patch(256 * 1024);
@@ -5056,7 +5079,7 @@ async function prepareRuntimeCheckpoint(input) {
5056
5079
  });
5057
5080
  return { checkpoint, verification, review, note };
5058
5081
  }
5059
- var message = (value) => (value instanceof Error ? value.message : String(value)).slice(0, 500);
5082
+ var message = (value2) => (value2 instanceof Error ? value2.message : String(value2)).slice(0, 500);
5060
5083
  var CodeRuntimeCheckpointManager = class {
5061
5084
  constructor(options) {
5062
5085
  this.options = options;
@@ -5250,7 +5273,7 @@ async function conversionPolicy(id, output) {
5250
5273
  return { ...definition, digest: await conversionPolicyDigest(definition) };
5251
5274
  }
5252
5275
  async function registeredPolicy(id, registryId, values) {
5253
- const mapping = Object.fromEntries(values.map((value) => [value, value]));
5276
+ const mapping = Object.fromEntries(values.map((value2) => [value2, value2]));
5254
5277
  return conversionPolicy(id, {
5255
5278
  kind: "registered_id",
5256
5279
  registryId,
@@ -5259,7 +5282,7 @@ async function registeredPolicy(id, registryId, values) {
5259
5282
  }
5260
5283
  async function conversionRegistry(policies, values) {
5261
5284
  const registeredIds = Object.fromEntries(await Promise.all(Object.entries(values).map(async ([id, entries]) => {
5262
- const mapping = Object.fromEntries(entries.map((value) => [value, value]));
5285
+ const mapping = Object.fromEntries(entries.map((value2) => [value2, value2]));
5263
5286
  return [id, { values: mapping, digest: await registeredIdRegistryDigest(mapping) }];
5264
5287
  })));
5265
5288
  return createConversionRegistry({ policies, registeredIds });
@@ -5283,8 +5306,8 @@ async function environment(input, options, tool) {
5283
5306
  };
5284
5307
  return { ingress, policy, fixedArgs, reader: ingress.control("reader"), runId: `${input.request.requestId}:${tool}` };
5285
5308
  }
5286
- function unsafe(base, value, field) {
5287
- return base.ingress.quarantinedOutput(value, {
5309
+ function unsafe(base, value2, field) {
5310
+ return base.ingress.quarantinedOutput(value2, {
5288
5311
  readers: base.reader.label.readers,
5289
5312
  runId: `${base.runId}:${field}`
5290
5313
  });
@@ -5364,14 +5387,14 @@ async function read(context, request2, options, policy) {
5364
5387
  }
5365
5388
  async function patch(context, request2, options, policy) {
5366
5389
  exactKeys(request2.input, ["patch"]);
5367
- const value = stringField(request2.input, "patch");
5368
- const paths = validateCodePatch(value, options.maxPatchBytes ?? 256 * 1024);
5390
+ const value2 = stringField(request2.input, "patch");
5391
+ const paths = validateCodePatch(value2, options.maxPatchBytes ?? 256 * 1024);
5369
5392
  if (paths.some((path) => options.readOnlyPrefixes?.some((prefix) => path === prefix || path.startsWith(`${prefix}/`)))) {
5370
5393
  throw new TypeError("patch targets a read-only reference source");
5371
5394
  }
5372
- const allowed = await policy.patch(policyContext(context, request2, options, { patch: value }));
5395
+ const allowed = await policy.patch(policyContext(context, request2, options, { patch: value2 }));
5373
5396
  if (!allowed) return response(request2, false, "tool denied by CaMeL policy");
5374
- await applyCodePatch(context.workspaceDir, value, paths);
5397
+ await applyCodePatch(context.workspaceDir, value2, paths);
5375
5398
  return response(request2, true, `Applied patch to ${paths.length} file(s).`, { paths });
5376
5399
  }
5377
5400
  async function recipe(context, request2, options, recipes, policy) {
@@ -5462,14 +5485,14 @@ function exactKeys(input, allowed) {
5462
5485
  if (Object.keys(input).some((key) => !allowed.includes(key))) throw new TypeError("tool input contains an unsupported field");
5463
5486
  }
5464
5487
  function stringField(input, name) {
5465
- const value = input[name];
5466
- if (typeof value !== "string" || !value) throw new TypeError(`${name} must be a non-empty string`);
5467
- return value;
5488
+ const value2 = input[name];
5489
+ if (typeof value2 !== "string" || !value2) throw new TypeError(`${name} must be a non-empty string`);
5490
+ return value2;
5468
5491
  }
5469
- function optionalInteger(value) {
5470
- if (value === void 0) return void 0;
5471
- if (!Number.isSafeInteger(value) || value < 1) throw new TypeError("line bounds must be positive integers");
5472
- return value;
5492
+ function optionalInteger(value2) {
5493
+ if (value2 === void 0) return void 0;
5494
+ if (!Number.isSafeInteger(value2) || value2 < 1) throw new TypeError("line bounds must be positive integers");
5495
+ return value2;
5473
5496
  }
5474
5497
  function response(request2, ok, content2, details) {
5475
5498
  return { requestId: request2.requestId, ok, content: content2, ...details ? { details } : {} };
@@ -5515,9 +5538,9 @@ function codeLocalSource(payload) {
5515
5538
  return source;
5516
5539
  }
5517
5540
  function codeCheckpointPayload(payload) {
5518
- const value = payload.checkpoint;
5519
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("resume checkpoint is missing");
5520
- return value;
5541
+ const value2 = payload.checkpoint;
5542
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) throw new TypeError("resume checkpoint is missing");
5543
+ return value2;
5521
5544
  }
5522
5545
  function fakeCodeLease(command, metadata2) {
5523
5546
  return {
@@ -5541,7 +5564,7 @@ function fakeCodeLease(command, metadata2) {
5541
5564
  }
5542
5565
  };
5543
5566
  }
5544
- var record22 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
5567
+ var record22 = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
5545
5568
  var SOURCE_LIMITS = { maxFiles: 2e4, maxBytes: 512 * 1024 * 1024 };
5546
5569
  async function prepareRuntimeLocalSource(input) {
5547
5570
  const { command, descriptor: descriptor2, available, repository, baseCommitSha, resume } = input;
@@ -5631,24 +5654,24 @@ async function appendCodeRuntimeEvent(control, command, event, refs) {
5631
5654
  const bounded = event.type === "message" ? { ...event, body: event.body.trim().slice(0, 2e4) || `${event.actor} event` } : event;
5632
5655
  await control.appendSessionEvent(command.sessionId, eventId, bounded);
5633
5656
  }
5634
- var digestRuntimeValue = (value) => `sha256:${createHash3("sha256").update(value).digest("hex")}`;
5635
- var runtimeErrorMessage = (value) => value instanceof Error ? value.message : String(value);
5636
- var runtimeRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
5637
- var safeRuntimeJson = (value) => {
5657
+ var digestRuntimeValue = (value2) => `sha256:${createHash3("sha256").update(value2).digest("hex")}`;
5658
+ var runtimeErrorMessage = (value2) => value2 instanceof Error ? value2.message : String(value2);
5659
+ var runtimeRecord = (value2) => value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
5660
+ var safeRuntimeJson = (value2) => {
5638
5661
  try {
5639
- return JSON.stringify(value).slice(0, 1e4);
5662
+ return JSON.stringify(value2).slice(0, 1e4);
5640
5663
  } catch {
5641
5664
  return "[event]";
5642
5665
  }
5643
5666
  };
5644
- function runtimeResultText(value) {
5645
- const record32 = runtimeRecord(value);
5667
+ function runtimeResultText(value2) {
5668
+ const record32 = runtimeRecord(value2);
5646
5669
  if (record32 && typeof record32.text === "string") return record32.text.slice(0, 2e4);
5647
5670
  if (record32 && typeof record32.error === "string") return `Pi failed: ${record32.error.slice(0, 19989)}`;
5648
5671
  return null;
5649
5672
  }
5650
- function runtimeResultError(value) {
5651
- const record32 = runtimeRecord(value);
5673
+ function runtimeResultError(value2) {
5674
+ const record32 = runtimeRecord(value2);
5652
5675
  return record32 && typeof record32.error === "string" && record32.error.trim() ? record32.error.trim().slice(0, 2e3) : null;
5653
5676
  }
5654
5677
  var CodePiRuntimeEngine = class {
@@ -5922,14 +5945,14 @@ var CodePiRuntimeEngine = class {
5922
5945
  this.#active.delete(command.sessionId);
5923
5946
  return result;
5924
5947
  }
5925
- async #failure(command, active, value) {
5926
- active.failure = value.slice(0, 2e3);
5948
+ async #failure(command, active, value2) {
5949
+ active.failure = value2.slice(0, 2e3);
5927
5950
  if (active.acknowledged) {
5928
5951
  await this.options.control.reportSessionFailure(command.sessionId, active.failure).catch(() => void 0);
5929
5952
  }
5930
5953
  }
5931
- async #diagnostic(command, active, value) {
5932
- const detail = value.trim().slice(0, 2e3) || "Pi runtime failed";
5954
+ async #diagnostic(command, active, value2) {
5955
+ const detail = value2.trim().slice(0, 2e3) || "Pi runtime failed";
5933
5956
  this.options.onDiagnostic?.(detail);
5934
5957
  await this.#event(
5935
5958
  command,
@@ -6014,6 +6037,7 @@ Usage:
6014
6037
  odla-ai context save <name> [--platform <url>] [--app <id>] [--env <name>] [--json]
6015
6038
  odla-ai context remove <name> --yes [--json]
6016
6039
  odla-ai o11y status [--app <id>] [--context <name>] [--platform https://odla.ai] [--env prod] [--minutes 60] [--json]
6040
+ odla-ai platform status [--context <name>] [--platform https://odla.ai] [--email <odla-account>] [--json]
6017
6041
  odla-ai whoami [--context <name>] [--platform https://odla.ai] [--json]
6018
6042
  odla-ai runbook ask "<question>" [--app <id>] [--all] [--json]
6019
6043
  odla-ai runbook search "<question>" [--app <id>] [--all] [--limit <n>] [--json]
@@ -6138,6 +6162,8 @@ Commands:
6138
6162
  canary, collector ingest/scheduler trust, Cloudflare-owned
6139
6163
  runtime metrics, and a machine verdict.
6140
6164
  --json keeps auth progress on stderr for unattended agents.
6165
+ platform Read canonical fleet health, releases, provider load/freshness,
6166
+ explicit unknowns, and next actions through a read-only grant.
6141
6167
  provision Register services, compose integrations, persist credentials, optionally push secrets.
6142
6168
  smoke Verify credentials, public-config, composed schema, db aggregate, and integration probes.
6143
6169
  skill Same installer; --agent accepts all, claude, codex, cursor,
@@ -6238,17 +6264,17 @@ async function prepareCodeLocalSource(cwd, repository, readHead = readGitHead) {
6238
6264
  }
6239
6265
  }
6240
6266
  async function readGitHead(cwd) {
6241
- const value = await new Promise((accept, reject) => {
6267
+ const value2 = await new Promise((accept, reject) => {
6242
6268
  execFile3("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8", maxBuffer: 16384 }, (error, stdout) => {
6243
6269
  if (error) reject(new Error("code connect requires a Git checkout with an initial commit"));
6244
6270
  else accept(stdout.trim());
6245
6271
  });
6246
6272
  });
6247
- if (!/^[0-9a-f]{40}$/.test(value)) throw new Error("code connect could not resolve the checkout HEAD commit");
6248
- return value;
6273
+ if (!/^[0-9a-f]{40}$/.test(value2)) throw new Error("code connect could not resolve the checkout HEAD commit");
6274
+ return value2;
6249
6275
  }
6250
- function digestText(value) {
6251
- return `sha256:${createHash4("sha256").update(value).digest("hex")}`;
6276
+ function digestText(value2) {
6277
+ return `sha256:${createHash4("sha256").update(value2).digest("hex")}`;
6252
6278
  }
6253
6279
 
6254
6280
  // src/code-connect.ts
@@ -6412,8 +6438,8 @@ async function runCodeRuntime(input) {
6412
6438
  for (const [name, handler] of handlers) process.removeListener(name, handler);
6413
6439
  }
6414
6440
  }
6415
- function parseConnection(value, appId, appEnv) {
6416
- const root = record4(value);
6441
+ function parseConnection(value2, appId, appEnv) {
6442
+ const root = record4(value2);
6417
6443
  const host = record4(root?.host);
6418
6444
  const offer = record4(root?.offer);
6419
6445
  const binding = record4(root?.binding);
@@ -6422,16 +6448,16 @@ function parseConnection(value, appId, appEnv) {
6422
6448
  }
6423
6449
  return root;
6424
6450
  }
6425
- function apiFailure(action, status, value) {
6426
- const message2 = record4(record4(value)?.error)?.message;
6451
+ function apiFailure(action, status, value2) {
6452
+ const message2 = record4(record4(value2)?.error)?.message;
6427
6453
  return `${action} failed (${status})${typeof message2 === "string" ? `: ${message2}` : ""}`;
6428
6454
  }
6429
- function record4(value) {
6430
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
6455
+ function record4(value2) {
6456
+ return value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : null;
6431
6457
  }
6432
6458
 
6433
6459
  // src/provision.ts
6434
- import { createAppsClient, tenantIdFor as tenantIdFor4 } from "@odla-ai/apps";
6460
+ import { createAppsClient, orderAppServices, tenantIdFor as tenantIdFor4 } from "@odla-ai/apps";
6435
6461
  import { putSecret as putSecret2 } from "@odla-ai/ai";
6436
6462
  import process8 from "process";
6437
6463
 
@@ -6476,8 +6502,8 @@ async function postJson2(doFetch, url, bearer, body) {
6476
6502
  if (!res.ok) throw new Error(`${new URL(url).pathname} failed: ${res.status} ${await responseText(res)}`);
6477
6503
  return res.json().catch(() => ({}));
6478
6504
  }
6479
- function isRecord7(value) {
6480
- return value !== null && typeof value === "object" && !Array.isArray(value);
6505
+ function isRecord7(value2) {
6506
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
6481
6507
  }
6482
6508
  async function responseText(res) {
6483
6509
  try {
@@ -6585,11 +6611,6 @@ async function safeText4(res) {
6585
6611
  // src/provision-helpers.ts
6586
6612
  import { DEFAULT_SECRET_NAMES } from "@odla-ai/ai";
6587
6613
  import { tenantIdFor as tenantIdFor3 } from "@odla-ai/apps";
6588
- function serviceRank(service) {
6589
- if (service === "db") return 0;
6590
- if (service === "calendar") return 2;
6591
- return 1;
6592
- }
6593
6614
  function defaultSecretName(provider) {
6594
6615
  const names = DEFAULT_SECRET_NAMES;
6595
6616
  return names[provider] ?? `${provider}_api_key`;
@@ -6615,14 +6636,14 @@ async function postJson3(doFetch, url, bearer, body) {
6615
6636
  });
6616
6637
  if (!res.ok) throw new Error(`${new URL(url).pathname} failed: ${res.status} ${await safeText5(res)}`);
6617
6638
  }
6618
- function normalizeClerkConfig(value) {
6619
- if (!value) return null;
6620
- if (typeof value === "string") {
6621
- const publishableKey2 = envValue(value);
6639
+ function normalizeClerkConfig(value2) {
6640
+ if (!value2) return null;
6641
+ if (typeof value2 === "string") {
6642
+ const publishableKey2 = envValue(value2);
6622
6643
  return publishableKey2 ? { publishableKey: publishableKey2 } : null;
6623
6644
  }
6624
- if (typeof value !== "object") return null;
6625
- const cfg = value;
6645
+ if (typeof value2 !== "object") return null;
6646
+ const cfg = value2;
6626
6647
  const publishableKey = envValue(cfg.publishableKey);
6627
6648
  return publishableKey ? { publishableKey, ...cfg.audience ? { audience: cfg.audience } : {}, ...cfg.mode ? { mode: cfg.mode } : {} } : null;
6628
6649
  }
@@ -6715,7 +6736,7 @@ async function provision(options) {
6715
6736
  for (const env of cfg.envs) {
6716
6737
  await assertTenantAdminAccess(doFetch, cfg, env, token);
6717
6738
  }
6718
- const serviceOrder = [...cfg.services].sort((a, b) => serviceRank(a) - serviceRank(b));
6739
+ const serviceOrder = orderAppServices(cfg.services);
6719
6740
  for (const env of cfg.envs) {
6720
6741
  for (const service of serviceOrder) {
6721
6742
  if (service === "ai") {
@@ -6895,6 +6916,7 @@ var COMMAND_SURFACE = {
6895
6916
  help: {},
6896
6917
  init: {},
6897
6918
  o11y: { status: {} },
6919
+ platform: { status: {} },
6898
6920
  pm: {
6899
6921
  ...PM_ENTITIES,
6900
6922
  handoff: {}
@@ -7062,13 +7084,13 @@ function selectEnv(requested, declared, configPath, rootDir) {
7062
7084
  return env;
7063
7085
  }
7064
7086
  async function injectedToken(options, request2) {
7065
- const value = options.token ?? await options.getToken?.(Object.freeze({ ...request2 }));
7066
- if (typeof value !== "string" || value.length < 8 || value.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value)) {
7087
+ const value2 = options.token ?? await options.getToken?.(Object.freeze({ ...request2 }));
7088
+ if (typeof value2 !== "string" || value2.length < 8 || value2.length > 8192 || /\s|[\u0000-\u001f\u007f]/.test(value2)) {
7067
7089
  throw new Error(
7068
7090
  request2.selfAudit ? "Self-audit requires an injected, scoped platform security token" : "Hosted security requires an injected app developer token or getToken callback"
7069
7091
  );
7070
7092
  }
7071
- return value;
7093
+ return value2;
7072
7094
  }
7073
7095
  function profileFor(name, maxHuntTasks) {
7074
7096
  const profile = name === "odla" ? odlaProfile() : name === "cloudflare-app" ? cloudflareAppProfile() : name === "generic" ? genericProfile() : void 0;
@@ -7114,8 +7136,8 @@ async function getHostedSecurityIntent(options) {
7114
7136
  }
7115
7137
  return response2;
7116
7138
  }
7117
- function isValidIntent(value, expected) {
7118
- return !!value && value.executionContract === "odla.hosted-security-execution-consent.v1" && /^sha256:[a-f0-9]{64}$/.test(value.executionDigest) && /^sha256:[a-f0-9]{64}$/.test(value.planDigest) && value.appId === expected.appId && value.env === expected.env && value.sourceId === expected.sourceId && typeof value.repository === "string" && value.repository.length > 2 && value.repository.length <= 201 && typeof value.defaultBranch === "string" && value.defaultBranch.length > 0 && value.defaultBranch.length <= 255 && typeof value.requestedRef === "string" && value.requestedRef.length > 0 && value.requestedRef.length <= 255 && !/[\u0000-\u001f\u007f]/.test(value.requestedRef) && ["odla", "cloudflare-app", "generic"].includes(value.profile) && value.sourceDisclosure === "redacted";
7139
+ function isValidIntent(value2, expected) {
7140
+ return !!value2 && value2.executionContract === "odla.hosted-security-execution-consent.v1" && /^sha256:[a-f0-9]{64}$/.test(value2.executionDigest) && /^sha256:[a-f0-9]{64}$/.test(value2.planDigest) && value2.appId === expected.appId && value2.env === expected.env && value2.sourceId === expected.sourceId && typeof value2.repository === "string" && value2.repository.length > 2 && value2.repository.length <= 201 && typeof value2.defaultBranch === "string" && value2.defaultBranch.length > 0 && value2.defaultBranch.length <= 255 && typeof value2.requestedRef === "string" && value2.requestedRef.length > 0 && value2.requestedRef.length <= 255 && !/[\u0000-\u001f\u007f]/.test(value2.requestedRef) && ["odla", "cloudflare-app", "generic"].includes(value2.profile) && value2.sourceDisclosure === "redacted";
7119
7141
  }
7120
7142
 
7121
7143
  // src/security-hosted-jobs.ts
@@ -7241,17 +7263,17 @@ function hostedJobPath(appIdInput, jobIdInput) {
7241
7263
  const jobId = hostedIdentifier(jobIdInput, "jobId");
7242
7264
  return `/registry/apps/${encodeURIComponent(appId)}/security/jobs/${encodeURIComponent(jobId)}`;
7243
7265
  }
7244
- function securityPlanDigest(value) {
7245
- if (!/^sha256:[a-f0-9]{64}$/.test(value)) {
7266
+ function securityPlanDigest(value2) {
7267
+ if (!/^sha256:[a-f0-9]{64}$/.test(value2)) {
7246
7268
  throw new Error("expected plan digest must be a sha256 digest from security plan");
7247
7269
  }
7248
- return value;
7270
+ return value2;
7249
7271
  }
7250
- function securityExecutionDigest(value) {
7251
- if (!/^sha256:[a-f0-9]{64}$/.test(value)) {
7272
+ function securityExecutionDigest(value2) {
7273
+ if (!/^sha256:[a-f0-9]{64}$/.test(value2)) {
7252
7274
  throw new Error("expected execution digest must be a sha256 digest from security intent");
7253
7275
  }
7254
- return value;
7276
+ return value2;
7255
7277
  }
7256
7278
 
7257
7279
  // src/argv.ts
@@ -7275,10 +7297,10 @@ function parseArgv(argv) {
7275
7297
  addOption(options, rawName, arg.slice(eq + 1));
7276
7298
  continue;
7277
7299
  }
7278
- const value = argv[i + 1];
7279
- if (value !== void 0 && !value.startsWith("--")) {
7300
+ const value2 = argv[i + 1];
7301
+ if (value2 !== void 0 && !value2.startsWith("--")) {
7280
7302
  i++;
7281
- addOption(options, rawName, value);
7303
+ addOption(options, rawName, value2);
7282
7304
  } else {
7283
7305
  addOption(options, rawName, true);
7284
7306
  }
@@ -7294,39 +7316,39 @@ function assertArgs(parsed, allowedOptions2, maxPositionals) {
7294
7316
  throw new Error(`unexpected argument "${parsed.positionals[maxPositionals]}"; run "odla-ai help"`);
7295
7317
  }
7296
7318
  }
7297
- function requiredString(value, name) {
7298
- const result = stringOpt(value);
7319
+ function requiredString(value2, name) {
7320
+ const result = stringOpt(value2);
7299
7321
  if (!result) throw new Error(`${name} is required`);
7300
7322
  return result;
7301
7323
  }
7302
- function stringOpt(value) {
7303
- if (typeof value === "string") return value;
7304
- if (Array.isArray(value)) return value[value.length - 1];
7324
+ function stringOpt(value2) {
7325
+ if (typeof value2 === "string") return value2;
7326
+ if (Array.isArray(value2)) return value2[value2.length - 1];
7305
7327
  return void 0;
7306
7328
  }
7307
- function listOpt(value) {
7308
- if (value === void 0 || typeof value === "boolean") return void 0;
7309
- const values = Array.isArray(value) ? value : [value];
7329
+ function listOpt(value2) {
7330
+ if (value2 === void 0 || typeof value2 === "boolean") return void 0;
7331
+ const values = Array.isArray(value2) ? value2 : [value2];
7310
7332
  return values.flatMap((item) => item.split(",")).map((item) => item.trim()).filter(Boolean);
7311
7333
  }
7312
- function boolOpt(value) {
7313
- if (typeof value === "boolean") return value;
7314
- if (typeof value === "string" && (value === "true" || value === "false")) return value === "true";
7315
- if (value === void 0) return void 0;
7334
+ function boolOpt(value2) {
7335
+ if (typeof value2 === "boolean") return value2;
7336
+ if (typeof value2 === "string" && (value2 === "true" || value2 === "false")) return value2 === "true";
7337
+ if (value2 === void 0) return void 0;
7316
7338
  throw new Error("boolean option must be true or false");
7317
7339
  }
7318
- function numberOpt(value, flag) {
7319
- if (value === void 0) return void 0;
7320
- const raw = stringOpt(value);
7340
+ function numberOpt(value2, flag) {
7341
+ if (value2 === void 0) return void 0;
7342
+ const raw = stringOpt(value2);
7321
7343
  const parsed = raw === void 0 ? Number.NaN : Number(raw);
7322
7344
  if (!Number.isSafeInteger(parsed) || parsed < 1) throw new Error(`${flag} requires a positive integer`);
7323
7345
  return parsed;
7324
7346
  }
7325
- function addOption(options, name, value) {
7347
+ function addOption(options, name, value2) {
7326
7348
  const current = options[name];
7327
- if (current === void 0) options[name] = value;
7328
- else if (Array.isArray(current)) current.push(String(value));
7329
- else options[name] = [String(current), String(value)];
7349
+ if (current === void 0) options[name] = value2;
7350
+ else if (Array.isArray(current)) current.push(String(value2));
7351
+ else options[name] = [String(current), String(value2)];
7330
7352
  }
7331
7353
 
7332
7354
  // src/operator-context.ts
@@ -7354,8 +7376,8 @@ function resolveOperatorProfile(parsed) {
7354
7376
  }
7355
7377
  assertOperatorName(name, "context");
7356
7378
  const profiles = readOperatorProfiles(file);
7357
- const value = Object.hasOwn(profiles, name) ? profiles[name] : void 0;
7358
- if (!value) {
7379
+ const value2 = Object.hasOwn(profiles, name) ? profiles[name] : void 0;
7380
+ if (!value2) {
7359
7381
  throw new Error(
7360
7382
  `operator context "${name}" not found in ${file}; run "odla-ai context list" or save it first`
7361
7383
  );
@@ -7364,7 +7386,7 @@ function resolveOperatorProfile(parsed) {
7364
7386
  name,
7365
7387
  source: fromFlag ? "flag" : "environment",
7366
7388
  file,
7367
- value
7389
+ value: value2
7368
7390
  };
7369
7391
  }
7370
7392
  function listOperatorProfiles(file = operatorProfileFile()) {
@@ -7392,8 +7414,8 @@ function operatorCredentialFiles(selection) {
7392
7414
  scoped: join9(base, "admin-token.local.json")
7393
7415
  };
7394
7416
  }
7395
- function assertOperatorName(value, label) {
7396
- if (!/^[a-z0-9][a-z0-9-]*$/.test(value)) {
7417
+ function assertOperatorName(value2, label) {
7418
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(value2)) {
7397
7419
  throw new Error(
7398
7420
  `${label} must contain lowercase letters, numbers, and hyphens`
7399
7421
  );
@@ -7419,22 +7441,22 @@ function readOperatorProfiles(file) {
7419
7441
  );
7420
7442
  }
7421
7443
  const profiles = emptyProfiles();
7422
- for (const [name, value] of Object.entries(
7444
+ for (const [name, value2] of Object.entries(
7423
7445
  raw.profiles
7424
7446
  )) {
7425
7447
  assertOperatorName(name, "context");
7426
- profiles[name] = validateProfile(value, `operator context "${name}"`);
7448
+ profiles[name] = validateProfile(value2, `operator context "${name}"`);
7427
7449
  }
7428
7450
  return profiles;
7429
7451
  }
7430
7452
  function emptyProfiles() {
7431
7453
  return /* @__PURE__ */ Object.create(null);
7432
7454
  }
7433
- function validateProfile(value, label) {
7434
- if (!value || typeof value !== "object" || Array.isArray(value)) {
7455
+ function validateProfile(value2, label) {
7456
+ if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
7435
7457
  throw new Error(`${label} has an invalid shape`);
7436
7458
  }
7437
- const unknown = Object.keys(value).filter(
7459
+ const unknown = Object.keys(value2).filter(
7438
7460
  (key) => !["platform", "app", "environment"].includes(key)
7439
7461
  );
7440
7462
  if (unknown.length > 0) {
@@ -7442,7 +7464,7 @@ function validateProfile(value, label) {
7442
7464
  `${label} contains unsupported field(s): ${unknown.sort().join(", ")}; contexts store scope metadata only, never credentials`
7443
7465
  );
7444
7466
  }
7445
- const candidate = value;
7467
+ const candidate = value2;
7446
7468
  if (typeof candidate.platform !== "string") {
7447
7469
  throw new Error(`${label} needs an absolute platform URL`);
7448
7470
  }
@@ -7457,8 +7479,8 @@ function validateProfile(value, label) {
7457
7479
  ...environment2 ? { environment: environment2 } : {}
7458
7480
  };
7459
7481
  }
7460
- function clean(value) {
7461
- const normalized = value?.trim();
7482
+ function clean(value2) {
7483
+ const normalized = value2?.trim();
7462
7484
  return normalized || void 0;
7463
7485
  }
7464
7486
 
@@ -7551,8 +7573,8 @@ async function resolveOperatorContext(parsed, options = {}) {
7551
7573
  }
7552
7574
  };
7553
7575
  }
7554
- function clean2(value) {
7555
- const normalized = value?.trim();
7576
+ function clean2(value2) {
7577
+ const normalized = value2?.trim();
7556
7578
  return normalized || void 0;
7557
7579
  }
7558
7580
 
@@ -8241,10 +8263,10 @@ function harnessList(parsed) {
8241
8263
  ];
8242
8264
  return selected.length ? selected : ["all"];
8243
8265
  }
8244
- function harnessOption(value, flag) {
8245
- if (value === void 0) return [];
8246
- if (typeof value === "boolean") throw new Error(`${flag} requires a harness name`);
8247
- const raw = Array.isArray(value) ? value : [value];
8266
+ function harnessOption(value2, flag) {
8267
+ if (value2 === void 0) return [];
8268
+ if (typeof value2 === "boolean") throw new Error(`${flag} requires a harness name`);
8269
+ const raw = Array.isArray(value2) ? value2 : [value2];
8248
8270
  const parts = raw.flatMap((item) => item.split(","));
8249
8271
  if (parts.some((item) => !item.trim())) {
8250
8272
  throw new Error(`${flag} requires a harness name`);
@@ -8413,8 +8435,8 @@ function developerTokenStatus(context, parsed, now = Date.now()) {
8413
8435
  cacheStatus
8414
8436
  };
8415
8437
  }
8416
- function clean3(value) {
8417
- const normalized = value?.trim();
8438
+ function clean3(value2) {
8439
+ const normalized = value2?.trim();
8418
8440
  return normalized || void 0;
8419
8441
  }
8420
8442
 
@@ -8563,8 +8585,8 @@ async function request(ctx, method, path, body) {
8563
8585
  throw new Error(`discuss ${method} ${path} failed: ${data.error ?? `registry returned ${res.status}`}`);
8564
8586
  return data;
8565
8587
  }
8566
- function emit(ctx, value, human) {
8567
- if (ctx.json) ctx.out.log(JSON.stringify(value, null, 2));
8588
+ function emit(ctx, value2, human) {
8589
+ if (ctx.json) ctx.out.log(JSON.stringify(value2, null, 2));
8568
8590
  else human();
8569
8591
  }
8570
8592
  var state = (topic) => topic.resolved ? "resolved" : "open";
@@ -8609,8 +8631,8 @@ async function discussList(ctx, parsed) {
8609
8631
  ["limit", "limit"],
8610
8632
  ["offset", "offset"]
8611
8633
  ]) {
8612
- const value = stringOpt(parsed.options[flag]);
8613
- if (value) query.set(param, value);
8634
+ const value2 = stringOpt(parsed.options[flag]);
8635
+ if (value2) query.set(param, value2);
8614
8636
  }
8615
8637
  const qs = query.toString();
8616
8638
  const page = await request(ctx, "GET", `/topics${qs ? `?${qs}` : ""}`);
@@ -8807,11 +8829,11 @@ var MAX_CONSECUTIVE_FAILURES = 5;
8807
8829
  var MAX_BACKOFF_MS = 3e4;
8808
8830
  function numberOpt2(parsed, flag, fallback) {
8809
8831
  const raw = stringOpt(parsed.options[flag]);
8810
- const value = raw == null ? NaN : Number(raw);
8811
- return Number.isFinite(value) && value > 0 ? value : fallback;
8832
+ const value2 = raw == null ? NaN : Number(raw);
8833
+ return Number.isFinite(value2) && value2 > 0 ? value2 : fallback;
8812
8834
  }
8813
- function jsonl(ctx, parsed, value) {
8814
- if (parsed.options.jsonl === true) ctx.out.log(JSON.stringify({ v: 1, ...value }));
8835
+ function jsonl(ctx, parsed, value2) {
8836
+ if (parsed.options.jsonl === true) ctx.out.log(JSON.stringify({ v: 1, ...value2 }));
8815
8837
  }
8816
8838
  async function discussWatch(ctx, topicId, parsed) {
8817
8839
  if (ctx.json && parsed.options.jsonl === true) throw new Error("--json and --jsonl cannot be combined");
@@ -9073,13 +9095,13 @@ async function pmRequest(ctx, method, path, body) {
9073
9095
  function collectFields(parsed, allowClear) {
9074
9096
  const out = {};
9075
9097
  for (const [flag, spec] of Object.entries(FIELD_MAP)) {
9076
- const value = parsed.options[flag];
9077
- if (value === void 0 || value === true) continue;
9078
- if (value === false) {
9098
+ const value2 = parsed.options[flag];
9099
+ if (value2 === void 0 || value2 === true) continue;
9100
+ if (value2 === false) {
9079
9101
  if (allowClear) out[spec.key] = null;
9080
9102
  continue;
9081
9103
  }
9082
- const text = stringOpt(value);
9104
+ const text = stringOpt(value2);
9083
9105
  out[spec.key] = spec.num ? Number(text) : text;
9084
9106
  }
9085
9107
  return out;
@@ -9100,8 +9122,8 @@ function statusCol(entity, r) {
9100
9122
  function printRecord(ctx, entity, r) {
9101
9123
  ctx.out.log(`${r.id} [${statusCol(entity, r)}] ${r.appId} ${r.title ?? ""}`);
9102
9124
  }
9103
- function emit2(ctx, value, human) {
9104
- if (ctx.json) ctx.out.log(JSON.stringify(value, null, 2));
9125
+ function emit2(ctx, value2, human) {
9126
+ if (ctx.json) ctx.out.log(JSON.stringify(value2, null, 2));
9105
9127
  else human();
9106
9128
  }
9107
9129
  async function pmList(ctx, entity, parsed) {
@@ -9147,8 +9169,8 @@ async function pmAdd(ctx, entity, parsed) {
9147
9169
  emit2(ctx, res, () => ctx.out.log(`created ${entity} ${res.id}`));
9148
9170
  }
9149
9171
  async function pmGet(ctx, entity, id) {
9150
- const { record: record7 } = await pmRequest(ctx, "GET", `/${entity}/${encodeURIComponent(id)}`);
9151
- emit2(ctx, record7, () => printRecord(ctx, entity, record7));
9172
+ const { record: record8 } = await pmRequest(ctx, "GET", `/${entity}/${encodeURIComponent(id)}`);
9173
+ emit2(ctx, record8, () => printRecord(ctx, entity, record8));
9152
9174
  }
9153
9175
  async function pmSet(ctx, entity, id, parsed) {
9154
9176
  const patch2 = collectEntityFields(entity, parsed, true);
@@ -9193,9 +9215,9 @@ async function pmHandoff(ctx, parsed) {
9193
9215
  ]);
9194
9216
  const handoff = {
9195
9217
  appId,
9196
- unmetGoals: goals.filter((record7) => record7.status !== "met"),
9197
- activeTasks: tasks.filter((record7) => record7.column !== "done"),
9198
- openBugs: bugs.filter((record7) => record7.status !== "fixed" && record7.status !== "wontfix")
9218
+ unmetGoals: goals.filter((record8) => record8.status !== "met"),
9219
+ activeTasks: tasks.filter((record8) => record8.column !== "done"),
9220
+ openBugs: bugs.filter((record8) => record8.status !== "fixed" && record8.status !== "wontfix")
9199
9221
  };
9200
9222
  const result = {
9201
9223
  ...handoff,
@@ -9214,10 +9236,10 @@ async function pmHandoff(ctx, parsed) {
9214
9236
  ]) {
9215
9237
  ctx.out.log(`${label}:`);
9216
9238
  if (!records.length) ctx.out.log("- (none)");
9217
- else for (const record7 of records) printRecord(
9239
+ else for (const record8 of records) printRecord(
9218
9240
  ctx,
9219
9241
  label === "unmet goals" ? "goal" : label === "active tasks" ? "task" : "bug",
9220
- record7
9242
+ record8
9221
9243
  );
9222
9244
  }
9223
9245
  });
@@ -9365,6 +9387,113 @@ async function pmCommand(parsed, deps = {}) {
9365
9387
  }
9366
9388
  }
9367
9389
 
9390
+ // src/platform-output.ts
9391
+ function printPlatformStatus(status, out) {
9392
+ out.log(`platform ${status.verdict.status} ${status.observedAt}`);
9393
+ out.log(
9394
+ `fleet ${status.summary.healthy}/${status.summary.services} healthy ${status.summary.required} required ${status.summary.unreachable} unreachable ${status.summary.notConfigured} not configured`
9395
+ );
9396
+ out.log(`catalog ${status.catalog.revision}`);
9397
+ out.log(
9398
+ "service required health probe ms version provider age requests errors cpu p99 us wall p99 us"
9399
+ );
9400
+ for (const service of status.services) {
9401
+ const metrics = service.provider.metrics;
9402
+ out.log([
9403
+ service.id,
9404
+ service.required ? "yes" : "no",
9405
+ service.health.status,
9406
+ value(service.health.latencyMs),
9407
+ service.release.observedVersionId ?? "unknown",
9408
+ service.provider.status,
9409
+ age(service.provider.ageMs),
9410
+ value(metrics?.requests),
9411
+ value(metrics?.errors),
9412
+ value(metrics?.cpuTimeP99),
9413
+ value(metrics?.wallTimeP99)
9414
+ ].join(" "));
9415
+ }
9416
+ if (status.verdict.reasons.length) {
9417
+ out.log(`reasons ${status.verdict.reasons.join(", ")}`);
9418
+ }
9419
+ for (const action of status.nextActions) {
9420
+ out.log(`next ${action.service} ${action.code} ${action.message}`);
9421
+ }
9422
+ }
9423
+ function value(input) {
9424
+ return input === null || input === void 0 ? "unknown" : String(input);
9425
+ }
9426
+ function age(input) {
9427
+ if (input === null) return "unknown";
9428
+ if (input < 1e3) return `${input}ms`;
9429
+ if (input < 6e4) return `${Math.round(input / 1e3)}s`;
9430
+ return `${Math.round(input / 6e4)}m`;
9431
+ }
9432
+
9433
+ // src/platform-command.ts
9434
+ async function platformCommand(parsed, deps = {}) {
9435
+ assertArgs(
9436
+ parsed,
9437
+ ["config", "context", "platform", "token", "email", "open", "json"],
9438
+ 2
9439
+ );
9440
+ const action = parsed.positionals[1];
9441
+ if (action !== "status") {
9442
+ throw new Error(
9443
+ `unknown platform action "${action ?? ""}". Try "odla-ai platform status --json".`
9444
+ );
9445
+ }
9446
+ const context = await resolveOperatorContext(parsed, {
9447
+ allowMissingConfig: true
9448
+ });
9449
+ const platform = context.platform.value;
9450
+ const doFetch = deps.fetch ?? fetch;
9451
+ const out = deps.stdout ?? console;
9452
+ const token = await resolveAdminPlatformToken({
9453
+ platform,
9454
+ scope: "platform:status:read",
9455
+ token: stringOpt(parsed.options.token),
9456
+ tokenFile: context.credentials.scopedTokenFile,
9457
+ email: stringOpt(parsed.options.email),
9458
+ open: parsed.options.open === false ? false : parsed.options.open === true ? true : void 0,
9459
+ fetch: doFetch,
9460
+ stdout: out,
9461
+ openApprovalUrl: deps.openUrl,
9462
+ label: "odla CLI (platform fleet status)"
9463
+ });
9464
+ const response2 = await doFetch(`${platform}/registry/platform/status`, {
9465
+ headers: { authorization: `Bearer ${token}` }
9466
+ });
9467
+ const body = await response2.json().catch(() => null);
9468
+ if (!response2.ok) {
9469
+ throw new Error(
9470
+ `read platform status failed (HTTP ${response2.status}): ${apiMessage(body)}`
9471
+ );
9472
+ }
9473
+ if (!isPlatformStatus(body)) {
9474
+ throw new Error("platform returned an invalid odla.platform-status/v1 envelope");
9475
+ }
9476
+ if (parsed.options.json === true) {
9477
+ out.log(JSON.stringify(body, null, 2));
9478
+ } else {
9479
+ printPlatformStatus(body, out);
9480
+ }
9481
+ }
9482
+ function isPlatformStatus(value2) {
9483
+ if (!record5(value2) || value2.schemaVersion !== "odla.platform-status/v1") return false;
9484
+ if (!record5(value2.verdict) || !Array.isArray(value2.verdict.reasons)) return false;
9485
+ if (!record5(value2.catalog) || !record5(value2.summary)) return false;
9486
+ return Array.isArray(value2.services) && Array.isArray(value2.nextActions);
9487
+ }
9488
+ function apiMessage(value2) {
9489
+ if (!record5(value2)) return "request failed";
9490
+ const error = record5(value2.error) ? value2.error : value2;
9491
+ return typeof error.message === "string" ? error.message : typeof error.code === "string" ? error.code : "request failed";
9492
+ }
9493
+ function record5(value2) {
9494
+ return !!value2 && typeof value2 === "object" && !Array.isArray(value2);
9495
+ }
9496
+
9368
9497
  // src/o11y-verdict.ts
9369
9498
  function statusVerdict(reads) {
9370
9499
  const reasons = [];
@@ -9402,7 +9531,7 @@ function statusVerdict(reads) {
9402
9531
  severity: "degraded"
9403
9532
  });
9404
9533
  }
9405
- const performance = record5(reads.liveSync.body.performance) ? reads.liveSync.body.performance : null;
9534
+ const performance = record6(reads.liveSync.body.performance) ? reads.liveSync.body.performance : null;
9406
9535
  if (performance?.status === "unavailable") {
9407
9536
  reasons.push({
9408
9537
  source: "liveSync",
@@ -9483,11 +9612,11 @@ function statusVerdict(reads) {
9483
9612
  reasons
9484
9613
  };
9485
9614
  }
9486
- function record5(value) {
9487
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
9615
+ function record6(value2) {
9616
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
9488
9617
  }
9489
- function numeric2(value) {
9490
- return typeof value === "number" && Number.isFinite(value) ? value : 0;
9618
+ function numeric2(value2) {
9619
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
9491
9620
  }
9492
9621
  function collectorReason(read3, fallback) {
9493
9622
  const reasons = read3.body.reasons;
@@ -9511,7 +9640,7 @@ function printO11yStatus(status, out) {
9511
9640
  out.log(
9512
9641
  `o11y status ${status.scope.appId}/${status.scope.env} (${status.scope.minutes}m)`
9513
9642
  );
9514
- const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(record6) : [];
9643
+ const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(record7) : [];
9515
9644
  const requests = routes.reduce(
9516
9645
  (total, row) => total + numeric3(row.requests),
9517
9646
  0
@@ -9523,39 +9652,39 @@ function printO11yStatus(status, out) {
9523
9652
  out.log(
9524
9653
  `application ${status.application.httpStatus} ${requests} requests ${errors} errors`
9525
9654
  );
9526
- const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(record6) : [];
9655
+ const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(record7) : [];
9527
9656
  out.log(
9528
9657
  `application-versions ${status.applicationVersions.httpStatus} ${versions.length ? versions.slice(0, 5).map(
9529
9658
  (row) => `${String(row.value || "(unattributed)")}:${numeric3(row.requests)}`
9530
9659
  ).join(", ") : "none observed"}`
9531
9660
  );
9532
9661
  out.log(liveSyncLine(status.liveSync));
9533
- const canaryDurations = record6(status.canary.body.durationsMs) ? status.canary.body.durationsMs : {};
9662
+ const canaryDurations = record7(status.canary.body.durationsMs) ? status.canary.body.durationsMs : {};
9534
9663
  out.log(
9535
9664
  `canary ${status.canary.httpStatus} ${String(status.canary.body.status ?? status.canary.body.error ?? "unavailable")} ${optionalNumeric(canaryDurations.publishToVisibleMs)} publish-to-visible`
9536
9665
  );
9537
- const collectorIngest = record6(status.collector.body.ingest) ? status.collector.body.ingest : {};
9538
- const collectorStorage = record6(collectorIngest.storage) ? collectorIngest.storage : {};
9666
+ const collectorIngest = record7(status.collector.body.ingest) ? status.collector.body.ingest : {};
9667
+ const collectorStorage = record7(collectorIngest.storage) ? collectorIngest.storage : {};
9539
9668
  out.log(
9540
9669
  `collector ${status.collector.httpStatus} ${String(status.collector.body.status ?? status.collector.body.error ?? "unavailable")} ${numeric3(collectorStorage.affectedPoints)} affected points`
9541
9670
  );
9542
- const providerMetrics = record6(status.provider.body.metrics) ? status.provider.body.metrics : {};
9543
- const providerCapacity = record6(status.provider.body.capacity) ? status.provider.body.capacity : {};
9544
- const workerMemory = record6(providerCapacity.memory) ? providerCapacity.memory : {};
9671
+ const providerMetrics = record7(status.provider.body.metrics) ? status.provider.body.metrics : {};
9672
+ const providerCapacity = record7(status.provider.body.capacity) ? status.provider.body.capacity : {};
9673
+ const workerMemory = record7(providerCapacity.memory) ? providerCapacity.memory : {};
9545
9674
  out.log(
9546
9675
  `cloudflare ${status.provider.httpStatus} ${String(status.provider.body.status ?? status.provider.body.error ?? "unavailable")} ${numeric3(providerMetrics.requests)} invocations ${numeric3(providerMetrics.errors)} runtime errors ${optionalBytes(workerMemory.headroomBytes)} isolate memory headroom`
9547
9676
  );
9548
9677
  for (const line of providerCapacityLines(status.providerCapacity)) {
9549
9678
  out.log(line);
9550
9679
  }
9551
- const coverage = record6(status.providerReconciliation.body.comparison) ? status.providerReconciliation.body.comparison : {};
9552
- const coverageCounts = record6(status.providerReconciliation.body.counts) ? status.providerReconciliation.body.counts : {};
9553
- const coverageBudget = record6(status.providerReconciliation.body.budget) ? status.providerReconciliation.body.budget : {};
9680
+ const coverage = record7(status.providerReconciliation.body.comparison) ? status.providerReconciliation.body.comparison : {};
9681
+ const coverageCounts = record7(status.providerReconciliation.body.counts) ? status.providerReconciliation.body.counts : {};
9682
+ const coverageBudget = record7(status.providerReconciliation.body.budget) ? status.providerReconciliation.body.budget : {};
9554
9683
  out.log(
9555
9684
  `request-coverage ${status.providerReconciliation.httpStatus} ${String(status.providerReconciliation.body.status ?? status.providerReconciliation.body.error ?? "unavailable")} ${optionalPercent(coverage.applicationCoverage)} application/provider ${numeric3(coverageCounts.applicationRequests)}/${numeric3(coverageCounts.providerRequests)} requests \xB1${optionalPercent(coverageBudget.maxRelativeError)} budget`
9556
9685
  );
9557
9686
  const providerPoints = Array.isArray(status.providerHistory.body.points) ? status.providerHistory.body.points.length : 0;
9558
- const providerFreshness = record6(status.providerHistory.body.freshness) ? status.providerHistory.body.freshness : {};
9687
+ const providerFreshness = record7(status.providerHistory.body.freshness) ? status.providerHistory.body.freshness : {};
9559
9688
  out.log(
9560
9689
  `cloudflare-history ${status.providerHistory.httpStatus} ${String(status.providerHistory.body.status ?? status.providerHistory.body.error ?? "unavailable")} ${providerPoints} snapshots ${optionalAge(providerFreshness.ageMs)} old`
9561
9690
  );
@@ -9564,17 +9693,17 @@ function printO11yStatus(status, out) {
9564
9693
  );
9565
9694
  }
9566
9695
  function providerCapacityLines(read3) {
9567
- const resources = record6(read3.body.resources) ? read3.body.resources : {};
9568
- const durableObjects = record6(resources.durableObjects) ? resources.durableObjects : {};
9569
- const periodic = record6(durableObjects.periodic) ? durableObjects.periodic : {};
9570
- const storage = record6(durableObjects.sqliteStorage) ? durableObjects.sqliteStorage : {};
9571
- const d1 = record6(resources.d1) ? resources.d1 : {};
9572
- const d1Activity = record6(d1.activity) ? d1.activity : {};
9573
- const d1Storage = record6(d1.storage) ? d1.storage : {};
9574
- const d1Latency = record6(d1Activity.latency) ? d1Activity.latency : {};
9575
- const r2 = record6(resources.r2) ? resources.r2 : {};
9576
- const r2Operations = record6(r2.operations) ? r2.operations : {};
9577
- const r2Storage = record6(r2.storage) ? r2.storage : {};
9696
+ const resources = record7(read3.body.resources) ? read3.body.resources : {};
9697
+ const durableObjects = record7(resources.durableObjects) ? resources.durableObjects : {};
9698
+ const periodic = record7(durableObjects.periodic) ? durableObjects.periodic : {};
9699
+ const storage = record7(durableObjects.sqliteStorage) ? durableObjects.sqliteStorage : {};
9700
+ const d1 = record7(resources.d1) ? resources.d1 : {};
9701
+ const d1Activity = record7(d1.activity) ? d1.activity : {};
9702
+ const d1Storage = record7(d1.storage) ? d1.storage : {};
9703
+ const d1Latency = record7(d1Activity.latency) ? d1Activity.latency : {};
9704
+ const r2 = record7(resources.r2) ? resources.r2 : {};
9705
+ const r2Operations = record7(r2.operations) ? r2.operations : {};
9706
+ const r2Storage = record7(r2.storage) ? r2.storage : {};
9578
9707
  const status = String(
9579
9708
  read3.body.status ?? read3.body.error ?? "unavailable"
9580
9709
  );
@@ -9585,42 +9714,42 @@ function providerCapacityLines(read3) {
9585
9714
  ];
9586
9715
  }
9587
9716
  function liveSyncLine(read3) {
9588
- const performance = record6(read3.body.performance) ? read3.body.performance : {};
9589
- const commitToSend = record6(performance.commitToSend) ? performance.commitToSend : {};
9717
+ const performance = record7(read3.body.performance) ? read3.body.performance : {};
9718
+ const commitToSend = record7(performance.commitToSend) ? performance.commitToSend : {};
9590
9719
  return `live-sync ${read3.httpStatus} ${String(read3.body.status ?? read3.body.error ?? "unavailable")} ${numeric3(read3.body.activeConnections)} active ${optionalNumeric(commitToSend.p95)} commit-to-send p95 ${numeric3(performance.sendFailures)} send failures`;
9591
9720
  }
9592
- function record6(value) {
9593
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
9721
+ function record7(value2) {
9722
+ return Boolean(value2) && typeof value2 === "object" && !Array.isArray(value2);
9594
9723
  }
9595
- function numeric3(value) {
9596
- return typeof value === "number" && Number.isFinite(value) ? value : 0;
9724
+ function numeric3(value2) {
9725
+ return typeof value2 === "number" && Number.isFinite(value2) ? value2 : 0;
9597
9726
  }
9598
- function optionalNumeric(value) {
9599
- return typeof value === "number" && Number.isFinite(value) ? `${value} ms` : "\u2014";
9727
+ function optionalNumeric(value2) {
9728
+ return typeof value2 === "number" && Number.isFinite(value2) ? `${value2} ms` : "\u2014";
9600
9729
  }
9601
- function optionalAge(value) {
9602
- if (typeof value !== "number" || !Number.isFinite(value)) return "unknown";
9603
- return `${Math.max(0, Math.round(value / 1e3))}s`;
9730
+ function optionalAge(value2) {
9731
+ if (typeof value2 !== "number" || !Number.isFinite(value2)) return "unknown";
9732
+ return `${Math.max(0, Math.round(value2 / 1e3))}s`;
9604
9733
  }
9605
- function optionalPercent(value) {
9606
- return typeof value === "number" && Number.isFinite(value) ? `${Math.round(value * 100)}%` : "\u2014";
9734
+ function optionalPercent(value2) {
9735
+ return typeof value2 === "number" && Number.isFinite(value2) ? `${Math.round(value2 * 100)}%` : "\u2014";
9607
9736
  }
9608
- function optionalBytes(value) {
9609
- if (typeof value !== "number" || !Number.isFinite(value)) return "\u2014";
9610
- if (value >= 1024 * 1024 * 1024) {
9611
- return `${(value / (1024 * 1024 * 1024)).toFixed(2)} GiB`;
9737
+ function optionalBytes(value2) {
9738
+ if (typeof value2 !== "number" || !Number.isFinite(value2)) return "\u2014";
9739
+ if (value2 >= 1024 * 1024 * 1024) {
9740
+ return `${(value2 / (1024 * 1024 * 1024)).toFixed(2)} GiB`;
9612
9741
  }
9613
- if (value >= 1024 * 1024) {
9614
- return `${(value / (1024 * 1024)).toFixed(1)} MiB`;
9742
+ if (value2 >= 1024 * 1024) {
9743
+ return `${(value2 / (1024 * 1024)).toFixed(1)} MiB`;
9615
9744
  }
9616
- if (value >= 1024) return `${(value / 1024).toFixed(1)} KiB`;
9617
- return `${Math.round(value)} B`;
9745
+ if (value2 >= 1024) return `${(value2 / 1024).toFixed(1)} KiB`;
9746
+ return `${Math.round(value2)} B`;
9618
9747
  }
9619
- function optionalCount(value, unit) {
9620
- return typeof value === "number" && Number.isFinite(value) ? `${value} ${unit}` : `\u2014 ${unit}`;
9748
+ function optionalCount(value2, unit) {
9749
+ return typeof value2 === "number" && Number.isFinite(value2) ? `${value2} ${unit}` : `\u2014 ${unit}`;
9621
9750
  }
9622
- function optionalAgeSeconds(value) {
9623
- return typeof value === "number" && Number.isFinite(value) ? `${Math.max(0, Math.round(value))}s` : "unknown";
9751
+ function optionalAgeSeconds(value2) {
9752
+ return typeof value2 === "number" && Number.isFinite(value2) ? `${Math.max(0, Math.round(value2))}s` : "unknown";
9624
9753
  }
9625
9754
 
9626
9755
  // src/o11y-command.ts
@@ -9750,11 +9879,11 @@ async function o11yCommand(parsed, deps = {}) {
9750
9879
  }
9751
9880
  printO11yStatus(status, out);
9752
9881
  }
9753
- function statusMinutes(value) {
9754
- if (!Number.isSafeInteger(value) || value < 1 || value > 7 * 24 * 60) {
9882
+ function statusMinutes(value2) {
9883
+ if (!Number.isSafeInteger(value2) || value2 < 1 || value2 > 7 * 24 * 60) {
9755
9884
  throw new Error("--minutes must be an integer from 1 to 10080");
9756
9885
  }
9757
- return value;
9886
+ return value2;
9758
9887
  }
9759
9888
  async function read2(url, headers, doFetch) {
9760
9889
  const response2 = await doFetch(url, { headers });
@@ -9762,8 +9891,8 @@ async function read2(url, headers, doFetch) {
9762
9891
  let body = {};
9763
9892
  if (text) {
9764
9893
  try {
9765
- const value = JSON.parse(text);
9766
- body = value && typeof value === "object" && !Array.isArray(value) ? value : { value };
9894
+ const value2 = JSON.parse(text);
9895
+ body = value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : { value: value2 };
9767
9896
  } catch {
9768
9897
  body = { message: text.slice(0, 300) };
9769
9898
  }
@@ -9780,7 +9909,7 @@ function recordInvocation(parsed) {
9780
9909
  try {
9781
9910
  const entry = {
9782
9911
  path: invocationPath(parsed.positionals),
9783
- options: Object.entries(parsed.options).map(([name, value]) => value === false ? `no-${name}` : name).sort()
9912
+ options: Object.entries(parsed.options).map(([name, value2]) => value2 === false ? `no-${name}` : name).sort()
9784
9913
  };
9785
9914
  if (!entry.path.length) return;
9786
9915
  appendFileSync(file, `${JSON.stringify(entry)}
@@ -9794,10 +9923,10 @@ import { readFileSync as readFileSync9 } from "fs";
9794
9923
 
9795
9924
  // src/runbook-requires.ts
9796
9925
  var SPEC = /^(@?[\w./-]+?)@(\d+\.\d+\.\d+(?:[\w.-]*)?)$/;
9797
- function parseRequires(value) {
9798
- if (!value) return [];
9926
+ function parseRequires(value2) {
9927
+ if (!value2) return [];
9799
9928
  const out = [];
9800
- for (const token of value.split(/[\s,]+/).filter(Boolean)) {
9929
+ for (const token of value2.split(/[\s,]+/).filter(Boolean)) {
9801
9930
  const match = SPEC.exec(token);
9802
9931
  if (match?.[1] && match[2]) out.push({ name: match[1], min: match[2] });
9803
9932
  }
@@ -9973,9 +10102,9 @@ function parseRunbook(text, slug) {
9973
10102
  for (const line of fm[1].split(/\r?\n/)) {
9974
10103
  const pair = /^(\w+)\s*:\s*(.+)$/.exec(line.trim());
9975
10104
  if (!pair) continue;
9976
- const value = pair[2].trim().replace(/^["']|["']$/g, "");
9977
- if (pair[1] === "summary") meta.summary = value;
9978
- if (pair[1] === "tags") meta.tags = value.replace(/^\[|\]$/g, "").trim();
10105
+ const value2 = pair[2].trim().replace(/^["']|["']$/g, "");
10106
+ if (pair[1] === "summary") meta.summary = value2;
10107
+ if (pair[1] === "tags") meta.tags = value2.replace(/^\[|\]$/g, "").trim();
9979
10108
  }
9980
10109
  }
9981
10110
  const lines = rest.split("\n");
@@ -10092,7 +10221,7 @@ var NOISE = /* @__PURE__ */ new Set([
10092
10221
  "and",
10093
10222
  "for"
10094
10223
  ]);
10095
- var words = (value) => value.replace(/^@[\w-]+\//, "").split(/[^A-Za-z0-9]+/).filter((w) => w.length > 1 && !NOISE.has(w.toLowerCase()));
10224
+ var words = (value2) => value2.replace(/^@[\w-]+\//, "").split(/[^A-Za-z0-9]+/).filter((w) => w.length > 1 && !NOISE.has(w.toLowerCase()));
10096
10225
  function namedExports(clause) {
10097
10226
  return clause.split(",").map((part) => part.trim().split(/\s+as\s+/)[0]?.trim() ?? "").filter((name) => /^[A-Za-z_$][\w$]*$/.test(name) && name !== "type");
10098
10227
  }
@@ -10445,8 +10574,8 @@ import process13 from "process";
10445
10574
  var EDITOR_ENV = ["ODLA_EDITOR", "VISUAL", "EDITOR"];
10446
10575
  function resolveEditor(env = process13.env) {
10447
10576
  for (const name of EDITOR_ENV) {
10448
- const value = env[name];
10449
- if (value && value.trim()) return value.trim();
10577
+ const value2 = env[name];
10578
+ if (value2 && value2.trim()) return value2.trim();
10450
10579
  }
10451
10580
  return null;
10452
10581
  }
@@ -10711,9 +10840,9 @@ async function runbookCommand(parsed, deps = {}) {
10711
10840
  });
10712
10841
  }
10713
10842
  case "visibility": {
10714
- const value = parsed.positionals[3] ?? stringOpt(parsed.options.visibility);
10715
- if (!value) throw new Error('"runbook visibility" needs operator|admin, e.g. "runbook visibility release operator"');
10716
- return runbookVisibility(ctx, requireSlug(slug, "visibility"), value);
10843
+ const value2 = parsed.positionals[3] ?? stringOpt(parsed.options.visibility);
10844
+ if (!value2) throw new Error('"runbook visibility" needs operator|admin, e.g. "runbook visibility release operator"');
10845
+ return runbookVisibility(ctx, requireSlug(slug, "visibility"), value2);
10717
10846
  }
10718
10847
  case "publish":
10719
10848
  return runbookStatus(ctx, requireSlug(slug, "publish"), "published");
@@ -10769,13 +10898,13 @@ async function interactiveConfirmation(message2, dependencies) {
10769
10898
  }
10770
10899
  }
10771
10900
  function requiredSecurityPositional(parsed, index, label) {
10772
- const value = parsed.positionals[index];
10773
- if (!value) throw new Error(`${label} is required`);
10774
- return value;
10901
+ const value2 = parsed.positionals[index];
10902
+ if (!value2) throw new Error(`${label} is required`);
10903
+ return value2;
10775
10904
  }
10776
- function securityProfile(value) {
10777
- if (value === void 0) return void 0;
10778
- if (value === "odla" || value === "cloudflare-app" || value === "generic") return value;
10905
+ function securityProfile(value2) {
10906
+ if (value2 === void 0) return void 0;
10907
+ if (value2 === "odla" || value2 === "cloudflare-app" || value2 === "generic") return value2;
10779
10908
  throw new Error("--profile must be odla, cloudflare-app, or generic");
10780
10909
  }
10781
10910
 
@@ -10876,9 +11005,9 @@ function routeLabel(route2) {
10876
11005
  return `${route2.provider}/${route2.model}${route2.policyVersion ? ` policy v${route2.policyVersion}` : ""}`;
10877
11006
  }
10878
11007
  var HOSTED_SEVERITIES = ["informational", "low", "medium", "high", "critical"];
10879
- function hostedSeverity(value, flag) {
10880
- if (HOSTED_SEVERITIES.includes(value)) {
10881
- return value;
11008
+ function hostedSeverity(value2, flag) {
11009
+ if (HOSTED_SEVERITIES.includes(value2)) {
11010
+ return value2;
10882
11011
  }
10883
11012
  throw new Error(`${flag} must be informational, low, medium, high, or critical`);
10884
11013
  }
@@ -10945,7 +11074,7 @@ async function runSourceSecurityCommand(parsed, dependencies, sourceId) {
10945
11074
  ...context,
10946
11075
  jobId: job.jobId,
10947
11076
  wait: dependencies.pollWait,
10948
- onUpdate: parsed.options.json === true ? void 0 : (value) => printHostedJob(context.stdout, value, context.platform, context.appId)
11077
+ onUpdate: parsed.options.json === true ? void 0 : (value2) => printHostedJob(context.stdout, value2, context.platform, context.appId)
10949
11078
  }) : job;
10950
11079
  if (!follow) {
10951
11080
  if (parsed.options.json === true) {
@@ -11045,9 +11174,9 @@ function enforceLocalGate(report4, parsed) {
11045
11174
  throw new Error(`hosted security gate failed: ${confirmed.length} confirmed >= ${failOn}; ${leads.length} leads >= ${failOnCandidates ?? "disabled"}${incomplete ? "; coverage incomplete" : ""}`);
11046
11175
  }
11047
11176
  }
11048
- function severityOpt(value, flag) {
11049
- if (["informational", "low", "medium", "high", "critical"].includes(value)) {
11050
- return value;
11177
+ function severityOpt(value2, flag) {
11178
+ if (["informational", "low", "medium", "high", "critical"].includes(value2)) {
11179
+ return value2;
11051
11180
  }
11052
11181
  throw new Error(`${flag} must be informational, low, medium, high, or critical`);
11053
11182
  }
@@ -11155,7 +11284,7 @@ async function securityStatus(parsed, dependencies) {
11155
11284
  ...context,
11156
11285
  jobId,
11157
11286
  wait: dependencies.pollWait,
11158
- onUpdate: parsed.options.json === true ? void 0 : (value) => printHostedJob(context.stdout, value, context.platform, context.appId)
11287
+ onUpdate: parsed.options.json === true ? void 0 : (value2) => printHostedJob(context.stdout, value2, context.platform, context.appId)
11159
11288
  }) : await getHostedSecurityJob({ ...context, jobId });
11160
11289
  if (parsed.options.json === true) context.stdout.log(JSON.stringify(job, null, 2));
11161
11290
  else if (parsed.options.follow !== true) {
@@ -11239,6 +11368,10 @@ async function runCli(argv = process.argv.slice(2), dependencies = {}) {
11239
11368
  await o11yCommand(parsed, runtime);
11240
11369
  return;
11241
11370
  }
11371
+ if (command === "platform") {
11372
+ await platformCommand(parsed, runtime);
11373
+ return;
11374
+ }
11242
11375
  if (command === "provision") {
11243
11376
  await provisionCommand(parsed, runtime);
11244
11377
  return;
@@ -11358,4 +11491,4 @@ export {
11358
11491
  exitCodeFor,
11359
11492
  runCli
11360
11493
  };
11361
- //# sourceMappingURL=chunk-S3EJ66VG.js.map
11494
+ //# sourceMappingURL=chunk-L2NG4UR4.js.map