diff --git a/.blueprint/CONVENTIONS.md b/.blueprint/CONVENTIONS.md index 5d0d728..cd2fc78 100644 --- a/.blueprint/CONVENTIONS.md +++ b/.blueprint/CONVENTIONS.md @@ -1,6 +1,6 @@ --- -version: 1.6.0 -updated: 2026-04-19 +version: 1.7.0 +updated: 2026-05-06 source: dev-manager-tauri --- @@ -653,6 +653,66 @@ mod tests { --- +## 前端代码可测试性规范 + +> 本规范适用于**新增** TypeScript/React 代码,存量代码不强制回填。 + +### 测试文件位置 + +前端测试文件与源文件同目录,命名约定:`.test.ts(x)`。 + +``` +src/components/MyComponent.tsx +src/components/MyComponent.test.tsx ← 同目录、同名 + .test 后缀 + +src/lib/utils.ts +src/lib/utils.test.ts ← vitest 自动发现 +``` + +### 测试框架 + +使用 vitest + `describe`/`it`/`expect`,配置见项目根 `vitest.config.ts`。 + +### 测试要求 + +| 代码类型 | 测试要求 | +|---------|---------| +| 纯逻辑函数(数据处理、格式化、解析、校验) | M 级任务卡强制附带测试,覆盖主路径 + 空/边界 | +| React 组件(含状态管理、数据流) | M 级任务卡建议附带测试,至少覆盖关键交互路径 | +| 纯样式组件 / Tauri IPC 薄包装层 | 无需测试 | + +### 任务卡 acceptance 模板补充 + +含前端纯逻辑的 M 级任务卡,acceptance 须包含: + +``` +- [ ] 附带 vitest 测试,覆盖主路径 + 空数据边界 +- [ ] npx vitest run 全绿 +``` + +### 测试写法模板 + +```typescript +import { describe, it, expect } from "vitest"; +import { myFunction } from "./utils"; + +describe("myFunction", () => { + it("正常路径", () => { + expect(myFunction("input")).toBe("expected"); + }); + + it("空输入不报错", () => { + expect(myFunction("")).toBeNull(); + }); + + it("非法输入返回安全默认值", () => { + expect(myFunction("invalid")).toBeNull(); + }); +}); +``` + +--- + ## 项目私有规则(rules.md) 每个项目可以在 `.blueprint/rules.md` 中维护**仅对本项目生效**的推荐规则,格式与全局规则库完全相同。 diff --git a/.blueprint/usage.json b/.blueprint/usage.json index cd9ec90..4544d8b 100644 --- a/.blueprint/usage.json +++ b/.blueprint/usage.json @@ -3649,6 +3649,609 @@ "todo": 1, "total": 164 } + }, + { + "at": "2026-04-30T01:01:42Z", + "blocked_reasons": [], + "conventions_version": "1.6.0", + "delta": { + "newly_blocked": [], + "newly_done": [], + "unblocked": [] + }, + "iteration": 1, + "modules": { + "blocked": 0, + "concept": 0, + "done": 47, + "in_progress": 1, + "planned": 0, + "stalled": [ + "flywheel-intelligence" + ], + "total": 48 + }, + "task_ids": { + "blocked": [], + "done": [ + "api-keys/API 密钥 CRUD 与安全展示", + "auto-update/Capabilities 权限配置", + "auto-update/下载 & 安装", + "auto-update/更新检测", + "auto-update/自动检查更新", + "auto-update/错误提示", + "blueprint-buff/BlueprintView 跨项目切换", + "blueprint-buff/Buff 生命周期 Rust 命令", + "blueprint-buff/blueprint_buffs 数据表", + "blueprint-buff/git watcher + 任务匹配写回 + 飞轮快照", + "blueprint-buff/前端 Buff 管理 UI", + "blueprint-buff/前端实时刷新", + "blueprint-feedback/归档 command", + "blueprint-feedback/归档候选展示", + "blueprint-feedback/梦核分析入口(蓝图弹窗)", + "blueprint-feedback/梦核提示词增加停滞模块数据", + "blueprint-flywheel/get_flywheel_stats command", + "blueprint-flywheel/get_flywheel_stats 支持迭代感知", + "blueprint-flywheel/usage.json 埋点写入", + "blueprint-flywheel/梦核提示词生成 command", + "blueprint-flywheel/飞轮健康面板", + "blueprint-governance/CLAUDE.md 模板定义", + "blueprint-governance/CONVENTIONS.md 版本化", + "blueprint-governance/GovernancePanel 规则编辑器 UI", + "blueprint-governance/get_blueprint_status command", + "blueprint-governance/sync/梦核/summary 切换为 effective 内容", + "blueprint-governance/sync_blueprint_rules command", + "blueprint-governance/批量同步所有项目规则", + "blueprint-governance/用户版 CONVENTIONS 存储层初始化", + "blueprint-governance/用户版 CONVENTIONS 读写 command", + "blueprint-onboarding/generate_blueprint_prompt command", + "blueprint-onboarding/蓝图操作弹窗", + "blueprint-onboarding/项目列表蓝图状态徽章", + "blueprint-reader/合并返回完整蓝图数据", + "blueprint-reader/读取 manifest.yaml", + "blueprint-reader/读取 modules/*.md", + "blueprint-view/.blueprint/ 数据结构设计", + "blueprint-view/React Flow 节点图渲染", + "blueprint-view/blocked 状态支持", + "blueprint-view/下一步汇总面板", + "blueprint-view/任务卡复制派发", + "blueprint-view/批量执行提示词入口", + "blueprint-view/智能连线路由", + "blueprint-view/模块详情面板", + "blueprint-view/统计汇总条", + "blueprint-view/蓝图治理面板", + "blueprint-view/蓝图读取 Command", + "blueprint-view/边高亮与模块聚焦", + "blueprint-view/顶部状态行扩展", + "blueprint-view/项目卡片蓝图入口", + "cicd-workflow/Actions 运行历史", + "cicd-workflow/CI/CD 配置 CRUD", + "cicd-workflow/Tauri OSS 分发模板", + "cicd-workflow/Web SSH 部署模板", + "cicd-workflow/Workflow 文件生成", + "claude-autonomy-config/Beast 全局状态读取与展示", + "cloud-db-instances/云数据库实例信息管理", + "cloud-docker-apps/Docker 应用列表与状态管理", + "cloud-products/DB 迁移:cloud_products 表", + "cloud-products/Dashboard 接入:云产品标签页", + "cloud-products/Rust CRUD:cloud_products.rs", + "cloud-products/前端 Panel:CloudProductsPanel.tsx", + "cloud-products/接线:mod.rs + lib.rs + commands.ts", + "deploy-info/项目部署信息记录面板", + "devtools-scan/WSL 工具扫描", + "devtools-scan/Windows 工具扫描", + "devtools-scan/工具信息持久化", + "flywheel-intelligence/MCP Server 支持 SSE 传输", + "flywheel-intelligence/复盘笔记覆盖率可见性", + "flywheel-intelligence/独立项目自动创建产品组", + "flywheel-intelligence/补测试:飞轮存量函数安全网", + "flywheel-intelligence/阶段一:复盘笔记接入梦核飞轮", + "flywheel-intelligence/阶段二:usage.json 扩展采集维度", + "git-ops/上游状态检测", + "git-ops/分支管理", + "git-ops/基础操作", + "github-auth/OAuth Device Flow", + "github-auth/Token 管理", + "github-publish/GitHub 仓库创建与推送", + "health-center/T1 · Backend 健康检查聚合命令", + "health-center/T2 · 质量指标聚合", + "health-center/T3 · 前端健康中心页面", + "health-center/T4 · 扩展 MCP get_diagnostics", + "host-apps/宿主机应用清单与快启", + "mcp-config-inject/加入产品组时注入配置", + "mcp-config-inject/端口变更时重新注入所有配置", + "mcp-config-inject/退出产品组时清除配置", + "mcp-server/MCP 端口可配置(Rust 侧)", + "mcp-server/启动时绑定 HTTP 端口", + "mcp-server/实现 MCP JSON-RPC 基础协议", + "mcp-server/实现产品组上下文工具", + "product-group-mcp/产品组详情显示 MCP 注入状态", + "product-group-mcp/设置页添加 MCP 端口配置", + "project-dashboard/分组画布", + "project-dashboard/项目卡片列表", + "project-dashboard/项目发现面板", + "project-dashboard/项目快捷操作", + "project-env-scan/环境信息持久化", + "project-env-scan/项目环境检测", + "project-mentor/T1 · 后端聚合 command(MentorContext)", + "project-mentor/T10 · 启动健康扫描 + 前端 Alert Banner", + "project-mentor/T11 · 项目历史快照", + "project-mentor/T2 · MCP 项目导师查询接口", + "project-mentor/T3 · 前端导师面板", + "project-mentor/T4 · 炼境自指接入", + "project-mentor/T5 · project_notes 数据层 + 后端命令", + "project-mentor/T6 · MCP append_project_note 工具", + "project-mentor/T7 · MentorPanel 展示 AI 笔记", + "project-mentor/T8 · 后端全组巡检命令", + "project-mentor/T9 · 前端全组巡检按钮", + "project-mgmt/子文件夹扫描", + "project-mgmt/批量导入项目", + "project-mgmt/项目 CRUD", + "project-mgmt/项目档案(Profile)", + "project-templates/P1+P3 模板扩充(React 生态全覆盖)", + "project-templates/从模板创建项目", + "project-templates/内置模板种植", + "project-templates/模板 CRUD", + "project-tools/工具 CRUD", + "project-tools/工具启动", + "repo-registry/仓库导入", + "repo-registry/仓库挂载", + "repo-registry/仓库注册表管理", + "runtime-diagnostics/T1 · SQLite runtime_logs 表", + "runtime-diagnostics/T2 · 替换 eprintln! 为结构化日志", + "runtime-diagnostics/T3 · MCP Server 新增 get_diagnostics 工具", + "runtime-diagnostics/T4 · 注入失败结果返回前端", + "runtime-diagnostics/T5 · 设置页 MCP 真实健康检查", + "server-registry/服务器 CRUD 与项目关联", + "server-software/服务器软件扫描与展示", + "service-config/服务配置 CRUD 与环境分组", + "settings-page/WSL 发行版选择", + "settings-page/关于 & 更新", + "settings-page/终端配置", + "settings-page/编辑器检测", + "shell-launch/打开终端", + "shell-launch/打开编辑器", + "source-library/源码库分类管理与项目详情", + "sqlite-db/数据库迁移", + "sqlite-db/连接池初始化", + "ssh-config-sync/SSH Config 写入与同步", + "tags-groups/分组管理", + "tags-groups/标签管理", + "tray-service/关闭窗口最小化到托盘", + "tray-service/系统托盘图标与菜单", + "tray-service/集成 tauri-plugin-single-instance", + "user-project-todos/前端:备忘清单 UI 组件", + "user-project-todos/数据层:user_project_todos 表 + Rust commands", + "v2rayn-import/当前节点读取", + "v2rayn-import/数据库路径检测", + "v2rayn-import/节点列表扫描", + "vscode-remote/VS Code Remote SSH 一键连接", + "workspace-mgmt/空间 CRUD", + "workspace-mgmt/空间级设置", + "workspace-mgmt/部署命令管理", + "wsl-proxy/代理一致性测试", + "wsl-proxy/代理同步", + "wsl-proxy/代理清除", + "wsl-proxy/代理状态检测" + ] + }, + "tasks": { + "avg_rounds_M": null, + "blocked": 0, + "complexity_dist": { + "L": 2, + "M": 55, + "S": 47 + }, + "dispatched": 0, + "done": 159, + "in_progress": 0, + "rework_count": 0, + "todo": 1, + "total": 164 + } + }, + { + "at": "2026-05-03T04:34:50Z", + "blocked_reasons": [], + "conventions_version": "1.6.0", + "delta": { + "newly_blocked": [], + "newly_done": [], + "unblocked": [] + }, + "iteration": 1, + "modules": { + "blocked": 0, + "concept": 0, + "done": 47, + "in_progress": 1, + "planned": 0, + "stalled": [ + "flywheel-intelligence" + ], + "total": 48 + }, + "task_ids": { + "blocked": [], + "done": [ + "api-keys/API 密钥 CRUD 与安全展示", + "auto-update/Capabilities 权限配置", + "auto-update/下载 & 安装", + "auto-update/更新检测", + "auto-update/自动检查更新", + "auto-update/错误提示", + "blueprint-buff/BlueprintView 跨项目切换", + "blueprint-buff/Buff 生命周期 Rust 命令", + "blueprint-buff/blueprint_buffs 数据表", + "blueprint-buff/git watcher + 任务匹配写回 + 飞轮快照", + "blueprint-buff/前端 Buff 管理 UI", + "blueprint-buff/前端实时刷新", + "blueprint-feedback/归档 command", + "blueprint-feedback/归档候选展示", + "blueprint-feedback/梦核分析入口(蓝图弹窗)", + "blueprint-feedback/梦核提示词增加停滞模块数据", + "blueprint-flywheel/get_flywheel_stats command", + "blueprint-flywheel/get_flywheel_stats 支持迭代感知", + "blueprint-flywheel/usage.json 埋点写入", + "blueprint-flywheel/梦核提示词生成 command", + "blueprint-flywheel/飞轮健康面板", + "blueprint-governance/CLAUDE.md 模板定义", + "blueprint-governance/CONVENTIONS.md 版本化", + "blueprint-governance/GovernancePanel 规则编辑器 UI", + "blueprint-governance/get_blueprint_status command", + "blueprint-governance/sync/梦核/summary 切换为 effective 内容", + "blueprint-governance/sync_blueprint_rules command", + "blueprint-governance/批量同步所有项目规则", + "blueprint-governance/用户版 CONVENTIONS 存储层初始化", + "blueprint-governance/用户版 CONVENTIONS 读写 command", + "blueprint-onboarding/generate_blueprint_prompt command", + "blueprint-onboarding/蓝图操作弹窗", + "blueprint-onboarding/项目列表蓝图状态徽章", + "blueprint-reader/合并返回完整蓝图数据", + "blueprint-reader/读取 manifest.yaml", + "blueprint-reader/读取 modules/*.md", + "blueprint-view/.blueprint/ 数据结构设计", + "blueprint-view/React Flow 节点图渲染", + "blueprint-view/blocked 状态支持", + "blueprint-view/下一步汇总面板", + "blueprint-view/任务卡复制派发", + "blueprint-view/批量执行提示词入口", + "blueprint-view/智能连线路由", + "blueprint-view/模块详情面板", + "blueprint-view/统计汇总条", + "blueprint-view/蓝图治理面板", + "blueprint-view/蓝图读取 Command", + "blueprint-view/边高亮与模块聚焦", + "blueprint-view/顶部状态行扩展", + "blueprint-view/项目卡片蓝图入口", + "cicd-workflow/Actions 运行历史", + "cicd-workflow/CI/CD 配置 CRUD", + "cicd-workflow/Tauri OSS 分发模板", + "cicd-workflow/Web SSH 部署模板", + "cicd-workflow/Workflow 文件生成", + "claude-autonomy-config/Beast 全局状态读取与展示", + "cloud-db-instances/云数据库实例信息管理", + "cloud-docker-apps/Docker 应用列表与状态管理", + "cloud-products/DB 迁移:cloud_products 表", + "cloud-products/Dashboard 接入:云产品标签页", + "cloud-products/Rust CRUD:cloud_products.rs", + "cloud-products/前端 Panel:CloudProductsPanel.tsx", + "cloud-products/接线:mod.rs + lib.rs + commands.ts", + "deploy-info/项目部署信息记录面板", + "devtools-scan/WSL 工具扫描", + "devtools-scan/Windows 工具扫描", + "devtools-scan/工具信息持久化", + "flywheel-intelligence/MCP Server 支持 SSE 传输", + "flywheel-intelligence/复盘笔记覆盖率可见性", + "flywheel-intelligence/独立项目自动创建产品组", + "flywheel-intelligence/补测试:飞轮存量函数安全网", + "flywheel-intelligence/阶段一:复盘笔记接入梦核飞轮", + "flywheel-intelligence/阶段二:usage.json 扩展采集维度", + "git-ops/上游状态检测", + "git-ops/分支管理", + "git-ops/基础操作", + "github-auth/OAuth Device Flow", + "github-auth/Token 管理", + "github-publish/GitHub 仓库创建与推送", + "health-center/T1 · Backend 健康检查聚合命令", + "health-center/T2 · 质量指标聚合", + "health-center/T3 · 前端健康中心页面", + "health-center/T4 · 扩展 MCP get_diagnostics", + "host-apps/宿主机应用清单与快启", + "mcp-config-inject/加入产品组时注入配置", + "mcp-config-inject/端口变更时重新注入所有配置", + "mcp-config-inject/退出产品组时清除配置", + "mcp-server/MCP 端口可配置(Rust 侧)", + "mcp-server/启动时绑定 HTTP 端口", + "mcp-server/实现 MCP JSON-RPC 基础协议", + "mcp-server/实现产品组上下文工具", + "product-group-mcp/产品组详情显示 MCP 注入状态", + "product-group-mcp/设置页添加 MCP 端口配置", + "project-dashboard/分组画布", + "project-dashboard/项目卡片列表", + "project-dashboard/项目发现面板", + "project-dashboard/项目快捷操作", + "project-env-scan/环境信息持久化", + "project-env-scan/项目环境检测", + "project-mentor/T1 · 后端聚合 command(MentorContext)", + "project-mentor/T10 · 启动健康扫描 + 前端 Alert Banner", + "project-mentor/T11 · 项目历史快照", + "project-mentor/T2 · MCP 项目导师查询接口", + "project-mentor/T3 · 前端导师面板", + "project-mentor/T4 · 炼境自指接入", + "project-mentor/T5 · project_notes 数据层 + 后端命令", + "project-mentor/T6 · MCP append_project_note 工具", + "project-mentor/T7 · MentorPanel 展示 AI 笔记", + "project-mentor/T8 · 后端全组巡检命令", + "project-mentor/T9 · 前端全组巡检按钮", + "project-mgmt/子文件夹扫描", + "project-mgmt/批量导入项目", + "project-mgmt/项目 CRUD", + "project-mgmt/项目档案(Profile)", + "project-templates/P1+P3 模板扩充(React 生态全覆盖)", + "project-templates/从模板创建项目", + "project-templates/内置模板种植", + "project-templates/模板 CRUD", + "project-tools/工具 CRUD", + "project-tools/工具启动", + "repo-registry/仓库导入", + "repo-registry/仓库挂载", + "repo-registry/仓库注册表管理", + "runtime-diagnostics/T1 · SQLite runtime_logs 表", + "runtime-diagnostics/T2 · 替换 eprintln! 为结构化日志", + "runtime-diagnostics/T3 · MCP Server 新增 get_diagnostics 工具", + "runtime-diagnostics/T4 · 注入失败结果返回前端", + "runtime-diagnostics/T5 · 设置页 MCP 真实健康检查", + "server-registry/服务器 CRUD 与项目关联", + "server-software/服务器软件扫描与展示", + "service-config/服务配置 CRUD 与环境分组", + "settings-page/WSL 发行版选择", + "settings-page/关于 & 更新", + "settings-page/终端配置", + "settings-page/编辑器检测", + "shell-launch/打开终端", + "shell-launch/打开编辑器", + "source-library/源码库分类管理与项目详情", + "sqlite-db/数据库迁移", + "sqlite-db/连接池初始化", + "ssh-config-sync/SSH Config 写入与同步", + "tags-groups/分组管理", + "tags-groups/标签管理", + "tray-service/关闭窗口最小化到托盘", + "tray-service/系统托盘图标与菜单", + "tray-service/集成 tauri-plugin-single-instance", + "user-project-todos/前端:备忘清单 UI 组件", + "user-project-todos/数据层:user_project_todos 表 + Rust commands", + "v2rayn-import/当前节点读取", + "v2rayn-import/数据库路径检测", + "v2rayn-import/节点列表扫描", + "vscode-remote/VS Code Remote SSH 一键连接", + "workspace-mgmt/空间 CRUD", + "workspace-mgmt/空间级设置", + "workspace-mgmt/部署命令管理", + "wsl-proxy/代理一致性测试", + "wsl-proxy/代理同步", + "wsl-proxy/代理清除", + "wsl-proxy/代理状态检测" + ] + }, + "tasks": { + "avg_rounds_M": null, + "blocked": 0, + "complexity_dist": { + "L": 2, + "M": 55, + "S": 47 + }, + "dispatched": 0, + "done": 159, + "in_progress": 0, + "rework_count": 0, + "todo": 1, + "total": 164 + } + }, + { + "at": "2026-05-05T04:15:23Z", + "blocked_reasons": [], + "conventions_version": "1.6.0", + "delta": { + "newly_blocked": [], + "newly_done": [], + "unblocked": [] + }, + "iteration": 1, + "modules": { + "blocked": 0, + "concept": 0, + "done": 47, + "in_progress": 1, + "planned": 0, + "stalled": [ + "flywheel-intelligence" + ], + "total": 48 + }, + "task_ids": { + "blocked": [], + "done": [ + "api-keys/API 密钥 CRUD 与安全展示", + "auto-update/Capabilities 权限配置", + "auto-update/下载 & 安装", + "auto-update/更新检测", + "auto-update/自动检查更新", + "auto-update/错误提示", + "blueprint-buff/BlueprintView 跨项目切换", + "blueprint-buff/Buff 生命周期 Rust 命令", + "blueprint-buff/blueprint_buffs 数据表", + "blueprint-buff/git watcher + 任务匹配写回 + 飞轮快照", + "blueprint-buff/前端 Buff 管理 UI", + "blueprint-buff/前端实时刷新", + "blueprint-feedback/归档 command", + "blueprint-feedback/归档候选展示", + "blueprint-feedback/梦核分析入口(蓝图弹窗)", + "blueprint-feedback/梦核提示词增加停滞模块数据", + "blueprint-flywheel/get_flywheel_stats command", + "blueprint-flywheel/get_flywheel_stats 支持迭代感知", + "blueprint-flywheel/usage.json 埋点写入", + "blueprint-flywheel/梦核提示词生成 command", + "blueprint-flywheel/飞轮健康面板", + "blueprint-governance/CLAUDE.md 模板定义", + "blueprint-governance/CONVENTIONS.md 版本化", + "blueprint-governance/GovernancePanel 规则编辑器 UI", + "blueprint-governance/get_blueprint_status command", + "blueprint-governance/sync/梦核/summary 切换为 effective 内容", + "blueprint-governance/sync_blueprint_rules command", + "blueprint-governance/批量同步所有项目规则", + "blueprint-governance/用户版 CONVENTIONS 存储层初始化", + "blueprint-governance/用户版 CONVENTIONS 读写 command", + "blueprint-onboarding/generate_blueprint_prompt command", + "blueprint-onboarding/蓝图操作弹窗", + "blueprint-onboarding/项目列表蓝图状态徽章", + "blueprint-reader/合并返回完整蓝图数据", + "blueprint-reader/读取 manifest.yaml", + "blueprint-reader/读取 modules/*.md", + "blueprint-view/.blueprint/ 数据结构设计", + "blueprint-view/React Flow 节点图渲染", + "blueprint-view/blocked 状态支持", + "blueprint-view/下一步汇总面板", + "blueprint-view/任务卡复制派发", + "blueprint-view/批量执行提示词入口", + "blueprint-view/智能连线路由", + "blueprint-view/模块详情面板", + "blueprint-view/统计汇总条", + "blueprint-view/蓝图治理面板", + "blueprint-view/蓝图读取 Command", + "blueprint-view/边高亮与模块聚焦", + "blueprint-view/顶部状态行扩展", + "blueprint-view/项目卡片蓝图入口", + "cicd-workflow/Actions 运行历史", + "cicd-workflow/CI/CD 配置 CRUD", + "cicd-workflow/Tauri OSS 分发模板", + "cicd-workflow/Web SSH 部署模板", + "cicd-workflow/Workflow 文件生成", + "claude-autonomy-config/Beast 全局状态读取与展示", + "cloud-db-instances/云数据库实例信息管理", + "cloud-docker-apps/Docker 应用列表与状态管理", + "cloud-products/DB 迁移:cloud_products 表", + "cloud-products/Dashboard 接入:云产品标签页", + "cloud-products/Rust CRUD:cloud_products.rs", + "cloud-products/前端 Panel:CloudProductsPanel.tsx", + "cloud-products/接线:mod.rs + lib.rs + commands.ts", + "deploy-info/项目部署信息记录面板", + "devtools-scan/WSL 工具扫描", + "devtools-scan/Windows 工具扫描", + "devtools-scan/工具信息持久化", + "flywheel-intelligence/MCP Server 支持 SSE 传输", + "flywheel-intelligence/复盘笔记覆盖率可见性", + "flywheel-intelligence/独立项目自动创建产品组", + "flywheel-intelligence/补测试:飞轮存量函数安全网", + "flywheel-intelligence/阶段一:复盘笔记接入梦核飞轮", + "flywheel-intelligence/阶段二:usage.json 扩展采集维度", + "git-ops/上游状态检测", + "git-ops/分支管理", + "git-ops/基础操作", + "github-auth/OAuth Device Flow", + "github-auth/Token 管理", + "github-publish/GitHub 仓库创建与推送", + "health-center/T1 · Backend 健康检查聚合命令", + "health-center/T2 · 质量指标聚合", + "health-center/T3 · 前端健康中心页面", + "health-center/T4 · 扩展 MCP get_diagnostics", + "host-apps/宿主机应用清单与快启", + "mcp-config-inject/加入产品组时注入配置", + "mcp-config-inject/端口变更时重新注入所有配置", + "mcp-config-inject/退出产品组时清除配置", + "mcp-server/MCP 端口可配置(Rust 侧)", + "mcp-server/启动时绑定 HTTP 端口", + "mcp-server/实现 MCP JSON-RPC 基础协议", + "mcp-server/实现产品组上下文工具", + "product-group-mcp/产品组详情显示 MCP 注入状态", + "product-group-mcp/设置页添加 MCP 端口配置", + "project-dashboard/分组画布", + "project-dashboard/项目卡片列表", + "project-dashboard/项目发现面板", + "project-dashboard/项目快捷操作", + "project-env-scan/环境信息持久化", + "project-env-scan/项目环境检测", + "project-mentor/T1 · 后端聚合 command(MentorContext)", + "project-mentor/T10 · 启动健康扫描 + 前端 Alert Banner", + "project-mentor/T11 · 项目历史快照", + "project-mentor/T2 · MCP 项目导师查询接口", + "project-mentor/T3 · 前端导师面板", + "project-mentor/T4 · 炼境自指接入", + "project-mentor/T5 · project_notes 数据层 + 后端命令", + "project-mentor/T6 · MCP append_project_note 工具", + "project-mentor/T7 · MentorPanel 展示 AI 笔记", + "project-mentor/T8 · 后端全组巡检命令", + "project-mentor/T9 · 前端全组巡检按钮", + "project-mgmt/子文件夹扫描", + "project-mgmt/批量导入项目", + "project-mgmt/项目 CRUD", + "project-mgmt/项目档案(Profile)", + "project-templates/P1+P3 模板扩充(React 生态全覆盖)", + "project-templates/从模板创建项目", + "project-templates/内置模板种植", + "project-templates/模板 CRUD", + "project-tools/工具 CRUD", + "project-tools/工具启动", + "repo-registry/仓库导入", + "repo-registry/仓库挂载", + "repo-registry/仓库注册表管理", + "runtime-diagnostics/T1 · SQLite runtime_logs 表", + "runtime-diagnostics/T2 · 替换 eprintln! 为结构化日志", + "runtime-diagnostics/T3 · MCP Server 新增 get_diagnostics 工具", + "runtime-diagnostics/T4 · 注入失败结果返回前端", + "runtime-diagnostics/T5 · 设置页 MCP 真实健康检查", + "server-registry/服务器 CRUD 与项目关联", + "server-software/服务器软件扫描与展示", + "service-config/服务配置 CRUD 与环境分组", + "settings-page/WSL 发行版选择", + "settings-page/关于 & 更新", + "settings-page/终端配置", + "settings-page/编辑器检测", + "shell-launch/打开终端", + "shell-launch/打开编辑器", + "source-library/源码库分类管理与项目详情", + "sqlite-db/数据库迁移", + "sqlite-db/连接池初始化", + "ssh-config-sync/SSH Config 写入与同步", + "tags-groups/分组管理", + "tags-groups/标签管理", + "tray-service/关闭窗口最小化到托盘", + "tray-service/系统托盘图标与菜单", + "tray-service/集成 tauri-plugin-single-instance", + "user-project-todos/前端:备忘清单 UI 组件", + "user-project-todos/数据层:user_project_todos 表 + Rust commands", + "v2rayn-import/当前节点读取", + "v2rayn-import/数据库路径检测", + "v2rayn-import/节点列表扫描", + "vscode-remote/VS Code Remote SSH 一键连接", + "workspace-mgmt/空间 CRUD", + "workspace-mgmt/空间级设置", + "workspace-mgmt/部署命令管理", + "wsl-proxy/代理一致性测试", + "wsl-proxy/代理同步", + "wsl-proxy/代理清除", + "wsl-proxy/代理状态检测" + ] + }, + "tasks": { + "avg_rounds_M": null, + "blocked": 0, + "complexity_dist": { + "L": 2, + "M": 55, + "S": 47 + }, + "dispatched": 0, + "done": 159, + "in_progress": 0, + "rework_count": 0, + "todo": 1, + "total": 164 + } } ] } \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8514853..3cf249b 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ src-tauri/target/ # 编辑器 .vscode/ .idea/ +.qwen/ *.suo *.user diff --git a/package.json b/package.json index 5f77706..6c0f234 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "dev": "vite", "build": "tsc && vite build", "preview": "vite preview", + "test": "vitest run", + "test:watch": "vitest", "tauri": "tauri" }, "dependencies": { @@ -34,6 +36,7 @@ "@vitejs/plugin-react": "^4.6.0", "tailwindcss": "^4.2.2", "typescript": "~5.8.3", - "vite": "^7.0.4" + "vite": "^7.0.4", + "vitest": "^4.1.5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index caaca5f..dc88a4b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,6 +78,9 @@ importers: vite: specifier: ^7.0.4 version: 7.3.1(jiti@2.6.1)(lightningcss@1.32.0) + vitest: + specifier: ^4.1.5 + version: 4.1.5(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)) packages: @@ -373,66 +376,79 @@ packages: resolution: {integrity: sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.60.0': resolution: {integrity: sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.60.0': resolution: {integrity: sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.60.0': resolution: {integrity: sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.60.0': resolution: {integrity: sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.60.0': resolution: {integrity: sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.60.0': resolution: {integrity: sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.60.0': resolution: {integrity: sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.60.0': resolution: {integrity: sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.60.0': resolution: {integrity: sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.60.0': resolution: {integrity: sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.60.0': resolution: {integrity: sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.60.0': resolution: {integrity: sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.60.0': resolution: {integrity: sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==} @@ -464,6 +480,9 @@ packages: cpu: [x64] os: [win32] + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tailwindcss/node@4.2.2': resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} @@ -502,24 +521,28 @@ packages: engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.2.2': resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.2.2': resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.2.2': resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.2.2': resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} @@ -593,30 +616,35 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-arm64-musl@2.10.1': resolution: {integrity: sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@tauri-apps/cli-linux-riscv64-gnu@2.10.1': resolution: {integrity: sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-x64-gnu@2.10.1': resolution: {integrity: sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-x64-musl@2.10.1': resolution: {integrity: sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@tauri-apps/cli-win32-arm64-msvc@2.10.1': resolution: {integrity: sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==} @@ -671,6 +699,9 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/d3-color@3.1.3': resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} @@ -692,6 +723,9 @@ packages: '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -730,6 +764,35 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/expect@4.1.5': + resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} + + '@vitest/mocker@4.1.5': + resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.5': + resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} + + '@vitest/runner@4.1.5': + resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} + + '@vitest/snapshot@4.1.5': + resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} + + '@vitest/spy@4.1.5': + resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} + + '@vitest/utils@4.1.5': + resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} + '@xyflow/react@12.10.2': resolution: {integrity: sha512-CgIi6HwlcHXwlkTpr0fxLv/0sRVNZ8IdwKLzzeCscaYBwpvfcH1QFOCeaTCuEn1FQEs/B8CjnTSjhs8udgmBgQ==} peerDependencies: @@ -739,6 +802,10 @@ packages: '@xyflow/system@0.0.76': resolution: {integrity: sha512-hvwvnRS1B3REwVDlWexsq7YQaPZeG3/mKo1jv38UmnpWmxihp14bW6VtEOuHEwJX2FvzFw8k77LyKSk/wiZVNA==} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -758,6 +825,10 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -855,6 +926,9 @@ packages: resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} engines: {node: '>=10.13.0'} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + esbuild@0.27.4: resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==} engines: {node: '>=18'} @@ -871,6 +945,13 @@ packages: estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -975,24 +1056,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} @@ -1162,9 +1247,15 @@ packages: node-releases@2.0.36: resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1226,6 +1317,9 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -1233,6 +1327,12 @@ packages: space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} + stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} @@ -1249,10 +1349,21 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.1.2: + resolution: {integrity: sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==} + engines: {node: '>=18'} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -1342,6 +1453,52 @@ packages: yaml: optional: true + vitest@4.1.5: + resolution: {integrity: sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.5 + '@vitest/browser-preview': 4.1.5 + '@vitest/browser-webdriverio': 4.1.5 + '@vitest/coverage-istanbul': 4.1.5 + '@vitest/coverage-v8': 4.1.5 + '@vitest/ui': 4.1.5 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -1669,6 +1826,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.60.0': optional: true + '@standard-schema/spec@1.1.0': {} + '@tailwindcss/node@4.2.2': dependencies: '@jridgewell/remapping': 2.3.5 @@ -1843,6 +2002,11 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + '@types/d3-color@3.1.3': {} '@types/d3-drag@3.0.7': @@ -1868,6 +2032,8 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/deep-eql@4.0.2': {} + '@types/estree-jsx@1.0.5': dependencies: '@types/estree': 1.0.8 @@ -1910,6 +2076,47 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/expect@4.1.5': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.5(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0))': + dependencies: + '@vitest/spy': 4.1.5 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.1(jiti@2.6.1)(lightningcss@1.32.0) + + '@vitest/pretty-format@4.1.5': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.5': + dependencies: + '@vitest/utils': 4.1.5 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.5': + dependencies: + '@vitest/pretty-format': 4.1.5 + '@vitest/utils': 4.1.5 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.5': {} + + '@vitest/utils@4.1.5': + dependencies: + '@vitest/pretty-format': 4.1.5 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + '@xyflow/react@12.10.2(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: '@xyflow/system': 0.0.76 @@ -1933,6 +2140,8 @@ snapshots: d3-selection: 3.0.0 d3-zoom: 3.0.0 + assertion-error@2.0.1: {} + bail@2.0.2: {} baseline-browser-mapping@2.10.10: {} @@ -1949,6 +2158,8 @@ snapshots: ccount@2.0.1: {} + chai@6.2.2: {} + character-entities-html4@2.1.0: {} character-entities-legacy@3.0.0: {} @@ -2026,6 +2237,8 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.0 + es-module-lexer@2.1.0: {} + esbuild@0.27.4: optionalDependencies: '@esbuild/aix-ppc64': 0.27.4 @@ -2061,6 +2274,12 @@ snapshots: estree-util-is-identifier-name@3.0.0: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + expect-type@1.3.0: {} + extend@3.0.2: {} fdir@6.5.0(picomatch@4.0.3): @@ -2534,6 +2753,8 @@ snapshots: node-releases@2.0.36: {} + obug@2.1.1: {} + parse-entities@4.0.2: dependencies: '@types/unist': 2.0.11 @@ -2544,6 +2765,8 @@ snapshots: is-decimal: 2.0.1 is-hexadecimal: 2.0.1 + pathe@2.0.3: {} + picocolors@1.1.1: {} picomatch@4.0.3: {} @@ -2657,10 +2880,16 @@ snapshots: semver@6.3.1: {} + siginfo@2.0.0: {} + source-map-js@1.2.1: {} space-separated-tokens@2.0.2: {} + stackback@0.0.2: {} + + std-env@4.1.0: {} + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 @@ -2678,11 +2907,17 @@ snapshots: tapable@2.3.0: {} + tinybench@2.9.0: {} + + tinyexec@1.1.2: {} + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinyrainbow@3.1.0: {} + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -2757,6 +2992,36 @@ snapshots: jiti: 2.6.1 lightningcss: 1.32.0 + vitest@4.1.5(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)): + dependencies: + '@vitest/expect': 4.1.5 + '@vitest/mocker': 4.1.5(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)) + '@vitest/pretty-format': 4.1.5 + '@vitest/runner': 4.1.5 + '@vitest/snapshot': 4.1.5 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.1.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.1.0 + vite: 7.3.1(jiti@2.6.1)(lightningcss@1.32.0) + why-is-node-running: 2.3.0 + transitivePeerDependencies: + - msw + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + yallist@3.1.1: {} zustand@4.5.7(@types/react@19.2.14)(react@19.2.4): diff --git a/src-tauri/src/commands/blueprint.rs b/src-tauri/src/commands/blueprint.rs index 60e87fd..7296826 100644 --- a/src-tauri/src/commands/blueprint.rs +++ b/src-tauri/src/commands/blueprint.rs @@ -807,7 +807,8 @@ fn build_init_prompt( 2. 创建 `.blueprint/manifest.yaml`(含 areas、modules、edges) 3. 为每个模块创建 `.blueprint/modules/.md`(含概述 + 任务卡,每张任务卡必须包含 files、acceptance、complexity 字段) 4. 已实现的功能标记 ✅ done,未实现的标记 📋 todo 或 💭 concept -5. 完成后更新 manifest.yaml 的 updated 日期为今天 +5. **检查测试基建**:查看 package.json 是否有 test 脚本、是否已安装 vitest/jest。若缺失,额外创建一张 📋「补测试基建」任务卡(complexity: S),acceptance 为「安装 vitest,配 vitest.config.ts,package.json 加 test 脚本,跑一个 smoke test 全绿」。Rust 项目同理,检查是否有 #[cfg(test)] 测试 +6. 完成后更新 manifest.yaml 的 updated 日期为今天 请直接输出需要创建的文件内容。 "#, @@ -840,7 +841,8 @@ fn build_sync_prompt( 2. 创建 `.blueprint/manifest.yaml`(含 areas、modules、edges)\n\ 3. 为每个模块创建 `.blueprint/modules/.md`(含概述 + 任务卡,每张任务卡必须包含 files、acceptance、complexity 字段)\n\ 4. 已有代码的功能标记 ✅ done,规划中的标记 📋 todo 或 💭 concept\n\ - 5. 更新 manifest.yaml 的 updated 日期为今天" + 5. 检查测试基建:若缺失测试框架,额外创建一张 📋「补测试基建」任务卡(complexity: S)\n\ + 6. 更新 manifest.yaml 的 updated 日期为今天" } else if no_git { // 有蓝图但无 git:只做结构对比,不做提交归因 "1. (跳过 git 对照,无法读取提交历史)\n\ diff --git a/src/lib/commands.test.ts b/src/lib/commands.test.ts new file mode 100644 index 0000000..ae0b093 --- /dev/null +++ b/src/lib/commands.test.ts @@ -0,0 +1,32 @@ +import { describe, it, expect } from "vitest"; +import { parseRepoPath } from "./commands"; + +describe("parseRepoPath", () => { + it("解析标准 HTTPS GitHub URL", () => { + expect(parseRepoPath("https://github.com/facebook/react")).toBe("facebook/react"); + }); + + it("解析带 .git 后缀的 URL", () => { + expect(parseRepoPath("https://github.com/facebook/react.git")).toBe("facebook/react"); + }); + + it("解析 SSH 格式 URL", () => { + expect(parseRepoPath("git@github.com:facebook/react.git")).toBe("facebook/react"); + }); + + it("非 GitHub URL 返回 null", () => { + expect(parseRepoPath("https://gitlab.com/foo/bar")).toBeNull(); + }); + + it("空字符串返回 null", () => { + expect(parseRepoPath("")).toBeNull(); + }); + + it("纯域名无路径返回 null", () => { + expect(parseRepoPath("https://github.com")).toBeNull(); + }); + + it("非 URL 的随机字符串返回 null", () => { + expect(parseRepoPath("not-a-url")).toBeNull(); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..e25fcb3 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,11 @@ +import tailwindcss from "@tailwindcss/vite"; +import { defineConfig } from "vitest/config"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [react(), tailwindcss()], + test: { + environment: "node", + include: ["src/**/*.test.{ts,tsx}"], + }, +});