@wenathlan/saddle 2.0.150 → 2.0.152

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.
Files changed (296) hide show
  1. package/Dockerfile +43 -23
  2. package/README.md +4 -4
  3. package/biome.jsonc +134 -0
  4. package/dist/App.d.ts +3 -0
  5. package/dist/App.js +50 -0
  6. package/dist/Sol/Sol.d.ts +3 -0
  7. package/dist/Sol/Sol.js +46 -0
  8. package/dist/Sol/agentbrowser/agentbrowser.d.ts +9 -0
  9. package/dist/Sol/agentbrowser/agentbrowser.js +121 -0
  10. package/dist/Sol/architecture/architecture.d.ts +9 -0
  11. package/dist/Sol/architecture/architecture.js +93 -0
  12. package/dist/Sol/compute/compute.d.ts +9 -0
  13. package/dist/Sol/compute/compute.js +22 -0
  14. package/dist/Sol/console/console.d.ts +15 -0
  15. package/dist/Sol/console/console.js +292 -0
  16. package/dist/Sol/dashboard/dashboard.d.ts +10 -0
  17. package/dist/Sol/dashboard/dashboard.js +181 -0
  18. package/dist/Sol/docs/docs.d.ts +9 -0
  19. package/dist/Sol/docs/docs.js +28 -0
  20. package/dist/Sol/home/home.d.ts +35 -0
  21. package/dist/Sol/home/home.js +239 -0
  22. package/dist/Sol/integrations/integrations.d.ts +9 -0
  23. package/dist/Sol/integrations/integrations.js +83 -0
  24. package/dist/Sol/intro/intro.d.ts +7 -0
  25. package/dist/Sol/intro/intro.js +102 -0
  26. package/dist/Sol/login/login.d.ts +16 -0
  27. package/dist/Sol/login/login.js +49 -0
  28. package/dist/Sol/notfound/notfound.d.ts +9 -0
  29. package/dist/Sol/notfound/notfound.js +15 -0
  30. package/dist/Sol/onboarding/onboarding.d.ts +25 -0
  31. package/dist/Sol/onboarding/onboarding.js +60 -0
  32. package/dist/Sol/playground/playground.d.ts +9 -0
  33. package/dist/Sol/playground/playground.js +127 -0
  34. package/dist/Sol/register/register.d.ts +16 -0
  35. package/dist/Sol/register/register.js +193 -0
  36. package/dist/Sol/shell/Shell.d.ts +124 -0
  37. package/dist/Sol/shell/Shell.js +335 -0
  38. package/dist/Sol/wingets/ComputeBootladder.d.ts +6 -0
  39. package/dist/Sol/wingets/ComputeBootladder.js +71 -0
  40. package/dist/Sol/wingets/ComputeModalitycatalog.d.ts +7 -0
  41. package/dist/Sol/wingets/ComputeModalitycatalog.js +71 -0
  42. package/dist/Sol/wingets/ConsoleApibadge.d.ts +7 -0
  43. package/dist/Sol/wingets/ConsoleApibadge.js +5 -0
  44. package/dist/Sol/wingets/ConsoleEdgelaw.d.ts +6 -0
  45. package/dist/Sol/wingets/ConsoleEdgelaw.js +36 -0
  46. package/dist/Sol/wingets/ConsoleEventstimeline.d.ts +19 -0
  47. package/dist/Sol/wingets/ConsoleEventstimeline.js +12 -0
  48. package/dist/Sol/wingets/ConsoleSnapshotcontrols.d.ts +8 -0
  49. package/dist/Sol/wingets/ConsoleSnapshotcontrols.js +8 -0
  50. package/dist/Sol/wingets/ConsoleSpecpanel.d.ts +21 -0
  51. package/dist/Sol/wingets/ConsoleSpecpanel.js +75 -0
  52. package/dist/Sol/wingets/ConsoleTerminal.d.ts +22 -0
  53. package/dist/Sol/wingets/ConsoleTerminal.js +77 -0
  54. package/dist/Sol/wingets/DashboardAccountpanel.d.ts +18 -0
  55. package/dist/Sol/wingets/DashboardAccountpanel.js +65 -0
  56. package/dist/Sol/wingets/DashboardAdminpanel.d.ts +6 -0
  57. package/dist/Sol/wingets/DashboardAdminpanel.js +90 -0
  58. package/dist/Sol/wingets/DashboardAuditlog.d.ts +8 -0
  59. package/dist/Sol/wingets/DashboardAuditlog.js +50 -0
  60. package/dist/Sol/wingets/DashboardCreatesandboxform.d.ts +10 -0
  61. package/dist/Sol/wingets/DashboardCreatesandboxform.js +71 -0
  62. package/dist/Sol/wingets/DashboardEventstimeline.d.ts +8 -0
  63. package/dist/Sol/wingets/DashboardEventstimeline.js +83 -0
  64. package/dist/Sol/wingets/DashboardGlobalsandboxestable.d.ts +8 -0
  65. package/dist/Sol/wingets/DashboardGlobalsandboxestable.js +57 -0
  66. package/dist/Sol/wingets/DashboardMeshnodestable.d.ts +8 -0
  67. package/dist/Sol/wingets/DashboardMeshnodestable.js +103 -0
  68. package/dist/Sol/wingets/DashboardSandboxlist.d.ts +10 -0
  69. package/dist/Sol/wingets/DashboardSandboxlist.js +163 -0
  70. package/dist/Sol/wingets/DashboardUserstable.d.ts +8 -0
  71. package/dist/Sol/wingets/DashboardUserstable.js +78 -0
  72. package/dist/Sol/wingets/HomeEntrygate.d.ts +23 -0
  73. package/dist/Sol/wingets/HomeEntrygate.js +73 -0
  74. package/dist/Sol/wingets/HomeMetricstrip.d.ts +9 -0
  75. package/dist/Sol/wingets/HomeMetricstrip.js +4 -0
  76. package/dist/Sol/wingets/HomeRuntimediagram.d.ts +1 -0
  77. package/dist/Sol/wingets/HomeRuntimediagram.js +22 -0
  78. package/dist/Sol/wingets/LoginForm.d.ts +19 -0
  79. package/dist/Sol/wingets/LoginForm.js +141 -0
  80. package/dist/Sol/wingets/RegisterPasswordconfirm.d.ts +13 -0
  81. package/dist/Sol/wingets/RegisterPasswordconfirm.js +16 -0
  82. package/dist/Sol/wingets/RegisterPasswordmeter.d.ts +19 -0
  83. package/dist/Sol/wingets/RegisterPasswordmeter.js +65 -0
  84. package/dist/Sol/wingets/RegisterUsernamerules.d.ts +11 -0
  85. package/dist/Sol/wingets/RegisterUsernamerules.js +16 -0
  86. package/dist/Sol/wingets/index.d.ts +39 -0
  87. package/dist/Sol/wingets/index.js +39 -0
  88. package/dist/alternatives.d.ts +508 -0
  89. package/dist/alternatives.js +950 -0
  90. package/dist/api.d.ts +154 -0
  91. package/dist/api.js +174 -0
  92. package/dist/auth.d.ts +268 -0
  93. package/dist/auth.js +476 -0
  94. package/dist/automation.d.ts +425 -0
  95. package/dist/automation.js +566 -0
  96. package/dist/browser.d.ts +561 -0
  97. package/dist/browser.js +1058 -0
  98. package/dist/capacitor.config.d.ts +45 -0
  99. package/dist/capacitor.config.js +48 -0
  100. package/dist/catalog.d.ts +43 -0
  101. package/dist/catalog.js +44 -0
  102. package/dist/cli.d.ts +16 -0
  103. package/dist/cli.js +168 -0
  104. package/dist/communication.d.ts +181 -0
  105. package/dist/communication.js +376 -0
  106. package/dist/compute.d.ts +1160 -0
  107. package/dist/compute.js +2272 -0
  108. package/dist/dashboardlib.d.ts +58 -0
  109. package/dist/dashboardlib.js +161 -0
  110. package/dist/db.d.ts +569 -0
  111. package/dist/db.js +1080 -0
  112. package/dist/distribution.d.ts +528 -0
  113. package/dist/distribution.js +810 -0
  114. package/dist/drizzle.config.d.ts +20 -0
  115. package/dist/drizzle.config.js +18 -0
  116. package/dist/edgelandes.d.ts +70 -0
  117. package/dist/edgelandes.host.d.ts +26 -0
  118. package/dist/edgelandes.host.js +1089 -0
  119. package/dist/edgelandes.inproc.d.ts +27 -0
  120. package/dist/edgelandes.inproc.js +952 -0
  121. package/dist/edgelandes.js +1133 -0
  122. package/dist/edgelandes.ninety.d.ts +31 -0
  123. package/dist/edgelandes.ninety.js +174 -0
  124. package/dist/edgelandes.virtual.d.ts +25 -0
  125. package/dist/edgelandes.virtual.js +629 -0
  126. package/dist/edgeplane.d.ts +114 -0
  127. package/dist/edgeplane.js +305 -0
  128. package/dist/examplelocaljob.d.ts +1 -0
  129. package/{docs/example-localjob.ts → dist/examplelocaljob.js} +0 -1
  130. package/dist/execution.d.ts +529 -0
  131. package/dist/execution.js +760 -0
  132. package/dist/family.d.ts +16 -0
  133. package/dist/family.js +42 -0
  134. package/dist/familyurl.d.ts +21 -0
  135. package/dist/familyurl.js +24 -0
  136. package/dist/format.d.ts +18 -0
  137. package/dist/format.js +59 -0
  138. package/dist/foundation.d.ts +172 -0
  139. package/dist/foundation.js +312 -0
  140. package/dist/index.d.ts +735 -0
  141. package/dist/index.js +1020 -0
  142. package/dist/integration.d.ts +235 -0
  143. package/dist/integration.js +228 -0
  144. package/dist/intelligence.d.ts +93 -0
  145. package/dist/intelligence.js +144 -0
  146. package/dist/isolation.d.ts +128 -0
  147. package/dist/isolation.js +95 -0
  148. package/dist/labels.d.ts +665 -0
  149. package/dist/labels.js +751 -0
  150. package/dist/localauth.d.ts +127 -0
  151. package/dist/localauth.js +413 -0
  152. package/dist/media.d.ts +343 -0
  153. package/dist/media.js +985 -0
  154. package/dist/mesh.d.ts +177 -0
  155. package/dist/mesh.js +468 -0
  156. package/dist/modalityregistry.d.ts +109 -0
  157. package/dist/modalityregistry.js +1386 -0
  158. package/dist/modes.d.ts +358 -0
  159. package/dist/modes.js +133 -0
  160. package/dist/onboardingstate.d.ts +79 -0
  161. package/dist/onboardingstate.js +282 -0
  162. package/dist/orchestrator.d.ts +1338 -0
  163. package/dist/orchestrator.js +4310 -0
  164. package/dist/packager/targetcli.js +4 -0
  165. package/dist/paths.d.ts +2 -0
  166. package/dist/paths.js +14 -0
  167. package/dist/performance.d.ts +415 -0
  168. package/dist/performance.js +826 -0
  169. package/dist/quantum.d.ts +809 -0
  170. package/dist/quantum.js +2072 -0
  171. package/dist/render.d.ts +380 -0
  172. package/dist/render.js +1072 -0
  173. package/dist/runall.d.ts +2 -0
  174. package/dist/runall.js +39 -0
  175. package/dist/runtimeprobe.d.ts +4 -0
  176. package/dist/runtimeprobe.js +8 -0
  177. package/dist/sandbox.d.ts +355 -0
  178. package/dist/sandbox.js +1721 -0
  179. package/dist/sandboxenvprofile.d.ts +29 -0
  180. package/dist/sandboxenvprofile.js +89 -0
  181. package/dist/sandboxprofile.d.ts +137 -0
  182. package/dist/sandboxprofile.js +241 -0
  183. package/dist/sandboxqueue.d.ts +108 -0
  184. package/dist/sandboxqueue.js +201 -0
  185. package/dist/sandboxquota.d.ts +121 -0
  186. package/dist/sandboxquota.js +236 -0
  187. package/dist/scheduler.d.ts +595 -0
  188. package/dist/scheduler.js +1258 -0
  189. package/dist/scriptlanes.d.ts +182 -0
  190. package/dist/scriptlanes.js +660 -0
  191. package/dist/scripts.buildengine.d.ts +1 -0
  192. package/dist/scripts.buildengine.js +39 -0
  193. package/dist/scripts.securitygate.d.ts +1 -0
  194. package/dist/scripts.securitygate.js +68 -0
  195. package/dist/scripts.validateflatnative.d.ts +1 -0
  196. package/dist/scripts.validateflatnative.js +72 -0
  197. package/dist/security.d.ts +500 -0
  198. package/dist/security.js +1169 -0
  199. package/dist/seedcatalog.d.ts +13 -0
  200. package/dist/seedcatalog.js +46 -0
  201. package/dist/server.d.ts +20 -0
  202. package/dist/server.js +53 -0
  203. package/dist/speccatalog.d.ts +31 -0
  204. package/dist/speccatalog.js +163 -0
  205. package/dist/tiers.d.ts +1001 -0
  206. package/dist/tiers.js +2169 -0
  207. package/dist/utils.d.ts +2 -0
  208. package/dist/utils.js +5 -0
  209. package/dist/vaulthandoff.d.ts +141 -0
  210. package/dist/vaulthandoff.js +444 -0
  211. package/dist/virtual.d.ts +640 -0
  212. package/dist/virtual.js +1284 -0
  213. package/dist/virtualcpu.d.ts +315 -0
  214. package/dist/virtualcpu.js +1180 -0
  215. package/dist/virtualgpu.d.ts +344 -0
  216. package/dist/virtualgpu.js +1000 -0
  217. package/dist/virtualization.d.ts +606 -0
  218. package/dist/virtualization.js +1186 -0
  219. package/dist/virtualmemory.d.ts +817 -0
  220. package/dist/virtualmemory.js +1795 -0
  221. package/dist/vite.config.d.ts +3 -0
  222. package/dist/vite.config.js +43 -0
  223. package/dist/vitest.config.d.ts +2 -0
  224. package/dist/vitest.config.js +25 -0
  225. package/dist/webserver.d.ts +166 -0
  226. package/dist/webserver.js +2226 -0
  227. package/dist/workloadlaw.d.ts +133 -0
  228. package/dist/workloadlaw.js +193 -0
  229. package/docker.config +13 -6
  230. package/docs/artifactavailability.md +2 -2
  231. package/docs/{containerplatforms-2.1.0.md → containerplatforms.2.1.0.md} +1 -1
  232. package/docs/{documentmap-1.8.12.md → documentmap.1.8.12.md} +1 -1
  233. package/docs/ninety.modalities.md +108 -0
  234. package/docs/planning.ninety.md +391 -0
  235. package/docs/{releasenotes-1.8.13.md → releasenotes.1.8.13.md} +2 -2
  236. package/docs/{releasenotes-1.8.14.md → releasenotes.1.8.14.md} +1 -1
  237. package/docs/{repo-synthesis-1.8.16.md → repo.synthesis.1.8.16.md} +1 -1
  238. package/docs/{todo-1.8.15.md → todo.1.8.15.md} +1 -1
  239. package/docs/{todo-1.8.16.md → todo.1.8.16.md} +5 -5
  240. package/docs/todo.md +2 -2
  241. package/docs/workloadlaw.md +104 -0
  242. package/index.ts +4 -3
  243. package/manifest.json +1 -1
  244. package/modalityregistry.ts +1493 -0
  245. package/orchestrator.ts +1 -1
  246. package/package.json +76 -37
  247. package/docs/CONVERSA.txt +0 -1523
  248. package/docs/architecture-1.8.19.png +0 -0
  249. package/docs/assets/architecture.svg +0 -45
  250. package/docs/assets/saddle-browser-trace.webp +0 -0
  251. package/docs/assets/saddle-hero-bridge.webp +0 -0
  252. package/docs/assets/saddle-mark.webp +0 -0
  253. package/docs/assets/saddle-runtime-map.webp +0 -0
  254. package/docs/assets/saddlemark.svg +0 -13
  255. package/docs/example-publicapi.ts +0 -7
  256. package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
  257. /package/docs/{architecture-1.8.19.md → architecture.1.8.19.md} +0 -0
  258. /package/docs/{architecture-1.8.19.mmd → architecture.1.8.19.mmd} +0 -0
  259. /package/docs/{artifactresearch-1.8.9.md → artifactresearch.1.8.9.md} +0 -0
  260. /package/docs/{batches-1816-1820.md → batches.1816.to.1820.md} +0 -0
  261. /package/docs/{brancharchive-2026-08-18.md → brancharchive.2026.08.18.md} +0 -0
  262. /package/docs/{containerplatforms-1.8.17.md → containerplatforms.1.8.17.md} +0 -0
  263. /package/docs/{e2ugh-engine.md → e2ugh.engine.md} +0 -0
  264. /package/docs/{flatbuildresearch-1.8.11.md → flatbuildresearch.1.8.11.md} +0 -0
  265. /package/docs/{licenseaudit-1.8.12.md → licenseaudit.1.8.12.md} +0 -0
  266. /package/docs/{mobileconversionresearch-1.8.10.md → mobileconversionresearch.1.8.10.md} +0 -0
  267. /package/docs/{native-wrappers.md → native.wrappers.md} +0 -0
  268. /package/docs/{nativeidentityresearch-1.8.11.md → nativeidentityresearch.1.8.11.md} +0 -0
  269. /package/docs/{releasenotes-1.8.12.md → releasenotes.1.8.12.md} +0 -0
  270. /package/docs/{releasenotes-1.8.15.md → releasenotes.1.8.15.md} +0 -0
  271. /package/docs/{releasenotes-1.8.16.md → releasenotes.1.8.16.md} +0 -0
  272. /package/docs/{releasenotes-1.8.17.md → releasenotes.1.8.17.md} +0 -0
  273. /package/docs/{releasenotes-1.8.18.md → releasenotes.1.8.18.md} +0 -0
  274. /package/docs/{releasenotes-1.8.19.md → releasenotes.1.8.19.md} +0 -0
  275. /package/docs/{reorganization-1.8.8.md → reorganization.1.8.8.md} +0 -0
  276. /package/docs/{reorganization-1.8.9.md → reorganization.1.8.9.md} +0 -0
  277. /package/docs/{repo-analysis-1.8.21.json → repo.analysis.1.8.21.json} +0 -0
  278. /package/docs/{repo-candidates-1.8.21.jsonl → repo.candidates.1.8.21.jsonl} +0 -0
  279. /package/docs/{repo-research-1.8.16.md → repo.research.1.8.16.md} +0 -0
  280. /package/docs/{repo-research-1.8.21.md → repo.research.1.8.21.md} +0 -0
  281. /package/docs/{repo-selected-1.8.21.json → repo.selected.1.8.21.json} +0 -0
  282. /package/docs/{repo-synthesis-1.8.21.md → repo.synthesis.1.8.21.md} +0 -0
  283. /package/docs/{research-1.8.18-isolation.md → research.1.8.18.isolation.md} +0 -0
  284. /package/docs/{research-1.8.19-virtual-browser.md → research.1.8.19.virtual.browser.md} +0 -0
  285. /package/docs/{scanningresearch-1.8.11.md → scanningresearch.1.8.11.md} +0 -0
  286. /package/docs/{securityaudit-1.8.7.md → securityaudit.1.8.7.md} +0 -0
  287. /package/docs/{securityreferences-1.8.11.md → securityreferences.1.8.11.md} +0 -0
  288. /package/docs/{securityresearch-1.8.11.md → securityresearch.1.8.11.md} +0 -0
  289. /package/docs/{signingresearch-1.8.12.md → signingresearch.1.8.12.md} +0 -0
  290. /package/docs/{tauri-glib-risk-1.8.11.md → tauri.glib.risk.1.8.11.md} +0 -0
  291. /package/docs/{todo-1.8.18.md → todo.1.8.18.md} +0 -0
  292. /package/docs/{todo-1.8.19.md → todo.1.8.19.md} +0 -0
  293. /package/docs/{toolchainresearch-1.8.9.md → toolchainresearch.1.8.9.md} +0 -0
  294. /package/docs/{web-duplicatecleanup.md → web.duplicatecleanup.md} +0 -0
  295. /package/docs/{web-ideas.md → web.ideas.md} +0 -0
  296. /package/docs/{workflowimprovements-2026-08-19.md → workflowimprovements.2026.08.19.md} +0 -0
package/Dockerfile CHANGED
@@ -13,7 +13,7 @@
13
13
  # compute service published as ghcr.io/wenathlan/saddle:<version>
14
14
  # across the four-arch family standard (amd64, arm64, ppc64le, s390x
15
15
  # — the trixie slim base line; the stage also builds the web SPA so
16
- # the image serves the self-hosted console via `node /app/web/server.ts`).
16
+ # the image serves the self-hosted console via `node /app/webserver.ts`).
17
17
  #
18
18
  # saddle v2 (grand merge) - virtual hardware engine, multi-stage, multi-arch image.
19
19
  #
@@ -641,17 +641,20 @@ ENTRYPOINT ["/usr/bin/tini", "--", "qemu-system-x86_64"]
641
641
  # ---------------------------------------------------------------------------
642
642
  # saddle-build: the node-engine build stage (defined here, before the
643
643
  # vhe runtime, so BOTH container surfaces can consume its output: the
644
- # vhe runtime copies the built web SPA for its /engine/web console and
645
- # the saddle-runtime stage copies the engine dist plus the same web
646
- # tree - one build, two consumers). The stage runs native (never under
647
- # QEMU): its outputs are platform-independent static/js payloads.
644
+ # vhe runtime copies the built web SPA beside the console server at
645
+ # /engine and the saddle-runtime stage copies the engine dist plus the
646
+ # same staged SPA - one build, two consumers). The stage runs native
647
+ # (never under QEMU): its outputs are platform-independent static/js
648
+ # payloads.
648
649
 
649
650
  # the build stage pins to the native build platform ($BUILDPLATFORM): its
650
651
  # outputs (the engine dist, pure js, and the web SPA, static assets) are
651
652
  # architecture-independent, while the tailwind/lightningcss pipeline only
652
653
  # ships native bindings for the builder platforms - the per-arch legs never
653
- # run it under QEMU.
654
- FROM --platform=$BUILDPLATFORM node:26.8.1-slim@sha256:c0753125a3789977aefe869cbebccf70e3cfd7ea84ca48547458f02e4f1d7146 AS saddle-build
654
+ # run it under QEMU. The base rides the family tag contract (tags only,
655
+ # never a @sha256: digest - a single digest cannot serve the
656
+ # four-architecture matrix the registry resolves per platform).
657
+ FROM --platform=$BUILDPLATFORM node:26.8.1-slim AS saddle-build
655
658
 
656
659
  ARG SADDLE_VERSION
657
660
  WORKDIR /app
@@ -663,7 +666,16 @@ RUN npm ci --ignore-scripts --legacy-peer-deps
663
666
  COPY . .
664
667
  RUN npm run build:engine \
665
668
  && node --check dist/cli.js \
666
- && npm run web:build:pages
669
+ && npm run web:build:pages \
670
+ # the theme build emits the hashed SPA bundles straight at the app
671
+ # root (the family static-first vite contract): stage them into a
672
+ # clean folder so the runtime stages copy exactly the console
673
+ # surface - the shell, the hashed js/css bundles and the icon and
674
+ # manifest assets the shell references. the extension popup
675
+ # stylesheet is the one root css that never belongs to the spa.
676
+ && mkdir -p /out/spa \
677
+ && cp index.html *.js *.css *.svg *.webmanifest /out/spa/ \
678
+ && rm -f /out/spa/popup.css
667
679
 
668
680
  FROM ${UBUNTU} AS runtime
669
681
  ARG TARGETARCH
@@ -895,19 +907,24 @@ COPY --from=python-bridge /bridge/qemubridge.py /engine/qemubridge.py
895
907
  # the engine sources and the specification files consumed at runtime
896
908
  # (docker.config "final" stage copies the whole tree; the flat layout
897
909
  # keeps that a single COPY layer).
898
- COPY *.ts package.json tsconfig.json biome.json jsdom.d.ts /engine/
910
+ COPY *.ts package.json tsconfig.json biome.jsonc jsdom.d.ts /engine/
899
911
  COPY processors.json gpus.json cores.json boards.json vm.config.json virtualhardware.json /engine/
900
- COPY qemu.config mttg.config passage.config docker.config /engine/
912
+ COPY qemu.config mttg.config passage.config docker.config mime.types /engine/
901
913
 
902
914
  # the web node ships inside the main container: the mesh edition (auth,
903
915
  # sqlite database, dashboard and the browser sandbox pages) runs from the
904
916
  # same image, so one container serves the engine AND the web surface.
905
- # run it with: docker run ghcr.io/wenathlan/saddle node /engine/web/server.ts
906
- COPY web /engine/web
907
- # the built web SPA (vite, from the saddle-build stage): the console
908
- # server (node /engine/web/server.ts) serves web/dist/public - the
909
- # unified React interface that absorbed the former static pages.
910
- COPY --from=saddle-build /app/web/dist /engine/web/dist
917
+ # run it with: docker run ghcr.io/wenathlan/saddle node /engine/webserver.ts
918
+ # (the console server is a root engine source - the COPY *.ts line above
919
+ # already lands it at /engine together with its console stack, and the
920
+ # extension denylist of its static resolver keeps every .ts/.json/.sql
921
+ # source unreachable).
922
+ # the built web SPA (vite, staged by saddle-build): the theme build emits
923
+ # the hashed bundles straight at the app root, so the staged spa lands
924
+ # beside the console server at /engine and webserver.ts serves it from
925
+ # its own module directory - the unified React interface that absorbed
926
+ # the former static pages.
927
+ COPY --from=saddle-build /out/spa /engine/
911
928
 
912
929
  RUN set -eux; \
913
930
  chmod 0755 /usr/local/bin/nvidia-smi /usr/local/bin/aetherforge; \
@@ -1310,7 +1327,7 @@ ENTRYPOINT ["/entrypoint.sh"]
1310
1327
  # docker build --target saddle-runtime -t saddle:<version> .
1311
1328
  # ══════════════════════════════════════════════════════════════════════
1312
1329
 
1313
- FROM node:26.8.1-slim@sha256:c0753125a3789977aefe869cbebccf70e3cfd7ea84ca48547458f02e4f1d7146 AS saddle-runtime
1330
+ FROM node:26.8.1-slim AS saddle-runtime
1314
1331
 
1315
1332
  ARG SADDLE_VERSION
1316
1333
  LABEL org.opencontainers.image.title="Saddle" \
@@ -1357,12 +1374,15 @@ RUN apt-get update \
1357
1374
  && rm -rf node_modules/cpu-features/deps \
1358
1375
  && find node_modules -type f -name Dockerfile -delete
1359
1376
  COPY --from=saddle-build /app/dist ./dist
1360
- # the web service surface (self-hosted console): the built SPA
1361
- # (web/dist/public from the saddle-build vite run) plus the pure-node
1362
- # server stack (server.ts, db.ts, auth.ts, mesh.ts, sandbox.ts,
1363
- # mime.types, init.sql, schema.prisma) - zero npm dependencies, the
1364
- # node 26 runtime carries everything (node:sqlite, node:crypto).
1365
- COPY --from=saddle-build /app/web ./web
1377
+ # the web service surface (self-hosted console): the staged spa plus the
1378
+ # pure-node server stack (webserver.ts, db.ts, labels.ts, auth.ts,
1379
+ # mesh.ts, sandbox.ts, sandboxprofile.ts, sandboxenvprofile.ts,
1380
+ # sandboxquota.ts, mime.types, init.sql, schema.prisma) - zero npm
1381
+ # dependencies, the node 26 runtime carries everything (node:sqlite,
1382
+ # node:crypto, native type stripping for the .ts sources).
1383
+ # run the console with: docker run saddle:<version> node webserver.ts
1384
+ COPY --from=saddle-build /app/webserver.ts /app/db.ts /app/labels.ts /app/auth.ts /app/mesh.ts /app/sandbox.ts /app/sandboxprofile.ts /app/sandboxenvprofile.ts /app/sandboxquota.ts /app/mime.types /app/init.sql /app/schema.prisma ./
1385
+ COPY --from=saddle-build /out/spa ./
1366
1386
 
1367
1387
  USER node
1368
1388
 
package/README.md CHANGED
@@ -31,12 +31,12 @@ domain modules land beside the saddle domains:
31
31
  | `media.ts`, `render.ts`, `quantum.ts`, `tiers.ts` | media pipeline, GPU registry, quantum simulation, tier policy |
32
32
  | `security.ts`, `alternatives.ts` | hardening gates and the alternative-stack catalog |
33
33
  | `index.html`, `App.tsx`, `Sol/` | the single SPA shell and the Sol theme (one tsx app with one stylesheet per theme) |
34
- | `server.ts`, `sandbox.ts` | the zero-dependency self-hosted API of the 2.0.150 grand-merge envelope (`node server.ts`; the api answers its version at `/api/v1/health`) and the browser-pure engine port |
34
+ | `server.ts`, `sandbox.ts` | the zero-dependency self-hosted API of the 2.0.152 grand-merge envelope (`node server.ts`; the api answers its version at `/api/v1/health`) and the browser-pure engine port |
35
35
  | `vercel.json`, `netlify.toml` | the platform deploy adapters beside the surface they publish (the caddy ghost stays out of the tree) |
36
36
  | `specs/*` package exports | processors, gpus, cores, boards and the qemu/mttg/passage/docker envelopes |
37
37
 
38
38
  The full pre-merge documentation of the engine lives in
39
- [docs/e2ugh-engine.md](docs/e2ugh-engine.md) and its release history in
39
+ [docs/e2ugh.engine.md](docs/e2ugh.engine.md) and its release history in
40
40
  [CHANGELOG.md (the e2ugh lineage sections)](CHANGELOG.md (the e2ugh lineage sections)).
41
41
 
42
42
  ## Start here
@@ -223,7 +223,7 @@ Saddle is applying to the SignPath Foundation for open-source code signing. Unti
223
223
 
224
224
  The requested policy is: **Free code signing provided by SignPath.io, certificate by SignPath Foundation**. Committers and reviewers are maintainers with write access to the public repository. Approvers are repository owners or release approvers recorded in `governance.md`. Every signed release must be built from repository source, pass the security and packaging gates, and receive manual signing approval.
225
225
 
226
- The core program will not transfer information to other networked systems unless specifically requested by the user or the person installing or operating it. Browser sessions, storage adapters, runners and external services remain caller-configured and subject to their own policies. See [`privacy-policy.md`](privacy-policy.md) and [`SECURITY.md`](SECURITY.md).
226
+ The core program will not transfer information to other networked systems unless specifically requested by the user or the person installing or operating it. Browser sessions, storage adapters, runners and external services remain caller-configured and subject to their own policies. See [`privacy.policy.md`](privacy.policy.md) and [`SECURITY.md`](SECURITY.md).
227
227
 
228
228
  ## GitHub Pages web surface
229
229
 
@@ -234,7 +234,7 @@ npm run web:check
234
234
  VITE_BASE_PATH=/saddle npm run web:build:pages
235
235
  ```
236
236
 
237
- Small public configuration and visual assets live under `web/public/`. The development collector is TypeScript source at `web/debugcollector.ts`, injected only in development, and uses `/debuglogs`; it is not part of the production build. The obsolete `web/public/__manus__` directory is intentionally absent.
237
+ Small public configuration and visual assets live under `web/public/`. The obsolete `web/public/__manus__` directory is intentionally absent; the development debug collector (the visitor-browser telemetry hook at the former `web/debugcollector.ts`) left the saddle together with the scrape lanes — the engine keeps no surface that watches the user's browser.
238
238
 
239
239
  ## Development
240
240
 
package/biome.jsonc ADDED
@@ -0,0 +1,134 @@
1
+ // the family biome baseline: identical across the apps, the identity only names the app.
2
+ {
3
+ "$schema": "https://biomejs.dev/schemas/2.6.4/schema.json",
4
+ "vcs": {
5
+ "enabled": true,
6
+ "clientKind": "git",
7
+ "useIgnoreFile": false
8
+ },
9
+ "files": {
10
+ "includes": [
11
+ "**/*.ts",
12
+ "**/*.tsx",
13
+ "**/*.js",
14
+ "**/*.mjs",
15
+ "**/*.cjs",
16
+ "**/*.json",
17
+ "!**/dist",
18
+ "!**/distpackage",
19
+ "!**/target",
20
+ "!**/node_modules",
21
+ "!**/bun.lock",
22
+ "!**/*.min.js",
23
+ "!**/docs",
24
+ "!**/tests/tmp",
25
+ "!**/tests/code",
26
+ "!**/Sol/dist",
27
+ "!**/Sol/.vite",
28
+ "!**/Sol/node_modules",
29
+ "!**/coverage",
30
+ "!**/android",
31
+ "!**/releasecheck",
32
+ "!**/build",
33
+ "!**/release",
34
+ "!index-*.js"
35
+ ]
36
+ },
37
+ "formatter": {
38
+ "enabled": true,
39
+ "indentStyle": "space",
40
+ "indentWidth": 2,
41
+ "lineWidth": 120,
42
+ "lineEnding": "lf"
43
+ },
44
+ "linter": {
45
+ "enabled": true,
46
+ "rules": {
47
+ "preset": "recommended",
48
+ "correctness": {
49
+ "noUnusedVariables": "warn",
50
+ "noUnsafeOptionalChaining": "warn",
51
+ "useExhaustiveDependencies": "warn",
52
+ "noUnusedImports": "warn",
53
+ "noUnusedPrivateClassMembers": "warn",
54
+ "noUnusedFunctionParameters": "warn",
55
+ "noConstantCondition": "warn",
56
+ "noVoidTypeReturn": "warn"
57
+ },
58
+ "a11y": {
59
+ "useButtonType": "warn",
60
+ "noStaticElementInteractions": "warn",
61
+ "useSemanticElements": "warn",
62
+ "useAriaPropsSupportedByRole": "warn"
63
+ },
64
+ "suspicious": {
65
+ "noExplicitAny": "warn",
66
+ "noArrayIndexKey": "warn",
67
+ "noControlCharactersInRegex": "warn",
68
+ "noRedeclare": "warn",
69
+ "noAssignInExpressions": "warn",
70
+ "noShadowRestrictedNames": "warn",
71
+ "noDuplicateElseIf": "warn",
72
+ "noImplicitAnyLet": "warn",
73
+ "noTsIgnore": "warn",
74
+ "noGlobalIsNan": "warn"
75
+ },
76
+ "style": {
77
+ "noNonNullAssertion": "warn",
78
+ "useTemplate": "warn",
79
+ "useExponentiationOperator": "warn",
80
+ "useConst": "warn"
81
+ },
82
+ "complexity": {
83
+ "useLiteralKeys": "warn",
84
+ "useOptionalChain": "warn",
85
+ "noUselessContinue": "warn",
86
+ "noUselessUndefinedInitialization": "warn",
87
+ "noUselessEscapeInRegex": "warn"
88
+ }
89
+ }
90
+ },
91
+ "javascript": {
92
+ "formatter": {
93
+ "quoteStyle": "double",
94
+ "semicolons": "always",
95
+ "trailingCommas": "all",
96
+ "arrowParentheses": "always"
97
+ }
98
+ },
99
+ "css": {
100
+ "parser": {
101
+ "tailwindDirectives": true
102
+ }
103
+ },
104
+ "overrides": [
105
+ {
106
+ "includes": ["**/*"],
107
+ "linter": {
108
+ "rules": {
109
+ "suspicious": {
110
+ "noDebugger": "off"
111
+ }
112
+ }
113
+ }
114
+ },
115
+ {
116
+ "includes": ["tests/workflowcheck.ts", "tests/publishlanes.test.ts"],
117
+ "linter": {
118
+ "rules": {
119
+ "suspicious": {
120
+ "noTemplateCurlyInString": "off"
121
+ }
122
+ }
123
+ }
124
+ }
125
+ ],
126
+ "assist": {
127
+ "enabled": true,
128
+ "actions": {
129
+ "source": {
130
+ "useSortedKeys": "off"
131
+ }
132
+ }
133
+ }
134
+ }
package/dist/App.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import './Sol/sol.css';
2
+ declare function App(): import("react").JSX.Element;
3
+ export default App;
package/dist/App.js ADDED
@@ -0,0 +1,50 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * App — the global anchor (layer 1 of the anchor architecture) and the only
4
+ * TSX outside the theme. The root manages the themes as single files: it
5
+ * imports only the theme anchor (Sol/Sol.tsx — the file named after the theme
6
+ * folder, beside Sol/sol.css) and the theme stylesheet, wraps the anchor in
7
+ * the global concerns it owns (the error boundary, the theme and tooltip
8
+ * providers, the toaster and the wouter router provider) and renders it. The
9
+ * whole route tree lives behind the theme anchor; no page or component of the
10
+ * theme is ever imported here.
11
+ */
12
+ import { createRoot } from 'react-dom/client';
13
+ import { Router as WouterRouter } from 'wouter';
14
+ import Sol from './Sol/Sol';
15
+ import { ErrorBoundary, ThemeProvider, Toaster, TooltipProvider } from './Sol/shell/Shell.tsx';
16
+ import './Sol/sol.css';
17
+ import { seedlabels } from './labels';
18
+ // the copy law rides the boot: the seed refreshes the label store rows
19
+ // (translated rows protected) before the first paint answers
20
+ if (typeof window !== 'undefined')
21
+ void seedlabels().catch(() => { });
22
+ // NOTE: About Theme
23
+ // - First choose a default theme according to your design style (dark or light bg), than change color palette in Sol/sol.css
24
+ // to keep consistent foreground/background color across components
25
+ // - If you want to make theme switchable, pass `switchable` ThemeProvider and use `useTheme` hook
26
+ /** The router base derives from the declared base path so the same build serves
27
+ * every host. A relative base ("./") cannot name the folder it lands in, but the
28
+ * dispatcher always boots cold links at the application root first — so the
29
+ * folder prefix of the boot pathname is exactly the router base (absolute, so
30
+ * wouter never has to match against a relative prefix). The absolute bases
31
+ * carry through unchanged. */
32
+ function routerBase() {
33
+ const declaredBase = import.meta.env.BASE_URL;
34
+ if (declaredBase !== '/' && declaredBase !== './')
35
+ return declaredBase.replace(/\/$/, '');
36
+ const bootPath = window.location.pathname.replace(/index\.html$/, '').replace(/\/$/, '');
37
+ return bootPath === '' ? '' : bootPath;
38
+ }
39
+ function App() {
40
+ return (_jsx(ErrorBoundary, { children: _jsx(ThemeProvider, { defaultTheme: "dark", children: _jsxs(TooltipProvider, { children: [_jsx(Toaster, {}), _jsx(WouterRouter, { base: routerBase(), children: _jsx(Sol, {}) })] }) }) }));
41
+ }
42
+ /* The self-mount: the app owns its bootstrap — the retired main.tsx
43
+ * wrapper is gone, so this module is the single entry the html loads
44
+ * (the doctrine of the 2.1.0 universal interface: one tsx app, the
45
+ * router and the mount live together). */
46
+ const rootmount = typeof document !== 'undefined' ? document.getElementById('root') : null;
47
+ if (rootmount) {
48
+ createRoot(rootmount).render(_jsx(App, {}));
49
+ }
50
+ export default App;
@@ -0,0 +1,3 @@
1
+ /** The route tree of the theme: the entry flow (intro, onboarding) before
2
+ * the catch-all that mounts the window over every page route. */
3
+ export default function Sol(): import("react").JSX.Element;
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Sol theme anchor — layer 2 of the anchor architecture.
4
+ * The file carrying the theme folder's own name (Sol/Sol.tsx, beside
5
+ * Sol/sol.css) is the path manager of the pages: it imports one anchor per
6
+ * page folder (`folder/folder.tsx`, each beside the loose components its
7
+ * folder keeps) and mounts every route and subroute of the theme. App.tsx
8
+ * consumes only this file and the theme stylesheet; no page component is
9
+ * ever imported outside this layer. When a theme folder changes its name
10
+ * (Moon, Aqua), this file follows the new name and App.tsx keeps importing
11
+ * the anchor by the folder path. Since the family window conversion the
12
+ * theme is an APPLICATION: the entry flow opens the route table — /intro
13
+ * (the akash-floor splash) and /onboarding (the first-run frames) — and
14
+ * every other route renders as the content of the ONE application window
15
+ * (the page anchors carry no chrome of their own; the window rail is the
16
+ * only nav). The flow contract rides the home anchor's entry gate
17
+ * (Sol/home/entrygate.tsx): "/" consults the seen flags (onboardingstate.ts)
18
+ * before anything shows, the intro hands straight to /onboarding and the
19
+ * onboarding lands home.
20
+ */
21
+ import { Route, Switch } from 'wouter';
22
+ import AgentBrowserAnchor from './agentbrowser/agentbrowser';
23
+ import ArchitectureAnchor from './architecture/architecture';
24
+ import ComputeAnchor from './compute/compute';
25
+ import ConsoleAnchor from './console/console';
26
+ import DashboardAnchor from './dashboard/dashboard';
27
+ import DocsAnchor from './docs/docs';
28
+ import HomeAnchor from './home/home';
29
+ import IntegrationsAnchor from './integrations/integrations';
30
+ import IntroAnchor from './intro/intro';
31
+ import LoginAnchor from './login/login';
32
+ import NotFoundAnchor from './notfound/notfound';
33
+ import OnboardingAnchor from './onboarding/onboarding';
34
+ import PlaygroundAnchor from './playground/playground';
35
+ import RegisterAnchor from './register/register';
36
+ import { Shell } from './shell/Shell.tsx';
37
+ /** The window stage: the ONE application window wrapping the whole page
38
+ * route table — every existing route stays alive inside the stage. */
39
+ function WindowStage() {
40
+ return (_jsx(Shell, { children: _jsxs(Switch, { children: [_jsx(Route, { path: '/', component: HomeAnchor }), _jsx(Route, { path: '/architecture', component: ArchitectureAnchor }), _jsx(Route, { path: '/agent-browser', component: AgentBrowserAnchor }), _jsx(Route, { path: '/compute', component: ComputeAnchor }), _jsx(Route, { path: '/integrations', component: IntegrationsAnchor }), _jsx(Route, { path: '/playground', component: PlaygroundAnchor }), _jsx(Route, { path: '/console', component: ConsoleAnchor }), _jsx(Route, { path: '/login', component: LoginAnchor }), _jsx(Route, { path: '/register', component: RegisterAnchor }), _jsx(Route, { path: '/dashboard', component: DashboardAnchor }), _jsx(Route, { path: '/docs', component: DocsAnchor }), _jsx(Route, { path: '/404', component: NotFoundAnchor }), _jsx(Route, { component: NotFoundAnchor })] }) }));
41
+ }
42
+ /** The route tree of the theme: the entry flow (intro, onboarding) before
43
+ * the catch-all that mounts the window over every page route. */
44
+ export default function Sol() {
45
+ return (_jsxs(Switch, { children: [_jsx(Route, { path: '/intro', component: IntroAnchor }), _jsx(Route, { path: '/onboarding', component: OnboardingAnchor }), _jsx(Route, { component: WindowStage })] }));
46
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * agent browser page anchor — layer 3 of the anchor architecture.
3
+ * The file carrying the folder's own name is the path manager of the page:
4
+ * it imports the loose components beside it, mounts the page and re-exports
5
+ * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
6
+ * this file. This anchor carries the former main component of the folder,
7
+ * which now lives here as the page mount itself.
8
+ */
9
+ export default function AgentBrowser(): import("react").JSX.Element;
@@ -0,0 +1,121 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * agent browser page anchor — layer 3 of the anchor architecture.
4
+ * The file carrying the folder's own name is the path manager of the page:
5
+ * it imports the loose components beside it, mounts the page and re-exports
6
+ * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
7
+ * this file. This anchor carries the former main component of the folder,
8
+ * which now lives here as the page mount itself.
9
+ */
10
+ import { PulseRegular as Activity, ProhibitedRegular as Ban, CameraRegular as Camera, CheckmarkCircleRegular as CheckCircle2, KeyboardRegular as Keyboard, CursorRegular as MousePointer2, PlayRegular as Play, ArrowCounterclockwiseRegular as RotateCcw, DocumentTextRegular as ScrollText, WindowConsoleRegular as Terminal, } from '@fluentui/react-icons';
11
+ // Signal & Ledger: agent browser as an event trail, evidence and deterministic replay.
12
+ // The session console renders the rows the sessions catalog serves — the
13
+ // documented example log of docs/logs/examplesession.json offline, the paired
14
+ // database rows over HTTPS — never invented coordinates or counts. Every
15
+ // word of the page itself rides the label store (labels.ts — the copy law).
16
+ import { useEffect, useState } from 'react';
17
+ import { PageShell } from '../shell/Shell.tsx';
18
+ import { label, labelfill } from '../../labels.ts';
19
+ import { agentsessions, mediaSlots, } from '../../catalog';
20
+ /** the glyph of one event kind of the session trail. */
21
+ function eventicon(type) {
22
+ if (type === 'scroll')
23
+ return ScrollText;
24
+ if (type === 'type')
25
+ return Keyboard;
26
+ return MousePointer2;
27
+ }
28
+ /** the value line of one event: exactly the fields the row carries. */
29
+ function eventvalue(event) {
30
+ if (event.type === 'scroll')
31
+ return `dy ${event.dy ?? 0}`;
32
+ if (event.type === 'type')
33
+ return `key ${event.key ?? ''}`;
34
+ return `x ${event.x ?? 0} / y ${event.y ?? 0}`;
35
+ }
36
+ /** the elapsed label of one event from its relative time. */
37
+ const eventtime = (event) => `+${event.t} ms`;
38
+ /** one rendered event row: the glyph, the relative time, the kind and the fields. */
39
+ function SessionEventRow({ event }) {
40
+ const Icon = eventicon(event.type);
41
+ return (_jsxs("div", { className: "console-row", children: [_jsx(Icon, { fontSize: 16 }), _jsx("span", { className: "console-time", children: eventtime(event) }), _jsx("strong", { children: event.type }), _jsx("span", { children: eventvalue(event) })] }));
42
+ }
43
+ /** the event trail of one session: one row per captured event. */
44
+ function SessionTrail({ events }) {
45
+ return (_jsx(_Fragment, { children: events.map((event) => (_jsx(SessionEventRow, { event: event }, `${event.t}-${event.type}`))) }));
46
+ }
47
+ /** the captcha verdict badge of one session: the honest outcome of the run. */
48
+ function CaptchaBadge({ verdict }) {
49
+ return (_jsxs("span", { className: verdict.passed ? 'console-pass' : 'console-denied', children: [verdict.passed ? _jsx(CheckCircle2, { fontSize: 14 }) : _jsx(Ban, { fontSize: 13 }), " ", verdict.kind, ' ', label(verdict.passed ? 'agentbrowser.captcha.passed' : 'agentbrowser.captcha.failed')] }));
50
+ }
51
+ /** the principle cards beside the console: the glyph is presentation code,
52
+ * the words ride the store (agentbrowser.principle.*). */
53
+ const principles = [
54
+ { icon: Camera, titlekey: 'agentbrowser.principle.dom.title', bodykey: 'agentbrowser.principle.dom.body' },
55
+ {
56
+ icon: RotateCcw,
57
+ titlekey: 'agentbrowser.principle.replay.title',
58
+ bodykey: 'agentbrowser.principle.replay.body',
59
+ },
60
+ {
61
+ icon: Play,
62
+ titlekey: 'agentbrowser.principle.evidence.title',
63
+ bodykey: 'agentbrowser.principle.evidence.body',
64
+ },
65
+ ];
66
+ export default function AgentBrowser() {
67
+ const [media, setMedia] = useState(undefined);
68
+ const [sessions, setSessions] = useState(null);
69
+ useEffect(() => {
70
+ void mediaSlots().then((rows) => setMedia(rows.find((slot) => slot.id === 'media.agentbrowser.trace')));
71
+ }, []);
72
+ useEffect(() => {
73
+ let live = true;
74
+ agentsessions()
75
+ .then((rows) => {
76
+ if (live)
77
+ setSessions(rows);
78
+ })
79
+ .catch(() => {
80
+ if (live)
81
+ setSessions([]);
82
+ });
83
+ return () => {
84
+ live = false;
85
+ };
86
+ }, []);
87
+ const session = sessions?.[0] ?? null;
88
+ const lastt = session ? session.events[session.events.length - 1]?.t ?? 0 : 0;
89
+ const sessionlabel = session ? session.session.id : label('agentbrowser.console.reading');
90
+ /** the trimmed json projection of the served row (the docs/logs shape). */
91
+ const sessionsummary = session
92
+ ? JSON.stringify({
93
+ version: session.version,
94
+ session: {
95
+ id: session.session.id,
96
+ browser: session.session.browser,
97
+ },
98
+ events: session.events.map((event) => event.type),
99
+ captcha: session.captcha,
100
+ }, null, 2)
101
+ : label('agentbrowser.console.waitingSession');
102
+ return (_jsxs(PageShell, { section: label('agentbrowser.shell.section'), label: label('agentbrowser.shell.label'), title: label('agentbrowser.shell.title'), intro: label('agentbrowser.shell.intro'), media: media, children: [_jsxs("section", { className: "content-section split-content", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label('agentbrowser.split.eyebrow') }), _jsx("h2", { className: "section-title", children: label('agentbrowser.split.title') })] }), _jsxs("div", { className: "prose-copy", children: [_jsx("p", { children: label('agentbrowser.split.body1') }), _jsx("p", { children: label('agentbrowser.split.body2') })] })] }), _jsxs("section", { className: "content-section browser-grid", children: [_jsxs("div", { className: "session-console", children: [_jsxs("div", { className: "console-head", children: [_jsxs("span", { children: [_jsx(Terminal, { fontSize: 14 }), ' ', labelfill('agentbrowser.console.session', {
103
+ id: sessionlabel,
104
+ })] }), session ? _jsx(CaptchaBadge, { verdict: session.captcha }) : null] }), _jsx("div", { className: "console-rows", children: session === null ? (_jsxs("div", { className: "console-row", "aria-live": "polite", children: [_jsx(Activity, { fontSize: 16 }), _jsx("span", { className: "console-time" }), _jsx("strong", { children: label('agentbrowser.console.catalog') }), _jsx("span", { children: label('agentbrowser.console.waiting') })] })) : session.events.length === 0 ? (_jsxs("div", { className: "console-row", "aria-live": "polite", children: [_jsx(Activity, { fontSize: 16 }), _jsx("span", { className: "console-time" }), _jsx("strong", { children: label('agentbrowser.console.catalog') }), _jsx("span", { children: label('agentbrowser.console.empty') })] })) : (_jsxs(_Fragment, { children: [_jsx(SessionTrail, { events: session.events }), _jsxs("div", { className: "console-row", children: [_jsx(Activity, { fontSize: 16 }), _jsxs("span", { className: "console-time", children: ["+", lastt, " ms"] }), _jsx("strong", { children: label('agentbrowser.console.metrics') }), _jsx("span", { children: labelfill('agentbrowser.console.events', {
105
+ n: String(session.events.length),
106
+ s: (lastt / 1000).toFixed(1),
107
+ }) })] })] })) }), _jsxs("div", { className: "console-footer", children: [_jsx("span", { children: labelfill('agentbrowser.console.seed', {
108
+ seed: session
109
+ ? session.session.seed
110
+ : label('agentbrowser.console.na'),
111
+ }) }), _jsx("span", { children: labelfill('agentbrowser.console.browser', {
112
+ browser: session
113
+ ? session.session.browser
114
+ : label('agentbrowser.console.na'),
115
+ }) })] })] }), _jsx("div", { className: "browser-principles", children: principles.map((principle) => {
116
+ const Icon = principle.icon;
117
+ return (_jsxs("div", { className: "principle-card", children: [_jsx(Icon, { fontSize: 19 }), _jsxs("div", { children: [_jsx("strong", { children: label(principle.titlekey) }), _jsx("span", { children: label(principle.bodykey) })] })] }, principle.titlekey));
118
+ }) })] }), _jsxs("section", { className: "content-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: labelfill('agentbrowser.json.eyebrow', {
119
+ version: String(session ? session.version : 1),
120
+ }) }), _jsx("span", { className: "mono-label", children: label('agentbrowser.json.mono') })] }), _jsx("pre", { className: "code-block", children: _jsx("code", { children: sessionsummary }) })] })] }));
121
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * architecture page anchor — layer 3 of the anchor architecture.
3
+ * The file carrying the folder's own name is the path manager of the page:
4
+ * it imports the loose components beside it, mounts the page and re-exports
5
+ * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
6
+ * this file. This anchor carries the former main component of the folder,
7
+ * which now lives here as the page mount itself.
8
+ */
9
+ export default function Architecture(): import("react").JSX.Element;
@@ -0,0 +1,93 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * architecture page anchor — layer 3 of the anchor architecture.
4
+ * The file carrying the folder's own name is the path manager of the page:
5
+ * it imports the loose components beside it, mounts the page and re-exports
6
+ * the public component surface. Only the theme anchor (Sol/Sol.tsx) consumes
7
+ * this file. This anchor carries the former main component of the folder,
8
+ * which now lives here as the page mount itself.
9
+ */
10
+ import { ArrowUpRightRegular as ArrowUpRight, BrainCircuitRegular as Cpu, DatabaseRegular as Database, BranchForkRegular as GitBranch, GlobeRegular as Globe2, ShieldTaskRegular as ShieldCheck, } from '@fluentui/react-icons';
11
+ // Signal & Ledger: the architecture as a diagram-as-ledger — layered hairline
12
+ // rows (the runtime forms of sandboxprofile: runtime/packages, full/docker,
13
+ // published/registries) with mono annotations and connector dashes, then the
14
+ // four layers, the provider chain and the physical limit band. No floating
15
+ // boxes: every layer is a ruled row on the same spine. The page ships zero
16
+ // fixed data of its own: the runtime forms ride the declared vocabulary of
17
+ // sandboxprofile, the provider chain and the layer words ride the label
18
+ // store (labels.ts — the seed mirrors the rows into the labels table), and
19
+ // every word reads through the typed accessor — the copy law.
20
+ import { useEffect, useState } from 'react';
21
+ import { PageShell } from '../shell/Shell.tsx';
22
+ import { mediaSlots } from '../../catalog';
23
+ import { label } from '../../labels.ts';
24
+ import { SANDBOXFORMS } from '../../sandboxprofile.ts';
25
+ /** the ledger annotations of the three runtime forms: the copy rides the
26
+ * store under the architecture.form.* family, keyed by the declared form
27
+ * ids of sandboxprofile (the ids are data, the words are copy). */
28
+ const formlabels = {
29
+ 'runtime-node': {
30
+ name: label('architecture.form.runtimeNode.name'),
31
+ pkg: label('architecture.form.runtimeNode.pkg'),
32
+ note: label('architecture.form.runtimeNode.note'),
33
+ },
34
+ 'full-docker': {
35
+ name: label('architecture.form.fullDocker.name'),
36
+ pkg: label('architecture.form.fullDocker.pkg'),
37
+ note: label('architecture.form.fullDocker.note'),
38
+ },
39
+ published: {
40
+ name: label('architecture.form.published.name'),
41
+ pkg: label('architecture.form.published.pkg'),
42
+ note: label('architecture.form.published.note'),
43
+ },
44
+ };
45
+ /** the four layers of the map: the glyph is presentation code, every word
46
+ * rides the store (the home surfaces() precedent). */
47
+ function layers() {
48
+ return [
49
+ {
50
+ icon: GitBranch,
51
+ name: label('architecture.layer.repository.name'),
52
+ sub: label('architecture.layer.repository.sub'),
53
+ body: label('architecture.layer.repository.body'),
54
+ },
55
+ {
56
+ icon: Cpu,
57
+ name: label('architecture.layer.runner.name'),
58
+ sub: label('architecture.layer.runner.sub'),
59
+ body: label('architecture.layer.runner.body'),
60
+ },
61
+ {
62
+ icon: Database,
63
+ name: label('architecture.layer.memory.name'),
64
+ sub: label('architecture.layer.memory.sub'),
65
+ body: label('architecture.layer.memory.body'),
66
+ },
67
+ {
68
+ icon: Globe2,
69
+ name: label('architecture.layer.surface.name'),
70
+ sub: label('architecture.layer.surface.sub'),
71
+ body: label('architecture.layer.surface.body'),
72
+ },
73
+ ];
74
+ }
75
+ /** the provider chain as config: the ordered ids ride the label store
76
+ * (architecture.chain.providers — the seed ingests the row into the labels
77
+ * table like every other string) and the page only splits the row; no fixed
78
+ * provider array survives inside the component. */
79
+ function providerchain() {
80
+ return label('architecture.chain.providers').split(' · ');
81
+ }
82
+ export default function Architecture() {
83
+ const [media, setMedia] = useState(undefined);
84
+ useEffect(() => {
85
+ void mediaSlots().then((rows) => setMedia(rows.find((slot) => slot.id === 'media.runtime.map')));
86
+ }, []);
87
+ return (_jsxs(PageShell, { section: label('architecture.shell.section'), label: label('architecture.shell.label'), title: label('architecture.shell.title'), intro: label('architecture.shell.intro'), media: media, children: [_jsxs("section", { className: "content-section split-content", children: [_jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label('architecture.model.eyebrow') }), _jsx("h2", { className: "section-title", children: label('architecture.model.title') })] }), _jsxs("div", { className: "prose-copy", children: [_jsx("p", { children: label('architecture.model.body1') }), _jsx("p", { children: label('architecture.model.body2') })] })] }), _jsxs("section", { className: "content-section", "aria-label": label('architecture.forms.aria'), children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.forms.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.forms.mono') })] }), _jsx("ol", { className: "r3-forms", children: SANDBOXFORMS.map((form, index) => (_jsxs("li", { className: "r3-form-row", children: [_jsx("span", { className: "r3-form-index", children: `0${index + 1}` }), _jsx("span", { className: "r3-form-name", children: formlabels[form].name }), _jsx("span", { className: "r3-form-pkg", children: formlabels[form].pkg }), _jsx("span", { className: "r3-form-note", children: formlabels[form].note })] }, form))) })] }), _jsxs("section", { className: "content-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.layers.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.layers.mono') })] }), _jsx("div", { className: "layer-stack", children: layers().map((layer, index) => {
88
+ const Icon = layer.icon;
89
+ return (_jsxs("div", { className: "layer-row", children: [_jsxs("span", { className: "layer-index", children: ["0", index + 1] }), _jsx(Icon, { fontSize: 20, strokeWidth: 1.5, "aria-hidden": "true" }), _jsxs("div", { className: "layer-name", children: [_jsx("strong", { children: layer.name }), _jsx("span", { children: layer.sub })] }), _jsx("p", { children: layer.body }), _jsx(ArrowUpRight, { fontSize: 16, "aria-hidden": "true" })] }, layer.name));
90
+ }) })] }), _jsxs("section", { className: "content-section", children: [_jsxs("div", { className: "content-section-heading", children: [_jsx("p", { className: "eyebrow", children: label('architecture.chain.eyebrow') }), _jsx("span", { className: "mono-label", children: label('architecture.chain.mono') })] }), _jsx("div", { className: "provider-grid", children: providerchain().map((name, index) => (_jsxs("div", { className: `provider-cell ${index === 0 ? 'is-active' : ''}`, children: [_jsxs("span", { className: "provider-index", children: ["0", index + 1] }), _jsx("strong", { children: name }), _jsx("small", { children: label(index === 0
91
+ ? 'architecture.chain.preferred'
92
+ : 'architecture.chain.fallback') })] }, name))) })] }), _jsxs("section", { className: "content-section architecture-note", children: [_jsx(ShieldCheck, { fontSize: 21, "aria-hidden": "true" }), _jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: label('architecture.limit.eyebrow') }), _jsx("p", { children: label('architecture.limit.body') })] })] })] }));
93
+ }