oysterun 1.6.0-beta.4 → 1.6.0-beta.5

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.
@@ -108,7 +108,7 @@ export function buildHostLifecycleRecoveryPlan({
108
108
  confirmation: "Finish this committed operation's cleanup. No additional restart is required.",
109
109
  } : restartOnly ? action("restart_only", "Recover restart", "Restart recovery required",
110
110
  "Retry the existing package with the retained fresh Session restore receipt.",
111
- "Restart this Host and verify the original Session roster and history. Active work will not replay.")
111
+ "Restart this Host and verify the original live Sessions and history. Active work will not replay.")
112
112
  : recovery ? { ...ACTIONS.restore_and_restart,
113
113
  title: "Update qualification did not finish",
114
114
  description: `Restore Oysterun ${r.source.version} using the retained package, definition and fresh Session snapshot.`,
@@ -72,7 +72,7 @@ export async function qualifyLifecycleContinuity({
72
72
  result.tunnel = await waitFor("TUNNEL_QUALIFIED", async () => {
73
73
  const observation = await observe({ configDir, operationId, origin: expectedOrigin });
74
74
  // A provider can exit while the user signs back in. Commit only a fresh
75
- // observation that still proves the same Host and complete Session roster.
75
+ // observation that still proves the same Host and complete live Sessions.
76
76
  const freshHost = checkHost(observation);
77
77
  const freshSessions = checkSessions(observation);
78
78
  // The scoped route probe proves transport and Host identity; a real
@@ -96,11 +96,11 @@ export function readContinuity(path, operationId) {
96
96
  return receipt;
97
97
  }
98
98
 
99
- // The final roster is captured by the running coordinator immediately before
100
- // its handoff gate closes. Installation may take minutes; the initial roster
99
+ // The final live Sessions are captured by the running coordinator immediately before
100
+ // its handoff gate closes. Installation may take minutes; the initial live Sessions
101
101
  // must never silently stand in for this fresh capture.
102
102
  export function assertFreshContinuitySnapshot(baseline, restartId, restartState) {
103
- requireValue(restartId && Array.isArray(baseline?.sessions), "preparation", "fresh_roster_identity", "Fresh roster identity is missing.");
103
+ requireValue(restartId && Array.isArray(baseline?.sessions), "preparation", "fresh_roster_identity", "Fresh live Session identity is missing.");
104
104
  const ids = baseline.sessions.map((row) => row.session_id);
105
105
  requireValue(new Set(ids).size === ids.length && baseline.sessions.every((row) => row.session_id &&
106
106
  row.provider_resume_id && !row.observation_error && Array.isArray(row.history_anchors)),
@@ -111,16 +111,16 @@ export function assertFreshContinuitySnapshot(baseline, restartId, restartState)
111
111
  const observed = baseline.sessions.find((item) => item.session_id === row.session_id);
112
112
  return observed && ["provider", "provider_resume_id", "agent_id", "agent_folder"].every((key) => row[key] === observed[key]) &&
113
113
  (row.provider_thread_id || row.provider_resume_id) === observed.provider_thread_id;
114
- }), "preparation", "fresh_snapshot_roster", "Fresh live roster differs from the exact prepared Session snapshot; stop before handoff.");
114
+ }), "preparation", "fresh_snapshot_roster", "Fresh live Sessions differ from the exact prepared Session snapshot; stop before handoff.");
115
115
  }
116
116
 
117
117
  export function bindFreshContinuityBaseline(path, operationId, baseline, restartId, restartState) {
118
118
  const receipt = readContinuity(path, operationId);
119
119
  requireValue((["PREPARED", "PACKAGE_SWITCHED"].includes(receipt.state) ||
120
120
  (receipt.state === "RECOVERY_REQUIRED" && !receipt.restart_id)) && !receipt.restart_attempted,
121
- "preparation", "fresh_roster_boundary", "The fresh roster cannot change after restart begins.");
121
+ "preparation", "fresh_roster_boundary", "The fresh live Sessions cannot change after restart begins.");
122
122
  requireValue(baseline?.host?.pid === receipt.baseline.host.pid,
123
- "preparation", "fresh_roster_identity", "Fresh roster must come from the retained running Host.");
123
+ "preparation", "fresh_roster_identity", "Fresh live Sessions must come from the retained running Host.");
124
124
  assertFreshContinuitySnapshot(baseline, restartId, restartState);
125
125
  receipt.initial_baseline_digest ||= receipt.baseline_digest;
126
126
  receipt.baseline = baseline;
@@ -135,10 +135,10 @@ export function prepareContinuity({ path, operationId, source, target, baseline,
135
135
  source.runtime_identity_digest === target.runtime_identity_digest,
136
136
  "preparation", "source_target_identity", "Source and target runtime identities must be complete and equal.");
137
137
  requireValue(baseline?.host && Array.isArray(baseline.sessions) && baseline.captured_at,
138
- "preparation", "fresh_roster", "A fresh Host and dynamic Session baseline is required.");
138
+ "preparation", "fresh_live_sessions", "A fresh Host and dynamic Session baseline is required.");
139
139
  const ids = baseline.sessions.map((row) => row.session_id);
140
140
  requireValue(ids.every(Boolean) && new Set(ids).size === ids.length,
141
- "preparation", "unique_roster", "The fresh Session roster has missing or duplicate identities.");
141
+ "preparation", "unique_roster", "The fresh live Sessions have missing or duplicate identities.");
142
142
  return publishDurableBoundary(path, writeContinuityAtomic(path, {
143
143
  ...authority, schema: CONTINUITY_SCHEMA, operation_id: operationId, transaction_kind: transactionKind,
144
144
  source, target, baseline, baseline_digest: continuityDigest(baseline), operation_root: operationRoot,
@@ -234,7 +234,7 @@ export function qualifyContinuityHost(baseline, observed, { version, runtimeIden
234
234
  }
235
235
 
236
236
  export function qualifyContinuitySessions(expected, observed, restoreResult, { requireRestore = true } = {}) {
237
- requireValue(Array.isArray(expected) && Array.isArray(observed), "session_qualification", "roster_missing", "Session qualification requires both exact rosters.");
237
+ requireValue(Array.isArray(expected) && Array.isArray(observed), "session_qualification", "roster_missing", "Session qualification requires both exact live Sessions.");
238
238
  if (requireRestore) {
239
239
  requireValue(restoreResult && Array.isArray(restoreResult.restored) && Array.isArray(restoreResult.failed) && Array.isArray(restoreResult.skipped),
240
240
  "session_qualification", "restore_result_missing", "Consumed state has no complete Session restore result.");
@@ -246,7 +246,7 @@ export function qualifyContinuitySessions(expected, observed, restoreResult, { r
246
246
  }
247
247
  const observedIds = observed.map((row) => row.session_id);
248
248
  requireValue(new Set(observedIds).size === observedIds.length, "session_qualification", "duplicate_runtime", "Duplicate live Session identity.");
249
- requireValue(observed.length === expected.length, "session_qualification", "roster_changed", "Live Session roster differs from the fresh retained roster.");
249
+ requireValue(observed.length === expected.length, "session_qualification", "roster_changed", "Current live Sessions differ from the freshly retained live Sessions.");
250
250
  for (const before of expected) {
251
251
  const after = observed.find((row) => row.session_id === before.session_id);
252
252
  requireValue(after, "session_qualification", "session_missing", `Session ${before.session_id} is missing.`);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oysterun-host-service",
3
- "version": "1.6.0-beta.4",
3
+ "version": "1.6.0-beta.5",
4
4
  "type": "module",
5
5
  "description": "Oysterun host service — runs on Mac mini, manages Claude Code sessions",
6
6
  "scripts": {
@@ -8359,7 +8359,7 @@ function assertSessionRosterMutationAvailable() {
8359
8359
  if (!operation.continuity_path || !isUpdateOperationBlocking(operation)) return;
8360
8360
  const receipt = readContinuity(operation.continuity_path, operation.operation_id);
8361
8361
  if (!receipt.restart_id || ["CLEANED", "ROLLED_BACK_HEALTHY"].includes(receipt.state)) return;
8362
- const error = new Error("Host lifecycle recovery is preserving the fresh Session roster. Finish that operation before changing Sessions.");
8362
+ const error = new Error("Host lifecycle recovery is preserving the fresh live Sessions. Finish that operation before changing Sessions.");
8363
8363
  error.code = "oysterun_session_roster_reserved";
8364
8364
  throw error;
8365
8365
  }
@@ -10548,7 +10548,7 @@ function scheduleContinuityRecovery({ kind, source }) {
10548
10548
  process.pid === receipt.baseline.host.pid && receipt.operation_root) {
10549
10549
  // Installation can finish while a newly created provider is still booting.
10550
10550
  // If no handoff snapshot was ever bound, recover from a fresh complete
10551
- // roster of the original running coordinator. Never replace a bound one.
10551
+ // live Sessions of the original running coordinator. Never replace a bound one.
10552
10552
  const fresh = buildHostContinuityObservation().baseline;
10553
10553
  if (fresh.sessions.some((row) => row.observation_error || !row.provider_resume_id)) throw continuityFailure("recovery", "fresh_roster_not_ready", "Wait for every current Session provider to be ready before recovering this unprepared handoff.");
10554
10554
  const prepared = prepareHostRestartRestore({ trigger: "p233_recovery_before_first_handoff_snapshot" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oysterun",
3
- "version": "1.6.0-beta.4",
3
+ "version": "1.6.0-beta.5",
4
4
  "type": "module",
5
5
  "description": "Oysterun Host installer and local service",
6
6
  "bin": {
@@ -1815,7 +1815,6 @@ wait_for_http() {
1815
1815
  local pid="$3"
1816
1816
  local log_file="$4"
1817
1817
  local launch_label="${5:-}"
1818
- local attempts=0
1819
1818
 
1820
1819
  until curl -fsS "${url}" >/dev/null 2>&1; do
1821
1820
  local current_pid="${pid}"
@@ -1825,15 +1824,6 @@ wait_for_http() {
1825
1824
 
1826
1825
  if [[ -n "${current_pid}" ]] && ! pid_is_running "${current_pid}" 2>/dev/null; then
1827
1826
  if [[ -n "${launch_label}" ]] && launchctl_label_exists "${launch_label}"; then
1828
- attempts=$((attempts + 1))
1829
- if [[ "${attempts}" -ge 60 ]]; then
1830
- echo "[oysterun-service] error: timed out waiting for ${label} at ${url}" >&2
1831
- if [[ -f "${log_file}" ]]; then
1832
- echo "[oysterun-service] Last ${label} log lines:" >&2
1833
- tail -n 40 "${log_file}" >&2 || true
1834
- fi
1835
- exit 1
1836
- fi
1837
1827
  sleep 1
1838
1828
  continue
1839
1829
  fi
@@ -1845,16 +1835,6 @@ wait_for_http() {
1845
1835
  exit 1
1846
1836
  fi
1847
1837
 
1848
- attempts=$((attempts + 1))
1849
- if [[ "${attempts}" -ge 60 ]]; then
1850
- echo "[oysterun-service] error: timed out waiting for ${label} at ${url}" >&2
1851
- if [[ -f "${log_file}" ]]; then
1852
- echo "[oysterun-service] Last ${label} log lines:" >&2
1853
- tail -n 40 "${log_file}" >&2 || true
1854
- fi
1855
- exit 1
1856
- fi
1857
-
1858
1838
  sleep 1
1859
1839
  done
1860
1840
  }
@@ -239,7 +239,7 @@ export async function executeP233Bootstrap(action, reviewed) {
239
239
  beforeForwardRestart: async (receipt) => {
240
240
  // 1.5.7 has no Session admission reservation. The one-time released
241
241
  // maintenance window is mandatory; this final read also rejects any
242
- // observed roster change after the pre-activation snapshot.
242
+ // observed live Sessions change after the pre-activation snapshot.
243
243
  const live = await legacyObserve({ origin: new URL(healthUrl).origin, retained: receipt.baseline });
244
244
  qualifyContinuitySessions(receipt.baseline.sessions, live.sessions, null, { requireRestore: false });
245
245
  },