@githolon/runtime 0.113.2 → 0.113.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.
@@ -9,7 +9,6 @@
9
9
  062ccf10c0501529b87e93598d27769304e2077de7cc9cc7c7b93efdabab9762 peer-office/src/runtime/read_authentication.ts
10
10
  063a8e43056578ecec6ba95eb1a9f28d8b704daea2260ef2943840def1cf9526 node_modules/@bufbuild/protobuf/dist/esm/wkt/gen/google/protobuf/source_context_pb.js
11
11
  06525d62b18918913a7fe7981204fba9e1f70369cc2aa785851caae39f546de3 node_modules/@bufbuild/protobuf/dist/esm/wire/base64-encoding.js
12
- 073fdbe5a86f289aa546aaa7e4b3658d8aa69f74baba8780a8af69e3a7c69750 peer-office/src/peer_office.ts
13
12
  082f4f24399a3f7dc46465903f825c0287a81f4cf8a17ccd96c4bf556ad3d7cb platform-shells/browser/runtime_fetch.ts
14
13
  09a24ed660112991f8105d8c0c2c250617b6ad99f6a12afe2d39b8a9305289ec peer-office/src/runtime/session_directory.ts
15
14
  0a687d73d1754114045dd64ab0125af437945ed11b1302753b1c3c46793a014b peer-office/src/runtime/replica_follow_lane.ts
@@ -35,7 +34,6 @@
35
34
  16d6522ee4ecf4a91c4d29357ebc874844c266f2ae89ef2a92ec2d391f3762e9 node_modules/is-unsafe/src/contexts/sql-strict.js
36
35
  17b0d228dd20748bd5fa03164478198c813214e4fa5d8f1650705128a954f0bd adapter/wasi_custody_filesystem.ts
37
36
  1963a804a9cfe7d44a76b2c476817639b939d7e93828da865cab40fe9ba536fa adapter/custody-transport.ts
38
- 198d9850ef7cf6f9d54cbec0ad6c168e6cc29a5a5f19a6366bfc537c0b021edc peer-office/src/runtime/read_maintenance_desk.ts
39
37
  19a320ee1d4c811af432f1b9d511d5cd840c0fc8bbca74a455a81836fe6c4d1f peer-office/src/runtime/workspace_sync_dependencies.ts
40
38
  1a5d9fd32360e2cec4adbee9e56221fb26def66bb9d122e0b5745cebc963d92e node_modules/xml-naming/src/index.js
41
39
  1a873dadab0fdef771d16b70d3ad318018dbf5c185337519f230064da4e7ea8a adapter/proto/nomos/kernel/v1/kernel_pb.js
@@ -54,7 +52,6 @@
54
52
  208a47278c60cd0f3470c58e981fdd2995d7ce1024cef9caebe208f6a9b291ae adapter/proto/nomos/runtime/v2/law_desk_pb.js
55
53
  20d82153da53012f461d67c21673fdf84dc2d9c62cb7339f95288d375e4ba23b peer-office/src/runtime/background_paper_slots.ts
56
54
  22a2b398e7c3fcbfc171080a6288c710522bf1baf5f56e63f5bdcfbaaf7757b7 node_modules/@bufbuild/protobuf/dist/esm/wkt/wrappers.js
57
- 24bc816455f9aef9c1d3d91724a59936014dabb732083d7833c197f8371251f2 peer-office/src/runtime/subscription_manager.ts
58
55
  24f5eb575e633b68771328cc12fa6fde751ecc5f2700a6f52ea325938dc94342 node_modules/is-unsafe/src/index.js
59
56
  25c033d29ed62a510d8c43054ec238776bcba0949808cb6054df5cbea951ddf7 adapter/proto/nomos/runtime/v2/interaction_desk_pb.js
60
57
  25d57b7e880708c04738087de674a8c98092e5bfd39d5193cdb63a2f1e33871e node_modules/@bufbuild/protobuf/dist/esm/wkt/gen/google/protobuf/compiler/plugin_pb.js
@@ -81,7 +78,6 @@
81
78
  3c092b8d4185badd23ecf4552434d05aa541b0cd0d534781d687db55260d5da8 adapter/proto/nomos/runtime/v2/sealing_desk_pb.js
82
79
  3c98fa838c05abcfd8dfda1128f2d1fca9b196a371fe9751abbd8f4c3b9d04ec node_modules/@bufbuild/protobuf/dist/esm/wkt/timestamp.js
83
80
  3d05089a8c1008f20e06da9907eec7f8824f871edfc95e907c15dc8e2bdf43e7 node_modules/@bufbuild/protobuf/dist/esm/extensions.js
84
- 3e5e0540872bcfb39a59047a1b1d1f5942e9de12f0a834e81912c6670a8e1269 platform-shells/browser/worker_page_entry.ts
85
81
  3eef60b7d08402d6a0b9427fde0308878929398918f09747833fd9a06ea3fa7d workspace-discovery/src/http.ts
86
82
  3fa38ca64538032d871cd44da41bf6a6ad2eb133b6b8ebc2d8b4d33615b00dcf peer-office/src/reception/application_session_pipe.ts
87
83
  3fade4f9262d10e39f346b57a7f08d03641e0ebd75556d087f6319f6c6003a24 peer-office/src/runtime/sha256.ts
@@ -130,6 +126,7 @@
130
126
  63a928e5632cca54994a7fdde23c44db762fdc3df6afba4677fe4fdc3101b98f adapter/proto/nomos/runtime/v2/observability_desk_pb.js
131
127
  64256c9570f2d73851f8b7e1a47ccee787120ca13b862b317d46c1bdb128f06c adapter/custody_paths.ts
132
128
  666242642051bff6e5bff6d2697b774fe518b78461bde4e0bdb497592cd56d95 peer-office/package/src/nominal_value.ts
129
+ 68fbb966cea063ed495d2b11117742a6829f4328ebd20fda06cb0a10358ad38c peer-office/src/runtime/subscription_manager.ts
133
130
  692c6542af574ad4ec2882ae9591db3be7635e7721b43af13158a5397f537ebb adapter/git_placement_custody.ts
134
131
  6b3d69203397fa63fa4d5d38a216de18193e128ee4843630531ef1e6232b3448 adapter/memory_custody_filesystem.ts
135
132
  6cfa5fe6f17219f03e2650dec635934cff6601dbee72f188bbd2874a9d1d4523 platform-shells/shared/credential_effects.ts
@@ -155,6 +152,7 @@
155
152
  7ec79572a67e1764cd0e93fe2c49d696cd179836293f62e5f50c54e01d6af242 peer-office/src/runtime/provider_origins.ts
156
153
  812a2077e073564d6470b8fda8ac0d20ecaaf75ddb1594d55d28acc2da8a1a71 node_modules/@nodable/entities/src/EntityEncoder.js
157
154
  81539d21eb82b21f6bab3b84d0b7296cb240532e0314c303d06799a1f5fe4e81 adapter/proto/nomos/runtime/v2/residency_desk_pb.js
155
+ 815a6dca44ffad90e4394a2e745c65a86e2abace4ac51aece9c8bf29144bc383 peer-office/src/runtime/placement_desk.ts
158
156
  8265b7063f35842f61f48c693eb9c740f07949284fb589380b6795dd88dd5ff1 peer-office/src/runtime/replica_follow_controller.ts
159
157
  829eadd8a1a441d25be0cb93b00e16a0d0c20fd294db95d8f2ed87e6954b7182 node_modules/base64-js/index.js
160
158
  836d6535b507906f82129a7cae5b1cbd42efaef969f18b13675b39ba7cb5ebcb peer-office/src/runtime/birth_custody_desk.ts
@@ -182,7 +180,6 @@
182
180
  94a3cef0f355a9a177661748d24faae32206a5cc382c8601a34dcf005340107b node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js
183
181
  95ad7c933403a0c8f7fd3e2df6c4df3008c29911d3d5db063a90460a14144da2 peer-office/src/runtime/records_desk.ts
184
182
  95dbcb2580ed30cb11222c773163c6a906a7e363c5ec4263bd39c1f3a7a16cc2 node_modules/@bufbuild/protobuf/dist/esm/from-json.js
185
- 9634891339d48126199a20c3ee535eb20b0635b862f632725fdc6d645542eff2 peer-office/package/package.json
186
183
  96cb2eb563ccb18dc23fd9f8fb0f65193a1b90f39758a561eed747368ead00b3 node_modules/@bufbuild/protobuf/dist/esm/wkt/index.js
187
184
  96ec5d127a4e8cd77bdc678422f0d57c8ff9e37bcec999983da71a7b72ce9a0e node_modules/@nodable/entities/src/entities.js
188
185
  98f5abf9a7fb522aab513ef3831dd9c5837cebcb38a960cb546ffd084926d746 node_modules/@bufbuild/protobuf/dist/esm/wkt/gen/google/protobuf/empty_pb.js
@@ -210,6 +207,7 @@ a91848ee180529e2a60c05dfb9584cad19cd4e1c6f391fdb76a938bcae4c0328 node_modules/@
210
207
  a9a2aefe743f0243ae1adb3acdd3db6cdb671b744b5f83235cc4e0be905f1a5b peer-office/package/src/typescript_application_desk.public.d.ts
211
208
  aa39c85046ef2b8cd9f7d825eefb502e382e9107b39c9110297f8b84f63f6011 peer-office/src/runtime/replica_inventory_desk.ts
212
209
  aa6349944f16d71986273ecfc8e552bfece3d61d5641e526c0ceabf3f154fdaf peer-office/src/runtime/application_desk.ts
210
+ aabbcb3d691d6ea517811feae5049f094a3a8ffeb14d8332137c8d7a033093e1 peer-office/package/runner/build.ts
213
211
  ab43714f566a6ccd988cc3a30810d857552dbd14d0f060934907fb4bba1000f0 peer-office/package/src/admission_decision.ts
214
212
  ab80eeeafd4d89a5daaf5d2e00fb471cc6b53fa90776750ca3ad82df482d7c3f peer-office/src/runtime/peer_lifecycle.ts
215
213
  ad3de46df125304b2a61c2fa5537b0e519635997d99686a76119b38cf260963f adapter/proto/nomos/runtime/v2/identity_desk_pb.js
@@ -219,13 +217,13 @@ b09ee99807e1edeb746b4a4a1e41519edaff1fed9f71a170bc15e8835af93e25 node_modules/@
219
217
  b1db7ea18d82851f6f19f0ce9c1e718bf64556425e7723cca5ba213b8558ac2d peer-office/src/runtime/peer_maintenance_scheduler.ts
220
218
  b2510e5dcadaccb131d63fd3900ab17f85f54c9c6e2178400ceb1eace6ca552a peer-office/src/runtime/kernel_port.ts
221
219
  b29d03c7242a44fa4e6b8ee5c8e9279965c328baf5f97b314272c5fefad855b2 platform-shells/browser/worker_entry.ts
220
+ b446886ee89ebda45bef4f4335cfb709af699efb21ecbec4ce90571197e9badb peer-office/package/package.json
222
221
  b4932f38ab2f4b89fbdd4458944591cbea052ef40180a2b64475ee44891e62e1 platform-shells/shared/with_workspace_discovery.ts
223
222
  b4c474e617f91b74f99322f19561ad699933becf7efe73f0582da94db1bec465 node_modules/@bufbuild/protobuf/dist/esm/codegenv2/boot.js
224
223
  b68312b9501ba96f45496f3f30db62c158a127bbb00d7e8ff081b2d741218497 adapter/git_custody_desk.ts
225
224
  b683cb36f7b9eacef4270428f7875d3211d84dd851eb226f6a3030a166ca9fa9 peer-office/src/reception/tally_read.ts
226
225
  b6d7539356e92bfa257edd790e8d5d697167205b7154106e8758455cc3483e82 runtime/osgi_repository.ts
227
226
  b82bb05bb957bb59990dda51bb60ed8b9f656cc090312295ea0958e4cd52bdb7 peer-office/src/runtime/device_recovery_journal.ts
228
- b95daa723d0b62946657a5dbaef9a2b14150a1cbd504102b95650b53cbf48c36 peer-office/package/runner/build.ts
229
227
  ba7223ebf0eea2f078ba83f0128830f7cd07224c57d7e61251541c1c17e83009 peer-office/src/runtime/workspace_effect_delivery.ts
230
228
  bb8e81020a9cbf3f8562c196fa5609ef5dec911e0981920c7d05de67769c79d4 peer-office/src/runtime/credential_failure.ts
231
229
  bcc5325758b3b940384c7bf2a7132874421989c2561a59dc49c4ef0b88c352dc node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js
@@ -256,6 +254,7 @@ cd5ced000d1c143e7718a1b9e741533c63f3fd9d4acd85119d521a7064569409 peer-office/sr
256
254
  cdb1f7869edc7171b689fd532fcaa4fa039680e1af44b32cce227cf61ca3fe05 node_modules/@bufbuild/protobuf/dist/esm/proto-int64.js
257
255
  ce9ba4862b010b1d01f2ea9846ac397188526c750e7bb9d437b9ee9dd563b37d peer-office/src/runtime/custodian_placement.ts
258
256
  cfc517180b5ade4339146bacf2ccd624770e071e00b601bd193422c2edbcabe6 node_modules/@bufbuild/protobuf/dist/esm/registry.js
257
+ d0031765c524858226a10c73c4b8f63264165680d2a5c66b6e4191410eb8957c peer-office/src/peer_office.ts
259
258
  d13d77a3ef4461782e678f9c4f9227be039f00233de69b1742e1922a84becadc peer-office/src/reception/typescript_application_desk.ts
260
259
  d1f73b0742c76b91aef4e20312062c2367a816de294d60f821bef2de58599413 peer-office/src/runtime/workspace_address.ts
261
260
  d2750ac2748256be73650606472cbbab097951f100c1dff684cf46e92415908e node_modules/@bufbuild/protobuf/dist/esm/clone.js
@@ -267,6 +266,7 @@ d4b90e97ac754d086a6ec26756bb2d5cff563396434f16aee3ae34d913d756b9 node_modules/@
267
266
  d4ecef7a571afb93de1f62b0e6877237febace34d5487687a8b7c92bc3234a19 peer-office/src/runtime/identity_recovery_desk.ts
268
267
  d730efb4ee5b52c492c1d04859568461a4efbfa7474048afa5f8f776a3b6d55b node_modules/@bufbuild/protobuf/dist/esm/wkt/duration.js
269
268
  d851f0d85aa051c8f7880855f4af21b56507afdaebfc99623693eda933df7726 peer-office/src/runtime/residency_pins.ts
269
+ d8f3407bb4a3d5ecd382eea801bab684c8b9345a2aa6e41f9033fad11c4a1750 peer-office/src/runtime/shell_contract.ts
270
270
  da6362509cb895cc68dc6c050f3a59ed47d2ee009108e2093e2905e0171efe9c peer-office/src/runtime/custody_retention_plan.ts
271
271
  db05a3f19bc575c1ed771fc6882af337a49cde7bd469181f3acc772d1a76df3e node_modules/@bufbuild/protobuf/dist/esm/to-json.js
272
272
  db61a17ab4dbb3514b676cd93cc702fe62a6582d5ec292725f1ada20dfbc1f72 peer-office/src/runtime/custody_replacement.ts
@@ -275,17 +275,19 @@ deaa25227d669aa3fbe99174275588dcc175de648ae6623fddf11d6ae69d7f67 platform-shell
275
275
  dff6af323ca5f9c73dd06120879fcd5f561d22a8a7fd36d3317e564ae4e10e3b platform-shells/shared/kernel_work_accounting.ts
276
276
  e20a132033f105a29db1cfdb3d85bbadbb7206b9a7e3336bcb030a63d66b4ab2 node_modules/is-unsafe/src/contexts/nosql.js
277
277
  e2133d7e0f0ce5491a3e9bd560e9e47db2243a6a9f762be89c82e027d99d278e peer-office/src/runtime/credential_sessions.ts
278
+ e2f82db2565bd1e8766c9220c7cde9cdb39023a861f6a8f24e14a6a0fb0bd62d peer-office/src/runtime/read_maintenance_desk.ts
278
279
  e394b7a580a2853949ec937d742b54fd8169029a5d10a3e4e521b984c60adb6d peer-office/src/runtime/identity_desk.ts
279
280
  e411cf95c1c0c7063b863a08ad568d61044069f9338028eace56e362029ad3a7 peer-office/src/runtime/residency_desk.ts
280
281
  e45a879696cd2e7b692aa282677abf216297c1d129135e914b8a76fd0cbe15bd peer-office/src/reception/generated_offer_counter.ts
282
+ e4a9e97abd58f2989428d7ed6fd771315a72c696ce0b65bdc938e477772f1edd peer-office/src/runtime/http_origin.ts
281
283
  eb9e106e81226ab9547882079e7fd6a9d885d2c71ba78784f7edaa7db61bb941 node_modules/is-unsafe/src/contexts/svg.js
282
284
  ebbf22c6979f6b2b05c580922e7dd197f4f4a246d504d4c0cc8e64778f12d4ed node_modules/path-expression-matcher/src/index.js
285
+ ecda8f47f925632826cbf8ac1a2c6b3ba6843d2ecf455ef84eb01d79d76983ad platform-shells/browser/worker_page_entry.ts
283
286
  ece435d3784d928d02bff4d015b7cb686f8c06de8536ff9f8ebc38a8f403a3be node_modules/@bjorn3/browser_wasi_shim/dist/strace.js
284
287
  eda289d9ef0e979fe77a578ffbbf8012cadcfec4629b66cd98c27d6229a9f020 node_modules/@bufbuild/protobuf/dist/esm/is-message.js
285
288
  efce20f9f127263ca66d855115e01b37af0afb8b8baafeba7dcc2e0834e99e4f node_modules/@bufbuild/protobuf/dist/esm/wkt/gen/google/protobuf/struct_pb.js
286
289
  f23513db2fea432df6121956d9bab4761dabf8034b6eba8988452104dba1783e adapter/proto/nomos/runtime/v2/records_desk_pb.js
287
290
  f3b9324922e08cffcc4c7ae3c6e08454f62e187a37404df31a00160cddf34d77 node_modules/@bufbuild/protobuf/dist/esm/reflect/guard.js
288
- f4eb625c1c0ebee8e5863b6958706af4635ca58d1d2544ae2b465e75060ba12c peer-office/src/runtime/placement_desk.ts
289
291
  f50218256bfd061c59b454fbaf8ca304f1799b1d0d09b0f7851ba2420e1129ca adapter/kernel_failure.ts
290
292
  f585f26c6fa18af890c32d00fbb00fbfd05b9c7217419b6fe8675bdcee264140 node_modules/fast-xml-builder/src/util.js
291
293
  f5f56922916f3b22e72a37521c5ca915506b8b205fe28e89a1986dbce15d4b47 node_modules/@bufbuild/protobuf/dist/esm/wkt/gen/google/protobuf/wrappers_pb.js
@@ -1051,6 +1051,7 @@ var NomosRuntimeComponent = (() => {
1051
1051
  // ../src/peer_office.ts
1052
1052
  var peer_office_exports = {};
1053
1053
  __export(peer_office_exports, {
1054
+ driveOfficeTurn: () => driveOfficeTurn,
1054
1055
  peerOffice: () => peerOffice
1055
1056
  });
1056
1057
 
@@ -7018,6 +7019,31 @@ var NomosRuntimeComponent = (() => {
7018
7019
  }
7019
7020
  };
7020
7021
 
7022
+ // ../src/runtime/http_origin.ts
7023
+ var AUTHORITY = /^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i;
7024
+ var DEFAULT_PORTS = { http: "80", https: "443" };
7025
+ function httpOrigin(url) {
7026
+ const match = AUTHORITY.exec(url.trim());
7027
+ if (!match) return void 0;
7028
+ const scheme = match[1].toLowerCase();
7029
+ if (scheme !== "http" && scheme !== "https") return void 0;
7030
+ const authority = match[2];
7031
+ const hostAndPort = authority.slice(authority.lastIndexOf("@") + 1);
7032
+ const ipv6 = /^(\[[0-9a-f:.]+\])(?::(\d*))?$/i.exec(hostAndPort);
7033
+ const named = /^([^:[\]\s]+)(?::(\d*))?$/.exec(hostAndPort);
7034
+ const parts = ipv6 ?? named;
7035
+ if (!parts) return void 0;
7036
+ const host = parts[1].toLowerCase();
7037
+ if (host.length === 0 || /[\s<>^`{|}%\\]/.test(host)) return void 0;
7038
+ let port = parts[2] ?? "";
7039
+ if (port !== "") {
7040
+ const value = Number(port);
7041
+ if (!Number.isInteger(value) || value > 65535) return void 0;
7042
+ port = String(value);
7043
+ }
7044
+ return port === "" || port === DEFAULT_PORTS[scheme] ? `${scheme}://${host}` : `${scheme}://${host}:${port}`;
7045
+ }
7046
+
7021
7047
  // ../src/git_read_lease.ts
7022
7048
  var GIT_READ_LEASE_MEDIA_TYPE = "application/vnd.nomos.git-read-lease+protobuf";
7023
7049
  function decodeGitReadLease(bytes, workspace, nowUnixSeconds = BigInt(Math.floor(Date.now() / 1e3))) {
@@ -7351,14 +7377,7 @@ var NomosRuntimeComponent = (() => {
7351
7377
  ...servedOrigin === void 0 ? {} : { servedOrigin }
7352
7378
  });
7353
7379
  };
7354
- var originOf2 = (url) => {
7355
- try {
7356
- const parsed = new URL(url);
7357
- return parsed.protocol === "https:" || parsed.protocol === "http:" ? parsed.origin : void 0;
7358
- } catch {
7359
- return void 0;
7360
- }
7361
- };
7380
+ var originOf2 = httpOrigin;
7362
7381
  var ReplicaPlacementDirectiveKind = Object.freeze({
7363
7382
  None: "none",
7364
7383
  Cache: "cache",
@@ -13103,7 +13122,10 @@ var NomosRuntimeComponent = (() => {
13103
13122
  ...background ? { background } : {},
13104
13123
  ...awaited || existing?.awaited ? { awaited: true } : {},
13105
13124
  failures: existing?.failures ?? 0,
13106
- retryNotBeforeNanoseconds: 0n
13125
+ // A foreground read may retry at once. Upkeep owed by a write or a sync keeps any back-off
13126
+ // it is already serving: otherwise every write retried a failing upkeep immediately, and a
13127
+ // workspace whose upkeep could not succeed retried on every write (CAP-693).
13128
+ retryNotBeforeNanoseconds: isReadDemand ? 0n : existing?.retryNotBeforeNanoseconds ?? 0n
13107
13129
  });
13108
13130
  if (isReadDemand && (!existing?.read || existing.read.owedByAdvance)) {
13109
13131
  const entries = [...this.#pending.entries()];
@@ -13722,18 +13744,17 @@ var NomosRuntimeComponent = (() => {
13722
13744
  #requestReadMaintenance;
13723
13745
  #clock;
13724
13746
  #subscriptions = /* @__PURE__ */ new Map();
13725
- /** Watches owed a re-read, drained one query group per turn when a turn scheduler is given. */
13747
+ /** Watches owed a re-read, drained one query group per office turn (see [drainOwedTurn]). */
13726
13748
  #owed = /* @__PURE__ */ new Set();
13727
- #nextTurn;
13728
- #draining = false;
13749
+ #deferRefreshes;
13729
13750
  #sequence = 0n;
13730
- constructor(queries, sessions, events, requestReadMaintenance, clock, nextTurn) {
13751
+ constructor(queries, sessions, events, requestReadMaintenance, clock, deferRefreshes = false) {
13731
13752
  this.#queries = queries;
13732
13753
  this.#sessions = sessions;
13733
13754
  this.#events = events;
13734
13755
  this.#requestReadMaintenance = requestReadMaintenance;
13735
13756
  this.#clock = clock;
13736
- this.#nextTurn = nextTurn;
13757
+ this.#deferRefreshes = deferRefreshes;
13737
13758
  }
13738
13759
  start(request, command) {
13739
13760
  if (!command.subscriptionId) throw new Error("watch requires a subscription identity");
@@ -13839,34 +13860,33 @@ var NomosRuntimeComponent = (() => {
13839
13860
  * or replace current authorization. Each watch still owns its delivery state.
13840
13861
  */
13841
13862
  #refreshMatching(matches, cause) {
13842
- if (this.#nextTurn && !cause) {
13863
+ if (this.#deferRefreshes && !cause) {
13843
13864
  for (const [id, subscription] of this.#subscriptions) {
13844
13865
  if (subscription.request.query && matches(subscription)) this.#owed.add(id);
13845
13866
  }
13846
- this.#drain();
13847
13867
  return;
13848
13868
  }
13849
13869
  this.#refreshGroups(this.#groups(matches), cause);
13850
13870
  }
13851
- #drain() {
13852
- if (this.#draining || this.#owed.size === 0) return;
13853
- this.#draining = true;
13854
- this.#nextTurn(() => {
13855
- this.#draining = false;
13856
- if (this.#owed.size === 0) return;
13857
- const first = this.#owed.values().next().value;
13858
- const lead = this.#subscriptions.get(first);
13859
- if (!lead?.request.query) {
13860
- this.#owed.delete(first);
13861
- } else {
13862
- const declaration = toBinary(QueryRequestSchema, lead.request.query);
13863
- const session = lead.request.session;
13864
- const group = this.#groups((subscription) => subscription.request.session === session && this.#owed.has(subscription.request.subscriptionId) && sameBytes(toBinary(QueryRequestSchema, subscription.request.query), declaration));
13865
- for (const each of group) for (const watch of each.watches) this.#owed.delete(watch.request.subscriptionId);
13866
- this.#refreshGroups(group);
13867
- }
13868
- this.#drain();
13869
- });
13871
+ /** Whether any watch is owed a re-read: the office's next drive() is due at once. */
13872
+ get owesRefresh() {
13873
+ return this.#owed.size > 0;
13874
+ }
13875
+ /** One office turn of owed re-reads: the first owed watch's query group. False when none was owed. */
13876
+ drainOwedTurn() {
13877
+ if (this.#owed.size === 0) return false;
13878
+ const first = this.#owed.values().next().value;
13879
+ const lead = this.#subscriptions.get(first);
13880
+ if (!lead?.request.query) {
13881
+ this.#owed.delete(first);
13882
+ return true;
13883
+ }
13884
+ const declaration = toBinary(QueryRequestSchema, lead.request.query);
13885
+ const session = lead.request.session;
13886
+ const group = this.#groups((subscription) => subscription.request.session === session && this.#owed.has(subscription.request.subscriptionId) && sameBytes(toBinary(QueryRequestSchema, subscription.request.query), declaration));
13887
+ for (const each of group) for (const watch of each.watches) this.#owed.delete(watch.request.subscriptionId);
13888
+ this.#refreshGroups(group);
13889
+ return true;
13870
13890
  }
13871
13891
  #groups(matches) {
13872
13892
  const groups = [];
@@ -13990,6 +14010,38 @@ var NomosRuntimeComponent = (() => {
13990
14010
  });
13991
14011
  }
13992
14012
 
14013
+ // ../src/runtime/shell_contract.ts
14014
+ var SHELL_CONTRACT_V1 = Object.freeze({
14015
+ version: 1,
14016
+ /** Host globals beyond ECMAScript 2022, which every shell supplies. */
14017
+ host: Object.freeze(["TextEncoder", "TextDecoder", "queueMicrotask", "console"]),
14018
+ /** Nomos bridges a native bootstrap installs for the ports it hands to peerOffice.open. */
14019
+ bridges: Object.freeze([
14020
+ "__nomosKernel",
14021
+ "__nomosCredentialVault",
14022
+ "__nomosProfile",
14023
+ "__nomosObservations",
14024
+ "__nomosCustodyStorage",
14025
+ "__nomosPeerDeskStore",
14026
+ "__nomosSyncDiagnostic",
14027
+ "__nomosShellContract"
14028
+ ]),
14029
+ /** Globals the runtime may only probe: used behind their own `typeof` test, never bare. */
14030
+ probed: Object.freeze(["process", "Deno", "Bun", "define"])
14031
+ });
14032
+ var SHELL_CONTRACT_V2 = Object.freeze({ ...SHELL_CONTRACT_V1, version: 2 });
14033
+ var SHELL_CONTRACT_MINIMUM = 1;
14034
+ function declaredShellContract(scope = globalThis) {
14035
+ const declared = scope.__nomosShellContract;
14036
+ return declared === void 0 ? 1 : Number(declared);
14037
+ }
14038
+ function assertShellContract(scope = globalThis) {
14039
+ const declared = declaredShellContract(scope);
14040
+ if (!Number.isInteger(declared) || declared < SHELL_CONTRACT_MINIMUM) {
14041
+ throw new Error(`nomos.runtime.shell_contract_unsupported: this runtime needs shell contract ${SHELL_CONTRACT_MINIMUM} or later; the shell declares ${String(declared)}`);
14042
+ }
14043
+ }
14044
+
13993
14045
  // ../src/runtime/replica_follow_state.ts
13994
14046
  var ReplicaFollowPhase = Object.freeze({
13995
14047
  Desired: "desired",
@@ -21930,10 +21982,9 @@ var NomosRuntimeComponent = (() => {
21930
21982
  this.#trace,
21931
21983
  (session) => this.#readMaintenance.schedule(session, ReadMaintenanceCause.READ_DEBT),
21932
21984
  observations,
21933
- // An interactive peer keeps its thread responsive while watches catch up.
21934
- this.#interactivePeer ? (run2) => {
21935
- setTimeout(run2, 0);
21936
- } : void 0
21985
+ // An interactive peer keeps its thread responsive while watches catch up: owed re-reads
21986
+ // wait for its drive() turns.
21987
+ this.#interactivePeer
21937
21988
  );
21938
21989
  this.#application = new ApplicationDesk({
21939
21990
  onAdmitted: (session) => {
@@ -22340,7 +22391,7 @@ var NomosRuntimeComponent = (() => {
22340
22391
  * mirrors queue/backoff state.
22341
22392
  */
22342
22393
  drive() {
22343
- return this.#maintenance.drive();
22394
+ return driveOfficeTurn(this.#subscriptions, this.#maintenance);
22344
22395
  }
22345
22396
  /**
22346
22397
  * Carry one exact maintenance demand through a durable host continuation.
@@ -23299,8 +23350,14 @@ var NomosRuntimeComponent = (() => {
23299
23350
  this.close();
23300
23351
  }
23301
23352
  };
23353
+ function driveOfficeTurn(subscriptions, maintenance) {
23354
+ subscriptions.drainOwedTurn();
23355
+ const wake = maintenance.drive();
23356
+ return subscriptions.owesRefresh ? 0n : wake;
23357
+ }
23302
23358
  var peerOffice = {
23303
23359
  open(kernel, credentials, profile, observations, custodyStorage, peerDeskStore) {
23360
+ assertShellContract();
23304
23361
  return new PeerOffice(kernel, credentials, profile, observations, custodyStorage, peerDeskStore);
23305
23362
  },
23306
23363
  Peer: PeerOffice
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  (() => {
3
3
  // ../../platform-shells/browser/worker_page_entry.ts
4
- var workerDigest = true ? "051bd37c4dec771340abac5fab088d66a63328bce47c928d3fe547fd950eaef5" : "";
4
+ var workerDigest = true ? "aa8ad2f6773925141b0634aae08c300f71e05fbf251afd0074e13b6e074a8bac" : "";
5
5
  var SLOW_OPERATION_MICROS = 1e6;
6
6
  var slowOperationsReported = 0;
7
7
  var bootStages = [];
@@ -42,6 +42,11 @@
42
42
  worker?.terminate();
43
43
  worker = void 0;
44
44
  };
45
+ var heldEvents = [];
46
+ var deliverEvent = (frame) => {
47
+ if (heldEvents) heldEvents.push(frame);
48
+ else window.__nomosOnMessage?.(`runtime-v2-event:${frame}`);
49
+ };
45
50
  var receive = (message) => {
46
51
  switch (message.kind) {
47
52
  case "boot-progress":
@@ -107,7 +112,7 @@
107
112
  })();
108
113
  break;
109
114
  case "event":
110
- window.__nomosOnMessage?.(`runtime-v2-event:${message.frame}`);
115
+ deliverEvent(message.frame);
111
116
  break;
112
117
  case "kernel-work":
113
118
  if (message.snapshot) lastSnapshot = message.snapshot;
@@ -166,6 +171,11 @@
166
171
  send({ kind: "invoke", id, frame: frameBase64, sentAt: Date.now() });
167
172
  });
168
173
  };
174
+ window.__nomosFlushEvents = () => {
175
+ const held = heldEvents ?? [];
176
+ heldEvents = void 0;
177
+ for (const frame of held) window.__nomosOnMessage?.(`runtime-v2-event:${frame}`);
178
+ };
169
179
  window.__nomosKernelWorkSnapshot = () => lastSnapshot;
170
180
  window.__nomosWorkerHosted = true;
171
181
  window.__nomosDisposeRuntime = () => {
@@ -13463,6 +13463,33 @@
13463
13463
  init_define_NOMOS_KERNEL_RELEASE();
13464
13464
  init_shims();
13465
13465
 
13466
+ // ../src/runtime/http_origin.ts
13467
+ init_define_NOMOS_KERNEL_RELEASE();
13468
+ init_shims();
13469
+ var AUTHORITY = /^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i;
13470
+ var DEFAULT_PORTS = { http: "80", https: "443" };
13471
+ function httpOrigin(url) {
13472
+ const match = AUTHORITY.exec(url.trim());
13473
+ if (!match) return void 0;
13474
+ const scheme = match[1].toLowerCase();
13475
+ if (scheme !== "http" && scheme !== "https") return void 0;
13476
+ const authority = match[2];
13477
+ const hostAndPort = authority.slice(authority.lastIndexOf("@") + 1);
13478
+ const ipv6 = /^(\[[0-9a-f:.]+\])(?::(\d*))?$/i.exec(hostAndPort);
13479
+ const named = /^([^:[\]\s]+)(?::(\d*))?$/.exec(hostAndPort);
13480
+ const parts = ipv6 ?? named;
13481
+ if (!parts) return void 0;
13482
+ const host = parts[1].toLowerCase();
13483
+ if (host.length === 0 || /[\s<>^`{|}%\\]/.test(host)) return void 0;
13484
+ let port = parts[2] ?? "";
13485
+ if (port !== "") {
13486
+ const value = Number(port);
13487
+ if (!Number.isInteger(value) || value > 65535) return void 0;
13488
+ port = String(value);
13489
+ }
13490
+ return port === "" || port === DEFAULT_PORTS[scheme] ? `${scheme}://${host}` : `${scheme}://${host}:${port}`;
13491
+ }
13492
+
13466
13493
  // ../src/runtime/provider_origins.ts
13467
13494
  init_define_NOMOS_KERNEL_RELEASE();
13468
13495
  init_shims();
@@ -13816,14 +13843,7 @@
13816
13843
  ...servedOrigin === void 0 ? {} : { servedOrigin }
13817
13844
  });
13818
13845
  };
13819
- var originOf2 = (url) => {
13820
- try {
13821
- const parsed = new URL(url);
13822
- return parsed.protocol === "https:" || parsed.protocol === "http:" ? parsed.origin : void 0;
13823
- } catch {
13824
- return void 0;
13825
- }
13826
- };
13846
+ var originOf2 = httpOrigin;
13827
13847
  var ReplicaPlacementDirectiveKind = Object.freeze({
13828
13848
  None: "none",
13829
13849
  Cache: "cache",
@@ -19934,7 +19954,10 @@
19934
19954
  ...background ? { background } : {},
19935
19955
  ...awaited || existing?.awaited ? { awaited: true } : {},
19936
19956
  failures: existing?.failures ?? 0,
19937
- retryNotBeforeNanoseconds: 0n
19957
+ // A foreground read may retry at once. Upkeep owed by a write or a sync keeps any back-off
19958
+ // it is already serving: otherwise every write retried a failing upkeep immediately, and a
19959
+ // workspace whose upkeep could not succeed retried on every write (CAP-693).
19960
+ retryNotBeforeNanoseconds: isReadDemand ? 0n : existing?.retryNotBeforeNanoseconds ?? 0n
19938
19961
  });
19939
19962
  if (isReadDemand && (!existing?.read || existing.read.owedByAdvance)) {
19940
19963
  const entries = [...__privateGet(this, _pending).entries()];
@@ -20388,9 +20411,9 @@
20388
20411
  }
20389
20412
  return true;
20390
20413
  };
20391
- var _queries4, _sessions6, _events2, _requestReadMaintenance, _clock9, _subscriptions2, _owed, _nextTurn, _draining, _sequence11, _SubscriptionManager_instances, now_fn4, refreshMatching_fn, drain_fn, groups_fn, refreshGroups_fn, read_fn, refresh_fn, failed_fn;
20414
+ var _queries4, _sessions6, _events2, _requestReadMaintenance, _clock9, _subscriptions2, _owed, _deferRefreshes, _sequence11, _SubscriptionManager_instances, now_fn4, refreshMatching_fn, groups_fn, refreshGroups_fn, read_fn, refresh_fn, failed_fn;
20392
20415
  var SubscriptionManager = class {
20393
- constructor(queries, sessions, events, requestReadMaintenance, clock, nextTurn) {
20416
+ constructor(queries, sessions, events, requestReadMaintenance, clock, deferRefreshes = false) {
20394
20417
  __privateAdd(this, _SubscriptionManager_instances);
20395
20418
  __privateAdd(this, _queries4);
20396
20419
  __privateAdd(this, _sessions6);
@@ -20398,17 +20421,16 @@
20398
20421
  __privateAdd(this, _requestReadMaintenance);
20399
20422
  __privateAdd(this, _clock9);
20400
20423
  __privateAdd(this, _subscriptions2, /* @__PURE__ */ new Map());
20401
- /** Watches owed a re-read, drained one query group per turn when a turn scheduler is given. */
20424
+ /** Watches owed a re-read, drained one query group per office turn (see [drainOwedTurn]). */
20402
20425
  __privateAdd(this, _owed, /* @__PURE__ */ new Set());
20403
- __privateAdd(this, _nextTurn);
20404
- __privateAdd(this, _draining, false);
20426
+ __privateAdd(this, _deferRefreshes);
20405
20427
  __privateAdd(this, _sequence11, 0n);
20406
20428
  __privateSet(this, _queries4, queries);
20407
20429
  __privateSet(this, _sessions6, sessions);
20408
20430
  __privateSet(this, _events2, events);
20409
20431
  __privateSet(this, _requestReadMaintenance, requestReadMaintenance);
20410
20432
  __privateSet(this, _clock9, clock);
20411
- __privateSet(this, _nextTurn, nextTurn);
20433
+ __privateSet(this, _deferRefreshes, deferRefreshes);
20412
20434
  }
20413
20435
  start(request, command) {
20414
20436
  if (!command.subscriptionId) throw new Error("watch requires a subscription identity");
@@ -20506,6 +20528,26 @@
20506
20528
  readIndexAdvanced(workspace) {
20507
20529
  this.refreshWorkspace(workspace);
20508
20530
  }
20531
+ /** Whether any watch is owed a re-read: the office's next drive() is due at once. */
20532
+ get owesRefresh() {
20533
+ return __privateGet(this, _owed).size > 0;
20534
+ }
20535
+ /** One office turn of owed re-reads: the first owed watch's query group. False when none was owed. */
20536
+ drainOwedTurn() {
20537
+ if (__privateGet(this, _owed).size === 0) return false;
20538
+ const first = __privateGet(this, _owed).values().next().value;
20539
+ const lead = __privateGet(this, _subscriptions2).get(first);
20540
+ if (!lead?.request.query) {
20541
+ __privateGet(this, _owed).delete(first);
20542
+ return true;
20543
+ }
20544
+ const declaration = toBinary(QueryRequestSchema, lead.request.query);
20545
+ const session = lead.request.session;
20546
+ const group = __privateMethod(this, _SubscriptionManager_instances, groups_fn).call(this, (subscription) => subscription.request.session === session && __privateGet(this, _owed).has(subscription.request.subscriptionId) && sameBytes(toBinary(QueryRequestSchema, subscription.request.query), declaration));
20547
+ for (const each of group) for (const watch of each.watches) __privateGet(this, _owed).delete(watch.request.subscriptionId);
20548
+ __privateMethod(this, _SubscriptionManager_instances, refreshGroups_fn).call(this, group);
20549
+ return true;
20550
+ }
20509
20551
  };
20510
20552
  _queries4 = new WeakMap();
20511
20553
  _sessions6 = new WeakMap();
@@ -20514,8 +20556,7 @@
20514
20556
  _clock9 = new WeakMap();
20515
20557
  _subscriptions2 = new WeakMap();
20516
20558
  _owed = new WeakMap();
20517
- _nextTurn = new WeakMap();
20518
- _draining = new WeakMap();
20559
+ _deferRefreshes = new WeakMap();
20519
20560
  _sequence11 = new WeakMap();
20520
20561
  _SubscriptionManager_instances = new WeakSet();
20521
20562
  now_fn4 = function() {
@@ -20526,35 +20567,14 @@
20526
20567
  * or replace current authorization. Each watch still owns its delivery state.
20527
20568
  */
20528
20569
  refreshMatching_fn = function(matches, cause) {
20529
- if (__privateGet(this, _nextTurn) && !cause) {
20570
+ if (__privateGet(this, _deferRefreshes) && !cause) {
20530
20571
  for (const [id, subscription] of __privateGet(this, _subscriptions2)) {
20531
20572
  if (subscription.request.query && matches(subscription)) __privateGet(this, _owed).add(id);
20532
20573
  }
20533
- __privateMethod(this, _SubscriptionManager_instances, drain_fn).call(this);
20534
20574
  return;
20535
20575
  }
20536
20576
  __privateMethod(this, _SubscriptionManager_instances, refreshGroups_fn).call(this, __privateMethod(this, _SubscriptionManager_instances, groups_fn).call(this, matches), cause);
20537
20577
  };
20538
- drain_fn = function() {
20539
- if (__privateGet(this, _draining) || __privateGet(this, _owed).size === 0) return;
20540
- __privateSet(this, _draining, true);
20541
- __privateGet(this, _nextTurn).call(this, () => {
20542
- __privateSet(this, _draining, false);
20543
- if (__privateGet(this, _owed).size === 0) return;
20544
- const first = __privateGet(this, _owed).values().next().value;
20545
- const lead = __privateGet(this, _subscriptions2).get(first);
20546
- if (!lead?.request.query) {
20547
- __privateGet(this, _owed).delete(first);
20548
- } else {
20549
- const declaration = toBinary(QueryRequestSchema, lead.request.query);
20550
- const session = lead.request.session;
20551
- const group = __privateMethod(this, _SubscriptionManager_instances, groups_fn).call(this, (subscription) => subscription.request.session === session && __privateGet(this, _owed).has(subscription.request.subscriptionId) && sameBytes(toBinary(QueryRequestSchema, subscription.request.query), declaration));
20552
- for (const each of group) for (const watch of each.watches) __privateGet(this, _owed).delete(watch.request.subscriptionId);
20553
- __privateMethod(this, _SubscriptionManager_instances, refreshGroups_fn).call(this, group);
20554
- }
20555
- __privateMethod(this, _SubscriptionManager_instances, drain_fn).call(this);
20556
- });
20557
- };
20558
20578
  groups_fn = function(matches) {
20559
20579
  const groups = [];
20560
20580
  for (const subscription of __privateGet(this, _subscriptions2).values()) {
@@ -20676,6 +20696,40 @@
20676
20696
  });
20677
20697
  }
20678
20698
 
20699
+ // ../src/runtime/shell_contract.ts
20700
+ init_define_NOMOS_KERNEL_RELEASE();
20701
+ init_shims();
20702
+ var SHELL_CONTRACT_V1 = Object.freeze({
20703
+ version: 1,
20704
+ /** Host globals beyond ECMAScript 2022, which every shell supplies. */
20705
+ host: Object.freeze(["TextEncoder", "TextDecoder", "queueMicrotask", "console"]),
20706
+ /** Nomos bridges a native bootstrap installs for the ports it hands to peerOffice.open. */
20707
+ bridges: Object.freeze([
20708
+ "__nomosKernel",
20709
+ "__nomosCredentialVault",
20710
+ "__nomosProfile",
20711
+ "__nomosObservations",
20712
+ "__nomosCustodyStorage",
20713
+ "__nomosPeerDeskStore",
20714
+ "__nomosSyncDiagnostic",
20715
+ "__nomosShellContract"
20716
+ ]),
20717
+ /** Globals the runtime may only probe: used behind their own `typeof` test, never bare. */
20718
+ probed: Object.freeze(["process", "Deno", "Bun", "define"])
20719
+ });
20720
+ var SHELL_CONTRACT_V2 = Object.freeze({ ...SHELL_CONTRACT_V1, version: 2 });
20721
+ var SHELL_CONTRACT_MINIMUM = 1;
20722
+ function declaredShellContract(scope2 = globalThis) {
20723
+ const declared = scope2.__nomosShellContract;
20724
+ return declared === void 0 ? 1 : Number(declared);
20725
+ }
20726
+ function assertShellContract(scope2 = globalThis) {
20727
+ const declared = declaredShellContract(scope2);
20728
+ if (!Number.isInteger(declared) || declared < SHELL_CONTRACT_MINIMUM) {
20729
+ throw new Error(`nomos.runtime.shell_contract_unsupported: this runtime needs shell contract ${SHELL_CONTRACT_MINIMUM} or later; the shell declares ${String(declared)}`);
20730
+ }
20731
+ }
20732
+
20679
20733
  // ../src/runtime/replica_follow_controller.ts
20680
20734
  init_define_NOMOS_KERNEL_RELEASE();
20681
20735
  init_shims();
@@ -29046,10 +29100,9 @@
29046
29100
  __privateGet(this, _trace13),
29047
29101
  (session) => __privateGet(this, _readMaintenance).schedule(session, ReadMaintenanceCause.READ_DEBT),
29048
29102
  observations,
29049
- // An interactive peer keeps its thread responsive while watches catch up.
29050
- __privateGet(this, _interactivePeer) ? (run2) => {
29051
- setTimeout(run2, 0);
29052
- } : void 0
29103
+ // An interactive peer keeps its thread responsive while watches catch up: owed re-reads
29104
+ // wait for its drive() turns.
29105
+ __privateGet(this, _interactivePeer)
29053
29106
  ));
29054
29107
  __privateSet(this, _application3, new ApplicationDesk({
29055
29108
  onAdmitted: (session) => {
@@ -29456,7 +29509,7 @@
29456
29509
  * mirrors queue/backoff state.
29457
29510
  */
29458
29511
  drive() {
29459
- return __privateGet(this, _maintenance2).drive();
29512
+ return driveOfficeTurn(__privateGet(this, _subscriptions5), __privateGet(this, _maintenance2));
29460
29513
  }
29461
29514
  /**
29462
29515
  * Carry one exact maintenance demand through a durable host continuation.
@@ -30429,8 +30482,14 @@
30429
30482
  candidateCustodyRequired_fn = function(request, workspace, reference) {
30430
30483
  return __privateGet(this, _responses).candidateCustodyRequired(request, workspace, reference);
30431
30484
  };
30485
+ function driveOfficeTurn(subscriptions, maintenance) {
30486
+ subscriptions.drainOwedTurn();
30487
+ const wake = maintenance.drive();
30488
+ return subscriptions.owesRefresh ? 0n : wake;
30489
+ }
30432
30490
  var peerOffice = {
30433
30491
  open(kernel, credentials, profile, observations, custodyStorage, peerDeskStore) {
30492
+ assertShellContract();
30434
30493
  return new PeerOffice(kernel, credentials, profile, observations, custodyStorage, peerDeskStore);
30435
30494
  },
30436
30495
  Peer: PeerOffice
@@ -13463,6 +13463,33 @@
13463
13463
  init_define_NOMOS_KERNEL_RELEASE();
13464
13464
  init_shims();
13465
13465
 
13466
+ // ../src/runtime/http_origin.ts
13467
+ init_define_NOMOS_KERNEL_RELEASE();
13468
+ init_shims();
13469
+ var AUTHORITY = /^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i;
13470
+ var DEFAULT_PORTS = { http: "80", https: "443" };
13471
+ function httpOrigin(url) {
13472
+ const match = AUTHORITY.exec(url.trim());
13473
+ if (!match) return void 0;
13474
+ const scheme = match[1].toLowerCase();
13475
+ if (scheme !== "http" && scheme !== "https") return void 0;
13476
+ const authority = match[2];
13477
+ const hostAndPort = authority.slice(authority.lastIndexOf("@") + 1);
13478
+ const ipv6 = /^(\[[0-9a-f:.]+\])(?::(\d*))?$/i.exec(hostAndPort);
13479
+ const named = /^([^:[\]\s]+)(?::(\d*))?$/.exec(hostAndPort);
13480
+ const parts = ipv6 ?? named;
13481
+ if (!parts) return void 0;
13482
+ const host = parts[1].toLowerCase();
13483
+ if (host.length === 0 || /[\s<>^`{|}%\\]/.test(host)) return void 0;
13484
+ let port = parts[2] ?? "";
13485
+ if (port !== "") {
13486
+ const value = Number(port);
13487
+ if (!Number.isInteger(value) || value > 65535) return void 0;
13488
+ port = String(value);
13489
+ }
13490
+ return port === "" || port === DEFAULT_PORTS[scheme] ? `${scheme}://${host}` : `${scheme}://${host}:${port}`;
13491
+ }
13492
+
13466
13493
  // ../src/runtime/provider_origins.ts
13467
13494
  init_define_NOMOS_KERNEL_RELEASE();
13468
13495
  init_shims();
@@ -13816,14 +13843,7 @@
13816
13843
  ...servedOrigin === void 0 ? {} : { servedOrigin }
13817
13844
  });
13818
13845
  };
13819
- var originOf2 = (url) => {
13820
- try {
13821
- const parsed = new URL(url);
13822
- return parsed.protocol === "https:" || parsed.protocol === "http:" ? parsed.origin : void 0;
13823
- } catch {
13824
- return void 0;
13825
- }
13826
- };
13846
+ var originOf2 = httpOrigin;
13827
13847
  var ReplicaPlacementDirectiveKind = Object.freeze({
13828
13848
  None: "none",
13829
13849
  Cache: "cache",
@@ -19931,7 +19951,10 @@
19931
19951
  ...background ? { background } : {},
19932
19952
  ...awaited || existing?.awaited ? { awaited: true } : {},
19933
19953
  failures: existing?.failures ?? 0,
19934
- retryNotBeforeNanoseconds: 0n
19954
+ // A foreground read may retry at once. Upkeep owed by a write or a sync keeps any back-off
19955
+ // it is already serving: otherwise every write retried a failing upkeep immediately, and a
19956
+ // workspace whose upkeep could not succeed retried on every write (CAP-693).
19957
+ retryNotBeforeNanoseconds: isReadDemand ? 0n : existing?.retryNotBeforeNanoseconds ?? 0n
19935
19958
  });
19936
19959
  if (isReadDemand && (!existing?.read || existing.read.owedByAdvance)) {
19937
19960
  const entries = [...__privateGet(this, _pending).entries()];
@@ -20385,9 +20408,9 @@
20385
20408
  }
20386
20409
  return true;
20387
20410
  };
20388
- var _queries4, _sessions6, _events2, _requestReadMaintenance, _clock9, _subscriptions2, _owed, _nextTurn, _draining, _sequence11, _SubscriptionManager_instances, now_fn4, refreshMatching_fn, drain_fn, groups_fn, refreshGroups_fn, read_fn, refresh_fn, failed_fn;
20411
+ var _queries4, _sessions6, _events2, _requestReadMaintenance, _clock9, _subscriptions2, _owed, _deferRefreshes, _sequence11, _SubscriptionManager_instances, now_fn4, refreshMatching_fn, groups_fn, refreshGroups_fn, read_fn, refresh_fn, failed_fn;
20389
20412
  var SubscriptionManager = class {
20390
- constructor(queries, sessions, events, requestReadMaintenance, clock, nextTurn) {
20413
+ constructor(queries, sessions, events, requestReadMaintenance, clock, deferRefreshes = false) {
20391
20414
  __privateAdd(this, _SubscriptionManager_instances);
20392
20415
  __privateAdd(this, _queries4);
20393
20416
  __privateAdd(this, _sessions6);
@@ -20395,17 +20418,16 @@
20395
20418
  __privateAdd(this, _requestReadMaintenance);
20396
20419
  __privateAdd(this, _clock9);
20397
20420
  __privateAdd(this, _subscriptions2, /* @__PURE__ */ new Map());
20398
- /** Watches owed a re-read, drained one query group per turn when a turn scheduler is given. */
20421
+ /** Watches owed a re-read, drained one query group per office turn (see [drainOwedTurn]). */
20399
20422
  __privateAdd(this, _owed, /* @__PURE__ */ new Set());
20400
- __privateAdd(this, _nextTurn);
20401
- __privateAdd(this, _draining, false);
20423
+ __privateAdd(this, _deferRefreshes);
20402
20424
  __privateAdd(this, _sequence11, 0n);
20403
20425
  __privateSet(this, _queries4, queries);
20404
20426
  __privateSet(this, _sessions6, sessions);
20405
20427
  __privateSet(this, _events2, events);
20406
20428
  __privateSet(this, _requestReadMaintenance, requestReadMaintenance);
20407
20429
  __privateSet(this, _clock9, clock);
20408
- __privateSet(this, _nextTurn, nextTurn);
20430
+ __privateSet(this, _deferRefreshes, deferRefreshes);
20409
20431
  }
20410
20432
  start(request, command) {
20411
20433
  if (!command.subscriptionId) throw new Error("watch requires a subscription identity");
@@ -20503,6 +20525,26 @@
20503
20525
  readIndexAdvanced(workspace) {
20504
20526
  this.refreshWorkspace(workspace);
20505
20527
  }
20528
+ /** Whether any watch is owed a re-read: the office's next drive() is due at once. */
20529
+ get owesRefresh() {
20530
+ return __privateGet(this, _owed).size > 0;
20531
+ }
20532
+ /** One office turn of owed re-reads: the first owed watch's query group. False when none was owed. */
20533
+ drainOwedTurn() {
20534
+ if (__privateGet(this, _owed).size === 0) return false;
20535
+ const first = __privateGet(this, _owed).values().next().value;
20536
+ const lead = __privateGet(this, _subscriptions2).get(first);
20537
+ if (!lead?.request.query) {
20538
+ __privateGet(this, _owed).delete(first);
20539
+ return true;
20540
+ }
20541
+ const declaration = toBinary(QueryRequestSchema, lead.request.query);
20542
+ const session = lead.request.session;
20543
+ const group = __privateMethod(this, _SubscriptionManager_instances, groups_fn).call(this, (subscription) => subscription.request.session === session && __privateGet(this, _owed).has(subscription.request.subscriptionId) && sameBytes(toBinary(QueryRequestSchema, subscription.request.query), declaration));
20544
+ for (const each of group) for (const watch of each.watches) __privateGet(this, _owed).delete(watch.request.subscriptionId);
20545
+ __privateMethod(this, _SubscriptionManager_instances, refreshGroups_fn).call(this, group);
20546
+ return true;
20547
+ }
20506
20548
  };
20507
20549
  _queries4 = new WeakMap();
20508
20550
  _sessions6 = new WeakMap();
@@ -20511,8 +20553,7 @@
20511
20553
  _clock9 = new WeakMap();
20512
20554
  _subscriptions2 = new WeakMap();
20513
20555
  _owed = new WeakMap();
20514
- _nextTurn = new WeakMap();
20515
- _draining = new WeakMap();
20556
+ _deferRefreshes = new WeakMap();
20516
20557
  _sequence11 = new WeakMap();
20517
20558
  _SubscriptionManager_instances = new WeakSet();
20518
20559
  now_fn4 = function() {
@@ -20523,35 +20564,14 @@
20523
20564
  * or replace current authorization. Each watch still owns its delivery state.
20524
20565
  */
20525
20566
  refreshMatching_fn = function(matches, cause) {
20526
- if (__privateGet(this, _nextTurn) && !cause) {
20567
+ if (__privateGet(this, _deferRefreshes) && !cause) {
20527
20568
  for (const [id, subscription] of __privateGet(this, _subscriptions2)) {
20528
20569
  if (subscription.request.query && matches(subscription)) __privateGet(this, _owed).add(id);
20529
20570
  }
20530
- __privateMethod(this, _SubscriptionManager_instances, drain_fn).call(this);
20531
20571
  return;
20532
20572
  }
20533
20573
  __privateMethod(this, _SubscriptionManager_instances, refreshGroups_fn).call(this, __privateMethod(this, _SubscriptionManager_instances, groups_fn).call(this, matches), cause);
20534
20574
  };
20535
- drain_fn = function() {
20536
- if (__privateGet(this, _draining) || __privateGet(this, _owed).size === 0) return;
20537
- __privateSet(this, _draining, true);
20538
- __privateGet(this, _nextTurn).call(this, () => {
20539
- __privateSet(this, _draining, false);
20540
- if (__privateGet(this, _owed).size === 0) return;
20541
- const first = __privateGet(this, _owed).values().next().value;
20542
- const lead = __privateGet(this, _subscriptions2).get(first);
20543
- if (!lead?.request.query) {
20544
- __privateGet(this, _owed).delete(first);
20545
- } else {
20546
- const declaration = toBinary(QueryRequestSchema, lead.request.query);
20547
- const session = lead.request.session;
20548
- const group = __privateMethod(this, _SubscriptionManager_instances, groups_fn).call(this, (subscription) => subscription.request.session === session && __privateGet(this, _owed).has(subscription.request.subscriptionId) && sameBytes(toBinary(QueryRequestSchema, subscription.request.query), declaration));
20549
- for (const each of group) for (const watch of each.watches) __privateGet(this, _owed).delete(watch.request.subscriptionId);
20550
- __privateMethod(this, _SubscriptionManager_instances, refreshGroups_fn).call(this, group);
20551
- }
20552
- __privateMethod(this, _SubscriptionManager_instances, drain_fn).call(this);
20553
- });
20554
- };
20555
20575
  groups_fn = function(matches) {
20556
20576
  const groups = [];
20557
20577
  for (const subscription of __privateGet(this, _subscriptions2).values()) {
@@ -20673,6 +20693,40 @@
20673
20693
  });
20674
20694
  }
20675
20695
 
20696
+ // ../src/runtime/shell_contract.ts
20697
+ init_define_NOMOS_KERNEL_RELEASE();
20698
+ init_shims();
20699
+ var SHELL_CONTRACT_V1 = Object.freeze({
20700
+ version: 1,
20701
+ /** Host globals beyond ECMAScript 2022, which every shell supplies. */
20702
+ host: Object.freeze(["TextEncoder", "TextDecoder", "queueMicrotask", "console"]),
20703
+ /** Nomos bridges a native bootstrap installs for the ports it hands to peerOffice.open. */
20704
+ bridges: Object.freeze([
20705
+ "__nomosKernel",
20706
+ "__nomosCredentialVault",
20707
+ "__nomosProfile",
20708
+ "__nomosObservations",
20709
+ "__nomosCustodyStorage",
20710
+ "__nomosPeerDeskStore",
20711
+ "__nomosSyncDiagnostic",
20712
+ "__nomosShellContract"
20713
+ ]),
20714
+ /** Globals the runtime may only probe: used behind their own `typeof` test, never bare. */
20715
+ probed: Object.freeze(["process", "Deno", "Bun", "define"])
20716
+ });
20717
+ var SHELL_CONTRACT_V2 = Object.freeze({ ...SHELL_CONTRACT_V1, version: 2 });
20718
+ var SHELL_CONTRACT_MINIMUM = 1;
20719
+ function declaredShellContract(scope = globalThis) {
20720
+ const declared = scope.__nomosShellContract;
20721
+ return declared === void 0 ? 1 : Number(declared);
20722
+ }
20723
+ function assertShellContract(scope = globalThis) {
20724
+ const declared = declaredShellContract(scope);
20725
+ if (!Number.isInteger(declared) || declared < SHELL_CONTRACT_MINIMUM) {
20726
+ throw new Error(`nomos.runtime.shell_contract_unsupported: this runtime needs shell contract ${SHELL_CONTRACT_MINIMUM} or later; the shell declares ${String(declared)}`);
20727
+ }
20728
+ }
20729
+
20676
20730
  // ../src/runtime/replica_follow_controller.ts
20677
20731
  init_define_NOMOS_KERNEL_RELEASE();
20678
20732
  init_shims();
@@ -29040,10 +29094,9 @@
29040
29094
  __privateGet(this, _trace13),
29041
29095
  (session) => __privateGet(this, _readMaintenance).schedule(session, ReadMaintenanceCause.READ_DEBT),
29042
29096
  observations,
29043
- // An interactive peer keeps its thread responsive while watches catch up.
29044
- __privateGet(this, _interactivePeer) ? (run2) => {
29045
- setTimeout(run2, 0);
29046
- } : void 0
29097
+ // An interactive peer keeps its thread responsive while watches catch up: owed re-reads
29098
+ // wait for its drive() turns.
29099
+ __privateGet(this, _interactivePeer)
29047
29100
  ));
29048
29101
  __privateSet(this, _application3, new ApplicationDesk({
29049
29102
  onAdmitted: (session) => {
@@ -29450,7 +29503,7 @@
29450
29503
  * mirrors queue/backoff state.
29451
29504
  */
29452
29505
  drive() {
29453
- return __privateGet(this, _maintenance2).drive();
29506
+ return driveOfficeTurn(__privateGet(this, _subscriptions5), __privateGet(this, _maintenance2));
29454
29507
  }
29455
29508
  /**
29456
29509
  * Carry one exact maintenance demand through a durable host continuation.
@@ -30423,8 +30476,14 @@
30423
30476
  candidateCustodyRequired_fn = function(request, workspace, reference) {
30424
30477
  return __privateGet(this, _responses).candidateCustodyRequired(request, workspace, reference);
30425
30478
  };
30479
+ function driveOfficeTurn(subscriptions, maintenance) {
30480
+ subscriptions.drainOwedTurn();
30481
+ const wake = maintenance.drive();
30482
+ return subscriptions.owesRefresh ? 0n : wake;
30483
+ }
30426
30484
  var peerOffice = {
30427
30485
  open(kernel, credentials, profile, observations, custodyStorage, peerDeskStore) {
30486
+ assertShellContract();
30428
30487
  return new PeerOffice(kernel, credentials, profile, observations, custodyStorage, peerDeskStore);
30429
30488
  },
30430
30489
  Peer: PeerOffice
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@githolon/runtime",
3
- "version": "0.113.2",
3
+ "version": "0.113.4",
4
4
  "type": "module",
5
5
  "description": "The portable Nomos application runtime, reception contracts, and Node/browser runners.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
package/runner/build.ts CHANGED
@@ -198,6 +198,17 @@ if (existsSync(FLUTTER_ASSETS)) {
198
198
  "// GENERATED by peer-office/package/runner/build.ts. Do not edit.\n"
199
199
  + "// The sha256 of the packaged nomos-runner-web.js this package ships.\n"
200
200
  + `const String kNomosRunnerWebSha256 =\n '${pageSha256}';\n`);
201
+ // The native Peer Office ships as Dart code, not a Flutter asset: a code-push update (Shorebird
202
+ // patch) replaces Dart but never assets, and this runtime is the code we most often need to fix.
203
+ const nativeRuntime = readFileSync(here("../dist/nomos-native-runtime.js"), "utf8");
204
+ if (nativeRuntime.includes("'''")) throw new Error("native runtime bundle cannot be a Dart raw string: it contains '''");
205
+ const nativeRuntimeSha256 = createHash("sha256").update(nativeRuntime).digest("hex");
206
+ writeFileSync(join(FLUTTER_ASSETS, "../lib/src/platform_shell/native_runtime_bundle.g.dart"),
207
+ "// GENERATED by peer-office/package/runner/build.ts from dist/nomos-native-runtime.js. Do not edit.\n"
208
+ + "// ignore_for_file: lines_longer_than_80_chars\n"
209
+ + "// The shared Peer Office the native hosts execute, as Dart code so a code patch can carry it.\n"
210
+ + `const String kNomosNativeRuntimeSha256 =\n '${nativeRuntimeSha256}';\n`
211
+ + `const String kNomosNativeRuntimeJavascript = r'''${nativeRuntime}''';\n`);
201
212
  console.error("✓ synced browser shell and shared Peer Office assets → nomos_flutter/assets");
202
213
  }
203
214
 
@@ -14587,6 +14587,32 @@ var KernelPort = class {
14587
14587
  // ../src/runtime/placement_desk.ts
14588
14588
  init_define_NOMOS_KERNEL_RELEASE();
14589
14589
 
14590
+ // ../src/runtime/http_origin.ts
14591
+ init_define_NOMOS_KERNEL_RELEASE();
14592
+ var AUTHORITY = /^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i;
14593
+ var DEFAULT_PORTS = { http: "80", https: "443" };
14594
+ function httpOrigin(url) {
14595
+ const match = AUTHORITY.exec(url.trim());
14596
+ if (!match) return void 0;
14597
+ const scheme = match[1].toLowerCase();
14598
+ if (scheme !== "http" && scheme !== "https") return void 0;
14599
+ const authority = match[2];
14600
+ const hostAndPort = authority.slice(authority.lastIndexOf("@") + 1);
14601
+ const ipv6 = /^(\[[0-9a-f:.]+\])(?::(\d*))?$/i.exec(hostAndPort);
14602
+ const named = /^([^:[\]\s]+)(?::(\d*))?$/.exec(hostAndPort);
14603
+ const parts = ipv6 ?? named;
14604
+ if (!parts) return void 0;
14605
+ const host = parts[1].toLowerCase();
14606
+ if (host.length === 0 || /[\s<>^`{|}%\\]/.test(host)) return void 0;
14607
+ let port = parts[2] ?? "";
14608
+ if (port !== "") {
14609
+ const value = Number(port);
14610
+ if (!Number.isInteger(value) || value > 65535) return void 0;
14611
+ port = String(value);
14612
+ }
14613
+ return port === "" || port === DEFAULT_PORTS[scheme] ? `${scheme}://${host}` : `${scheme}://${host}:${port}`;
14614
+ }
14615
+
14590
14616
  // ../src/runtime/provider_origins.ts
14591
14617
  init_define_NOMOS_KERNEL_RELEASE();
14592
14618
 
@@ -14926,14 +14952,7 @@ var normalizeProfile = (profile) => {
14926
14952
  ...servedOrigin === void 0 ? {} : { servedOrigin }
14927
14953
  });
14928
14954
  };
14929
- var originOf2 = (url) => {
14930
- try {
14931
- const parsed = new URL(url);
14932
- return parsed.protocol === "https:" || parsed.protocol === "http:" ? parsed.origin : void 0;
14933
- } catch {
14934
- return void 0;
14935
- }
14936
- };
14955
+ var originOf2 = httpOrigin;
14937
14956
  var ReplicaPlacementDirectiveKind = Object.freeze({
14938
14957
  None: "none",
14939
14958
  Cache: "cache",
@@ -20783,7 +20802,10 @@ var ReadMaintenanceDesk = class {
20783
20802
  ...background ? { background } : {},
20784
20803
  ...awaited || existing?.awaited ? { awaited: true } : {},
20785
20804
  failures: existing?.failures ?? 0,
20786
- retryNotBeforeNanoseconds: 0n
20805
+ // A foreground read may retry at once. Upkeep owed by a write or a sync keeps any back-off
20806
+ // it is already serving: otherwise every write retried a failing upkeep immediately, and a
20807
+ // workspace whose upkeep could not succeed retried on every write (CAP-693).
20808
+ retryNotBeforeNanoseconds: isReadDemand ? 0n : existing?.retryNotBeforeNanoseconds ?? 0n
20787
20809
  });
20788
20810
  if (isReadDemand && (!existing?.read || existing.read.owedByAdvance)) {
20789
20811
  const entries = [...this.#pending.entries()];
@@ -21392,18 +21414,17 @@ var SubscriptionManager = class {
21392
21414
  #requestReadMaintenance;
21393
21415
  #clock;
21394
21416
  #subscriptions = /* @__PURE__ */ new Map();
21395
- /** Watches owed a re-read, drained one query group per turn when a turn scheduler is given. */
21417
+ /** Watches owed a re-read, drained one query group per office turn (see [drainOwedTurn]). */
21396
21418
  #owed = /* @__PURE__ */ new Set();
21397
- #nextTurn;
21398
- #draining = false;
21419
+ #deferRefreshes;
21399
21420
  #sequence = 0n;
21400
- constructor(queries, sessions, events, requestReadMaintenance, clock, nextTurn) {
21421
+ constructor(queries, sessions, events, requestReadMaintenance, clock, deferRefreshes = false) {
21401
21422
  this.#queries = queries;
21402
21423
  this.#sessions = sessions;
21403
21424
  this.#events = events;
21404
21425
  this.#requestReadMaintenance = requestReadMaintenance;
21405
21426
  this.#clock = clock;
21406
- this.#nextTurn = nextTurn;
21427
+ this.#deferRefreshes = deferRefreshes;
21407
21428
  }
21408
21429
  start(request, command) {
21409
21430
  if (!command.subscriptionId) throw new Error("watch requires a subscription identity");
@@ -21509,34 +21530,33 @@ var SubscriptionManager = class {
21509
21530
  * or replace current authorization. Each watch still owns its delivery state.
21510
21531
  */
21511
21532
  #refreshMatching(matches, cause) {
21512
- if (this.#nextTurn && !cause) {
21533
+ if (this.#deferRefreshes && !cause) {
21513
21534
  for (const [id, subscription] of this.#subscriptions) {
21514
21535
  if (subscription.request.query && matches(subscription)) this.#owed.add(id);
21515
21536
  }
21516
- this.#drain();
21517
21537
  return;
21518
21538
  }
21519
21539
  this.#refreshGroups(this.#groups(matches), cause);
21520
21540
  }
21521
- #drain() {
21522
- if (this.#draining || this.#owed.size === 0) return;
21523
- this.#draining = true;
21524
- this.#nextTurn(() => {
21525
- this.#draining = false;
21526
- if (this.#owed.size === 0) return;
21527
- const first = this.#owed.values().next().value;
21528
- const lead = this.#subscriptions.get(first);
21529
- if (!lead?.request.query) {
21530
- this.#owed.delete(first);
21531
- } else {
21532
- const declaration = toBinary(QueryRequestSchema, lead.request.query);
21533
- const session = lead.request.session;
21534
- const group = this.#groups((subscription) => subscription.request.session === session && this.#owed.has(subscription.request.subscriptionId) && sameBytes(toBinary(QueryRequestSchema, subscription.request.query), declaration));
21535
- for (const each of group) for (const watch of each.watches) this.#owed.delete(watch.request.subscriptionId);
21536
- this.#refreshGroups(group);
21537
- }
21538
- this.#drain();
21539
- });
21541
+ /** Whether any watch is owed a re-read: the office's next drive() is due at once. */
21542
+ get owesRefresh() {
21543
+ return this.#owed.size > 0;
21544
+ }
21545
+ /** One office turn of owed re-reads: the first owed watch's query group. False when none was owed. */
21546
+ drainOwedTurn() {
21547
+ if (this.#owed.size === 0) return false;
21548
+ const first = this.#owed.values().next().value;
21549
+ const lead = this.#subscriptions.get(first);
21550
+ if (!lead?.request.query) {
21551
+ this.#owed.delete(first);
21552
+ return true;
21553
+ }
21554
+ const declaration = toBinary(QueryRequestSchema, lead.request.query);
21555
+ const session = lead.request.session;
21556
+ const group = this.#groups((subscription) => subscription.request.session === session && this.#owed.has(subscription.request.subscriptionId) && sameBytes(toBinary(QueryRequestSchema, subscription.request.query), declaration));
21557
+ for (const each of group) for (const watch of each.watches) this.#owed.delete(watch.request.subscriptionId);
21558
+ this.#refreshGroups(group);
21559
+ return true;
21540
21560
  }
21541
21561
  #groups(matches) {
21542
21562
  const groups = [];
@@ -21660,6 +21680,39 @@ function createSyntheticRequest(requestId) {
21660
21680
  });
21661
21681
  }
21662
21682
 
21683
+ // ../src/runtime/shell_contract.ts
21684
+ init_define_NOMOS_KERNEL_RELEASE();
21685
+ var SHELL_CONTRACT_V1 = Object.freeze({
21686
+ version: 1,
21687
+ /** Host globals beyond ECMAScript 2022, which every shell supplies. */
21688
+ host: Object.freeze(["TextEncoder", "TextDecoder", "queueMicrotask", "console"]),
21689
+ /** Nomos bridges a native bootstrap installs for the ports it hands to peerOffice.open. */
21690
+ bridges: Object.freeze([
21691
+ "__nomosKernel",
21692
+ "__nomosCredentialVault",
21693
+ "__nomosProfile",
21694
+ "__nomosObservations",
21695
+ "__nomosCustodyStorage",
21696
+ "__nomosPeerDeskStore",
21697
+ "__nomosSyncDiagnostic",
21698
+ "__nomosShellContract"
21699
+ ]),
21700
+ /** Globals the runtime may only probe: used behind their own `typeof` test, never bare. */
21701
+ probed: Object.freeze(["process", "Deno", "Bun", "define"])
21702
+ });
21703
+ var SHELL_CONTRACT_V2 = Object.freeze({ ...SHELL_CONTRACT_V1, version: 2 });
21704
+ var SHELL_CONTRACT_MINIMUM = 1;
21705
+ function declaredShellContract(scope = globalThis) {
21706
+ const declared = scope.__nomosShellContract;
21707
+ return declared === void 0 ? 1 : Number(declared);
21708
+ }
21709
+ function assertShellContract(scope = globalThis) {
21710
+ const declared = declaredShellContract(scope);
21711
+ if (!Number.isInteger(declared) || declared < SHELL_CONTRACT_MINIMUM) {
21712
+ throw new Error(`nomos.runtime.shell_contract_unsupported: this runtime needs shell contract ${SHELL_CONTRACT_MINIMUM} or later; the shell declares ${String(declared)}`);
21713
+ }
21714
+ }
21715
+
21663
21716
  // ../src/runtime/replica_follow_controller.ts
21664
21717
  init_define_NOMOS_KERNEL_RELEASE();
21665
21718
 
@@ -29657,10 +29710,9 @@ var PeerOffice = class {
29657
29710
  this.#trace,
29658
29711
  (session) => this.#readMaintenance.schedule(session, ReadMaintenanceCause.READ_DEBT),
29659
29712
  observations,
29660
- // An interactive peer keeps its thread responsive while watches catch up.
29661
- this.#interactivePeer ? (run2) => {
29662
- setTimeout(run2, 0);
29663
- } : void 0
29713
+ // An interactive peer keeps its thread responsive while watches catch up: owed re-reads
29714
+ // wait for its drive() turns.
29715
+ this.#interactivePeer
29664
29716
  );
29665
29717
  this.#application = new ApplicationDesk({
29666
29718
  onAdmitted: (session) => {
@@ -30067,7 +30119,7 @@ var PeerOffice = class {
30067
30119
  * mirrors queue/backoff state.
30068
30120
  */
30069
30121
  drive() {
30070
- return this.#maintenance.drive();
30122
+ return driveOfficeTurn(this.#subscriptions, this.#maintenance);
30071
30123
  }
30072
30124
  /**
30073
30125
  * Carry one exact maintenance demand through a durable host continuation.
@@ -31026,8 +31078,14 @@ var PeerOffice = class {
31026
31078
  this.close();
31027
31079
  }
31028
31080
  };
31081
+ function driveOfficeTurn(subscriptions, maintenance) {
31082
+ subscriptions.drainOwedTurn();
31083
+ const wake = maintenance.drive();
31084
+ return subscriptions.owesRefresh ? 0n : wake;
31085
+ }
31029
31086
  var peerOffice = {
31030
31087
  open(kernel, credentials, profile, observations, custodyStorage, peerDeskStore) {
31088
+ assertShellContract();
31031
31089
  return new PeerOffice(kernel, credentials, profile, observations, custodyStorage, peerDeskStore);
31032
31090
  },
31033
31091
  Peer: PeerOffice