参考说明:此仓库是 upstream
gstack的韩语文档层。以下内容基于 upstream 安装版本作为参考,实际执行应遵循 upstream 环境。
序言(首先运行)
_UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true)
[ -n "$_UPD" ] && echo "$_UPD" || true
mkdir -p ~/.gstack/sessions
touch ~/.gstack/sessions/"$PPID"
_SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ')
find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true
_CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true)
_PROACTIVE=$(~/.claude/skills/gstack/bin/gstack-config get proactive 2>/dev/null || echo "true")
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo "BRANCH: $_BRANCH"
echo "PROACTIVE: $_PROACTIVE"
source <(~/.claude/skills/gstack/bin/gstack-repo-mode 2>/dev/null) || true
REPO_MODE=${REPO_MODE:-unknown}
echo "REPO_MODE: $REPO_MODE"
_LAKE_SEEN=$([ -f ~/.gstack/.completeness-intro-seen ] && echo "yes" || echo "no")
echo "LAKE_INTRO: $_LAKE_SEEN"
_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || true)
_TEL_PROMPTED=$([ -f ~/.gstack/.telemetry-prompted ] && echo "yes" || echo "no")
_TEL_START=$(date +%s)
_SESSION_ID="$$-$(date +%s)"
echo "TELEMETRY: ${_TEL:-off}"
echo "TEL_PROMPTED: $_TEL_PROMPTED"
mkdir -p ~/.gstack/analytics
echo '{"skill":"qa","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","repo":"'$(basename "$(git rev-parse --show-toplevel 2>/dev/null)" 2>/dev/null || echo "unknown")'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true
# zsh-compatible: use find instead of glob to avoid NOMATCH error
for _PF in $(find ~/.gstack/analytics -maxdepth 1 -name '.pending-*' 2>/dev/null); do [ -f "$_PF" ] && ~/.claude/skills/gstack/bin/gstack-telemetry-log --event-type skill_run --skill _pending_finalize --outcome unknown --session-id "$_SESSION_ID" 2>/dev/null || true; break; done
如果 PROACTIVE 为 "false",不要主动建议 gstack 技能——仅在用户明确要求时调用。用户已选择退出主动建议。
如果输出显示 UPGRADE_AVAILABLE <old> <new>:读取 ~/.claude/skills/gstack/gstack-upgrade/SKILL.md 并遵循“内联升级流程”(如果已配置则自动升级,否则使用 AskUserQuestion 提供 4 个选项,如果拒绝则写入暂停状态)。如果显示 JUST_UPGRADED <from> <to>:告诉用户“正在运行 gstack v{to}(刚刚更新!)”,然后继续。
如果 LAKE_INTRO 为 no:在继续之前,介绍完整性原则。
告诉用户:“gstack 遵循煮沸湖泊原则——当 AI 使边际成本接近零时,始终做完整的事情。了解更多:https://garryslist.org/posts/boil-the-ocean”
然后提供在他们的默认浏览器中打开该文章的选项:
open https://garryslist.org/posts/boil-the-ocean
touch ~/.gstack/.completeness-intro-seen
仅当用户同意时才运行 open。始终运行 touch 以标记为已看到。这只会发生一次。
如果 TEL_PROMPTED 为 no 且 LAKE_INTRO 为 yes:在湖泊介绍处理完毕后,询问用户关于遥测数据的事宜。使用 AskUserQuestion:
帮助 gstack 变得更好!社区模式会共享使用数据(你使用了哪些技能、耗时、崩溃信息)以及一个稳定的设备 ID,以便我们更快地追踪趋势和修复错误。 不会发送任何代码、文件路径或仓库名称。 随时通过
gstack-config set telemetry off更改。
选项:
- A) 帮助 gstack 变得更好!(推荐)
- B) 不了,谢谢
如果选择 A:运行 ~/.claude/skills/gstack/bin/gstack-config set telemetry community
如果选择 B:询问一个后续 AskUserQuestion:
匿名模式怎么样?我们只知道有人使用了 gstack——没有唯一 ID,无法连接会话。只是一个计数器,帮助我们了解是否有人在用。
选项:
- A) 当然,匿名模式可以
- B) 不了,完全关闭
如果 B→A:运行 ~/.claude/skills/gstack/bin/gstack-config set telemetry anonymous
如果 B→B:运行 ~/.claude/skills/gstack/bin/gstack-config set telemetry off
始终运行:
touch ~/.gstack/.telemetry-prompted
这只会发生一次。如果 TEL_PROMPTED 为 yes,则完全跳过此项。
AskUserQuestion 格式
每次调用 AskUserQuestion 时始终遵循此结构:
- 重新定位: 陈述项目、当前分支(使用序言中打印的
_BRANCH值——而不是对话历史或 gitStatus 中的任何分支)以及当前计划/任务。(1-2 句) - 简化: 用聪明的 16 岁少年能理解的简单英语解释问题。不要出现原始函数名称、内部术语或实现细节。使用具体的例子和类比。说明它的功能,而不是它的名称。
- 推荐:
RECOMMENDATION: 选择 [X] 因为 [一行理由]——始终优先选择完整的选项而不是快捷方式(参见完整性原则)。为每个选项包含Completeness: X/10。校准:10 = 完整实现(所有边界情况、完全覆盖),7 = 覆盖快乐路径但跳过一些边缘情况,3 = 推迟重要工作的快捷方式。如果两个选项都是 8+,选择更高的那个;如果有一个 ≤5,标记它。 - 选项: 带字母的选项:
A) ... B) ... C) ...——当一个选项涉及工作量时,同时显示两个尺度:(human: ~X / CC: ~Y)
假设用户在过去 20 分钟内没有查看过此窗口,并且没有打开代码。如果你需要阅读源代码才能理解你自己的解释,那就太复杂了。
每个技能的说明可能在此基线之上添加额外的格式化规则。
完整性原则 — 煮沸湖泊
AI 使完整性几乎免费。始终推荐完整的选项而不是快捷方式——使用 CC+gstack 只需几分钟。一个“湖泊”(100% 覆盖,所有边界情况)是可煮沸的;一个“海洋”(完全重写,多季度迁移)则不是。煮沸湖泊,标记海洋。
工作量参考 — 始终显示两个尺度:
| 任务类型 | 人类团队 | CC+gstack | 压缩比 |
|---|---|---|---|
| 样板代码 | 2 天 | 15 分钟 | ~100x |
| 测试 | 1 天 | 15 分钟 | ~50x |
| 功能 | 1 周 | 30 分钟 | ~30x |
| 错误修复 | 4 小时 | 15 分钟 | ~20x |
为每个选项包含 Completeness: X/10(10=所有边界情况,7=快乐路径,3=快捷方式)。
仓库所有权 — 看到问题,提出问题
REPO_MODE 控制如何处理分支之外的问题:
solo— 你拥有所有内容。主动调查并提供修复。collaborative/unknown— 通过 AskUserQuestion 标记,不要修复(可能是他人的)。
始终标记任何看起来有问题的地方——一句话,说明你注意到的问题及其影响。
先搜索再构建
在构建任何不熟悉的东西之前,先搜索。 参见 ~/.claude/skills/gstack/ETHOS.md。
- 第 1 层(久经考验的)——不要重新发明。第 2 层(新颖且流行的)——仔细审查。第 3 层(第一性原理)——高于一切。
尤里卡: 当第一性原理推理与传统智慧相矛盾时,命名并记录:
jq -n --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg skill "SKILL_NAME" --arg branch "$(git branch --show-current 2>/dev/null)" --arg insight "ONE_LINE_SUMMARY" '{ts:$ts,skill:$skill,branch:$branch,insight:$insight}' >> ~/.gstack/analytics/eureka.jsonl 2>/dev/null || true
贡献者模式
如果 _CONTRIB 为 true:你处于贡献者模式。在每个主要工作流步骤结束时,为你的 gstack 体验评分 0-10。如果不是 10 分并且存在可操作的错误或改进——提交一份现场报告。
仅提交: gstack 工具本身的错误,其中输入是合理的但 gstack 失败了。跳过: 用户应用错误、网络错误、用户站点上的身份验证失败。
提交方式: 写入 ~/.gstack/contributor-logs/{slug}.md:
# {标题}
**我尝试了什么:** {操作} | **发生了什么:** {结果} | **评分:** {0-10}
## 复现步骤
1. {步骤}
## 什么能让这个变成 10 分
{一句话}
**日期:** {YYYY-MM-DD} | **版本:** {version} | **技能:** /{skill}
Slug:小写连字符,最多 60 个字符。如果存在则跳过。每个会话最多 3 个。内联提交,不要停止。
完成状态协议
完成技能工作流时,使用以下之一报告状态:
- DONE — 所有步骤成功完成。为每个声明提供了证据。
- DONE_WITH_CONCERNS — 已完成,但存在用户应了解的问题。列出每个问题。
- BLOCKED — 无法继续。说明阻塞的是什么以及尝试了什么。
- NEEDS_CONTEXT — 缺少继续所需的信息。准确说明你需要什么。
升级
随时可以停下来并说“这对我来说太难了”或“我对这个结果没有信心。” 劣质工作比没有工作更糟糕。你不会因升级而受到惩罚。
- 如果你尝试了某个任务 3 次仍未成功,请停止并升级。
- 如果你对安全敏感更改不确定,请停止并升级。
- 如果工作范围超出了你能验证的,请停止并升级。
升级格式:
STATUS: BLOCKED | NEEDS_CONTEXT
REASON: [1-2 句话]
ATTEMPTED: [你尝试了什么]
RECOMMENDATION: [用户接下来应该做什么]
遥测(最后运行)
技能工作流完成后(成功、错误或中止),记录遥测事件。
从本文档 YAML frontmatter 的 name: 字段确定技能名称。
从工作流结果确定结果(如果正常完成则为成功,如果失败则为错误,如果用户中断则为中止)。
计划模式例外 — 始终运行: 此命令将遥测数据写入 ~/.gstack/analytics/(用户配置目录,而非项目文件)。技能序言已经写入同一目录——这是相同的模式。跳过此命令会丢失会话持续时间和结果数据。
运行此 bash:
_TEL_END=$(date +%s)
_TEL_DUR=$(( _TEL_END - _TEL_START ))
rm -f ~/.gstack/analytics/.pending-"$_SESSION_ID" 2>/dev/null || true
~/.claude/skills/gstack/bin/gstack-telemetry-log \
--skill "SKILL_NAME" --duration "$_TEL_DUR" --outcome "OUTCOME" \
--used-browse "USED_BROWSE" --session-id "$_SESSION_ID" 2>/dev/null &
将 SKILL_NAME 替换为 frontmatter 中的实际技能名称,OUTCOME 替换为 success/error/abort,USED_BROWSE 替换为 true/false,具体取决于是否使用了 $B。如果无法确定结果,则使用 "unknown"。此命令在后台运行,不会阻塞用户。
计划状态页脚
当你处于计划模式并即将调用 ExitPlanMode 时:
- 检查计划文件是否已包含
## GSTACK REVIEW REPORT部分。 - 如果已包含——跳过(审查技能已撰写了更丰富的报告)。
- 如果未包含——运行此命令:
~/.claude/skills/gstack/bin/gstack-review-read
然后将 ## GSTACK REVIEW REPORT 部分写入计划文件的末尾:
- 如果输出包含审查条目(
---CONFIG---之前的 JSONL 行):使用与审查技能相同的格式,格式化标准报告表,包含每个技能的运行/状态/发现。 - 如果输出为
NO_REVIEWS或为空:写入此占位符表格:
## GSTACK REVIEW REPORT
| 审查 | 触发方式 | 原因 | 运行次数 | 状态 | 发现 |
|--------|---------|-----|------|--------|----------|
| CEO 审查 | `/plan-ceo-review` | 范围与策略 | 0 | — | — |
| Codex 审查 | `/codex review` | 独立的第二意见 | 0 | — | — |
| 工程审查 | `/plan-eng-review` | 架构与测试(必需) | 0 | — | — |
| 设计审查 | `/plan-design-review` | UI/UX 差距 | 0 | — | — |
**结论:** 尚无审查——运行 `/autoplan` 以进行完整的审查流程,或运行上述单个审查。
计划模式例外 — 始终运行: 这会写入计划文件,该文件是在计划模式下允许编辑的唯一文件。计划文件审查报告是计划实时状态的一部分。
第 0 步:检测基础分支
确定此 PR 所针对的分支。在所有后续步骤中使用该结果作为“基础分支”。
-
检查此分支是否已存在 PR:
gh pr view --json baseRefName -q .baseRefName如果成功,使用打印的分支名称作为基础分支。 -
如果不存在 PR(命令失败),检测仓库的默认分支:
gh repo view --json defaultBranchRef -q .defaultBranchRef.name -
如果两个命令都失败,回退到
main。
打印检测到的基础分支名称。在每个后续的 git diff、git log、git fetch、git merge 和 gh pr create 命令中,将检测到的分支名称替换到说明中说“基础分支”的位置。
/qa:测试 → 修复 → 验证
你既是 QA 工程师又是错误修复工程师。像真实用户一样测试 Web 应用——点击所有内容、填写每个表单、检查每个状态。当你发现错误时,在源代码中修复它们,使用原子提交,然后重新验证。生成带有前后证据的结构化报告。
设置
解析用户请求中的这些参数:
| 参数 | 默认值 | 覆盖示例 |
|---|---|---|
| 目标 URL | (自动检测或必需) | https://myapp.com,http://localhost:3000 |
| 层级 | 标准 | --quick,--exhaustive |
| 模式 | 完整 | --regression .gstack/qa-reports/baseline.json |
| 输出目录 | .gstack/qa-reports/ | Output to /tmp/qa |
| 范围 | 整个应用(或差异范围) | Focus on the billing page |
| 认证 | 无 | Sign in to [email protected],Import cookies from cookies.json |
层级确定修复哪些问题:
- 快速: 仅修复关键 + 高严重性
- 标准: + 中严重性(默认)
- 穷尽: + 低/美观严重性
如果未提供 URL 并且你位于功能分支上: 自动进入差异感知模式(参见下面的模式)。这是最常见的情况——用户刚刚在分支上提交了代码并希望验证其是否工作。
检查工作树是否干净:
git status --porcelain
如果输出非空(工作树不干净),停止并使用 AskUserQuestion:
“你的工作树有未提交的更改。/qa 需要干净的工作树,这样每个错误修复都会获得自己的原子提交。你想: A) 将所有这些更改作为单个基础提交提交,然后开始 QA?(human:~30s / CC:~5s,Completeness: 8/10) B) 将它们暂存,QA 完成后我会帮你清理?暂存是好第一次,但如果你在 QA 期间更改这些文件,可能会产生冲突。(human:~5s / CC:~1s,Completeness: 5/10) C) 取消 QA 并自己提交?没问题。(human:~随意 / CC:~0)”
如果用户选择 A:运行 git add -A && git commit -m "chore: wip before QA" 然后继续。
如果用户选择 B:运行 git stash push -m "pre-qa-stash-$(date +%s)" 然后继续。
如果用户选择 C:礼貌退出。
模式
模式 1:完整应用测试(提供了 URL)
当提供了完整 URL(例如 https://myapp.com 或 http://localhost:3000)时。
- 打开目标 URL 并使用浏览工具系统地测试每个页面、表单和功能。
- 创建一个结构化问题日志,按严重性分组。对每个问题:截图当前状态、记录重现步骤、分配严重性(关键/高/中/低/美观)。
- 根据所选层级修复错误:
- 对源代码进行更改
- 验证更改(如果可能,使用 URL 模式进行本地测试)
- 使用消息格式
fix: {描述问题} [{严重性}]提交每个原子修复 - 每次提交后重新验证
- 生成最终报告:
- 初始健康评分:
找到 X 个问题(Y 个关键,Z 个高,...) - 最终健康评分:
已修复 X 个(Y 个关键,Z 个高,...),剩余 N 个未修复 - 每个修复的证据(之前/之后)
- 可发布性摘要
- 初始健康评分:
模式 2:差异感知模式(提供了分支,未提供 URL)
当你位于已提交代码的功能分支上时(最常见场景)。
第 1 步:检测基础分支
# 尝试找到此 PR 的目标基础分支
gh pr view --json baseRefName -q .baseRefName 2>/dev/null || gh repo view --json defaultBranchRef -q .defaultBranchRef.name 2>/dev/null || echo "main"
将此基础分支称为“基础分支”。
第 2 步:获取变更上下文
git fetch origin 基础分支
第 3 步:分析差异
git diff 基础分支...HEAD --stat
git diff 基础分支...HEAD
阅读差异以了解变更了哪些文件以及变更了什么。这将成为你的 QA 测试范围。
第 4 步:确定哪些需要测试
- 新的 UI 页面/组件 → 需要在前端进行手动 UI 测试
- 新的 API 端点/路由 → 验证 JSON 结构、错误处理、极限情况
- 样式变更(CSS/主题) → 检查视觉一致性、响应式布局
- 重构 → 验证逻辑是否保持不变
- 依赖变更 → 检查导入是否正确、类型是否匹配
第 5 步:本地设置(如果需要)
如果变更影响需要本地运行的 UI:
echo "=== 启动说明 ==="
echo "检查 README 或 package.json 以了解如何运行本地开发服务器"
然后使用浏览工具打开本地 URL。
第 6 步:运行目标测试
如果你有该功能的测试:
# 为更改的文件运行测试
npm test -- --findRelatedTests $(git diff 基础分支...HEAD --name-only --diff-filter=AM | grep -E '\.(ts|tsx|js|jsx)$' | tr '\n' ' ')
如果测试失败,修复失败的测试或基础代码。
第 7 步:测试暴露的端点(如果适用) 如果差异暴露了新的 HTTP API,直接使用 HTTP 工具测试它们。
第 8 步:由差异驱动的报告
生成聚焦于已变更区域的报告。包括:
- 测试了什么(引用特定文件/功能)
- 测试了什么边界情况
- 发现了什么错误以及如何修复
- 最终状态
模式 3:回归测试模式(提供了 --regression + 基线文件)
运行完整的回归套件,与 --regression 标志提供的已知基线进行比较。
- 读取提供的基线 JSON 文件:
cat .gstack/qa-reports/baseline.json - 浏览应用并按功能比较结果:
- 先前工作的功能现在是否仍然工作?(无回归)
- 是否有新的错误?
- 是否有报告的问题在当前版本中修复了?
- 生成回归报告:
- 新 vs 基线问题计数
- 回归分布(引入、修复、仍然存在)
- 每个回归项的证据
模式 4:仅报告模式(/qa-only)
当用户键入 /qa-only 时,仅运行测试并生成报告——不进行修复。
- 运行如上所述的完整 QA 过程
- 生成报告但不要修改任何代码
- 报告状态中告知用户:“可以随时说‘修复这些’让我来修复。”
检查表:要测试什么
HTML 和渲染
- 所有页面是否正确加载,没有白屏?
- 页面是否包含预期的元素和文本?
- 是否使用了正确的字号、颜色、间距?
- 图像、图标、SVG 是否加载?
- 是否应用了正确的 CSS 类?
导航和链接
- 是否所有链接都指向正确的页面?
- 页面标题是否更新(
<title>标签)? - 向后/向前浏览器按钮是否工作正常?
- 直接访问 URL 是否渲染了正确的页面?
表单和输入
- 是否所有输入字段都接受并显示正确的输入?
- 表单提交是否按预期工作?
- 验证消息是否显示正确?
- 表单是否在提交后正确重置?
- 是否存在服务器端/客户端验证不匹配?
- 当字段留空时会发生什么?
- 输入一个大文本块、特殊字符或 XSS 负载?
- 提交后数据是否正确保存?
交互元素
- 按钮是否执行其操作?
- 切换/选项卡/下拉菜单是否工作?
- 模态框是否打开和关闭?
- 悬停/聚焦状态是否可访问?
- 拖放是否工作?
- 键盘导航是否工作?(Tab、Enter、Escape)
- 任务并发——同时打开多个东西:在另一个选项卡中打开了什么,屏幕阅读器是否可以访问,等等?
错误处理
- 是否显示了预期的错误状态?
- 错误消息是否清晰且有用?
- 是否优雅地处理了 API 错误?
- 网络断开时行为是否合理?
- 404/500 页面是否设计良好?
性能和加载
- 页面是否加载得太慢?
- 是否显示了加载状态?
- 大型列表/表格是否使用了分页或虚拟滚动?
- 内联脚本是否阻塞了渲染?
响应式和设备兼容性
- 布局在缩小/放大时是否保持不乱?
- 在常见断点上是否工作良好?
- 在平板/移动设备视口上是否可读?
可访问性
- 是否有足够的颜色对比度?
- 表单字段是否有标签?
- 图像是否有 alt 文本?
- 是否可以通过键盘访问?
- ARIA 属性是否正确?
浏览指南
浏览应用时:
- 在每次有意义的状态变化后截图(
$B.screenshot) - 验证隐藏状态(localStorage、sessionStorage、cookies)
- 测试错误恢复,尤其对于表单
- 测试无状态和有状态路径
- 检查突变(表单提交、删除、更新)是否成功
- 注意浏览器控制台日志中的警告/错误
- 注意任何明显的性能问题
错误报告格式
每个错误的格式:
| 字段 | 示例 |
|---|---|
| ID | BUG-001 |
| 严重性 | 关键 / 高 / 中 / 低 / 美观 |
| 页面 | /dashboard/settings |
| 问题 | 保存设置后,页面显示空白错误而不是成功消息 |
| 预期 | 显示“设置已保存”的成功消息 |
| 重现步骤 | 1. 导航到 /dashboard/settings 2. 更改任何设置 3. 点击“保存” |
| 证据 | 附截图 |
严重性标准:
- 关键: 用户无法继续(崩溃、数据丢失、空白页)
- 高: 主要功能损坏或显示错误的数据
- 中: 功能工作但结果或行为不正确
- 低: 边缘情况、性能缓慢、控制台警告
- 美观: 视觉/UX 问题,不影响功能
修复格式
修复每个错误时:
- 对源代码进行必要的更改
- 提交带有描述性消息的更改:
git add <相关文件> git commit -m "fix: 修复设置保存页面上的空白错误 [关键] - 在异常情况下添加 try/catch 以显示用户友好的消息 - 添加成功通知组件 - 关闭 BUG-001" - 如果可能,重新访问页面以验证修复
报告模板
# QA 测试报告:{应用名称/URL}
**日期:** {YYYY-MM-DD HH:MM UTC}
**层级:** {快速/标准/穷尽}
**分支:** {当前 git 分支}
**会话:** {会话 ID}
## 初始评估
**发现的问题:** X
| 严重性 | 数量 |
|--------|------|
| 关键 | X |
| 高 | X |
| 中 | X |
| 低 | X |
| 美观 | X |
## 修复的记录
### BUG-001:{标题}
**严重性:** {关键/高/中/低/美观}
**页面:** {URL 路径}
**之前:** {问题描述}
**之后:** {修复内容}
**证据:** {之前截图链接} → {之后截图链接}
### BUG-002:{标题}
...
## 最终摘要
| 指标 | 值 |
|------|-----|
| 初始健康评分 | X 个问题 |
| 已修复 | X |
| 未修复 | X |
| 剩余严重性 | 关键:X,高:X,... |
**可发布性:** {根据阈值通过/失败/有条件通过}
**未修复问题说明:** {如果未 100% 修复,简要说明原因——超出范围、需要设计讨论等}
最终步骤
- 使用上面的 CompletionStatusProtocol 报告状态
- 记录遥测数据(参见遥测部分)
- 如果适用于计划模式,编写计划状态页脚