githolon 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.
@@ -16883,7 +16883,7 @@ import { create as create54, fromBinary as fromBinary20 } from "@bufbuild/protob
16883
16883
  function releaseSyncJudgment(workspace) {
16884
16884
  judgedThisLifetime.delete(workspace);
16885
16885
  }
16886
- var PLACEMENT_REF3, LAW_PRODUCTS_MEDIA_TYPE, WorkspaceSyncPhase, trackedMain, NO_COMMON_BASE, deferredRemote, deferredLocal, judgedThisLifetime, MAX_REBASES_PER_ROUND, elapsedMillis, WorkspaceSyncWork;
16886
+ var PLACEMENT_REF3, LAW_PRODUCTS_MEDIA_TYPE, WorkspaceSyncPhase, trackedMain, deferredRemote, deferredLocal, judgedThisLifetime, MAX_REBASES_PER_ROUND, elapsedMillis, WorkspaceSyncWork;
16887
16887
  var init_workspace_sync = __esm({
16888
16888
  "../peer-office/src/runtime/workspace_sync.ts"() {
16889
16889
  "use strict";
@@ -16909,7 +16909,6 @@ var init_workspace_sync = __esm({
16909
16909
  Done: "done"
16910
16910
  });
16911
16911
  trackedMain = "refs/remotes/nomos/main";
16912
- 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";
16913
16912
  deferredRemote = "refs/remotes/nomos/deferred";
16914
16913
  deferredLocal = "refs/nomos/sync-deferred-local";
16915
16914
  judgedThisLifetime = /* @__PURE__ */ new Map();
@@ -17117,38 +17116,13 @@ var init_workspace_sync = __esm({
17117
17116
  }), { case: "awaiting", requestId });
17118
17117
  }
17119
17118
  /**
17120
- * NO COMMON BASE — a round that cannot converge, and must not pay for history to find out.
17121
- *
17122
- * This replica holds a non-empty ledger but has never recorded a frontier its upstream
17123
- * confirmed (`refs/remotes/nomos/main` is absent). The kernel refuses convergence in that
17124
- * state ("a non-empty live ledger requires a common admitted base"), so every step after the
17125
- * O(1) frontier probe is wasted work — and it is not cheap waste: the fetch negotiates with
17126
- * no `have` (a full-history pack), and the dependency planner decodes EVERY intent from
17127
- * genesis and inspects every change, once per round. That is O(history) per follow round,
17128
- * repeated at every retry, for a round that can only end in a refusal.
17129
- *
17130
- * The one base this round can establish costs nothing and is established before this is
17131
- * asked: an upstream holding exactly this replica's head (the probe's answer) converges it
17132
- * and records the tracking frontier. Anything else needs the local copy to be dropped and
17133
- * refetched (an application decision, which preserves the copy), or a re-discovery that
17134
- * names a provider holding this lineage. Both are reported, at O(1), as this failure.
17135
- */
17136
- /**
17137
- * Establish this round's base when none is tracked, without walking any history it can avoid.
17138
- *
17139
- * The upstream just named its own frontier. If that commit is in THIS replica's lineage, it is
17140
- * a common admitted base by definition — both sides hold it — and adopting it turns the round
17141
- * into an ordinary fast-forward: the offer carries only the suffix above it, the fetch can name
17142
- * it as a truthful `have`, and convergence has the base the kernel requires. One commit walk
17143
- * (no change decoding, no pack, no network) decides it.
17144
- *
17145
- * If it is not in this replica's lineage, no base exists to establish and the round is refused
17146
- * (#noCommonBase) before it leases, fetches or plans anything.
17147
- *
17148
- * A kernel without the commit walk cannot be asked, so it keeps the previous behaviour.
17119
+ * Establish a cheap base when the provider's current tip is in our local chain.
17120
+ * A negative answer means the base is unknown: both sides may have advanced from
17121
+ * an earlier shared commit. Acquire the candidate and let the kernel discover
17122
+ * and judge that history. A tracking bookmark is not an admission prerequisite.
17149
17123
  */
17150
17124
  #establishBase(upstreamHead) {
17151
- if (!this.#noCommonBase() || !this.#kernel.historySummary) return true;
17125
+ if (!this.#missingTrackedBase() || !this.#kernel.historySummary) return true;
17152
17126
  const summary = this.#kernel.historySummary(this.#mount, this.#requestId, upstreamHead, this.#localHead);
17153
17127
  if (!summary.reachedBase) return false;
17154
17128
  this.#previousHead = upstreamHead;
@@ -17163,26 +17137,9 @@ var init_workspace_sync = __esm({
17163
17137
  get establishedBase() {
17164
17138
  return this.#establishedBase;
17165
17139
  }
17166
- #noCommonBase() {
17140
+ #missingTrackedBase() {
17167
17141
  return this.#previousHead === void 0 && this.#localHead !== void 0 && this.#replaceLocalHead === void 0;
17168
17142
  }
17169
- #noCommonBaseResult() {
17170
- return this.#finish(create54(SyncWorkspaceResponseSchema, {
17171
- workspace: this.#mount.workspace,
17172
- ...this.#localHead === void 0 ? {} : { currentHead: this.#localHead },
17173
- stillAhead: true,
17174
- ...this.#offerReceipt === void 0 ? {} : { offerReceipt: this.#offerReceipt },
17175
- pushError: create54(RuntimeTransportFailureSchema, {
17176
- endpoint: this.#offerEndpoint(),
17177
- status: 409,
17178
- refused: true,
17179
- message: NO_COMMON_BASE
17180
- }),
17181
- timings: create54(SyncPhaseTimingsSchema, {
17182
- convergeMillis: elapsedMillis(this.#clock, this.#started)
17183
- })
17184
- }));
17185
- }
17186
17143
  #holdsLocalWork() {
17187
17144
  return this.#command.admit && !!this.#localHead && this.#localHead !== this.#previousHead;
17188
17145
  }
@@ -17334,7 +17291,6 @@ var init_workspace_sync = __esm({
17334
17291
  if (!this.#desiredHead) return this.#transportFailure("resident peer returned no admitted frontier", false);
17335
17292
  this.#candidateDurable = admission.sealedMain === this.#desiredHead;
17336
17293
  if (state.phase === WorkspaceSyncPhase.Probe && this.#desiredHead !== this.#localHead) {
17337
- if (!this.#establishBase(this.#desiredHead)) return this.#noCommonBaseResult();
17338
17294
  if (this.#alreadyJudged(this.#desiredHead)) {
17339
17295
  return this.#finish(create54(SyncWorkspaceResponseSchema, {
17340
17296
  workspace: this.#mount.workspace,
@@ -17346,6 +17302,22 @@ var init_workspace_sync = __esm({
17346
17302
  offerReceipt: this.#offerReceipt
17347
17303
  }));
17348
17304
  }
17305
+ if (!this.#establishBase(this.#desiredHead)) {
17306
+ this.#offerAfterConverge = this.#command.admit;
17307
+ this.#rebaseFrom = void 0;
17308
+ return this.#leaseEffect();
17309
+ }
17310
+ if (this.#establishedBase && !this.#candidateDurable && this.#kernel.resolveRef(this.#mount, this.#requestId, trackedMain) === void 0) {
17311
+ return this.#finish(create54(SyncWorkspaceResponseSchema, {
17312
+ workspace: this.#mount.workspace,
17313
+ currentHead: this.#localHead,
17314
+ previousHead: this.#previousHead,
17315
+ stillAhead: true,
17316
+ directOfferDeferred: true,
17317
+ reconnectRequired: false,
17318
+ offerReceipt: this.#offerReceipt
17319
+ }));
17320
+ }
17349
17321
  if (this.#probeOnly) {
17350
17322
  this.#needsReconciliation = true;
17351
17323
  return this.#finish(create54(SyncWorkspaceResponseSchema, {
@@ -17391,7 +17363,7 @@ var init_workspace_sync = __esm({
17391
17363
  return this.#converge(this.#desiredHead, admission.resultPack.byteLength, 0);
17392
17364
  }
17393
17365
  if (this.#desiredHead === this.#previousHead) return this.#converge(this.#desiredHead, 0, 0);
17394
- if (!this.#establishBase(this.#desiredHead)) return this.#noCommonBaseResult();
17366
+ this.#establishBase(this.#desiredHead);
17395
17367
  if (admission.recoveryRequired !== false) return this.#leaseEffect();
17396
17368
  return this.#transportFailure("resident peer supplied neither the missing delta nor a history gap", false);
17397
17369
  }
@@ -17614,7 +17586,7 @@ var init_workspace_sync = __esm({
17614
17586
  }
17615
17587
  }
17616
17588
  #converge(candidateHead, receivedBytes, prefetchMillis) {
17617
- if (!this.#establishBase(candidateHead)) return this.#noCommonBaseResult();
17589
+ this.#establishBase(candidateHead);
17618
17590
  this.#beforeConverge?.(candidateHead, this.#previousHead);
17619
17591
  const convergeStarted = this.#clock.monotonicNanoseconds();
17620
17592
  let judged;
@@ -20148,13 +20120,21 @@ var init_correspondence_desk = __esm({
20148
20120
  }
20149
20121
  #observeSyncResult(requestId, workId2, result) {
20150
20122
  const timings = result.timings;
20123
+ const receipt = result.offerReceipt?.outcome;
20124
+ const admission = receipt?.case === "admission" ? receipt.value : void 0;
20151
20125
  this.#events.instant("peer.follow.sync-result", {
20152
20126
  request: create59(RuntimeRequestSchema, { protocolVersion: 2, requestId }),
20153
20127
  workspace: result.workspace
20154
20128
  }, {
20155
20129
  "sync.workId": workId2,
20156
20130
  ...result.currentHead ? { "sync.head": result.currentHead } : {},
20131
+ ...result.previousHead ? { "sync.previousHead": result.previousHead } : {},
20132
+ ...admission?.main ? { "sync.providerHead": admission.main } : {},
20133
+ ...admission?.sealedMain ? { "sync.sealedHead": admission.sealedMain } : {},
20157
20134
  "sync.stillAhead": result.stillAhead,
20135
+ "sync.reconnectRequired": result.reconnectRequired,
20136
+ "sync.refused": result.refused,
20137
+ "sync.deferred": result.deferred,
20158
20138
  "sync.directOfferDeferred": result.directOfferDeferred,
20159
20139
  "sync.offline": result.offline,
20160
20140
  ...timings ? {
@@ -26456,8 +26436,19 @@ async function ensureApplicationWorkspace(application, opts = {}) {
26456
26436
  }
26457
26437
  const statusUrl = `${cloud}/v2/workspaces/${encodeURIComponent(application)}`;
26458
26438
  const current = await fetch(statusUrl).catch(() => null);
26459
- if (current?.ok) {
26460
- const status = await current.json().catch(() => null);
26439
+ const status = current?.ok ? await current.json().catch(() => null) : null;
26440
+ let unborn = false;
26441
+ if (current?.ok && !status?.lineage && !status?.durableHead && !status?.sealedHead) {
26442
+ const domains2 = await fetch(`${statusUrl}/domains`);
26443
+ if (domains2.status === 409) {
26444
+ const body2 = await domains2.json().catch(() => null);
26445
+ unborn = typeof body2?.error === "string" && body2.error.includes("unborn");
26446
+ }
26447
+ if (!unborn && !domains2.ok) {
26448
+ throw new Error(`could not establish whether application '${application}' has custody (${domains2.status})`);
26449
+ }
26450
+ }
26451
+ if (current?.ok && !unborn) {
26461
26452
  const principal = String(status?.lineage?.principal ?? "");
26462
26453
  const actualParent = String(status?.lineage?.parent ?? "");
26463
26454
  const expectedParent = requestedParent === "root" ? "" : requestedParent;
@@ -26493,7 +26484,7 @@ async function ensureApplicationWorkspace(application, opts = {}) {
26493
26484
  ...principal !== "" && session !== "" && sameIdentity(principal, session) ? { deployPrincipal: principal } : {}
26494
26485
  };
26495
26486
  }
26496
- if (current !== null && current.status !== 404 && current.status !== 409) {
26487
+ if (current !== null && !unborn && current.status !== 404 && current.status !== 409) {
26497
26488
  throw new Error(`could not inspect deploy target '${application}' (${current.status}); refusing to guess that it is unborn`);
26498
26489
  }
26499
26490
  if (requestedParent !== void 0) {
@@ -14249,7 +14249,6 @@ var WorkspaceSyncPhase = Object.freeze({
14249
14249
  Done: "done"
14250
14250
  });
14251
14251
  var trackedMain = "refs/remotes/nomos/main";
14252
- 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";
14253
14252
  var deferredRemote = "refs/remotes/nomos/deferred";
14254
14253
  var deferredLocal = "refs/nomos/sync-deferred-local";
14255
14254
  var judgedThisLifetime = /* @__PURE__ */ new Map();
@@ -14460,38 +14459,13 @@ var WorkspaceSyncWork = class {
14460
14459
  }), { case: "awaiting", requestId });
14461
14460
  }
14462
14461
  /**
14463
- * NO COMMON BASE — a round that cannot converge, and must not pay for history to find out.
14464
- *
14465
- * This replica holds a non-empty ledger but has never recorded a frontier its upstream
14466
- * confirmed (`refs/remotes/nomos/main` is absent). The kernel refuses convergence in that
14467
- * state ("a non-empty live ledger requires a common admitted base"), so every step after the
14468
- * O(1) frontier probe is wasted work — and it is not cheap waste: the fetch negotiates with
14469
- * no `have` (a full-history pack), and the dependency planner decodes EVERY intent from
14470
- * genesis and inspects every change, once per round. That is O(history) per follow round,
14471
- * repeated at every retry, for a round that can only end in a refusal.
14472
- *
14473
- * The one base this round can establish costs nothing and is established before this is
14474
- * asked: an upstream holding exactly this replica's head (the probe's answer) converges it
14475
- * and records the tracking frontier. Anything else needs the local copy to be dropped and
14476
- * refetched (an application decision, which preserves the copy), or a re-discovery that
14477
- * names a provider holding this lineage. Both are reported, at O(1), as this failure.
14478
- */
14479
- /**
14480
- * Establish this round's base when none is tracked, without walking any history it can avoid.
14481
- *
14482
- * The upstream just named its own frontier. If that commit is in THIS replica's lineage, it is
14483
- * a common admitted base by definition — both sides hold it — and adopting it turns the round
14484
- * into an ordinary fast-forward: the offer carries only the suffix above it, the fetch can name
14485
- * it as a truthful `have`, and convergence has the base the kernel requires. One commit walk
14486
- * (no change decoding, no pack, no network) decides it.
14487
- *
14488
- * If it is not in this replica's lineage, no base exists to establish and the round is refused
14489
- * (#noCommonBase) before it leases, fetches or plans anything.
14490
- *
14491
- * A kernel without the commit walk cannot be asked, so it keeps the previous behaviour.
14462
+ * Establish a cheap base when the provider's current tip is in our local chain.
14463
+ * A negative answer means the base is unknown: both sides may have advanced from
14464
+ * an earlier shared commit. Acquire the candidate and let the kernel discover
14465
+ * and judge that history. A tracking bookmark is not an admission prerequisite.
14492
14466
  */
14493
14467
  #establishBase(upstreamHead) {
14494
- if (!this.#noCommonBase() || !this.#kernel.historySummary) return true;
14468
+ if (!this.#missingTrackedBase() || !this.#kernel.historySummary) return true;
14495
14469
  const summary = this.#kernel.historySummary(this.#mount, this.#requestId, upstreamHead, this.#localHead);
14496
14470
  if (!summary.reachedBase) return false;
14497
14471
  this.#previousHead = upstreamHead;
@@ -14506,26 +14480,9 @@ var WorkspaceSyncWork = class {
14506
14480
  get establishedBase() {
14507
14481
  return this.#establishedBase;
14508
14482
  }
14509
- #noCommonBase() {
14483
+ #missingTrackedBase() {
14510
14484
  return this.#previousHead === void 0 && this.#localHead !== void 0 && this.#replaceLocalHead === void 0;
14511
14485
  }
14512
- #noCommonBaseResult() {
14513
- return this.#finish(create59(SyncWorkspaceResponseSchema, {
14514
- workspace: this.#mount.workspace,
14515
- ...this.#localHead === void 0 ? {} : { currentHead: this.#localHead },
14516
- stillAhead: true,
14517
- ...this.#offerReceipt === void 0 ? {} : { offerReceipt: this.#offerReceipt },
14518
- pushError: create59(RuntimeTransportFailureSchema, {
14519
- endpoint: this.#offerEndpoint(),
14520
- status: 409,
14521
- refused: true,
14522
- message: NO_COMMON_BASE
14523
- }),
14524
- timings: create59(SyncPhaseTimingsSchema, {
14525
- convergeMillis: elapsedMillis(this.#clock, this.#started)
14526
- })
14527
- }));
14528
- }
14529
14486
  #holdsLocalWork() {
14530
14487
  return this.#command.admit && !!this.#localHead && this.#localHead !== this.#previousHead;
14531
14488
  }
@@ -14677,7 +14634,6 @@ var WorkspaceSyncWork = class {
14677
14634
  if (!this.#desiredHead) return this.#transportFailure("resident peer returned no admitted frontier", false);
14678
14635
  this.#candidateDurable = admission.sealedMain === this.#desiredHead;
14679
14636
  if (state.phase === WorkspaceSyncPhase.Probe && this.#desiredHead !== this.#localHead) {
14680
- if (!this.#establishBase(this.#desiredHead)) return this.#noCommonBaseResult();
14681
14637
  if (this.#alreadyJudged(this.#desiredHead)) {
14682
14638
  return this.#finish(create59(SyncWorkspaceResponseSchema, {
14683
14639
  workspace: this.#mount.workspace,
@@ -14689,6 +14645,22 @@ var WorkspaceSyncWork = class {
14689
14645
  offerReceipt: this.#offerReceipt
14690
14646
  }));
14691
14647
  }
14648
+ if (!this.#establishBase(this.#desiredHead)) {
14649
+ this.#offerAfterConverge = this.#command.admit;
14650
+ this.#rebaseFrom = void 0;
14651
+ return this.#leaseEffect();
14652
+ }
14653
+ if (this.#establishedBase && !this.#candidateDurable && this.#kernel.resolveRef(this.#mount, this.#requestId, trackedMain) === void 0) {
14654
+ return this.#finish(create59(SyncWorkspaceResponseSchema, {
14655
+ workspace: this.#mount.workspace,
14656
+ currentHead: this.#localHead,
14657
+ previousHead: this.#previousHead,
14658
+ stillAhead: true,
14659
+ directOfferDeferred: true,
14660
+ reconnectRequired: false,
14661
+ offerReceipt: this.#offerReceipt
14662
+ }));
14663
+ }
14692
14664
  if (this.#probeOnly) {
14693
14665
  this.#needsReconciliation = true;
14694
14666
  return this.#finish(create59(SyncWorkspaceResponseSchema, {
@@ -14734,7 +14706,7 @@ var WorkspaceSyncWork = class {
14734
14706
  return this.#converge(this.#desiredHead, admission.resultPack.byteLength, 0);
14735
14707
  }
14736
14708
  if (this.#desiredHead === this.#previousHead) return this.#converge(this.#desiredHead, 0, 0);
14737
- if (!this.#establishBase(this.#desiredHead)) return this.#noCommonBaseResult();
14709
+ this.#establishBase(this.#desiredHead);
14738
14710
  if (admission.recoveryRequired !== false) return this.#leaseEffect();
14739
14711
  return this.#transportFailure("resident peer supplied neither the missing delta nor a history gap", false);
14740
14712
  }
@@ -14957,7 +14929,7 @@ var WorkspaceSyncWork = class {
14957
14929
  }
14958
14930
  }
14959
14931
  #converge(candidateHead, receivedBytes, prefetchMillis) {
14960
- if (!this.#establishBase(candidateHead)) return this.#noCommonBaseResult();
14932
+ this.#establishBase(candidateHead);
14961
14933
  this.#beforeConverge?.(candidateHead, this.#previousHead);
14962
14934
  const convergeStarted = this.#clock.monotonicNanoseconds();
14963
14935
  let judged;
@@ -17402,13 +17374,21 @@ var CorrespondenceDesk = class {
17402
17374
  }
17403
17375
  #observeSyncResult(requestId, workId2, result) {
17404
17376
  const timings = result.timings;
17377
+ const receipt = result.offerReceipt?.outcome;
17378
+ const admission = receipt?.case === "admission" ? receipt.value : void 0;
17405
17379
  this.#events.instant("peer.follow.sync-result", {
17406
17380
  request: create64(RuntimeRequestSchema, { protocolVersion: 2, requestId }),
17407
17381
  workspace: result.workspace
17408
17382
  }, {
17409
17383
  "sync.workId": workId2,
17410
17384
  ...result.currentHead ? { "sync.head": result.currentHead } : {},
17385
+ ...result.previousHead ? { "sync.previousHead": result.previousHead } : {},
17386
+ ...admission?.main ? { "sync.providerHead": admission.main } : {},
17387
+ ...admission?.sealedMain ? { "sync.sealedHead": admission.sealedMain } : {},
17411
17388
  "sync.stillAhead": result.stillAhead,
17389
+ "sync.reconnectRequired": result.reconnectRequired,
17390
+ "sync.refused": result.refused,
17391
+ "sync.deferred": result.deferred,
17412
17392
  "sync.directOfferDeferred": result.directOfferDeferred,
17413
17393
  "sync.offline": result.offline,
17414
17394
  ...timings ? {
package/dist/full-cli.mjs CHANGED
@@ -22818,7 +22818,7 @@ import { create as create55, fromBinary as fromBinary20 } from "@bufbuild/protob
22818
22818
  function releaseSyncJudgment(workspace) {
22819
22819
  judgedThisLifetime.delete(workspace);
22820
22820
  }
22821
- var PLACEMENT_REF3, LAW_PRODUCTS_MEDIA_TYPE, WorkspaceSyncPhase, trackedMain, NO_COMMON_BASE, deferredRemote, deferredLocal, judgedThisLifetime, MAX_REBASES_PER_ROUND, elapsedMillis, WorkspaceSyncWork;
22821
+ var PLACEMENT_REF3, LAW_PRODUCTS_MEDIA_TYPE, WorkspaceSyncPhase, trackedMain, deferredRemote, deferredLocal, judgedThisLifetime, MAX_REBASES_PER_ROUND, elapsedMillis, WorkspaceSyncWork;
22822
22822
  var init_workspace_sync = __esm({
22823
22823
  "../peer-office/src/runtime/workspace_sync.ts"() {
22824
22824
  "use strict";
@@ -22844,7 +22844,6 @@ var init_workspace_sync = __esm({
22844
22844
  Done: "done"
22845
22845
  });
22846
22846
  trackedMain = "refs/remotes/nomos/main";
22847
- 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";
22848
22847
  deferredRemote = "refs/remotes/nomos/deferred";
22849
22848
  deferredLocal = "refs/nomos/sync-deferred-local";
22850
22849
  judgedThisLifetime = /* @__PURE__ */ new Map();
@@ -23052,38 +23051,13 @@ var init_workspace_sync = __esm({
23052
23051
  }), { case: "awaiting", requestId });
23053
23052
  }
23054
23053
  /**
23055
- * NO COMMON BASE — a round that cannot converge, and must not pay for history to find out.
23056
- *
23057
- * This replica holds a non-empty ledger but has never recorded a frontier its upstream
23058
- * confirmed (`refs/remotes/nomos/main` is absent). The kernel refuses convergence in that
23059
- * state ("a non-empty live ledger requires a common admitted base"), so every step after the
23060
- * O(1) frontier probe is wasted work — and it is not cheap waste: the fetch negotiates with
23061
- * no `have` (a full-history pack), and the dependency planner decodes EVERY intent from
23062
- * genesis and inspects every change, once per round. That is O(history) per follow round,
23063
- * repeated at every retry, for a round that can only end in a refusal.
23064
- *
23065
- * The one base this round can establish costs nothing and is established before this is
23066
- * asked: an upstream holding exactly this replica's head (the probe's answer) converges it
23067
- * and records the tracking frontier. Anything else needs the local copy to be dropped and
23068
- * refetched (an application decision, which preserves the copy), or a re-discovery that
23069
- * names a provider holding this lineage. Both are reported, at O(1), as this failure.
23070
- */
23071
- /**
23072
- * Establish this round's base when none is tracked, without walking any history it can avoid.
23073
- *
23074
- * The upstream just named its own frontier. If that commit is in THIS replica's lineage, it is
23075
- * a common admitted base by definition — both sides hold it — and adopting it turns the round
23076
- * into an ordinary fast-forward: the offer carries only the suffix above it, the fetch can name
23077
- * it as a truthful `have`, and convergence has the base the kernel requires. One commit walk
23078
- * (no change decoding, no pack, no network) decides it.
23079
- *
23080
- * If it is not in this replica's lineage, no base exists to establish and the round is refused
23081
- * (#noCommonBase) before it leases, fetches or plans anything.
23082
- *
23083
- * A kernel without the commit walk cannot be asked, so it keeps the previous behaviour.
23054
+ * Establish a cheap base when the provider's current tip is in our local chain.
23055
+ * A negative answer means the base is unknown: both sides may have advanced from
23056
+ * an earlier shared commit. Acquire the candidate and let the kernel discover
23057
+ * and judge that history. A tracking bookmark is not an admission prerequisite.
23084
23058
  */
23085
23059
  #establishBase(upstreamHead) {
23086
- if (!this.#noCommonBase() || !this.#kernel.historySummary) return true;
23060
+ if (!this.#missingTrackedBase() || !this.#kernel.historySummary) return true;
23087
23061
  const summary = this.#kernel.historySummary(this.#mount, this.#requestId, upstreamHead, this.#localHead);
23088
23062
  if (!summary.reachedBase) return false;
23089
23063
  this.#previousHead = upstreamHead;
@@ -23098,26 +23072,9 @@ var init_workspace_sync = __esm({
23098
23072
  get establishedBase() {
23099
23073
  return this.#establishedBase;
23100
23074
  }
23101
- #noCommonBase() {
23075
+ #missingTrackedBase() {
23102
23076
  return this.#previousHead === void 0 && this.#localHead !== void 0 && this.#replaceLocalHead === void 0;
23103
23077
  }
23104
- #noCommonBaseResult() {
23105
- return this.#finish(create55(SyncWorkspaceResponseSchema, {
23106
- workspace: this.#mount.workspace,
23107
- ...this.#localHead === void 0 ? {} : { currentHead: this.#localHead },
23108
- stillAhead: true,
23109
- ...this.#offerReceipt === void 0 ? {} : { offerReceipt: this.#offerReceipt },
23110
- pushError: create55(RuntimeTransportFailureSchema, {
23111
- endpoint: this.#offerEndpoint(),
23112
- status: 409,
23113
- refused: true,
23114
- message: NO_COMMON_BASE
23115
- }),
23116
- timings: create55(SyncPhaseTimingsSchema, {
23117
- convergeMillis: elapsedMillis(this.#clock, this.#started)
23118
- })
23119
- }));
23120
- }
23121
23078
  #holdsLocalWork() {
23122
23079
  return this.#command.admit && !!this.#localHead && this.#localHead !== this.#previousHead;
23123
23080
  }
@@ -23269,7 +23226,6 @@ var init_workspace_sync = __esm({
23269
23226
  if (!this.#desiredHead) return this.#transportFailure("resident peer returned no admitted frontier", false);
23270
23227
  this.#candidateDurable = admission.sealedMain === this.#desiredHead;
23271
23228
  if (state.phase === WorkspaceSyncPhase.Probe && this.#desiredHead !== this.#localHead) {
23272
- if (!this.#establishBase(this.#desiredHead)) return this.#noCommonBaseResult();
23273
23229
  if (this.#alreadyJudged(this.#desiredHead)) {
23274
23230
  return this.#finish(create55(SyncWorkspaceResponseSchema, {
23275
23231
  workspace: this.#mount.workspace,
@@ -23281,6 +23237,22 @@ var init_workspace_sync = __esm({
23281
23237
  offerReceipt: this.#offerReceipt
23282
23238
  }));
23283
23239
  }
23240
+ if (!this.#establishBase(this.#desiredHead)) {
23241
+ this.#offerAfterConverge = this.#command.admit;
23242
+ this.#rebaseFrom = void 0;
23243
+ return this.#leaseEffect();
23244
+ }
23245
+ if (this.#establishedBase && !this.#candidateDurable && this.#kernel.resolveRef(this.#mount, this.#requestId, trackedMain) === void 0) {
23246
+ return this.#finish(create55(SyncWorkspaceResponseSchema, {
23247
+ workspace: this.#mount.workspace,
23248
+ currentHead: this.#localHead,
23249
+ previousHead: this.#previousHead,
23250
+ stillAhead: true,
23251
+ directOfferDeferred: true,
23252
+ reconnectRequired: false,
23253
+ offerReceipt: this.#offerReceipt
23254
+ }));
23255
+ }
23284
23256
  if (this.#probeOnly) {
23285
23257
  this.#needsReconciliation = true;
23286
23258
  return this.#finish(create55(SyncWorkspaceResponseSchema, {
@@ -23326,7 +23298,7 @@ var init_workspace_sync = __esm({
23326
23298
  return this.#converge(this.#desiredHead, admission.resultPack.byteLength, 0);
23327
23299
  }
23328
23300
  if (this.#desiredHead === this.#previousHead) return this.#converge(this.#desiredHead, 0, 0);
23329
- if (!this.#establishBase(this.#desiredHead)) return this.#noCommonBaseResult();
23301
+ this.#establishBase(this.#desiredHead);
23330
23302
  if (admission.recoveryRequired !== false) return this.#leaseEffect();
23331
23303
  return this.#transportFailure("resident peer supplied neither the missing delta nor a history gap", false);
23332
23304
  }
@@ -23549,7 +23521,7 @@ var init_workspace_sync = __esm({
23549
23521
  }
23550
23522
  }
23551
23523
  #converge(candidateHead, receivedBytes, prefetchMillis) {
23552
- if (!this.#establishBase(candidateHead)) return this.#noCommonBaseResult();
23524
+ this.#establishBase(candidateHead);
23553
23525
  this.#beforeConverge?.(candidateHead, this.#previousHead);
23554
23526
  const convergeStarted = this.#clock.monotonicNanoseconds();
23555
23527
  let judged;
@@ -26083,13 +26055,21 @@ var init_correspondence_desk = __esm({
26083
26055
  }
26084
26056
  #observeSyncResult(requestId, workId2, result) {
26085
26057
  const timings = result.timings;
26058
+ const receipt = result.offerReceipt?.outcome;
26059
+ const admission = receipt?.case === "admission" ? receipt.value : void 0;
26086
26060
  this.#events.instant("peer.follow.sync-result", {
26087
26061
  request: create60(RuntimeRequestSchema, { protocolVersion: 2, requestId }),
26088
26062
  workspace: result.workspace
26089
26063
  }, {
26090
26064
  "sync.workId": workId2,
26091
26065
  ...result.currentHead ? { "sync.head": result.currentHead } : {},
26066
+ ...result.previousHead ? { "sync.previousHead": result.previousHead } : {},
26067
+ ...admission?.main ? { "sync.providerHead": admission.main } : {},
26068
+ ...admission?.sealedMain ? { "sync.sealedHead": admission.sealedMain } : {},
26092
26069
  "sync.stillAhead": result.stillAhead,
26070
+ "sync.reconnectRequired": result.reconnectRequired,
26071
+ "sync.refused": result.refused,
26072
+ "sync.deferred": result.deferred,
26093
26073
  "sync.directOfferDeferred": result.directOfferDeferred,
26094
26074
  "sync.offline": result.offline,
26095
26075
  ...timings ? {
@@ -32391,8 +32371,19 @@ async function ensureApplicationWorkspace(application, opts = {}) {
32391
32371
  }
32392
32372
  const statusUrl = `${cloud}/v2/workspaces/${encodeURIComponent(application)}`;
32393
32373
  const current = await fetch(statusUrl).catch(() => null);
32394
- if (current?.ok) {
32395
- const status2 = await current.json().catch(() => null);
32374
+ const status2 = current?.ok ? await current.json().catch(() => null) : null;
32375
+ let unborn = false;
32376
+ if (current?.ok && !status2?.lineage && !status2?.durableHead && !status2?.sealedHead) {
32377
+ const domains2 = await fetch(`${statusUrl}/domains`);
32378
+ if (domains2.status === 409) {
32379
+ const body2 = await domains2.json().catch(() => null);
32380
+ unborn = typeof body2?.error === "string" && body2.error.includes("unborn");
32381
+ }
32382
+ if (!unborn && !domains2.ok) {
32383
+ throw new Error(`could not establish whether application '${application}' has custody (${domains2.status})`);
32384
+ }
32385
+ }
32386
+ if (current?.ok && !unborn) {
32396
32387
  const principal = String(status2?.lineage?.principal ?? "");
32397
32388
  const actualParent = String(status2?.lineage?.parent ?? "");
32398
32389
  const expectedParent = requestedParent === "root" ? "" : requestedParent;
@@ -32428,7 +32419,7 @@ async function ensureApplicationWorkspace(application, opts = {}) {
32428
32419
  ...principal !== "" && session !== "" && sameIdentity(principal, session) ? { deployPrincipal: principal } : {}
32429
32420
  };
32430
32421
  }
32431
- if (current !== null && current.status !== 404 && current.status !== 409) {
32422
+ if (current !== null && !unborn && current.status !== 404 && current.status !== 409) {
32432
32423
  throw new Error(`could not inspect deploy target '${application}' (${current.status}); refusing to guess that it is unborn`);
32433
32424
  }
32434
32425
  if (requestedParent !== void 0) {
@@ -34308,6 +34299,7 @@ var init_commands = __esm({
34308
34299
  "test",
34309
34300
  "doctor",
34310
34301
  "cloud",
34302
+ "console",
34311
34303
  "status",
34312
34304
  "model",
34313
34305
  "platform",
@@ -34358,6 +34350,19 @@ var init_help = __esm({
34358
34350
  "use strict";
34359
34351
  init_commands();
34360
34352
  HELP = {
34353
+ console: {
34354
+ usage: "githolon console <login|logout|workspaces|universe|rollouts>",
34355
+ what: "Use a downloaded console API credential. The browser and CLI use the same console API.\nCredentials are stored locally with owner-only permissions; tokens are never printed.",
34356
+ flags: [
34357
+ ["login --file <credential.json>", "verify and save a downloaded credential"],
34358
+ ["logout", "remove the local credential; revoke other copies in the console"],
34359
+ ["workspaces | universe", "read registered workspaces or their live subtree as JSON"],
34360
+ ["rollouts [show <id>]", "list runs or inspect one"],
34361
+ ["rollouts start --file <request.json>", "submit {payload:{kind:law,source:workspace},only:[workspace]} (JSON strings quoted)"],
34362
+ ["rollouts resume <id>", "retry an existing law rollout"]
34363
+ ],
34364
+ examples: ["githolon console login --file nomos-console-example.json", "githolon console workspaces"]
34365
+ },
34361
34366
  compile: {
34362
34367
  usage: "githolon compile [config] [--require-usdcat]",
34363
34368
  what: "Compile typed authoring input into canonical OpenUSD. nomos.project.ts emits the readable law\nclosure, its .law.usdz transport archive, and generated clients; nomos.application.ts emits the application\ncomposition stage. TypeScript is authoring input only: the kernel admits and custodies USD.",
@@ -34689,6 +34694,84 @@ var init_help = __esm({
34689
34694
  }
34690
34695
  });
34691
34696
 
34697
+ // src/console.ts
34698
+ var console_exports = {};
34699
+ __export(console_exports, {
34700
+ consoleCommand: () => consoleCommand,
34701
+ consoleCredential: () => consoleCredential,
34702
+ consoleRequest: () => consoleRequest
34703
+ });
34704
+ import { URL as URL2 } from "node:url";
34705
+ import { chmodSync as chmodSync3, mkdirSync as mkdirSync10, readFileSync as readFileSync11, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync11 } from "node:fs";
34706
+ import { join as join15 } from "node:path";
34707
+ import { randomUUID as randomUUID4 } from "node:crypto";
34708
+ function consoleCredential(value) {
34709
+ if (!value || typeof value !== "object") throw new Error("Invalid console credential file");
34710
+ const v = value;
34711
+ if (v.format !== "nomos-console-credential-v1" || typeof v.endpoint !== "string" || typeof v.tenant !== "string" || typeof v.token !== "string") throw new Error("Invalid console credential file");
34712
+ const endpoint = new URL2(v.endpoint);
34713
+ if (endpoint.protocol !== "https:" || endpoint.username || endpoint.password || endpoint.pathname !== "/" || endpoint.search || endpoint.hash) throw new Error("Console endpoint must be an HTTPS origin");
34714
+ const token = /^nomos_api\.([a-z][a-z0-9-]{1,62})\.[a-f0-9]{32}\.[A-Za-z0-9_-]{43}$/.exec(v.token);
34715
+ if (!token || token[1] !== v.tenant) throw new Error("Credential does not match its workspace account");
34716
+ return { format: v.format, endpoint: endpoint.origin, tenant: v.tenant, token: v.token };
34717
+ }
34718
+ async function consoleRequest(profile, path4, method = "GET", body, fetcher = fetch) {
34719
+ const response = await fetcher(profile.endpoint + path4, {
34720
+ method,
34721
+ redirect: "error",
34722
+ signal: AbortSignal.timeout(12e4),
34723
+ headers: { authorization: `Bearer ${profile.token}`, "content-type": "application/json" },
34724
+ ...body !== void 0 ? { body: JSON.stringify(body) } : {}
34725
+ });
34726
+ const result = await response.json();
34727
+ if (!response.ok) throw new Error(`Console ${response.status}: ${result.error ?? "request refused"}`);
34728
+ return result;
34729
+ }
34730
+ async function consoleCommand(args) {
34731
+ const file = join15(configDir(), "console.json");
34732
+ if (args[0] === "login" && args.length === 3 && args[1] === "--file") {
34733
+ const profile2 = consoleCredential(JSON.parse(readFileSync11(args[2], "utf8")));
34734
+ await consoleRequest(profile2, `/v1/tenants/${profile2.tenant}/workspaces`);
34735
+ mkdirSync10(configDir(), { recursive: true });
34736
+ const temporary = `${file}.${randomUUID4()}.tmp`;
34737
+ try {
34738
+ writeFileSync11(temporary, JSON.stringify(profile2) + "\n", { mode: 384, flag: "wx" });
34739
+ renameSync4(temporary, file);
34740
+ chmodSync3(file, 384);
34741
+ } finally {
34742
+ rmSync5(temporary, { force: true });
34743
+ }
34744
+ console.log(`Console credential saved for ${profile2.tenant} at ${profile2.endpoint}`);
34745
+ return 0;
34746
+ }
34747
+ if (args[0] === "logout" && args.length === 1) {
34748
+ rmSync5(file, { force: true });
34749
+ console.log("Local console credential removed. Revoke the key in the console to disable other copies.");
34750
+ return 0;
34751
+ }
34752
+ const profile = consoleCredential(JSON.parse(readFileSync11(file, "utf8")));
34753
+ const root = `/v1/tenants/${encodeURIComponent(profile.tenant)}`;
34754
+ let result;
34755
+ if (args[0] === "workspaces" && args.length === 1) result = await consoleRequest(profile, `${root}/workspaces`);
34756
+ else if (args[0] === "universe" && args.length === 1) result = await consoleRequest(profile, "/v1/universe");
34757
+ else if (args[0] === "rollouts" && args.length === 1) result = await consoleRequest(profile, `${root}/rollouts`);
34758
+ else if (args[0] === "rollouts" && args[1] === "show" && args.length === 3) result = await consoleRequest(profile, `${root}/rollouts/${encodeURIComponent(args[2])}`);
34759
+ else if (args[0] === "rollouts" && args[1] === "resume" && args.length === 3) result = await consoleRequest(profile, `${root}/rollouts/${encodeURIComponent(args[2])}/resume`, "POST", {});
34760
+ else if (args[0] === "rollouts" && args[1] === "start" && args[2] === "--file" && args.length === 4) {
34761
+ const input = JSON.parse(readFileSync11(args[3], "utf8"));
34762
+ if (input?.payload?.kind !== "law") throw new Error("Console CLI supports law rollouts only");
34763
+ result = await consoleRequest(profile, `${root}/rollouts`, "POST", input);
34764
+ } else throw new Error("See githolon console --help for supported commands");
34765
+ console.log(JSON.stringify(result, null, 2));
34766
+ return 0;
34767
+ }
34768
+ var init_console = __esm({
34769
+ "src/console.ts"() {
34770
+ "use strict";
34771
+ init_cloud();
34772
+ }
34773
+ });
34774
+
34692
34775
  // src/mcp.ts
34693
34776
  var mcp_exports = {};
34694
34777
  __export(mcp_exports, {
@@ -35619,7 +35702,7 @@ var init_law_command_projection = __esm({
35619
35702
  });
35620
35703
 
35621
35704
  // src/law_encoder.ts
35622
- import { readFileSync as readFileSync11 } from "node:fs";
35705
+ import { readFileSync as readFileSync12 } from "node:fs";
35623
35706
  async function loadInstalledLaw(input) {
35624
35707
  const file = discoverLawUsdz(input.cwd ?? process.cwd(), input.file);
35625
35708
  const inspected = await inspectLawArchive(input.cloud, file);
@@ -35631,7 +35714,7 @@ async function loadInstalledLaw(input) {
35631
35714
  );
35632
35715
  }
35633
35716
  const projection = parseLawCommandProjection(
35634
- readLawClosureAsset(new Uint8Array(readFileSync11(file)), COMMAND_PROJECTION)
35717
+ readLawClosureAsset(new Uint8Array(readFileSync12(file)), COMMAND_PROJECTION)
35635
35718
  );
35636
35719
  return { identity: inspected.identity, servedDomains: served, projection, file };
35637
35720
  }
@@ -36117,8 +36200,8 @@ __export(platform_exports, {
36117
36200
  storeSeatDevice: () => storeSeatDevice
36118
36201
  });
36119
36202
  import { createHash as createHash6 } from "node:crypto";
36120
- import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "node:fs";
36121
- import { join as join16 } from "node:path";
36203
+ import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync12 } from "node:fs";
36204
+ import { join as join17 } from "node:path";
36122
36205
  function refuse(message) {
36123
36206
  throw new PlatformRefusal(message);
36124
36207
  }
@@ -36192,7 +36275,7 @@ async function readModelAuthority(cloud, platform, seatedAt) {
36192
36275
  function loadSeatDevice(workspace) {
36193
36276
  const path4 = seatDevicePath(workspace);
36194
36277
  if (!existsSync14(path4)) return void 0;
36195
- const stored = JSON.parse(readFileSync12(path4, "utf8"));
36278
+ const stored = JSON.parse(readFileSync13(path4, "utf8"));
36196
36279
  const publicKey = stored.publicKey ?? (stored.publicKeyHex === void 0 ? void 0 : Buffer.from(stored.publicKeyHex, "hex").toString("base64"));
36197
36280
  if (typeof stored.secret !== "string" || publicKey === void 0 || typeof stored.keyHash !== "string") {
36198
36281
  refuse(`${path4} is not a stored device key {secret, publicKey, keyHash}`);
@@ -36201,8 +36284,8 @@ function loadSeatDevice(workspace) {
36201
36284
  }
36202
36285
  function storeSeatDevice(workspace, device) {
36203
36286
  const path4 = seatDevicePath(workspace);
36204
- mkdirSync10(join16(path4, ".."), { recursive: true });
36205
- writeFileSync11(path4, JSON.stringify(device, null, 2) + "\n", { mode: 384 });
36287
+ mkdirSync11(join17(path4, ".."), { recursive: true });
36288
+ writeFileSync12(path4, JSON.stringify(device, null, 2) + "\n", { mode: 384 });
36206
36289
  }
36207
36290
  async function mintSeatDevice(cloud) {
36208
36291
  const generated = await generateDeviceKey(cloud);
@@ -36425,7 +36508,7 @@ async function platformAuthor(workspace, directiveId, opts) {
36425
36508
  }
36426
36509
  }
36427
36510
  function readPayload(opts) {
36428
- const raw = opts.payloadFile !== void 0 ? readFileSync12(opts.payloadFile, "utf8") : opts.payload;
36511
+ const raw = opts.payloadFile !== void 0 ? readFileSync13(opts.payloadFile, "utf8") : opts.payload;
36429
36512
  if (raw === void 0 || raw.trim() === "") refuse("author needs --payload <json> or --payload-file <file>");
36430
36513
  let parsed;
36431
36514
  try {
@@ -36637,7 +36720,7 @@ var init_platform = __esm({
36637
36720
  PlatformRefusal = class extends Error {
36638
36721
  };
36639
36722
  ws = (name) => encodeURIComponent(name);
36640
- seatDevicePath = (workspace) => join16(configDir(), `seat-device-${workspace}.json`);
36723
+ seatDevicePath = (workspace) => join17(configDir(), `seat-device-${workspace}.json`);
36641
36724
  SEAT_CONVERGENCE_MILLIS = 18e4;
36642
36725
  }
36643
36726
  });
@@ -36703,8 +36786,8 @@ var init_dlq = __esm({
36703
36786
 
36704
36787
  // src/custodian.ts
36705
36788
  import { createHash as createHash7, createPrivateKey as createPrivateKey2, createPublicKey as createPublicKey2 } from "node:crypto";
36706
- import { existsSync as existsSync15, readFileSync as readFileSync13 } from "node:fs";
36707
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join17, resolve as resolve6 } from "node:path";
36789
+ import { existsSync as existsSync15, readFileSync as readFileSync14 } from "node:fs";
36790
+ import { dirname as dirname5, isAbsolute as isAbsolute3, join as join18, resolve as resolve6 } from "node:path";
36708
36791
  import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL3 } from "node:url";
36709
36792
  import { create as create80 } from "@bufbuild/protobuf";
36710
36793
  import { AnySchema as AnySchema3 } from "@bufbuild/protobuf/wkt";
@@ -36752,7 +36835,7 @@ async function resolveCustodianCredential(reference) {
36752
36835
  }
36753
36836
  if (scheme === "file") {
36754
36837
  if (rest === "" || !existsSync15(rest)) throw new Error(`--custodian-key file:<path> \u2014 no file at '${rest}'`);
36755
- return fromSeed(custodianSeedFromText(readFileSync13(rest, "utf8"), rest), `file:${rest}`);
36838
+ return fromSeed(custodianSeedFromText(readFileSync14(rest, "utf8"), rest), `file:${rest}`);
36756
36839
  }
36757
36840
  if (scheme === "env") {
36758
36841
  const value = process.env[rest];
@@ -36779,7 +36862,7 @@ async function resolveCustodianCredential(reference) {
36779
36862
  function readCustodianChain(file) {
36780
36863
  if (file === void 0) return [];
36781
36864
  if (!existsSync15(file)) throw new Error(`--chain <file> \u2014 no file at '${file}'`);
36782
- const parsed = JSON.parse(readFileSync13(file, "utf8"));
36865
+ const parsed = JSON.parse(readFileSync14(file, "utf8"));
36783
36866
  const links = Array.isArray(parsed) ? parsed : typeof parsed === "object" && parsed !== null && Array.isArray(parsed.certChain) ? parsed.certChain : void 0;
36784
36867
  if (links === void 0) {
36785
36868
  throw new Error(
@@ -36829,7 +36912,7 @@ function scarFromVerdict(verdict) {
36829
36912
  }
36830
36913
  function frameworkReceptionPath(here = moduleDirectory()) {
36831
36914
  const candidates = [
36832
- join17(here, "framework", "nomos.reception.mjs"),
36915
+ join18(here, "framework", "nomos.reception.mjs"),
36833
36916
  resolve6(here, "../../cloud/cloudflare-shell/domains/build/nomos/nomos.reception.mjs")
36834
36917
  ];
36835
36918
  const found = candidates.find((candidate) => existsSync15(candidate));
@@ -36907,7 +36990,7 @@ async function encodeDirectiveCall(receptionPath, domain, directiveId, workspace
36907
36990
  return captured;
36908
36991
  }
36909
36992
  function readPayload2(opts) {
36910
- const text2 = opts.payloadFile !== void 0 ? readFileSync13(opts.payloadFile, "utf8") : opts.payload;
36993
+ const text2 = opts.payloadFile !== void 0 ? readFileSync14(opts.payloadFile, "utf8") : opts.payload;
36911
36994
  if (text2 === void 0) throw new Error("pass the directive's payload with --payload <json> or --payload-file <file>");
36912
36995
  const parsed = JSON.parse(text2);
36913
36996
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
@@ -37247,8 +37330,8 @@ Options
37247
37330
  });
37248
37331
 
37249
37332
  // src/cli.ts
37250
- import { existsSync as existsSync16, readFileSync as readFileSync14 } from "node:fs";
37251
- import { dirname as dirname6, join as join18, resolve as resolve7 } from "node:path";
37333
+ import { existsSync as existsSync16, readFileSync as readFileSync15 } from "node:fs";
37334
+ import { dirname as dirname6, join as join19, resolve as resolve7 } from "node:path";
37252
37335
  import { pathToFileURL as pathToFileURL4, fileURLToPath as fileURLToPath4 } from "node:url";
37253
37336
 
37254
37337
  // src/generate.ts
@@ -37949,6 +38032,9 @@ async function main(argv) {
37949
38032
  process.stdout.write(USAGE2);
37950
38033
  return 0;
37951
38034
  }
38035
+ if (argv[0] === "console") {
38036
+ return (await Promise.resolve().then(() => (init_console(), console_exports))).consoleCommand(argv.slice(1));
38037
+ }
37952
38038
  if (argv[0] === "compile") {
37953
38039
  return runCompileCommand(argv.slice(1));
37954
38040
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.110.1",
3
+ "version": "0.111.0",
4
4
  "type": "module",
5
5
  "description": "githolon — the Nomos developer CLI: Rails-style generators for @githolon/dsl domains + the package compiler. Kernel-independent.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -30,7 +30,7 @@
30
30
  "dependencies": {
31
31
  "@bjorn3/browser_wasi_shim": "0.4.2",
32
32
  "@bufbuild/protobuf": "^2.13.0",
33
- "@githolon/dsl": "^0.110.1",
33
+ "@githolon/dsl": "^0.111.0",
34
34
  "fast-xml-parser": "5.10.1",
35
35
  "isomorphic-git": "^1.38.4",
36
36
  "tsx": "^4.19.2",