githolon 0.13.0 → 0.15.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.
- package/dist/cli.mjs +105 -66
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -476,7 +476,14 @@ function call(ex, mode, fields, STDERR) {
|
|
|
476
476
|
const reqPtr = ex.git_holon_alloc(req.length);
|
|
477
477
|
try {
|
|
478
478
|
new Uint8Array(ex.memory.buffer, reqPtr, req.length).set(req);
|
|
479
|
-
|
|
479
|
+
let packed;
|
|
480
|
+
try {
|
|
481
|
+
packed = ex.git_holon_call(reqPtr, req.length);
|
|
482
|
+
} catch (e) {
|
|
483
|
+
const tail = STDERR.length ? ` | stderr: ${STDERR.slice(-8).join(" / ")}` : "";
|
|
484
|
+
throw new Error(`${String(e && e.stack || e)}${tail}`);
|
|
485
|
+
}
|
|
486
|
+
const { ptr, len } = unpack(packed);
|
|
480
487
|
try {
|
|
481
488
|
const e = JSON.parse(dec2.decode(new Uint8Array(ex.memory.buffer, ptr, len).slice()));
|
|
482
489
|
if (!e.ok) throw new Error((e.error || "holon error") + (STDERR.length ? ` | ${STDERR.slice(-4).join(" / ")}` : ""));
|
|
@@ -488,14 +495,9 @@ function call(ex, mode, fields, STDERR) {
|
|
|
488
495
|
ex.git_holon_dealloc(reqPtr, req.length);
|
|
489
496
|
}
|
|
490
497
|
}
|
|
491
|
-
function
|
|
492
|
-
m.set("domain_manifests.json", new File(enc2.encode(strings.read)));
|
|
493
|
-
m.set("identity-manifests.json", new File(enc2.encode(strings.identity)));
|
|
494
|
-
}
|
|
495
|
-
async function createEngine({ wasmModule, bootstrapPkg, nomosPkg, manifestStrings, replica, installedBy = "nomos-cloud" }) {
|
|
498
|
+
async function createEngine({ wasmModule, bootstrapPkg, nomosPkg, replica, installedBy = "nomos-cloud" }) {
|
|
496
499
|
const hashes = { bootstrap: await sha256hex(bootstrapPkg), nomos: await sha256hex(nomosPkg) };
|
|
497
500
|
const root = /* @__PURE__ */ new Map();
|
|
498
|
-
seedManifests(root, manifestStrings);
|
|
499
501
|
root.set("domain.package.usda", new File(enc2.encode(bootstrapPkg)));
|
|
500
502
|
root.set("ws", new Directory(/* @__PURE__ */ new Map()));
|
|
501
503
|
const preopen = new PreopenDirectory("/work", root);
|
|
@@ -516,55 +518,56 @@ async function createEngine({ wasmModule, bootstrapPkg, nomosPkg, manifestString
|
|
|
516
518
|
hashes,
|
|
517
519
|
bootstrapPkg,
|
|
518
520
|
nomosPkg,
|
|
519
|
-
manifestStrings,
|
|
520
521
|
installedBy,
|
|
521
522
|
fs: makeGitFs(preopen, "/work", { File, Directory }),
|
|
522
523
|
mounted: /* @__PURE__ */ new Map(),
|
|
523
524
|
// ws -> { restored, remoteMain, restoreError }
|
|
524
|
-
mainIntents: /* @__PURE__ */ new Map()
|
|
525
|
+
mainIntents: /* @__PURE__ */ new Map()
|
|
525
526
|
// ws -> { head, ids:Set, oids:Set } (admission idempotence)
|
|
526
|
-
knownDomainsCache: null
|
|
527
527
|
};
|
|
528
528
|
return eng;
|
|
529
529
|
}
|
|
530
|
-
function
|
|
531
|
-
|
|
532
|
-
eng.
|
|
533
|
-
eng.directiveRoutesCache = null;
|
|
534
|
-
eng.scopedReadsCache = null;
|
|
535
|
-
eng.placementDirectivesCache = null;
|
|
536
|
-
eng.tenantTypesCache = null;
|
|
537
|
-
eng.globalAggregatesCache = null;
|
|
538
|
-
const root = eng.preopen.dir.contents;
|
|
539
|
-
seedManifests(root, strings);
|
|
540
|
-
const wsRoot = root.get("ws");
|
|
541
|
-
for (const ws of eng.mounted.keys()) {
|
|
542
|
-
const wsDir = wsRoot.contents.get(ws);
|
|
543
|
-
if (wsDir) seedManifests(wsDir.contents, strings);
|
|
544
|
-
}
|
|
530
|
+
function stageWorkspaceDir(eng, ws) {
|
|
531
|
+
const wsContents = /* @__PURE__ */ new Map();
|
|
532
|
+
eng.preopen.dir.contents.get("ws").contents.set(ws, new Directory(wsContents));
|
|
545
533
|
}
|
|
546
534
|
async function mountWorkspace(eng, ws, ledger) {
|
|
547
535
|
if (eng.mounted.has(ws)) return eng.mounted.get(ws);
|
|
548
|
-
|
|
549
|
-
seedManifests(wsContents, eng.manifestStrings);
|
|
550
|
-
eng.preopen.dir.contents.get("ws").contents.set(ws, new Directory(wsContents));
|
|
536
|
+
stageWorkspaceDir(eng, ws);
|
|
551
537
|
const gitdir = gitdirOf(ws);
|
|
552
|
-
let restored = false, remoteMain = null, restoreError = null;
|
|
538
|
+
let restored = false, remoteMain = null, restoreError = null, checkpoint = null;
|
|
553
539
|
try {
|
|
554
540
|
const info = await git.getRemoteInfo({ http, url: ledger.remote, headers: ledger.headers });
|
|
555
541
|
remoteMain = info.refs && info.refs.heads && info.refs.heads.main || null;
|
|
556
542
|
if (remoteMain) {
|
|
557
543
|
await git.init({ fs: eng.fs, gitdir, bare: true, defaultBranch: "main" });
|
|
558
544
|
await git.addRemote({ fs: eng.fs, gitdir, remote: "origin", url: ledger.remote, force: true });
|
|
559
|
-
|
|
545
|
+
const ckpt = await discoverCheckpointFromCustody(ledger).catch(() => null);
|
|
546
|
+
let shallowOk = false;
|
|
547
|
+
if (ckpt?.cursor && ckpt.frontier) {
|
|
548
|
+
const steps = [32, 96, 256, 1024];
|
|
549
|
+
for (let i = 0; i < steps.length; i++) {
|
|
550
|
+
const depth = steps[i], relative = i > 0;
|
|
551
|
+
await git.fetch({ fs: eng.fs, http, gitdir, remote: "origin", ref: "main", singleBranch: true, depth, relative, headers: ledger.headers });
|
|
552
|
+
if (await git.readCommit({ fs: eng.fs, gitdir, oid: ckpt.cursor }).then(() => true, () => false)) {
|
|
553
|
+
shallowOk = true;
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (!shallowOk) await git.fetch({ fs: eng.fs, http, gitdir, remote: "origin", ref: "main", singleBranch: true, headers: ledger.headers });
|
|
560
559
|
await git.writeRef({ fs: eng.fs, gitdir, ref: "refs/heads/main", value: remoteMain, force: true });
|
|
561
560
|
await git.writeRef({ fs: eng.fs, gitdir, ref: "HEAD", value: "ref: refs/heads/main", force: true, symbolic: true });
|
|
561
|
+
if (shallowOk && ckpt?.blob) {
|
|
562
|
+
const r = importCheckpoint(eng, ws, ckpt.blob, ckpt.frontier);
|
|
563
|
+
checkpoint = { restored: !!(r && r.restored), frontierSeeded: !!(r && r.frontierSeeded), cursor: r && r.cursor ? r.cursor : ckpt.cursor, ref: ckpt.ref };
|
|
564
|
+
}
|
|
562
565
|
restored = true;
|
|
563
566
|
}
|
|
564
567
|
} catch (e) {
|
|
565
568
|
restoreError = String(e && e.stack || e).split("\n").slice(0, 5).join(" | ");
|
|
566
569
|
}
|
|
567
|
-
const m = { restored, remoteMain, restoreError };
|
|
570
|
+
const m = { restored, remoteMain, restoreError, checkpoint };
|
|
568
571
|
eng.mounted.set(ws, m);
|
|
569
572
|
return m;
|
|
570
573
|
}
|
|
@@ -591,6 +594,71 @@ function author(eng, ws, domain, directiveId, payload, controllerHash, opts = {}
|
|
|
591
594
|
if (defer && res.ok) (eng.pendingProjection ??= /* @__PURE__ */ new Set()).add(ws);
|
|
592
595
|
return res;
|
|
593
596
|
}
|
|
597
|
+
function importCheckpoint(eng, ws, blobB64, frontierB64) {
|
|
598
|
+
return JSON.parse(call(eng.ex, "checkpoint_import", { repoArg: repoArgOf(ws), workspace: ws, branch: BRANCH, blob: blobB64, ...frontierB64 ? { frontier: frontierB64 } : {} }, eng.STDERR));
|
|
599
|
+
}
|
|
600
|
+
async function streamAll(stream) {
|
|
601
|
+
const chunks = [];
|
|
602
|
+
const reader = stream.getReader();
|
|
603
|
+
for (; ; ) {
|
|
604
|
+
const { done, value } = await reader.read();
|
|
605
|
+
if (done) break;
|
|
606
|
+
chunks.push(value);
|
|
607
|
+
}
|
|
608
|
+
let len = 0;
|
|
609
|
+
for (const c of chunks) len += c.length;
|
|
610
|
+
const out10 = new Uint8Array(len);
|
|
611
|
+
let at = 0;
|
|
612
|
+
for (const c of chunks) {
|
|
613
|
+
out10.set(c, at);
|
|
614
|
+
at += c.length;
|
|
615
|
+
}
|
|
616
|
+
return out10;
|
|
617
|
+
}
|
|
618
|
+
async function gunzip(bytes) {
|
|
619
|
+
const ds = new DecompressionStream("gzip");
|
|
620
|
+
return streamAll(new Response(bytes).body.pipeThrough(ds));
|
|
621
|
+
}
|
|
622
|
+
async function discoverCheckpointFromCustody(ledger) {
|
|
623
|
+
const freshHeaders = () => ({ ...ledger.headers || {} });
|
|
624
|
+
const refs = (await git.listServerRefs({ http, url: ledger.remote, headers: freshHeaders(), prefix: "refs/meta/checkpoint/", protocolVersion: 2 }) || []).filter((r) => r.ref && r.ref.startsWith("refs/meta/checkpoint/") && r.oid);
|
|
625
|
+
if (!refs.length) return null;
|
|
626
|
+
const root = /* @__PURE__ */ new Map();
|
|
627
|
+
root.set("ckpt", new Directory(/* @__PURE__ */ new Map()));
|
|
628
|
+
const preopen = new PreopenDirectory("/work", root);
|
|
629
|
+
const fs = makeGitFs(preopen, "/work", { File, Directory });
|
|
630
|
+
const gitdir = "/work/ckpt/nomos.git";
|
|
631
|
+
await git.init({ fs, gitdir, bare: true, defaultBranch: BRANCH });
|
|
632
|
+
await git.addRemote({ fs, gitdir, remote: "origin", url: ledger.remote, force: true });
|
|
633
|
+
const readFile = async (oid, filepath) => {
|
|
634
|
+
try {
|
|
635
|
+
return (await git.readBlob({ fs, gitdir, oid, filepath })).blob;
|
|
636
|
+
} catch {
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
for (let i = refs.length - 1; i >= 0 && i >= refs.length - 3; i--) {
|
|
641
|
+
const { ref, oid } = refs[i];
|
|
642
|
+
try {
|
|
643
|
+
await git.fetch({ fs, http, gitdir, remote: "origin", ref, singleBranch: true, depth: 1, headers: freshHeaders() });
|
|
644
|
+
const gz = await readFile(oid, "checkpoint");
|
|
645
|
+
if (!gz) continue;
|
|
646
|
+
let meta = {};
|
|
647
|
+
try {
|
|
648
|
+
const mb = await readFile(oid, "meta");
|
|
649
|
+
if (mb) meta = JSON.parse(dec2.decode(mb));
|
|
650
|
+
} catch {
|
|
651
|
+
}
|
|
652
|
+
const codec = meta.codec ?? "gzip";
|
|
653
|
+
const blob = dec2.decode(codec === "gzip" ? await gunzip(gz) : gz);
|
|
654
|
+
const fgz = await readFile(oid, "frontier");
|
|
655
|
+
const frontier = fgz ? dec2.decode(codec === "gzip" ? await gunzip(fgz) : fgz) : null;
|
|
656
|
+
return { ref, oid, cursor: meta.cursor || null, blob, frontier };
|
|
657
|
+
} catch {
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return null;
|
|
661
|
+
}
|
|
594
662
|
function applyIntentBytes(eng, ws, bytes) {
|
|
595
663
|
const name = `intent-in-${eng.seq++}.json`;
|
|
596
664
|
writeWork(eng, name, bytes);
|
|
@@ -648,9 +716,8 @@ async function fetchRuntime(cloud) {
|
|
|
648
716
|
const localWasm = process.env["NOMOS_LOCAL_WASM"];
|
|
649
717
|
if (localWasm) {
|
|
650
718
|
const bytes = readFileSync2(localWasm);
|
|
651
|
-
const manifests2 = await fetchJsonCached(`${cloud}/v1/runtime/manifests`, join4(cache, "manifests.json"));
|
|
652
719
|
const packages2 = await fetchJsonCached(`${cloud}/v1/runtime/packages`, join4(cache, "packages.json"));
|
|
653
|
-
return { wasmBytes: bytes,
|
|
720
|
+
return { wasmBytes: bytes, packages: packages2 };
|
|
654
721
|
}
|
|
655
722
|
try {
|
|
656
723
|
const r = await fetch(`${cloud}/v1/runtime/holon.wasm`);
|
|
@@ -662,25 +729,8 @@ async function fetchRuntime(cloud) {
|
|
|
662
729
|
if (!existsSync3(wasmCache)) throw e;
|
|
663
730
|
wasmBytes = readFileSync2(wasmCache);
|
|
664
731
|
}
|
|
665
|
-
const manifests = await fetchJsonCached(`${cloud}/v1/runtime/manifests`, join4(cache, "manifests.json"));
|
|
666
732
|
const packages = await fetchJsonCached(`${cloud}/v1/runtime/packages`, join4(cache, "packages.json"));
|
|
667
|
-
return { wasmBytes,
|
|
668
|
-
}
|
|
669
|
-
function mergeManifests(baked, overlay) {
|
|
670
|
-
const read = JSON.parse(baked.domainManifests);
|
|
671
|
-
const identity = JSON.parse(baked.identityManifests);
|
|
672
|
-
for (const [k, v] of Object.entries(overlay.identityManifests ?? {})) identity[k] = v;
|
|
673
|
-
const r = overlay.readManifest;
|
|
674
|
-
if (r !== void 0) {
|
|
675
|
-
for (const [t, schema] of Object.entries(r["aggregateFieldKinds"] ?? {})) read["aggregateFieldKinds"][t] = schema;
|
|
676
|
-
for (const key of ["queries", "counts", "sums", "mins", "maxes", "spatials", "deriveds", "combineds"]) {
|
|
677
|
-
for (const d of r[key] ?? []) {
|
|
678
|
-
const list = read[key] = read[key] ?? [];
|
|
679
|
-
if (!list.some((x) => JSON.stringify(x) === JSON.stringify(d))) list.push(d);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
return { read: JSON.stringify(read), identity: JSON.stringify(identity) };
|
|
733
|
+
return { wasmBytes, packages };
|
|
684
734
|
}
|
|
685
735
|
function writeTreeToDisk(dir, diskPath) {
|
|
686
736
|
mkdirSync3(diskPath, { recursive: true });
|
|
@@ -701,13 +751,11 @@ function readTreeFromDisk(diskPath) {
|
|
|
701
751
|
}
|
|
702
752
|
async function holonEngine(cloud, overlay, installedBy) {
|
|
703
753
|
const runtime = await fetchRuntime(cloud);
|
|
704
|
-
const manifestStrings = overlay === void 0 ? { read: runtime.manifests.domainManifests, identity: runtime.manifests.identityManifests } : mergeManifests(runtime.manifests, overlay);
|
|
705
754
|
const replica = BigInt(`0x${randomBytes(8).toString("hex")}`) & (1n << 63n) - 1n;
|
|
706
755
|
const eng = await createEngine({
|
|
707
756
|
wasmModule: await WebAssembly.compile(runtime.wasmBytes),
|
|
708
757
|
bootstrapPkg: runtime.packages.bootstrap,
|
|
709
758
|
nomosPkg: runtime.packages.nomos,
|
|
710
|
-
manifestStrings,
|
|
711
759
|
replica,
|
|
712
760
|
installedBy
|
|
713
761
|
});
|
|
@@ -1475,12 +1523,9 @@ function readDeployBody(cwd, packageName) {
|
|
|
1475
1523
|
async function installLaw(s, deployBody, installedBy) {
|
|
1476
1524
|
const newHash = await sha256hex(deployBody.packageUsda);
|
|
1477
1525
|
if (newHash === s.lawHash) return { ok: true };
|
|
1478
|
-
const previous = { ...s.eng.manifestStrings };
|
|
1479
1526
|
const t0 = performance.now();
|
|
1480
|
-
setManifests(s.eng, mergeManifests(s.runtime.manifests, deployBody));
|
|
1481
1527
|
const res = author(s.eng, WS, "nomos", "installDomain", installPayload(newHash, deployBody.packageUsda, installedBy), s.eng.hashes.nomos);
|
|
1482
1528
|
if (res.ok === false) {
|
|
1483
|
-
setManifests(s.eng, previous);
|
|
1484
1529
|
return { ok: false, error: `law install refused: ${res.error ?? "unknown"} \u2014 the previous law (${s.lawHash.slice(0, 12)}\u2026) keeps serving; fix and save again` };
|
|
1485
1530
|
}
|
|
1486
1531
|
s.lawHash = newHash;
|
|
@@ -1758,7 +1803,7 @@ async function gitRemote(ws, name, opts) {
|
|
|
1758
1803
|
var HELP = {
|
|
1759
1804
|
compile: {
|
|
1760
1805
|
usage: "githolon compile [config] [--layered]",
|
|
1761
|
-
what: "Compile the package by ./nomos.package.mjs (the @githolon/dsl launcher): ONE deterministic\n.package.usda (sha256 = the law's content hash) +
|
|
1806
|
+
what: "Compile the package by ./nomos.package.mjs (the @githolon/dsl launcher): ONE deterministic\n.package.usda (sha256 = the law's content hash) + the deploy body +\nthe typed TS client + the generated proof \u2014 all into build/.",
|
|
1762
1807
|
flags: [
|
|
1763
1808
|
["[config]", "an alternate config file (default: nomos.package.mjs)"],
|
|
1764
1809
|
["--layered", "also emit the per-domain layered USD view"]
|
|
@@ -1792,7 +1837,7 @@ var HELP = {
|
|
|
1792
1837
|
["<ws|dir>", "a workspace name on the cloud, or a local holon directory (githolon ledger init)"],
|
|
1793
1838
|
["--step N", "non-interactive; print the running tallies every N intents"],
|
|
1794
1839
|
["--json", "one JSON line per step + the final verdict (pipe it)"],
|
|
1795
|
-
["--file <deploy.json>", "
|
|
1840
|
+
["--file <deploy.json>", "reserved for local package hints (default: the one in ./build)"]
|
|
1796
1841
|
],
|
|
1797
1842
|
examples: ["githolon replay my-guestbook", "githolon replay ./my-holon --step 10", "githolon replay my-guestbook --json | jq .directive"]
|
|
1798
1843
|
},
|
|
@@ -1965,7 +2010,7 @@ init_engine();
|
|
|
1965
2010
|
init_engine();
|
|
1966
2011
|
init_cloud();
|
|
1967
2012
|
init_local_holon();
|
|
1968
|
-
import { existsSync as existsSync8
|
|
2013
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
1969
2014
|
import { join as join9 } from "node:path";
|
|
1970
2015
|
import git3 from "isomorphic-git";
|
|
1971
2016
|
var out7 = (s) => void process.stdout.write(s + "\n");
|
|
@@ -2055,15 +2100,9 @@ async function replay(target, opts) {
|
|
|
2055
2100
|
const cloud = cloudBase(opts.cloud);
|
|
2056
2101
|
const json = opts.json === true;
|
|
2057
2102
|
const emit = (o) => out7(JSON.stringify(o));
|
|
2058
|
-
let overlay;
|
|
2059
|
-
try {
|
|
2060
|
-
overlay = JSON.parse(readFileSync7(discoverDeployJson(process.cwd(), opts.file), "utf8"));
|
|
2061
|
-
} catch {
|
|
2062
|
-
overlay = void 0;
|
|
2063
|
-
}
|
|
2064
2103
|
let eng;
|
|
2065
2104
|
try {
|
|
2066
|
-
({ eng } = await holonEngine(cloud,
|
|
2105
|
+
({ eng } = await holonEngine(cloud, void 0, "githolon-replay"));
|
|
2067
2106
|
} catch (e) {
|
|
2068
2107
|
err7(`cannot boot the local holon: ${String(e.message ?? e)}
|
|
2069
2108
|
the runtime rides ${cloud}/v1/runtime/* (cached in ~/.holon/runtime after one fetch)`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "githolon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"directory": "cli"
|
|
11
11
|
},
|
|
12
12
|
"bin": {
|
|
13
|
-
"githolon": "
|
|
13
|
+
"githolon": "dist/cli.mjs"
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@bjorn3/browser_wasi_shim": "0.4.2",
|
|
30
|
-
"@githolon/dsl": "^0.
|
|
30
|
+
"@githolon/dsl": "^0.15.0",
|
|
31
31
|
"isomorphic-git": "^1.38.4"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|