# 3-5 [done] Rust Web 主 Web 执行面迁移实施计划 v1

> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** 让 `mnote-web` / Rust family 成为主 Web 执行面，`3000` 继续作为唯一公开入口，但不再由 Next App Router / React 旧壳承担产品主执行语义。

**Architecture:** 采用“Rust Web gateway + server-first Rust shell + islands + legacy Next compat”分层。`mnote-web` 先接管公开入口、runtime config、auth/session、页面 shell、API transport 与 realtime stream；Next App Router 降为内部 compat/legacy adapter，最终只在显式 legacy/debug 开关下启动。

**Tech Stack:** Rust workspace、`mnote-web`、`axum`、Leptos/WASM islands、Convex substrate、Next App Router legacy compat、Vitest、Playwright smoke、Cargo tests。

---

## 1. 当前基线

树域 `Sidebar / 页面树 / 文件树 / picker` 已完成 Rust family 默认执行面切换，但这不等于主 Web 执行面已经迁移完成。当前仍成立的事实是：

- `3000` 是唯一公开入口。
- `wolai-frontend/src/app` 仍是 Next App Router 主应用入口。
- `mnote-web` 已具备 documents、tree、kernel、stream、bridge、debug shell 等 route，但默认不是公开主站进程。
- `scripts/desktop-hot.js` 默认启动 `pnpm dev` 作为前端 3000，并启动 FastAPI 8000；没有默认启动 Rust Web gateway。
- `3104` 已退役为显式 debug/internal 边界，不能把“恢复 3104 双入口”当作迁移方案。

因此，本计划的完成判定不是“某个 route 可从 Rust 调用”，而是：

> **主站公开入口仍是 3000，但 3000 背后的主执行 owner 从 Next App Router 迁到 `mnote-web`。**

## 2. 边界原则

- `3000` 保持唯一公开入口，不新增长期公开端口。
- `mnote-web` 成为主 gateway、主 SSR shell、主 API transport、主 realtime transport 的 owner。
- Next App Router 只能保留为内部 compat，负责尚未迁完的 legacy 页面或 React island bundle，不再新增长期业务语义。
- Convex 保留为历史迁移源、显式 cloud source / compat / sync replica 边界；主 Web Rust 化后默认 storage / realtime / control-plane 不再依赖 Convex。
- 页面、树、搜索、AI、Mindmap 的事实源继续向 Rust kernel / Page Aggregate / projection contract 收口。
- `BlockNote` 保留为 fallback / 对照链，不作为主执行面迁移的阻塞项。

## 3. 目标文件结构

### Rust Web

- `rust/crates/mnote-web/src/app.rs`
  - 扩展主 gateway 配置、公开入口配置、legacy Next upstream 配置。
- `rust/crates/mnote-web/src/routes/mod.rs`
  - 注册主页面 shell、runtime config、auth/session、API transport、stream route。
- `rust/crates/mnote-web/src/routes/web_shell.rs`
  - 新建主 Web shell route：`/`、`/auth`、`/documents/:id`、必要的 workspace shell。
- `rust/crates/mnote-web/src/routes/session.rs`
  - 新建 Rust-owned session / runtime config / token handoff route。
- `rust/crates/mnote-web/src/routes/gateway.rs`
  - 新建 legacy Next compat proxy，只代理尚未迁移的路径。
- `rust/crates/mnote-web/src/routes/search.rs`
  - 新建 server-first search shell 和 Rust-owned search transport。
- `rust/crates/mnote-web/src/routes/mindmap_shell.rs`
  - 新建独立对象页 shell，先承接轻壳与 island mount。

### Frontend Legacy Compat

- `wolai-frontend/src/lib/rust-web-main-execution-boundary.ts`
  - 新建主执行面边界 manifest，固定 route owner、legacy owner、forbidden Next semantics。
- `wolai-frontend/src/lib/rust-web-main-execution-boundary.test.ts`
  - 新建负向门禁，阻止把 Next App Router 再写成主执行 owner。
- `wolai-frontend/src/app/api/**`
  - 逐步变成 thin proxy / compat adapter；新增业务语义必须失败。
- `wolai-frontend/src/app/(app)/**`
  - 逐步从主入口降级为 legacy compat shell。
- `wolai-frontend/src/components/**`
  - 可继续提供 islands 和重交互组件，但不能再拥有 page/tree/search/AI 的系统事实源。

### Scripts / Smoke

- `scripts/desktop-hot.js`
  - 改为默认启动 Rust Web gateway 作为 3000 owner，Next dev 只在内部 legacy port 启动。
- `scripts/desktop-hot.test.js`
  - 覆盖 Rust gateway、legacy Next upstream、端口释放、跳过 legacy 的组合。
- `scripts/task114-rust-web-gateway-entry-smoke.js`
  - 新建公开入口 smoke，证明 3000 由 Rust gateway 服务。
- `scripts/task115-rust-web-document-shell-smoke.js`
  - 新建文档页 Rust shell smoke。
- `scripts/task116-rust-web-islands-smoke.js`
  - 新建 search / AI / Mindmap islands smoke。
- `scripts/task117-next-retirement-guard.js`
  - 新建最终退役门禁，证明主 smoke 不依赖 Next dev server。

### Design

- `design/03-rust-web/process/3-6-rust-web-main-execution-plane-checklist-v1.md`
  - 作为本计划的执行 checklist 和 harness task 来源。
- `design/03-rust-web/done/*`
  - 只有当 checklist 全部完成并验证后，才移动完成项。

## 4. 非目标

- 不恢复 `3104` 作为公开入口。
- 不在本阶段强制删除 Convex。
- 不要求一次性重写所有 React 组件；重交互可以作为 island/legacy bundle 保留。
- 不把 `BlockNote` 的最终删除作为主 Web 执行面迁移的完成前提。
- 不把“Rust kernel 拥有业务语义”误写成“Rust Web 已拥有主 Web 执行面”。

## 5. 实施任务

### Task W-0：冻结主执行面 owner manifest 与负向门禁

**Files:**

- Create: `wolai-frontend/src/lib/rust-web-main-execution-boundary.ts`
- Create: `wolai-frontend/src/lib/rust-web-main-execution-boundary.test.ts`
- Modify: `design/03-rust-web/process/3-6-rust-web-main-execution-plane-checklist-v1.md`
- Modify: `ARCHITECTURE.md`

- [ ] **Step 1: 写主执行面 manifest**

```ts
export const RUST_WEB_MAIN_EXECUTION_BOUNDARY = {
  schema: "mnote.rust_web.main_execution_boundary.v1",
  publicEntry: "3000",
  mainWebOwner: "mnote-web",
  legacyCompatOwner: "next-app-router",
  rustOwnedPlanes: [
    "web_gateway",
    "runtime_config",
    "auth_session_handoff",
    "document_shell",
    "page_aggregate_transport",
    "tree_projection_transport",
    "tree_command_transport",
    "tree_realtime_stream",
    "search_shell",
    "ai_bridge_transport",
    "mindmap_object_shell",
  ],
  nextAllowedDuties: [
    "legacy_react_bundle",
    "legacy_app_router_compat",
    "island_asset_source_until_migrated",
  ],
  forbiddenNextSemantics: [
    "主 Web gateway owner",
    "页面事实源",
    "树排序 canonical plan",
    "Page Aggregate command family owner",
    "tree realtime event contract owner",
    "搜索事实源",
    "AI tool protocol owner",
  ],
} as const;
```

- [ ] **Step 2: 写负向测试**

```ts
import { describe, expect, it } from "vitest";
import { RUST_WEB_MAIN_EXECUTION_BOUNDARY } from "./rust-web-main-execution-boundary";

describe("RUST_WEB_MAIN_EXECUTION_BOUNDARY", () => {
  it("固定 3000 公开入口由 mnote-web 拥有，Next 只能作为 legacy compat", () => {
    expect(RUST_WEB_MAIN_EXECUTION_BOUNDARY.publicEntry).toBe("3000");
    expect(RUST_WEB_MAIN_EXECUTION_BOUNDARY.mainWebOwner).toBe("mnote-web");
    expect(RUST_WEB_MAIN_EXECUTION_BOUNDARY.legacyCompatOwner).toBe("next-app-router");
    expect(RUST_WEB_MAIN_EXECUTION_BOUNDARY.nextAllowedDuties).not.toContain("main_web_owner");
    expect(RUST_WEB_MAIN_EXECUTION_BOUNDARY.forbiddenNextSemantics).toContain("主 Web gateway owner");
  });
});
```

- [ ] **Step 3: 更新架构文档口径**

把 `ARCHITECTURE.md` 的 Rust Web 状态改成：

> `mnote-web` 已成为主 Web 执行面 owner；Next App Router 降为 legacy compat / island bundle source，`3-5 / 3-6` 收口项已由 task-019..task-026 验证完成。

- [ ] **Step 4: 验证**

Run:

```bash
cd /mnt/Data1T/mnote/wolai-frontend
pnpm vitest run src/lib/rust-web-main-execution-boundary.test.ts src/lib/runtime-config.test.ts
cd /mnt/Data1T/mnote
git diff --check -- ARCHITECTURE.md design/03-rust-web wolai-frontend/src/lib
```

Expected:

- Vitest 通过。
- `git diff --check` 无输出。

### Task W-1：让 `mnote-web` 默认成为 3000 gateway owner

**Files:**

- Modify: `rust/crates/mnote-web/src/app.rs`
- Modify: `rust/crates/mnote-web/src/routes/mod.rs`
- Create: `rust/crates/mnote-web/src/routes/gateway.rs`
- Modify: `scripts/desktop-hot.js`
- Modify: `scripts/desktop-hot.test.js`
- Create: `scripts/task114-rust-web-gateway-entry-smoke.js`

- [ ] **Step 1: 扩展 Rust gateway 配置**

新增配置项：

```rust
pub public_bind_addr: String,
pub legacy_next_base_url: Option<String>,
pub enable_legacy_next_compat: bool,
```

默认值：

- `MNOTE_WEB_PUBLIC_BIND` 默认 `127.0.0.1:3000`
- `MNOTE_WEB_LEGACY_NEXT_BASE_URL` 默认 `http://127.0.0.1:3100`
- `MNOTE_WEB_ENABLE_LEGACY_NEXT_COMPAT` 默认 `true`

- [ ] **Step 2: 新建 legacy gateway route**

`gateway.rs` 只允许代理尚未迁移的 legacy 页面和 asset，不允许承接新业务语义。代理响应必须加：

```text
x-mnote-web-owner: mnote-web
x-mnote-legacy-upstream: next-app-router
```

- [ ] **Step 3: 修改 `desktop-hot` 启动链**

默认启动顺序改为：

1. 释放 `3000 / 3100 / 8000`。
2. 启动 Next dev 到 `127.0.0.1:3100`，只作为 legacy upstream。
3. 启动 `mnote-web` 到 `127.0.0.1:3000`。
4. 启动 FastAPI 8000。

保留环境变量：

- `MNOTE_WEB_SKIP_GATEWAY=1`：临时恢复旧 Next 3000，仅用于紧急回退。
- `NEXT_LEGACY_PORT=3100`：覆盖 legacy upstream 端口。

- [ ] **Step 4: 写 smoke**

`task114` 必须断言：

- `GET http://127.0.0.1:3000/health` 或等价 gateway health 返回 Rust owner header。
- `GET http://127.0.0.1:3000/auth` 可进入。
- 主请求响应头含 `x-mnote-web-owner: mnote-web`。
- 未显式设置 legacy smoke 时不依赖 `3104`。

- [ ] **Step 5: 验证**

Run:

```bash
node --test /mnt/Data1T/mnote/scripts/desktop-hot.test.js
cd /mnt/Data1T/mnote/rust
cargo test -p mnote-web gateway
cd /mnt/Data1T/mnote
node scripts/task114-rust-web-gateway-entry-smoke.js
```

Expected:

- `desktop-hot` 测试证明默认 3000 owner 是 Rust gateway。
- Cargo gateway 测试通过。
- Smoke 证明 3000 主入口不再直接依赖 Next dev owner。

### Task W-2：把 runtime config 与 auth/session handoff 迁到 Rust Web

**Files:**

- Create: `rust/crates/mnote-web/src/routes/session.rs`
- Modify: `rust/crates/mnote-web/src/routes/mod.rs`
- Modify: `wolai-frontend/src/lib/runtime-config.ts`
- Modify: `wolai-frontend/src/lib/runtime-config.test.ts`
- Modify: `wolai-frontend/src/app/api/auth/mnote-web-token/route.ts`

- [ ] **Step 1: Rust Web 输出运行时配置**

新增：

```text
GET /api/runtime/config
GET /api/auth/session
POST /api/auth/session/refresh
```

响应必须只暴露浏览器安全字段，禁止暴露 `CONVEX_SELF_HOSTED_ADMIN_KEY`、内部 `MNOTE_WEB_*_BASE_URL`、legacy upstream secret。

- [ ] **Step 2: 前端 runtime config 改为消费 Rust-owned contract**

浏览器侧继续只读同源 `/api/runtime/config`，不再从 `NEXT_PUBLIC_MNOTE_WEB_BASE_URL` 等 legacy env 兜底恢复 internal-only 边界。

- [ ] **Step 3: 保留 Next auth route 为 compat**

`/api/auth/mnote-web-token` 只做兼容转发或测试入口，文档中标记为 legacy debug，不再作为主 session owner。

- [ ] **Step 4: 验证**

Run:

```bash
cd /mnt/Data1T/mnote/rust
cargo test -p mnote-web session runtime_config
cd /mnt/Data1T/mnote/wolai-frontend
pnpm vitest run src/lib/runtime-config.test.ts src/app/api/auth/mnote-web-token/route.test.ts
```

Expected:

- Rust Web session/config 测试通过。
- 前端 runtime config 负向测试仍证明 internal `mnote-web` URL 不会泄漏回浏览器。

### Task W-3：建立 Rust-owned 文档页 / Page Aggregate server-first shell

**Files:**

- Create: `rust/crates/mnote-web/src/routes/web_shell.rs`
- Modify: `rust/crates/mnote-web/src/routes/documents.rs`
- Modify: `rust/crates/mnote-web/src/routes/mod.rs`
- Modify: `wolai-frontend/src/components/editor/document-shell.tsx`
- Modify: `wolai-frontend/src/components/editor/document-content.tsx`
- Create: `scripts/task115-rust-web-document-shell-smoke.js`

- [ ] **Step 1: Rust Web 输出文档 server-first shell**

新增：

```text
GET /documents/:id
GET /api/page-aggregate/:id
```

`/documents/:id` 首屏必须由 Rust shell 决定 page aggregate snapshot、document read shell、editor island mount 信息。

- [ ] **Step 2: Next 文档页降级为 legacy compat**

`wolai-frontend/src/app/(app)/documents/[id]/page.tsx` 只能继续服务 legacy upstream；新语义必须从 Rust shell 进入。

- [ ] **Step 3: 写文档 shell smoke**

`task115` 必须断言：

- `GET /documents/<id>` 响应头含 `x-mnote-web-owner: mnote-web`。
- 首屏 HTML 包含 page aggregate snapshot 标识。
- 默认主编辑器仍是 `leptos_tiptap_island`。
- 不挂载 `mnote-web-document-shell` iframe。

- [ ] **Step 4: 验证**

Run:

```bash
cd /mnt/Data1T/mnote/rust
cargo test -p mnote-web document_shell page_aggregate
cd /mnt/Data1T/mnote/wolai-frontend
pnpm vitest run src/components/editor/document-content.test.ts src/lib/documents/page-aggregate-builder.test.ts
cd /mnt/Data1T/mnote
node scripts/task115-rust-web-document-shell-smoke.js
```

Expected:

- Rust 文档 shell contract 测试通过。
- 前端文档组件继续作为 island / legacy component 可用。
- Smoke 证明默认文档页入口由 Rust Web shell 服务。

### Task W-4：把主 API transport 从 Next route 收薄为 Rust Web owned

**Files:**

- Modify: `rust/crates/mnote-web/src/routes/documents.rs`
- Modify: `rust/crates/mnote-web/src/routes/tree.rs`
- Create: `rust/crates/mnote-web/src/routes/search.rs`
- Modify: `wolai-frontend/src/lib/tree-route-boundary.ts`
- Modify: `wolai-frontend/src/app/api/documents/route-adapters.test.ts`
- Modify: `wolai-frontend/src/lib/search/request.test.ts`

- [ ] **Step 1: Rust Web 承接 documents / tree / search 主 transport**

Rust Web route owner 至少覆盖：

- `/api/documents/meta`
- `/api/documents/content`
- `/api/documents/save`
- `/api/tree/commands`
- `/api/tree/projections/sidebar`
- `/api/tree/projections/page`
- `/api/tree/projections/file`
- `/api/search/documents`

- [ ] **Step 2: Next route 只保留 thin proxy / compat**

Next route 可以做 cookie/header 透传、同源兼容和 legacy 测试，但不得再新增：

- canonical tree sort
- Page Aggregate payload 组装语义
- search result shape owner
- AI tool protocol owner

- [ ] **Step 3: 更新 route boundary manifest**

`TREE_3000_ROUTE_BOUNDARY_MANIFEST` 继续保留 3000 public entry，但 owner 从 `next-3000` 改为 `rust-web-gateway`，Next duties 改为 `legacy_thin_proxy`。

- [ ] **Step 4: 验证**

Run:

```bash
cd /mnt/Data1T/mnote/rust
cargo test -p mnote-web documents_api tree_commands search
cargo test -p bridge-runtime page_aggregate tree_subtree_move_command
cd /mnt/Data1T/mnote/wolai-frontend
pnpm vitest run src/lib/tree-route-boundary.test.ts src/app/api/documents/route-adapters.test.ts src/lib/search/request.test.ts
```

Expected:

- Rust Web 主 transport 测试通过。
- Next route boundary 测试证明 Next 只保留 thin proxy / compat duties。

### Task W-5：把 tree realtime stream 固定为 Rust Web 主链

**Files:**

- Modify: `rust/crates/mnote-web/src/routes/sse.rs`
- Modify: `rust/crates/mnote-web/src/routes/stream_support.rs`
- Modify: `wolai-frontend/src/app/api/mnote-web/stream/route.ts`
- Modify: `wolai-frontend/src/lib/tree-stream/protocol.ts`
- Modify: `wolai-frontend/src/lib/tree-stream/tree-stream.test.ts`
- Modify: `wolai-frontend/src/lib/tree-stream/use-sidebar-tree-stream.test.tsx`

- [ ] **Step 1: Rust Web 输出正式 snapshot + delta stream**

同源主入口：

```text
GET /api/tree/events?workspaceId=...&rootNodeId=...
```

事件必须覆盖：

- `snapshot`
- `delta`
- `resync`
- `heartbeat`

- [ ] **Step 2: 前端 stream consumer 改为 Rust-owned endpoint**

`/api/mnote-web/stream` 降级为 compat alias；正式 consumer 使用 `/api/tree/events`。

- [ ] **Step 3: 删除 freshness 补偿式主语义**

`PreferredSidebarSnapshotProvider` 可以保留 fallback，但不能把 query/refetch freshness 作为正式实时主链的事实 owner。

- [ ] **Step 4: 验证**

Run:

```bash
cd /mnt/Data1T/mnote/rust
cargo test -p mnote-web tree_realtime stream
cd /mnt/Data1T/mnote/wolai-frontend
pnpm vitest run src/app/api/mnote-web/stream/route.test.ts src/lib/tree-stream/tree-stream.test.ts src/lib/tree-stream/use-sidebar-tree-stream.test.tsx
cd /mnt/Data1T/mnote
node scripts/task112-tree-rust-family-regression-smoke.js
```

Expected:

- Rust Web stream contract 测试通过。
- Sidebar / page tree / file tree consumer 使用正式 Rust-owned stream。
- 旧 `/api/mnote-web/stream` 只作为 compat alias。

### Task W-6：把 Search / AI / Mindmap 页面壳迁到 Rust Web shell + islands

**Files:**

- Create: `rust/crates/mnote-web/src/routes/search.rs`
- Create: `rust/crates/mnote-web/src/routes/mindmap_shell.rs`
- Modify: `rust/crates/mnote-web/src/routes/hermes.rs`
- Modify: `wolai-frontend/src/components/search/SearchPaletteHost.tsx`
- Modify: `wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx`
- Modify: `wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/page.tsx`
- Create: `scripts/task116-rust-web-islands-smoke.js`

- [ ] **Step 1: Search 建立 server-first shell**

`GET /search` 由 Rust Web 输出首屏和初始结果 contract；React search palette 只保留热键打开和交互 island。

- [ ] **Step 2: AI 面板收口为 bridge island**

Rust Web / Hermes route 拥有 session、tool event、client action contract；前端 runtime 只负责展示、输入和 tool result 回传。

- [ ] **Step 3: Mindmap 独立页成为 Rust object shell**

`GET /mindmap/:docId/:mindmapId` 由 Rust Web 输出对象页壳、initial projection 与 island mount 配置；Next page 降为 legacy compat。

- [ ] **Step 4: 验证**

Run:

```bash
cd /mnt/Data1T/mnote/rust
cargo test -p mnote-web search_shell ai_bridge mindmap_shell
cd /mnt/Data1T/mnote/wolai-frontend
pnpm vitest run src/components/editor/DocumentAiAgentPanel.runtime.test.tsx src/lib/ai-agent/runtime/runAgent.test.ts src/lib/search/request.test.ts
cd /mnt/Data1T/mnote
node scripts/task116-rust-web-islands-smoke.js
```

Expected:

- Search / AI / Mindmap 的页面壳 owner 是 Rust Web。
- React runtime 只作为 island 或 legacy compat 存在。

### Task W-7：退役 Next App Router 主入口，完成文档收口

**Files:**

- Modify: `ARCHITECTURE.md`
- Modify: `design/03-rust-web/reference/3-1-rust-web-long-term-checklist-v2.md`
- Modify: `design/03-rust-web/process/3-6-rust-web-main-execution-plane-checklist-v1.md`
- Move when complete: `design/03-rust-web/process/3-5-rust-web-main-execution-plane-cutover-plan-v1.md`
- Move when complete: `design/03-rust-web/process/3-6-rust-web-main-execution-plane-checklist-v1.md`
- Create: `scripts/task117-next-retirement-guard.js`

- [ ] **Step 1: 写最终退役 guard**

`task117` 必须证明：

- `SKIP_NEXT_LEGACY=1` 时，`/auth`、`/documents/:id`、tree realtime、search shell 的主 smoke 仍可通过。
- 未显式 legacy/debug 时不会启动 `pnpm dev` 作为 3000 owner。
- `3104` 不作为公开入口。
- Next App Router 文档中标记为 legacy compat，而不是主入口。

- [ ] **Step 2: 更新 checklist 勾选状态**

当 W-0 到 W-6 全部完成后，把 checklist 中所有完成项勾选，并将仍未迁移的 React islands 明确列为“允许保留的交互 island”，不能算主 Web 执行面 blocker。

- [ ] **Step 3: 移动完成文档到 done**

只有 `task117` 通过后，才能把：

- `3-5-rust-web-main-execution-plane-cutover-plan-v1.md`
- `3-6-rust-web-main-execution-plane-checklist-v1.md`

移动到：

- `design/03-rust-web/done/`

- [ ] **Step 4: 验证**

Run:

```bash
cd /mnt/Data1T/mnote
node scripts/task097-homepage-entry-smoke.js
node scripts/task114-rust-web-gateway-entry-smoke.js
node scripts/task115-rust-web-document-shell-smoke.js
node scripts/task116-rust-web-islands-smoke.js
node scripts/task117-next-retirement-guard.js
git diff --check -- ARCHITECTURE.md design/03-rust-web scripts wolai-frontend rust/crates/mnote-web
```

Expected:

- 主入口 smoke 不依赖 Next 作为 3000 owner。
- 文档已把 Next App Router 从“当前主入口”改为“legacy compat”。
- `design/03-rust-web/process` 不再保留已经完成的主执行面收口项。

## 6. 完成判定

本计划完成时必须同时满足：

- `3000` 仍是唯一公开入口。
- `mnote-web` 是 3000 背后的默认 owner。
- Next App Router 不再作为主 Web 执行面，只保留 legacy compat / island bundle / debug。
- 文档页、tree realtime、search shell、AI bridge、Mindmap object shell 的 owner 已迁到 Rust Web。
- `SKIP_NEXT_LEGACY=1` 的主 smoke 能覆盖核心入口。
- `design/03-rust-web/process` 中本计划和 checklist 已移动到 `done/`。

## 7. 自检

- Spec coverage：覆盖 gateway、runtime config、auth/session、document shell、API transport、tree realtime、Search/AI/Mindmap islands、Next retirement。
- Placeholder scan：本文不使用 `TBD` 或未定义的“后续处理”作为验收条件。
- Type consistency：统一使用 `mnote-web`、`rust-web-gateway`、`next-app-router legacy compat` 三个 owner 名称。
- Scope check：不要求删除 Convex，不要求一次性删除所有 React island，不恢复 3104 双入口。
