ship
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseShip: 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)
- In-branch test failures (pre-existing failures are triaged, not auto-blocking)
- Pre-landing review finds ASK items that need user judgment
- MINOR or MAJOR version bump needed (ask — see Step 8)
Never stop for:
- Uncommitted changes (always include them)
- Version bump choice (auto-pick MICRO or PATCH — see Step 8)
- CHANGELOG content (auto-generate from diff)
- Commit message approval (auto-commit)
Re-run behavior (idempotency):
Re-running means "run the whole checklist again." Every verification step
runs on every invocation. Only actions are idempotent:
/ship- Step 8: If VERSION already bumped, skip the bump but still read the version
- Step 11: If already pushed, skip the push command
- Step 12: If PR exists, update the body instead of creating a new PR
你正在运行工作流。这是一个非交互式、全自动化的工作流。
任何步骤都不要请求确认。用户输入意味着直接执行。
全程执行,最终输出PR链接。
/ship/ship仅在以下情况停止:
- 当前处于基础分支(终止)
- 无法自动解决的合并冲突(停止并展示冲突)
- 分支内测试失败(预先存在的失败会被分类,不会自动阻止流程)
- 预发布审查发现需要用户判断的ASK项
- 需要升级MINOR或MAJOR版本(询问用户——见步骤8)
永远不要因以下情况停止:
- 未提交的更改(始终包含这些更改)
- 版本升级选择(自动选择MICRO或PATCH——见步骤8)
- CHANGELOG内容(根据差异自动生成)
- 提交消息审批(自动提交)
重运行行为(幂等性):
重运行意味着“重新执行整个检查清单”。每次调用都会运行所有验证步骤。仅操作具备幂等性:
/ship- 步骤8:如果VERSION已升级,跳过升级步骤但仍读取版本号
- 步骤11:如果已推送,跳过推送命令
- 步骤12:如果PR已存在,更新PR正文而非创建新PR
Step 0: Detect platform and base branch
步骤0:检测平台和基础分支
First, detect the git hosting platform from the remote URL:
bash
git remote get-url origin 2>/dev/null- If the URL contains "github.com" → platform is GitHub
- Otherwise → unknown (use git-native commands only)
Determine which branch this PR targets, or the repo's default branch:
If GitHub:
- — if succeeds, use it
gh pr view --json baseRefName -q .baseRefName - — if succeeds, use it
gh repo view --json defaultBranchRef -q .defaultBranchRef.name
Git-native fallback:
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||'- If that fails: → use
git rev-parse --verify origin/main 2>/dev/nullmain - If that fails: → use
git rev-parse --verify origin/master 2>/dev/nullmaster
If all fail, fall back to .
mainPrint the detected base branch name. In every subsequent command, substitute the
detected branch name wherever the instructions say "the base branch" or .
<base>首先,从远程URL检测Git托管平台:
bash
git remote get-url origin 2>/dev/null- 如果URL包含"github.com" → 平台为GitHub
- 否则 → 未知(仅使用Git原生命令)
确定此PR的目标分支,或仓库的默认分支:
如果是GitHub:
- — 如果成功,使用该分支
gh pr view --json baseRefName -q .baseRefName - — 如果成功,使用该分支
gh repo view --json defaultBranchRef -q .defaultBranchRef.name
Git原生备选方案:
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||'- 如果失败:→ 使用
git rev-parse --verify origin/main 2>/dev/nullmain - 如果失败:→ 使用
git rev-parse --verify origin/master 2>/dev/nullmaster
如果全部失败,默认使用。
main打印检测到的基础分支名称。在后续所有命令中,凡说明提到“基础分支”或的地方,均替换为检测到的分支名称。
<base>Step 1: Pre-flight
步骤1:预检
-
Check the current branch. If on the base branch, abort: "You're on the base branch. Ship from a feature branch."
-
Run(never use
git status). Uncommitted changes are always included.-uall -
Runand
git diff <base>...HEAD --statto understand what's being shipped.git log <base>..HEAD --oneline
-
检查当前分支。如果处于基础分支,终止:“你当前在基础分支上,请从功能分支执行发布操作。”
-
运行(永远不要使用
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, 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、CHANGELOG排序),尝试自动解决。若冲突复杂或不明确,停止并展示冲突。
如果已同步: 继续执行,无需提示。
Step 3: Run tests (on merged code)
步骤3:运行测试(在合并后的代码上)
Run the project's test and build pipeline:
bash
pnpm run build 2>&1 | tee /tmp/ship_build.txt
pnpm run lint 2>&1 | tee /tmp/ship_lint.txt
pnpm run test 2>&1 | tee /tmp/ship_tests.txtAfter all complete, read the output files and check pass/fail.
If any test fails: Do NOT immediately stop. Apply the Test Failure Ownership Triage:
运行项目的测试和构建流水线:
bash
pnpm run build 2>&1 | tee /tmp/ship_build.txt
pnpm run lint 2>&1 | tee /tmp/ship_lint.txt
pnpm run test 2>&1 | tee /tmp/ship_tests.txt所有命令完成后,读取输出文件并检查通过/失败情况。
如果任何测试失败: 不要立即停止。应用测试失败归属分类:
Test Failure Ownership Triage
测试失败归属分类
For each failing test:
-
Get the files changed on this branch:bash
git diff origin/<base>...HEAD --name-only -
Classify the failure:
- In-branch if: the failing test file or the code it tests was modified on this branch, OR you can trace the failure to a change in the branch diff.
- Likely pre-existing if: neither the test file nor the code it tests was modified on this branch, AND the failure is unrelated to any branch change.
- When ambiguous, default to in-branch.
-
Handle in-branch failures: STOP. Show them and do not proceed.
-
Handle pre-existing failures: Use AskUserQuestion:These test failures appear pre-existing (not caused by your branch changes): [list each failure with file:line and brief error]A) Investigate and fix now B) Skip — ship anyway
If all pass: Continue silently — note the counts briefly.
针对每个失败的测试:
-
获取此分支上更改的文件:bash
git diff origin/<base>...HEAD --name-only -
对失败进行分类:
- 分支内问题:如果失败的测试文件或其测试的代码在此分支上被修改,或者可以将失败追溯到分支差异中的更改。
- 可能预先存在的问题:如果测试文件及其测试的代码均未在此分支上修改,且失败与分支更改无关。
- 若不明确,默认归为分支内问题。
-
处理分支内失败: 停止。展示失败内容,不再继续。
-
处理预先存在的失败: 使用AskUserQuestion:这些测试失败似乎是预先存在的(并非由你的分支更改导致): [列出每个失败的文件:行号和简要错误信息]A) 立即调查并修复 B) 跳过——继续发布
如果全部通过: 继续执行,简要记录通过数量。
Step 4: Test Coverage Audit
步骤4:测试覆盖率审核
Dispatch this step as a subagent using the Agent tool. The subagent runs the
coverage audit in a fresh context window.
Subagent prompt: Pass the following instructions to the subagent, with substituted:
<base>You are running a ship-workflow test coverage audit for a NestJS monorepo with 4-layer Clean Architecture (domain, application, infrastructure, api). Runto see what changed. Do not commit or push — report only.git diff <base>...HEAD
Trace every codepath changed in the diff. Read every changed file (full file, not just diff). For each, trace data flow through every branch (if/else, switch, guard, early return, error path). Check each branch against existing tests. For each function/method changed, search for correspondingfiles. Score quality:.spec.ts
- ★★★ Tests behavior with edge cases AND error paths
- ★★ Tests correct behavior, happy path only
- ★ Smoke test / existence check / trivial assertion
Output ASCII coverage diagram:CODE PATH COVERAGE =========================== [+] src/application/units/commands/sync-unit.handler.ts ├── [★★★ TESTED] Happy path — sync-unit.handler.spec.ts:42 ├── [GAP] Error when unit not found — NO TEST └── [GAP] Partial update scenario — NO TEST Generate tests for uncovered paths (if test framework exists):
- Read 2-3 existing
files to match conventions exactly.spec.ts- Generate unit tests. Mock external dependencies (TypeORM repos, external APIs).
- Run each test. Passes → keep. Fails → fix once. Still fails → delete silently.
After your analysis, output a single JSON object on the LAST LINE:{"coverage_pct":N,"gaps":N,"diagram":"<markdown diagram>","tests_added":["path",...]}
Parent processing:
- Parse the LAST line as JSON.
- Store for the PR body's section.
## Test Coverage - Print:
Coverage: {coverage_pct}%, {gaps} gaps. {tests_added.length} tests added.
If the subagent fails: Fall back to running the audit inline.
使用Agent工具将此步骤分派给子代理。子代理在全新的上下文窗口中运行覆盖率审核。
子代理提示: 将以下说明传递给子代理,并替换:
<base>你正在为采用4层Clean Architecture(领域层、应用层、基础设施层、API层)的NestJS单体仓库执行ship-workflow测试覆盖率审核。运行查看更改内容。不要提交或推送——仅报告结果。git diff <base>...HEAD
追踪差异中更改的每个代码路径。读取每个更改的文件(完整文件,而非仅差异部分)。 针对每个文件,追踪数据在所有分支(if/else、switch、守卫、提前返回、错误路径)中的流动。 对照现有测试检查每个分支。针对每个更改的函数/方法,搜索对应的文件。对测试质量评分:.spec.ts
- ★★★ 测试了包含边缘情况和错误路径的行为
- ★★ 仅测试了正常路径的正确行为
- ★ 冒烟测试/存在性检查/无关紧要的断言
输出ASCII覆盖率图表:代码路径覆盖率 =========================== [+] src/application/units/commands/sync-unit.handler.ts ├── [★★★ 已测试] 正常路径 — sync-unit.handler.spec.ts:42 ├── [缺口] 单元未找到时的错误 — 无测试 └── [缺口] 部分更新场景 — 无测试 为未覆盖的路径生成测试(如果测试框架存在):
- 读取2-3个现有
文件以完全匹配约定.spec.ts- 生成单元测试。模拟外部依赖(TypeORM仓库、外部API)。
- 运行每个测试。通过则保留。失败则修复一次。仍失败则静默删除。
分析完成后,在最后一行输出单个JSON对象:{"coverage_pct":N,"gaps":N,"diagram":"<markdown图表>","tests_added":["路径",...]}
父代理处理:
- 将最后一行解析为JSON。
- 存储用于PR正文中的部分。
## 测试覆盖率 - 打印:
覆盖率: {coverage_pct}%, 缺口: {gaps}个。新增测试: {tests_added.length}个。
如果子代理失败: 回退到内联运行审核。
Step 5: Pre-Landing Review
步骤5:预发布审查
Review the diff for structural issues that tests don't catch.
-
Runto get the full diff.
git diff origin/<base> -
Apply this review checklist in two passes:
审查差异以发现测试无法捕获的结构性问题。
-
运行获取完整差异。
git diff origin/<base> -
分两轮应用此审查清单:
Pass 1 (CRITICAL) — must fix before shipping:
第一轮(CRITICAL)——发布前必须修复:
- SQL & Data Safety: Raw SQL with string interpolation, missing transactions on multi-table writes, missing on UPDATE/DELETE, unvalidated user input in queries
WHERE - Security: Exposed secrets, missing gitignored files and directories properly, missing auth guards on endpoints, XSS via unsanitized output, CORS misconfiguration
- Breaking Changes: Removed/renamed public API endpoints, changed response shapes, removed required fields
- SQL与数据安全: 使用字符串插值的原生SQL、多表写入缺少事务、UPDATE/DELETE缺少子句、查询中包含未验证的用户输入
WHERE - 安全: 暴露的密钥、未正确忽略的Git文件和目录、端点缺少认证守卫、未 sanitize 输出导致的XSS、CORS配置错误
- 破坏性更改: 删除/重命名公开API端点、更改响应结构、删除必填字段
Pass 2 (INFORMATIONAL) — fix or note:
第二轮(INFORMATIONAL)——修复或记录:
- Architecture: Layer boundary violations (framework imports in domain/), DTOs mixed with entities, missing barrel exports
- Error Handling: Inline string error messages (should use error enums), swallowed errors, missing Problem Details format
- Performance: N+1 queries, missing pagination, unbounded queries, missing indexes
- Code Quality: Dead code, orphan code, unused imports, duplicated logic, overly complex conditionals
- 架构: 层边界违规(领域层中导入框架)、DTO与实体混合、缺少桶导出(barrel exports)
- 错误处理: 内联字符串错误消息(应使用错误枚举)、被吞掉的错误、缺少Problem Details格式
- 性能: N+1查询、缺少分页、无界查询、缺少索引
- 代码质量: 死代码、孤立代码、未使用的导入、重复逻辑、过于复杂的条件判断
Confidence Calibration
置信度校准
Every finding MUST include a confidence score (1-10):
| Score | Meaning |
|---|---|
| 9-10 | Verified by reading specific code. Concrete bug demonstrated. |
| 7-8 | High confidence pattern match. Very likely correct. |
| 5-6 | Moderate. Could be a false positive. Show with caveat. |
| 3-4 | Low confidence. Suppress from main report. |
| 1-2 | Speculation. Only report if severity would be P0. |
Finding format:
[SEVERITY] (confidence: N/10) file:line — description每个发现必须包含置信度评分(1-10):
| 评分 | 含义 |
|---|---|
| 9-10 | 通过阅读特定代码验证。已证实存在具体bug。 |
| 7-8 | 高置信度模式匹配。极有可能正确。 |
| 5-6 | 中等置信度。可能是误报。附带说明展示。 |
| 3-4 | 低置信度。不在主报告中展示。 |
| 1-2 | 推测。仅在严重性为P0时报告。 |
发现格式:
[严重性] (置信度: N/10) 文件:行号 — 描述Fix-First Flow
优先修复流程
-
Classify each finding as AUTO-FIX or ASK:
- AUTO-FIX: Dead code removal, unused imports, missing barrel exports, obvious formatting
- ASK: Anything that changes behavior, security fixes, architectural decisions
-
Auto-fix all AUTO-FIX items. Output one line per fix:
[AUTO-FIXED] [file:line] Problem → what you did -
If ASK items remain, present them in ONE AskUserQuestion:
- List each with severity, problem, recommended fix
- Per-item options: A) Fix B) Skip
-
After all fixes:
- If ANY fixes were applied: commit fixed files (), then re-run tests (Step 3).
git add <files> && git commit -m "fix: pre-landing review fixes" - If no fixes applied: continue to Step 8.
- If ANY fixes were applied: commit fixed files (
-
Output summary:
Pre-Landing Review: N issues — M auto-fixed, K asked (J fixed, L skipped)
-
将每个发现分类为AUTO-FIX或ASK:
- AUTO-FIX:删除死代码、移除未使用的导入、添加缺失的桶导出、明显的格式问题
- ASK:任何会更改行为的内容、安全修复、架构决策
-
自动修复所有AUTO-FIX项。每项修复输出一行:
[已自动修复] [文件:行号] 问题 → 修复内容 -
如果仍有ASK项,通过一个AskUserQuestion展示:
- 列出每项的严重性、问题和推荐修复方案
- 每项选项:A) 修复 B) 跳过
-
所有修复完成后:
- 如果应用了任何修复:提交修复后的文件(),然后重新运行测试(步骤3)。
git add <文件> && git commit -m "fix: 预发布审查修复" - 如果未应用修复:继续执行步骤8。
- 如果应用了任何修复:提交修复后的文件(
-
输出摘要:
预发布审查: 共发现N个问题 — M个已自动修复,K个需确认(J个已修复,L个已跳过)
Step 6: Scope Drift Detection
步骤6:范围漂移检测
Check: did the branch build what was stated — nothing more, nothing less?
-
Read commit messages ().
git log origin/<base>..HEAD --oneline -
Identify the stated intent from the branch name and commits.
-
Runand compare files changed against intent.
git diff origin/<base>...HEAD --stat -
Detect:
- SCOPE CREEP: Files changed that are unrelated to the stated intent
- MISSING REQUIREMENTS: Expected work not present in the diff
-
Output:
Scope Check: [CLEAN / DRIFT DETECTED / REQUIREMENTS MISSING] Intent: <1-line summary> Delivered: <1-line summary> -
This is INFORMATIONAL — does not block. Continue.
检查:分支是否实现了既定目标——不多不少?
-
读取提交消息()。
git log origin/<base>..HEAD --oneline -
从分支名称和提交中识别既定意图。
-
运行并将更改的文件与意图进行比较。
git diff origin/<base>...HEAD --stat -
检测:
- 范围蔓延: 更改的文件与既定意图无关
- 需求缺失: 预期的工作未出现在差异中
-
输出:
范围检查: [正常 / 检测到漂移 / 需求缺失] 意图: <1行摘要> 交付内容: <1行摘要> -
此步骤为信息性——不会阻止流程。继续执行。
Step 7: Plan Completion Audit
步骤7:计划完成情况审核
Dispatch as a subagent. Searches for an active plan file related to the current branch.
Subagent prompt:
You are running a ship-workflow plan completion audit. The base branch is.<base>
- Search for plan files:
find ~/.claude/plans ~/.gstack/projects -name "*.md" -mmin -1440 2>/dev/null | head -10- If a plan references the current branch, read it and extract every actionable item.
- Cross-reference each item against
.git diff origin/<base>...HEAD- Classify: DONE, PARTIAL, NOT DONE, CHANGED.
Output JSON on the LAST LINE:{"total_items":N,"done":N,"changed":N,"deferred":N,"summary":"<markdown checklist>"}
Parent processing:
- If : present deferred items via AskUserQuestion.
deferred > 0 - Embed in PR body.
summary - If no plan file found: skip with "No plan file detected."
分派给子代理。搜索与当前分支相关的活动计划文件。
子代理提示:
你正在执行ship-workflow计划完成情况审核。基础分支为。<base>
- 搜索计划文件:
find ~/.claude/plans ~/.gstack/projects -name "*.md" -mmin -1440 2>/dev/null | head -10- 如果某个计划引用了当前分支,读取该计划并提取所有可操作项。
- 将每个项与
进行交叉引用。git diff origin/<base>...HEAD- 分类:已完成、部分完成、未完成、已变更。
在最后一行输出JSON:{"total_items":N,"done":N,"changed":N,"deferred":N,"summary":"<markdown检查清单>"}
父代理处理:
- 如果:通过AskUserQuestion展示延迟的项。
deferred > 0 - 将嵌入PR正文。
summary - 如果未找到计划文件:跳过并提示“未检测到计划文件。”
Step 8: Version bump (auto-decide)
步骤8:版本升级(自动决策)
Idempotency check: Compare VERSION against the base branch.
bash
BASE_VERSION=$(git show origin/<base>:VERSION 2>/dev/null || echo "0.0.0.0")
CURRENT_VERSION=$(cat VERSION 2>/dev/null || echo "0.0.0.0")
echo "BASE: $BASE_VERSION HEAD: $CURRENT_VERSION"
if [ "$CURRENT_VERSION" != "$BASE_VERSION" ]; then echo "ALREADY_BUMPED"; fiIf , skip the bump but read the current version. Otherwise:
ALREADY_BUMPED-
Read(4-digit format:
VERSION)MAJOR.MINOR.PATCH.MICRO -
Auto-decide the bump level:
- Count lines changed ()
git diff origin/<base>...HEAD --stat | tail -1 - MICRO (4th digit): < 50 lines changed, trivial tweaks, config
- PATCH (3rd digit): 50+ lines, no feature signals
- MINOR (2nd digit): ASK if feature signals detected (new routes, migrations, branch)
feat/ - MAJOR (1st digit): ASK — only for milestones or breaking changes
- Count lines changed (
-
Compute and write the new version to.
VERSION
幂等性检查: 比较VERSION与基础分支的版本。
bash
BASE_VERSION=$(git show origin/<base>:VERSION 2>/dev/null || echo "0.0.0.0")
CURRENT_VERSION=$(cat VERSION 2>/dev/null || echo "0.0.0.0")
echo "BASE: $BASE_VERSION HEAD: $CURRENT_VERSION"
if [ "$CURRENT_VERSION" != "$BASE_VERSION" ]; then echo "ALREADY_BUMPED"; fi如果输出,跳过升级步骤但读取当前版本。否则:
ALREADY_BUMPED-
读取(4位格式:
VERSION)MAJOR.MINOR.PATCH.MICRO -
自动决定升级级别:
- 统计更改行数()
git diff origin/<base>...HEAD --stat | tail -1 - MICRO(第4位):更改行数<50行,微小调整、配置更改
- PATCH(第3位):更改行数≥50行,无功能新增迹象
- MINOR(第2位):如果检测到功能新增迹象(新路由、迁移、分支),询问用户
feat/ - MAJOR(第1位):询问用户——仅用于里程碑或破坏性更改
- 统计更改行数(
-
计算新版本并写入文件。
VERSION
Step 9: CHANGELOG (auto-generate)
步骤9:CHANGELOG(自动生成)
-
Readheader to know the format.
CHANGELOG.md -
Enumerate every commit:
git log <base>..HEAD --oneline -
Read the full diff:
git diff <base>...HEAD -
Group commits by theme (features, fixes, cleanup, infra).
-
Write the CHANGELOG entry:
- Sections: ,
### Added,### Changed,### Fixed### Removed - Format:
## [X.Y.Z.W] - YYYY-MM-DD - Lead with what the user can now do that they couldn't before.
- Sections:
-
Cross-check: every commit must map to at least one bullet point.
-
读取的头部以了解格式。
CHANGELOG.md -
枚举所有提交:
git log <base>..HEAD --oneline -
读取完整差异:
git diff <base>...HEAD -
按主题分组提交(功能、修复、清理、基础设施)。
-
编写CHANGELOG条目:
- 章节:、
### Added、### Changed、### Fixed### Removed - 格式:
## [X.Y.Z.W] - YYYY-MM-DD - 开头说明用户现在可以做哪些之前无法做的事情。
- 章节:
-
交叉检查:每个提交必须至少对应一个项目符号。
Step 10: Commit (bisectable chunks)
步骤10:提交(可二分的块)
-
Analyze the diff and group changes into logical commits.
-
Commit ordering (earlier commits first):
- Infrastructure: migrations, config changes
- Domain & Application: entities, value objects, use cases, services (with tests)
- Infrastructure implementations: repositories, TypeORM entities (with tests)
- API layer: controllers, DTOs (with tests)
- VERSION + CHANGELOG: always in the final commit
-
Rules:
- A service and its test file go in the same commit
- Each commit must be independently valid — no broken imports
- If total diff is small (< 50 lines across < 4 files), a single commit is fine
-
Compose commit messages:
- Invoke the skill using the Skill tool.
/git-commit-format - Never include or any AI attribution trailer (per project convention)
Co-Authored-By
- Invoke the
-
分析差异并将更改分组为逻辑提交。
-
提交顺序(先提交早期内容):
- 基础设施:迁移、配置更改
- 领域与应用层:实体、值对象、用例、服务(附带测试)
- 基础设施实现:仓库、TypeORM实体(附带测试)
- API层:控制器、DTO(附带测试)
- VERSION + CHANGELOG:始终放在最后一个提交
-
规则:
- 服务及其测试文件放在同一个提交中
- 每个提交必须独立有效——无导入错误
- 如果总差异较小(<50行,涉及<4个文件),单个提交即可
-
编写提交消息:
- 使用Skill工具调用技能。
/git-commit-format - 永远不要包含或任何AI归属尾部(遵循项目约定)
Co-Authored-By
- 使用Skill工具调用
Step 11: Verification Gate
步骤11:验证关卡
IRON LAW: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.
Before pushing, re-verify if code changed during Steps 4-6:
-
Re-run tests if ANY code changed after Step 3's test run:bash
pnpm run build && pnpm run lint && pnpm run test -
Rationalization prevention:
- "Should work now" → RUN IT.
- "I already tested earlier" → Code changed since then. Test again.
- "It's a trivial change" → Trivial changes break production.
If tests fail here: STOP. Do not push.
铁律:无新鲜验证证据,不得声称完成。
推送前,重新验证步骤4-6期间代码是否有更改:
-
如果步骤3测试运行后有任何代码更改,重新运行测试:bash
pnpm run build && pnpm run lint && pnpm run test -
防止主观判断:
- “现在应该可以运行了” → 执行测试。
- “我之前已经测试过了” → 从那时起代码已更改。重新测试。
- “这是微小更改” → 微小更改也会导致生产故障。
如果此处测试失败: 停止。不要推送。
Step 12: Push
步骤12:推送
Idempotency check:
bash
BRANCH_NAME=$(git branch --show-current)
git fetch origin "$BRANCH_NAME" 2>/dev/null
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse "origin/$BRANCH_NAME" 2>/dev/null || echo "none")
echo "LOCAL: $LOCAL REMOTE: $REMOTE"
[ "$LOCAL" = "$REMOTE" ] && echo "ALREADY_PUSHED" || echo "PUSH_NEEDED"If , skip. Otherwise:
ALREADY_PUSHEDbash
git push -u origin "$BRANCH_NAME"幂等性检查:
bash
BRANCH_NAME=$(git branch --show-current)
git fetch origin "$BRANCH_NAME" 2>/dev/null
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse "origin/$BRANCH_NAME" 2>/dev/null || echo "none")
echo "LOCAL: $LOCAL REMOTE: $REMOTE"
[ "$LOCAL" = "$REMOTE" ] && echo "ALREADY_PUSHED" || echo "PUSH_NEEDED"如果输出,跳过。否则:
ALREADY_PUSHEDbash
git push -u origin "$BRANCH_NAME"Step 13: Create PR
步骤13:创建PR
Idempotency check:
bash
gh pr view --json url,number,state -q 'if .state == "OPEN" then "PR #\(.number): \(.url)" else "NO_PR" end' 2>/dev/null || echo "NO_PR"If an open PR already exists: update the PR body using .
gh pr edit --body "..."If no PR exists: create one.
The PR body should contain:
undefined幂等性检查:
bash
gh pr view --json url,number,state -q 'if .state == "OPEN" then "PR #\(.number): \(.url)" else "NO_PR" end' 2>/dev/null || echo "NO_PR"如果已有开放的PR:更新PR正文,使用。
gh pr edit --body "..."如果没有PR:创建一个。
PR正文应包含:
undefinedSummary
摘要
<Summarize ALL changes. Group commits into logical sections. Every commit
must appear in at least one section.>
<总结所有更改。将提交分组为逻辑章节。每个提交必须至少出现在一个章节中。>
Test Coverage
测试覆盖率
<Coverage diagram from Step 4, or "All new code paths have test coverage.">
<步骤4中的覆盖率图表,或“所有新代码路径均有测试覆盖。”>
Pre-Landing Review
预发布审查
<Findings from Step 5, or "No issues found.">
<步骤5中的发现,或“未发现问题。”>
Scope Drift
范围漂移
<From Step 6, or omit if CLEAN>
<步骤6的结果,若无漂移可省略>
Plan Completion
计划完成情况
<From Step 7, or "No plan file detected.">
<步骤7的结果,或“未检测到计划文件。”>
Test plan
测试计划
- TypeScript compilation passes (strict mode)
- ESLint passes
- All Jest tests pass (N tests)
- No regressions in affected modules
**Create the PR:**
```bash
gh pr create --base <base> --title "<type>(<scope>): <summary>" --body "$(cat <<'EOF'
<PR body from above>
EOF
)"Output the PR URL.
- TypeScript编译通过(严格模式)
- ESLint检查通过
- 所有Jest测试通过(共N个测试)
- 受影响模块无回归问题
**创建PR:**
```bash
gh pr create --base <base> --title "<type>(<scope>): <summary>" --body "$(cat <<'EOF'
<上述PR正文>
EOF
)"输出PR链接。
Important Rules
重要规则
- Never skip tests. If tests fail, stop.
- Never force push. Use regular only.
git push - Never ask for trivial confirmations (e.g., "ready to push?", "create PR?").
- 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.
- Never push without fresh verification evidence. If code changed after Step 3 tests, re-run before pushing.
- Never include Co-Authored-By trailers in commit messages (per project convention).
- The goal is: user says , next thing they see is the PR URL.
/ship
- 永远不要跳过测试。如果测试失败,停止流程。
- 永远不要强制推送。仅使用常规。
git push - 永远不要请求无关紧要的确认(例如“准备好推送了吗?”“创建PR吗?”)。
- 始终使用VERSION文件中的4位版本格式。
- CHANGELOG中的日期格式:
YYYY-MM-DD - 拆分提交以支持二分查找——每个提交对应一个逻辑更改。
- 无新鲜验证证据,永远不要推送。如果步骤3测试后代码有更改,推送前重新运行测试。
- 提交消息中永远不要包含Co-Authored-By尾部(遵循项目约定)。
- 目标是:用户输入,接下来看到的就是PR链接。
/ship