@githolon/dsl 0.102.1 → 0.102.3
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/dart/CHANGELOG.md +9 -0
- package/dart/lib/src/dev_cloud.dart +61 -18
- package/dart/lib/src/runner/node-entry.mjs +27 -6
- package/dart/lib/src/runner/offline-install.mjs +80 -18
- package/dart/lib/src/test_harness.dart +874 -554
- package/dart/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/runtime/generated-application-host.js +14 -6
- package/src/application_composition.ts +117 -2
- package/src/business_birth.ts +11 -9
- package/src/codegen_dart_application.ts +42 -31
- package/src/codegen_dart_client.ts +9 -5
- package/src/codegen_dart_scenario.ts +68 -9
- package/src/compile_package_main.ts +168 -42
- package/src/framework/home.ts +7 -1
- package/src/law_check.ts +13 -5
- package/src/usd_layers.ts +68 -51
- package/src/workspace_sharing.ts +5 -3
package/dart/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 0.64.1
|
|
2
|
+
|
|
3
|
+
- Resolve a compiled OpenUSD application as one ordered package set in generated offline and connected
|
|
4
|
+
scenarios, keeping reference-only control law off user replicas while payload law births their workspaces.
|
|
5
|
+
- Pin source and published test runs to the exact coordinated kernel release, and make restart, reconnect and
|
|
6
|
+
clean reinstall use the same hidden multi-workspace custody lifecycle.
|
|
7
|
+
- Seat every business workspace founder on its private transport relation at genesis so public business
|
|
8
|
+
records can coexist with framework-private identity state and still reopen on a fresh device.
|
|
9
|
+
|
|
1
10
|
## 0.64.0
|
|
2
11
|
|
|
3
12
|
- Generate one self-documenting application object: intent-shaped business actions at the root, typed
|
|
@@ -58,8 +58,14 @@ class NomosTestCloud {
|
|
|
58
58
|
bool _online = true;
|
|
59
59
|
bool _stopped = false;
|
|
60
60
|
|
|
61
|
-
NomosTestCloud._(
|
|
62
|
-
|
|
61
|
+
NomosTestCloud._(
|
|
62
|
+
this._server,
|
|
63
|
+
this._proxy,
|
|
64
|
+
this._upstream,
|
|
65
|
+
this._client,
|
|
66
|
+
this._onDiagnostic,
|
|
67
|
+
this.testKRootPublic,
|
|
68
|
+
);
|
|
63
69
|
|
|
64
70
|
/// The base URL a cloud-BOUND session connects to (`connect(cloud: cloud.origin)`). Points at the PARTITION
|
|
65
71
|
/// PROXY, so [setOnline] deterministically severs/heals the whole plane's link to custody.
|
|
@@ -71,7 +77,8 @@ class NomosTestCloud {
|
|
|
71
77
|
void setOnline(bool online) {
|
|
72
78
|
_online = online;
|
|
73
79
|
_log(
|
|
74
|
-
|
|
80
|
+
'partition: ${online ? "ONLINE (link up)" : "OFFLINE (link severed)"}',
|
|
81
|
+
);
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
bool get online => _online;
|
|
@@ -80,8 +87,9 @@ class NomosTestCloud {
|
|
|
80
87
|
/// live cloud state DIRECTLY (bypassing the partition proxy) — a test assertion about custody must see the
|
|
81
88
|
/// truth even while the app's link is partitioned OFFLINE.
|
|
82
89
|
Future<RemoteWorkspaceState> remoteHead(String workspace) async {
|
|
83
|
-
final body =
|
|
84
|
-
|
|
90
|
+
final body = await _getJson(
|
|
91
|
+
_upstream.replace(path: '/v2/workspaces/$workspace'),
|
|
92
|
+
);
|
|
85
93
|
final ledger =
|
|
86
94
|
(body['ledgerState'] as Map?)?.cast<String, Object?>() ?? const {};
|
|
87
95
|
return RemoteWorkspaceState(
|
|
@@ -110,9 +118,14 @@ class NomosTestCloud {
|
|
|
110
118
|
/// (the old lane — the harness POST-creating the platform — refuses 409 `unborn` by design).
|
|
111
119
|
String? platform,
|
|
112
120
|
|
|
113
|
-
/// Optional platform law to deploy at boot
|
|
114
|
-
/// installs it on [platform] before serving. The harness may also deploy law itself post-boot.
|
|
121
|
+
/// Optional single platform law to deploy at boot. Prefer [deployJsonPaths] for a composed application.
|
|
115
122
|
String? deployJsonPath,
|
|
123
|
+
|
|
124
|
+
/// Ordered application package set installed by the warranted bootstrap operator before serving.
|
|
125
|
+
/// Reference-only/control packages go first and remain active on the parent; the home payload package
|
|
126
|
+
/// goes last and is retained as the explicit law used to birth a receiving group. A payload package is
|
|
127
|
+
/// not made current on the parent merely to make it available to a child.
|
|
128
|
+
List<String> deployJsonPaths = const [],
|
|
116
129
|
Duration readyTimeout = const Duration(seconds: 30),
|
|
117
130
|
void Function(String line)? onDiagnostic,
|
|
118
131
|
}) async {
|
|
@@ -124,19 +137,31 @@ class NomosTestCloud {
|
|
|
124
137
|
if (ephemeral) '--ephemeral',
|
|
125
138
|
if (dataDir != null) ...['--data', dataDir],
|
|
126
139
|
if (platform != null) ...['--platform', platform],
|
|
127
|
-
|
|
140
|
+
for (final deploy in [
|
|
141
|
+
...deployJsonPaths,
|
|
142
|
+
if (deployJsonPath != null && !deployJsonPaths.contains(deployJsonPath))
|
|
143
|
+
deployJsonPath,
|
|
144
|
+
]) ...['--deploy', deploy],
|
|
128
145
|
];
|
|
129
146
|
void log(String m) => onDiagnostic?.call('[nomos-test-cloud] $m');
|
|
130
147
|
log('spawning: $node ${args.join(' ')}');
|
|
131
148
|
final proc = await Process.start(node, args, mode: ProcessStartMode.normal);
|
|
149
|
+
final serverTail = <String>[];
|
|
150
|
+
void remember(String stream, String line) {
|
|
151
|
+
serverTail.add('$stream: $line');
|
|
152
|
+
if (serverTail.length > 24) serverTail.removeAt(0);
|
|
153
|
+
log('$stream: $line');
|
|
154
|
+
}
|
|
132
155
|
proc.stdout
|
|
133
156
|
.transform(utf8.decoder)
|
|
134
157
|
.transform(const LineSplitter())
|
|
135
|
-
.listen((l) =>
|
|
158
|
+
.listen((l) => remember('server', l));
|
|
136
159
|
proc.stderr
|
|
137
160
|
.transform(utf8.decoder)
|
|
138
161
|
.transform(const LineSplitter())
|
|
139
|
-
.listen((l) =>
|
|
162
|
+
.listen((l) => remember('server!', l));
|
|
163
|
+
int? prematureExitCode;
|
|
164
|
+
unawaited(proc.exitCode.then((code) => prematureExitCode = code));
|
|
140
165
|
|
|
141
166
|
final upstream = Uri.parse('http://127.0.0.1:$chosenPort');
|
|
142
167
|
final client = HttpClient();
|
|
@@ -147,6 +172,7 @@ class NomosTestCloud {
|
|
|
147
172
|
var ready = false;
|
|
148
173
|
String? testKRootPublic;
|
|
149
174
|
while (DateTime.now().isBefore(deadline)) {
|
|
175
|
+
if (prematureExitCode != null) break;
|
|
150
176
|
try {
|
|
151
177
|
final req = await client.getUrl(upstream.replace(path: '/health'));
|
|
152
178
|
final resp = await req.close();
|
|
@@ -160,20 +186,35 @@ class NomosTestCloud {
|
|
|
160
186
|
break;
|
|
161
187
|
}
|
|
162
188
|
}
|
|
163
|
-
} catch (_) {
|
|
189
|
+
} catch (_) {
|
|
190
|
+
/* not up yet */
|
|
191
|
+
}
|
|
164
192
|
await Future<void>.delayed(const Duration(milliseconds: 200));
|
|
165
193
|
}
|
|
166
194
|
if (!ready) {
|
|
167
|
-
proc.kill(ProcessSignal.sigkill);
|
|
195
|
+
if (prematureExitCode == null) proc.kill(ProcessSignal.sigkill);
|
|
196
|
+
final exited = prematureExitCode;
|
|
197
|
+
final tail = serverTail.isEmpty ? '' : '\nserver tail:\n${serverTail.join('\n')}';
|
|
168
198
|
throw NomosTestCloudException(
|
|
169
|
-
|
|
199
|
+
exited == null
|
|
200
|
+
? 'the dev cloud did not answer /health${platform != null ? ' with platformReady:true' : ''} within ${readyTimeout.inSeconds}s (serverEntry: $serverEntry)$tail'
|
|
201
|
+
: 'the dev cloud exited with code $exited before /health${platform != null ? ' reported platformReady:true' : ' became ready'} (serverEntry: $serverEntry)$tail',
|
|
202
|
+
);
|
|
170
203
|
}
|
|
171
|
-
log(
|
|
204
|
+
log(
|
|
205
|
+
'dev cloud healthy at $upstream${platform != null ? ' (platform ceremony complete)' : ''}',
|
|
206
|
+
);
|
|
172
207
|
|
|
173
208
|
// The partition proxy — forwards to the dev cloud when ONLINE, fails fast when OFFLINE.
|
|
174
209
|
final proxy = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
|
|
175
210
|
final cloud = NomosTestCloud._(
|
|
176
|
-
|
|
211
|
+
proc,
|
|
212
|
+
proxy,
|
|
213
|
+
upstream,
|
|
214
|
+
client,
|
|
215
|
+
onDiagnostic,
|
|
216
|
+
testKRootPublic,
|
|
217
|
+
);
|
|
177
218
|
proxy.listen(cloud._handleProxy);
|
|
178
219
|
log('partition proxy at ${cloud.origin} → $upstream');
|
|
179
220
|
return cloud;
|
|
@@ -192,8 +233,9 @@ class NomosTestCloud {
|
|
|
192
233
|
}
|
|
193
234
|
try {
|
|
194
235
|
final target = _upstream.replace(
|
|
195
|
-
|
|
196
|
-
|
|
236
|
+
path: req.uri.path,
|
|
237
|
+
query: req.uri.query.isEmpty ? null : req.uri.query,
|
|
238
|
+
);
|
|
197
239
|
final fwd = await _client.openUrl(req.method, target);
|
|
198
240
|
req.headers.forEach((name, values) {
|
|
199
241
|
if (name.toLowerCase() != 'host')
|
|
@@ -220,7 +262,8 @@ class NomosTestCloud {
|
|
|
220
262
|
final text = await resp.transform(utf8.decoder).join();
|
|
221
263
|
if (resp.statusCode != 200) {
|
|
222
264
|
throw NomosTestCloudException(
|
|
223
|
-
|
|
265
|
+
'GET $url → ${resp.statusCode}: ${text.substring(0, text.length.clamp(0, 200))}',
|
|
266
|
+
);
|
|
224
267
|
}
|
|
225
268
|
return (jsonDecode(text) as Map).cast<String, Object?>();
|
|
226
269
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// <define:__NOMOS_KERNEL_RELEASE__>
|
|
4
|
+
var define_NOMOS_KERNEL_RELEASE_default = { production: { hash: "bc52f7eb630bc5a9a03b4c62b9b7ab58c4b6f25e687ecd51c72f9251763593fc", version: "kernel-bc52f7eb", features: ["compoundKeys", "capturedReads", "invariantGate", "surfacedMerge", "fieldProvenance", "nullSemantics", "attestedReads", "conflictSnapshots", "ownedAudience"], protocol: 1 }, testMint: { hash: "17d8f91b661dc8c3a6dea72d699f9f5759ab5e6b4e3e3e5e90afceb3a7034154", version: "kernel-17d8f91b", features: ["compoundKeys", "capturedReads", "invariantGate", "surfacedMerge", "fieldProvenance", "nullSemantics", "attestedReads", "conflictSnapshots", "ownedAudience"], protocol: 1 } };
|
|
5
|
+
|
|
3
6
|
// runner/node-entry.ts
|
|
4
7
|
import { createInterface } from "node:readline";
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
5
9
|
import { readFileSync } from "node:fs";
|
|
6
10
|
import { homedir } from "node:os";
|
|
7
11
|
import { join } from "node:path";
|
|
@@ -2597,12 +2601,20 @@ function parseBulkReadForbidden(status, bodyText) {
|
|
|
2597
2601
|
// src/kernel_provider_wasm.ts
|
|
2598
2602
|
var enc2 = new TextEncoder();
|
|
2599
2603
|
var dec2 = new TextDecoder();
|
|
2600
|
-
var
|
|
2604
|
+
var nmsInternalSnapshotToBase64 = (bytes) => {
|
|
2605
|
+
if (typeof Buffer !== "undefined") {
|
|
2606
|
+
return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("base64");
|
|
2607
|
+
}
|
|
2601
2608
|
let s = "";
|
|
2602
|
-
for (let i = 0; i < bytes.length; i += 32768)
|
|
2609
|
+
for (let i = 0; i < bytes.length; i += 32768) {
|
|
2610
|
+
s += String.fromCharCode.apply(null, bytes.subarray(i, i + 32768));
|
|
2611
|
+
}
|
|
2603
2612
|
return btoa(s);
|
|
2604
2613
|
};
|
|
2605
|
-
var
|
|
2614
|
+
var nmsInternalSnapshotFromBase64 = (s) => {
|
|
2615
|
+
if (typeof Buffer !== "undefined") return Buffer.from(s, "base64");
|
|
2616
|
+
return Uint8Array.from(atob(s), (c) => c.charCodeAt(0));
|
|
2617
|
+
};
|
|
2606
2618
|
var unpack = (p) => {
|
|
2607
2619
|
const v = typeof p === "bigint" ? p : BigInt(p);
|
|
2608
2620
|
return { ptr: Number(v >> 32n), len: Number(v & 0xffffffffn) };
|
|
@@ -2647,7 +2659,7 @@ function wasmModuleFor(base, fetchImpl) {
|
|
|
2647
2659
|
function parseSnapshot(bytes) {
|
|
2648
2660
|
try {
|
|
2649
2661
|
const o = JSON.parse(dec2.decode(bytes));
|
|
2650
|
-
if (o && o.v === 2 && typeof o.tree === "string") return { treeBytes:
|
|
2662
|
+
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 };
|
|
2651
2663
|
} catch {
|
|
2652
2664
|
}
|
|
2653
2665
|
return { treeBytes: bytes, ckpt: null, frontier: null, syncedBase: null };
|
|
@@ -2656,7 +2668,7 @@ function buildSnapshot(treeBytes, ckpt, syncedBase) {
|
|
|
2656
2668
|
if ((!ckpt || !ckpt.blob && !ckpt.frontier) && !syncedBase) return treeBytes;
|
|
2657
2669
|
return enc2.encode(JSON.stringify({
|
|
2658
2670
|
v: 2,
|
|
2659
|
-
tree:
|
|
2671
|
+
tree: nmsInternalSnapshotToBase64(treeBytes),
|
|
2660
2672
|
ckpt: ckpt && ckpt.blob ? ckpt.blob : null,
|
|
2661
2673
|
frontier: ckpt ? ckpt.frontier ?? null : null,
|
|
2662
2674
|
cursor: ckpt ? ckpt.cursor ?? null : null,
|
|
@@ -2896,7 +2908,7 @@ function createWasmEnginePlane({ span } = {}) {
|
|
|
2896
2908
|
}
|
|
2897
2909
|
const buf = new Uint8Array(await r.arrayBuffer());
|
|
2898
2910
|
if (!buf.length) return { applied: false };
|
|
2899
|
-
view.applyPack(
|
|
2911
|
+
view.applyPack(nmsInternalSnapshotToBase64(buf));
|
|
2900
2912
|
return { applied: true };
|
|
2901
2913
|
} finally {
|
|
2902
2914
|
if (end) end();
|
|
@@ -9027,6 +9039,15 @@ function offlineOpenRealm() {
|
|
|
9027
9039
|
const restorePath = process.env["NOMOS_OFFLINE_RESTORE"];
|
|
9028
9040
|
const wasmName = process.env["NOMOS_OFFLINE_WASM"] || "holon.wasm";
|
|
9029
9041
|
const wasm = readFileSync(join(runtimeDir, wasmName));
|
|
9042
|
+
if (typeof define_NOMOS_KERNEL_RELEASE_default !== "undefined") {
|
|
9043
|
+
const expected = wasmName === "holon-testmint.wasm" ? define_NOMOS_KERNEL_RELEASE_default.testMint.hash : define_NOMOS_KERNEL_RELEASE_default.production.hash;
|
|
9044
|
+
const actual = createHash("sha256").update(wasm).digest("hex");
|
|
9045
|
+
if (actual !== expected) {
|
|
9046
|
+
throw new Error(
|
|
9047
|
+
`offline runtime/kernel skew: ${wasmName} is ${actual.slice(0, 12)}\u2026, but this SDK requires ${expected.slice(0, 12)}\u2026; the installer must acquire the release-pinned runtime before boot`
|
|
9048
|
+
);
|
|
9049
|
+
}
|
|
9050
|
+
}
|
|
9030
9051
|
const pkgs = readFileSync(join(runtimeDir, "packages.json"));
|
|
9031
9052
|
let manifests = null;
|
|
9032
9053
|
try {
|
|
@@ -5,15 +5,19 @@ var __export = (target, all) => {
|
|
|
5
5
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
// <define:__NOMOS_KERNEL_RELEASE__>
|
|
9
|
+
var define_NOMOS_KERNEL_RELEASE_default = { production: { hash: "bc52f7eb630bc5a9a03b4c62b9b7ab58c4b6f25e687ecd51c72f9251763593fc", version: "kernel-bc52f7eb", features: ["compoundKeys", "capturedReads", "invariantGate", "surfacedMerge", "fieldProvenance", "nullSemantics", "attestedReads", "conflictSnapshots", "ownedAudience"], protocol: 1 }, testMint: { hash: "17d8f91b661dc8c3a6dea72d699f9f5759ab5e6b4e3e3e5e90afceb3a7034154", version: "kernel-17d8f91b", features: ["compoundKeys", "capturedReads", "invariantGate", "surfacedMerge", "fieldProvenance", "nullSemantics", "attestedReads", "conflictSnapshots", "ownedAudience"], protocol: 1 } };
|
|
10
|
+
|
|
8
11
|
// runner/offline-install.ts
|
|
9
|
-
import { readFileSync, writeFileSync as writeFileSync2, existsSync } from "node:fs";
|
|
12
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync } from "node:fs";
|
|
10
13
|
import { homedir } from "node:os";
|
|
11
14
|
import { join as join2, dirname } from "node:path";
|
|
12
15
|
import { randomBytes, webcrypto as wc } from "node:crypto";
|
|
13
16
|
import { fileURLToPath } from "node:url";
|
|
14
17
|
|
|
15
18
|
// runner/runtime-refresh.ts
|
|
16
|
-
import { statSync, renameSync, writeFileSync, mkdirSync } from "node:fs";
|
|
19
|
+
import { statSync, renameSync, writeFileSync, mkdirSync, readFileSync } from "node:fs";
|
|
20
|
+
import { createHash } from "node:crypto";
|
|
17
21
|
import { join } from "node:path";
|
|
18
22
|
var RUNTIME_FRESH_MS = 15 * 60 * 1e3;
|
|
19
23
|
var _refreshedDirs = /* @__PURE__ */ new Set();
|
|
@@ -32,12 +36,29 @@ function atomicWrite(target, data) {
|
|
|
32
36
|
writeFileSync(tmp, data);
|
|
33
37
|
renameSync(tmp, target);
|
|
34
38
|
}
|
|
35
|
-
|
|
39
|
+
var sha256 = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
40
|
+
function runtimeReleaseMismatch(dir, expected) {
|
|
41
|
+
try {
|
|
42
|
+
const production = sha256(readFileSync(join(dir, "holon.wasm")));
|
|
43
|
+
if (production !== expected.production) {
|
|
44
|
+
return `production kernel ${production.slice(0, 12)}\u2026; SDK requires ${expected.production.slice(0, 12)}\u2026`;
|
|
45
|
+
}
|
|
46
|
+
const testMint = sha256(readFileSync(join(dir, "holon-testmint.wasm")));
|
|
47
|
+
if (testMint !== expected.testMint) {
|
|
48
|
+
return `test-mint kernel ${testMint.slice(0, 12)}\u2026; SDK requires ${expected.testMint.slice(0, 12)}\u2026`;
|
|
49
|
+
}
|
|
50
|
+
return void 0;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return `runtime cache is incomplete (${error.message})`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function refreshRuntimeDir(cloud, dir, { fetchImpl = globalThis.fetch, log: log2, mode, expected } = {}) {
|
|
36
56
|
const m = String(mode ?? process.env["NOMOS_RUNTIME_REFRESH"] ?? "auto").toLowerCase();
|
|
37
57
|
if (m === "never") return false;
|
|
58
|
+
const coherent = expected === void 0 || runtimeReleaseMismatch(dir, expected) === void 0;
|
|
38
59
|
if (m !== "always") {
|
|
39
|
-
if (_refreshedDirs.has(dir)) return false;
|
|
40
|
-
if (runtimeIsWarm(dir)) return false;
|
|
60
|
+
if (coherent && _refreshedDirs.has(dir)) return false;
|
|
61
|
+
if (coherent && runtimeIsWarm(dir)) return false;
|
|
41
62
|
}
|
|
42
63
|
try {
|
|
43
64
|
const r = await fetchImpl(`${cloud}/v1/runtime/holon.wasm`);
|
|
@@ -46,6 +67,15 @@ async function refreshRuntimeDir(cloud, dir, { fetchImpl = globalThis.fetch, log
|
|
|
46
67
|
const testmintResp = await fetchImpl(`${cloud}/v1/runtime/holon-testmint.wasm`);
|
|
47
68
|
if (!testmintResp.ok) throw new Error(`test-mint runtime wasm \u2192 ${testmintResp.status}`);
|
|
48
69
|
const testmintBytes = new Uint8Array(await testmintResp.arrayBuffer());
|
|
70
|
+
if (expected !== void 0) {
|
|
71
|
+
const productionHash = sha256(bytes);
|
|
72
|
+
const testMintHash = sha256(testmintBytes);
|
|
73
|
+
if (productionHash !== expected.production || testMintHash !== expected.testMint) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`cloud runtime does not match this SDK release (production ${productionHash.slice(0, 12)}\u2026/${expected.production.slice(0, 12)}\u2026, test-mint ${testMintHash.slice(0, 12)}\u2026/${expected.testMint.slice(0, 12)}\u2026)`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
49
79
|
const pkgsResp = await fetchImpl(`${cloud}/v1/runtime/packages`);
|
|
50
80
|
if (!pkgsResp.ok) throw new Error(`runtime packages \u2192 ${pkgsResp.status}`);
|
|
51
81
|
const pkgText = await pkgsResp.text();
|
|
@@ -56,7 +86,10 @@ async function refreshRuntimeDir(cloud, dir, { fetchImpl = globalThis.fetch, log
|
|
|
56
86
|
_refreshedDirs.add(dir);
|
|
57
87
|
if (typeof log2 === "function") log2(`offline-install: refreshed runtime cache from the cloud \u2192 ${dir}`);
|
|
58
88
|
return true;
|
|
59
|
-
} catch {
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (typeof log2 === "function" && expected !== void 0) {
|
|
91
|
+
log2(`offline-install: release-pinned runtime refresh failed: ${error.message}`);
|
|
92
|
+
}
|
|
60
93
|
return false;
|
|
61
94
|
}
|
|
62
95
|
}
|
|
@@ -1863,11 +1896,16 @@ async function pushPack(remote, headers = {}, { updates = [], pack = null } = {}
|
|
|
1863
1896
|
});
|
|
1864
1897
|
cmds.push(FLUSH);
|
|
1865
1898
|
const body = concatBytes([...cmds, pack && pack.length ? pack : EMPTY_PACK]);
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1899
|
+
let r;
|
|
1900
|
+
try {
|
|
1901
|
+
r = await fetch(`${remote}/git-receive-pack`, {
|
|
1902
|
+
method: "POST",
|
|
1903
|
+
headers: { "content-type": "application/x-git-receive-pack-request", ...headers },
|
|
1904
|
+
body
|
|
1905
|
+
});
|
|
1906
|
+
} catch (error) {
|
|
1907
|
+
throw new Error(`receive-pack transport failed (${body.byteLength} bytes): ${String(error)}`, { cause: error });
|
|
1908
|
+
}
|
|
1871
1909
|
const txt = dec2.decode(new Uint8Array(await r.arrayBuffer()));
|
|
1872
1910
|
const unpacked = /unpack ok/.test(txt);
|
|
1873
1911
|
const everyRefOk = updates.every((u) => new RegExp(`ok ${u.ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`).test(txt));
|
|
@@ -3322,7 +3360,12 @@ async function custodyFetch(eng2, ws, ledger, { remoteRef = "refs/heads/main", l
|
|
|
3322
3360
|
async function custodyPush(eng2, ws, ledger, { localRef = null, remoteRef, del = false, pointer = false, newOid = null }) {
|
|
3323
3361
|
const headers = ledger.headers || {};
|
|
3324
3362
|
const remoteRefFull = fullRef(remoteRef);
|
|
3325
|
-
|
|
3363
|
+
let remote;
|
|
3364
|
+
try {
|
|
3365
|
+
remote = await lsRefs(ledger.remote, headers, { service: "git-receive-pack", prefix: remoteRefFull });
|
|
3366
|
+
} catch (error) {
|
|
3367
|
+
throw new Error(`custody receive-pack advertisement failed for ${remoteRefFull}: ${String(error)}`, { cause: error });
|
|
3368
|
+
}
|
|
3326
3369
|
const oldOid = remote[remoteRefFull] || ZERO_OID;
|
|
3327
3370
|
if (del) {
|
|
3328
3371
|
if (oldOid === ZERO_OID) return;
|
|
@@ -3336,14 +3379,21 @@ async function custodyPush(eng2, ws, ledger, { localRef = null, remoteRef, del =
|
|
|
3336
3379
|
pack = oldOid !== ZERO_OID ? packDelta(eng2, ws, oldOid, tgt) : null;
|
|
3337
3380
|
if (!pack) pack = packDelta(eng2, ws, "", tgt);
|
|
3338
3381
|
}
|
|
3339
|
-
|
|
3382
|
+
const packBytes = pack?.byteLength ?? 0;
|
|
3383
|
+
try {
|
|
3384
|
+
return await pushVia(ledger, () => pushPack(ledger.remote, headers, { updates: [{ ref: remoteRefFull, oldOid, newOid: tgt }], pack }));
|
|
3385
|
+
} catch (error) {
|
|
3386
|
+
throw new Error(`custody receive-pack push failed for ${remoteRefFull} (${packBytes} pack bytes): ${String(error)}`, { cause: error });
|
|
3387
|
+
}
|
|
3340
3388
|
}
|
|
3341
3389
|
async function commitAndPush(eng2, ws, ledger) {
|
|
3342
3390
|
try {
|
|
3343
3391
|
await custodyPush(eng2, ws, ledger, { remoteRef: "refs/heads/main" });
|
|
3344
3392
|
} catch (e) {
|
|
3345
3393
|
unmount(eng2, ws);
|
|
3346
|
-
|
|
3394
|
+
const cause = e instanceof Error ? e.cause : void 0;
|
|
3395
|
+
const detail = cause === void 0 ? String(e) : `${e}; cause: ${String(cause)}`;
|
|
3396
|
+
throw new Error(`ledger push failed \u2014 write NOT durable, rolled back to ledger: ${detail}`, { cause: e });
|
|
3347
3397
|
}
|
|
3348
3398
|
}
|
|
3349
3399
|
async function pushShape(eng2, ws, ledger) {
|
|
@@ -4627,6 +4677,7 @@ function sealAttestationBatches(eng2, ws, domain, controllerHash, opts = {}) {
|
|
|
4627
4677
|
|
|
4628
4678
|
// runner/offline-install.ts
|
|
4629
4679
|
var HERE = dirname(fileURLToPath(import.meta.url));
|
|
4680
|
+
var EXPECTED_RUNTIME = typeof define_NOMOS_KERNEL_RELEASE_default === "undefined" ? void 0 : { production: define_NOMOS_KERNEL_RELEASE_default.production.hash, testMint: define_NOMOS_KERNEL_RELEASE_default.testMint.hash };
|
|
4630
4681
|
var engineModule = process.env["NOMOS_ADAPTER_ENGINE"] ? await import(process.env["NOMOS_ADAPTER_ENGINE"]) : engine_exports;
|
|
4631
4682
|
var treeModule = process.env["NOMOS_ADAPTER_TREE"] ? await import(process.env["NOMOS_ADAPTER_TREE"]) : { serializeTree };
|
|
4632
4683
|
var { createEngine: createEngine2, mountWorkspace: mountWorkspace2, author: author2, installPayload: installPayload2, authorKeygen: authorKeygen2, refreshProjection: refreshProjection2, currentLaw: currentLaw2, exportCheckpoint: exportCheckpoint2 } = engineModule;
|
|
@@ -4654,14 +4705,25 @@ if (!outPath) die("no --out snapshot path given");
|
|
|
4654
4705
|
var CLOUD = (process.env["NOMOS_CLOUD"] || "https://nomos.captainapp.co.uk").replace(/\/+$/, "");
|
|
4655
4706
|
var STALE_RUNTIME_HINT = "your cached kernel runtime may be stale \u2014 rm -rf ~/.holon/runtime and re-run (it re-fetches from the cloud)";
|
|
4656
4707
|
var looksLikeStaleRuntime = (msg) => /\bbbox param\b|missing.*param|non-numeric|unknown (op|query op)|unsupported op|unexpected (field|key)|no such op/i.test(msg);
|
|
4657
|
-
await refreshRuntimeDir(CLOUD, runtimeDir, {
|
|
4708
|
+
await refreshRuntimeDir(CLOUD, runtimeDir, {
|
|
4709
|
+
log: (m) => process.stderr.write(m + "\n"),
|
|
4710
|
+
...EXPECTED_RUNTIME !== void 0 ? { expected: EXPECTED_RUNTIME } : {}
|
|
4711
|
+
});
|
|
4712
|
+
if (EXPECTED_RUNTIME !== void 0) {
|
|
4713
|
+
const mismatch = runtimeReleaseMismatch(runtimeDir, EXPECTED_RUNTIME);
|
|
4714
|
+
if (mismatch !== void 0) {
|
|
4715
|
+
die(
|
|
4716
|
+
`runtime release coherence failed: ${mismatch}. The SDK will not run generated law against a different kernel; reconnect once so it can fetch this release's runtime, or set NOMOS_OFFLINE_RUNTIME to the exact candidate bundle.`
|
|
4717
|
+
);
|
|
4718
|
+
}
|
|
4719
|
+
}
|
|
4658
4720
|
var wasmFile = join2(runtimeDir, "holon-testmint.wasm");
|
|
4659
4721
|
var pkgsFile = join2(runtimeDir, "packages.json");
|
|
4660
4722
|
if (!existsSync(wasmFile) || !existsSync(pkgsFile)) {
|
|
4661
4723
|
die(`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.`);
|
|
4662
4724
|
}
|
|
4663
|
-
var wasm =
|
|
4664
|
-
var pkgs = JSON.parse(
|
|
4725
|
+
var wasm = readFileSync2(wasmFile);
|
|
4726
|
+
var pkgs = JSON.parse(readFileSync2(pkgsFile, "utf8"));
|
|
4665
4727
|
var wasmModule = await WebAssembly.compile(wasm);
|
|
4666
4728
|
var replica = BigInt(`0x${randomBytes(8).toString("hex")}`) & (1n << 63n) - 1n;
|
|
4667
4729
|
var eng = await createEngine2({ wasmModule, bootstrapPkg: pkgs.bootstrap, nomosPkg: pkgs.nomos, replica, installedBy: "nomos-test-harness" });
|
|
@@ -4688,7 +4750,7 @@ var lawHashes = [];
|
|
|
4688
4750
|
var expectedDomainLaw = /* @__PURE__ */ new Map();
|
|
4689
4751
|
for (const p of deployPaths) {
|
|
4690
4752
|
if (!existsSync(p)) die(`deploy JSON not found: ${p} \u2014 run \`npx githolon compile\` first`);
|
|
4691
|
-
const deploy2 = JSON.parse(
|
|
4753
|
+
const deploy2 = JSON.parse(readFileSync2(p, "utf8"));
|
|
4692
4754
|
const usda = deploy2.packageUsda;
|
|
4693
4755
|
if (typeof usda !== "string" || !usda.startsWith("#usda")) die(`${p} has no #usda packageUsda`);
|
|
4694
4756
|
const lawHash = await sha256hex2(usda);
|