# 开发与维护规范 适用于本插件的所有修改,包括 Gemini、Codex 和人工维护。目标是让 UX 持续改善,同时让代码职责、状态来源和验证方式保持清楚。 用户明确的当前要求优先;确需偏离本规范时,采用最小例外,在交付说明中写明原因、影响和验证。常规实现选择自行处理,不因本规范增加无必要的确认步骤。 ## 1. 修改前先定位责任 1. 查看 `git status` 和相关差异,保留已有工作;不覆盖、回退或提交他人的无关修改。 2. 阅读 [ARCHITECTURE.md](ARCHITECTURE.md),再按阅读地图打开与任务有关的专题,避免每次加载全部文档。 3. 搜索目标函数的调用方、相关状态、CSS 选择器及已有辅助函数,再确定修改位置。 4. 简短说明本次行为变化和负责它的模块。一个修复优先落在能解释问题的最小责任范围内。 UX 请求默认允许调整布局、交互和文案,不代表允许改变文件存储位置、接口协议、工作流语义、模型识别依据或用户数据。 ### 小型 UX 修改快速流程 仅调整文案、图标、颜色、间距或局部交互时:查看相关差异 → 定位负责规则 → 最小修改 → 验证受影响界面 → 本地提交。 同一任务已读过且未变化的规范不反复通读;只读相关专题,不做全仓审查,不顺手重构。 按第 7 节选择相关检查,不默认运行全部 JS/Python 测试。检查通过后,除非又改了代码或出现新问题,不重复运行。 没有改变职责、接口或持久化契约时,不更新架构文档或新增经验记录。提交说明由 AI 根据实际差异编写,无需用户代写。 ### 任务中断后的接续与快照 - 开工先检查状态和差异。工作区干净时直接继续,不制造空提交。 - 上次因额度或其他原因中断,存在属于该任务的改动时,先确认文件范围,再选择性暂存这些文件;不得使用无差别的 `git add .` 收入用户数据、凭据、临时文件或无关工作。 - 已完成且有验证记录的改动可补正式提交;尚未验证或未完成的改动可先保存 `chore(checkpoint): <实际改动摘要>` 恢复快照,提交正文明确“未完成/验证待完成”、已做检查和下一步。快照是恢复点,不代表验收通过。 - 后续修改和验证另作正式提交,不自动 amend、reset 或改写快照历史。若无法区分遗留文件归属,保留原状并说明,不猜测打包。 - 长任务按可独立验证的完整阶段提交,避免把所有 Git 收尾留到最后。测试范围内检查完成后及时提交,不为额外润色拖延快照。 - 上述快照和正式提交均只保存在本地,未经明确授权不推送。 ## 2. 模块职责与规模 - `web/main.js` 负责注册和接线;`ui_sidebar.js` 的 `createDOM` 负责外壳装配。新工具的完整实现放在自己的模块,不继续塞进这两个入口。 - 界面模块负责交互和渲染;组合、转换、校验等纯逻辑放在对应领域模块。底层模块不能反向导入上层界面,也不能读取 DOM 或选中节点来暗中决定业务行为。 - 一个模块应有可用一句话解释的主要职责。按“谁拥有状态、谁负责关闭、谁发起请求”拆分,不按随意的行号切割。 - 复用现有 `ui_lifecycle.js`、`ui_dom.js`、`translation_service.js`、`node_material_actions.js` 等接口。不要为同一行为再复制一套实现。 - 通用文件不能成为杂物箱。不要为了省一个文件,把新领域逻辑塞进 `utils`、素材详情渲染器或浏览器主对象。 - 不引入没有当前调用方的管理器、适配层、配置项、事件总线或依赖。一次性的简单逻辑可以留在其责任模块内。 **规模审查阈值:** 普通逻辑文件超过约 600 行,或单函数超过约 100 行时,新增功能前必须检查能否提取独立职责。继续扩展时,在交付说明中解释为什么仍属于同一职责。已有超大模块的小修复不要求顺手重写全文件;语言目录、数据表和样式表不按这个行数阈值拆分。不能通过空壳包装、压缩代码或碎片化文件绕过审查。 ## 3. 状态、关闭与异步 - 每份可变状态只有一个权威来源。预览、计数、序列化结果从它派生,不维护几份会互相覆盖的数据。 - 子视图状态默认留在子视图。跨界面确需保留的状态才放到 `owner`;新增共享字段时说明拥有者、初始化、重置和释放时机。 - 父子视图传容器、必要数据和明确回调,不让子模块随意修改父视图的私有 DOM 和字段。 - 新建临时窗口优先使用 `createViewScope()`。按钮、Esc、遮罩、替换窗口、父窗口关闭必须走同一个清理入口;重复关闭应安全。 - 视图创建的全局事件、观察器、定时任务、拖拽监听和临时预览都要有对应释放路径。禁止仅 `element.remove()` 就当作关闭完成。 - 拖拽中关闭也必须释放鼠标监听,恢复此前的 cursor 和 user-select。子窗口消费 Esc 时,不能顺带关闭父窗口。 - 视图读取请求使用其生命周期的 `AbortSignal`;重新查询时取消或隔离旧请求。请求返回后检查当前视图和请求身份,不能让旧结果覆盖新内容。 - 异步写入画布前捕获原 graph/node/widget/value,返回后复核身份及输入;不能在返回后重新找“当前选中节点”然后直接写。 - 已发出的保存可能在窗口关闭后完成。不要假称取消了服务端写入,也不要让完成回调重新打开或修改已关闭的界面。 提示词工坊的具体状态约定见 [frontend.md](docs/architecture/frontend.md)。不要恢复已删除的嵌入式工坊、旧导入抽屉或第二套草稿来源。 ## 4. CSS 和 UX 迭代 - 改样式前搜索同名选择器及主题、响应式覆盖,修改实际负责该属性的规则。禁止每轮都在文件末尾追加“最终修复 / override v2”覆盖包。 - 变更后删除本次取代的重复声明、失效选择器和旧布局分支;不能仅依靠更高 specificity 让旧实现暂时失效。 - 优先使用现有 `--amb-*` 设计变量。新增变量必须有实际用途和清楚的归属,不为每个常量包装一层变量。 - 不新增无解释的 `!important`。确因宿主样式或既有层叠边界需要时,在附近注释说明冲突对象与原因,并验证普通模式和受影响主题。 - 静态布局和外观放在 CSS。行内样式用于实际运行时值,例如拖动宽度、定位和数据决定的颜色,不用 JavaScript 重写整套固定样式。 - 保持插件选择器作用域,避免影响 ComfyUI 的其他按钮、弹窗和输入框。 - 添加功能时检查窄宽度、长中文、空列表、加载中、失败和禁用状态,以及焦点、键盘访问和嵌套窗口层级。 - 不为了视觉调整改变按钮的写入、覆盖、删除含义。成功提示必须来自真实成功结果,失败和取消不能显示“已应用”。 ## 5. 文案、数据与文件 - 新增固定界面文案放入 `locales.js`,同步中英文;不继续增加散落的 `lang === 'zh' ? ... : ...` 分支。 - 用户输入、文件名、模型名和元数据通过 `textContent` 或已验证的转义工具进入 DOM;不要拼进未转义的 `innerHTML`。 - 列表摘要不能当作详情。正文通过对应详情接口读取;分页、去重、空结果和取消语义必须明确。 - 路径与文件名在后端使用现有边界校验;不能只检查 `..`。前端校验不能替代后端校验。 - 修改模型、封面、附属文件或导入包前先完整校验和暂存。失败时保留旧数据,避免先删除旧文件再尝试保存新文件。 - 修改多文件发布流程要覆盖中途失败和冲突。单个 JSON 的原子写入不能冒充整组文件的事务。 - 大目录遍历、哈希和大量磁盘 I/O 使用已有工作线程/进程路径,不阻塞 aiohttp 事件循环。 - UI 适配不能偷偷迁移用户数据、修改全局配置或改变现有路由与存储格式。确需改协议时同步调用方、兼容策略和测试。 ## 6. 清理旧实现 - 替换一条路径时搜索它的导入、导出、调用、字段、事件和选择器;确认无用后一起移除。 - 不保留注释掉的大段旧代码、`EXTRACTED` 占位、无人使用的备选实现或“以后可能需要”的分支。 - 拆模块后检查移动函数引用的闭包变量、导入、回调参数和返回值。语法通过不代表按钮点击不会出现未定义变量。 - 不保留两个相互覆盖的 `onclick` 或两条完成同一请求的路径;让所有入口调用同一个实现。 - 不用空 `catch`、伪造成功值或任意 optional chaining 掩盖结构错误。可选宿主能力才允许局部降级,并给出准确结果。 ## 7. 按风险验证 从插件根目录运行相关检查。选择与变化相称的验证,不为纯文案、文档或低风险样式改动制造镜像测试。 | 修改范围 | 至少验证 | | --- | --- | | 导入、导出、模块拆分 | JS 语法、模块链接,以及受影响按钮的真实执行路径 | | 工坊状态与生命周期 | `node --experimental-vm-modules tests/prompt_ui_lifecycle.mjs` | | 词卡读取、分页 | `node tests/prompt_material_source.mjs` | | 翻译桥接 | `node tests/translation_service_contracts.mjs`,异步节点写入另跑工坊生命周期测试 | | 素材应用、笔记隔离 | `node --experimental-vm-modules tests/material_workspace_flow.mjs` | | 素材提示词协议、配方筛选、拖拽清理 | `node --experimental-vm-modules tests/studio_contracts.mjs` | | CSS、布局、交互 | 实际浏览器验证受影响状态;涉及宿主行为时验证 ComfyUI | | 文件修改、导入、存储 | 对应 Python 测试,至少覆盖成功、冲突和中途失败保留旧数据 | | 仅文档 | 检查链接、命令、实际代码一致性和 Git 差异 | - 模拟测试尽量加载实际模块,只替换外部系统边界;不要把待验证的业务函数也 mock 成成功。 - 修复故障时,优先补充能复现原故障的行为测试。不能只通过源码字符串“存在某段代码”来证明修复。 - UX 明确替换旧交互时,更新测试到新的用户流程,并保留原本要保护的行为;不要仅删除失败断言或重新塞回废弃功能。 - 新增应随仓库交付的回归测试要检查 `.gitignore`,确认确实进入版本控制。 - 历史本地 Python 测试可能不在 Git 中。使用合适环境运行相关测试,例如 `python -m unittest discover -s tests -p 'test_*.py'`,核对实际发现的数量;零项测试不算通过。 - 无法运行真实宿主、网络服务或完整测试时,准确说明缺口;不要将模拟画布、语法检查或已有通过数量称为本轮宿主验证。 ## 8. 文档与交付 - 架构文档只记录职责、数据流、契约和关键约束。颜色、像素值及审美描述以 CSS 为准,不每次 UX 更新都往架构入口追加长篇设计说明。 - 改动架构时更新最窄的相关专题。修改规范时以本文件为唯一正文,`GEMINI.md` 只保留阅读入口,避免两套要求漂移。 - 完成前审查差异、死代码、临时文件和空白错误;保留现有文件编码及换行风格。 - 验证后按仓库约定形成一个连贯的本地提交,只包含本任务文件;没有明确授权不推送 GitHub。 - 交付说明包含:改了什么与原因、验证结果与限制、剩余问题、本地提交。仅在触发规模阈值或规则例外时额外解释取舍。 **交付自查:** 新职责放对位置了吗?是否只有一个状态来源?每条关闭路径会释放资源吗?迟到请求会写错对象吗?旧代码和旧 CSS 清掉了吗?新文案已本地化吗?用户文件失败时还在吗?测试验证了实际行为吗?