lua-cli 3.43.0 → 3.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -357,7 +357,11 @@ export declare type LuaWorkflowBuildCode = 'duplicate-step-id' | 'unknown-step-r
357
357
  */
358
358
  | 'approval-inside-container' | 'node-type-unsupported-in-container' | 'empty-graph' | 'ephemeral-role-too-long' | 'role-ref-and-inline' | 'approver-excludes-only-candidate' | 'four-eyes-requires-editable' | 'escalation-chain-not-terminal' | 'escalation-chain-too-long'
359
359
  /** LUA-973: `remindAfterHours` is not a number of hours in 1..720 (`validateApprovalReminder`). */
360
- | 'remind-after-invalid' | 'editable-path-invalid' | 'env-template-secret-key' | 'invalid-envelope' | 'invalid-step' | 'invalid-step-id' | 'invalid-workflow-name' | 'schedule-input-required' | 'schedule-input-invalid' | 'hitl-duration-defaulted' | 'WORKFLOW_UNPLACED_STEP';
360
+ | 'remind-after-invalid'
361
+ /** BAC-2062: the builder mirror of the BAC-619 validator codes: a `waitForSignal` name a delivery refuses. */
362
+ | 'signal-name-invalid'
363
+ /** BAC-2062: a numeric approval / waitForSignal `timeoutHours` outside 1..720. */
364
+ | 'timeout-hours-out-of-range' | 'editable-path-invalid' | 'env-template-secret-key' | 'invalid-envelope' | 'invalid-step' | 'invalid-step-id' | 'invalid-workflow-name' | 'schedule-input-required' | 'schedule-input-invalid' | 'hitl-duration-defaulted' | 'WORKFLOW_UNPLACED_STEP';
361
365
 
362
366
  export declare interface LuaWorkflowBuilder {
363
367
  then(step: StepRef): this;
@@ -448,7 +452,10 @@ export declare interface LuaWorkflowConfig {
448
452
  * marketplace template freezes from this schedule: `'installer'` (the default when absent — every install's
449
453
  * fires run as the person who installed, who gets the run card in their inbox) or `'system'` (the frozen copy
450
454
  * runs user-less and unwatched — no inbox card for its runs; the install response says so). On this agent the
451
- * schedule runs as you either way.
455
+ * schedule runs as you, unless the platform has enabled author system schedules: then `'system'` makes this
456
+ * agent's own schedule run as the agent (`system:<agentId>`), like a template copy's, with you recorded as the
457
+ * deployer who scheduled it (the schedule stops if you lose access to the agent). A manual run ("Run now")
458
+ * always runs as the person who starts it.
452
459
  */
453
460
  schedule?: JobSchedule & {
454
461
  runAs?: 'installer' | 'system';
@@ -548,7 +548,20 @@ var SUPERVISION_OPS = {
548
548
  * agentId }`) to its env. `act`, on a turn whose platform-picked user is the target's owner, never overwriting a
549
549
  * key (`LUA_SECRET_ATTACH_EXISTING_ENABLED`).
550
550
  */
551
- "secrets.attach": "act"
551
+ "secrets.attach": "act",
552
+ /**
553
+ * SV (LUA-1080) — `Agents.deployed(id)`: what the target serves RIGHT NOW, read from each primitive's live pointer
554
+ * (skills with their tools, the published persona, pre/postprocessors), with version ids comparable to an agent
555
+ * version snapshot. Works whether or not the target has a promoted agent version. Metadata and hashes only.
556
+ */
557
+ "primitives.deployed": "observe",
558
+ // [WD]
559
+ /**
560
+ * WD (watchdog grant) — `Agents.versions(id).rollback(version, { expectActive })`: restore a version of the target
561
+ * that was ACTIVE before, is OLDER than the active one and was active within the last 7 days. CAS on the active
562
+ * version; only from a workflow step the watchdog grant names. Held only by a watchdog grant.
563
+ */
564
+ "versions.rollback": "rollback"
552
565
  };
553
566
  function isSupervisionOp(op) {
554
567
  return typeof op === "string" && Object.prototype.hasOwnProperty.call(SUPERVISION_OPS, op);
@@ -729,8 +742,165 @@ var SUPERVISION_OPS_WAVE2 = {
729
742
  gate: "act",
730
743
  targeted: true,
731
744
  item: "SV"
745
+ },
746
+ /** SV (LUA-1080) — `Agents.deployed(id)`: the target's deployed primitives (live pointers, no agent version needed). */
747
+ "primitives.deployed": {
748
+ gate: "observe",
749
+ targeted: true,
750
+ item: "SV"
751
+ },
752
+ /** WD — `Agents.versions(id).rollback(version, { expectActive })` (watchdog grant only). */
753
+ "versions.rollback": {
754
+ gate: "rollback",
755
+ targeted: true,
756
+ item: "WD"
732
757
  }
733
758
  };
759
+ var SUPERVISION_WATCHDOG_OPS = {
760
+ logs: "observe",
761
+ "runs.list": "observe",
762
+ "runs.get": "observe",
763
+ "data.get": "observe",
764
+ "data.query": "observe",
765
+ "versions.list": "observe",
766
+ "versions.get": "observe",
767
+ "versions.diff": "observe",
768
+ "versions.rollback": "rollback"
769
+ };
770
+ function isSupervisionWatchdogOp(op) {
771
+ return typeof op === "string" && Object.prototype.hasOwnProperty.call(SUPERVISION_WATCHDOG_OPS, op);
772
+ }
773
+ __name(isSupervisionWatchdogOp, "isSupervisionWatchdogOp");
774
+ __name3(isSupervisionWatchdogOp, "isSupervisionWatchdogOp");
775
+ var SUPERVISION_WATCHDOG_ERRORS = {
776
+ /** A watchdog holder called an op outside {@link SUPERVISION_WATCHDOG_OPS}. */
777
+ OP_REFUSED: "supervision_watchdog_op_refused",
778
+ /** See {@link SupervisionRollbackRefusalReason}. */
779
+ ROLLBACK_NEVER_ACTIVE: "supervision_rollback_never_active",
780
+ ROLLBACK_NOT_OLDER: "supervision_rollback_not_older",
781
+ ROLLBACK_NOT_IN_LINEAGE: "supervision_rollback_not_in_lineage",
782
+ ROLLBACK_AFTER_ROLLBACK: "supervision_rollback_after_rollback",
783
+ ROLLBACK_AFTER_BACKWARD_PROMOTE: "supervision_rollback_after_backward_promote",
784
+ ROLLBACK_TOO_OLD: "supervision_rollback_too_old",
785
+ /** `expectActive` is not the active version (CAS). */
786
+ ROLLBACK_CONFLICT: "supervision_rollback_conflict",
787
+ /** The promote failed part-way and its compensation restored the previous active version. */
788
+ ROLLBACK_INCOMPLETE: "supervision_rollback_incomplete",
789
+ /** The promote failed part-way AND its compensation failed: the Agents DB may have moved (manual triage). */
790
+ ROLLBACK_INCOMPLETE_UNCOMPENSATED: "supervision_rollback_incomplete_uncompensated"
791
+ };
792
+ var SUPERVISION_ROLLBACK_REFUSAL_CODES = {
793
+ never_active: SUPERVISION_WATCHDOG_ERRORS.ROLLBACK_NEVER_ACTIVE,
794
+ not_older: SUPERVISION_WATCHDOG_ERRORS.ROLLBACK_NOT_OLDER,
795
+ not_in_lineage: SUPERVISION_WATCHDOG_ERRORS.ROLLBACK_NOT_IN_LINEAGE,
796
+ after_rollback: SUPERVISION_WATCHDOG_ERRORS.ROLLBACK_AFTER_ROLLBACK,
797
+ after_backward_promote: SUPERVISION_WATCHDOG_ERRORS.ROLLBACK_AFTER_BACKWARD_PROMOTE,
798
+ too_old: SUPERVISION_WATCHDOG_ERRORS.ROLLBACK_TOO_OLD
799
+ };
800
+ function isSupervisionRollbackRefusalReason(v) {
801
+ return typeof v === "string" && Object.prototype.hasOwnProperty.call(SUPERVISION_ROLLBACK_REFUSAL_CODES, v);
802
+ }
803
+ __name(isSupervisionRollbackRefusalReason, "isSupervisionRollbackRefusalReason");
804
+ __name3(isSupervisionRollbackRefusalReason, "isSupervisionRollbackRefusalReason");
805
+ var SUPERVISION_ROLLBACK_LINEAGE_MAX = 25;
806
+ function supervisionRollbackTargetRefusal(target, expectActive, window) {
807
+ if (target.status !== "superseded" || !target.promotedAt || target.compensationFailed === true) {
808
+ return {
809
+ reason: "never_active",
810
+ message: `Version ${target.version} was never fully the active version (status ${target.status ?? "unknown"})`
811
+ };
812
+ }
813
+ if (typeof expectActive !== "number" || !(target.version < expectActive)) {
814
+ return {
815
+ reason: "not_older",
816
+ message: `Version ${target.version} is not older than the active version ${expectActive ?? "none"}`
817
+ };
818
+ }
819
+ if (window) {
820
+ if (target.supersededVia === "rollback" || target.promotedVia === "rollback") {
821
+ return {
822
+ reason: "after_rollback",
823
+ message: `Version ${target.version} was retired or restored by a rollback`
824
+ };
825
+ }
826
+ if (target.supersededVia !== "promote" && target.supersededVia !== "scoped") {
827
+ return {
828
+ reason: "not_in_lineage",
829
+ message: `Version ${target.version} has no forward-promote history`
830
+ };
831
+ }
832
+ const ended = target.supersededAt ? new Date(target.supersededAt).getTime() : NaN;
833
+ if (!Number.isFinite(ended) || ended < window.now - window.windowMs) {
834
+ return {
835
+ reason: "too_old",
836
+ message: `Version ${target.version} was last active outside the ${Math.round(window.windowMs / 864e5)}-day window`
837
+ };
838
+ }
839
+ }
840
+ return null;
841
+ }
842
+ __name(supervisionRollbackTargetRefusal, "supervisionRollbackTargetRefusal");
843
+ __name3(supervisionRollbackTargetRefusal, "supervisionRollbackTargetRefusal");
844
+ function supervisionRollbackRefusal(input) {
845
+ const { target, active, lineage, expectActive, windowMs, now } = input;
846
+ const pre = supervisionRollbackTargetRefusal(target, expectActive);
847
+ if (pre) return pre;
848
+ if (!active || active.version !== expectActive) {
849
+ return {
850
+ reason: "not_older",
851
+ message: `Version ${expectActive ?? "none"} is not the active version`
852
+ };
853
+ }
854
+ if (active.promotedVia === "rollback") {
855
+ return {
856
+ reason: "after_rollback",
857
+ message: `The active version ${active.version} was restored by a rollback; a watchdog does not roll back twice in a row`
858
+ };
859
+ }
860
+ let previous = active;
861
+ for (const step3 of lineage.slice(0, SUPERVISION_ROLLBACK_LINEAGE_MAX)) {
862
+ const label = `version ${step3.version}`;
863
+ if (step3.supersededVia === "rollback" || step3.promotedVia === "rollback") {
864
+ return {
865
+ reason: "after_rollback",
866
+ message: `The rollback lineage crosses ${label}, which a rollback retired or restored`
867
+ };
868
+ }
869
+ if (step3.supersededVia !== "promote" && step3.supersededVia !== "scoped") {
870
+ return {
871
+ reason: "not_in_lineage",
872
+ message: `The rollback lineage stops at ${label} (no forward-promote history)`
873
+ };
874
+ }
875
+ if (step3.compensationFailed === true || step3.status !== "superseded" || !step3.promotedAt) {
876
+ return {
877
+ reason: "not_in_lineage",
878
+ message: `The rollback lineage stops at ${label} (not fully served)`
879
+ };
880
+ }
881
+ if (!(step3.version < previous.version)) {
882
+ return {
883
+ reason: "after_backward_promote",
884
+ message: `Version ${previous.version} was promoted BACK over ${label}; a watchdog never reaches behind that`
885
+ };
886
+ }
887
+ const ended = step3.supersededAt ? new Date(step3.supersededAt).getTime() : NaN;
888
+ if (!Number.isFinite(ended) || ended < now - windowMs) {
889
+ return {
890
+ reason: "too_old",
891
+ message: `The rollback lineage reaches ${label}, last active outside the ${Math.round(windowMs / 864e5)}-day window`
892
+ };
893
+ }
894
+ if (step3.version === target.version && (!target.id || !step3.id || step3.id === target.id)) return null;
895
+ previous = step3;
896
+ }
897
+ return {
898
+ reason: "not_in_lineage",
899
+ message: `Version ${target.version} is not in the active version's recent forward-promote lineage`
900
+ };
901
+ }
902
+ __name(supervisionRollbackRefusal, "supervisionRollbackRefusal");
903
+ __name3(supervisionRollbackRefusal, "supervisionRollbackRefusal");
734
904
  var SUPERVISION_UNTARGETED_OPS = [
735
905
  "agents.list",
736
906
  ...Object.entries(SUPERVISION_OPS_WAVE2).filter(([, contract]) => !contract.targeted).map(([op]) => op)
@@ -1806,7 +1976,9 @@ var SECRET_REQUEST_ERRORS = {
1806
1976
  /** `secrets.attach` would set an env key the agent already has: never overwritten (remove or rotate it first). */
1807
1977
  KEY_EXISTS: "secret_key_exists",
1808
1978
  /** A request held for an existing agent submitted on the public token page: its owner submits it signed in. */
1809
- OWNER_SUBMIT_REQUIRED: "secret_submit_requires_owner"
1979
+ OWNER_SUBMIT_REQUIRED: "secret_submit_requires_owner",
1980
+ /** LUA-1079 — `requestSecret` with `pendingFor` on a client that did not declare the pending card capability. */
1981
+ PENDING_CARD_UNSUPPORTED: "secret_pending_card_unsupported"
1810
1982
  };
1811
1983
  var SECRET_OUTCOME_STATUSES = [
1812
1984
  ...SECRET_TEST_RESULTS,
@@ -4163,6 +4335,26 @@ var CHANNEL_SETTING_GROUPS = {
4163
4335
  welcome: "Welcome and Home page",
4164
4336
  takeover: "Human takeover"
4165
4337
  };
4338
+ var THREAD_SCOPING_NOUN = {
4339
+ front: "Front conversation",
4340
+ messagebird: "MessageBird conversation",
4341
+ imessage: "iMessage chat"
4342
+ };
4343
+ function threadScopingSetting(type) {
4344
+ const noun = THREAD_SCOPING_NOUN[type];
4345
+ return {
4346
+ key: `${type}.threadScoping`,
4347
+ group: "conversations",
4348
+ label: `One conversation per ${noun}`,
4349
+ help: `Each ${noun} is its own conversation with its own history.`,
4350
+ effect: "Off: every message from the same person shares one conversation.",
4351
+ type: "boolean",
4352
+ default: false,
4353
+ confirm: "Changing this starts fresh conversations for ones that are already open. Earlier history isn't carried over."
4354
+ };
4355
+ }
4356
+ __name(threadScopingSetting, "threadScopingSetting");
4357
+ __name3(threadScopingSetting, "threadScopingSetting");
4166
4358
  var TAKEOVER_CHANNEL_TYPES = [
4167
4359
  "whatsapp",
4168
4360
  "instagram",
@@ -4469,7 +4661,10 @@ var SLACK_SETTINGS = [
4469
4661
  var CHANNEL_SETTINGS = {
4470
4662
  ...Object.fromEntries(TAKEOVER_CHANNEL_TYPES.map((type) => [
4471
4663
  type,
4472
- type === "email" ? EMAIL_SETTINGS : takeoverSettings(type)
4664
+ type === "email" ? EMAIL_SETTINGS : type === "front" || type === "messagebird" || type === "imessage" ? [
4665
+ ...takeoverSettings(type),
4666
+ threadScopingSetting(type)
4667
+ ] : takeoverSettings(type)
4473
4668
  ])),
4474
4669
  slack: SLACK_SETTINGS
4475
4670
  };
@@ -8145,6 +8340,12 @@ function workflowOrgSlotKey(orgId, kind) {
8145
8340
  __name(workflowOrgSlotKey, "workflowOrgSlotKey");
8146
8341
  __name3(workflowOrgSlotKey, "workflowOrgSlotKey");
8147
8342
  var WORKFLOW_CONNECTION_KEY_RE = /^[a-z][a-z0-9_-]{0,63}$/;
8343
+ var WORKFLOW_AGENT_APP_CONNECTION_PREFIX = "agentapp_";
8344
+ function isWorkflowAgentAppConnectionId(id2) {
8345
+ return typeof id2 === "string" && id2.startsWith(WORKFLOW_AGENT_APP_CONNECTION_PREFIX) && /^[A-Za-z0-9_-]{1,128}$/.test(id2);
8346
+ }
8347
+ __name(isWorkflowAgentAppConnectionId, "isWorkflowAgentAppConnectionId");
8348
+ __name3(isWorkflowAgentAppConnectionId, "isWorkflowAgentAppConnectionId");
8148
8349
  var WORKFLOW_JOB_MODEL_SOURCE_LABELS = {
8149
8350
  stamp: "lease stamp",
8150
8351
  initData: "run input",
@@ -8179,6 +8380,7 @@ var WORKFLOW_RUN_NOTIFICATION_SUSPENDED_KINDS = [
8179
8380
  ...WORKFLOW_RUN_GATE_KINDS
8180
8381
  ];
8181
8382
  var WORKFLOW_SIGNAL_PAYLOAD_MAX_BYTES = 64 * 1024;
8383
+ var WORKFLOW_SIGNAL_NAME_RE = /^[a-zA-Z0-9_.-]{1,64}$/;
8182
8384
  var WORKFLOW_SUSPEND_DEFAULT_TIMEOUT_HOURS = 168;
8183
8385
  var WORKFLOW_RESOLVE_OUTPUT_MAX_BYTES = 256 * 1024;
8184
8386
  var SCHEDULE_HEALTH_NOTIFY_CHANNELS = [
@@ -11309,6 +11511,8 @@ __name(validateApproverBlock, "validateApproverBlock");
11309
11511
  __name4(validateApproverBlock, "validateApproverBlock");
11310
11512
  var APPROVAL_REMIND_AFTER_HOURS_MIN = 1;
11311
11513
  var APPROVAL_REMIND_AFTER_HOURS_MAX = 720;
11514
+ var APPROVAL_TIMEOUT_HOURS_MIN = 1;
11515
+ var APPROVAL_TIMEOUT_HOURS_MAX = 720;
11312
11516
  function validateApprovalReminder(node, path) {
11313
11517
  if (node.remindAfterHours === void 0) return [];
11314
11518
  const h = node.remindAfterHours;
@@ -11338,6 +11542,21 @@ function validateApprovalReminder(node, path) {
11338
11542
  }
11339
11543
  __name(validateApprovalReminder, "validateApprovalReminder");
11340
11544
  __name4(validateApprovalReminder, "validateApprovalReminder");
11545
+ function validateHitlTimeoutHours(node, path) {
11546
+ const h = node.timeoutHours;
11547
+ if (typeof h !== "number") return [];
11548
+ if (Number.isFinite(h) && h >= APPROVAL_TIMEOUT_HOURS_MIN && h <= APPROVAL_TIMEOUT_HOURS_MAX) return [];
11549
+ return [
11550
+ {
11551
+ code: "timeout-hours-out-of-range",
11552
+ path: `${path}.timeoutHours`,
11553
+ severity: "error",
11554
+ message: `timeoutHours must be a number of hours in [${APPROVAL_TIMEOUT_HOURS_MIN}, ${APPROVAL_TIMEOUT_HOURS_MAX}] (got ${h})`
11555
+ }
11556
+ ];
11557
+ }
11558
+ __name(validateHitlTimeoutHours, "validateHitlTimeoutHours");
11559
+ __name4(validateHitlTimeoutHours, "validateHitlTimeoutHours");
11341
11560
  function firstAskDeadline(node) {
11342
11561
  const head = Array.isArray(node.onTimeout) ? node.onTimeout[0] : node.onTimeout;
11343
11562
  if (typeof head === "object" && head !== null && "escalateTo" in head) {
@@ -11426,6 +11645,11 @@ function sleepUntilUnsupportedMessage(id2) {
11426
11645
  }
11427
11646
  __name(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
11428
11647
  __name4(sleepUntilUnsupportedMessage, "sleepUntilUnsupportedMessage");
11648
+ function signalNameInvalidMessage(id2, name) {
11649
+ return `waitForSignal "${id2}" signal "${name}" must match /${WORKFLOW_SIGNAL_NAME_RE.source}/ (the names a delivery accepts)`;
11650
+ }
11651
+ __name(signalNameInvalidMessage, "signalNameInvalidMessage");
11652
+ __name4(signalNameInvalidMessage, "signalNameInvalidMessage");
11429
11653
  function armSubrunUnsupportedMessage(id2, workflowId) {
11430
11654
  return `the engine does not execute the implicit \`${workflowId}\` arm subrun (node "${id2}") \u2014 a [map, step] container arm is the step itself with the map as its \`input\` since lua-cli 3.32.4; re-run \`lua compile\` with the current CLI (a hand-written artifact: put the map on the arm node's \`input\` and drop the \`workflow\` wrapper)`;
11431
11655
  }
@@ -12099,10 +12323,13 @@ function validateLuaExtensions(g, caps = WORKFLOW_CAPS_DEFAULT, opts = {
12099
12323
  const w = node;
12100
12324
  checkId(w.id, path);
12101
12325
  if (typeof w.signal !== "string" || w.signal.length === 0) err("invalid-envelope", "waitForSignal.signal is required", `${path}.signal`, w.id);
12326
+ else if (!WORKFLOW_SIGNAL_NAME_RE.test(w.signal)) err("signal-name-invalid", signalNameInvalidMessage(w.id, w.signal), `${path}.signal`, w.id);
12327
+ for (const r of validateHitlTimeoutHours(w, path)) err(r.code, r.message, r.path, w.id);
12102
12328
  return;
12103
12329
  }
12104
12330
  const a = node;
12105
12331
  checkId(a.id, path);
12332
+ for (const r of validateHitlTimeoutHours(a, path)) err(r.code, r.message, r.path, a.id);
12106
12333
  if ((a.approver ?? "creator") === "creator" && a.excludeInitiator === true) {
12107
12334
  err("approver-excludes-only-candidate", "approver:'creator' with excludeInitiator:true always excludes the only candidate", path, a.id);
12108
12335
  }
@@ -15848,6 +16075,9 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
15848
16075
  for (const r of validateApprovalReminder(opts, `approval("${id2}")`)) {
15849
16076
  if (r.severity === "error") throw new LuaWorkflowBuildError("remind-after-invalid", `"${id2}": ${r.message}`);
15850
16077
  }
16078
+ for (const r of validateHitlTimeoutHours(opts, `approval("${id2}")`)) {
16079
+ throw new LuaWorkflowBuildError("timeout-hours-out-of-range", `"${id2}": ${r.message}`);
16080
+ }
15851
16081
  if (typeof opts.details === "function") throw new LuaWorkflowBuildError("closure-binding", `approval("${id2}").details must be template(...)`);
15852
16082
  this.recordEnvRefs(opts.details, opts.timeoutHours, opts.approver);
15853
16083
  const node = defined({
@@ -15878,6 +16108,10 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
15878
16108
  waitForSignal(id2, opts) {
15879
16109
  this.assertId(id2, "waitForSignal()");
15880
16110
  if (!opts || typeof opts.signal !== "string" || opts.signal.length === 0) throw new LuaWorkflowBuildError("invalid-envelope", `waitForSignal("${id2}") needs a signal name`);
16111
+ if (!WORKFLOW_SIGNAL_NAME_RE.test(opts.signal)) throw new LuaWorkflowBuildError("signal-name-invalid", signalNameInvalidMessage(id2, opts.signal));
16112
+ for (const r of validateHitlTimeoutHours(opts, `waitForSignal("${id2}")`)) {
16113
+ throw new LuaWorkflowBuildError("timeout-hours-out-of-range", `"${id2}": ${r.message}`);
16114
+ }
15881
16115
  this.recordEnvRefs(opts.timeoutHours);
15882
16116
  const node = defined({
15883
16117
  type: "waitForSignal",
@@ -15940,7 +16174,7 @@ var WorkflowBuilderImpl = class WorkflowBuilderImpl2 {
15940
16174
  if (this.mapCount >= 2 && this.unnamedMaps > 0) {
15941
16175
  this.warnings.push({
15942
16176
  code: "map-id-required",
15943
- message: `${this.unnamedMaps} of ${this.mapCount} map() calls have no explicit id \u2014 positional ids renumber on insert; pass { id } (error at push)`
16177
+ message: `${this.unnamedMaps} of ${this.mapCount} map() calls have no explicit id \u2014 positional ids renumber on insert; pass { id } to every map() to keep step ids stable`
15944
16178
  });
15945
16179
  }
15946
16180
  if (graphHasHitl(graph, this.steps) && this.config.budget?.maxDurationSeconds === void 0) {