githolon 0.99.0 → 0.100.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -3098,6 +3098,8 @@ __export(governance_exports, {
3098
3098
  certifyEra: () => certifyEra,
3099
3099
  consentRebirth: () => consentRebirth,
3100
3100
  discoverSigningDomain: () => discoverSigningDomain,
3101
+ ensureSovereignHome: () => ensureSovereignHome,
3102
+ exchangeOnboardingToken: () => exchangeOnboardingToken,
3101
3103
  executeRepairRebirth: () => executeRepairRebirth,
3102
3104
  governanceOffer: () => governanceOffer,
3103
3105
  governanceRelay: () => governanceRelay,
@@ -3120,6 +3122,8 @@ __export(governance_exports, {
3120
3122
  resolveGovernancePrincipal: () => resolveGovernancePrincipal,
3121
3123
  signAndPostGovernance: () => signAndPostGovernance,
3122
3124
  signAndPostOffer: () => signAndPostOffer,
3125
+ signAndPostWorkspaceBirth: () => signAndPostWorkspaceBirth,
3126
+ signAndPostWorkspaceRetirement: () => signAndPostWorkspaceRetirement,
3123
3127
  validatePlanForApply: () => validatePlanForApply,
3124
3128
  verifyWorkspaceVerdict: () => verifyWorkspaceVerdict
3125
3129
  });
@@ -3195,28 +3199,239 @@ function canonicalPrincipal(principal) {
3195
3199
  return s.includes(":") ? s : `user:${s}`;
3196
3200
  }
3197
3201
  async function signAndPostOffer(ws, domain, directiveId, payload, opts) {
3202
+ return signAndPostPreparedOffer(ws, domain, () => ({ directiveId, payload }), opts);
3203
+ }
3204
+ async function signAndPostPreparedOffer(ws, domain, prepare, opts, authorMode = "account", preferActor) {
3198
3205
  const cloud = cloudBase(opts.cloud);
3199
3206
  const principal = resolveGovernancePrincipal(opts);
3200
3207
  const holon = await connectGovernance(cloud, ws);
3201
- const resolvedDomain = domain ?? await discoverSigningDomain(holon, ws, directiveId, void 0);
3202
3208
  const device = await ensureDeviceKey(holon, principal);
3209
+ const accountActor = canonicalPrincipal(principal);
3210
+ const keyActor = `key:${device.keyHash}`;
3211
+ let actor = accountActor;
3212
+ if (preferActor !== void 0 && preferActor === keyActor) {
3213
+ actor = keyActor;
3214
+ } else if (preferActor !== void 0 && sameIdentity(preferActor, accountActor)) {
3215
+ actor = accountActor;
3216
+ } else if (authorMode === "self-if-unenrolled" && typeof holon.parentSignerEnrollment === "function") {
3217
+ try {
3218
+ const posture = await holon.parentSignerEnrollment({ parent: ws, principal: accountActor, keyHash: device.keyHash });
3219
+ if (!posture.enrolled) actor = keyActor;
3220
+ } catch {
3221
+ }
3222
+ }
3223
+ const prepared = prepare(actor);
3224
+ const resolvedDomain = domain ?? await discoverSigningDomain(holon, ws, prepared.directiveId, void 0);
3203
3225
  const sealed = await holon.signGovernanceOffer({
3204
3226
  domain: resolvedDomain,
3205
- directiveId,
3206
- payload,
3227
+ directiveId: prepared.directiveId,
3228
+ payload: prepared.payload,
3207
3229
  authorSecret: device.secret,
3208
- actor: canonicalPrincipal(principal)
3230
+ actor
3209
3231
  });
3210
3232
  if (sealed.intentBytes.length > STAGE_THRESHOLD_CHARS) {
3211
- const staged = await relaySealedOfferViaStage(cloud, ws, directiveId, sealed.intentBytes, fetch);
3233
+ const staged = await relaySealedOfferViaStage(cloud, ws, prepared.directiveId, sealed.intentBytes, fetch);
3212
3234
  if (staged !== null) {
3213
3235
  out2(` staged ${staged.size} sealed bytes content-addressed (sha256 ${staged.sha256.slice(0, 16)}\u2026) \u2014 the signed offer names the hash`);
3214
- return { ...staged.verdict, principal };
3236
+ return { ...staged.verdict, principal, actor, directiveId: prepared.directiveId };
3215
3237
  }
3216
3238
  err2(`this cloud has no /v2/stage content-addressed lane \u2014 relaying the ${sealed.intentBytes.length}-char sealed offer inline (a 413 here means the worker needs upgrading to accept law this large signed)`);
3217
3239
  }
3218
- const verdict = await holon.postGovernanceOffer({ directiveId, intentBytes: sealed.intentBytes, ws, domain: resolvedDomain });
3219
- return { ...verdict, principal };
3240
+ const verdict = await holon.postGovernanceOffer({ directiveId: prepared.directiveId, intentBytes: sealed.intentBytes, ws, domain: resolvedDomain });
3241
+ return { ...verdict, principal, actor, directiveId: prepared.directiveId };
3242
+ }
3243
+ async function signAndPostWorkspaceBirth(parent, name, opts) {
3244
+ return signAndPostPreparedOffer(
3245
+ parent,
3246
+ "workspaces",
3247
+ (actor) => {
3248
+ const identity = lineageIdentity(actor);
3249
+ return {
3250
+ directiveId: "createWorkspace",
3251
+ payload: {
3252
+ name,
3253
+ tier: "edge",
3254
+ parent: parent === "root" ? "" : parent,
3255
+ principal: identity,
3256
+ requestedBy: identity,
3257
+ requestedAt: Date.now()
3258
+ }
3259
+ };
3260
+ },
3261
+ opts,
3262
+ "self-if-unenrolled"
3263
+ );
3264
+ }
3265
+ async function exchangeOnboardingToken(session, keyHash, idp = process.env["NOMOS_ONBOARDING_IDP"] ?? DEFAULT_ONBOARDING_IDP, fetchImpl = fetch) {
3266
+ const r = await fetchImpl(`${idp.replace(/\/+$/, "")}/token`, {
3267
+ method: "POST",
3268
+ headers: { authorization: `Bearer ${session}`, "content-type": "application/json" },
3269
+ body: JSON.stringify({ nonce: keyHash })
3270
+ });
3271
+ const body = await r.json().catch(() => null);
3272
+ if (!r.ok || typeof body?.token !== "string" || typeof body.issuer !== "string" || typeof body.subject !== "string") {
3273
+ throw new Error(
3274
+ `Nomos could not establish the first device identity (${r.status}): ${String(body?.error ?? "invalid identity-provider response")}`
3275
+ );
3276
+ }
3277
+ return { token: body.token, issuer: body.issuer, subject: body.subject };
3278
+ }
3279
+ async function ensureSovereignHome(opts = {}) {
3280
+ const cloud = cloudBase(opts.cloud);
3281
+ const uid = opts.principal ?? currentPrincipal();
3282
+ if (!uid) throw new Error("a Nomos session is required \u2014 githolon login --agent");
3283
+ const actor = canonicalPrincipal(uid);
3284
+ if (!actor.startsWith("user:")) throw new Error("blank-session bootstrap requires an identity-provider principal");
3285
+ const bare = actor.slice("user:".length);
3286
+ const auth = await sessionToken();
3287
+ if (!auth) throw new Error("blank-session bootstrap needs the live login session \u2014 githolon login --agent");
3288
+ const client = await import("@githolon/client");
3289
+ const home = await client.homeNameOf(actor);
3290
+ const exists = await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home)}`).then((r) => r.ok).catch(() => false);
3291
+ const root = await connectGovernance(cloud, "root");
3292
+ const device = await ensureDeviceKey(root, bare);
3293
+ let signerReady = false;
3294
+ if (typeof root.parentSignerEnrollment === "function") {
3295
+ signerReady = await root.parentSignerEnrollment({ parent: "root", principal: actor, keyHash: device.keyHash, authToken: auth }).then((p) => p.enrolled && p.revoked !== true).catch(() => false);
3296
+ }
3297
+ const delegationReady = await fetch(
3298
+ `${cloud}/v2/workspaces/root/workspaces/signerDelegationByUser?user=${encodeURIComponent(actor)}`
3299
+ ).then(async (r) => {
3300
+ if (!r.ok) return false;
3301
+ const d = await r.json();
3302
+ return Array.isArray(d.rows) && d.rows.length > 0;
3303
+ }).catch(() => false);
3304
+ if (!signerReady || !delegationReady) {
3305
+ if (typeof root.enrollFirstDevice !== "function") {
3306
+ throw new Error("the installed @githolon/client predates automatic first-device enrollment");
3307
+ }
3308
+ const assertion = await exchangeOnboardingToken(auth, device.keyHash);
3309
+ if (assertion.subject !== bare) {
3310
+ throw new Error(`identity provider returned '${assertion.subject}' for logged-in principal '${bare}'`);
3311
+ }
3312
+ await root.enrollFirstDevice({
3313
+ parent: "root",
3314
+ domain: "workspaces",
3315
+ principal: actor,
3316
+ device,
3317
+ idToken: assertion.token,
3318
+ authToken: assertion.token,
3319
+ verifiedVia: assertion.issuer
3320
+ });
3321
+ }
3322
+ if (!exists) {
3323
+ const domains = await fetch(`${cloud}/v2/workspaces/root/domains`).then(async (r) => {
3324
+ if (!r.ok) throw new Error(`root law discovery failed (${r.status})`);
3325
+ return await r.json();
3326
+ });
3327
+ const frameworkHash = domains.currentLaw?.["nomos"];
3328
+ const lawHash = domains.currentLaw?.["workspaces"];
3329
+ if (!frameworkHash || !lawHash) throw new Error("root does not report the framework and governance laws needed for birth");
3330
+ const birthCert = await root.certSign({
3331
+ child: home,
3332
+ founder: actor,
3333
+ verified: true,
3334
+ parentKey: device.public,
3335
+ parentId: "root",
3336
+ epoch: 0,
3337
+ secret: device.secret
3338
+ });
3339
+ const now = Date.now();
3340
+ const birth = await fetch(`${cloud}/v2/workspaces/root/workspaces/birthChild`, {
3341
+ method: "POST",
3342
+ headers: { "content-type": "application/json" },
3343
+ body: JSON.stringify({
3344
+ name: home,
3345
+ parent: "",
3346
+ principal: bare,
3347
+ tier: "edge",
3348
+ requestedBy: bare,
3349
+ requestedAt: now,
3350
+ foundingAdminHash: device.keyHash,
3351
+ bornAt: new Date(now).toISOString(),
3352
+ frameworkHash,
3353
+ lawHash,
3354
+ platformCert: JSON.stringify(birthCert),
3355
+ actor,
3356
+ authorSecret: device.secret
3357
+ })
3358
+ });
3359
+ const body = await birth.json().catch(() => null);
3360
+ const failed = body?.birthOutcomes?.find((o) => o.status !== "born");
3361
+ if (!birth.ok || body?.ok === false || failed) {
3362
+ throw new Error(
3363
+ `Nomos could not birth the session home (${birth.status}): ${failed?.reason ?? String(body?.error ?? JSON.stringify(body))}`
3364
+ );
3365
+ }
3366
+ const deadline = Date.now() + 3e4;
3367
+ while (Date.now() < deadline) {
3368
+ if (await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home)}`).then((r) => r.ok).catch(() => false)) break;
3369
+ await new Promise((resolve6) => setTimeout(resolve6, 250));
3370
+ }
3371
+ if (!await fetch(`${cloud}/v2/workspaces/${encodeURIComponent(home)}`).then((r) => r.ok).catch(() => false)) {
3372
+ throw new Error(`Nomos admitted the birth of '${home}' but its custody did not become readable`);
3373
+ }
3374
+ const admin = await signAndPostOffer(
3375
+ home,
3376
+ "workspaces",
3377
+ "grantAdmin",
3378
+ { principal: bare, label: "founding admin", grantedBy: bare, grantedAt: now },
3379
+ { ...opts, principal: bare }
3380
+ );
3381
+ if (!admin.ok) throw new Error(`the born home refused its founding admin (${admin.status}): ${JSON.stringify(admin.body)}`);
3382
+ }
3383
+ const homeHolon = await connectGovernance(cloud, home);
3384
+ const homeSigner = typeof homeHolon.parentSignerEnrollment === "function" ? await homeHolon.parentSignerEnrollment({ parent: home, principal: actor, keyHash: device.keyHash, authToken: auth }).catch(() => null) : null;
3385
+ if (!homeSigner?.verifiedVia) {
3386
+ if (typeof homeHolon.enrollFirstDevice !== "function") {
3387
+ throw new Error("the installed @githolon/client predates verified session-home enrollment");
3388
+ }
3389
+ const assertion = await exchangeOnboardingToken(auth, device.keyHash);
3390
+ if (assertion.subject !== bare) {
3391
+ throw new Error(`identity provider returned '${assertion.subject}' for logged-in principal '${bare}'`);
3392
+ }
3393
+ const domain = await discoverSigningDomain(homeHolon, home, "enrollFirstDevice", "workspaces");
3394
+ await homeHolon.enrollFirstDevice({
3395
+ parent: home,
3396
+ domain,
3397
+ principal: actor,
3398
+ device,
3399
+ idToken: assertion.token,
3400
+ authToken: assertion.token,
3401
+ verifiedVia: assertion.issuer,
3402
+ includeDelegation: false
3403
+ });
3404
+ const object = `identity:${actor}`;
3405
+ const deadline = Date.now() + 3e4;
3406
+ let visible = false;
3407
+ while (Date.now() < deadline) {
3408
+ visible = await fetch(
3409
+ `${cloud}/v2/workspaces/${encodeURIComponent(home)}/workspaces/relationTuplesByObject?object=${encodeURIComponent(object)}`
3410
+ ).then(async (r) => {
3411
+ if (!r.ok) return false;
3412
+ const body = await r.json();
3413
+ const leaf = body.rows?.[0]?.data?.subjects?.[`key:${device.keyHash}`];
3414
+ return typeof leaf?.verifiedVia === "string" && leaf.verifiedVia.length > 0;
3415
+ }).catch(() => false);
3416
+ if (visible) break;
3417
+ await new Promise((resolve6) => setTimeout(resolve6, 250));
3418
+ }
3419
+ if (!visible) throw new Error(`the session home's verified device enrollment did not become readable`);
3420
+ }
3421
+ return { home, principal: actor, device, created: !exists };
3422
+ }
3423
+ async function signAndPostWorkspaceRetirement(parent, workspaceId, creator, opts) {
3424
+ return signAndPostPreparedOffer(
3425
+ parent,
3426
+ "workspaces",
3427
+ (actor) => ({
3428
+ directiveId: creator !== "" && sameIdentity(creator, actor) ? "retireOwnWorkspace" : "retireWorkspace",
3429
+ payload: { workspaceId, retiredBy: lineageIdentity(actor), retiredAt: Date.now() }
3430
+ }),
3431
+ opts,
3432
+ "self-if-unenrolled",
3433
+ creator
3434
+ );
3220
3435
  }
3221
3436
  async function relaySealedOfferViaStage(cloud, ws, directiveId, intentBytesB64, fetchImpl) {
3222
3437
  const raw = Buffer.from(intentBytesB64, "base64");
@@ -4517,13 +4732,16 @@ function readSealedIntentBytes(eng, ws, intentOut) {
4517
4732
  if (f?.data === void 0) return void 0;
4518
4733
  return Buffer.from(f.data).toString("base64");
4519
4734
  }
4520
- var out2, err2, STAGE_THRESHOLD_CHARS, HONEST_CEILING, ROOT_CUSTODIAN_SECRET, CLIENT_IMPACT;
4735
+ var out2, err2, lineageIdentity, sameIdentity, DEFAULT_ONBOARDING_IDP, STAGE_THRESHOLD_CHARS, HONEST_CEILING, ROOT_CUSTODIAN_SECRET, CLIENT_IMPACT;
4521
4736
  var init_governance = __esm({
4522
4737
  "src/governance.ts"() {
4523
4738
  "use strict";
4524
4739
  init_cloud();
4525
4740
  out2 = (s) => void process.stdout.write(s + "\n");
4526
4741
  err2 = (s) => void process.stderr.write("error: " + s + "\n");
4742
+ lineageIdentity = (actor) => actor.startsWith("user:") ? actor.slice("user:".length) : actor;
4743
+ sameIdentity = (a, b) => lineageIdentity(a) === lineageIdentity(b);
4744
+ DEFAULT_ONBOARDING_IDP = "https://id.nomos.captainapp.co.uk";
4527
4745
  STAGE_THRESHOLD_CHARS = 4 * 1024 * 1024;
4528
4746
  HONEST_CEILING = `The operator controls root's law and could deploy law removing the consent check \u2014 but that act is itself a signed, ordered, permanent fact in root's chain, visible to every tenant running \`replay root\`, and grounds for exit-with-everything. Not "we can't" \u2014 "we can't secretly, and you can always leave."`;
4529
4747
  ROOT_CUSTODIAN_SECRET = "nomos-root-custodian-key";
@@ -5181,16 +5399,10 @@ async function logout() {
5181
5399
  async function wsCreate(name, opts) {
5182
5400
  const cloud = cloudBase(opts.cloud);
5183
5401
  if (opts.via !== void 0) {
5184
- const { signAndPostGovernance: signAndPostGovernance2, resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5402
+ const { signAndPostWorkspaceBirth: signAndPostWorkspaceBirth2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5185
5403
  let v;
5186
5404
  try {
5187
- const principal2 = resolveGovernancePrincipal2(opts);
5188
- v = await signAndPostGovernance2(
5189
- opts.via,
5190
- "createWorkspace",
5191
- { name, tier: "edge", parent: opts.via === "root" ? "" : opts.via, principal: principal2, requestedBy: principal2, requestedAt: Date.now() },
5192
- opts
5193
- );
5405
+ v = await signAndPostWorkspaceBirth2(opts.via, name, opts);
5194
5406
  } catch (e) {
5195
5407
  err4(e.message);
5196
5408
  return 1;
@@ -5259,7 +5471,7 @@ async function wsStatus(name, opts) {
5259
5471
  }
5260
5472
  async function wsRetire(ws, opts) {
5261
5473
  const cloud = cloudBase(opts.cloud);
5262
- const { signAndPostGovernance: signAndPostGovernance2, resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5474
+ const { signAndPostWorkspaceRetirement: signAndPostWorkspaceRetirement2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
5263
5475
  const parent = opts.parent ?? "root";
5264
5476
  let record;
5265
5477
  try {
@@ -5280,12 +5492,8 @@ async function wsRetire(ws, opts) {
5280
5492
  }
5281
5493
  let v;
5282
5494
  try {
5283
- const principal = resolveGovernancePrincipal2(opts);
5284
- const payload = { workspaceId: recordId, retiredBy: principal, retiredAt: Date.now() };
5285
- const bare = (s) => s.startsWith("user:") ? s.slice(5) : s;
5286
5495
  const creator = record?.data?.createdBy ?? record?.data?.principal ?? "";
5287
- const own = creator !== "" && bare(creator) === bare(principal);
5288
- v = await signAndPostGovernance2(parent, own ? "retireOwnWorkspace" : "retireWorkspace", payload, opts);
5496
+ v = await signAndPostWorkspaceRetirement2(parent, recordId, creator, opts);
5289
5497
  } catch (e) {
5290
5498
  err4(e.message);
5291
5499
  return 1;
@@ -6083,7 +6291,11 @@ async function runChildBirthLeg(eng, ws, lawHash, cb, frameworkHash) {
6083
6291
  const checks = downgraded.certChecks !== void 0 ? ` certChecks=${JSON.stringify(downgraded.certChecks)}` : "";
6084
6292
  lines.push(`\u26A0 child ${childWs} was born UNWARRANTED \u2014 ${String(downgraded.reason ?? "cert not seeded")}${checks}`);
6085
6293
  }
6086
- lines.push(`\u2713 child birth ${cb.parentDomain}/${cb.birthDirectiveId} \u2014 ${childWs} born (the offer-effect folded the child genesis through the child's OWN gate)`);
6294
+ if (cb.businessAggregateId !== void 0) {
6295
+ lines.push(`\u2713 birth(${cb.businessAggregateId}) \u2014 business facts became a durable holon`);
6296
+ } else {
6297
+ lines.push(`\u2713 child birth ${cb.parentDomain}/${cb.birthDirectiveId} \u2014 ${childWs} born (the offer-effect folded the child genesis through the child's OWN gate)`);
6298
+ }
6087
6299
  const installed = (hash) => {
6088
6300
  try {
6089
6301
  return qById(eng, childWs, `domain-installation:${hash}`).length > 0;
@@ -6097,7 +6309,11 @@ async function runChildBirthLeg(eng, ws, lawHash, cb, frameworkHash) {
6097
6309
  if (!installed(lawHash)) {
6098
6310
  return done(false, `the born child ${childWs} did not install the child law in-chain (domain-installation:${lawHash.slice(0, 12)}\u2026 absent) \u2014 the genesis nomos/installDomain did not fold (by-hash byte routing failed: does the parent fold this law?)`);
6099
6311
  }
6100
- lines.push(`\u2713 the born child installed the framework + child law IN-CHAIN (the genesis installDomain\xD72 folded)`);
6312
+ if (cb.businessAggregateId !== void 0) {
6313
+ lines.push(`\u2713 law travelled with ${cb.businessAggregateId} and admitted its first business fact`);
6314
+ } else {
6315
+ lines.push(`\u2713 the born child installed the framework + child law IN-CHAIN (the genesis installDomain\xD72 folded)`);
6316
+ }
6101
6317
  let seedRows = [];
6102
6318
  if (cb.childSeedInstanceId !== void 0) {
6103
6319
  try {
@@ -6116,7 +6332,9 @@ async function runChildBirthLeg(eng, ws, lawHash, cb, frameworkHash) {
6116
6332
  if ((cb.childSeedInstanceId !== void 0 || cb.childQuery !== void 0) && seedRows.length < 1) {
6117
6333
  return done(false, `the born child ${childWs} did not seed ${cb.childSeedAggregateId ?? "its genesis record"} (${cb.childSeedDirectiveId} produced no readable row) \u2014 the child genesis seed did not run`);
6118
6334
  }
6119
- lines.push(`\u2713 the born child's genesis seed ran \u2014 ${cb.childSeedDirectiveId} produced ${seedRows.length} readable ${cb.childSeedAggregateId ?? "row"}(s) in ${childWs}`);
6335
+ if (cb.businessAggregateId === void 0) {
6336
+ lines.push(`\u2713 the born child's genesis seed ran \u2014 ${cb.childSeedDirectiveId} produced ${seedRows.length} readable ${cb.childSeedAggregateId ?? "row"}(s) in ${childWs}`);
6337
+ }
6120
6338
  let verdict;
6121
6339
  try {
6122
6340
  verdict = verifyChainLocal(eng, childWs);
@@ -6126,7 +6344,11 @@ async function runChildBirthLeg(eng, ws, lawHash, cb, frameworkHash) {
6126
6344
  if (verdict.valid !== true) {
6127
6345
  return done(false, `the born child ${childWs} FAILED verify_chain at ${verdict.check ?? "?"}${verdict.atIndex !== void 0 ? ` (intent ${verdict.atIndex})` : ""}: ${verdict.error ?? "invalid"} \u2014 the child's own gate refused its genesis`);
6128
6346
  }
6129
- lines.push(`\u2713 verify_chain GREEN on the born child ${childWs} (${verdict.plansRerun ?? "?"} plans re-run \u2014 it self-validates from intent 0 through its OWN gate)`);
6347
+ if (cb.businessAggregateId !== void 0) {
6348
+ lines.push(`\u2713 full history replayed green locally (${verdict.plansRerun ?? "?"} plans re-run)`);
6349
+ } else {
6350
+ lines.push(`\u2713 verify_chain GREEN on the born child ${childWs} (${verdict.plansRerun ?? "?"} plans re-run \u2014 it self-validates from intent 0 through its OWN gate)`);
6351
+ }
6130
6352
  const bornEntry = (res.born ?? []).find((b) => b?.workspace === childWs);
6131
6353
  const packed = packBornChildren(eng, bornEntry === void 0 ? [] : [bornEntry]);
6132
6354
  const childPack = packed.find((b) => b.workspace === childWs);
@@ -6148,7 +6370,11 @@ async function runChildBirthLeg(eng, ws, lawHash, cb, frameworkHash) {
6148
6370
  return done(false, `the recovered child ${childWs} verified but its business root ${cb.childSeedInstanceId} was missing`);
6149
6371
  }
6150
6372
  }
6151
- lines.push(`\u2713 persistence + recovery \u2014 child custody packed, resident copy discarded, verify_chain GREEN and ${cb.childSeedInstanceId ?? cb.childSeedAggregateId ?? "the business root"} readable after reopen`);
6373
+ if (cb.businessAggregateId !== void 0) {
6374
+ lines.push(`\u2713 persistence + recovery \u2014 evicted, restored from durable custody, and ${cb.businessAggregateId} read back`);
6375
+ } else {
6376
+ lines.push(`\u2713 persistence + recovery \u2014 child custody packed, resident copy discarded, verify_chain GREEN and ${cb.childSeedInstanceId ?? cb.childSeedAggregateId ?? "the business root"} readable after reopen`);
6377
+ }
6152
6378
  return done(true);
6153
6379
  }
6154
6380
  function seatRelationAuthority(eng, ws, lawHash, rb, actor, stamp, lines, authorSecret, subjectActor = actor) {
@@ -6388,7 +6614,7 @@ async function runOfflineProofStandalone(proofPath, cloud, domain) {
6388
6614
  }
6389
6615
  const deployBody = JSON.parse(readFileSync7(deployFile, "utf8"));
6390
6616
  const lawHash = await sha256hex(deployBody.packageUsda);
6391
- console.log(`githolon proof \u2014 OFFLINE legs on a local holon (the cloud loop: githolon proof --live)`);
6617
+ console.log(`githolon proof \u2014 generated business proof in the real local engine`);
6392
6618
  const runtimeKind = legs.childBirth !== void 0 || (legs.childBirths?.length ?? 0) > 0 ? "test-mint" : "production";
6393
6619
  const { eng } = await holonEngine(cloud, deployBody, "githolon-proof", runtimeKind);
6394
6620
  const ws = "proof-offline";
@@ -6403,7 +6629,7 @@ async function runOfflineProofStandalone(proofPath, cloud, domain) {
6403
6629
  }
6404
6630
  console.log(`
6405
6631
  OFFLINE PROOF GREEN (${Math.round(v.ms)}ms) \u2014 the same legs rerun on every save in \`githolon dev\`.`);
6406
- console.log(`Deploy with confidence when ready: githolon ws create <ws> && githolon deploy <ws> (or the full cloud proof: githolon proof --live)`);
6632
+ console.log(`Run the same generated business proof against Nomos Cloud when ready: githolon proof --live`);
6407
6633
  return 0;
6408
6634
  }
6409
6635
  var keyHashOf, OFFLINE_PROOF_VERIFIER;
@@ -8822,9 +9048,9 @@ var HELP = {
8822
9048
  examples: ["githolon compile", "githolon compile nomos.package.mjs --layered"]
8823
9049
  },
8824
9050
  proof: {
8825
- usage: "githolon proof [build/<name>.proof.mts] [--domain <key>] [--live] [--keep]",
8826
- what: "Run the proof GENERATED from your law. DEFAULT: the OFFLINE legs on a LOCAL holon \u2014 the\nsame engine plane the cloud edge runs; no cloud workspace is touched (develop/play/understand\nhere, deploy with confidence after). --domain <key> proves a SPECIFIC domain of a multi-domain\npackage (offline; the default is the first). --live runs the full cloud loop (throwaway\nworkspace \u2192 deploy \u2192 offline write \u2192 admission \u2192 cloud reads \u2192 convergence). The throwaway is\ncreated REGISTERED (a signed createWorkspace at root \u2014 your principal needs creation authority\nthere) and RETIRED on every exit via the lawful retireOwnWorkspace; --keep keeps it. ALL GREEN or it names the jam. The offline\nlegs also rerun on every save in `githolon dev`.",
8827
- examples: ["githolon proof", "githolon proof --domain co2_platform", "githolon proof --live", "githolon proof --live --keep"]
9051
+ usage: "githolon proof [build/<name>.proof.mts] [--domain <key>] [--live]",
9052
+ what: "Run the proof GENERATED from your business law. By default it drives the real local engine:\nbirth, full-history verification, durable custody, eviction, restore, and read-back. --live runs the\nsame business proof against Nomos Cloud; identity, provisioning, persistence, and cleanup remain\ninside Nomos. --domain selects one domain in a multi-domain package. ALL GREEN or it names the jam.",
9053
+ examples: ["githolon proof", "githolon proof --domain co2_platform", "githolon proof --live"]
8828
9054
  },
8829
9055
  dev: {
8830
9056
  usage: "githolon dev [--port <n>] [--cloud <url>] [--once]",
@@ -8911,7 +9137,7 @@ var HELP = {
8911
9137
  },
8912
9138
  login: {
8913
9139
  usage: "githolon login --agent | --token <refresh_token>",
8914
- what: "Establish the principal births ride. --agent self-onboards an anonymous VERIFIED identity\n(no human, no browser; linkable later); --token adopts an existing captain app session.\nSessions live in ~/.holon/credentials.json and auto-refresh.",
9140
+ what: "Establish the identity Nomos uses beneath birth. --agent creates a verified development identity\n(no browser; linkable later); --token adopts an existing session. Credentials auto-refresh.",
8915
9141
  examples: ["githolon login --agent", "githolon login --token <refresh_token>"]
8916
9142
  },
8917
9143
  whoami: {
@@ -8932,16 +9158,14 @@ var HELP = {
8932
9158
  what: "Clear the session. Stored workspace secrets are KEPT."
8933
9159
  },
8934
9160
  ws: {
8935
- usage: "githolon ws <create|status|retire|reclaim> [<name>] [--principal <uid|token>] [--via <parent>] [--parent <ws>] [--cloud <url>] [--target <name>]",
8936
- what: "Workspace lifecycle on Nomos Cloud. `create` births one (NO host secret is issued \u2014\nownership is a ledger fact; deploy is open + kernel-gated) or, with --via <parent>, requests it\nas a SIGNED createWorkspace governance offer. `status` shows lineage/phase/verdicts. `retire`\nand `reclaim` are SIGNED governance offers to the parent (default root) \u2014 never host-author\nendpoints; retire withdraws the law (data retained), reclaim authorizes the bailiff to drop\ncustody (only a retired workspace; never root). `status` with no <name> resolves the project's\n`workspace` binding.",
9161
+ usage: "githolon ws <status|retire|reclaim> [<name>] [--parent <ws>] [--cloud <url>] [--target <name>]",
9162
+ what: "Operator inspection and disposal of existing cloud custody. Application creation is not here:\ndeclare birth(Aggregate, spec) and call the generated app.birth(businessFacts). `status` inspects\nlineage and verdicts; `retire` withdraws law while retaining data; `reclaim` discards custody only\nafter retirement.",
8937
9163
  flags: [
8938
- ["--principal <p>", "the birth's principal (uid or access token; remembered as the default)"],
8939
- ["--via <parent>", "ws create: sign a createWorkspace offer at <parent> instead of the raw birth"],
8940
9164
  ["--parent <ws>", "retire/reclaim: the governance workspace to sign against (default root)"],
8941
9165
  ["--cloud <url>", "target cloud (default: $NOMOS_CLOUD or the public cloud)"],
8942
9166
  ["--target <name>", "ws status: pick among the project's named workspace targets"]
8943
9167
  ],
8944
- examples: ["githolon ws create my-guestbook", "githolon ws create app1 --via co2", "githolon ws status", "githolon ws retire my-guestbook"]
9168
+ examples: ["githolon ws status", "githolon ws retire my-guestbook"]
8945
9169
  },
8946
9170
  key: {
8947
9171
  usage: "githolon key <enroll|show|import|export> [--principal <uid>] [--secret <key>] [--sha256] [--format hex|base64] [--parent <ws>] [--yes]",
@@ -8977,9 +9201,8 @@ var HELP = {
8977
9201
  ],
8978
9202
  examples: [
8979
9203
  `githolon gov root grantCreation --payload '{"principal":"d205ca94-\u2026"}' --as 32c7100e-\u2026 --stamp`,
8980
- "githolon gov co2-platform birthHome --payload-file home.json --as d205ca94-\u2026",
8981
- "githolon gov root birthChild --payload-file co2.json --as 32c7100e-\u2026 --save co2.offer.json",
8982
- "githolon gov relay root co2.offer.json"
9204
+ "githolon gov root setGovernancePosture --payload-file posture.json --as 32c7100e-\u2026 --save posture.offer.json",
9205
+ "githolon gov relay root posture.offer.json"
8983
9206
  ]
8984
9207
  },
8985
9208
  rebirth: {
@@ -9050,12 +9273,12 @@ var HELP = {
9050
9273
  },
9051
9274
  git: {
9052
9275
  usage: "githolon git <setup | remote [<ws>] [<remoteName>]> [--cloud <url>] [--target <name>]",
9053
- what: "Stock git as the sync transport. `setup` installs the credential helper for the cloud host;\n`remote` wires this repo to a workspace (then push your session branch: git push nomos\nrefs/heads/session/<id>). `main` is not push-writable \u2014 a workspace is born by its PARENT\nauthoring its birth (birthHome/birthChild), never by a push. With no <ws>, the project's\n`workspace` binding resolves it.",
9276
+ what: "Operator transport plumbing for existing holons. `setup` installs the credential helper;\n`remote` wires a local repo to existing cloud custody. Application code does not use git to\ncreate business things; it calls the generated birth(businessFacts).",
9054
9277
  examples: ["githolon git setup", "githolon git remote my-guestbook", "git push nomos refs/heads/session/dev"]
9055
9278
  },
9056
9279
  ledger: {
9057
9280
  usage: "githolon ledger <init|verify> <dir> [--file <deploy.json>] [--cloud <url>]",
9058
- what: "Mint + assert a holon ON YOUR MACHINE. `init` writes genesis + your compiled law as a normal\ngit repo, verified by the SAME wasm gate the cloud runs; `verify` re-runs the chain's\nself-verification from disk. Push the repo to an unborn workspace to birth it.",
9281
+ what: "Low-level local custody and verification for framework development. `init` writes compiled\nlaw into a git-backed holon; `verify` replays its full history. Application packages use the\ngenerated birth(businessFacts) surface instead.",
9059
9282
  examples: ["githolon ledger init ./my-holon", "githolon ledger verify ./my-holon"]
9060
9283
  }
9061
9284
  };
@@ -9555,117 +9778,37 @@ async function status(wsArg, opts) {
9555
9778
  // src/cli.ts
9556
9779
  var KINDS = ["domain", "aggregate", "intent"];
9557
9780
  var DEFAULT_OUT = "domains";
9558
- var USAGE = `githolon \u2014 the Nomos developer CLI
9781
+ var USAGE = `githolon \u2014 model a business; Nomos owns the compute science
9559
9782
 
9560
- The inner loop:
9561
- githolon dev watch \u2192 recompile \u2192 law LIVE in a local holon \u2192
9562
- the generated proof's offline legs rerun \u2192 local
9563
- reads served \u2014 sub-second, offline after warmup
9564
- githolon status [<ws>] local law hash vs the DEPLOYED law, remedy named
9565
- githolon replay <ws|dir> the ledger as film: step the chain intent-by-
9566
- intent; finale = the verify_chain verdict
9567
- githolon scene <ws|dir> [--out <dir>] the ledger as a PORTABLE USD scene: verify_chain-
9568
- gated chain\u2192USD projection (.usda + .usdz, loads
9569
- in three.js/usdview/QuickLook; timeCode = index)
9570
- githolon decrypt <ws> --as <p> --secret <b64> clone + decrypt as a principal: unwrap their scope
9571
- --query <id> [--param k=v] keys from the chain, read private fields in cleartext
9783
+ Start here:
9784
+ githolon compile compile aggregates, birth, directives, and reads into law + a typed client
9785
+ githolon proof run the generated business proof in the real local engine
9786
+ githolon dev watch, compile, and rerun that proof on every save
9787
+ githolon check explain anything the law can already prove it would refuse
9572
9788
 
9573
- Authoring:
9574
- githolon check [config] [--json] [--against <p>] run the author-time gate (static twins) on
9575
- ./nomos.package.mjs \u2014 the unified report; exits
9576
- non-zero on any REFUSE (compile runs it implicitly).
9577
- --json emits the findings (with file:line) as an array
9578
- githolon compat <ws-url|deploy.json|dir> [--json] THE CI GATE: compare the current build's interface
9579
- against a target's installed law, PER MEMBER (#72
9580
- subtyping); exits non-zero on any incompatible member
9581
- githolon lsp the author-time gate as a stdio Language Server:
9582
- red squiggles while you write law (VS Code/Neovim/\u2026)
9583
- githolon mcp the author-time gate as a stdio MCP server for AI
9584
- agents (Codex/Claude): tools nomos_check +
9585
- nomos_evolve_preview. Setup: codex mcp add nomos -- githolon mcp
9586
- githolon compile [compiler args] compile the package by ./nomos.package.mjs
9587
- githolon init-editor write .vscode/extensions.json recommending the
9588
- Nomos Law extension \u2014 the check gate as red
9589
- squiggles while you type (idempotent)
9590
- githolon proof [build/<name>.proof.mts] run the proof GENERATED from your law, live
9591
- (every compile emits it; ALL GREEN or it names the jam)
9592
- githolon harness-install --deploy <deploy.json[,...]> offline install for the headless TEST HARNESS:
9593
- --workspace <ws> --out <snapshot> install tenant law IN-CHAIN (no cloud), write the
9594
- restore snapshot, print { ok, snapshot, lawHashes }
9595
- githolon generate <domain|aggregate|intent> <name> [options]
9596
- githolon g <domain|aggregate|intent> <name> [options]
9789
+ The application surface is one idea:
9790
+ const thing = await app.birth(businessFacts)
9597
9791
 
9598
- Identity (~/.holon/credentials.json \u2014 sessions auto-refresh):
9599
- githolon login --agent anonymous sign-in: a verified self-onboarded identity
9600
- githolon login --token <refresh_token> adopt an existing captain app session
9601
- githolon whoami show the principal births will ride + keys on file
9602
- githolon use [<uid>] [--clear] set/show/clear the ACTIVE signing principal: the one
9603
- deploy/gov/grant/key author as (--as overrides per-cmd)
9604
- githolon logout clear the session (workspace secrets kept)
9605
- githolon key enroll [--principal <uid>] [--parent <ws>] [--domain <d>] [--directive <id>] mint a signing device key + enroll it on-chain (the signing directive is DISCOVERED from the parent's installed law; the flags override)
9606
- (secret stays local; warrants SIGNED governance)
9607
- githolon key import --principal <uid> --secret <key> bring an EXISTING admin key into ~/.holon (accepts
9608
- hex / base64 seed, or --sha256 <passphrase>)
9609
- githolon key show | export [--principal <uid>] the device key's public identity (export --yes: secret)
9792
+ A born aggregate is a holon: its law, facts, and history travel together. Nomos owns durable identity,
9793
+ authorship, local execution, validation, persistence, synchronisation, provenance, and recovery beneath
9794
+ that call. Those mechanisms are not separate application workflows.
9610
9795
 
9611
- Governance (SIGNED client-side, relayed as {intentBytes} \u2014 never a host-author endpoint):
9612
- githolon gov <ws> <directive> [--domain <d>] author ANY governance directive (domain discovered
9613
- [--payload <json>] from installed law; --domain overrides) as a signed offer
9614
- [--as <uid>] [--stamp] [--save <file>] to <ws> (--save signs without relaying; relay later)
9615
- githolon gov relay <ws> <offer-file> relay a saved offer (the only step that hits the cloud)
9616
- githolon gov rebirth <ws> --reason <text> LAWFUL SUPERSESSION (recovery verb 3): supersede a
9617
- [--dry-run [--json]] [--yes] scarred chain; --dry-run = READ-ONLY impact report
9618
- githolon rebirth plan <ws> [--reason <text>] [--out D] write a stable plan.json + impact.md (rebirths-as-code)
9619
- githolon rebirth apply --plan <plan.json> drift-pinned apply of a reviewed plan \u2192 certificate.json
9620
- --gcp-secret nomos-root-custodian-key [--yes] (apply needs the ROOT CUSTODIAN seed; --gcp-secret is blessed)
9621
- githolon replay <ws> --repair execute the repair matching a red verify (\u2192 certificate)
9622
- githolon grant <admin|creation> <principal> [--label L] grant authority at the parent (default root)
9623
- githolon grant quota <principal> --max <N> grant a per-principal workspace allowance
9624
- githolon revoke <admin|creation> <principal> revoke it (the revoked fact rides the chain)
9625
- (all gated by the parent's law: only an admin's
9626
- signature is admitted; --parent <p> targets a platform)
9796
+ Useful authoring commands:
9797
+ githolon generate <domain|aggregate|intent> <name>
9798
+ githolon compat <target>
9799
+ githolon lsp
9800
+ githolon mcp
9801
+ githolon login --agent
9627
9802
 
9628
- Nomos Cloud (a bare <ws> resolves from nomos.package.mjs's optional \`workspace\` binding;
9629
- deploy is OPEN + kernel-gated \u2014 births return no host secret, ownership is a ledger fact):
9630
- githolon ws create <name> [--principal <uid|token>] birth a workspace (no host secret is issued)
9631
- (no identity on file? it self-onboards an agent login)
9632
- githolon ws create <name> --via <parent> request it as a SIGNED createWorkspace governance
9633
- offer at the parent
9634
- githolon ws status [<name>] workspace status (lineage, phase, verdicts)
9635
- githolon ws retire <name> [--parent <ws>] retire a workspace via a SIGNED governance offer;
9636
- quota freed; data retained; reads keep serving
9637
- githolon ws reclaim <name> [--parent <ws>] lawful custody discard via a SIGNED governance offer
9638
- (only a retired workspace; never root)
9639
- githolon deploy [<ws>] [--file <deploy.json>] deploy build/*.deploy.json \u2014 DEFAULT replace-current:
9640
- [--keep-beside] [--retire-replaced] new law becomes active; prior install is superseded
9641
- per domain key (prints what moved). --keep-beside
9642
- installs beside; --retire-replaced marks retired
9643
- githolon domains status <ws> per domain key: active law plus superseded/retired
9644
- [--explain-current-interface] lineage (active = served now)
9645
- githolon domains retire <ws> <hashOrKey> retire an install (marks it retired \u2014 replayable,
9646
- [--with <hashOrKey>] no longer served) via a signed installDomain offer
9647
- githolon dlq sweep <ws> [--depth <n>] [--full] sweep a platform subtree's dead-letter queues
9648
- (registry-enumerated; exit 2 when jams exist)
9649
- githolon secret set <ws> <push-password> store a git push password (authenticated git sync)
9650
- githolon secret rotate <ws> RETIRED \u2014 host holds no ownership credential (410)
9651
-
9652
- Git lane (stock git as the sync transport \u2014 main is not push-writable; a workspace is born by its parent):
9653
- githolon git setup install the credential helper for the cloud host
9654
- githolon git remote [<ws>] [<remoteName>] wire this repo to a workspace (default name: nomos)
9655
- then: git push nomos refs/heads/session/<id>
9656
-
9657
- The local-first lane (mint + assert a holon on YOUR machine, under YOUR identity):
9658
- githolon ledger init <dir> genesis + your compiled law, verified by the SAME
9659
- wasm gate the cloud runs, written as a git repo
9660
- githolon ledger verify <dir> re-run the chain's self-verification from disk
9803
+ Operational and inspection commands remain available to maintain Nomos itself. Ask any command for its
9804
+ focused screen: githolon <command> --help (for example: status, replay, scene, deploy, domains, or gov).
9661
9805
 
9662
9806
  Options:
9663
- --cloud <url> target cloud (default: $NOMOS_CLOUD or https://nomos.captainapp.co.uk)
9664
- --target <name> pick among the project's named workspace targets (workspace: { dev: \u2026, prod: \u2026 })
9665
- --out <dir> generate: target directory (default: ${DEFAULT_OUT})
9666
- --force generate: overwrite an existing file
9667
- --dry-run generate: print to stdout, write nothing
9668
- -h, --help top level here; \`githolon <command> --help\` for that command's flags + examples
9807
+ --cloud <url> target cloud
9808
+ --out <dir> generate into a different directory (default: ${DEFAULT_OUT})
9809
+ --force overwrite generated source
9810
+ --dry-run print generated source without writing it
9811
+ -h, --help show this page; githolon <command> --help shows one focused command
9669
9812
  `;
9670
9813
  function cloudArgs(rest) {
9671
9814
  const pos = [];
@@ -9771,8 +9914,7 @@ async function runProof(args) {
9771
9914
  return 1;
9772
9915
  };
9773
9916
  const live = args.includes("--live");
9774
- const keep = args.includes("--keep");
9775
- if (keep && !live) return refuse("--keep only applies to --live (the offline proof creates no cloud workspace to keep)");
9917
+ if (args.includes("--keep")) return refuse("--keep no longer applies: proof --live uses your durable signed Nomos home and creates only the requested business aggregate");
9776
9918
  let domain;
9777
9919
  let domainValueIdx = -1;
9778
9920
  const di = args.findIndex((a) => a === "--domain" || a.startsWith("--domain="));
@@ -9839,58 +9981,40 @@ async function runProof(args) {
9839
9981
  const tsxPkg = JSON.parse(readFileSync16(join17(tsxDir, "package.json"), "utf8"));
9840
9982
  const tsxBinRel = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.["tsx"];
9841
9983
  const tsxCli = join17(tsxDir, tsxBinRel ?? "dist/cli.mjs");
9842
- console.log("githolon proof --live \u2014 the full cloud loop (throwaway workspace, retired on exit" + (keep ? "; --keep: kept" : "") + ")");
9843
- const { wsCreate: wsCreate2, wsRetire: wsRetire2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
9844
- const { resolveGovernancePrincipal: resolveGovernancePrincipal2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
9845
- const { login: login2, activePrincipal: activePrincipal2 } = await Promise.resolve().then(() => (init_cloud(), cloud_exports));
9846
- let principal = process.env.NOMOS_PRINCIPAL;
9847
- try {
9848
- principal ??= resolveGovernancePrincipal2({});
9849
- } catch {
9850
- const lr = await login2({ agent: true });
9851
- principal = lr === 0 ? activePrincipal2() : void 0;
9984
+ console.log("githolon proof --live \u2014 one generated app.birth against Nomos Cloud");
9985
+ const { ensureSovereignHome: ensureSovereignHome2 } = await Promise.resolve().then(() => (init_governance(), governance_exports));
9986
+ if (currentPrincipal() === void 0) {
9987
+ const lr = await login({ agent: true });
9988
+ if (lr !== 0) {
9989
+ return refuse("proof --live needs a login \u2014 githolon login --agent failed; try it directly");
9990
+ }
9852
9991
  }
9853
- if (principal === void 0) {
9992
+ if (currentPrincipal() === void 0) {
9854
9993
  return refuse("proof --live needs a principal \u2014 githolon login --agent (self-onboarding) failed; try it directly or pass NOMOS_PRINCIPAL");
9855
9994
  }
9856
- const proofSlug = proofPath.split("/").pop().replace(/\.proof\.mts$/, "").toLowerCase().replace(/[^a-z0-9-]+/g, "-");
9857
- const ws = process.env.NOMOS_WS ?? `${proofSlug}-proof-${Math.random().toString(36).slice(2, 8)}`;
9858
- if (process.env.NOMOS_WS === void 0) {
9859
- const cr = await wsCreate2(ws, { via: "root", principal });
9860
- if (cr !== 0) {
9861
- return refuse(
9862
- `proof --live: registered create refused at root \u2014 principal ${principal} lacks creation authority, and the open birth lane would leak an unretirable workspace.
9863
- remedies:
9864
- \u2022 ask an operator: githolon grant creation ${principal} (then rerun)
9865
- \u2022 or pre-create a REGISTERED workspace yourself and hand it over: NOMOS_WS=<ws> githolon proof --live
9866
- \u2022 or develop offline (no cloud workspace at all): githolon proof`
9867
- );
9868
- }
9995
+ let home;
9996
+ try {
9997
+ home = await ensureSovereignHome2();
9998
+ } catch (e) {
9999
+ return refuse(
10000
+ `proof --live: Nomos could not establish the signed session home: ${e.message}. No certificate, signer, parent, or provisioning step is part of the application contract.`
10001
+ );
9869
10002
  }
10003
+ const barePrincipal = home.principal.startsWith("user:") ? home.principal.slice("user:".length) : home.principal;
10004
+ const deployed = await deploy2(home.home, { principal: barePrincipal });
10005
+ if (deployed !== 0) return refuse("proof --live: Nomos could not install the compiled business law into the signed session home");
9870
10006
  const r = spawnSync6(process.execPath, [tsxCli, proofPath], {
9871
10007
  stdio: "inherit",
9872
10008
  cwd: process.cwd(),
9873
10009
  env: {
9874
10010
  ...process.env,
9875
- NOMOS_WS: ws,
9876
- NOMOS_PRINCIPAL: principal,
9877
- NOMOS_PROOF_MANAGED: "1",
9878
- // the proof skips its own (dead) cleanup lane; the CLI retires below
9879
- ...keep ? { PROOF_KEEP: "1" } : {}
10011
+ NOMOS_WS: home.home,
10012
+ NOMOS_PRINCIPAL: home.principal,
10013
+ NOMOS_AUTHOR_SECRET: home.device.secret,
10014
+ NOMOS_PROOF_MANAGED: "1"
9880
10015
  }
9881
10016
  });
9882
- const proofStatus = r.status ?? 1;
9883
- if (keep) {
9884
- console.log(`workspace ${ws} KEPT (--keep) \u2014 retire it when done: githolon ws retire ${ws}`);
9885
- return proofStatus;
9886
- }
9887
- const rr = await wsRetire2(ws, { principal }).catch(() => 1);
9888
- if (rr !== 0) {
9889
- console.error(`\u26A0 THROWAWAY WORKSPACE NOT RETIRED: ${ws}`);
9890
- console.error(`\u26A0 retire it manually: githolon ws retire ${ws}`);
9891
- console.error(`\u26A0 (if it has no root registry row it was born unregistered and needs a custodian sweep)`);
9892
- }
9893
- return proofStatus;
10017
+ return r.status ?? 1;
9894
10018
  }
9895
10019
  function parseArgs(argv) {
9896
10020
  const [command, ...rest] = argv;
@@ -10176,6 +10300,12 @@ ${commandHelp("status")}`);
10176
10300
  }
10177
10301
  return status(pos[0], opts);
10178
10302
  }
10303
+ if (argv[0] === "ws" && argv[1] === "create") {
10304
+ process.stderr.write(
10305
+ "error: `githolon ws create` is not an application birth API. Declare birth(Aggregate, spec) and call the generated app.birth(businessFacts); Nomos owns custody beneath it.\n"
10306
+ );
10307
+ return 1;
10308
+ }
10179
10309
  if (argv[0] === "ws" || argv[0] === "deploy" || argv[0] === "secret") {
10180
10310
  return runCloud(argv);
10181
10311
  }
@@ -1851,7 +1851,21 @@ function resolveGatewayOperation(spec, opName, method) {
1851
1851
  const exactPath = `/${String(opName).replace(/^\/+/, "")}`;
1852
1852
  const exact = spec.paths[exactPath]?.[normalizedMethod];
1853
1853
  if (exact) return { op: exact, path: exactPath, ambiguous: null };
1854
- if (String(opName).includes("/")) return { op: null };
1854
+ const slash = String(opName).indexOf("/");
1855
+ if (slash > 0) {
1856
+ const requestedDomain = String(opName).slice(0, slash);
1857
+ const requestedAlias = String(opName).slice(slash + 1);
1858
+ const matches2 = [];
1859
+ for (const [path2, methods] of Object.entries(spec.paths)) {
1860
+ const op = methods?.[normalizedMethod];
1861
+ const x = op?.["x-nomos"];
1862
+ if (!op || !x || x.domain !== requestedDomain) continue;
1863
+ if (aliasIdsFor(x, path2).has(requestedAlias)) matches2.push({ op, path: path2 });
1864
+ }
1865
+ if (matches2.length === 1) return { ...matches2[0], ambiguous: null };
1866
+ if (matches2.length > 1) return { op: null, ambiguous: matches2.map((m) => m.path).sort() };
1867
+ return { op: null, ambiguous: null };
1868
+ }
1855
1869
  const matches = [];
1856
1870
  for (const [path2, methods] of Object.entries(spec.paths)) {
1857
1871
  const op = methods?.[normalizedMethod];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githolon",
3
- "version": "0.99.0",
3
+ "version": "0.100.1",
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.99.0",
33
- "@githolon/dsl": "^0.99.0",
32
+ "@githolon/client": "^0.100.1",
33
+ "@githolon/dsl": "^0.100.1",
34
34
  "isomorphic-git": "^1.38.4"
35
35
  },
36
36
  "devDependencies": {