githolon 0.48.1 → 0.50.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 +173 -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
@@ -3671,6 +3779,20 @@ function runCompile(args) {
3671
3779
  const r = spawnSync(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
3672
3780
  return r.status ?? 1;
3673
3781
  }
3782
+ function resolveCheckLauncher(cwd) {
3783
+ const launcher = resolveCompileLauncher(cwd);
3784
+ return launcher === void 0 ? void 0 : join3(dirname(launcher), "check_package.mjs");
3785
+ }
3786
+ function runCheck(args) {
3787
+ const launcher = resolveCheckLauncher(process.cwd());
3788
+ if (launcher === void 0) {
3789
+ process.stderr.write(`error: ${NO_DSL_REMEDY}
3790
+ `);
3791
+ return 1;
3792
+ }
3793
+ const r = spawnSync(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
3794
+ return r.status ?? 1;
3795
+ }
3674
3796
  function compileAsync(cwd, args = []) {
3675
3797
  const launcher = resolveCompileLauncher(cwd);
3676
3798
  const t0 = performance.now();
@@ -4826,9 +4948,15 @@ The inner loop:
4826
4948
  --query <id> [--param k=v] keys from the chain, read private fields in cleartext
4827
4949
 
4828
4950
  Authoring:
4951
+ githolon check [config] run the author-time gate (static twins) on
4952
+ ./nomos.package.mjs \u2014 the unified report; exits
4953
+ non-zero on any REFUSE (compile runs it implicitly)
4829
4954
  githolon compile [compiler args] compile the package by ./nomos.package.mjs
4830
4955
  githolon proof [build/<name>.proof.mts] run the proof GENERATED from your law, live
4831
4956
  (every compile emits it; ALL GREEN or it names the jam)
4957
+ githolon harness-install --deploy <deploy.json[,...]> offline install for the headless TEST HARNESS:
4958
+ --workspace <ws> --out <snapshot> install tenant law IN-CHAIN (no cloud), write the
4959
+ restore snapshot, print { ok, snapshot, lawHashes }
4832
4960
  githolon generate <domain|aggregate|intent> <name> [options]
4833
4961
  githolon g <domain|aggregate|intent> <name> [options]
4834
4962
 
@@ -5009,10 +5137,10 @@ async function runProof(args) {
5009
5137
  let proofPath;
5010
5138
  if (explicit !== void 0) {
5011
5139
  proofPath = resolve3(process.cwd(), explicit);
5012
- if (!existsSync10(proofPath)) return refuse(`proof not found: ${proofPath} \u2014 run \`githolon compile\` to (re)generate it`);
5140
+ if (!existsSync11(proofPath)) return refuse(`proof not found: ${proofPath} \u2014 run \`githolon compile\` to (re)generate it`);
5013
5141
  } else {
5014
- const buildDir = join11(process.cwd(), "build");
5015
- if (!existsSync10(buildDir)) {
5142
+ const buildDir = join12(process.cwd(), "build");
5143
+ if (!existsSync11(buildDir)) {
5016
5144
  return refuse("no build/ directory here \u2014 run `githolon compile` first (every compile generates build/<name>.proof.mts from your law)");
5017
5145
  }
5018
5146
  const proofs = readdirSync4(buildDir).filter((f) => f.endsWith(".proof.mts"));
@@ -5022,7 +5150,7 @@ async function runProof(args) {
5022
5150
  if (proofs.length > 1) {
5023
5151
  return refuse(`found ${proofs.length} proofs (${proofs.join(", ")}) \u2014 name one: githolon proof build/<name>.proof.mts`);
5024
5152
  }
5025
- proofPath = join11(buildDir, proofs[0]);
5153
+ proofPath = join12(buildDir, proofs[0]);
5026
5154
  }
5027
5155
  if (!live) {
5028
5156
  try {
@@ -5035,14 +5163,14 @@ async function runProof(args) {
5035
5163
  }
5036
5164
  const resolvePkgDir = (name, fromDir) => {
5037
5165
  try {
5038
- return dirname5(createRequire2(pathToFileURL4(join11(fromDir, "noop.js"))).resolve(`${name}/package.json`));
5166
+ return dirname5(createRequire2(pathToFileURL4(join12(fromDir, "noop.js"))).resolve(`${name}/package.json`));
5039
5167
  } catch {
5040
5168
  return void 0;
5041
5169
  }
5042
5170
  };
5043
5171
  const dslDir = (() => {
5044
5172
  try {
5045
- return dirname5(createRequire2(pathToFileURL4(join11(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
5173
+ return dirname5(createRequire2(pathToFileURL4(join12(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
5046
5174
  } catch {
5047
5175
  try {
5048
5176
  return dirname5(createRequire2(import.meta.url).resolve("@githolon/dsl/package.json"));
@@ -5055,9 +5183,9 @@ async function runProof(args) {
5055
5183
  if (tsxDir === void 0) {
5056
5184
  return refuse("tsx not found \u2014 add @githolon/dsl to your project's dependencies (tsx rides along) and npm install");
5057
5185
  }
5058
- const tsxPkg = JSON.parse(readFileSync11(join11(tsxDir, "package.json"), "utf8"));
5186
+ const tsxPkg = JSON.parse(readFileSync12(join12(tsxDir, "package.json"), "utf8"));
5059
5187
  const tsxBinRel = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.["tsx"];
5060
- const tsxCli = join11(tsxDir, tsxBinRel ?? "dist/cli.mjs");
5188
+ const tsxCli = join12(tsxDir, tsxBinRel ?? "dist/cli.mjs");
5061
5189
  console.log("githolon proof --live \u2014 the full cloud loop (throwaway workspace, retired on exit" + (keep ? "; --keep: kept" : "") + ")");
5062
5190
  const { wsCreate: wsCreate2, wsRetire: wsRetire2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
5063
5191
  const { resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
@@ -5165,9 +5293,33 @@ async function main(argv) {
5165
5293
  if (argv[0] === "compile") {
5166
5294
  return runCompile(argv.slice(1));
5167
5295
  }
5296
+ if (argv[0] === "check") {
5297
+ return runCheck(argv.slice(1));
5298
+ }
5168
5299
  if (argv[0] === "proof") {
5169
5300
  return runProof(argv.slice(1));
5170
5301
  }
5302
+ if (argv[0] === "harness-install") {
5303
+ const rest = argv.slice(1);
5304
+ const pull = (flag) => {
5305
+ const at = rest.indexOf(flag);
5306
+ return at >= 0 ? rest[at + 1] : void 0;
5307
+ };
5308
+ const deployArg = pull("--deploy");
5309
+ const workspace = pull("--workspace") ?? "test-ws";
5310
+ const out12 = pull("--out");
5311
+ const runtime = pull("--runtime");
5312
+ const deploy2 = (deployArg ?? "").split(",").map((s) => s.trim()).filter(Boolean);
5313
+ if (deploy2.length === 0 || out12 === void 0) {
5314
+ process.stderr.write(
5315
+ `error: usage: githolon harness-install --deploy <deploy.json[,deploy.json...]> --workspace <ws> --out <snapshotPath> [--runtime <dir>]
5316
+ `
5317
+ );
5318
+ return 1;
5319
+ }
5320
+ const { harnessInstall: harnessInstall2 } = await Promise.resolve().then(() => (init_harness(), harness_exports));
5321
+ return harnessInstall2({ deploy: deploy2, workspace, out: out12, ...runtime !== void 0 ? { runtime } : {} });
5322
+ }
5171
5323
  if (argv[0] === "dev") {
5172
5324
  const rest = argv.slice(1);
5173
5325
  let cloud;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.48.1",
3
+ "version": "0.50.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.50.0",
33
+ "@githolon/dsl": "^0.50.0",
34
34
  "isomorphic-git": "^1.38.4"
35
35
  },
36
36
  "devDependencies": {