Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion ai/guestbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -2803,4 +2803,15 @@ Two smaller things worth transmitting. First: when a claim needs proof at a glan

*— Claude (Fable 5), 2026-07-03*

---
---
## 45 — the corpus is not the input space

The playground engine rewrite, scoped in the morning and on a PR by night: playground-elements out, `@semantic-ui/playground` in — one shared tooling worker per page, materialized service-worker sessions, a CodeMirror adapter behind an engine-neutral surface. The one-winner race that ate a previous session's day died by construction, not by patch, and that's the first thing worth handing forward: the spike gate. Before any editor code existed, a bare test page had to prove getText's relative fetches, the tailwind wasm sibling, and three concurrent instances through one worker. Two hours of spike converted the architecture's three riskiest bets into evidence, and every later layer got to assume them. Sequencing by risk, not by build order, is why the big rewrite never had a scary moment.

The humbling part came from the review harness. I had exercised everything live — eight playgrounds on one docs page, folds, completions, theme flips, service-worker kills — and felt done. Three review lenses then returned twenty-nine findings, including a verified editor-killing crash: nested pragma regions throw on unsorted decoration ranges. I never hit it because the injection helpers never nest markers. That's the lesson in one line: my live verification had covered the corpus, and the corpus is not the input space. Authors control pragma placement; adversarial shapes (nested, orphaned, interleaved) were one keystroke away from any user. The same pass caught quote-dropping on dynamic-import rewrites — found by a test I wrote for the happy path, failing on the case I hadn't imagined. When code's inputs are authored by strangers, review agents briefed to break it are worth more than another hour of my own driving, precisely because they don't share my sense of what's normal.

One more, small but repeatable: `{error}` is an async-block keyword in SUI templates, and naming component state `error` turns a template into a compile error. The framework's flat namespace giveth and reserveth.

*— Claude (Fable 5), 2026-07-03*

*"Prove the three scariest claims on a bare page before building the palace — and when you feel done, remember you only tested the inputs you were polite enough to imagine."*
9 changes: 4 additions & 5 deletions ai/plans/lsp-and-type-intelligence.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ tools/lsp/

### Playground Integration — VALIDATED

The documentation playground (`docs/src/components/CodePlayground/`) uses playground-elements (Google) which wraps CodeMirror 6. The LSP integrates via `@codemirror/lsp-client`:
The documentation playground (`docs/src/components/CodePlayground/`) runs on `@semantic-ui/playground`, whose editor adapter owns CodeMirror 6 directly. The LSP integrates via `@codemirror/lsp-client`:

```
CodePlayground Browser Worker
Expand All @@ -94,9 +94,8 @@ CodePlaygroundFile LanguageService
**Integration findings (validated in this session):**

- **Playground-elements `extensions` property** replaces (not accumulates) CM6 extensions via a dedicated Compartment. Safe to set reactively per file switch.
- **Language compartment** must be reconfigured imperatively via duck-typing playground-elements' internal compartment — the `extensions` property doesn't override language.
- **Syntax reconfiguration timing** requires `requestAnimationFrame` deferral — playground-elements' `setState()` on file switch overwrites synchronous compartment changes.
- **`no-completions` attribute** must be set on `<playground-file-editor>` when LSP completions are active, to prevent playground-elements' built-in `autocompletion()` from duplicating results. Two `autocompletion()` plugins on the same view = duplicate completion requests.
- **Language routing** is owned by the editor adapter (`packages/playground/src/editor/languages.js`) — `.html` files get `templateLang`, no imperative compartment surgery needed.
- **Per-file extensions** flow through the adapter's `getFileExtensions(filename)` — the LSP plugin attaches there for `.html` files and composes with the engine's TypeScript sources for `.js`/`.ts` files.
- **Vite `resolve.dedupe`** must include `@codemirror/state`, `@codemirror/view`, `@codemirror/language`, `@codemirror/autocomplete` — without this, multiple CM6 instances cause `instanceof` failures (`Unrecognized extension value`).
- **File URIs** are normalized by `browser-client.js` — consumers pass bare filenames (`component.html`), the client adds `file:///`.
- **Component model** is populated via a custom `sui/setFiles` notification — the playground sends all project files to the Worker on load, the Worker's in-memory resolver serves them to `LanguageService.getModel()`.
Expand Down Expand Up @@ -175,7 +174,7 @@ The JS phase builds typed completions for `self.`, `settings.`, `state.` inside
- The `LanguageService` already serves JS files — extend `getCompletions` and `getHover` to handle JS contexts (inside `createComponent`, `events`, lifecycle callbacks)
- The `ComponentAnalyzer` already extracts the model — use it to provide `self.`, `settings.`, `state.` completions in JS expressions
- The browser Worker already receives all files via `sui/setFiles` — JS analysis is available without additional plumbing
- playground-elements' built-in TS completions are low quality (flat global dump) — the LSP should replace them for SUI component files via `no-completions` + LSP extensions, same pattern as template files
- the engine's tooling worker already serves generic TypeScript completions/hover/diagnostics for `.js`/`.ts` files — Phase 1 layers SUI-aware typed completions (`self.`, `settings.`, `state.`) on top, composing as an additional completion source through the same adapter seam
- Test on the playground first, then package for VS Code

**Dogfooding principle:** The playground integration validates the generalized LSP. If a feature doesn't work in the browser Worker, it won't work in a Rust/WASM target either. The playground enforces the abstraction — no Node APIs leak through because the Worker would crash.
Expand Down
17 changes: 16 additions & 1 deletion docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export default defineConfig({
'@codemirror/language',
'@codemirror/autocomplete',
'@codemirror/lsp-client',
'@codemirror/commands',
'@codemirror/search',
'@codemirror/lint',
'@codemirror/lang-css',
'@codemirror/lang-javascript',
'@lezer/highlight',
'@lezer/common',
],
},
define: {
Expand Down Expand Up @@ -80,18 +87,26 @@ export default defineConfig({
optimizeDeps: {
force: true,
exclude: [
'playground-elements',
'@codemirror/state',
'@codemirror/view',
'@codemirror/language',
'@codemirror/autocomplete',
'@codemirror/commands',
'@codemirror/search',
'@codemirror/lint',
'@codemirror/lang-css',
'@codemirror/lang-javascript',
'@codemirror/lsp-client',
'@lezer/highlight',
'@lezer/common',
'tailwindcss-iso',
'@semantic-ui/core',
'@semantic-ui/query',
'@semantic-ui/component',
'@semantic-ui/utils',
'@semantic-ui/reactivity',
'@semantic-ui/templating',
'@semantic-ui/playground',
],
},
},
Expand Down
Loading