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.
Files changed (2) hide show
  1. package/dist/cli.mjs +1034 -107
  2. 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 resolve5(ps) {
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) => resolve5(ps.slice(0, -1));
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 = resolve5(parts(p));
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 = resolve5(parts(p));
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 = resolve5(parts(p));
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 mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
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 join3 } from "node:path";
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"] ?? join3(homedir(), ".holon");
4214
+ return process.env["HOLON_CONFIG_DIR"] ?? join4(homedir(), ".holon");
3540
4215
  }
3541
4216
  function credsPath() {
3542
- return join3(configDir(), "credentials.json");
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
- mkdirSync3(configDir(), { recursive: true });
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 = join3(cwd, "build");
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 join3(buildDir, bodies[0]);
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 mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
4040
- import { dirname as dirname2, join as join4 } from "node:path";
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 = join4(cwd, ".vscode", "extensions.json");
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 = join4(cwd, ".vscode");
4053
- const path = join4(dir, "extensions.json");
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
- mkdirSync4(dirname2(path), { recursive: true });
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 dirname3, join as join5 } from "node:path";
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(join5(fromDir, "noop.js")));
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 : join5(dirname3(dslPkg), "compile_package.mjs");
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 : join5(dirname3(launcher), "check_package.mjs");
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 : join5(dirname3(launcher), "compat_package.mjs");
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 : join5(dirname3(launcher), "lsp_server.mjs");
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 dirname4, join as join7 } from "node:path";
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 = join7(dirname4(proofPath), `${packageName}.deploy.json`);
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 = join7(dirname4(proofPath), `${packageName}.proof-legs.json`);
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 spawnSync4 } from "node:child_process";
4718
- import { existsSync as existsSync10 } from "node:fs";
4719
- import { dirname as dirname6, isAbsolute, resolve as resolve2 } from "node:path";
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 = isAbsolute(arg) ? arg : resolve2(process.cwd(), arg);
4723
- return { configPath, cfgDir: dirname6(configPath) };
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 = dirname6(configPath);
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 = spawnSync4(process.execPath, [launcher, configPath, ...extraArgs], {
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 (!existsSync10(configPath)) {
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 (!existsSync10(configPath)) {
5630
+ if (!existsSync11(configPath)) {
4815
5631
  return { text: `nomos_evolve_preview: config not found: ${configPath}`, isError: true };
4816
5632
  }
4817
- const againstPath = isAbsolute(args.against) ? args.against : resolve2(dirname6(configPath), args.against);
4818
- const priorArg = existsSync10(againstPath) ? againstPath : args.against;
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 existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync7 } from "node:fs";
4982
- import { join as join12 } from "node:path";
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"] || join12(configDir(), "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 = join12(runtimeDir, "holon.wasm");
4997
- const pkgsFile = join12(runtimeDir, "packages.json");
4998
- if (!existsSync11(wasmFile) || !existsSync11(pkgsFile)) {
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 = readFileSync12(wasmFile);
5004
- const pkgs = JSON.parse(readFileSync12(pkgsFile, "utf8"));
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 (!existsSync11(p)) die(`deploy JSON not found: ${p} \u2014 run \`npx githolon compile\` first`);
5027
- const deploy3 = JSON.parse(readFileSync12(p, "utf8"));
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
- writeFileSync7(outPath, treeBytes);
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 existsSync12, mkdirSync as mkdirSync5, writeFileSync as writeFileSync8 } from "node:fs";
6119
- import { join as join13, resolve as resolve3 } from "node:path";
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 = existsSync12(join13(target, ".git")) ? join13(target, ".git") : target;
6141
- if (!existsSync12(join13(gitDir, "HEAD"))) throw new Error(`${target} is not a git repo (no HEAD)`);
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 = existsSync12(target) || target.includes("/") || target.startsWith(".");
6201
- const name = isDir ? (resolve3(target).split("/").filter(Boolean).pop() ?? "scene").replace(/\.git$/, "") : target;
6202
- out11(`scene \u2014 ${name} (${isDir ? resolve3(target) : `${cloud} :: ${target}`})`);
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 = resolve3(opts.out ?? join13("scene", name));
6221
- mkdirSync5(outDir, { recursive: true });
6222
- const usdaPath = join13(outDir, `${name}.usda`);
6223
- const usdzPath = join13(outDir, `${name}.usdz`);
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
- writeFileSync8(usdaPath, usdaBytes);
6226
- writeFileSync8(usdzPath, usdzPack([[`${name}.usda`, usdaBytes]]));
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 existsSync13, readdirSync as readdirSync4, readFileSync as readFileSync13 } from "node:fs";
6253
- import { spawnSync as spawnSync5 } from "node:child_process";
6254
- import { createRequire as createRequire2 } from "node:module";
6255
- import { dirname as dirname7, join as join14, resolve as resolve4 } from "node:path";
6256
- import { pathToFileURL as pathToFileURL4 } from "node:url";
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 dirname5, join as join8, resolve } from "node:path";
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 join6 } from "node:path";
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 = join6(cwd, CONFIG_FILE);
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 = join8(cwd, "build", `${packageName}.deploy.json`);
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 = join8(cwd, "build", `${s.packageName}.proof.mts`);
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(join8(cwd, CONFIG_FILE))) {
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(dirname5(resolve(cwd, m)));
7548
+ for (const m of d.modules ?? []) moduleDirs.add(dirname6(resolve(cwd, m)));
6733
7549
  }
6734
7550
  } catch {
6735
- moduleDirs.add(join8(cwd, "domains"));
7551
+ moduleDirs.add(join9(cwd, "domains"));
6736
7552
  }
6737
- if (moduleDirs.size === 0) moduleDirs.add(join8(cwd, "domains"));
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 join9 } from "node:path";
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 = join9(dir, ".git");
7996
+ const gitDir = join10(dir, ".git");
7181
7997
  writeTreeToDisk(gitTree, gitDir);
7182
- const cfgPath = join9(gitDir, "config");
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(join9(dir, ".git")) ? join9(dir, ".git") : dir;
7193
- if (!existsSync8(join9(gitDir, "HEAD"))) {
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 existsSync9 } from "node:fs";
7210
- import { join as join10 } from "node:path";
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 = existsSync9(target) || target.includes("/") || target.startsWith(".");
8122
+ const isDir = existsSync10(target) || target.includes("/") || target.startsWith(".");
7307
8123
  if (isDir) {
7308
- const gitDir = existsSync9(join10(target, ".git")) ? join10(target, ".git") : target;
7309
- if (!existsSync9(join10(gitDir, "HEAD"))) {
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 readFileSync11 } from "node:fs";
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(readFileSync11(discoverDeployJson(process.cwd(), opts.file), "utf8"));
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 = resolve4(process.cwd(), explicit);
7792
- if (!existsSync13(proofPath)) return refuse(`proof not found: ${proofPath} \u2014 run \`githolon compile\` to (re)generate it`);
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 = join14(process.cwd(), "build");
7795
- if (!existsSync13(buildDir)) {
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 = readdirSync4(buildDir).filter((f) => f.endsWith(".proof.mts"));
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 = join14(buildDir, proofs[0]);
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 dirname7(createRequire2(pathToFileURL4(join14(fromDir, "noop.js"))).resolve(`${name}/package.json`));
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 dirname7(createRequire2(pathToFileURL4(join14(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
8680
+ return dirname9(createRequire3(pathToFileURL5(join16(process.cwd(), "noop.js"))).resolve("@githolon/dsl/package.json"));
7826
8681
  } catch {
7827
8682
  try {
7828
- return dirname7(createRequire2(import.meta.url).resolve("@githolon/dsl/package.json"));
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(readFileSync13(join14(tsxDir, "package.json"), "utf8"));
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 = join14(tsxDir, tsxBinRel ?? "dist/cli.mjs");
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 = spawnSync5(process.execPath, [tsxCli, proofPath], {
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 cleaned = rest.filter((a, i) => a !== "--json" && a !== "--step" && !(sAt >= 0 && i === sAt + 1));
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>]