@githolon/dsl 0.110.1 → 0.111.0

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.
package/dart/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.66.7
2
+
3
+ - Recover sync after loss of the upstream bookmark by fetching provider history and allowing the kernel to verify a shared ancestor. Preserve pending local work and reject unrelated history through the existing admission gate.
4
+ - Wait for a sealed initial sync base before sending a first suffix, and expose provider/local heads in sync diagnostics.
5
+
1
6
  ## 0.66.6
2
7
 
3
8
  - Let reception close promptly when presentation stream listeners are paused.
@@ -23913,7 +23913,6 @@ var WorkspaceSyncPhase = Object.freeze({
23913
23913
  Done: "done"
23914
23914
  });
23915
23915
  var trackedMain = "refs/remotes/nomos/main";
23916
- var NO_COMMON_BASE = "this replica holds local history with no frontier its upstream ever confirmed; convergence needs a common admitted base \u2014 drop the local copy to refetch it, or re-discover a provider holding this lineage";
23917
23916
  var deferredRemote = "refs/remotes/nomos/deferred";
23918
23917
  var deferredLocal = "refs/nomos/sync-deferred-local";
23919
23918
  var judgedThisLifetime = /* @__PURE__ */ new Map();
@@ -24124,38 +24123,13 @@ var WorkspaceSyncWork = class {
24124
24123
  }), { case: "awaiting", requestId });
24125
24124
  }
24126
24125
  /**
24127
- * NO COMMON BASE — a round that cannot converge, and must not pay for history to find out.
24128
- *
24129
- * This replica holds a non-empty ledger but has never recorded a frontier its upstream
24130
- * confirmed (`refs/remotes/nomos/main` is absent). The kernel refuses convergence in that
24131
- * state ("a non-empty live ledger requires a common admitted base"), so every step after the
24132
- * O(1) frontier probe is wasted work — and it is not cheap waste: the fetch negotiates with
24133
- * no `have` (a full-history pack), and the dependency planner decodes EVERY intent from
24134
- * genesis and inspects every change, once per round. That is O(history) per follow round,
24135
- * repeated at every retry, for a round that can only end in a refusal.
24136
- *
24137
- * The one base this round can establish costs nothing and is established before this is
24138
- * asked: an upstream holding exactly this replica's head (the probe's answer) converges it
24139
- * and records the tracking frontier. Anything else needs the local copy to be dropped and
24140
- * refetched (an application decision, which preserves the copy), or a re-discovery that
24141
- * names a provider holding this lineage. Both are reported, at O(1), as this failure.
24142
- */
24143
- /**
24144
- * Establish this round's base when none is tracked, without walking any history it can avoid.
24145
- *
24146
- * The upstream just named its own frontier. If that commit is in THIS replica's lineage, it is
24147
- * a common admitted base by definition — both sides hold it — and adopting it turns the round
24148
- * into an ordinary fast-forward: the offer carries only the suffix above it, the fetch can name
24149
- * it as a truthful `have`, and convergence has the base the kernel requires. One commit walk
24150
- * (no change decoding, no pack, no network) decides it.
24151
- *
24152
- * If it is not in this replica's lineage, no base exists to establish and the round is refused
24153
- * (#noCommonBase) before it leases, fetches or plans anything.
24154
- *
24155
- * A kernel without the commit walk cannot be asked, so it keeps the previous behaviour.
24126
+ * Establish a cheap base when the provider's current tip is in our local chain.
24127
+ * A negative answer means the base is unknown: both sides may have advanced from
24128
+ * an earlier shared commit. Acquire the candidate and let the kernel discover
24129
+ * and judge that history. A tracking bookmark is not an admission prerequisite.
24156
24130
  */
24157
24131
  #establishBase(upstreamHead) {
24158
- if (!this.#noCommonBase() || !this.#kernel.historySummary) return true;
24132
+ if (!this.#missingTrackedBase() || !this.#kernel.historySummary) return true;
24159
24133
  const summary = this.#kernel.historySummary(this.#mount, this.#requestId, upstreamHead, this.#localHead);
24160
24134
  if (!summary.reachedBase) return false;
24161
24135
  this.#previousHead = upstreamHead;
@@ -24170,26 +24144,9 @@ var WorkspaceSyncWork = class {
24170
24144
  get establishedBase() {
24171
24145
  return this.#establishedBase;
24172
24146
  }
24173
- #noCommonBase() {
24147
+ #missingTrackedBase() {
24174
24148
  return this.#previousHead === void 0 && this.#localHead !== void 0 && this.#replaceLocalHead === void 0;
24175
24149
  }
24176
- #noCommonBaseResult() {
24177
- return this.#finish(create(SyncWorkspaceResponseSchema, {
24178
- workspace: this.#mount.workspace,
24179
- ...this.#localHead === void 0 ? {} : { currentHead: this.#localHead },
24180
- stillAhead: true,
24181
- ...this.#offerReceipt === void 0 ? {} : { offerReceipt: this.#offerReceipt },
24182
- pushError: create(RuntimeTransportFailureSchema, {
24183
- endpoint: this.#offerEndpoint(),
24184
- status: 409,
24185
- refused: true,
24186
- message: NO_COMMON_BASE
24187
- }),
24188
- timings: create(SyncPhaseTimingsSchema, {
24189
- convergeMillis: elapsedMillis(this.#clock, this.#started)
24190
- })
24191
- }));
24192
- }
24193
24150
  #holdsLocalWork() {
24194
24151
  return this.#command.admit && !!this.#localHead && this.#localHead !== this.#previousHead;
24195
24152
  }
@@ -24341,7 +24298,6 @@ var WorkspaceSyncWork = class {
24341
24298
  if (!this.#desiredHead) return this.#transportFailure("resident peer returned no admitted frontier", false);
24342
24299
  this.#candidateDurable = admission.sealedMain === this.#desiredHead;
24343
24300
  if (state.phase === WorkspaceSyncPhase.Probe && this.#desiredHead !== this.#localHead) {
24344
- if (!this.#establishBase(this.#desiredHead)) return this.#noCommonBaseResult();
24345
24301
  if (this.#alreadyJudged(this.#desiredHead)) {
24346
24302
  return this.#finish(create(SyncWorkspaceResponseSchema, {
24347
24303
  workspace: this.#mount.workspace,
@@ -24353,6 +24309,22 @@ var WorkspaceSyncWork = class {
24353
24309
  offerReceipt: this.#offerReceipt
24354
24310
  }));
24355
24311
  }
24312
+ if (!this.#establishBase(this.#desiredHead)) {
24313
+ this.#offerAfterConverge = this.#command.admit;
24314
+ this.#rebaseFrom = void 0;
24315
+ return this.#leaseEffect();
24316
+ }
24317
+ if (this.#establishedBase && !this.#candidateDurable && this.#kernel.resolveRef(this.#mount, this.#requestId, trackedMain) === void 0) {
24318
+ return this.#finish(create(SyncWorkspaceResponseSchema, {
24319
+ workspace: this.#mount.workspace,
24320
+ currentHead: this.#localHead,
24321
+ previousHead: this.#previousHead,
24322
+ stillAhead: true,
24323
+ directOfferDeferred: true,
24324
+ reconnectRequired: false,
24325
+ offerReceipt: this.#offerReceipt
24326
+ }));
24327
+ }
24356
24328
  if (this.#probeOnly) {
24357
24329
  this.#needsReconciliation = true;
24358
24330
  return this.#finish(create(SyncWorkspaceResponseSchema, {
@@ -24398,7 +24370,7 @@ var WorkspaceSyncWork = class {
24398
24370
  return this.#converge(this.#desiredHead, admission.resultPack.byteLength, 0);
24399
24371
  }
24400
24372
  if (this.#desiredHead === this.#previousHead) return this.#converge(this.#desiredHead, 0, 0);
24401
- if (!this.#establishBase(this.#desiredHead)) return this.#noCommonBaseResult();
24373
+ this.#establishBase(this.#desiredHead);
24402
24374
  if (admission.recoveryRequired !== false) return this.#leaseEffect();
24403
24375
  return this.#transportFailure("resident peer supplied neither the missing delta nor a history gap", false);
24404
24376
  }
@@ -24621,7 +24593,7 @@ var WorkspaceSyncWork = class {
24621
24593
  }
24622
24594
  }
24623
24595
  #converge(candidateHead, receivedBytes, prefetchMillis) {
24624
- if (!this.#establishBase(candidateHead)) return this.#noCommonBaseResult();
24596
+ this.#establishBase(candidateHead);
24625
24597
  this.#beforeConverge?.(candidateHead, this.#previousHead);
24626
24598
  const convergeStarted = this.#clock.monotonicNanoseconds();
24627
24599
  let judged;
@@ -27076,13 +27048,21 @@ var CorrespondenceDesk = class {
27076
27048
  }
27077
27049
  #observeSyncResult(requestId, workId2, result) {
27078
27050
  const timings = result.timings;
27051
+ const receipt = result.offerReceipt?.outcome;
27052
+ const admission = receipt?.case === "admission" ? receipt.value : void 0;
27079
27053
  this.#events.instant("peer.follow.sync-result", {
27080
27054
  request: create(RuntimeRequestSchema, { protocolVersion: 2, requestId }),
27081
27055
  workspace: result.workspace
27082
27056
  }, {
27083
27057
  "sync.workId": workId2,
27084
27058
  ...result.currentHead ? { "sync.head": result.currentHead } : {},
27059
+ ...result.previousHead ? { "sync.previousHead": result.previousHead } : {},
27060
+ ...admission?.main ? { "sync.providerHead": admission.main } : {},
27061
+ ...admission?.sealedMain ? { "sync.sealedHead": admission.sealedMain } : {},
27085
27062
  "sync.stillAhead": result.stillAhead,
27063
+ "sync.reconnectRequired": result.reconnectRequired,
27064
+ "sync.refused": result.refused,
27065
+ "sync.deferred": result.deferred,
27086
27066
  "sync.directOfferDeferred": result.directOfferDeferred,
27087
27067
  "sync.offline": result.offline,
27088
27068
  ...timings ? {
package/dart/pubspec.yaml CHANGED
@@ -7,7 +7,7 @@ repository: https://github.com/Captain-App/nomos2
7
7
  description: >-
8
8
  Nomos 2 Dart client — generated domain values, intent payloads and application
9
9
  lifecycle types over the typed Nomos kernel protocol and USDA custody model.
10
- version: 0.66.6
10
+ version: 0.66.7
11
11
 
12
12
  environment:
13
13
  sdk: ^3.5.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@githolon/dsl",
3
- "version": "0.110.1",
3
+ "version": "0.111.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Nomos 2 domain-authoring DSL: aggregates + directives in TS, executed and encoded to the Rust kernel's wire shapes.",
@@ -72,7 +72,7 @@
72
72
  "test": "vitest run"
73
73
  },
74
74
  "dependencies": {
75
- "@githolon/runtime": "^0.110.1",
75
+ "@githolon/runtime": "^0.111.0",
76
76
  "@bufbuild/protobuf": "^2.13.0",
77
77
  "@bufbuild/protoc-gen-es": "^2.13.0",
78
78
  "esbuild": "0.24.2",
@@ -2544,8 +2544,8 @@ const NOMOS_TYPES_DEP = "^0.11.2";
2544
2544
  // 0.48.x: session-bound clients (XClient.bind/NomosClientInterface/DomainClientSessionMismatch/
2545
2545
  // DomainNotInstalledForSession, engine.follow, pendingConflicts lanes) — the generated client
2546
2546
  // REQUIRES this surface. 0.48.1 fixes NomosSession.watchPendingConflicts delegation.
2547
- const NOMOS_CLIENT_DEP = "^0.66.6";
2548
- const NOMOS_FLUTTER_DEP = "^0.65.8";
2547
+ const NOMOS_CLIENT_DEP = "^0.66.7";
2548
+ const NOMOS_FLUTTER_DEP = "^0.65.9";
2549
2549
  // DRIFT TRIPWIRE: pubspec_pins.test.ts asserts these equal the CURRENT versions in the Dart and Flutter
2550
2550
  // package pubspecs — a release without this bump fails the suite, so tenants never
2551
2551
  // land back in dependency_overrides (the exact co2 report this closes, third occurrence).