diff --git a/.cursor/skills/cyclegui-app-development/SKILL.md b/.cursor/skills/cyclegui-app-development/SKILL.md
new file mode 100644
index 0000000..e576ec3
--- /dev/null
+++ b/.cursor/skills/cyclegui-app-development/SKILL.md
@@ -0,0 +1,99 @@
+---
+name: cyclegui-app-development
+description: 构建或修改基于 CycleGUI 框架的 .NET 桌面/Web 应用。CycleGUI 提供 ImGui 式立即模式 UI 面板和 3D Workspace 渲染能力。用于用户提到 CycleGUI、RefCycleGUI.dll、Costura.Fody、SimpleLite、PanelBuilder、GUI.PromptPanel、GUI.DeclarePanel、Workspace、Painter、LocalTerminal、LocalTerminal.Start、MinimizeToTray、HideConsoleOnStart、libVRender、WebTerminal、TCPTerminal、3D 场景、立即模式 UI、LoadModel、PutPointCloud,或需要新建/修改 CycleGUI 应用、示例、面板、工具栏、HoverMenu、菜单栏、视口、对象选择、坐标拾取、调试绘制时。
+---
+
+# CycleGUI 应用开发
+
+本 skill 是 CycleGUI 应用开发的启动卡片。普通任务应能在没有 CycleGUI 源码的情况下完成:先用本文搭出正确结构;需要完整签名、长示例或专题规则时,再按主题加载 reference。只有维护 CycleGUI 框架本体、修复底层 bug、或本地仓库已存在且需要核对变更时,才读取源码。
+
+## 按需读取
+
+- 项目引用、宿主/插件边界、启动流程:`references/project-setup-and-packaging.md`
+- 面板、工具栏、HoverMenu、控件、菜单栏:`references/panels-controls-menus.md`
+- Workspace 模型、点云、相机、视口、Painter:`references/workspace-scene-and-painter.md`
+- Workspace 对象选择、坐标拾取、async 操作陷阱:`references/workspace-interaction.md`
+- WebTerminal、LocalTerminal、LeastServer:`references/terminals-and-web.md`
+- 完整 API 签名:`references/api-signatures.md`
+- 完整示例:`references/examples.md`
+
+## 引用策略
+
+先判断项目类型:
+
+1. **同解决方案示例**:例如 `LearnCycleGUI`,可以 `ProjectReference` 到 `CycleGUI\CycleGUI.csproj`。
+2. **宿主/调度程序**:例如 `SimpleLite`,引用真实 `CycleGUI.dll`,并用 `Costura.Fody` 把托管程序集包进宿主 Assembly。
+3. **插件或二次开发项目**:默认引用 `RefCycleGUI.dll`,不要引用真实 `CycleGUI.dll`。真实 CycleGUI 实现由宿主提供,用于保护 CycleGUI 代码资产并隔离二开项目。
+
+最容易写错的是插件/二开项目:
+
+```xml
+
+ $(CGUILibDir)RefCycleGUI.dll
+ false
+
+```
+
+不要指导插件二开项目显式部署或打包真实 `CycleGUI.dll`。
+
+## 最小骨架
+
+常用 using:
+
+```csharp
+using CycleGUI;
+using CycleGUI.API;
+using CycleGUI.Terminals;
+using System.Drawing;
+using System.Numerics;
+```
+
+启动本地窗口:
+
+```csharp
+Terminal.RegisterRemotePanel(CreateMainPanel);
+LocalTerminal.SetTitle("MyApp");
+LocalTerminal.Start();
+GUI.PromptPanel(CreateMainPanel(GUI.defaultTerminal));
+```
+
+最小面板:
+
+```csharp
+PanelBuilder.CycleGUIHandler CreateMainPanel(Terminal terminal)
+{
+ return pb =>
+ {
+ pb.Panel.ShowTitle("Main").InitSize(400, 300);
+ pb.Label("Ready");
+ if (pb.Button("Run")) { }
+ if (pb.Closing()) pb.Panel.Exit();
+ };
+}
+```
+
+需要保留 panel 引用、控制 dock/toolbar/单实例时,用 `GUI.DeclarePanel().Define(...)`;细节见 `references/panels-controls-menus.md`。
+
+## 常见任务路由
+
+- 新建普通桌面/Web 应用:用本文骨架;需要完整 csproj 和 WebTerminal 细节时读 `references/project-setup-and-packaging.md`、`references/terminals-and-web.md`。
+- 做插件二开:先确认引用 `RefCycleGUI.dll`;不要把真实 `CycleGUI.dll` 带进插件。
+- 做表单、表格、toolbar、HoverMenu、菜单栏:读 `references/panels-controls-menus.md`。
+- 加载模型、点云、相机、Painter 调试绘制:读 `references/workspace-scene-and-painter.md`。
+- 做对象选择、坐标拾取、拖拽/放置或 async 交互:读 `references/workspace-interaction.md`。
+- 不确定 API 签名:读 `references/api-signatures.md`,不要凭 ImGui 习惯猜 CycleGUI 方法。
+
+## 必须记住
+
+- 普通应用开发不要求用户或下游 agent 读取 CycleGUI 源码。
+- CycleGUI 公开颜色字段使用 `System.Drawing.Color`;不要把 ARGB `uint` 直接塞给颜色字段。
+- 所有 `namePattern` 是 glob,不是 regex:`"UISite-*"` 正确,`"UISite-.*"` 错。
+- `InitPosRelative` 的参数是 `left` / `top`;不要写不存在的 `offsetX` / `offsetY`。
+- CycleGUI 没有 `BeginChild` / `ChildWindow` / `BeginTabBar` / `BeginTabItem`;分区用 `Table(height:)`、`CollapsingHeader`,标签页用 `TabButtons`(支持 `forceSelect` 程序化切 Tab;`Table` 支持 `scrollToRow` 程序化滚动到行,变化检测在 API 内部)。
+- 不要依赖空壳控件:`Progress`、`BulletText`、`Indent` / `UnIndent`、`QuestionMark`、`ToolTip`。
+- 控件 id 由标签经 **ASCII** 哈希得到(中文、全角符号等非 ASCII 字符全部折叠成 `?`):同一面板内两个「ASCII 折叠后相同」的标签会抛 `Duplicated id`——最典型是**同字数的纯中文**标签(如 `筛选条件` 撞 `设为类型`),或仅中文字符不同、ASCII 部分相同的两个标签(如 `起点筛选(站点ID或名称)` 撞 `终点筛选(站点ID或名称)`)。修法:标签加 `###唯一ASCII后缀`(显示不变,`###` 会重置哈希),`Button` 用唯一 `distinct:`,或加 `1. `/`2. ` 等数字前缀;循环内渲染带状态控件须给每项拼唯一 id(如 `$"启用###en-{item.Id}"`)。详见 `references/panels-controls-menus.md`。
+- 立即模式:面板默认**不会**每帧重绘;只在 `pb.Panel.Repaint()` 被调用时重新执行 handler。静态面板(Properties / Actions 等)不要无条件 Repaint;仅实时数据区(Status、MiniPlot、后台线程推送等)才持续 Repaint。延迟回调或跨线程改数据后须显式 Repaint。详见 `references/panels-controls-menus.md`。
+- 画布/Workspace 里的业务对象需要点击或选择时,默认用原生 `SelectObject` + 可选 Workspace 对象,不要用 `GetPosition` 手写命中测试。
+- `SelectObject` 和 `GetPosition` 是互斥交互;进入拾取前结束选择 op,结束后重新启动选择 op。
+- 修改 CycleGUI C# API、维护框架本体、排查 libVRender/协议问题、或发现 reference 缺失时,才核对源码并同步更新 references。
+
diff --git a/.cursor/skills/cyclegui-app-development/agents/openai.yaml b/.cursor/skills/cyclegui-app-development/agents/openai.yaml
new file mode 100644
index 0000000..d6c4565
--- /dev/null
+++ b/.cursor/skills/cyclegui-app-development/agents/openai.yaml
@@ -0,0 +1,7 @@
+interface:
+ display_name: "CycleGUI App Development"
+ short_description: "Build CycleGUI panels, HoverMenus, and 3D workspace apps"
+ default_prompt: "Use $cyclegui-app-development to build or modify a CycleGUI panel, HoverMenu, workspace, viewport, or demo app."
+
+policy:
+ allow_implicit_invocation: true
diff --git a/.cursor/skills/cyclegui-app-development/examples.md b/.cursor/skills/cyclegui-app-development/examples.md
new file mode 100644
index 0000000..14cefd3
--- /dev/null
+++ b/.cursor/skills/cyclegui-app-development/examples.md
@@ -0,0 +1,8 @@
+# CycleGUI Examples
+
+完整示例已整理到 `references/examples.md`。优先按任务主题读取:
+
+- 最小应用、多面板、模态、实时数据、表格:`references/examples.md` 示例 1-5。
+- 模型、点云、Painter、选择、坐标拾取:`references/examples.md` 示例 6-9、13。
+- 工具栏、Local + Web:`references/examples.md` 示例 11-12。
+- Medulla2 插件结构:`references/examples.md` 示例 10、14。
diff --git a/.cursor/skills/cyclegui-app-development/reference.md b/.cursor/skills/cyclegui-app-development/reference.md
new file mode 100644
index 0000000..eaa406c
--- /dev/null
+++ b/.cursor/skills/cyclegui-app-development/reference.md
@@ -0,0 +1,18 @@
+# CycleGUI Reference Index
+
+按需读取主题文件,不要一次加载所有 reference。
+
+## 主题文件
+
+- `references/project-setup-and-packaging.md`:项目类型、`RefCycleGUI.dll`、`CycleGUI.dll`、Costura、启动流程。
+- `references/panels-controls-menus.md`:Panel 生命周期、定位、toolbar、HoverMenu、PanelBuilder、菜单栏。
+- `references/workspace-scene-and-painter.md`:模型、点云、线、相机、外观、Viewport、Painter。
+- `references/workspace-interaction.md`:对象选择、sticky pattern、坐标拾取、WorkspaceUIOperation async 包装。
+- `references/terminals-and-web.md`:LocalTerminal、WebTerminal、TCPTerminal、LeastServer。
+- `references/api-signatures.md`:完整 API 签名和维护者核对路径。
+- `references/examples.md`:完整示例代码。
+
+## 选择规则
+
+普通应用开发优先使用 `SKILL.md`。只有任务需要某个领域的完整签名、长示例或排障细节时,再读取对应主题文件。
+
diff --git a/.cursor/skills/cyclegui-app-development/references/api-signatures.md b/.cursor/skills/cyclegui-app-development/references/api-signatures.md
new file mode 100644
index 0000000..e24d27e
--- /dev/null
+++ b/.cursor/skills/cyclegui-app-development/references/api-signatures.md
@@ -0,0 +1,643 @@
+# CycleGUI API 参考
+
+> **颜色字段统一为 `System.Drawing.Color`**(2026-05 改造):所有公开 API 的 color/colors/_shine/_border_color/team_color/shine_color 字段都是 `Color`,不再有 `uint` 入口。详见 `SKILL.md` `## 颜色契约` 章节。如果你拿到的是引擎 wire-format `uint`(bit0..7=R),用 `Extensions.FromRgba8(uint)` 升回 `Color`;System.Drawing ARGB 布局(`0xAARRGGBB`)则用 `Color.FromArgb(unchecked((int)argb))`。
+
+## PanelBuilder 控件完整签名
+
+维护者核对路径:`D:\MDCS\Source\Core\CycleGUI\CycleGUI\PanelBuilder.Controls.cs`
+
+### 布局
+
+```csharp
+void Label(string text)
+void Separator()
+void SeparatorText(string text)
+void SameLine(int spacing = 0)
+void CollapsingHeaderStart(string label) // 必须与 End 配对;不可嵌套
+void CollapsingHeaderEnd()
+```
+
+> CycleGUI **没有** `BeginChild` / `ChildWindow` / `BeginTabBar` / `BeginTabItem`。容器分区用 `Table(height:)` + `CollapsingHeader`;Tab 切换用 `TabButtons`(见下方"列表与选择")。
+
+### 按钮与切换
+
+```csharp
+// 返回 true 表示被点击
+bool Button(string text, string shortcut = "", string hint = "", string distinct = "", bool disabled = false)
+
+// 弹出菜单按钮
+void PopMenuButton(string buttonTxt, MenuItem[] menu, Action clickBtn = null)
+
+// 按钮组,返回 true 表示有选择,selecting 为选中索引
+bool ButtonGroup(string prompt, string[] buttonText, out int selecting, bool sameLine = false)
+
+// 复选框,返回 true 表示值改变
+bool CheckBox(string desc, ref bool chk)
+
+// 开关,返回 true 表示值改变
+bool Toggle(string desc, ref bool on)
+
+// 单选按钮,返回 true 表示选择改变
+bool RadioButtons(string prompt, string[] items, ref int selected, bool sameLine = false)
+```
+
+### 输入
+
+```csharp
+// 文本输入。ret 为当前文本,doneInput 为 true 表示按下回车
+(string ret, bool doneInput) TextInput(string prompt, string defaultText = "",
+ string hintText = "", bool focusOnAppearing = false,
+ bool hidePrompt = false, bool alwaysReturnString = false)
+```
+
+### 数值控件
+
+```csharp
+bool DragFloat(string prompt, ref float valf, float step,
+ float min = float.MinValue, float max = float.MaxValue, bool disableCache = false)
+
+bool SliderInt(string prompt, ref int val, int min, int max, bool disableCache = false)
+
+bool SliderFloat(string prompt, ref float val, float min, float max, bool disableCache = false)
+
+bool DragVector2(string prompt, ref Vector2 vector, float step = 0.01f,
+ float min = float.MinValue, float max = float.MaxValue)
+
+bool DragMatrix(int m, int n, float[] vals)
+
+bool BezierEditor(string prompt, ref Vector4 controlPoints, ref float startY, ref float endY)
+```
+
+### 颜色
+
+```csharp
+bool ColorEdit(string label, ref Color color, bool alphaEnabled = true)
+```
+
+### 列表与选择
+
+```csharp
+// 返回选中索引,-1 无选择
+int ListBox(string prompt, string[] items, int height = 5,
+ bool persistentSelecting = false, int preselected = -1)
+
+bool DropdownBox(string prompt, string[] items, ref int selected)
+
+// 返回选中标签页索引
+int TabButtons(string prompt, string[] items, int forceSelect = -1)
+```
+
+`forceSelect`:希望激活的标签页索引(0-based);`-1` 不强制。API 内建变化检测:仅当该值相对上次变化时才下发 `ImGuiTabItemFlags_SetSelected`,调用方可每帧传入当前目标 Tab,无需自己做 one-shot 门控。用户手动切换 Tab 后,只要 `forceSelect` 不变就不会再被拉回。
+
+### 表格
+
+```csharp
+unsafe void Table(string strId, string[] header, int rows,
+ Action content, int height = 0,
+ bool enableSearch = false, string title = "",
+ bool freezeFirstCol = false, int scrollToRow = -1,
+ Action? onHeaderSort = null)
+```
+
+`height`:可见数据行数;`<=0` 表示不限制高度、显示全部行。`scrollToRow`:希望滚动到可见的数据行索引(0-based);`-1` 不滚动。API 内建变化检测:仅当该值相对上次变化时才下发 `ImGui::SetScrollHereY`,调用方可每帧传入当前选中行,用户之后可自由滚动列表。传入 `-1` 会复位持久态,便于「取消选中后再选同一行」能重新触发滚动。
+
+Row 对象可用方法:`Label`, `ButtonGroup`, `Checkbox`, `SetColor`, `Image`
+
+### 图表
+
+```csharp
+// 实时折线图,返回可选按钮索引
+int RealtimePlot(string prompt, float val, bool freeze = false, string[] optionalButtons = null)
+
+// 迷你指标
+bool MiniPlot(string name, float value)
+bool MiniPlot(string name, string value)
+bool MiniPlot(string name, TEnum value) where TEnum : Enum
+
+// 静态折线图
+void Plot2D(string prompt, float[] vals, int height = 200)
+
+// ⚠️ 以下为占位/空壳(源码 body 为空,调用无效果,请勿依赖):
+// Progress, BulletText, Indent / UnIndent, QuestionMark, ToolTip
+// - 需要进度展示:用 RealtimePlot 或 Label 渲染百分比
+// - 需要 tooltip:用 Button(hint:) / Table.Row.Label(hint:) 等已实现的入口
+void Progress(float val, float max = 1) // 空壳,无效果
+```
+
+### 图像
+
+```csharp
+void Image(string prompt, string rgba, int height = -1)
+
+// 图像列表,返回选中索引
+int ImageList(string prompt, (string rgba, string top_title, string bottom_title)[] items,
+ bool persistentSelecting = false, int height_px = 100,
+ bool hideSeparator = false, int selecting = -1)
+```
+
+### 聊天框
+
+```csharp
+(bool ret, string sending) ChatBox(string prompt, string[] appending,
+ int lines = 18, bool input = true)
+```
+
+### 文本展示
+
+```csharp
+void SelectableText(string prompt, string content, bool copyButton = true)
+```
+
+### 文件对话框
+
+```csharp
+bool OpenFile(string prompt, string filters, out string dir, string defaultFn = "")
+bool SaveFile(string prompt, string filter, out string dir, string defaultFn = "")
+bool SelectFolder(string prompt, out string dir)
+```
+
+### Web 与链接
+
+```csharp
+void OpenWebview(string name, string url, string hint = "")
+void DisplayFileLink(string localfilename, string displayName)
+```
+
+### 菜单栏
+
+```csharp
+void MenuBar(List