@@ -42,8 +42,9 @@ extensions/levelcode-sync/ 'levelcode' auth provider that lights up the bu
4242extensions/levelcode-updater/ notify-only update checker (polls the update feed; never auto-applies)
4343modules/extension-signature/ Open VSX signature verifier the built app loads as @vscode/vsce-sign, + the signing keys it trusts
4444patches/levelcode-core.patch our core source edits, applied on bootstrap
45- scripts/ bootstrap.sh, apply-branding.mjs, run-dev.sh, editor-identity.mjs, extension-signature.mjs, build-macos.sh, make-dmg.sh, make-icon.sh; atom (CLI launcher) + install-level.sh
45+ scripts/ bootstrap.sh, apply-branding.mjs, run-dev.sh, editor-identity.mjs, extension-signature.mjs, build-macos.sh, make-dmg.sh, make-icon.sh, build-web.mjs ; atom (CLI launcher) + install-level.sh
4646tools/ dependency-free reference servers: sync-server (/v1 Settings-Sync), update-server (/api/update feed)
47+ web/ LevelCode in a browser tab: page entry + callback, scratch-workspace extension, layout, themes + chat skin, browser build of levelcode-ai, dev server, tests (docs/WEB.md)
4748vscode/ GITIGNORED upstream Code-OSS checkout (generated)
4849```
4950
@@ -111,6 +112,39 @@ module for that slot. Full account + runbooks: `docs/EXTENSION-SIGNATURES.md`.
111112- Its tests live in ` modules/extension-signature/test/ ` — outside ` extensions/ ` , whose ` test/ ` folders
112113 ship in the app. ` scripts/test-extensions.sh ` discovers ` modules/*/test/*.test.js ` too.
113114
115+ ## LevelCode in a tab (` web/ ` ) — read ` docs/WEB.md ` first
116+
117+ The same ` extensions/levelcode-ai ` source runs in a browser tab (web-worker extension host). Rules that keep
118+ the desktop app exactly as it was:
119+
120+ - ** A workspace read or write goes through ` extensions/levelcode-ai/host.js ` ** , never ` fs ` on a workspace path:
121+ in a tab the workspace is whatever the editor's file-system provider says, and every read is asynchronous.
122+ On the desktop each ` host ` function does what the call site did before, behind ` await ` .
123+ - ** Nothing outside ` host.js ` asks "am I in a browser?"** — a call site asks for a capability (` host.caps.shell ` ,
124+ ` .mcpStdio ` , ` .ripgrep ` ) or calls a function that already knows. A new tool that needs a shell/disk/process is
125+ listed in ` NEEDS_SHELL ` (agent.js) so the browser neither offers it nor promises it.
126+ - The browser build is ` web/ai-extension/ ` (esbuild + shims for ` fs ` /` path ` /` os ` /` crypto ` /` child_process ` ).
127+ Strings that are true on a Mac and false in a tab are rewritten by ` web/ai-extension/copy.js ` , which fails the
128+ build when the desktop text it expects is gone — change both together. ` manifest.js ` drops the commands and
129+ settings a tab cannot honour.
130+ - ` web/main.js ` is a plain ES module with a ** top-level ` await ` ** : a ` const ` declared lower in the file is not
131+ initialised until that await finishes (this cleared a saved session once). Declare constants above the
132+ ` try ` , and use function declarations for helpers it calls.
133+ - ** The look is web-only and lives in ` web/ ` ** (theme package, ` chrome.css ` , the chat skin, the layout commands;
134+ ` docs/WEB.md ` "The look and the layout"). The chat skin is cut into the browser build's ** copy** of
135+ ` media/chat.html ` by ` web/ai-extension/skin.js ` ; never edit the desktop file for it (its suites pin the page).
136+ Every skin rule is under ` body.lc-web ` . An extension's ` configurationDefaults ` outrank the embedder's, so
137+ ` levelcode-themes ` ' pinned default theme is stripped from the staged copy (` withoutConfigurationDefaults ` ).
138+ ` node web/test/e2e-look.mjs --dist dist-web --stub-port <port> ` is the check; look at its screenshots (` --shots ` ).
139+ The embedder's command API is the module's ` commands ` (` api.commands.executeCommand ` ): ` create() ` returns a
140+ disposable, so ` workbench.commands ` is ` undefined ` — a helper that used it ran inside a ` try ` and silently did
141+ nothing until a browser test asked for its effect.
142+ - The session store (` createSecretStorage ` ) belongs to every tab: no cache, one-key read-modify-write under a
143+ Web Lock. The refresh token is rotated on use; do not reintroduce a start-up snapshot.
144+ - Build: ` node scripts/build-web.mjs --account <origin> ` → ` dist-web/ ` ; serve with ` node web/serve.mjs --dist dist-web ` .
145+ Tests: the unit gate (` scripts/test-extensions.sh ` includes ` web/test/unit/*.test.js ` ) and the end-to-end checks in
146+ ` web/test/e2e*.mjs ` (headless Chrome, stand-in backend; Node 22+). What was not run is listed in ` docs/WEB.md ` .
147+
114148## Toolchain (hard requirements — these bit us)
115149
116150- ** Node = ` vscode/.nvmrc ` (currently 24.15.0)** . Older majors fail to compile native modules.
@@ -242,7 +276,7 @@ big-file mode badge. Files: extension.js + fileOps/lineOps/columnOps/encodingEol
242276 is not in the editor until you load it: ` ./scripts/run-dev.sh --extensionDevelopmentPath=<worktree>/extensions/levelcode-ai `
243277 (from the main checkout; the dev extension replaces the built-in one). Uncommitted work is not "on the branch" —
244278 checking the branch out somewhere else gets none of it. Run it in the editor before telling anyone to try it.
245- - Commit ` extensions/ ` , ` modules/ ` , ` patches/ ` , ` branding/ ` , ` scripts/ ` , ` docs/ ` , ` PLAN.md ` , ` CLAUDE.md ` . Never commit ` vscode/ ` .
279+ - Commit ` extensions/ ` , ` modules/ ` , ` patches/ ` , ` branding/ ` , ` scripts/ ` , ` web/ ` , ` docs/ ` , ` PLAN.md ` , ` CLAUDE.md ` . Never commit ` vscode/ ` or ` dist-web /` .
246280- ` extensions/levelcode-ai/diagram/ ` modules listed in ` bundle.FILES ` are pasted INTO a script block in ` chat.html ` .
247281 They must never contain the text of a script tag or an HTML comment opener — not even in a comment — or the block
248282 ends early; ` bundle.js ` refuses to build if one does. Keep them dependency-free and free of ` require('vscode') ` /` fs ` .
0 commit comments