@sealant/mend 0.33.0 → 0.34.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +74 -13
  2. package/dist/{chunk-GJFMD7XF.js → chunk-AAAXHRWL.js} +457 -87
  3. package/dist/{dashboard-NWHR7I5W.js → dashboard-DWXXYFPE.js} +41 -13
  4. package/dist/main.js +916 -322
  5. package/man/mend-accounts.1 +1 -1
  6. package/man/mend-adopt.1 +1 -1
  7. package/man/mend-attach.1 +1 -1
  8. package/man/mend-codex.1 +1 -1
  9. package/man/mend-completions.1 +1 -1
  10. package/man/mend-connect.1 +1 -1
  11. package/man/mend-continue.1 +1 -1
  12. package/man/mend-doctor.1 +2 -2
  13. package/man/mend-dotfiles-repo.1 +1 -1
  14. package/man/mend-dotfiles-sync.1 +1 -1
  15. package/man/mend-dotfiles.1 +1 -1
  16. package/man/mend-env-cluster.1 +1 -1
  17. package/man/mend-env-load.1 +1 -1
  18. package/man/mend-env-show.1 +1 -1
  19. package/man/mend-folder-create.1 +1 -1
  20. package/man/mend-folder-list.1 +1 -1
  21. package/man/mend-folder-push.1 +1 -1
  22. package/man/mend-folder-rm.1 +1 -1
  23. package/man/mend-git-author.1 +1 -1
  24. package/man/mend-help.1 +1 -1
  25. package/man/mend-invite.1 +1 -1
  26. package/man/mend-keys-init.1 +1 -1
  27. package/man/mend-keys-mode.1 +1 -1
  28. package/man/mend-keys-share.1 +1 -1
  29. package/man/mend-keys-show.1 +1 -1
  30. package/man/mend-land.1 +1 -1
  31. package/man/mend-login.1 +1 -1
  32. package/man/mend-logout.1 +1 -1
  33. package/man/mend-man.1 +1 -1
  34. package/man/mend-members.1 +1 -1
  35. package/man/mend-operator-exposure.1 +1 -1
  36. package/man/mend-operator-gate.1 +1 -1
  37. package/man/mend-operator-grant-owner.1 +1 -1
  38. package/man/mend-operator-org-create.1 +1 -1
  39. package/man/mend-operator-org-invite-owner.1 +1 -1
  40. package/man/mend-operator-org-list.1 +1 -1
  41. package/man/mend-operator-org-rename.1 +1 -1
  42. package/man/mend-operator-reset-link.1 +1 -1
  43. package/man/mend-pair.1 +1 -1
  44. package/man/mend-projects.1 +1 -1
  45. package/man/mend-pull.1 +1 -1
  46. package/man/mend-refresh.1 +1 -1
  47. package/man/mend-rejoin.1 +1 -1
  48. package/man/mend-resume.1 +1 -1
  49. package/man/mend-run.1 +1 -1
  50. package/man/mend-server-logs.1 +1 -1
  51. package/man/mend-server-restart.1 +1 -1
  52. package/man/mend-server-setup.1 +1 -1
  53. package/man/mend-server-start.1 +1 -1
  54. package/man/mend-server-status.1 +1 -1
  55. package/man/mend-server-stop.1 +1 -1
  56. package/man/mend-server-upgrade.1 +1 -1
  57. package/man/mend-server.1 +1 -1
  58. package/man/mend-service-add.1 +1 -1
  59. package/man/mend-service-connect.1 +1 -1
  60. package/man/mend-service-init.1 +1 -1
  61. package/man/mend-service-list.1 +1 -1
  62. package/man/mend-service-logs.1 +1 -1
  63. package/man/mend-service-restart.1 +1 -1
  64. package/man/mend-service-run.1 +1 -1
  65. package/man/mend-service-stop.1 +1 -1
  66. package/man/mend-session-share.1 +1 -1
  67. package/man/mend-sessions.1 +1 -1
  68. package/man/mend-shell.1 +1 -1
  69. package/man/mend-skills-push.1 +1 -1
  70. package/man/mend-skills.1 +1 -1
  71. package/man/mend-snake.1 +1 -1
  72. package/man/mend-ssh-setup.1 +1 -1
  73. package/man/mend-ssh.1 +1 -1
  74. package/man/mend-stop.1 +1 -1
  75. package/man/mend-ui.1 +1 -1
  76. package/man/mend-uninstall.1 +1 -1
  77. package/man/mend-version.1 +1 -1
  78. package/man/mend-worktrees.1 +1 -1
  79. package/man/mend.1 +1 -1
  80. package/package.json +3 -3
@@ -26829,6 +26829,8 @@ var AuditAction = Schema_exports.Literals([
26829
26829
  "reference.removed",
26830
26830
  "session.shared_control_on",
26831
26831
  "session.shared_control_off",
26832
+ // The owner ended a session's workspace with captures still pending: work was discarded.
26833
+ "session.unsaved_discarded",
26832
26834
  "member.password_reset_issued",
26833
26835
  "organization.created",
26834
26836
  "organization.renamed",
@@ -26931,7 +26933,7 @@ var ChangeLanding = class extends Schema_exports.Class("ChangeLanding")({
26931
26933
  createdAt: Timestamp
26932
26934
  }) {
26933
26935
  };
26934
- var RequestIntent = Schema_exports.Literals(["change", "question"]);
26936
+ var RequestIntent = Schema_exports.Literals(["change", "question", "land"]);
26935
26937
  var RequestIntentSource = Schema_exports.Literals(["read", "option", "unread"]);
26936
26938
  var RequestIntentReading = Schema_exports.Union([
26937
26939
  Schema_exports.Struct({ intent: RequestIntent, source: Schema_exports.Literals(["read", "option"]) }),
@@ -26939,12 +26941,23 @@ var RequestIntentReading = Schema_exports.Union([
26939
26941
  ]);
26940
26942
  var LANDING_GUARD = [
26941
26943
  "--- How this work is published ---",
26942
- "Mend publishes the changes this session makes: it pushes the branch and opens or updates the pull request.",
26944
+ "Mend publishes this session's change, not you: after a turn that asked for a change, Mend pushes the branch and opens or updates the pull request.",
26943
26945
  "- If the request is a question, answer it and change no files.",
26944
26946
  "- Change code only when the request asks for a change.",
26945
- "- Never push and never open a pull request. Committing is fine.",
26947
+ "- If the user asks you to land, push, publish or open a pull request, run `mend land` and report the lines it prints as they are. It lands as the change's owner, or says why it did not.",
26948
+ "- Never push and never open a pull request yourself. Committing is fine.",
26946
26949
  "--- End of how this work is published ---"
26947
26950
  ].join("\n");
26951
+ var EARLIER_LANDING_GUARDS = [
26952
+ [
26953
+ "--- How this work is published ---",
26954
+ "Mend publishes the changes this session makes: it pushes the branch and opens or updates the pull request.",
26955
+ "- If the request is a question, answer it and change no files.",
26956
+ "- Change code only when the request asks for a change.",
26957
+ "- Never push and never open a pull request. Committing is fine.",
26958
+ "--- End of how this work is published ---"
26959
+ ].join("\n")
26960
+ ];
26948
26961
  var NotLandedReason = Schema_exports.Literals([
26949
26962
  /** The request read as a question. */
26950
26963
  "question",
@@ -26953,7 +26966,17 @@ var NotLandedReason = Schema_exports.Literals([
26953
26966
  /** Automatic landing is off for the session. */
26954
26967
  "off",
26955
26968
  /** Someone other than the owner sent the turn under shared control. */
26956
- "not-owner"
26969
+ "not-owner",
26970
+ /** The request asked for a change or a landing, and the change is empty. */
26971
+ "no-change",
26972
+ /** The request asked for a change or a landing, and the last landing already pushed it all. */
26973
+ "nothing-new",
26974
+ /**
26975
+ * The executor's captures never caught up with the turn (`capture.flush` refused, timed out
26976
+ * or partial however often Mend asked), so the change Mend can read may be stale. Mend does not
26977
+ * land it, and does not call it empty either.
26978
+ */
26979
+ "not-captured"
26957
26980
  ]);
26958
26981
  var TurnLanding = Schema_exports.Literals([
26959
26982
  "attempted",
@@ -26961,6 +26984,9 @@ var TurnLanding = Schema_exports.Literals([
26961
26984
  "option",
26962
26985
  "off",
26963
26986
  "not-owner",
26987
+ "no-change",
26988
+ "nothing-new",
26989
+ "not-captured",
26964
26990
  "skipped"
26965
26991
  ]);
26966
26992
  var LandingFact = Schema_exports.Union([
@@ -27005,11 +27031,15 @@ var observedAgo = (at, now2) => {
27005
27031
  return `${Math.floor(seconds2 / 86400)} d ago`;
27006
27032
  };
27007
27033
  var NOT_LANDED = {
27008
- question: "the request read as a question",
27009
- option: "the request said autopr=false",
27010
- off: "automatic landing is off",
27011
- "not-owner": "the turn was not sent by the owner"
27012
- };
27034
+ question: "changes not landed \xB7 the request read as a question",
27035
+ option: "changes not landed \xB7 the request said autopr=false",
27036
+ off: "changes not landed \xB7 automatic landing is off",
27037
+ "not-owner": "changes not landed \xB7 the turn was not sent by the owner",
27038
+ "no-change": "not landed \xB7 the change is empty",
27039
+ "nothing-new": "not landed \xB7 nothing new since the last landing",
27040
+ "not-captured": "not landed \xB7 the change was not captured"
27041
+ };
27042
+ var notLandedLine = (reason) => NOT_LANDED[reason];
27013
27043
  var landingFactLine = (fact, now2) => {
27014
27044
  switch (fact._tag) {
27015
27045
  case "pushed":
@@ -27029,7 +27059,7 @@ var landingFactLine = (fact, now2) => {
27029
27059
  case "agent-push":
27030
27060
  return fact.sha === null ? `deleted by the agent \xB7 ${fact.ref}` : `pushed by the agent \xB7 ${fact.ref} \xB7 ${shortSha(fact.sha)}`;
27031
27061
  case "not-landed":
27032
- return `changes not landed \xB7 ${NOT_LANDED[fact.reason]}`;
27062
+ return notLandedLine(fact.reason);
27033
27063
  case "intent-not-read":
27034
27064
  return "intent not read";
27035
27065
  }
@@ -27211,6 +27241,139 @@ var AgentEvent = Schema_exports.Union([
27211
27241
  Schema_exports.TaggedStruct("runtime.error", { message: Schema_exports.String })
27212
27242
  ]);
27213
27243
 
27244
+ // ../../packages/domain/src/workbench/capture-drain.ts
27245
+ var CaptureDrainReason = Schema_exports.Literals(["stop", "relaunch", "replacement"]);
27246
+ var FALLBACK_REPLACEMENT_AGE_SECONDS = 7 * 60 * 60 + 30 * 60;
27247
+ var CAPTURE_EXECUTOR_RETAINED = "retained";
27248
+ var CAPTURE_COMPLETION_UNREPORTED = "unreported";
27249
+ var captureDurationWords = (ms) => {
27250
+ const seconds2 = Math.max(0, Math.floor(ms / 1e3));
27251
+ if (seconds2 < 60) return `${seconds2} s`;
27252
+ const minutes2 = Math.floor(seconds2 / 60);
27253
+ if (minutes2 < 60) return `${minutes2} min`;
27254
+ const rest = minutes2 % 60;
27255
+ return `${Math.floor(minutes2 / 60)} h${rest === 0 ? "" : ` ${rest} min`}`;
27256
+ };
27257
+ var captureOverdueWords = (overdue) => [
27258
+ "capture step overdue",
27259
+ overdue.step.trim() === "" ? "a capture step" : clipped(overdue.step),
27260
+ ...overdue.runningMs === null ? [] : [`running ${captureDurationWords(overdue.runningMs)}`],
27261
+ ...overdue.boundMs === null ? [] : [`bound ${captureDurationWords(overdue.boundMs)}`]
27262
+ ].join(" \xB7 ");
27263
+ var DETAIL_MAX = 200;
27264
+ var clipped = (text) => {
27265
+ const flat = text.replace(/\s+/g, " ").trim();
27266
+ return flat.length <= DETAIL_MAX ? flat : `${flat.slice(0, DETAIL_MAX - 1)}\u2026`;
27267
+ };
27268
+ var captureIncompleteWords = (reason) => {
27269
+ switch (reason) {
27270
+ case void 0:
27271
+ case null:
27272
+ case "pending":
27273
+ case "in-progress":
27274
+ return null;
27275
+ case CAPTURE_COMPLETION_UNREPORTED:
27276
+ return "final flush not reported";
27277
+ case "not-final":
27278
+ return "final flush not supported";
27279
+ case "processes-remain":
27280
+ return "processes remain";
27281
+ case "sweep-unavailable":
27282
+ return "process sweep unavailable";
27283
+ case "snapshot-failed":
27284
+ return "snapshot failed";
27285
+ case "unreadable":
27286
+ return "unreadable paths";
27287
+ case "fenced":
27288
+ return "fenced";
27289
+ case "conflict":
27290
+ return "conflict";
27291
+ case "deadline":
27292
+ return "deadline passed";
27293
+ case "ship-failed":
27294
+ return "upload failed";
27295
+ case "sealing":
27296
+ return "final seal not confirmed";
27297
+ case "changed":
27298
+ return "changed after the final flush";
27299
+ case "unwatched":
27300
+ return "a capture class is polled, currency not observed";
27301
+ case "store-fidelity":
27302
+ return "the store does not read every manifest feature this executor writes";
27303
+ case "internal":
27304
+ return "executor error";
27305
+ case CAPTURE_EXECUTOR_RETAINED:
27306
+ return "executor kept for recovery";
27307
+ default:
27308
+ return reason;
27309
+ }
27310
+ };
27311
+ var UNITS = ["B", "KB", "MB", "GB", "TB"];
27312
+ var captureBytesWords = (bytes) => {
27313
+ let value3 = Math.max(0, bytes);
27314
+ let unit = 0;
27315
+ while (value3 >= 1e3 && unit < UNITS.length - 1) {
27316
+ value3 /= 1e3;
27317
+ unit += 1;
27318
+ }
27319
+ const shown = unit === 0 || value3 >= 10 ? Math.round(value3).toString() : value3.toFixed(1);
27320
+ return `${shown} ${UNITS[unit]}`;
27321
+ };
27322
+ var leftWords = (facts) => {
27323
+ if (facts.capturePendingBytes !== null) return captureBytesWords(facts.capturePendingBytes);
27324
+ if (facts.capturePending !== null) return `${facts.capturePending}`;
27325
+ return null;
27326
+ };
27327
+ var utcTime = (at) => `${at.toISOString().slice(11, 19)} UTC`;
27328
+ var timeOf = (at) => {
27329
+ if (at === null || at === void 0) return null;
27330
+ const date2 = typeof at === "string" ? new Date(at) : at;
27331
+ return Number.isNaN(date2.getTime()) ? null : date2;
27332
+ };
27333
+ var captureStatusLine = (facts) => {
27334
+ const left = leftWords(facts);
27335
+ const step = facts.captureOverdueStep ?? null;
27336
+ const overdue = step === null ? null : captureOverdueWords({
27337
+ step,
27338
+ runningMs: facts.captureOverdueRunningMs ?? null,
27339
+ boundMs: facts.captureOverdueBoundMs ?? null
27340
+ });
27341
+ if (facts.captureDrain !== null) {
27342
+ if (facts.captureNotSavedAt !== null) {
27343
+ const why = captureIncompleteWords(facts.captureIncompleteReason);
27344
+ const detail = facts.captureIncompleteDetail ?? null;
27345
+ return [
27346
+ "not saved",
27347
+ ...why === null ? [] : [why],
27348
+ ...detail === null || detail === "" ? [] : [detail],
27349
+ ...overdue === null ? [] : [overdue],
27350
+ ...left === null ? [] : [`${left} pending`],
27351
+ ...facts.captureIncompleteReason === CAPTURE_EXECUTOR_RETAINED ? [] : ["workspace kept"]
27352
+ ].join(" \xB7 ");
27353
+ }
27354
+ return [
27355
+ left === null ? "saving" : `saving \xB7 ${left} left`,
27356
+ ...overdue === null ? [] : [overdue]
27357
+ ].join(" \xB7 ");
27358
+ }
27359
+ if (overdue !== null) return overdue;
27360
+ const failingSince = timeOf(facts.captureFailingSince);
27361
+ if (failingSince !== null) {
27362
+ const error = facts.captureFailingError ?? null;
27363
+ return [
27364
+ `capture failing since ${utcTime(failingSince)}`,
27365
+ ...error === null || error === "" ? [] : [error]
27366
+ ].join(" \xB7 ");
27367
+ }
27368
+ if ((facts.captureRefused ?? 0) > 0) return `not saved \xB7 ${facts.captureRefused} refused`;
27369
+ const discardedAt = timeOf(facts.captureDiscardedAt);
27370
+ if (discardedAt !== null) {
27371
+ const by = facts.captureDiscardedBy ?? null;
27372
+ return `unsaved work discarded${by === null || by === "" ? "" : ` by ${by}`} at ${utcTime(discardedAt)}`;
27373
+ }
27374
+ return null;
27375
+ };
27376
+
27214
27377
  // ../../packages/domain/src/workbench/change.ts
27215
27378
  var Change = class extends Schema_exports.Class("WorkbenchChange")({
27216
27379
  id: ChangeId,
@@ -27485,6 +27648,7 @@ var SessionStatus = Schema_exports.Literals([
27485
27648
  "running",
27486
27649
  "waiting",
27487
27650
  "idle",
27651
+ "stopping",
27488
27652
  "completed",
27489
27653
  "failed",
27490
27654
  "stopped"
@@ -27567,6 +27731,116 @@ var Session = class extends Schema_exports.Class("Session")({
27567
27731
  * boot sweep has not classified yet).
27568
27732
  */
27569
27733
  hasTranscript: Schema_exports.NullOr(Schema_exports.Boolean),
27734
+ /**
27735
+ * When Mend stopped the session's protocol agent for idleness (MEND_PROTOCOL_IDLE_STOP_MINUTES,
27736
+ * `protocolIdleReading`), and the claim that stops it once across workers. Null again once the
27737
+ * session reopens.
27738
+ */
27739
+ idleStoppedAt: Schema_exports.NullOr(Timestamp).pipe(Schema_exports.withConstructorDefault(Effect_exports.succeed(null))),
27740
+ /**
27741
+ * Capture mode (docs/adr/0002-session-capture-store.md, "Stop drains, then terminates"): what
27742
+ * the session's executor last answered to a flush — captures staged and not yet registered
27743
+ * (bulk included), the bytes left once sealantd reports them, captures its byte quota refused —
27744
+ * when Mend asked, and the chain head's registration time as seen then. Null until asked.
27745
+ */
27746
+ capturePending: Schema_exports.NullOr(Schema_exports.Int).pipe(
27747
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27748
+ ),
27749
+ capturePendingBytes: Schema_exports.NullOr(Schema_exports.Number).pipe(
27750
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27751
+ ),
27752
+ captureRefused: Schema_exports.NullOr(Schema_exports.Int).pipe(
27753
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27754
+ ),
27755
+ captureRegisteredAt: Schema_exports.NullOr(Timestamp).pipe(
27756
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27757
+ ),
27758
+ captureObservedAt: Schema_exports.NullOr(Timestamp).pipe(
27759
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27760
+ ),
27761
+ /**
27762
+ * A drain under way: why (a stop, a relaunch, a replacement before the platform's cap), since
27763
+ * when, the last time anything moved, and when it stopped moving (`not saved · workspace kept`).
27764
+ * The intent is durable: a Mend restart takes the drain up again. All null once the workspace
27765
+ * is saved and terminated, or discarded by its owner.
27766
+ */
27767
+ captureDrain: Schema_exports.NullOr(CaptureDrainReason).pipe(
27768
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27769
+ ),
27770
+ captureDrainRequestedAt: Schema_exports.NullOr(Timestamp).pipe(
27771
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27772
+ ),
27773
+ captureDrainProgressAt: Schema_exports.NullOr(Timestamp).pipe(
27774
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27775
+ ),
27776
+ captureNotSavedAt: Schema_exports.NullOr(Timestamp).pipe(
27777
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27778
+ ),
27779
+ /**
27780
+ * Why the executor's last final flush did not complete, in sealantd's words
27781
+ * (`captureIncompleteReasonOf`): what `not saved · … · workspace kept` names. Null once one
27782
+ * completed, and outside a drain.
27783
+ */
27784
+ captureIncompleteReason: Schema_exports.NullOr(Schema_exports.String).pipe(
27785
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27786
+ ),
27787
+ /**
27788
+ * What sealantd named behind that reason (`captureSnapDetailOf`): the snap's error, the first
27789
+ * path it could not read. Null when it named nothing, and outside a drain.
27790
+ */
27791
+ captureIncompleteDetail: Schema_exports.NullOr(Schema_exports.String).pipe(
27792
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27793
+ ),
27794
+ /**
27795
+ * A running executor whose snaps are failing (`capture failing since … · <error>`): since when,
27796
+ * as sealantd said or as Mend first observed it, and sealantd's last error. Both null once a
27797
+ * reading shows its snaps succeed again.
27798
+ */
27799
+ captureFailingSince: Schema_exports.NullOr(Timestamp).pipe(
27800
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27801
+ ),
27802
+ captureFailingError: Schema_exports.NullOr(Schema_exports.String).pipe(
27803
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27804
+ ),
27805
+ /**
27806
+ * A capture step the executor reported still running past its bound (sealantd `overdue`, e2e8):
27807
+ * what it is, when it started, how long it had run and the bound it passed, as last observed.
27808
+ * All null once a reading reports none, and once the executor is gone. Not a failure, and never
27809
+ * idle or saved while it lasts.
27810
+ */
27811
+ captureOverdueStep: Schema_exports.NullOr(Schema_exports.String).pipe(
27812
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27813
+ ),
27814
+ captureOverdueSince: Schema_exports.NullOr(Timestamp).pipe(
27815
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27816
+ ),
27817
+ captureOverdueRunningMs: Schema_exports.NullOr(Schema_exports.Number).pipe(
27818
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27819
+ ),
27820
+ captureOverdueBoundMs: Schema_exports.NullOr(Schema_exports.Number).pipe(
27821
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27822
+ ),
27823
+ /**
27824
+ * The owner's "discard unsaved and stop" ended this executor with work not saved: when, and
27825
+ * who (their display name). Null until then, and again once the session runs again.
27826
+ */
27827
+ captureDiscardedAt: Schema_exports.NullOr(Timestamp).pipe(
27828
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27829
+ ),
27830
+ captureDiscardedBy: Schema_exports.NullOr(Schema_exports.String).pipe(
27831
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27832
+ ),
27833
+ /**
27834
+ * When the session's current executor started — what the platform's cap counts from, not the
27835
+ * latest run. Null before launch and for rows from before the column.
27836
+ */
27837
+ executorStartedAt: Schema_exports.NullOr(Timestamp).pipe(
27838
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27839
+ ),
27840
+ /** Removal asked while the workspace was still up: the row goes once the workspace has. */
27841
+ removalRequestedAt: Schema_exports.NullOr(Timestamp).pipe(
27842
+ Schema_exports.withConstructorDefault(Effect_exports.succeed(null))
27843
+ ),
27570
27844
  status: SessionStatus,
27571
27845
  /** What the harness reported at settle, when anything. */
27572
27846
  summary: Schema_exports.NullOr(Schema_exports.String),
@@ -27690,7 +27964,7 @@ var ProjectClusterBindingsSnapshot = class extends Schema_exports.Class(
27690
27964
  }) {
27691
27965
  };
27692
27966
 
27693
- // ../../node_modules/.pnpm/@sealant+api-contracts@0.37.2_effect@4.0.0-beta.93/node_modules/@sealant/api-contracts/dist/workspace-environment.js
27967
+ // ../../node_modules/.pnpm/@sealant+api-contracts@0.38.0_effect@4.0.0-beta.93/node_modules/@sealant/api-contracts/dist/workspace-environment.js
27694
27968
  var RESERVED_NAMES = new Map([
27695
27969
  // Identity/process roots the daemon and shells own.
27696
27970
  ...[
@@ -27789,6 +28063,80 @@ var ProjectSecretsSnapshot = class extends Schema_exports.Class(
27789
28063
  }) {
27790
28064
  };
27791
28065
 
28066
+ // ../../packages/domain/src/workbench/session-process.ts
28067
+ var SessionProcessKind = Schema_exports.Literals([
28068
+ "shell",
28069
+ "agent-pty",
28070
+ "agent-protocol",
28071
+ "agent-external",
28072
+ "service"
28073
+ ]);
28074
+ var SessionProcessStatus = Schema_exports.Literals([
28075
+ "starting",
28076
+ "running",
28077
+ "reachable",
28078
+ "unreachable",
28079
+ "exited",
28080
+ "stopped"
28081
+ ]);
28082
+ var ProtocolLaunchOptions = Schema_exports.Struct({
28083
+ model: Schema_exports.NullOr(Schema_exports.String),
28084
+ effort: Schema_exports.NullOr(Schema_exports.Literals(EFFORT_LEVELS)),
28085
+ permissionMode: Schema_exports.Literals(PERMISSION_MODES)
28086
+ });
28087
+ var SessionProcess = class extends Schema_exports.Class("SessionProcess")({
28088
+ id: SessionProcessId,
28089
+ sessionId: SessionId,
28090
+ /** The workspace incarnation this process ran in; processes never migrate. */
28091
+ sealantWorkspaceId: SealantWorkspaceId,
28092
+ /** The platform interactive-session id — the attach handle. Null for adopted Services (no process of ours). */
28093
+ sealantSessionId: Schema_exports.NullOr(Schema_exports.String),
28094
+ /** The run recording this process — its record outlives the process AND the workspace. */
28095
+ sealantRunId: Schema_exports.NullOr(SealantRunId),
28096
+ /** Server-owned launch intent used to reconcile retries after process acceptance. */
28097
+ launchCorrelationId: Schema_exports.NullOr(Schema_exports.String),
28098
+ /** Stable Service identity when this process is one Service attempt. */
28099
+ serviceId: Schema_exports.NullOr(ServiceId),
28100
+ /** Monotonic within one Service; null for non-Service and legacy projection rows. */
28101
+ attemptOrdinal: Schema_exports.NullOr(Schema_exports.Int),
28102
+ kind: SessionProcessKind,
28103
+ /**
28104
+ * Agent processes: the adapter that launched this process — `codex` · `claude` · `opencode` ·
28105
+ * `shell` (an open-workbench launch inside an agent session). Null for shells and Services.
28106
+ */
28107
+ harness: Schema_exports.NullOr(Schema_exports.String),
28108
+ /**
28109
+ * Agent processes: the harness's OWN session id, harvested when the process ends (or known
28110
+ * up front for a native resume). Resume addresses the latest agent process's id.
28111
+ */
28112
+ providerSessionId: Schema_exports.NullOr(Schema_exports.String),
28113
+ /** agent-protocol rows: the persisted adapter options; null for every other kind and legacy rows. */
28114
+ protocolOptions: Schema_exports.NullOr(ProtocolLaunchOptions),
28115
+ /** Human name for pickers and lists ("claude", "shell", "web"). */
28116
+ label: Schema_exports.NullOr(Schema_exports.String),
28117
+ argv: Schema_exports.Array(Schema_exports.String),
28118
+ status: SessionProcessStatus,
28119
+ /** Observed exit code, when the platform reported one. */
28120
+ exitCode: Schema_exports.NullOr(Schema_exports.Int),
28121
+ /** Services: the port the process listens on INSIDE the workspace. */
28122
+ workspacePort: Schema_exports.NullOr(Schema_exports.Int),
28123
+ /** Services: declared transport. UDP relays datagrams; there is no probe. */
28124
+ protocol: Schema_exports.Literals(["tcp", "udp"]),
28125
+ /** Services: the host port Mend binds on its private interfaces. */
28126
+ hostPort: Schema_exports.NullOr(Schema_exports.Int),
28127
+ createdAt: Timestamp,
28128
+ exitedAt: Schema_exports.NullOr(Timestamp),
28129
+ updatedAt: Timestamp
28130
+ }) {
28131
+ };
28132
+
28133
+ // ../../packages/domain/src/workbench/session-fold.ts
28134
+ var servicesHoldLine = (input) => {
28135
+ if (input.agentLive || input.liveServices <= 0) return null;
28136
+ const hold = input.liveServices === 1 ? "1 service keeps the workspace up" : `${input.liveServices} services keep the workspace up`;
28137
+ return input.agentOutcome === null ? hold : `agent ${input.agentOutcome} \xB7 ${hold}`;
28138
+ };
28139
+
27792
28140
  // ../../packages/domain/src/workbench/review-comment.ts
27793
28141
  var CommentAuthor = Schema_exports.Literals(["reviewer", "mend"]);
27794
28142
  var CommentState = Schema_exports.Literals(["draft", "open", "addressed", "dismissed"]);
@@ -27865,73 +28213,6 @@ var ServiceRecipe = class extends Schema_exports.Class("ServiceRecipe")({
27865
28213
  }) {
27866
28214
  };
27867
28215
 
27868
- // ../../packages/domain/src/workbench/session-process.ts
27869
- var SessionProcessKind = Schema_exports.Literals([
27870
- "shell",
27871
- "agent-pty",
27872
- "agent-protocol",
27873
- "agent-external",
27874
- "service"
27875
- ]);
27876
- var SessionProcessStatus = Schema_exports.Literals([
27877
- "starting",
27878
- "running",
27879
- "reachable",
27880
- "unreachable",
27881
- "exited",
27882
- "stopped"
27883
- ]);
27884
- var ProtocolLaunchOptions = Schema_exports.Struct({
27885
- model: Schema_exports.NullOr(Schema_exports.String),
27886
- effort: Schema_exports.NullOr(Schema_exports.Literals(EFFORT_LEVELS)),
27887
- permissionMode: Schema_exports.Literals(PERMISSION_MODES)
27888
- });
27889
- var SessionProcess = class extends Schema_exports.Class("SessionProcess")({
27890
- id: SessionProcessId,
27891
- sessionId: SessionId,
27892
- /** The workspace incarnation this process ran in; processes never migrate. */
27893
- sealantWorkspaceId: SealantWorkspaceId,
27894
- /** The platform interactive-session id — the attach handle. Null for adopted Services (no process of ours). */
27895
- sealantSessionId: Schema_exports.NullOr(Schema_exports.String),
27896
- /** The run recording this process — its record outlives the process AND the workspace. */
27897
- sealantRunId: Schema_exports.NullOr(SealantRunId),
27898
- /** Server-owned launch intent used to reconcile retries after process acceptance. */
27899
- launchCorrelationId: Schema_exports.NullOr(Schema_exports.String),
27900
- /** Stable Service identity when this process is one Service attempt. */
27901
- serviceId: Schema_exports.NullOr(ServiceId),
27902
- /** Monotonic within one Service; null for non-Service and legacy projection rows. */
27903
- attemptOrdinal: Schema_exports.NullOr(Schema_exports.Int),
27904
- kind: SessionProcessKind,
27905
- /**
27906
- * Agent processes: the adapter that launched this process — `codex` · `claude` · `opencode` ·
27907
- * `shell` (an open-workbench launch inside an agent session). Null for shells and Services.
27908
- */
27909
- harness: Schema_exports.NullOr(Schema_exports.String),
27910
- /**
27911
- * Agent processes: the harness's OWN session id, harvested when the process ends (or known
27912
- * up front for a native resume). Resume addresses the latest agent process's id.
27913
- */
27914
- providerSessionId: Schema_exports.NullOr(Schema_exports.String),
27915
- /** agent-protocol rows: the persisted adapter options; null for every other kind and legacy rows. */
27916
- protocolOptions: Schema_exports.NullOr(ProtocolLaunchOptions),
27917
- /** Human name for pickers and lists ("claude", "shell", "web"). */
27918
- label: Schema_exports.NullOr(Schema_exports.String),
27919
- argv: Schema_exports.Array(Schema_exports.String),
27920
- status: SessionProcessStatus,
27921
- /** Observed exit code, when the platform reported one. */
27922
- exitCode: Schema_exports.NullOr(Schema_exports.Int),
27923
- /** Services: the port the process listens on INSIDE the workspace. */
27924
- workspacePort: Schema_exports.NullOr(Schema_exports.Int),
27925
- /** Services: declared transport. UDP relays datagrams; there is no probe. */
27926
- protocol: Schema_exports.Literals(["tcp", "udp"]),
27927
- /** Services: the host port Mend binds on its private interfaces. */
27928
- hostPort: Schema_exports.NullOr(Schema_exports.Int),
27929
- createdAt: Timestamp,
27930
- exitedAt: Schema_exports.NullOr(Timestamp),
27931
- updatedAt: Timestamp
27932
- }) {
27933
- };
27934
-
27935
28216
  // ../../packages/domain/src/workbench/service.ts
27936
28217
  var ServiceDeclarationSource = Schema_exports.Literals([
27937
28218
  "explicit-run",
@@ -28025,13 +28306,6 @@ var ServiceView = class extends Schema_exports.Class("ServiceView")({
28025
28306
  }) {
28026
28307
  };
28027
28308
 
28028
- // ../../packages/domain/src/workbench/session-fold.ts
28029
- var servicesHoldLine = (input) => {
28030
- if (input.agentLive || input.liveServices <= 0) return null;
28031
- const hold = input.liveServices === 1 ? "1 service keeps the workspace up" : `${input.liveServices} services keep the workspace up`;
28032
- return input.agentOutcome === null ? hold : `agent ${input.agentOutcome} \xB7 ${hold}`;
28033
- };
28034
-
28035
28309
  // ../../packages/domain/src/workbench/session-control.ts
28036
28310
  var SessionControlKind = Schema_exports.Literals([
28037
28311
  "interrupt",
@@ -28039,8 +28313,10 @@ var SessionControlKind = Schema_exports.Literals([
28039
28313
  "shell-open",
28040
28314
  "stop",
28041
28315
  "services-stop",
28316
+ "idle-stop",
28042
28317
  "shared-control-on",
28043
- "shared-control-off"
28318
+ "shared-control-off",
28319
+ "discard-unsaved-stop"
28044
28320
  ]);
28045
28321
  var SessionControlEvent = class extends Schema_exports.Class("SessionControlEvent")({
28046
28322
  id: SessionControlEventId,
@@ -28159,7 +28435,8 @@ var SlackSessionState = Schema_exports.Literals([
28159
28435
  "waiting",
28160
28436
  "completed",
28161
28437
  "failed",
28162
- "stopped"
28438
+ "stopped",
28439
+ "idle-stopped"
28163
28440
  ]);
28164
28441
  var SlackPendingFile = Schema_exports.Struct({
28165
28442
  id: Schema_exports.String,
@@ -28419,6 +28696,26 @@ var servicesHoldOf = (session, currentAgent, liveServices) => servicesHoldLine({
28419
28696
  agentOutcome: agentOutcome(currentAgent),
28420
28697
  liveServices
28421
28698
  });
28699
+ var captureLineOf = (session) => {
28700
+ const drain = session.captureDrain;
28701
+ return captureStatusLine({
28702
+ capturePending: session.capturePending ?? null,
28703
+ capturePendingBytes: session.capturePendingBytes ?? null,
28704
+ captureRefused: session.captureRefused ?? null,
28705
+ captureDrain: drain === "stop" || drain === "relaunch" || drain === "replacement" ? drain : null,
28706
+ captureNotSavedAt: session.captureNotSavedAt ?? null,
28707
+ captureIncompleteReason: session.captureIncompleteReason ?? null,
28708
+ captureIncompleteDetail: session.captureIncompleteDetail ?? null,
28709
+ captureFailingSince: session.captureFailingSince ?? null,
28710
+ captureFailingError: session.captureFailingError ?? null,
28711
+ captureOverdueStep: session.captureOverdueStep ?? null,
28712
+ captureOverdueSince: session.captureOverdueSince ?? null,
28713
+ captureOverdueRunningMs: session.captureOverdueRunningMs ?? null,
28714
+ captureOverdueBoundMs: session.captureOverdueBoundMs ?? null,
28715
+ captureDiscardedAt: session.captureDiscardedAt ?? null,
28716
+ captureDiscardedBy: session.captureDiscardedBy ?? null
28717
+ });
28718
+ };
28422
28719
  var normalizeRemoteUrl = (raw) => {
28423
28720
  if (raw === null) return null;
28424
28721
  const trimmed = raw.trim();
@@ -28502,6 +28799,73 @@ var trackBracketedPaste = (output, current) => {
28502
28799
  };
28503
28800
  var pasteBytes = (text, bracketed) => Buffer.from(bracketed ? `\x1B[200~${text}\x1B[201~` : text, "utf8");
28504
28801
 
28802
+ // src/server-request.ts
28803
+ var MendRequestError = class extends Error {
28804
+ kind;
28805
+ status;
28806
+ constructor(kind, message, status = null) {
28807
+ super(message);
28808
+ this.name = "MendRequestError";
28809
+ this.kind = kind;
28810
+ this.status = status;
28811
+ }
28812
+ };
28813
+ var TIMEOUT_CODES = /* @__PURE__ */ new Set([
28814
+ "UND_ERR_HEADERS_TIMEOUT",
28815
+ "UND_ERR_BODY_TIMEOUT"
28816
+ ]);
28817
+ var DROPPED_CODES = /* @__PURE__ */ new Set([
28818
+ "UND_ERR_SOCKET",
28819
+ "UND_ERR_CLOSED",
28820
+ "ECONNRESET",
28821
+ "EPIPE"
28822
+ ]);
28823
+ var codeOf = (value3) => {
28824
+ if (typeof value3 !== "object" || value3 === null || !("code" in value3)) return null;
28825
+ return typeof value3.code === "string" ? value3.code : null;
28826
+ };
28827
+ var nameOf = (value3) => {
28828
+ if (typeof value3 !== "object" || value3 === null || !("name" in value3)) return null;
28829
+ return typeof value3.name === "string" ? value3.name : null;
28830
+ };
28831
+ var noAnswerOf = (error) => {
28832
+ const name = nameOf(error);
28833
+ if (name === "TimeoutError" || name === "AbortError") return "timeout";
28834
+ const cause = typeof error === "object" && error !== null && "cause" in error ? error.cause : null;
28835
+ const code = codeOf(cause) ?? codeOf(error);
28836
+ if (code !== null && TIMEOUT_CODES.has(code)) return "timeout";
28837
+ if (code !== null && DROPPED_CODES.has(code)) return "dropped";
28838
+ return "unreachable";
28839
+ };
28840
+ var spoken = (ms) => {
28841
+ const seconds2 = Math.round(ms / 1e3);
28842
+ if (seconds2 < 90) return `${seconds2}s`;
28843
+ return `${Math.round(seconds2 / 60)} min`;
28844
+ };
28845
+ var noAnswerMessage = (kind, serverUrl, call, waitedMs) => {
28846
+ if (kind === "unreachable")
28847
+ return `cannot reach the Mend server at ${serverUrl} \u2014 is it running?`;
28848
+ if (kind === "timeout") {
28849
+ return `${call} has had no answer from ${serverUrl} after ${spoken(waitedMs)} \u2014 the server accepted it and may still be working on it`;
28850
+ }
28851
+ return `the connection to ${serverUrl} closed before ${call} answered \u2014 the server may still be working on it`;
28852
+ };
28853
+ var noAnswerError = (error, serverUrl, call, waitedMs) => {
28854
+ const kind = noAnswerOf(error);
28855
+ return new MendRequestError(kind, noAnswerMessage(kind, serverUrl, call, waitedMs));
28856
+ };
28857
+ var GATEWAY_STATUSES = /* @__PURE__ */ new Set([
28858
+ 502,
28859
+ 503,
28860
+ 504,
28861
+ 520,
28862
+ 521,
28863
+ 522,
28864
+ 523,
28865
+ 524
28866
+ ]);
28867
+ var mayStillBeWorking = (error) => error instanceof MendRequestError && (error.kind === "timeout" || error.kind === "dropped" || error.kind === "http" && error.status !== null && GATEWAY_STATUSES.has(error.status));
28868
+
28505
28869
  // src/workbench-events.ts
28506
28870
  var createSseParser = () => {
28507
28871
  let buffer = "";
@@ -28571,6 +28935,7 @@ export {
28571
28935
  agentIsLive,
28572
28936
  agentOutcome,
28573
28937
  servicesHoldOf,
28938
+ captureLineOf,
28574
28939
  normalizeRemoteUrl,
28575
28940
  matchProjectByCwd,
28576
28941
  cwdFacts,
@@ -28581,6 +28946,11 @@ export {
28581
28946
  isPasteChunk,
28582
28947
  trackBracketedPaste,
28583
28948
  pasteBytes,
28949
+ MendRequestError,
28950
+ spoken,
28951
+ noAnswerError,
28952
+ GATEWAY_STATUSES,
28953
+ mayStillBeWorking,
28584
28954
  createSseParser,
28585
28955
  eventFamilies
28586
28956
  };