@sealant/mend 0.32.1 → 0.34.2

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-J3TR4UAG.js → chunk-JJ66V76Y.js} +424 -92
  3. package/dist/{dashboard-3HNFSQZD.js → dashboard-OADX3PHI.js} +10 -1
  4. package/dist/main.js +611 -243
  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 +1 -1
@@ -26460,7 +26460,12 @@ var DEFAULT_WORKSPACE_PACKAGES = [
26460
26460
  "jq",
26461
26461
  "ripgrep",
26462
26462
  "fd",
26463
- "fzf"
26463
+ "fzf",
26464
+ "starship",
26465
+ "zsh-autosuggestions",
26466
+ "zsh-syntax-highlighting",
26467
+ "zsh-history-substring-search",
26468
+ "direnv"
26464
26469
  ];
26465
26470
  var workspaceImageServices = Schema_exports.Struct({
26466
26471
  docker: Schema_exports.Boolean.pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(true)))
@@ -26495,7 +26500,7 @@ var defaultWorkspaceImage = {
26495
26500
  mode: "family",
26496
26501
  os: "arch",
26497
26502
  packages: [...DEFAULT_WORKSPACE_PACKAGES],
26498
- shell: "bash",
26503
+ shell: "zsh",
26499
26504
  services: { docker: true }
26500
26505
  };
26501
26506
  var workspaceImageWithDefault = WorkspaceImage.pipe(
@@ -26533,8 +26538,9 @@ var MendSettings = class extends Schema_exports.Class("MendSettings")({
26533
26538
  /**
26534
26539
  * Review automation defaults — the machine-side prep that runs when a
26535
26540
  * session settles, so review opens ready. Each switch is overridable per
26536
- * project (`inherit` follows these): the cascade is settings → project,
26537
- * resolved per session at settle.
26541
+ * organization and per project: the cascade is instance → organization →
26542
+ * project (`organizationDefaults`, then `resolveAutomation`), resolved per
26543
+ * session at settle.
26538
26544
  */
26539
26545
  /** Compose the tour when a session settles — description and walkthrough ready before review opens. */
26540
26546
  autoTour: onByDefault,
@@ -26569,6 +26575,25 @@ var defaultSettings = new MendSettings({
26569
26575
  workspaceImage: defaultWorkspaceImage,
26570
26576
  backgroundSessions: true
26571
26577
  });
26578
+ var OrganizationSettings = class extends Schema_exports.Class(
26579
+ "OrganizationSettings"
26580
+ )({
26581
+ workspaceImage: Schema_exports.NullOr(WorkspaceImage),
26582
+ autoTour: Schema_exports.NullOr(Schema_exports.Boolean),
26583
+ autoSuggest: Schema_exports.NullOr(Schema_exports.Boolean),
26584
+ autoName: Schema_exports.NullOr(Schema_exports.Boolean),
26585
+ autoLand: Schema_exports.NullOr(Schema_exports.Boolean),
26586
+ backgroundSessions: Schema_exports.NullOr(Schema_exports.Boolean)
26587
+ }) {
26588
+ };
26589
+ var inheritedOrganizationSettings = new OrganizationSettings({
26590
+ workspaceImage: null,
26591
+ autoTour: null,
26592
+ autoSuggest: null,
26593
+ autoName: null,
26594
+ autoLand: null,
26595
+ backgroundSessions: null
26596
+ });
26572
26597
 
26573
26598
  // ../../packages/domain/src/timestamp.ts
26574
26599
  var Timestamp = Schema_exports.Union([
@@ -26700,6 +26725,12 @@ var Project = class extends Schema_exports.Class("Project")({
26700
26725
  * "does this project want them applied".
26701
26726
  */
26702
26727
  applyDotfiles: Schema_exports.Boolean,
26728
+ /**
26729
+ * Whether a launch into a zsh workspace writes Mend's default shell profile (`~/.zshrc`,
26730
+ * `~/.config/starship.toml`) where the owner's dotfiles left no file. Never overwrites. Older
26731
+ * values decode to on, the column's default.
26732
+ */
26733
+ defaultShellProfile: Schema_exports.Boolean.pipe(Schema_exports.withDecodingDefaultKey(Effect_exports.succeed(true))),
26703
26734
  /**
26704
26735
  * Whether sessions receive skills from the launching user's library. Project skills always
26705
26736
  * remain enabled and override inherited user skills with the same name. Older values decode to
@@ -26798,9 +26829,13 @@ var AuditAction = Schema_exports.Literals([
26798
26829
  "reference.removed",
26799
26830
  "session.shared_control_on",
26800
26831
  "session.shared_control_off",
26832
+ // The owner ended a session's workspace with captures still pending: work was discarded.
26833
+ "session.unsaved_discarded",
26801
26834
  "member.password_reset_issued",
26802
26835
  "organization.created",
26803
26836
  "organization.renamed",
26837
+ // An owner changed the defaults every project in the organization inherits.
26838
+ "organization.settings_changed",
26804
26839
  "recovery.owner_granted",
26805
26840
  "recovery.password_reset_issued",
26806
26841
  // docs/adr/0006-slack.md, "Audit".
@@ -26833,7 +26868,8 @@ var AuditEvent = class extends Schema_exports.Class("AuditEvent")({
26833
26868
  action: AuditAction,
26834
26869
  /**
26835
26870
  * What the action touched: `member`, `invitation`, `project`, `session`, `folder`, `reference`,
26836
- * `slack` (the organization's Slack app) or `change` (a landing).
26871
+ * `organization` (its name or defaults), `slack` (the organization's Slack app) or `change` (a
26872
+ * landing).
26837
26873
  */
26838
26874
  subjectType: Schema_exports.String,
26839
26875
  subjectId: Schema_exports.String,
@@ -26897,7 +26933,7 @@ var ChangeLanding = class extends Schema_exports.Class("ChangeLanding")({
26897
26933
  createdAt: Timestamp
26898
26934
  }) {
26899
26935
  };
26900
- var RequestIntent = Schema_exports.Literals(["change", "question"]);
26936
+ var RequestIntent = Schema_exports.Literals(["change", "question", "land"]);
26901
26937
  var RequestIntentSource = Schema_exports.Literals(["read", "option", "unread"]);
26902
26938
  var RequestIntentReading = Schema_exports.Union([
26903
26939
  Schema_exports.Struct({ intent: RequestIntent, source: Schema_exports.Literals(["read", "option"]) }),
@@ -26905,12 +26941,23 @@ var RequestIntentReading = Schema_exports.Union([
26905
26941
  ]);
26906
26942
  var LANDING_GUARD = [
26907
26943
  "--- How this work is published ---",
26908
- "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.",
26909
26945
  "- If the request is a question, answer it and change no files.",
26910
26946
  "- Change code only when the request asks for a change.",
26911
- "- 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.",
26912
26949
  "--- End of how this work is published ---"
26913
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
+ ];
26914
26961
  var NotLandedReason = Schema_exports.Literals([
26915
26962
  /** The request read as a question. */
26916
26963
  "question",
@@ -26919,7 +26966,17 @@ var NotLandedReason = Schema_exports.Literals([
26919
26966
  /** Automatic landing is off for the session. */
26920
26967
  "off",
26921
26968
  /** Someone other than the owner sent the turn under shared control. */
26922
- "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"
26923
26980
  ]);
26924
26981
  var TurnLanding = Schema_exports.Literals([
26925
26982
  "attempted",
@@ -26927,6 +26984,9 @@ var TurnLanding = Schema_exports.Literals([
26927
26984
  "option",
26928
26985
  "off",
26929
26986
  "not-owner",
26987
+ "no-change",
26988
+ "nothing-new",
26989
+ "not-captured",
26930
26990
  "skipped"
26931
26991
  ]);
26932
26992
  var LandingFact = Schema_exports.Union([
@@ -26971,11 +27031,15 @@ var observedAgo = (at, now2) => {
26971
27031
  return `${Math.floor(seconds2 / 86400)} d ago`;
26972
27032
  };
26973
27033
  var NOT_LANDED = {
26974
- question: "the request read as a question",
26975
- option: "the request said autopr=false",
26976
- off: "automatic landing is off",
26977
- "not-owner": "the turn was not sent by the owner"
26978
- };
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];
26979
27043
  var landingFactLine = (fact, now2) => {
26980
27044
  switch (fact._tag) {
26981
27045
  case "pushed":
@@ -26995,7 +27059,7 @@ var landingFactLine = (fact, now2) => {
26995
27059
  case "agent-push":
26996
27060
  return fact.sha === null ? `deleted by the agent \xB7 ${fact.ref}` : `pushed by the agent \xB7 ${fact.ref} \xB7 ${shortSha(fact.sha)}`;
26997
27061
  case "not-landed":
26998
- return `changes not landed \xB7 ${NOT_LANDED[fact.reason]}`;
27062
+ return notLandedLine(fact.reason);
26999
27063
  case "intent-not-read":
27000
27064
  return "intent not read";
27001
27065
  }
@@ -27177,6 +27241,139 @@ var AgentEvent = Schema_exports.Union([
27177
27241
  Schema_exports.TaggedStruct("runtime.error", { message: Schema_exports.String })
27178
27242
  ]);
27179
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
+
27180
27377
  // ../../packages/domain/src/workbench/change.ts
27181
27378
  var Change = class extends Schema_exports.Class("WorkbenchChange")({
27182
27379
  id: ChangeId,
@@ -27451,6 +27648,7 @@ var SessionStatus = Schema_exports.Literals([
27451
27648
  "running",
27452
27649
  "waiting",
27453
27650
  "idle",
27651
+ "stopping",
27454
27652
  "completed",
27455
27653
  "failed",
27456
27654
  "stopped"
@@ -27533,6 +27731,116 @@ var Session = class extends Schema_exports.Class("Session")({
27533
27731
  * boot sweep has not classified yet).
27534
27732
  */
27535
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
+ ),
27536
27844
  status: SessionStatus,
27537
27845
  /** What the harness reported at settle, when anything. */
27538
27846
  summary: Schema_exports.NullOr(Schema_exports.String),
@@ -27656,7 +27964,7 @@ var ProjectClusterBindingsSnapshot = class extends Schema_exports.Class(
27656
27964
  }) {
27657
27965
  };
27658
27966
 
27659
- // ../../node_modules/.pnpm/@sealant+api-contracts@0.37.1_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
27660
27968
  var RESERVED_NAMES = new Map([
27661
27969
  // Identity/process roots the daemon and shells own.
27662
27970
  ...[
@@ -27755,6 +28063,80 @@ var ProjectSecretsSnapshot = class extends Schema_exports.Class(
27755
28063
  }) {
27756
28064
  };
27757
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
+
27758
28140
  // ../../packages/domain/src/workbench/review-comment.ts
27759
28141
  var CommentAuthor = Schema_exports.Literals(["reviewer", "mend"]);
27760
28142
  var CommentState = Schema_exports.Literals(["draft", "open", "addressed", "dismissed"]);
@@ -27831,73 +28213,6 @@ var ServiceRecipe = class extends Schema_exports.Class("ServiceRecipe")({
27831
28213
  }) {
27832
28214
  };
27833
28215
 
27834
- // ../../packages/domain/src/workbench/session-process.ts
27835
- var SessionProcessKind = Schema_exports.Literals([
27836
- "shell",
27837
- "agent-pty",
27838
- "agent-protocol",
27839
- "agent-external",
27840
- "service"
27841
- ]);
27842
- var SessionProcessStatus = Schema_exports.Literals([
27843
- "starting",
27844
- "running",
27845
- "reachable",
27846
- "unreachable",
27847
- "exited",
27848
- "stopped"
27849
- ]);
27850
- var ProtocolLaunchOptions = Schema_exports.Struct({
27851
- model: Schema_exports.NullOr(Schema_exports.String),
27852
- effort: Schema_exports.NullOr(Schema_exports.Literals(EFFORT_LEVELS)),
27853
- permissionMode: Schema_exports.Literals(PERMISSION_MODES)
27854
- });
27855
- var SessionProcess = class extends Schema_exports.Class("SessionProcess")({
27856
- id: SessionProcessId,
27857
- sessionId: SessionId,
27858
- /** The workspace incarnation this process ran in; processes never migrate. */
27859
- sealantWorkspaceId: SealantWorkspaceId,
27860
- /** The platform interactive-session id — the attach handle. Null for adopted Services (no process of ours). */
27861
- sealantSessionId: Schema_exports.NullOr(Schema_exports.String),
27862
- /** The run recording this process — its record outlives the process AND the workspace. */
27863
- sealantRunId: Schema_exports.NullOr(SealantRunId),
27864
- /** Server-owned launch intent used to reconcile retries after process acceptance. */
27865
- launchCorrelationId: Schema_exports.NullOr(Schema_exports.String),
27866
- /** Stable Service identity when this process is one Service attempt. */
27867
- serviceId: Schema_exports.NullOr(ServiceId),
27868
- /** Monotonic within one Service; null for non-Service and legacy projection rows. */
27869
- attemptOrdinal: Schema_exports.NullOr(Schema_exports.Int),
27870
- kind: SessionProcessKind,
27871
- /**
27872
- * Agent processes: the adapter that launched this process — `codex` · `claude` · `opencode` ·
27873
- * `shell` (an open-workbench launch inside an agent session). Null for shells and Services.
27874
- */
27875
- harness: Schema_exports.NullOr(Schema_exports.String),
27876
- /**
27877
- * Agent processes: the harness's OWN session id, harvested when the process ends (or known
27878
- * up front for a native resume). Resume addresses the latest agent process's id.
27879
- */
27880
- providerSessionId: Schema_exports.NullOr(Schema_exports.String),
27881
- /** agent-protocol rows: the persisted adapter options; null for every other kind and legacy rows. */
27882
- protocolOptions: Schema_exports.NullOr(ProtocolLaunchOptions),
27883
- /** Human name for pickers and lists ("claude", "shell", "web"). */
27884
- label: Schema_exports.NullOr(Schema_exports.String),
27885
- argv: Schema_exports.Array(Schema_exports.String),
27886
- status: SessionProcessStatus,
27887
- /** Observed exit code, when the platform reported one. */
27888
- exitCode: Schema_exports.NullOr(Schema_exports.Int),
27889
- /** Services: the port the process listens on INSIDE the workspace. */
27890
- workspacePort: Schema_exports.NullOr(Schema_exports.Int),
27891
- /** Services: declared transport. UDP relays datagrams; there is no probe. */
27892
- protocol: Schema_exports.Literals(["tcp", "udp"]),
27893
- /** Services: the host port Mend binds on its private interfaces. */
27894
- hostPort: Schema_exports.NullOr(Schema_exports.Int),
27895
- createdAt: Timestamp,
27896
- exitedAt: Schema_exports.NullOr(Timestamp),
27897
- updatedAt: Timestamp
27898
- }) {
27899
- };
27900
-
27901
28216
  // ../../packages/domain/src/workbench/service.ts
27902
28217
  var ServiceDeclarationSource = Schema_exports.Literals([
27903
28218
  "explicit-run",
@@ -27991,13 +28306,6 @@ var ServiceView = class extends Schema_exports.Class("ServiceView")({
27991
28306
  }) {
27992
28307
  };
27993
28308
 
27994
- // ../../packages/domain/src/workbench/session-fold.ts
27995
- var servicesHoldLine = (input) => {
27996
- if (input.agentLive || input.liveServices <= 0) return null;
27997
- const hold = input.liveServices === 1 ? "1 service keeps the workspace up" : `${input.liveServices} services keep the workspace up`;
27998
- return input.agentOutcome === null ? hold : `agent ${input.agentOutcome} \xB7 ${hold}`;
27999
- };
28000
-
28001
28309
  // ../../packages/domain/src/workbench/session-control.ts
28002
28310
  var SessionControlKind = Schema_exports.Literals([
28003
28311
  "interrupt",
@@ -28005,8 +28313,10 @@ var SessionControlKind = Schema_exports.Literals([
28005
28313
  "shell-open",
28006
28314
  "stop",
28007
28315
  "services-stop",
28316
+ "idle-stop",
28008
28317
  "shared-control-on",
28009
- "shared-control-off"
28318
+ "shared-control-off",
28319
+ "discard-unsaved-stop"
28010
28320
  ]);
28011
28321
  var SessionControlEvent = class extends Schema_exports.Class("SessionControlEvent")({
28012
28322
  id: SessionControlEventId,
@@ -28125,7 +28435,8 @@ var SlackSessionState = Schema_exports.Literals([
28125
28435
  "waiting",
28126
28436
  "completed",
28127
28437
  "failed",
28128
- "stopped"
28438
+ "stopped",
28439
+ "idle-stopped"
28129
28440
  ]);
28130
28441
  var SlackPendingFile = Schema_exports.Struct({
28131
28442
  id: Schema_exports.String,
@@ -28385,6 +28696,26 @@ var servicesHoldOf = (session, currentAgent, liveServices) => servicesHoldLine({
28385
28696
  agentOutcome: agentOutcome(currentAgent),
28386
28697
  liveServices
28387
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
+ };
28388
28719
  var normalizeRemoteUrl = (raw) => {
28389
28720
  if (raw === null) return null;
28390
28721
  const trimmed = raw.trim();
@@ -28537,6 +28868,7 @@ export {
28537
28868
  agentIsLive,
28538
28869
  agentOutcome,
28539
28870
  servicesHoldOf,
28871
+ captureLineOf,
28540
28872
  normalizeRemoteUrl,
28541
28873
  matchProjectByCwd,
28542
28874
  cwdFacts,