create-githolon 0.96.0 → 0.97.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/index.mjs CHANGED
@@ -1,106 +1,77 @@
1
1
  #!/usr/bin/env node
2
- // `npm create githolon <dir>` — scaffold a Nomos domain package (the starter
3
- // guestbook domain + compile config + live e2e) into <dir> and init it as a
4
- // git repo. The holon itself is MINTED LOCALLY after compile (`githolon ledger
5
- // init holon` — genesis + your law under YOUR identity, verified by the same
6
- // wasm gate the cloud runs), so it is yours from the first byte. Plain node,
7
- // zero dependencies; the heavy lifting (compile, codegen, the engine) lives in
8
- // @githolon/dsl and githolon and arrives with the scaffold's `npm install`.
9
- //
10
- // Everything scaffolded here belongs to the user — see LICENSE.md ("You may /
11
- // keep everything that's yours").
2
+
3
+ // src/index.ts
12
4
  import { spawnSync } from "node:child_process";
13
5
  import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
14
6
  import path from "node:path";
15
7
  import { fileURLToPath } from "node:url";
16
-
17
- const TEMPLATE = path.join(path.dirname(fileURLToPath(import.meta.url)), "template");
18
-
19
- const args = process.argv.slice(2);
8
+ var HERE = path.dirname(fileURLToPath(import.meta.url));
9
+ var TEMPLATE = path.join(HERE, "template");
10
+ var NOMOS_VERSION = (() => {
11
+ try {
12
+ return JSON.parse(readFileSync(path.join(HERE, "package.json"), "utf8")).version || "latest";
13
+ } catch {
14
+ return "latest";
15
+ }
16
+ })();
17
+ var args = process.argv.slice(2);
20
18
  if (args.includes("-h") || args.includes("--help")) {
21
19
  process.stdout.write(
22
- "create-githolon — scaffold a Nomos domain package\n\n" +
23
- "Usage:\n npm create githolon <dir> (or: npx create-githolon <dir>)\n\n" +
24
- "Scaffolds the starter domain + compile config + live e2e into <dir>\n" +
25
- "(default: my-holon-app) and inits a git repo. After `githolon compile`,\n" +
26
- "`githolon ledger init holon` mints YOUR holon locally — verified by the\n" +
27
- "same wasm gate the cloud runs, ready to birth by git push.\n\n" +
28
- "Flags:\n --no-git skip git init\n",
20
+ "create-githolon \u2014 scaffold a Nomos domain package\n\nUsage:\n npm create githolon <dir> (or: npx create-githolon <dir>)\n\nScaffolds the starter domain + compile config + live e2e into <dir>\n(default: my-holon-app) and inits a git repo. After `githolon compile`,\n`githolon ledger init holon` mints YOUR holon locally \u2014 verified by the\nsame wasm gate the cloud runs, ready to birth by git push.\n\nFlags:\n --no-git skip git init\n"
29
21
  );
30
22
  process.exit(0);
31
23
  }
32
- const noGit = args.includes("--no-git");
33
- const dirArg = args.find((a) => !a.startsWith("-"));
34
-
35
- const targetDir = path.resolve(process.cwd(), dirArg ?? "my-holon-app");
36
- const appName = path
37
- .basename(targetDir)
38
- .toLowerCase()
39
- .replace(/[^a-z0-9-_.]+/g, "-")
40
- .replace(/^[-_.]+|[-_.]+$/g, "");
24
+ var noGit = args.includes("--no-git");
25
+ var dirArg = args.find((a) => !a.startsWith("-"));
26
+ var targetDir = path.resolve(process.cwd(), dirArg ?? "my-holon-app");
27
+ var appName = path.basename(targetDir).toLowerCase().replace(/[^a-z0-9-_.]+/g, "-").replace(/^[-_.]+|[-_.]+$/g, "");
41
28
  if (!appName) {
42
29
  console.error(`create-githolon: '${path.basename(targetDir)}' does not reduce to a valid package name`);
43
30
  process.exit(1);
44
31
  }
45
-
46
32
  if (existsSync(targetDir) && readdirSync(targetDir).length > 0) {
47
33
  console.error(`create-githolon: refusing to scaffold into non-empty directory: ${targetDir}`);
48
34
  process.exit(1);
49
35
  }
50
-
51
36
  mkdirSync(targetDir, { recursive: true });
52
37
  cpSync(TEMPLATE, targetDir, { recursive: true });
53
-
54
- // npm strips dotfiles from published packages — the template ships `gitignore`
55
- // and the scaffold restores the dot.
56
38
  renameSync(path.join(targetDir, "gitignore"), path.join(targetDir, ".gitignore"));
57
-
58
- // Same dotfile-restore for the VS Code workspace recommendation: the template ships
59
- // `vscode/` (no dot; a leading-dot dir does not reliably survive `npm publish`), and
60
- // the scaffold restores `.vscode/` so opening the project prompts installing the
61
- // Nomos Law extension (the author-time check gate as red squiggles while typing).
62
39
  if (existsSync(path.join(targetDir, "vscode"))) {
63
40
  renameSync(path.join(targetDir, "vscode"), path.join(targetDir, ".vscode"));
64
41
  }
65
-
66
- // Parameterize the scaffold to the app name. The generated typed client + its baked
67
- // hash const are NAMED off the package name (`__APP_NAME__`): the artifact filename
68
- // keeps the raw name (build/<app>.client.ts), the hash SYMBOL normalizes it to
69
- // UPPER_SNAKE (the same transform `githolon compile` uses — see codegen_ts.ts). The
70
- // client FACTORY (`todoClient`) is named off the DOMAIN key, which stays `todo`.
71
- const appHash = `${appName.replace(/[-\s]+/g, "_").replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase()}_DOMAIN_HASH`;
72
- const subst = (s) => s.replaceAll("__APP_NAME__", appName).replaceAll("__APP_HASH__", appHash);
42
+ var appHash = `${appName.replace(/[-\s]+/g, "_").replace(/([a-z0-9])([A-Z])/g, "$1_$2").toUpperCase()}_DOMAIN_HASH`;
43
+ var subst = (s) => s.replaceAll("__APP_NAME__", appName).replaceAll("__APP_HASH__", appHash).replaceAll("__NOMOS_VERSION__", NOMOS_VERSION);
73
44
  for (const f of ["package.json", "README.md", "nomos.package.mjs", "CLAUDE.md", "domains/todo.ts", "test/e2e.mts"]) {
74
45
  const p = path.join(targetDir, f);
75
46
  if (existsSync(p)) writeFileSync(p, subst(readFileSync(p, "utf8")), "utf8");
76
47
  }
77
-
78
- const git = (cmd) => spawnSync("git", cmd, { cwd: targetDir, stdio: "ignore" }).status === 0;
79
-
80
- // git init. Degrades gracefully: no git leaves a perfectly usable scaffold.
81
- let gitInited = false;
48
+ var git = (cmd) => spawnSync("git", cmd, { cwd: targetDir, stdio: "ignore" }).status === 0;
49
+ var gitInited = false;
82
50
  if (!noGit) {
83
51
  gitInited = git(["init", "-b", "main"]) || git(["init"]);
84
52
  if (gitInited) {
85
53
  git(["add", "-A"]);
86
- // Identity fallback keeps the initial commit working on unconfigured machines.
87
- git(["commit", "-m", "scaffold: create-githolon starter"]) ||
88
- git(["-c", "user.name=create-githolon", "-c", "user.email=create-githolon@nomos", "commit", "-m", "scaffold: create-githolon starter"]);
54
+ git(["commit", "-m", "scaffold: create-githolon starter"]) || git(["-c", "user.name=create-githolon", "-c", "user.email=create-githolon@nomos", "commit", "-m", "scaffold: create-githolon starter"]);
89
55
  }
90
56
  }
91
-
92
- const rel = path.relative(process.cwd(), targetDir) || ".";
57
+ var rel = path.relative(process.cwd(), targetDir) || ".";
93
58
  process.stdout.write(
94
- `\nScaffolded ${appName} into ${rel}/${gitInited ? " (git repo)" : ""}\n` +
95
- `\nRead docs/01-mental-model.md first — the docs travel with you, offline.\n` +
96
- `\nNext:\n` +
97
- ` cd ${rel}\n` +
98
- ` npm install\n` +
99
- ` npx githolon compile # → build/: deployable package + manifests + typed client + a generated proof\n` +
100
- ` npx githolon proof # run that proof live — GENERATED from your own law, no test rewriting\n` +
101
- ` npx githolon login --agent # a verified identity, no browser\n\n` +
102
- `Then pick a path (README.md walks both):\n` +
103
- ` A) npx githolon ws create <ws> && npx githolon deploy <ws>\n` +
104
- ` B) npx githolon ledger init holon # YOUR holon, minted + verified LOCALLY\n` +
105
- ` cd holon && npx githolon git remote <ws> && git push nomos main\n`,
59
+ `
60
+ Scaffolded ${appName} into ${rel}/${gitInited ? " (git repo)" : ""}
61
+
62
+ Read docs/01-mental-model.md first \u2014 the docs travel with you, offline.
63
+
64
+ Next:
65
+ cd ${rel}
66
+ npm install
67
+ npx githolon compile # \u2192 build/: deployable package + manifests + typed client + a generated proof
68
+ npx githolon proof # run that proof live \u2014 GENERATED from your own law, no test rewriting
69
+ npx githolon login --agent # a verified identity, no browser
70
+
71
+ Your law compiles + proves OFFLINE today (compile + proof above \u2014 no cloud, no account).
72
+ To run it LIVE, deploy to a workspace you own: a workspace is born by its PARENT (a platform
73
+ you control births homes/children \u2014 birthHome/birthChild). There is no host-side create \u2014 the
74
+ flat 'ws create' lane is retired (orphanless holarchy). See docs/04-cloud.md for the birth-on-
75
+ parent flow; self-serve keyless birth-under-root is in flight.
76
+ `
106
77
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-githolon",
3
- "version": "0.96.0",
3
+ "version": "0.97.1",
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",
@@ -18,5 +18,16 @@
18
18
  ],
19
19
  "publishConfig": {
20
20
  "access": "public"
21
+ },
22
+ "scripts": {
23
+ "build": "tsx build.ts",
24
+ "prepublishOnly": "tsx build.ts",
25
+ "typecheck": "tsc --noEmit"
26
+ },
27
+ "devDependencies": {
28
+ "esbuild": "^0.24.0",
29
+ "tsx": "^4.19.2",
30
+ "typescript": "^5.6.3",
31
+ "@types/node": "^25.9.2"
21
32
  }
22
33
  }
@@ -43,8 +43,9 @@ before serving anything. Authority lives in the git; no holon outranks another.
43
43
  npx githolon ledger init holon # mint + assert locally: chain VALID, head <h>, under YOUR uid
44
44
  npx githolon ledger verify holon # re-assert any time
45
45
  cd holon
46
- npx githolon git remote <ws> # wires the remote + credential helper; mints + stores the owner secret
47
- git push nomos main # the upload birth — the cloud re-derives the verdict, byte-identical adoption
46
+ npx githolon ws create <ws> # birth the workspace (its parent's offer-effect); no secret minted
47
+ npx githolon git remote <ws> # wire the remote + credential helper for syncing
48
+ git push nomos refs/heads/session/<id> # sync your writes to the edge (main is not push-writable)
48
49
  npx githolon deploy <ws> # idempotent (alreadyInstalled) + stages the read manifests so queries route
49
50
  cd ..
50
51
  ```
@@ -19,29 +19,24 @@ the principal births will ride; sessions auto-refresh from
19
19
 
20
20
  ## Two deploy lanes, one destination
21
21
 
22
- **Path A — deploy your law** (the cloud births the workspace):
22
+ **Deploy your law** (the cloud births the workspace by its parent's offer-effect):
23
23
 
24
24
  ```bash
25
25
  npx githolon ws create <ws> # birth; NO secret is minted — ownership is a law fact in the chain
26
26
  npx githolon deploy <ws> # POST build/<pkg>.deploy.json, authenticated as your principal
27
27
  ```
28
28
 
29
- **Path B — the upload birth** (you birth it, the cloud verifies):
30
-
31
- ```bash
32
- npx githolon ledger init holon
33
- cd holon && npx githolon git remote <ws> && git push nomos main
34
- ```
35
-
36
- Both end in the same place — all holons are equal in authority; the chain
37
- proves itself either way ([05-superpowers.md](./05-superpowers.md) walks B).
29
+ A workspace is born ONLY by its PARENT authoring its birth (an offer-effect that records the
30
+ child in the parent's own chain). There is no "push a repo to create a workspace" — pushing
31
+ `refs/heads/main` to an unborn name is refused. You sync your work by pushing session branches
32
+ (`refs/heads/session/<client-id>`) to an EXISTING workspace; child workspaces you author offline
33
+ (e.g. an estate under a home in local custody) materialize on the cloud when you sync the parent.
38
34
 
39
35
  ## Ownership
40
36
 
41
- There is no host secret. Ownership is a LAW FACT bound IN THE CHAIN —
42
- `sha256(the push password)` written onto the law record at the upload birth (push
43
- with no password ⇒ born OPEN). Born-ness derives from custody (the ledger has a
44
- `main`); `/boot` returns no secret. DEPLOY write-authority is judged by the
37
+ There is no host secret. Ownership is a LAW FACT bound IN THE CHAIN — the principal the parent's
38
+ birth records as the owner (e.g. `HomeOwner.principal`). Born-ness derives from custody (the ledger
39
+ has a `main`); `/boot` returns no secret. DEPLOY write-authority is judged by the
45
40
  KERNEL at the offer gate — you authenticate as a principal the law grants deploy
46
41
  authority (`x-nomos-auth`, or transitionally `x-nomos-principal`), not a Bearer
47
42
  secret. End-user apps carry no credential: reads and session pushes are open,
@@ -16,26 +16,29 @@ identity>` — and verifies the chain with the SAME byte-identical wasm gate the
16
16
  cloud runs. This is not a mock or a dev server. It is a holon, born valid,
17
17
  and you can assert that yourself, offline, before any network exists.
18
18
 
19
- ## The upload birth — the cloud re-derives YOUR verdict
19
+ ## Offline birth — the parent births the child, the cloud re-derives it on sync
20
+
21
+ A workspace is born ONLY by its PARENT authoring its birth. You don't push a repo to create a
22
+ workspace; you author the birth on a parent you hold, and the child materializes when the parent
23
+ syncs (or when you offer the birth to the parent's edge online). A home you hold in local custody
24
+ can birth an estate OFFLINE — no network — and the cloud materializes that estate, byte-identical,
25
+ the moment the home syncs:
20
26
 
21
27
  ```bash
22
28
  cd holon
23
- npx githolon git remote <ws> # wires the remote + credential helper, mints the owner secret
24
- git push nomos main # stock git; the credential helper answers the 401
29
+ npx githolon git remote <ws> # wire the remote + credential helper for THIS workspace
30
+ git push nomos refs/heads/session/<id> # sync your writes (incl. any births you authored) to the edge
25
31
  ```
26
32
 
27
- Pushing `refs/heads/main` to an unborn workspace births it FROM YOUR REPO. The
28
- cloud replay-verifies the whole chain from genesis — contiguity, every intent
29
- re-admitted against the state folded from the chain prefix, every plan re-run
30
- and byte-compared — and re-derives your exact local verdict: same head, same
31
- plans. Valid ⇒ custody adopts your head BYTE-IDENTICAL (no re-seal), and
32
- sha256 of your push password becomes the owner credential. Invalid ⇒ archived
33
- under `refs/heads/refused/`, the workspace stays unborn, the verdict rides
34
- `githolon ws status <ws>`. The pushed bytes buy nothing; the chain proves
35
- itself. The git holon executes — and thus validates — itself.
36
-
37
- Why this matters: deployment is `git push`, the audit trail is `git log`, and
38
- "does the cloud agree with my machine?" is a checkable equation, not a hope.
33
+ The cloud replay-verifies every synced intent — contiguity, each intent re-admitted against the
34
+ state folded from the chain prefix, every plan re-run and byte-compared — and re-derives your exact
35
+ local verdict: same head, same plans. A birth intent's consequence is the child, materialized in
36
+ cloud custody with an immutable `nomos-birth-record` on the parent (so the whole tree is walkable
37
+ from root — no orphans). Pushing `refs/heads/main` to an unborn name is REFUSED: the pushed bytes
38
+ buy nothing; a workspace comes to exist through its parent's law, not a push.
39
+
40
+ Why this matters: authorship is `git log`, "does the cloud agree with my machine?" is a checkable
41
+ equation, and every workspace's parentage is a verifiable ledger fact — no host says what exists.
39
42
 
40
43
  ## Byte-identical wasm everywhere
41
44
 
@@ -11,12 +11,12 @@
11
11
  "typecheck": "tsc --noEmit"
12
12
  },
13
13
  "dependencies": {
14
- "@githolon/dsl": "^0.16.0",
15
- "@githolon/client": "^0.16.0",
14
+ "@githolon/dsl": "^__NOMOS_VERSION__",
15
+ "@githolon/client": "^__NOMOS_VERSION__",
16
16
  "zod": "^4.4.3"
17
17
  },
18
18
  "devDependencies": {
19
- "githolon": "^0.16.0",
19
+ "githolon": "^__NOMOS_VERSION__",
20
20
  "@types/node": "^25.9.2",
21
21
  "tsx": "^4.19.2",
22
22
  "typescript": "^5.6.3"