@githolon/dsl 0.99.0 → 0.100.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@githolon/dsl",
3
- "version": "0.99.0",
3
+ "version": "0.100.0",
4
4
  "type": "module",
5
5
  "description": "Nomos 2 domain-authoring DSL: aggregates + directives in TS, executed and encoded to the Rust kernel's wire shapes.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
package/src/births.ts CHANGED
@@ -56,29 +56,8 @@ export function __drainBirths(): BirthRecipe[] {
56
56
  * chains carry no key, so they replay byte-green and the kernel does nothing). A plan may birth at most one
57
57
  * child per intent (one offer, one defined consequence — the unix model).
58
58
  *
59
- * TO BIRTH A LEAF CHILD RUNNING ITS OWN LAW (a home, an estate child) — copy `framework/home.ts`'s
60
- * `birthHome`. The recipe is just the two-layer law install + your own seed step; there is NO helper to
61
- * fabricate it and you do NOT need a new primitive (recursion is the law — a home births children exactly
62
- * as root births platforms). `buildGenesisChain` is the ONE builder for the PLATFORM shape (it adds the
63
- * `seedGenesis → grantAdmin → birthCloud` tail); a leaf just omits that tail:
64
- *
65
- * ```ts
66
- * export const birthEstateChild = directive("birthEstateChild")
67
- * .creates(EstateChild)
68
- * .payload(z.object({ child: z.string(), owner: z.string(),
69
- * frameworkHash: z.string(), lawHash: z.string(), bornAt: z.string() }))
70
- * .plan((p) => {
71
- * const actor = "user:" + p.owner;
72
- * birth({ workspace: p.child, genesisChain: [
73
- * { domain: "bootstrap", directiveId: "installDomain", actor, payload: { domainHash: p.frameworkHash }, domainHash: p.frameworkHash, domainPackageB64: "" },
74
- * { domain: "nomos", directiveId: "installDomain", actor, payload: { domainHash: p.lawHash }, domainHash: p.lawHash, domainPackageB64: "" },
75
- * { domain: "estate", directiveId: "seedEstateChild", actor, payload: { owner: p.owner, bornAt: p.bornAt } },
76
- * ] });
77
- * return [];
78
- * })
79
- * .births() // the kernel's run_birth_effect folds the recipe through the CHILD's own gate
80
- * .requires("creator"); // grant the parent's owner #creator (self-bound) — the birth authority
81
- * ```
59
+ * This is framework implementation plumbing. Application packages declare
60
+ * `birth(Aggregate, spec)` and never construct a recipe.
82
61
  */
83
62
  /**
84
63
  * A business thing that is important enough to have its own durable, sovereign life.
@@ -112,10 +91,10 @@ export interface BusinessBirthSpec<
112
91
  readonly namespace?: string;
113
92
  }
114
93
 
115
- /** @internal Framework lane: record an already-lowered child recipe during a directive plan. Tenant law
116
- * should declare `birth(Aggregate, spec)` and let Nomos own the recipe, identity and recovery machinery. */
94
+ /** @internal Record an already-lowered child recipe during a framework directive plan. Application law
95
+ * declares `birth(Aggregate, spec)` and leaves the recipe, identity, and recovery machinery to Nomos. */
117
96
  export function birth(recipe: BirthRecipe): void;
118
- /** Tenant lane: declare that one business aggregate is born as a durable workspace root. */
97
+ /** Declare that one business aggregate is given its own durable life. */
119
98
  export function birth<P extends Record<string, unknown>, F extends Record<string, Field>>(
120
99
  aggregate: AggregateHandle<string, F>,
121
100
  spec: BusinessBirthSpec<P, F>,
@@ -184,39 +163,19 @@ interface MintedRef {
184
163
 
185
164
  /**
186
165
  * @deprecated Tenant law should declare `birth(Aggregate, spec)`. This framework helper remains for the
187
- * built-in workspace laws that implement that declaration.
188
- *
189
- * `birth.keyed(...)` — THE way to birth a child workspace. A workspace exists to be USED, and using it means
190
- * FINDING IT AGAIN, so its name is ALWAYS derived from a `key` the caller owns (a business id, an owner uid)
191
- * via {@link workspaceNameForKey}. The client re-derives the SAME name with `deriveWorkspaceName(namespace,
192
- * key)` — so the born workspace is addressable from the key alone, with zero persistence. Same key ⇒ same
193
- * workspace (re-birth is idempotent). This is the only birth verb you need.
166
+ * built-in framework laws that implement that declaration.
194
167
  *
195
- * ```ts
196
- * export const birthEstate = directive("birthEstate")
197
- * .creates(EstateBirth)
198
- * .payload(z.object({ estateId: z.string(), owner: z.string(), frameworkHash: z.string(), lawHash: z.string(), bornAt: z.string() }))
199
- * .plan((p) => {
200
- * birth.keyed({ key: p.estateId, namespace: "estate", genesisChain: (ws) => [
201
- * { domain: "bootstrap", directiveId: "installDomain", actor: p.owner, payload: { domainHash: p.frameworkHash }, domainHash: p.frameworkHash, domainPackageB64: "" },
202
- * { domain: "nomos", directiveId: "installDomain", actor: p.owner, payload: { domainHash: p.lawHash }, domainHash: p.lawHash, domainPackageB64: "" },
203
- * { domain: "estate", directiveId: "seedEstate", actor: p.owner, payload: { estateId: p.estateId, workspaceName: ws, bornAt: p.bornAt } },
204
- * ] });
205
- * return [];
206
- * })
207
- * .births().requires("estateCreator");
208
- * // app (Dart / TS): final ws = client.deriveWorkspaceName('estate', estateId); // open it, any time, any device
209
- * ```
168
+ * Internal compatibility helper: derives a child address from a stable key. Application packages use
169
+ * `birth(Aggregate, spec)`; generated clients expose only `birth(businessFacts)`.
210
170
  */
211
171
  export const birthKeyed = ({
212
172
  key,
213
173
  namespace,
214
174
  genesisChain,
215
175
  }: {
216
- /** The id you already own that this workspace is FOR (an estateId, an owner uid). The client addresses the
217
- * born workspace by re-deriving its name from this same key — so pick a key the client will have in hand. */
176
+ /** A stable id from which the framework can re-derive the durable address. */
218
177
  key: string;
219
- /** The workspace-name namespace (e.g. `"estate"` → `estate-<hash>`). Groups a domain's children. */
178
+ /** Internal address namespace. */
220
179
  namespace: string;
221
180
  genesisChain: GenesisChainOrBuilder;
222
181
  }): string => {
@@ -258,7 +258,7 @@ export function expandBusinessBirthExports<M extends Record<string, unknown>>(
258
258
  if (declarations.length > 1) {
259
259
  throw new Error(
260
260
  `domain '${domain}' declares ${declarations.length} business births; one generated birth(payload) cannot be ` +
261
- "ambiguous — model one workspace root per domain",
261
+ "ambiguous — model one born aggregate root per domain",
262
262
  );
263
263
  }
264
264
  const lowered = lowerOne(declarations[0]!, domain);
@@ -348,8 +348,8 @@ export function generateDartBridgeClient(mod: DomainModule, opts: DartBridgeClie
348
348
  }).businessBirth;
349
349
  if (businessBirth !== undefined) {
350
350
  methods.push(
351
- ` /// Give one ${businessBirth.aggregateId} its own durable life. Nomos owns identity proof, signer`,
352
- ` /// seating, provenance, persistence and recovery; the app supplies only business facts.`,
351
+ ` /// Give one ${businessBirth.aggregateId} its own durable life. Nomos owns identity, authorship,`,
352
+ ` /// provenance, persistence and recovery; the app supplies only business facts.`,
353
353
  ` Future<NomosRef> birth(${payloadClass} payload) async {`,
354
354
  ` final principal = actor ?? bridge.principal;`,
355
355
  ` if (principal == null || principal.trim().isEmpty) {`,
@@ -1720,6 +1720,9 @@ interface DiscoveredGenesisStep {
1720
1720
  * synthesized payload (the synthesizer only produces `sample-*` placeholders, which the child install
1721
1721
  * would refuse). */
1722
1722
  export interface ChildBirthLeg {
1723
+ /** Present for the one application-facing `birth(Aggregate, spec)` declaration. Proof renderers use the
1724
+ * business noun and keep the lowered framework ceremony out of normal output. */
1725
+ readonly businessAggregateId?: string;
1723
1726
  /** The domain the `.births()` directive lives in. */
1724
1727
  readonly parentDomain: string;
1725
1728
  /** The `.births()` directive id the parent drives to birth the child. */
@@ -2021,9 +2024,11 @@ export function discoverChildBirthLegOrReason(
2021
2024
  if (frameworkHashField !== undefined) delete birthPayload[frameworkHashField];
2022
2025
  if (lawHashField !== undefined) delete birthPayload[lawHashField];
2023
2026
 
2027
+ const businessAggregateId = (birthDir as unknown as { businessBirth?: { aggregateId?: string } }).businessBirth?.aggregateId;
2024
2028
  const leg: ChildBirthLeg = {
2025
2029
  parentDomain,
2026
2030
  birthDirectiveId: birthDir.id,
2031
+ ...(businessAggregateId !== undefined ? { businessAggregateId } : {}),
2027
2032
  birthPayload,
2028
2033
  birthAutoStamped: synth.autoStamped,
2029
2034
  ...(actorField !== undefined ? { birthActorField: actorField } : {}),
@@ -2961,19 +2961,16 @@ async function main(): Promise<void> {
2961
2961
  console.log(` parses on every kernel (larger deploy body; may need the signed-upload deploy lane).`);
2962
2962
  }
2963
2963
  console.log(``);
2964
- console.log(`deploy (Nomos Cloud):`);
2965
- console.log(` githolon login --agent && githolon ws create <ws> && githolon deploy <ws> # no secret — deploy is OPEN, kernel-judged at the offer gate`);
2966
- console.log(` # raw lane: curl -X POST -H 'content-type: application/json' -H 'x-nomos-principal: <your-auth-uid>' \\`);
2967
- console.log(` # --data-binary @${rel(deployPath)} https://nomos.captainapp.co.uk/v2/workspaces/<ws>/domains`);
2964
+ console.log(`your business path:`);
2968
2965
  if (proofPath !== undefined) {
2969
- console.log(`prove it OFFLINE first: npx githolon proof # the generated proof's offline legs on a LOCAL holon (no cloud workspace)`);
2970
- console.log(` inner loop: npx githolon dev # watch -> recompile -> law live locally -> offline proof, on every save`);
2971
- console.log(` then the cloud loop: npx githolon proof --live # throwaway workspace, retired on exit (--keep keeps it)`);
2966
+ console.log(` npx githolon proof # generated birth -> verify -> durable restore -> business read-back`);
2967
+ console.log(` npx githolon dev # rerun that proof on every save`);
2968
+ console.log(` npx githolon proof --live # the same business proof against Nomos Cloud`);
2972
2969
  if (proofDomains.length > 1) {
2973
2970
  console.log(` this package proves ${proofDomains.length} domains (${proofDomains.join(", ")}) — default '${proofDomains[0]}'; pick another: npx githolon proof --domain <key>`);
2974
2971
  }
2975
2972
  } else {
2976
- console.log(`prove it: npm run e2e # offline write -> sync -> admission -> cloud query, live`);
2973
+ console.log(` add a business birth declaration to generate an end-to-end proof`);
2977
2974
  }
2978
2975
 
2979
2976
  if (analyzeFlag) runDartAnalyze(dartOut);