githolon 0.69.0 → 0.69.2

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 +375 -256
  2. package/package.json +3 -3
package/dist/cli.mjs CHANGED
@@ -2828,9 +2828,151 @@ var init_local_holon = __esm({
2828
2828
  }
2829
2829
  });
2830
2830
 
2831
+ // src/repairs.ts
2832
+ var repairs_exports = {};
2833
+ __export(repairs_exports, {
2834
+ discoverRepairs: () => discoverRepairs,
2835
+ knownRepairBlock: () => knownRepairBlock,
2836
+ matchRepair: () => matchRepair,
2837
+ parseRefusal: () => parseRefusal
2838
+ });
2839
+ import { spawnSync } from "node:child_process";
2840
+ import { createRequire } from "node:module";
2841
+ import { existsSync as existsSync3, mkdtempSync, readdirSync as readdirSync2, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
2842
+ import { tmpdir } from "node:os";
2843
+ import { dirname as dirname2, isAbsolute, join as join3, resolve } from "node:path";
2844
+ import { pathToFileURL } from "node:url";
2845
+ function parseRefusal(verdict) {
2846
+ const check2 = String(verdict["check"] ?? "");
2847
+ const error = String(verdict["error"] ?? "");
2848
+ const raw = `${check2}: ${error}`;
2849
+ const kind = /evolve.?gate/i.test(raw) || /evolve/i.test(check2) ? "evolve-gate" : "other";
2850
+ const sids = /* @__PURE__ */ new Set();
2851
+ const structured = verdict["stableId"] ?? verdict["stableIds"];
2852
+ if (typeof structured === "string" && SID_SHAPE.test(structured)) sids.add(structured.toLowerCase());
2853
+ if (Array.isArray(structured)) {
2854
+ for (const s of structured) if (typeof s === "string" && SID_SHAPE.test(s)) sids.add(s.toLowerCase());
2855
+ }
2856
+ for (const m of raw.matchAll(SID_RE)) sids.add(m[1].toLowerCase());
2857
+ return { kind, stableIds: [...sids], raw };
2858
+ }
2859
+ function matchRepair(refusal, repairs) {
2860
+ if (refusal.kind === "other") return void 0;
2861
+ return repairs.find(
2862
+ (r) => r.matcher.refusal === refusal.kind && refusal.stableIds.includes(r.matcher.stableId.toLowerCase())
2863
+ );
2864
+ }
2865
+ function knownRepairBlock(repair) {
2866
+ return [
2867
+ "",
2868
+ `\u2726 KNOWN REPAIR: '${repair.id}' (${repair.file}) declares a remedy for exactly this refusal.`,
2869
+ ` reason: ${repair.reason}`,
2870
+ " Re-run with --repair to execute it."
2871
+ ].join("\n");
2872
+ }
2873
+ function resolveTsxCli(cwd) {
2874
+ const pkgDir = (name, fromDir) => {
2875
+ try {
2876
+ return dirname2(createRequire(pathToFileURL(join3(fromDir, "noop.js")).href).resolve(`${name}/package.json`));
2877
+ } catch {
2878
+ return void 0;
2879
+ }
2880
+ };
2881
+ const dslDir = pkgDir("@githolon/dsl", cwd) ?? (() => {
2882
+ try {
2883
+ return dirname2(createRequire(import.meta.url).resolve("@githolon/dsl/package.json"));
2884
+ } catch {
2885
+ return void 0;
2886
+ }
2887
+ })();
2888
+ const tsxDir = pkgDir("tsx", cwd) ?? (dslDir !== void 0 ? pkgDir("tsx", dslDir) : void 0);
2889
+ if (tsxDir === void 0) return void 0;
2890
+ try {
2891
+ const pkg = JSON.parse(
2892
+ readFileSync2(join3(tsxDir, "package.json"), "utf8")
2893
+ );
2894
+ const rel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.["tsx"];
2895
+ return join3(tsxDir, rel ?? "dist/cli.mjs");
2896
+ } catch {
2897
+ return void 0;
2898
+ }
2899
+ }
2900
+ function resolveDslEntry(cwd) {
2901
+ const tryFrom = (fromUrl) => {
2902
+ try {
2903
+ return createRequire(fromUrl).resolve("@githolon/dsl");
2904
+ } catch {
2905
+ return void 0;
2906
+ }
2907
+ };
2908
+ return tryFrom(pathToFileURL(join3(cwd, "noop.js")).href) ?? tryFrom(import.meta.url);
2909
+ }
2910
+ function discoverRepairs(cwd) {
2911
+ const dir = join3(cwd, "repairs");
2912
+ if (!existsSync3(dir)) return { repairs: [] };
2913
+ let files;
2914
+ try {
2915
+ files = readdirSync2(dir).filter((f) => /\.(ts|mts|cts)$/.test(f) && !/\.d\.ts$/.test(f)).sort().map((f) => resolve(dir, f));
2916
+ } catch (e) {
2917
+ return { error: `could not read the repairs/ folder: ${e.message}` };
2918
+ }
2919
+ if (files.length === 0) return { repairs: [] };
2920
+ const tsxCli = resolveTsxCli(cwd);
2921
+ const dslEntry = resolveDslEntry(cwd);
2922
+ if (tsxCli === void 0 || dslEntry === void 0) {
2923
+ 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" };
2924
+ }
2925
+ const scratch = mkdtempSync(join3(tmpdir(), "githolon-repairs-"));
2926
+ const loader = join3(scratch, "discover.mts");
2927
+ const loaderSrc = `
2928
+ import { repairsOf } from ${JSON.stringify(dslEntry)};
2929
+ const files = ${JSON.stringify(files)};
2930
+ const out = [];
2931
+ const seen = new Map();
2932
+ for (const file of files) {
2933
+ const mod = await import(${JSON.stringify("file://")} + file);
2934
+ for (const r of repairsOf(mod)) {
2935
+ if (seen.has(r.id)) {
2936
+ throw new Error("duplicate repair id '" + r.id + "' \u2014 declared in " + seen.get(r.id) + " and " + file);
2937
+ }
2938
+ seen.set(r.id, file);
2939
+ out.push({ id: r.id, matcher: r.matcher, reason: r.reason, verb: r.verb, file });
2940
+ }
2941
+ }
2942
+ process.stdout.write("\\u0001REPAIRS\\u0001" + JSON.stringify(out) + "\\u0001END\\u0001\\n");
2943
+ `;
2944
+ try {
2945
+ writeFileSync3(loader, loaderSrc, "utf8");
2946
+ const r = spawnSync(process.execPath, [tsxCli, loader], { cwd, encoding: "utf8" });
2947
+ if (r.status !== 0) {
2948
+ const msg = (r.stderr || r.stdout || "").trim().split("\n").filter(Boolean).slice(-4).join("\n");
2949
+ return { error: `loading repairs/ failed:
2950
+ ${msg || `tsx exited ${r.status ?? "?"}`}` };
2951
+ }
2952
+ const m = /REPAIRS([\s\S]*?)END/.exec(r.stdout);
2953
+ if (m === null) return { error: "the repairs loader produced no manifest (unexpected \u2014 the DSL/tsx may be too old)" };
2954
+ const parsed = JSON.parse(m[1]);
2955
+ const repairs = parsed.map((p) => ({ ...p, file: isAbsolute(p.file) ? p.file : resolve(cwd, p.file) }));
2956
+ return { repairs };
2957
+ } catch (e) {
2958
+ return { error: `loading repairs/ failed: ${e.message}` };
2959
+ } finally {
2960
+ rmSync(scratch, { recursive: true, force: true });
2961
+ }
2962
+ }
2963
+ var SID_RE, SID_SHAPE;
2964
+ var init_repairs = __esm({
2965
+ "src/repairs.ts"() {
2966
+ "use strict";
2967
+ SID_RE = /stable id ([0-9a-f]{16})/gi;
2968
+ SID_SHAPE = /^[0-9a-f]{16}$/i;
2969
+ }
2970
+ });
2971
+
2831
2972
  // src/governance.ts
2832
2973
  var governance_exports = {};
2833
2974
  __export(governance_exports, {
2975
+ ROOT_CUSTODIAN_SECRET: () => ROOT_CUSTODIAN_SECRET,
2834
2976
  buildCertificate: () => buildCertificate,
2835
2977
  buildRebirthPlan: () => buildRebirthPlan,
2836
2978
  certifyEra: () => certifyEra,
@@ -2853,8 +2995,8 @@ __export(governance_exports, {
2853
2995
  verifyWorkspaceVerdict: () => verifyWorkspaceVerdict
2854
2996
  });
2855
2997
  import { createHash, createPrivateKey, createPublicKey } from "node:crypto";
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";
2998
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
2999
+ import { dirname as dirname3, join as join4 } from "node:path";
2858
3000
  async function clientConnect() {
2859
3001
  const mod = await import("@githolon/client");
2860
3002
  return mod.connect;
@@ -3072,7 +3214,7 @@ async function keyExport(opts) {
3072
3214
  return 0;
3073
3215
  }
3074
3216
  function buildOfferPayload(opts) {
3075
- const raw = opts.payloadFile !== void 0 ? readFileSync2(opts.payloadFile, "utf8") : opts.payload;
3217
+ const raw = opts.payloadFile !== void 0 ? readFileSync3(opts.payloadFile, "utf8") : opts.payload;
3076
3218
  let payload = {};
3077
3219
  if (raw !== void 0 && raw.trim() !== "") payload = JSON.parse(raw);
3078
3220
  if (typeof payload !== "object" || payload === null || Array.isArray(payload)) {
@@ -3106,7 +3248,7 @@ async function governanceOffer(ws, directiveId, opts) {
3106
3248
  const holon = await connectGovernance(cloudBase(opts.cloud), ws);
3107
3249
  const device = await ensureDeviceKey(holon, principal);
3108
3250
  const sealed = await holon.signGovernanceOffer({ directiveId, payload, authorSecret: device.secret, actor: `user:${principal}` });
3109
- writeFileSync3(opts.save, JSON.stringify({ ws, directiveId, principal, intentBytes: sealed.intentBytes }, null, 2) + "\n");
3251
+ writeFileSync4(opts.save, JSON.stringify({ ws, directiveId, principal, intentBytes: sealed.intentBytes }, null, 2) + "\n");
3110
3252
  } catch (e) {
3111
3253
  err2(e.message);
3112
3254
  return 1;
@@ -3133,7 +3275,7 @@ async function governanceOffer(ws, directiveId, opts) {
3133
3275
  async function governanceRelay(ws, file, opts) {
3134
3276
  let saved;
3135
3277
  try {
3136
- saved = JSON.parse(readFileSync2(file, "utf8"));
3278
+ saved = JSON.parse(readFileSync3(file, "utf8"));
3137
3279
  } catch (e) {
3138
3280
  err2(`cannot read offer file ${file}: ${e.message}`);
3139
3281
  return 1;
@@ -3351,18 +3493,27 @@ async function buildRebirthPlan(cloud, ws, reason) {
3351
3493
  } catch {
3352
3494
  }
3353
3495
  const lawHashes = {};
3496
+ let currentLaw2 = {};
3354
3497
  try {
3355
3498
  const d = await (await fetch(`${cloud}/v2/workspaces/${ws}/domains`)).json();
3499
+ currentLaw2 = d.currentLaw ?? {};
3500
+ const currentHashes = new Set(Object.values(currentLaw2));
3356
3501
  for (const dom of d.domains ?? []) {
3357
- if (typeof dom.domainHash === "string" && dom.phase === "Active") lawHashes[dom.domainHash] = dom.phase;
3502
+ if (typeof dom.domainHash !== "string") continue;
3503
+ lawHashes[dom.domainHash] = {
3504
+ phase: dom.phase ?? "unknown",
3505
+ current: dom.current === true || currentHashes.has(dom.domainHash)
3506
+ };
3358
3507
  }
3359
3508
  } catch {
3360
3509
  }
3361
3510
  let verdict = { replay: "unknown", firstRefusal: null };
3511
+ let rawVerdict = null;
3362
3512
  try {
3363
3513
  const m = await mountWorkspace2(eng, ws, { remote: `${cloud}/v2/workspaces/${ws}/git`, headers: {} });
3364
3514
  if (m.restored === true) {
3365
3515
  const v = verifyChainLocal2(eng, ws);
3516
+ rawVerdict = v;
3366
3517
  if (v["valid"] === true) verdict = { replay: "green", firstRefusal: null };
3367
3518
  else verdict = { replay: "red", firstRefusal: `${String(v["check"] ?? "?")}${v["atIndex"] !== void 0 ? ` @intent ${v["atIndex"]}` : ""}: ${String(v["error"] ?? "").slice(0, 200)}` };
3368
3519
  }
@@ -3384,13 +3535,42 @@ async function buildRebirthPlan(cloud, ws, reason) {
3384
3535
  } catch {
3385
3536
  }
3386
3537
  const mode = compaction.scarShape === "mid-chain" && !((compaction.parked ?? 99) <= 2 && parkedAllLawInstalls) ? "state-seed" : "replay-compact";
3538
+ let repairs = [];
3539
+ if (rawVerdict !== null && rawVerdict["valid"] !== true) {
3540
+ try {
3541
+ const { discoverRepairs: discoverRepairs2, parseRefusal: parseRefusal2, matchRepair: matchRepair2 } = await Promise.resolve().then(() => (init_repairs(), repairs_exports));
3542
+ const discovered = discoverRepairs2(process.cwd());
3543
+ if (!("error" in discovered) && discovered.repairs.length > 0) {
3544
+ const refusal = parseRefusal2(rawVerdict);
3545
+ for (const r of discovered.repairs) {
3546
+ if (r.matcher.refusal === refusal.kind && refusal.stableIds.includes(r.matcher.stableId.toLowerCase())) {
3547
+ const v = r.verb;
3548
+ repairs.push({
3549
+ id: r.id,
3550
+ file: r.file,
3551
+ reason: r.reason,
3552
+ matcher: { refusal: r.matcher.refusal, stableId: r.matcher.stableId },
3553
+ verb: {
3554
+ kind: String(v.kind ?? ""),
3555
+ ...typeof v.aggregateId === "string" ? { aggregateId: v.aggregateId } : {},
3556
+ ...typeof v.field === "string" ? { field: v.field } : {},
3557
+ ...typeof v.through === "string" ? { through: v.through } : {}
3558
+ },
3559
+ execution: "recorded"
3560
+ });
3561
+ }
3562
+ }
3563
+ }
3564
+ } catch {
3565
+ }
3566
+ }
3387
3567
  const frozenAt = priorSupersessions === 0 ? ws : `${ws}--i${priorSupersessions}`;
3388
3568
  const newCustodyAddress = `${ws}--i${priorSupersessions + 1}`;
3389
3569
  const plan = {
3390
3570
  v: 1,
3391
3571
  workspace: ws,
3392
3572
  reason: reason ?? null,
3393
- pinned: { incarnation, lawHashes, parent },
3573
+ pinned: { incarnation, lawHashes, currentLaw: currentLaw2, parent },
3394
3574
  will: {
3395
3575
  newCustodyAddress,
3396
3576
  frozenAt,
@@ -3400,7 +3580,7 @@ async function buildRebirthPlan(cloud, ws, reason) {
3400
3580
  verdict,
3401
3581
  mode,
3402
3582
  compaction,
3403
- repairs: [],
3583
+ repairs,
3404
3584
  clientImpact: CLIENT_IMPACT,
3405
3585
  generatedAt: (/* @__PURE__ */ new Date()).toISOString()
3406
3586
  };
@@ -3416,8 +3596,15 @@ function renderRebirthImpact(plan, ledgerCommits) {
3416
3596
  L.push(` incarnation : ${plan.pinned.incarnation ? plan.pinned.incarnation.slice(0, 16) + "\u2026" : "(none recorded \u2014 first incarnation)"}`);
3417
3597
  L.push(` verify_chain : ${plan.verdict.replay.toUpperCase()}${plan.verdict.firstRefusal ? ` \u2014 first refusal: ${plan.verdict.firstRefusal}` : ""}`);
3418
3598
  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)"}`);
3599
+ const laws = Object.entries(plan.pinned.lawHashes);
3600
+ const currentLaw2 = plan.pinned.currentLaw ?? {};
3601
+ const keysForHash = (hash) => Object.entries(currentLaw2).filter(([, h]) => h === hash).map(([k]) => k);
3602
+ const currentHashes = laws.filter(([, m]) => m.current).map(([h]) => h);
3603
+ const currentDesc = currentHashes.length ? currentHashes.map((h) => {
3604
+ const ks = keysForHash(h);
3605
+ return `${h.slice(0, 8)}\u2026${ks.length ? ` (${ks.join(", ")})` : ""}`;
3606
+ }).join(" \xB7 ") : "(none current)";
3607
+ L.push(` installed law : ${laws.length} historical \xB7 current: ${currentDesc}`);
3421
3608
  L.push(` parent : ${plan.pinned.parent || "(root)"}`);
3422
3609
  L.push("");
3423
3610
  L.push("WHAT A REBIRTH WOULD DO");
@@ -3450,9 +3637,33 @@ function renderRebirthImpact(plan, ledgerCommits) {
3450
3637
  L.push(" \u2192 preserved by lineage continuity; their birth-cert chains stay valid (same founding key + self-id).");
3451
3638
  }
3452
3639
  L.push("");
3640
+ L.push(`REPAIRS (${plan.repairs.length})`);
3641
+ if (plan.repairs.length === 0) L.push(" (none matched \u2014 a plain compaction; no corrective verb declared for this refusal)");
3642
+ else {
3643
+ for (const r of plan.repairs) {
3644
+ const v = r.verb;
3645
+ const verbDesc = `${v.kind}${v.aggregateId ? ` ${v.aggregateId}${v.field ? `.${v.field}` : ""}` : ""}${v.through ? ` through ${v.through}` : ""}`;
3646
+ L.push(` \u2726 ${r.id} [${r.execution}]`);
3647
+ L.push(` matches : ${r.matcher.refusal} \xB7 stable id ${r.matcher.stableId}`);
3648
+ L.push(` verb : ${verbDesc} (${r.file})`);
3649
+ L.push(` reason : ${r.reason}`);
3650
+ }
3651
+ L.push(" \u2192 v1 records the repair as provenance/justification (the certificate + supersession reason name it);");
3652
+ L.push(" state-transform verbs execute at the re-fold seam in a future release.");
3653
+ }
3654
+ L.push("");
3453
3655
  L.push("CLIENT IMPACT");
3454
3656
  L.push(` ${plan.clientImpact}.`);
3455
3657
  L.push(" Recommend tenants DRAIN/SYNC their clients before the rebirth window.");
3658
+ L.push("");
3659
+ L.push("NEXT STEPS \u2014 the blessed golden path");
3660
+ L.push(" 1. plan (this)");
3661
+ L.push(` 2. apply githolon rebirth apply --plan <path> --gcp-secret ${ROOT_CUSTODIAN_SECRET} [--yes]`);
3662
+ L.push(" (apply requires the ROOT CUSTODIAN seed \u2014 --gcp-secret is the blessed path;");
3663
+ L.push(" --seed-secret <b64> is break-glass, env NOMOS_ROOT_SEED is the CI lane)");
3664
+ L.push(` 3. replay githolon replay ${plan.workspace} (expect GREEN from intent 0)`);
3665
+ L.push(` 4. status githolon status ${plan.workspace} (incarnation + supersession history)`);
3666
+ L.push(" 5. compat githolon compat (clients raise CustodyBreak \u2014 choose adopt/reject)");
3456
3667
  return L.join("\n");
3457
3668
  }
3458
3669
  async function rebirthPlanCommand(ws, opts) {
@@ -3463,19 +3674,22 @@ async function rebirthPlanCommand(ws, opts) {
3463
3674
  return 1;
3464
3675
  }
3465
3676
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3466
- const dir = opts.out ?? join3("rebirths", `${date}-${ws}`);
3677
+ const dir = opts.out ?? join4("rebirths", `${date}-${ws}`);
3467
3678
  try {
3468
3679
  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");
3680
+ writeFileSync4(join4(dir, "plan.json"), JSON.stringify(built.plan, null, 2) + "\n");
3681
+ writeFileSync4(join4(dir, "impact.md"), "```\n" + renderRebirthImpact(built.plan, built.ledgerCommits) + "\n```\n");
3471
3682
  } catch (e) {
3472
3683
  err2(`could not write the plan into ${dir}: ${e.message}`);
3473
3684
  return 1;
3474
3685
  }
3475
3686
  out2(renderRebirthImpact(built.plan, built.ledgerCommits));
3476
3687
  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).");
3688
+ out2(`\u2713 plan written: ${join4(dir, "plan.json")} + ${join4(dir, "impact.md")}`);
3689
+ if (built.plan.reason === null) out2(" fill in the plan's `reason` (the mandatory audit justification) before apply.");
3690
+ out2(" apply requires the ROOT CUSTODIAN seed. The blessed command:");
3691
+ out2(` githolon rebirth apply --plan ${join4(dir, "plan.json")} --gcp-secret ${ROOT_CUSTODIAN_SECRET} [--yes]`);
3692
+ out2(" (--seed-secret <b64> is break-glass \u2014 avoid in shell history; env NOMOS_ROOT_SEED is the CI lane.)");
3479
3693
  return 0;
3480
3694
  }
3481
3695
  async function rebirthWorkspace(ws, opts) {
@@ -3503,9 +3717,12 @@ async function rebirthWorkspace(ws, opts) {
3503
3717
  err2("the law refuses to rebirth root \u2014 the seat of the authorizing law cannot supersede itself");
3504
3718
  return 1;
3505
3719
  }
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;
3720
+ if (opts.plan !== void 0 && Array.isArray(opts.plan.repairs)) {
3721
+ const unknown = opts.plan.repairs.find((r2) => r2.execution !== "recorded");
3722
+ if (unknown !== void 0) {
3723
+ err2(`the plan carries a repair with an unsupported execution '${String(unknown.execution)}' \u2014 v1 executes only execution:"recorded" (state-transform verbs land in a future release)`);
3724
+ return 1;
3725
+ }
3509
3726
  }
3510
3727
  let seed = opts.seedSecret ?? process.env["NOMOS_ROOT_SEED"];
3511
3728
  if (seed === void 0 && opts.gcpSecret !== void 0) {
@@ -3518,7 +3735,7 @@ async function rebirthWorkspace(ws, opts) {
3518
3735
  }
3519
3736
  }
3520
3737
  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>");
3738
+ err2(`gov rebirth needs the ROOT CUSTODIAN seed \u2014 the blessed path is --gcp-secret ${ROOT_CUSTODIAN_SECRET}; --seed-secret <b64> is break-glass (avoid in shell history), env NOMOS_ROOT_SEED is the CI lane`);
3522
3739
  return 1;
3523
3740
  }
3524
3741
  const cloud = cloudBase(opts.cloud);
@@ -3628,8 +3845,11 @@ function validatePlanForApply(plan, liveIncarnation) {
3628
3845
  if (plan.reason === null || typeof plan.reason === "string" && plan.reason.trim() === "") {
3629
3846
  return { error: "the plan's `reason` is still null \u2014 fill it in (the mandatory audit justification) before apply" };
3630
3847
  }
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" };
3848
+ if (Array.isArray(plan.repairs)) {
3849
+ const bad = plan.repairs.find((r) => r.execution !== "recorded");
3850
+ if (bad !== void 0) {
3851
+ return { error: `the plan carries a repair with an unsupported execution '${String(bad.execution)}' \u2014 this CLI executes only execution:"recorded" (state-transform verbs land in a future release)` };
3852
+ }
3633
3853
  }
3634
3854
  if (plan.pinned.incarnation !== null) {
3635
3855
  if (liveIncarnation === void 0) {
@@ -3643,6 +3863,7 @@ function validatePlanForApply(plan, liveIncarnation) {
3643
3863
  }
3644
3864
  function buildCertificate(args) {
3645
3865
  const { plan } = args;
3866
+ const childNames = plan.children.map((c) => c.name);
3646
3867
  return {
3647
3868
  v: 1,
3648
3869
  plan,
@@ -3651,12 +3872,17 @@ function buildCertificate(args) {
3651
3872
  custodian: args.custodian,
3652
3873
  oldIncarnation: args.oldIncarnation,
3653
3874
  newIncarnation: args.newIncarnation,
3875
+ oldHead: args.oldHead ?? args.oldIncarnation,
3876
+ newHead: args.newHead ?? args.newIncarnation,
3877
+ oldCustodyAddress: plan.will.frozenAt,
3654
3878
  newCustodyAddress: plan.will.newCustodyAddress,
3655
3879
  carried: plan.compaction.carried,
3656
3880
  parked: plan.compaction.parked,
3657
3881
  verdictBefore: args.verdictBefore,
3658
3882
  ...args.firstRefusal ? { firstRefusal: args.firstRefusal } : {},
3659
- verdictAfter: args.verdictAfter
3883
+ verdictAfter: args.verdictAfter,
3884
+ activeLawAfter: args.activeLawAfter ?? {},
3885
+ childrenCarried: { count: childNames.length, names: childNames }
3660
3886
  },
3661
3887
  supersessionFacts: {
3662
3888
  supersededBy: plan.will.newCustodyAddress,
@@ -3665,6 +3891,7 @@ function buildCertificate(args) {
3665
3891
  custodian: args.custodian,
3666
3892
  at: args.at
3667
3893
  },
3894
+ repairs: Array.isArray(plan.repairs) ? plan.repairs : [],
3668
3895
  ...args.repair !== void 0 ? { repair: args.repair } : {}
3669
3896
  };
3670
3897
  }
@@ -3684,6 +3911,14 @@ async function verifyWorkspaceVerdict(cloud, ws) {
3684
3911
  return { replay: "unknown", firstRefusal: null };
3685
3912
  }
3686
3913
  }
3914
+ async function currentLawOf(cloud, ws) {
3915
+ try {
3916
+ const d = await (await fetch(`${cloud}/v2/workspaces/${ws}/domains`)).json();
3917
+ return d.currentLaw ?? {};
3918
+ } catch {
3919
+ return {};
3920
+ }
3921
+ }
3687
3922
  async function liveIncarnationOf(cloud, ws) {
3688
3923
  try {
3689
3924
  const s = await (await fetch(`${cloud}/v2/workspaces/${ws}`)).json();
@@ -3695,7 +3930,7 @@ async function liveIncarnationOf(cloud, ws) {
3695
3930
  async function rebirthApply(planPath, opts) {
3696
3931
  let plan;
3697
3932
  try {
3698
- plan = JSON.parse(readFileSync2(planPath, "utf8"));
3933
+ plan = JSON.parse(readFileSync3(planPath, "utf8"));
3699
3934
  } catch (e) {
3700
3935
  err2(`cannot read the plan ${planPath}: ${e.message}`);
3701
3936
  return 1;
@@ -3730,9 +3965,11 @@ async function rebirthApply(planPath, opts) {
3730
3965
  }
3731
3966
  const verdictBefore = plan.verdict.replay === "green" ? "green" : "red";
3732
3967
  const custodian = opts.principal ?? activePrincipal() ?? "root-custodian";
3968
+ const repairIds = (plan.repairs ?? []).map((r) => r.id);
3969
+ const effectiveReason = repairIds.length ? `${plan.reason ?? ""} ${repairIds.map((id) => `[repair:${id}]`).join(" ")}`.trim() : plan.reason ?? void 0;
3733
3970
  const code = await rebirthWorkspace(ws, {
3734
3971
  ...opts,
3735
- reason: plan.reason ?? void 0,
3972
+ reason: effectiveReason,
3736
3973
  plan,
3737
3974
  quiet: true,
3738
3975
  yes: true
@@ -3743,19 +3980,21 @@ async function rebirthApply(planPath, opts) {
3743
3980
  }
3744
3981
  const newIncarnation = await liveIncarnationOf(cloud, ws) ?? null;
3745
3982
  const verdictAfter = await verifyWorkspaceVerdict(cloud, ws);
3983
+ const activeLawAfter = await currentLawOf(cloud, ws);
3746
3984
  const cert = buildCertificate({
3747
3985
  plan,
3748
3986
  custodian,
3749
3987
  at: (/* @__PURE__ */ new Date()).toISOString(),
3750
3988
  oldIncarnation: plan.pinned.incarnation,
3751
3989
  newIncarnation,
3990
+ activeLawAfter,
3752
3991
  verdictBefore,
3753
3992
  ...plan.verdict.firstRefusal ? { firstRefusal: plan.verdict.firstRefusal } : {},
3754
3993
  verdictAfter
3755
3994
  });
3756
- const certPath = join3(dirname2(planPath), "certificate.json");
3995
+ const certPath = join4(dirname3(planPath), "certificate.json");
3757
3996
  try {
3758
- writeFileSync3(certPath, JSON.stringify(cert, null, 2) + "\n");
3997
+ writeFileSync4(certPath, JSON.stringify(cert, null, 2) + "\n");
3759
3998
  } catch (e) {
3760
3999
  err2(`the rebirth succeeded but the certificate could not be written to ${certPath}: ${e.message}`);
3761
4000
  return 1;
@@ -3806,12 +4045,14 @@ async function executeRepairRebirth(cloud, ws, repair, verdict, opts) {
3806
4045
  }
3807
4046
  const newIncarnation = await liveIncarnationOf(cloudBaseUrl, ws) ?? null;
3808
4047
  const verdictAfter = await verifyWorkspaceVerdict(cloudBaseUrl, ws);
4048
+ const activeLawAfter = await currentLawOf(cloudBaseUrl, ws);
3809
4049
  const cert = buildCertificate({
3810
4050
  plan,
3811
4051
  custodian,
3812
4052
  at: (/* @__PURE__ */ new Date()).toISOString(),
3813
4053
  oldIncarnation: plan.pinned.incarnation,
3814
4054
  newIncarnation,
4055
+ activeLawAfter,
3815
4056
  verdictBefore,
3816
4057
  firstRefusal,
3817
4058
  verdictAfter,
@@ -3822,9 +4063,9 @@ async function executeRepairRebirth(cloud, ws, repair, verdict, opts) {
3822
4063
  note: "repair verb recorded; state transform verbs land in a future release (v1 rebirth only)"
3823
4064
  }
3824
4065
  });
3825
- const certPath = join3(dirname2(repair.file), "certificate.json");
4066
+ const certPath = join4(dirname3(repair.file), "certificate.json");
3826
4067
  try {
3827
- writeFileSync3(certPath, JSON.stringify(cert, null, 2) + "\n");
4068
+ writeFileSync4(certPath, JSON.stringify(cert, null, 2) + "\n");
3828
4069
  } catch (e) {
3829
4070
  err2(`the repair rebirth succeeded but the certificate could not be written to ${certPath}: ${e.message}`);
3830
4071
  return 1;
@@ -3844,13 +4085,14 @@ function readSealedIntentBytes(eng, ws, intentOut) {
3844
4085
  if (f?.data === void 0) return void 0;
3845
4086
  return Buffer.from(f.data).toString("base64");
3846
4087
  }
3847
- var out2, err2, CLIENT_IMPACT;
4088
+ var out2, err2, ROOT_CUSTODIAN_SECRET, CLIENT_IMPACT;
3848
4089
  var init_governance = __esm({
3849
4090
  "src/governance.ts"() {
3850
4091
  "use strict";
3851
4092
  init_cloud();
3852
4093
  out2 = (s) => void process.stdout.write(s + "\n");
3853
4094
  err2 = (s) => void process.stderr.write("error: " + s + "\n");
4095
+ ROOT_CUSTODIAN_SECRET = "nomos-root-custodian-key";
3854
4096
  CLIENT_IMPACT = "every connected client raises CustodyBreak(superseded); unsynced client work is invisible to the cloud \u2014 drain/sync clients first";
3855
4097
  }
3856
4098
  });
@@ -3874,7 +4116,7 @@ __export(lifecycle_exports, {
3874
4116
  signingAvailable: () => signingAvailable
3875
4117
  });
3876
4118
  import { createHash as createHash2 } from "node:crypto";
3877
- import { readFileSync as readFileSync3 } from "node:fs";
4119
+ import { readFileSync as readFileSync4 } from "node:fs";
3878
4120
  async function fetchInstalledLaw(cloud, ws) {
3879
4121
  try {
3880
4122
  const r = await fetch(`${cloud}/v2/workspaces/${ws}/domains`);
@@ -3897,7 +4139,7 @@ async function fetchInstalledPackage(cloud, ws, hash) {
3897
4139
  function readDeployBody(file) {
3898
4140
  let body;
3899
4141
  try {
3900
- body = JSON.parse(readFileSync3(file, "utf8"));
4142
+ body = JSON.parse(readFileSync4(file, "utf8"));
3901
4143
  } catch (e) {
3902
4144
  throw new Error(`deploy body ${file} is not valid JSON \u2014 recompile (githolon compile): ${e.message}`);
3903
4145
  }
@@ -4197,9 +4439,9 @@ __export(cloud_exports, {
4197
4439
  wsRetire: () => wsRetire,
4198
4440
  wsStatus: () => wsStatus
4199
4441
  });
4200
- import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
4442
+ import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync4, readdirSync as readdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
4201
4443
  import { createHash as createHash3 } from "node:crypto";
4202
- import { join as join4 } from "node:path";
4444
+ import { join as join5 } from "node:path";
4203
4445
  import { homedir } from "node:os";
4204
4446
  function cloudBase(flag) {
4205
4447
  return (flag ?? process.env["NOMOS_CLOUD"] ?? DEFAULT_CLOUD).replace(/\/+$/, "");
@@ -4211,18 +4453,18 @@ function authAnonKey() {
4211
4453
  return process.env["HOLON_AUTH_ANON_KEY"] ?? DEFAULT_AUTH_ANON_KEY;
4212
4454
  }
4213
4455
  function configDir() {
4214
- return process.env["HOLON_CONFIG_DIR"] ?? join4(homedir(), ".holon");
4456
+ return process.env["HOLON_CONFIG_DIR"] ?? join5(homedir(), ".holon");
4215
4457
  }
4216
4458
  function credsPath() {
4217
- return join4(configDir(), "credentials.json");
4459
+ return join5(configDir(), "credentials.json");
4218
4460
  }
4219
4461
  function loadCreds() {
4220
- if (!existsSync3(credsPath())) return { version: 1, secrets: {} };
4221
- return JSON.parse(readFileSync4(credsPath(), "utf8"));
4462
+ if (!existsSync4(credsPath())) return { version: 1, secrets: {} };
4463
+ return JSON.parse(readFileSync5(credsPath(), "utf8"));
4222
4464
  }
4223
4465
  function saveCreds(c) {
4224
4466
  mkdirSync4(configDir(), { recursive: true });
4225
- writeFileSync4(credsPath(), JSON.stringify(c, null, 2) + "\n", "utf8");
4467
+ writeFileSync5(credsPath(), JSON.stringify(c, null, 2) + "\n", "utf8");
4226
4468
  chmodSync(credsPath(), 384);
4227
4469
  }
4228
4470
  function getSecret(cloud, ws) {
@@ -4337,21 +4579,21 @@ async function sessionToken() {
4337
4579
  }
4338
4580
  function discoverDeployJson(cwd, explicit) {
4339
4581
  if (explicit !== void 0) {
4340
- if (!existsSync3(explicit)) throw new Error(`deploy body not found: ${explicit}`);
4582
+ if (!existsSync4(explicit)) throw new Error(`deploy body not found: ${explicit}`);
4341
4583
  return explicit;
4342
4584
  }
4343
- const buildDir = join4(cwd, "build");
4344
- if (!existsSync3(buildDir)) {
4585
+ const buildDir = join5(cwd, "build");
4586
+ if (!existsSync4(buildDir)) {
4345
4587
  throw new Error("no build/ directory \u2014 run `githolon compile` first (or pass --file <path>)");
4346
4588
  }
4347
- const bodies = readdirSync2(buildDir).filter((f) => f.endsWith(".deploy.json"));
4589
+ const bodies = readdirSync3(buildDir).filter((f) => f.endsWith(".deploy.json"));
4348
4590
  if (bodies.length === 0) {
4349
4591
  throw new Error("no build/*.deploy.json \u2014 run `githolon compile` first (or pass --file <path>)");
4350
4592
  }
4351
4593
  if (bodies.length > 1) {
4352
4594
  throw new Error(`multiple deploy bodies in build/ (${bodies.join(", ")}) \u2014 pass --file <path>`);
4353
4595
  }
4354
- return join4(buildDir, bodies[0]);
4596
+ return join5(buildDir, bodies[0]);
4355
4597
  }
4356
4598
  async function login(opts) {
4357
4599
  if (opts.agent !== true && opts.token === void 0) {
@@ -4578,7 +4820,7 @@ async function deploy2(ws, opts) {
4578
4820
  if (signed) {
4579
4821
  let body;
4580
4822
  try {
4581
- body = JSON.parse(readFileSync4(file, "utf8"));
4823
+ body = JSON.parse(readFileSync5(file, "utf8"));
4582
4824
  } catch (e) {
4583
4825
  err4(`deploy body ${file} is not valid JSON \u2014 recompile: ${e.message}`);
4584
4826
  return 1;
@@ -4617,7 +4859,7 @@ async function deploy2(ws, opts) {
4617
4859
  const r = await fetch(`${cloud}/v2/workspaces/${ws}/domains`, {
4618
4860
  method: "POST",
4619
4861
  headers: { "content-type": "application/json" },
4620
- body: readFileSync4(file, "utf8")
4862
+ body: readFileSync5(file, "utf8")
4621
4863
  });
4622
4864
  const d = await r.json().catch(() => void 0);
4623
4865
  if (!r.ok || d?.ok !== true) {
@@ -4711,27 +4953,27 @@ __export(editor_exports, {
4711
4953
  initEditor: () => initEditor,
4712
4954
  writeEditorRecommendation: () => writeEditorRecommendation
4713
4955
  });
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";
4956
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
4957
+ import { dirname as dirname4, join as join6 } from "node:path";
4716
4958
  function hasEditorRecommendation(cwd) {
4717
- const p = join5(cwd, ".vscode", "extensions.json");
4718
- if (!existsSync4(p)) return false;
4959
+ const p = join6(cwd, ".vscode", "extensions.json");
4960
+ if (!existsSync5(p)) return false;
4719
4961
  try {
4720
- const json = JSON.parse(readFileSync5(p, "utf8"));
4962
+ const json = JSON.parse(readFileSync6(p, "utf8"));
4721
4963
  return Array.isArray(json.recommendations) && json.recommendations.includes(NOMOS_LAW_EXTENSION_ID);
4722
4964
  } catch {
4723
4965
  return true;
4724
4966
  }
4725
4967
  }
4726
4968
  function writeEditorRecommendation(cwd) {
4727
- const dir = join5(cwd, ".vscode");
4728
- const path = join5(dir, "extensions.json");
4969
+ const dir = join6(cwd, ".vscode");
4970
+ const path = join6(dir, "extensions.json");
4729
4971
  let json = {};
4730
4972
  let existed = false;
4731
- if (existsSync4(path)) {
4973
+ if (existsSync5(path)) {
4732
4974
  existed = true;
4733
4975
  try {
4734
- const parsed = JSON.parse(readFileSync5(path, "utf8"));
4976
+ const parsed = JSON.parse(readFileSync6(path, "utf8"));
4735
4977
  if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
4736
4978
  json = parsed;
4737
4979
  } else {
@@ -4749,8 +4991,8 @@ function writeEditorRecommendation(cwd) {
4749
4991
  }
4750
4992
  recs.push(NOMOS_LAW_EXTENSION_ID);
4751
4993
  json.recommendations = recs;
4752
- mkdirSync5(dirname3(path), { recursive: true });
4753
- writeFileSync5(path, JSON.stringify(json, null, 2) + "\n", "utf8");
4994
+ mkdirSync5(dirname4(path), { recursive: true });
4995
+ writeFileSync6(path, JSON.stringify(json, null, 2) + "\n", "utf8");
4754
4996
  return { path, action: existed ? "updated" : "created" };
4755
4997
  }
4756
4998
  function initEditor(cwd = process.cwd()) {
@@ -4784,21 +5026,21 @@ var init_editor = __esm({
4784
5026
  });
4785
5027
 
4786
5028
  // src/compile.ts
4787
- import { spawn, spawnSync } from "node:child_process";
4788
- import { createRequire } from "node:module";
4789
- import { dirname as dirname4, join as join6 } from "node:path";
4790
- import { pathToFileURL } from "node:url";
5029
+ import { spawn, spawnSync as spawnSync2 } from "node:child_process";
5030
+ import { createRequire as createRequire2 } from "node:module";
5031
+ import { dirname as dirname5, join as join7 } from "node:path";
5032
+ import { pathToFileURL as pathToFileURL2 } from "node:url";
4791
5033
  function resolveCompileLauncher(cwd) {
4792
5034
  const resolveDslPkg = (fromDir) => {
4793
5035
  try {
4794
- const req = fromDir === void 0 ? createRequire(import.meta.url) : createRequire(pathToFileURL(join6(fromDir, "noop.js")));
5036
+ const req = fromDir === void 0 ? createRequire2(import.meta.url) : createRequire2(pathToFileURL2(join7(fromDir, "noop.js")));
4795
5037
  return req.resolve("@githolon/dsl/package.json");
4796
5038
  } catch {
4797
5039
  return void 0;
4798
5040
  }
4799
5041
  };
4800
5042
  const dslPkg = resolveDslPkg(cwd) ?? resolveDslPkg(void 0);
4801
- return dslPkg === void 0 ? void 0 : join6(dirname4(dslPkg), "compile_package.mjs");
5043
+ return dslPkg === void 0 ? void 0 : join7(dirname5(dslPkg), "compile_package.mjs");
4802
5044
  }
4803
5045
  function runCompile(args) {
4804
5046
  const launcher = resolveCompileLauncher(process.cwd());
@@ -4807,7 +5049,7 @@ function runCompile(args) {
4807
5049
  `);
4808
5050
  return 1;
4809
5051
  }
4810
- const r = spawnSync(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
5052
+ const r = spawnSync2(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
4811
5053
  const status2 = r.status ?? 1;
4812
5054
  if (status2 === 0 && process.stdout.isTTY) {
4813
5055
  try {
@@ -4821,7 +5063,7 @@ ${INIT_EDITOR_HINT}
4821
5063
  }
4822
5064
  function resolveCheckLauncher(cwd) {
4823
5065
  const launcher = resolveCompileLauncher(cwd);
4824
- return launcher === void 0 ? void 0 : join6(dirname4(launcher), "check_package.mjs");
5066
+ return launcher === void 0 ? void 0 : join7(dirname5(launcher), "check_package.mjs");
4825
5067
  }
4826
5068
  function runCheck(args) {
4827
5069
  const launcher = resolveCheckLauncher(process.cwd());
@@ -4830,12 +5072,12 @@ function runCheck(args) {
4830
5072
  `);
4831
5073
  return 1;
4832
5074
  }
4833
- const r = spawnSync(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
5075
+ const r = spawnSync2(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
4834
5076
  return r.status ?? 1;
4835
5077
  }
4836
5078
  function resolveCompatLauncher(cwd) {
4837
5079
  const launcher = resolveCompileLauncher(cwd);
4838
- return launcher === void 0 ? void 0 : join6(dirname4(launcher), "compat_package.mjs");
5080
+ return launcher === void 0 ? void 0 : join7(dirname5(launcher), "compat_package.mjs");
4839
5081
  }
4840
5082
  function runCompat(args) {
4841
5083
  const launcher = resolveCompatLauncher(process.cwd());
@@ -4844,12 +5086,12 @@ function runCompat(args) {
4844
5086
  `);
4845
5087
  return 1;
4846
5088
  }
4847
- const r = spawnSync(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
5089
+ const r = spawnSync2(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
4848
5090
  return r.status ?? 1;
4849
5091
  }
4850
5092
  function resolveLspLauncher(cwd) {
4851
5093
  const launcher = resolveCompileLauncher(cwd);
4852
- return launcher === void 0 ? void 0 : join6(dirname4(launcher), "lsp_server.mjs");
5094
+ return launcher === void 0 ? void 0 : join7(dirname5(launcher), "lsp_server.mjs");
4853
5095
  }
4854
5096
  function runLsp(args) {
4855
5097
  const launcher = resolveLspLauncher(process.cwd());
@@ -4858,7 +5100,7 @@ function runLsp(args) {
4858
5100
  `);
4859
5101
  return 1;
4860
5102
  }
4861
- const r = spawnSync(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
5103
+ const r = spawnSync2(process.execPath, [launcher, ...args], { stdio: "inherit", cwd: process.cwd() });
4862
5104
  return r.status ?? 1;
4863
5105
  }
4864
5106
  function compileAsync(cwd, args = []) {
@@ -4898,8 +5140,8 @@ __export(proof_offline_exports, {
4898
5140
  runOfflineProofStandalone: () => runOfflineProofStandalone,
4899
5141
  runRelationBootstrapLeg: () => runRelationBootstrapLeg
4900
5142
  });
4901
- import { existsSync as existsSync6, readFileSync as readFileSync6 } from "node:fs";
4902
- import { basename, dirname as dirname5, join as join8 } from "node:path";
5143
+ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
5144
+ import { basename, dirname as dirname6, join as join9 } from "node:path";
4903
5145
  function parseOfflineLegs(proofSource) {
4904
5146
  if (!proofSource.includes("AUTO-GENERATED by nomos-compile")) {
4905
5147
  throw new Error("not a generated proof (missing the AUTO-GENERATED header) \u2014 run `githolon compile` to (re)generate build/<name>.proof.mts");
@@ -5324,16 +5566,16 @@ function actorFromPayload(payload, field) {
5324
5566
  return typeof value === "string" && value.trim().length > 0 ? value : void 0;
5325
5567
  }
5326
5568
  async function runOfflineProofStandalone(proofPath, cloud, domain) {
5327
- const src = readFileSync6(proofPath, "utf8");
5569
+ const src = readFileSync7(proofPath, "utf8");
5328
5570
  const packageName = basename(proofPath).replace(/\.proof\.mts$/, "");
5329
- const deployFile = join8(dirname5(proofPath), `${packageName}.deploy.json`);
5330
- if (!existsSync6(deployFile)) {
5571
+ const deployFile = join9(dirname6(proofPath), `${packageName}.deploy.json`);
5572
+ if (!existsSync7(deployFile)) {
5331
5573
  throw new Error(`missing ${deployFile} \u2014 run \`githolon compile\` (the proof and the deploy body are built together)`);
5332
5574
  }
5333
5575
  let legs;
5334
- const legsFile = join8(dirname5(proofPath), `${packageName}.proof-legs.json`);
5335
- if (existsSync6(legsFile)) {
5336
- const index = JSON.parse(readFileSync6(legsFile, "utf8"));
5576
+ const legsFile = join9(dirname6(proofPath), `${packageName}.proof-legs.json`);
5577
+ if (existsSync7(legsFile)) {
5578
+ const index = JSON.parse(readFileSync7(legsFile, "utf8"));
5337
5579
  const keys = Object.keys(index.domains);
5338
5580
  const chosen = domain ?? index.default;
5339
5581
  if (index.domains[chosen] === void 0) {
@@ -5351,7 +5593,7 @@ async function runOfflineProofStandalone(proofPath, cloud, domain) {
5351
5593
  if (domain !== void 0) throw new Error(`--domain needs a per-domain legs index (build/${packageName}.proof-legs.json) \u2014 recompile with \`githolon compile\` to emit it`);
5352
5594
  legs = parseOfflineLegs(src);
5353
5595
  }
5354
- const deployBody = JSON.parse(readFileSync6(deployFile, "utf8"));
5596
+ const deployBody = JSON.parse(readFileSync7(deployFile, "utf8"));
5355
5597
  const lawHash = await sha256hex(deployBody.packageUsda);
5356
5598
  console.log(`githolon proof \u2014 OFFLINE legs on a local holon (the cloud loop: githolon proof --live)`);
5357
5599
  const { eng } = await holonEngine(cloud, deployBody, "githolon-proof");
@@ -5378,147 +5620,6 @@ var init_proof_offline = __esm({
5378
5620
  }
5379
5621
  });
5380
5622
 
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
-
5522
5623
  // src/mcp.ts
5523
5624
  var mcp_exports = {};
5524
5625
  __export(mcp_exports, {
@@ -7258,20 +7359,20 @@ init_engine();
7258
7359
  init_cloud();
7259
7360
  init_compile();
7260
7361
  init_local_holon();
7261
- import { existsSync as existsSync7, readFileSync as readFileSync7, watch } from "node:fs";
7362
+ import { existsSync as existsSync8, readFileSync as readFileSync8, watch } from "node:fs";
7262
7363
  import { createServer } from "node:http";
7263
- import { dirname as dirname6, join as join9, resolve } from "node:path";
7264
- import { pathToFileURL as pathToFileURL3 } from "node:url";
7364
+ import { dirname as dirname7, join as join10, resolve as resolve2 } from "node:path";
7365
+ import { pathToFileURL as pathToFileURL4 } from "node:url";
7265
7366
 
7266
7367
  // src/project.ts
7267
- import { existsSync as existsSync5, statSync as statSync2 } from "node:fs";
7268
- import { join as join7 } from "node:path";
7269
- import { pathToFileURL as pathToFileURL2 } from "node:url";
7368
+ import { existsSync as existsSync6, statSync as statSync2 } from "node:fs";
7369
+ import { join as join8 } from "node:path";
7370
+ import { pathToFileURL as pathToFileURL3 } from "node:url";
7270
7371
  var CONFIG_FILE = "nomos.package.mjs";
7271
7372
  async function loadProject(cwd, opts = {}) {
7272
- const configPath = join7(cwd, CONFIG_FILE);
7273
- if (!existsSync5(configPath)) return void 0;
7274
- const href = pathToFileURL2(configPath).href + (opts.bust === true ? `?v=${statSync2(configPath).mtimeMs}-${Date.now()}` : "");
7373
+ const configPath = join8(cwd, CONFIG_FILE);
7374
+ if (!existsSync6(configPath)) return void 0;
7375
+ const href = pathToFileURL3(configPath).href + (opts.bust === true ? `?v=${statSync2(configPath).mtimeMs}-${Date.now()}` : "");
7275
7376
  const mod = await import(href);
7276
7377
  const cfg = mod.default;
7277
7378
  if (cfg === void 0 || typeof cfg.name !== "string" || cfg.name.length === 0) {
@@ -7435,11 +7536,11 @@ function startServer(s) {
7435
7536
  });
7436
7537
  }
7437
7538
  function readDeployBody2(cwd, packageName) {
7438
- const file = join9(cwd, "build", `${packageName}.deploy.json`);
7439
- if (!existsSync7(file)) {
7539
+ const file = join10(cwd, "build", `${packageName}.deploy.json`);
7540
+ if (!existsSync8(file)) {
7440
7541
  throw new Error(`compile produced no ${file} \u2014 check the compile output above`);
7441
7542
  }
7442
- return JSON.parse(readFileSync7(file, "utf8"));
7543
+ return JSON.parse(readFileSync8(file, "utf8"));
7443
7544
  }
7444
7545
  async function installLaw(s, deployBody, installedBy) {
7445
7546
  const newHash = await sha256hex(deployBody.packageUsda);
@@ -7455,11 +7556,11 @@ async function installLaw(s, deployBody, installedBy) {
7455
7556
  return { ok: true };
7456
7557
  }
7457
7558
  async function runProofCycle(s, cwd, deployBody, installedBy) {
7458
- const proofPath = join9(cwd, "build", `${s.packageName}.proof.mts`);
7459
- if (!existsSync7(proofPath)) return void 0;
7559
+ const proofPath = join10(cwd, "build", `${s.packageName}.proof.mts`);
7560
+ if (!existsSync8(proofPath)) return void 0;
7460
7561
  const scratch = `proof-${s.cycle}`;
7461
7562
  try {
7462
- const legs = parseOfflineLegs(readFileSync7(proofPath, "utf8"));
7563
+ const legs = parseOfflineLegs(readFileSync8(proofPath, "utf8"));
7463
7564
  await mountFresh(s.eng, scratch);
7464
7565
  author(s.eng, scratch, "bootstrap", "installDomain", installPayload(s.eng.hashes.nomos, s.eng.nomosPkg, installedBy), "");
7465
7566
  author(s.eng, scratch, "nomos", "installDomain", installPayload(s.lawHash, deployBody.packageUsda, installedBy), s.eng.hashes.nomos);
@@ -7478,7 +7579,7 @@ async function dev(opts) {
7478
7579
  return void 0;
7479
7580
  });
7480
7581
  if (project === void 0) {
7481
- if (!existsSync7(join9(cwd, CONFIG_FILE))) {
7582
+ if (!existsSync8(join10(cwd, CONFIG_FILE))) {
7482
7583
  err5(`no ${CONFIG_FILE} here (${cwd}) \u2014 \`githolon dev\` runs inside a project; scaffold one from examples/guestbook or \`githolon generate domain <name>\``);
7483
7584
  }
7484
7585
  return 1;
@@ -7543,14 +7644,14 @@ ${firstCompile.output}`);
7543
7644
  }
7544
7645
  const moduleDirs = /* @__PURE__ */ new Set();
7545
7646
  try {
7546
- const cfgModule = await import(pathToFileURL3(project.configPath).href);
7647
+ const cfgModule = await import(pathToFileURL4(project.configPath).href);
7547
7648
  for (const d of cfgModule.default?.domains ?? []) {
7548
- for (const m of d.modules ?? []) moduleDirs.add(dirname6(resolve(cwd, m)));
7649
+ for (const m of d.modules ?? []) moduleDirs.add(dirname7(resolve2(cwd, m)));
7549
7650
  }
7550
7651
  } catch {
7551
- moduleDirs.add(join9(cwd, "domains"));
7652
+ moduleDirs.add(join10(cwd, "domains"));
7552
7653
  }
7553
- if (moduleDirs.size === 0) moduleDirs.add(join9(cwd, "domains"));
7654
+ if (moduleDirs.size === 0) moduleDirs.add(join10(cwd, "domains"));
7554
7655
  let timer;
7555
7656
  let cycling = false;
7556
7657
  let queued = false;
@@ -7600,7 +7701,7 @@ ${run.output}`);
7600
7701
  };
7601
7702
  const watchers = [];
7602
7703
  for (const d of moduleDirs) {
7603
- if (!existsSync7(d)) continue;
7704
+ if (!existsSync8(d)) continue;
7604
7705
  watchers.push(watch(d, { recursive: true }, (_evt, f) => onChange(f)));
7605
7706
  s.watchRoots.push(d.startsWith(cwd) ? d.slice(cwd.length + 1) + "/" : d);
7606
7707
  }
@@ -7625,13 +7726,13 @@ ${run.output}`);
7625
7726
 
7626
7727
  // src/git.ts
7627
7728
  init_cloud();
7628
- import { spawnSync as spawnSync2 } from "node:child_process";
7729
+ import { spawnSync as spawnSync3 } from "node:child_process";
7629
7730
  import { randomBytes as randomBytes2 } from "node:crypto";
7630
- import { readFileSync as readFileSync8 } from "node:fs";
7731
+ import { readFileSync as readFileSync9 } from "node:fs";
7631
7732
  var out6 = (s) => void process.stdout.write(s + "\n");
7632
7733
  var err6 = (s) => void process.stderr.write("error: " + s + "\n");
7633
7734
  function git(args, opts = {}) {
7634
- const r = spawnSync2("git", args, { stdio: opts.quiet === true ? "ignore" : "inherit" });
7735
+ const r = spawnSync3("git", args, { stdio: opts.quiet === true ? "ignore" : "inherit" });
7635
7736
  return r.status ?? 1;
7636
7737
  }
7637
7738
  function ensureSecret(cloud, ws) {
@@ -7656,7 +7757,7 @@ function workspaceFromPath(path) {
7656
7757
  }
7657
7758
  async function gitCredential(action) {
7658
7759
  if (action !== "get") return 0;
7659
- const kv = parseCredentialInput(readFileSync8(0, "utf8"));
7760
+ const kv = parseCredentialInput(readFileSync9(0, "utf8"));
7660
7761
  const ws = workspaceFromPath(kv["path"]);
7661
7762
  if (kv["protocol"] !== "https" || ws === void 0) return 0;
7662
7763
  const cloud = `https://${kv["host"]}`;
@@ -7878,6 +7979,23 @@ var HELP = {
7878
7979
  "githolon gov relay root co2.offer.json"
7879
7980
  ]
7880
7981
  },
7982
+ rebirth: {
7983
+ usage: "githolon rebirth plan <ws> [--reason <text>] [--out <dir>]\n githolon rebirth apply --plan <plan.json> --gcp-secret nomos-root-custodian-key [--yes]",
7984
+ what: "LAWFUL SUPERSESSION as code (the migrations-folder workflow; architecture/rebirth_and_custody_lifecycle.md).\n`plan` writes a read-only, drift-pinned plan.json + impact.md into rebirths/<date>-<ws>/ \u2014 the reviewable\nintent (pinned incarnation, law lifecycle, children, verdict, and any MATCHED repairs from repairs/*.ts).\n`apply` drives the reviewed plan through the signed rebirth path \u2192 certificate.json beside it.\nAPPLY REQUIRES THE ROOT CUSTODIAN SEED \u2014 the blessed path is --gcp-secret nomos-root-custodian-key;\n--seed-secret <b64> is break-glass (avoid in shell history), env NOMOS_ROOT_SEED is the CI lane.\n\nTHE BLESSED GOLDEN PATH:\n 1. githolon rebirth plan <ws>\n 2. githolon rebirth apply --plan <path> --gcp-secret nomos-root-custodian-key [--yes]\n 3. githolon replay <ws> (expect GREEN from intent 0)\n 4. githolon status <ws> (incarnation + supersession history)\n 5. githolon compat (clients raise CustodyBreak \u2014 choose adopt/reject)",
7985
+ flags: [
7986
+ ["--reason <text>", "the mandatory audit justification (fill it into the plan before apply)"],
7987
+ ["--out <dir>", "plan: an alternate output dir (default: rebirths/<date>-<ws>)"],
7988
+ ["--plan <plan.json>", "apply: the reviewed plan file to execute (drift-pinned)"],
7989
+ ["--gcp-secret <name>", "apply: read the root custodian seed from this GCP secret (blessed: nomos-root-custodian-key)"],
7990
+ ["--seed-secret <b64>", "apply: break-glass \u2014 the seed inline (avoid in shell history)"],
7991
+ ["--yes", "apply: skip the interactive confirm"],
7992
+ ["--cloud <url>", "target cloud"]
7993
+ ],
7994
+ examples: [
7995
+ "githolon rebirth plan co2-platform --reason 'evolve-gate scar at intent 74'",
7996
+ "githolon rebirth apply --plan rebirths/2026-07-09-co2-platform/plan.json --gcp-secret nomos-root-custodian-key --yes"
7997
+ ]
7998
+ },
7881
7999
  grant: {
7882
8000
  usage: "githolon grant <admin|creation|quota> <principal> [--max <N>] [--label <L>] [--parent <ws>] [--cloud <url>]",
7883
8001
  what: "Grant authority as a SIGNED governance offer to the parent (default root) \u2014 never a host\nendpoint. The grant is attributed to YOUR signing principal; only an admin's signature is\nadmitted by the far-side gate. `admin`/`creation` grant the principal-centric relation; `quota`\ngrants a per-principal workspace allowance (--max). Enroll a device key first (githolon key enroll).",
@@ -7958,15 +8076,15 @@ function commandHelp(cmd) {
7958
8076
  init_engine();
7959
8077
  init_cloud();
7960
8078
  init_local_holon();
7961
- import { spawnSync as spawnSync3 } from "node:child_process";
7962
- import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
7963
- import { join as join10 } from "node:path";
8079
+ import { spawnSync as spawnSync4 } from "node:child_process";
8080
+ import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "node:fs";
8081
+ import { join as join11 } from "node:path";
7964
8082
  var out7 = (s) => void process.stdout.write(s + "\n");
7965
8083
  var err7 = (s) => void process.stderr.write("error: " + s + "\n");
7966
8084
  var WS2 = "local";
7967
8085
  async function ledgerInit(dir, opts) {
7968
8086
  const cloud = cloudBase(opts.cloud);
7969
- if (existsSync8(dir) && readdirSync3(dir).length > 0) {
8087
+ if (existsSync9(dir) && readdirSync4(dir).length > 0) {
7970
8088
  err7(`refusing to mint into non-empty directory: ${dir}`);
7971
8089
  return 1;
7972
8090
  }
@@ -7977,7 +8095,7 @@ async function ledgerInit(dir, opts) {
7977
8095
  err7(e.message);
7978
8096
  return 1;
7979
8097
  }
7980
- const deployBody = JSON.parse(readFileSync9(deployFile, "utf8"));
8098
+ const deployBody = JSON.parse(readFileSync10(deployFile, "utf8"));
7981
8099
  const domainHash = await sha256hex(deployBody.packageUsda);
7982
8100
  const c = loadCreds();
7983
8101
  const principal = await sessionToken().catch(() => void 0) !== void 0 ? c.session.uid : c.principal;
@@ -7993,11 +8111,11 @@ async function ledgerInit(dir, opts) {
7993
8111
  const verdict = verifyChainLocal(eng, WS2);
7994
8112
  if (!printVerdict(verdict)) return 1;
7995
8113
  const gitTree = eng.preopen.dir.contents.get("ws").contents.get(WS2).contents.get("nomos.git");
7996
- const gitDir = join10(dir, ".git");
8114
+ const gitDir = join11(dir, ".git");
7997
8115
  writeTreeToDisk(gitTree, gitDir);
7998
- const cfgPath = join10(gitDir, "config");
7999
- writeFileSync6(cfgPath, readFileSync9(cfgPath, "utf8").replace(/bare = true/, "bare = false"), "utf8");
8000
- spawnSync3("git", ["-C", dir, "reset", "--hard", "main"], { stdio: "ignore" });
8116
+ const cfgPath = join11(gitDir, "config");
8117
+ writeFileSync7(cfgPath, readFileSync10(cfgPath, "utf8").replace(/bare = true/, "bare = false"), "utf8");
8118
+ spawnSync4("git", ["-C", dir, "reset", "--hard", "main"], { stdio: "ignore" });
8001
8119
  out7(`\u2713 holon written \u2192 ${dir} (a normal git repo; git log IS the audit trail)`);
8002
8120
  out7(`
8003
8121
  Birth it on Nomos Cloud (the cloud re-derives this exact verdict):`);
@@ -8005,8 +8123,8 @@ Birth it on Nomos Cloud (the cloud re-derives this exact verdict):`);
8005
8123
  return 0;
8006
8124
  }
8007
8125
  async function ledgerVerify(dir, opts) {
8008
- const gitDir = existsSync8(join10(dir, ".git")) ? join10(dir, ".git") : dir;
8009
- if (!existsSync8(join10(gitDir, "HEAD"))) {
8126
+ const gitDir = existsSync9(join11(dir, ".git")) ? join11(dir, ".git") : dir;
8127
+ if (!existsSync9(join11(gitDir, "HEAD"))) {
8010
8128
  err7(`${dir} is not a git repo (no HEAD)`);
8011
8129
  return 1;
8012
8130
  }
@@ -8480,7 +8598,8 @@ Governance (SIGNED client-side, relayed as {intentBytes} \u2014 never a host-aut
8480
8598
  githolon gov rebirth <ws> --reason <text> LAWFUL SUPERSESSION (recovery verb 3): supersede a
8481
8599
  [--dry-run [--json]] [--yes] scarred chain; --dry-run = READ-ONLY impact report
8482
8600
  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
8601
+ githolon rebirth apply --plan <plan.json> drift-pinned apply of a reviewed plan \u2192 certificate.json
8602
+ --gcp-secret nomos-root-custodian-key [--yes] (apply needs the ROOT CUSTODIAN seed; --gcp-secret is blessed)
8484
8603
  githolon replay <ws> --repair execute the repair matching a red verify (\u2192 certificate)
8485
8604
  githolon grant <admin|creation> <principal> [--label L] grant authority at the parent (default root)
8486
8605
  githolon grant quota <principal> --max <N> grant a per-principal workspace allowance
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.69.0",
3
+ "version": "0.69.2",
4
4
  "type": "module",
5
5
  "description": "githolon — the Nomos developer CLI: Rails-style generators for @githolon/dsl domains + the package compiler. Kernel-independent.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -29,8 +29,8 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@bjorn3/browser_wasi_shim": "0.4.2",
32
- "@githolon/client": "^0.69.0",
33
- "@githolon/dsl": "^0.69.0",
32
+ "@githolon/client": "^0.69.2",
33
+ "@githolon/dsl": "^0.69.2",
34
34
  "isomorphic-git": "^1.38.4"
35
35
  },
36
36
  "devDependencies": {