githolon 0.48.1 → 0.49.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.
Files changed (2) hide show
  1. package/dist/cli.mjs +153 -21
  2. package/package.json +3 -3
package/dist/cli.mjs CHANGED
@@ -1299,6 +1299,44 @@ var init_git_fs = __esm({
1299
1299
  });
1300
1300
 
1301
1301
  // vendor/engine/tree.mjs
1302
+ function flatten(dir, prefix, out12) {
1303
+ for (const [name, inode] of dir.contents) {
1304
+ const path = prefix ? prefix + "/" + name : name;
1305
+ if (inode.contents instanceof Map) {
1306
+ out12.push({ path, dir: true });
1307
+ flatten(inode, path, out12);
1308
+ } else {
1309
+ out12.push({ path, dir: false, bytes: inode.data ?? new Uint8Array(0) });
1310
+ }
1311
+ }
1312
+ }
1313
+ function serializeTree(workTree) {
1314
+ const entries = [];
1315
+ flatten(workTree, "", entries);
1316
+ const chunks = [];
1317
+ const header = new Uint8Array(4);
1318
+ new DataView(header.buffer).setUint32(0, entries.length, true);
1319
+ chunks.push(header);
1320
+ for (const e of entries) {
1321
+ const pathBytes = enc.encode(e.path);
1322
+ const body = e.dir ? new Uint8Array(0) : e.bytes ?? new Uint8Array(0);
1323
+ const meta = new Uint8Array(9);
1324
+ const dv = new DataView(meta.buffer);
1325
+ dv.setUint8(0, e.dir ? 1 : 0);
1326
+ dv.setUint32(1, pathBytes.length, true);
1327
+ dv.setUint32(5, body.length, true);
1328
+ chunks.push(meta, pathBytes, body);
1329
+ }
1330
+ let total = 0;
1331
+ for (const c of chunks) total += c.length;
1332
+ const out12 = new Uint8Array(total);
1333
+ let off = 0;
1334
+ for (const c of chunks) {
1335
+ out12.set(c, off);
1336
+ off += c.length;
1337
+ }
1338
+ return out12;
1339
+ }
1302
1340
  var enc, dec;
1303
1341
  var init_tree = __esm({
1304
1342
  "vendor/engine/tree.mjs"() {
@@ -2268,6 +2306,74 @@ var init_proof_offline = __esm({
2268
2306
  }
2269
2307
  });
2270
2308
 
2309
+ // src/harness.ts
2310
+ var harness_exports = {};
2311
+ __export(harness_exports, {
2312
+ harnessInstall: () => harnessInstall
2313
+ });
2314
+ import { existsSync as existsSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
2315
+ import { join as join10 } from "node:path";
2316
+ import { randomBytes as randomBytes3 } from "node:crypto";
2317
+ async function harnessInstall(opts) {
2318
+ const { deploy: deployPaths, workspace, out: outPath } = opts;
2319
+ if (deployPaths.length === 0) die("no --deploy JSON path(s) given");
2320
+ const runtimeDir = opts.runtime || process.env["NOMOS_OFFLINE_RUNTIME"] || join10(configDir(), "runtime");
2321
+ const wasmFile = join10(runtimeDir, "holon.wasm");
2322
+ const pkgsFile = join10(runtimeDir, "packages.json");
2323
+ if (!existsSync9(wasmFile) || !existsSync9(pkgsFile)) {
2324
+ die(
2325
+ `runtime cache missing at ${runtimeDir} (holon.wasm + packages.json). Warm it once with a \`githolon\` run (it fetches + caches the runtime), then re-run offline.`
2326
+ );
2327
+ }
2328
+ const wasm = readFileSync11(wasmFile);
2329
+ const pkgs = JSON.parse(readFileSync11(pkgsFile, "utf8"));
2330
+ const replica = BigInt(`0x${randomBytes3(8).toString("hex")}`) & (1n << 63n) - 1n;
2331
+ const eng = await createEngine({
2332
+ wasmModule: await WebAssembly.compile(wasm),
2333
+ bootstrapPkg: pkgs.bootstrap,
2334
+ nomosPkg: pkgs.nomos,
2335
+ replica,
2336
+ installedBy: "nomos-test-harness"
2337
+ });
2338
+ await mountFresh(eng, workspace);
2339
+ author(eng, workspace, "bootstrap", "installDomain", installPayload(eng.hashes.nomos, eng.nomosPkg, "nomos-test-harness"), "");
2340
+ const lawHashes = [];
2341
+ for (const p of deployPaths) {
2342
+ if (!existsSync9(p)) die(`deploy JSON not found: ${p} \u2014 run \`npx githolon compile\` first`);
2343
+ const deploy2 = JSON.parse(readFileSync11(p, "utf8"));
2344
+ const usda = deploy2.packageUsda;
2345
+ if (typeof usda !== "string" || !usda.startsWith("#usda")) die(`${p} has no #usda packageUsda`);
2346
+ const lawHash = await sha256hex(usda);
2347
+ author(eng, workspace, "nomos", "installDomain", installPayload(lawHash, usda, "nomos-test-harness"), eng.hashes.nomos);
2348
+ lawHashes.push(lawHash);
2349
+ process.stderr.write(`harness-install: installed ${p} (law ${lawHash.slice(0, 12)}\u2026)
2350
+ `);
2351
+ }
2352
+ const wsNode = eng.preopen.dir.contents.get("ws").contents.get(workspace);
2353
+ if (!wsNode) die(`internal: workspace tree '${workspace}' not found after install`);
2354
+ const treeBytes = serializeTree(wsNode);
2355
+ writeFileSync6(outPath, treeBytes);
2356
+ process.stderr.write(`harness-install: snapshot written (${treeBytes.length} bytes) \u2192 ${outPath}
2357
+ `);
2358
+ process.stdout.write(JSON.stringify({ ok: true, snapshot: outPath, workspace, lawHashes }) + "\n");
2359
+ return 0;
2360
+ }
2361
+ var die;
2362
+ var init_harness = __esm({
2363
+ "src/harness.ts"() {
2364
+ "use strict";
2365
+ init_engine();
2366
+ init_tree();
2367
+ init_local_holon();
2368
+ init_cloud();
2369
+ die = (msg) => {
2370
+ process.stderr.write(`harness-install: ${msg}
2371
+ `);
2372
+ process.exit(1);
2373
+ };
2374
+ }
2375
+ });
2376
+
2271
2377
  // src/scene_projector.ts
2272
2378
  import { createHash as createHash4 } from "node:crypto";
2273
2379
  function fnv1a32(s) {
@@ -2517,8 +2623,10 @@ function glyphSignature(structJson, name, partCount) {
2517
2623
  return { structureHash: h, facetCount, hue, hueBase, elongation, size, color: hslToRgb(hue, 0.62, 0.6) };
2518
2624
  }
2519
2625
  function packageLayers(packageUsda) {
2626
+ const b = /nomos:usdJsonB64 = "([A-Za-z0-9+/=]+)"/.exec(packageUsda);
2627
+ if (b) return JSON.parse(Buffer.from(b[1], "base64").toString("utf8")).layers;
2520
2628
  const m = /nomos:usdJsonHex = "([0-9a-f]+)"/.exec(packageUsda);
2521
- if (!m) throw new Error("a chain-installed package carries no nomos:usdJsonHex \u2014 not an openusd-ir package");
2629
+ if (!m) throw new Error("a chain-installed package carries no nomos:usdJson blob \u2014 not an openusd-ir package");
2522
2630
  return JSON.parse(Buffer.from(m[1], "hex").toString("utf8")).layers;
2523
2631
  }
2524
2632
  function lawInstallsFromChain(entries) {
@@ -3322,8 +3430,8 @@ var scene_exports = {};
3322
3430
  __export(scene_exports, {
3323
3431
  scene: () => scene
3324
3432
  });
3325
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, writeFileSync as writeFileSync6 } from "node:fs";
3326
- import { join as join10, resolve as resolve2 } from "node:path";
3433
+ import { existsSync as existsSync10, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7 } from "node:fs";
3434
+ import { join as join11, resolve as resolve2 } from "node:path";
3327
3435
  import { createHash as createHash5 } from "node:crypto";
3328
3436
  import git3 from "isomorphic-git";
3329
3437
  async function walkChain2(eng, ws) {
@@ -3344,8 +3452,8 @@ async function projectOnce(cloud, target, isDir, name) {
3344
3452
  const { eng } = await holonEngine(cloud, void 0, "githolon-scene");
3345
3453
  const SOURCE3 = "source";
3346
3454
  if (isDir) {
3347
- const gitDir = existsSync9(join10(target, ".git")) ? join10(target, ".git") : target;
3348
- if (!existsSync9(join10(gitDir, "HEAD"))) throw new Error(`${target} is not a git repo (no HEAD)`);
3455
+ const gitDir = existsSync10(join11(target, ".git")) ? join11(target, ".git") : target;
3456
+ if (!existsSync10(join11(gitDir, "HEAD"))) throw new Error(`${target} is not a git repo (no HEAD)`);
3349
3457
  await mountFresh(eng, SOURCE3);
3350
3458
  eng.preopen.dir.contents.get("ws").contents.get(SOURCE3).contents.set("nomos.git", readTreeFromDisk(gitDir));
3351
3459
  } else {
@@ -3404,7 +3512,7 @@ async function projectOnce(cloud, target, isDir, name) {
3404
3512
  }
3405
3513
  async function scene(target, opts) {
3406
3514
  const cloud = cloudBase(opts.cloud);
3407
- const isDir = existsSync9(target) || target.includes("/") || target.startsWith(".");
3515
+ const isDir = existsSync10(target) || target.includes("/") || target.startsWith(".");
3408
3516
  const name = isDir ? (resolve2(target).split("/").filter(Boolean).pop() ?? "scene").replace(/\.git$/, "") : target;
3409
3517
  out11(`scene \u2014 ${name} (${isDir ? resolve2(target) : `${cloud} :: ${target}`})`);
3410
3518
  let first, second;
@@ -3424,13 +3532,13 @@ async function scene(target, opts) {
3424
3532
  err11(`the emitted stage violates the portable profile: ${violations.join("; ")}`);
3425
3533
  return 1;
3426
3534
  }
3427
- const outDir = resolve2(opts.out ?? join10("scene", name));
3535
+ const outDir = resolve2(opts.out ?? join11("scene", name));
3428
3536
  mkdirSync4(outDir, { recursive: true });
3429
- const usdaPath = join10(outDir, `${name}.usda`);
3430
- const usdzPath = join10(outDir, `${name}.usdz`);
3537
+ const usdaPath = join11(outDir, `${name}.usda`);
3538
+ const usdzPath = join11(outDir, `${name}.usdz`);
3431
3539
  const usdaBytes = new TextEncoder().encode(first.usda);
3432
- writeFileSync6(usdaPath, usdaBytes);
3433
- writeFileSync6(usdzPath, usdzPack([[`${name}.usda`, usdaBytes]]));
3540
+ writeFileSync7(usdaPath, usdaBytes);
3541
+ writeFileSync7(usdzPath, usdzPack([[`${name}.usda`, usdaBytes]]));
3434
3542
  const s = first.stats;
3435
3543
  out11(` verify_chain ${s.verdictLine}`);
3436
3544
  out11(` law canopy ${s.nodes} node(s), ${s.edges} edge(s) \u2014 from the chain's own installed packages`);
@@ -3456,10 +3564,10 @@ var init_scene = __esm({
3456
3564
  });
3457
3565
 
3458
3566
  // src/cli.ts
3459
- import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync11 } from "node:fs";
3567
+ import { existsSync as existsSync11, readdirSync as readdirSync4, readFileSync as readFileSync12 } from "node:fs";
3460
3568
  import { spawnSync as spawnSync4 } from "node:child_process";
3461
3569
  import { createRequire as createRequire2 } from "node:module";
3462
- import { dirname as dirname5, join as join11, resolve as resolve3 } from "node:path";
3570
+ import { dirname as dirname5, join as join12, resolve as resolve3 } from "node:path";
3463
3571
  import { pathToFileURL as pathToFileURL4 } from "node:url";
3464
3572
 
3465
3573
  // src/generate.ts
@@ -4829,6 +4937,9 @@ Authoring:
4829
4937
  githolon compile [compiler args] compile the package by ./nomos.package.mjs
4830
4938
  githolon proof [build/<name>.proof.mts] run the proof GENERATED from your law, live
4831
4939
  (every compile emits it; ALL GREEN or it names the jam)
4940
+ githolon harness-install --deploy <deploy.json[,...]> offline install for the headless TEST HARNESS:
4941
+ --workspace <ws> --out <snapshot> install tenant law IN-CHAIN (no cloud), write the
4942
+ restore snapshot, print { ok, snapshot, lawHashes }
4832
4943
  githolon generate <domain|aggregate|intent> <name> [options]
4833
4944
  githolon g <domain|aggregate|intent> <name> [options]
4834
4945
 
@@ -5009,10 +5120,10 @@ async function runProof(args) {
5009
5120
  let proofPath;
5010
5121
  if (explicit !== void 0) {
5011
5122
  proofPath = resolve3(process.cwd(), explicit);
5012
- if (!existsSync10(proofPath)) return refuse(`proof not found: ${proofPath} \u2014 run \`githolon compile\` to (re)generate it`);
5123
+ if (!existsSync11(proofPath)) return refuse(`proof not found: ${proofPath} \u2014 run \`githolon compile\` to (re)generate it`);
5013
5124
  } else {
5014
- const buildDir = join11(process.cwd(), "build");
5015
- if (!existsSync10(buildDir)) {
5125
+ const buildDir = join12(process.cwd(), "build");
5126
+ if (!existsSync11(buildDir)) {
5016
5127
  return refuse("no build/ directory here \u2014 run `githolon compile` first (every compile generates build/<name>.proof.mts from your law)");
5017
5128
  }
5018
5129
  const proofs = readdirSync4(buildDir).filter((f) => f.endsWith(".proof.mts"));
@@ -5022,7 +5133,7 @@ async function runProof(args) {
5022
5133
  if (proofs.length > 1) {
5023
5134
  return refuse(`found ${proofs.length} proofs (${proofs.join(", ")}) \u2014 name one: githolon proof build/<name>.proof.mts`);
5024
5135
  }
5025
- proofPath = join11(buildDir, proofs[0]);
5136
+ proofPath = join12(buildDir, proofs[0]);
5026
5137
  }
5027
5138
  if (!live) {
5028
5139
  try {
@@ -5035,14 +5146,14 @@ async function runProof(args) {
5035
5146
  }
5036
5147
  const resolvePkgDir = (name, fromDir) => {
5037
5148
  try {
5038
- return dirname5(createRequire2(pathToFileURL4(join11(fromDir, "noop.js"))).resolve(`${name}/package.json`));
5149
+ return dirname5(createRequire2(pathToFileURL4(join12(fromDir, "noop.js"))).resolve(`${name}/package.json`));
5039
5150
  } catch {
5040
5151
  return void 0;
5041
5152
  }
5042
5153
  };
5043
5154
  const dslDir = (() => {
5044
5155
  try {
5045
- return dirname5(createRequire2(pathToFileURL4(join11(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
5156
+ return dirname5(createRequire2(pathToFileURL4(join12(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
5046
5157
  } catch {
5047
5158
  try {
5048
5159
  return dirname5(createRequire2(import.meta.url).resolve("@githolon/dsl/package.json"));
@@ -5055,9 +5166,9 @@ async function runProof(args) {
5055
5166
  if (tsxDir === void 0) {
5056
5167
  return refuse("tsx not found \u2014 add @githolon/dsl to your project's dependencies (tsx rides along) and npm install");
5057
5168
  }
5058
- const tsxPkg = JSON.parse(readFileSync11(join11(tsxDir, "package.json"), "utf8"));
5169
+ const tsxPkg = JSON.parse(readFileSync12(join12(tsxDir, "package.json"), "utf8"));
5059
5170
  const tsxBinRel = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.["tsx"];
5060
- const tsxCli = join11(tsxDir, tsxBinRel ?? "dist/cli.mjs");
5171
+ const tsxCli = join12(tsxDir, tsxBinRel ?? "dist/cli.mjs");
5061
5172
  console.log("githolon proof --live \u2014 the full cloud loop (throwaway workspace, retired on exit" + (keep ? "; --keep: kept" : "") + ")");
5062
5173
  const { wsCreate: wsCreate2, wsRetire: wsRetire2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
5063
5174
  const { resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
@@ -5168,6 +5279,27 @@ async function main(argv) {
5168
5279
  if (argv[0] === "proof") {
5169
5280
  return runProof(argv.slice(1));
5170
5281
  }
5282
+ if (argv[0] === "harness-install") {
5283
+ const rest = argv.slice(1);
5284
+ const pull = (flag) => {
5285
+ const at = rest.indexOf(flag);
5286
+ return at >= 0 ? rest[at + 1] : void 0;
5287
+ };
5288
+ const deployArg = pull("--deploy");
5289
+ const workspace = pull("--workspace") ?? "test-ws";
5290
+ const out12 = pull("--out");
5291
+ const runtime = pull("--runtime");
5292
+ const deploy2 = (deployArg ?? "").split(",").map((s) => s.trim()).filter(Boolean);
5293
+ if (deploy2.length === 0 || out12 === void 0) {
5294
+ process.stderr.write(
5295
+ `error: usage: githolon harness-install --deploy <deploy.json[,deploy.json...]> --workspace <ws> --out <snapshotPath> [--runtime <dir>]
5296
+ `
5297
+ );
5298
+ return 1;
5299
+ }
5300
+ const { harnessInstall: harnessInstall2 } = await Promise.resolve().then(() => (init_harness(), harness_exports));
5301
+ return harnessInstall2({ deploy: deploy2, workspace, out: out12, ...runtime !== void 0 ? { runtime } : {} });
5302
+ }
5171
5303
  if (argv[0] === "dev") {
5172
5304
  const rest = argv.slice(1);
5173
5305
  let cloud;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.48.1",
3
+ "version": "0.49.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",
@@ -29,8 +29,8 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@bjorn3/browser_wasi_shim": "0.4.2",
32
- "@githolon/client": "^0.48.1",
33
- "@githolon/dsl": "^0.48.1",
32
+ "@githolon/client": "^0.49.0",
33
+ "@githolon/dsl": "^0.49.0",
34
34
  "isomorphic-git": "^1.38.4"
35
35
  },
36
36
  "devDependencies": {