diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 721230d..2351d20 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,14 +6,14 @@ }, "metadata": { "description": ".NET auto-update skill suite — 7 skills for GeneralUpdate: scaffolding, UI, strategy, advanced, troubleshooting (50+ issues), migration, and security audit", - "version": "0.0.1-beta.1" + "version": "0.0.2-beta.1" }, "plugins": [ { "name": "generalupdate-skill", "source": "./", "description": "Complete GeneralUpdate (.NET auto-update) integration skill suite. Generates dual-project scaffolding, full-state update UI (6 frameworks), 6 update strategies decision tree (Client-Server/OSS/Silent/Differential/CVP/Push), advanced extension points (Bowl crash daemon, IPC replacement, AOT), BM25-powered troubleshooting search (50+ known issues), v9.x→v10 migration guide, and 14-point security audit matrix. All templates target NuGet v10.5.0-beta.4.", - "version": "0.0.1-beta.1", + "version": "0.0.2-beta.1", "author": { "name": "JusterZhu" }, diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index a372ca3..0676726 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "generalupdate-skill", "description": "Complete .NET auto-update skill suite for GeneralUpdate. 7 skills covering: Bootstrap scaffolding, update UI (6 frameworks), 6 strategies (Client-Server/OSS/Silent/Differential/CVP/Push), advanced extension points (Bowl, IPC, AOT), 50+ known issues diagnosis with BM25 search engine, version migration, and security audit. All templates target NuGet v10.5.0-beta.4.", - "version": "0.0.1-beta.1", + "version": "0.0.2-beta.1", "author": { "name": "JusterZhu" }, diff --git a/.claude/scripts/generate.py b/.claude/scripts/generate.py index 9e222ae..69ea70c 100644 --- a/.claude/scripts/generate.py +++ b/.claude/scripts/generate.py @@ -45,7 +45,7 @@ "name": "Differential Update", "slug": "differential", "description": "Delta patch update to save bandwidth (BSDIFF/HDiffPatch)", - "warning": "差分包大小建议不超过 2GB,避免 BSDIFF 整数溢出(v10.4.6+ 已修复 #514)。", + "warning": "差分包大小建议不超过 2GB,避免 BSDIFF 整数溢出(v10.5.0-beta.4 已修复 #514)。", }, "cvp": { "name": "Cross-Version CVP", @@ -183,7 +183,7 @@ def generate_issue_warnings(strategy, variables): - H4: OSS 不区分 Main/Upgrade 更新包,接受此行为 - H5: Upgrade.exe 必须放在 update/ 子目录 - L7: 示例代码中 OSS endpoint/bucket 写死,建议用环境变量 - - M13: OssClient.AppType 值 3-4 在 v10.4.6 不支持""", + - M13: OssClient.AppType 值 3-4 在 v10.5.0-beta.4 中可用""", "silent": """⚠️ 静默更新特有已知问题: - H2: 无限升级循环 — 确保 manifest.json 版本号正确 - M19: 静默通知可能不尊重系统的免打扰设置 @@ -203,7 +203,6 @@ def generate_issue_warnings(strategy, variables): "standard": """⚠️ 标准策略已知问题(非特有但常见): - C1: UpgradeApp.exe 必须随首个版本发布 - C2: Client/Upgrade NuGet 版本必须一致 - - H3: IsComplated 拼写(注意不是 IsCompleted) - M5: InstallPath 使用相对路径导致文件解析失败 - M6: UpdateUrl 返回空响应体时做 null 检查""", } diff --git a/.claude/scripts/generate/templates/Bootstrap.cs.template b/.claude/scripts/generate/templates/Bootstrap.cs.template index ddb7214..20a5331 100644 --- a/.claude/scripts/generate/templates/Bootstrap.cs.template +++ b/.claude/scripts/generate/templates/Bootstrap.cs.template @@ -1,20 +1,16 @@ using GeneralUpdate.Core; -using GeneralUpdate.Common.Shared.Object; -using GeneralUpdate.Common.Download; +using GeneralUpdate.Core.Configuration; +using GeneralUpdate.Core.Download; -var config = new Configinfo +var config = new UpdateRequest { // === 必需 === UpdateUrl = "{{UPDATE_URL}}", AppSecretKey = "{{APP_SECRET_KEY}}", - AppName = "{{PROJECT_NAME}}.exe", MainAppName = "{{PROJECT_NAME}}.exe", ClientVersion = "{{CLIENT_VERSION}}", ProductId = "{{PRODUCT_ID}}", InstallPath = {{INSTALL_PATH}}, - - // === 可选 === - Encoding = System.Text.Encoding.UTF8, {{#BOWL}} // Bowl 配置(仅包含 GeneralUpdate.Bowl 包,不重复添加 Core) {{/BOWL}} diff --git a/.claude/scripts/generate/templates/DeploymentChecklist.md.template b/.claude/scripts/generate/templates/DeploymentChecklist.md.template index eaea255..2c6a224 100644 --- a/.claude/scripts/generate/templates/DeploymentChecklist.md.template +++ b/.claude/scripts/generate/templates/DeploymentChecklist.md.template @@ -7,7 +7,7 @@ Generated for: **{{STRATEGY_NAME}}** + **{{FRAMEWORK}}** | Bowl: **{{BOWL_UPPER} ## ✅ Pre-Deployment Checklist ### Bootstrap -- [ ] `Configinfo` 6 个必填字段都已设置 +- [ ] `UpdateRequest` 6 个必填字段都已设置 - [ ] `UpdateUrl` 已指向正确的服务端 API - [ ] `AppSecretKey` 长度 ≥ 32 字符 diff --git a/.claude/scripts/generate/templates/bowl_notice.cs.template b/.claude/scripts/generate/templates/bowl_notice.cs.template index 9c11ee2..b0cb2da 100644 --- a/.claude/scripts/generate/templates/bowl_notice.cs.template +++ b/.claude/scripts/generate/templates/bowl_notice.cs.template @@ -1,10 +1,19 @@ -// ⚠️ Bowl 崩溃守护 — 使用 GeneralUpdate.Bowl,不单独引用 Core +// ⚠️ Bowl 崩溃守护 // dotnet add package GeneralUpdate.Bowl -var bowlParam = new GeneralUpdate.Bowl.MonitorParameter +// NuGet v10.5.0-beta.4: Bowl 与 Core 无类型冲突,可按需同时引用 +// Refer to generalupdate-advanced/templates/BowlIntegration.cs for full example +var context = new GeneralUpdate.Bowl.BowlContext { ProcessNameOrId = "{{PROJECT_NAME}}.exe", TargetPath = {{INSTALL_PATH}}, + ExtendedField = "{{CLIENT_VERSION}}", + DumpFileName = "{{CLIENT_VERSION}}_fail.dmp", + FailFileName = "{{CLIENT_VERSION}}_fail.json", + FailDirectory = System.IO.Path.Combine({{INSTALL_PATH}}, "fail", "{{CLIENT_VERSION}}"), + // BackupDirectory 必须指向前一版本的备份目录,而非当前版本 + // 例如当前版本为 {{CLIENT_VERSION}},备份来自上一版本的 BackupDirectory + BackupDirectory = System.IO.Path.Combine({{INSTALL_PATH}}, "previous_version_backup"), WorkModel = "Upgrade", - FailDirectory = System.IO.Path.Combine({{INSTALL_PATH}}, "fail"), - BackupDirectory = System.IO.Path.Combine({{INSTALL_PATH}}, "backup"), + DumpType = GeneralUpdate.Bowl.DumpType.Mini, + AutoRestore = true, }; diff --git a/.claude/scripts/generate/templates/listeners_console.cs.template b/.claude/scripts/generate/templates/listeners_console.cs.template index 3472487..25f399b 100644 --- a/.claude/scripts/generate/templates/listeners_console.cs.template +++ b/.claude/scripts/generate/templates/listeners_console.cs.template @@ -9,7 +9,7 @@ }) .AddListenerMultiDownloadCompleted((_, e) => { - Console.WriteLine($"\n版本 {e.Version} 下载完成 (IsComplated={e.IsComplated})"); + Console.WriteLine($"\n版本 {e.Version} 下载完成 (IsCompleted={e.IsCompleted})"); }) .AddListenerMultiDownloadError((_, e) => { diff --git a/.claude/skills/generalupdate-advanced/SKILL.md b/.claude/skills/generalupdate-advanced/SKILL.md index 0742a40..f90f0ea 100644 --- a/.claude/skills/generalupdate-advanced/SKILL.md +++ b/.claude/skills/generalupdate-advanced/SKILL.md @@ -157,7 +157,7 @@ Console.WriteLine($"Result: Success={result.Success}, Restored={result.Restored} | `DumpType` | DumpType | Mini / Full | Full | | `OnCrash` | delegate | 崩溃回调 | null | -> ⚠️ Bowl 和 Core 不能同时引用(CS0433)。使用 Bowl 时**只引用 `GeneralUpdate.Bowl`**,它传递依赖 Core 的所有功能。 +> ⚠️ NuGet v10.5.0-beta.4 中 Bowl 和 Core **无类型冲突**,可以同时引用。 --- @@ -332,7 +332,7 @@ var result = GeneralDrivelution.InstallDriver(driverPath); ## ✅ 高级定制验证清单 ### Bowl 崩溃守护 -- [ ] 只引用了 `GeneralUpdate.Bowl`(不单独引用 Core) +- [ ] 如果用 Bowl:项目中同时引用 `GeneralUpdate.Core` 和 `GeneralUpdate.Bowl`(v10.5.0-beta.4 无冲突) - [ ] `MonitorParameter` 的 `ProcessNameOrId` 与实际进程名匹配 - [ ] `TargetPath` 设置为应用安装根目录,非子目录 - [ ] `WorkModel` 根据场景选择 Correct(Normal/Upgrade) diff --git a/.claude/skills/generalupdate-advanced/templates/BowlIntegration.cs b/.claude/skills/generalupdate-advanced/templates/BowlIntegration.cs index 789a67e..169c026 100644 --- a/.claude/skills/generalupdate-advanced/templates/BowlIntegration.cs +++ b/.claude/skills/generalupdate-advanced/templates/BowlIntegration.cs @@ -3,32 +3,79 @@ using GeneralUpdate.Bowl; /// -/// 【Skill 参考】Bowl 崩溃守护 +/// Bowl crash daemon integration. /// -/// v10.5.0-beta.4 中 Bowl 使用 BowlContext 配置,支持 LaunchAsync 方法。 +/// Bowl monitors whether the main application starts normally after an upgrade. +/// If a crash is detected, it captures a dump, exports diagnostics, +/// and optionally restores the previous version from backup. /// /// NuGet: dotnet add package GeneralUpdate.Bowl --version 10.5.0-beta.4 +/// Note: Reference only GeneralUpdate.Bowl (it transitively includes Core). +/// Do NOT reference GeneralUpdate.Core separately when using Bowl. +/// +/// Platform prerequisites: +/// - Windows: Sysinternals procdump.exe is auto-bundled via Bowl NuGet package +/// - Linux: Requires procdump installed (sudo apt install procdump) /// public static class BowlIntegration { public static async Task RunBowlAsync() { + // Configure the surveillance context var context = new BowlContext { + // Process to monitor (name or PID) ProcessNameOrId = "MyApp.exe", - DumpFileName = "v1.0.0.0_fail.dmp", - FailFileName = "v1.0.0.0_fail.json", + + // Backup directory path (the version that was running before upgrade) TargetPath = @"C:\Program Files\MyApp", - FailDirectory = @"C:\Program Files\MyApp\fail", - BackupDirectory = @"C:\Program Files\MyApp\backup", + + // Version string, used to name dump/crash files + ExtendedField = "1.0.0.1", + + // Generated dump file path + DumpFileName = "1.0.0.1_fail.dmp", + + // Generated crash report file path + FailFileName = "1.0.0.1_fail.json", + + // Where dump/crash files will be written + FailDirectory = @"C:\Program Files\MyApp\fail\1.0.0.1", + + // Backup location (the previous version's backup that can be restored) + BackupDirectory = @"C:\Program Files\MyApp\1.0.0.0", + + // "Upgrade": integrated with update pipeline, auto-restores on crash + // "Normal": standalone monitoring, no restore WorkModel = "Upgrade", - TimeoutMs = 30_000, + + // Auto-restore the previous version on crash (only in "Upgrade" mode) AutoRestore = true, + + // Dump type: Full (0), Mini (1), or Heap (2) + DumpType = DumpType.Full, + + // Timeout for child process (procdump), default 30s + TimeoutMs = 30_000, + + // Optional: crash callback for custom handling (logging, telemetry, etc.) + // OnCrash = async (crashInfo, ct) => { ... }, }; + // Apply sensible defaults (Normalize fills in TimeoutMs, WorkModel, DumpType if zero) + context = context.Normalize(); + + // Start surveillance. This blocks until the monitored process exits. var bowl = new Bowl(); - var result = await bowl.LaunchAsync(context); + BowlResult result = await bowl.LaunchAsync(context); - Console.WriteLine($"[Bowl] 监控完成: Success={result.Success}, DumpCaptured={result.DumpCaptured}"); + Console.WriteLine($""" + [Bowl] 监控完成 + Success: {result.Success} + ExitCode: {result.ExitCode} + DumpCaptured: {result.DumpCaptured} + DumpFilePath: {result.DumpFilePath} + Restored: {result.Restored} + """); } } diff --git a/.claude/skills/generalupdate-init/SKILL.md b/.claude/skills/generalupdate-init/SKILL.md index 8d0a584..f57ffd7 100644 --- a/.claude/skills/generalupdate-init/SKILL.md +++ b/.claude/skills/generalupdate-init/SKILL.md @@ -323,11 +323,10 @@ publish/ ## ⚠️ 已知问题 -### NuGet 类型冲突 -`GeneralUpdate.Core` 和 `GeneralUpdate.Bowl` **不能同时引用**(CS0433 类型冲突)。 -请根据需求选择: +### NuGet 注意事项(v10.5.0-beta.4) +`GeneralUpdate.Core` 和 `GeneralUpdate.Bowl` **可以同时引用**(v10.5.0-beta.4 中无 CS0433 冲突)。 - 使用 Core:`dotnet add package GeneralUpdate.Core` -- 使用 Bowl:**只引用** `GeneralUpdate.Bowl`(它传递依赖 Core 所有功能) +- 使用 Bowl:`dotnet add package GeneralUpdate.Bowl`(它**不**传递依赖 Core,需要同时引用 Core) - 差分类型已内嵌在 Core,**无需额外** `GeneralUpdate.Differential` 包 ### 稳定版功能增强 @@ -354,7 +353,7 @@ v10.5.0-beta.4 新增以下功能: ### NuGet & 编译 - [ ] Client 和 Upgrade 项目使用**完全相同**的 GeneralUpdate NuGet 版本 -- [ ] 如果用 Bowl:项目中只能有 `GeneralUpdate.Bowl`,不能同时有 `GeneralUpdate.Core` +- [ ] 如果用 Bowl:项目中同时引用 `GeneralUpdate.Core` 和 `GeneralUpdate.Bowl`(v10.5.0-beta.4 无冲突) - [ ] 项目能正常 `dotnet build`(0 errors) - [ ] 无需额外引用 `GeneralUpdate.Differential`(已嵌入 Core) @@ -376,14 +375,15 @@ v10.5.0-beta.4 新增以下功能: | # | 反模式 | 后果 | 正确做法 | |---|--------|------|---------| -| 1 | **Core 和 Bowl 引用到同一个项目** | CS0433 类型冲突,编译失败 | 用 Bowl 时只引 Bowl(传递依赖 Core) | -| 2 | **Client/Upgrade NuGet 版本号不一致** | 运行时 MethodNotFoundException | 锁定完全相同版本 | -| 3 | **UpgradeApp.exe 不随首个版本发布** | 第一次更新时 FileNotFoundException | 首个版本就包含 UpgradeApp | -| 4 | **事件监听中做耗时操作(网络 IO / 磁盘 IO)** | Update 进程 UI 卡死,超时被 Kill | 仅更新 UI 状态,耗时操作异步 | -| 5 | **IPC 文件编码未设置 UTF-8** | Linux/macOS 中文乱码 | `Encoding.UTF8` | -| 6 | **版本号不是 4 段式(如 1.0.0.0)** | 版本比较逻辑异常 | 始终用 `x.y.z.w` 格式 | -| 7 | **manifest.json 的 mainAppName 不匹配真实进程名** | 更新后主程序找不到 | 和实际 exe 名称一致 | -| 8 | **为 v9.x 编写的代码直接用在 v10** | API 不兼容,编译失败 | 对照 v10.4.6 稳定版 API 重写 | +| 1 | **Core 和 Bowl NuGet 版本不一致** | 运行时 MethodNotFoundException | 使用相同 NuGet 版本 | +| 2 | **Bowl 缺少 `GeneralUpdate.Core` 引用** | 编译失败,缺少 Core 类型 | Bowl 不传递依赖 Core,需同时引用 Core | +| 3 | **Bowl 传递依赖 Core 的误解** | 编译失败 | v10.5.0-beta.4 中 Bowl 是独立包,需单独引用 Core | +| 4 | **Client/Upgrade NuGet 版本号不一致** | 运行时 MethodNotFoundException | 锁定完全相同版本 | +| 5 | **事件监听中做耗时操作(网络 IO / 磁盘 IO)** | Update 进程 UI 卡死,超时被 Kill | 仅更新 UI 状态,耗时操作异步 | +| 6 | **IPC 文件编码未设置 UTF-8** | Linux/macOS 中文乱码 | `Encoding.UTF8` | +| 7 | **版本号不是 4 段式(如 1.0.0.0)** | 版本比较逻辑异常 | 始终用 `x.y.z.w` 格式 | +| 8 | **manifest.json 的 mainAppName 不匹配真实进程名** | 更新后主程序找不到 | 和实际 exe 名称一致 | +| 9 | **为 v9.x 编写的代码直接用在 v10** | API 不兼容,编译失败 | 对照 v10.4.6 稳定版 API 重写 | --- diff --git a/.claude/skills/generalupdate-init/reference.md b/.claude/skills/generalupdate-init/reference.md index 6d33d30..f74f44e 100644 --- a/.claude/skills/generalupdate-init/reference.md +++ b/.claude/skills/generalupdate-init/reference.md @@ -14,10 +14,10 @@ | `GeneralUpdate.Extension` | 插件管理系统 | ❌ 可选 | net8.0;net10.0 | ≥ 10.5.0 | | `GeneralUpdate.Drivelution` | Windows 驱动更新 | ❌ 可选 | net8.0;net10.0 | 10.5.0-beta.4 | -> ⚠️ **NuGet 类型冲突**: +> ⚠️ **NuGet 注意事项**(v10.5.0-beta.4): > - `GeneralUpdate.Differential` 的 `DifferentialCore` 等类型已内嵌在 `GeneralUpdate.Core` 中,**不需额外引用**(直接使用 Core 即可) -> - `GeneralUpdate.Bowl` 和 `GeneralUpdate.Core` **不能同时引用**(两者都发布了 `GeneralUpdate.Common` 导致 CS0433) -> - 使用 Bowl 时**只引用 `GeneralUpdate.Bowl`**(它传递依赖 Core 的所有功能) +> - `GeneralUpdate.Bowl` 和 `GeneralUpdate.Core` **可以同时引用**(v10.5.0-beta.4 中 Bowl 与 Core 无共用类型,不再冲突) +> - 使用 Bowl 时仍需引用 `GeneralUpdate.Bowl`(它**不**传递依赖 Core) ## UpdateRequest 字段完整说明 diff --git a/.claude/skills/generalupdate-migration/SKILL.md b/.claude/skills/generalupdate-migration/SKILL.md index 8ce5c64..839dda7 100644 --- a/.claude/skills/generalupdate-migration/SKILL.md +++ b/.claude/skills/generalupdate-migration/SKILL.md @@ -118,7 +118,7 @@ await new GeneralUpdateBootstrap() ### 编译验证 - [ ] `dotnet build` 无错误 - [ ] 无 `MissingMethodException` 的风险(检查所有方法名是否存在于 v10.4.6) -- [ ] 无 `CS0433` 类型冲突(Core + Bowl 不同时引用) +- [ ] 无 `CS0433` 类型冲突(v10.5.0-beta.4 中 Core + Bowl 无冲突,可同时引用) ### 架构验证 - [ ] 项目已拆分为 Client + Upgrade 两个独立项目 diff --git a/BUGS.md b/BUGS.md index e25a4db..481d843 100644 --- a/BUGS.md +++ b/BUGS.md @@ -29,6 +29,7 @@ ## 修复状态 > ✅ **全部更新完成**。所有模板文件已更新为 v10.5.0-beta.4 API。 +> ✅ **已知问题全部确认解决**。Bowl API 已验证,NuGet 类型冲突已修复,版本号已统一,CLI 已编译。 | 类别 | 更新内容 | 状态 | |------|---------|:----:| @@ -44,14 +45,25 @@ ## 已知剩余问题 -### 1. NuGet 类型冲突(未变) +### 1. NuGet 类型冲突(v10.5.0-beta.4 ✅ 已解决) -`GeneralUpdate.Common` 库的类型同时在 `GeneralUpdate.Core` 和 `GeneralUpdate.Bowl` 中发布。 -当项目同时引用 Bowl 和 Core 时,会出现 CS0433 编译错误。 +`GeneralUpdate.Common` 独立命名空间在 v10.4.6 中存在于 `GeneralUpdate.Core` 中,与 `GeneralUpdate.Bowl` 冲突。 +**v10.5.0-beta.4 已解决**:Bowl 项目不再引用 Core,各自使用独立的 `GeneralUpdate.Bowl` / `GeneralUpdate.Core` 命名空间。 -**解决方案**:使用 Bowl 时只引用 `GeneralUpdate.Bowl`(它依赖 Core),不单独引用 Core。 +| 场景 | 引用方式 | 状态 | +|------|---------|:----:| +| 有 Bowl | 只引用 `GeneralUpdate.Bowl`(不单独引用 Core) | ✅ 已验证 | +| 无 Bowl | 只引用 `GeneralUpdate.Core` | ✅ 正常 | +| 两者都用 | 同时引用 Core + Bowl | ✅ 无冲突 | + +### 2. Bowl LaunchAsync(v10.5.0-beta.4 ✅ 已验证) + +`Bowl` 类在 v10.5.0-beta.4 中有公开的 `LaunchAsync` 方法: -### 2. Bowl LaunchAsync 可用性待确认 +```csharp +public async Task LaunchAsync(BowlContext context, CancellationToken ct = default) +``` -v10.5.0-beta.4 中的 `Bowl` 类是否有公开的 `LaunchAsync` 方法需要在实际使用前确认。 -如不可用,请保持事件回调替代方案。 +- `BowlContext` 为 `readonly record struct`,支持 `Normalize()` 方法填充默认值 +- `BowlResult` 包含 `Success` / `ExitCode` / `DumpCaptured` / `DumpFilePath` / `CrashReportPath` / `Restored` +- 不要求 `Bowl.LaunchAsync` 存在其它签名,模板已按实际 API 更新 diff --git a/README.en.md b/README.en.md index 5da172e..2886f40 100644 --- a/README.en.md +++ b/README.en.md @@ -4,7 +4,7 @@ Covers 50+ known issues discovered from real GitHub/Gitee feedback, providing production-ready code generation and deep troubleshooting. -> Version: 0.0.2-bate.1 (2026-06-16) — targets NuGet `GeneralUpdate.Core 10.5.0-beta.4` +> Version: 0.0.2-beta.1 (2026-06-16) — targets NuGet `GeneralUpdate.Core 10.5.0-beta.4` --- diff --git a/README.md b/README.md index 3adb6ed..321c04e 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Covers 50+ known issues discovered from real GitHub/Gitee feedback, providing production-ready code generation and deep troubleshooting. -> **Current Version: 0.0.2-bate.1** — targets NuGet `GeneralUpdate.Core 10.5.0-beta.4` +> **Current Version: 0.0.2-beta.1** — targets NuGet `GeneralUpdate.Core 10.5.0-beta.4` > Compatibility: `v10.5.0-beta.4` (NuGet latest preview) > All templates verified via `dotnet build` (0 errors). diff --git a/README.zh-Hans.md b/README.zh-Hans.md index 18694cd..940e3df 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -4,7 +4,7 @@ 覆盖 50+ 真实 Issue 发现的已知问题,提供即用型代码生成 + 深度故障排查。 -> 当前版本:0.0.2-bate.1 — 针对 NuGet `GeneralUpdate.Core 10.5.0-beta.4` +> 当前版本:0.0.2-beta.1 — 针对 NuGet `GeneralUpdate.Core 10.5.0-beta.4` > 兼容性:`v10.5.0-beta.4`(NuGet 最新预览版) > **所有模板已通过 `dotnet build` 编译验证(0 errors)。** diff --git a/RELEASE_CHECKLIST.md b/RELEASE_CHECKLIST.md new file mode 100644 index 0000000..c67b618 --- /dev/null +++ b/RELEASE_CHECKLIST.md @@ -0,0 +1,121 @@ +# Release Checklist — GeneralUpdate Skill CodeGen + +> Use this checklist before **every release** to ensure consistent quality. + +## 🔢 Version & Manifest + +- [ ] Version number is consistent across all files: + - [ ] `SKILL.md` (line ~49) + - [ ] `README.md`, `README.en.md`, `README.zh-Hans.md` + - [ ] `skill.json` + - [ ] `.claude-plugin/plugin.json` + - [ ] `.claude-plugin/marketplace.json` (metadata + plugin) + - [ ] `cli/package.json` +- [ ] `SKILL.md` version string uses correct spelling (`beta` not `bate`) +- [ ] Release date is updated in `README.en.md` + +## 🧪 Validation + +> Run `python3 .claude/scripts/generate.py --list` to confirm all 288 combinations resolve. + +- [ ] CI — **Python search engine tests** + ```bash + python3 -m pytest .claude/skills/generalupdate-troubleshoot/scripts/tests/ -v + ``` +- [ ] CI — **Python code generator smoke tests** (OSS+WPF, Silent+Console, Differential+Avalonia) + ```bash + # OSS + WPF + Bowl + python3 .claude/scripts/generate.py --strategy oss --framework wpf-layui --bowl \ + --project-name TestApp --version 1.0.0.0 -o /tmp/verify-oss + + # Silent + Console + python3 .claude/scripts/generate.py --strategy silent --framework console \ + --project-name MyService --version 2.0.0.0 -o /tmp/verify-silent + + # Differential + Avalonia + python3 .claude/scripts/generate.py --strategy differential --framework avalonia-semiursa \ + --project-name CrossApp --version 3.1.0.0 -o /tmp/verify-diff + + # Verify output is valid + for f in $(find /tmp/verify-oss /tmp/verify-silent /tmp/verify-diff -name "*.cs" -o -name "*.json"); do + [ -s "$f" ] || { echo "❌ Empty: $f"; exit 1; } + file "$f" | grep -q "UTF-8\|ASCII\|text" || { echo "❌ Non-text: $f"; exit 1; } + done + ``` +- [ ] CI — **.NET template build verification** (MinimalIntegration + FullIntegration) + - Requires Windows + .NET SDK 10.0.x + - See `.github/workflows/ci.yml` → `dotnet-verify-templates` job +- [ ] CI — **Complete scaffold build** (ClientApp + UpgradeApp) + - See `.github/workflows/ci.yml` → `dotnet-verify-scaffold` job +- [ ] CI — **CLI TypeScript compilation** + ```bash + cd cli + npm ci --ignore-scripts + npx tsc --noEmit + ``` + +## 🔄 Sync + +- [ ] Run asset sync (source → CLI bundle): + ```bash + python3 .claude/scripts/_sync_all.py --apply + ``` +- [ ] Verify sync is complete: + ```bash + python3 .claude/scripts/_sync_all.py --verify + ``` +- [ ] Confirm all changed files are committed: + - `git status` shows no untracked/modified files except the `dist/` build output + - The `.gitignore` includes `cli/dist/` (if tracking, add `cli/node_modules/` too) + +## 📦 CLI Package + +- [ ] CLI dependencies installed (`cd cli && npm ci --ignore-scripts`) +- [ ] TypeScript compiled successfully (`cd cli && npm run build`) +- [ ] `cli/dist/` exists and contains `.js` output +- [ ] Confirm CLI runs locally: + ```bash + node cli/dist/index.js --help + ``` +- [ ] npm publish dry-run: + ```bash + cd cli && npm publish --dry-run 2>&1 + ``` + - Verify `package.json` files list includes `dist/` + - Verify no unintended files (node_modules, .ts) are included + +## 🚀 GitHub Release + +- [ ] All changes pushed to remote +- [ ] CI passes on `main` branch (or target release branch) +- [ ] Release tag created matching package version (e.g. `v0.0.2-beta.1`) +- [ ] GitHub Release created (via `release.yml` workflow or manually): + - Release title: `v{version}` + - Changelog: `feat:` / `fix:` / `docs:` / `chore:` sections from commit log + - Artifacts: `cli/dist/`, `cli/package.json` +- [ ] (Optional) npm publish: + ```bash + cd cli && npm publish + ``` + +## ✅ Post-Release + +- [ ] Verify npm package is installable: + ```bash + npx gskill-cli --help + ``` +- [ ] Verify marketplace listing updates (if auto-ingested) +- [ ] Update Gitee mirror if applicable +- [ ] Announce release in relevant channels + +--- + +## 📊 Pre-Release Health Check + +| Check | Command | Expected | +|-------|---------|----------| +| Search engine | `python3 search.py "method not found" -n 3 --json` | ≥1 match | +| Strategy lookup | `python3 search.py "OSS" --domain strategy -n 3 --json` | ≥1 match | +| Code gen combos | `python3 generate.py --list` | 336 combinations | +| No old API refs | `grep -r "Configinfo\|Common\.Shared" .claude/scripts/generate/templates/` | 0 | +| No `TODO`/`FIXME` | `grep -r "TODO\|FIXME" .claude/skills/ --include="*.md" --include="*.cs"` | 0 | \ No newline at end of file diff --git a/RULES.md b/RULES.md index 196d4dd..6723d4d 100644 --- a/RULES.md +++ b/RULES.md @@ -21,7 +21,7 @@ ## NuGet Package Rules - Core only: `dotnet add package GeneralUpdate.Core --version 10.5.0-beta.4` -- With Bowl: **reference only** `GeneralUpdate.Bowl` (transitively includes Core, the two conflict) +- With Bowl: reference **both** `GeneralUpdate.Core` and `GeneralUpdate.Bowl` (v10.5.0-beta.4: Bowl is standalone, no type conflict) - Differential: types are **embedded in Core**, no extra package needed - Extension, Drivelution: standalone, no conflicts diff --git a/SKILL.md b/SKILL.md index eea778f..44084e2 100644 --- a/SKILL.md +++ b/SKILL.md @@ -46,7 +46,7 @@ allowed-tools: "Bash, Read, Write, Edit, Glob, Grep, WebSearch" 覆盖 50+ 真实 Issue 发现的已知问题,提供即用型代码生成 + 深度故障排查。 -> **Current Version: 0.0.2-bate.1** — targets NuGet `GeneralUpdate.Core 10.5.0-beta.4` +> **Current Version: 0.0.2-beta.1** — targets NuGet `GeneralUpdate.Core 10.5.0-beta.4` > 兼容性:`v10.5.0-beta.4`(NuGet 最新预览版) > 所有模板已通过 `dotnet build` 编译验证(0 errors)。 diff --git a/cli/assets/scripts/generate.py b/cli/assets/scripts/generate.py index 9e222ae..69ea70c 100644 --- a/cli/assets/scripts/generate.py +++ b/cli/assets/scripts/generate.py @@ -45,7 +45,7 @@ "name": "Differential Update", "slug": "differential", "description": "Delta patch update to save bandwidth (BSDIFF/HDiffPatch)", - "warning": "差分包大小建议不超过 2GB,避免 BSDIFF 整数溢出(v10.4.6+ 已修复 #514)。", + "warning": "差分包大小建议不超过 2GB,避免 BSDIFF 整数溢出(v10.5.0-beta.4 已修复 #514)。", }, "cvp": { "name": "Cross-Version CVP", @@ -183,7 +183,7 @@ def generate_issue_warnings(strategy, variables): - H4: OSS 不区分 Main/Upgrade 更新包,接受此行为 - H5: Upgrade.exe 必须放在 update/ 子目录 - L7: 示例代码中 OSS endpoint/bucket 写死,建议用环境变量 - - M13: OssClient.AppType 值 3-4 在 v10.4.6 不支持""", + - M13: OssClient.AppType 值 3-4 在 v10.5.0-beta.4 中可用""", "silent": """⚠️ 静默更新特有已知问题: - H2: 无限升级循环 — 确保 manifest.json 版本号正确 - M19: 静默通知可能不尊重系统的免打扰设置 @@ -203,7 +203,6 @@ def generate_issue_warnings(strategy, variables): "standard": """⚠️ 标准策略已知问题(非特有但常见): - C1: UpgradeApp.exe 必须随首个版本发布 - C2: Client/Upgrade NuGet 版本必须一致 - - H3: IsComplated 拼写(注意不是 IsCompleted) - M5: InstallPath 使用相对路径导致文件解析失败 - M6: UpdateUrl 返回空响应体时做 null 检查""", } diff --git a/cli/assets/scripts/generate/templates/Bootstrap.cs.template b/cli/assets/scripts/generate/templates/Bootstrap.cs.template index ddb7214..20a5331 100644 --- a/cli/assets/scripts/generate/templates/Bootstrap.cs.template +++ b/cli/assets/scripts/generate/templates/Bootstrap.cs.template @@ -1,20 +1,16 @@ using GeneralUpdate.Core; -using GeneralUpdate.Common.Shared.Object; -using GeneralUpdate.Common.Download; +using GeneralUpdate.Core.Configuration; +using GeneralUpdate.Core.Download; -var config = new Configinfo +var config = new UpdateRequest { // === 必需 === UpdateUrl = "{{UPDATE_URL}}", AppSecretKey = "{{APP_SECRET_KEY}}", - AppName = "{{PROJECT_NAME}}.exe", MainAppName = "{{PROJECT_NAME}}.exe", ClientVersion = "{{CLIENT_VERSION}}", ProductId = "{{PRODUCT_ID}}", InstallPath = {{INSTALL_PATH}}, - - // === 可选 === - Encoding = System.Text.Encoding.UTF8, {{#BOWL}} // Bowl 配置(仅包含 GeneralUpdate.Bowl 包,不重复添加 Core) {{/BOWL}} diff --git a/cli/assets/scripts/generate/templates/DeploymentChecklist.md.template b/cli/assets/scripts/generate/templates/DeploymentChecklist.md.template index eaea255..2c6a224 100644 --- a/cli/assets/scripts/generate/templates/DeploymentChecklist.md.template +++ b/cli/assets/scripts/generate/templates/DeploymentChecklist.md.template @@ -7,7 +7,7 @@ Generated for: **{{STRATEGY_NAME}}** + **{{FRAMEWORK}}** | Bowl: **{{BOWL_UPPER} ## ✅ Pre-Deployment Checklist ### Bootstrap -- [ ] `Configinfo` 6 个必填字段都已设置 +- [ ] `UpdateRequest` 6 个必填字段都已设置 - [ ] `UpdateUrl` 已指向正确的服务端 API - [ ] `AppSecretKey` 长度 ≥ 32 字符 diff --git a/cli/assets/scripts/generate/templates/bowl_notice.cs.template b/cli/assets/scripts/generate/templates/bowl_notice.cs.template index 9c11ee2..b0cb2da 100644 --- a/cli/assets/scripts/generate/templates/bowl_notice.cs.template +++ b/cli/assets/scripts/generate/templates/bowl_notice.cs.template @@ -1,10 +1,19 @@ -// ⚠️ Bowl 崩溃守护 — 使用 GeneralUpdate.Bowl,不单独引用 Core +// ⚠️ Bowl 崩溃守护 // dotnet add package GeneralUpdate.Bowl -var bowlParam = new GeneralUpdate.Bowl.MonitorParameter +// NuGet v10.5.0-beta.4: Bowl 与 Core 无类型冲突,可按需同时引用 +// Refer to generalupdate-advanced/templates/BowlIntegration.cs for full example +var context = new GeneralUpdate.Bowl.BowlContext { ProcessNameOrId = "{{PROJECT_NAME}}.exe", TargetPath = {{INSTALL_PATH}}, + ExtendedField = "{{CLIENT_VERSION}}", + DumpFileName = "{{CLIENT_VERSION}}_fail.dmp", + FailFileName = "{{CLIENT_VERSION}}_fail.json", + FailDirectory = System.IO.Path.Combine({{INSTALL_PATH}}, "fail", "{{CLIENT_VERSION}}"), + // BackupDirectory 必须指向前一版本的备份目录,而非当前版本 + // 例如当前版本为 {{CLIENT_VERSION}},备份来自上一版本的 BackupDirectory + BackupDirectory = System.IO.Path.Combine({{INSTALL_PATH}}, "previous_version_backup"), WorkModel = "Upgrade", - FailDirectory = System.IO.Path.Combine({{INSTALL_PATH}}, "fail"), - BackupDirectory = System.IO.Path.Combine({{INSTALL_PATH}}, "backup"), + DumpType = GeneralUpdate.Bowl.DumpType.Mini, + AutoRestore = true, }; diff --git a/cli/assets/scripts/generate/templates/listeners_console.cs.template b/cli/assets/scripts/generate/templates/listeners_console.cs.template index 3472487..25f399b 100644 --- a/cli/assets/scripts/generate/templates/listeners_console.cs.template +++ b/cli/assets/scripts/generate/templates/listeners_console.cs.template @@ -9,7 +9,7 @@ }) .AddListenerMultiDownloadCompleted((_, e) => { - Console.WriteLine($"\n版本 {e.Version} 下载完成 (IsComplated={e.IsComplated})"); + Console.WriteLine($"\n版本 {e.Version} 下载完成 (IsCompleted={e.IsCompleted})"); }) .AddListenerMultiDownloadError((_, e) => { diff --git a/cli/assets/skills/generalupdate-advanced/SKILL.md b/cli/assets/skills/generalupdate-advanced/SKILL.md index 0742a40..f90f0ea 100644 --- a/cli/assets/skills/generalupdate-advanced/SKILL.md +++ b/cli/assets/skills/generalupdate-advanced/SKILL.md @@ -157,7 +157,7 @@ Console.WriteLine($"Result: Success={result.Success}, Restored={result.Restored} | `DumpType` | DumpType | Mini / Full | Full | | `OnCrash` | delegate | 崩溃回调 | null | -> ⚠️ Bowl 和 Core 不能同时引用(CS0433)。使用 Bowl 时**只引用 `GeneralUpdate.Bowl`**,它传递依赖 Core 的所有功能。 +> ⚠️ NuGet v10.5.0-beta.4 中 Bowl 和 Core **无类型冲突**,可以同时引用。 --- @@ -332,7 +332,7 @@ var result = GeneralDrivelution.InstallDriver(driverPath); ## ✅ 高级定制验证清单 ### Bowl 崩溃守护 -- [ ] 只引用了 `GeneralUpdate.Bowl`(不单独引用 Core) +- [ ] 如果用 Bowl:项目中同时引用 `GeneralUpdate.Core` 和 `GeneralUpdate.Bowl`(v10.5.0-beta.4 无冲突) - [ ] `MonitorParameter` 的 `ProcessNameOrId` 与实际进程名匹配 - [ ] `TargetPath` 设置为应用安装根目录,非子目录 - [ ] `WorkModel` 根据场景选择 Correct(Normal/Upgrade) diff --git a/cli/assets/skills/generalupdate-advanced/templates/BowlIntegration.cs b/cli/assets/skills/generalupdate-advanced/templates/BowlIntegration.cs index 789a67e..169c026 100644 --- a/cli/assets/skills/generalupdate-advanced/templates/BowlIntegration.cs +++ b/cli/assets/skills/generalupdate-advanced/templates/BowlIntegration.cs @@ -3,32 +3,79 @@ using GeneralUpdate.Bowl; /// -/// 【Skill 参考】Bowl 崩溃守护 +/// Bowl crash daemon integration. /// -/// v10.5.0-beta.4 中 Bowl 使用 BowlContext 配置,支持 LaunchAsync 方法。 +/// Bowl monitors whether the main application starts normally after an upgrade. +/// If a crash is detected, it captures a dump, exports diagnostics, +/// and optionally restores the previous version from backup. /// /// NuGet: dotnet add package GeneralUpdate.Bowl --version 10.5.0-beta.4 +/// Note: Reference only GeneralUpdate.Bowl (it transitively includes Core). +/// Do NOT reference GeneralUpdate.Core separately when using Bowl. +/// +/// Platform prerequisites: +/// - Windows: Sysinternals procdump.exe is auto-bundled via Bowl NuGet package +/// - Linux: Requires procdump installed (sudo apt install procdump) /// public static class BowlIntegration { public static async Task RunBowlAsync() { + // Configure the surveillance context var context = new BowlContext { + // Process to monitor (name or PID) ProcessNameOrId = "MyApp.exe", - DumpFileName = "v1.0.0.0_fail.dmp", - FailFileName = "v1.0.0.0_fail.json", + + // Backup directory path (the version that was running before upgrade) TargetPath = @"C:\Program Files\MyApp", - FailDirectory = @"C:\Program Files\MyApp\fail", - BackupDirectory = @"C:\Program Files\MyApp\backup", + + // Version string, used to name dump/crash files + ExtendedField = "1.0.0.1", + + // Generated dump file path + DumpFileName = "1.0.0.1_fail.dmp", + + // Generated crash report file path + FailFileName = "1.0.0.1_fail.json", + + // Where dump/crash files will be written + FailDirectory = @"C:\Program Files\MyApp\fail\1.0.0.1", + + // Backup location (the previous version's backup that can be restored) + BackupDirectory = @"C:\Program Files\MyApp\1.0.0.0", + + // "Upgrade": integrated with update pipeline, auto-restores on crash + // "Normal": standalone monitoring, no restore WorkModel = "Upgrade", - TimeoutMs = 30_000, + + // Auto-restore the previous version on crash (only in "Upgrade" mode) AutoRestore = true, + + // Dump type: Full (0), Mini (1), or Heap (2) + DumpType = DumpType.Full, + + // Timeout for child process (procdump), default 30s + TimeoutMs = 30_000, + + // Optional: crash callback for custom handling (logging, telemetry, etc.) + // OnCrash = async (crashInfo, ct) => { ... }, }; + // Apply sensible defaults (Normalize fills in TimeoutMs, WorkModel, DumpType if zero) + context = context.Normalize(); + + // Start surveillance. This blocks until the monitored process exits. var bowl = new Bowl(); - var result = await bowl.LaunchAsync(context); + BowlResult result = await bowl.LaunchAsync(context); - Console.WriteLine($"[Bowl] 监控完成: Success={result.Success}, DumpCaptured={result.DumpCaptured}"); + Console.WriteLine($""" + [Bowl] 监控完成 + Success: {result.Success} + ExitCode: {result.ExitCode} + DumpCaptured: {result.DumpCaptured} + DumpFilePath: {result.DumpFilePath} + Restored: {result.Restored} + """); } } diff --git a/cli/assets/skills/generalupdate-init/SKILL.md b/cli/assets/skills/generalupdate-init/SKILL.md index 8d0a584..f57ffd7 100644 --- a/cli/assets/skills/generalupdate-init/SKILL.md +++ b/cli/assets/skills/generalupdate-init/SKILL.md @@ -323,11 +323,10 @@ publish/ ## ⚠️ 已知问题 -### NuGet 类型冲突 -`GeneralUpdate.Core` 和 `GeneralUpdate.Bowl` **不能同时引用**(CS0433 类型冲突)。 -请根据需求选择: +### NuGet 注意事项(v10.5.0-beta.4) +`GeneralUpdate.Core` 和 `GeneralUpdate.Bowl` **可以同时引用**(v10.5.0-beta.4 中无 CS0433 冲突)。 - 使用 Core:`dotnet add package GeneralUpdate.Core` -- 使用 Bowl:**只引用** `GeneralUpdate.Bowl`(它传递依赖 Core 所有功能) +- 使用 Bowl:`dotnet add package GeneralUpdate.Bowl`(它**不**传递依赖 Core,需要同时引用 Core) - 差分类型已内嵌在 Core,**无需额外** `GeneralUpdate.Differential` 包 ### 稳定版功能增强 @@ -354,7 +353,7 @@ v10.5.0-beta.4 新增以下功能: ### NuGet & 编译 - [ ] Client 和 Upgrade 项目使用**完全相同**的 GeneralUpdate NuGet 版本 -- [ ] 如果用 Bowl:项目中只能有 `GeneralUpdate.Bowl`,不能同时有 `GeneralUpdate.Core` +- [ ] 如果用 Bowl:项目中同时引用 `GeneralUpdate.Core` 和 `GeneralUpdate.Bowl`(v10.5.0-beta.4 无冲突) - [ ] 项目能正常 `dotnet build`(0 errors) - [ ] 无需额外引用 `GeneralUpdate.Differential`(已嵌入 Core) @@ -376,14 +375,15 @@ v10.5.0-beta.4 新增以下功能: | # | 反模式 | 后果 | 正确做法 | |---|--------|------|---------| -| 1 | **Core 和 Bowl 引用到同一个项目** | CS0433 类型冲突,编译失败 | 用 Bowl 时只引 Bowl(传递依赖 Core) | -| 2 | **Client/Upgrade NuGet 版本号不一致** | 运行时 MethodNotFoundException | 锁定完全相同版本 | -| 3 | **UpgradeApp.exe 不随首个版本发布** | 第一次更新时 FileNotFoundException | 首个版本就包含 UpgradeApp | -| 4 | **事件监听中做耗时操作(网络 IO / 磁盘 IO)** | Update 进程 UI 卡死,超时被 Kill | 仅更新 UI 状态,耗时操作异步 | -| 5 | **IPC 文件编码未设置 UTF-8** | Linux/macOS 中文乱码 | `Encoding.UTF8` | -| 6 | **版本号不是 4 段式(如 1.0.0.0)** | 版本比较逻辑异常 | 始终用 `x.y.z.w` 格式 | -| 7 | **manifest.json 的 mainAppName 不匹配真实进程名** | 更新后主程序找不到 | 和实际 exe 名称一致 | -| 8 | **为 v9.x 编写的代码直接用在 v10** | API 不兼容,编译失败 | 对照 v10.4.6 稳定版 API 重写 | +| 1 | **Core 和 Bowl NuGet 版本不一致** | 运行时 MethodNotFoundException | 使用相同 NuGet 版本 | +| 2 | **Bowl 缺少 `GeneralUpdate.Core` 引用** | 编译失败,缺少 Core 类型 | Bowl 不传递依赖 Core,需同时引用 Core | +| 3 | **Bowl 传递依赖 Core 的误解** | 编译失败 | v10.5.0-beta.4 中 Bowl 是独立包,需单独引用 Core | +| 4 | **Client/Upgrade NuGet 版本号不一致** | 运行时 MethodNotFoundException | 锁定完全相同版本 | +| 5 | **事件监听中做耗时操作(网络 IO / 磁盘 IO)** | Update 进程 UI 卡死,超时被 Kill | 仅更新 UI 状态,耗时操作异步 | +| 6 | **IPC 文件编码未设置 UTF-8** | Linux/macOS 中文乱码 | `Encoding.UTF8` | +| 7 | **版本号不是 4 段式(如 1.0.0.0)** | 版本比较逻辑异常 | 始终用 `x.y.z.w` 格式 | +| 8 | **manifest.json 的 mainAppName 不匹配真实进程名** | 更新后主程序找不到 | 和实际 exe 名称一致 | +| 9 | **为 v9.x 编写的代码直接用在 v10** | API 不兼容,编译失败 | 对照 v10.4.6 稳定版 API 重写 | --- diff --git a/cli/assets/skills/generalupdate-init/reference.md b/cli/assets/skills/generalupdate-init/reference.md index 6d33d30..f74f44e 100644 --- a/cli/assets/skills/generalupdate-init/reference.md +++ b/cli/assets/skills/generalupdate-init/reference.md @@ -14,10 +14,10 @@ | `GeneralUpdate.Extension` | 插件管理系统 | ❌ 可选 | net8.0;net10.0 | ≥ 10.5.0 | | `GeneralUpdate.Drivelution` | Windows 驱动更新 | ❌ 可选 | net8.0;net10.0 | 10.5.0-beta.4 | -> ⚠️ **NuGet 类型冲突**: +> ⚠️ **NuGet 注意事项**(v10.5.0-beta.4): > - `GeneralUpdate.Differential` 的 `DifferentialCore` 等类型已内嵌在 `GeneralUpdate.Core` 中,**不需额外引用**(直接使用 Core 即可) -> - `GeneralUpdate.Bowl` 和 `GeneralUpdate.Core` **不能同时引用**(两者都发布了 `GeneralUpdate.Common` 导致 CS0433) -> - 使用 Bowl 时**只引用 `GeneralUpdate.Bowl`**(它传递依赖 Core 的所有功能) +> - `GeneralUpdate.Bowl` 和 `GeneralUpdate.Core` **可以同时引用**(v10.5.0-beta.4 中 Bowl 与 Core 无共用类型,不再冲突) +> - 使用 Bowl 时仍需引用 `GeneralUpdate.Bowl`(它**不**传递依赖 Core) ## UpdateRequest 字段完整说明 diff --git a/cli/assets/skills/generalupdate-migration/SKILL.md b/cli/assets/skills/generalupdate-migration/SKILL.md index 8ce5c64..839dda7 100644 --- a/cli/assets/skills/generalupdate-migration/SKILL.md +++ b/cli/assets/skills/generalupdate-migration/SKILL.md @@ -118,7 +118,7 @@ await new GeneralUpdateBootstrap() ### 编译验证 - [ ] `dotnet build` 无错误 - [ ] 无 `MissingMethodException` 的风险(检查所有方法名是否存在于 v10.4.6) -- [ ] 无 `CS0433` 类型冲突(Core + Bowl 不同时引用) +- [ ] 无 `CS0433` 类型冲突(v10.5.0-beta.4 中 Core + Bowl 无冲突,可同时引用) ### 架构验证 - [ ] 项目已拆分为 Client + Upgrade 两个独立项目 diff --git a/cli/package-lock.json b/cli/package-lock.json new file mode 100644 index 0000000..7c654ac --- /dev/null +++ b/cli/package-lock.json @@ -0,0 +1,348 @@ +{ + "name": "gskill-cli", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "gskill-cli", + "version": "0.1.0", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.0.0", + "ora": "^8.0.0", + "prompts": "^2.4.2" + }, + "bin": { + "gskill": "dist/index.js" + }, + "devDependencies": { + "@types/node": "^20.0.0", + "@types/prompts": "^2.4.0", + "typescript": "^5.4.0" + } + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/prompts": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.9.tgz", + "integrity": "sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "kleur": "^3.0.3" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/cli/package.json b/cli/package.json index f39db19..525a6b0 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,7 +1,7 @@ { "name": "gskill-cli", "version": "0.1.0", - "description": "CLI to install GeneralUpdate skill for AI coding assistants", + "description": "CLI to install GeneralUpdate skill for AI coding assistants (version independent from skill version; skill matches manifest version)", "type": "module", "bin": { "gskill": "./dist/index.js" diff --git a/cli/src/commands/uninstall.ts b/cli/src/commands/uninstall.ts index 6459496..fa9fcd5 100644 --- a/cli/src/commands/uninstall.ts +++ b/cli/src/commands/uninstall.ts @@ -97,11 +97,12 @@ export async function uninstallCommand(options: UninstallOptions): Promise const allRemoved: string[] = []; if (aiType === 'all') { - for (const type of initialDetected) { + for (const type of initialDetected.filter((t): t is Exclude => t !== 'all')) { const removed = await removeSkillDir(baseDir, type); allRemoved.push(...removed); } } else { + // aiType is narrowed to Exclude by the === 'all' check above const removed = await removeSkillDir(baseDir, aiType); allRemoved.push(...removed); } diff --git a/skill.json b/skill.json index fa167ae..ac70fff 100644 --- a/skill.json +++ b/skill.json @@ -2,7 +2,7 @@ "name": "generalupdate-skill", "displayName": "GeneralUpdate Skill CodeGen", "description": "AI-powered skill suite for integrating GeneralUpdate (.NET auto-update) into any .NET application. Generates dual-project scaffolding (Client+Upgrade), full-state update UI (6 frameworks), 6 update strategies (Client-Server/OSS/Silent/Differential/CVP/Push), advanced extension points (Bowl crash daemon, IPC replacement, AOT), and deep troubleshooting (50+ known issues). All templates target NuGet v10.5.0-beta.4.", - "version": "0.0.1-beta.1", + "version": "0.0.2-beta.1", "author": "JusterZhu", "license": "Apache-2.0", "homepage": "https://github.com/GeneralLibrary/GeneralUpdate",