ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

gstack /ios-fix:基于真机状态快照的 iOS 自主 Bug 修复闭环工作流

2026/9/7 6:37:04 拓冰建站 浏览量
gstack /ios-fix:基于真机状态快照的 iOS 自主 Bug 修复闭环工作流 gstack /ios-fix基于真机状态快照的 iOS 自主 Bug 修复闭环工作流【免费下载链接】gstackUse Garry Tans exact Claude Code setup: 23 opinionated tools that serve as CEO, Designer, Eng Manager, Release Manager, Doc Engineer, and QA项目地址: https://gitcode.com/GitHub_Trending/gs/gstackgstack 中的/ios-fix技能把发现 bug → 复现 bug → 定位根因 → 修复 → 真机验证 → 固化回归测试串成一条零人工干预的自主修复流水线并立下一条铁律没有可复现的状态快照就不许动任何一行 Swift 源码。读完本文你将掌握该技能的五阶段修复协议、真机控制链daemon StateServer的端点与权限分层、快照字段的默认拒绝机制以及重建后409 schema_mismatch等典型故障的处理方式。一、技能定位/ios-qa 负责找 bug/ios-fix 负责修 bug/ios-fix定义在 ios-fix/SKILL.md 中是一份 Claude Code 技能文件skill 文件即可执行指令Agent 逐条照做而非仅作参考资料。其 frontmatter 声明了技能的元信息name: ios-fix preamble-tier: 3 version: 1.0.0 description: Autonomous iOS bug fixer. (gstack) allowed-tools: - Bash - Read - Write - Edit - Grep - Glob - AskUserQuestion triggers: - fix this ios bug - patch the iphone app - auto-fix the ios issue几个关键字段的含义triggers三种自然语言触发短语fix this ios bug、patch the iphone app、auto-fix the ios issue用户说出这些话或/ios-qa报告了 bug 后想要自动修复时技能会被调用语音触发别名包括 fix the iOS bug、patch the iPhone app 等。allowed-tools技能运行期间被允许使用的宿主工具集——Bash、Read、Write、Edit、Grep、Glob外加用于向用户提问的 AskUserQuestion。preamble-tier: 3该技能携带第三档前导程序Preamble即所有 gstack 技能共享的一段运行时引导逻辑详见第五节。上游依赖是/ios-qaios-qa/SKILL.md/ios-qa负责驱动真机做 QA 并产出 bug 发现bug 描述、截图、疑似的 accessibility-tree 节点/ios-fix负责消费这份发现并闭环修复。官方文档对两者的分工概括为Iron Law: no fix without a reproducing snapshot. The agent captures pre-bug state viaGET /state/snapshot, writes the fix, rebuilds, redeploys, restores the snapshot, and verifies the bug is gone. The snapshot becomes a regression test fixture so the bug cant recur silently. —— docs/skills.md二、铁律没有复现快照就不许修技能正文开头ios-fix/SKILL.md立下整条流水线的锚NO FIX WITHOUT A REPRODUCING SNAPSHOT.在编辑任何 Swift 源码之前Agent 必须先抓取一个能复现该 bug 的GET /state/snapshot。该快照会沉淀为回归测试夹具test/fixtures/ios-fix/。 没有复现快照就落地的修复等于三个月后还得再修一次。这条铁律的技术支撑是 gstack iOS 能力里的状态快照机制iOS 应用内嵌一个StateServerDebugBridgeSPM 库仅#if DEBUG编译监听::1/127.0.0.19999 端口其中被// Snapshotable标记的字段可以被完整导出为 JSON并可通过POST /state/restore全量恢复。快照因此既是复现手段restore 到 bug 状态也是验证手段恢复后截图对比还是回归夹具提交进仓库。三、五阶段修复协议Phase 1复现 bug读取/ios-qa的 bug 发现bug 描述、截图、疑似出错的 accessibility-tree 节点通过POST /tap、/swipe、/type或POST /state/key仅限可快照字段把设备带入 bug 状态抓取GET /state/snapshot→ 写入test/fixtures/ios-fix/bug-slug-pre.json抓取GET /screenshot→ 写入test/fixtures/ios-fix/bug-slug-pre.png用一行文字固化哪里错了 期望行为。注意第 2 步的分层约束直接操作 UItap/swipe/type走interact权限层而写状态字段POST /state/key走更高的mutate层恢复整个快照POST /state/restore则是最高层restore。权限分层在 daemon 源码 ios-qa/daemon/src/types.ts 中逐条映射export const TAILNET_ENDPOINT_TIERS: Recordstring, Capability { GET /screenshot: observe, GET /state/snapshot: observe, POST /tap: interact, POST /swipe: interact, POST /type: interact, POST /state/*: mutate, // 通配/state/ 下的写操作 POST /state/restore: restore, // 最高层 };四个权限层是嵌套的observe ⊂ interact ⊂ mutate ⊂ restore原则是最小够用。这意味着复现阶段把设备带到 bug 状态这个动作本身就受到权限审计见第五节审计日志而不是随意的黑盒操作。Phase 2定位根因沿用/investigate的铁律没有根因就不修。Agent 读取 Swift 源码从出错的屏幕反向追踪到 view model、数据流、状态变更点并找出能修复行为的最小改动。如果存在多个可信的根因假设协议要求使用 AskUserQuestion 让用户选择要修哪一个——这是整条零人工干预流水线中唯一被明确允许的人工介入点。gstack 对 AskUserQuestion 有严格格式规范D 决策简报、ELI10 白话解释、每选项完整性评分、(recommended)标签其拆分链完整规则见 docs/askuserquestion-split.mdCJK 文本直接输出规范见 docs/askuserquestion-cjk.md。Phase 3应用修复编辑 Swift 源码diff 保持最小化重建xcodebuild -scheme SchemeName -destination platformiOS,idUDID build installdaemon 感知到重建重新连接 StateServer 隧道重新部署——执行与首次启动相同的 boot-token 轮换流程app 内的一次性启动 token 在 daemon 侧被消费后轮换为内存态凭证约 5 秒内完成防止日志抓取者拿到长期凭证。这里与 docs/howto-ios-testing-with-gstack.md 描述的部署流程一致xcodebuild构建后通过xcrun devicectl device install app/device process launch --terminate-existing装机并拉起daemon 通过 CoreDevice IPv6 ULA 隧道中转流量iOS 侧 StateServer 始终只绑 loopback身份校验全部发生在 Mac 侧。Phase 4验证用修复前的快照调POST /state/restore→ 在真机上精确重现 bug 前的状态重新截图与test/fixtures/ios-fix/bug-slug-pre.png对比bug 仍可见 → 修复失败回滚改动重试最多 3 轮后升级给用户bug 消失→ 抓一张bug-slug-post.png存档供回归测试引用。restore 后验证正是快照机制的核心价值修复效果不依赖人工把手机点回原状态而是用同一份 JSON 确定性还原。Phase 5固化回归测试在test/fixtures/ios-fix/bug-slug.test.ts写一个测试要求三步加载修复前快照通过POST /state/restore还原到 bug 状态在真机上断言修复后的行为——该测试受环境变量GSTACK_HAS_IOS_DEVICE1门控归属periodic周期性测试层即只在挂了真机的环境里跑CI 无设备时自动跳过。快照夹具 测试文件与修复代码一同提交。至此闭环完成下次任何人包括未来的 Agent跑回归测试就能在真机上确定性复现修复前状态bug 无法静默复发。四、快照机制的底层细节理解五阶段协议必须理解Snapshotable快照的设计约束完整说明见 docs/howto-ios-testing-with-gstack.mdObservable final class AppState { // Snapshotable var username: String var authToken: String // never exported }默认拒绝default-deny只有字段上方带独立标记注释// Snapshotable的实例var才会被导出token、PII、鉴权状态默认不会出现在快照里避免敏感数据被写进提交到仓库的回归夹具类型白名单标记字段必须是 JSON 原生标量String、Bool、各宽度整数、Float、Double、CGFloat、数组、String 键字典及其 Optional 组合非法声明自定义值、IUO、嵌套 observable、重复 key会让生成器报错停止而不是产出有损 Swift两阶段恢复POST /state/restore先让每个模型校验完整输入全部通过后才在 MainActor 上执行赋值避免恢复一半的坏状态构建防泄漏Package.swift用.when(configuration: .debug)从结构上禁止 Release 构建链接任何DebugBridge*target正式发布前用/ios-cleanios-clean/SKILL.md移除依赖并剥掉#if DEBUG接线。版本防错409 schema_mismatch快照信封中携带_accessor_hash——访问器代码的哈希。若某份快照是在旧版 app 构建上抓的新构建恢复它会大声地以 409 schema_mismatch 拒绝而不是静默写坏状态见 CHANGELOG.md 中 iOS 能力的发布记录。这正是重建后快照失效这一高频故障的防线也是下一节故障表的来源。五、技能运行时契约共享前导与收尾/ios-fix与其他 gstack 技能一样执行前有一段共享 Preamble由 SKILL.md.tmpl 中的{{PREAMBLE}}占位符在生成时注入SKILL.md头部注明 AUTO-GENERATED from SKILL.md.tmpl — do not edit directly重新生成命令为bun run gen:skill-docs。前导程序按序完成更新检查与会话登记运行gstack-update-check在~/.gstack/sessions/落一个以$PPID命名的会话文件并清理 120 分钟前的陈旧文件环境探测读取proactive、skill_prefix、telemetry、explain_level、question_tuning、update_check、checkpoint_mode/checkpoint_push等配置检测当前分支、会话类型spawned/headless/interactive非法值回退interactive、Conductor 宿主此时决策以 prose 渲染而非调用工具、plan-mode 状态GSTACK_PLAN_MODEactive/inactive默认 inactive 是安全回退遥测与学习注入telemetry 非 off 时向~/.gstack/analytics/skill-usage.jsonl追加一条{skill:ios-fix,...}记录加载本项目的learnings.jsonl超过 5 条时自动检索 top 3 相关学习向 timeline 记录started事件一次性引导各带标记文件只问一次首次运行按项目类型给一句话建议greenfield/code_ios/branch_ahead等 token 映射Boil the Ocean 完整性原则介绍telemetry 三档选择community/anonymous/offCLAUDE.md 技能路由规则注入vendored gstack 迁移提醒spawned 会话则全部静默、自动选择推荐项。工作流收尾时的契约包括Artifacts Sync 尾部运行gstack-brain-sync --discover-new与--once把本地产物计划、报告等按配置同步到 GBrain/artifacts 仓库持续检查点checkpoint_modecontinuous时完成一个逻辑单元即以WIP:前缀自动提交提交信息内嵌[gstack-context]块记录 Decisions/Remaining/Tried/ship时再压平成干净提交完成状态协议以DONE/DONE_WITH_CONCERNS/BLOCKED/NEEDS_CONTEXT之一收尾三次尝试失败、安全敏感不确定变更时按STATUS / REASON / ATTEMPTED / RECOMMENDATION格式升级经验沉淀结束前强制回顾可持久学习的坑项目怪癖、命令修正、可节省 5 分钟以上的模式用gstack-learnings-log记录确无可记时显式声明 No durable learnings this session遥测收尾PLAN MODE EXCEPTION — ALWAYS RUN写本地 timelinecompleted事件与本地 analytics远端遥测仅当用户 opt-in 且二进制存在时执行。六、故障模式与处理动作原文档ios-fix/SKILL.md给出的故障模式表完整保留如下症状处理动作3 轮迭代后 bug 仍在STOP把当前最优假设报告给用户重建后/state/restore返回409 schema_mismatch重新生成访问器swift run gen-accessors重新抓快照修复中途设备断连daemon 自动重连从 Phase 4 恢复执行构建失败回滚 Swift 改动先排查编译错误再重新应用修复补充两个来自/ios-qa故障表的相邻情况/ios-fix流程同样会遇到409 schema_mismatch的根因是快照抓自旧版 app 构建标准动作是丢弃旧快照重新抓取413 body_too_large表示快照超过 1MB 上限需要调大 daemon 的--max-body或裁剪快照字段见 ios-qa/SKILL.md 故障表。gen-accessors本身有 Swift 工具插件与 TS 回退双实现ios-qa/scripts/gen-accessors.ts缓存键为sha256(source || swift_version || tool_git_rev || platform_triple)——所以 Swift 版本变化、生成器自身 git rev 变化、源码变化都会使缓存失效这解释了为什么重建后快照 hash 不匹配是跨版本升级时的预期行为而非异常。七、运行前提与适用边界要跑通/ios-fix全闭环仓库文档给出的硬件/软件前提是docs/howto-ios-testing-with-gstack.mdmacOS Xcode 16.0xcrun devicectl --version可用CoreDevice 隧道依赖 Xcode 16iOS 16 真机已解锁、已配对、开启 Developer ModeApple 开发者团队免费个人团队即可gstack 已安装./setup完成gstack-ios-qa-regen与gstack-ios-qa-daemon在 PATH 上Bun 运行时在 PATH 上回归测试仅在GSTACK_HAS_IOS_DEVICE1的环境执行无设备环境只验证非真机部分iOS 17 及以下的设备存在 SwiftUI Button 点击不生效的平台限制_UIHitTestContext缺失/tap会返回ok:true但手势不触发需要 iOS 18 或改用 UIKit 控件。从仓库结构看该技能的模板与生成物一一对应ios-fix/SKILL.md.tmpl →gen:skill-docs→ ios-fix/SKILL.md修改工作流时应当改模板而非生成物其五阶段协议、铁律与故障表是可复制的操作规程而 daemon 端点表、权限分层、快照哈希校验则给出了这套规程能在真机上确定性执行的底层保证。【免费下载链接】gstackUse Garry Tans exact Claude Code setup: 23 opinionated tools that serve as CEO, Designer, Eng Manager, Release Manager, Doc Engineer, and QA项目地址: https://gitcode.com/GitHub_Trending/gs/gstack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考