sh3-core 0.6.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.
Files changed (242) hide show
  1. package/README.md +9 -0
  2. package/dist/Shell.svelte +283 -0
  3. package/dist/Shell.svelte.d.ts +5 -0
  4. package/dist/api.d.ts +28 -0
  5. package/dist/api.js +50 -0
  6. package/dist/app/admin/ApiKeysView.svelte +169 -0
  7. package/dist/app/admin/ApiKeysView.svelte.d.ts +3 -0
  8. package/dist/app/admin/AuthSettingsView.svelte +105 -0
  9. package/dist/app/admin/AuthSettingsView.svelte.d.ts +3 -0
  10. package/dist/app/admin/SystemView.svelte +73 -0
  11. package/dist/app/admin/SystemView.svelte.d.ts +3 -0
  12. package/dist/app/admin/UsersView.svelte +188 -0
  13. package/dist/app/admin/UsersView.svelte.d.ts +3 -0
  14. package/dist/app/admin/adminApp.d.ts +7 -0
  15. package/dist/app/admin/adminApp.js +25 -0
  16. package/dist/app/admin/adminShard.svelte.d.ts +4 -0
  17. package/dist/app/admin/adminShard.svelte.js +62 -0
  18. package/dist/app/store/InstalledView.svelte +246 -0
  19. package/dist/app/store/InstalledView.svelte.d.ts +3 -0
  20. package/dist/app/store/StoreView.svelte +522 -0
  21. package/dist/app/store/StoreView.svelte.d.ts +3 -0
  22. package/dist/app/store/storeApp.d.ts +10 -0
  23. package/dist/app/store/storeApp.js +26 -0
  24. package/dist/app/store/storeShard.svelte.d.ts +38 -0
  25. package/dist/app/store/storeShard.svelte.js +218 -0
  26. package/dist/apps/lifecycle.d.ts +42 -0
  27. package/dist/apps/lifecycle.js +184 -0
  28. package/dist/apps/registry.svelte.d.ts +40 -0
  29. package/dist/apps/registry.svelte.js +59 -0
  30. package/dist/apps/terminal/manifest.d.ts +8 -0
  31. package/dist/apps/terminal/manifest.js +13 -0
  32. package/dist/apps/terminal/terminal-app.d.ts +7 -0
  33. package/dist/apps/terminal/terminal-app.js +14 -0
  34. package/dist/apps/types.d.ts +93 -0
  35. package/dist/apps/types.js +10 -0
  36. package/dist/artifact.d.ts +32 -0
  37. package/dist/artifact.js +1 -0
  38. package/dist/assets/SH3.png +0 -0
  39. package/dist/assets/icons.svg +1126 -0
  40. package/dist/assets.d.ts +13 -0
  41. package/dist/auth/GuestBanner.svelte +134 -0
  42. package/dist/auth/GuestBanner.svelte.d.ts +3 -0
  43. package/dist/auth/SignInWall.svelte +203 -0
  44. package/dist/auth/SignInWall.svelte.d.ts +7 -0
  45. package/dist/auth/auth.svelte.d.ts +69 -0
  46. package/dist/auth/auth.svelte.js +165 -0
  47. package/dist/auth/index.d.ts +2 -0
  48. package/dist/auth/index.js +1 -0
  49. package/dist/auth/types.d.ts +41 -0
  50. package/dist/auth/types.js +6 -0
  51. package/dist/build.d.ts +49 -0
  52. package/dist/build.js +236 -0
  53. package/dist/contract.d.ts +20 -0
  54. package/dist/contract.js +28 -0
  55. package/dist/createShell.d.ts +24 -0
  56. package/dist/createShell.js +131 -0
  57. package/dist/documents/backends.d.ts +17 -0
  58. package/dist/documents/backends.js +156 -0
  59. package/dist/documents/config.d.ts +7 -0
  60. package/dist/documents/config.js +27 -0
  61. package/dist/documents/handle.d.ts +6 -0
  62. package/dist/documents/handle.js +154 -0
  63. package/dist/documents/http-backend.d.ts +22 -0
  64. package/dist/documents/http-backend.js +78 -0
  65. package/dist/documents/index.d.ts +6 -0
  66. package/dist/documents/index.js +8 -0
  67. package/dist/documents/notifications.d.ts +9 -0
  68. package/dist/documents/notifications.js +39 -0
  69. package/dist/documents/types.d.ts +97 -0
  70. package/dist/documents/types.js +12 -0
  71. package/dist/env/client.d.ts +44 -0
  72. package/dist/env/client.js +106 -0
  73. package/dist/env/index.d.ts +2 -0
  74. package/dist/env/index.js +1 -0
  75. package/dist/env/types.d.ts +12 -0
  76. package/dist/env/types.js +8 -0
  77. package/dist/host-entry.d.ts +13 -0
  78. package/dist/host-entry.js +17 -0
  79. package/dist/host.d.ts +15 -0
  80. package/dist/host.js +86 -0
  81. package/dist/index.d.ts +4 -0
  82. package/dist/index.js +14 -0
  83. package/dist/layout/DragPreview.svelte +63 -0
  84. package/dist/layout/DragPreview.svelte.d.ts +3 -0
  85. package/dist/layout/LayoutRenderer.svelte +262 -0
  86. package/dist/layout/LayoutRenderer.svelte.d.ts +6 -0
  87. package/dist/layout/SlotContainer.svelte +140 -0
  88. package/dist/layout/SlotContainer.svelte.d.ts +8 -0
  89. package/dist/layout/SlotDropZone.svelte +122 -0
  90. package/dist/layout/SlotDropZone.svelte.d.ts +8 -0
  91. package/dist/layout/drag.svelte.d.ts +45 -0
  92. package/dist/layout/drag.svelte.js +200 -0
  93. package/dist/layout/inspection.d.ts +72 -0
  94. package/dist/layout/inspection.js +209 -0
  95. package/dist/layout/ops.d.ts +100 -0
  96. package/dist/layout/ops.js +310 -0
  97. package/dist/layout/slotHostPool.svelte.d.ts +36 -0
  98. package/dist/layout/slotHostPool.svelte.js +229 -0
  99. package/dist/layout/store.svelte.d.ts +39 -0
  100. package/dist/layout/store.svelte.js +153 -0
  101. package/dist/layout/tree-walk.d.ts +15 -0
  102. package/dist/layout/tree-walk.js +33 -0
  103. package/dist/layout/types.d.ts +108 -0
  104. package/dist/layout/types.js +25 -0
  105. package/dist/migrations/shell-rename.d.ts +16 -0
  106. package/dist/migrations/shell-rename.js +48 -0
  107. package/dist/overlays/ModalFrame.svelte +87 -0
  108. package/dist/overlays/ModalFrame.svelte.d.ts +10 -0
  109. package/dist/overlays/PopupFrame.svelte +85 -0
  110. package/dist/overlays/PopupFrame.svelte.d.ts +10 -0
  111. package/dist/overlays/ToastItem.svelte +77 -0
  112. package/dist/overlays/ToastItem.svelte.d.ts +9 -0
  113. package/dist/overlays/focusTrap.d.ts +1 -0
  114. package/dist/overlays/focusTrap.js +64 -0
  115. package/dist/overlays/modal.d.ts +9 -0
  116. package/dist/overlays/modal.js +141 -0
  117. package/dist/overlays/popup.d.ts +9 -0
  118. package/dist/overlays/popup.js +108 -0
  119. package/dist/overlays/roots.d.ts +4 -0
  120. package/dist/overlays/roots.js +31 -0
  121. package/dist/overlays/toast.d.ts +6 -0
  122. package/dist/overlays/toast.js +93 -0
  123. package/dist/overlays/types.d.ts +31 -0
  124. package/dist/overlays/types.js +15 -0
  125. package/dist/platform/index.d.ts +10 -0
  126. package/dist/platform/index.js +33 -0
  127. package/dist/platform/tauri-backend.d.ts +15 -0
  128. package/dist/platform/tauri-backend.js +58 -0
  129. package/dist/primitives/.gitkeep +0 -0
  130. package/dist/primitives/ResizableSplitter.svelte +333 -0
  131. package/dist/primitives/ResizableSplitter.svelte.d.ts +35 -0
  132. package/dist/primitives/TabbedPanel.svelte +305 -0
  133. package/dist/primitives/TabbedPanel.svelte.d.ts +50 -0
  134. package/dist/primitives/base.css +42 -0
  135. package/dist/registry/client.d.ts +74 -0
  136. package/dist/registry/client.js +117 -0
  137. package/dist/registry/index.d.ts +13 -0
  138. package/dist/registry/index.js +14 -0
  139. package/dist/registry/installer.d.ts +53 -0
  140. package/dist/registry/installer.js +168 -0
  141. package/dist/registry/integrity.d.ts +32 -0
  142. package/dist/registry/integrity.js +92 -0
  143. package/dist/registry/loader.d.ts +50 -0
  144. package/dist/registry/loader.js +145 -0
  145. package/dist/registry/schema.d.ts +47 -0
  146. package/dist/registry/schema.js +185 -0
  147. package/dist/registry/storage.d.ts +37 -0
  148. package/dist/registry/storage.js +101 -0
  149. package/dist/registry/types.d.ts +262 -0
  150. package/dist/registry/types.js +14 -0
  151. package/dist/server-shard/types.d.ts +67 -0
  152. package/dist/server-shard/types.js +13 -0
  153. package/dist/sh3core-shard/ShellHome.svelte +192 -0
  154. package/dist/sh3core-shard/ShellHome.svelte.d.ts +3 -0
  155. package/dist/sh3core-shard/ShellTitle.svelte +171 -0
  156. package/dist/sh3core-shard/ShellTitle.svelte.d.ts +3 -0
  157. package/dist/sh3core-shard/sh3coreShard.svelte.d.ts +2 -0
  158. package/dist/sh3core-shard/sh3coreShard.svelte.js +53 -0
  159. package/dist/shards/activate.svelte.d.ts +52 -0
  160. package/dist/shards/activate.svelte.js +186 -0
  161. package/dist/shards/registry.d.ts +4 -0
  162. package/dist/shards/registry.js +28 -0
  163. package/dist/shards/types.d.ts +207 -0
  164. package/dist/shards/types.js +20 -0
  165. package/dist/shell-shard/InputLine.svelte +133 -0
  166. package/dist/shell-shard/InputLine.svelte.d.ts +11 -0
  167. package/dist/shell-shard/ScrollbackView.svelte +47 -0
  168. package/dist/shell-shard/ScrollbackView.svelte.d.ts +7 -0
  169. package/dist/shell-shard/Terminal.svelte +122 -0
  170. package/dist/shell-shard/Terminal.svelte.d.ts +8 -0
  171. package/dist/shell-shard/entries/PromptEntry.svelte +25 -0
  172. package/dist/shell-shard/entries/PromptEntry.svelte.d.ts +7 -0
  173. package/dist/shell-shard/entries/RichEntry.svelte +19 -0
  174. package/dist/shell-shard/entries/RichEntry.svelte.d.ts +8 -0
  175. package/dist/shell-shard/entries/StatusEntry.svelte +22 -0
  176. package/dist/shell-shard/entries/StatusEntry.svelte.d.ts +7 -0
  177. package/dist/shell-shard/entries/TextEntry.svelte +25 -0
  178. package/dist/shell-shard/entries/TextEntry.svelte.d.ts +7 -0
  179. package/dist/shell-shard/manifest.d.ts +2 -0
  180. package/dist/shell-shard/manifest.js +11 -0
  181. package/dist/shell-shard/protocol.d.ts +90 -0
  182. package/dist/shell-shard/protocol.js +11 -0
  183. package/dist/shell-shard/registry.d.ts +69 -0
  184. package/dist/shell-shard/registry.js +47 -0
  185. package/dist/shell-shard/rich/AppCard.svelte +25 -0
  186. package/dist/shell-shard/rich/AppCard.svelte.d.ts +10 -0
  187. package/dist/shell-shard/rich/AppsTable.svelte +29 -0
  188. package/dist/shell-shard/rich/AppsTable.svelte.d.ts +12 -0
  189. package/dist/shell-shard/rich/EnvTable.svelte +27 -0
  190. package/dist/shell-shard/rich/EnvTable.svelte.d.ts +8 -0
  191. package/dist/shell-shard/rich/HelpTable.svelte +29 -0
  192. package/dist/shell-shard/rich/HelpTable.svelte.d.ts +12 -0
  193. package/dist/shell-shard/rich/HistoryList.svelte +37 -0
  194. package/dist/shell-shard/rich/HistoryList.svelte.d.ts +9 -0
  195. package/dist/shell-shard/rich/ShardsTable.svelte +28 -0
  196. package/dist/shell-shard/rich/ShardsTable.svelte.d.ts +12 -0
  197. package/dist/shell-shard/rich/ViewsTable.svelte +31 -0
  198. package/dist/shell-shard/rich/ViewsTable.svelte.d.ts +13 -0
  199. package/dist/shell-shard/rich/ZoneTree.svelte +19 -0
  200. package/dist/shell-shard/rich/ZoneTree.svelte.d.ts +8 -0
  201. package/dist/shell-shard/rich/ZonesTable.svelte +27 -0
  202. package/dist/shell-shard/rich/ZonesTable.svelte.d.ts +11 -0
  203. package/dist/shell-shard/scrollback.svelte.d.ts +36 -0
  204. package/dist/shell-shard/scrollback.svelte.js +43 -0
  205. package/dist/shell-shard/session-client.svelte.d.ts +23 -0
  206. package/dist/shell-shard/session-client.svelte.js +120 -0
  207. package/dist/shell-shard/shellShard.svelte.d.ts +2 -0
  208. package/dist/shell-shard/shellShard.svelte.js +139 -0
  209. package/dist/shell-shard/verbs/apps.d.ts +3 -0
  210. package/dist/shell-shard/verbs/apps.js +50 -0
  211. package/dist/shell-shard/verbs/clear.d.ts +2 -0
  212. package/dist/shell-shard/verbs/clear.js +7 -0
  213. package/dist/shell-shard/verbs/help.d.ts +2 -0
  214. package/dist/shell-shard/verbs/help.js +21 -0
  215. package/dist/shell-shard/verbs/history.d.ts +2 -0
  216. package/dist/shell-shard/verbs/history.js +20 -0
  217. package/dist/shell-shard/verbs/index.d.ts +2 -0
  218. package/dist/shell-shard/verbs/index.js +29 -0
  219. package/dist/shell-shard/verbs/session.d.ts +5 -0
  220. package/dist/shell-shard/verbs/session.js +65 -0
  221. package/dist/shell-shard/verbs/shards.d.ts +2 -0
  222. package/dist/shell-shard/verbs/shards.js +14 -0
  223. package/dist/shell-shard/verbs/views.d.ts +4 -0
  224. package/dist/shell-shard/verbs/views.js +90 -0
  225. package/dist/shell-shard/verbs/zones.d.ts +3 -0
  226. package/dist/shell-shard/verbs/zones.js +38 -0
  227. package/dist/shellRuntime.svelte.d.ts +27 -0
  228. package/dist/shellRuntime.svelte.js +27 -0
  229. package/dist/state/backends.d.ts +26 -0
  230. package/dist/state/backends.js +99 -0
  231. package/dist/state/manage.d.ts +14 -0
  232. package/dist/state/manage.js +40 -0
  233. package/dist/state/types.d.ts +55 -0
  234. package/dist/state/types.js +17 -0
  235. package/dist/state/zones.svelte.d.ts +53 -0
  236. package/dist/state/zones.svelte.js +141 -0
  237. package/dist/theme.d.ts +28 -0
  238. package/dist/theme.js +92 -0
  239. package/dist/tokens.css +102 -0
  240. package/dist/version.d.ts +2 -0
  241. package/dist/version.js +2 -0
  242. package/package.json +60 -0
@@ -0,0 +1,192 @@
1
+ <script lang="ts">
2
+ /*
3
+ * Shell home — the view shown when no app is active. Sections:
4
+ * 1. User apps — always visible
5
+ * 2. Admin apps — visible when user has admin role
6
+ */
7
+
8
+ import { listRegisteredApps, launchApp, isAdmin, VERSION } from '../api';
9
+ import ShellTitle from './ShellTitle.svelte';
10
+
11
+ const apps = $derived(listRegisteredApps());
12
+ const userApps = $derived(apps.filter(m => !m.admin));
13
+ const adminApps = $derived(apps.filter(m => m.admin));
14
+ const elevated = $derived(isAdmin());
15
+ </script>
16
+
17
+ <div class="shell-home">
18
+ <header class="shell-home-header">
19
+ <div class="shell-home-title-row">
20
+ <ShellTitle/>
21
+ <span class="shell-home-version">v{VERSION}</span>
22
+ <span class="shell-home-alpha">alpha</span>
23
+ </div>
24
+ <div class="shell-home-credit">
25
+ Art: by <a href="https://www.andbc.co/" target="_blank" rel="noopener noreferrer">andbc</a>
26
+ </div>
27
+ </header>
28
+
29
+ {#if userApps.length > 0}
30
+ <section class="shell-home-section">
31
+ <h2 class="shell-home-section-title">Apps</h2>
32
+ <ul class="shell-home-list">
33
+ {#each userApps as manifest (manifest.id)}
34
+ <li class="shell-home-entry">
35
+ <div class="shell-home-entry-label">{manifest.label}</div>
36
+ <div class="shell-home-entry-meta">
37
+ {manifest.id} · v{manifest.version}
38
+ </div>
39
+ <button
40
+ type="button"
41
+ class="shell-home-launch"
42
+ onclick={() => launchApp(manifest.id)}
43
+ >
44
+ Launch
45
+ </button>
46
+ </li>
47
+ {/each}
48
+ </ul>
49
+ </section>
50
+ {/if}
51
+
52
+ {#if elevated && adminApps.length > 0}
53
+ <section class="shell-home-section">
54
+ <h2 class="shell-home-section-title">Admin</h2>
55
+ <ul class="shell-home-list">
56
+ {#each adminApps as manifest (manifest.id)}
57
+ <li class="shell-home-entry">
58
+ <div class="shell-home-entry-label">{manifest.label}</div>
59
+ <div class="shell-home-entry-meta">
60
+ {manifest.id} · v{manifest.version}
61
+ </div>
62
+ <button
63
+ type="button"
64
+ class="shell-home-launch"
65
+ onclick={() => launchApp(manifest.id)}
66
+ >
67
+ Launch
68
+ </button>
69
+ </li>
70
+ {/each}
71
+ </ul>
72
+ </section>
73
+ {/if}
74
+
75
+ {#if userApps.length === 0 && (!elevated || adminApps.length === 0)}
76
+ <p class="shell-home-empty">No apps registered.</p>
77
+ {/if}
78
+ </div>
79
+
80
+ <style>
81
+ .shell-home {
82
+ position: absolute;
83
+ inset: 0;
84
+ display: flex;
85
+ flex-direction: column;
86
+ align-items: center;
87
+ justify-content: flex-start;
88
+ padding: 48px 24px;
89
+ overflow: auto;
90
+ background: var(--shell-grad-bg, var(--shell-bg));
91
+ color: var(--shell-fg);
92
+ font-family: system-ui, sans-serif;
93
+ }
94
+ .shell-home-header {
95
+ text-align: center;
96
+ margin-bottom: 32px;
97
+ display: flex;
98
+ flex-direction: column;
99
+ align-items: center;
100
+ gap: 12px;
101
+ }
102
+ .shell-home-title-row {
103
+ display: flex;
104
+ align-items: baseline;
105
+ gap: 6px;
106
+ }
107
+ .shell-home-credit {
108
+ font-size: 11px;
109
+ color: var(--shell-fg-muted);
110
+ letter-spacing: 0.04em;
111
+ margin-top: -4px;
112
+ }
113
+ .shell-home-credit a {
114
+ color: var(--shell-fg-subtle);
115
+ text-decoration: none;
116
+ border-bottom: 1px dotted var(--shell-fg-muted);
117
+ }
118
+ .shell-home-credit a:hover {
119
+ color: var(--shell-accent);
120
+ border-bottom-color: var(--shell-accent);
121
+ }
122
+ .shell-home-version {
123
+ font-size: 14px;
124
+ color: var(--shell-fg-subtle);
125
+ letter-spacing: 0.04em;
126
+ }
127
+ .shell-home-alpha {
128
+ font-size: 10px;
129
+ font-weight: 700;
130
+ text-transform: uppercase;
131
+ letter-spacing: 0.08em;
132
+ color: #fff;
133
+ background: var(--shell-accent);
134
+ padding: 2px 8px;
135
+ border-radius: 8px;
136
+ position: relative;
137
+ top: -1px;
138
+ }
139
+ .shell-home-empty {
140
+ color: var(--shell-fg-muted);
141
+ font-style: italic;
142
+ }
143
+ .shell-home-section {
144
+ width: 100%;
145
+ max-width: 440px;
146
+ margin-bottom: 24px;
147
+ }
148
+ .shell-home-section-title {
149
+ font-size: 13px;
150
+ font-weight: 600;
151
+ text-transform: uppercase;
152
+ letter-spacing: 0.06em;
153
+ color: var(--shell-fg-subtle);
154
+ margin: 0 0 12px;
155
+ }
156
+ .shell-home-list {
157
+ list-style: none;
158
+ margin: 0;
159
+ padding: 0;
160
+ display: flex;
161
+ flex-direction: column;
162
+ gap: 12px;
163
+ }
164
+ .shell-home-entry {
165
+ display: grid;
166
+ grid-template-columns: 1fr auto;
167
+ grid-template-rows: auto auto;
168
+ gap: 4px 16px;
169
+ align-items: center;
170
+ padding: 14px 18px;
171
+ background: var(--shell-grad-bg-elevated, var(--shell-bg-elevated));
172
+ border: 1px solid var(--shell-border);
173
+ border-radius: var(--shell-radius-md);
174
+ }
175
+ .shell-home-entry-label {
176
+ grid-column: 1;
177
+ grid-row: 1;
178
+ font-weight: 600;
179
+ }
180
+ .shell-home-entry-meta {
181
+ grid-column: 1;
182
+ grid-row: 2;
183
+ font-size: 11px;
184
+ color: var(--shell-fg-subtle);
185
+ }
186
+ .shell-home-launch {
187
+ grid-column: 2;
188
+ grid-row: 1 / span 2;
189
+ padding: 8px 16px;
190
+ font-weight: 600;
191
+ }
192
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const ShellHome: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type ShellHome = ReturnType<typeof ShellHome>;
3
+ export default ShellHome;
@@ -0,0 +1,171 @@
1
+ <script lang="ts" module>
2
+ /*
3
+ * p5 is loaded from a CDN rather than bundled, to keep sh3-core's
4
+ * footprint small. The promise is cached at module scope so repeated
5
+ * mounts reuse a single <script> injection.
6
+ */
7
+ const P5_CDN = 'https://cdn.jsdelivr.net/npm/p5@1.11.13/lib/p5.min.js';
8
+ let p5Promise: Promise<any> | null = null;
9
+
10
+ function loadP5(): Promise<any> {
11
+ if (p5Promise) return p5Promise;
12
+ p5Promise = new Promise((resolve, reject) => {
13
+ const existing = (window as any).p5;
14
+ if (existing) {
15
+ resolve(existing);
16
+ return;
17
+ }
18
+ const s = document.createElement('script');
19
+ s.src = P5_CDN;
20
+ s.async = true;
21
+ s.onload = () => resolve((window as any).p5);
22
+ s.onerror = (err) => {
23
+ p5Promise = null;
24
+ reject(err);
25
+ };
26
+ document.head.appendChild(s);
27
+ });
28
+ return p5Promise;
29
+ }
30
+ </script>
31
+
32
+ <script lang="ts">
33
+ import sh3Img from '../assets/SH3.png';
34
+
35
+ const CHARS = '`.-\':;,^"~=+<>*?!/\\|()[]{}x1ltzrcvunsXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$';
36
+ const ASCII_W = 64;
37
+ const ASCII_H = Math.floor(64 / (442 / 193)); // ~28, matches image ratio
38
+ const CELL_W = 8;
39
+ const CELL_H = 7;
40
+ const DISPLAY_H = 80; // rendered CSS height in px; width auto-derived from aspect ratio
41
+ // Canvas keeps its native pixel buffer (ASCII_W*CELL_W × ASCII_H*CELL_H) for full
42
+ // text resolution; CSS transform scales the painted output down to DISPLAY_H, and
43
+ // the container is sized to the scaled dimensions so layout sees the visible size.
44
+ const NATIVE_W = ASCII_W * CELL_W;
45
+ const NATIVE_H = ASCII_H * CELL_H;
46
+ const SCALE = DISPLAY_H / NATIVE_H;
47
+ const DISPLAY_W = NATIVE_W * SCALE;
48
+
49
+ let container = $state<HTMLDivElement | undefined>(undefined);
50
+ let p5inst: any = null;
51
+ let failed = $state(false);
52
+
53
+ const buildSketch = () => (p: any) => {
54
+ const rootStyle = getComputedStyle(document.documentElement);
55
+ const accentColor = rootStyle.getPropertyValue('--shell-accent').trim();
56
+ let gfx: any;
57
+ let src: any;
58
+ let ready = false;
59
+
60
+ p.setup = () => {
61
+ // Create the canvas synchronously in setup, otherwise p5 will auto-create
62
+ // a default 100x100 canvas and a later createCanvas() call would produce
63
+ // a SECOND canvas rather than replacing the first.
64
+ p.createCanvas(NATIVE_W, NATIVE_H);
65
+
66
+ p.noSmooth();
67
+ p.noStroke();
68
+ p.textAlign(p.CENTER, p.CENTER);
69
+ p.textFont('monospace');
70
+ p.textSize(10);
71
+ p.textStyle(p.BOLD);
72
+
73
+ src = p.loadImage(
74
+ sh3Img,
75
+ () => {
76
+ gfx = p.createGraphics(ASCII_W, ASCII_H);
77
+ gfx.pixelDensity(1);
78
+ gfx.image(src, 0, 0, ASCII_W, ASCII_H);
79
+ gfx.loadPixels();
80
+ ready = true;
81
+ },
82
+ () => { failed = true; },
83
+ );
84
+ };
85
+
86
+ p.draw = () => {
87
+ if (!ready) return;
88
+ const t = p.millis() * 0.001;
89
+ let n: number;
90
+
91
+ p.clear();
92
+ p.background(0, 0);
93
+ p.fill(accentColor);
94
+
95
+ for (let y = 0; y < ASCII_H; y++) {
96
+ for (let x = 0; x < ASCII_W; x++) {
97
+ const i = (y * ASCII_W + x) * 4;
98
+ if (gfx.pixels[i] < 64) {
99
+ n = p.noise(x / ASCII_W * 2.0, y / ASCII_H * 2.0, t * 0.15);
100
+ if (n > 0.33) continue;
101
+ p.text(CHARS[Math.floor(n * CHARS.length * 0.25)], (x + 0.5) * CELL_W, (y + 0.5) * CELL_H);
102
+ continue;
103
+ }
104
+ n = p.noise(x / ASCII_W * 4.0, y / ASCII_H * 4.0, t * 0.5);
105
+ p.text(CHARS[Math.floor(n * CHARS.length)], (x + 0.5) * CELL_W, (y + 0.5) * CELL_H);
106
+ }
107
+ }
108
+ };
109
+ };
110
+
111
+ $effect(() => {
112
+ if (failed) return;
113
+ let cancelled = false;
114
+ loadP5()
115
+ .then((P5) => {
116
+ if (cancelled || !container) return;
117
+ try {
118
+ p5inst = new P5(buildSketch(), container);
119
+ } catch (err) {
120
+ console.error('[ShellTitle] p5 sketch failed to start', err);
121
+ failed = true;
122
+ }
123
+ })
124
+ .catch((err) => {
125
+ console.error('[ShellTitle] failed to load p5 from CDN', err);
126
+ failed = true;
127
+ });
128
+
129
+ return () => {
130
+ cancelled = true;
131
+ if (p5inst) {
132
+ p5inst.remove();
133
+ p5inst = null;
134
+ }
135
+ };
136
+ });
137
+ </script>
138
+
139
+ {#if failed}
140
+ <h1 class="shell-title-fallback">SH3</h1>
141
+ {:else}
142
+ <div
143
+ bind:this={container}
144
+ class="shell-title"
145
+ style:width="{DISPLAY_W}px"
146
+ style:height="{DISPLAY_H}px"
147
+ style:--shell-title-scale={SCALE}
148
+ ></div>
149
+ {/if}
150
+
151
+ <style>
152
+ .shell-title {
153
+ display: inline-block;
154
+ line-height: 0;
155
+ overflow: hidden;
156
+ }
157
+ /* canvas is injected by p5 at runtime, so scoped selectors don't reach it */
158
+ .shell-title :global(canvas) {
159
+ transform: scale(var(--shell-title-scale));
160
+ transform-origin: top left;
161
+ /* p5 sets inline width/height attributes on the canvas; override its inline
162
+ style so layout doesn't get the intrinsic pixel-buffer size. */
163
+ display: block;
164
+ }
165
+ .shell-title-fallback {
166
+ margin: 0;
167
+ font-size: 42px;
168
+ color: var(--shell-accent);
169
+ letter-spacing: 2px;
170
+ }
171
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const ShellTitle: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type ShellTitle = ReturnType<typeof ShellTitle>;
3
+ export default ShellTitle;
@@ -0,0 +1,2 @@
1
+ import type { Shard } from '../api';
2
+ export declare const sh3coreShard: Shard;
@@ -0,0 +1,53 @@
1
+ /*
2
+ * SH3-core pseudo-shard — the framework-owned shard with reserved id
3
+ * `__sh3core__`. Contributes exactly one view, `sh3core:home`, which the
4
+ * layout manager's home tree references.
5
+ *
6
+ * Renamed from the former `__shell__` pseudo-shard on 2026-04-10 to free
7
+ * the `shell` id and the `src/shell-shard/` directory for the new
8
+ * user-facing shell-shard (terminal). See
9
+ * `docs/superpowers/specs/2026-04-10-shell-shard-design.md` § Step 0.
10
+ *
11
+ * This shard uses the public contract same as any other shard (see
12
+ * ADR-008 / the phase-8 shell-as-shard feasibility check). Its only
13
+ * concession to being framework-owned is:
14
+ * - The reserved id `__sh3core__`
15
+ * - It is registered by `bootstrap()` itself, not by the glob loop
16
+ *
17
+ * Activation goes through the same `registerShard` / `activateShard`
18
+ * pipeline as mock and diagnostic. `autostart` is a no-op, defined only
19
+ * so activation is driven by the self-starting pass in bootstrap rather
20
+ * than by requiring a special code path.
21
+ *
22
+ * `.svelte.ts` because mounting Svelte components requires rune access.
23
+ */
24
+ import { mount, unmount } from 'svelte';
25
+ import ShellHome from './ShellHome.svelte';
26
+ import { VERSION } from '../version';
27
+ export const sh3coreShard = {
28
+ manifest: {
29
+ id: '__sh3core__',
30
+ label: 'SH3 Core',
31
+ version: VERSION,
32
+ views: [{ id: 'sh3core:home', label: 'Home' }],
33
+ },
34
+ activate(ctx) {
35
+ const factory = {
36
+ mount(container, _context) {
37
+ const instance = mount(ShellHome, { target: container });
38
+ return {
39
+ unmount() {
40
+ unmount(instance);
41
+ },
42
+ // Home does not need onResize — it uses absolute inset:0 layout.
43
+ };
44
+ },
45
+ };
46
+ ctx.registerView('sh3core:home', factory);
47
+ },
48
+ autostart() {
49
+ // Intentionally empty. Defining this field is what puts the sh3core
50
+ // pseudo-shard on the self-starting path at boot (see bootstrap),
51
+ // so `sh3core:home` is available before any app launches.
52
+ },
53
+ };
@@ -0,0 +1,52 @@
1
+ import type { Shard, ShardContext } from './types';
2
+ /**
3
+ * Reactive registry of every shard known to the host. Keys are shard ids.
4
+ * Populated once at boot by the glob-discovery loop in main.ts (through
5
+ * `registerShard`); a future runtime loader appends late without touching
6
+ * the rest of the framework. Callers that need a live list subscribe via
7
+ * Svelte reactivity (e.g. shell home listing apps cross-references this
8
+ * map to show which shards they require).
9
+ */
10
+ export declare const registeredShards: Map<string, Shard>;
11
+ export declare const activeShards: Map<string, Shard>;
12
+ /**
13
+ * Register (or re-register) a shard with the framework so it can later be
14
+ * activated. Records the shard in `registeredShards` but does not run
15
+ * `activate` — that happens at app launch (or for self-starting shards).
16
+ *
17
+ * If a shard with the same id already exists it is silently replaced,
18
+ * which is the expected path during package updates. If the old shard was
19
+ * active it is deactivated first so the new version can be cleanly
20
+ * activated on next launch.
21
+ */
22
+ export declare function registerShard(shard: Shard): void;
23
+ /**
24
+ * Activate a registered shard. Builds a `ShardContext`, calls `shard.activate`,
25
+ * verifies that every view declared in the manifest received a factory, then
26
+ * calls `shard.autostart` if defined. Idempotent — calling on an already-active
27
+ * shard is a no-op.
28
+ *
29
+ * @param id - The `ShardManifest.id` of the shard to activate. Must be registered.
30
+ * @throws If the shard is not registered, or if a manifest view has no factory after activation.
31
+ */
32
+ export declare function activateShard(id: string): Promise<void>;
33
+ /**
34
+ * Deactivate an active shard. Calls `shard.deactivate`, flushes and disposes
35
+ * all document handles, unregisters all view factories, and removes the shard
36
+ * from `activeShards`. The shard remains in `registeredShards` and can be
37
+ * re-activated. No-op if the shard is not currently active.
38
+ *
39
+ * @param id - The `ShardManifest.id` of the shard to deactivate.
40
+ */
41
+ export declare function deactivateShard(id: string): void;
42
+ /**
43
+ * Return true if the shard with the given id is currently active.
44
+ *
45
+ * @param id - The `ShardManifest.id` to check.
46
+ */
47
+ export declare function isActive(id: string): boolean;
48
+ /**
49
+ * Return the ShardContext for an active shard, or undefined if not active.
50
+ * Used by lifecycle.ts to pass context to `shard.resume()`.
51
+ */
52
+ export declare function getShardContext(id: string): ShardContext | undefined;
@@ -0,0 +1,186 @@
1
+ /*
2
+ * Shard lifecycle — phase 8 split into register and activate.
3
+ *
4
+ * registerShard(shard): adds the shard's manifest to the reactive
5
+ * `registeredShards` map. No side effects. The host (main.ts) calls
6
+ * this once per shard via its glob-discovery boot loop. A future
7
+ * runtime loader calls it after fetching a shard module.
8
+ *
9
+ * activateShard(id): looks up a registered shard, builds its
10
+ * ShardContext, runs `activate(ctx)`, verifies every manifest view id
11
+ * received a factory, then runs `autostart(ctx)` if present. The shard
12
+ * moves into the reactive `activeShards` map. Called internally by
13
+ * app launch and by the bootstrap self-starting pass. Not public.
14
+ *
15
+ * deactivateShard(id): inverse of activate. Calls `deactivate()`,
16
+ * unregisters view factories, drops from `activeShards`. The shard
17
+ * stays in `registeredShards` — it's still known, just not running.
18
+ */
19
+ import { shell } from '../shellRuntime.svelte';
20
+ import { registerView, unregisterView } from './registry';
21
+ import { createDocumentHandle, getTenantId, getDocumentBackend } from '../documents';
22
+ import { fetchEnvState, putEnvState } from '../env/client';
23
+ import { isAdmin as checkIsAdmin } from '../auth/index';
24
+ import { createZoneManager } from '../state/manage';
25
+ import { PERMISSION_STATE_MANAGE } from '../state/types';
26
+ /**
27
+ * Reactive registry of every shard known to the host. Keys are shard ids.
28
+ * Populated once at boot by the glob-discovery loop in main.ts (through
29
+ * `registerShard`); a future runtime loader appends late without touching
30
+ * the rest of the framework. Callers that need a live list subscribe via
31
+ * Svelte reactivity (e.g. shell home listing apps cross-references this
32
+ * map to show which shards they require).
33
+ */
34
+ export const registeredShards = $state(new Map());
35
+ /**
36
+ * Reactive map of currently-active shards. A shard lands here when
37
+ * `activateShard` runs successfully and stays until `deactivateShard`.
38
+ */
39
+ const active = new Map();
40
+ export const activeShards = $state(new Map());
41
+ /**
42
+ * Register (or re-register) a shard with the framework so it can later be
43
+ * activated. Records the shard in `registeredShards` but does not run
44
+ * `activate` — that happens at app launch (or for self-starting shards).
45
+ *
46
+ * If a shard with the same id already exists it is silently replaced,
47
+ * which is the expected path during package updates. If the old shard was
48
+ * active it is deactivated first so the new version can be cleanly
49
+ * activated on next launch.
50
+ */
51
+ export function registerShard(shard) {
52
+ const id = shard.manifest.id;
53
+ if (registeredShards.has(id) && activeShards.has(id)) {
54
+ deactivateShard(id);
55
+ }
56
+ registeredShards.set(id, shard);
57
+ }
58
+ /**
59
+ * Activate a registered shard. Builds a `ShardContext`, calls `shard.activate`,
60
+ * verifies that every view declared in the manifest received a factory, then
61
+ * calls `shard.autostart` if defined. Idempotent — calling on an already-active
62
+ * shard is a no-op.
63
+ *
64
+ * @param id - The `ShardManifest.id` of the shard to activate. Must be registered.
65
+ * @throws If the shard is not registered, or if a manifest view has no factory after activation.
66
+ */
67
+ export async function activateShard(id) {
68
+ var _a, _b;
69
+ const shard = registeredShards.get(id);
70
+ if (!shard) {
71
+ throw new Error(`Cannot activate shard "${id}": not registered`);
72
+ }
73
+ if (active.has(id)) {
74
+ // Already active (e.g. self-starting shard that was activated at boot
75
+ // and is now being required by an app). Idempotent — no error.
76
+ return;
77
+ }
78
+ const entry = { shard, ctx: undefined, viewIds: new Set(), cleanupFns: [] };
79
+ // envState holds the reactive env data for this shard.
80
+ // Must be declared with $state at variable declaration time (Svelte 5 rule).
81
+ const envState = $state({
82
+ proxy: null,
83
+ defaults: null,
84
+ });
85
+ const ctx = {
86
+ state: (schema) => shell.state(id, schema),
87
+ registerView: (viewId, factory) => {
88
+ registerView(viewId, factory);
89
+ entry.viewIds.add(viewId);
90
+ },
91
+ documents: (options) => {
92
+ const handle = createDocumentHandle(getTenantId(), id, getDocumentBackend(), options);
93
+ entry.cleanupFns.push(() => handle.dispose());
94
+ return handle;
95
+ },
96
+ env(defaults) {
97
+ if (envState.proxy) {
98
+ console.warn(`[sh3] Shard "${id}" called ctx.env() more than once; extra calls are ignored.`);
99
+ return envState.proxy;
100
+ }
101
+ envState.defaults = defaults;
102
+ envState.proxy = Object.assign({}, defaults);
103
+ return envState.proxy;
104
+ },
105
+ async envUpdate(patch) {
106
+ if (!envState.proxy || !envState.defaults) {
107
+ throw new Error(`Shard "${id}" called envUpdate() without declaring env state`);
108
+ }
109
+ const previous = $state.snapshot(envState.proxy);
110
+ Object.assign(envState.proxy, patch);
111
+ try {
112
+ const snapshot = $state.snapshot(envState.proxy);
113
+ await putEnvState(id, snapshot);
114
+ }
115
+ catch (err) {
116
+ Object.assign(envState.proxy, previous);
117
+ throw err;
118
+ }
119
+ },
120
+ get isAdmin() {
121
+ return checkIsAdmin();
122
+ },
123
+ zones: ((_a = shard.manifest.permissions) === null || _a === void 0 ? void 0 : _a.includes(PERMISSION_STATE_MANAGE))
124
+ ? createZoneManager()
125
+ : undefined,
126
+ };
127
+ entry.ctx = ctx;
128
+ active.set(id, entry);
129
+ activeShards.set(id, shard);
130
+ await shard.activate(ctx);
131
+ for (const view of shard.manifest.views) {
132
+ if (!entry.viewIds.has(view.id)) {
133
+ throw new Error(`Shard "${id}" declared view "${view.id}" in its manifest but registered no factory for it.`);
134
+ }
135
+ }
136
+ // Hydrate env state if the shard declared it via ctx.env().
137
+ if (envState.proxy && envState.defaults) {
138
+ try {
139
+ const stored = await fetchEnvState(id);
140
+ const merged = Object.assign({}, envState.defaults, stored);
141
+ Object.assign(envState.proxy, merged);
142
+ }
143
+ catch (err) {
144
+ console.warn(`[sh3] Failed to hydrate env state for shard "${id}":`, err instanceof Error ? err.message : err);
145
+ }
146
+ }
147
+ void ((_b = shard.autostart) === null || _b === void 0 ? void 0 : _b.call(shard, ctx));
148
+ }
149
+ /**
150
+ * Deactivate an active shard. Calls `shard.deactivate`, flushes and disposes
151
+ * all document handles, unregisters all view factories, and removes the shard
152
+ * from `activeShards`. The shard remains in `registeredShards` and can be
153
+ * re-activated. No-op if the shard is not currently active.
154
+ *
155
+ * @param id - The `ShardManifest.id` of the shard to deactivate.
156
+ */
157
+ export function deactivateShard(id) {
158
+ var _a, _b;
159
+ const entry = active.get(id);
160
+ if (!entry)
161
+ return;
162
+ void ((_b = (_a = entry.shard).deactivate) === null || _b === void 0 ? void 0 : _b.call(_a));
163
+ // Flush and dispose document handles before tearing down views.
164
+ for (const fn of entry.cleanupFns)
165
+ void fn();
166
+ for (const viewId of entry.viewIds)
167
+ unregisterView(viewId);
168
+ active.delete(id);
169
+ activeShards.delete(id);
170
+ }
171
+ /**
172
+ * Return true if the shard with the given id is currently active.
173
+ *
174
+ * @param id - The `ShardManifest.id` to check.
175
+ */
176
+ export function isActive(id) {
177
+ return active.has(id);
178
+ }
179
+ /**
180
+ * Return the ShardContext for an active shard, or undefined if not active.
181
+ * Used by lifecycle.ts to pass context to `shard.resume()`.
182
+ */
183
+ export function getShardContext(id) {
184
+ var _a;
185
+ return (_a = active.get(id)) === null || _a === void 0 ? void 0 : _a.ctx;
186
+ }
@@ -0,0 +1,4 @@
1
+ import type { ViewFactory } from './types';
2
+ export declare function registerView(viewId: string, factory: ViewFactory): void;
3
+ export declare function getView(viewId: string): ViewFactory | undefined;
4
+ export declare function unregisterView(viewId: string): void;