githolon 0.53.0 → 0.54.1

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 +82 -7
  2. package/package.json +3 -3
package/dist/cli.mjs CHANGED
@@ -1326,6 +1326,20 @@ function runCheck(args) {
1326
1326
  const r = spawnSync(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
1327
1327
  return r.status ?? 1;
1328
1328
  }
1329
+ function resolveCompatLauncher(cwd) {
1330
+ const launcher = resolveCompileLauncher(cwd);
1331
+ return launcher === void 0 ? void 0 : join4(dirname2(launcher), "compat_package.mjs");
1332
+ }
1333
+ function runCompat(args) {
1334
+ const launcher = resolveCompatLauncher(process.cwd());
1335
+ if (launcher === void 0) {
1336
+ process.stderr.write(`error: ${NO_DSL_REMEDY}
1337
+ `);
1338
+ return 1;
1339
+ }
1340
+ const r = spawnSync(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
1341
+ return r.status ?? 1;
1342
+ }
1329
1343
  function resolveLspLauncher(cwd) {
1330
1344
  const launcher = resolveCompileLauncher(cwd);
1331
1345
  return launcher === void 0 ? void 0 : join4(dirname2(launcher), "lsp_server.mjs");
@@ -1877,7 +1891,7 @@ function parseAttestedReadNeed(error) {
1877
1891
  function verifyChainLocal(eng, ws) {
1878
1892
  return JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "verifyChain" }), branch: BRANCH }, eng.STDERR));
1879
1893
  }
1880
- var enc3, dec3, BRANCH, RESULT_PACK_INLINE_MAX, repoArgOf, gitdirOf, unpack, repoArgOfGitdir, bytesFromB64, kgit, installPayload, fullRef, applyPackInto, custodyLsRefs, qById, query, attestedRead, cryptoUnwrapKey, count, sum, spatialWithin;
1894
+ var enc3, dec3, BRANCH, RESULT_PACK_INLINE_MAX, repoArgOf, gitdirOf, unpack, repoArgOfGitdir, bytesFromB64, kgit, installPayload, fullRef, applyPackInto, custodyLsRefs, qById, query, attestedRead, cryptoUnwrapKey, count, sum, spatialBboxParams, spatialWithin;
1881
1895
  var init_engine = __esm({
1882
1896
  "vendor/engine/engine.mjs"() {
1883
1897
  "use strict";
@@ -1943,7 +1957,11 @@ var init_engine = __esm({
1943
1957
  cryptoUnwrapKey = (eng, { secret, hpkeEpk, ct }) => JSON.parse(call(eng.ex, "query", { queryBytes: b64Json({ op: "cryptoUnwrapKey", secret, hpkeEpk, ct }) }, eng.STDERR)).scopeKey;
1944
1958
  count = (eng, ws, countId, groupKey, principal = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "count", countId, groupKey }), principal, branch: BRANCH }, eng.STDERR));
1945
1959
  sum = (eng, ws, sumId, groupKey, principal = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "sum", sumId, groupKey }), principal, branch: BRANCH }, eng.STDERR));
1946
- spatialWithin = (eng, ws, spatialId, bbox, principal = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "spatial", spatialId, minLng: bbox.minLng, minLat: bbox.minLat, maxLng: bbox.maxLng, maxLat: bbox.maxLat }), principal, branch: BRANCH }, eng.STDERR));
1960
+ spatialBboxParams = (bbox) => {
1961
+ const minX = bbox.minX ?? bbox.minLng, minY = bbox.minY ?? bbox.minLat, maxX = bbox.maxX ?? bbox.maxLng, maxY = bbox.maxY ?? bbox.maxLat;
1962
+ return { minX, minY, maxX, maxY, minLng: minX, minLat: minY, maxLng: maxX, maxLat: maxY };
1963
+ };
1964
+ spatialWithin = (eng, ws, spatialId, bbox, principal = "") => JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "spatial", spatialId, ...spatialBboxParams(bbox) }), principal, branch: BRANCH }, eng.STDERR));
1947
1965
  }
1948
1966
  });
1949
1967
 
@@ -1988,6 +2006,22 @@ async function fetchRuntime(cloud) {
1988
2006
  const packages = await fetchJsonCached(`${cloud}/v1/runtime/packages`, join5(cache, "packages.json"));
1989
2007
  return { wasmBytes, packages };
1990
2008
  }
2009
+ async function refreshRuntimeDir(cloud, runtimeDir) {
2010
+ try {
2011
+ const r = await fetch(`${cloud}/v1/runtime/holon.wasm`);
2012
+ if (!r.ok) throw new Error(`runtime wasm \u2192 ${r.status}`);
2013
+ const wasmBytes = new Uint8Array(await r.arrayBuffer());
2014
+ const pkgs = await fetch(`${cloud}/v1/runtime/packages`);
2015
+ if (!pkgs.ok) throw new Error(`runtime packages \u2192 ${pkgs.status}`);
2016
+ const pkgText = await pkgs.text();
2017
+ mkdirSync4(runtimeDir, { recursive: true });
2018
+ writeFileSync5(join5(runtimeDir, "holon.wasm"), wasmBytes);
2019
+ writeFileSync5(join5(runtimeDir, "packages.json"), pkgText, "utf8");
2020
+ return true;
2021
+ } catch {
2022
+ return false;
2023
+ }
2024
+ }
1991
2025
  function writeTreeToDisk(dir, diskPath) {
1992
2026
  mkdirSync4(diskPath, { recursive: true });
1993
2027
  for (const [name, inode] of dir.contents) {
@@ -2168,7 +2202,7 @@ async function runOfflineLegs(eng, ws, lawHash, legs, frameworkHash, deployUsda)
2168
2202
  lines.push(`\u2713 declared count ${leg.count.id}(${JSON.stringify(leg.count.group)}) = 1 locally`);
2169
2203
  }
2170
2204
  if (leg.spatial !== void 0) {
2171
- const world = { minLng: -180, minLat: -90, maxLng: 180, maxLat: 90 };
2205
+ const world = { minX: -180, minY: -90, maxX: 180, maxY: 90 };
2172
2206
  const sr = spatialWithin(eng, ws, leg.spatial.id, world);
2173
2207
  const ids = (sr.rows ?? []).map((r) => r.id);
2174
2208
  if (sr.ok === false || createdId === void 0 || !ids.includes(createdId)) {
@@ -2750,15 +2784,25 @@ var init_mcp = __esm({
2750
2784
  // src/harness.ts
2751
2785
  var harness_exports = {};
2752
2786
  __export(harness_exports, {
2753
- harnessInstall: () => harnessInstall
2787
+ STALE_RUNTIME_HINT: () => STALE_RUNTIME_HINT,
2788
+ harnessInstall: () => harnessInstall,
2789
+ looksLikeStaleRuntime: () => looksLikeStaleRuntime
2754
2790
  });
2755
2791
  import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
2756
2792
  import { join as join12 } from "node:path";
2757
2793
  import { randomBytes as randomBytes3 } from "node:crypto";
2794
+ function looksLikeStaleRuntime(msg) {
2795
+ return /\bbbox param\b|missing.*param|non-numeric|unknown (op|query op)|unsupported op|unexpected (field|key)|no such op/i.test(
2796
+ msg
2797
+ );
2798
+ }
2758
2799
  async function harnessInstall(opts) {
2759
2800
  const { deploy: deployPaths, workspace, out: outPath } = opts;
2760
2801
  if (deployPaths.length === 0) die("no --deploy JSON path(s) given");
2761
2802
  const runtimeDir = opts.runtime || process.env["NOMOS_OFFLINE_RUNTIME"] || join12(configDir(), "runtime");
2803
+ const refreshed = await refreshRuntimeDir(cloudBase(), runtimeDir);
2804
+ if (refreshed) process.stderr.write(`harness-install: refreshed runtime cache from the cloud \u2192 ${runtimeDir}
2805
+ `);
2762
2806
  const wasmFile = join12(runtimeDir, "holon.wasm");
2763
2807
  const pkgsFile = join12(runtimeDir, "packages.json");
2764
2808
  if (!existsSync11(wasmFile) || !existsSync11(pkgsFile)) {
@@ -2768,6 +2812,15 @@ async function harnessInstall(opts) {
2768
2812
  }
2769
2813
  const wasm = readFileSync12(wasmFile);
2770
2814
  const pkgs = JSON.parse(readFileSync12(pkgsFile, "utf8"));
2815
+ const guarded = async (fn) => {
2816
+ try {
2817
+ return await fn();
2818
+ } catch (e) {
2819
+ const msg = e instanceof Error ? e.message : String(e);
2820
+ if (looksLikeStaleRuntime(msg)) throw new Error(`${msg} \u2014 ${STALE_RUNTIME_HINT}`);
2821
+ throw e;
2822
+ }
2823
+ };
2771
2824
  const replica = BigInt(`0x${randomBytes3(8).toString("hex")}`) & (1n << 63n) - 1n;
2772
2825
  const eng = await createEngine({
2773
2826
  wasmModule: await WebAssembly.compile(wasm),
@@ -2777,7 +2830,7 @@ async function harnessInstall(opts) {
2777
2830
  installedBy: "nomos-test-harness"
2778
2831
  });
2779
2832
  await mountFresh(eng, workspace);
2780
- author(eng, workspace, "bootstrap", "installDomain", installPayload(eng.hashes.nomos, eng.nomosPkg, "nomos-test-harness"), "");
2833
+ await guarded(() => author(eng, workspace, "bootstrap", "installDomain", installPayload(eng.hashes.nomos, eng.nomosPkg, "nomos-test-harness"), ""));
2781
2834
  const lawHashes = [];
2782
2835
  for (const p of deployPaths) {
2783
2836
  if (!existsSync11(p)) die(`deploy JSON not found: ${p} \u2014 run \`npx githolon compile\` first`);
@@ -2785,7 +2838,7 @@ async function harnessInstall(opts) {
2785
2838
  const usda = deploy2.packageUsda;
2786
2839
  if (typeof usda !== "string" || !usda.startsWith("#usda")) die(`${p} has no #usda packageUsda`);
2787
2840
  const lawHash = await sha256hex(usda);
2788
- author(eng, workspace, "nomos", "installDomain", installPayload(lawHash, usda, "nomos-test-harness"), eng.hashes.nomos);
2841
+ await guarded(() => author(eng, workspace, "nomos", "installDomain", installPayload(lawHash, usda, "nomos-test-harness"), eng.hashes.nomos));
2789
2842
  lawHashes.push(lawHash);
2790
2843
  process.stderr.write(`harness-install: installed ${p} (law ${lawHash.slice(0, 12)}\u2026)
2791
2844
  `);
@@ -2799,7 +2852,7 @@ async function harnessInstall(opts) {
2799
2852
  process.stdout.write(JSON.stringify({ ok: true, snapshot: outPath, workspace, lawHashes }) + "\n");
2800
2853
  return 0;
2801
2854
  }
2802
- var die;
2855
+ var STALE_RUNTIME_HINT, die;
2803
2856
  var init_harness = __esm({
2804
2857
  "src/harness.ts"() {
2805
2858
  "use strict";
@@ -2807,6 +2860,7 @@ var init_harness = __esm({
2807
2860
  init_tree();
2808
2861
  init_local_holon();
2809
2862
  init_cloud();
2863
+ STALE_RUNTIME_HINT = "your cached kernel runtime may be stale \u2014 rm -rf ~/.holon/runtime and re-run (it re-fetches from the cloud)";
2810
2864
  die = (msg) => {
2811
2865
  process.stderr.write(`harness-install: ${msg}
2812
2866
  `);
@@ -4722,6 +4776,21 @@ var HELP = {
4722
4776
  ],
4723
4777
  examples: ["githolon status", "githolon status my-guestbook", "githolon status --target prod"]
4724
4778
  },
4779
+ compat: {
4780
+ usage: "githolon compat <ws-url | deploy.json | interface.json | dir> [--config <cfg>] [--workspace <ws>] [--json]",
4781
+ what: "THE CI GATE (the compat superpower): compare the CURRENT build's structural interface\n(build/<name>.interface.json \u2014 run `githolon compile` first) against a TARGET's installed law,\nPER MEMBER via #72 subtyping. Exits NON-ZERO on any incompatible member, so a client/law\nmismatch is caught before it ships. Target: a deploy.json (its staged .interface is the offer),\nan .interface.json / build dir, or a LIVE workspace URL (connect()s + reads the on-ledger offer).",
4782
+ flags: [
4783
+ ["<target>", "a workspace URL (https://host/v2/workspaces/<ws>), a deploy.json/interface.json, or a dir"],
4784
+ ["--config <cfg>", "the package config naming the current build (default: nomos.package.mjs)"],
4785
+ ["--workspace <ws>", "the workspace name when the live URL is a bare host"],
4786
+ ["--json", "emit { package, target, verdict, members[] } as one JSON line (the CI surface)"]
4787
+ ],
4788
+ examples: [
4789
+ "githolon compat build/guestbook.deploy.json",
4790
+ "githolon compat https://nomos.captainapp.co.uk/v2/workspaces/my-guestbook",
4791
+ "githolon compat ../deployed-law --json"
4792
+ ]
4793
+ },
4725
4794
  generate: {
4726
4795
  usage: "githolon generate <domain|aggregate|intent> <name> [--out <dir>] [--force] [--dry-run]",
4727
4796
  what: "Rails-style scaffolds on @githolon/dsl: a full domain (aggregate + create/mutate directives),\na lone aggregate, or a lone directive. Names arrive in any casing.",
@@ -5333,6 +5402,9 @@ Authoring:
5333
5402
  ./nomos.package.mjs \u2014 the unified report; exits
5334
5403
  non-zero on any REFUSE (compile runs it implicitly).
5335
5404
  --json emits the findings (with file:line) as an array
5405
+ githolon compat <ws-url|deploy.json|dir> [--json] THE CI GATE: compare the current build's interface
5406
+ against a target's installed law, PER MEMBER (#72
5407
+ subtyping); exits non-zero on any incompatible member
5336
5408
  githolon lsp the author-time gate as a stdio Language Server:
5337
5409
  red squiggles while you write law (VS Code/Neovim/\u2026)
5338
5410
  githolon mcp the author-time gate as a stdio MCP server for AI
@@ -5686,6 +5758,9 @@ async function main(argv) {
5686
5758
  if (argv[0] === "check") {
5687
5759
  return runCheck(argv.slice(1));
5688
5760
  }
5761
+ if (argv[0] === "compat") {
5762
+ return runCompat(argv.slice(1));
5763
+ }
5689
5764
  if (argv[0] === "lsp") {
5690
5765
  return runLsp(argv.slice(1));
5691
5766
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.53.0",
3
+ "version": "0.54.1",
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.53.0",
33
- "@githolon/dsl": "^0.53.0",
32
+ "@githolon/client": "^0.54.1",
33
+ "@githolon/dsl": "^0.54.1",
34
34
  "isomorphic-git": "^1.38.4"
35
35
  },
36
36
  "devDependencies": {