` emits `_let("helpOpen/1", $scope => { _$signalReset($scope, 0); _text(...); $helpOpen__script($scope); })`, while the same body writing `helpOpen = true` leaves `$setup__script($scope)` in `$setup`. Mounted, three `?` presses take the read version's run counter from 1 to 4 and add three `document.addEventListener` calls; the write-only body and a `` rewrite stay at 1 with none.
diff --git a/agent-feedback/items/2026-08-20-compiler-api-docs.md b/agent-feedback/items/2026-08-20-compiler-api-docs.md
index 294828951..3f0f19f74 100644
--- a/agent-feedback/items/2026-08-20-compiler-api-docs.md
+++ b/agent-feedback/items/2026-08-20-compiler-api-docs.md
@@ -10,3 +10,7 @@ site: docs/guide/low-level-apis.md › ## Writing a Migrator
`docs/guide/low-level-apis.md` is 379 bytes: one intro paragraph, then `## Writing a Migrator` and `## Writing a Translator` with nothing under either, and it is the only entry `public/llms.txt` offers for the compiler ("Advanced low-level APIs"). Nothing else on the site names the API those sections need. `grep -rniE 'compileSync|compileFile|@marko/compiler|babel-utils' docs/` matches one newsletter sentence, and the generated `/docs/reference-full.md` bundle contains none of it, so an agent asked to write a codemod, a migrator or a bundler integration reverse-engineers `@marko/compiler`'s `index.d.ts`, which exports `compile`, `compileSync`, `compileFile`, `compileFileSync`, `configure`, `getRuntimeEntryFiles` and a `taglib` namespace. The version relationship is unstated too: `marko@6.3.44` depends on `@marko/compiler@^5.42.2`, so a search for the installed compiler's documentation lands on the Marko 5 site, and no page says that pairing is expected. Fill the two sections against the `migrator` and `translator` hooks the taglib loader reads from `marko.json`, and give the compiler entry points a reference page indexed in `llms.txt`.
Check: `grep -rniE 'compileSync|compileFile|@marko/compiler' docs/ | grep -v newsletter` returns nothing and `wc -c docs/guide/low-level-apis.md` prints 379; expect both sections to have bodies and the compiler entry points and their output modes to be documented somewhere under `docs/`.
+
+The `./register` subpath belongs in the same reference. `@marko/compiler/register` self-installs a `require.extensions[".marko"]` hook on require (`packages/compiler/src/register.cjs` › `register`, typed by `register.d.ts`, pinned by `compiler/test/register.test.js`) that compiles each template with `compileFileSync` and forces `modules: "cjs"`, so `require("./hello.marko").default.render(input)` renders a template from a plain Node process with no bundler, and an ESM entry bridges through `createRequire` because the hook does not serve `import("./hello.marko")`. It is the one bundler-free render path the site could describe: `docs/introduction/installation.md` › ## Manual Setup starts from "your preferred bundler", `docs/introduction/integrations.md` › Bundlers lists Vite, Webpack, Rollup and Lasso, and `docs/reference/template.md`'s Node `http.createServer` examples import `./template.marko` without saying what loads it. Document the hook, its CommonJS output and its `output`, `sourceMaps` and `extensions` options alongside the entry points.
+
+Check: `grep -rn -i 'compiler/register\|require.extensions\|node-require' docs public/llms.txt` exits 1. In a scratch dir with a package.json (the compiler resolves `marko/translator` from the nearest package root above `process.cwd()`, and without one the hook throws `Cannot find module 'marko/translator'`) and node_modules resolving marko 6.3.46 with @marko/compiler 5.42.3, with `hello.marko` = `
Hello ${input.name}
`, `node -e 'require("@marko/compiler/register")({output:"html",sourceMaps:false});require("./hello.marko").default.render({name:"Ada"}).then(h=>console.log(String(h)))'` prints `
Hello Ada
`, while `import "@marko/compiler/register"; await import("./hello.marko")` from an `.mjs` throws `ERR_UNKNOWN_FILE_EXTENSION` and the same file's `createRequire(import.meta.url)("./hello.marko").default.render({ name: "Ada" })` prints the same HTML.
diff --git a/agent-feedback/items/2026-08-28-browser-only-setup.md b/agent-feedback/items/2026-08-28-browser-only-setup.md
new file mode 100644
index 000000000..6fc92cac0
--- /dev/null
+++ b/agent-feedback/items/2026-08-28-browser-only-setup.md
@@ -0,0 +1,12 @@
+---
+type: dx
+impact: med
+effort: low
+site: docs/introduction/installation.md › ## Manual Setup
+---
+
+# Document the browser-only setup (`marko({ linked: false })`, `index.html`, `Template.mount`) under Manual Setup
+
+`docs/introduction/installation.md` › ## Manual Setup walks through Vite plus `marko()` plus an express SSR server, and the browser-only alternative survives as a parenthetical on the "Add a server" step ("this can be disabled with the Marko plugin's `linked` option"). `linked` appears in one other place under `docs/`, the `docs/reference/lazy-loading.md` note that `linked: false` cannot code-split; `docs/introduction/integrations.md` covers bundlers with no browser build; and `docs/reference/template.md` › ## `Template.mount(input, node, position?)` documents the API, warning that it is "primarily intended to be used in exclusively client rendered environments", without tying it to a build setup. Following Manual Setup and dropping the server file without also passing `linked: false` fails the build with `[marko-vite:pre] You must run the "ssr" build before the "browser" build.`, an error the docs do not explain. Add a Manual Setup subsection assembling the three files a client-only app needs, a `vite.config.ts` with `marko({ linked: false })`, an `index.html` holding a mount node and a module script, and an entry module calling `Template.mount`; carry the lazy-loading note that `linked: false` cannot code-split and link the `Template.mount` section. The site already runs this mode itself in the playground (`src/util/workspace.ts`).
+
+Check: `grep -rn '\blinked\b' docs` prints only `docs/introduction/installation.md:88` (the parenthetical) and `docs/reference/lazy-loading.md:180`, and `grep -rni 'client-only\|SPA' docs` prints nothing. In a scratch dir with marko 6.3.46, @marko/vite 6.1.11 and vite 8.2.2, with `vite.config.ts` = `export default defineConfig({ plugins: [marko({ linked: false })] })`, `index.html` = ``, `src/app.marko` = `` and `src/main.ts` = `App.mount({ start: 3 }, document.getElementById("app")!)`, `npx vite build` prints `✓ 7 modules transformed` plus `dist/assets/index-*.js 4.76 kB` and `npx vite preview` serves a page whose button goes from `Clicked 3` to `Clicked 4` with no server file. The same project with plain `marko()` fails `npx vite build` with `You must run the "ssr" build before the "browser" build.`
diff --git a/agent-feedback/items/2026-08-28-catch-scope-render-errors.md b/agent-feedback/items/2026-08-28-catch-scope-render-errors.md
new file mode 100644
index 000000000..175217438
--- /dev/null
+++ b/agent-feedback/items/2026-08-28-catch-scope-render-errors.md
@@ -0,0 +1,12 @@
+---
+type: dx
+impact: med
+effort: low
+site: docs/reference/core-tag.md › ### `@catch`
+---
+
+# Scope `@catch` to errors thrown while rendering the `` content
+
+`docs/reference/core-tag.md` › ### `@catch` says "When a runtime error occurs in the content of the `` or its `@placeholder` attribute tag, the content is replaced", which a reader takes to include the event handlers and effects written in that content. The runtime scopes it to the render path: marko `dom/catch.feat.ts` wraps `runRender` alone, with a comment recording that an error thrown from a `