create-githolon 0.18.0 → 0.19.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": "create-githolon",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "type": "module",
5
5
  "description": "Scaffold a Nomos domain package: the starter domain + compile config + live e2e. `npm create githolon my-app`.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -0,0 +1,78 @@
1
+ # Birthing child workspaces (law-at-birth)
2
+
3
+ A directive in your law can **birth a child workspace** that is born already running its own domain law.
4
+ A home births estate children; a platform births workspaces; root births platforms — all the **same one
5
+ way**. You do *not* ask Nomos for a new primitive and you do *not* hand a finished workspace to the cloud.
6
+
7
+ ## How it works (birth is a kernel concern, defined by the ledger)
8
+
9
+ Your directive declares `.births()` and, in its `plan`, authors the child's **genesis recipe** — the
10
+ ordered intents the child will run — then calls `birth({ workspace, genesisChain })`. That's it. When the
11
+ parent's offer is admitted, the kernel's birth offer-effect:
12
+
13
+ 1. spawns the child's (empty) custody,
14
+ 2. **installs the child's law in-chain** and folds the genesis recipe **through the child's own gate**,
15
+ 3. so the child **self-validates from intent 0** — it is not trusted, it proves itself.
16
+
17
+ The host installs nothing and decides nothing. The recipe is a **ledger fact**, not a runtime trick.
18
+
19
+ ## The leaf recipe = two installs + your seed
20
+
21
+ A leaf child (a home, an estate item) is born with exactly:
22
+
23
+ ```
24
+ [ bootstrap/installDomain(<frameworkHash>), // the bootstrap controller (bytes-by-hash, kernel-resolved)
25
+ nomos/installDomain(<lawHash>), // YOUR child's domain law package
26
+ <your own seed step(s)> ] // e.g. seed the owner / initial state
27
+ ```
28
+
29
+ `frameworkHash` + `lawHash` are the content hashes of the two packages, pinned at compile time (the kernel
30
+ resolves the bytes from custody by hash — they are never shipped on the wire).
31
+
32
+ ## Copy `birthHome` — the canonical template
33
+
34
+ `birthHome` (in `@githolon/dsl`'s framework) is exactly this pattern for the **home** domain. To birth an
35
+ **estate child** (or any leaf running your law), copy it and swap the seed:
36
+
37
+ ```ts
38
+ import { directive, birth, z } from "@githolon/dsl";
39
+
40
+ export const birthEstateChild = directive("birthEstateChild")
41
+ .creates(EstateChild) // the child lineage record on YOUR chain
42
+ .payload(z.object({
43
+ child: z.string().min(1), // the child workspace name
44
+ owner: z.string().min(1), // the verified owner (a user:<uid> subject)
45
+ frameworkHash: z.string().min(1), // pinned at your governance compile
46
+ lawHash: z.string().min(1), // your ESTATE domain law package hash
47
+ bornAt: z.string().min(1), // ISO-8601, caller-stamped (determinism)
48
+ }))
49
+ .plan((p) => {
50
+ const actor = "user:" + p.owner;
51
+ birth({
52
+ workspace: p.child,
53
+ genesisChain: [
54
+ { domain: "bootstrap", directiveId: "installDomain", actor, payload: { domainHash: p.frameworkHash }, domainHash: p.frameworkHash, domainPackageB64: "" },
55
+ { domain: "nomos", directiveId: "installDomain", actor, payload: { domainHash: p.lawHash }, domainHash: p.lawHash, domainPackageB64: "" },
56
+ { domain: "estate", directiveId: "seedEstateChild", actor, payload: { owner: p.owner, bornAt: p.bornAt } },
57
+ ],
58
+ });
59
+ return [];
60
+ })
61
+ .births() // declares the birth — the kernel folds the recipe
62
+ .requires("creator"); // the birth authority (see below)
63
+ ```
64
+
65
+ ## Authority — who may birth
66
+
67
+ `.requires("creator")` gates the birth on a relation tuple. Grant the home owner `#creator` on their own
68
+ home (self-bound at birth, the same way the owner is seeded) so a verified owner can birth their estate
69
+ children — and only their own. (Relations: `grant` / `writeTuple`, see `07-security.md`. Use whatever
70
+ relation models your policy; `creator` is the convention `birthChild` uses.)
71
+
72
+ ## What NOT to do
73
+
74
+ - **Don't ask for a "child-birth primitive."** It already exists — `.births()` + `birth(recipe)`. A home is
75
+ a first-class workspace; it births children exactly as root births platforms. Recursion is the law.
76
+ - **Don't hand-roll a second recipe *builder*** across your domains — keep the recipe inline (it's small)
77
+ or share one tiny helper *in your own code*; the framework deliberately keeps **one** birth verb.
78
+ - **Don't put a clock/random in the plan** — `bornAt` rides the payload (the timestamp doctrine).