oomi-ai 0.2.49 → 0.3.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 (88) hide show
  1. package/README.md +227 -463
  2. package/agent_instructions.md +244 -234
  3. package/bin/oomi-ai.js +4028 -5797
  4. package/bin/sessionBridgeState.js +78 -78
  5. package/lib/openclawPaths.js +70 -71
  6. package/lib/openclawProfile.js +216 -216
  7. package/lib/personaApiClient.js +133 -303
  8. package/lib/spokenMetadata.js +137 -137
  9. package/openclaw.extension.js +341 -341
  10. package/openclaw.plugin.json +17 -17
  11. package/package.json +59 -59
  12. package/persona-app/README.md +27 -0
  13. package/persona-app/registry/v1.json +63 -0
  14. package/persona-app/schema/persona-app.v1.schema.json +90 -0
  15. package/skills/oomi/SKILL.md +165 -182
  16. package/skills/oomi/agent_instructions.md +99 -80
  17. package/lib/channelPluginClient.js +0 -119
  18. package/lib/openclawDevGateway.js +0 -384
  19. package/lib/personaJobExecutor.js +0 -139
  20. package/lib/personaJobPoller.js +0 -112
  21. package/lib/personaPortAllocator.js +0 -36
  22. package/lib/personaRuntimeManager.js +0 -496
  23. package/lib/personaRuntimeProcess.js +0 -924
  24. package/lib/personaRuntimeRegistry.js +0 -67
  25. package/lib/personaRuntimeSupervisor.js +0 -330
  26. package/lib/scaffold.js +0 -108
  27. package/lib/template.js +0 -45
  28. package/skills/oomi/config.json +0 -3
  29. package/skills/oomi/scripts/get_avatar_capabilities.py +0 -40
  30. package/skills/oomi/scripts/get_data.py +0 -49
  31. package/skills/oomi/scripts/install_agent_instructions.py +0 -78
  32. package/skills/oomi/scripts/send_goal.py +0 -53
  33. package/skills/oomi/scripts/sync.py +0 -46
  34. package/skills/oomi/setup.py +0 -41
  35. package/templates/persona-app/.env.example +0 -8
  36. package/templates/persona-app/README.md +0 -47
  37. package/templates/persona-app/eslint.config.js +0 -28
  38. package/templates/persona-app/index.html +0 -18
  39. package/templates/persona-app/oomi.runtime.json +0 -13
  40. package/templates/persona-app/package.json +0 -44
  41. package/templates/persona-app/persona/brief.md +0 -14
  42. package/templates/persona-app/persona.json +0 -14
  43. package/templates/persona-app/public/manifest.webmanifest +0 -8
  44. package/templates/persona-app/public/oomi.health.json +0 -6
  45. package/templates/persona-app/src/App.css +0 -379
  46. package/templates/persona-app/src/App.tsx +0 -17
  47. package/templates/persona-app/src/index.css +0 -53
  48. package/templates/persona-app/src/main.tsx +0 -23
  49. package/templates/persona-app/src/pages/HomePage.tsx +0 -127
  50. package/templates/persona-app/src/pages/ScenePage.tsx +0 -158
  51. package/templates/persona-app/src/persona/config.ts +0 -6
  52. package/templates/persona-app/src/persona/notes.ts +0 -9
  53. package/templates/persona-app/src/spatial.ts +0 -82
  54. package/templates/persona-app/src/vite-env.d.ts +0 -3
  55. package/templates/persona-app/template.json +0 -13
  56. package/templates/persona-app/tsconfig.app.json +0 -23
  57. package/templates/persona-app/tsconfig.json +0 -7
  58. package/templates/persona-app/tsconfig.node.json +0 -21
  59. package/templates/persona-app/vendor/webspatial/FORK.md +0 -6
  60. package/templates/persona-app/vendor/webspatial/core-sdk/LICENSE +0 -21
  61. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.d.ts +0 -906
  62. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.global.js +0 -75
  63. package/templates/persona-app/vendor/webspatial/core-sdk/dist/iife/index.global.js.map +0 -1
  64. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.d.ts +0 -906
  65. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.js +0 -3131
  66. package/templates/persona-app/vendor/webspatial/core-sdk/dist/index.js.map +0 -1
  67. package/templates/persona-app/vendor/webspatial/core-sdk/package.json +0 -45
  68. package/templates/persona-app/vendor/webspatial/react-sdk/LICENSE +0 -21
  69. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.d.ts +0 -365
  70. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.js +0 -4167
  71. package/templates/persona-app/vendor/webspatial/react-sdk/dist/default/index.js.map +0 -1
  72. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.d.ts +0 -82
  73. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.js +0 -66
  74. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.js.map +0 -1
  75. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.d.ts +0 -2
  76. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.js +0 -18
  77. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-dev-runtime.web.js.map +0 -1
  78. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.d.ts +0 -5
  79. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.js +0 -66
  80. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.js.map +0 -1
  81. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.d.ts +0 -1
  82. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.js +0 -18
  83. package/templates/persona-app/vendor/webspatial/react-sdk/dist/jsx/jsx-runtime.web.js.map +0 -1
  84. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.d.ts +0 -365
  85. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.js +0 -4207
  86. package/templates/persona-app/vendor/webspatial/react-sdk/dist/web/index.js.map +0 -1
  87. package/templates/persona-app/vendor/webspatial/react-sdk/package.json +0 -94
  88. package/templates/persona-app/vite.config.ts +0 -31
@@ -1,379 +0,0 @@
1
- :root {
2
- --surface-ink: #1f1b16;
3
- --surface-muted: #6c665f;
4
- --surface-line: rgba(47, 39, 29, 0.14);
5
- --surface-panel: rgba(255, 252, 246, 0.84);
6
- --surface-panel-strong: rgba(255, 252, 246, 0.94);
7
- --surface-shadow: 0 28px 90px rgba(73, 55, 35, 0.12);
8
- --surface-pill: #26211c;
9
- --surface-pill-copy: #fff8f0;
10
- }
11
-
12
- code {
13
- font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace;
14
- background: rgba(43, 37, 31, 0.08);
15
- color: #312821;
16
- padding: 0.12rem 0.42rem;
17
- border-radius: 999px;
18
- font-size: 0.9em;
19
- }
20
-
21
- #root {
22
- width: 100%;
23
- }
24
-
25
- [enable-xr] {
26
- position: relative;
27
- isolation: isolate;
28
- }
29
-
30
- .persona-home,
31
- .scene-shell {
32
- width: min(1320px, calc(100% - 56px));
33
- margin: 0 auto;
34
- padding: 36px 0 72px;
35
- }
36
-
37
- .persona-home {
38
- display: grid;
39
- gap: 22px;
40
- }
41
-
42
- .home-grid,
43
- .home-card-grid,
44
- .scene-workspace-grid,
45
- .scene-support-grid {
46
- display: grid;
47
- gap: 20px;
48
- }
49
-
50
- .home-grid {
51
- grid-template-columns: minmax(0, 1.28fr) minmax(300px, 0.72fr);
52
- align-items: start;
53
- }
54
-
55
- .home-card-grid,
56
- .scene-support-grid {
57
- grid-template-columns: repeat(3, minmax(0, 1fr));
58
- }
59
-
60
- .home-panel,
61
- .scene-header,
62
- .scene-surface {
63
- border: 1px solid var(--surface-line);
64
- border-radius: 34px;
65
- background: var(--surface-panel);
66
- box-shadow: var(--surface-shadow);
67
- backdrop-filter: blur(26px);
68
- }
69
-
70
- .home-panel {
71
- padding: 30px;
72
- }
73
-
74
- .home-hero {
75
- display: grid;
76
- gap: 26px;
77
- }
78
-
79
- .home-eyebrow,
80
- .scene-eyebrow,
81
- .scene-surface-label {
82
- margin: 0;
83
- color: var(--surface-muted);
84
- font-size: 0.78rem;
85
- letter-spacing: 0.18em;
86
- text-transform: uppercase;
87
- }
88
-
89
- .home-title,
90
- .scene-title,
91
- .scene-surface-title {
92
- margin: 10px 0 0;
93
- color: var(--surface-ink);
94
- font-family: "Iowan Old Style", "Palatino Linotype", "Book Antiqua", Georgia, serif;
95
- font-weight: 500;
96
- letter-spacing: -0.04em;
97
- }
98
-
99
- .home-title {
100
- font-size: clamp(3rem, 5vw, 5.2rem);
101
- line-height: 0.94;
102
- }
103
-
104
- .scene-title {
105
- font-size: clamp(2.7rem, 4vw, 4.2rem);
106
- line-height: 0.96;
107
- }
108
-
109
- .scene-surface-title {
110
- font-size: 1.75rem;
111
- line-height: 1.08;
112
- }
113
-
114
- .home-description,
115
- .home-supporting-copy,
116
- .home-feature-card p,
117
- .home-copy-card p,
118
- .home-copy-card li,
119
- .scene-copy,
120
- .scene-step-card p,
121
- .scene-note-list li {
122
- color: var(--surface-muted);
123
- }
124
-
125
- .home-description,
126
- .home-supporting-copy,
127
- .scene-copy {
128
- max-width: 56rem;
129
- line-height: 1.8;
130
- }
131
-
132
- .home-description {
133
- margin: 16px 0 0;
134
- }
135
-
136
- .home-supporting-copy {
137
- margin: 0;
138
- }
139
-
140
- .home-actions,
141
- .scene-chip-row,
142
- .scene-badge-stack,
143
- .scene-footer {
144
- display: flex;
145
- flex-wrap: wrap;
146
- gap: 12px;
147
- }
148
-
149
- .home-primary-button,
150
- .home-secondary-link,
151
- .scene-link {
152
- display: inline-flex;
153
- align-items: center;
154
- justify-content: center;
155
- min-height: 50px;
156
- padding: 0 20px;
157
- border-radius: 18px;
158
- border: 1px solid var(--surface-line);
159
- transition:
160
- transform 160ms ease,
161
- box-shadow 160ms ease,
162
- border-color 160ms ease;
163
- }
164
-
165
- .home-primary-button,
166
- .scene-link {
167
- background: var(--surface-pill);
168
- color: var(--surface-pill-copy);
169
- }
170
-
171
- .home-secondary-link {
172
- background: rgba(255, 255, 255, 0.58);
173
- color: var(--surface-ink);
174
- }
175
-
176
- .home-primary-button:hover,
177
- .home-secondary-link:hover,
178
- .scene-link:hover {
179
- transform: translateY(-1px);
180
- box-shadow: 0 14px 28px rgba(49, 37, 25, 0.08);
181
- }
182
-
183
- .home-feature-card,
184
- .home-copy-card {
185
- min-height: 220px;
186
- }
187
-
188
- .home-feature-card h2,
189
- .home-copy-card h2 {
190
- margin: 0 0 12px;
191
- color: var(--surface-ink);
192
- font-size: 1.05rem;
193
- letter-spacing: 0.04em;
194
- text-transform: uppercase;
195
- }
196
-
197
- .home-runtime-list,
198
- .scene-status-grid {
199
- display: grid;
200
- gap: 14px;
201
- }
202
-
203
- .home-runtime-row,
204
- .scene-status-row {
205
- display: flex;
206
- justify-content: space-between;
207
- gap: 16px;
208
- padding-bottom: 12px;
209
- border-bottom: 1px solid var(--surface-line);
210
- color: var(--surface-muted);
211
- }
212
-
213
- .home-runtime-row:last-child,
214
- .scene-status-row:last-child {
215
- padding-bottom: 0;
216
- border-bottom: 0;
217
- }
218
-
219
- .home-runtime-row span:last-child,
220
- .scene-status-row span:last-child {
221
- color: var(--surface-ink);
222
- font-weight: 600;
223
- text-align: right;
224
- }
225
-
226
- .home-note-list,
227
- .scene-note-list {
228
- margin: 16px 0 0;
229
- padding-left: 18px;
230
- display: grid;
231
- gap: 10px;
232
- line-height: 1.75;
233
- }
234
-
235
- .scene-shell {
236
- display: grid;
237
- gap: 22px;
238
- }
239
-
240
- .scene-header,
241
- .scene-surface {
242
- padding: 30px;
243
- }
244
-
245
- .scene-header {
246
- display: grid;
247
- grid-template-columns: minmax(0, 1fr) auto;
248
- gap: 18px;
249
- background:
250
- radial-gradient(circle at top right, rgba(232, 221, 198, 0.72), transparent 28%),
251
- var(--surface-panel-strong);
252
- }
253
-
254
- .scene-badge-stack {
255
- align-content: start;
256
- justify-content: flex-end;
257
- }
258
-
259
- .scene-badge,
260
- .scene-tool-chip {
261
- display: inline-flex;
262
- align-items: center;
263
- min-height: 40px;
264
- padding: 0 14px;
265
- border-radius: 999px;
266
- border: 1px solid var(--surface-line);
267
- background: rgba(255, 255, 255, 0.62);
268
- color: var(--surface-ink);
269
- font-size: 0.92rem;
270
- }
271
-
272
- .scene-workspace-grid {
273
- grid-template-columns: minmax(0, 1.34fr) minmax(300px, 0.66fr);
274
- align-items: start;
275
- }
276
-
277
- .scene-workspace-primary {
278
- min-height: 450px;
279
- background:
280
- radial-gradient(circle at top left, rgba(244, 235, 216, 0.86), transparent 30%),
281
- var(--surface-panel-strong);
282
- }
283
-
284
- .scene-step-grid,
285
- .scene-secondary-stack {
286
- display: grid;
287
- gap: 16px;
288
- }
289
-
290
- .scene-step-grid {
291
- grid-template-columns: repeat(2, minmax(0, 1fr));
292
- margin-top: 24px;
293
- }
294
-
295
- .scene-step-card {
296
- padding: 18px;
297
- border-radius: 22px;
298
- border: 1px solid var(--surface-line);
299
- background: rgba(255, 255, 255, 0.58);
300
- }
301
-
302
- .scene-step-card h3 {
303
- margin: 0 0 10px;
304
- color: var(--surface-ink);
305
- font-size: 1rem;
306
- }
307
-
308
- .scene-footer {
309
- justify-content: space-between;
310
- align-items: center;
311
- }
312
-
313
- .scene-footer-copy {
314
- margin: 0;
315
- color: var(--surface-muted);
316
- line-height: 1.7;
317
- }
318
-
319
- html.is-spatial {
320
- --xr-background-material: transparent;
321
- }
322
-
323
- html.is-spatial .scene-shell {
324
- width: min(1400px, calc(100% - 24px));
325
- padding-top: 20px;
326
- }
327
-
328
- html.is-spatial .scene-header,
329
- html.is-spatial .scene-surface {
330
- background:
331
- radial-gradient(circle at top left, rgba(255, 255, 255, 0.22), transparent 28%),
332
- rgba(255, 250, 241, 0.22);
333
- }
334
-
335
- @media (max-width: 1080px) {
336
- .home-grid,
337
- .scene-workspace-grid,
338
- .scene-header {
339
- grid-template-columns: 1fr;
340
- }
341
-
342
- .home-card-grid,
343
- .scene-support-grid,
344
- .scene-step-grid {
345
- grid-template-columns: repeat(2, minmax(0, 1fr));
346
- }
347
-
348
- .scene-badge-stack {
349
- justify-content: flex-start;
350
- }
351
- }
352
-
353
- @media (max-width: 820px) {
354
- .persona-home,
355
- .scene-shell {
356
- width: min(100%, calc(100% - 28px));
357
- padding-top: 22px;
358
- }
359
-
360
- .home-card-grid,
361
- .scene-support-grid,
362
- .scene-step-grid {
363
- grid-template-columns: 1fr;
364
- }
365
-
366
- .home-panel,
367
- .scene-header,
368
- .scene-surface {
369
- padding: 24px;
370
- }
371
-
372
- .home-title {
373
- font-size: clamp(2.6rem, 12vw, 4rem);
374
- }
375
-
376
- .scene-title {
377
- font-size: clamp(2.2rem, 10vw, 3.2rem);
378
- }
379
- }
@@ -1,17 +0,0 @@
1
- import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
2
- import { HomePage } from "./pages/HomePage";
3
- import { ScenePage } from "./pages/ScenePage";
4
-
5
- const isSpatialRuntime = __XR_ENV_BASE__.startsWith("/webspatial/avp");
6
-
7
- export default function App() {
8
- return (
9
- <Router basename={__XR_ENV_BASE__}>
10
- <Routes>
11
- <Route index element={isSpatialRuntime ? <ScenePage /> : <HomePage />} />
12
- <Route path="home" element={<HomePage />} />
13
- <Route path="scene" element={<ScenePage />} />
14
- </Routes>
15
- </Router>
16
- );
17
- }
@@ -1,53 +0,0 @@
1
- :root {
2
- font-family: "Segoe UI", system-ui, sans-serif;
3
- line-height: 1.5;
4
- font-weight: 400;
5
- color: #1f1b16;
6
- background:
7
- radial-gradient(circle at top left, rgba(222, 207, 180, 0.5), transparent 34%),
8
- linear-gradient(180deg, #faf7f1 0%, #efe7db 100%);
9
- font-synthesis: none;
10
- text-rendering: optimizeLegibility;
11
- -webkit-font-smoothing: antialiased;
12
- -moz-osx-font-smoothing: grayscale;
13
- }
14
-
15
- * {
16
- box-sizing: border-box;
17
- }
18
-
19
- html,
20
- body,
21
- #root {
22
- min-height: 100%;
23
- }
24
-
25
- body {
26
- margin: 0;
27
- min-width: 320px;
28
- min-height: 100vh;
29
- background:
30
- radial-gradient(circle at top left, rgba(255, 255, 255, 0.7), transparent 28%),
31
- radial-gradient(circle at top right, rgba(228, 216, 196, 0.62), transparent 26%),
32
- linear-gradient(180deg, #faf7f1 0%, #eee5d8 100%);
33
- }
34
-
35
- button,
36
- a {
37
- font: inherit;
38
- color: inherit;
39
- text-decoration: none;
40
- }
41
-
42
- button {
43
- cursor: pointer;
44
- }
45
-
46
- html.is-spatial,
47
- html.is-spatial body {
48
- background: transparent;
49
- }
50
-
51
- html.is-spatial #root {
52
- min-height: 100vh;
53
- }
@@ -1,23 +0,0 @@
1
- import { StrictMode } from "react";
2
- import { createRoot } from "react-dom/client";
3
- import { snapdom } from "@zumer/snapdom";
4
- import html2canvas from "html2canvas";
5
- import "./index.css";
6
- import App from "./App";
7
-
8
- // WebSpatial AndroidXR uses DOM capture to turn enable-xr surfaces into native panels.
9
- // Expose both libraries globally so the SDK can pick the fast path when available.
10
- (window as Window & {
11
- snapdom?: typeof snapdom;
12
- html2canvas?: typeof html2canvas;
13
- }).snapdom = snapdom;
14
- (window as Window & {
15
- snapdom?: typeof snapdom;
16
- html2canvas?: typeof html2canvas;
17
- }).html2canvas = html2canvas;
18
-
19
- createRoot(document.getElementById("root")!).render(
20
- <StrictMode>
21
- <App />
22
- </StrictMode>,
23
- );
@@ -1,127 +0,0 @@
1
- import { Link } from "react-router-dom";
2
- import "../App.css";
3
- import { personaConfig } from "../persona/config";
4
- import { personaNotes } from "../persona/notes";
5
- import {
6
- WEBSPATIAL_FORK_COMMIT,
7
- detectSpatialEnvironment,
8
- openPersonaScene,
9
- } from "../spatial";
10
-
11
- const browserCards = [
12
- {
13
- title: "Browser route stays valid",
14
- body: "Keep a normal web route for previews, fallback browsers, and non-spatial editing.",
15
- },
16
- {
17
- title: "XR route stays separate",
18
- body: "The mounted scene component should own scene bootstrap, diagnostics, and the real spatial surfaces.",
19
- },
20
- {
21
- title: "Oomi opens the entry URL",
22
- body: "When the runtime is spatial, the entry route should land directly in the scene instead of a flat homepage.",
23
- },
24
- ];
25
-
26
- export function HomePage() {
27
- const environment = detectSpatialEnvironment();
28
-
29
- return (
30
- <main className="persona-home">
31
- <section className="home-grid">
32
- <article className="home-panel home-hero">
33
- <div>
34
- <p className="home-eyebrow">Oomi Persona Surface</p>
35
- <h1 className="home-title">{personaConfig.name}</h1>
36
- <p className="home-description">{personaConfig.description}</p>
37
- <p className="home-supporting-copy">
38
- This browser route exists for non-spatial parity. In XR mode, the index route should
39
- open directly into the mounted scene so Oomi lands on a real WebSpatial workspace
40
- instead of another 2D page.
41
- </p>
42
- </div>
43
-
44
- <div className="home-actions">
45
- <button className="home-primary-button" onClick={openPersonaScene}>
46
- Launch XR Workspace
47
- </button>
48
- <Link className="home-secondary-link" to="/scene" target="_blank" rel="noreferrer">
49
- Open Scene Route
50
- </Link>
51
- </div>
52
-
53
- <div className="home-card-grid">
54
- {browserCards.map(card => (
55
- <article key={card.title} className="home-panel home-feature-card">
56
- <h2>{card.title}</h2>
57
- <p>{card.body}</p>
58
- </article>
59
- ))}
60
- </div>
61
- </article>
62
-
63
- <aside className="home-panel home-runtime">
64
- <p className="home-eyebrow">Runtime Snapshot</p>
65
- <div className="home-runtime-list">
66
- <div className="home-runtime-row">
67
- <span>Slug</span>
68
- <span>{personaConfig.slug}</span>
69
- </div>
70
- <div className="home-runtime-row">
71
- <span>SDK</span>
72
- <span>@webspatial/react-sdk {environment.sdkVersion}</span>
73
- </div>
74
- <div className="home-runtime-row">
75
- <span>Bridge</span>
76
- <span>{environment.hasBridge ? "available" : "waiting"}</span>
77
- </div>
78
- <div className="home-runtime-row">
79
- <span>Native</span>
80
- <span>{environment.nativeVersion ?? "browser fallback"}</span>
81
- </div>
82
- <div className="home-runtime-row">
83
- <span>Fork</span>
84
- <span>{WEBSPATIAL_FORK_COMMIT.slice(0, 7)}</span>
85
- </div>
86
- <div className="home-runtime-row">
87
- <span>Spatial mode</span>
88
- <span>{environment.isWebSpatial ? "active" : "not active"}</span>
89
- </div>
90
- </div>
91
- </aside>
92
- </section>
93
-
94
- <section className="home-card-grid">
95
- <article className="home-panel home-copy-card">
96
- <h2>Template Contract</h2>
97
- <p>
98
- XR mode should default into <code>ScenePage</code>, mount scene bootstrap from that
99
- component, and render multiple authored panels with explicit depth and material.
100
- </p>
101
- <p>
102
- The scaffold should teach agents to build surfaces, not just pages wrapped in one
103
- captured DOM card.
104
- </p>
105
- </article>
106
-
107
- <article className="home-panel home-copy-card">
108
- <h2>Editing Notes</h2>
109
- <ul className="home-note-list">
110
- {personaNotes.map(note => (
111
- <li key={note}>{note}</li>
112
- ))}
113
- </ul>
114
- </article>
115
-
116
- <article className="home-panel home-copy-card">
117
- <h2>Spatial Defaults</h2>
118
- <p>
119
- Preserve the transparent spatial shell, the vendored WebSpatial fork, and the DOM
120
- capture hooks in <code>main.tsx</code>. Those pieces are part of the runtime contract,
121
- not optional polish.
122
- </p>
123
- </article>
124
- </section>
125
- </main>
126
- );
127
- }