githolon 0.102.0 → 0.102.2

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/dist/cli.mjs CHANGED
@@ -372,7 +372,7 @@ function makeGitFs(preopen, mount, { File: File4, Directory: Directory4 }) {
372
372
  const rel = p.slice(mount.length + 1).replace(/\/+$/, "");
373
373
  return rel === "" ? [] : rel.split("/");
374
374
  }
375
- function resolve7(ps) {
375
+ function resolve8(ps) {
376
376
  let cur = root;
377
377
  for (const part of ps) {
378
378
  if (!isDir(cur)) return null;
@@ -382,11 +382,11 @@ function makeGitFs(preopen, mount, { File: File4, Directory: Directory4 }) {
382
382
  }
383
383
  return cur;
384
384
  }
385
- const parent = (ps) => resolve7(ps.slice(0, -1));
385
+ const parent = (ps) => resolve8(ps.slice(0, -1));
386
386
  const leaf = (ps) => ps[ps.length - 1];
387
387
  const promises = {
388
388
  async readFile(p, opts) {
389
- const n = resolve7(parts(p));
389
+ const n = resolve8(parts(p));
390
390
  if (n === null) throw fsErr("ENOENT", p);
391
391
  if (isDir(n)) throw fsErr("EISDIR", p);
392
392
  const data = n.data ?? new Uint8Array(0);
@@ -405,7 +405,7 @@ function makeGitFs(preopen, mount, { File: File4, Directory: Directory4 }) {
405
405
  if (!isDir(par) || !par.contents.delete(leaf(ps))) throw fsErr("ENOENT", p);
406
406
  },
407
407
  async readdir(p) {
408
- const n = resolve7(parts(p));
408
+ const n = resolve8(parts(p));
409
409
  if (n === null) throw fsErr("ENOENT", p);
410
410
  if (!isDir(n)) throw fsErr("ENOTDIR", p);
411
411
  return [...n.contents.keys()];
@@ -425,7 +425,7 @@ function makeGitFs(preopen, mount, { File: File4, Directory: Directory4 }) {
425
425
  return promises.lstat(p);
426
426
  },
427
427
  async lstat(p) {
428
- const n = resolve7(parts(p));
428
+ const n = resolve8(parts(p));
429
429
  if (n === null) throw fsErr("ENOENT", p);
430
430
  const dir = isDir(n);
431
431
  return {
@@ -621,7 +621,7 @@ function wasmModuleFor(base, fetchImpl) {
621
621
  function parseSnapshot(bytes) {
622
622
  try {
623
623
  const o = JSON.parse(dec2.decode(bytes));
624
- if (o && o.v === 2 && typeof o.tree === "string") return { treeBytes: snapUnb64(o.tree), ckpt: o.ckpt ?? null, frontier: o.frontier ?? null, syncedBase: o.syncedBase ?? null };
624
+ if (o && o.v === 2 && typeof o.tree === "string") return { treeBytes: nmsInternalSnapshotFromBase64(o.tree), ckpt: o.ckpt ?? null, frontier: o.frontier ?? null, syncedBase: o.syncedBase ?? null };
625
625
  } catch {
626
626
  }
627
627
  return { treeBytes: bytes, ckpt: null, frontier: null, syncedBase: null };
@@ -630,7 +630,7 @@ function buildSnapshot(treeBytes, ckpt, syncedBase) {
630
630
  if ((!ckpt || !ckpt.blob && !ckpt.frontier) && !syncedBase) return treeBytes;
631
631
  return enc2.encode(JSON.stringify({
632
632
  v: 2,
633
- tree: snapB64(treeBytes),
633
+ tree: nmsInternalSnapshotToBase64(treeBytes),
634
634
  ckpt: ckpt && ckpt.blob ? ckpt.blob : null,
635
635
  frontier: ckpt ? ckpt.frontier ?? null : null,
636
636
  cursor: ckpt ? ckpt.cursor ?? null : null,
@@ -870,7 +870,7 @@ function createWasmEnginePlane({ span } = {}) {
870
870
  }
871
871
  const buf = new Uint8Array(await r.arrayBuffer());
872
872
  if (!buf.length) return { applied: false };
873
- view.applyPack(snapB64(buf));
873
+ view.applyPack(nmsInternalSnapshotToBase64(buf));
874
874
  return { applied: true };
875
875
  } finally {
876
876
  if (end) end();
@@ -920,7 +920,7 @@ function createWasmEnginePlane({ span } = {}) {
920
920
  function createWasmKernelProvider({ span } = {}) {
921
921
  return createWasmEnginePlane({ span }).providerFor();
922
922
  }
923
- var enc2, dec2, snapB64, snapUnb64, unpack, wasmModuleCache;
923
+ var enc2, dec2, nmsInternalSnapshotToBase64, nmsInternalSnapshotFromBase64, unpack, wasmModuleCache;
924
924
  var init_kernel_provider_wasm = __esm({
925
925
  "../cloud/web-client/src/kernel_provider_wasm.ts"() {
926
926
  "use strict";
@@ -930,12 +930,20 @@ var init_kernel_provider_wasm = __esm({
930
930
  init_pack_auth_contract();
931
931
  enc2 = new TextEncoder();
932
932
  dec2 = new TextDecoder();
933
- snapB64 = (bytes) => {
933
+ nmsInternalSnapshotToBase64 = (bytes) => {
934
+ if (typeof Buffer !== "undefined") {
935
+ return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("base64");
936
+ }
934
937
  let s = "";
935
- for (let i = 0; i < bytes.length; i += 32768) s += String.fromCharCode.apply(null, bytes.subarray(i, i + 32768));
938
+ for (let i = 0; i < bytes.length; i += 32768) {
939
+ s += String.fromCharCode.apply(null, bytes.subarray(i, i + 32768));
940
+ }
936
941
  return btoa(s);
937
942
  };
938
- snapUnb64 = (s) => Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
943
+ nmsInternalSnapshotFromBase64 = (s) => {
944
+ if (typeof Buffer !== "undefined") return Buffer.from(s, "base64");
945
+ return Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
946
+ };
939
947
  unpack = (p) => {
940
948
  const v = typeof p === "bigint" ? p : BigInt(p);
941
949
  return { ptr: Number(v >> 32n), len: Number(v & 0xffffffffn) };
@@ -7430,7 +7438,7 @@ var init_src = __esm({
7430
7438
  };
7431
7439
  ownedRecoveryScope = (principal2) => `${ownedKeyObject(principal2)}#${OWNED_RECOVERY_RELATION}`;
7432
7440
  ownedRecoveryPolicyId = (principal2) => `nomos-owned-recovery-policy:${ownedKeyObject(principal2).slice("nomos-owned-principal:".length)}`;
7433
- sleep = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms));
7441
+ sleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
7434
7442
  OFFER_TIMEOUT_MS = 2e4;
7435
7443
  DIRECT_OFFER_PENDING_MS = 45e3;
7436
7444
  OID40_RE = /^[0-9a-f]{40}$/i;
@@ -7494,7 +7502,7 @@ function makeGitFs2(preopen, mount, { File: File4, Directory: Directory4 }) {
7494
7502
  const rel = p.slice(mount.length + 1).replace(/\/+$/, "");
7495
7503
  return rel === "" ? [] : rel.split("/");
7496
7504
  }
7497
- function resolve7(ps) {
7505
+ function resolve8(ps) {
7498
7506
  let cur = root;
7499
7507
  for (const part of ps) {
7500
7508
  if (!isDir(cur)) return null;
@@ -7504,11 +7512,11 @@ function makeGitFs2(preopen, mount, { File: File4, Directory: Directory4 }) {
7504
7512
  }
7505
7513
  return cur;
7506
7514
  }
7507
- const parent = (ps) => resolve7(ps.slice(0, -1));
7515
+ const parent = (ps) => resolve8(ps.slice(0, -1));
7508
7516
  const leaf = (ps) => ps[ps.length - 1];
7509
7517
  const promises = {
7510
7518
  async readFile(p, opts) {
7511
- const n = resolve7(parts(p));
7519
+ const n = resolve8(parts(p));
7512
7520
  if (n === null) throw fsErr2("ENOENT", p);
7513
7521
  if (isDir(n)) throw fsErr2("EISDIR", p);
7514
7522
  const data = n.data ?? new Uint8Array(0);
@@ -7527,7 +7535,7 @@ function makeGitFs2(preopen, mount, { File: File4, Directory: Directory4 }) {
7527
7535
  if (!isDir(par) || !par.contents.delete(leaf(ps))) throw fsErr2("ENOENT", p);
7528
7536
  },
7529
7537
  async readdir(p) {
7530
- const n = resolve7(parts(p));
7538
+ const n = resolve8(parts(p));
7531
7539
  if (n === null) throw fsErr2("ENOENT", p);
7532
7540
  if (!isDir(n)) throw fsErr2("ENOTDIR", p);
7533
7541
  return [...n.contents.keys()];
@@ -7547,7 +7555,7 @@ function makeGitFs2(preopen, mount, { File: File4, Directory: Directory4 }) {
7547
7555
  return promises.lstat(p);
7548
7556
  },
7549
7557
  async lstat(p) {
7550
- const n = resolve7(parts(p));
7558
+ const n = resolve8(parts(p));
7551
7559
  if (n === null) throw fsErr2("ENOENT", p);
7552
7560
  const dir = isDir(n);
7553
7561
  return {
@@ -7739,11 +7747,16 @@ async function pushPack(remote, headers = {}, { updates = [], pack = null } = {}
7739
7747
  });
7740
7748
  cmds.push(FLUSH);
7741
7749
  const body = concatBytes([...cmds, pack && pack.length ? pack : EMPTY_PACK]);
7742
- const r = await fetch(`${remote}/git-receive-pack`, {
7743
- method: "POST",
7744
- headers: { "content-type": "application/x-git-receive-pack-request", ...headers },
7745
- body
7746
- });
7750
+ let r;
7751
+ try {
7752
+ r = await fetch(`${remote}/git-receive-pack`, {
7753
+ method: "POST",
7754
+ headers: { "content-type": "application/x-git-receive-pack-request", ...headers },
7755
+ body
7756
+ });
7757
+ } catch (error) {
7758
+ throw new Error(`receive-pack transport failed (${body.byteLength} bytes): ${String(error)}`, { cause: error });
7759
+ }
7747
7760
  const txt = dec5.decode(new Uint8Array(await r.arrayBuffer()));
7748
7761
  const unpacked = /unpack ok/.test(txt);
7749
7762
  const everyRefOk = updates.every((u) => new RegExp(`ok ${u.ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`).test(txt));
@@ -9301,7 +9314,12 @@ async function custodyFetch(eng, ws, ledger, { remoteRef = "refs/heads/main", lo
9301
9314
  async function custodyPush(eng, ws, ledger, { localRef = null, remoteRef, del = false, pointer = false, newOid = null }) {
9302
9315
  const headers = ledger.headers || {};
9303
9316
  const remoteRefFull = fullRef(remoteRef);
9304
- const remote = await lsRefs(ledger.remote, headers, { service: "git-receive-pack", prefix: remoteRefFull });
9317
+ let remote;
9318
+ try {
9319
+ remote = await lsRefs(ledger.remote, headers, { service: "git-receive-pack", prefix: remoteRefFull });
9320
+ } catch (error) {
9321
+ throw new Error(`custody receive-pack advertisement failed for ${remoteRefFull}: ${String(error)}`, { cause: error });
9322
+ }
9305
9323
  const oldOid = remote[remoteRefFull] || ZERO_OID;
9306
9324
  if (del) {
9307
9325
  if (oldOid === ZERO_OID) return;
@@ -9315,14 +9333,21 @@ async function custodyPush(eng, ws, ledger, { localRef = null, remoteRef, del =
9315
9333
  pack = oldOid !== ZERO_OID ? packDelta(eng, ws, oldOid, tgt) : null;
9316
9334
  if (!pack) pack = packDelta(eng, ws, "", tgt);
9317
9335
  }
9318
- return pushVia(ledger, () => pushPack(ledger.remote, headers, { updates: [{ ref: remoteRefFull, oldOid, newOid: tgt }], pack }));
9336
+ const packBytes = pack?.byteLength ?? 0;
9337
+ try {
9338
+ return await pushVia(ledger, () => pushPack(ledger.remote, headers, { updates: [{ ref: remoteRefFull, oldOid, newOid: tgt }], pack }));
9339
+ } catch (error) {
9340
+ throw new Error(`custody receive-pack push failed for ${remoteRefFull} (${packBytes} pack bytes): ${String(error)}`, { cause: error });
9341
+ }
9319
9342
  }
9320
9343
  async function commitAndPush(eng, ws, ledger) {
9321
9344
  try {
9322
9345
  await custodyPush(eng, ws, ledger, { remoteRef: "refs/heads/main" });
9323
9346
  } catch (e) {
9324
9347
  unmount(eng, ws);
9325
- throw new Error(`ledger push failed \u2014 write NOT durable, rolled back to ledger: ${e}`);
9348
+ const cause = e instanceof Error ? e.cause : void 0;
9349
+ const detail = cause === void 0 ? String(e) : `${e}; cause: ${String(cause)}`;
9350
+ throw new Error(`ledger push failed \u2014 write NOT durable, rolled back to ledger: ${detail}`, { cause: e });
9326
9351
  }
9327
9352
  }
9328
9353
  async function pushShape(eng, ws, ledger) {
@@ -11216,7 +11241,7 @@ async function waitForWorkspaceMain(cloud, workspace, timeoutMs = 3e4) {
11216
11241
  while (Date.now() < deadline) {
11217
11242
  const head = await workspaceMainHead(cloud, workspace);
11218
11243
  if (head !== void 0) return head;
11219
- await new Promise((resolve7) => setTimeout(resolve7, 250));
11244
+ await new Promise((resolve8) => setTimeout(resolve8, 250));
11220
11245
  }
11221
11246
  return void 0;
11222
11247
  }
@@ -11310,7 +11335,7 @@ async function ensureSovereignHome(opts = {}) {
11310
11335
  const deadline = Date.now() + 3e4;
11311
11336
  while (Date.now() < deadline) {
11312
11337
  if (await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home)}`).then((r) => r.ok).catch(() => false)) break;
11313
- await new Promise((resolve7) => setTimeout(resolve7, 250));
11338
+ await new Promise((resolve8) => setTimeout(resolve8, 250));
11314
11339
  }
11315
11340
  if (!await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home)}`).then((r) => r.ok).catch(() => false)) {
11316
11341
  throw new Error(`Nomos admitted the birth of '${home}' but its custody did not become readable`);
@@ -11358,7 +11383,7 @@ async function ensureSovereignHome(opts = {}) {
11358
11383
  return typeof leaf?.verifiedVia === "string" && leaf.verifiedVia.length > 0;
11359
11384
  }).catch(() => false);
11360
11385
  if (visible) break;
11361
- await new Promise((resolve7) => setTimeout(resolve7, 250));
11386
+ await new Promise((resolve8) => setTimeout(resolve8, 250));
11362
11387
  }
11363
11388
  if (!visible) throw new Error(`the session home's verified device enrollment did not become readable`);
11364
11389
  }
@@ -13414,7 +13439,13 @@ function discoverDeployJson(cwd, explicit) {
13414
13439
  if (!existsSync4(buildDir)) {
13415
13440
  throw new Error("no build/ directory \u2014 run `githolon compile` first (or pass --file <path>)");
13416
13441
  }
13417
- const bodies = readdirSync3(buildDir).filter((f) => f.endsWith(".deploy.json"));
13442
+ const files = readdirSync3(buildDir);
13443
+ const applications = files.filter((f) => f.endsWith(".application.usda"));
13444
+ if (applications.length === 1) return join5(buildDir, applications[0]);
13445
+ if (applications.length > 1) {
13446
+ throw new Error(`multiple application stages in build/ (${applications.join(", ")}) \u2014 pass --file <path>`);
13447
+ }
13448
+ const bodies = files.filter((f) => f.endsWith(".deploy.json"));
13418
13449
  if (bodies.length === 0) {
13419
13450
  throw new Error("no build/*.deploy.json \u2014 run `githolon compile` first (or pass --file <path>)");
13420
13451
  }
@@ -13668,12 +13699,11 @@ async function waitForDurableMainAdvance(cloud, ws, previousHead, opts = {}) {
13668
13699
  while (Date.now() < deadline) {
13669
13700
  const head = await durableMainHead(cloud, ws, fetchImpl);
13670
13701
  if (head !== void 0 && head !== previousHead) return head;
13671
- await new Promise((resolve7) => setTimeout(resolve7, pollMs));
13702
+ await new Promise((resolve8) => setTimeout(resolve8, pollMs));
13672
13703
  }
13673
13704
  return void 0;
13674
13705
  }
13675
13706
  async function deploy2(ws, opts) {
13676
- const cloud = cloudBase(opts.cloud);
13677
13707
  let file;
13678
13708
  try {
13679
13709
  file = discoverDeployJson(process.cwd(), opts.file);
@@ -13681,6 +13711,31 @@ async function deploy2(ws, opts) {
13681
13711
  err4(e.message);
13682
13712
  return 1;
13683
13713
  }
13714
+ if (file.endsWith(".application.usda")) {
13715
+ let application;
13716
+ try {
13717
+ const { applicationDeploymentPlan } = await import("@githolon/dsl/application-composition");
13718
+ application = applicationDeploymentPlan(file);
13719
+ } catch (error) {
13720
+ err4(`application deployment refused: ${error.message}`);
13721
+ return 1;
13722
+ }
13723
+ out4(`deploying ${application.application} from ${file.split("/").pop()} \u2014 topology comes from OpenUSD`);
13724
+ for (const pkg of application.packages) {
13725
+ out4(` ${pkg.placement === "payload" ? "payload" : "reference"} ${pkg.packageName}`);
13726
+ const code = await deployPackage(ws, opts, pkg.deployPath, pkg.placement);
13727
+ if (code !== 0) {
13728
+ err4(`application '${application.application}' stopped at ${pkg.packageName}; later packages were not attempted`);
13729
+ return code;
13730
+ }
13731
+ }
13732
+ out4(`\u2713 application ${application.application} deployed from its OpenUSD composition`);
13733
+ return 0;
13734
+ }
13735
+ return deployPackage(ws, opts, file, "auto");
13736
+ }
13737
+ async function deployPackage(ws, opts, file, placement) {
13738
+ const cloud = cloudBase(opts.cloud);
13684
13739
  const fileName = file.split("/").pop();
13685
13740
  try {
13686
13741
  const { ensureApplicationWorkspace: ensureApplicationWorkspace2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
@@ -13742,9 +13797,16 @@ async function deploy2(ws, opts) {
13742
13797
  );
13743
13798
  return 1;
13744
13799
  }
13745
- let expectsPending = plan !== void 0 && plan.predecessorCandidates.length === 1 && !plan.idempotent;
13800
+ let expectsPending = placement === "payload" || plan !== void 0 && plan.predecessorCandidates.length === 1 && !plan.idempotent;
13746
13801
  const principal2 = opts.principal ?? activePrincipal();
13747
13802
  const signed = opts.principal !== void 0 || principal2 !== void 0 && getDeviceKey(principal2) !== void 0;
13803
+ if (placement === "payload" && !signed) {
13804
+ err4(
13805
+ `application payload '${fileName}' must be staged by a signed principal; the unsigned package lane cannot promise that child law stays inactive on the platform workspace`
13806
+ );
13807
+ err4(` run githolon login --agent and enroll/import that principal's device key, then deploy again`);
13808
+ return 1;
13809
+ }
13748
13810
  let phaseSuffix = "";
13749
13811
  let deployedHash;
13750
13812
  if (signed) {
@@ -17366,7 +17428,11 @@ var init_home = __esm({
17366
17428
  workspaceName: t.string().merge(Lww),
17367
17429
  /** ISO-8601, caller-stamped (determinism — no clock in the plan). */
17368
17430
  bornAt: t.string().merge(Lww)
17369
- }, { cap: 1 }).public();
17431
+ // The group's genesis seats its controller in OWNED_READ_RELATION below. Declaring that same capability
17432
+ // here makes the law's coarse pack gate recognise the seat, so a newly enrolled device can clone its own
17433
+ // receiving group before any tenant records or tenant-authored grants exist. This remains ordinary,
17434
+ // replayable Zanzibar state: revocation removes the seat; there is no kernel-level founder bypass.
17435
+ }, { cap: 1 }).readableBy(OWNED_READ_RELATION2);
17370
17436
  ReceivingGroupPolicy = aggregate("NomosInternalReceivingGroupPolicy7c1f5e", {
17371
17437
  additionalDevice: t.string().merge(Lww),
17372
17438
  revocation: t.string().merge(Lww),
@@ -17386,7 +17452,7 @@ var init_home = __esm({
17386
17452
  allow: [user()]
17387
17453
  });
17388
17454
  seedReceivingGroup = directive("nomosInternalSeedReceivingGroup7c1f5e").ensures(ReceivingGroup).payload(z9.object({ principal: z9.string().min(1), workspaceName: z9.string().min(1), bornAt: z9.string().min(1) })).plan((p) => writeReceivingGroup(p));
17389
- receivingGroupNameBindsPrincipal = workspaceInvariant("ReceivingGroupNameBindsPrincipal").on("nomosInternalSeedReceivingGroup7c1f5e").reads(() => [refAs("group", "NomosInternalReceivingGroup7c1f5e", RECEIVING_GROUP_ID)]).assert(({ group: group2 }) => {
17455
+ receivingGroupNameBindsPrincipal = workspaceInvariant("ReceivingGroupNameBindsPrincipal").on("nomosInternalSeedReceivingGroup7c1f5e").reads(() => [refAs("group", "NomosInternalReceivingGroup7c1f5e", RECEIVING_GROUP_ID)]).declassify("the receiving-group address is a public hash of its stable principal; refusing a mismatch reveals no private field").assert(({ group: group2 }) => {
17390
17456
  const g = group2 ?? {};
17391
17457
  const expected = RECEIVING_GROUP_NAME_PREFIX + nomos.sha256(String(g.principal ?? "")).slice(0, RECEIVING_GROUP_NAME_HASH_LEN);
17392
17458
  return g.workspaceName === expected ? { accept: true } : { reject: "a receiving group's workspace name must hash its stable principal" };
@@ -17395,7 +17461,7 @@ var init_home = __esm({
17395
17461
  refAs("group", "NomosInternalReceivingGroup7c1f5e", RECEIVING_GROUP_ID),
17396
17462
  refAs("policy", "NomosInternalReceivingGroupPolicy7c1f5e", RECEIVING_GROUP_POLICY_ID)
17397
17463
  ];
17398
- receivingGroupRejectsKeylessAdditionalDevice = workspaceInvariant("ReceivingGroupRejectsKeylessAdditionalDevice").on("enrollFirstDevice").reads(receivingGroupPolicyRefs).assert(({ group: group2 }) => typeof group2?.principal !== "string" || group2.principal.length === 0 ? { accept: true } : { reject: "receiving-group-additional-device-requires-current-device-or-guardian" });
17464
+ receivingGroupRejectsKeylessAdditionalDevice = workspaceInvariant("ReceivingGroupRejectsKeylessAdditionalDevice").on("enrollFirstDevice").reads(receivingGroupPolicyRefs).declassify("device enrollment deliberately reveals that this receiving group has already completed first-device bootstrap").assert(({ group: group2 }) => typeof group2?.principal !== "string" || group2.principal.length === 0 ? { accept: true } : { reject: "receiving-group-additional-device-requires-current-device-or-guardian" });
17399
17465
  receivingGroupAdditionalDeviceFollowsPolicy = workspaceInvariant("ReceivingGroupAdditionalDeviceFollowsPolicy").on("enrollSignerSelf").reads(receivingGroupPolicyRefs).declassify("device lifecycle policy intentionally branches on principal_verified").assert(({ group: group2, policy }, ctx) => {
17400
17466
  if (typeof group2?.principal !== "string" || group2.principal.length === 0) return { accept: true };
17401
17467
  const p = policy;
@@ -18918,6 +18984,74 @@ var init_mcp = __esm({
18918
18984
  }
18919
18985
  });
18920
18986
 
18987
+ // src/test.ts
18988
+ var test_exports = {};
18989
+ __export(test_exports, {
18990
+ resolveTestCloudEntry: () => resolveTestCloudEntry,
18991
+ runDartTests: () => runDartTests
18992
+ });
18993
+ import { spawnSync as spawnSync6 } from "node:child_process";
18994
+ import { existsSync as existsSync12 } from "node:fs";
18995
+ import { dirname as dirname8, resolve as resolve5 } from "node:path";
18996
+ import { fileURLToPath } from "node:url";
18997
+ function resolveTestCloudEntry(options = {}) {
18998
+ const cwd = options.cwd ?? process.cwd();
18999
+ const environment = options.environment ?? process.env;
19000
+ const explicit = environment.NOMOS_TEST_CLOUD_ENTRY;
19001
+ if (explicit !== void 0) {
19002
+ const candidate = resolve5(cwd, explicit);
19003
+ if (!existsSync12(candidate)) {
19004
+ throw new Error(`NOMOS_TEST_CLOUD_ENTRY does not exist: ${candidate}`);
19005
+ }
19006
+ return candidate;
19007
+ }
19008
+ const here = dirname8(fileURLToPath(options.moduleUrl ?? import.meta.url));
19009
+ const candidates = [
19010
+ resolve5(here, "dev-server.mjs"),
19011
+ resolve5(here, "../dist/dev-server.mjs"),
19012
+ resolve5(here, "../../cloud/dev-server/server.ts"),
19013
+ resolve5(cwd, "cloud/dev-server/server.ts")
19014
+ ];
19015
+ const server = candidates.find((candidate) => existsSync12(candidate));
19016
+ if (server === void 0) {
19017
+ throw new Error("the bundled local Nomos cloud is missing \u2014 rebuild or reinstall githolon");
19018
+ }
19019
+ return server;
19020
+ }
19021
+ function runDartTests(args) {
19022
+ const diagnostics = args.includes("--diagnostics");
19023
+ const forwarded = args.filter((arg) => arg !== "--diagnostics");
19024
+ let serverEntry;
19025
+ try {
19026
+ serverEntry = resolveTestCloudEntry();
19027
+ } catch (error) {
19028
+ process.stderr.write(`error: ${error instanceof Error ? error.message : error}
19029
+ `);
19030
+ return 1;
19031
+ }
19032
+ process.stdout.write("githolon test \u2014 generated application scenarios with real local custody\n");
19033
+ const result = spawnSync6("flutter", ["test", ...forwarded], {
19034
+ cwd: process.cwd(),
19035
+ stdio: "inherit",
19036
+ env: {
19037
+ ...process.env,
19038
+ NOMOS_TEST_CLOUD_ENTRY: serverEntry,
19039
+ ...diagnostics ? { NOMOS_TEST_DIAGNOSTICS: "1" } : {}
19040
+ }
19041
+ });
19042
+ if (result.error !== void 0) {
19043
+ process.stderr.write(`error: could not run Flutter tests: ${result.error.message}
19044
+ `);
19045
+ return 1;
19046
+ }
19047
+ return result.status ?? 1;
19048
+ }
19049
+ var init_test = __esm({
19050
+ "src/test.ts"() {
19051
+ "use strict";
19052
+ }
19053
+ });
19054
+
18921
19055
  // src/harness.ts
18922
19056
  var harness_exports = {};
18923
19057
  __export(harness_exports, {
@@ -18925,7 +19059,7 @@ __export(harness_exports, {
18925
19059
  harnessInstall: () => harnessInstall,
18926
19060
  looksLikeStaleRuntime: () => looksLikeStaleRuntime
18927
19061
  });
18928
- import { existsSync as existsSync12, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
19062
+ import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
18929
19063
  import { join as join14 } from "node:path";
18930
19064
  import { randomBytes as randomBytes3 } from "node:crypto";
18931
19065
  function looksLikeStaleRuntime(msg) {
@@ -18942,7 +19076,7 @@ async function harnessInstall(opts) {
18942
19076
  `);
18943
19077
  const wasmFile = join14(runtimeDir, "holon-testmint.wasm");
18944
19078
  const pkgsFile = join14(runtimeDir, "packages.json");
18945
- if (!existsSync12(wasmFile) || !existsSync12(pkgsFile)) {
19079
+ if (!existsSync13(wasmFile) || !existsSync13(pkgsFile)) {
18946
19080
  die(
18947
19081
  `test runtime cache missing at ${runtimeDir} (holon-testmint.wasm + packages.json). Warm it once with a \`githolon\` run (it fetches + caches the runtime), then re-run offline.`
18948
19082
  );
@@ -18979,7 +19113,7 @@ async function harnessInstall(opts) {
18979
19113
  const lawHashes = [];
18980
19114
  const expectedDomainLaw = /* @__PURE__ */ new Map();
18981
19115
  for (const p of deployPaths) {
18982
- if (!existsSync12(p)) die(`deploy JSON not found: ${p} \u2014 run \`npx githolon compile\` first`);
19116
+ if (!existsSync13(p)) die(`deploy JSON not found: ${p} \u2014 run \`npx githolon compile\` first`);
18983
19117
  const deploy3 = JSON.parse(readFileSync13(p, "utf8"));
18984
19118
  const usda = deploy3.packageUsda;
18985
19119
  if (typeof usda !== "string" || !usda.startsWith("#usda")) die(`${p} has no #usda packageUsda`);
@@ -19043,11 +19177,11 @@ var doctor_exports = {};
19043
19177
  __export(doctor_exports, {
19044
19178
  doctor: () => doctor
19045
19179
  });
19046
- import { existsSync as existsSync13, readFileSync as readFileSync14 } from "node:fs";
19180
+ import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
19047
19181
  function readLocalCompat(cwd, file) {
19048
19182
  try {
19049
19183
  const path2 = discoverDeployJson(cwd, file);
19050
- if (!existsSync13(path2)) return void 0;
19184
+ if (!existsSync14(path2)) return void 0;
19051
19185
  const body = JSON.parse(readFileSync14(path2, "utf8"));
19052
19186
  return body.nomosCompat;
19053
19187
  } catch {
@@ -22328,8 +22462,8 @@ var scene_exports = {};
22328
22462
  __export(scene_exports, {
22329
22463
  scene: () => scene
22330
22464
  });
22331
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, writeFileSync as writeFileSync9 } from "node:fs";
22332
- import { join as join15, resolve as resolve5 } from "node:path";
22465
+ import { existsSync as existsSync15, mkdirSync as mkdirSync6, writeFileSync as writeFileSync9 } from "node:fs";
22466
+ import { join as join15, resolve as resolve6 } from "node:path";
22333
22467
  import { createHash as createHash6 } from "node:crypto";
22334
22468
  import git3 from "isomorphic-git";
22335
22469
  async function walkChain2(eng, ws) {
@@ -22350,8 +22484,8 @@ async function projectOnce(cloud, target, isDir, name) {
22350
22484
  const { eng } = await holonEngine(cloud, void 0, "githolon-scene");
22351
22485
  const SOURCE3 = "source";
22352
22486
  if (isDir) {
22353
- const gitDir = existsSync14(join15(target, ".git")) ? join15(target, ".git") : target;
22354
- if (!existsSync14(join15(gitDir, "HEAD"))) throw new Error(`${target} is not a git repo (no HEAD)`);
22487
+ const gitDir = existsSync15(join15(target, ".git")) ? join15(target, ".git") : target;
22488
+ if (!existsSync15(join15(gitDir, "HEAD"))) throw new Error(`${target} is not a git repo (no HEAD)`);
22355
22489
  await mountFresh(eng, SOURCE3);
22356
22490
  eng.preopen.dir.contents.get("ws").contents.get(SOURCE3).contents.set("nomos.git", readTreeFromDisk(gitDir));
22357
22491
  } else {
@@ -22410,9 +22544,9 @@ async function projectOnce(cloud, target, isDir, name) {
22410
22544
  }
22411
22545
  async function scene(target, opts) {
22412
22546
  const cloud = cloudBase(opts.cloud);
22413
- const isDir = existsSync14(target) || target.includes("/") || target.startsWith(".");
22414
- const name = isDir ? (resolve5(target).split("/").filter(Boolean).pop() ?? "scene").replace(/\.git$/, "") : target;
22415
- out11(`scene \u2014 ${name} (${isDir ? resolve5(target) : `${cloud} :: ${target}`})`);
22547
+ const isDir = existsSync15(target) || target.includes("/") || target.startsWith(".");
22548
+ const name = isDir ? (resolve6(target).split("/").filter(Boolean).pop() ?? "scene").replace(/\.git$/, "") : target;
22549
+ out11(`scene \u2014 ${name} (${isDir ? resolve6(target) : `${cloud} :: ${target}`})`);
22416
22550
  let first2, second;
22417
22551
  try {
22418
22552
  first2 = await projectOnce(cloud, target, isDir, name);
@@ -22430,7 +22564,7 @@ async function scene(target, opts) {
22430
22564
  err11(`the emitted stage violates the portable profile: ${violations.join("; ")}`);
22431
22565
  return 1;
22432
22566
  }
22433
- const outDir = resolve5(opts.out ?? join15("scene", name));
22567
+ const outDir = resolve6(opts.out ?? join15("scene", name));
22434
22568
  mkdirSync6(outDir, { recursive: true });
22435
22569
  const usdaPath = join15(outDir, `${name}.usda`);
22436
22570
  const usdzPath = join15(outDir, `${name}.usdz`);
@@ -22521,12 +22655,12 @@ var init_dlq = __esm({
22521
22655
  });
22522
22656
 
22523
22657
  // src/cli.ts
22524
- import { existsSync as existsSync15, readdirSync as readdirSync6, readFileSync as readFileSync15 } from "node:fs";
22525
- import { spawn as spawn2, spawnSync as spawnSync6 } from "node:child_process";
22658
+ import { existsSync as existsSync16, readdirSync as readdirSync6, readFileSync as readFileSync15 } from "node:fs";
22659
+ import { spawn as spawn2, spawnSync as spawnSync7 } from "node:child_process";
22526
22660
  import { createHash as createHash7 } from "node:crypto";
22527
22661
  import { createRequire as createRequire3 } from "node:module";
22528
- import { dirname as dirname8, join as join16, resolve as resolve6 } from "node:path";
22529
- import { pathToFileURL as pathToFileURL5, fileURLToPath } from "node:url";
22662
+ import { dirname as dirname9, join as join16, resolve as resolve7 } from "node:path";
22663
+ import { pathToFileURL as pathToFileURL5, fileURLToPath as fileURLToPath2 } from "node:url";
22530
22664
 
22531
22665
  // src/generate.ts
22532
22666
  import { mkdirSync, existsSync, writeFileSync } from "node:fs";
@@ -25383,7 +25517,8 @@ var HELP = {
25383
25517
  ["[config]", "package or application authoring input (default: nomos.package.mjs)"],
25384
25518
  ["--require-usdcat", "refuse unless stock OpenUSD flattens to the same canonical law"],
25385
25519
  ["--compact", "emit the compact executable package envelope"],
25386
- ["--analyze", "run dart analyze on generated Dart packages"]
25520
+ ["--analyze", "run dart analyze on generated Dart packages"],
25521
+ ["--no-mount-check", "emit without the CLI runtime mountability gate (framework/CI escape hatch)"]
25387
25522
  ],
25388
25523
  examples: ["githolon compile", "githolon compile nomos.application.mjs --require-usdcat"]
25389
25524
  },
@@ -25392,6 +25527,15 @@ var HELP = {
25392
25527
  what: "Run the application-wide proof GENERATED from your business law. By default it opens a blank\nlocal application through the same generated API tenant code uses, executes its business journey,\nsynchronizes, reopens, and reads the saved records back. --live runs that same business proof against\nNomos Cloud; identity, provisioning, persistence, and cleanup remain inside Nomos. ALL GREEN or it names the jam.",
25393
25528
  examples: ["githolon proof", "githolon proof build/co2.proof.mts", "githolon proof --live"]
25394
25529
  },
25530
+ test: {
25531
+ usage: "githolon test [test-file-or-flutter-test-flags] [--diagnostics]",
25532
+ what: "Run generated Dart application scenarios through Flutter with the real local Nomos custody plane.\nThe server rides inside githolon; connected scenarios, partitions, restarts and fresh reinstalls need no\nserver path, environment variables, certificates, workspace setup or separate application state.",
25533
+ flags: [
25534
+ ["[test file/flags]", "forwarded to flutter test"],
25535
+ ["--diagnostics", "show framework/cloud diagnostics when investigating a failing scenario"]
25536
+ ],
25537
+ examples: ["githolon test", "githolon test test/catalogue_birth_test.dart", "githolon test --diagnostics"]
25538
+ },
25395
25539
  dev: {
25396
25540
  usage: "githolon dev [--port <n>] [--cloud <url>] [--once]",
25397
25541
  what: "THE INNER LOOP: watch domains/ + nomos.package.mjs, recompile on save, install the law into\na LOCAL holon (the same engine plane the cloud edge runs \u2014 your data SURVIVES law edits),\nrerun the generated local business checks, and serve the generated application on localhost.\nFully offline after the first runtime fetch (~/.holon/runtime).",
@@ -25583,11 +25727,11 @@ var HELP = {
25583
25727
  examples: ["githolon revoke creation 32c7100e-\u2026", "githolon revoke admin 32c7100e-\u2026"]
25584
25728
  },
25585
25729
  deploy: {
25586
- usage: "githolon deploy [<ws>] [--as <uid>] [--file <deploy.json>] [--cloud <url>] [--target <name>]",
25587
- what: "Put the compiled model in the workspace's verified custody. There is one lifecycle: the first\nmodel becomes active so a blank application can start; every successor stays Pending while the current\nmodel keeps serving. The candidate generated client then runs the exact-history proof through\n`model.adopt()` and either adopts immediately or returns a business-readable decision requiring\n`decision.accept(reason)`. Deployment cannot choose a replacement mode or bypass that proof.\nRe-deploying the same content hash is idempotent. With no <ws>, the project's workspace binding resolves it.",
25730
+ usage: "githolon deploy [<ws>] [--as <uid>] [--file <application.usda|deploy.json>] [--cloud <url>] [--target <name>]",
25731
+ what: "Deploy the compiled application from its OpenUSD composition. Reference-only packages serve on\nthe application workspace; payload packages are staged for child birth and never made current there.\nFor a one-package project, the package deploy body remains the shorthand. There is one model lifecycle:\nthe first serving model becomes active; a successor stays Pending while the current model keeps serving,\nand the generated candidate client owns exact-history adoption. Re-deploying the same content hash is\nidempotent. With no <ws>, the project's workspace binding resolves it.",
25588
25732
  flags: [
25589
25733
  ["--as <uid>", "attribute the deployment to this principal (needs its enrolled signing key)"],
25590
- ["--file <path>", "an explicit deploy body (default: the one build/*.deploy.json)"],
25734
+ ["--file <path>", "an application USDA or package deploy body (default: build/*.application.usda, else the one deploy body)"],
25591
25735
  ["--target <name>", "pick among named targets (workspace: { dev: \u2026, prod: \u2026 })"],
25592
25736
  ["--cloud <url>", "target cloud"]
25593
25737
  ],
@@ -26121,6 +26265,7 @@ var USAGE = `githolon \u2014 model a business; Nomos owns the compute science
26121
26265
  Start here:
26122
26266
  githolon compile compile aggregates, birth, directives, and reads into law + a typed client
26123
26267
  githolon proof run the generated business proof in the real local engine
26268
+ githolon test run generated Dart scenarios with real local custody
26124
26269
  githolon dev watch, compile, and rerun that proof on every save
26125
26270
  githolon check explain anything the law can already prove it would refuse
26126
26271
 
@@ -26246,17 +26391,17 @@ function isKind(s) {
26246
26391
  function resolvedTsxCli() {
26247
26392
  const resolvePkgDir = (name, fromDir) => {
26248
26393
  try {
26249
- return dirname8(createRequire3(pathToFileURL5(join16(fromDir, "noop.js"))).resolve(`${name}/package.json`));
26394
+ return dirname9(createRequire3(pathToFileURL5(join16(fromDir, "noop.js"))).resolve(`${name}/package.json`));
26250
26395
  } catch {
26251
26396
  return void 0;
26252
26397
  }
26253
26398
  };
26254
26399
  const dslDir = (() => {
26255
26400
  try {
26256
- return dirname8(createRequire3(pathToFileURL5(join16(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
26401
+ return dirname9(createRequire3(pathToFileURL5(join16(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
26257
26402
  } catch {
26258
26403
  try {
26259
- return dirname8(createRequire3(import.meta.url).resolve("@githolon/dsl/package.json"));
26404
+ return dirname9(createRequire3(import.meta.url).resolve("@githolon/dsl/package.json"));
26260
26405
  } catch {
26261
26406
  return void 0;
26262
26407
  }
@@ -26270,24 +26415,24 @@ function resolvedTsxCli() {
26270
26415
  }
26271
26416
  async function runGeneratedApplicationProofLocally(proofPath) {
26272
26417
  const deployPath = proofPath.replace(/\.proof\.mts$/, ".deploy.json");
26273
- if (deployPath === proofPath || !existsSync15(deployPath)) {
26418
+ if (deployPath === proofPath || !existsSync16(deployPath)) {
26274
26419
  throw new Error(`generated application proof needs its sibling deploy artifact: ${deployPath}`);
26275
26420
  }
26276
- const here = dirname8(fileURLToPath(import.meta.url));
26421
+ const here = dirname9(fileURLToPath2(import.meta.url));
26277
26422
  const serverCandidates = [
26278
- resolve6(here, "dev-server.mjs"),
26279
- resolve6(here, "../dist/dev-server.mjs"),
26280
- resolve6(here, "../../cloud/dev-server/server.ts"),
26281
- resolve6(process.cwd(), "cloud/dev-server/server.ts")
26423
+ resolve7(here, "dev-server.mjs"),
26424
+ resolve7(here, "../dist/dev-server.mjs"),
26425
+ resolve7(here, "../../cloud/dev-server/server.ts"),
26426
+ resolve7(process.cwd(), "cloud/dev-server/server.ts")
26282
26427
  ];
26283
- const serverPath = serverCandidates.find((candidate) => existsSync15(candidate));
26428
+ const serverPath = serverCandidates.find((candidate) => existsSync16(candidate));
26284
26429
  if (serverPath === void 0) {
26285
26430
  throw new Error("the bundled local Nomos cloud is missing \u2014 rebuild or reinstall githolon");
26286
26431
  }
26287
26432
  const candidateRuntime = process.env.NOMOS_CANDIDATE_RUNTIME ?? process.env.NOMOS_OFFLINE_RUNTIME;
26288
26433
  const candidateTestMint = candidateRuntime === void 0 ? void 0 : join16(candidateRuntime, "holon-testmint.wasm");
26289
26434
  const priorLocalWasm = process.env.NOMOS_LOCAL_WASM;
26290
- if (candidateTestMint !== void 0 && existsSync15(candidateTestMint)) process.env.NOMOS_LOCAL_WASM = candidateTestMint;
26435
+ if (candidateTestMint !== void 0 && existsSync16(candidateTestMint)) process.env.NOMOS_LOCAL_WASM = candidateTestMint;
26291
26436
  const module = await import(pathToFileURL5(serverPath).href);
26292
26437
  if (typeof module.startGeneratedApplicationProofCloud !== "function") {
26293
26438
  throw new Error("the bundled local Nomos cloud predates generated application execution \u2014 rebuild githolon");
@@ -26351,11 +26496,11 @@ async function runProof(args) {
26351
26496
  const explicit = args.find((a, i) => !a.startsWith("--") && i !== domainValueIdx);
26352
26497
  let proofPath;
26353
26498
  if (explicit !== void 0) {
26354
- proofPath = resolve6(process.cwd(), explicit);
26355
- if (!existsSync15(proofPath)) return refuse(`proof not found: ${proofPath} \u2014 run \`githolon compile\` to (re)generate it`);
26499
+ proofPath = resolve7(process.cwd(), explicit);
26500
+ if (!existsSync16(proofPath)) return refuse(`proof not found: ${proofPath} \u2014 run \`githolon compile\` to (re)generate it`);
26356
26501
  } else {
26357
26502
  const buildDir = join16(process.cwd(), "build");
26358
- if (!existsSync15(buildDir)) {
26503
+ if (!existsSync16(buildDir)) {
26359
26504
  return refuse("no build/ directory here \u2014 run `githolon compile` first (every compile generates build/<name>.proof.mts from your law)");
26360
26505
  }
26361
26506
  const proofs = readdirSync6(buildDir).filter((f) => f.endsWith(".proof.mts"));
@@ -26407,7 +26552,7 @@ async function runProof(args) {
26407
26552
  const proofWorkspace = `nomos-proof-${proofIdentity}`;
26408
26553
  const deployed = await deploy2(proofWorkspace, { principal: barePrincipal });
26409
26554
  if (deployed !== 0) return refuse("proof --live: Nomos could not install the compiled business law into its isolated acceptance application");
26410
- const r = spawnSync6(process.execPath, [tsxCli, proofPath], {
26555
+ const r = spawnSync7(process.execPath, [tsxCli, proofPath], {
26411
26556
  stdio: "inherit",
26412
26557
  cwd: process.cwd(),
26413
26558
  env: {
@@ -26473,9 +26618,10 @@ async function main(argv) {
26473
26618
  return 0;
26474
26619
  }
26475
26620
  if (argv[0] === "compile") {
26476
- const status2 = runCompile(argv.slice(1));
26621
+ const skipMountCheck = argv.includes("--no-mount-check");
26622
+ const status2 = runCompile(argv.slice(1).filter((arg) => arg !== "--no-mount-check"));
26477
26623
  if (status2 !== 0) return status2;
26478
- if (argv.includes("--no-mount-check")) return status2;
26624
+ if (skipMountCheck) return status2;
26479
26625
  try {
26480
26626
  const { assertCompiledMountable: assertCompiledMountable2 } = await Promise.resolve().then(() => (init_mountability(), mountability_exports));
26481
26627
  const { cloudBase: cloudBase2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
@@ -26516,6 +26662,10 @@ async function main(argv) {
26516
26662
  if (argv[0] === "proof") {
26517
26663
  return runProof(argv.slice(1));
26518
26664
  }
26665
+ if (argv[0] === "test") {
26666
+ const { runDartTests: runDartTests2 } = await Promise.resolve().then(() => (init_test(), test_exports));
26667
+ return runDartTests2(argv.slice(1));
26668
+ }
26519
26669
  if (argv[0] === "harness-install") {
26520
26670
  const rest = argv.slice(1);
26521
26671
  const pull = (flag) => {
@@ -26591,22 +26741,22 @@ usage: githolon cloud dev [--port <n>] [--data <dir>] [--ephemeral]
26591
26741
  `);
26592
26742
  return 1;
26593
26743
  }
26594
- const { spawnSync: spawnSync7 } = await import("node:child_process");
26595
- const here = dirname8(fileURLToPath(import.meta.url));
26744
+ const { spawnSync: spawnSync8 } = await import("node:child_process");
26745
+ const here = dirname9(fileURLToPath2(import.meta.url));
26596
26746
  const candidates = [
26597
- resolve6(here, "dev-server.mjs"),
26747
+ resolve7(here, "dev-server.mjs"),
26598
26748
  // published: dist/dev-server.mjs
26599
- resolve6(here, "../../cloud/dev-server/server.mjs"),
26749
+ resolve7(here, "../../cloud/dev-server/server.mjs"),
26600
26750
  // in-repo (tsx / unbuilt) fallbacks
26601
- resolve6(here, "../../../cloud/dev-server/server.mjs"),
26602
- resolve6(process.cwd(), "cloud/dev-server/server.mjs")
26751
+ resolve7(here, "../../../cloud/dev-server/server.mjs"),
26752
+ resolve7(process.cwd(), "cloud/dev-server/server.mjs")
26603
26753
  ];
26604
- const serverPath = candidates.find((p) => existsSync15(p));
26754
+ const serverPath = candidates.find((p) => existsSync16(p));
26605
26755
  if (!serverPath) {
26606
26756
  process.stderr.write("error: dev-server not found \u2014 reinstall `githolon` or run `npm run build` in the cli package\n");
26607
26757
  return 1;
26608
26758
  }
26609
- const r = spawnSync7(process.execPath, [serverPath, ...argv.slice(2)], { stdio: "inherit" });
26759
+ const r = spawnSync8(process.execPath, [serverPath, ...argv.slice(2)], { stdio: "inherit" });
26610
26760
  return r.status ?? 0;
26611
26761
  }
26612
26762
  if (argv[0] === "replay") {
@@ -268,11 +268,16 @@ async function pushPack(remote, headers = {}, { updates = [], pack = null } = {}
268
268
  });
269
269
  cmds.push(FLUSH);
270
270
  const body = concatBytes([...cmds, pack && pack.length ? pack : EMPTY_PACK]);
271
- const r = await fetch(`${remote}/git-receive-pack`, {
272
- method: "POST",
273
- headers: { "content-type": "application/x-git-receive-pack-request", ...headers },
274
- body
275
- });
271
+ let r;
272
+ try {
273
+ r = await fetch(`${remote}/git-receive-pack`, {
274
+ method: "POST",
275
+ headers: { "content-type": "application/x-git-receive-pack-request", ...headers },
276
+ body
277
+ });
278
+ } catch (error) {
279
+ throw new Error(`receive-pack transport failed (${body.byteLength} bytes): ${String(error)}`, { cause: error });
280
+ }
276
281
  const txt = dec2.decode(new Uint8Array(await r.arrayBuffer()));
277
282
  const unpacked = /unpack ok/.test(txt);
278
283
  const everyRefOk = updates.every((u) => new RegExp(`ok ${u.ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`).test(txt));
@@ -878,7 +883,12 @@ async function custodyFetch(eng, ws, ledger, { remoteRef = "refs/heads/main", lo
878
883
  async function custodyPush(eng, ws, ledger, { localRef = null, remoteRef, del = false, pointer = false, newOid = null }) {
879
884
  const headers = ledger.headers || {};
880
885
  const remoteRefFull = fullRef(remoteRef);
881
- const remote = await lsRefs(ledger.remote, headers, { service: "git-receive-pack", prefix: remoteRefFull });
886
+ let remote;
887
+ try {
888
+ remote = await lsRefs(ledger.remote, headers, { service: "git-receive-pack", prefix: remoteRefFull });
889
+ } catch (error) {
890
+ throw new Error(`custody receive-pack advertisement failed for ${remoteRefFull}: ${String(error)}`, { cause: error });
891
+ }
882
892
  const oldOid = remote[remoteRefFull] || ZERO_OID;
883
893
  if (del) {
884
894
  if (oldOid === ZERO_OID) return;
@@ -892,14 +902,21 @@ async function custodyPush(eng, ws, ledger, { localRef = null, remoteRef, del =
892
902
  pack = oldOid !== ZERO_OID ? packDelta(eng, ws, oldOid, tgt) : null;
893
903
  if (!pack) pack = packDelta(eng, ws, "", tgt);
894
904
  }
895
- return pushVia(ledger, () => pushPack(ledger.remote, headers, { updates: [{ ref: remoteRefFull, oldOid, newOid: tgt }], pack }));
905
+ const packBytes = pack?.byteLength ?? 0;
906
+ try {
907
+ return await pushVia(ledger, () => pushPack(ledger.remote, headers, { updates: [{ ref: remoteRefFull, oldOid, newOid: tgt }], pack }));
908
+ } catch (error) {
909
+ throw new Error(`custody receive-pack push failed for ${remoteRefFull} (${packBytes} pack bytes): ${String(error)}`, { cause: error });
910
+ }
896
911
  }
897
912
  async function commitAndPush(eng, ws, ledger) {
898
913
  try {
899
914
  await custodyPush(eng, ws, ledger, { remoteRef: "refs/heads/main" });
900
915
  } catch (e) {
901
916
  unmount(eng, ws);
902
- throw new Error(`ledger push failed \u2014 write NOT durable, rolled back to ledger: ${e}`);
917
+ const cause = e instanceof Error ? e.cause : void 0;
918
+ const detail = cause === void 0 ? String(e) : `${e}; cause: ${String(cause)}`;
919
+ throw new Error(`ledger push failed \u2014 write NOT durable, rolled back to ledger: ${detail}`, { cause: e });
903
920
  }
904
921
  }
905
922
  function describe(eng, ws) {
@@ -1711,9 +1728,11 @@ function completeDevAuthProviderPayload(deployBody, homeDomain, initial, nowMill
1711
1728
  return payload;
1712
1729
  }
1713
1730
  function homeDomainOf(opts) {
1714
- if (!opts || !opts.deploy) return null;
1731
+ if (!opts) return null;
1732
+ const deploy2 = homeDeployPathOf(opts);
1733
+ if (!deploy2) return null;
1715
1734
  try {
1716
- const body = JSON.parse(readFileSync(opts.deploy, "utf8"));
1735
+ const body = JSON.parse(readFileSync(deploy2, "utf8"));
1717
1736
  const frameworkPaths = body.openapi?.["x-nomos-framework-routes"]?.paths ?? {};
1718
1737
  for (const pathItem of Object.values(frameworkPaths)) {
1719
1738
  const route = pathItem.post?.["x-nomos"];
@@ -1802,7 +1821,8 @@ async function bootstrapPlatform(dev, opts) {
1802
1821
  {
1803
1822
  let apPayload = { issuer: idpIssuer, keys: idpJwks, audience: idpAudience, principalClaim: "sub", deviceBindingClaim: "nonce" };
1804
1823
  try {
1805
- const deployBody = opts.deploy ? JSON.parse(readFileSync(opts.deploy, "utf8")) : null;
1824
+ const homeDeploy = homeDeployPathOf(opts);
1825
+ const deployBody = homeDeploy ? JSON.parse(readFileSync(homeDeploy, "utf8")) : null;
1806
1826
  apPayload = completeDevAuthProviderPayload(deployBody, homeDomain, apPayload, Date.now(), OPERATOR);
1807
1827
  } catch (e) {
1808
1828
  log2(`dev test IdP: BYO-shape fill failed (${errMsg(e).slice(0, 200)}) \u2014 the canonical payload stands`);
@@ -1869,28 +1889,33 @@ async function bootstrapPlatform(dev, opts) {
1869
1889
  dev.homeDomain = homeDomain;
1870
1890
  }
1871
1891
  }
1872
- if (opts.deploy) {
1873
- const body = JSON.parse(readFileSync(opts.deploy, "utf8"));
1874
- const usda = body.packageUsda || body.usda;
1875
- if (!usda) throw new Error(`--deploy ${opts.deploy} has no packageUsda (nothing to install)`);
1892
+ const deployPaths = deployPathsOf(opts);
1893
+ if (deployPaths.length > 0) {
1876
1894
  const founderDevice = dev.operatorDevice;
1877
1895
  if (!founderDevice) throw new Error("platform law deploy needs the warranted founder device established by bootstrap");
1878
- const deployErr = await serialize(async () => {
1879
- const ledger = ledgerFor(platform);
1880
- const domainHash = await sha256hex(usda);
1881
- try {
1882
- const out = await deploy(eng, platform, ledger, usda, domainHash, body.dispositions || null, {
1883
- actor: "user:dev-operator",
1884
- authorSecret: founderDevice.secret
1885
- });
1886
- if (out && out.ok === false) return String(out.error || "the law refused the platform package");
1887
- log2(`platform law deployed: ${domainHash.slice(0, 12)} (head ${String(out.head).slice(0, 12)})`);
1888
- return null;
1889
- } catch (e) {
1890
- return errMsg(e);
1891
- }
1892
- });
1893
- if (deployErr) throw new Error(`platform law deploy REFUSED: ${deployErr.slice(0, 400)}`);
1896
+ for (const deployPath of deployPaths) {
1897
+ const body = JSON.parse(readFileSync(deployPath, "utf8"));
1898
+ const usda = body.packageUsda || body.usda;
1899
+ if (!usda) throw new Error(`--deploy ${deployPath} has no packageUsda (nothing to install)`);
1900
+ const deployErr = await serialize(async () => {
1901
+ const ledger = ledgerFor(platform);
1902
+ const domainHash = await sha256hex(usda);
1903
+ try {
1904
+ const out = await deploy(eng, platform, ledger, usda, domainHash, body.dispositions || null, {
1905
+ actor: "user:dev-operator",
1906
+ authorSecret: founderDevice.secret
1907
+ });
1908
+ if (out && out.ok === false) return String(out.error || "the law refused the platform package");
1909
+ log2(
1910
+ out.staged === true ? `application payload staged for child birth: ${domainHash.slice(0, 12)} (head ${String(out.head).slice(0, 12)})` : `platform law deployed: ${domainHash.slice(0, 12)} (head ${String(out.head).slice(0, 12)})`
1911
+ );
1912
+ return null;
1913
+ } catch (e) {
1914
+ return errStack(e);
1915
+ }
1916
+ });
1917
+ if (deployErr) throw new Error(`platform law deploy REFUSED (${deployPath}): ${deployErr.slice(0, 400)}`);
1918
+ }
1894
1919
  } else {
1895
1920
  log2("no --deploy given; platform runs framework law only (deploy your platform package to enable births)");
1896
1921
  }
@@ -1902,7 +1927,7 @@ async function bootstrapPlatform(dev, opts) {
1902
1927
  log2(attested ? "bootstrap complete \u2014 platform law deployed + ROOT-ATTESTED (BirthAttestation certChain seeded; birthHome assembles a valid travelling cert)." : "bootstrap complete (platform law deployed; attested-birth legs gated as noted above \u2014 need the test-mint wasm).");
1903
1928
  return { platform, testMint, attested };
1904
1929
  }
1905
- var log2, FRAMEWORK_HOME_DOMAIN;
1930
+ var log2, FRAMEWORK_HOME_DOMAIN, deployPathsOf, homeDeployPathOf;
1906
1931
  var init_bootstrap = __esm({
1907
1932
  "../cloud/dev-server/bootstrap.ts"() {
1908
1933
  "use strict";
@@ -1910,6 +1935,8 @@ var init_bootstrap = __esm({
1910
1935
  init_types();
1911
1936
  log2 = (m) => console.log(`[bootstrap] ${m}`);
1912
1937
  FRAMEWORK_HOME_DOMAIN = "__nomos_application_home_v1";
1938
+ deployPathsOf = (opts) => opts.deploys && opts.deploys.length > 0 ? [...opts.deploys] : opts.deploy ? [opts.deploy] : [];
1939
+ homeDeployPathOf = (opts) => deployPathsOf(opts).at(-1);
1913
1940
  }
1914
1941
  });
1915
1942
 
@@ -2123,17 +2150,24 @@ function runGitHttpBackend(projectRoot, { method, pathInfo, query: query2, conte
2123
2150
  CONTENT_TYPE: contentType || "",
2124
2151
  CONTENT_LENGTH: String(body ? body.length : 0),
2125
2152
  REMOTE_ADDR: "127.0.0.1",
2126
- REMOTE_USER: "nomos-dev",
2127
- GIT_HTTP_MAX_REQUEST_BUFFER: String(64 * 1024 * 1024)
2153
+ REMOTE_USER: "nomos-dev"
2128
2154
  };
2129
2155
  const cgi = spawn(GIT_HTTP_BACKEND, [], { env });
2130
2156
  const chunks = [];
2157
+ const stderrChunks = [];
2131
2158
  cgi.stdout.on("data", (d) => chunks.push(d));
2132
- cgi.stderr.on("data", () => {
2133
- });
2159
+ cgi.stderr.on("data", (d) => stderrChunks.push(d));
2134
2160
  cgi.on("error", reject);
2135
- cgi.on("close", () => {
2161
+ cgi.stdin.on("error", reject);
2162
+ cgi.on("close", (code, signal) => {
2136
2163
  const out = Buffer.concat(chunks);
2164
+ const stderr = Buffer.concat(stderrChunks).toString("utf8").trim();
2165
+ if (code !== 0 && out.length === 0) {
2166
+ reject(new Error(
2167
+ `git-http-backend exited ${signal ? `on ${signal}` : `with ${code}`}${stderr ? `: ${stderr}` : ""}`
2168
+ ));
2169
+ return;
2170
+ }
2137
2171
  let sep = out.indexOf("\r\n\r\n");
2138
2172
  let sepLen = 4;
2139
2173
  if (sep < 0) {
@@ -2157,8 +2191,7 @@ function runGitHttpBackend(projectRoot, { method, pathInfo, query: query2, conte
2157
2191
  }
2158
2192
  resolve({ status, headers, body: payload });
2159
2193
  });
2160
- if (body && body.length) cgi.stdin.write(body);
2161
- cgi.stdin.end();
2194
+ cgi.stdin.end(body && body.length ? body : void 0);
2162
2195
  });
2163
2196
  }
2164
2197
  function receivePackCommands(raw) {
@@ -2227,6 +2260,18 @@ var unb64 = (s) => new Uint8Array(Buffer.from(s, "base64"));
2227
2260
  function configDir() {
2228
2261
  return process.env.HOLON_CONFIG_DIR || path.join(os.homedir(), ".holon");
2229
2262
  }
2263
+ function explicitRuntimeDir() {
2264
+ if (process.env.NOMOS_CANDIDATE_RUNTIME) {
2265
+ return { dir: process.env.NOMOS_CANDIDATE_RUNTIME, candidate: true };
2266
+ }
2267
+ if (process.env.NOMOS_OFFLINE_RUNTIME) {
2268
+ return { dir: process.env.NOMOS_OFFLINE_RUNTIME, candidate: false };
2269
+ }
2270
+ return null;
2271
+ }
2272
+ function selectedRuntimeDir() {
2273
+ return explicitRuntimeDir()?.dir ?? path.join(configDir(), "runtime");
2274
+ }
2230
2275
  function firstExisting(...paths) {
2231
2276
  for (const p of paths) {
2232
2277
  if (p && existsSync2(p)) return p;
@@ -2272,21 +2317,39 @@ function capabilitiesForKernelHash(hash) {
2272
2317
  }
2273
2318
  var DEFAULT_KERNEL_SOURCE = "https://nomos.captainapp.co.uk";
2274
2319
  async function resolveTestMintWasm(kernelSource) {
2275
- const runtimeCache = path.join(configDir(), "runtime");
2320
+ const explicitRuntime = explicitRuntimeDir();
2321
+ const runtimeCache = selectedRuntimeDir();
2276
2322
  const cachePath = path.join(runtimeCache, "holon-testmint.wasm");
2323
+ if (explicitRuntime) {
2324
+ if (existsSync2(cachePath)) {
2325
+ const bytes = readFileSync2(cachePath);
2326
+ if (isTestMintBytes(bytes)) {
2327
+ return { wasmPath: cachePath, wasmBytes: bytes, kernelKind: "test-mint", kernelSource: "explicit-runtime" };
2328
+ }
2329
+ }
2330
+ if (explicitRuntime.candidate || String(process.env.NOMOS_RUNTIME_REFRESH || "auto").toLowerCase() === "never") {
2331
+ throw new Error(
2332
+ `explicit runtime is missing a valid test-mint kernel at ${cachePath}; hydrate that exact runtime bundle before running the generated proof`
2333
+ );
2334
+ }
2335
+ }
2277
2336
  const local = process.env.NOMOS_LOCAL_WASM;
2278
- if (local && existsSync2(local)) {
2337
+ if (!explicitRuntime && local && existsSync2(local)) {
2279
2338
  const bytes = readFileSync2(local);
2280
2339
  if (isTestMintBytes(bytes)) return { wasmPath: local, wasmBytes: bytes, kernelKind: "test-mint", kernelSource: "NOMOS_LOCAL_WASM" };
2281
2340
  }
2282
2341
  const bundled = path.join(DIR, "kernel-testmint.wasm");
2283
- if (existsSync2(bundled)) {
2342
+ if (!explicitRuntime && existsSync2(bundled)) {
2284
2343
  const bytes = readFileSync2(bundled);
2285
2344
  if (isTestMintBytes(bytes)) return { wasmPath: bundled, wasmBytes: bytes, kernelKind: "test-mint", kernelSource: "bundled" };
2286
2345
  }
2287
- if (existsSync2(cachePath)) {
2346
+ if (!explicitRuntime && existsSync2(cachePath)) {
2288
2347
  const bytes = readFileSync2(cachePath);
2289
- if (isTestMintBytes(bytes)) return { wasmPath: cachePath, wasmBytes: bytes, kernelKind: "test-mint", kernelSource: "cache" };
2348
+ const sha = createHash2("sha256").update(bytes).digest("hex");
2349
+ const currentTestMint = DEPLOYED_KERNELS.find((entry) => /test-mint/i.test(entry.note));
2350
+ if (isTestMintBytes(bytes) && currentTestMint?.hash === sha) {
2351
+ return { wasmPath: cachePath, wasmBytes: bytes, kernelKind: "test-mint", kernelSource: "cache" };
2352
+ }
2290
2353
  }
2291
2354
  const src = String(kernelSource || process.env.NOMOS_KERNEL_SOURCE || DEFAULT_KERNEL_SOURCE).replace(/\/+$/, "");
2292
2355
  const url = `${src}/v1/runtime/holon-testmint.wasm`;
@@ -2307,7 +2370,8 @@ async function resolveTestMintWasm(kernelSource) {
2307
2370
  );
2308
2371
  }
2309
2372
  async function loadRuntime(opts = {}) {
2310
- const runtimeCache = path.join(configDir(), "runtime");
2373
+ const explicitRuntime = explicitRuntimeDir();
2374
+ const runtimeCache = selectedRuntimeDir();
2311
2375
  const repoDomainsDir = path.join(REPO_ROOT, "cloud/cloudflare-shell/container/domains");
2312
2376
  const vendoredFrameworkDir = path.join(DIR, "framework");
2313
2377
  let wasmPath, wasmBytes, kernelKind, kernelSource;
@@ -2315,9 +2379,10 @@ async function loadRuntime(opts = {}) {
2315
2379
  ({ wasmPath, wasmBytes, kernelKind, kernelSource } = await resolveTestMintWasm(opts.kernelSource));
2316
2380
  } else {
2317
2381
  wasmPath = firstExisting(
2318
- process.env.NOMOS_LOCAL_WASM,
2319
- path.join(REPO_ROOT, "cloud/cloudflare-shell/container/vendor/wasm_git_holon.wasm"),
2320
- path.join(runtimeCache, "holon.wasm")
2382
+ explicitRuntime ? path.join(runtimeCache, "holon.wasm") : null,
2383
+ explicitRuntime ? null : process.env.NOMOS_LOCAL_WASM,
2384
+ explicitRuntime ? null : path.join(REPO_ROOT, "cloud/cloudflare-shell/container/vendor/wasm_git_holon.wasm"),
2385
+ explicitRuntime ? null : path.join(runtimeCache, "holon.wasm")
2321
2386
  );
2322
2387
  if (!wasmPath) {
2323
2388
  throw new Error(
@@ -2331,7 +2396,16 @@ async function loadRuntime(opts = {}) {
2331
2396
  const repoBootstrap = firstExisting(path.join(repoDomainsDir, "domain_bootstrap.package.usda"));
2332
2397
  const repoNomos = firstExisting(path.join(repoDomainsDir, "domain_nomos.package.usda"));
2333
2398
  let bootstrapPkg, nomosPkg;
2334
- if (repoBootstrap && repoNomos) {
2399
+ const explicitPackages = explicitRuntime ? path.join(runtimeCache, "packages.json") : null;
2400
+ if (explicitPackages && existsSync2(explicitPackages)) {
2401
+ const pkgs = JSON.parse(readFileSync2(explicitPackages, "utf8"));
2402
+ bootstrapPkg = pkgs.bootstrap;
2403
+ nomosPkg = pkgs.nomos;
2404
+ } else if (explicitRuntime) {
2405
+ throw new Error(
2406
+ `explicit runtime is missing framework packages at ${explicitPackages}; hydrate that exact runtime bundle before starting the local Nomos cloud`
2407
+ );
2408
+ } else if (repoBootstrap && repoNomos) {
2335
2409
  bootstrapPkg = readFileSync2(repoBootstrap, "utf8");
2336
2410
  nomosPkg = readFileSync2(repoNomos, "utf8");
2337
2411
  } else if (existsSync2(path.join(vendoredFrameworkDir, "domain_bootstrap.package.usda"))) {
@@ -2452,6 +2526,9 @@ async function startDevCloud(opts = {}) {
2452
2526
  } catch {
2453
2527
  return false;
2454
2528
  }
2529
+ if (process.env.NOMOS_TEST_DIAGNOSTICS === "1") {
2530
+ console.error(`[dev-cloud] read-posture ${ws} ${kind} ${JSON.stringify(posture)}`);
2531
+ }
2455
2532
  if (posture && posture.private && !posture.allowedAny) {
2456
2533
  sendJson(res, bulkReadForbidden(ws, kind, posture), 403);
2457
2534
  return true;
@@ -2925,6 +3002,9 @@ async function startDevCloud(opts = {}) {
2925
3002
  });
2926
3003
  async function gitBackend(req, res, repoPathInfo, ws) {
2927
3004
  const body = await readBody(req);
3005
+ if (process.env.NOMOS_TEST_DIAGNOSTICS === "1") {
3006
+ console.error(`[dev-cloud] git-http ${req.method || ""} /${repoPathInfo} body=${body.byteLength}`);
3007
+ }
2928
3008
  let sessionPush = false;
2929
3009
  if (ws && req.method === "POST" && /git-receive-pack/.test(repoPathInfo)) {
2930
3010
  try {
@@ -2945,7 +3025,10 @@ async function startDevCloud(opts = {}) {
2945
3025
  contentType: req.headers["content-type"],
2946
3026
  body
2947
3027
  });
2948
- res.writeHead(out.status, { ...out.headers, ...CORS });
3028
+ if (process.env.NOMOS_TEST_DIAGNOSTICS === "1") {
3029
+ console.error(`[dev-cloud] git-http ${req.method || ""} /${repoPathInfo} -> ${out.status} body=${out.body.byteLength}`);
3030
+ }
3031
+ res.writeHead(out.status, { ...out.headers, ...CORS, connection: "close" });
2949
3032
  res.end(out.body);
2950
3033
  if (sessionPush && ws) scheduleAdmit(ws);
2951
3034
  }
@@ -3061,8 +3144,11 @@ function parseArgs(argv) {
3061
3144
  else if (a === "--data") o.data = argv[++i];
3062
3145
  else if (a === "--firebase-project") o.firebaseProject = argv[++i];
3063
3146
  else if (a === "--platform") o.platform = argv[++i];
3064
- else if (a === "--deploy") o.deploy = argv[++i];
3065
- else if (a === "--auth-provider") o.authProvider = argv[++i];
3147
+ else if (a === "--deploy") {
3148
+ const deploy2 = argv[++i];
3149
+ o.deploy = deploy2;
3150
+ (o.deploys ??= []).push(deploy2);
3151
+ } else if (a === "--auth-provider") o.authProvider = argv[++i];
3066
3152
  else if (a === "--bootstrap") o.bootstrap = true;
3067
3153
  else if (a === "--attested") o.attested = true;
3068
3154
  else if (a === "--kernel-source") o.kernelSource = argv[++i];
@@ -3107,6 +3193,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
3107
3193
  });
3108
3194
  }
3109
3195
  export {
3196
+ resolveTestMintWasm,
3110
3197
  startDevCloud,
3111
3198
  startGeneratedApplicationProofCloud
3112
3199
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.102.0",
3
+ "version": "0.102.2",
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",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@bjorn3/browser_wasi_shim": "0.4.2",
32
- "@githolon/dsl": "^0.102.0",
32
+ "@githolon/dsl": "^0.102.2",
33
33
  "isomorphic-git": "^1.38.4"
34
34
  },
35
35
  "devDependencies": {