1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 | {;; Exact pins — the Closure compiler version rides on these two, and the
;; committed stack-a/dist + stack-b/dist must rebuild byte-identical
;; (deploy/check-dist.sh).
;;
;; ============================================================================
;; THE CLASSPATH LAW — and the two npm roots that finally let it be whole.
;;
;; THE RULE: our own kits are ClojureScript libraries and are consumed AS
;; SOURCE — their `src` on the classpath, required under their real
;; `ardegazu.*` namespace names, one compiled copy per build. Foreign packages
;; (@tensorflow/*, @libp2p/*, @noble/*, multiformats, node:*) stay string
;; requires: that is ordinary JS interop, and it is not what this is about.
;; Never require a kit's `index` namespace — those are re-export shims for the
;; ESM dist surface and requiring one links the whole kit whether used or not.
;;
;; ONE COMPILE, TWO NPM ROOTS. peer-kit and rooms-kit each carry a NETWORK
;; STACK built on a different generation of libp2p, and this process tree runs
;; both; two builds of libdatachannel in one process abort it (house rule 11).
;; Isolation used to be an ACCIDENT: libp2p v3 hoisted at bot/node_modules,
;; v2 nested inside bot/node_modules/ardegazu-rooms-kit/, and only the fact
;; that rooms-kit's DIST files physically live in that directory made their
;; bare `import "libp2p"` land on v2. Node resolves a bare specifier from the
;; IMPORTING FILE's directory upward, so the fix is a file-location fix:
;;
;; stack-a/ package.json + node_modules libp2p v3 family, peer-kit,
;; dist/main.js dist/rl/train.js dist/fleet/link.js
;; stack-b/ package.json + node_modules libp2p v2 family, rooms-kit,
;; dist/worker.js
;;
;; Each bundle sits INSIDE its own root, so every bare import it emits —
;; `libp2p`, `helia`, `@orbitdb/core`, `multiformats`, `@noble/curves` —
;; resolves in that stack's tree and can never reach the other generation.
;; Compile time is still ONE project: one deps.edn, one shadow-cljs.edn, one
;; classpath. Only the emitted files' locations and the npm trees differ. That
;; is the whole trick, and it is why peer-kit and rooms-kit no longer need an
;; exception: THERE IS NO EXCEPTION LEFT. Every kit this repo consumes — id,
;; social, wallet, train, peer, rooms — is ClojureScript source on the paths
;; below, and no bundle imports one as an npm dist. check-dist asserts it.
;;
;; WHERE EACH SOURCE TREE IS READ FROM, and why that column matters: a kit's
;; sources are read out of the npm root that also owns its RUNTIME, so the
;; foreign imports its compiled code emits resolve against the tree the pin
;; was solved for. rooms-kit, id-kit, social-kit, wallet-kit, banca and bursa
;; are stack-b's; peer-kit and train-kit are stack-a's (train-kit's
;; @tensorflow/tfjs-node peer lives there). id-kit and social-kit are read
;; from stack-b although BOTH stacks compile them: they are native-free, the
;; two roots hold the same sha, and one path means one compiled copy of the
;; ONE identity implementation the whole suite shares.
;; A path is INERT until something requires the namespaces behind it, and
;; consumption is TRANSITIVE — wallet-kit requires ardegazu.id.* and
;; ardegazu.social.canon, peer-kit requires ardegazu.social.{friends,presence}
;; and ardegazu.id.xkey — so the full closure is listed, not just what src/bot
;; names directly.
;;
;; WHAT THE PATHS BELOW ADMIT, per source tree:
;;
;; banca banca.lib.{fold,protocol,view,link,wallet,mailbox}, banca.config,
;; banca.{fx,wire} (the mailbox lib's own leaves; both require-free
;; or js-only)
;; bursa bursa.lib.{match,trade,artifacts,protocol,view,floor,mailbox},
;; bursa.config, bursa.{fx,wire}
;; peer the whole kit, but STACK A ONLY
;; rooms the whole kit in the :worker build; in a STACK-A build, the two
;; webcrypto leaves ardegazu.rooms.js and ardegazu.rooms.lib.crypto
;; AND NOTHING ELSE (the vendored banca/bursa mailbox libs require
;; them, and the bursa gym rides on those libs)
;; id / social / wallet / train
;; the whole kits; bind the DEFINING namespace, never `*.index`
;;
;; THE ONE RULE THE TWO ROOTS DO NOT REPEAL — and it is now the ONLY thing
;; standing between the fleet and two libdatachannels in one process. The
;; roots make each stack's own imports resolve correctly; they do NOT stop
;; :main from requiring ardegazu.rooms.lib.net, which would emit
;; `import "libp2p"` from stack-a/dist and get v3. Both names are identical in
;; both stacks, so no import-name grep can see that mistake. What can:
;; deploy/check-dist.sh counts ardegazu.rooms.* namespaces in the stack-A
;; bundles (only the two leaves allowed) and ardegazu.peer.* in stack B's
;; (none), forbids each stack the packages that exist only in the other's
;; generation, and resolves every bare import of every bundle against its own
;; root. Three angles on one law.
;;
;; ardegazu.rooms.lib.crypto is on the STACK-A allowed list because the
;; vendored mailbox libs (banca/bursa lib/mailbox — chat's canon) require it,
;; and it is a webcrypto-only leaf: its requires are ardegazu.rooms.js +
;; clojure.string. The mailbox libs also value-import multiformats (CID
;; parsing — pure JS, native-free), which stack-b declares explicitly at the
;; version the fleet already runs. There is no cross-copy question left inside
;; a bundle: one classpath means one RoomCrypto, one AtRestCipher, one
;; Identity per build. What still crosses copies is the wire, which is the
;; only place it ever belonged — the seed and the signature bytes, verified
;; against the other implementation's, never an object's class.
;; ============================================================================
:paths ["src"
"stack-a/node_modules/ardegazu-peer-kit/src"
"stack-b/node_modules/ardegazu-rooms-kit/src"
"stack-b/node_modules/ardegazu-id-kit/src"
"stack-b/node_modules/ardegazu-social-kit/src"
"stack-b/node_modules/ardegazu-wallet-kit/src"
"stack-a/node_modules/ardegazu-train-kit/src"
"stack-b/node_modules/ardegazu-banca/client/src"
"stack-b/node_modules/ardegazu-bursa/client/src"]
;; promesa: the ONE async idiom the vendored mailbox libs are written in —
;; the same pin as banca's and bursa's own client deps.edn, so the classpath
;; compiles the identical expansion the browsers ship
:deps {org.clojure/clojurescript {:mvn/version "1.12.134"}
thheller/shadow-cljs {:mvn/version "3.3.6"}
funcool/promesa {:mvn/version "12.0.1"}}
:aliases
{:dev {:extra-deps {cider/cider-nrepl {:mvn/version "0.59.0"}}}}}
|