diff --git a/.vscodeignore b/.vscodeignore
index bfc8888..03f4411 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -16,7 +16,7 @@ tsconfig.json
scripts/**
jetbrains/**
.gitmodules
-RELEASING.md
+RELEASING*.md
DEVELOPMENT.md
DEVELOPMENT.en.md
# 仓库自身的忽略规则对运行时毫无用处,打进 VSIX 只是噪音
@@ -33,7 +33,6 @@ logs/**/*.log
.vscode/tasks.json
.vscode/launch.json
.vscode/ok-lang-hints-*.json
-AGENT.md
AGENTS.md
**/agent.md
**/agents.md
@@ -47,7 +46,7 @@ python/test_*.py
**/*.bak
**/*.ok-script-toolkit.tmp
# 审查/修复计划类的一次性工作目录(verification-<日期> at <时间>/ 等)。
-# 这些是开发过程产物,按 AGENT.md 的打包红线不得进产物。用通配而不是逐个列名 ——
+# 这些是开发过程产物,按 AGENTS.md 的打包红线不得进产物。用通配而不是逐个列名 ——
# 每次审查都会新建一个带时间戳的目录,逐个列名必然漏(2026-09-20 实测漏了 107 KB)。
verification-*/
verification */*
diff --git a/AGENT.md b/AGENT.md
deleted file mode 100644
index 95c956b..0000000
--- a/AGENT.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# 开发规范:资源外置与插件打包 / Development Standards: External Resources & Plugin Packaging
-
-## 中文
-
-### 资源外置
-
-* **i18n 文案必须外置**,禁止在业务代码中硬编码可翻译文本。
-* **任何代码内使用的 HTML 资源必须外置**,禁止将 HTML 模板、HTML 片段直接嵌入 Python/JS/TS 等代码中。
-* 外置资源应放在项目约定的资源目录中,并通过统一的资源加载机制读取。
-* 新增功能时,如果涉及 i18n 或 HTML,必须同步新增对应的外部资源文件,不得为了方便直接写入代码。
-* 修改现有功能时,如发现已有代码内嵌 i18n 或 HTML,应优先一并迁移到外部资源。
-
-### 插件打包
-
-以下属于**仅开发使用的文件**,不得进入插件最终打包产物:
-
-* `AGENTS.md`
-* `AGENT.md`
-* 其他 `agent.md` / `agents.md` 文件
-* 项目开发说明、AI Agent 指令及相关开发辅助文件
-* 测试文件及其他明确标记为开发用途的资源
-
-插件打包配置必须显式忽略上述文件,避免将开发文件随插件发布。
-
-### 检查要求
-
-提交代码前应检查:
-
-1. 是否存在新增的代码内嵌 i18n 文案。
-2. 是否存在新增的代码内嵌 HTML。
-3. 新增的 HTML/i18n 是否已经外置到规定目录。
-4. 插件打包产物中不得包含 `AGENT.md`、`AGENTS.md` 等 Agent 开发文件。
-5. 修改打包忽略规则后,应验证最终插件压缩包/产物中确实不存在这些文件。
-
----
-
-## English
-
-### External Resources
-
-* **i18n strings must be externalized** — hardcoding translatable text in business code is prohibited.
-* **Any HTML resources used in code must be externalized** — embedding HTML templates or HTML fragments directly into Python/JS/TS code is prohibited.
-* Externalized resources should be placed in the project's designated resource directories and loaded through a unified resource loading mechanism.
-* When adding new features that involve i18n or HTML, corresponding external resource files must be added simultaneously — do not embed them directly in code for convenience.
-* When modifying existing features, if inline i18n or HTML is found, it should be migrated to external resources as a priority.
-
-### Plugin Packaging
-
-The following are **development-only files** and must not be included in the final plugin package:
-
-* `AGENTS.md`
-* `AGENT.md`
-* Other `agent.md` / `agents.md` files
-* Project development documentation, AI Agent instructions, and related development auxiliary files
-* Test files and other resources explicitly marked as development-purpose
-
-The plugin packaging configuration must explicitly ignore the above files to prevent development files from being shipped with the plugin.
-
-### Checklist
-
-Before committing code, verify:
-
-1. No new inline i18n strings have been added to code.
-2. No new inline HTML has been added to code.
-3. New HTML/i18n has been externalized to the designated directories.
-4. The plugin package does not contain `AGENT.md`, `AGENTS.md`, or other Agent development files.
-5. After modifying packaging ignore rules, verify the final plugin archive/products do not contain these files.
diff --git a/AGENTS.md b/AGENTS.md
index 7271c6b..79aed98 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,6 +1,66 @@
-# 仓库协作指引
+# 仓库协作指引与开发规范
-- 开发与打包约束见 [AGENT.md](AGENT.md)。
-- 处理主仓或 `jetbrains/` 子仓的 PR review 时,先读
- [.agents/skills/ok-script-pr-review/SKILL.md](.agents/skills/ok-script-pr-review/SKILL.md)。
- 两边是独立 Git 仓库,调用 GitHub API 时须明确仓库。
+## PR review
+
+处理主仓或 `jetbrains/` 子仓的 PR review 时,先读
+[.agents/skills/ok-script-pr-review/SKILL.md](.agents/skills/ok-script-pr-review/SKILL.md)。
+两边是独立 Git 仓库,调用 GitHub API 时须明确仓库。
+
+等待 PR review 时使用技能提供的长时间等待脚本,复用已有终端进程,并让用户能在 Codex 侧边查看输出。不要默认改成隐藏进程,也不要为等待另外创建定时任务、heartbeat 或轮询 automation,除非用户明确要求。
+
+## 仓库定位与功能边界
+
+本仓库是面向 **ok-script 项目开发者的 IDE 插件**,用于开发、调试和资源制作。功能取舍以缩短开发步骤、准确操作当前本地代码、方便定位问题为目标。
+
+**需要承担:**
+
+* 准确识别本地工作区当前的项目、解释器、任务注册、参数声明和资源入口;核对功能时以本地代码为准,历史版本与远程提交仅作参考。
+* 支持任务运行、触发任务启用、暂停、停止和当前参数试验,尽量沿用项目与框架的真实启动方式。
+* 隔离调试配置与项目实际配置,明确覆盖范围;用户主动编辑模板、框、角色等项目资源时,按该操作的既有保存语义写入。
+* 提供真实的保存结果、可确认的运行状态、日志与错误入口。项目路径、执行器、任务标识、配置来源等技术信息应清楚可达。
+* 支持截图、标注、模板与区域制作、代码引用、补全、预览和来源跳转;两端保持操作含义一致,界面紧凑、清晰、易操作。
+* 插件依赖的框架 API、任务元数据、配置定位或资源格式变化,导致当前功能读错、写错或不能运行时,修正插件的检测与调用入口。
+
+**不需要承担:**
+
+* 业务项目的参数迁移、历史值恢复、跨任务配置搬运、账号覆盖迁移或旧业务版本兼容。这些由业务项目负责;项目启动链内已有逻辑可正常执行,插件不另建一套业务迁移机制。
+* 恢复业务项目已经移除、不再需要的参数。参数删除、任务拆分、参数归属调整和内部检测点更换属于正常内容改造;能正确读取当前声明时,不据此安排额外适配。
+* 把旧调试快照中的键当作当前任务仍支持的参数,或凭字段同名、旧任务关系自动推断并搬运历史值。
+* 默认扩展普通业务软件的账号生命周期、迁移恢复向导、完整健康看板等流程;也不为凑齐 UI 状态要求每个业务项目新增应用回执或观测协议。
+
+插件仍负责**自己的**持久化格式、协议和缓存兼容。无法确认运行应用或等待原因时,如实说明并提供日志入口。优先保证当前调试链可靠,再改善开发效率与视觉体验。详细依据见 [开发者插件功能范围](docs/developer-tool-scope.md)。
+
+## 协作说明文档
+
+* 面向大模型的指令、技能和配套说明(包括 `AGENTS.md`、`SKILL.md`)每份文档只维护单文件、单语言版本,本仓库使用中文;不混写中英文正文,也不另建 `.en.md` 等翻译副本。
+* 除 Agent 指令、技能及技能配套说明外,所有文档必须同时维护中文与英文版本,分别放在 `名称.md` 与 `名称.en.md` 中;每个文件只保留对应语言的正文,更新时同步两份内容与相应链接。
+* 文件名、代码、API 名称和必要的原始界面文字保留原文,不视为双语正文。
+
+## 资源外置
+
+* **i18n 文案必须外置**,禁止在业务代码中硬编码可翻译文本。
+* **任何代码内使用的 HTML 资源必须外置**,禁止将 HTML 模板、HTML 片段直接嵌入 Python/JS/TS 等代码中。
+* 外置资源应放在项目约定的资源目录中,并通过统一的资源加载机制读取。
+* 新增功能时,如果涉及 i18n 或 HTML,必须同步新增对应的外部资源文件,不得为了方便直接写入代码。
+* 修改现有功能时,如发现已有代码内嵌 i18n 或 HTML,应优先一并迁移到外部资源。
+
+## 插件打包
+
+以下属于**仅开发使用的文件**,不得进入插件最终打包产物:
+
+* `AGENTS.md`
+* 其他 `agent.md` / `agents.md` 文件
+* 项目开发说明、AI Agent 指令及相关开发辅助文件
+* 测试文件及其他明确标记为开发用途的资源
+
+插件打包配置必须显式忽略上述文件,避免将开发文件随插件发布。
+
+## 检查要求
+
+提交代码前应检查:
+
+1. 是否存在新增的代码内嵌 i18n 文案。
+2. 是否存在新增的代码内嵌 HTML。
+3. 新增的 HTML/i18n 是否已经外置到规定目录。
+4. 插件打包产物中不得包含 `AGENTS.md` 等 Agent 开发文件。
+5. 修改打包忽略规则后,应验证最终插件压缩包/产物中确实不存在这些文件。
diff --git a/DEVELOPMENT.en.md b/DEVELOPMENT.en.md
index 0f796d4..0fb0578 100644
--- a/DEVELOPMENT.en.md
+++ b/DEVELOPMENT.en.md
@@ -1,4 +1,4 @@
-# 开发指南 / Development Guide
+# Development Guide
@@ -6,18 +6,16 @@
-本文档面向扩展开发者,包含项目结构、本地构建安装和发布流程。
-
This document is for extension developers and covers the project structure, local build/installation, and release workflow.
-The shared runtime scripts, protocol, and host boundaries are documented in [Shared core](docs/shared-core.md).
+The shared runtime scripts, protocol, and host boundaries are documented in [Shared core](docs/shared-core.en.md); see [feature parity](docs/feature-parity.en.md) for current capabilities and limits.
---
## Project Structure
```text
-src/ VS Code extension host TypeScript source (33 modules; entry points and major ones listed)
+src/ VS Code extension host TypeScript source (entry points and major modules listed, not a complete inventory)
projectConfig.ts Read side of the project convention file ok-script-toolkit.json (locate + cache + personal preference)
projectConfigPure.ts Pure precedence-chain logic (no vscode dependency, unit-testable): parse + precedence + winning layer
conventionSources.ts Data source for the "Project Convention vs My Settings" tracing panel
@@ -62,7 +60,7 @@ media/ Per-Webview HTML/CSS/JS (loaded by the host via CS
python/ Helper scripts shipped with the extension: task discovery, probing & execution (parse_config_tasks.py, probe_task_schemas.py, run_executor.py), plus game window capture & config probing for the template asset panel (capture_game_window.py, probe_window_config.py)
python/tests/ Development-time Python regression tests (test_probe_*.py ×5 and test_run_executor_*.py ×4,
9 in total, all wired into npm test; plus _test_tmp.py, the shared per-suite temp-dir infrastructure);
- excluded from VSIX / JetBrains JAR per AGENT.md packaging rules
+ excluded from VSIX / JetBrains JAR per AGENTS.md packaging rules
jetbrains/ The JetBrains plugin's **separate public repository** (git submodule), with its own README / CI / release flow
schemas/ JSON Schema for ok-script-toolkit.json (editor completion and validation)
docs/ Design documents (config-reads overview, convention-file design, global UI design system, copy-pasteable example config)
@@ -118,7 +116,7 @@ The `jetbrains/` directory contains a standalone Kotlin + IntelliJ Platform plug
Drag **works here** — the two tool windows share the same JVM and use a custom `DataFlavor` to pass paths;
note that `JPanel` has no built-in auto-drag-out, requiring manual `exportAsDrag` in `mouseDragged`.
- Follow-up parity work from main-repo v1.9.0 → v1.13.0 (Swing-side spec at
- [`jetbrains/docs/design-parity.md`](https://github.com/AliceJump/ok-script-toolkit-jetbrains/blob/main/docs/design-parity.md)):
+ [`jetbrains/docs/design-parity.md`](https://github.com/AliceJump/ok-script-toolkit-jetbrains/blob/main/docs/design-parity.en.md)):
**global config takeover** (probe parses global config groups → parameter snapshots persisted →
full snapshot injected via `OK_TOOLKIT_GCONFIG` at executor launch → live push via `gparams` while running),
the health bar and the idle-state **run center** (current task / execution queue / trigger polling),
@@ -131,7 +129,7 @@ cd jetbrains
./gradlew test buildPlugin verifyPluginStructure verifyPluginConfiguration
```
-Use `gradlew.bat` on Windows. The generated ZIP is at `jetbrains/build/distributions/` and can be installed via **Settings / Plugins / Install Plugin from Disk...** in a JetBrains IDE. For per-feature alignment status and remaining gaps, see [`jetbrains/docs/parity-review.md`](https://github.com/AliceJump/ok-script-toolkit-jetbrains/blob/main/docs/parity-review.md) (re-verified line by line against the code on 2026-09-21, baseline v1.8.0).
+Use `gradlew.bat` on Windows. The generated ZIP is at `jetbrains/build/distributions/` and can be installed via **Settings / Plugins / Install Plugin from Disk...** in a JetBrains IDE. For per-feature alignment status and remaining gaps, see [`jetbrains/docs/parity-review.md`](https://github.com/AliceJump/ok-script-toolkit-jetbrains/blob/main/docs/parity-review.en.md) (historical baseline; see [current feature parity](docs/feature-parity.en.md)).
## Installation
@@ -284,4 +282,4 @@ Add each one in the GitHub repo under **Settings → Secrets and variables → A
When using VS Marketplace OIDC, also add `VSCE_USE_OIDC=true` under **Actions → Variables → New repository variable**; only enable after completing Marketplace Trusted Publishing policy.
-See [RELEASING.md](RELEASING.md) for full token setup, signing key generation, and step-by-step release instructions.
+See [RELEASING.md](RELEASING.en.md) for full token setup, signing key generation, and step-by-step release instructions.
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 18483e3..727f183 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -1,4 +1,4 @@
-# 开发指南 / Development Guide
+# 开发指南
@@ -8,16 +8,14 @@
本文档面向扩展开发者,包含项目结构、本地构建安装和发布流程。
-两端共同维护的运行脚本、协议和宿主边界见 [共用核心](docs/shared-core.md)。
-
-This document is for extension developers and covers the project structure, local build/installation, and release workflow.
+两端共同维护的运行脚本、协议和宿主边界见 [共用核心](docs/shared-core.md),当前功能和限制见 [功能对齐表](docs/feature-parity.md)。
---
## 项目结构
```text
-src/ VS Code 扩展宿主 TypeScript 源码(33 个模块,下列为入口与主要模块)
+src/ VS Code 扩展宿主 TypeScript 源码(下列为入口与主要模块,非完整清单)
projectConfig.ts 项目约定文件 ok-script-toolkit.json 的读盘侧(定位 + 缓存 + 个人偏好)
projectConfigPure.ts 取值链纯逻辑(不依赖 vscode,可单测):解析 + 优先级 + 来源层
conventionSources.ts 「项目约定 vs 我的设置」溯源面板的数据源
@@ -62,7 +60,7 @@ media/ 每个外置 Webview 的 HTML/CSS/JS(宿主经 C
python/ 随扩展发布的辅助脚本:任务发现、探测与执行(parse_config_tasks.py、probe_task_schemas.py、run_executor.py),以及模板素材面板的游戏窗口截图与配置探测(capture_game_window.py、probe_window_config.py)
python/tests/ 开发期 Python 回归测试(test_probe_*.py ×5、test_run_executor_*.py ×4,
共 9 个,npm test 全部接入;另有三端共用的测试临时目录基建 _test_tmp.py);
- 按 AGENT.md 打包规范不进 VSIX / JetBrains JAR
+ 按 AGENTS.md 打包规范不进 VSIX / JetBrains JAR
jetbrains/ JetBrains 插件的**独立公开仓库**(git submodule),有自己的 README / CI / 发版流程
schemas/ ok-script-toolkit.json 的 JSON Schema(编辑器补全与校验)
docs/ 设计文档(配置读取全景、项目约定文件设计、全局 UI 设计规范、可直接复制的示例配置)
@@ -130,7 +128,7 @@ cd jetbrains
./gradlew test buildPlugin verifyPluginStructure verifyPluginConfiguration
```
-Windows 使用 `gradlew.bat`。生成的 ZIP 位于 `jetbrains/build/distributions/`,可在 JetBrains IDE 的 **Settings / Plugins / Install Plugin from Disk...** 中安装。逐功能的对齐状态与剩余差异见 [`jetbrains/docs/parity-review.md`](https://github.com/AliceJump/ok-script-toolkit-jetbrains/blob/main/docs/parity-review.md)(2026-09-21 已按代码逐条重核,基线 v1.8.0)。
+Windows 使用 `gradlew.bat`。生成的 ZIP 位于 `jetbrains/build/distributions/`,可在 JetBrains IDE 的 **Settings / Plugins / Install Plugin from Disk...** 中安装。逐功能的对齐状态与剩余差异见 [`jetbrains/docs/parity-review.md`](https://github.com/AliceJump/ok-script-toolkit-jetbrains/blob/main/docs/parity-review.md)(保留历史基线;当前实现见 [功能对齐表](docs/feature-parity.md))。
## 安装
diff --git a/README.en.md b/README.en.md
index b6d2981..d8536fe 100644
--- a/README.en.md
+++ b/README.en.md
@@ -6,11 +6,8 @@
# ok-script Toolkit
-**把 ok-script 的语言、OCR、模板、技能和任务数据,直接搬进 VS Code 的开发流程。**
-
**Bring ok-script's language keys, OCR fixes, templates, skills and task data straight into your VS Code workflow.**
-语言键补全 · OCR 修正提示 · 模板浏览 · 任务启动 · 角色技能管理
Language key completion · OCR fix hints · Template browsing · Task launching · Character skill management
[](https://marketplace.visualstudio.com/items?itemName=AliceJump.ok-script-toolkit)
@@ -26,8 +23,6 @@ Language key completion · OCR fix hints · Template browsing · Task launching
---
-VS Code 扩展,为 ok-script 项目的 Python 开发提供语言键、OCR 修正、模板和技能效果的数据提示,同时内置模板浏览、任务启动和角色技能管理面板,让 ok-script 的语言、OCR、模板、技能和任务数据直接进入开发流程。
-
A VS Code extension that brings ok-script language keys, OCR fixes, templates, skill effects, and task data directly into your Python development workflow. It also includes built-in template browsing, task launching, and character skill management panels.
> [!TIP]
@@ -51,6 +46,8 @@ For PyCharm / IntelliJ IDEA users, install the JetBrains version: [ok-script Too
## Features
+See [feature and documentation parity](docs/feature-parity.en.md) for current host implementations and remaining differences.
+
| Module | Description |
|---|---|
| [Code development assistance](#code-development-assistance) | Complete and explain `self.lang`, OCR regex, and skill effect IDs in the editor |
@@ -84,7 +81,7 @@ When editing Python code, the extension automatically detects ok-script-specific
- **Template panel**: Open via the sidebar icon or `Ctrl+Alt+T` shortcut (requires focus on a Python editor). Displays all workspace templates in a thumbnail grid with real-time name search and filtering.
-- **Quick insert**: Click a card to insert `fL.
` at the editor cursor, double-click to copy to clipboard, click the thumbnail to open the source image.
+- **Quick insert**: Click a card to insert `fL.` at the editor cursor, double-click to copy to clipboard, or use **View Original** to open the source. VS Code template and box galleries use a shared 500 ms card double-click window; clicks beyond that window are independent single clicks. The insert, copy and source buttons act immediately.
- **Template code hints**: Type `fL.` or `FeatureList.` to complete template names with size info. Hover shows thumbnail preview, dimensions, and source info.
- You can also open a larger grid view in the editor area via the command **ok-script Toolkit: Open Template Panel in Editor**.
- Supports both sidebar (template panel and template asset views) and large editor window browsing modes.
@@ -96,6 +93,10 @@ self.wait_click_feature(feature=fL.give_gift, time_out=10)
Hover over `fL.give_gift` to see the cropped template image; type `fL.` to select from the template name list.
+### Box Resources
+
+Box resource management reuses source annotation images and the COCO editor. Edit boxes, generate enclosing boxes from templates, and explicitly publish normalized position tables. The box gallery provides cropped previews, source navigation, and insertion/copy/completion/Hover for `self.pos` references. Working and runtime files are separate; business projects own game loading. See [Box Resource Design](docs/box-resources.en.md).
+
### Temp Screenshots
@@ -239,10 +240,10 @@ Settings that take part in the precedence chain ↔ the field they map to:
> The **`okScriptToolkit.showConventionSources`** command ("Project Convention vs My Settings")
> lists which layer each effective value comes from and lets you revert to the project convention.
-See [`docs/project-config.md`](docs/project-config.md) for the full field list and design notes,
+See [`docs/project-config.md`](docs/project-config.en.md) for the full field list and design notes,
and [`docs/ok-script-toolkit.example.json`](docs/ok-script-toolkit.example.json) for a copy-paste example.
For **what the plugin actually reads at runtime, what each setting does, and the precedence rules**,
-see [`docs/config-reads.md`](docs/config-reads.md) (six read-path types, per-item purpose, the invariants, and a troubleshooting list).
+see [`docs/config-reads.md`](docs/config-reads.en.md) (six read-path types, per-item purpose, the invariants, and a troubleshooting list).
### Configuration Example
@@ -307,6 +308,6 @@ If you just modified the extension's `package.json` configuration declarations,
**Related**
-[ok-script Toolkit for JetBrains](https://github.com/AliceJump/ok-script-toolkit-jetbrains) · [Development Guide](DEVELOPMENT.en.md) · [Release Process](RELEASING.md)
+[ok-script Toolkit for JetBrains](https://github.com/AliceJump/ok-script-toolkit-jetbrains) · [Development Guide](DEVELOPMENT.en.md) · [Release Process](RELEASING.en.md)
diff --git a/README.md b/README.md
index 78c1bd3..fd7e4ee 100644
--- a/README.md
+++ b/README.md
@@ -8,10 +8,7 @@
**把 ok-script 的语言、OCR、模板、技能和任务数据,直接搬进 VS Code 的开发流程。**
-**Bring ok-script's language keys, OCR fixes, templates, skills and task data straight into your VS Code workflow.**
-
语言键补全 · OCR 修正提示 · 模板浏览 · 任务启动 · 角色技能管理
-Language key completion · OCR fix hints · Template browsing · Task launching · Character skill management
[](https://marketplace.visualstudio.com/items?itemName=AliceJump.ok-script-toolkit)
[](https://plugins.jetbrains.com/plugin/34091-ok-script-toolkit)
@@ -28,8 +25,6 @@ Language key completion · OCR fix hints · Template browsing · Task launching
VS Code 扩展,为 ok-script 项目的 Python 开发提供语言键、OCR 修正、模板和技能效果的数据提示,同时内置模板浏览、任务启动和角色技能管理面板,让 ok-script 的语言、OCR、模板、技能和任务数据直接进入开发流程。
-A VS Code extension that brings ok-script language keys, OCR fixes, templates, skill effects, and task data directly into your Python development workflow. It also includes built-in template browsing, task launching, and character skill management panels.
-
> [!TIP]
> 下面每个功能章节开头的演示图都是可点的——如果动图没加载出来,直接点开链接看。
@@ -51,6 +46,8 @@ PyCharm / IntelliJ IDEA 用户请装 JetBrains 版:[ok-script Toolkit for JetB
## 功能
+当前两端实现及保留差异见 [功能与文档对齐表](docs/feature-parity.md)。
+
| 模块 | 一句话说明 |
|---|---|
| [代码开发辅助](#代码开发辅助) | 在编辑器内补全和解释 `self.lang`、OCR 正则与技能效果 ID |
@@ -84,7 +81,7 @@ PyCharm / IntelliJ IDEA 用户请装 JetBrains 版:[ok-script Toolkit for JetB
- **模板面板**:通过侧边栏图标或 `Ctrl+Alt+T` 快捷键(需聚焦 Python 编辑器时生效)打开,网格展示工作区全部模板的缩略图,支持按名称实时搜索和过滤。
-- **快速插入**:单击卡片将 `fL.<模板名>` 插入编辑器光标处,双击复制到剪贴板,点击缩略图打开来源原图。
+- **快速插入**:单击卡片将 `fL.<模板名>` 插入编辑器光标处,双击复制到剪贴板,使用「查看原图」按钮打开来源。VS Code 模板与框图库统一使用 500 ms 的卡片双击窗口;超过窗口的点击分别按单击处理。插入、复制和查看原图按钮立即执行。
- **模板代码提示**:输入 `fL.` 或 `FeatureList.` 补全模板名称并显示尺寸,悬停显示缩略图预览、尺寸和来源信息。
- 也可通过命令 **ok-script 工具箱: 在编辑器中打开模板面板** 在编辑器区打开更大的网格视图。
- 支持侧边栏(模板面板和模板素材两个视图)和编辑器大窗口两种浏览方式。
@@ -96,6 +93,10 @@ self.wait_click_feature(feature=fL.give_gift, time_out=10)
悬停 `fL.give_gift` 可查看对应模板裁剪图;输入 `fL.` 可从模板名称列表中选择。
+### 框资源
+
+框资源管理复用标注原图与 COCO 编辑器,支持编辑框、从模板生成包围框,并显式发布归一化位置表。框画廊提供裁剪预览、来源定位及 `self.pos` 引用的插入、复制、补全和 Hover。工作文件与运行时文件分开,游戏中的加载由业务项目负责。详见 [框资源设计](docs/box-resources.md)。
+
### 临时截图
diff --git a/RELEASING.en.md b/RELEASING.en.md
new file mode 100644
index 0000000..cc5c1a1
--- /dev/null
+++ b/RELEASING.en.md
@@ -0,0 +1,153 @@
+# Dual-Platform Tag Release
+
+[简体中文](RELEASING.md) | [English](RELEASING.en.md)
+
+Releases are coordinated by the parent repository `AliceJump/ok-script-toolkit`. Regular commits and manual runs do not publish; only the first push of a matching version tag triggers a Release:
+
+```text
+vMAJOR.MINOR.PATCH
+```
+
+## One-time Configuration
+
+All Secrets are added to the parent repo:
+
+**Settings → Secrets and variables → Actions → New repository secret**
+
+### Visual Studio Marketplace
+
+It is recommended to configure **Trusted Publishing/OIDC** for Visual Studio Marketplace, avoiding long-lived Secrets:
+
+1. Go to the Visual Studio Marketplace Publisher/extension management page.
+2. Add a Trusted Publishing policy for `AliceJump.ok-script-toolkit`.
+3. Fill in GitHub repo as `AliceJump/ok-script-toolkit`, workflow as `release.yml`, and environment as required by the Marketplace page (or leave empty).
+4. Add `VSCE_USE_OIDC=true` in the parent repo under **Settings → Secrets and variables → Actions → Variables**.
+5. The tag workflow already has `id-token: write` granted; when `VSCE_PAT` is not configured and this variable is `true`, it will execute `vsce publish --oidc`.
+
+If continuing with PAT for now, add Secret: `VSCE_PAT`
+
+1. Open the Azure DevOps Personal Access Tokens page.
+2. Create a new Token, selecting **All accessible organizations** for Organization.
+3. Select **Custom defined**, expand all permissions, and check only **Marketplace → Manage**.
+4. Copy the Token immediately after creation and save as `VSCE_PAT`.
+5. Ensure the account that created the Token is a member of Visual Studio Marketplace Publisher `AliceJump`.
+
+The repo already has this Secret configured as a fallback before OIDC setup is complete. Microsoft has announced global PATs will retire on 2026-12-01; migration to Trusted Publishing/OIDC should be done as soon as possible.
+
+### JetBrains Marketplace First Listing
+
+The first time requires manual plugin creation:
+
+1. Log in to https://plugins.jetbrains.com/author/me.
+2. Select **Add new plugin**.
+3. Build the ZIP locally: `cd jetbrains && ./gradlew buildPlugin`.
+4. Upload `build/distributions/ok-script-toolkit-jetbrains-.zip`.
+5. Confirm the Plugin XML ID is `com.alicejump.okscripttoolkit`, complete license, source code, issue tracker info, and submit for review.
+
+After the first successful creation, the tag workflow can upload subsequent versions via API.
+
+### JetBrains Release Token
+
+Secret: `JETBRAINS_TOKEN`
+
+1. Open https://plugins.jetbrains.com/author/me/tokens.
+2. Select **Generate Token** and enter a name.
+3. Copy the permanent Token immediately (shown only once).
+4. Save as parent repo Secret `JETBRAINS_TOKEN`.
+
+### JetBrains Signing Keys
+
+Secrets:
+
+- `JETBRAINS_PRIVATE_KEY`
+- `JETBRAINS_PRIVATE_KEY_PASSWORD`
+- `JETBRAINS_CERTIFICATE_CHAIN`
+
+Generate using OpenSSL:
+
+```bash
+openssl genpkey -aes-256-cbc -algorithm RSA \
+ -out private_encrypted.pem -pkeyopt rsa_keygen_bits:4096
+openssl rsa -in private_encrypted.pem -out private.pem
+openssl req -key private.pem -new -x509 -days 365 -out chain.crt
+```
+
+- `JETBRAINS_PRIVATE_KEY`: Full text of `private.pem`.
+- `JETBRAINS_PRIVATE_KEY_PASSWORD`: Password set in the first command and used in the second.
+- `JETBRAINS_CERTIFICATE_CHAIN`: Full text of `chain.crt`.
+
+GitHub Secrets support multi-line text; you can paste PEM/CRT full text directly, or Base64-encode to a single line first. Never commit private keys, certificates, or passwords. Generate new certificates and update corresponding Secrets before expiration.
+
+## Each Release
+
+> **Prefer the one-shot script**: `npm run release -- --minor` (or `sh scripts/release.sh --minor`;
+> Windows can use `scripts/release.ps1`). It performs every step below automatically — syncing the
+> seven version locations, verifying, committing/pushing sub-repo then parent, and finally tagging.
+> Add `--dry-run` to preview first. The script only runs on the `main` branch
+> (required for both the parent repo and the jetbrains submodule) and refuses
+> otherwise — the release commit lands on whatever branch it runs from (hit on v1.12.0).
+> If releasing manually, follow the order below exactly and
+> **do not skip any step**.
+
+On Windows, `scripts/release.ps1` first stashes uncommitted changes separately in the
+parent and JetBrains repositories, including untracked files but excluding ignored files.
+The release uses committed code; automatic version increments use the version in `HEAD`.
+It attempts to restore this run's stashes and the original staging state afterward,
+without touching existing stashes. Conflicting stashes are retained and their commit IDs
+are printed. Uncommitted version changes left by a failed release are stashed separately;
+successful commits or pushes are not rolled back. PowerShell uses `-DryRun` to preview
+without stashing or releasing. The Shell script still requires clean workspaces.
+
+Run `node scripts/test_release.js` to verify the PowerShell release flow. It requires
+`git`, `node`, and `pwsh`, and uses temporary repositories and local remotes only.
+
+For example, releasing `0.6.0`:
+
+```bash
+# 1. Sync all seven version locations: package.json, package-lock.json, jetbrains/gradle.properties
+# and all four README version badges (missing any one causes Release validation failure)
+npm run version:sync -- 0.6.0
+
+# 2. Verify
+npm test
+cd jetbrains
+./gradlew test buildPlugin verifyPluginStructure verifyPluginConfiguration
+cd ..
+
+# 3. Commit sub-repo version changes first
+cd jetbrains
+git add .
+git commit -m "chore(release): prepare v0.6.0"
+git push origin main
+cd ..
+
+# 4. Then commit parent repo version, README badge, and new submodule pointer
+# Note: README.md must be committed together — version:sync modifies its badge,
+# and verify-version.js checks it in the tag pipeline (a missing commit in 2026-09
+# caused v1.6.0 validation failure)
+npm run verify:version
+git add package.json package-lock.json README.md jetbrains
+git commit -m "chore(release): prepare v0.6.0"
+git push origin main
+
+# 5. The only release action: create and push a new tag
+git tag -a v0.6.0 -m "Release v0.6.0"
+git push origin v0.6.0
+```
+
+Tag release proceeds as:
+
+1. Check out the parent repo and pinned JetBrains submodule commit.
+2. Validate all seven version locations (`package.json`, `package-lock.json`, `jetbrains/gradle.properties`, and all four README badges) match the tag exactly.
+3. Test and build VSIX.
+4. Test, validate, build, and sign the JetBrains ZIP using the Secrets.
+5. Create a GitHub Release with both installers attached.
+6. Publish to Visual Studio Marketplace if `VSCE_PAT` is present.
+7. Publish to JetBrains Marketplace if complete JetBrains Token and signing Secrets are present.
+
+## Failure Handling
+
+- Do not move or force-push a tag that has already been pushed.
+- When a tag build fails, fix the code, bump the patch version (e.g., `0.6.0` → `0.6.1`), and push a new tag.
+- Tags and GitHub Releases are not reusable; both Marketplaces also reject duplicate versions.
+- If only Marketplace Secrets are missing, the GitHub Release is still created with both offline installers available.
diff --git a/RELEASING.md b/RELEASING.md
index 32de944..557b520 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -1,8 +1,8 @@
-# 双端标签发布 / Dual-Platform Tag Release
+# 双端标签发布
-发布由父仓库 `AliceJump/ok-script-toolkit` 统一协调。普通提交和手动运行不会发布;只有首次推送匹配版本的标签会运行 Release:
+[简体中文](RELEASING.md) | [English](RELEASING.en.md)
-Releases are coordinated by the parent repo `AliceJump/ok-script-toolkit`. Regular commits and manual runs do not publish; only a first-time push of a matching version tag triggers a Release:
+发布由父仓库 `AliceJump/ok-script-toolkit` 统一协调。普通提交和手动运行不会发布;只有首次推送匹配版本的标签会运行 Release:
```text
vMAJOR.MINOR.PATCH
@@ -10,15 +10,13 @@ vMAJOR.MINOR.PATCH
---
-## 中文
-
-### 一次性配置
+## 一次性配置
所有 Secret 都添加到父仓库:
**Settings → Secrets and variables → Actions → New repository secret**
-#### Visual Studio Marketplace
+### Visual Studio Marketplace
推荐配置 Visual Studio Marketplace 的 **Trusted Publishing/OIDC**,无需保存长期 Secret:
@@ -38,7 +36,7 @@ vMAJOR.MINOR.PATCH
目前仓库已经配置该 Secret,可作为 OIDC 配置完成前的回退。Microsoft 已宣布全局 PAT 将于 2026-12-01 退役,应尽快迁移到 Trusted Publishing/OIDC。
-#### JetBrains Marketplace 首次上架
+### JetBrains Marketplace 首次上架
第一次必须手动创建插件:
@@ -50,7 +48,7 @@ vMAJOR.MINOR.PATCH
第一次创建成功之后,标签工作流才能通过 API 上传后续版本。
-#### JetBrains 发布 Token
+### JetBrains 发布 Token
Secret:`JETBRAINS_TOKEN`
@@ -59,7 +57,7 @@ Secret:`JETBRAINS_TOKEN`
3. 立即复制只显示一次的永久 Token。
4. 保存为父仓库 Secret `JETBRAINS_TOKEN`。
-#### JetBrains 签名密钥
+### JetBrains 签名密钥
Secrets:
@@ -82,7 +80,7 @@ openssl req -key private.pem -new -x509 -days 365 -out chain.crt
GitHub Secret 支持多行文本,可直接粘贴 PEM/CRT 全文;也可先 Base64 编码为单行。不要提交私钥、证书或密码。证书到期前需生成新证书并更新对应 Secrets。
-### 每次发布
+## 每次发布
> **推荐用一键脚本**:`npm run release -- --minor`(或 `sh scripts/release.sh --minor`,
> Windows 可用 `scripts/release.ps1`)。它会自动完成下面全部步骤——同步七处版本、
@@ -144,157 +142,9 @@ git push origin v0.6.0
6. 有 `VSCE_PAT` 时发布 Visual Studio Marketplace。
7. 有完整 JetBrains Token 和签名 Secrets 时发布 JetBrains Marketplace。
-### 失败处理
+## 失败处理
- 不要移动或强制覆盖已经推送的标签。
- 标签构建失败时,修复后提升补丁版本,例如从 `0.6.0` 改为 `0.6.1`,再推送新标签。
- 标签和 GitHub Release 都不可复用;两个 Marketplace 也拒绝重复版本。
- 如果只缺 Marketplace Secret,GitHub Release 仍会创建并提供两个离线安装包。
-
----
-
-## English
-
-### One-time Configuration
-
-All Secrets are added to the parent repo:
-
-**Settings → Secrets and variables → Actions → New repository secret**
-
-#### Visual Studio Marketplace
-
-It is recommended to configure **Trusted Publishing/OIDC** for Visual Studio Marketplace, avoiding long-lived Secrets:
-
-1. Go to the Visual Studio Marketplace Publisher/extension management page.
-2. Add a Trusted Publishing policy for `AliceJump.ok-script-toolkit`.
-3. Fill in GitHub repo as `AliceJump/ok-script-toolkit`, workflow as `release.yml`, and environment as required by the Marketplace page (or leave empty).
-4. Add `VSCE_USE_OIDC=true` in the parent repo under **Settings → Secrets and variables → Actions → Variables**.
-5. The tag workflow already has `id-token: write` granted; when `VSCE_PAT` is not configured and this variable is `true`, it will execute `vsce publish --oidc`.
-
-If continuing with PAT for now, add Secret: `VSCE_PAT`
-
-1. Open the Azure DevOps Personal Access Tokens page.
-2. Create a new Token, selecting **All accessible organizations** for Organization.
-3. Select **Custom defined**, expand all permissions, and check only **Marketplace → Manage**.
-4. Copy the Token immediately after creation and save as `VSCE_PAT`.
-5. Ensure the account that created the Token is a member of Visual Studio Marketplace Publisher `AliceJump`.
-
-The repo already has this Secret configured as a fallback before OIDC setup is complete. Microsoft has announced global PATs will retire on 2026-12-01; migration to Trusted Publishing/OIDC should be done as soon as possible.
-
-#### JetBrains Marketplace First Listing
-
-The first time requires manual plugin creation:
-
-1. Log in to https://plugins.jetbrains.com/author/me.
-2. Select **Add new plugin**.
-3. Build the ZIP locally: `cd jetbrains && ./gradlew buildPlugin`.
-4. Upload `build/distributions/ok-script-toolkit-jetbrains-.zip`.
-5. Confirm the Plugin XML ID is `com.alicejump.okscripttoolkit`, complete license, source code, issue tracker info, and submit for review.
-
-After the first successful creation, the tag workflow can upload subsequent versions via API.
-
-#### JetBrains Release Token
-
-Secret: `JETBRAINS_TOKEN`
-
-1. Open https://plugins.jetbrains.com/author/me/tokens.
-2. Select **Generate Token** and enter a name.
-3. Copy the permanent Token immediately (shown only once).
-4. Save as parent repo Secret `JETBRAINS_TOKEN`.
-
-#### JetBrains Signing Keys
-
-Secrets:
-
-- `JETBRAINS_PRIVATE_KEY`
-- `JETBRAINS_PRIVATE_KEY_PASSWORD`
-- `JETBRAINS_CERTIFICATE_CHAIN`
-
-Generate using OpenSSL:
-
-```bash
-openssl genpkey -aes-256-cbc -algorithm RSA \
- -out private_encrypted.pem -pkeyopt rsa_keygen_bits:4096
-openssl rsa -in private_encrypted.pem -out private.pem
-openssl req -key private.pem -new -x509 -days 365 -out chain.crt
-```
-
-- `JETBRAINS_PRIVATE_KEY`: Full text of `private.pem`.
-- `JETBRAINS_PRIVATE_KEY_PASSWORD`: Password set in the first command and used in the second.
-- `JETBRAINS_CERTIFICATE_CHAIN`: Full text of `chain.crt`.
-
-GitHub Secrets support multi-line text; you can paste PEM/CRT full text directly, or Base64-encode to a single line first. Never commit private keys, certificates, or passwords. Generate new certificates and update corresponding Secrets before expiration.
-
-### Each Release
-
-> **Prefer the one-shot script**: `npm run release -- --minor` (or `sh scripts/release.sh --minor`;
-> Windows can use `scripts/release.ps1`). It performs every step below automatically — syncing the
-> seven version locations, verifying, committing/pushing sub-repo then parent, and finally tagging.
-> Add `--dry-run` to preview first. The script only runs on the `main` branch
-> (required for both the parent repo and the jetbrains submodule) and refuses
-> otherwise — the release commit lands on whatever branch it runs from (hit on v1.12.0).
-> If releasing manually, follow the order below exactly and
-> **do not skip any step**.
-
-On Windows, `scripts/release.ps1` first stashes uncommitted changes separately in the
-parent and JetBrains repositories, including untracked files but excluding ignored files.
-The release uses committed code; automatic version increments use the version in `HEAD`.
-It attempts to restore this run's stashes and the original staging state afterward,
-without touching existing stashes. Conflicting stashes are retained and their commit IDs
-are printed. Uncommitted version changes left by a failed release are stashed separately;
-successful commits or pushes are not rolled back. PowerShell uses `-DryRun` to preview
-without stashing or releasing. The Shell script still requires clean workspaces.
-
-Run `node scripts/test_release.js` to verify the PowerShell release flow. It requires
-`git`, `node`, and `pwsh`, and uses temporary repositories and local remotes only.
-
-For example, releasing `0.6.0`:
-
-```bash
-# 1. Sync all seven version locations: package.json, package-lock.json, jetbrains/gradle.properties
-# and all four README version badges (missing any one causes Release validation failure)
-npm run version:sync -- 0.6.0
-
-# 2. Verify
-npm test
-cd jetbrains
-./gradlew test buildPlugin verifyPluginStructure verifyPluginConfiguration
-cd ..
-
-# 3. Commit sub-repo version changes first
-cd jetbrains
-git add .
-git commit -m "chore(release): prepare v0.6.0"
-git push origin main
-cd ..
-
-# 4. Then commit parent repo version, README badge, and new submodule pointer
-# Note: README.md must be committed together — version:sync modifies its badge,
-# and verify-version.js checks it in the tag pipeline (a missing commit in 2026-09
-# caused v1.6.0 validation failure)
-npm run verify:version
-git add package.json package-lock.json README.md jetbrains
-git commit -m "chore(release): prepare v0.6.0"
-git push origin main
-
-# 5. The only release action: create and push a new tag
-git tag -a v0.6.0 -m "Release v0.6.0"
-git push origin v0.6.0
-```
-
-Tag release proceeds as:
-
-1. Check out the parent repo and pinned JetBrains submodule commit.
-2. Validate all seven version locations (`package.json`, `package-lock.json`, `jetbrains/gradle.properties`, and all four README badges) match the tag exactly.
-3. Test and build VSIX.
-4. Test, validate, build, and sign the JetBrains ZIP using the Secrets.
-5. Create a GitHub Release with both installers attached.
-6. Publish to Visual Studio Marketplace if `VSCE_PAT` is present.
-7. Publish to JetBrains Marketplace if complete JetBrains Token and signing Secrets are present.
-
-### Failure Handling
-
-- Do not move or force-push a tag that has already been pushed.
-- When a tag build fails, fix the code, bump the patch version (e.g., `0.6.0` → `0.6.1`), and push a new tag.
-- Tags and GitHub Releases are not reusable; both Marketplaces also reject duplicate versions.
-- If only Marketplace Secrets are missing, the GitHub Release is still created with both offline installers available.
diff --git a/docs/box-resources.en.md b/docs/box-resources.en.md
new file mode 100644
index 0000000..7f61e2f
--- /dev/null
+++ b/docs/box-resources.en.md
@@ -0,0 +1,198 @@
+# Box Resource Design
+
+[简体中文](box-resources.md) | [English](box-resources.en.md)
+
+Local status, 2026-10-01: both hosts have box editing, publication, runtime galleries, completion, and source preview entry points; see [feature parity](feature-parity.en.md). This document retains data contracts and implementation order. Section 1 describes the pre-change foundation; section 10 is not a current TODO list. Actual project `ScreenPosition` loading is outside this repository's acceptance.
+
+Box management follows template management, with two resources. The annotation working copy is edited by the plugin only. The runtime copy is a published position table read by box management and `self.pos` completion. The game uses it only after the business project's `ScreenPosition` loads it; current ok-framework template matching still reads only `template_matching.coco_feature_json`. Reuse existing images, canvas, and visibility handling.
+
+This document is an implementation reference. The real call in ok-neverness-to-everness (ok-nte) is `self.pos.screen.main_viewport.to_box()`, not `self.pos.main_viewport`; there is no `screen_pos`.
+
+## 1. Existing Capabilities
+
+The toolkit already separates two template paths.
+
+| | Annotation resource | Runtime resource |
+|---|---|---|
+| File | `/coco_annotations.json`; default directory `ok_templates` | `config.py`'s `template_matching.coco_feature_json`; otherwise probe `assets/coco_annotations.json` and `ok_tasks/assets/coco_annotations.json` |
+| Readers/writers | Annotation management (asset panel) | Template gallery, completion, Hover; ok-framework template matching |
+| Transfer | Explicit Export to assets; editing does not automatically write runtime files | |
+
+The annotation editor (`AnnotationDialog` / `media/annotationPanel`) already supports selection, dragging, eight-direction resizing, add/delete, zoom, pan, undo, copy/paste, and image navigation. Memory uses pixel `xywh`; disk uses COCO `bbox`. `NormalizedBox` only serves coordinate copying: it is neither persisted nor ok-script's `Box`.
+
+Previously, the editor had no annotation list or visibility controls. Hiding and deletion were the same operation.
+
+The template gallery reads runtime COCO only. A click inserts `fL.`. Region previews dynamically crop the source image with pixel bbox; cache keys combine image-content hash and bbox. Quick Documentation and Hover share that crop. JetBrains lookup entries show dimensions on the right; VS Code adds the image to documentation when resolving a completion entry.
+
+This repository has no business Point resource or position table.
+
+## 2. ok-nte pos / Box
+
+The handwritten Python position table lives in `src/scene/`.
+
+- `self.pos` is a `PositionMap`, created in `BaseNTETask`.
+- `self.pos.screen` contains rectangles: currently `center`, `dialog_icon`, and `main_viewport`, using four screen-relative `(left, top, right, bottom)` values.
+- `self.pos.panels.*` contains two-value click points, unpacked with `*self.pos.panels.esc.mail`. Calling `to_box()` on a point raises an error.
+- `ScreenRatio.to_box()` calls `box_of_screen(..., hcenter=True)` to create a pixel `ok.Box` for the current captured frame. `hcenter` applies at call time and must not enter resources.
+- A descriptor sets `Box.name` to `ScreenPosition.` for debugging only. Search regions are not matched by that name.
+- Approximately 73 task-private `box_of_screen(...)` calls explicitly remain outside the position table; box resources do not absorb them.
+- Runtime does not depend on the IDE plugin.
+
+## 3. Two Box Resources
+
+| | Templates | Boxes |
+|---|---|---|
+| Annotation resource | `/coco_annotations.json` | `/boxes.json` |
+| Runtime resource | `templates.cocoAnnotations` → `config.py` → discovery | `boxes.runtime` → `config.py`'s `boxes_json` → probe `src/scene/boxes.json` |
+| Editing entry | Annotation management | Box resource management |
+| Browsing / completion | Template management | Box management |
+| Annotation-to-runtime transfer | Explicit export | Explicit publish |
+
+The game loader does not read `ok-script-toolkit.json`. Plugin indexing gives conventions precedence over `config.py`, as with templates. If ok-nte declares neither, both use `src/scene/boxes.json`.
+
+The `panels` prefix is reserved for existing click points and cannot be occupied by box paths.
+
+## 4. Data Model
+
+Templates and boxes have separate source annotations, both using exactly the same COCO format. Box names use `categories.name`; image links, dimensions, and pixel rectangles use standard fields:
+
+```json
+{
+ "images": [
+ { "id": 1, "file_name": "12.png", "width": 1920, "height": 1080 }
+ ],
+ "annotations": [
+ { "id": 1, "image_id": 1, "category_id": 1, "bbox": [184, 112, 1544, 853], "area": 1317032, "iscrowd": 0 }
+ ],
+ "categories": [
+ { "id": 1, "name": "screen.main_viewport", "supercategory": "" }
+ ]
+}
+```
+
+Source files no longer have a separate version/boxes model. VS Code templates and boxes share CocoAnnotationData and AnnotationController; JetBrains shares CocoAnnotationData and AnnotationDialog. Image registration, rectangle validation, swapping, atomic saves, and refresh notifications are shared too. Only source paths, name validation, and export differ. Both hosts can edit the same COCO source interchangeably.
+
+Legacy version 1/version 2 box sources are compatibility inputs only. Reads do not alter disk. Before the first edited save, back up the original as `boxes.json.pre-coco..bak`, then write COCO. Missing image dimensions needed for conversion or corrupt sources stop saving and preserve all original data.
+
+Runtime resources contain normalized geometry only (unchanged version 1). `to_box()` needs no image:
+
+```json
+{
+ "version": 1,
+ "boxes": [
+ {
+ "path": "screen.main_viewport",
+ "rect": [0.095833, 0.103704, 0.900000, 0.893519]
+ }
+ ]
+}
+```
+
+Rules:
+
+- `path` is the attribute path following `self.pos.`: at least two segments, each a Python identifier. `screen.main_viewport` corresponds to `self.pos.screen.main_viewport`. One rule source (`boxResourcePure.boxPathError`) supplies the grammar sent through `config` for webview validation.
+- `bbox` is a pixel `[x, y, w, h]`, identical in shape to template COCO: integers, width/height ≥ 1, wholly within source `width × height`. Editing, saving, and validation remain in pixels, never normalized coordinates.
+- `images` registers dimensions for every referenced source image. Box saves register/refresh them from image headers; publish and previews read this table.
+- Serialization shares template COCO serialization for sources. Runtime entries sort by path and retain six decimal places in rectangles.
+- `image` is a filename in the template directory, aligned through existing filename normalization. Do not duplicate images or write cropped PNGs into the repository.
+- Reference images must be full-screen screenshots. Packed crops in `assets/images` cannot be box source images.
+- `to_box()` derives its debug name from path: leaves under `screen` become `ScreenPosition.`. This is not a primary key.
+
+Publishing projects box-source COCO into normalized runtime data. Empty or missing sources report no publishable boxes and do not overwrite existing runtime resources. This is the only normalization point in the normal workflow:
+
+```text
+left = x / width
+top = y / height
+right = (x + w) / width
+bottom = (y + h) / height
+```
+
+Publishing writes a complete snapshot: deleted annotations disappear from runtime after publication. Confirm first if existing runtime paths will be removed. Boxes with unreadable dimensions are not published and are reported explicitly. Editor saves write annotation resources only.
+
+## 5. Images and Editor
+
+Boxes reference the same source images used by annotation management. Box resource management does not import images, capture screenshots into the library, or package exports.
+
+Share canvas, controller, and COCO storage. Template labels validate template names; box labels validate Python attribute paths. Both use `categories.name` and `annotations.bbox`. A missing source is an empty annotation set; the first save registers images/dimensions and creates it.
+
+Generating boxes from templates takes the minimum enclosing pixel rectangle of selected annotations and writes a normal COCO annotation to the box source. A successful save immediately refreshes the resource list, open box editors, and occupied-path table. Internal saves and external changes use the same refresh channel; repeated file events do not reset an editor's undo history.
+
+Image swapping changes ownership only for equal dimensions. Different dimensions use proportional mapping with template `annotationSwapPure`, clamped to target bounds; the confirmation explains scaling.
+
+## 6. Visibility
+
+Visibility is editor-session state: entry identifiers in a hidden set. It enters neither COCO, either box file, nor the undo stack.
+
+The annotation list always shows all entries. Canvas rendering and hit testing use visible entries only.
+
+| Action | Behavior |
+|---|---|
+| Show all | Clear the hidden set |
+| Hide all | Hide every entry on the current image |
+| Show current only | Keep only the selected entry visible |
+| Checkbox | Update individual hidden entries |
+
+Each image has its own hidden set for the current editing session, discarded when the dialog closes. New images default to fully visible. Templates, boxes, and points share this filter.
+
+## 7. Preview, Completion, Generation
+
+Box management follows template management: each box path has a **bbox-cropped resource thumbnail**. Annotation management and box resource management use source thumbnails; template management and box management use cropped thumbnails. Reuse template cropping, content-hash caches, asynchronous batch generation, and failure handling. Completion indexes runtime resources only. Insertion is `self.pos.screen.main_viewport.to_box()`; provide a separate copy-attribute-path action.
+
+Previews do not enter runtime files. Look up annotation sources by path for `image` and pixel bbox, crop the original, and reuse the template cache keyed by content hash and bbox. Box edits naturally invalidate it. If no source matches, including runtime-only paths, documentation shows the path only.
+
+Documentation follows templates: crop, expression, path, normalized rect, relative source-image path. JetBrains may add a short coordinate inlay; VS Code does not, consistent with no template ghost hints.
+
+A single template generates a pixel union of selected annotations. Suggest `screen.` by default; any existing use on any image requires another name. Enclosing boxes from multiple templates require the same source image:
+
+```text
+left = min(x)
+top = min(y)
+right = max(x + w)
+bottom = max(y + h)
+
+bbox = [left, top, right - left, bottom - top]
+```
+
+The result is a normal annotation box and reaches runtime only after publication.
+
+## 8. Runtime Loading
+
+Loading belongs in the business project's `ScreenPosition`, not the plugin; do not change `ok.Box`.
+
+`ScreenRatio` implements only `__get__`. An instance attribute of the same name shadows the class descriptor. Use JSON for names present there; other names still use handwritten class attributes. `to_box()` continues calling `box_of_screen(..., hcenter=True)`.
+
+The three existing rectangles can be imported into annotation resources once and bound to full-screen originals. Handwritten attributes remain valid before publication; plugin box management and completion read runtime JSON only.
+
+## 9. Modules
+
+| Location | Responsibility |
+|---|---|
+| `src/cocoAnnotationData.ts` / `src/annotationPanel.ts` | Shared VS Code COCO source data and annotation controller |
+| `core/CocoAnnotationData.kt` / `ui/AnnotationDialog.kt` | Shared JetBrains COCO source data and annotation dialog |
+| `src/annotationGeometry.ts` | Pixel rectangle validation shared by templates and boxes |
+| `core/AnnotationGeometry.kt` / `core/CocoSource.kt` | Shared JetBrains pixel validation, source parsing, atomic writes, refresh notifications |
+| `src/boxResourcePure.ts` / `src/boxResourceStore.ts` | Box name validation, legacy source import, runtime export |
+| `core/BoxResource.kt` / `core/BoxAnnotationStore.kt` | JetBrains box naming, legacy import, runtime export adapters |
+| `core/BoxRuntimePath.kt` and pure-module path functions | Runtime path precedence, following `CocoFeaturePath` |
+| `boxes.runtime` in `schemas/ok-script-toolkit.schema.json` | Convention file; no personal preference layer |
+| `boxes_json` in `python/probe_window_config.py` | Read runtime path from top-level `config.py` |
+| Both annotation editors | Annotation list and visibility |
+| Later: resource management, box management, completion, template generation | Continue in section 10 order, reusing these contracts |
+
+## 10. Implementation Order
+
+1. Data contract, path resolution, editor visibility.
+2. Box resource management: browse by source image and edit with the existing editor.
+3. Publish runtime files.
+4. Box management cards and documentation previews.
+5. `self.pos` completion and Hover.
+6. Generate boxes from one template or enclose multiple templates on the same image.
+7. ok-nte `ScreenPosition` loader. Manually remove the three corresponding class attributes after confirming rectangles.
+
+## 11. Risks
+
+- Editor changes must preserve template annotation saves. All entries default visible; visibility is outside undo.
+- Older plugins cannot read COCO box sources; update both hosts together. Keep legacy-source backups in the annotation directory and runtime format unchanged.
+- Annotating a crop produces coordinates relative to that crop, not the screen.
+- JSON takes precedence over class attributes of the same name. After import/publication, remove corresponding handwritten attributes in the business project to avoid conflicting maintenance.
+- The plugin must not include `hcenter` in `rect`.
diff --git a/docs/box-resources.md b/docs/box-resources.md
index 77866be..06ba277 100644
--- a/docs/box-resources.md
+++ b/docs/box-resources.md
@@ -1,5 +1,9 @@
# 框资源设计
+[简体中文](box-resources.md) | [English](box-resources.en.md)
+
+2026-10-01 本地状态:两端已有框资源编辑、发布、运行时画廊、补全和来源预览入口,见 [功能对齐表](feature-parity.md)。本文保留数据契约及实现顺序;第 1 节描述的是改造前基础,第 10 节不是当前未完成清单。业务项目 `ScreenPosition` 的实际加载不属于本仓代码验收。
+
框管理对标现有模板管理,分成两份资源。标注工作副本只给插件编辑。运行时副本是发布后的位置表:插件的框管理和 `self.pos` 补全读它。游戏进程要等业务项目的 `ScreenPosition` 加载这份文件之后才会用到它;ok 框架现在的模板匹配仍然只读 `template_matching.coco_feature_json`。图片、画布和显隐不另起一套。
本文是实现依据。ok-neverness-to-everness(下称 ok-nte)里的真实调用是 `self.pos.screen.main_viewport.to_box()`,不是 `self.pos.main_viewport`,也没有 `screen_pos`。
diff --git a/docs/config-reads.en.md b/docs/config-reads.en.md
new file mode 100644
index 0000000..6af0992
--- /dev/null
+++ b/docs/config-reads.en.md
@@ -0,0 +1,329 @@
+# Runtime Configuration Read Paths
+
+[简体中文](config-reads.md) | [English](config-reads.en.md)
+
+> **Summary:** configuration is classified by actual read entry points; not every field uses all four layers. This document explains each setting's purpose, resolution rules, and where changes take effect.
+>
+> Related documents:
+>
+> - [Project convention design](project-config.en.md): `ok-script-toolkit.json` design and fields.
+> - [`docs/ok-script-toolkit.example.json`](ok-script-toolkit.example.json): copyable example.
+> - [`schemas/ok-script-toolkit.schema.json`](../schemas/ok-script-toolkit.schema.json): editor completion/validation.
+> - Source entry points: parent `src/projectConfig.ts` / `src/projectConfigPure.ts`, child `core/ProjectConvention.kt` / `settings/OkScriptToolkitSettings.kt`.
+
+---
+
+## 0. Six Types by Actual Layer Combination
+
+⚠️ Four layers are a pool of possible sources, not a mandatory path. Classify by actual combinations so each type has a clear boundary.
+
+| Type | Actual layers | Settings | Count | Meaning | Entry point |
+|---|---|---|---|---|---|
+| **A** | **① ② ④** | Enum 3 + template directory 1 + i18n 4 + characters 5 + effects 1 | **14** | Team conventions plus personal overrides; no `config.py` in ordinary accessors | `projectConfig.ts` `xxxSetting()`; child `OkScriptToolkitSettings.xxx()` |
+| **B** | **② ③ ④** | `templates.cocoAnnotations`, `boxes.runtime` | **2** | Project convention or `config.py`; no personal preferences | `cocoFeaturePath.ts` / `boxResourcePure.ts`; child `core/CocoFeaturePath.kt` / `core/BoxRuntimePath.kt` |
+| **C** | **③** | `windows.{exe, title, hwnd_class, args}` | **4**, plus 2 unused fields (§9) | `config.py` only; interactive title-regex fallback | `python/probe_window_config.py` |
+| **D** | **① ④** | `displayLocale` / `enableInlayHints` / `annotationKeybindings` / `enableTemplateGallery` / `okScriptProjectPath` / `okScriptPython` / `captureMethod` | **7**, 6 per host | Personal/machine preferences; no project files | `getConfiguration().get()`; child `SettingsState` |
+| **E** | Independent discovery (`okScriptProjectPath` → detection) | Project root resolution | **2 paths** | Where to find the project | Parent `resolveProjectDir()`; child `core/ProjectDirResolution.kt` |
+| **F** | **② ④** | `executor.startupHooks.{before,after}ConfigImport` | **2** | Convention + built-in fallback; no IDE setting; executor only | `python/run_executor.py` |
+
+The order reflects proximity to the project: conventions + personal values → project only → `config.py` only → personal only → finding the project → executor only.
+
+> **Enum export has an additional project-fact fallback.** Ordinary `labelEnumPath` accessors read personal settings, conventions, and empty fallback. Export entry points probe `template_tab.label_enum_relative_path` when the first two supply no path. Both hosts implement this (§9.4). In this document, ① means personal settings, ② conventions, ③ project facts, ④ built-ins; numbering differs from the diagram in `project-config.en.md`.
+
+---
+
+### 2.1 Enum `labelEnum` (3 Settings)
+
+| IDE key | Convention field | Purpose | Fallback | Normalization |
+|---|---|---|---|---|
+| `featureAliases` | `labelEnum.aliases` | How code references the enum; recognize `fL.account_switch` etc. for completion, hover, inlay hints | `["fL","FeatureList","Labels"]` | List; empty means undeclared |
+| `labelEnumPath` | `labelEnum.path` | Where Save to assets writes the enum; empty skips generation | `''` | Relative path + **`.py` suffix** |
+| `labelEnumName` | `labelEnum.name` | Generated class name; imports such as `from src.data.feature_list import FeatureList` make it a **code contract** | File basename | Plain text |
+
+**Notes:**
+
+- `config.py` never declares aliases. Without them, imports such as `FeatureList as PL` defeat guessing from `fL`/`FeatureList`.
+- Project paths are module paths (`src/data/FeatureList`, without `.py`, like `label_enum_relative_path`); IDE input expects file paths. Both layers share normalization: preserve existing `.py`, otherwise add it. Do not assemble paths at consumers.
+- Wrong personal path/name overrides can cause project-wide `ImportError`. Both hosts validate before overwriting: no prompt for absent files or unchanged names; otherwise scan old-name imports and report affected files for confirmation (`src/labelEnumGuard.ts` / `core/LabelEnumGuard.kt`).
+- Change path writes settings relative to the project root, preserving remembered values in both hosts. **Empty clears the override and restores conventions.**
+
+### 2.2 Template Assets `templates.directory` (1 Setting)
+
+| IDE key | Convention field | Purpose | Fallback | Normalization |
+|---|---|---|---|---|
+| `okTemplatesDirectory` | `templates.directory` | Asset panel working directory relative to root, containing PNGs and its own `coco_annotations.json`; also controls thumbnail-cache source classification and watcher globs | `ok_templates` | Relative path |
+
+There are **9 call sites**:
+
+| Location | Use |
+|---|---|
+| `extension.ts` ×5 | Watcher globs, change ownership (`rel.startsWith(...)`), inject directory into `pngCrop` |
+| `featureData.ts` | Index PNGs and `coco_annotations.json` in the directory |
+| `templateAssetData.ts` | Panel data root |
+| `templateAssetPanel.ts` ×2 | Save to assets output directory and import-dialog title |
+
+`pngCrop.ts` does **not** read configuration itself; tests require it in pure Node with an empty `vscode` stub. Hosts inject the name through `setTemplatesDirName()`, like `setCropLogger`.
+
+⚠️ Normalize and escape directory segments before putting them in globs; names may contain `[` or `*`. Otherwise watchers silently miss changes despite a normal-looking UI.
+
+### 2.3 i18n (4 Settings)
+
+| IDE key | Convention field | Purpose | Fallback | Normalization |
+|---|---|---|---|---|
+| `langDirectory` | `i18n.langDirectory` | Language JSON (e.g. character names), for hover/completion/inlay values | `assets/lang` | Relative path |
+| `poDirectory` | `i18n.poDirectory` | gettext `/LC_MESSAGES/*.po`, merged with language JSON; launcher also localizes schemas from it | `i18n` | Relative path |
+| `enablePoData` | `i18n.enabled` | Whether `.po` is a data source; disabled uses JSON only | `true` | Strict boolean |
+| `poDomains` | `i18n.poDomains` | Domain whitelist, excluding UI/general task domains such as `ok.po` by default | `["ocr"]` | List |
+
+**Notes:**
+
+- Different names `enablePoData` / `i18n.enabled` are intentional: personal data-source preference versus project layout.
+- Guard boolean types: `"enabled": "false"` is a truthy string without validation and prevents disabling.
+- Language JSON, PO, and effect-file watcher paths all require segment escaping.
+
+### 2.4 Characters and Skills `characters` (5 Settings)
+
+| IDE key | Convention field | Purpose | Fallback | Normalization |
+|---|---|---|---|---|
+| `characterProjectPath` | `characters.projectPath` | Character/skill data root; may be another repository | `''` (current project) | **Plain text; absolute paths must not be normalized** |
+| `characterMasterFile` | `characters.masterFile` | Master JSON, including IDs and English slugs | `assets/data/characters.json` | Relative to character root |
+| `characterSkillsDirectory` | `characters.skillsDirectory` | Skill JSON directory | `assets/data/character_skills` | Relative path |
+| `characterLocaleFile` | `characters.localeFile` | Localized character names | `assets/lang/characters.json` | Relative path |
+| `characterAvatarTemplateRegex` | `characters.avatarTemplateRegex` | Extract character identifiers from templates such as `battle_icon_1011` | `^battle[_-]?icon[_-]?` | **Plain regex text; never path-normalize** |
+
+**Notes:**
+
+- An empty character project path legitimately means the current project. Plain-text resolution preserves absolute POSIX leading slashes.
+- Never normalize the regex: `normalizeRelPath` replaces `\d` with `/d` and removes trailing `/`, yielding valid syntax that never matches.
+- Invalid handwritten regexes fall back to built-ins (`new RegExp` in try/catch), not a broken whole panel.
+- All five fields read the **current workspace** convention file (`loadProjectConfig()` without a root). `characters.projectPath` selects data location, not config source. See open questions in [project convention design](project-config.en.md).
+
+### 2.5 Effects `effects` (1 Setting)
+
+| IDE key | Convention field | Purpose | Fallback | Normalization |
+|---|---|---|---|---|
+| `effectsFile` | `effects.file` | `EffectType` + `EFFECT_DESCRIPTIONS`; hover/completion/inlays for `EffectType.XXX` or `"effect_id": "XXX"` | `src/data/effects.py` | Relative path |
+
+Parsed data maps effect ID → description/category, both from that file. Adding effects needs only project-file changes, not plugin changes.
+
+### 2.6 Executor-Only `executor.startupHooks`
+
+| Convention field | Purpose | Reader |
+|---|---|---|
+| `executor.startupHooks.beforeConfigImport` | Sequential `module:function` calls **before** `import config` | Shared `python/run_executor.py` only |
+| `executor.startupHooks.afterConfigImport` | Calls **after** config import; absent declarations use `src.patches.startup_patches:install_startup_patches` | Same |
+
+Neither host directly reading this is intentional, not a parity gap. Hook names have no universal convention, so declare them explicitly (e.g. ok-end-field's pre-import `pre_config_patch` / `qfluent_mute_promo_patch`). Optional hook failures are logged without preventing executor startup.
+
+---
+
+## 3. Type B · ② ③ ④: Project-Owned (2 Settings)
+
+| Convention field | Purpose | Resolution |
+|---|---|---|
+| `templates.cocoAnnotations` | Framework **runtime template library** for hints/indexing | Convention → `template_matching.coco_feature_json` → `assets/coco_annotations.json`, then `ok_tasks/assets/coco_annotations.json` |
+| `boxes.runtime` | **Runtime box table** for galleries/completion/Hover; game loading belongs to the business project | Convention → top-level `boxes_json` → `src/scene/boxes.json` |
+
+No personal preference layer or provenance-panel entry: these describe project facts, not machine preferences.
+
+**Two invariants:**
+
+1. A usable preferred file excludes discovery candidates, preventing duplicate names with silent first-wins behavior after relocation.
+2. `config.py` values are resolved to absolute paths without normalization; convention values are normalized first.
+
+> A real fix: ok-infinity-nikki declared `assets/coco_detection.json`, while old hardcoded discovery searched `coco_annotations.json`, leaving the library empty.
+
+⚠️ Same filename, different resource:
+
+| File | Meaning | Path source |
+|---|---|---|
+| `assets/coco_annotations.json` (or config.py location) | Framework runtime library | `templates.cocoAnnotations` |
+| `/coco_annotations.json` | Asset-panel annotation working file | `templates.directory`, unaffected by `cocoAnnotations` |
+
+---
+
+## 4. Type C · ③: `config.py` Only (Window Matching, 4 Settings)
+
+No IDE/convention layers. Unavailable usable configuration falls back **interactively** to a window-title regex.
+
+Of the seven outputs below, `coco_feature_json` is an **intermediate layer** in type B, not a terminal setting; `top_hwnd_class` / `capture_method` have unused consumers described in §9.
+
+**Script:** `python/probe_window_config.py`, safe AST parsing **without importing project code**. Callers: parent `src/screenshotCapture.ts` `probeWindowConfig()`, child `core/ScreenshotCapture.kt`, and Python `connect_game.py` / `capture_game_window.py` importing probe helpers. Child `core/OkProjectDataService` uses the same probe for template paths; the instance probe is on `ScreenshotCapture`, while `detectPythonPath` / `detectProjectDir` belong to the service itself.
+
+Window and template matching share a probe because each Python process costs roughly hundreds of milliseconds and reads the same file/AST. Locate `config.py` through imports in `main.py` / `run.py` / `run_task.py`, then fall back to `src/config.py` / `config.py`.
+
+**Outputs (last-line JSON):**
+
+| Key | Purpose | Consumer |
+|---|---|---|
+| `exe` | Game process names for window discovery | Both screenshot hosts; `connect_game.py` |
+| `title` | Window-title regex | Same |
+| `hwnd_class` | Window class | Same |
+| `top_hwnd_class` | Top-level class for embedded windows | See §9 |
+| `args` (`windows.args`) | Game startup arguments such as `-start=xxx_launcher` | `connect_game.py` only; framework `start_device()` uses Launch with DX11, not `windows.args`. Projects formerly patched this in `main.py`, which the plugin does not execute, so it reads/passes arguments itself |
+| `capture_method` | Project-declared capture backend | See §9 |
+| `coco_feature_json` | Runtime template path | Intermediate layer in §3 |
+
+**Static parsing boundaries (`_extract_value`):**
+
+- Supports `os.path.join("assets", "coco_annotations.json")`, pathlib `Path("a") / "b"`, and `re.compile("...")`.
+- Variables return `None`; AST cannot statically evaluate them, so callers fall back.
+- Only `join` with `func.value.attr == "path"` matches, excluding `str.join`.
+
+**Lazy discovery + background refresh:** synchronous consumers treat unprobed values as undeclared (existing behavior), launching discovery in the background. After discovery, invalidate snapshots, rebuild watchers, and broadcast. On config changes, **reprobe → refresh data → rebuild watchers**, avoiding reads with stale paths.
+
+---
+
+## 5. Type D · ① ④: Personal/Machine Settings (7 Total, 6 per Host)
+
+IDE settings plus their own defaults only; neither conventions nor `config.py` participate. `annotationKeybindings` exists only in the parent; `enableTemplateGallery` only in the child.
+
+| IDE key | Purpose | Why outside project resolution | Default |
+|---|---|---|---|
+| `displayLocale` | Inlay language; `auto` follows IDE | UI preference | `auto` |
+| `enableInlayHints` | Inline language values/effect descriptions | UI preference | `true` |
+| `annotationKeybindings` | `drawBbox` / `copyCoords` / `deleteMode` / `undo` / `redo` / `copy` / `paste` / `deleteSelected` / `prevImage` / `nextImage` | UI preference | See `package.json` |
+| `enableTemplateGallery` | Template asset gallery view | UI preference | `true` |
+| `okScriptProjectPath` | Root containing project `src/config.py` | Machine paths differ | Empty, auto-discovery |
+| `okScriptPython` | Python for tasks/scripts | Machine-specific | Empty; prefer target `.venv/Scripts/python.exe` |
+| `captureMethod` | `auto` / `wgc` / `bitblt` / `foreground` | WGC availability depends on OS/GPU | `auto` |
+
+**Intentional host differences:**
+
+| Key | Parent | Child | Reason |
+|---|---|---|---|
+| `annotationKeybindings` | ✅ | ❌ | Child uses native IntelliJ keymap |
+| `enableTemplateGallery` | ❌ | ✅ | Parent gallery is always enabled |
+
+---
+
+## 6. Type E · Independent Project Discovery (2 Paths)
+
+This finds a project rather than resolves a value. Start with `okScriptProjectPath` in layer ①, then filesystem discovery (`src/config.py`); neither ② nor ③ applies.
+
+### 6.1 Main Project: `resolveProjectDir()`
+
+One implementation replaces formerly copied task-launcher/screenshot implementations, avoiding different directories in UI and scripts:
+
+```text
+okScriptProjectPath (expand ~, remove trailing slash)
+ → detect whether a workspace root has src/config.py or config.py
+ → '' (empty)
+```
+
+### 6.2 Character Data Root: `characterPanel`
+
+Intentionally separate: character data may live in another project.
+
+```text
+characterProjectPath (resolution chain)
+ → okScriptProjectPath
+ → workspace folder with assets/data/characters.json or assets/data/character_skills
+ → first workspace
+```
+
+Child counterpart: `core/ProjectDirResolution.kt` (setting first, validate config.py).
+
+---
+
+## 7. Type F · ② ④: Executor Only (2 Settings)
+
+Convention declarations plus built-in fallback; no IDE setting or `config.py`. Kept separately because shared `python/run_executor.py`, not hosts, reads it.
+
+| Convention field | Purpose | Reader |
+|---|---|---|
+| `executor.startupHooks.beforeConfigImport` | Sequential `module:function` calls before config import | Shared executor only |
+| `executor.startupHooks.afterConfigImport` | Post-import calls; otherwise `src.patches.startup_patches:install_startup_patches` | Same |
+
+No direct host consumption is intentional. Names cannot be inferred universally; declare pre-import hooks like `pre_config_patch` / `qfluent_mute_promo_patch`. Optional patch failures log without preventing startup.
+
+---
+
+## 8. Read Invariants
+
+Check all eight before modifying configuration reads; violations fail silently.
+
+1. Personal preferences deliberately win: team defaults apply until explicitly overridden.
+2. Distinguish explicit settings from defaults: VS Code `inspect()`, child `overriddenKeys`. `get()` alone makes ① always win over ②.
+3. Normalize relative paths, **never absolute paths/regexes**. `path.join`, segment comparisons, globs imply normalization; `new RegExp`, `path.resolve`, `File()` do not.
+4. Empty arrays/strings/whitespace fall back, rather than pinning an empty value, enabling convention restoration.
+5. Resolution produces provenance: `{ value, layer }` from `resolveSetting()`, overrides from `layer === PERSONAL`, never value comparisons. `declared` reruns the same chain with personal preferences cleared.
+6. Do not normalize `config.py` values, which may be absolute or built with `os.path.join`. A usable preferred file excludes discovery candidates.
+7. Unprobed lazy values return undeclared; discovered values invalidate snapshots/rebuild watchers.
+8. All consumers use accessors, not manual paths/type checks. Add each new setting to `conventionSources()` / `conventionSourceRows()` for provenance/restoration.
+
+**Complete checklist for a new resolved setting:**
+
+| Host | Changes |
+|---|---|
+| VS Code | ① `package.json` configuration ② six `package.nls*.json` files ③ pure `xxxResolved()` with `{value, layer}` ④ `xxxSetting()` using `ideSetting()` ⑤ provenance registry ⑥ six `l10n/bundle.l10n*.json` files |
+| JetBrains | ① `SettingsState` field ② `KEY_*` constant ③ `personal(KEY_X)` ④ configurable `recordIfChanged` + UI + `reset()` ⑤ `ConventionPersonal` + registry ⑥ six `OkScriptToolkitBundle*.properties` files |
+
+Guards: parent `scripts/test_convention_sources.js` checks `package.json` keys and every `ideSetting` consumer; child `OverrideKeyParityTest` enforces declaration = consumption = change-tracking sets, including counts.
+
+---
+
+## 9. Known Inconsistencies and Open Questions
+
+These retain the initial audit record. Item 4 is implemented in both export entry points; ordinary accessors/provenance do not directly include that probe layer. Other rows record historical risks, not failures reproduced in this pass.
+
+| # | Observation | Kind | Recommendation |
+|---|---|---|---|
+| 1 | Probe extracts `windows.capture_method` with no host consumers | Unused extraction | Connect it or remove extraction; prefer removal because capture method is machine-specific (§5) |
+| 2 | `player_id` exists only in probe docstring | Stale comment | Update docstring |
+| 3 | Parent parses `top_hwnd_class`, but capture JSON sends only exe/title/hwnd_class | Unused field | `connect_game.py` probes it independently; pass it through or remove from `WindowConfig` |
+| 4 | Initial audit lacked the `labelEnum.path` project-fact layer; 4/7 projects declared it | Former missing layer | All four sources can participate at export. Support slash `src/data/FeatureList` and framework-normalized dotted `src.data.FeatureList` (framework strips `.py` and converts `/` to `.`) |
+| 5 | `template_tab.generate_label_enum` is not consumed (framework default False; 4/7 projects True) | Missing layer | Overlaps empty path = no generation. Decide precedence before wiring; existing policy gives personal choice priority |
+| 6 | Template and character roots differ for convention reads | Unresolved | Templates accept an optional root; characters read current workspace. Clarify semantics first; see [project convention design](project-config.en.md) |
+| 7 | Historical `featureAliasesTouched` plus `overriddenKeys` mechanisms coexist | Legacy | Do not confuse them when changing aliases |
+
+---
+
+## 10. Source Index Across Hosts
+
+| Responsibility | VS Code | JetBrains |
+|---|---|---|
+| Pure parsing/resolution/provenance | `src/projectConfigPure.ts` | `core/ProjectConvention.kt` |
+| Disk/cache/personal normalization | `src/projectConfig.ts` (`ideSetting()` / `setIdeSetting()`) | `core/ProjectConventionConfig.kt` + `settings/OkScriptToolkitSettings.kt` |
+| Pure provenance rows | `src/conventionSources.ts` `conventionSources()` | `core/ConventionSources.kt` `conventionSourceRows()` |
+| Provenance UI | `okScriptToolkit.showConventionSources` QuickPick | `ui/ShowConventionSourcesAction.kt` DialogWrapper |
+| Clear overrides | `clearOverride()` for populated scopes | `clearOverridden(key)`, reversible |
+| Runtime template path | `src/cocoFeaturePath.ts` + `cocoFeaturePathPure.ts` | `core/CocoFeaturePath.kt` |
+| Enum class guard | `src/labelEnumGuard.ts` | `core/LabelEnumGuard.kt` |
+| config.py AST probe | Shared `python/probe_window_config.py` | Same |
+| Normalization helpers | `relPathResolved` / `textResolved` / `boolResolved` / `listResolved` | `normalizeRelPath` / `textOrNull` / type guards / `isNotBlank` filtering |
+
+These are corresponding independent implementations. Change both; identical JSON must produce identical normalization results.
+
+---
+
+## 11. Troubleshooting Ineffective Configuration Changes
+
+Follow this order; each step can independently disprove a cause:
+
+1. Identify the type (§0). Type D does not read project files; type C reads only `config.py`, so convention edits cannot affect it.
+2. Check provenance. Personal source means ① overrides ②; restore project conventions.
+3. Check normalization of `assets\lang` / `./assets/lang`. A skipped consumer can silently miss otherwise normal-looking values.
+4. Check watchers: unescaped/non-normalized glob names prevent refresh after template/language changes.
+5. Check whether undeclared was mistaken for pinned empty. Empty lists/strings fall through; expressing an intentional absence requires another mechanism.
+6. Check lazy config.py discovery. Before probing it is undeclared; expressions such as `os.path.join(variable, ...)` cannot be statically parsed and fall back.
+7. Check that both hosts changed; one host's implementation does not update the other.
+
+---
+
+## 12. Two Global Configuration Sources (Probe)
+
+Projects declare which of two independent chains applies; the plugin does not assume paths.
+
+| Source | Project declaration | Probe read |
+|---|---|---|
+| **Framework** (`source: framework`) | `config.py` `"global_configs": [option, ...]` registers framework GlobalConfig | `ok.task_executor.global_config.get_all_visible_configs()` |
+| **Project store** (`source: project_store`) | GUI page in `custom_tabs` (e.g. `src.gui.GlobalConfigTab`) imports `get_all_visible_configs` from a store | Statically resolve declared store module → import → `get_all_visible_configs()` |
+
+Both merge into one `globalConfigGroups` array, distinguished by `source`.
+
+`python/project_store.py` derives the store module from `custom_tabs` → page file → imported module exposing `get_all_visible_configs`. The criterion is the **interface**, not the module name, allowing project moves/renames without plugin changes. Declarations and already imported modules take precedence; legacy `src.core.global_config_store` remains the last candidate. Re-exported enumeration functions are collected once.
+
+> Previously, probe/executor hardcoding silently lost groups after project path changes. Regression test: `python python/tests/test_project_store.py`.
+
+Executor `resolve_group_config()` uses the same `project_store.store_modules(config, cwd)` candidates with `get_global_config(name)`, so runtime `gparams` recognizes the same groups.
diff --git a/docs/config-reads.md b/docs/config-reads.md
index fd06efa..c2e33ab 100644
--- a/docs/config-reads.md
+++ b/docs/config-reads.md
@@ -1,6 +1,8 @@
# 运行时配置读取全景
-> **一句话**:插件运行时读的配置有**四类入口**,其中只有**甲类**走四层取值链。
+[简体中文](config-reads.md) | [English](config-reads.en.md)
+
+> **一句话**:插件配置按实际读取入口分类;四层取值链不是每个字段都会经过。
> 本文件逐项写清 **「这一项是干什么的」**、按什么规则取值、改了会在哪里生效。
>
> 相关文档:
@@ -10,11 +12,8 @@
> - [`schemas/ok-script-toolkit.schema.json`](../schemas/ok-script-toolkit.schema.json) —— 编辑器里的补全与校验
> - 源码入口:父仓 `src/projectConfig.ts` / `src/projectConfigPure.ts`,子仓 `core/ProjectConvention.kt` / `settings/OkScriptToolkitSettings.kt`
-
-
---
-
## 0. 六型 · 按「实际经过哪几层」分类
⚠️ **四层是"池子",不是每一项都经过。** 按**实际经过的层组合**分类,一共**六型** ——
@@ -23,7 +22,7 @@
| 型 | 实际经过的层 | 有哪些 | 数量 | 一句话 | 代码入口 |
| ----- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | --------------------------------------------- | ---------------------------------------------------------------------- |
| **甲** | **① ② ④** | 枚举 3 项 + 模板目录 1 项 + i18n 4 项 + 角色 5 项 + 效果 1 项 | **14** | 能被团队约定,也能被我覆盖;**不碰 `config.py`** | `projectConfig.ts` 的 `xxxSetting()`;子仓 `OkScriptToolkitSettings.xxx()` |
-| **乙** | **② ③ ④** | `templates.cocoAnnotations` | **1** | 由**项目**决定(约定文件 或 `config.py`);**没有个人偏好层** | `cocoFeaturePath.ts` / `core/CocoFeaturePath.kt` |
+| **乙** | **② ③ ④** | `templates.cocoAnnotations`、`boxes.runtime` | **2** | 由**项目**决定(约定文件 或 `config.py`);**没有个人偏好层** | `cocoFeaturePath.ts` / `boxResourcePure.ts`;子仓 `core/CocoFeaturePath.kt` / `core/BoxRuntimePath.kt` |
| **丙** | **③** | `windows.{exe, title, hwnd_class, args}` | **4**(另有 2 项是死字段,见 §9) | 只有 `config.py` 这一层;探不到时**交互式兜底**(让用户手输窗口标题正则) | `python/probe_window_config.py` |
| **丁** | **① ④** | `displayLocale` / `enableInlayHints` / `annotationKeybindings` / `enableTemplateGallery` / `okScriptProjectPath` / `okScriptPython` / `captureMethod` | **7**(任一端 6) | 只属于**我这台机器 / 我个人**;**不碰项目文件** | `getConfiguration().get()`;子仓直接读 `SettingsState` |
| **戊** | 独立探测链(`okScriptProjectPath` → 自动探测) | 项目根解析 | **2 条** | "到哪儿去找这个项目" | 父仓 `resolveProjectDir()`;子仓 `core/ProjectDirResolution.kt` |
@@ -32,14 +31,10 @@
**顺序就是"离项目有多近"**:甲(约定 + 我)→ 乙(只由项目定)→ 丙(只由 `config.py` 定)→
丁(只由我定)→ 戊(找项目本身)→ 己(连插件都不读,只有执行器读)。
-> **⚠️ 当前没有任何一项走满四层。** ① 层("我这台机器要不要读它")与 ③ 层("项目 `config.py`
-> 声明的真话")**至今没有交集** —— 唯一"本可以走满"的是 `labelEnum.path`,见 §9 第 4 条。
-
-
+> **枚举导出有额外的项目事实后备。** 普通 `labelEnumPath` 设置访问器仍只读个人设置、约定文件与空值;导出入口在前两层均未给出路径时,会探测 `config.py` 的 `template_tab.label_enum_relative_path`。两端已接入,见 §9 第 4 条。编号在本文为①个人设置、②约定文件、③项目事实、④内置兜底,与 `project-config.md` 的图示编号顺序不同。
---
-
### 2.1 枚举 `labelEnum`(3 项)
| IDE 键 | 约定字段 | 这个配置是干什么的 | 兜底 | 归一化 |
@@ -100,7 +95,6 @@
不做守卫会把开关反向锁死(关不掉)。
- 这三项都会拼进文件监听 glob(lang JSON / PO / 效果文件各一条),同样要按段转义。
-
### 2.4 角色与技能 `characters`(5 项)
| IDE 键 | 约定字段 | 这个配置是干什么的 | 兜底 | 归一化 |
@@ -144,11 +138,12 @@
---
-## 3. 乙型 · ② ③ ④:由项目决定(1 项)
+## 3. 乙型 · ② ③ ④:由项目决定(2 项)
| 约定字段 | 这个配置是干什么的 | 取值链 |
| --------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `templates.cocoAnnotations` | **ok 框架加载的「运行时模板库」**(那份 COCO)在哪。插件用它做模板匹配提示与索引 | 约定文件 → `config.py` 的 `template_matching.coco_feature_json` → 依次探测 `assets/coco_annotations.json`、`ok_tasks/assets/coco_annotations.json` |
+| `boxes.runtime` | **运行时框位置表**,用于框画廊、补全和 Hover;游戏加载器由业务项目提供 | 约定文件 → `config.py` 顶层 `boxes_json` → `src/scene/boxes.json` |
**它没有"个人偏好"层**(不进溯源面板)—— 这是刻意的:它是"项目自己的真话",不是"我这台机器的偏好"。
@@ -215,7 +210,6 @@
---
-
## 5. 丁型 · ① ④:只属于我这台机器(7 项,任一端 6)
**层组合 = ① ④**:只读 IDE 设置,兜底是设置项自己的 `default`。
@@ -273,7 +267,6 @@ characterProjectPath(走取值链)
---
-
## 7. 己型 · ② ④:只由**执行器**读(2 项)
**层组合 = ② ④**:约定文件字段(②)+ 内置兜底(④)。**没有 ①** —— 没有对应的 IDE 设置;
@@ -293,7 +286,6 @@ characterProjectPath(走取值链)
---
-
## 8. 读取规则(不变量清单)
改任何一项配置读取前,先过一遍这 8 条。**违反任何一条的后果都是"静默"的**。
@@ -329,10 +321,9 @@ characterProjectPath(走取值链)
---
-
## 9. 已知不一致与待定事项
-以下保留初次审计时的现象。第 4 项已于本轮适配修复:VS Code 和 JetBrains 现在都把 `config.py` 的 `template_tab.label_enum_relative_path` 作为枚举路径的后备来源。
+以下保留初次审计记录。第 4 项已实现:VS Code 和 JetBrains 的导出入口都把 `config.py` 的 `template_tab.label_enum_relative_path` 作为枚举路径后备;普通设置访问器和溯源面板不直接包含这一探测层。其他行是历史风险记录,不等同于本轮已复现的故障。
| # | 现象 | 性质 | 建议 |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
@@ -346,7 +337,6 @@ characterProjectPath(走取值链)
---
-
## 10. 代码索引(两端对照)
| 职责 | VS Code | JetBrains |
diff --git a/docs/design-system.en.md b/docs/design-system.en.md
new file mode 100644
index 0000000..3daa363
--- /dev/null
+++ b/docs/design-system.en.md
@@ -0,0 +1,159 @@
+# ok-script-toolkit · Unified UI Design System
+
+[简体中文](design-system.md) | [English](design-system.en.md)
+
+> This is the authoritative UI specification for the entire project. All webview panels (console / templatePanel / templateAssetPanel / tempScreenshots / annotationPanel / characterManager / boxPanel) must follow it.
+> Implementation sources: `media/shared/tokens.css` (design tokens) and `media/shared/controls.css` (shared controls).
+> **Pages compose these classes; they must not independently redefine visual rules.**
+
+## 0. Core Requirement
+
+> **The whole UI must look like it comes from one design system, rather than separately decorated pages.**
+
+This is a **developer IDE plugin**. Experience design serves local-code debugging, resource editing, and diagnosis. Follow [Developer Plugin Scope and User Experience](developer-tool-scope.en.md) for feature boundaries and priorities. Keep technical information accessible. Business parameter removal, transfer, and historical configuration migration are not required plugin adaptations. Visual consistency does not imply consumer-software configuration, account, and recovery workflows.
+
+---
+
+## 1. Shared Design Language
+
+Establish and follow one design system for page/container backgrounds, cards, buttons, inputs, selects, Checkbox/Radio/Switch, tabs, tags, lists, separators, icons, tooltips, Dialog/Modal, status messages, loading, empty states, and errors. Components of the same kind must share a visual language.
+
+## 2. Shared Color System
+
+Use a shared hierarchy (page background > first-level container > control surface > Hover/Active). Do not define independent per-component colors.
+
+| Meaning | Token | Notes |
+|---|---|---|
+| Page background | `--bg-page` | Bottom layer |
+| First-level container | `--bg-container` / `--bg-container-raised` | Panels / cards |
+| Control surface (actual buttons) | `--bg-control` | Default Button/IconButton background with border |
+| Row surface (group/collapsible headings) | `--bg-row` | Very light clickable-row background: recognizable, lower visual weight than buttons |
+| Hover / Active | `--bg-control-hover` / `--bg-control-active` / `--bg-row-hover` / `--surface-hover` | Interaction states |
+| Border | `--border` / `--border-strong` | Regular / focused |
+| Primary text | `--text-primary` | |
+| Secondary text | `--text-muted` | |
+| Disabled text | `--text-disabled` | |
+| Semantic colors | `--ok` / `--run` / `--warn` / `--pause` / `--err` | Do not introduce other values |
+
+**Prohibited:** direct `--vscode-*` references in pages/components (allowed only in `tokens.css`), or hardcoded hex/rgba.
+
+## 3. Consistent Clickable Controls
+
+Clickable controls must be recognizable in their **default state**:
+
+- ❌ Plain text / blending into the container / background appearing only on hover.
+- ✅ A visible default surface; hover enhances it instead of revealing clickability for the first time.
+
+**Two control categories** avoid a screen filled with nested boxes:
+
+| Category | Use | Default state |
+|---|---|---|
+| Actual buttons | Save/sync/reset/enable/close/icon actions | `background: var(--bg-control)` + `border: 1px solid var(--border)` |
+| Clickable rows | Group headings, collapsible headings, clickable list rows | `background: var(--bg-row)` (very light) + **no border**; hover uses `--bg-row-hover` |
+
+Buttons of the same kind share height (`--control-h-sm/md/lg`), padding (`--space-*`), font, radius (`--radius-*`), border, background, icon size, icon/text spacing, and Hover/Active/Focus/Disabled treatment.
+
+## 4. Shared Size Scale
+
+- Spacing: `--space-xs(4) / sm(6) / md(10) / lg(14) / xl(20)`.
+- Control height: `--control-h-sm(24) / md(30) / lg(34)`.
+- Radius: `--radius-sm(5) / md(8) / lg(11) / pill`.
+- Font size: `--font-xs(11) / sm(12) / md(13) / lg(15)`; weights only `--weight-regular(400)` / `--weight-medium(500)`.
+
+Do not mix arbitrary 32/35/38/30px button heights or 4/6/10/square corners without justification.
+
+## 5. Shared Typography
+
+Inherit `--vscode-font-family`. Hierarchy: page title / section title (`.panel-section-title`) / body / helper text (`.panel-hint`) / label / button text / caption / error/warning text. Weights are only 400 / 500.
+
+## 6. Shared Radius, Borders, Shadows
+
+- Radius: only `--radius-sm/md/lg/pill`.
+- Border width: `--border-width` (1px); color: `--border` / `--border-strong`.
+- Shadow: only `--shadow`, for floating layers (drawers, dialogs, hover cards) only.
+
+## 7. Shared Interaction States
+
+All interactive components follow `Default / Hover / Active / Focus / Disabled / Loading`. Focus uses `--border-strong` or an outline. Disabled uses `opacity: .45` and `not-allowed`.
+
+## 8. Same Function, Same Component
+
+Save/cancel/delete/add/edit/refresh/settings/close/confirm reuse shared Button/IconButton. Inputs use Input; selects use Select; dialogs use Dialog; tags use Tag; messages use Toast/Alert; toggles use Switch. **Reuse existing components before copying CSS.**
+
+## 9. Shared Layout
+
+Keep page margins, maximum content width, section spacing, header height, toolbar height (`.panel-toolbar`), card spacing, dialog layout, and action-area layout consistent. Moving between pages should feel like using one application.
+
+## 10. No Unjustified Local Exceptions
+
+Remove oversized buttons, missing borders, hover-only backgrounds, inconsistent radii/fonts/color systems, different appearances for the same action, and duplicate implementations of the same component. Do not invent special styles for one page without a clear UX reason.
+
+## 11. Design System Assets
+
+```text
+media/shared/tokens.css Colors · Typography · Spacing · Radius · Border · Shadow · Sizes
+media/shared/controls.css Button(primary/secondary/mini/ghost/icon) · Input · Select · Checkbox/Switch
+ · Tag · Card · Toolbar · SectionTitle · Empty/Broken/Hint · Divider
+ · Clickability rules ([role=button], actual-button/clickable-row categories)
+```
+
+Connect a new panel in **three steps; omitting any step silently breaks styling**:
+
+1. In `index.html`, load `__SHARED_TOKENS_URI__` → `__SHARED_CONTROLS_URI__` → panel styles in that order. This is cascade precedence; panel styles may override the shared layer.
+2. Host `buildHtml` replaces both placeholders using `applySharedAssets(webview, extensionUri, html)` in `src/webviewHtml.ts`, the only implementation. Do not copy `asWebviewUri` assembly into panels.
+3. If `localResourceRoots` does not allow all of `extensionUri`, add `sharedResourceRoot(extensionUri)`. Restricting roots to `media/` otherwise blocks shared assets.
+
+**Automated audit:** `node scripts/test_design_system.js` checks these steps, no literal colors or direct `--vscode-*` references in panel CSS, scaled radii/font sizes, and defined `var()` references. Canvas drawing colors (such as annotation outlines) are **image content**, not UI theme, and are exempt.
+
+## 12. Final Acceptance (Global UI Audit)
+
+1. Every page uses the same design language.
+2. Components of the same kind look consistent.
+3. Every clickable control is recognizable by default.
+4. Hover does not reveal clickability for the first time.
+5. No plain-text buttons.
+6. No buttons completely blending into their containers.
+7. Colors, fonts, spacing, radii, borders, and shadows are consistent.
+8. The same function reuses the same component.
+9. No unnecessary style unique to one page.
+10. Switching between any two pages clearly feels like one complete product.
+
+---
+
+## Implementation Progress
+
+2026-10-01 addendum: box panels/galleries share `media/boxPanel`, connected through `src/boxPanels.ts` and included in the static audit. The table and six-panel record below describe the 2026-09-23 migration baseline, not a reason to omit newer panels.
+
+| Stage | Work | Status |
+|---|---|---|
+| S1 | Create `media/shared/{tokens,controls}.css`; connect console without visual changes, protected by 4 jsdom tests; allow host `localResourceRoots` | ✅ Complete |
+| S2 | Migrate templatePanel / templateAssetPanel | ✅ Complete |
+| S3 | Migrate tempScreenshots / annotationPanel | ✅ Complete |
+| S4 | Migrate characterManager: token aliases, deduplicate basic controls, scale tabs/radii/fonts | ✅ Complete |
+| S5 | Global audit: static `scripts/test_design_system.js` in place; hardcoded i18n cleanup and manual real-theme screenshot review remain | 🔄 In progress |
+
+**All six panels use the shared layer** (2026-09-23, `feat/sidebar-styling`): `console` / `templatePanel` / `templateAssetPanel` / `tempScreenshots` / `annotationPanel` / `characterManager`. Automated audit assertions cover these results:
+
+| Metric | Before | After |
+|---|---|---|
+| Direct `--vscode-*` in panel CSS | 6 files, 40+ references | **0**; only `media/shared/tokens.css` may use them |
+| Literal hex/rgb colors in panel CSS | 6 files | **0**, except canvas drawing colors |
+| Unscaled px radii / fonts | 17 / multiple occurrences | **0**, using `--radius-*` / `--font-*` |
+| Toolbar buttons | Separate padding/border/background implementations | Shared `.mini-btn` / `.icon-btn` / `.mini-btn.is-active` |
+
+**Migration issue, fixed:** top-level `import vscode` in `src/webviewHtml.ts` broke pure-function tests in `scripts/` with `Cannot find module 'vscode'`. Type-only import and lazy `require` inside functions keep pure functions independently testable.
+
+**Completed console changes:**
+
+- The parameter button no longer uses yellow `--warn` semantics. All states are neutral: default control surface plus border; modified stronger border; open darker control surface.
+- Clickability categories, finalized 2026-09-23:
+ - **Actual buttons:** `--bg-control` plus border for group-collapse buttons, `.btn-mini`, icon buttons, and destructive buttons.
+ - **Clickable rows:** very light `--bg-row` without border for startup-settings headings, task/kind group headings, card headings, unselected segmented tabs, and game-status rows.
+ - Applying `--bg-control` to everything initially made the sidebar a wall of nested boxes; users disliked it. Buttons and row headings carry different visual weights and must not use identical surfaces and borders.
+- `[hidden]` fallback, persistent collapsed state (`uiState`), and i18n key parity in six languages.
+
+**Other panel changes:**
+
+- Floating actions on thumbnails/tiles (`templatePanel.open-btn`, `templateAssetPanel.actions`, `tempScreenshots` card actions) changed from hover-only to always visible, with control surfaces and borders. Removed `rgba(0,0,0,.55)+#fff`, which appeared as black blocks in light themes.
+- Modal scrims/shadows use `--scrim` / `--shadow-sm` / `--shadow-lg`.
+- `annotationPanel` toolbar/modal buttons use shared `.mini-btn`. `characterManager` removed local `:root` token definitions (keeping short aliases to shared tokens), deduplicated basic `button/input` declarations, and uses light unselected tabs / control-surface selected tabs.
diff --git a/docs/design-system.md b/docs/design-system.md
index a06fe09..658228b 100644
--- a/docs/design-system.md
+++ b/docs/design-system.md
@@ -1,7 +1,9 @@
# ok-script-toolkit · 全局 UI 统一设计规范
+[简体中文](design-system.md) | [English](design-system.en.md)
+
> 本文件是全项目 UI 的唯一权威规范。所有 webview 面板(console / templatePanel /
-> templateAssetPanel / tempScreenshots / annotationPanel / characterManager)必须遵循。
+> templateAssetPanel / tempScreenshots / annotationPanel / characterManager / boxPanel)必须遵循。
> 实现真源:`media/shared/tokens.css`(Design Tokens)+ `media/shared/controls.css`(共享控件),
> **页面只负责组合这些类,不得自行重定义视觉规则。**
@@ -9,6 +11,8 @@
> **不是把每个页面分别做得好看,而是让整个 UI 看起来像由同一套设计系统设计出来的。**
+本项目是**开发者 IDE 插件**,体验设计服务于当前本地代码的调试、资源编辑与问题定位。功能范围及优先级遵循 [开发者插件的功能范围与使用体验](developer-tool-scope.md)。技术信息应清楚可达;业务参数删除、转移和历史配置迁移不作为插件必须适配的功能。视觉统一不意味着扩展成普通业务软件的完整配置、账户与恢复流程。
+
---
## 1. 统一设计语言
@@ -134,6 +138,8 @@ media/shared/controls.css Button(主/次/迷你/幽灵/图标) · Input · Se
## 落地进度
+2026-10-01 补充:框面板与框画廊共用 `media/boxPanel`,由 `src/boxPanels.ts` 接入共享层,静态审计已包含此目录。下表与“六个面板”记录的是 2026-09-23 的迁移基线,不能据此漏掉新增面板。
+
| 阶段 | 内容 | 状态 |
|---|---|---|
| S1 | 建立 `media/shared/{tokens,controls}.css`;console 接入(视觉零变化,4 个 jsdom 测试守护);宿主 `localResourceRoots` 放行 | ✅ 已完成 |
diff --git a/docs/developer-tool-scope.en.md b/docs/developer-tool-scope.en.md
new file mode 100644
index 0000000..ea606f2
--- /dev/null
+++ b/docs/developer-tool-scope.en.md
@@ -0,0 +1,55 @@
+# Developer Plugin Scope and User Experience
+
+[简体中文](developer-tool-scope.md) | [English](developer-tool-scope.en.md)
+
+Updated: 2026-10-01. This document governs feature choices and experience improvements. See the [UI design system](design-system.en.md) for visual rules and [project convention design](project-config.en.md) for project metadata entry points.
+
+## 1. Product Positioning
+
+ok-script-toolkit is an IDE plugin for ok-script project developers. Its value is shortening the cycle of viewing code and resources, adjusting current parameters, running validation, and diagnosing problems, while accurately operating the local version under development.
+
+Acceptance uses the current local workspace's code, task registrations, parameter declarations, and resources. Remote commits and historical versions can explain changes, but cannot override local facts or turn normal business refactoring into a plugin defect.
+
+Developers need access to technical information including project paths, interpreters, executors, task identifiers, configuration sources, capture backends, and logs. Organize this information with direct entry points; do not hide technical concepts indiscriminately to imitate consumer-software onboarding.
+
+## 2. Required Capabilities
+
+| Capability | Developer need | Acceptance focus |
+|---|---|---|
+| Current project discovery | Find the project, interpreter, registered tasks, editable parameters | Refresh matches local code; broken entry points or collection failures have clear diagnostics |
+| Task debugging | Run once, enable triggers, pause, stop; use the project's and framework's real startup chain | Actions execute with clear scope, without rebuilding business execution logic to bypass issues |
+| Parameter experiments | Edit debug values for current tasks or global groups, with clear sources and override scope | Isolate real project configuration; report actual writes and never present successful sending as runtime application |
+| Diagnosis | Logs, error locations, actual startup stages, current task, runtime target | State follows observable facts, with direct code or log evidence |
+| Screenshots and resource authoring | Capture, annotate, generate templates or regions, export, use code references | Correct edits, generated files, and references; fewer repeated lookups and panel switches |
+| Code and data navigation | Hints, previews, navigation, copying for template, language, effect, and position references | Find current sources; generate references appropriate for the current project |
+| Host consistency | The same action means the same thing in VS Code and JetBrains | Native interaction conventions, keyboard access, compact layout, discoverable actions |
+
+Existing capabilities such as account overrides debug interfaces currently offered by the project. The plugin does not become a business account manager or infer future compatibility from old account configuration.
+
+## 3. Boundaries for Business Parameter Changes
+
+- **Removed parameters:** Parameters absent from current declarations leave the editable and effective override sets. The plugin neither restores them nor requires the project to keep supporting them.
+- **Parameter transfers or task splits:** Display current registrations and parameter ownership. Do not transfer historical values based on matching field names, display titles, or former task relationships.
+- **Old debug snapshots:** Retained keys do not prove current task support. Old data may remain archived, but cannot create current parameter entry points, bypass current key sets, or require a business compatibility fix merely because it no longer applies.
+- **Business migrations:** The project owns these. Existing project migrations may run during isolated startup; the plugin does not add business migration tables, batches, historical parameter recovery, or account override transfers.
+- **Plugin format upgrades:** The plugin owns compatibility for its persistence formats, protocol, and caches. Assess this separately from business parameter migration.
+
+Adapt interfaces or metadata entry points actually consumed by the plugin: task registration, schema declarations, configuration discovery, resource index formats, or framework APIs whose changes cause incorrect reads/writes or execution failure. Internal detection-template changes, parameter removal, and task splits need no extra adaptation if the plugin can still read current declarations correctly.
+
+## 4. Experience Priorities
+
+**P0: reliable debugging and truthful results.** Fix startup failures, probes misreading local structure, uneditable current parameters, incorrect writes, project configuration contamination, and inaccessible errors/logs first. Save confirmation, runtime targets, and necessary startup state serve these problems.
+
+**P1: developer efficiency.** Improve current schema refresh, source navigation, resource previews, reference generation, screenshot/annotation transitions, shortcuts, and local action feedback. Consistent layout and visuals improve information recognition and operation efficiency.
+
+Do not make consumer onboarding, account lifecycle, cross-version business-setting inheritance, migration recovery wizards, or complete runtime health dashboards default goals. Add such UI and mechanisms only when they demonstrably reduce development steps or solve actual debugging problems.
+
+Show waiting reasons, recognition states, and parameter application confirmation only with evidence from the project or framework. Otherwise state uncertainty and offer logs; do not demand new acknowledgement or observation protocols from every business project merely to complete a UI state model.
+
+## 5. Local okef Verification Record
+
+Verification used local `ok-end-field` commit `4feea90f` and plugin workspace `efc4ff9`. Current `DailyTask` mainly retains daily switches and runtime settings; independent gift and stamina tasks declare their own parameters. Current declarations determine removed parameters; historical versions do not restore them.
+
+The isolated probe found 31 one-time tasks, 5 triggers, and 7 global configuration groups, with no schema collection failures. The account store interface was readable; window, template library, and enum paths resolved. The production template index read new `main_char` annotations and images. Project configuration contents were unchanged before and after verification; no game tasks were started.
+
+Old `DailyTask` debug values not automatically entering new subtasks, and whether old account overrides undergo project business migration, concern business content and historical data. They do not justify plugin migration features. No task, parameter, or template entry-point discovery failure was observed from these local changes. Actual game execution and in-IDE interaction were not verified in this check.
diff --git a/docs/developer-tool-scope.md b/docs/developer-tool-scope.md
new file mode 100644
index 0000000..b5e5bfb
--- /dev/null
+++ b/docs/developer-tool-scope.md
@@ -0,0 +1,55 @@
+# 开发者插件的功能范围与使用体验
+
+[简体中文](developer-tool-scope.md) | [English](developer-tool-scope.en.md)
+
+更新日期:2026-10-01。本文约束功能取舍与体验改进;视觉规则见 [全局 UI 统一设计规范](design-system.md),项目元数据入口见 [项目约定文件设计](project-config.md)。
+
+## 1. 产品定位
+
+ok-script-toolkit 是面向 ok-script 项目开发者的 IDE 插件。核心价值是缩短“查看代码与资源 → 调整当前参数 → 运行验证 → 定位问题”的往返,让开发者准确操作本地正在开发的版本。
+
+功能验收以本地工作区的当前代码、任务注册、参数声明与资源文件为准。远程提交和历史版本可以用于解释变化,不能覆盖本地事实,也不能把正常的业务重构判断为插件故障。
+
+开发者需要能看到项目路径、解释器、执行器、任务标识、配置来源、采集后端与日志等技术信息。界面应组织好这些信息,保留直接入口,不因普通软件的入门体验要求而一律隐藏技术概念。
+
+## 2. 插件需要承担的能力
+
+| 能力 | 开发者实际需要 | 验收重点 |
+| --- | --- | --- |
+| 当前项目识别 | 定位项目、解释器、注册任务及可编辑参数 | 刷新后与本地代码一致;入口失效或采集失败有明确诊断 |
+| 任务调试 | 运行一次、启用触发任务、暂停、停止;沿用项目与框架的真实启动链 | 操作能执行,作用范围清楚,不为了绕过问题重建业务执行逻辑 |
+| 参数试验 | 编辑当前任务或全局组的调试值,明确配置来源与覆盖范围 | 项目实际配置隔离;写入结果真实,发送成功不冒充运行已应用 |
+| 排查问题 | 查看日志、错误位置、实际启动阶段、当前任务与运行目标 | 状态来自可观察事实,能直接找到代码或日志证据 |
+| 截图与资源制作 | 获取画面、标注、生成模板或区域、导出并使用代码引用 | 编辑结果、生成文件和引用正确;减少重复定位与面板切换 |
+| 代码与数据导航 | 模板、语言、效果与位置引用的提示、预览、跳转和复制 | 能找到当前来源,生成的引用适合当前项目 |
+| 两端一致性 | VS Code 与 JetBrains 的同一操作具有相同含义 | 沿用宿主交互习惯,键盘可达、布局紧凑、动作可发现 |
+
+账号覆盖等已有能力用于调试项目当前提供的接口。插件不扩展成业务账号管理器,也不根据旧账号配置推断项目应如何继续兼容。
+
+## 3. 业务参数变化的处理边界
+
+- **参数删除:** 当前声明已移除的参数退出当前可编辑与有效覆盖集合。插件不恢复它,也不要求业务项目继续支持它。
+- **参数转移或任务拆分:** 按新的注册与参数归属展示。插件不凭字段同名、显示标题或旧任务关系自动搬运历史值。
+- **旧调试快照:** 保存了旧键不等于当前任务还支持它。旧数据可以留档,但不能凭它生成当前参数入口、绕过当前键集,或把其失效作为必须修复的业务兼容问题。
+- **项目业务迁移:** 由项目负责。隔离启动时项目已有的迁移逻辑可以正常执行;插件不另建业务迁移表、迁移批次、历史参数恢复或账号覆盖搬运机制。
+- **插件自己的格式升级:** 插件负责自己的持久化格式、协议和缓存兼容;这与业务参数迁移分开判断。
+
+需要修改的是插件所消费的**接口或元数据入口**:例如任务注册方式、schema 声明、配置文件定位、资源索引格式或框架 API 确实变化,使插件读错当前数据、写错位置或不能运行。业务任务内部更换检测模板、删除不用的参数或拆分任务,若插件仍能正确读取当前声明,就没有额外适配要求。
+
+## 4. 体验改进的优先级
+
+**P0:调试链可靠且结果真实。** 优先处理任务不能启动、探针读错本地结构、当前参数无法编辑、配置写入错误、项目配置被污染、错误与日志不可达。保存确认、运行目标和必要的启动状态服务于这些问题。
+
+**P1:提高开发效率。** 完善刷新当前 schema、来源跳转、资源预览、生成引用、截图与标注衔接、快捷键和局部操作反馈。布局与视觉统一用于提高信息辨识和操作效率。
+
+不把普通业务软件的首次引导、账户生命周期、跨版本业务设置继承、迁移恢复向导或完整运行健康看板默认列为插件目标。只有明确减少开发步骤或解决实际调试问题时,才增加相关界面与机制。
+
+等待原因、识别状态和参数应用确认仅在项目或框架提供证据时展示。无法确认时如实说明并提供日志入口,不为完成一套 UI 状态而要求每个业务项目实现新的回执或观测协议。
+
+## 5. 本地 okef 核对记录
+
+本次依据本地 `ok-end-field` 提交 `4feea90f` 和插件当前工作区 `efc4ff9` 核对。`DailyTask` 当前主要保留日常开关及运行设置;送礼、刷体力等独立任务按自己的声明提供参数。被删除的参数以当前声明为准,不按旧版本恢复。
+
+隔离探针读到 31 个一次性任务、5 个触发任务和 7 个全局配置组,schema 无采集失败;账号存储接口可读取,窗口、模板库和枚举路径可解析。生产模板索引能读取新的 `main_char` 标注与图片。核对前后项目配置文件内容一致,没有启动游戏任务。
+
+旧 `DailyTask` 调试值不自动进入新子任务,以及旧账号覆盖是否执行项目业务迁移,属于业务内容与历史数据的行为,不据此安排插件迁移功能。当前未观察到这些本地改动导致的任务、参数或模板入口识别失效;真实游戏运行与 IDE 内操作未在本次核对中验证。
diff --git a/docs/feature-parity.en.md b/docs/feature-parity.en.md
new file mode 100644
index 0000000..7411db8
--- /dev/null
+++ b/docs/feature-parity.en.md
@@ -0,0 +1,55 @@
+# Feature and Documentation Parity
+
+Verified: 2026-10-01. Local baseline: parent `efc4ff9`, JetBrains child `4df0cee`, both version `1.19.0`. This matrix uses current source entry points and the checks below, not design plans, other branches, or historical review conclusions.
+
+[简体中文](feature-parity.md) | [English](feature-parity.en.md)
+
+## 1. Current Features
+
+“Present” means an actual implementation entry point exists in both hosts, not that real IDE/game acceptance was completed in this pass.
+
+| Feature | VS Code | JetBrains | Parity and evidence |
+|---|---|---|---|
+| Language/OCR/template/effect reference hints | Present | Present | `src/providers.ts` / child `editor/OkEditorSupport.kt`; native host extension points |
+| AST task list and runtime schemas | Present | Present | Shared `python/parse_config_tasks.py` / `python/probe_task_schemas.py`; host caches/UI |
+| Persistent executor, one-time queues, triggers, pause/stop | Present | Present | `src/consolePanel.ts` / child `TaskRunnerService.kt`; shared `python/run_executor.py` |
+| Native startup and configuration isolation | Present | Present | Shared `OK.start_runtime()`, native controller, sandbox; nonblocking Windows input in `python/executor_input.py` |
+| Current task/global-group parameter editing | Present | Present | `src/consolePanel.ts` / child `TaskLauncherService.kt`, `GlobalSnapshotRules.kt`; startup `OK_TOOLKIT_GCONFIG`, runtime `gparams` |
+| Account override debugging | Present | Present | Shared `python/account_store.py`; child `AccountEditorDialog.kt`, beyond probe metadata passthrough |
+| Project conventions and personal provenance | Present | Present | `src/projectConfig.ts` / child `ProjectConvention.kt`, `ConventionSources.kt`; declared fields connected with corresponding type/provenance rules |
+| Runtime template paths and enum export fallback | Present | Present | Template library consumes `config.py`; export entry points in `templateAssetPanel.ts` / child `TemplateAssetToolWindowFactory.kt` provide enum fallback |
+| Template assets, export, previews, source navigation | Present | Present | `src/templateAssetPanel.ts`, `templatePanel.ts` / child `TemplateAssetToolWindowFactory.kt`, `TemplatesToolWindowFactory.kt` |
+| Box editing, publication, runtime galleries | Present | Present | `src/boxPanels.ts`, `boxResourceStore.ts` / child `BoxWindows.kt`, `BoxCatalogService.kt`; separate COCO working files and runtime tables |
+| `self.pos` completion/Hover | Present | Present | `src/providers.ts` / child `editor/OkEditorSupport.kt`; business projects still own game loading |
+| Thumbnail actions and Python insertion target | Present | Present | `src/pythonEditor.ts` / child `PythonEditorTarget.kt`; templates/boxes reuse recent Python editors, no longer TODO |
+| Annotation editing, undo, copy, image swapping, visibility | Present | Present | `src/annotationPanel.ts` / child `AnnotationDialog.kt`; common COCO contract, different save timing |
+| Temporary screenshots, capture, connection, overlay | Present | Present | Shared Python calls; separate host storage and UI |
+
+## 2. Remaining Differences and Boundaries
+
+- **Annotation save timing:** VS Code saves on change; JetBrains aggregates writes in `AnnotationDialog.doOKAction()`, discarding edits on cancel. Do not describe this as autosave or change semantics during documentation work.
+- **UI carriers:** Webview versus Swing. Parameter layouts, keymaps, and editor entry points follow their IDEs; parity does not require pixel-identical UI structure.
+- **Application feedback:** snapshot persistence, command sending, and business runtime application are separate outcomes. No uniform business acknowledgement exists; save/send success does not prove game usage.
+- **Business changes:** current declarations govern removed parameters, task splits, and internal detection templates; they do not automatically require plugin adaptation or migration.
+- **External loaders:** correct published box files do not prove project loading; actual game execution requires separate validation.
+
+## 3. Documentation Corrections
+
+| Document | Correction |
+|---|---|
+| `AGENTS.md` | Merge former `AGENT.md`; consolidate scope, boundaries, language rules |
+| `project-config.en.md` | Remove stale claims of unwired global fields, unread box management, and skipped pre-import hooks |
+| `config-reads.en.md` | Add `boxes.runtime`; distinguish ordinary enum accessors from export fallback; clarify layer numbering |
+| Child `design-parity.en.md` | Mark global injection/pushes and account editing implemented instead of original planned gaps |
+| Child `parity-review.en.md` | Update recent Python editor tracking; retain historical baselines explicitly and use this matrix for current status |
+| Child architecture report | Preserve historical analysis without treating old missing features/line counts as current acceptance |
+
+All documents except Agent instructions, skills, and skill references have separate Chinese `.md` and English `.en.md` versions maintained together. Code, APIs, and necessary original UI labels are not mixed-language prose.
+
+## 4. Validation and Limits
+
+Parent checks passed: `test_box_resource.js`, `test_thumbnail_actions.js`, `test_project_config.js`, `test_coco_feature_path.js`, `test_run_executor_sandbox.py`, `test_run_executor_gconfig.py`, covering resources, thumbnail actions, precedence, template paths, isolation, and global configuration application.
+
+JetBrains `BoxResourceTest`, `GlobalSnapshotRulesTest`, `TaskConfigMergeTest`, and `BundleParityTest` passed all 45 cases. The global UI static audit passed for 7 panels. Documentation checks confirmed 16 bilingual pairs and 7 Chinese Agent/skill references, without missing local links or numbered sections; both repositories passed `git diff --check`. VSIX build/archive checks passed with no Agent, skill, or development documents included.
+
+No real IDE walkthrough or game execution was performed; source entry points and automated tests do not replace that acceptance.
diff --git a/docs/feature-parity.md b/docs/feature-parity.md
new file mode 100644
index 0000000..2dfba49
--- /dev/null
+++ b/docs/feature-parity.md
@@ -0,0 +1,55 @@
+# 功能与文档对齐表
+
+复核日期:2026-10-01。本地基线:主仓 `efc4ff9`、JetBrains 子仓 `4df0cee`,版本均为 `1.19.0`。本表依据当前代码入口与下列验证,不把设计计划、其他分支的改动或历史审查结论算作当前功能。
+
+[简体中文](feature-parity.md) | [English](feature-parity.en.md)
+
+## 1. 当前功能
+
+“已有”表示两端有实际实现入口,不代表本轮已完成真实 IDE 或游戏验收。
+
+| 功能 | VS Code | JetBrains | 对齐结论与证据 |
+|---|---|---|---|
+| 语言、OCR、模板、效果引用提示 | 已有 | 已有 | `src/providers.ts` / 子仓 `editor/OkEditorSupport.kt`;载体为 VS Code provider 与 IntelliJ 扩展点 |
+| AST 任务列表与运行时 schema | 已有 | 已有 | 共用 `python/parse_config_tasks.py` / `python/probe_task_schemas.py`,宿主分别缓存与展示 |
+| 常驻执行器、一次性入队、触发任务启用、暂停与停止 | 已有 | 已有 | `src/consolePanel.ts` / 子仓 `TaskRunnerService.kt`;执行核心共用 `python/run_executor.py` |
+| 原生启动链与配置隔离 | 已有 | 已有 | 共用 `OK.start_runtime()`、原生启动控制器和沙箱;`python/executor_input.py` 使用 Windows 非阻塞命令管道 |
+| 当前任务参数与全局配置组编辑 | 已有 | 已有 | `src/consolePanel.ts` / 子仓 `TaskLauncherService.kt`、`GlobalSnapshotRules.kt`;启动注入 `OK_TOOLKIT_GCONFIG`、运行中推送 `gparams` |
+| 账号覆盖调试 | 已有 | 已有 | 共用 `python/account_store.py`;子仓 `AccountEditorDialog.kt`,不是只有 probe 元数据透传 |
+| 项目约定与个人覆盖溯源 | 已有 | 已有 | `src/projectConfig.ts` / 子仓 `ProjectConvention.kt`、`ConventionSources.kt`;声明字段已接入,类型和来源规则需保持一致 |
+| 运行时模板路径与枚举导出后备 | 已有 | 已有 | 模板库消费 `config.py`;枚举路径后备在 `templateAssetPanel.ts` / 子仓 `TemplateAssetToolWindowFactory.kt` 的导出入口读取 |
+| 模板素材、导出、预览与原图定位 | 已有 | 已有 | `src/templateAssetPanel.ts`、`templatePanel.ts` / 子仓 `TemplateAssetToolWindowFactory.kt`、`TemplatesToolWindowFactory.kt` |
+| 框资源编辑、发布与运行时画廊 | 已有 | 已有 | `src/boxPanels.ts`、`boxResourceStore.ts` / 子仓 `BoxWindows.kt`、`BoxCatalogService.kt`;COCO 工作文件与运行时位置表分开 |
+| `self.pos` 框补全与 Hover | 已有 | 已有 | `src/providers.ts` / 子仓 `editor/OkEditorSupport.kt`;游戏中的加载仍由业务项目负责 |
+| 缩略图动作与 Python 插入目标 | 已有 | 已有 | `src/pythonEditor.ts` / 子仓 `PythonEditorTarget.kt`;模板和框均复用最近 Python 编辑器,不再列为待办 |
+| 标注编辑、撤销、复制、图片交换、显隐 | 已有 | 已有 | `src/annotationPanel.ts` / 子仓 `AnnotationDialog.kt`;共用 COCO 契约,保存时机仍有差异 |
+| 临时截图、窗口采集、连接与浮层 | 已有 | 已有 | 两端调用共用 Python,宿主存储和界面各自实现 |
+
+## 2. 保留的差异与范围
+
+- **标注保存时机不同**:VS Code 改动即保存;JetBrains 在 `AnnotationDialog.doOKAction()` 中汇总保存,取消丢弃编辑。不能把后者写成自动保存,也不在本次文档整理中改变既有语义。
+- **界面载体不同**:Webview 与 Swing,参数详情布局、键位设置和编辑器入口遵循各自 IDE。功能对齐不要求界面结构逐像素相同。
+- **参数应用反馈有限**:快照保存、命令发送和业务运行应用是不同结果;当前没有统一的业务应用回执。不能据保存或发送成功宣称游戏已使用新值。
+- **业务变化由当前声明决定**:删除参数、拆分任务、更换内部检测模板不自动产生插件适配或迁移需求。
+- **本表不保证外部项目加载器**:框发布文件正确并不证明业务项目已经加载它;真实游戏运行需单独验证。
+
+## 3. 文档状态修正
+
+| 文档 | 已修正内容 |
+|---|---|
+| `AGENTS.md` | 合并原 `AGENT.md`,统一仓库定位、功能边界和文档语言规则 |
+| `project-config.md` | 去掉“全局字段未接线”“框管理尚未读取”“配置导入前钩子仍被跳过”等过时描述 |
+| `config-reads.md` | 补充 `boxes.runtime`,区分普通枚举设置访问器与导出入口后备,说明本文编号与设计图不同 |
+| 子仓 `design-parity.md` | 全局配置注入、运行中推送和账号编辑改为当前已实现,不再按最初计划列为缺失 |
+| 子仓 `parity-review.md` | 更新最近 Python 编辑器跟踪状态;旧条目明确保留历史基线,当前结论以本表为入口 |
+| 子仓架构比较报告 | 保留历史分析,不把旧缺失清单或旧行数当作当前验收结果 |
+
+除 Agent、skill 及技能配套说明外,文档均提供独立中文 `.md` 和英文 `.en.md`,同步维护内容;代码、API 和必要的原始界面文字不作为混写正文。
+
+## 4. 验证与限制
+
+本轮主仓验证通过:`test_box_resource.js`、`test_thumbnail_actions.js`、`test_project_config.js`、`test_coco_feature_path.js`、`test_run_executor_sandbox.py`、`test_run_executor_gconfig.py`。覆盖框资源、缩略图动作、配置优先级、模板路径、配置隔离及全局配置应用链。
+
+JetBrains 的 `BoxResourceTest`、`GlobalSnapshotRulesTest`、`TaskConfigMergeTest`、`BundleParityTest` 共 45 个用例通过。全局 UI 静态审计覆盖 7 个面板并通过。文档检查确认 16 组双语文件、7 份中文 Agent/skill 说明,本地链接和编号章节无缺漏;两仓 `git diff --check` 通过。VSIX 构建与压缩包检查通过,未包含 Agent、skill 或开发文档。
+
+没有在真实 IDE 中逐项操作,也没有启动游戏;源码中存在入口和自动测试通过不替代这些验收。
diff --git a/docs/project-config.en.md b/docs/project-config.en.md
new file mode 100644
index 0000000..3b64224
--- /dev/null
+++ b/docs/project-config.en.md
@@ -0,0 +1,310 @@
+# Project Convention File (`ok-script-toolkit.json`) Design
+
+[简体中文](project-config.md) | [English](project-config.en.md)
+
+This file helps the developer plugin discover **current local project interfaces and resource entry points**; see [Developer Plugin Scope and User Experience](developer-tool-scope.en.md). It does not contain business parameter migration tables. When projects remove or transfer parameters, the plugin follows current declarations instead of restoring or transferring old debug values.
+
+> Status: **existing fields connected in both hosts** (local source verification, 2026-10-01). Companion artifacts: `schemas/ok-script-toolkit.schema.json` and `docs/ok-script-toolkit.example.json`.
+>
+> | Scope | Status |
+> |---|---|
+> | Executor (`load_project_config` / `executor.startupHooks`) | ✅ `13f754b` |
+> | VS Code loader + `labelEnum` | ✅ `df41a85` |
+> | JetBrains loader + `labelEnum` | ✅ `core/ProjectConventionConfig.kt` + `core/ProjectConvention.kt` |
+> | Screenshot shortcut (§6.4) | ✅ Both hosts |
+> | `templates.directory` (formerly unused setting in §8.1) | ✅ Both hosts |
+> | Project convention vs my settings provenance panel (§3) | ✅ Both hosts |
+> | `i18n` / `characters` / `effects` | ✅ Both hosts |
+> | `templates.cocoAnnotations` (including `config.py` facts) | ✅ Both hosts |
+
+> **Companion reading:** [Runtime Configuration Read Paths](config-reads.en.md) covers **all** runtime configuration reads: six actual layer combinations, each setting's purpose, invariants, and troubleshooting. This document covers only the project convention file layer; the companion also covers IDE settings and the `config.py` probe.
+
+## 1. Problems to Solve
+
+The plugin currently stores **project conventions** in **IDE user settings**. Both hosts have fields with matching names and meanings (18 in VS Code / 19 in JetBrains, with 17 overlapping), but:
+
+1. **They do not travel with projects:** changing machines or colleagues requires configuration again.
+2. **Each host stores a copy:** using two IDEs requires entering values twice and can cause disagreement.
+3. **Defaults are guesses:** `assets/lang`, `i18n`, `ok_templates`, and `src/data/effects.py` only fit standard layouts.
+4. **Some project facts are never read:** values are declared in `config.py`, but the plugin guesses from names.
+
+The fourth problem is most serious. Enum paths for ok-end-field and ok-infinity-nikki are declared, or should be declared, in `config.py`, while the plugin relies on regexes assembled from `featureAliases` to guess from code.
+
+## 2. Design Principles
+
+> **Read facts already declared in project `config.py` first. `ok-script-toolkit.json` covers only what `config.py` lacks or does not consistently declare.**
+
+This keeps the convention file small and avoids maintaining one fact twice.
+
+### Evidence: `config.py` Survey of Five ok Projects
+
+| Project | `config_folder` | `screenshots_folder` | `template_tab.label_enum_relative_path` | `generate_label_enum` | `template_matching.coco_feature_json` |
+|---|---|---|---|---|---|
+| ok-end-field | ✓ | ✓ | ✓ | ✓ | ✓ |
+| OK-AzurPromilia | ✓ | ✓ | ✓ | ✓ | ✓ |
+| ok-gf2 | ✓ | ✓ | ✓ | ✓ | ✓ |
+| ok-infinity-nikki | ✓ | ✓ | **✗** | **✗** | ✓ |
+| ok-gm | ✓ | ✓ | **✗** | **✗** | ✓ |
+
+Three categories follow:
+
+- **5/5 declare** `config_folder`, `screenshots_folder`, and `coco_feature_json`: no need to duplicate them in the convention file; read `config.py` (`config_folder` already works this way).
+- **3/5 declare** `label_enum_relative_path`: cannot rely on it.
+- **0/5 declare** enum class names or reference aliases: the convention file must declare them.
+
+The last two justify `labelEnum`. ok-infinity-nikki and ok-gm lack even `template_tab`, although `src/data/FeatureList.py` exists.
+
+## 3. Value Precedence
+
+```text
+① Built-in defaults (fallback)
+ ↑ overridden by
+② Facts declared in project config.py
+ ↑ overridden by
+③ ok-script-toolkit.json (committed team defaults)
+ ↑ overridden by
+④ Personal preferences (IDE settings) ← highest
+```
+
+The purpose of **④ highest**: the project file gives team defaults; explicitly changed personal values win.
+
+⚠️ **Side effect:** once someone changes a value, the project declaration for that setting stops applying indefinitely, hiding later team changes. Implement these mitigations together:
+
+1. Show whether a value comes from project conventions or personal overrides.
+2. Provide Restore project convention, clearing the personal override back to ③.
+
+> ✅ **VS Code mitigation implemented:** `src/conventionSources.ts` and `okScriptToolkit.showConventionSources` (QuickPick, with a `discard` icon on overridden rows).
+>
+> Two requirements:
+>
+> - **The resolution chain produces provenance; UI does not recompute it.** `projectConfigPure.resolveSetting()` returns `{ value, layer }`. Independent provenance logic eventually disagrees with actual values, yielding misleading UI. Derive `overridden` from `layer === 'personal'`, not value comparison.
+> - **Restore clears populated values in all three scopes**: workspace folder / workspace / user. Clearing one scope leaves effective overrides behind; writing `undefined` indiscriminately leaves empty entries. First use `inspect()` to find populated scopes.
+>
+> This is a command because **VS Code's settings UI is not extensible**: `contributes.configuration` supports static descriptions, not dynamic provenance or buttons.
+>
+> Add each newly connected setting to `conventionSources()`. `scripts/test_convention_sources.js` checks keys against `package.json`, catching typos that silently break restoration.
+>
+> The panel's `declared` value is **not read separately from the config object**. Clear personal preferences and run the same chain again; a `builtin` result means no declaration. This gives displayed and effective values identical normalization, so `./lang` becomes `lang` in both.
+>
+> ✅ **JetBrains counterpart implemented:** pure `core/ConventionSources.kt` and `ui/ShowConventionSourcesAction.kt` (`AnAction` + `DialogWrapper`). `ProjectConvention` yields the same `{ value, layer }`; registration lives in `conventionSourceRows()`.
+
+Every layer is optional. Missing layers fall through; if all are absent, behavior remains unchanged. **A missing file preserves existing behavior: this is additive.**
+
+### ⚠️ Implementation Trap: Explicit Settings vs Defaults in Layer ④
+
+Both hosts encountered this real, silent failure. IDE settings have nonempty defaults:
+
+- VS Code: `okScriptToolkit.featureAliases` in `package.json` defaults to `["fL","FeatureList","Labels"]`.
+- JetBrains: `SettingsState.init` initializes the same list.
+
+Simply reading IDE settings always returns a value, so ④ always wins and **③ never applies**. The UI looks normal while project settings have no effect.
+
+| Host | Correct criterion |
+|---|---|
+| VS Code | `getConfiguration().inspect('featureAliases')`, using `workspaceFolderValue ?? workspaceValue ?? globalValue`; unset only when all are `undefined` |
+| JetBrains | Empty state defaults (empty list means unset). Legacy defaults use `featureAliasesTouched` to distinguish initialization from an identical user-entered value, with a one-time migration |
+| JetBrains scalar settings | Nonempty `SettingsState` defaults such as `ok_templates` / `assets/lang` cannot use emptiness. Track `overriddenKeys`; `OkScriptToolkitConfigurable.apply()` records only actual changes, `init` seeds legacy users once, and resolution checks membership first |
+
+**General rule:** any nonempty-default setting needs a signal of actual user changes before joining the chain, or ④ permanently masks ③. Check defaults before wiring.
+
+⚠️ Record changes **before assignment in `apply()`**; after assignment the old value is lost. Unconditionally recording keys means merely opening settings and clicking Apply silently overrides every project convention.
+
+> **Known tradeoff:** JetBrains settings UI alone maintains `overriddenKeys`. Direct edits to `ok-script-toolkit.xml` are not recorded, so those keys remain unset and project conventions apply. This is acceptable because manual XML editing is unsupported.
+
+> **Both mitigations are complete** (see §3). Adding groups increases the surface of hidden team changes, so **update the provenance registries with every new group**: VS Code `conventionSources()` and JetBrains `conventionSourceRows()`. Tests check keys against `package.json` in VS Code and registry contents/order in JetBrains.
+
+## 4. File Shape
+
+- Name: **`ok-script-toolkit.json`**, visible, without a leading dot, intended for commits.
+- Location: **root of the project being debugged**.
+- Format: **plain JSON**, not JSONC.
+ - Neither host needs parser changes; the child's bare `ObjectMapper()` rejects comments by default.
+ - Schema `description` provides hover documentation from one maintained source.
+- Associate the schema through `contributes.jsonValidation` for completion and validation.
+
+**Boundary:** the plugin **reads only**, never silently writes this file.
+
+## 5. Fields
+
+### Included in the Convention File
+
+| Group | Field | Declared in config.py? | Fallback |
+|---|---|---|---|
+| `labelEnum` | `path` | 3/5 | IDE `labelEnumPath` → `template_tab.label_enum_relative_path` → empty (no enum generation) |
+| | `name` | **0/5** | IDE `labelEnumName` → path basename (existing behavior) |
+| | `aliases` | **0/5** | IDE `featureAliases` → `["fL","FeatureList","Labels"]` |
+| `executor.startupHooks` | `beforeConfigImport` | **No such information** | Statically identify direct `patches.*` calls in `main.py` before config import |
+| | `afterConfigImport` | **No such information** | Try convention `src.patches.startup_patches:install_startup_patches` |
+| `templates` | `directory` | No (plugin convention) | IDE setting → `ok_templates` |
+| | `cocoAnnotations` | **6/6** | `template_matching.coco_feature_json` → two discovery candidates |
+| `boxes` | `runtime` | New; absent in existing projects | Top-level `boxes_json` → `src/scene/boxes.json` |
+| `i18n` | `enabled` / `langDirectory` / `poDirectory` / `poDomains` | No | IDE settings → built-ins |
+| `characters` | `projectPath` / `masterFile` / `skillsDirectory` / `localeFile` / `avatarTemplateRegex` | No | IDE settings → built-ins |
+| `effects` | `file` | No | IDE setting → `src/data/effects.py` |
+
+**Wiring status:** all fields connected (`templates.directory`, `templates.cocoAnnotations`, `boxes.runtime`, `labelEnum.*`, `i18n`, `characters`, `effects`). `boxes.runtime` supports file discovery, box resource management, runtime galleries, and `self.pos` completion through `src/boxPanels.ts` / `src/providers.ts` and child `ui/BoxWindows.kt` / `editor/OkEditorSupport.kt`. See [Box Resource Design](box-resources.en.md) for geometry and save contracts.
+
+**⚠️ Files named `coco_annotations.json` can mean different things.** Wrong wiring silently selects the wrong file:
+
+| File | Meaning | Readers/writers | Path source |
+|---|---|---|---|
+| `assets/coco_annotations.json` (or config.py location) | Framework **runtime template library** | `featureData` / `OkProjectDataService` read and watch | `templates.cocoAnnotations` → config.py → two conventions |
+| `/coco_annotations.json` | Asset panel **annotation working file** | `templateAssetData` / `TemplateAssetDataService` read/write | `templates.directory`, **unaffected by** `cocoAnnotations` |
+| `src/scene/boxes.json` (or `boxes_json` location) | Business-project **runtime boxes** | Read by box galleries, completion, and Hover; game loading still belongs to project `ScreenPosition` | `boxes.runtime` → config.py → discovery |
+| `/boxes.json` | Box management **annotation working file** | Both resource panels and shared annotation editors read/write it; explicit runtime publication | `templates.directory`, **unaffected by** `boxes.runtime` |
+
+`cocoAnnotations` and `boxes.runtime` both consume project facts and have **no IDE/personal preference layer**. Existing projects lack `boxes_json`; absence probes `src/scene/boxes.json`.
+
+**Choose normalization by field type**; wrong choices fail silently:
+
+| Type | Helper | Reason |
+|---|---|---|
+| Relative paths (directories/data files) | `relPathResolved` | Used in globs or directory-segment comparisons; `assets\lang` / `./assets/lang` otherwise miss |
+| Absolute paths (`characters.projectPath`) | `textResolved` | Normalization strips the leading POSIX slash |
+| Regex (`characters.avatarTemplateRegex`) | `textResolved` | Normalization changes `\d` to `/d` and strips trailing `/`, breaking regex |
+| Boolean | `boolResolved` | Handwritten `"enabled": "false"` is a truthy string without a guard |
+| String arrays | `listResolved` | Empty means undeclared, allowing restoration of project conventions |
+
+### ⚠️ `labelEnum.path` Is a Module Path; Consumers Add `.py`
+
+`labelEnum.path` has the same shape as `label_enum_relative_path`: a module path such as `src/data/FeatureList` without `.py`. Framework `_normalize_label_enum_relative_path()` in `ok/ui/qt/tasks/TemplateTab.py` actively strips `.py` before saving; ok-end-field, OK-AzurPromilia, and ok-gf2 declare `src/data/FeatureList`.
+
+Consumers generating files or absolute paths need a **file path**. Writing the module path directly creates extensionless `FeatureList`, which Python cannot import and breaks the project.
+
+Each host provides one explicit conversion: VS Code pure `labelEnumPath()` / setting accessor `labelEnumPathSetting()`; child `LabelEnumConvention.filePathOr()`. **Do not assemble suffixes at call sites**; accept existing `.py` without duplication. Both layers share `normalizeLabelEnumFile`. The old implementation normalized only project declarations and returned personal preferences unchanged, generating extensionless files from module-path input.
+
+### ⚠️ `labelEnum.name` Is a Code Contract
+
+Most fields control only plugin reads. `labelEnum.path` / `name` determine **written file location and class name**, while project code imports by name:
+
+```python
+from src.data.feature_list import FeatureList # 10 occurrences in OK-AzurPromilia
+```
+
+Changing the class to `MyEnum` can prevent the entire project from running, not merely change local display. Personal overrides can break the project.
+
+**Allow changes, but confirm before overwriting an existing file**, in both hosts.
+
+| Step | Implementation |
+|---|---|
+| Pure, testable criterion | VS Code `src/labelEnumGuard.ts`; child `core/LabelEnumGuard.kt` |
+| IO/dialog | VS Code `templateAssetPanel.confirmLabelEnumRename()`; child `ui/TemplateAssetToolWindowFactory` |
+| Tests | `scripts/test_label_enum_guard.js`, including 5 destructive comparisons |
+
+Three invariants:
+
+1. **No file → no prompt:** new generation cannot invalidate an old name.
+2. **Same old/new class name → no prompt:** regeneration on every save should not create noise.
+3. **Existing file with unrecognizable class → prompt:** the path may point to an ordinary module whose contents would be deleted.
+
+Report impact by scanning project `**/*.py` for old-class imports. `importsName` handles `from a import X`, `(A, X)`, `X as fL`, and `import a.X`. **Prefer false positives over missed references**, including commented imports. This informs confirmation, not automatic decisions.
+
+**Validate class changes, not path changes.** Changing paths leaves the old module intact, so old imports still work (without new labels). Renaming inside the same file immediately breaks references. Only class changes need this guard.
+
+### 🧹 Related Fix: Global Last-Saved Path in `globalState`
+
+The personal `labelEnumPath` formerly lived in `context.globalState['okScriptToolkit.lastEnumFilePath']`. It is now **deprecated in favor of a real IDE setting** because:
+
+1. It was global while consumers resolved against current roots. A path entered for project A could silently generate nonexistent directory trees in B through `mkdirSync(dir, { recursive: true })`.
+2. It was invisible in settings/provenance, leaving users unable to see remembered values.
+3. Restore project convention clears IDE scopes, not `globalState`, producing the prohibited provenance/effective-value disagreement.
+
+The chain becomes `IDE setting > project convention > fallback`, like `featureAliases`. Change path now writes an **IDE setting** at workspace-folder scope, or globally only without a workspace. Remembered-path convenience remains visible, editable, and traceable.
+
+> **No migration:** the old global value may itself be wrong. Copying it would preserve the bug. Fall back to the correct project convention and ask again on the first save.
+
+### Excluded from the Convention File
+
+- **Personal preferences:** `displayLocale`, `enableInlayHints`, `enableTemplateGallery`, `annotationKeybindings`, and **screenshot shortcuts** (§6.4).
+- **Machine-specific:** `okScriptPython`, `captureMethod`, `okScriptProjectPath`.
+
+Committing these would impose one person's machine/preferences on colleagues.
+
+## 6. Host Change Checklist
+
+### Additions (Corresponding Logic in Both Hosts)
+
+| Host | File | Responsibility |
+|---|---|---|
+| VS Code | `src/projectConfig.ts` | Find/parse `ok-script-toolkit.json`, expose accessors with defaults |
+| JetBrains | `core/ProjectConventionConfig.kt` | Same |
+
+### Precedence Changes (Add a Layer to Existing Accessors)
+
+| Host | File | Fields |
+|---|---|---|
+| VS Code | `src/langData.ts` | `langDirectory`, `poDirectory`, `poDomains`, `enablePoData` |
+| | `src/characterPanel.ts` | `characterMasterFile`, `characterSkillsDirectory`, `characterLocaleFile`, `characterAvatarTemplateRegex` |
+| | `src/characterData.ts`, `src/effectData.ts`, `src/extension.ts`, `src/taskLauncher.ts` | `effectsFile`, `poDirectory` |
+| JetBrains | `settings/OkScriptToolkitSettings.kt` | All accessors: insert project layer before `ifBlank { default }`; `overriddenKeys` distinguishes explicit scalar/boolean/list values from defaults |
+| | `core/OkProjectDataService.kt`, `core/OkDataChangeService.kt`, `ui/CharacterManagerPanel.kt`, `tasklauncher/TaskLauncherToolWindowFactory.kt` | Consumers already use setting accessors; change the accessors themselves |
+
+> **Host symmetry:** `projectConfigPure.ts` ↔ `core/ProjectConvention.kt` (pure objects + resolution); `projectConfig.ts` ↔ `settings/OkScriptToolkitSettings.kt` (disk + personal preferences); `conventionSources.ts` ↔ `core/ConventionSources.kt` (registry). Change both sides; identical JSON must yield identical normalization results.
+
+### `labelEnum` Implementation
+
+| Host | File | Change |
+|---|---|---|
+| VS Code | `src/providers.ts:25` | `featureAliases()` reads `labelEnum.aliases` |
+| | `src/templatePanel.ts:23` | Same |
+| | `src/templateAssetData.ts:50,519,573` | Configurable `TEMPLATE_FOLDER`; `enumFile` defaults to `labelEnum.path`; class comes from `labelEnum.name`, **not inferred from filename** |
+| | `src/templateAssetPanel.ts:202` | Input defaults through `labelEnumPathSetting()`; validate class rename before overwrite |
+| JetBrains | `settings/OkScriptToolkitSettings.kt:65` | Same aliases change |
+| | `editor/OkEditorSupport.kt:76,120`, `ui/TemplatesToolWindowFactory.kt` | Same |
+| | `core/TemplateAssetDataService.kt:495,510` | Same enum path/class sources |
+
+> **Actual implementation scope (code is authoritative; do not audit only by the table):**
+>
+> - **`aliases`:** both hosts connected through one entry each, `providers.featureAliases()` and `OkScriptToolkitSettings.featureAliases()`. Other consumers benefit automatically.
+> - **`name`:** generation uses `labelEnum.name`, falling back to filename only when absent. Both have `labelEnumName` personal overrides and existing-file class-change guards (§5).
+> - **`path`:** generation defaults use explicit module-to-file conversion (§5); personal persistence moved from `globalState` to IDE `labelEnumPath` (§5).
+> - **`templates.directory`:** both connected, including the formerly dead VS Code setting (§8.1). Consumers use `projectConfig.templatesDirectory(projectDir)` / `OkScriptToolkitSettings.okTemplatesDirectory()`, including watcher globs and `thumbSourceSubdir()` source detection. Both normalize names first through `normalizeRelPath`.
+> - **Later wiring completed:** `templates.cocoAnnotations` including `template_matching.coco_feature_json`, `boxes.runtime`, and `i18n` / `characters` / `effects`. During export, both hosts probe `template_tab.label_enum_relative_path` if personal preferences and project conventions supply no enum path. This fallback belongs to the export entry point, not ordinary setting accessors.
+> - **This does not make every interaction prompt-free:** export targets, path changes, and overwrite confirmations retain their current workflows.
+
+### Executor (`python/run_executor.py`)
+
+| Change | Location |
+|---|---|
+| Read `executor.startupHooks.beforeConfigImport`, call sequentially **before** `import config` | Before `config_module = __import__(...)` in `main()` |
+| Read `executor.startupHooks.afterConfigImport`, retain convention discovery if absent | Existing `install_project_startup_patches()` call |
+
+> This chain is implemented and fixes previously skipped pre-import hooks. ok-end-field's `pre_config_patch` / `qfluent_mute_promo_patch` must run before config import. The plugin follows project declarations or safe static entry discovery; business parameter changes do not introduce migration logic.
+
+### 6.4 Screenshot Shortcut (Not Project Configuration)
+
+**Goal:** screenshot → annotation template management. Target **template asset management** (`openTemplateAssets` / `ShowTemplateAssetsAction`), whose own screenshot action saves and refreshes assets, rather than temporary screenshots (`showTempScreenshots` / `ShowTempShotsAction`).
+
+**IDE scope:** keybindings are personal. Project configuration would impose them on colleagues. VS Code and IntelliJ already have native keymap editors; do not invent another system.
+
+| Host | Approach |
+|---|---|
+| VS Code | Add `okScriptToolkit.screenshotToTemplate` to `contributes.commands`, with a default in `contributes.keybindings` and no `when` restriction; users edit Keyboard Shortcuts |
+| JetBrains | Add `AnAction` and a default keybinding under `plugin.xml` actions; users edit Settings → Keymap |
+
+Open the annotation template management panel and invoke its screenshot action. **Reuse existing `handleScreenshot`; do not add capture implementation.**
+
+## 7. Migration and Compatibility
+
+- **Missing file → unchanged behavior**; no one-time migration.
+- Keep all IDE settings; their role changes from sole source to personal override.
+- Document full (ok-end-field) and minimal (ok-infinity-nikki) examples.
+
+## 8. Related Findings Outside This Design
+
+1. **VS Code `okScriptToolkit.okTemplatesDirectory` was unused:** `templateAssetData.ts` hardcoded `ok_templates`, while the child read the setting in 10 places. **✅ Fixed:** both use `templates.directory` accessors. Removed `TemplateAssetDataService.load/cocoPath` default `templatesDir: String = "ok_templates"`, which would allow silent bypasses.
+2. **Previously unread `label_enum_relative_path` now supplies an export fallback**, through parent `templateAssetPanel.ts` and child `TemplateAssetToolWindowFactory.kt`, consuming the same probe field.
+3. **VS Code lacks a JSONC parser**, supporting the plain-JSON decision (§4).
+
+## 9. Open Questions
+
+1. ~~Is `captureMethod` project convention or machine-specific?~~ **Decided:** machine-specific, excluded (§5), alongside `okScriptPython` / `okScriptProjectPath`. It varies by hardware, drivers, and window behavior.
+2. A Generate project configuration command? The design is read-only except explicit writes; **not implemented**.
+3. If `characters.projectPath` points elsewhere, does that repository's convention file participate? **Observed: no.** Both hosts read all `characters.*`, including the project path itself, from the **current workspace** (`charactersMasterFileSetting()` etc. use `loadProjectConfig()` without a root). The path determines data location, not configuration source.
+
+ ⚠️ **Templates do the opposite:** `TemplateAssetData` explicitly passes its own root via `templatesDirectory(this.rootDir)` because data can come from another repository. This is **unresolved inconsistency**, not a settled decision:
+
+ - If `characters.masterFile` describes the other repository's layout, read that repository's file, like templates.
+ - If it describes where to find character data while debugging the current project, the current behavior is correct.
+
+ Establish the meaning before unifying; both interpretations are coherent. Do not change one host alone.
diff --git a/docs/project-config.md b/docs/project-config.md
index cadaf33..93e786f 100644
--- a/docs/project-config.md
+++ b/docs/project-config.md
@@ -1,6 +1,10 @@
# 项目约定文件(`ok-script-toolkit.json`)设计
-> 状态:**部分实现**。配套产物:`schemas/ok-script-toolkit.schema.json`、
+[简体中文](project-config.md) | [English](project-config.en.md)
+
+本文件服务于开发者插件识别**当前本地项目的接口与资源入口**,范围见 [开发者插件的功能范围与使用体验](developer-tool-scope.md)。约定文件不承载业务参数迁移表;业务项目删除或转移参数时,插件跟随当前声明,不自动恢复或搬运旧调试值。
+
+> 状态:**现有字段已接入两端**(2026-10-01 本地代码复核)。配套产物:`schemas/ok-script-toolkit.schema.json`、
> `docs/ok-script-toolkit.example.json`。
>
> | 范围 | 状态 |
@@ -175,7 +179,7 @@
**接线状态**:全部字段已接线(`templates.directory` / `templates.cocoAnnotations` /
`boxes.runtime` / `labelEnum.*` / `i18n` / `characters` / `effects`)。
-`boxes.runtime` 的后半段(读 `config.py`、定位文件)已接上;框管理界面仍按 `docs/box-resources.md` 继续。
+`boxes.runtime` 已接入文件定位、框资源管理、运行时框画廊及 `self.pos` 补全;实现分别在 `src/boxPanels.ts` / `src/providers.ts` 与子仓 `ui/BoxWindows.kt` / `editor/OkEditorSupport.kt`。几何和保存契约见 [框资源设计](box-resources.md)。
**⚠️ 两个同名的 `coco_annotations.json` 不是一回事** —— 接错会静默指向错的文件:
@@ -183,8 +187,8 @@
|---|---|---|---|
| `assets/coco_annotations.json`(或 config.py 指的别处) | ok 框架加载的**运行时模板库** | `featureData` / `OkProjectDataService` 读,文件监听盯它 | `templates.cocoAnnotations` → config.py → 两个惯例位置 |
| `<模板目录>/coco_annotations.json` | 素材面板自己的**标注工作文件** | `templateAssetData` / `TemplateAssetDataService` 读写 | `templates.directory`(**不受** `cocoAnnotations` 影响) |
-| `src/scene/boxes.json`(或 `boxes_json` 指的别处) | 业务项目加载的**运行时框** | 路径已能解析;框管理 / 补全尚未读取。加载器在业务项目的 `ScreenPosition` | `boxes.runtime` → config.py → 探测位置 |
-| `<模板目录>/boxes.json` | 框资源管理的**标注工作文件** | 契约已定,面板尚未接上 | `templates.directory`(**不受** `boxes.runtime` 影响) |
+| `src/scene/boxes.json`(或 `boxes_json` 指的别处) | 业务项目加载的**运行时框** | 框画廊、补全和 Hover 读取;游戏加载器仍由业务项目的 `ScreenPosition` 提供 | `boxes.runtime` → config.py → 探测位置 |
+| `<模板目录>/boxes.json` | 框资源管理的**标注工作文件** | 两端框资源管理和共用标注编辑器读写,显式发布到运行时文件 | `templates.directory`(**不受** `boxes.runtime` 影响) |
`cocoAnnotations` 与 `boxes.runtime` 是"`config.py` 已声明的事实"落地的两条链,
都**没有 IDE 设置**(没有"个人偏好"层)。`boxes_json` 在现有项目里还没有,缺席时探测 `src/scene/boxes.json`。
@@ -331,10 +335,8 @@ import 得到(只是拿不到新标签),不会报错;而改类名是**
> `OkScriptToolkitSettings.okTemplatesDirectory()`,包括文件监听 glob 与
> `thumbSourceSubdir()` 的来源判定(目录名要拼进 glob / 做目录段匹配,所以
> 两端都先归一化一次 —— 见 `normalizeRelPath`)。
-> - **未做**:`templates.cocoAnnotations`(消费点散在 6 个文件,且要先读 `config.py`
-> 的 `template_matching.coco_feature_json` —— 两端目前都**完全不读** `config.py` 的
-> 这一项,只有执行器侧用 AST 读 `config_folder`);`i18n` / `characters` / `effects`
-> 各组;"有值时不再弹框"未做 —— 仍会弹输入框,只是默认值变了。
+> - **已完成后续接线**:`templates.cocoAnnotations`(含 `config.py` 的 `template_matching.coco_feature_json`)、`boxes.runtime`、`i18n` / `characters` / `effects` 各组。导出时,两端会在个人与项目约定均未提供枚举路径时探测 `template_tab.label_enum_relative_path`;这个后备发生在导出入口,不由普通设置访问器直接读取。
+> - **不能据此宣称所有交互都免输入**:导出目标、路径修改和覆盖确认仍按当前工作流处理。
### 执行器(`python/run_executor.py`)
@@ -343,9 +345,7 @@ import 得到(只是拿不到新标签),不会报错;而改类名是**
| 读 `executor.startupHooks.beforeConfigImport`,在 `import config` **之前**依次调用 | `main()` 中 `config_module = __import__(...)` 之前 |
| 读 `executor.startupHooks.afterConfigImport`;缺席时保持现有的约定探测 | 现有 `install_project_startup_patches()` 调用点 |
-> 这一项**直接补上已确认的缺口**:ok-end-field 的 `pre_config_patch` /
-> `qfluent_mute_promo_patch` 必须在 `import config` 之前跑,而执行器**至今整段跳过**
-> (它们的名字没有通用约定,插件无从推断)。
+> 此链路已实现,补上了原先跳过配置导入前钩子的缺口。ok-end-field 的 `pre_config_patch` / `qfluent_mute_promo_patch` 必须在 `import config` 前运行;插件通过项目声明或安全的静态入口识别执行,不根据业务参数变化增加迁移逻辑。
### 6.4 截图快捷键(新增,**不进项目配置**)
@@ -379,7 +379,7 @@ IntelliJ 各有原生 keymap 编辑器,用户改键位本来就该走那里
**✅ 已修**:两端统一走 `templates.directory` 取值链,消费点全部改为读访问器;
顺带把 `TemplateAssetDataService.load/cocoPath` 的 `templatesDir: String = "ok_templates"`
默认值**去掉**了 —— 留一个默认值等于给调用方留一条绕过取值链的静默通道。
-2. **`label_enum_relative_path` 插件完全没读** —— 即便项目声明了,插件也在按名字猜。
+2. **`label_enum_relative_path` 原先未读,现已作为导出路径的后备** —— 主仓 `templateAssetPanel.ts` 和子仓 `TemplateAssetToolWindowFactory.kt` 消费同一个探针字段。
3. **VS Code 侧无 jsonc 解析器** —— 这是本设计选纯 JSON 的原因之一(见 §4)。
## 9. 未决事项
diff --git a/docs/shared-core.en.md b/docs/shared-core.en.md
new file mode 100644
index 0000000..34740a0
--- /dev/null
+++ b/docs/shared-core.en.md
@@ -0,0 +1,30 @@
+# Shared Core for VS Code and JetBrains (v1.15)
+
+[简体中文](shared-core.md) | [English](shared-core.en.md)
+
+The parent repository maintains the protocol and Python runtime core. `jetbrains/` is an independent Git repository whose build tasks bundle the parent's Python scripts and JSON Schema. Both installation packages must contain **byte-identical** runtime scripts.
+
+| Responsibility | Single maintenance location | How both hosts use it |
+|---|---|---|
+| Fast task registration parsing | `python/parse_config_tasks.py` | Start Python and show the AST task list first |
+| Task parameters, global configuration, multi-account summary | `python/probe_task_schemas.py` | Read and cache the same JSON protocol; the complete probe determines the final task set |
+| Project configuration directory, account store discovery, sandbox environment variables | `python/project_runtime.py` | Shared by the probe, account gateway, and executor; account store path changes belong here |
+| Project-defined global configuration store discovery | `python/project_store.py` | The probe and executor share discovery from project declarations |
+| Account reads and writes | `python/account_store.py` | Use the project's own store; hosts do not edit account files directly |
+| Persistent execution, task visibility, parameter overrides | `python/run_executor.py`, `python/executor_runtime.py`, `python/executor_input.py`, `python/task_visibility.py` | Use the same commands and state protocol |
+| Window discovery, connection, screenshots, overlay | Scripts including `python/probe_window_config.py` | Call the same scripts |
+| Project convention file structure | `schemas/ok-script-toolkit.schema.json` | VS Code registers it directly; JetBrains reads it from JAR resources |
+
+Hosts own IDE lifecycle, controls, Python processes, caches, and user data locations. VS Code uses TypeScript/Webview and `.vscode/`; JetBrains uses Kotlin/Swing and `.idea/`. These directories are intentionally isolated. All three runtime entry points (schema probe, account gateway, executor) receive an explicit `OK_TOOLKIT_RUN_DIR` from the host. The account gateway still accepts the legacy `--run-dir` argument for existing callers.
+
+Task keys use `module::Class`. The first screen takes task membership from a fresh AST parse; cached data only supplies names and types. After a successful probe, runtime schema keys determine the final list. Probe failures must tell users that only stale cache or task names may be available; degraded results must not appear as a successful complete scan.
+
+Each host still persists its own configuration snapshots, with the same semantics: inherit current values initially, use defaults for new keys later, retain old keys, and isolate by project root. Forms and IDE storage cannot share source code across languages. When changing these rules, verify both `src/consolePanel.ts` and the child's `TaskConfigMerge.kt` / `GlobalSnapshotRules.kt`. Asset and editor UIs also remain host implementations; they are not presented as shared Python core.
+
+Before release, run parent `npm test` and `npm run package`, and child `gradlew test buildPlugin`. Check that the `python/*.py` file sets and contents match between the VSIX and JetBrains JAR. Parent version validation also checks both repositories' versions.
+
+The executor initializes project services, overlays, and device discovery through `OK.start_runtime()`, then connects and starts tasks through native `StartController.start()`. If the framework has already initiated a connection through autostart settings or command-line tasks, the adapter waits for that result instead of starting again. Startup failure or timeout never sends READY; timeout prints thread stacks for diagnosis. Missing runtime startup APIs produce an explicit error requiring an ok-script update. For direct Windows game startup, the outer timeout covers the native controller's separate window-stability and device-readiness waits; a custom task that starts the game retains a single-stage budget.
+
+On Windows, the stdin command pipe checks arrived bytes with `PeekNamedPipe` before reading and incrementally decoding. When idle, it only waits for cancellation instead of blocking in CRT pipe reads. Otherwise, NTE native-library initialization may block subsequent thread creation, leaving both an enqueued custom startup task and READY waiting for another input. Startup requires no trigger-task toggle. Split UTF-8 sequences, CRLF, multiple commands, and pipe closure retain the same protocol handling.
+
+The configuration baseline is copied into the host sandbox before project import. Both framework Config paths and project paths obtained through `get_relative_path` are redirected, including custom directories and absolute paths. Environment preparation hooks run before the first framework import. Runtime-computed directories are copied and registered before Config first opens a file; checks after import do not overwrite sandbox writes already produced. Sandbox creation/copy failures and overlap with project configuration abort startup. Containers in the project configuration dictionary are also copied before adaptation; window, interaction, capture backend, and task registration declarations retain project values. Task commands received during startup are queued and handled by the main loop after connection completes.
diff --git a/docs/shared-core.md b/docs/shared-core.md
index c218e42..870bcf7 100644
--- a/docs/shared-core.md
+++ b/docs/shared-core.md
@@ -1,5 +1,7 @@
# VS Code 与 JetBrains 的共用核心(v1.15)
+[简体中文](shared-core.md) | [English](shared-core.en.md)
+
主仓库存放协议与 Python 运行核心;`jetbrains/` 是独立 Git 子仓库,通过构建任务把主仓的 Python 脚本和 JSON Schema 打入插件。两个安装包应携带**字节相同**的运行脚本。
| 职责 | 唯一维护位置 | 两端如何使用 |
diff --git a/jetbrains b/jetbrains
index bc08ca4..caaaf73 160000
--- a/jetbrains
+++ b/jetbrains
@@ -1 +1 @@
-Subproject commit bc08ca47aede1ad533514fae105fa0f9d7e81133
+Subproject commit caaaf735d6afe69fbfb1b3093803a5be418b0fa1
diff --git a/media/boxPanel/app.js b/media/boxPanel/app.js
index 2030e49..0b636aa 100644
--- a/media/boxPanel/app.js
+++ b/media/boxPanel/app.js
@@ -18,14 +18,14 @@
const img = document.createElement('img');
img.alt = '';
img.addEventListener('error', () => img.remove());
- box.textContent = '';
- box.append(img);
+ box.querySelector('.placeholder')?.remove();
+ box.prepend(img);
img.src = url;
}
window.addEventListener('message', (event) => {
const msg = event.data;
const rows = document.getElementById('rows');
- // 框管理对标模板管理:每个 box path 一张 bbox 裁剪缩略图,分批到达逐张填充
+ // 原图上下文裁剪与红框标记,分批到达逐张填充。
if (msg.type === 'thumbs') {
(msg.items || []).forEach((item) => {
const card = cards.get(item.id);
@@ -38,31 +38,38 @@
while (rows.firstChild) rows.removeChild(rows.firstChild);
rows.className = 'asset-grid';
(msg.rows || []).forEach((row) => {
- const button = document.createElement('button');
- button.type = 'button';
- button.className = 'card asset-card';
- button.title = row.id;
+ const card = document.createElement('div');
+ card.className = 'card asset-card';
+ card.title = row.id;
const box = document.createElement('div');
box.className = 'thumb-box';
- box.textContent = '…';
+ const placeholder = document.createElement('span');
+ placeholder.className = 'placeholder';
+ placeholder.textContent = '…';
+ box.append(placeholder);
const name = document.createElement('div');
name.className = 'asset-name';
name.textContent = row.id;
const count = document.createElement('div');
count.className = 'asset-count';
count.textContent = row.label;
- button.append(box, name, count);
- cards.set(row.id, button);
- let clickTimer = 0;
- button.onclick = () => {
- window.clearTimeout(clickTimer);
- clickTimer = window.setTimeout(() => vscode.postMessage({ type: 'activate', id: row.id, clicks: 1 }), 250);
- };
- button.ondblclick = () => {
- window.clearTimeout(clickTimer);
- vscode.postMessage({ type: 'activate', id: row.id, clicks: 2 });
- };
- rows.append(button);
+ const actions = document.createElement('div');
+ actions.className = 'actions thumbnail-actions';
+ actions.append(
+ ThumbnailActions.button('+', t('insertExpression'), () => vscode.postMessage({ type: 'activate', id: row.id, clicks: 1 })),
+ ThumbnailActions.button('⧉', t('copyExpression'), () => vscode.postMessage({ type: 'activate', id: row.id, clicks: 2 })),
+ );
+ const open = ThumbnailActions.button('👁', t('viewOriginal'), () => vscode.postMessage({ type: 'open', id: row.id }));
+ open.disabled = !(row.imagePath && row.bbox);
+ actions.append(open);
+ box.append(actions);
+ card.append(box, name, count);
+ cards.set(row.id, card);
+ ThumbnailActions.bindClicks(card,
+ () => vscode.postMessage({ type: 'activate', id: row.id, clicks: 1 }),
+ () => vscode.postMessage({ type: 'activate', id: row.id, clicks: 2 }),
+ );
+ rows.append(card);
});
if (!(msg.rows || []).length) {
const empty = document.createElement('div');
diff --git a/media/boxPanel/index.html b/media/boxPanel/index.html
index 8e4b1ee..3a4a78a 100644
--- a/media/boxPanel/index.html
+++ b/media/boxPanel/index.html
@@ -16,6 +16,7 @@
__I18N_JSON__
__MODE__
-
+
+