githolon 0.67.0 → 0.69.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 +1034 -107
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -24,7 +24,7 @@ function makeGitFs(preopen, mount, { File: File3, Directory: Directory3 }) {
|
|
|
24
24
|
const rel = p.slice(mount.length + 1).replace(/\/+$/, "");
|
|
25
25
|
return rel === "" ? [] : rel.split("/");
|
|
26
26
|
}
|
|
27
|
-
function
|
|
27
|
+
function resolve6(ps) {
|
|
28
28
|
let cur = root;
|
|
29
29
|
for (const part of ps) {
|
|
30
30
|
if (!isDir(cur)) return null;
|
|
@@ -34,11 +34,11 @@ function makeGitFs(preopen, mount, { File: File3, Directory: Directory3 }) {
|
|
|
34
34
|
}
|
|
35
35
|
return cur;
|
|
36
36
|
}
|
|
37
|
-
const parent = (ps) =>
|
|
37
|
+
const parent = (ps) => resolve6(ps.slice(0, -1));
|
|
38
38
|
const leaf = (ps) => ps[ps.length - 1];
|
|
39
39
|
const promises = {
|
|
40
40
|
async readFile(p, opts) {
|
|
41
|
-
const n =
|
|
41
|
+
const n = resolve6(parts(p));
|
|
42
42
|
if (n === null) throw fsErr("ENOENT", p);
|
|
43
43
|
if (isDir(n)) throw fsErr("EISDIR", p);
|
|
44
44
|
const data = n.data ?? new Uint8Array(0);
|
|
@@ -57,7 +57,7 @@ function makeGitFs(preopen, mount, { File: File3, Directory: Directory3 }) {
|
|
|
57
57
|
if (!isDir(par) || !par.contents.delete(leaf(ps))) throw fsErr("ENOENT", p);
|
|
58
58
|
},
|
|
59
59
|
async readdir(p) {
|
|
60
|
-
const n =
|
|
60
|
+
const n = resolve6(parts(p));
|
|
61
61
|
if (n === null) throw fsErr("ENOENT", p);
|
|
62
62
|
if (!isDir(n)) throw fsErr("ENOTDIR", p);
|
|
63
63
|
return [...n.contents.keys()];
|
|
@@ -77,7 +77,7 @@ function makeGitFs(preopen, mount, { File: File3, Directory: Directory3 }) {
|
|
|
77
77
|
return promises.lstat(p);
|
|
78
78
|
},
|
|
79
79
|
async lstat(p) {
|
|
80
|
-
const n =
|
|
80
|
+
const n = resolve6(parts(p));
|
|
81
81
|
if (n === null) throw fsErr("ENOENT", p);
|
|
82
82
|
const dir = isDir(n);
|
|
83
83
|
return {
|
|
@@ -386,6 +386,7 @@ __export(engine_exports, {
|
|
|
386
386
|
ingestPackAsCustody: () => ingestPackAsCustody,
|
|
387
387
|
installPayload: () => installPayload,
|
|
388
388
|
installedLaw: () => installedLaw,
|
|
389
|
+
kgit: () => kgit,
|
|
389
390
|
lawParity: () => lawParity,
|
|
390
391
|
ledgerStats: () => ledgerStats,
|
|
391
392
|
listRefusedRefs: () => listRefusedRefs,
|
|
@@ -414,6 +415,7 @@ __export(engine_exports, {
|
|
|
414
415
|
readCheckpointBlob: () => readCheckpointBlob,
|
|
415
416
|
readPosture: () => readPosture,
|
|
416
417
|
readShape: () => readShape,
|
|
418
|
+
rebirthCompact: () => rebirthCompact,
|
|
417
419
|
refreshProjection: () => refreshProjection,
|
|
418
420
|
replicateIntents: () => replicateIntents,
|
|
419
421
|
repoArgOf: () => repoArgOf,
|
|
@@ -2169,6 +2171,123 @@ async function verifyChain(eng, ws, ledger) {
|
|
|
2169
2171
|
function verifyChainLocal(eng, ws) {
|
|
2170
2172
|
return JSON.parse(call(eng.ex, "query", { repoArg: repoArgOf(ws), workspace: ws, queryBytes: b64Json({ op: "verifyChain" }), branch: BRANCH }, eng.STDERR));
|
|
2171
2173
|
}
|
|
2174
|
+
async function rebirthCompact(eng, ws, ledger, { reason = "", supersededAt = 0, parent = "" } = {}) {
|
|
2175
|
+
const incWs = `${ws}__rebirth`;
|
|
2176
|
+
try {
|
|
2177
|
+
if (!eng.mounted.has(ws)) await mountWorkspace(eng, ws, ledger || { remote: "https://unborn.invalid/", headers: {} });
|
|
2178
|
+
const srcGitdir = gitdirOf(ws);
|
|
2179
|
+
const oldHead = kgit.resolveRef(eng, srcGitdir, BRANCH);
|
|
2180
|
+
if (!/^[0-9a-f]{40}$/i.test(oldHead || "")) return { ok: false, error: `'${ws}' has no refs/heads/main to rebirth \u2014 nothing to compact` };
|
|
2181
|
+
const sealed = kgit.intentsAbove(eng, srcGitdir, oldHead, "", 0);
|
|
2182
|
+
if (!Array.isArray(sealed) || !sealed.length) return { ok: false, error: `'${ws}' main carries no intents to replay` };
|
|
2183
|
+
unmount(eng, incWs);
|
|
2184
|
+
await mountEphemeralWorkspace(eng, incWs, {});
|
|
2185
|
+
const isGenesisBootstrapInstall = (c) => {
|
|
2186
|
+
try {
|
|
2187
|
+
const doc = JSON.parse(dec3.decode(bytesFromB64(c.intentB64)));
|
|
2188
|
+
return doc?.payload?.domain === "bootstrap" && doc?.payload?.directiveId === "installDomain";
|
|
2189
|
+
} catch {
|
|
2190
|
+
return false;
|
|
2191
|
+
}
|
|
2192
|
+
};
|
|
2193
|
+
const transformState = (sealedBytes) => sealedBytes;
|
|
2194
|
+
const carried = [];
|
|
2195
|
+
const parkedIntents = [];
|
|
2196
|
+
const parkedBlobs = [];
|
|
2197
|
+
let idx = -1, lastCarriedIdx = -1, firstParkedIdx = -1;
|
|
2198
|
+
for (const c of sealed) {
|
|
2199
|
+
idx++;
|
|
2200
|
+
if (isGenesisBootstrapInstall(c)) continue;
|
|
2201
|
+
let bytes;
|
|
2202
|
+
try {
|
|
2203
|
+
bytes = transformState(bytesFromB64(c.intentB64), { oid: c.oid, incWs });
|
|
2204
|
+
} catch {
|
|
2205
|
+
parkedIntents.push({ oid: c.oid, reason: "undecodable intent blob" });
|
|
2206
|
+
parkedBlobs.push(bytesFromB64(c.intentB64));
|
|
2207
|
+
if (firstParkedIdx < 0) firstParkedIdx = idx;
|
|
2208
|
+
continue;
|
|
2209
|
+
}
|
|
2210
|
+
const r = applyIntentBytes(eng, incWs, bytes, { defer: false });
|
|
2211
|
+
if (r && r.ok) {
|
|
2212
|
+
carried.push(c.oid);
|
|
2213
|
+
lastCarriedIdx = idx;
|
|
2214
|
+
} else {
|
|
2215
|
+
parkedIntents.push({ oid: c.oid, reason: String(r && r.error || "refused").slice(0, 200) });
|
|
2216
|
+
parkedBlobs.push(bytes);
|
|
2217
|
+
if (firstParkedIdx < 0) firstParkedIdx = idx;
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
const scarShape = parkedIntents.length === 0 ? "none" : firstParkedIdx > lastCarriedIdx ? "tail" : "mid-chain";
|
|
2221
|
+
const incGitdir = gitdirOf(incWs);
|
|
2222
|
+
const head = kgit.resolveRef(eng, incGitdir, BRANCH);
|
|
2223
|
+
if (!/^[0-9a-f]{40}$/i.test(head || "")) {
|
|
2224
|
+
unmount(eng, incWs);
|
|
2225
|
+
return { ok: false, error: `the incarnation folded no intents (all ${sealed.length} refused \u2014 all parked-to-be, nothing to serve)`, parked: parkedIntents.length, parkedIntents };
|
|
2226
|
+
}
|
|
2227
|
+
const incChain = kgit.intentsAbove(eng, incGitdir, head, "", 0);
|
|
2228
|
+
const genesisOid = incChain.length ? incChain[0].oid : head;
|
|
2229
|
+
let parkedRef = "";
|
|
2230
|
+
let parkedTip = "";
|
|
2231
|
+
if (parkedBlobs.length) {
|
|
2232
|
+
parkedRef = `refs/heads/unreplayed/${supersededAt || Date.now()}`;
|
|
2233
|
+
let parentOid = head;
|
|
2234
|
+
for (let i = 0; i < parkedBlobs.length; i++) {
|
|
2235
|
+
parentOid = kgit.writeMetaCommit(eng, incGitdir, {
|
|
2236
|
+
parents: [parentOid],
|
|
2237
|
+
files: [{ path: "intent.json", bytes: parkedBlobs[i] }],
|
|
2238
|
+
message: `unreplayed: ${parkedIntents[i].oid.slice(0, 12)} \u2014 ${parkedIntents[i].reason.slice(0, 120)}`,
|
|
2239
|
+
timeSecs: 0,
|
|
2240
|
+
ref: i === parkedBlobs.length - 1 ? parkedRef : ""
|
|
2241
|
+
});
|
|
2242
|
+
}
|
|
2243
|
+
parkedTip = parentOid;
|
|
2244
|
+
}
|
|
2245
|
+
const verdict = verifyChainLocal(eng, incWs);
|
|
2246
|
+
const verified = verdict && verdict.valid === true;
|
|
2247
|
+
let packB64 = "";
|
|
2248
|
+
let parkedPackB64 = "";
|
|
2249
|
+
if (verified) {
|
|
2250
|
+
const pack = packDelta(eng, incWs, "", head);
|
|
2251
|
+
if (pack && pack.length) packB64 = b64Bytes(pack);
|
|
2252
|
+
if (parkedTip) {
|
|
2253
|
+
const ppack = packDelta(eng, incWs, head, parkedTip);
|
|
2254
|
+
if (ppack && ppack.length) parkedPackB64 = b64Bytes(ppack);
|
|
2255
|
+
if (!parkedPackB64) {
|
|
2256
|
+
unmount(eng, incWs);
|
|
2257
|
+
return { ok: false, error: "parked intents exist but produced no parked pack \u2014 refusing (parked work must never be lost)", parked: parkedIntents.length };
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
unmount(eng, incWs);
|
|
2262
|
+
if (verified && !packB64) return { ok: false, error: "the incarnation self-verified but produced no pack", verified: true };
|
|
2263
|
+
return {
|
|
2264
|
+
ok: true,
|
|
2265
|
+
packB64,
|
|
2266
|
+
head,
|
|
2267
|
+
genesisOid,
|
|
2268
|
+
verified,
|
|
2269
|
+
...verified ? {} : { verifyError: verdict && verdict.error || "verify_chain returned invalid" },
|
|
2270
|
+
carried: carried.length,
|
|
2271
|
+
parked: parkedIntents.length,
|
|
2272
|
+
parkedIntents,
|
|
2273
|
+
scarShape,
|
|
2274
|
+
...parkedTip ? { parkedRef, parkedTip, parkedPackB64 } : {},
|
|
2275
|
+
// rebornFrom = the SUPERSEDED chain's genesis oid (the old ancestry the reborn holon descends
|
|
2276
|
+
// from). Surfaced for the worker's status contract; NOT re-authored IN-CHAIN here (stamping it
|
|
2277
|
+
// onto birthCloud would re-sign the record → the operator key, the CLI lane).
|
|
2278
|
+
rebornFrom: sealed[0].oid,
|
|
2279
|
+
parent,
|
|
2280
|
+
reason,
|
|
2281
|
+
supersededAt
|
|
2282
|
+
};
|
|
2283
|
+
} catch (e) {
|
|
2284
|
+
try {
|
|
2285
|
+
unmount(eng, incWs);
|
|
2286
|
+
} catch {
|
|
2287
|
+
}
|
|
2288
|
+
return { ok: false, error: String(e && e.message || e).slice(0, 300) };
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2172
2291
|
async function archiveRefusedMain(eng, ws, ledger, label) {
|
|
2173
2292
|
unmount(eng, ws);
|
|
2174
2293
|
const m = await mountWorkspace(eng, ws, ledger);
|
|
@@ -2483,6 +2602,8 @@ var init_engine = __esm({
|
|
|
2483
2602
|
writeRef: (eng, gitdir, ref, value) => JSON.parse(call(eng.ex, "write_ref", { repoArg: repoArgOfGitdir(gitdir), ref, value }, eng.STDERR)),
|
|
2484
2603
|
// deleteRef → remove a local ref, idempotent (replaces git.deleteRef).
|
|
2485
2604
|
deleteRef: (eng, gitdir, ref) => JSON.parse(call(eng.ex, "delete_ref", { repoArg: repoArgOfGitdir(gitdir), ref }, eng.STDERR)),
|
|
2605
|
+
// applyPack → ingest a pack's objects into ws's repo (kernel apply_pack; refs are the caller's job).
|
|
2606
|
+
applyPack: (eng, ws, packBytes) => applyPackInto(eng, ws, packBytes),
|
|
2486
2607
|
// writeMetaCommit → blobs→tree→commit→ref for a CUSTODY-META fact (checkpoint/refused/outbox/shape).
|
|
2487
2608
|
// `files`: [{ path, bytes:Uint8Array }]; returns the commit oid (replaces writeBlob+writeTree+writeCommit[+writeRef]).
|
|
2488
2609
|
writeMetaCommit: (eng, gitdir, { parents = [], files, message = "nomos custody meta", timeSecs = 0, ref = "" }) => JSON.parse(call(eng.ex, "write_meta_commit", {
|
|
@@ -2710,7 +2831,10 @@ var init_local_holon = __esm({
|
|
|
2710
2831
|
// src/governance.ts
|
|
2711
2832
|
var governance_exports = {};
|
|
2712
2833
|
__export(governance_exports, {
|
|
2834
|
+
buildCertificate: () => buildCertificate,
|
|
2835
|
+
buildRebirthPlan: () => buildRebirthPlan,
|
|
2713
2836
|
certifyEra: () => certifyEra,
|
|
2837
|
+
executeRepairRebirth: () => executeRepairRebirth,
|
|
2714
2838
|
governanceOffer: () => governanceOffer,
|
|
2715
2839
|
governanceRelay: () => governanceRelay,
|
|
2716
2840
|
grantOrRevoke: () => grantOrRevoke,
|
|
@@ -2718,12 +2842,19 @@ __export(governance_exports, {
|
|
|
2718
2842
|
keyExport: () => keyExport,
|
|
2719
2843
|
keyImport: () => keyImport,
|
|
2720
2844
|
keyShow: () => keyShow,
|
|
2845
|
+
rebirthApply: () => rebirthApply,
|
|
2846
|
+
rebirthPlanCommand: () => rebirthPlanCommand,
|
|
2847
|
+
rebirthWorkspace: () => rebirthWorkspace,
|
|
2848
|
+
renderRebirthImpact: () => renderRebirthImpact,
|
|
2721
2849
|
resolveGovernancePrincipal: () => resolveGovernancePrincipal,
|
|
2722
2850
|
signAndPostGovernance: () => signAndPostGovernance,
|
|
2723
|
-
signAndPostOffer: () => signAndPostOffer
|
|
2851
|
+
signAndPostOffer: () => signAndPostOffer,
|
|
2852
|
+
validatePlanForApply: () => validatePlanForApply,
|
|
2853
|
+
verifyWorkspaceVerdict: () => verifyWorkspaceVerdict
|
|
2724
2854
|
});
|
|
2725
2855
|
import { createHash, createPrivateKey, createPublicKey } from "node:crypto";
|
|
2726
|
-
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
2856
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
2857
|
+
import { dirname as dirname2, join as join3 } from "node:path";
|
|
2727
2858
|
async function clientConnect() {
|
|
2728
2859
|
const mod = await import("@githolon/client");
|
|
2729
2860
|
return mod.connect;
|
|
@@ -3163,6 +3294,549 @@ certify-era ${ws}:`);
|
|
|
3163
3294
|
out2(` verify: githolon ledger verify ${ws} (expect GREEN with certifiedRanges naming the oids)`);
|
|
3164
3295
|
return 0;
|
|
3165
3296
|
}
|
|
3297
|
+
async function parkedAreAllLawInstalls(engMod, eng, ws, oids) {
|
|
3298
|
+
try {
|
|
3299
|
+
const git4 = (await import("isomorphic-git")).default;
|
|
3300
|
+
const { gitdirOf: gitdirOf2 } = engMod;
|
|
3301
|
+
const fs = eng.fs;
|
|
3302
|
+
const gitdir = gitdirOf2(ws);
|
|
3303
|
+
const dec4 = new TextDecoder();
|
|
3304
|
+
for (const oid of oids) {
|
|
3305
|
+
const { blob } = await git4.readBlob({ fs, gitdir, oid, filepath: "intent.json" });
|
|
3306
|
+
const doc = JSON.parse(dec4.decode(blob));
|
|
3307
|
+
const domain = doc.payload?.domain;
|
|
3308
|
+
const dir = doc.payload?.directiveId;
|
|
3309
|
+
if (!((domain === "nomos" || domain === "bootstrap") && dir === "installDomain")) return false;
|
|
3310
|
+
}
|
|
3311
|
+
return true;
|
|
3312
|
+
} catch {
|
|
3313
|
+
return false;
|
|
3314
|
+
}
|
|
3315
|
+
}
|
|
3316
|
+
async function buildRebirthPlan(cloud, ws, reason) {
|
|
3317
|
+
const engMod = await Promise.resolve().then(() => (init_engine(), engine_exports));
|
|
3318
|
+
const { query: query2, verifyChainLocal: verifyChainLocal2 } = engMod;
|
|
3319
|
+
const { mountWorkspace: mountWorkspace2 } = engMod;
|
|
3320
|
+
const { holonEngine: holonEngine2 } = await Promise.resolve().then(() => (init_local_holon(), local_holon_exports));
|
|
3321
|
+
let eng;
|
|
3322
|
+
try {
|
|
3323
|
+
({ eng } = await holonEngine2(cloud, void 0, "gov-rebirth-plan"));
|
|
3324
|
+
const m = await mountWorkspace2(eng, "root", { remote: `${cloud}/v2/workspaces/root/git`, headers: {} });
|
|
3325
|
+
if (m.restored !== true) return { error: `root has no ledger on ${cloud} \u2014 cannot analyse a supersession` };
|
|
3326
|
+
} catch (e) {
|
|
3327
|
+
return { error: `could not mount root: ${e.message}` };
|
|
3328
|
+
}
|
|
3329
|
+
const rows = query2(eng, "root", "workspaceByName", JSON.stringify({ name: ws }));
|
|
3330
|
+
const rec = rows[rows.length - 1];
|
|
3331
|
+
const workspaceId = rec?.id;
|
|
3332
|
+
if (typeof workspaceId !== "string" || workspaceId === "") {
|
|
3333
|
+
return { error: `no CloudWorkspace record named '${ws}' in root's registry \u2014 cannot supersede an unregistered workspace`, status: 404 };
|
|
3334
|
+
}
|
|
3335
|
+
const isRoot = String(rec?.data?.["name"]) === "root" || ws === "root";
|
|
3336
|
+
const parent = String(rec?.data?.["parent"] ?? "");
|
|
3337
|
+
let children = [];
|
|
3338
|
+
try {
|
|
3339
|
+
const kids = query2(eng, "root", "workspacesByParent", JSON.stringify({ parent: workspaceId }));
|
|
3340
|
+
children = kids.map((k) => String(k?.data?.["name"] ?? "")).filter((n) => n !== "").map((name) => ({ name, preserved: true }));
|
|
3341
|
+
} catch {
|
|
3342
|
+
}
|
|
3343
|
+
let incarnation = null;
|
|
3344
|
+
let priorSupersessions = 0;
|
|
3345
|
+
let ledgerCommits = null;
|
|
3346
|
+
try {
|
|
3347
|
+
const s = await (await fetch(`${cloud}/v2/workspaces/${ws}`)).json();
|
|
3348
|
+
incarnation = typeof s.incarnation === "string" && s.incarnation !== "" ? s.incarnation : null;
|
|
3349
|
+
priorSupersessions = Array.isArray(s.supersededChains) ? s.supersededChains.length : 0;
|
|
3350
|
+
ledgerCommits = Number.isFinite(s.ledgerState?.commits) ? s.ledgerState?.commits ?? null : null;
|
|
3351
|
+
} catch {
|
|
3352
|
+
}
|
|
3353
|
+
const lawHashes = {};
|
|
3354
|
+
try {
|
|
3355
|
+
const d = await (await fetch(`${cloud}/v2/workspaces/${ws}/domains`)).json();
|
|
3356
|
+
for (const dom of d.domains ?? []) {
|
|
3357
|
+
if (typeof dom.domainHash === "string" && dom.phase === "Active") lawHashes[dom.domainHash] = dom.phase;
|
|
3358
|
+
}
|
|
3359
|
+
} catch {
|
|
3360
|
+
}
|
|
3361
|
+
let verdict = { replay: "unknown", firstRefusal: null };
|
|
3362
|
+
try {
|
|
3363
|
+
const m = await mountWorkspace2(eng, ws, { remote: `${cloud}/v2/workspaces/${ws}/git`, headers: {} });
|
|
3364
|
+
if (m.restored === true) {
|
|
3365
|
+
const v = verifyChainLocal2(eng, ws);
|
|
3366
|
+
if (v["valid"] === true) verdict = { replay: "green", firstRefusal: null };
|
|
3367
|
+
else verdict = { replay: "red", firstRefusal: `${String(v["check"] ?? "?")}${v["atIndex"] !== void 0 ? ` @intent ${v["atIndex"]}` : ""}: ${String(v["error"] ?? "").slice(0, 200)}` };
|
|
3368
|
+
}
|
|
3369
|
+
} catch {
|
|
3370
|
+
}
|
|
3371
|
+
let compaction = { carried: null, parked: null, scarShape: "unknown" };
|
|
3372
|
+
let parkedAllLawInstalls = false;
|
|
3373
|
+
try {
|
|
3374
|
+
const { rebirthCompact: rebirthCompact2 } = engMod;
|
|
3375
|
+
const est = await rebirthCompact2(eng, ws, { remote: `${cloud}/v2/workspaces/${ws}/git`, headers: {} }, { parent });
|
|
3376
|
+
if (est?.ok === true) {
|
|
3377
|
+
const shape = est.scarShape === "none" || est.scarShape === "tail" || est.scarShape === "mid-chain" ? est.scarShape : "unknown";
|
|
3378
|
+
compaction = { carried: est.carried ?? null, parked: est.parked ?? null, scarShape: shape };
|
|
3379
|
+
const parkedOids = (est.parkedIntents ?? []).map((p) => p?.oid).filter((o) => typeof o === "string");
|
|
3380
|
+
if (parkedOids.length > 0 && parkedOids.length <= 2) {
|
|
3381
|
+
parkedAllLawInstalls = await parkedAreAllLawInstalls(engMod, eng, ws, parkedOids);
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
} catch {
|
|
3385
|
+
}
|
|
3386
|
+
const mode = compaction.scarShape === "mid-chain" && !((compaction.parked ?? 99) <= 2 && parkedAllLawInstalls) ? "state-seed" : "replay-compact";
|
|
3387
|
+
const frozenAt = priorSupersessions === 0 ? ws : `${ws}--i${priorSupersessions}`;
|
|
3388
|
+
const newCustodyAddress = `${ws}--i${priorSupersessions + 1}`;
|
|
3389
|
+
const plan = {
|
|
3390
|
+
v: 1,
|
|
3391
|
+
workspace: ws,
|
|
3392
|
+
reason: reason ?? null,
|
|
3393
|
+
pinned: { incarnation, lawHashes, parent },
|
|
3394
|
+
will: {
|
|
3395
|
+
newCustodyAddress,
|
|
3396
|
+
frozenAt,
|
|
3397
|
+
lineageFacts: { supersededBy: newCustodyAddress, rebornFrom: incarnation ?? "" }
|
|
3398
|
+
},
|
|
3399
|
+
children,
|
|
3400
|
+
verdict,
|
|
3401
|
+
mode,
|
|
3402
|
+
compaction,
|
|
3403
|
+
repairs: [],
|
|
3404
|
+
clientImpact: CLIENT_IMPACT,
|
|
3405
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3406
|
+
};
|
|
3407
|
+
return { plan, workspaceId, ledgerCommits, isRoot };
|
|
3408
|
+
}
|
|
3409
|
+
function renderRebirthImpact(plan, ledgerCommits) {
|
|
3410
|
+
const L = [];
|
|
3411
|
+
const dim = (s) => s;
|
|
3412
|
+
L.push(`REBIRTH IMPACT \u2014 ${plan.workspace}`);
|
|
3413
|
+
L.push("\u2550".repeat(48));
|
|
3414
|
+
L.push("");
|
|
3415
|
+
L.push("CURRENT STATE");
|
|
3416
|
+
L.push(` incarnation : ${plan.pinned.incarnation ? plan.pinned.incarnation.slice(0, 16) + "\u2026" : "(none recorded \u2014 first incarnation)"}`);
|
|
3417
|
+
L.push(` verify_chain : ${plan.verdict.replay.toUpperCase()}${plan.verdict.firstRefusal ? ` \u2014 first refusal: ${plan.verdict.firstRefusal}` : ""}`);
|
|
3418
|
+
L.push(` ledger size : ${ledgerCommits !== null ? `${ledgerCommits} commit(s)` : "(unknown)"}`);
|
|
3419
|
+
const laws = Object.keys(plan.pinned.lawHashes);
|
|
3420
|
+
L.push(` installed law : ${laws.length ? laws.map((h) => h.slice(0, 12) + "\u2026").join(", ") : "(none read)"}`);
|
|
3421
|
+
L.push(` parent : ${plan.pinned.parent || "(root)"}`);
|
|
3422
|
+
L.push("");
|
|
3423
|
+
L.push("WHAT A REBIRTH WOULD DO");
|
|
3424
|
+
L.push(` new custody : ${plan.will.newCustodyAddress} (the incarnation is born here, self-verified GREEN from intent 0 before the name repoints)`);
|
|
3425
|
+
L.push(` old holon \u2192 FROZEN UNTOUCHED at ${plan.will.frozenAt} (retained, GC-later; never rewritten)`);
|
|
3426
|
+
L.push(` parent : ${plan.pinned.parent || "(root)"} (UNCHANGED \u2014 a rebirth may never reparent)`);
|
|
3427
|
+
L.push(` lineage facts : supersededBy=${plan.will.lineageFacts.supersededBy} \xB7 rebornFrom=${plan.will.lineageFacts.rebornFrom ? plan.will.lineageFacts.rebornFrom.slice(0, 16) + "\u2026" : "(the current incarnation)"} \xB7 reason=${plan.reason ?? "(supply --reason)"}`);
|
|
3428
|
+
L.push("");
|
|
3429
|
+
L.push(`COMPACTION (mode: ${plan.mode})`);
|
|
3430
|
+
const c = plan.compaction;
|
|
3431
|
+
const n = (x) => x === null ? "?" : String(x);
|
|
3432
|
+
L.push(` replay-compact estimate : ${n(c.carried)} intent(s) CARRY onto the new main \xB7 ${n(c.parked)} PARK (scar shape: ${c.scarShape})`);
|
|
3433
|
+
if ((c.parked ?? 0) > 0 || c.scarShape === "unknown") {
|
|
3434
|
+
L.push(" parked intents are NEVER dropped \u2014 they land byte-identical, in order, on the session-shaped");
|
|
3435
|
+
L.push(" refs/heads/unreplayed/<ts> branch in the NEW repo, and re-enter through the STANDARD admit lane");
|
|
3436
|
+
L.push(" after the law is corrected (a law fix / dispositions deploy).");
|
|
3437
|
+
}
|
|
3438
|
+
if (c.scarShape === "mid-chain") {
|
|
3439
|
+
const rc = plan.mode === "replay-compact";
|
|
3440
|
+
L.push(" MID-CHAIN scar \u2014 two options, choose informed:");
|
|
3441
|
+
L.push(` \u2022 replay-compact : keeps ${n(c.carried)} admissible intent(s) (incl. post-scar ones); parks ${n(c.parked)} for later re-admission${rc ? " \u2014 RECOMMENDED" : ""}`);
|
|
3442
|
+
L.push(` \u2022 state-seed : the operator-signed compact re-genesis (current law + state seed, _rebirth_chains.mjs lane)${rc ? "" : " \u2014 RECOMMENDED"}`);
|
|
3443
|
+
if (rc) L.push(` \u2192 the parked set is \u22642 LAW INSTALL(s) (no data behind them) \u2014 replay-compact keeps FULL PROVENANCE at no real cost; the parked installs re-enter via the standard admit lane after the law fix.`);
|
|
3444
|
+
}
|
|
3445
|
+
L.push("");
|
|
3446
|
+
L.push(`CHILDREN (${plan.children.length})`);
|
|
3447
|
+
if (plan.children.length === 0) L.push(" (none \u2014 no downward lineage to preserve)");
|
|
3448
|
+
else {
|
|
3449
|
+
for (const c2 of plan.children) L.push(` \u2022 ${c2.name} [preserved]`);
|
|
3450
|
+
L.push(" \u2192 preserved by lineage continuity; their birth-cert chains stay valid (same founding key + self-id).");
|
|
3451
|
+
}
|
|
3452
|
+
L.push("");
|
|
3453
|
+
L.push("CLIENT IMPACT");
|
|
3454
|
+
L.push(` ${plan.clientImpact}.`);
|
|
3455
|
+
L.push(" Recommend tenants DRAIN/SYNC their clients before the rebirth window.");
|
|
3456
|
+
return L.join("\n");
|
|
3457
|
+
}
|
|
3458
|
+
async function rebirthPlanCommand(ws, opts) {
|
|
3459
|
+
const cloud = cloudBase(opts.cloud);
|
|
3460
|
+
const built = await buildRebirthPlan(cloud, ws, opts.reason ?? null);
|
|
3461
|
+
if ("error" in built) {
|
|
3462
|
+
err2(built.error);
|
|
3463
|
+
return 1;
|
|
3464
|
+
}
|
|
3465
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3466
|
+
const dir = opts.out ?? join3("rebirths", `${date}-${ws}`);
|
|
3467
|
+
try {
|
|
3468
|
+
mkdirSync3(dir, { recursive: true });
|
|
3469
|
+
writeFileSync3(join3(dir, "plan.json"), JSON.stringify(built.plan, null, 2) + "\n");
|
|
3470
|
+
writeFileSync3(join3(dir, "impact.md"), "```\n" + renderRebirthImpact(built.plan, built.ledgerCommits) + "\n```\n");
|
|
3471
|
+
} catch (e) {
|
|
3472
|
+
err2(`could not write the plan into ${dir}: ${e.message}`);
|
|
3473
|
+
return 1;
|
|
3474
|
+
}
|
|
3475
|
+
out2(renderRebirthImpact(built.plan, built.ledgerCommits));
|
|
3476
|
+
out2("");
|
|
3477
|
+
out2(`\u2713 plan written: ${join3(dir, "plan.json")} + ${join3(dir, "impact.md")}`);
|
|
3478
|
+
out2(" fill in `reason` before a future `githolon rebirth apply --plan` (apply is not yet available).");
|
|
3479
|
+
return 0;
|
|
3480
|
+
}
|
|
3481
|
+
async function rebirthWorkspace(ws, opts) {
|
|
3482
|
+
const cloudForPlan = cloudBase(opts.cloud);
|
|
3483
|
+
if (opts.dryRun === true) {
|
|
3484
|
+
const built = await buildRebirthPlan(cloudForPlan, ws, opts.reason ?? null);
|
|
3485
|
+
if ("error" in built) {
|
|
3486
|
+
err2(built.error);
|
|
3487
|
+
return 1;
|
|
3488
|
+
}
|
|
3489
|
+
if (opts.json === true) out2(JSON.stringify(built.plan, null, 2));
|
|
3490
|
+
else {
|
|
3491
|
+
out2(renderRebirthImpact(built.plan, built.ledgerCommits));
|
|
3492
|
+
out2("");
|
|
3493
|
+
out2("DRY RUN \u2014 nothing was changed.");
|
|
3494
|
+
}
|
|
3495
|
+
return 0;
|
|
3496
|
+
}
|
|
3497
|
+
const reason = opts.reason;
|
|
3498
|
+
if (reason === void 0 || reason.trim() === "") {
|
|
3499
|
+
err2("gov rebirth requires a --reason (the mandatory audit justification for superseding this chain)");
|
|
3500
|
+
return 1;
|
|
3501
|
+
}
|
|
3502
|
+
if (ws === "root") {
|
|
3503
|
+
err2("the law refuses to rebirth root \u2014 the seat of the authorizing law cannot supersede itself");
|
|
3504
|
+
return 1;
|
|
3505
|
+
}
|
|
3506
|
+
if (opts.plan !== void 0 && Array.isArray(opts.plan.repairs) && opts.plan.repairs.length > 0) {
|
|
3507
|
+
err2("repair verbs are not yet available \u2014 the plan may not carry repairs (the `repairs` array must be empty)");
|
|
3508
|
+
return 1;
|
|
3509
|
+
}
|
|
3510
|
+
let seed = opts.seedSecret ?? process.env["NOMOS_ROOT_SEED"];
|
|
3511
|
+
if (seed === void 0 && opts.gcpSecret !== void 0) {
|
|
3512
|
+
try {
|
|
3513
|
+
const { execFileSync } = await import("node:child_process");
|
|
3514
|
+
seed = execFileSync("gcloud", ["secrets", "versions", "access", "latest", "--secret", opts.gcpSecret], { encoding: "utf8" }).trim();
|
|
3515
|
+
} catch (e) {
|
|
3516
|
+
err2(`could not read GCP secret ${opts.gcpSecret}: ${e.message}`);
|
|
3517
|
+
return 1;
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
if (seed === void 0 || seed.trim() === "") {
|
|
3521
|
+
err2("gov rebirth needs the custodian seed \u2014 --seed-secret <b64>, env NOMOS_ROOT_SEED, or --gcp-secret <name>");
|
|
3522
|
+
return 1;
|
|
3523
|
+
}
|
|
3524
|
+
const cloud = cloudBase(opts.cloud);
|
|
3525
|
+
const engMod = await Promise.resolve().then(() => (init_engine(), engine_exports));
|
|
3526
|
+
const { author: author2, query: query2 } = engMod;
|
|
3527
|
+
const { holonEngine: holonEngine2 } = await Promise.resolve().then(() => (init_local_holon(), local_holon_exports));
|
|
3528
|
+
const { mountWorkspace: mountWorkspace2 } = engMod;
|
|
3529
|
+
let eng;
|
|
3530
|
+
try {
|
|
3531
|
+
({ eng } = await holonEngine2(cloud, void 0, "gov-rebirth"));
|
|
3532
|
+
const m = await mountWorkspace2(eng, "root", { remote: `${cloud}/v2/workspaces/root/git`, headers: {} });
|
|
3533
|
+
if (m.restored !== true) {
|
|
3534
|
+
err2(`root has no ledger on ${cloud} \u2014 cannot author a supersession`);
|
|
3535
|
+
return 1;
|
|
3536
|
+
}
|
|
3537
|
+
} catch (e) {
|
|
3538
|
+
err2(`could not mount root: ${e.message}`);
|
|
3539
|
+
return 1;
|
|
3540
|
+
}
|
|
3541
|
+
const rows = query2(eng, "root", "workspaceByName", JSON.stringify({ name: ws }));
|
|
3542
|
+
const rec = rows[rows.length - 1];
|
|
3543
|
+
const workspaceId = rec?.id;
|
|
3544
|
+
if (typeof workspaceId !== "string" || workspaceId === "") {
|
|
3545
|
+
err2(`no CloudWorkspace record named '${ws}' in root's registry \u2014 cannot supersede an unregistered workspace`);
|
|
3546
|
+
return 1;
|
|
3547
|
+
}
|
|
3548
|
+
if (String(rec?.data?.["name"]) === "root") {
|
|
3549
|
+
err2("refusing to rebirth root (the fixed point)");
|
|
3550
|
+
return 1;
|
|
3551
|
+
}
|
|
3552
|
+
if (opts.quiet !== true) {
|
|
3553
|
+
try {
|
|
3554
|
+
const built = await buildRebirthPlan(cloud, ws, reason);
|
|
3555
|
+
if (!("error" in built)) {
|
|
3556
|
+
out2("");
|
|
3557
|
+
out2(renderRebirthImpact(built.plan, built.ledgerCommits));
|
|
3558
|
+
}
|
|
3559
|
+
} catch {
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
if (opts.quiet !== true) {
|
|
3563
|
+
out2(`
|
|
3564
|
+
gov rebirth ${ws}:`);
|
|
3565
|
+
out2(` workspaceId : ${workspaceId}`);
|
|
3566
|
+
out2(` reason : ${reason}`);
|
|
3567
|
+
out2(` effect : supersedes the current chain \u2014 a NEW incarnation is re-genesised into fresh custody; the old holon is FROZEN UNTOUCHED at its own custody address (retained, GC-later)`);
|
|
3568
|
+
}
|
|
3569
|
+
if (opts.yes !== true && opts.quiet !== true) {
|
|
3570
|
+
const rl = (await import("node:readline")).createInterface({ input: process.stdin, output: process.stdout });
|
|
3571
|
+
const ans = await new Promise((res2) => rl.question(" proceed? [y/N] ", (a) => {
|
|
3572
|
+
rl.close();
|
|
3573
|
+
res2(a);
|
|
3574
|
+
}));
|
|
3575
|
+
if (!/^y(es)?$/i.test(ans.trim())) {
|
|
3576
|
+
out2("aborted (nothing signed).");
|
|
3577
|
+
return 1;
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
const rebornAt = Date.now();
|
|
3581
|
+
const controllerHash = opts.controllerHash ?? eng.hashes?.nomos;
|
|
3582
|
+
if (typeof controllerHash !== "string") {
|
|
3583
|
+
err2("could not resolve root's governance controller hash (pass --controller-hash)");
|
|
3584
|
+
return 1;
|
|
3585
|
+
}
|
|
3586
|
+
const res = author2(eng, "root", "workspaces", "rebirthWorkspace", { workspaceId, reason, rebornAt }, controllerHash, { authorSecret: seed, actor: "user:root-custodian" });
|
|
3587
|
+
if (res.ok === false) {
|
|
3588
|
+
err2(`rebirthWorkspace refused locally: ${res.error}`);
|
|
3589
|
+
return 1;
|
|
3590
|
+
}
|
|
3591
|
+
const intentBytes = readSealedIntentBytes(eng, "root", res.intentOut);
|
|
3592
|
+
if (intentBytes === void 0) {
|
|
3593
|
+
err2("could not read the sealed rebirthWorkspace bytes to relay");
|
|
3594
|
+
return 1;
|
|
3595
|
+
}
|
|
3596
|
+
let r;
|
|
3597
|
+
try {
|
|
3598
|
+
r = await fetch(`${cloud}/v2/workspaces/root/rebirthWorkspace`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ intentBytes }) });
|
|
3599
|
+
} catch (e) {
|
|
3600
|
+
err2(`relay to root failed: ${e.message}`);
|
|
3601
|
+
return 1;
|
|
3602
|
+
}
|
|
3603
|
+
const text = await r.text();
|
|
3604
|
+
if (!r.ok) {
|
|
3605
|
+
err2(`rebirthWorkspace refused by root (${r.status}): ${text.slice(0, 300)}`);
|
|
3606
|
+
return 1;
|
|
3607
|
+
}
|
|
3608
|
+
out2(`\u2713 rebirthWorkspace admitted at root \u2014 the supersession fact is folded; the bailiff will build the new incarnation`);
|
|
3609
|
+
out2(" waiting for the new incarnation to serve \u2026");
|
|
3610
|
+
for (let i = 0; i < 30; i++) {
|
|
3611
|
+
await new Promise((res2) => setTimeout(res2, 2e3));
|
|
3612
|
+
try {
|
|
3613
|
+
const s = await (await fetch(`${cloud}/v2/workspaces/${ws}`)).json();
|
|
3614
|
+
if (typeof s.incarnation === "string" && s.incarnation !== "") {
|
|
3615
|
+
out2(`\u2713 new incarnation serving: ${s.incarnation.slice(0, 16)}\u2026 (superseded chains retained: ${(s.supersededChains ?? []).length})`);
|
|
3616
|
+
out2(` verify: githolon ledger verify ${ws} (expect GREEN from intent 0)`);
|
|
3617
|
+
return 0;
|
|
3618
|
+
}
|
|
3619
|
+
} catch {
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
out2(` (the supersession is recorded; the custody swap has not surfaced an incarnation yet \u2014 check: githolon status ${ws})`);
|
|
3623
|
+
return 0;
|
|
3624
|
+
}
|
|
3625
|
+
function validatePlanForApply(plan, liveIncarnation) {
|
|
3626
|
+
if (plan.v !== 1) return { error: `unsupported plan schema v${String(plan.v)} \u2014 this CLI applies v1 plans` };
|
|
3627
|
+
if (typeof plan.workspace !== "string" || plan.workspace === "") return { error: "the plan names no workspace" };
|
|
3628
|
+
if (plan.reason === null || typeof plan.reason === "string" && plan.reason.trim() === "") {
|
|
3629
|
+
return { error: "the plan's `reason` is still null \u2014 fill it in (the mandatory audit justification) before apply" };
|
|
3630
|
+
}
|
|
3631
|
+
if (Array.isArray(plan.repairs) && plan.repairs.length > 0) {
|
|
3632
|
+
return { error: "repair verbs are not yet executable \u2014 the plan may not carry `repairs` (the array must be empty); state-transform verbs land in a future release" };
|
|
3633
|
+
}
|
|
3634
|
+
if (plan.pinned.incarnation !== null) {
|
|
3635
|
+
if (liveIncarnation === void 0) {
|
|
3636
|
+
return { error: "could not read the live workspace incarnation to confirm no drift \u2014 refusing (apply is drift-pinned)" };
|
|
3637
|
+
}
|
|
3638
|
+
if (liveIncarnation !== plan.pinned.incarnation) {
|
|
3639
|
+
return { error: `the live workspace has DRIFTED from the plan: pinned incarnation ${plan.pinned.incarnation.slice(0, 16)}\u2026 but live is ${liveIncarnation === null ? "(none)" : liveIncarnation.slice(0, 16) + "\u2026"} \u2014 re-run \`githolon rebirth plan\` and re-review` };
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
return { ok: true };
|
|
3643
|
+
}
|
|
3644
|
+
function buildCertificate(args) {
|
|
3645
|
+
const { plan } = args;
|
|
3646
|
+
return {
|
|
3647
|
+
v: 1,
|
|
3648
|
+
plan,
|
|
3649
|
+
executed: {
|
|
3650
|
+
at: args.at,
|
|
3651
|
+
custodian: args.custodian,
|
|
3652
|
+
oldIncarnation: args.oldIncarnation,
|
|
3653
|
+
newIncarnation: args.newIncarnation,
|
|
3654
|
+
newCustodyAddress: plan.will.newCustodyAddress,
|
|
3655
|
+
carried: plan.compaction.carried,
|
|
3656
|
+
parked: plan.compaction.parked,
|
|
3657
|
+
verdictBefore: args.verdictBefore,
|
|
3658
|
+
...args.firstRefusal ? { firstRefusal: args.firstRefusal } : {},
|
|
3659
|
+
verdictAfter: args.verdictAfter
|
|
3660
|
+
},
|
|
3661
|
+
supersessionFacts: {
|
|
3662
|
+
supersededBy: plan.will.newCustodyAddress,
|
|
3663
|
+
rebornFrom: args.oldIncarnation ?? plan.will.lineageFacts.rebornFrom,
|
|
3664
|
+
reason: plan.reason ?? "",
|
|
3665
|
+
custodian: args.custodian,
|
|
3666
|
+
at: args.at
|
|
3667
|
+
},
|
|
3668
|
+
...args.repair !== void 0 ? { repair: args.repair } : {}
|
|
3669
|
+
};
|
|
3670
|
+
}
|
|
3671
|
+
async function verifyWorkspaceVerdict(cloud, ws) {
|
|
3672
|
+
try {
|
|
3673
|
+
const engMod = await Promise.resolve().then(() => (init_engine(), engine_exports));
|
|
3674
|
+
const { verifyChainLocal: verifyChainLocal2 } = engMod;
|
|
3675
|
+
const { mountWorkspace: mountWorkspace2 } = engMod;
|
|
3676
|
+
const { holonEngine: holonEngine2 } = await Promise.resolve().then(() => (init_local_holon(), local_holon_exports));
|
|
3677
|
+
const { eng } = await holonEngine2(cloud, void 0, "rebirth-verify");
|
|
3678
|
+
const m = await mountWorkspace2(eng, ws, { remote: `${cloud}/v2/workspaces/${ws}/git`, headers: {} });
|
|
3679
|
+
if (m.restored !== true) return { replay: "unknown", firstRefusal: null };
|
|
3680
|
+
const v = verifyChainLocal2(eng, ws);
|
|
3681
|
+
if (v["valid"] === true) return { replay: "green", firstRefusal: null };
|
|
3682
|
+
return { replay: "red", firstRefusal: `${String(v["check"] ?? "?")}${v["atIndex"] !== void 0 ? ` @intent ${v["atIndex"]}` : ""}: ${String(v["error"] ?? "").slice(0, 200)}` };
|
|
3683
|
+
} catch {
|
|
3684
|
+
return { replay: "unknown", firstRefusal: null };
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3687
|
+
async function liveIncarnationOf(cloud, ws) {
|
|
3688
|
+
try {
|
|
3689
|
+
const s = await (await fetch(`${cloud}/v2/workspaces/${ws}`)).json();
|
|
3690
|
+
return typeof s.incarnation === "string" && s.incarnation !== "" ? s.incarnation : null;
|
|
3691
|
+
} catch {
|
|
3692
|
+
return void 0;
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
async function rebirthApply(planPath, opts) {
|
|
3696
|
+
let plan;
|
|
3697
|
+
try {
|
|
3698
|
+
plan = JSON.parse(readFileSync2(planPath, "utf8"));
|
|
3699
|
+
} catch (e) {
|
|
3700
|
+
err2(`cannot read the plan ${planPath}: ${e.message}`);
|
|
3701
|
+
return 1;
|
|
3702
|
+
}
|
|
3703
|
+
const cloud = cloudBase(opts.cloud);
|
|
3704
|
+
const ws = plan.workspace;
|
|
3705
|
+
const liveIncarnation = await liveIncarnationOf(cloud, ws);
|
|
3706
|
+
const check2 = validatePlanForApply(plan, liveIncarnation);
|
|
3707
|
+
if ("error" in check2) {
|
|
3708
|
+
err2(check2.error);
|
|
3709
|
+
return 1;
|
|
3710
|
+
}
|
|
3711
|
+
let ledgerCommits = null;
|
|
3712
|
+
try {
|
|
3713
|
+
const s = await (await fetch(`${cloud}/v2/workspaces/${ws}`)).json();
|
|
3714
|
+
ledgerCommits = Number.isFinite(s.ledgerState?.commits) ? s.ledgerState?.commits ?? null : null;
|
|
3715
|
+
} catch {
|
|
3716
|
+
}
|
|
3717
|
+
out2(renderRebirthImpact(plan, ledgerCommits));
|
|
3718
|
+
out2("");
|
|
3719
|
+
out2(`APPLY \u2014 driving the reviewed plan (pinned incarnation ${plan.pinned.incarnation ? plan.pinned.incarnation.slice(0, 16) + "\u2026" : "(none)"}, mode ${plan.mode}).`);
|
|
3720
|
+
if (opts.yes !== true) {
|
|
3721
|
+
const rl = (await import("node:readline")).createInterface({ input: process.stdin, output: process.stdout });
|
|
3722
|
+
const ans = await new Promise((res) => rl.question(" proceed with the rebirth? [y/N] ", (a) => {
|
|
3723
|
+
rl.close();
|
|
3724
|
+
res(a);
|
|
3725
|
+
}));
|
|
3726
|
+
if (!/^y(es)?$/i.test(ans.trim())) {
|
|
3727
|
+
out2("aborted (nothing signed).");
|
|
3728
|
+
return 1;
|
|
3729
|
+
}
|
|
3730
|
+
}
|
|
3731
|
+
const verdictBefore = plan.verdict.replay === "green" ? "green" : "red";
|
|
3732
|
+
const custodian = opts.principal ?? activePrincipal() ?? "root-custodian";
|
|
3733
|
+
const code = await rebirthWorkspace(ws, {
|
|
3734
|
+
...opts,
|
|
3735
|
+
reason: plan.reason ?? void 0,
|
|
3736
|
+
plan,
|
|
3737
|
+
quiet: true,
|
|
3738
|
+
yes: true
|
|
3739
|
+
});
|
|
3740
|
+
if (code !== 0) {
|
|
3741
|
+
err2("the rebirth did not complete \u2014 no certificate written (re-check status and retry)");
|
|
3742
|
+
return code;
|
|
3743
|
+
}
|
|
3744
|
+
const newIncarnation = await liveIncarnationOf(cloud, ws) ?? null;
|
|
3745
|
+
const verdictAfter = await verifyWorkspaceVerdict(cloud, ws);
|
|
3746
|
+
const cert = buildCertificate({
|
|
3747
|
+
plan,
|
|
3748
|
+
custodian,
|
|
3749
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3750
|
+
oldIncarnation: plan.pinned.incarnation,
|
|
3751
|
+
newIncarnation,
|
|
3752
|
+
verdictBefore,
|
|
3753
|
+
...plan.verdict.firstRefusal ? { firstRefusal: plan.verdict.firstRefusal } : {},
|
|
3754
|
+
verdictAfter
|
|
3755
|
+
});
|
|
3756
|
+
const certPath = join3(dirname2(planPath), "certificate.json");
|
|
3757
|
+
try {
|
|
3758
|
+
writeFileSync3(certPath, JSON.stringify(cert, null, 2) + "\n");
|
|
3759
|
+
} catch (e) {
|
|
3760
|
+
err2(`the rebirth succeeded but the certificate could not be written to ${certPath}: ${e.message}`);
|
|
3761
|
+
return 1;
|
|
3762
|
+
}
|
|
3763
|
+
out2(`\u2713 certificate written: ${certPath}`);
|
|
3764
|
+
if (verdictAfter.replay !== "green") {
|
|
3765
|
+
err2(`WARNING: the new incarnation did NOT verify green (${verdictAfter.replay}${verdictAfter.firstRefusal ? `: ${verdictAfter.firstRefusal}` : ""}) \u2014 investigate before trusting the rebirth`);
|
|
3766
|
+
return 1;
|
|
3767
|
+
}
|
|
3768
|
+
out2(` new incarnation verifies GREEN from intent 0 \u2014 the certificate is cross-checkable against root lineage.`);
|
|
3769
|
+
return 0;
|
|
3770
|
+
}
|
|
3771
|
+
async function executeRepairRebirth(cloud, ws, repair, verdict, opts) {
|
|
3772
|
+
const cloudBaseUrl = cloudBase(cloud);
|
|
3773
|
+
const reason = `${repair.reason} [repair:${repair.id}]`;
|
|
3774
|
+
const built = await buildRebirthPlan(cloudBaseUrl, ws, reason);
|
|
3775
|
+
if ("error" in built) {
|
|
3776
|
+
err2(built.error);
|
|
3777
|
+
return 1;
|
|
3778
|
+
}
|
|
3779
|
+
const plan = built.plan;
|
|
3780
|
+
out2("");
|
|
3781
|
+
out2(renderRebirthImpact(plan, built.ledgerCommits));
|
|
3782
|
+
out2("");
|
|
3783
|
+
out2(`\u2726 REPAIR: '${repair.id}' (${repair.file})`);
|
|
3784
|
+
out2(` matches: ${repair.matcher.refusal} \xB7 stable id ${repair.matcher.stableId}`);
|
|
3785
|
+
out2(` reason : ${repair.reason}`);
|
|
3786
|
+
out2(` NOTE: repair verb recorded; state transform verbs land in a future release (v1 executes the`);
|
|
3787
|
+
out2(` rebirth with the repair recorded in the reason + certificate \u2014 no state is transformed yet).`);
|
|
3788
|
+
if (opts.yes !== true) {
|
|
3789
|
+
const rl = (await import("node:readline")).createInterface({ input: process.stdin, output: process.stdout });
|
|
3790
|
+
const ans = await new Promise((res) => rl.question(" execute this repair (a rebirth)? [y/N] ", (a) => {
|
|
3791
|
+
rl.close();
|
|
3792
|
+
res(a);
|
|
3793
|
+
}));
|
|
3794
|
+
if (!/^y(es)?$/i.test(ans.trim())) {
|
|
3795
|
+
out2("aborted (nothing signed).");
|
|
3796
|
+
return 1;
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
const custodian = opts.principal ?? activePrincipal() ?? "root-custodian";
|
|
3800
|
+
const verdictBefore = "red";
|
|
3801
|
+
const firstRefusal = `${String(verdict["check"] ?? "?")}: ${String(verdict["error"] ?? "").slice(0, 200)}`;
|
|
3802
|
+
const code = await rebirthWorkspace(ws, { ...opts, reason, plan, quiet: true, yes: true });
|
|
3803
|
+
if (code !== 0) {
|
|
3804
|
+
err2("the repair rebirth did not complete \u2014 no certificate written");
|
|
3805
|
+
return code;
|
|
3806
|
+
}
|
|
3807
|
+
const newIncarnation = await liveIncarnationOf(cloudBaseUrl, ws) ?? null;
|
|
3808
|
+
const verdictAfter = await verifyWorkspaceVerdict(cloudBaseUrl, ws);
|
|
3809
|
+
const cert = buildCertificate({
|
|
3810
|
+
plan,
|
|
3811
|
+
custodian,
|
|
3812
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3813
|
+
oldIncarnation: plan.pinned.incarnation,
|
|
3814
|
+
newIncarnation,
|
|
3815
|
+
verdictBefore,
|
|
3816
|
+
firstRefusal,
|
|
3817
|
+
verdictAfter,
|
|
3818
|
+
repair: {
|
|
3819
|
+
id: repair.id,
|
|
3820
|
+
file: repair.file,
|
|
3821
|
+
matcher: { refusal: repair.matcher.refusal, stableId: repair.matcher.stableId },
|
|
3822
|
+
note: "repair verb recorded; state transform verbs land in a future release (v1 rebirth only)"
|
|
3823
|
+
}
|
|
3824
|
+
});
|
|
3825
|
+
const certPath = join3(dirname2(repair.file), "certificate.json");
|
|
3826
|
+
try {
|
|
3827
|
+
writeFileSync3(certPath, JSON.stringify(cert, null, 2) + "\n");
|
|
3828
|
+
} catch (e) {
|
|
3829
|
+
err2(`the repair rebirth succeeded but the certificate could not be written to ${certPath}: ${e.message}`);
|
|
3830
|
+
return 1;
|
|
3831
|
+
}
|
|
3832
|
+
out2(`\u2713 certificate written: ${certPath}`);
|
|
3833
|
+
if (verdictAfter.replay !== "green") {
|
|
3834
|
+
err2(`WARNING: the new incarnation did NOT verify green (${verdictAfter.replay}) \u2014 investigate`);
|
|
3835
|
+
return 1;
|
|
3836
|
+
}
|
|
3837
|
+
out2(` re-run \`githolon replay ${ws}\` \u2014 the refusal is gone (green), so the repair no longer matches (idempotent).`);
|
|
3838
|
+
return 0;
|
|
3839
|
+
}
|
|
3166
3840
|
function readSealedIntentBytes(eng, ws, intentOut) {
|
|
3167
3841
|
if (typeof intentOut !== "string") return void 0;
|
|
3168
3842
|
const tree = eng.preopen.dir.contents?.get("ws");
|
|
@@ -3170,13 +3844,14 @@ function readSealedIntentBytes(eng, ws, intentOut) {
|
|
|
3170
3844
|
if (f?.data === void 0) return void 0;
|
|
3171
3845
|
return Buffer.from(f.data).toString("base64");
|
|
3172
3846
|
}
|
|
3173
|
-
var out2, err2;
|
|
3847
|
+
var out2, err2, CLIENT_IMPACT;
|
|
3174
3848
|
var init_governance = __esm({
|
|
3175
3849
|
"src/governance.ts"() {
|
|
3176
3850
|
"use strict";
|
|
3177
3851
|
init_cloud();
|
|
3178
3852
|
out2 = (s) => void process.stdout.write(s + "\n");
|
|
3179
3853
|
err2 = (s) => void process.stderr.write("error: " + s + "\n");
|
|
3854
|
+
CLIENT_IMPACT = "every connected client raises CustodyBreak(superseded); unsynced client work is invisible to the cloud \u2014 drain/sync clients first";
|
|
3180
3855
|
}
|
|
3181
3856
|
});
|
|
3182
3857
|
|
|
@@ -3522,9 +4197,9 @@ __export(cloud_exports, {
|
|
|
3522
4197
|
wsRetire: () => wsRetire,
|
|
3523
4198
|
wsStatus: () => wsStatus
|
|
3524
4199
|
});
|
|
3525
|
-
import { chmodSync, existsSync as existsSync3, mkdirSync as
|
|
4200
|
+
import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
3526
4201
|
import { createHash as createHash3 } from "node:crypto";
|
|
3527
|
-
import { join as
|
|
4202
|
+
import { join as join4 } from "node:path";
|
|
3528
4203
|
import { homedir } from "node:os";
|
|
3529
4204
|
function cloudBase(flag) {
|
|
3530
4205
|
return (flag ?? process.env["NOMOS_CLOUD"] ?? DEFAULT_CLOUD).replace(/\/+$/, "");
|
|
@@ -3536,17 +4211,17 @@ function authAnonKey() {
|
|
|
3536
4211
|
return process.env["HOLON_AUTH_ANON_KEY"] ?? DEFAULT_AUTH_ANON_KEY;
|
|
3537
4212
|
}
|
|
3538
4213
|
function configDir() {
|
|
3539
|
-
return process.env["HOLON_CONFIG_DIR"] ??
|
|
4214
|
+
return process.env["HOLON_CONFIG_DIR"] ?? join4(homedir(), ".holon");
|
|
3540
4215
|
}
|
|
3541
4216
|
function credsPath() {
|
|
3542
|
-
return
|
|
4217
|
+
return join4(configDir(), "credentials.json");
|
|
3543
4218
|
}
|
|
3544
4219
|
function loadCreds() {
|
|
3545
4220
|
if (!existsSync3(credsPath())) return { version: 1, secrets: {} };
|
|
3546
4221
|
return JSON.parse(readFileSync4(credsPath(), "utf8"));
|
|
3547
4222
|
}
|
|
3548
4223
|
function saveCreds(c) {
|
|
3549
|
-
|
|
4224
|
+
mkdirSync4(configDir(), { recursive: true });
|
|
3550
4225
|
writeFileSync4(credsPath(), JSON.stringify(c, null, 2) + "\n", "utf8");
|
|
3551
4226
|
chmodSync(credsPath(), 384);
|
|
3552
4227
|
}
|
|
@@ -3665,7 +4340,7 @@ function discoverDeployJson(cwd, explicit) {
|
|
|
3665
4340
|
if (!existsSync3(explicit)) throw new Error(`deploy body not found: ${explicit}`);
|
|
3666
4341
|
return explicit;
|
|
3667
4342
|
}
|
|
3668
|
-
const buildDir =
|
|
4343
|
+
const buildDir = join4(cwd, "build");
|
|
3669
4344
|
if (!existsSync3(buildDir)) {
|
|
3670
4345
|
throw new Error("no build/ directory \u2014 run `githolon compile` first (or pass --file <path>)");
|
|
3671
4346
|
}
|
|
@@ -3676,7 +4351,7 @@ function discoverDeployJson(cwd, explicit) {
|
|
|
3676
4351
|
if (bodies.length > 1) {
|
|
3677
4352
|
throw new Error(`multiple deploy bodies in build/ (${bodies.join(", ")}) \u2014 pass --file <path>`);
|
|
3678
4353
|
}
|
|
3679
|
-
return
|
|
4354
|
+
return join4(buildDir, bodies[0]);
|
|
3680
4355
|
}
|
|
3681
4356
|
async function login(opts) {
|
|
3682
4357
|
if (opts.agent !== true && opts.token === void 0) {
|
|
@@ -4036,10 +4711,10 @@ __export(editor_exports, {
|
|
|
4036
4711
|
initEditor: () => initEditor,
|
|
4037
4712
|
writeEditorRecommendation: () => writeEditorRecommendation
|
|
4038
4713
|
});
|
|
4039
|
-
import { existsSync as existsSync4, mkdirSync as
|
|
4040
|
-
import { dirname as
|
|
4714
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
4715
|
+
import { dirname as dirname3, join as join5 } from "node:path";
|
|
4041
4716
|
function hasEditorRecommendation(cwd) {
|
|
4042
|
-
const p =
|
|
4717
|
+
const p = join5(cwd, ".vscode", "extensions.json");
|
|
4043
4718
|
if (!existsSync4(p)) return false;
|
|
4044
4719
|
try {
|
|
4045
4720
|
const json = JSON.parse(readFileSync5(p, "utf8"));
|
|
@@ -4049,8 +4724,8 @@ function hasEditorRecommendation(cwd) {
|
|
|
4049
4724
|
}
|
|
4050
4725
|
}
|
|
4051
4726
|
function writeEditorRecommendation(cwd) {
|
|
4052
|
-
const dir =
|
|
4053
|
-
const path =
|
|
4727
|
+
const dir = join5(cwd, ".vscode");
|
|
4728
|
+
const path = join5(dir, "extensions.json");
|
|
4054
4729
|
let json = {};
|
|
4055
4730
|
let existed = false;
|
|
4056
4731
|
if (existsSync4(path)) {
|
|
@@ -4074,7 +4749,7 @@ function writeEditorRecommendation(cwd) {
|
|
|
4074
4749
|
}
|
|
4075
4750
|
recs.push(NOMOS_LAW_EXTENSION_ID);
|
|
4076
4751
|
json.recommendations = recs;
|
|
4077
|
-
|
|
4752
|
+
mkdirSync5(dirname3(path), { recursive: true });
|
|
4078
4753
|
writeFileSync5(path, JSON.stringify(json, null, 2) + "\n", "utf8");
|
|
4079
4754
|
return { path, action: existed ? "updated" : "created" };
|
|
4080
4755
|
}
|
|
@@ -4111,19 +4786,19 @@ var init_editor = __esm({
|
|
|
4111
4786
|
// src/compile.ts
|
|
4112
4787
|
import { spawn, spawnSync } from "node:child_process";
|
|
4113
4788
|
import { createRequire } from "node:module";
|
|
4114
|
-
import { dirname as
|
|
4789
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
4115
4790
|
import { pathToFileURL } from "node:url";
|
|
4116
4791
|
function resolveCompileLauncher(cwd) {
|
|
4117
4792
|
const resolveDslPkg = (fromDir) => {
|
|
4118
4793
|
try {
|
|
4119
|
-
const req = fromDir === void 0 ? createRequire(import.meta.url) : createRequire(pathToFileURL(
|
|
4794
|
+
const req = fromDir === void 0 ? createRequire(import.meta.url) : createRequire(pathToFileURL(join6(fromDir, "noop.js")));
|
|
4120
4795
|
return req.resolve("@githolon/dsl/package.json");
|
|
4121
4796
|
} catch {
|
|
4122
4797
|
return void 0;
|
|
4123
4798
|
}
|
|
4124
4799
|
};
|
|
4125
4800
|
const dslPkg = resolveDslPkg(cwd) ?? resolveDslPkg(void 0);
|
|
4126
|
-
return dslPkg === void 0 ? void 0 :
|
|
4801
|
+
return dslPkg === void 0 ? void 0 : join6(dirname4(dslPkg), "compile_package.mjs");
|
|
4127
4802
|
}
|
|
4128
4803
|
function runCompile(args) {
|
|
4129
4804
|
const launcher = resolveCompileLauncher(process.cwd());
|
|
@@ -4146,7 +4821,7 @@ ${INIT_EDITOR_HINT}
|
|
|
4146
4821
|
}
|
|
4147
4822
|
function resolveCheckLauncher(cwd) {
|
|
4148
4823
|
const launcher = resolveCompileLauncher(cwd);
|
|
4149
|
-
return launcher === void 0 ? void 0 :
|
|
4824
|
+
return launcher === void 0 ? void 0 : join6(dirname4(launcher), "check_package.mjs");
|
|
4150
4825
|
}
|
|
4151
4826
|
function runCheck(args) {
|
|
4152
4827
|
const launcher = resolveCheckLauncher(process.cwd());
|
|
@@ -4160,7 +4835,7 @@ function runCheck(args) {
|
|
|
4160
4835
|
}
|
|
4161
4836
|
function resolveCompatLauncher(cwd) {
|
|
4162
4837
|
const launcher = resolveCompileLauncher(cwd);
|
|
4163
|
-
return launcher === void 0 ? void 0 :
|
|
4838
|
+
return launcher === void 0 ? void 0 : join6(dirname4(launcher), "compat_package.mjs");
|
|
4164
4839
|
}
|
|
4165
4840
|
function runCompat(args) {
|
|
4166
4841
|
const launcher = resolveCompatLauncher(process.cwd());
|
|
@@ -4174,7 +4849,7 @@ function runCompat(args) {
|
|
|
4174
4849
|
}
|
|
4175
4850
|
function resolveLspLauncher(cwd) {
|
|
4176
4851
|
const launcher = resolveCompileLauncher(cwd);
|
|
4177
|
-
return launcher === void 0 ? void 0 :
|
|
4852
|
+
return launcher === void 0 ? void 0 : join6(dirname4(launcher), "lsp_server.mjs");
|
|
4178
4853
|
}
|
|
4179
4854
|
function runLsp(args) {
|
|
4180
4855
|
const launcher = resolveLspLauncher(process.cwd());
|
|
@@ -4224,7 +4899,7 @@ __export(proof_offline_exports, {
|
|
|
4224
4899
|
runRelationBootstrapLeg: () => runRelationBootstrapLeg
|
|
4225
4900
|
});
|
|
4226
4901
|
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "node:fs";
|
|
4227
|
-
import { basename, dirname as
|
|
4902
|
+
import { basename, dirname as dirname5, join as join8 } from "node:path";
|
|
4228
4903
|
function parseOfflineLegs(proofSource) {
|
|
4229
4904
|
if (!proofSource.includes("AUTO-GENERATED by nomos-compile")) {
|
|
4230
4905
|
throw new Error("not a generated proof (missing the AUTO-GENERATED header) \u2014 run `githolon compile` to (re)generate build/<name>.proof.mts");
|
|
@@ -4651,12 +5326,12 @@ function actorFromPayload(payload, field) {
|
|
|
4651
5326
|
async function runOfflineProofStandalone(proofPath, cloud, domain) {
|
|
4652
5327
|
const src = readFileSync6(proofPath, "utf8");
|
|
4653
5328
|
const packageName = basename(proofPath).replace(/\.proof\.mts$/, "");
|
|
4654
|
-
const deployFile =
|
|
5329
|
+
const deployFile = join8(dirname5(proofPath), `${packageName}.deploy.json`);
|
|
4655
5330
|
if (!existsSync6(deployFile)) {
|
|
4656
5331
|
throw new Error(`missing ${deployFile} \u2014 run \`githolon compile\` (the proof and the deploy body are built together)`);
|
|
4657
5332
|
}
|
|
4658
5333
|
let legs;
|
|
4659
|
-
const legsFile =
|
|
5334
|
+
const legsFile = join8(dirname5(proofPath), `${packageName}.proof-legs.json`);
|
|
4660
5335
|
if (existsSync6(legsFile)) {
|
|
4661
5336
|
const index = JSON.parse(readFileSync6(legsFile, "utf8"));
|
|
4662
5337
|
const keys = Object.keys(index.domains);
|
|
@@ -4703,6 +5378,147 @@ var init_proof_offline = __esm({
|
|
|
4703
5378
|
}
|
|
4704
5379
|
});
|
|
4705
5380
|
|
|
5381
|
+
// src/repairs.ts
|
|
5382
|
+
var repairs_exports = {};
|
|
5383
|
+
__export(repairs_exports, {
|
|
5384
|
+
discoverRepairs: () => discoverRepairs,
|
|
5385
|
+
knownRepairBlock: () => knownRepairBlock,
|
|
5386
|
+
matchRepair: () => matchRepair,
|
|
5387
|
+
parseRefusal: () => parseRefusal
|
|
5388
|
+
});
|
|
5389
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
5390
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
5391
|
+
import { existsSync as existsSync9, mkdtempSync, readdirSync as readdirSync4, readFileSync as readFileSync10, rmSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
5392
|
+
import { tmpdir } from "node:os";
|
|
5393
|
+
import { dirname as dirname7, isAbsolute, join as join11, resolve as resolve2 } from "node:path";
|
|
5394
|
+
import { pathToFileURL as pathToFileURL4 } from "node:url";
|
|
5395
|
+
function parseRefusal(verdict) {
|
|
5396
|
+
const check2 = String(verdict["check"] ?? "");
|
|
5397
|
+
const error = String(verdict["error"] ?? "");
|
|
5398
|
+
const raw = `${check2}: ${error}`;
|
|
5399
|
+
const kind = /evolve.?gate/i.test(raw) || /evolve/i.test(check2) ? "evolve-gate" : "other";
|
|
5400
|
+
const sids = /* @__PURE__ */ new Set();
|
|
5401
|
+
const structured = verdict["stableId"] ?? verdict["stableIds"];
|
|
5402
|
+
if (typeof structured === "string" && SID_SHAPE.test(structured)) sids.add(structured.toLowerCase());
|
|
5403
|
+
if (Array.isArray(structured)) {
|
|
5404
|
+
for (const s of structured) if (typeof s === "string" && SID_SHAPE.test(s)) sids.add(s.toLowerCase());
|
|
5405
|
+
}
|
|
5406
|
+
for (const m of raw.matchAll(SID_RE)) sids.add(m[1].toLowerCase());
|
|
5407
|
+
return { kind, stableIds: [...sids], raw };
|
|
5408
|
+
}
|
|
5409
|
+
function matchRepair(refusal, repairs) {
|
|
5410
|
+
if (refusal.kind === "other") return void 0;
|
|
5411
|
+
return repairs.find(
|
|
5412
|
+
(r) => r.matcher.refusal === refusal.kind && refusal.stableIds.includes(r.matcher.stableId.toLowerCase())
|
|
5413
|
+
);
|
|
5414
|
+
}
|
|
5415
|
+
function knownRepairBlock(repair) {
|
|
5416
|
+
return [
|
|
5417
|
+
"",
|
|
5418
|
+
`\u2726 KNOWN REPAIR: '${repair.id}' (${repair.file}) declares a remedy for exactly this refusal.`,
|
|
5419
|
+
` reason: ${repair.reason}`,
|
|
5420
|
+
" Re-run with --repair to execute it."
|
|
5421
|
+
].join("\n");
|
|
5422
|
+
}
|
|
5423
|
+
function resolveTsxCli(cwd) {
|
|
5424
|
+
const pkgDir = (name, fromDir) => {
|
|
5425
|
+
try {
|
|
5426
|
+
return dirname7(createRequire2(pathToFileURL4(join11(fromDir, "noop.js")).href).resolve(`${name}/package.json`));
|
|
5427
|
+
} catch {
|
|
5428
|
+
return void 0;
|
|
5429
|
+
}
|
|
5430
|
+
};
|
|
5431
|
+
const dslDir = pkgDir("@githolon/dsl", cwd) ?? (() => {
|
|
5432
|
+
try {
|
|
5433
|
+
return dirname7(createRequire2(import.meta.url).resolve("@githolon/dsl/package.json"));
|
|
5434
|
+
} catch {
|
|
5435
|
+
return void 0;
|
|
5436
|
+
}
|
|
5437
|
+
})();
|
|
5438
|
+
const tsxDir = pkgDir("tsx", cwd) ?? (dslDir !== void 0 ? pkgDir("tsx", dslDir) : void 0);
|
|
5439
|
+
if (tsxDir === void 0) return void 0;
|
|
5440
|
+
try {
|
|
5441
|
+
const pkg = JSON.parse(
|
|
5442
|
+
readFileSync10(join11(tsxDir, "package.json"), "utf8")
|
|
5443
|
+
);
|
|
5444
|
+
const rel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.["tsx"];
|
|
5445
|
+
return join11(tsxDir, rel ?? "dist/cli.mjs");
|
|
5446
|
+
} catch {
|
|
5447
|
+
return void 0;
|
|
5448
|
+
}
|
|
5449
|
+
}
|
|
5450
|
+
function resolveDslEntry(cwd) {
|
|
5451
|
+
const tryFrom = (fromUrl) => {
|
|
5452
|
+
try {
|
|
5453
|
+
return createRequire2(fromUrl).resolve("@githolon/dsl");
|
|
5454
|
+
} catch {
|
|
5455
|
+
return void 0;
|
|
5456
|
+
}
|
|
5457
|
+
};
|
|
5458
|
+
return tryFrom(pathToFileURL4(join11(cwd, "noop.js")).href) ?? tryFrom(import.meta.url);
|
|
5459
|
+
}
|
|
5460
|
+
function discoverRepairs(cwd) {
|
|
5461
|
+
const dir = join11(cwd, "repairs");
|
|
5462
|
+
if (!existsSync9(dir)) return { repairs: [] };
|
|
5463
|
+
let files;
|
|
5464
|
+
try {
|
|
5465
|
+
files = readdirSync4(dir).filter((f) => /\.(ts|mts|cts)$/.test(f) && !/\.d\.ts$/.test(f)).sort().map((f) => resolve2(dir, f));
|
|
5466
|
+
} catch (e) {
|
|
5467
|
+
return { error: `could not read the repairs/ folder: ${e.message}` };
|
|
5468
|
+
}
|
|
5469
|
+
if (files.length === 0) return { repairs: [] };
|
|
5470
|
+
const tsxCli = resolveTsxCli(cwd);
|
|
5471
|
+
const dslEntry = resolveDslEntry(cwd);
|
|
5472
|
+
if (tsxCli === void 0 || dslEntry === void 0) {
|
|
5473
|
+
return { error: "repairs/ is present but the toolchain to load it is missing \u2014 add @githolon/dsl (tsx + the DSL ride it) to the project and npm install" };
|
|
5474
|
+
}
|
|
5475
|
+
const scratch = mkdtempSync(join11(tmpdir(), "githolon-repairs-"));
|
|
5476
|
+
const loader = join11(scratch, "discover.mts");
|
|
5477
|
+
const loaderSrc = `
|
|
5478
|
+
import { repairsOf } from ${JSON.stringify(dslEntry)};
|
|
5479
|
+
const files = ${JSON.stringify(files)};
|
|
5480
|
+
const out = [];
|
|
5481
|
+
const seen = new Map();
|
|
5482
|
+
for (const file of files) {
|
|
5483
|
+
const mod = await import(${JSON.stringify("file://")} + file);
|
|
5484
|
+
for (const r of repairsOf(mod)) {
|
|
5485
|
+
if (seen.has(r.id)) {
|
|
5486
|
+
throw new Error("duplicate repair id '" + r.id + "' \u2014 declared in " + seen.get(r.id) + " and " + file);
|
|
5487
|
+
}
|
|
5488
|
+
seen.set(r.id, file);
|
|
5489
|
+
out.push({ id: r.id, matcher: r.matcher, reason: r.reason, verb: r.verb, file });
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5492
|
+
process.stdout.write("\\u0001REPAIRS\\u0001" + JSON.stringify(out) + "\\u0001END\\u0001\\n");
|
|
5493
|
+
`;
|
|
5494
|
+
try {
|
|
5495
|
+
writeFileSync7(loader, loaderSrc, "utf8");
|
|
5496
|
+
const r = spawnSync4(process.execPath, [tsxCli, loader], { cwd, encoding: "utf8" });
|
|
5497
|
+
if (r.status !== 0) {
|
|
5498
|
+
const msg = (r.stderr || r.stdout || "").trim().split("\n").filter(Boolean).slice(-4).join("\n");
|
|
5499
|
+
return { error: `loading repairs/ failed:
|
|
5500
|
+
${msg || `tsx exited ${r.status ?? "?"}`}` };
|
|
5501
|
+
}
|
|
5502
|
+
const m = /REPAIRS([\s\S]*?)END/.exec(r.stdout);
|
|
5503
|
+
if (m === null) return { error: "the repairs loader produced no manifest (unexpected \u2014 the DSL/tsx may be too old)" };
|
|
5504
|
+
const parsed = JSON.parse(m[1]);
|
|
5505
|
+
const repairs = parsed.map((p) => ({ ...p, file: isAbsolute(p.file) ? p.file : resolve2(cwd, p.file) }));
|
|
5506
|
+
return { repairs };
|
|
5507
|
+
} catch (e) {
|
|
5508
|
+
return { error: `loading repairs/ failed: ${e.message}` };
|
|
5509
|
+
} finally {
|
|
5510
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
5511
|
+
}
|
|
5512
|
+
}
|
|
5513
|
+
var SID_RE, SID_SHAPE;
|
|
5514
|
+
var init_repairs = __esm({
|
|
5515
|
+
"src/repairs.ts"() {
|
|
5516
|
+
"use strict";
|
|
5517
|
+
SID_RE = /stable id ([0-9a-f]{16})/gi;
|
|
5518
|
+
SID_SHAPE = /^[0-9a-f]{16}$/i;
|
|
5519
|
+
}
|
|
5520
|
+
});
|
|
5521
|
+
|
|
4706
5522
|
// src/mcp.ts
|
|
4707
5523
|
var mcp_exports = {};
|
|
4708
5524
|
__export(mcp_exports, {
|
|
@@ -4714,21 +5530,21 @@ __export(mcp_exports, {
|
|
|
4714
5530
|
toolCheck: () => toolCheck,
|
|
4715
5531
|
toolEvolvePreview: () => toolEvolvePreview
|
|
4716
5532
|
});
|
|
4717
|
-
import { spawnSync as
|
|
4718
|
-
import { existsSync as
|
|
4719
|
-
import { dirname as
|
|
5533
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
5534
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
5535
|
+
import { dirname as dirname8, isAbsolute as isAbsolute2, resolve as resolve3 } from "node:path";
|
|
4720
5536
|
function resolveConfig(config) {
|
|
4721
5537
|
const arg = config ?? "nomos.package.mjs";
|
|
4722
|
-
const configPath =
|
|
4723
|
-
return { configPath, cfgDir:
|
|
5538
|
+
const configPath = isAbsolute2(arg) ? arg : resolve3(process.cwd(), arg);
|
|
5539
|
+
return { configPath, cfgDir: dirname8(configPath) };
|
|
4724
5540
|
}
|
|
4725
5541
|
function runCheckLauncher(configPath, extraArgs) {
|
|
4726
|
-
const cfgDir =
|
|
5542
|
+
const cfgDir = dirname8(configPath);
|
|
4727
5543
|
const launcher = resolveCheckLauncher(cfgDir) ?? resolveCheckLauncher(process.cwd());
|
|
4728
5544
|
if (launcher === void 0) {
|
|
4729
5545
|
return { findings: [], stdout: "", stderr: "", status: 1, error: NO_DSL_REMEDY };
|
|
4730
5546
|
}
|
|
4731
|
-
const r =
|
|
5547
|
+
const r = spawnSync5(process.execPath, [launcher, configPath, ...extraArgs], {
|
|
4732
5548
|
cwd: cfgDir,
|
|
4733
5549
|
encoding: "utf8"
|
|
4734
5550
|
});
|
|
@@ -4794,7 +5610,7 @@ function extractDispositions(humanReport) {
|
|
|
4794
5610
|
}
|
|
4795
5611
|
function toolCheck(args) {
|
|
4796
5612
|
const { configPath } = resolveConfig(args.config);
|
|
4797
|
-
if (!
|
|
5613
|
+
if (!existsSync11(configPath)) {
|
|
4798
5614
|
return { text: `nomos_check: config not found: ${configPath}`, isError: true };
|
|
4799
5615
|
}
|
|
4800
5616
|
const extra = args.against !== void 0 ? ["--against", args.against] : [];
|
|
@@ -4811,11 +5627,11 @@ ${JSON.stringify(payload, null, 2)}`, isError: false };
|
|
|
4811
5627
|
}
|
|
4812
5628
|
function toolEvolvePreview(args) {
|
|
4813
5629
|
const { configPath } = resolveConfig(args.config);
|
|
4814
|
-
if (!
|
|
5630
|
+
if (!existsSync11(configPath)) {
|
|
4815
5631
|
return { text: `nomos_evolve_preview: config not found: ${configPath}`, isError: true };
|
|
4816
5632
|
}
|
|
4817
|
-
const againstPath =
|
|
4818
|
-
const priorArg =
|
|
5633
|
+
const againstPath = isAbsolute2(args.against) ? args.against : resolve3(dirname8(configPath), args.against);
|
|
5634
|
+
const priorArg = existsSync11(againstPath) ? againstPath : args.against;
|
|
4819
5635
|
const jsonRun = runCheckJson(configPath, ["--against", priorArg]);
|
|
4820
5636
|
if (jsonRun.error !== void 0) {
|
|
4821
5637
|
return {
|
|
@@ -4978,8 +5794,8 @@ __export(harness_exports, {
|
|
|
4978
5794
|
harnessInstall: () => harnessInstall,
|
|
4979
5795
|
looksLikeStaleRuntime: () => looksLikeStaleRuntime
|
|
4980
5796
|
});
|
|
4981
|
-
import { existsSync as
|
|
4982
|
-
import { join as
|
|
5797
|
+
import { existsSync as existsSync12, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "node:fs";
|
|
5798
|
+
import { join as join14 } from "node:path";
|
|
4983
5799
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
4984
5800
|
function looksLikeStaleRuntime(msg) {
|
|
4985
5801
|
return /\bbbox param\b|missing.*param|non-numeric|unknown (op|query op)|unsupported op|unexpected (field|key)|no such op/i.test(
|
|
@@ -4989,19 +5805,19 @@ function looksLikeStaleRuntime(msg) {
|
|
|
4989
5805
|
async function harnessInstall(opts) {
|
|
4990
5806
|
const { deploy: deployPaths, workspace, out: outPath } = opts;
|
|
4991
5807
|
if (deployPaths.length === 0) die("no --deploy JSON path(s) given");
|
|
4992
|
-
const runtimeDir = opts.runtime || process.env["NOMOS_OFFLINE_RUNTIME"] ||
|
|
5808
|
+
const runtimeDir = opts.runtime || process.env["NOMOS_OFFLINE_RUNTIME"] || join14(configDir(), "runtime");
|
|
4993
5809
|
const refreshed = await refreshRuntimeDir(cloudBase(), runtimeDir);
|
|
4994
5810
|
if (refreshed) process.stderr.write(`harness-install: refreshed runtime cache from the cloud \u2192 ${runtimeDir}
|
|
4995
5811
|
`);
|
|
4996
|
-
const wasmFile =
|
|
4997
|
-
const pkgsFile =
|
|
4998
|
-
if (!
|
|
5812
|
+
const wasmFile = join14(runtimeDir, "holon.wasm");
|
|
5813
|
+
const pkgsFile = join14(runtimeDir, "packages.json");
|
|
5814
|
+
if (!existsSync12(wasmFile) || !existsSync12(pkgsFile)) {
|
|
4999
5815
|
die(
|
|
5000
5816
|
`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.`
|
|
5001
5817
|
);
|
|
5002
5818
|
}
|
|
5003
|
-
const wasm =
|
|
5004
|
-
const pkgs = JSON.parse(
|
|
5819
|
+
const wasm = readFileSync13(wasmFile);
|
|
5820
|
+
const pkgs = JSON.parse(readFileSync13(pkgsFile, "utf8"));
|
|
5005
5821
|
const guarded = async (fn) => {
|
|
5006
5822
|
try {
|
|
5007
5823
|
return await fn();
|
|
@@ -5023,8 +5839,8 @@ async function harnessInstall(opts) {
|
|
|
5023
5839
|
await guarded(() => author(eng, workspace, "bootstrap", "installDomain", installPayload(eng.hashes.nomos, eng.nomosPkg, "nomos-test-harness"), ""));
|
|
5024
5840
|
const lawHashes = [];
|
|
5025
5841
|
for (const p of deployPaths) {
|
|
5026
|
-
if (!
|
|
5027
|
-
const deploy3 = JSON.parse(
|
|
5842
|
+
if (!existsSync12(p)) die(`deploy JSON not found: ${p} \u2014 run \`npx githolon compile\` first`);
|
|
5843
|
+
const deploy3 = JSON.parse(readFileSync13(p, "utf8"));
|
|
5028
5844
|
const usda = deploy3.packageUsda;
|
|
5029
5845
|
if (typeof usda !== "string" || !usda.startsWith("#usda")) die(`${p} has no #usda packageUsda`);
|
|
5030
5846
|
const lawHash = await sha256hex(usda);
|
|
@@ -5036,7 +5852,7 @@ async function harnessInstall(opts) {
|
|
|
5036
5852
|
const wsNode = eng.preopen.dir.contents.get("ws").contents.get(workspace);
|
|
5037
5853
|
if (!wsNode) die(`internal: workspace tree '${workspace}' not found after install`);
|
|
5038
5854
|
const treeBytes = serializeTree(wsNode);
|
|
5039
|
-
|
|
5855
|
+
writeFileSync8(outPath, treeBytes);
|
|
5040
5856
|
process.stderr.write(`harness-install: snapshot written (${treeBytes.length} bytes) \u2192 ${outPath}
|
|
5041
5857
|
`);
|
|
5042
5858
|
process.stdout.write(JSON.stringify({ ok: true, snapshot: outPath, workspace, lawHashes }) + "\n");
|
|
@@ -6115,8 +6931,8 @@ var scene_exports = {};
|
|
|
6115
6931
|
__export(scene_exports, {
|
|
6116
6932
|
scene: () => scene
|
|
6117
6933
|
});
|
|
6118
|
-
import { existsSync as
|
|
6119
|
-
import { join as
|
|
6934
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, writeFileSync as writeFileSync9 } from "node:fs";
|
|
6935
|
+
import { join as join15, resolve as resolve4 } from "node:path";
|
|
6120
6936
|
import { createHash as createHash5 } from "node:crypto";
|
|
6121
6937
|
import git3 from "isomorphic-git";
|
|
6122
6938
|
async function walkChain2(eng, ws) {
|
|
@@ -6137,8 +6953,8 @@ async function projectOnce(cloud, target, isDir, name) {
|
|
|
6137
6953
|
const { eng } = await holonEngine(cloud, void 0, "githolon-scene");
|
|
6138
6954
|
const SOURCE3 = "source";
|
|
6139
6955
|
if (isDir) {
|
|
6140
|
-
const gitDir =
|
|
6141
|
-
if (!
|
|
6956
|
+
const gitDir = existsSync13(join15(target, ".git")) ? join15(target, ".git") : target;
|
|
6957
|
+
if (!existsSync13(join15(gitDir, "HEAD"))) throw new Error(`${target} is not a git repo (no HEAD)`);
|
|
6142
6958
|
await mountFresh(eng, SOURCE3);
|
|
6143
6959
|
eng.preopen.dir.contents.get("ws").contents.get(SOURCE3).contents.set("nomos.git", readTreeFromDisk(gitDir));
|
|
6144
6960
|
} else {
|
|
@@ -6197,9 +7013,9 @@ async function projectOnce(cloud, target, isDir, name) {
|
|
|
6197
7013
|
}
|
|
6198
7014
|
async function scene(target, opts) {
|
|
6199
7015
|
const cloud = cloudBase(opts.cloud);
|
|
6200
|
-
const isDir =
|
|
6201
|
-
const name = isDir ? (
|
|
6202
|
-
out11(`scene \u2014 ${name} (${isDir ?
|
|
7016
|
+
const isDir = existsSync13(target) || target.includes("/") || target.startsWith(".");
|
|
7017
|
+
const name = isDir ? (resolve4(target).split("/").filter(Boolean).pop() ?? "scene").replace(/\.git$/, "") : target;
|
|
7018
|
+
out11(`scene \u2014 ${name} (${isDir ? resolve4(target) : `${cloud} :: ${target}`})`);
|
|
6203
7019
|
let first, second;
|
|
6204
7020
|
try {
|
|
6205
7021
|
first = await projectOnce(cloud, target, isDir, name);
|
|
@@ -6217,13 +7033,13 @@ async function scene(target, opts) {
|
|
|
6217
7033
|
err11(`the emitted stage violates the portable profile: ${violations.join("; ")}`);
|
|
6218
7034
|
return 1;
|
|
6219
7035
|
}
|
|
6220
|
-
const outDir =
|
|
6221
|
-
|
|
6222
|
-
const usdaPath =
|
|
6223
|
-
const usdzPath =
|
|
7036
|
+
const outDir = resolve4(opts.out ?? join15("scene", name));
|
|
7037
|
+
mkdirSync6(outDir, { recursive: true });
|
|
7038
|
+
const usdaPath = join15(outDir, `${name}.usda`);
|
|
7039
|
+
const usdzPath = join15(outDir, `${name}.usdz`);
|
|
6224
7040
|
const usdaBytes = new TextEncoder().encode(first.usda);
|
|
6225
|
-
|
|
6226
|
-
|
|
7041
|
+
writeFileSync9(usdaPath, usdaBytes);
|
|
7042
|
+
writeFileSync9(usdzPath, usdzPack([[`${name}.usda`, usdaBytes]]));
|
|
6227
7043
|
const s = first.stats;
|
|
6228
7044
|
out11(` verify_chain ${s.verdictLine}`);
|
|
6229
7045
|
out11(` law canopy ${s.nodes} node(s), ${s.edges} edge(s) \u2014 from the chain's own installed packages`);
|
|
@@ -6249,11 +7065,11 @@ var init_scene = __esm({
|
|
|
6249
7065
|
});
|
|
6250
7066
|
|
|
6251
7067
|
// src/cli.ts
|
|
6252
|
-
import { existsSync as
|
|
6253
|
-
import { spawnSync as
|
|
6254
|
-
import { createRequire as
|
|
6255
|
-
import { dirname as
|
|
6256
|
-
import { pathToFileURL as
|
|
7068
|
+
import { existsSync as existsSync14, readdirSync as readdirSync5, readFileSync as readFileSync14 } from "node:fs";
|
|
7069
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
7070
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
7071
|
+
import { dirname as dirname9, join as join16, resolve as resolve5 } from "node:path";
|
|
7072
|
+
import { pathToFileURL as pathToFileURL5 } from "node:url";
|
|
6257
7073
|
|
|
6258
7074
|
// src/generate.ts
|
|
6259
7075
|
import { mkdirSync, existsSync, writeFileSync } from "node:fs";
|
|
@@ -6444,16 +7260,16 @@ init_compile();
|
|
|
6444
7260
|
init_local_holon();
|
|
6445
7261
|
import { existsSync as existsSync7, readFileSync as readFileSync7, watch } from "node:fs";
|
|
6446
7262
|
import { createServer } from "node:http";
|
|
6447
|
-
import { dirname as
|
|
7263
|
+
import { dirname as dirname6, join as join9, resolve } from "node:path";
|
|
6448
7264
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
6449
7265
|
|
|
6450
7266
|
// src/project.ts
|
|
6451
7267
|
import { existsSync as existsSync5, statSync as statSync2 } from "node:fs";
|
|
6452
|
-
import { join as
|
|
7268
|
+
import { join as join7 } from "node:path";
|
|
6453
7269
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
6454
7270
|
var CONFIG_FILE = "nomos.package.mjs";
|
|
6455
7271
|
async function loadProject(cwd, opts = {}) {
|
|
6456
|
-
const configPath =
|
|
7272
|
+
const configPath = join7(cwd, CONFIG_FILE);
|
|
6457
7273
|
if (!existsSync5(configPath)) return void 0;
|
|
6458
7274
|
const href = pathToFileURL2(configPath).href + (opts.bust === true ? `?v=${statSync2(configPath).mtimeMs}-${Date.now()}` : "");
|
|
6459
7275
|
const mod = await import(href);
|
|
@@ -6619,7 +7435,7 @@ function startServer(s) {
|
|
|
6619
7435
|
});
|
|
6620
7436
|
}
|
|
6621
7437
|
function readDeployBody2(cwd, packageName) {
|
|
6622
|
-
const file =
|
|
7438
|
+
const file = join9(cwd, "build", `${packageName}.deploy.json`);
|
|
6623
7439
|
if (!existsSync7(file)) {
|
|
6624
7440
|
throw new Error(`compile produced no ${file} \u2014 check the compile output above`);
|
|
6625
7441
|
}
|
|
@@ -6639,7 +7455,7 @@ async function installLaw(s, deployBody, installedBy) {
|
|
|
6639
7455
|
return { ok: true };
|
|
6640
7456
|
}
|
|
6641
7457
|
async function runProofCycle(s, cwd, deployBody, installedBy) {
|
|
6642
|
-
const proofPath =
|
|
7458
|
+
const proofPath = join9(cwd, "build", `${s.packageName}.proof.mts`);
|
|
6643
7459
|
if (!existsSync7(proofPath)) return void 0;
|
|
6644
7460
|
const scratch = `proof-${s.cycle}`;
|
|
6645
7461
|
try {
|
|
@@ -6662,7 +7478,7 @@ async function dev(opts) {
|
|
|
6662
7478
|
return void 0;
|
|
6663
7479
|
});
|
|
6664
7480
|
if (project === void 0) {
|
|
6665
|
-
if (!existsSync7(
|
|
7481
|
+
if (!existsSync7(join9(cwd, CONFIG_FILE))) {
|
|
6666
7482
|
err5(`no ${CONFIG_FILE} here (${cwd}) \u2014 \`githolon dev\` runs inside a project; scaffold one from examples/guestbook or \`githolon generate domain <name>\``);
|
|
6667
7483
|
}
|
|
6668
7484
|
return 1;
|
|
@@ -6729,12 +7545,12 @@ ${firstCompile.output}`);
|
|
|
6729
7545
|
try {
|
|
6730
7546
|
const cfgModule = await import(pathToFileURL3(project.configPath).href);
|
|
6731
7547
|
for (const d of cfgModule.default?.domains ?? []) {
|
|
6732
|
-
for (const m of d.modules ?? []) moduleDirs.add(
|
|
7548
|
+
for (const m of d.modules ?? []) moduleDirs.add(dirname6(resolve(cwd, m)));
|
|
6733
7549
|
}
|
|
6734
7550
|
} catch {
|
|
6735
|
-
moduleDirs.add(
|
|
7551
|
+
moduleDirs.add(join9(cwd, "domains"));
|
|
6736
7552
|
}
|
|
6737
|
-
if (moduleDirs.size === 0) moduleDirs.add(
|
|
7553
|
+
if (moduleDirs.size === 0) moduleDirs.add(join9(cwd, "domains"));
|
|
6738
7554
|
let timer;
|
|
6739
7555
|
let cycling = false;
|
|
6740
7556
|
let queued = false;
|
|
@@ -7144,7 +7960,7 @@ init_cloud();
|
|
|
7144
7960
|
init_local_holon();
|
|
7145
7961
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
7146
7962
|
import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
7147
|
-
import { join as
|
|
7963
|
+
import { join as join10 } from "node:path";
|
|
7148
7964
|
var out7 = (s) => void process.stdout.write(s + "\n");
|
|
7149
7965
|
var err7 = (s) => void process.stderr.write("error: " + s + "\n");
|
|
7150
7966
|
var WS2 = "local";
|
|
@@ -7177,9 +7993,9 @@ async function ledgerInit(dir, opts) {
|
|
|
7177
7993
|
const verdict = verifyChainLocal(eng, WS2);
|
|
7178
7994
|
if (!printVerdict(verdict)) return 1;
|
|
7179
7995
|
const gitTree = eng.preopen.dir.contents.get("ws").contents.get(WS2).contents.get("nomos.git");
|
|
7180
|
-
const gitDir =
|
|
7996
|
+
const gitDir = join10(dir, ".git");
|
|
7181
7997
|
writeTreeToDisk(gitTree, gitDir);
|
|
7182
|
-
const cfgPath =
|
|
7998
|
+
const cfgPath = join10(gitDir, "config");
|
|
7183
7999
|
writeFileSync6(cfgPath, readFileSync9(cfgPath, "utf8").replace(/bare = true/, "bare = false"), "utf8");
|
|
7184
8000
|
spawnSync3("git", ["-C", dir, "reset", "--hard", "main"], { stdio: "ignore" });
|
|
7185
8001
|
out7(`\u2713 holon written \u2192 ${dir} (a normal git repo; git log IS the audit trail)`);
|
|
@@ -7189,8 +8005,8 @@ Birth it on Nomos Cloud (the cloud re-derives this exact verdict):`);
|
|
|
7189
8005
|
return 0;
|
|
7190
8006
|
}
|
|
7191
8007
|
async function ledgerVerify(dir, opts) {
|
|
7192
|
-
const gitDir = existsSync8(
|
|
7193
|
-
if (!existsSync8(
|
|
8008
|
+
const gitDir = existsSync8(join10(dir, ".git")) ? join10(dir, ".git") : dir;
|
|
8009
|
+
if (!existsSync8(join10(gitDir, "HEAD"))) {
|
|
7194
8010
|
err7(`${dir} is not a git repo (no HEAD)`);
|
|
7195
8011
|
return 1;
|
|
7196
8012
|
}
|
|
@@ -7206,8 +8022,8 @@ init_engine();
|
|
|
7206
8022
|
init_engine();
|
|
7207
8023
|
init_cloud();
|
|
7208
8024
|
init_local_holon();
|
|
7209
|
-
import { existsSync as
|
|
7210
|
-
import { join as
|
|
8025
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
8026
|
+
import { join as join12 } from "node:path";
|
|
7211
8027
|
import git2 from "isomorphic-git";
|
|
7212
8028
|
var out8 = (s) => void process.stdout.write(s + "\n");
|
|
7213
8029
|
var err8 = (s) => void process.stderr.write("error: " + s + "\n");
|
|
@@ -7303,10 +8119,10 @@ async function replay(target, opts) {
|
|
|
7303
8119
|
the runtime rides ${cloud}/v1/runtime/* (cached in ~/.holon/runtime after one fetch)`);
|
|
7304
8120
|
return 1;
|
|
7305
8121
|
}
|
|
7306
|
-
const isDir =
|
|
8122
|
+
const isDir = existsSync10(target) || target.includes("/") || target.startsWith(".");
|
|
7307
8123
|
if (isDir) {
|
|
7308
|
-
const gitDir =
|
|
7309
|
-
if (!
|
|
8124
|
+
const gitDir = existsSync10(join12(target, ".git")) ? join12(target, ".git") : target;
|
|
8125
|
+
if (!existsSync10(join12(gitDir, "HEAD"))) {
|
|
7310
8126
|
err8(`${target} is not a git repo (no HEAD) \u2014 pass a holon directory (githolon ledger init <dir>) or a workspace name`);
|
|
7311
8127
|
return 1;
|
|
7312
8128
|
}
|
|
@@ -7331,6 +8147,26 @@ async function replay(target, opts) {
|
|
|
7331
8147
|
if (verdict["valid"] !== true) {
|
|
7332
8148
|
if (json) emit({ finale: true, verdict });
|
|
7333
8149
|
else printVerdict(verdict);
|
|
8150
|
+
if (json && opts.repair !== true) return 1;
|
|
8151
|
+
const { discoverRepairs: discoverRepairs2, parseRefusal: parseRefusal2, matchRepair: matchRepair2, knownRepairBlock: knownRepairBlock2 } = await Promise.resolve().then(() => (init_repairs(), repairs_exports));
|
|
8152
|
+
const discovered = discoverRepairs2(process.cwd());
|
|
8153
|
+
if ("error" in discovered) {
|
|
8154
|
+
if (!json) err8(discovered.error);
|
|
8155
|
+
} else if (discovered.repairs.length > 0) {
|
|
8156
|
+
const refusal = parseRefusal2(verdict);
|
|
8157
|
+
const hit = matchRepair2(refusal, discovered.repairs);
|
|
8158
|
+
if (hit !== void 0) {
|
|
8159
|
+
if (opts.repair === true) {
|
|
8160
|
+
if (isDir) {
|
|
8161
|
+
err8("--repair executes a rebirth of a cloud WORKSPACE \u2014 replay a workspace name (not a local directory) to repair it");
|
|
8162
|
+
return 1;
|
|
8163
|
+
}
|
|
8164
|
+
const { executeRepairRebirth: executeRepairRebirth2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
8165
|
+
return executeRepairRebirth2(cloud, target, hit, verdict, opts);
|
|
8166
|
+
}
|
|
8167
|
+
if (!json) out8(knownRepairBlock2(hit));
|
|
8168
|
+
}
|
|
8169
|
+
}
|
|
7334
8170
|
return 1;
|
|
7335
8171
|
}
|
|
7336
8172
|
const interactive = !json && opts.step === void 0 && process.stdout.isTTY === true && process.stdin.isTTY === true;
|
|
@@ -7470,7 +8306,7 @@ async function decrypt(ws, opts) {
|
|
|
7470
8306
|
init_engine();
|
|
7471
8307
|
init_cloud();
|
|
7472
8308
|
init_lifecycle();
|
|
7473
|
-
import { readFileSync as
|
|
8309
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
7474
8310
|
var out10 = (s) => void process.stdout.write(s + "\n");
|
|
7475
8311
|
var err10 = (s) => void process.stderr.write("error: " + s + "\n");
|
|
7476
8312
|
function lawDiffVerdict(localHash, installed, ws, hasCurrencyData) {
|
|
@@ -7525,7 +8361,7 @@ async function status(wsArg, opts) {
|
|
|
7525
8361
|
}
|
|
7526
8362
|
let localHash;
|
|
7527
8363
|
try {
|
|
7528
|
-
const body = JSON.parse(
|
|
8364
|
+
const body = JSON.parse(readFileSync12(discoverDeployJson(process.cwd(), opts.file), "utf8"));
|
|
7529
8365
|
if (typeof body.packageUsda === "string") localHash = await sha256hex(body.packageUsda);
|
|
7530
8366
|
} catch {
|
|
7531
8367
|
localHash = void 0;
|
|
@@ -7542,6 +8378,18 @@ async function status(wsArg, opts) {
|
|
|
7542
8378
|
return 1;
|
|
7543
8379
|
}
|
|
7544
8380
|
out10(`workspace ${ws} on ${cloud}`);
|
|
8381
|
+
try {
|
|
8382
|
+
const s = await (await fetch(`${cloud}/v2/workspaces/${ws}`)).json();
|
|
8383
|
+
if (typeof s.incarnation === "string" && s.incarnation !== "") out10(`incarnation ${s.incarnation.slice(0, 16)}\u2026 (current genesis oid)`);
|
|
8384
|
+
const superseded = s.supersededChains ?? [];
|
|
8385
|
+
if (superseded.length > 0) {
|
|
8386
|
+
out10(`superseded ${superseded.length} retired holon(s) (frozen whole at their own custody addresses):`);
|
|
8387
|
+
for (const c of superseded) out10(` ${c.custodyAddress ?? c.ref ?? "?"} ${c.supersededAt ? new Date(c.supersededAt).toISOString() : ""} ${c.reason ? "\u2014 " + String(c.reason).slice(0, 80) : ""}`);
|
|
8388
|
+
} else if (s.lineage?.supersededAt) {
|
|
8389
|
+
out10(`superseded supersession recorded (${s.lineage.supersessionReason ? String(s.lineage.supersessionReason).slice(0, 80) : "reborn"}); custody swap pending`);
|
|
8390
|
+
}
|
|
8391
|
+
} catch {
|
|
8392
|
+
}
|
|
7545
8393
|
const allDomains = d.domains ?? [];
|
|
7546
8394
|
const frameworkHashes = new Set(FRAMEWORK_DOMAIN_KEYS.map((k) => d.currentLaw?.[k]).filter(Boolean));
|
|
7547
8395
|
const domains = allDomains.filter((dm) => !frameworkHashes.has(dm.domainHash));
|
|
@@ -7629,6 +8477,11 @@ Governance (SIGNED client-side, relayed as {intentBytes} \u2014 never a host-aut
|
|
|
7629
8477
|
githolon gov <ws> <directive> [--payload <json>] author ANY workspaces directive as a signed offer
|
|
7630
8478
|
[--as <uid>] [--stamp] [--save <file>] to <ws> (--save signs without relaying; relay later)
|
|
7631
8479
|
githolon gov relay <ws> <offer-file> relay a saved offer (the only step that hits the cloud)
|
|
8480
|
+
githolon gov rebirth <ws> --reason <text> LAWFUL SUPERSESSION (recovery verb 3): supersede a
|
|
8481
|
+
[--dry-run [--json]] [--yes] scarred chain; --dry-run = READ-ONLY impact report
|
|
8482
|
+
githolon rebirth plan <ws> [--reason <text>] [--out D] write a stable plan.json + impact.md (rebirths-as-code)
|
|
8483
|
+
githolon rebirth apply --plan <plan.json> [--yes] drift-pinned apply of a reviewed plan \u2192 certificate.json
|
|
8484
|
+
githolon replay <ws> --repair execute the repair matching a red verify (\u2192 certificate)
|
|
7632
8485
|
githolon grant <admin|creation> <principal> [--label L] grant authority at the parent (default root)
|
|
7633
8486
|
githolon grant quota <principal> --max <N> grant a per-principal workspace allowance
|
|
7634
8487
|
githolon revoke <admin|creation> <principal> revoke it (the revoked fact rides the chain)
|
|
@@ -7678,8 +8531,8 @@ Options:
|
|
|
7678
8531
|
function cloudArgs(rest) {
|
|
7679
8532
|
const pos = [];
|
|
7680
8533
|
const opts = {};
|
|
7681
|
-
const VALUE_FLAGS = ["--cloud", "--principal", "--as", "--file", "--target", "--parent", "--via", "--max", "--label", "--secret", "--payload", "--payload-file", "--save", "--format", "--with", "--out", "--reason", "--oid", "--seed-secret", "--gcp-secret", "--controller-hash"];
|
|
7682
|
-
const BOOL_FLAGS = ["--sha256", "--stamp", "--yes", "--clear", "--keep-beside", "--retire-replaced", "--explain-current-interface"];
|
|
8534
|
+
const VALUE_FLAGS = ["--cloud", "--principal", "--as", "--file", "--target", "--parent", "--via", "--max", "--label", "--secret", "--payload", "--payload-file", "--save", "--format", "--with", "--out", "--reason", "--oid", "--seed-secret", "--gcp-secret", "--controller-hash", "--plan"];
|
|
8535
|
+
const BOOL_FLAGS = ["--sha256", "--stamp", "--yes", "--clear", "--keep-beside", "--retire-replaced", "--explain-current-interface", "--dry-run", "--json"];
|
|
7683
8536
|
for (let i = 0; i < rest.length; i++) {
|
|
7684
8537
|
const a = rest[i];
|
|
7685
8538
|
if (BOOL_FLAGS.includes(a)) {
|
|
@@ -7689,6 +8542,8 @@ function cloudArgs(rest) {
|
|
|
7689
8542
|
else if (a === "--keep-beside") opts.keepBeside = true;
|
|
7690
8543
|
else if (a === "--retire-replaced") opts.retireReplaced = true;
|
|
7691
8544
|
else if (a === "--explain-current-interface") opts.explain = true;
|
|
8545
|
+
else if (a === "--dry-run") opts.dryRun = true;
|
|
8546
|
+
else if (a === "--json") opts.json = true;
|
|
7692
8547
|
else opts.yes = true;
|
|
7693
8548
|
} else if (VALUE_FLAGS.includes(a)) {
|
|
7694
8549
|
const v = rest[++i];
|
|
@@ -7788,21 +8643,21 @@ async function runProof(args) {
|
|
|
7788
8643
|
const explicit = args.find((a, i) => !a.startsWith("--") && i !== domainValueIdx);
|
|
7789
8644
|
let proofPath;
|
|
7790
8645
|
if (explicit !== void 0) {
|
|
7791
|
-
proofPath =
|
|
7792
|
-
if (!
|
|
8646
|
+
proofPath = resolve5(process.cwd(), explicit);
|
|
8647
|
+
if (!existsSync14(proofPath)) return refuse(`proof not found: ${proofPath} \u2014 run \`githolon compile\` to (re)generate it`);
|
|
7793
8648
|
} else {
|
|
7794
|
-
const buildDir =
|
|
7795
|
-
if (!
|
|
8649
|
+
const buildDir = join16(process.cwd(), "build");
|
|
8650
|
+
if (!existsSync14(buildDir)) {
|
|
7796
8651
|
return refuse("no build/ directory here \u2014 run `githolon compile` first (every compile generates build/<name>.proof.mts from your law)");
|
|
7797
8652
|
}
|
|
7798
|
-
const proofs =
|
|
8653
|
+
const proofs = readdirSync5(buildDir).filter((f) => f.endsWith(".proof.mts"));
|
|
7799
8654
|
if (proofs.length === 0) {
|
|
7800
8655
|
return refuse("no build/*.proof.mts found \u2014 run `githolon compile` (every compile generates the proof from your law; the compile summary says why when it can't)");
|
|
7801
8656
|
}
|
|
7802
8657
|
if (proofs.length > 1) {
|
|
7803
8658
|
return refuse(`found ${proofs.length} proofs (${proofs.join(", ")}) \u2014 name one: githolon proof build/<name>.proof.mts`);
|
|
7804
8659
|
}
|
|
7805
|
-
proofPath =
|
|
8660
|
+
proofPath = join16(buildDir, proofs[0]);
|
|
7806
8661
|
}
|
|
7807
8662
|
if (!live) {
|
|
7808
8663
|
try {
|
|
@@ -7815,17 +8670,17 @@ async function runProof(args) {
|
|
|
7815
8670
|
}
|
|
7816
8671
|
const resolvePkgDir = (name, fromDir) => {
|
|
7817
8672
|
try {
|
|
7818
|
-
return
|
|
8673
|
+
return dirname9(createRequire3(pathToFileURL5(join16(fromDir, "noop.js"))).resolve(`${name}/package.json`));
|
|
7819
8674
|
} catch {
|
|
7820
8675
|
return void 0;
|
|
7821
8676
|
}
|
|
7822
8677
|
};
|
|
7823
8678
|
const dslDir = (() => {
|
|
7824
8679
|
try {
|
|
7825
|
-
return
|
|
8680
|
+
return dirname9(createRequire3(pathToFileURL5(join16(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
|
|
7826
8681
|
} catch {
|
|
7827
8682
|
try {
|
|
7828
|
-
return
|
|
8683
|
+
return dirname9(createRequire3(import.meta.url).resolve("@githolon/dsl/package.json"));
|
|
7829
8684
|
} catch {
|
|
7830
8685
|
return void 0;
|
|
7831
8686
|
}
|
|
@@ -7835,9 +8690,9 @@ async function runProof(args) {
|
|
|
7835
8690
|
if (tsxDir === void 0) {
|
|
7836
8691
|
return refuse("tsx not found \u2014 add @githolon/dsl to your project's dependencies (tsx rides along) and npm install");
|
|
7837
8692
|
}
|
|
7838
|
-
const tsxPkg = JSON.parse(
|
|
8693
|
+
const tsxPkg = JSON.parse(readFileSync14(join16(tsxDir, "package.json"), "utf8"));
|
|
7839
8694
|
const tsxBinRel = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.["tsx"];
|
|
7840
|
-
const tsxCli =
|
|
8695
|
+
const tsxCli = join16(tsxDir, tsxBinRel ?? "dist/cli.mjs");
|
|
7841
8696
|
console.log("githolon proof --live \u2014 the full cloud loop (throwaway workspace, retired on exit" + (keep ? "; --keep: kept" : "") + ")");
|
|
7842
8697
|
const { wsCreate: wsCreate2, wsRetire: wsRetire2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
|
|
7843
8698
|
const { resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
@@ -7866,7 +8721,7 @@ async function runProof(args) {
|
|
|
7866
8721
|
);
|
|
7867
8722
|
}
|
|
7868
8723
|
}
|
|
7869
|
-
const r =
|
|
8724
|
+
const r = spawnSync6(process.execPath, [tsxCli, proofPath], {
|
|
7870
8725
|
stdio: "inherit",
|
|
7871
8726
|
cwd: process.cwd(),
|
|
7872
8727
|
env: {
|
|
@@ -8031,7 +8886,8 @@ ${commandHelp("dev")}`);
|
|
|
8031
8886
|
}
|
|
8032
8887
|
}
|
|
8033
8888
|
const json = rest.includes("--json");
|
|
8034
|
-
const
|
|
8889
|
+
const wantRepair = rest.includes("--repair");
|
|
8890
|
+
const cleaned = rest.filter((a, i) => a !== "--json" && a !== "--repair" && a !== "--step" && !(sAt >= 0 && i === sAt + 1));
|
|
8035
8891
|
const { pos, opts, bad } = cloudArgs(cleaned);
|
|
8036
8892
|
if (bad !== void 0) {
|
|
8037
8893
|
process.stderr.write(`error: ${bad}
|
|
@@ -8046,7 +8902,7 @@ ${commandHelp("replay")}`);
|
|
|
8046
8902
|
${commandHelp("replay")}`);
|
|
8047
8903
|
return 1;
|
|
8048
8904
|
}
|
|
8049
|
-
return replay(target, { ...opts, ...step !== void 0 ? { step } : {}, ...json ? { json: true } : {} });
|
|
8905
|
+
return replay(target, { ...opts, ...step !== void 0 ? { step } : {}, ...json ? { json: true } : {}, ...wantRepair ? { repair: true } : {} });
|
|
8050
8906
|
}
|
|
8051
8907
|
if (argv[0] === "scene") {
|
|
8052
8908
|
const { scene: scene2 } = await Promise.resolve().then(() => (init_scene(), scene_exports));
|
|
@@ -8171,6 +9027,53 @@ ${USAGE}`);
|
|
|
8171
9027
|
${USAGE}`);
|
|
8172
9028
|
return 1;
|
|
8173
9029
|
}
|
|
9030
|
+
if (argv[0] === "rebirth") {
|
|
9031
|
+
const { pos, opts, bad } = cloudArgs(argv.slice(1));
|
|
9032
|
+
if (bad !== void 0) {
|
|
9033
|
+
process.stderr.write(`error: ${bad}
|
|
9034
|
+
|
|
9035
|
+
${USAGE}`);
|
|
9036
|
+
return 1;
|
|
9037
|
+
}
|
|
9038
|
+
if (pos[0] === "plan") {
|
|
9039
|
+
const ws = pos[1];
|
|
9040
|
+
if (ws === void 0) {
|
|
9041
|
+
process.stderr.write("error: expected: githolon rebirth plan <ws> [--reason <text>] [--out <dir>]\n");
|
|
9042
|
+
return 1;
|
|
9043
|
+
}
|
|
9044
|
+
const { rebirthPlanCommand: rebirthPlanCommand2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
9045
|
+
const flag = (n) => {
|
|
9046
|
+
const i = argv.indexOf(n);
|
|
9047
|
+
return i >= 0 ? argv[i + 1] : void 0;
|
|
9048
|
+
};
|
|
9049
|
+
return rebirthPlanCommand2(ws, {
|
|
9050
|
+
...opts,
|
|
9051
|
+
...flag("--reason") !== void 0 ? { reason: flag("--reason") } : {},
|
|
9052
|
+
...flag("--out") !== void 0 ? { out: flag("--out") } : {}
|
|
9053
|
+
});
|
|
9054
|
+
}
|
|
9055
|
+
if (pos[0] === "apply") {
|
|
9056
|
+
const flag = (n) => {
|
|
9057
|
+
const i = argv.indexOf(n);
|
|
9058
|
+
return i >= 0 ? argv[i + 1] : void 0;
|
|
9059
|
+
};
|
|
9060
|
+
const planPath = flag("--plan") ?? pos[1];
|
|
9061
|
+
if (planPath === void 0) {
|
|
9062
|
+
process.stderr.write("error: expected: githolon rebirth apply --plan <plan.json> [--seed-secret <b64>|--gcp-secret <name>] [--yes]\n");
|
|
9063
|
+
return 1;
|
|
9064
|
+
}
|
|
9065
|
+
const { rebirthApply: rebirthApply2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
9066
|
+
return rebirthApply2(planPath, {
|
|
9067
|
+
...opts,
|
|
9068
|
+
...flag("--seed-secret") !== void 0 ? { seedSecret: flag("--seed-secret") } : {},
|
|
9069
|
+
...flag("--gcp-secret") !== void 0 ? { gcpSecret: flag("--gcp-secret") } : {},
|
|
9070
|
+
...flag("--controller-hash") !== void 0 ? { controllerHash: flag("--controller-hash") } : {},
|
|
9071
|
+
yes: argv.includes("--yes")
|
|
9072
|
+
});
|
|
9073
|
+
}
|
|
9074
|
+
process.stderr.write("error: expected: githolon rebirth <plan <ws> | apply --plan <plan.json>>\n");
|
|
9075
|
+
return 1;
|
|
9076
|
+
}
|
|
8174
9077
|
if (argv[0] === "gov") {
|
|
8175
9078
|
const { governanceOffer: governanceOffer2, governanceRelay: governanceRelay2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
8176
9079
|
const { pos, opts, bad } = cloudArgs(argv.slice(1));
|
|
@@ -8218,6 +9121,30 @@ ${commandHelp("gov") ?? USAGE}`);
|
|
|
8218
9121
|
yes: argv.includes("--yes")
|
|
8219
9122
|
});
|
|
8220
9123
|
}
|
|
9124
|
+
if (pos[0] === "rebirth") {
|
|
9125
|
+
const ws2 = pos[1];
|
|
9126
|
+
if (ws2 === void 0) {
|
|
9127
|
+
process.stderr.write(`error: expected: githolon gov rebirth <ws> --reason <text> [--seed-secret <b64>|--gcp-secret <name>] [--yes]
|
|
9128
|
+
|
|
9129
|
+
${commandHelp("gov") ?? USAGE}`);
|
|
9130
|
+
return 1;
|
|
9131
|
+
}
|
|
9132
|
+
const { rebirthWorkspace: rebirthWorkspace2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
|
|
9133
|
+
const flag = (n) => {
|
|
9134
|
+
const i = argv.indexOf(n);
|
|
9135
|
+
return i >= 0 ? argv[i + 1] : void 0;
|
|
9136
|
+
};
|
|
9137
|
+
return rebirthWorkspace2(ws2, {
|
|
9138
|
+
...opts,
|
|
9139
|
+
...flag("--reason") !== void 0 ? { reason: flag("--reason") } : {},
|
|
9140
|
+
...flag("--seed-secret") !== void 0 ? { seedSecret: flag("--seed-secret") } : {},
|
|
9141
|
+
...flag("--gcp-secret") !== void 0 ? { gcpSecret: flag("--gcp-secret") } : {},
|
|
9142
|
+
...flag("--controller-hash") !== void 0 ? { controllerHash: flag("--controller-hash") } : {},
|
|
9143
|
+
dryRun: argv.includes("--dry-run"),
|
|
9144
|
+
json: argv.includes("--json"),
|
|
9145
|
+
yes: argv.includes("--yes")
|
|
9146
|
+
});
|
|
9147
|
+
}
|
|
8221
9148
|
const [ws, directiveId] = pos;
|
|
8222
9149
|
if (ws === void 0 || directiveId === void 0) {
|
|
8223
9150
|
process.stderr.write(`error: expected: githolon gov <ws> <directiveId> [--payload <json>] [--as <uid>]
|