ship
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly -->
<!-- Regenerate: bun run gen:skill-docs -->
<!-- 由SKILL.md.tmpl自动生成——请勿直接编辑 -->
<!-- 重新生成:bun run gen:skill-docs -->
Preamble (run first)
前置步骤(首先运行)
bash
_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)
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo "BRANCH: $_BRANCH"If output shows : read and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If : tell user "Running gstack v{to} (just updated!)" and continue.
UPGRADE_AVAILABLE <old> <new>~/.claude/skills/gstack/gstack-upgrade/SKILL.mdJUST_UPGRADED <from> <to>bash
_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)
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
echo "BRANCH: $_BRANCH"如果输出显示:请阅读并遵循"内联升级流程"(如果已配置则自动升级,否则向用户提供4个选项的问题,若用户拒绝则记录 snooze 状态)。如果显示:告知用户"正在运行gstack v{to}(刚刚完成更新!)"并继续后续步骤。
UPGRADE_AVAILABLE <old> <new>~/.claude/skills/gstack/gstack-upgrade/SKILL.mdJUST_UPGRADED <from> <to>AskUserQuestion Format
AskUserQuestion格式要求
ALWAYS follow this structure for every AskUserQuestion call:
- Re-ground: State the project, the current branch (use the value printed by the preamble — NOT any branch from conversation history or gitStatus), and the current plan/task. (1-2 sentences)
_BRANCH - Simplify: Explain the problem in plain English a smart 16-year-old could follow. No raw function names, no internal jargon, no implementation details. Use concrete examples and analogies. Say what it DOES, not what it's called.
- Recommend:
RECOMMENDATION: Choose [X] because [one-line reason] - Options: Lettered options:
A) ... B) ... C) ...
Assume the user hasn't looked at this window in 20 minutes and doesn't have the code open. If you'd need to read the source to understand your own explanation, it's too complex.
Per-skill instructions may add additional formatting rules on top of this baseline.
每次调用AskUserQuestion时必须严格遵循以下结构:
- 重新说明背景:说明项目名称、当前分支(使用前置步骤输出的值——而非对话历史或gitStatus中的任何分支)以及当前计划/任务。(1-2句话)
_BRANCH - 简化解释:用普通16岁青少年能理解的简单语言解释问题。不要使用原始函数名、内部术语或实现细节。使用具体示例和类比。说明功能是什么,而非叫什么名字。
- 推荐方案:
RECOMMENDATION: 选择[X],因为[一句话理由] - 选项:带字母的选项:
A) ... B) ... C) ...
假设用户已经20分钟没看这个窗口,且没有打开代码。如果你需要阅读源代码才能理解自己的解释,说明解释太复杂了。
针对特定技能的说明可能会在这个基础格式上添加额外的格式规则。
Contributor Mode
贡献者模式
If is : you are in contributor mode. You're a gstack user who also helps make it better.
_CONTRIBtrueAt the end of each major workflow step (not after every single command), reflect on the gstack tooling you used. Rate your experience 0 to 10. If it wasn't a 10, think about why. If there is an obvious, actionable bug OR an insightful, interesting thing that could have been done better by gstack code or skill markdown — file a field report. Maybe our contributor will help make us better!
Calibration — this is the bar: For example, used to fail with because gstack didn't wrap expressions in async context. Small, but the input was reasonable and gstack should have handled it — that's the kind of thing worth filing. Things less consequential than this, ignore.
$B js "await fetch(...)"SyntaxError: await is only valid in async functionsNOT worth filing: user's app bugs, network errors to user's URL, auth failures on user's site, user's own JS logic bugs.
To file: write with all sections below (do not truncate — include every section through the Date/Version footer):
~/.gstack/contributor-logs/{slug}.mdundefined如果为:你处于贡献者模式。你是一名gstack用户,同时也参与gstack的改进工作。
_CONTRIBtrue在每个主要工作流步骤结束时(而非每个命令之后),反思你使用的gstack工具。给你的体验打分(0到10分)。如果不是10分,思考原因。如果存在明显的、可操作的bug,或者gstack的代码或技能markdown有可以改进的、有见地的点——提交一份现场报告。也许我们的贡献者能帮助我们变得更好!
**校准标准——参考案例:**例如,曾因gstack未将表达式包裹在async上下文中而失败,报错。这是个小问题,但输入是合理的,gstack本应处理好——这类问题就值得提交报告。比这影响更小的问题,可以忽略。
$B js "await fetch(...)"SyntaxError: await is only valid in async functions**不值得提交的情况:**用户应用程序的bug、用户URL的网络错误、用户网站的认证失败、用户自己的JS逻辑bug。
提交报告:编写文件,包含以下所有部分(不要截断——包含从标题到日期/版本页脚的所有部分):
~/.gstack/contributor-logs/{slug}.mdundefined{Title}
{标题}
Hey gstack team — ran into this while using /{skill-name}:
What I was trying to do: {what the user/agent was attempting}
What happened instead: {what actually happened}
My rating: {0-10} — {one sentence on why it wasn't a 10}
嘿gstack团队——我在使用/{技能名称}时遇到了这个问题:
我当时尝试做什么: {用户/智能体当时的操作目标}
实际发生了什么: {实际出现的情况}
我的评分: {0-10} — {一句话说明为什么不是10分}
Steps to reproduce
复现步骤
- {step}
- {步骤}
Raw output
原始输出
{paste the actual error or unexpected output here}{paste the actual error or unexpected output here}What would make this a 10
如何改进到10分
{one sentence: what gstack should have done differently}
Date: {YYYY-MM-DD} | Version: {gstack version} | Skill: /{skill}
Slug: lowercase, hyphens, max 60 chars (e.g. `browse-js-no-await`). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: "Filed gstack field report: {title}"{一句话说明gstack本应做出哪些不同的处理}
日期: {YYYY-MM-DD} | 版本: {gstack版本} | 技能: /{技能名称}
Slug:小写,用连字符连接,最多60个字符(例如`browse-js-no-await`)。如果文件已存在则跳过。每个会话最多提交3份报告。直接在当前流程中编写并继续——不要中断工作流。告知用户:"已提交gstack现场报告:{标题}"Step 0: Detect base branch
步骤0:检测基础分支
Determine which branch this PR targets. Use the result as "the base branch" in all subsequent steps.
-
Check if a PR already exists for this branch:If this succeeds, use the printed branch name as the base branch.
gh pr view --json baseRefName -q .baseRefName -
If no PR exists (command fails), detect the repo's default branch:
gh repo view --json defaultBranchRef -q .defaultBranchRef.name -
If both commands fail, fall back to.
main
Print the detected base branch name. In every subsequent , ,
, , and command, substitute the detected
branch name wherever the instructions say "the base branch."
git diffgit loggit fetchgit mergegh pr create确定此PR的目标分支。后续所有步骤中均将此结果作为"基础分支"。
-
检查当前分支是否已有对应的PR:如果命令执行成功,使用输出的分支名称作为基础分支。
gh pr view --json baseRefName -q .baseRefName -
如果不存在PR(命令执行失败),检测仓库的默认分支:
gh repo view --json defaultBranchRef -q .defaultBranchRef.name -
如果两个命令都失败,回退使用分支。
main
输出检测到的基础分支名称。在后续所有、、、和命令中,凡说明中提到"基础分支"的地方,均替换为检测到的分支名称。
git diffgit loggit fetchgit mergegh pr createShip: Fully Automated Ship Workflow
Ship:全自动化发布工作流
You are running the workflow. This is a non-interactive, fully automated workflow. Do NOT ask for confirmation at any step. The user said which means DO IT. Run straight through and output the PR URL at the end.
/ship/shipOnly stop for:
- On the base branch (abort)
- Merge conflicts that can't be auto-resolved (stop, show conflicts)
- Test failures (stop, show failures)
- Pre-landing review finds CRITICAL issues and user chooses to fix (not acknowledge or skip)
- MINOR or MAJOR version bump needed (ask — see Step 4)
- Greptile review comments that need user decision (complex fixes, false positives)
- TODOS.md missing and user wants to create one (ask — see Step 5.5)
- TODOS.md disorganized and user wants to reorganize (ask — see Step 5.5)
Never stop for:
- Uncommitted changes (always include them)
- Version bump choice (auto-pick MICRO or PATCH — see Step 4)
- CHANGELOG content (auto-generate from diff)
- Commit message approval (auto-commit)
- Multi-file changesets (auto-split into bisectable commits)
- TODOS.md completed-item detection (auto-mark)
你正在运行工作流。这是一个非交互式、全自动化的工作流。任何步骤都不要请求确认。用户输入意味着直接执行。全程运行直到最后输出PR URL。
/ship/ship仅在以下情况中断:
- 当前处于基础分支(终止)
- 存在无法自动解决的合并冲突(终止,显示冲突内容)
- 测试失败(终止,显示失败内容)
- 预发布审查发现CRITICAL问题且用户选择修复(而非确认或跳过)
- 需要升级MINOR或MAJOR版本(询问用户——见步骤4)
- Greptile审查评论需要用户决策(复杂修复、误报)
- TODOS.md缺失且用户想要创建(询问用户——见步骤5.5)
- TODOS.md结构混乱且用户想要重新组织(询问用户——见步骤5.5)
绝对不要因以下情况中断:
- 存在未提交的更改(始终包含这些更改)
- 版本升级选择(自动选择MICRO或PATCH——见步骤4)
- CHANGELOG内容(根据差异自动生成)
- 提交消息确认(自动提交)
- 多文件变更集(自动拆分为可二分查找的提交)
- TODOS.md已完成项检测(自动标记)
Step 1: Pre-flight
步骤1:预检
-
Check the current branch. If on the base branch or the repo's default branch, abort: "You're on the base branch. Ship from a feature branch."
-
Run(never use
git status). Uncommitted changes are always included — no need to ask.-uall -
Runand
git diff <base>...HEAD --statto understand what's being shipped.git log <base>..HEAD --oneline
-
检查当前分支。如果处于基础分支或仓库默认分支,终止:"你当前处于基础分支,请从功能分支执行Ship操作。"
-
运行(永远不要使用
git status参数)。未提交的更改始终包含在内——无需询问用户。-uall -
运行和
git diff <base>...HEAD --stat以了解即将发布的内容。git log <base>..HEAD --oneline
Step 2: Merge the base branch (BEFORE tests)
步骤2:合并基础分支(测试之前)
Fetch and merge the base branch into the feature branch so tests run against the merged state:
bash
git fetch origin <base> && git merge origin/<base> --no-editIf there are merge conflicts: Try to auto-resolve if they are simple (VERSION, schema.rb, CHANGELOG ordering). If conflicts are complex or ambiguous, STOP and show them.
If already up to date: Continue silently.
拉取并将基础分支合并到功能分支,以便测试在合并后的代码状态下运行:
bash
git fetch origin <base> && git merge origin/<base> --no-edit**如果存在合并冲突:**如果是简单冲突(VERSION、schema.rb、CHANGELOG排序),尝试自动解决。如果冲突复杂或不明确,终止并显示冲突内容。
**如果已经是最新状态:**静默继续。
Step 3: Run tests (on merged code)
步骤3:运行测试(在合并后的代码上)
Do NOT run — already calls
internally, which loads the schema into the correct lane database.
Running bare test migrations without INSTANCE hits an orphan DB and corrupts structure.sql.
RAILS_ENV=test bin/rails db:migratebin/test-lanedb:test:prepareRun both test suites in parallel:
bash
bin/test-lane 2>&1 | tee /tmp/ship_tests.txt &
npm run test 2>&1 | tee /tmp/ship_vitest.txt &
waitAfter both complete, read the output files and check pass/fail.
If any test fails: Show the failures and STOP. Do not proceed.
If all pass: Continue silently — just note the counts briefly.
不要运行——内部已调用، 它会将schema加载到正确的lane数据库中。在未指定INSTANCE的情况下运行裸测试迁移会导致孤立数据库并损坏structure.sql。
RAILS_ENV=test bin/rails db:migratebin/test-lanedb:test:prepare并行运行两个测试套件:
bash
bin/test-lane 2>&1 | tee /tmp/ship_tests.txt &
npm run test 2>&1 | tee /tmp/ship_vitest.txt &
wait两个测试都完成后,读取输出文件并检查通过/失败情况。
如果任何测试失败:显示失败内容并终止。不要继续。
**如果全部通过:**静默继续——只需简要记录通过数量。
Step 3.25: Eval Suites (conditional)
步骤3.25:评估套件(可选)
Evals are mandatory when prompt-related files change. Skip this step entirely if no prompt files are in the diff.
1. Check if the diff touches prompt-related files:
bash
git diff origin/<base> --name-onlyMatch against these patterns (from CLAUDE.md):
app/services/*_prompt_builder.rb- ,
app/services/*_generation_service.rb,*_writer_service.rb*_designer_service.rb - ,
app/services/*_evaluator.rb,*_scorer.rb,*_classifier_service.rb*_analyzer.rb - ,
app/services/concerns/*voice*.rb,*writing*.rb,*prompt*.rb*token*.rb - ,
app/services/chat_tools/*.rbapp/services/x_thread_tools/*.rb config/system_prompts/*.txt- (eval infrastructure changes affect all suites)
test/evals/**/*
If no matches: Print "No prompt-related files changed — skipping evals." and continue to Step 3.5.
2. Identify affected eval suites:
Each eval runner () declares listing which source files affect it. Grep these to find which suites match the changed files:
test/evals/*_eval_runner.rbPROMPT_SOURCE_FILESbash
grep -l "changed_file_basename" test/evals/*_eval_runner.rbMap runner → test file: → .
post_generation_eval_runner.rbpost_generation_eval_test.rbSpecial cases:
- Changes to ,
test/evals/judges/*.rb, ortest/evals/support/*.rbaffect ALL suites that use those judges/support files. Check imports in the eval test files to determine which.test/evals/fixtures/ - Changes to — grep eval runners for the prompt filename to find affected suites.
config/system_prompts/*.txt - If unsure which suites are affected, run ALL suites that could plausibly be impacted. Over-testing is better than missing a regression.
3. Run affected suites at :
EVAL_JUDGE_TIER=full/shipbash
EVAL_JUDGE_TIER=full EVAL_VERBOSE=1 bin/test-lane --eval test/evals/<suite>_eval_test.rb 2>&1 | tee /tmp/ship_evals.txtIf multiple suites need to run, run them sequentially (each needs a test lane). If the first suite fails, stop immediately — don't burn API cost on remaining suites.
4. Check results:
- If any eval fails: Show the failures, the cost dashboard, and STOP. Do not proceed.
- If all pass: Note pass counts and cost. Continue to Step 3.5.
5. Save eval output — include eval results and cost dashboard in the PR body (Step 8).
Tier reference (for context — /ship always uses ):
full| Tier | When | Speed (cached) | Cost |
|---|---|---|---|
| Dev iteration, smoke tests | ~5s (14x faster) | ~$0.07/run |
| Default dev, | ~17s (4x faster) | ~$0.37/run |
| | ~72s (baseline) | ~$1.27/run |
当与prompt相关的文件发生更改时,必须运行评估。如果差异中没有prompt相关文件,则完全跳过此步骤。
1. 检查差异是否涉及prompt相关文件:
bash
git diff origin/<base> --name-only匹配以下模式(来自CLAUDE.md):
app/services/*_prompt_builder.rb- 、
app/services/*_generation_service.rb、*_writer_service.rb*_designer_service.rb - 、
app/services/*_evaluator.rb、*_scorer.rb、*_classifier_service.rb*_analyzer.rb - 、
app/services/concerns/*voice*.rb、*writing*.rb、*prompt*.rb*token*.rb - 、
app/services/chat_tools/*.rbapp/services/x_thread_tools/*.rb config/system_prompts/*.txt- (评估基础设施变更会影响所有套件)
test/evals/**/*
**如果没有匹配项:**输出"未检测到prompt相关文件变更——跳过评估。"并继续到步骤3.5。
2. 确定受影响的评估套件:
每个评估运行器()都声明了列表,列出了哪些源文件会影响它。通过grep这些文件来找到与变更文件匹配的套件:
test/evals/*_eval_runner.rbPROMPT_SOURCE_FILESbash
grep -l "changed_file_basename" test/evals/*_eval_runner.rb运行器与测试文件的映射关系: → 。
post_generation_eval_runner.rbpost_generation_eval_test.rb特殊情况:
- 对、
test/evals/judges/*.rb或test/evals/support/*.rb的变更会影响所有使用这些judge/支持文件的套件。检查评估测试文件中的导入以确定受影响的套件。test/evals/fixtures/ - 对的变更——grep评估运行器中的prompt文件名以找到受影响的套件。
config/system_prompts/*.txt - 如果不确定哪些套件受影响,运行所有可能受影响的套件。过度测试总比遗漏回归问题好。
3. 在级别运行受影响的套件:
EVAL_JUDGE_TIER=full/shipbash
EVAL_JUDGE_TIER=full EVAL_VERBOSE=1 bin/test-lane --eval test/evals/<suite>_eval_test.rb 2>&1 | tee /tmp/ship_evals.txt如果需要运行多个套件,依次运行(每个套件需要一个测试lane)。如果第一个套件失败,立即终止——不要在剩余套件上浪费API成本。
4. 检查结果:
- 如果任何评估失败:显示失败内容、成本仪表板并终止。不要继续。
- **如果全部通过:**记录通过数量和成本。继续到步骤3.5。
5. 保存评估输出——在步骤8的PR正文中包含评估结果和成本仪表板。
级别参考(仅作参考——/ship始终使用):
full| 级别 | 使用场景 | 速度(缓存后) | 成本 |
|---|---|---|---|
| 开发迭代、冒烟测试 | ~5秒(快14倍) | ~$0.07/次 |
| 默认开发、 | ~17秒(快4倍) | ~$0.37/次 |
| | ~72秒(基准速度) | ~$1.27/次 |
Step 3.5: Pre-Landing Review
步骤3.5:预发布审查
Review the diff for structural issues that tests don't catch.
-
Read. If the file cannot be read, STOP and report the error.
.claude/skills/review/checklist.md -
Runto get the full diff (scoped to feature changes against the freshly-fetched base branch).
git diff origin/<base> -
Apply the review checklist in two passes:
- Pass 1 (CRITICAL): SQL & Data Safety, LLM Output Trust Boundary
- Pass 2 (INFORMATIONAL): All remaining categories
-
Always output ALL findings — both critical and informational. The user must see every issue found.
-
Output a summary header:
Pre-Landing Review: N issues (X critical, Y informational) -
If CRITICAL issues found: For EACH critical issue, use a separate AskUserQuestion with:
- The problem (+ description)
file:line RECOMMENDATION: Choose A because [one-line reason]- Options: A) Fix it now, B) Acknowledge and ship anyway, C) It's a false positive — skip
After resolving all critical issues: if the user chose A (fix) on any issue, apply the recommended fixes, then commit only the fixed files by name (), then STOP and tell the user to run
git add <fixed-files> && git commit -m "fix: apply pre-landing review fixes"again to re-test with the fixes applied. If the user chose only B (acknowledge) or C (false positive) on all issues, continue with Step 4./ship
- The problem (
-
If only non-critical issues found: Output them and continue. They will be included in the PR body at Step 8.
-
If no issues found: Outputand continue.
Pre-Landing Review: No issues found.
Save the review output — it goes into the PR body in Step 8.
审查代码差异,找出测试无法检测到的结构性问题。
-
读取。如果无法读取该文件,终止并报告错误。
.claude/skills/review/checklist.md -
运行获取完整差异(针对刚拉取的基础分支的功能变更范围)。
git diff origin/<base> -
分两轮应用审查清单:
- 第一轮(CRITICAL): SQL与数据安全、LLM输出信任边界
- 第二轮(INFORMATIONAL): 所有剩余类别
-
始终输出所有发现——包括CRITICAL和INFORMATIONAL问题。用户必须看到所有发现的问题。
-
输出摘要标题:
预发布审查:共N个问题(X个CRITICAL,Y个INFORMATIONAL) -
**如果发现CRITICAL问题:**针对每个CRITICAL问题,单独使用AskUserQuestion:
- 问题内容(+ 描述)
file:line RECOMMENDATION: 选择A,因为[一句话理由]- 选项:A) 立即修复,B) 确认问题并继续发布,C) 这是误报——跳过
解决所有CRITICAL问题后:如果用户对任何问题选择了A(修复),应用推荐的修复,然后仅提交修复的文件(),然后终止并告知用户重新运行
git add <fixed-files> && git commit -m "fix: apply pre-landing review fixes"以在修复后重新测试。如果用户对所有问题都选择了B(确认)或C(误报),继续到步骤4。/ship
- 问题内容(
-
**如果仅发现非CRITICAL问题:**输出问题并继续。这些问题将在步骤8的PR正文中包含。
-
**如果未发现问题:**输出并继续。
预发布审查:未发现问题。
保存审查输出——将在步骤8的PR正文中使用。
Step 3.75: Address Greptile review comments (if PR exists)
步骤3.75:处理Greptile审查评论(如果PR已存在)
Read and follow the fetch, filter, classify, and escalation detection steps.
.claude/skills/review/greptile-triage.mdIf no PR exists, fails, API returns an error, or there are zero Greptile comments: Skip this step silently. Continue to Step 4.
ghIf Greptile comments are found:
Include a Greptile summary in your output:
+ N Greptile comments (X valid, Y fixed, Z FP)Before replying to any comment, run the Escalation Detection algorithm from greptile-triage.md to determine whether to use Tier 1 (friendly) or Tier 2 (firm) reply templates.
For each classified comment:
VALID & ACTIONABLE: Use AskUserQuestion with:
- The comment (file:line or [top-level] + body summary + permalink URL)
RECOMMENDATION: Choose A because [one-line reason]- Options: A) Fix now, B) Acknowledge and ship anyway, C) It's a false positive
- If user chooses A: apply the fix, commit the fixed files (), reply using the Fix reply template from greptile-triage.md (include inline diff + explanation), and save to both per-project and global greptile-history (type: fix).
git add <fixed-files> && git commit -m "fix: address Greptile review — <brief description>" - If user chooses C: reply using the False Positive reply template from greptile-triage.md (include evidence + suggested re-rank), save to both per-project and global greptile-history (type: fp).
VALID BUT ALREADY FIXED: Reply using the Already Fixed reply template from greptile-triage.md — no AskUserQuestion needed:
- Include what was done and the fixing commit SHA
- Save to both per-project and global greptile-history (type: already-fixed)
FALSE POSITIVE: Use AskUserQuestion:
- Show the comment and why you think it's wrong (file:line or [top-level] + body summary + permalink URL)
- Options:
- A) Reply to Greptile explaining the false positive (recommended if clearly wrong)
- B) Fix it anyway (if trivial)
- C) Ignore silently
- If user chooses A: reply using the False Positive reply template from greptile-triage.md (include evidence + suggested re-rank), save to both per-project and global greptile-history (type: fp)
SUPPRESSED: Skip silently — these are known false positives from previous triage.
After all comments are resolved: If any fixes were applied, the tests from Step 3 are now stale. Re-run tests (Step 3) before continuing to Step 4. If no fixes were applied, continue to Step 4.
读取并遵循获取、过滤、分类和升级检测步骤。
.claude/skills/review/greptile-triage.md**如果PR不存在、命令失败、API返回错误或没有Greptile评论:**静默跳过此步骤。继续到步骤4。
gh如果发现Greptile评论:
在输出中包含Greptile摘要:
+ N条Greptile评论(X条有效,Y条已修复,Z条误报)回复任何评论之前,运行greptile-triage.md中的升级检测算法,以确定使用Tier 1(友好)还是Tier 2(正式)回复模板。
针对每个分类后的评论:
**有效且可操作:**使用AskUserQuestion:
- 评论内容(或[顶级] + 正文摘要 + 永久链接URL)
file:line RECOMMENDATION: 选择A,因为[一句话理由]- 选项:A) 立即修复,B) 确认问题并继续发布,C) 这是误报
- 如果用户选择A:应用修复,提交修复的文件(),使用greptile-triage.md中的修复回复模板回复(包含内联差异 + 解释),并保存到项目专属和全局greptile-history(类型:fix)。
git add <fixed-files> && git commit -m "fix: address Greptile review — <简要描述>" - 如果用户选择C:使用greptile-triage.md中的误报回复模板回复(包含证据 + 建议重新排序),并保存到项目专属和全局greptile-history(类型:fp)。
有效但已修复:使用greptile-triage.md中的已修复回复模板回复——无需AskUserQuestion:
- 说明已完成的操作和修复提交的SHA
- 保存到项目专属和全局greptile-history(类型:already-fixed)
**误报:**使用AskUserQuestion:
- 显示评论内容以及你认为它错误的原因(或[顶级] + 正文摘要 + 永久链接URL)
file:line - 选项:
- A) 回复Greptile说明这是误报(如果明显错误则推荐此选项)
- B) 无论如何修复(如果修复很简单)
- C) 静默忽略
- 如果用户选择A:使用greptile-triage.md中的误报回复模板回复(包含证据 + 建议重新排序),并保存到项目专属和全局greptile-history(类型:fp)。
**已抑制:**静默跳过——这些是之前分类过的已知误报。
**所有评论处理完成后:**如果应用了任何修复,步骤3中的测试现在已过期。重新运行测试(步骤3)后再继续到步骤4。如果未应用任何修复,直接继续到步骤4。
Step 4: Version bump (auto-decide)
步骤4:版本号升级(自动决策)
-
Read the currentfile (4-digit format:
VERSION)MAJOR.MINOR.PATCH.MICRO -
Auto-decide the bump level based on the diff:
- Count lines changed ()
git diff origin/<base>...HEAD --stat | tail -1 - MICRO (4th digit): < 50 lines changed, trivial tweaks, typos, config
- PATCH (3rd digit): 50+ lines changed, bug fixes, small-medium features
- MINOR (2nd digit): ASK the user — only for major features or significant architectural changes
- MAJOR (1st digit): ASK the user — only for milestones or breaking changes
- Count lines changed (
-
Compute the new version:
- Bumping a digit resets all digits to its right to 0
- Example: + PATCH →
0.19.1.00.19.2.0
-
Write the new version to thefile.
VERSION
-
读取当前文件(四位格式:
VERSION)MAJOR.MINOR.PATCH.MICRO -
根据差异自动决定升级级别:
- 统计变更行数()
git diff origin/<base>...HEAD --stat | tail -1 - MICRO(第4位):变更行数<50行,微小调整、拼写错误、配置变更
- PATCH(第3位):变更行数≥50行, bug修复、中小型功能
- MINOR(第2位):询问用户——仅用于大型功能或重大架构变更
- MAJOR(第1位):询问用户——仅用于里程碑或破坏性变更
- 统计变更行数(
-
计算新版本号:
- 升级某一位时,将其右侧的所有位重置为0
- 示例:+ PATCH →
0.19.1.00.19.2.0
-
将新版本号写入文件。
VERSION
Step 5: CHANGELOG (auto-generate)
步骤5:自动生成CHANGELOG
-
Readheader to know the format.
CHANGELOG.md -
Auto-generate the entry from ALL commits on the branch (not just recent ones):
- Use to see every commit being shipped
git log <base>..HEAD --oneline - Use to see the full diff against the base branch
git diff <base>...HEAD - The CHANGELOG entry must be comprehensive of ALL changes going into the PR
- If existing CHANGELOG entries on the branch already cover some commits, replace them with one unified entry for the new version
- Categorize changes into applicable sections:
- — new features
### Added - — changes to existing functionality
### Changed - — bug fixes
### Fixed - — removed features
### Removed
- Write concise, descriptive bullet points
- Insert after the file header (line 5), dated today
- Format:
## [X.Y.Z.W] - YYYY-MM-DD
- Use
Do NOT ask the user to describe changes. Infer from the diff and commit history.
-
读取的头部以了解格式。
CHANGELOG.md -
根据分支上的所有提交自动生成条目(不仅是最近的提交):
- 使用查看即将发布的所有提交
git log <base>..HEAD --oneline - 使用查看相对于基础分支的完整差异
git diff <base>...HEAD - CHANGELOG条目必须全面涵盖PR中的所有变更
- 如果分支上已有的CHANGELOG条目已覆盖部分提交,将它们替换为新版本的统一条目
- 将变更分类到适用的章节:
- — 新功能
### Added - — 现有功能变更
### Changed - — bug修复
### Fixed - — 移除的功能
### Removed
- 编写简洁、描述性的项目符号
- 插入到文件头部之后(第5行),日期为今天
- 格式:
## [X.Y.Z.W] - YYYY-MM-DD
- 使用
**不要让用户描述变更。**从差异和提交历史中推断。
Step 5.5: TODOS.md (auto-update)
步骤5.5:自动更新TODOS.md
Cross-reference the project's TODOS.md against the changes being shipped. Mark completed items automatically; prompt only if the file is missing or disorganized.
Read for the canonical format reference.
.claude/skills/review/TODOS-format.md1. Check if TODOS.md exists in the repository root.
If TODOS.md does not exist: Use AskUserQuestion:
- Message: "GStack recommends maintaining a TODOS.md organized by skill/component, then priority (P0 at top through P4, then Completed at bottom). See TODOS-format.md for the full format. Would you like to create one?"
- Options: A) Create it now, B) Skip for now
- If A: Create with a skeleton (# TODOS heading + ## Completed section). Continue to step 3.
TODOS.md - If B: Skip the rest of Step 5.5. Continue to Step 6.
2. Check structure and organization:
Read TODOS.md and verify it follows the recommended structure:
- Items grouped under headings
## <Skill/Component> - Each item has field with P0-P4 value
**Priority:** - A section at the bottom
## Completed
If disorganized (missing priority fields, no component groupings, no Completed section): Use AskUserQuestion:
- Message: "TODOS.md doesn't follow the recommended structure (skill/component groupings, P0-P4 priority, Completed section). Would you like to reorganize it?"
- Options: A) Reorganize now (recommended), B) Leave as-is
- If A: Reorganize in-place following TODOS-format.md. Preserve all content — only restructure, never delete items.
- If B: Continue to step 3 without restructuring.
3. Detect completed TODOs:
This step is fully automatic — no user interaction.
Use the diff and commit history already gathered in earlier steps:
- (full diff against the base branch)
git diff <base>...HEAD - (all commits being shipped)
git log <base>..HEAD --oneline
For each TODO item, check if the changes in this PR complete it by:
- Matching commit messages against the TODO title and description
- Checking if files referenced in the TODO appear in the diff
- Checking if the TODO's described work matches the functional changes
Be conservative: Only mark a TODO as completed if there is clear evidence in the diff. If uncertain, leave it alone.
4. Move completed items to the section at the bottom. Append:
## Completed**Completed:** vX.Y.Z (YYYY-MM-DD)5. Output summary:
TODOS.md: N items marked complete (item1, item2, ...). M items remaining.- Or:
TODOS.md: No completed items detected. M items remaining. - Or: /
TODOS.md: Created.TODOS.md: Reorganized.
6. Defensive: If TODOS.md cannot be written (permission error, disk full), warn the user and continue. Never stop the ship workflow for a TODOS failure.
Save this summary — it goes into the PR body in Step 8.
将项目的TODOS.md与即将发布的变更进行交叉引用。自动标记已完成的项;仅当文件缺失或结构混乱时才提示用户。
读取获取标准格式参考。
.claude/skills/review/TODOS-format.md1. 检查仓库根目录是否存在TODOS.md
**如果TODOS.md不存在:**使用AskUserQuestion:
- 消息:"GStack建议维护一个按技能/组件分组,然后按优先级排序(顶部为P0,依次到P4,最后是已完成项)的TODOS.md。完整格式请参考TODOS-format.md。是否要创建一个?"
- 选项:A) 立即创建,B) 暂时跳过
- 如果选择A:创建带有骨架的(# TODOS标题 + ## Completed章节)。继续到步骤3。
TODOS.md - 如果选择B:跳过步骤5.5的剩余部分。继续到步骤6。
2. 检查结构和组织:
读取TODOS.md并验证是否遵循推荐结构:
- 项按标题分组
## <Skill/Component> - 每个项都有字段,值为P0-P4
**Priority:** - 底部有章节
## Completed
如果结构混乱(缺少优先级字段、没有组件分组、没有Completed章节):使用AskUserQuestion:
- 消息:"TODOS.md未遵循推荐结构(按技能/组件分组、P0-P4优先级、Completed章节)。是否要重新组织?"
- 选项:A) 立即重新组织(推荐),B) 保持原样
- 如果选择A:按照TODOS-format.md原地重新组织。保留所有内容——仅重新结构,绝不删除项。
- 如果选择B:不进行重新组织,直接继续到步骤3。
3. 检测已完成的TODO项:
此步骤完全自动化——无需用户交互。
使用之前步骤中收集的差异和提交历史:
- (相对于基础分支的完整差异)
git diff <base>...HEAD - (即将发布的所有提交)
git log <base>..HEAD --oneline
对于每个TODO项,通过以下方式检查此PR中的变更是否已完成该项:
- 将提交消息与TODO标题和描述匹配
- 检查TODO中引用的文件是否出现在差异中
- 检查TODO描述的工作是否与功能性变更匹配
**保持保守:**仅当差异中存在明确证据时,才将TODO项标记为已完成。如果不确定,保持不变。
**4. 将已完成的项移动到底部的章节。**追加:
## Completed**Completed:** vX.Y.Z (YYYY-MM-DD)5. 输出摘要:
TODOS.md:已标记N项为已完成(item1, item2, ...)。剩余M项。- 或:
TODOS.md:未检测到已完成项。剩余M项。 - 或:/
TODOS.md:已创建。TODOS.md:已重新组织。
**6. 防御性处理:**如果无法写入TODOS.md(权限错误、磁盘满),警告用户并继续。绝不要因TODOS相关问题终止Ship工作流。
保存此摘要——将在步骤8的PR正文中使用。
Step 6: Commit (bisectable chunks)
步骤6:提交(可二分查找的块)
Goal: Create small, logical commits that work well with and help LLMs understand what changed.
git bisect-
Analyze the diff and group changes into logical commits. Each commit should represent one coherent change — not one file, but one logical unit.
-
Commit ordering (earlier commits first):
- Infrastructure: migrations, config changes, route additions
- Models & services: new models, services, concerns (with their tests)
- Controllers & views: controllers, views, JS/React components (with their tests)
- VERSION + CHANGELOG + TODOS.md: always in the final commit
-
Rules for splitting:
- A model and its test file go in the same commit
- A service and its test file go in the same commit
- A controller, its views, and its test go in the same commit
- Migrations are their own commit (or grouped with the model they support)
- Config/route changes can group with the feature they enable
- If the total diff is small (< 50 lines across < 4 files), a single commit is fine
-
Each commit must be independently valid — no broken imports, no references to code that doesn't exist yet. Order commits so dependencies come first.
-
Compose each commit message:
- First line: (type = feat/fix/chore/refactor/docs)
<type>: <summary> - Body: brief description of what this commit contains
- Only the final commit (VERSION + CHANGELOG) gets the version tag and co-author trailer:
- First line:
bash
git commit -m "$(cat <<'EOF'
chore: bump version and changelog (vX.Y.Z.W)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"**目标:**创建小而逻辑清晰的提交,以便与配合使用,并帮助LLM理解变更内容。
git bisect-
分析差异并将变更分组为逻辑提交。每个提交应代表一个连贯的变更——不是一个文件,而是一个逻辑单元。
-
提交顺序(先提交前面的):
- 基础设施: 迁移、配置变更、路由添加
- 模型与服务: 新模型、服务、concerns(及其测试)
- 控制器与视图: 控制器、视图、JS/React组件(及其测试)
- VERSION + CHANGELOG + TODOS.md: 始终在最后一个提交
-
拆分规则:
- 模型及其测试文件放在同一个提交中
- 服务及其测试文件放在同一个提交中
- 控制器、其视图及其测试放在同一个提交中
- 迁移单独作为一个提交(或与其支持的模型分组)
- 配置/路由变更可与它们支持的功能分组
- 如果总变更量小(<50行,<4个文件),单个提交即可
-
每个提交必须独立有效——没有缺失的导入,没有引用不存在的代码。按依赖顺序提交,先提交依赖项。
-
编写每个提交的消息:
- 第一行:(type = feat/fix/chore/refactor/docs)
<type>: <summary> - 正文:简要描述此提交包含的内容
- 只有最后一个提交(VERSION + CHANGELOG)带有版本标签和共同作者信息:
- 第一行:
bash
git commit -m "$(cat <<'EOF'
chore: bump version and changelog (vX.Y.Z.W)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
EOF
)"Step 7: Push
步骤7:推送
Push to the remote with upstream tracking:
bash
git push -u origin <branch-name>推送到远程仓库并设置上游跟踪:
bash
git push -u origin <branch-name>Step 8: Create PR
步骤8:创建PR
Create a pull request using :
ghbash
gh pr create --base <base> --title "<type>: <summary>" --body "$(cat <<'EOF'使用创建拉取请求:
ghbash
gh pr create --base <base> --title "<type>: <summary>" --body "$(cat <<'EOF'Summary
摘要
<bullet points from CHANGELOG>
<bullet points from CHANGELOG>
Pre-Landing Review
预发布审查
<findings from Step 3.5, or "No issues found.">
<findings from Step 3.5, or "No issues found.">
Eval Results
Eval Results
<If evals ran: suite names, pass/fail counts, cost dashboard summary. If skipped: "No prompt-related files changed — evals skipped.">
<If evals ran: suite names, pass/fail counts, cost dashboard summary. If skipped: "No prompt-related files changed — evals skipped.">
Greptile Review
Greptile Review
<If Greptile comments were found: bullet list with [FIXED] / [FALSE POSITIVE] / [ALREADY FIXED] tag + one-line summary per comment>
<If no Greptile comments found: "No Greptile comments.">
<If no PR existed during Step 3.75: omit this section entirely>
<If Greptile comments were found: bullet list with [FIXED] / [FALSE POSITIVE] / [ALREADY FIXED] tag + one-line summary per comment>
<If no Greptile comments found: "No Greptile comments.">
<If no PR existed during Step 3.75: omit this section entirely>
TODOS
TODOS
<If items marked complete: bullet list of completed items with version>
<If no items completed: "No TODO items completed in this PR.">
<If TODOS.md created or reorganized: note that>
<If TODOS.md doesn't exist and user skipped: omit this section>
<If items marked complete: bullet list of completed items with version>
<If no items completed: "No TODO items completed in this PR.">
<If TODOS.md created or reorganized: note that>
<If TODOS.md doesn't exist and user skipped: omit this section>
Test plan
Test plan
- All Rails tests pass (N runs, 0 failures)
- All Vitest tests pass (N tests)
🤖 Generated with Claude Code
EOF
)"
**Output the PR URL** — this should be the final output the user sees.
---- All Rails tests pass (N runs, 0 failures)
- All Vitest tests pass (N tests)
🤖 Generated with Claude Code
EOF
)"
**输出PR URL**——这应该是用户看到的最终输出。
---Important Rules
重要规则
- Never skip tests. If tests fail, stop.
- Never skip the pre-landing review. If checklist.md is unreadable, stop.
- Never force push. Use regular only.
git push - Never ask for confirmation except for MINOR/MAJOR version bumps and CRITICAL review findings (one AskUserQuestion per critical issue with fix recommendation).
- Always use the 4-digit version format from the VERSION file.
- Date format in CHANGELOG:
YYYY-MM-DD - Split commits for bisectability — each commit = one logical change.
- TODOS.md completion detection must be conservative. Only mark items as completed when the diff clearly shows the work is done.
- Use Greptile reply templates from greptile-triage.md. Every reply includes evidence (inline diff, code references, re-rank suggestion). Never post vague replies.
- The goal is: user says , next thing they see is the review + PR URL.
/ship
- **永远不要跳过测试。**如果测试失败,终止。
- **永远不要跳过预发布审查。**如果checklist.md无法读取,终止。
- **永远不要强制推送。**仅使用常规。
git push - 永远不要请求确认,除非是MINOR/MAJOR版本升级和CRITICAL审查发现(每个CRITICAL问题单独使用AskUserQuestion并提供修复建议)。
- 始终使用VERSION文件中的四位版本格式。
- CHANGELOG中的日期格式:
YYYY-MM-DD - 拆分提交以支持二分查找——每个提交 = 一个逻辑变更。
- **TODOS.md完成项检测必须保守。**仅当差异明确显示工作已完成时才标记为已完成。
- **使用greptile-triage.md中的Greptile回复模板。**每个回复都包含证据(内联差异、代码引用、重新排序建议)。永远不要发布模糊的回复。
- 目标是:用户输入,接下来看到的是审查结果 + PR URL。
/ship