oysterun 1.5.0-beta.2 → 1.5.0-beta.3

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.
@@ -568,6 +568,11 @@
568
568
  align-content: start;
569
569
  }
570
570
 
571
+ .host-update-handoff.hidden {
572
+ display: grid !important;
573
+ visibility: hidden;
574
+ }
575
+
571
576
  .host-restart-handoff-countdown,
572
577
  .host-update-handoff-countdown {
573
578
  color: var(--accent-strong);
@@ -597,12 +602,40 @@
597
602
  }
598
603
 
599
604
  .host-update-confirmation-actions {
605
+ display: grid;
606
+ min-height: 40px;
607
+ align-items: center;
608
+ }
609
+
610
+ .host-update-confirmation-button-row,
611
+ .host-update-confirmation-progress {
612
+ grid-area: 1 / 1;
600
613
  display: flex;
601
614
  justify-content: flex-end;
615
+ align-items: center;
602
616
  gap: 10px;
617
+ min-width: 0;
618
+ }
619
+
620
+ .host-update-confirmation-button-row {
603
621
  flex-wrap: wrap;
604
622
  }
605
623
 
624
+ .host-update-confirmation-progress {
625
+ min-height: 40px;
626
+ color: var(--ink-soft);
627
+ font-size: 13px;
628
+ line-height: 1.45;
629
+ }
630
+
631
+ .host-update-confirmation-progress:focus {
632
+ outline: none;
633
+ }
634
+
635
+ .host-update-beta-actions {
636
+ grid-template-columns: repeat(2, minmax(0, 1fr));
637
+ }
638
+
606
639
  .browser-notification-card {
607
640
  grid-column: span 2;
608
641
  }
@@ -9042,14 +9075,24 @@
9042
9075
  >
9043
9076
  Checking npm beta tag...
9044
9077
  </div>
9045
- <button
9046
- class="btn-ghost"
9047
- type="button"
9048
- id="host-update-beta-run-btn"
9049
- onClick=${call("runOysterunBetaUpdate")}
9050
- >
9051
- Install Beta & Restart
9052
- </button>
9078
+ <div class="control-cell host-update-beta-actions">
9079
+ <button
9080
+ class="btn-ghost"
9081
+ type="button"
9082
+ id="host-update-beta-check-btn"
9083
+ onClick=${call("checkOysterunBetaUpdate")}
9084
+ >
9085
+ Check Beta
9086
+ </button>
9087
+ <button
9088
+ class="btn-ghost"
9089
+ type="button"
9090
+ id="host-update-beta-run-btn"
9091
+ onClick=${call("runOysterunBetaUpdate")}
9092
+ >
9093
+ Install Beta & Restart
9094
+ </button>
9095
+ </div>
9053
9096
  </div>
9054
9097
  </div>
9055
9098
  <div class="kv-label">Action</div>
@@ -9149,27 +9192,50 @@
9149
9192
  id="host-update-handoff-countdown"
9150
9193
  ></div>
9151
9194
  </div>
9152
- <div class="host-update-confirmation-actions">
9153
- <button
9154
- class="btn-ghost"
9155
- type="button"
9156
- id="host-update-confirm-cancel-btn"
9157
- onClick=${call(
9158
- "cancelOysterunUpdateConfirmation"
9159
- )}
9195
+ <div
9196
+ class="host-update-confirmation-actions"
9197
+ id="host-update-confirmation-actions"
9198
+ >
9199
+ <div
9200
+ class="host-update-confirmation-button-row"
9201
+ id="host-update-confirmation-button-row"
9160
9202
  >
9161
- Cancel
9162
- </button>
9163
- <button
9164
- class="btn-primary"
9165
- type="button"
9166
- id="host-update-confirm-run-btn"
9167
- onClick=${call(
9168
- "confirmOysterunUpdateRestart"
9169
- )}
9203
+ <button
9204
+ class="btn-ghost"
9205
+ type="button"
9206
+ id="host-update-confirm-cancel-btn"
9207
+ onClick=${call(
9208
+ "cancelOysterunUpdateConfirmation"
9209
+ )}
9210
+ >
9211
+ Cancel
9212
+ </button>
9213
+ <button
9214
+ class="btn-primary"
9215
+ type="button"
9216
+ id="host-update-confirm-run-btn"
9217
+ onClick=${call(
9218
+ "confirmOysterunUpdateRestart"
9219
+ )}
9220
+ >
9221
+ Confirm Update & Restart
9222
+ </button>
9223
+ </div>
9224
+ <div
9225
+ class="host-update-confirmation-progress hidden"
9226
+ id="host-update-confirmation-progress"
9227
+ role="status"
9228
+ aria-live="polite"
9229
+ tabindex="-1"
9170
9230
  >
9171
- Confirm Update & Restart
9172
- </button>
9231
+ <span
9232
+ class="host-update-progress-spinner"
9233
+ aria-hidden="true"
9234
+ ></span>
9235
+ <span
9236
+ id="host-update-confirmation-progress-copy"
9237
+ ></span>
9238
+ </div>
9173
9239
  </div>
9174
9240
  </div>
9175
9241
  </div>
@@ -13311,6 +13377,12 @@ Waiting for Claude login output…</pre
13311
13377
  });
13312
13378
  }
13313
13379
 
13380
+ function focusHostUpdateProgressWithoutScroll() {
13381
+ const progress = $("host-update-confirmation-progress");
13382
+ if (!progress || progress.classList.contains("hidden")) return;
13383
+ progress.focus({ preventScroll: true });
13384
+ }
13385
+
13314
13386
  function startHostRestartHandoff(payload, mode) {
13315
13387
  clearHostRestartHandoffTimer();
13316
13388
  const handoff = normalizeHostRestartHandoff(payload, mode);
@@ -13326,6 +13398,9 @@ Waiting for Claude login output…</pre
13326
13398
  betaUpdateStatus: mode === "beta" ? "Restart scheduled." : "",
13327
13399
  };
13328
13400
  renderHostPreferences();
13401
+ if (mode !== "restart") {
13402
+ focusHostUpdateProgressWithoutScroll();
13403
+ }
13329
13404
 
13330
13405
  const tick = () => {
13331
13406
  const active = hostPreferencesState.restartHandoff;
@@ -34955,16 +35030,13 @@ Waiting for Claude login output…</pre
34955
35030
  updateConfirmationVisible ||
34956
35031
  updateRequestPending ||
34957
35032
  updateHandoffActive;
35033
+ const updateConfirmationProgressVisible =
35034
+ updateRequestPending || updateHandoffActive;
34958
35035
  const updateProgressSpinner = $("host-update-progress-spinner");
34959
35036
  if (updateProgressSpinner) {
34960
35037
  updateProgressSpinner.classList.toggle(
34961
35038
  "hidden",
34962
- !(
34963
- hostPreferencesState.updateRunning ||
34964
- updateRequestPending ||
34965
- updateHandoffActive ||
34966
- updateOperationBlocking
34967
- )
35039
+ !(updateOperationBlocking && !updateConfirmationSurfaceVisible)
34968
35040
  );
34969
35041
  }
34970
35042
  const updateCheckButton = $("host-update-check-btn");
@@ -34972,7 +35044,6 @@ Waiting for Claude login output…</pre
34972
35044
  updateCheckButton.disabled =
34973
35045
  disabled ||
34974
35046
  hostPreferencesState.updateChecking ||
34975
- hostPreferencesState.betaUpdateChecking ||
34976
35047
  hostPreferencesState.updateRunning ||
34977
35048
  updateOperationBlocking ||
34978
35049
  updateConfirmationVisible;
@@ -34980,12 +35051,24 @@ Waiting for Claude login output…</pre
34980
35051
  ? "Checking..."
34981
35052
  : "Check for updates";
34982
35053
  }
35054
+ const betaUpdateCheckButton = $("host-update-beta-check-btn");
35055
+ if (betaUpdateCheckButton) {
35056
+ betaUpdateCheckButton.disabled =
35057
+ disabled ||
35058
+ hostPreferencesState.betaUpdateChecking ||
35059
+ hostPreferencesState.updateRunning ||
35060
+ updateOperationBlocking ||
35061
+ updateConfirmationVisible;
35062
+ betaUpdateCheckButton.textContent =
35063
+ hostPreferencesState.betaUpdateChecking
35064
+ ? "Checking..."
35065
+ : "Check Beta";
35066
+ }
34983
35067
  const updateRunButton = $("host-update-run-btn");
34984
35068
  if (updateRunButton) {
34985
35069
  updateRunButton.disabled =
34986
35070
  disabled ||
34987
35071
  hostPreferencesState.updateChecking ||
34988
- hostPreferencesState.betaUpdateChecking ||
34989
35072
  hostPreferencesState.updateRunning ||
34990
35073
  updateOperationBlocking ||
34991
35074
  updateConfirmationVisible ||
@@ -34998,7 +35081,6 @@ Waiting for Claude login output…</pre
34998
35081
  if (betaUpdateRunButton) {
34999
35082
  betaUpdateRunButton.disabled =
35000
35083
  disabled ||
35001
- hostPreferencesState.updateChecking ||
35002
35084
  hostPreferencesState.betaUpdateChecking ||
35003
35085
  hostPreferencesState.updateRunning ||
35004
35086
  updateOperationBlocking ||
@@ -35046,6 +35128,22 @@ Waiting for Claude login output…</pre
35046
35128
  ? `You will be logged out in ${restartHandoff.countdownSeconds} seconds.`
35047
35129
  : ""
35048
35130
  );
35131
+ setVisible(
35132
+ "host-update-confirmation-button-row",
35133
+ updateConfirmationVisible
35134
+ );
35135
+ setVisible(
35136
+ "host-update-confirmation-progress",
35137
+ updateConfirmationProgressVisible
35138
+ );
35139
+ setText(
35140
+ "host-update-confirmation-progress-copy",
35141
+ updateHandoffActive
35142
+ ? "Restart scheduled."
35143
+ : updateRequestPending
35144
+ ? "Preparing update and restart..."
35145
+ : ""
35146
+ );
35049
35147
  const updateConfirmRunButton = $("host-update-confirm-run-btn");
35050
35148
  if (updateConfirmRunButton) {
35051
35149
  updateConfirmRunButton.disabled =
@@ -35296,7 +35394,6 @@ Waiting for Claude login output…</pre
35296
35394
  async function checkOysterunUpdate() {
35297
35395
  if (
35298
35396
  hostPreferencesState.updateChecking ||
35299
- hostPreferencesState.betaUpdateChecking ||
35300
35397
  hostPreferencesState.updateRunning ||
35301
35398
  isOysterunUpdateOperationBlocking(hostPreferencesState.update)
35302
35399
  ) {
@@ -35539,6 +35636,7 @@ Waiting for Claude login output…</pre
35539
35636
  betaUpdateError: "",
35540
35637
  };
35541
35638
  renderHostPreferences();
35639
+ focusHostUpdateProgressWithoutScroll();
35542
35640
  try {
35543
35641
  const data = await apiWithAuthRetry(
35544
35642
  "POST",
@@ -123,9 +123,10 @@ Host Preferences edits Host config and Host-level Session Setup defaults.
123
123
  | Update | Current Version / `host-update-current` | no | installed npm package metadata | none | Diagnostic display of the currently installed Oysterun Host package version. |
124
124
  | Update | Newest Version / `host-update-newest` | no | Host `/admin/update-status` and `/admin/update-check` `newest_version` | none | Displays the newest eligible production npm version after automatic or manual check. The legacy hidden `host-update-latest` alias may mirror this value for compatibility, but normal UI copy uses newest version. No beta/dev/source channel selector or arbitrary exact-version install field is exposed. |
125
125
  | Update | Latest Beta / `host-update-beta-version` | no | npm `dist-tags.beta` through Host `/admin/update-beta-check` | none | Hidden unless `debug_host_preferences_beta_update_enabled` is true in `<host_config_dir>/config.debug.json`. The beta check is isolated from production `latest` reminder state, noticed-version state, and automatic-check cooldown. The fixed beta action never accepts a frontend-provided version, channel, package spec, or registry. |
126
+ | Update | Check Beta / `host-update-beta-check-btn` | action | installed package metadata + fixed npm `dist-tags.beta` through Host `/admin/update-beta-check` | none | Debug-gated P021 refresh action. It updates only the isolated Beta row, so a beta published after Host Preferences opened can be discovered without reloading the page. It does not call the production check, mutate production newest/reminder state, or accept a client-provided channel/version/registry. |
126
127
  | Update | Status / `host-update-status` | no | Host-owned update check / update operation state | none | Shows concise check status, update availability, unsupported stack state, failure, or final reconciliation status. Automatic check failures stay quiet and do not overwrite visible manual/success status. Normal UI does not display operation log paths. |
127
128
  | Update | Last checked / `host-update-last-checked` | no | Host `checked_at` + `source` | none | Compact footnote-style text beside `Update & Restart`, including automatic/manual source and timestamp. |
128
- | Update | Progress / `host-update-progress-spinner` + `host-update-phase` | no | Host update operation state | none | Reserves stable layout space and becomes visible while an update request, handoff, install, restart, or post-restart verification is active. The accepted handoff uses the server-owned `execute_not_before` deadline and shows the 30-second estimate plus a visible 10-to-0 logout countdown without redirecting or moving the viewport. `Check for updates` and both update actions are disabled while an operation is running or persisted operation state is unknown/nonterminal. |
129
+ | Update | Progress / `host-update-progress-spinner` + `host-update-confirmation-progress` + `host-update-phase` | no | Host update operation state | none | Reserves stable layout space and becomes visible while an update request, handoff, install, restart, or post-restart verification is active. After confirmation, the action-region spinner replaces the clicked confirmation action at the same visual position; focus moves to that status with `preventScroll` and the confirmation surface does not collapse. The accepted handoff uses the server-owned `execute_not_before` deadline and shows the 30-second estimate plus a visible 10-to-0 logout countdown without redirecting or moving the viewport. `Check for updates` and both update actions are disabled while an operation is running or persisted operation state is unknown/nonterminal. |
129
130
  | Update | Check for updates / `host-update-check-btn` | action | installed package metadata + effective npm registry | `<host_config_dir>/update-noticed-version.json` when a new production update is found | Manual check bypasses automatic cooldown, writes a redacted operation log, records `noticed_version` when an update is available, and never installs or restarts by itself. Verification stacks may set `OYSTERUN_UPDATE_REGISTRY_URL`; the registry URL is not a normal Host Preferences control. |
130
131
  | Update | Update & Restart / `host-update-run-btn` + `host-update-confirmation` | action | newest production version resolved to exact npm version + Host-local restart restore transaction | npm global package + `<host_config_dir>/restart-restore-state.json` + service restart + redacted operation log + update operation state | Explicit owner action. The button opens a visible in-app confirmation surface with current version, target version, P76 restore-aware restart copy, interruption/no-replay copy, visible Cancel, and visible Confirm Update & Restart. `/admin/update-run` fires only after the visible confirm action. After acceptance, the same stable confirmation region shows the server-owned 10-second handoff and logs the dashboard out at its deadline; the detached install remains scheduled if the page closes. Production npm Host stack by default; Route C verification stacks may exercise the same production/latest path only when a valid `OYSTERUN_UPDATE_REGISTRY_URL` override is active. Installs `oysterun@<exact-version>` with `--prefer-online`, passes the same `--registry` override used by update-check when `OYSTERUN_UPDATE_REGISTRY_URL` is set, prepares P76 restore state before restart through the shared restore prepare helper, schedules restart through a one-shot non-keepalive runner with an operation-state claim guard, reconciles Host return through persisted operation state, verifies the observed package version, and keeps dev/test/source stacks without a verification registry override from mutating the global npm installation. Active work is marked interrupted and is not replayed. |
131
132
  | Update | Install Beta & Restart / `host-update-beta-run-btn` + `host-update-confirmation` | action | exact npm `dist-tags.beta` version + Host-local restart restore transaction | npm global package + `<host_config_dir>/restart-restore-state.json` + service restart + the shared redacted operation log and operation state | Debug-gated P021 action. It is enabled only when the fixed beta tag resolves to a valid prerelease strictly newer than the installed version; equal or older beta versions never downgrade the Host. It reuses the P77/P018 exact-version installer, P76 restore preparation, server-owned 10-second handoff, one-shot restart runner, persisted operation lock, and post-restart version verification. Production and beta actions cannot run concurrently. The confirmation surface explicitly identifies the beta target and remains in place for the countdown. |
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oysterun-host-service",
3
- "version": "1.5.0-beta.2",
3
+ "version": "1.5.0-beta.3",
4
4
  "type": "module",
5
5
  "description": "Oysterun host service — runs on Mac mini, manages Claude Code sessions",
6
6
  "scripts": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oysterun",
3
- "version": "1.5.0-beta.2",
3
+ "version": "1.5.0-beta.3",
4
4
  "type": "module",
5
5
  "description": "Oysterun Host installer and local service",
6
6
  "bin": {