@oxgeneral/orch 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/App-Q6LOPAZT.js +22 -0
  2. package/dist/{agent-Q34L27AY.js → agent-SI4JF5MV.js} +1 -1
  3. package/dist/{agent-shop-D2RS4BZK.js → agent-shop-JHDTCWCD.js} +1 -1
  4. package/dist/chunk-3AXNSYCM.js +2 -0
  5. package/dist/{chunk-4TDXD3LA.js → chunk-5YSW77VI.js} +104 -21
  6. package/dist/chunk-5YSW77VI.js.map +1 -0
  7. package/dist/{chunk-BCPUTULS.js → chunk-HWEMBO36.js} +83 -54
  8. package/dist/chunk-J7ITYXE6.js +116 -0
  9. package/dist/chunk-J7ITYXE6.js.map +1 -0
  10. package/dist/chunk-U2JVMD2G.js +66 -0
  11. package/dist/chunk-U2JVMD2G.js.map +1 -0
  12. package/dist/{chunk-EH3HRQP4.js → chunk-W3J7CURM.js} +8 -116
  13. package/dist/chunk-W3J7CURM.js.map +1 -0
  14. package/dist/{chunk-UMZEA3JT.js → chunk-XLBV2PFL.js} +1 -1
  15. package/dist/chunk-ZMLF5HI5.js +11 -0
  16. package/dist/cli.js +1 -1
  17. package/dist/container-LV3WOPMS.js +4 -0
  18. package/dist/doctor-Q3GHJNZL.js +2 -0
  19. package/dist/index.d.ts +44 -1
  20. package/dist/index.js +12 -5
  21. package/dist/index.js.map +1 -1
  22. package/dist/init-D4356W7G.js +73 -0
  23. package/dist/orchestrator-PSXVHP2L.js +17 -0
  24. package/dist/orchestrator-WLWIAFXH.js +6 -0
  25. package/dist/{orchestrator-XPEMMBOO.js.map → orchestrator-WLWIAFXH.js.map} +1 -1
  26. package/dist/{org-WAK3CDPG.js → org-KLYK6MMJ.js} +1 -1
  27. package/dist/serve-4RT4HERL.js +3 -0
  28. package/dist/skill-loader-IGRIELEM.js +9 -0
  29. package/dist/skill-loader-RHCFIK74.js +4 -0
  30. package/dist/skill-loader-RHCFIK74.js.map +1 -0
  31. package/dist/{task-QFLIIRKZ.js → task-6Z5P7ODZ.js} +1 -1
  32. package/dist/tui-GH3Z5CO4.js +2 -0
  33. package/dist/{update-FFKCOV63.js → update-XGJZFV4H.js} +1 -1
  34. package/dist/{update-check-HGMBDYHL.js → update-check-CZJC7VW6.js} +1 -1
  35. package/dist/{workspace-manager-5EYCMAEO.js → workspace-manager-RH24FSNT.js} +4 -3
  36. package/dist/workspace-manager-RH24FSNT.js.map +1 -0
  37. package/dist/workspace-manager-VJ4FN5PJ.js +3 -0
  38. package/package.json +1 -1
  39. package/readme.md +2 -2
  40. package/skills/library/autoplan.md +315 -0
  41. package/skills/library/benchmark.md +242 -0
  42. package/skills/library/browse.md +266 -0
  43. package/skills/library/canary.md +248 -0
  44. package/skills/library/careful.md +42 -0
  45. package/skills/library/codex.md +431 -0
  46. package/skills/library/design-consultation.md +367 -0
  47. package/skills/library/design-review.md +744 -0
  48. package/skills/library/document-release.md +365 -0
  49. package/skills/library/freeze.md +60 -0
  50. package/skills/library/guard.md +55 -0
  51. package/skills/library/investigate.md +171 -0
  52. package/skills/library/land-and-deploy.md +636 -0
  53. package/skills/library/office-hours.md +746 -0
  54. package/skills/library/plan-ceo-review.md +1029 -0
  55. package/skills/library/plan-design-review.md +428 -0
  56. package/skills/library/plan-eng-review.md +420 -0
  57. package/skills/library/qa-only.md +388 -0
  58. package/skills/library/qa.md +766 -0
  59. package/skills/library/retro.md +532 -0
  60. package/skills/library/review.md +421 -0
  61. package/skills/library/setup-browser-cookies.md +86 -0
  62. package/skills/library/setup-deploy.md +211 -0
  63. package/skills/library/ship.md +1018 -0
  64. package/skills/library/unfreeze.md +31 -0
  65. package/skills/library/upgrade.md +220 -0
  66. package/skills/orch/SKILL.md +138 -0
  67. package/dist/App-LEVUTWQN.js +0 -22
  68. package/dist/chunk-4TDXD3LA.js.map +0 -1
  69. package/dist/chunk-EH3HRQP4.js.map +0 -1
  70. package/dist/chunk-WVJTXBPL.js +0 -11
  71. package/dist/container-FXUUV6PP.js +0 -4
  72. package/dist/doctor-P2J6VAUX.js +0 -2
  73. package/dist/init-PTAYCSMO.js +0 -53
  74. package/dist/orchestrator-JOTMB5XT.js +0 -13
  75. package/dist/orchestrator-XPEMMBOO.js +0 -6
  76. package/dist/serve-5OAANN6J.js +0 -3
  77. package/dist/tui-BJHZBCIR.js +0 -2
  78. package/dist/workspace-manager-5EYCMAEO.js.map +0 -1
  79. package/dist/workspace-manager-XKOZ5WM6.js +0 -3
@@ -0,0 +1,1018 @@
1
+ ---
2
+ name: ship
3
+ version: 1.0.0
4
+ description: |
5
+ Ship workflow: detect + merge base branch, run tests, review diff, bump VERSION, update CHANGELOG, commit, push, create PR. Use when asked to "ship", "deploy", "push to main", "create a PR", or "merge and push".
6
+ Proactively suggest when the user says code is ready or asks about deploying.
7
+ ---
8
+
9
+ ## Step 0: Detect base branch
10
+
11
+ Determine which branch this PR targets. Use the result as "the base branch" in all subsequent steps.
12
+
13
+ 1. Check if a PR already exists for this branch:
14
+ `gh pr view --json baseRefName -q .baseRefName`
15
+ If this succeeds, use the printed branch name as the base branch.
16
+
17
+ 2. If no PR exists (command fails), detect the repo's default branch:
18
+ `gh repo view --json defaultBranchRef -q .defaultBranchRef.name`
19
+
20
+ 3. If both commands fail, fall back to `main`.
21
+
22
+ Print the detected base branch name. In every subsequent `git diff`, `git log`,
23
+ `git fetch`, `git merge`, and `gh pr create` command, substitute the detected
24
+ branch name wherever the instructions say "the base branch."
25
+
26
+ ---
27
+
28
+ # Ship: Fully Automated Ship Workflow
29
+
30
+ You are running the `/ship` workflow. This is a **non-interactive, fully automated** workflow. Do NOT ask for confirmation at any step. The user said `/ship` which means DO IT. Run straight through and output the PR URL at the end.
31
+
32
+ **Only stop for:**
33
+ - On the base branch (abort)
34
+ - Merge conflicts that can't be auto-resolved (stop, show conflicts)
35
+ - Test failures (stop, show failures)
36
+ - Pre-landing review finds ASK items that need user judgment
37
+ - MINOR or MAJOR version bump needed (ask — see Step 4)
38
+ - Greptile review comments that need user decision (complex fixes, false positives)
39
+ - TODOS.md missing and user wants to create one (ask — see Step 5.5)
40
+ - TODOS.md disorganized and user wants to reorganize (ask — see Step 5.5)
41
+
42
+ **Never stop for:**
43
+ - Uncommitted changes (always include them)
44
+ - Version bump choice (auto-pick MICRO or PATCH — see Step 4)
45
+ - CHANGELOG content (auto-generate from diff)
46
+ - Commit message approval (auto-commit)
47
+ - Multi-file changesets (auto-split into bisectable commits)
48
+ - TODOS.md completed-item detection (auto-mark)
49
+ - Auto-fixable review findings (dead code, N+1, stale comments — fixed automatically)
50
+ - Test coverage gaps (auto-generate and commit, or flag in PR body)
51
+
52
+ ---
53
+
54
+ ## Step 1: Pre-flight
55
+
56
+ 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."
57
+
58
+ 2. Run `git status` (never use `-uall`). Uncommitted changes are always included — no need to ask.
59
+
60
+ 3. Run `git diff <base>...HEAD --stat` and `git log <base>..HEAD --oneline` to understand what's being shipped.
61
+
62
+ 4. Check review readiness:
63
+
64
+ ## Review Readiness Dashboard
65
+
66
+ After completing the review, read the review log and config to display the dashboard.
67
+
68
+ ```bash
69
+ ~/.claude/skills/orch/bin/orch-review-read
70
+ ```
71
+
72
+ Parse the output. Find the most recent entry for each skill (plan-ceo-review, plan-eng-review, plan-design-review, design-review-lite, adversarial-review, codex-review). Ignore entries with timestamps older than 7 days. For the Adversarial row, show whichever is more recent between `adversarial-review` (new auto-scaled) and `codex-review` (legacy). For Design Review, show whichever is more recent between `plan-design-review` (full visual audit) and `design-review-lite` (code-level check). Append "(FULL)" or "(LITE)" to the status to distinguish. Display:
73
+
74
+ ```
75
+ +====================================================================+
76
+ | REVIEW READINESS DASHBOARD |
77
+ +====================================================================+
78
+ | Review | Runs | Last Run | Status | Required |
79
+ |-----------------|------|---------------------|-----------|----------|
80
+ | Eng Review | 1 | 2026-03-16 15:00 | CLEAR | YES |
81
+ | CEO Review | 0 | — | — | no |
82
+ | Design Review | 0 | — | — | no |
83
+ | Adversarial | 0 | — | — | no |
84
+ +--------------------------------------------------------------------+
85
+ | VERDICT: CLEARED — Eng Review passed |
86
+ +====================================================================+
87
+ ```
88
+
89
+ **Review tiers:**
90
+ - **Eng Review (required by default):** The only review that gates shipping. Covers architecture, code quality, tests, performance. Can be disabled globally with \`orch-config set skip_eng_review true\` (the "don't bother me" setting).
91
+ - **CEO Review (optional):** Use your judgment. Recommend it for big product/business changes, new user-facing features, or scope decisions. Skip for bug fixes, refactors, infra, and cleanup.
92
+ - **Design Review (optional):** Use your judgment. Recommend it for UI/UX changes. Skip for backend-only, infra, or prompt-only changes.
93
+ - **Adversarial Review (automatic):** Auto-scales by diff size. Small diffs (<50 lines) skip adversarial. Medium diffs (50–199) get cross-model adversarial. Large diffs (200+) get all 4 passes: Claude structured, Codex structured, Claude adversarial subagent, Codex adversarial. No configuration needed.
94
+
95
+ **Verdict logic:**
96
+ - **CLEARED**: Eng Review has >= 1 entry within 7 days with status "clean" (or \`skip_eng_review\` is \`true\`)
97
+ - **NOT CLEARED**: Eng Review missing, stale (>7 days), or has open issues
98
+ - CEO, Design, and Codex reviews are shown for context but never block shipping
99
+ - If \`skip_eng_review\` config is \`true\`, Eng Review shows "SKIPPED (global)" and verdict is CLEARED
100
+
101
+ **Staleness detection:** After displaying the dashboard, check if any existing reviews may be stale:
102
+ - Parse the \`---HEAD---\` section from the bash output to get the current HEAD commit hash
103
+ - For each review entry that has a \`commit\` field: compare it against the current HEAD. If different, count elapsed commits: \`git rev-list --count STORED_COMMIT..HEAD\`. Display: "Note: {skill} review from {date} may be stale — {N} commits since review"
104
+ - For entries without a \`commit\` field (legacy entries): display "Note: {skill} review from {date} has no commit tracking — consider re-running for accurate staleness detection"
105
+ - If all reviews match the current HEAD, do not display any staleness notes
106
+
107
+ If the Eng Review is NOT "CLEAR":
108
+
109
+ 1. **Check for a prior override on this branch:**
110
+ ```bash
111
+ source <(~/.claude/skills/orch/bin/orch-slug 2>/dev/null)
112
+ grep '"skill":"ship-review-override"' ~/.orch/projects/$SLUG/$BRANCH-reviews.jsonl 2>/dev/null || echo "NO_OVERRIDE"
113
+ ```
114
+ If an override exists, display the dashboard and note "Review gate previously accepted — continuing." Do NOT ask again.
115
+
116
+ 2. **If no override exists,** use AskUserQuestion:
117
+ - Show that Eng Review is missing or has open issues
118
+ - RECOMMENDATION: Choose C if the change is obviously trivial (< 20 lines, typo fix, config-only); Choose B for larger changes
119
+ - Options: A) Ship anyway B) Abort — run /plan-eng-review first C) Change is too small to need eng review
120
+ - If CEO Review is missing, mention as informational ("CEO Review not run — recommended for product changes") but do NOT block
121
+ - For Design Review: run `source <(~/.claude/skills/orch/bin/orch-diff-scope <base> 2>/dev/null)`. If `SCOPE_FRONTEND=true` and no design review (plan-design-review or design-review-lite) exists in the dashboard, mention: "Design Review not run — this PR changes frontend code. The lite design check will run automatically in Step 3.5, but consider running /design-review for a full visual audit post-implementation." Still never block.
122
+
123
+ 3. **If the user chooses A or C,** persist the decision so future `/ship` runs on this branch skip the gate:
124
+ ```bash
125
+ source <(~/.claude/skills/orch/bin/orch-slug 2>/dev/null)
126
+ echo '{"skill":"ship-review-override","timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","decision":"USER_CHOICE"}' >> ~/.orch/projects/$SLUG/$BRANCH-reviews.jsonl
127
+ ```
128
+ Substitute USER_CHOICE with "ship_anyway" or "not_relevant".
129
+
130
+ ---
131
+
132
+ ## Step 2: Merge the base branch (BEFORE tests)
133
+
134
+ Fetch and merge the base branch into the feature branch so tests run against the merged state:
135
+
136
+ ```bash
137
+ git fetch origin <base> && git merge origin/<base> --no-edit
138
+ ```
139
+
140
+ **If 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.
141
+
142
+ **If already up to date:** Continue silently.
143
+
144
+ ---
145
+
146
+ ## Step 2.5: Test Framework Bootstrap
147
+
148
+ ## Test Framework Bootstrap
149
+
150
+ **Detect existing test framework and project runtime:**
151
+
152
+ ```bash
153
+ # Detect project runtime
154
+ [ -f Gemfile ] && echo "RUNTIME:ruby"
155
+ [ -f package.json ] && echo "RUNTIME:node"
156
+ [ -f requirements.txt ] || [ -f pyproject.toml ] && echo "RUNTIME:python"
157
+ [ -f go.mod ] && echo "RUNTIME:go"
158
+ [ -f Cargo.toml ] && echo "RUNTIME:rust"
159
+ [ -f composer.json ] && echo "RUNTIME:php"
160
+ [ -f mix.exs ] && echo "RUNTIME:elixir"
161
+ # Detect sub-frameworks
162
+ [ -f Gemfile ] && grep -q "rails" Gemfile 2>/dev/null && echo "FRAMEWORK:rails"
163
+ [ -f package.json ] && grep -q '"next"' package.json 2>/dev/null && echo "FRAMEWORK:nextjs"
164
+ # Check for existing test infrastructure
165
+ ls jest.config.* vitest.config.* playwright.config.* .rspec pytest.ini pyproject.toml phpunit.xml 2>/dev/null
166
+ ls -d test/ tests/ spec/ __tests__/ cypress/ e2e/ 2>/dev/null
167
+ # Check opt-out marker
168
+ [ -f .orch/no-test-bootstrap ] && echo "BOOTSTRAP_DECLINED"
169
+ ```
170
+
171
+ **If test framework detected** (config files or test directories found):
172
+ Print "Test framework detected: {name} ({N} existing tests). Skipping bootstrap."
173
+ Read 2-3 existing test files to learn conventions (naming, imports, assertion style, setup patterns).
174
+ Store conventions as prose context for use in Phase 8e.5 or Step 3.4. **Skip the rest of bootstrap.**
175
+
176
+ **If BOOTSTRAP_DECLINED** appears: Print "Test bootstrap previously declined — skipping." **Skip the rest of bootstrap.**
177
+
178
+ **If NO runtime detected** (no config files found): Use AskUserQuestion:
179
+ "I couldn't detect your project's language. What runtime are you using?"
180
+ Options: A) Node.js/TypeScript B) Ruby/Rails C) Python D) Go E) Rust F) PHP G) Elixir H) This project doesn't need tests.
181
+ If user picks H → write `.orch/no-test-bootstrap` and continue without tests.
182
+
183
+ **If runtime detected but no test framework — bootstrap:**
184
+
185
+ ### B2. Research best practices
186
+
187
+ Use WebSearch to find current best practices for the detected runtime:
188
+ - `"[runtime] best test framework 2025 2026"`
189
+ - `"[framework A] vs [framework B] comparison"`
190
+
191
+ If WebSearch is unavailable, use this built-in knowledge table:
192
+
193
+ | Runtime | Primary recommendation | Alternative |
194
+ |---------|----------------------|-------------|
195
+ | Ruby/Rails | minitest + fixtures + capybara | rspec + factory_bot + shoulda-matchers |
196
+ | Node.js | vitest + @testing-library | jest + @testing-library |
197
+ | Next.js | vitest + @testing-library/react + playwright | jest + cypress |
198
+ | Python | pytest + pytest-cov | unittest |
199
+ | Go | stdlib testing + testify | stdlib only |
200
+ | Rust | cargo test (built-in) + mockall | — |
201
+ | PHP | phpunit + mockery | pest |
202
+ | Elixir | ExUnit (built-in) + ex_machina | — |
203
+
204
+ ### B3. Framework selection
205
+
206
+ Use AskUserQuestion:
207
+ "I detected this is a [Runtime/Framework] project with no test framework. I researched current best practices. Here are the options:
208
+ A) [Primary] — [rationale]. Includes: [packages]. Supports: unit, integration, smoke, e2e
209
+ B) [Alternative] — [rationale]. Includes: [packages]
210
+ C) Skip — don't set up testing right now
211
+ RECOMMENDATION: Choose A because [reason based on project context]"
212
+
213
+ If user picks C → write `.orch/no-test-bootstrap`. Tell user: "If you change your mind later, delete `.orch/no-test-bootstrap` and re-run." Continue without tests.
214
+
215
+ If multiple runtimes detected (monorepo) → ask which runtime to set up first, with option to do both sequentially.
216
+
217
+ ### B4. Install and configure
218
+
219
+ 1. Install the chosen packages (npm/bun/gem/pip/etc.)
220
+ 2. Create minimal config file
221
+ 3. Create directory structure (test/, spec/, etc.)
222
+ 4. Create one example test matching the project's code to verify setup works
223
+
224
+ If package installation fails → debug once. If still failing → revert with `git checkout -- package.json package-lock.json` (or equivalent for the runtime). Warn user and continue without tests.
225
+
226
+ ### B4.5. First real tests
227
+
228
+ Generate 3-5 real tests for existing code:
229
+
230
+ 1. **Find recently changed files:** `git log --since=30.days --name-only --format="" | sort | uniq -c | sort -rn | head -10`
231
+ 2. **Prioritize by risk:** Error handlers > business logic with conditionals > API endpoints > pure functions
232
+ 3. **For each file:** Write one test that tests real behavior with meaningful assertions. Never `expect(x).toBeDefined()` — test what the code DOES.
233
+ 4. Run each test. Passes → keep. Fails → fix once. Still fails → delete silently.
234
+ 5. Generate at least 1 test, cap at 5.
235
+
236
+ Never import secrets, API keys, or credentials in test files. Use environment variables or test fixtures.
237
+
238
+ ### B5. Verify
239
+
240
+ ```bash
241
+ # Run the full test suite to confirm everything works
242
+ {detected test command}
243
+ ```
244
+
245
+ If tests fail → debug once. If still failing → revert all bootstrap changes and warn user.
246
+
247
+ ### B5.5. CI/CD pipeline
248
+
249
+ ```bash
250
+ # Check CI provider
251
+ ls -d .github/ 2>/dev/null && echo "CI:github"
252
+ ls .gitlab-ci.yml .circleci/ bitrise.yml 2>/dev/null
253
+ ```
254
+
255
+ If `.github/` exists (or no CI detected — default to GitHub Actions):
256
+ Create `.github/workflows/test.yml` with:
257
+ - `runs-on: ubuntu-latest`
258
+ - Appropriate setup action for the runtime (setup-node, setup-ruby, setup-python, etc.)
259
+ - The same test command verified in B5
260
+ - Trigger: push + pull_request
261
+
262
+ If non-GitHub CI detected → skip CI generation with note: "Detected {provider} — CI pipeline generation supports GitHub Actions only. Add test step to your existing pipeline manually."
263
+
264
+ ### B6. Create TESTING.md
265
+
266
+ First check: If TESTING.md already exists → read it and update/append rather than overwriting. Never destroy existing content.
267
+
268
+ Write TESTING.md with:
269
+ - Philosophy: "100% test coverage is the key to great vibe coding. Tests let you move fast, trust your instincts, and ship with confidence — without them, vibe coding is just yolo coding. With tests, it's a superpower."
270
+ - Framework name and version
271
+ - How to run tests (the verified command from B5)
272
+ - Test layers: Unit tests (what, where, when), Integration tests, Smoke tests, E2E tests
273
+ - Conventions: file naming, assertion style, setup/teardown patterns
274
+
275
+ ### B7. Update CLAUDE.md
276
+
277
+ First check: If CLAUDE.md already has a `## Testing` section → skip. Don't duplicate.
278
+
279
+ Append a `## Testing` section:
280
+ - Run command and test directory
281
+ - Reference to TESTING.md
282
+ - Test expectations:
283
+ - 100% test coverage is the goal — tests make vibe coding safe
284
+ - When writing new functions, write a corresponding test
285
+ - When fixing a bug, write a regression test
286
+ - When adding error handling, write a test that triggers the error
287
+ - When adding a conditional (if/else, switch), write tests for BOTH paths
288
+ - Never commit code that makes existing tests fail
289
+
290
+ ### B8. Commit
291
+
292
+ ```bash
293
+ git status --porcelain
294
+ ```
295
+
296
+ Only commit if there are changes. Stage all bootstrap files (config, test directory, TESTING.md, CLAUDE.md, .github/workflows/test.yml if created):
297
+ `git commit -m "chore: bootstrap test framework ({framework name})"`
298
+
299
+ ---
300
+
301
+ ---
302
+
303
+ ## Step 3: Run tests (on merged code)
304
+
305
+ **Do NOT run `RAILS_ENV=test bin/rails db:migrate`** — `bin/test-lane` already calls
306
+ `db:test:prepare` internally, which loads the schema into the correct lane database.
307
+ Running bare test migrations without INSTANCE hits an orphan DB and corrupts structure.sql.
308
+
309
+ Run both test suites in parallel:
310
+
311
+ ```bash
312
+ bin/test-lane 2>&1 | tee /tmp/ship_tests.txt &
313
+ npm run test 2>&1 | tee /tmp/ship_vitest.txt &
314
+ wait
315
+ ```
316
+
317
+ After both complete, read the output files and check pass/fail.
318
+
319
+ **If any test fails:** Show the failures and **STOP**. Do not proceed.
320
+
321
+ **If all pass:** Continue silently — just note the counts briefly.
322
+
323
+ ---
324
+
325
+ ## Step 3.25: Eval Suites (conditional)
326
+
327
+ Evals are mandatory when prompt-related files change. Skip this step entirely if no prompt files are in the diff.
328
+
329
+ **1. Check if the diff touches prompt-related files:**
330
+
331
+ ```bash
332
+ git diff origin/<base> --name-only
333
+ ```
334
+
335
+ Match against these patterns (from CLAUDE.md):
336
+ - `app/services/*_prompt_builder.rb`
337
+ - `app/services/*_generation_service.rb`, `*_writer_service.rb`, `*_designer_service.rb`
338
+ - `app/services/*_evaluator.rb`, `*_scorer.rb`, `*_classifier_service.rb`, `*_analyzer.rb`
339
+ - `app/services/concerns/*voice*.rb`, `*writing*.rb`, `*prompt*.rb`, `*token*.rb`
340
+ - `app/services/chat_tools/*.rb`, `app/services/x_thread_tools/*.rb`
341
+ - `config/system_prompts/*.txt`
342
+ - `test/evals/**/*` (eval infrastructure changes affect all suites)
343
+
344
+ **If no matches:** Print "No prompt-related files changed — skipping evals." and continue to Step 3.5.
345
+
346
+ **2. Identify affected eval suites:**
347
+
348
+ Each eval runner (`test/evals/*_eval_runner.rb`) declares `PROMPT_SOURCE_FILES` listing which source files affect it. Grep these to find which suites match the changed files:
349
+
350
+ ```bash
351
+ grep -l "changed_file_basename" test/evals/*_eval_runner.rb
352
+ ```
353
+
354
+ Map runner → test file: `post_generation_eval_runner.rb` → `post_generation_eval_test.rb`.
355
+
356
+ **Special cases:**
357
+ - Changes to `test/evals/judges/*.rb`, `test/evals/support/*.rb`, or `test/evals/fixtures/` affect ALL suites that use those judges/support files. Check imports in the eval test files to determine which.
358
+ - Changes to `config/system_prompts/*.txt` — grep eval runners for the prompt filename to find affected suites.
359
+ - If unsure which suites are affected, run ALL suites that could plausibly be impacted. Over-testing is better than missing a regression.
360
+
361
+ **3. Run affected suites at `EVAL_JUDGE_TIER=full`:**
362
+
363
+ `/ship` is a pre-merge gate, so always use full tier (Sonnet structural + Opus persona judges).
364
+
365
+ ```bash
366
+ EVAL_JUDGE_TIER=full EVAL_VERBOSE=1 bin/test-lane --eval test/evals/<suite>_eval_test.rb 2>&1 | tee /tmp/ship_evals.txt
367
+ ```
368
+
369
+ If 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.
370
+
371
+ **4. Check results:**
372
+
373
+ - **If any eval fails:** Show the failures, the cost dashboard, and **STOP**. Do not proceed.
374
+ - **If all pass:** Note pass counts and cost. Continue to Step 3.5.
375
+
376
+ **5. Save eval output** — include eval results and cost dashboard in the PR body (Step 8).
377
+
378
+ **Tier reference (for context — /ship always uses `full`):**
379
+ | Tier | When | Speed (cached) | Cost |
380
+ |------|------|----------------|------|
381
+ | `fast` (Haiku) | Dev iteration, smoke tests | ~5s (14x faster) | ~$0.07/run |
382
+ | `standard` (Sonnet) | Default dev, `bin/test-lane --eval` | ~17s (4x faster) | ~$0.37/run |
383
+ | `full` (Opus persona) | **`/ship` and pre-merge** | ~72s (baseline) | ~$1.27/run |
384
+
385
+ ---
386
+
387
+ ## Step 3.4: Test Coverage Audit
388
+
389
+ 100% coverage is the goal — every untested path is a path where bugs hide and vibe coding becomes yolo coding. Evaluate what was ACTUALLY coded (from the diff), not what was planned.
390
+
391
+ **0. Before/after test count:**
392
+
393
+ ```bash
394
+ # Count test files before any generation
395
+ find . -name '*.test.*' -o -name '*.spec.*' -o -name '*_test.*' -o -name '*_spec.*' | grep -v node_modules | wc -l
396
+ ```
397
+
398
+ Store this number for the PR body.
399
+
400
+ **1. Trace every codepath changed** using `git diff origin/<base>...HEAD`:
401
+
402
+ Read every changed file. For each one, trace how data flows through the code — don't just list functions, actually follow the execution:
403
+
404
+ 1. **Read the diff.** For each changed file, read the full file (not just the diff hunk) to understand context.
405
+ 2. **Trace data flow.** Starting from each entry point (route handler, exported function, event listener, component render), follow the data through every branch:
406
+ - Where does input come from? (request params, props, database, API call)
407
+ - What transforms it? (validation, mapping, computation)
408
+ - Where does it go? (database write, API response, rendered output, side effect)
409
+ - What can go wrong at each step? (null/undefined, invalid input, network failure, empty collection)
410
+ 3. **Diagram the execution.** For each changed file, draw an ASCII diagram showing:
411
+ - Every function/method that was added or modified
412
+ - Every conditional branch (if/else, switch, ternary, guard clause, early return)
413
+ - Every error path (try/catch, rescue, error boundary, fallback)
414
+ - Every call to another function (trace into it — does IT have untested branches?)
415
+ - Every edge: what happens with null input? Empty array? Invalid type?
416
+
417
+ This is the critical step — you're building a map of every line of code that can execute differently based on input. Every branch in this diagram needs a test.
418
+
419
+ **2. Map user flows, interactions, and error states:**
420
+
421
+ Code coverage isn't enough — you need to cover how real users interact with the changed code. For each changed feature, think through:
422
+
423
+ - **User flows:** What sequence of actions does a user take that touches this code? Map the full journey (e.g., "user clicks 'Pay' → form validates → API call → success/failure screen"). Each step in the journey needs a test.
424
+ - **Interaction edge cases:** What happens when the user does something unexpected?
425
+ - Double-click/rapid resubmit
426
+ - Navigate away mid-operation (back button, close tab, click another link)
427
+ - Submit with stale data (page sat open for 30 minutes, session expired)
428
+ - Slow connection (API takes 10 seconds — what does the user see?)
429
+ - Concurrent actions (two tabs, same form)
430
+ - **Error states the user can see:** For every error the code handles, what does the user actually experience?
431
+ - Is there a clear error message or a silent failure?
432
+ - Can the user recover (retry, go back, fix input) or are they stuck?
433
+ - What happens with no network? With a 500 from the API? With invalid data from the server?
434
+ - **Empty/zero/boundary states:** What does the UI show with zero results? With 10,000 results? With a single character input? With maximum-length input?
435
+
436
+ Add these to your diagram alongside the code branches. A user flow with no test is just as much a gap as an untested if/else.
437
+
438
+ **3. Check each branch against existing tests:**
439
+
440
+ Go through your diagram branch by branch — both code paths AND user flows. For each one, search for a test that exercises it:
441
+ - Function `processPayment()` → look for `billing.test.ts`, `billing.spec.ts`, `test/billing_test.rb`
442
+ - An if/else → look for tests covering BOTH the true AND false path
443
+ - An error handler → look for a test that triggers that specific error condition
444
+ - A call to `helperFn()` that has its own branches → those branches need tests too
445
+ - A user flow → look for an integration or E2E test that walks through the journey
446
+ - An interaction edge case → look for a test that simulates the unexpected action
447
+
448
+ Quality scoring rubric:
449
+ - ★★★ Tests behavior with edge cases AND error paths
450
+ - ★★ Tests correct behavior, happy path only
451
+ - ★ Smoke test / existence check / trivial assertion (e.g., "it renders", "it doesn't throw")
452
+
453
+ **4. Output ASCII coverage diagram:**
454
+
455
+ Include BOTH code paths and user flows in the same diagram:
456
+
457
+ ```
458
+ CODE PATH COVERAGE
459
+ ===========================
460
+ [+] src/services/billing.ts
461
+
462
+ ├── processPayment()
463
+ │ ├── [★★★ TESTED] Happy path + card declined + timeout — billing.test.ts:42
464
+ │ ├── [GAP] Network timeout — NO TEST
465
+ │ └── [GAP] Invalid currency — NO TEST
466
+
467
+ └── refundPayment()
468
+ ├── [★★ TESTED] Full refund — billing.test.ts:89
469
+ └── [★ TESTED] Partial refund (checks non-throw only) — billing.test.ts:101
470
+
471
+ USER FLOW COVERAGE
472
+ ===========================
473
+ [+] Payment checkout flow
474
+
475
+ ├── [★★★ TESTED] Complete purchase — checkout.e2e.ts:15
476
+ ├── [GAP] Double-click submit — NO TEST
477
+ ├── [GAP] Navigate away during payment — NO TEST
478
+ └── [★ TESTED] Form validation errors (checks render only) — checkout.test.ts:40
479
+
480
+ [+] Error states
481
+
482
+ ├── [★★ TESTED] Card declined message — billing.test.ts:58
483
+ ├── [GAP] Network timeout UX (what does user see?) — NO TEST
484
+ └── [GAP] Empty cart submission — NO TEST
485
+
486
+ ─────────────────────────────────
487
+ COVERAGE: 5/12 paths tested (42%)
488
+ Code paths: 3/5 (60%)
489
+ User flows: 2/7 (29%)
490
+ QUALITY: ★★★: 2 ★★: 2 ★: 1
491
+ GAPS: 7 paths need tests
492
+ ─────────────────────────────────
493
+ ```
494
+
495
+ **Fast path:** All paths covered → "Step 3.4: All new code paths have test coverage ✓" Continue.
496
+
497
+ **5. Generate tests for uncovered paths:**
498
+
499
+ If test framework detected (or bootstrapped in Step 2.5):
500
+ - Prioritize error handlers and edge cases first (happy paths are more likely already tested)
501
+ - Read 2-3 existing test files to match conventions exactly
502
+ - Generate unit tests. Mock all external dependencies (DB, API, Redis).
503
+ - Write tests that exercise the specific uncovered path with real assertions
504
+ - Run each test. Passes → commit as `test: coverage for {feature}`
505
+ - Fails → fix once. Still fails → revert, note gap in diagram.
506
+
507
+ Caps: 30 code paths max, 20 tests generated max (code + user flow combined), 2-min per-test exploration cap.
508
+
509
+ If no test framework AND user declined bootstrap → diagram only, no generation. Note: "Test generation skipped — no test framework configured."
510
+
511
+ **Diff is test-only changes:** Skip Step 3.4 entirely: "No new application code paths to audit."
512
+
513
+ **6. After-count and coverage summary:**
514
+
515
+ ```bash
516
+ # Count test files after generation
517
+ find . -name '*.test.*' -o -name '*.spec.*' -o -name '*_test.*' -o -name '*_spec.*' | grep -v node_modules | wc -l
518
+ ```
519
+
520
+ For PR body: `Tests: {before} → {after} (+{delta} new)`
521
+ Coverage line: `Test Coverage Audit: N new code paths. M covered (X%). K tests generated, J committed.`
522
+
523
+ ---
524
+
525
+ ## Step 3.5: Pre-Landing Review
526
+
527
+ Review the diff for structural issues that tests don't catch.
528
+
529
+ 1. Read `.claude/skills/review/checklist.md`. If the file cannot be read, **STOP** and report the error.
530
+
531
+ 2. Run `git diff origin/<base>` to get the full diff (scoped to feature changes against the freshly-fetched base branch).
532
+
533
+ 3. Apply the review checklist in two passes:
534
+ - **Pass 1 (CRITICAL):** SQL & Data Safety, LLM Output Trust Boundary
535
+ - **Pass 2 (INFORMATIONAL):** All remaining categories
536
+
537
+ ## Design Review (conditional, diff-scoped)
538
+
539
+ Check if the diff touches frontend files using `orch-diff-scope`:
540
+
541
+ ```bash
542
+ source <(~/.claude/skills/orch/bin/orch-diff-scope <base> 2>/dev/null)
543
+ ```
544
+
545
+ **If `SCOPE_FRONTEND=false`:** Skip design review silently. No output.
546
+
547
+ **If `SCOPE_FRONTEND=true`:**
548
+
549
+ 1. **Check for DESIGN.md.** If `DESIGN.md` or `design-system.md` exists in the repo root, read it. All design findings are calibrated against it — patterns blessed in DESIGN.md are not flagged. If not found, use universal design principles.
550
+
551
+ 2. **Read `.claude/skills/review/design-checklist.md`.** If the file cannot be read, skip design review with a note: "Design checklist not found — skipping design review."
552
+
553
+ 3. **Read each changed frontend file** (full file, not just diff hunks). Frontend files are identified by the patterns listed in the checklist.
554
+
555
+ 4. **Apply the design checklist** against the changed files. For each item:
556
+ - **[HIGH] mechanical CSS fix** (`outline: none`, `!important`, `font-size < 16px`): classify as AUTO-FIX
557
+ - **[HIGH/MEDIUM] design judgment needed**: classify as ASK
558
+ - **[LOW] intent-based detection**: present as "Possible — verify visually or run /design-review"
559
+
560
+ 5. **Include findings** in the review output under a "Design Review" header, following the output format in the checklist. Design findings merge with code review findings into the same Fix-First flow.
561
+
562
+ 6. **Log the result** for the Review Readiness Dashboard:
563
+
564
+ ```bash
565
+ ~/.claude/skills/orch/bin/orch-review-log '{"skill":"design-review-lite","timestamp":"TIMESTAMP","status":"STATUS","findings":N,"auto_fixed":M,"commit":"COMMIT"}'
566
+ ```
567
+
568
+ Substitute: TIMESTAMP = ISO 8601 datetime, STATUS = "clean" if 0 findings or "issues_found", N = total findings, M = auto-fixed count, COMMIT = output of `git rev-parse --short HEAD`.
569
+
570
+ Include any design findings alongside the code review findings. They follow the same Fix-First flow below.
571
+
572
+ 4. **Classify each finding as AUTO-FIX or ASK** per the Fix-First Heuristic in
573
+ checklist.md. Critical findings lean toward ASK; informational lean toward AUTO-FIX.
574
+
575
+ 5. **Auto-fix all AUTO-FIX items.** Apply each fix. Output one line per fix:
576
+ `[AUTO-FIXED] [file:line] Problem → what you did`
577
+
578
+ 6. **If ASK items remain,** present them in ONE AskUserQuestion:
579
+ - List each with number, severity, problem, recommended fix
580
+ - Per-item options: A) Fix B) Skip
581
+ - Overall RECOMMENDATION
582
+ - If 3 or fewer ASK items, you may use individual AskUserQuestion calls instead
583
+
584
+ 7. **After all fixes (auto + user-approved):**
585
+ - If ANY fixes were applied: commit fixed files by name (`git add <fixed-files> && git commit -m "fix: pre-landing review fixes"`), then **STOP** and tell the user to run `/ship` again to re-test.
586
+ - If no fixes applied (all ASK items skipped, or no issues found): continue to Step 4.
587
+
588
+ 8. Output summary: `Pre-Landing Review: N issues — M auto-fixed, K asked (J fixed, L skipped)`
589
+
590
+ If no issues found: `Pre-Landing Review: No issues found.`
591
+
592
+ Save the review output — it goes into the PR body in Step 8.
593
+
594
+ ---
595
+
596
+ ## Step 3.75: Address Greptile review comments (if PR exists)
597
+
598
+ Read `.claude/skills/review/greptile-triage.md` and follow the fetch, filter, classify, and **escalation detection** steps.
599
+
600
+ **If no PR exists, `gh` fails, API returns an error, or there are zero Greptile comments:** Skip this step silently. Continue to Step 4.
601
+
602
+ **If Greptile comments are found:**
603
+
604
+ Include a Greptile summary in your output: `+ N Greptile comments (X valid, Y fixed, Z FP)`
605
+
606
+ 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.
607
+
608
+ For each classified comment:
609
+
610
+ **VALID & ACTIONABLE:** Use AskUserQuestion with:
611
+ - The comment (file:line or [top-level] + body summary + permalink URL)
612
+ - `RECOMMENDATION: Choose A because [one-line reason]`
613
+ - Options: A) Fix now, B) Acknowledge and ship anyway, C) It's a false positive
614
+ - If user chooses A: apply the fix, commit the fixed files (`git add <fixed-files> && git commit -m "fix: address Greptile review — <brief description>"`), 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).
615
+ - 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).
616
+
617
+ **VALID BUT ALREADY FIXED:** Reply using the **Already Fixed reply template** from greptile-triage.md — no AskUserQuestion needed:
618
+ - Include what was done and the fixing commit SHA
619
+ - Save to both per-project and global greptile-history (type: already-fixed)
620
+
621
+ **FALSE POSITIVE:** Use AskUserQuestion:
622
+ - Show the comment and why you think it's wrong (file:line or [top-level] + body summary + permalink URL)
623
+ - Options:
624
+ - A) Reply to Greptile explaining the false positive (recommended if clearly wrong)
625
+ - B) Fix it anyway (if trivial)
626
+ - C) Ignore silently
627
+ - 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)
628
+
629
+ **SUPPRESSED:** Skip silently — these are known false positives from previous triage.
630
+
631
+ **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.
632
+
633
+ ---
634
+
635
+ ## Step 3.8: Adversarial review (auto-scaled)
636
+
637
+ Adversarial review thoroughness scales automatically based on diff size. No configuration needed.
638
+
639
+ **Detect diff size and tool availability:**
640
+
641
+ ```bash
642
+ DIFF_INS=$(git diff origin/<base> --stat | tail -1 | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' || echo "0")
643
+ DIFF_DEL=$(git diff origin/<base> --stat | tail -1 | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' || echo "0")
644
+ DIFF_TOTAL=$((DIFF_INS + DIFF_DEL))
645
+ which codex 2>/dev/null && echo "CODEX_AVAILABLE" || echo "CODEX_NOT_AVAILABLE"
646
+ # Respect old opt-out
647
+ OLD_CFG=$(~/.claude/skills/orch/bin/orch-config get codex_reviews 2>/dev/null || true)
648
+ echo "DIFF_SIZE: $DIFF_TOTAL"
649
+ echo "OLD_CFG: ${OLD_CFG:-not_set}"
650
+ ```
651
+
652
+ If `OLD_CFG` is `disabled`: skip this step silently. Continue to the next step.
653
+
654
+ **User override:** If the user explicitly requested a specific tier (e.g., "run all passes", "paranoid review", "full adversarial", "do all 4 passes", "thorough review"), honor that request regardless of diff size. Jump to the matching tier section.
655
+
656
+ **Auto-select tier based on diff size:**
657
+ - **Small (< 50 lines changed):** Skip adversarial review entirely. Print: "Small diff ($DIFF_TOTAL lines) — adversarial review skipped." Continue to the next step.
658
+ - **Medium (50–199 lines changed):** Run Codex adversarial challenge (or Claude adversarial subagent if Codex unavailable). Jump to the "Medium tier" section.
659
+ - **Large (200+ lines changed):** Run all remaining passes — Codex structured review + Claude adversarial subagent + Codex adversarial. Jump to the "Large tier" section.
660
+
661
+ ---
662
+
663
+ ### Medium tier (50–199 lines)
664
+
665
+ Claude's structured review already ran. Now add a **cross-model adversarial challenge**.
666
+
667
+ **If Codex is available:** run the Codex adversarial challenge. **If Codex is NOT available:** fall back to the Claude adversarial subagent instead.
668
+
669
+ **Codex adversarial:**
670
+
671
+ ```bash
672
+ TMPERR_ADV=$(mktemp /tmp/codex-adv-XXXXXXXX)
673
+ codex exec "Review the changes on this branch against the base branch. Run git diff origin/<base> to see the diff. Your job is to find ways this code will fail in production. Think like an attacker and a chaos engineer. Find edge cases, race conditions, security holes, resource leaks, failure modes, and silent data corruption paths. Be adversarial. Be thorough. No compliments — just the problems." -s read-only -c 'model_reasoning_effort="xhigh"' --enable web_search_cached 2>"$TMPERR_ADV"
674
+ ```
675
+
676
+ Use a 5-minute timeout (`timeout: 300000`). After the command completes, read stderr:
677
+ ```bash
678
+ cat "$TMPERR_ADV"
679
+ ```
680
+
681
+ Present the full output verbatim. This is informational — it never blocks shipping.
682
+
683
+ **Error handling:** All errors are non-blocking — adversarial review is a quality enhancement, not a prerequisite.
684
+ - **Auth failure:** If stderr contains "auth", "login", "unauthorized", or "API key": "Codex authentication failed. Run \`codex login\` to authenticate."
685
+ - **Timeout:** "Codex timed out after 5 minutes."
686
+ - **Empty response:** "Codex returned no response. Stderr: <paste relevant error>."
687
+
688
+ On any Codex error, fall back to the Claude adversarial subagent automatically.
689
+
690
+ **Claude adversarial subagent** (fallback when Codex unavailable or errored):
691
+
692
+ Dispatch via the Agent tool. The subagent has fresh context — no checklist bias from the structured review. This genuine independence catches things the primary reviewer is blind to.
693
+
694
+ Subagent prompt:
695
+ "Read the diff for this branch with `git diff origin/<base>`. Think like an attacker and a chaos engineer. Your job is to find ways this code will fail in production. Look for: edge cases, race conditions, security holes, resource leaks, failure modes, silent data corruption, logic errors that produce wrong results silently, error handling that swallows failures, and trust boundary violations. Be adversarial. Be thorough. No compliments — just the problems. For each finding, classify as FIXABLE (you know how to fix it) or INVESTIGATE (needs human judgment)."
696
+
697
+ Present findings under an `ADVERSARIAL REVIEW (Claude subagent):` header. **FIXABLE findings** flow into the same Fix-First pipeline as the structured review. **INVESTIGATE findings** are presented as informational.
698
+
699
+ If the subagent fails or times out: "Claude adversarial subagent unavailable. Continuing without adversarial review."
700
+
701
+ **Persist the review result:**
702
+ ```bash
703
+ ~/.claude/skills/orch/bin/orch-review-log '{"skill":"adversarial-review","timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","status":"STATUS","source":"SOURCE","tier":"medium","commit":"'"$(git rev-parse --short HEAD)"'"}'
704
+ ```
705
+ Substitute STATUS: "clean" if no findings, "issues_found" if findings exist. SOURCE: "codex" if Codex ran, "claude" if subagent ran. If both failed, do NOT persist.
706
+
707
+ **Cleanup:** Run `rm -f "$TMPERR_ADV"` after processing (if Codex was used).
708
+
709
+ ---
710
+
711
+ ### Large tier (200+ lines)
712
+
713
+ Claude's structured review already ran. Now run **all three remaining passes** for maximum coverage:
714
+
715
+ **1. Codex structured review (if available):**
716
+ ```bash
717
+ TMPERR=$(mktemp /tmp/codex-review-XXXXXXXX)
718
+ codex review --base <base> -c 'model_reasoning_effort="xhigh"' --enable web_search_cached 2>"$TMPERR"
719
+ ```
720
+
721
+ Use a 5-minute timeout. Present output under `CODEX SAYS (code review):` header.
722
+ Check for `[P1]` markers: found → `GATE: FAIL`, not found → `GATE: PASS`.
723
+
724
+ If GATE is FAIL, use AskUserQuestion:
725
+ ```
726
+ Codex found N critical issues in the diff.
727
+
728
+ A) Investigate and fix now (recommended)
729
+ B) Continue — review will still complete
730
+ ```
731
+
732
+ If A: address the findings. After fixing, re-run tests (Step 3) since code has changed. Re-run `codex review` to verify.
733
+
734
+ Read stderr for errors (same error handling as medium tier).
735
+
736
+ After stderr: `rm -f "$TMPERR"`
737
+
738
+ **2. Claude adversarial subagent:** Dispatch a subagent with the adversarial prompt (same prompt as medium tier). This always runs regardless of Codex availability.
739
+
740
+ **3. Codex adversarial challenge (if available):** Run `codex exec` with the adversarial prompt (same as medium tier).
741
+
742
+ If Codex is not available for steps 1 and 3, note to the user: "Codex CLI not found — large-diff review ran Claude structured + Claude adversarial (2 of 4 passes). Install Codex for full 4-pass coverage: `npm install -g @openai/codex`"
743
+
744
+ **Persist the review result AFTER all passes complete** (not after each sub-step):
745
+ ```bash
746
+ ~/.claude/skills/orch/bin/orch-review-log '{"skill":"adversarial-review","timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","status":"STATUS","source":"SOURCE","tier":"large","gate":"GATE","commit":"'"$(git rev-parse --short HEAD)"'"}'
747
+ ```
748
+ Substitute: STATUS = "clean" if no findings across ALL passes, "issues_found" if any pass found issues. SOURCE = "both" if Codex ran, "claude" if only Claude subagent ran. GATE = the Codex structured review gate result ("pass"/"fail"), or "informational" if Codex was unavailable. If all passes failed, do NOT persist.
749
+
750
+ ---
751
+
752
+ ### Cross-model synthesis (medium and large tiers)
753
+
754
+ After all passes complete, synthesize findings across all sources:
755
+
756
+ ```
757
+ ADVERSARIAL REVIEW SYNTHESIS (auto: TIER, N lines):
758
+ ════════════════════════════════════════════════════════════
759
+ High confidence (found by multiple sources): [findings agreed on by >1 pass]
760
+ Unique to Claude structured review: [from earlier step]
761
+ Unique to Claude adversarial: [from subagent, if ran]
762
+ Unique to Codex: [from codex adversarial or code review, if ran]
763
+ Models used: Claude structured ✓ Claude adversarial ✓/✗ Codex ✓/✗
764
+ ════════════════════════════════════════════════════════════
765
+ ```
766
+
767
+ High-confidence findings (agreed on by multiple sources) should be prioritized for fixes.
768
+
769
+ ---
770
+
771
+ ## Step 4: Version bump (auto-decide)
772
+
773
+ 1. Read the current `VERSION` file (4-digit format: `MAJOR.MINOR.PATCH.MICRO`)
774
+
775
+ 2. **Auto-decide the bump level based on the diff:**
776
+ - Count lines changed (`git diff origin/<base>...HEAD --stat | tail -1`)
777
+ - **MICRO** (4th digit): < 50 lines changed, trivial tweaks, typos, config
778
+ - **PATCH** (3rd digit): 50+ lines changed, bug fixes, small-medium features
779
+ - **MINOR** (2nd digit): **ASK the user** — only for major features or significant architectural changes
780
+ - **MAJOR** (1st digit): **ASK the user** — only for milestones or breaking changes
781
+
782
+ 3. Compute the new version:
783
+ - Bumping a digit resets all digits to its right to 0
784
+ - Example: `0.19.1.0` + PATCH → `0.19.2.0`
785
+
786
+ 4. Write the new version to the `VERSION` file.
787
+
788
+ ---
789
+
790
+ ## Step 5: CHANGELOG (auto-generate)
791
+
792
+ 1. Read `CHANGELOG.md` header to know the format.
793
+
794
+ 2. Auto-generate the entry from **ALL commits on the branch** (not just recent ones):
795
+ - Use `git log <base>..HEAD --oneline` to see every commit being shipped
796
+ - Use `git diff <base>...HEAD` to see the full diff against the base branch
797
+ - The CHANGELOG entry must be comprehensive of ALL changes going into the PR
798
+ - If existing CHANGELOG entries on the branch already cover some commits, replace them with one unified entry for the new version
799
+ - Categorize changes into applicable sections:
800
+ - `### Added` — new features
801
+ - `### Changed` — changes to existing functionality
802
+ - `### Fixed` — bug fixes
803
+ - `### Removed` — removed features
804
+ - Write concise, descriptive bullet points
805
+ - Insert after the file header (line 5), dated today
806
+ - Format: `## [X.Y.Z.W] - YYYY-MM-DD`
807
+
808
+ **Do NOT ask the user to describe changes.** Infer from the diff and commit history.
809
+
810
+ ---
811
+
812
+ ## Step 5.5: TODOS.md (auto-update)
813
+
814
+ 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.
815
+
816
+ Read `.claude/skills/review/TODOS-format.md` for the canonical format reference.
817
+
818
+ **1. Check if TODOS.md exists** in the repository root.
819
+
820
+ **If TODOS.md does not exist:** Use AskUserQuestion:
821
+ - 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?"
822
+ - Options: A) Create it now, B) Skip for now
823
+ - If A: Create `TODOS.md` with a skeleton (# TODOS heading + ## Completed section). Continue to step 3.
824
+ - If B: Skip the rest of Step 5.5. Continue to Step 6.
825
+
826
+ **2. Check structure and organization:**
827
+
828
+ Read TODOS.md and verify it follows the recommended structure:
829
+ - Items grouped under `## <Skill/Component>` headings
830
+ - Each item has `**Priority:**` field with P0-P4 value
831
+ - A `## Completed` section at the bottom
832
+
833
+ **If disorganized** (missing priority fields, no component groupings, no Completed section): Use AskUserQuestion:
834
+ - Message: "TODOS.md doesn't follow the recommended structure (skill/component groupings, P0-P4 priority, Completed section). Would you like to reorganize it?"
835
+ - Options: A) Reorganize now (recommended), B) Leave as-is
836
+ - If A: Reorganize in-place following TODOS-format.md. Preserve all content — only restructure, never delete items.
837
+ - If B: Continue to step 3 without restructuring.
838
+
839
+ **3. Detect completed TODOs:**
840
+
841
+ This step is fully automatic — no user interaction.
842
+
843
+ Use the diff and commit history already gathered in earlier steps:
844
+ - `git diff <base>...HEAD` (full diff against the base branch)
845
+ - `git log <base>..HEAD --oneline` (all commits being shipped)
846
+
847
+ For each TODO item, check if the changes in this PR complete it by:
848
+ - Matching commit messages against the TODO title and description
849
+ - Checking if files referenced in the TODO appear in the diff
850
+ - Checking if the TODO's described work matches the functional changes
851
+
852
+ **Be conservative:** Only mark a TODO as completed if there is clear evidence in the diff. If uncertain, leave it alone.
853
+
854
+ **4. Move completed items** to the `## Completed` section at the bottom. Append: `**Completed:** vX.Y.Z (YYYY-MM-DD)`
855
+
856
+ **5. Output summary:**
857
+ - `TODOS.md: N items marked complete (item1, item2, ...). M items remaining.`
858
+ - Or: `TODOS.md: No completed items detected. M items remaining.`
859
+ - Or: `TODOS.md: Created.` / `TODOS.md: Reorganized.`
860
+
861
+ **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.
862
+
863
+ Save this summary — it goes into the PR body in Step 8.
864
+
865
+ ---
866
+
867
+ ## Step 6: Commit (bisectable chunks)
868
+
869
+ **Goal:** Create small, logical commits that work well with `git bisect` and help LLMs understand what changed.
870
+
871
+ 1. Analyze the diff and group changes into logical commits. Each commit should represent **one coherent change** — not one file, but one logical unit.
872
+
873
+ 2. **Commit ordering** (earlier commits first):
874
+ - **Infrastructure:** migrations, config changes, route additions
875
+ - **Models & services:** new models, services, concerns (with their tests)
876
+ - **Controllers & views:** controllers, views, JS/React components (with their tests)
877
+ - **VERSION + CHANGELOG + TODOS.md:** always in the final commit
878
+
879
+ 3. **Rules for splitting:**
880
+ - A model and its test file go in the same commit
881
+ - A service and its test file go in the same commit
882
+ - A controller, its views, and its test go in the same commit
883
+ - Migrations are their own commit (or grouped with the model they support)
884
+ - Config/route changes can group with the feature they enable
885
+ - If the total diff is small (< 50 lines across < 4 files), a single commit is fine
886
+
887
+ 4. **Each commit must be independently valid** — no broken imports, no references to code that doesn't exist yet. Order commits so dependencies come first.
888
+
889
+ 5. Compose each commit message:
890
+ - First line: `<type>: <summary>` (type = feat/fix/chore/refactor/docs)
891
+ - Body: brief description of what this commit contains
892
+ - Only the **final commit** (VERSION + CHANGELOG) gets the version tag and co-author trailer:
893
+
894
+ ```bash
895
+ git commit -m "$(cat <<'EOF'
896
+ chore: bump version and changelog (vX.Y.Z.W)
897
+
898
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
899
+ EOF
900
+ )"
901
+ ```
902
+
903
+ ---
904
+
905
+ ## Step 6.5: Verification Gate
906
+
907
+ **IRON LAW: NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE.**
908
+
909
+ Before pushing, re-verify if code changed during Steps 4-6:
910
+
911
+ 1. **Test verification:** If ANY code changed after Step 3's test run (fixes from review findings, CHANGELOG edits don't count), re-run the test suite. Paste fresh output. Stale output from Step 3 is NOT acceptable.
912
+
913
+ 2. **Build verification:** If the project has a build step, run it. Paste output.
914
+
915
+ 3. **Rationalization prevention:**
916
+ - "Should work now" → RUN IT.
917
+ - "I'm confident" → Confidence is not evidence.
918
+ - "I already tested earlier" → Code changed since then. Test again.
919
+ - "It's a trivial change" → Trivial changes break production.
920
+
921
+ **If tests fail here:** STOP. Do not push. Fix the issue and return to Step 3.
922
+
923
+ Claiming work is complete without verification is dishonesty, not efficiency.
924
+
925
+ ---
926
+
927
+ ## Step 7: Push
928
+
929
+ Push to the remote with upstream tracking:
930
+
931
+ ```bash
932
+ git push -u origin <branch-name>
933
+ ```
934
+
935
+ ---
936
+
937
+ ## Step 8: Create PR
938
+
939
+ Create a pull request using `gh`:
940
+
941
+ ```bash
942
+ gh pr create --base <base> --title "<type>: <summary>" --body "$(cat <<'EOF'
943
+ ## Summary
944
+ <bullet points from CHANGELOG>
945
+
946
+ ## Test Coverage
947
+ <coverage diagram from Step 3.4, or "All new code paths have test coverage.">
948
+ <If Step 3.4 ran: "Tests: {before} → {after} (+{delta} new)">
949
+
950
+ ## Pre-Landing Review
951
+ <findings from Step 3.5 code review, or "No issues found.">
952
+
953
+ ## Design Review
954
+ <If design review ran: "Design Review (lite): N findings — M auto-fixed, K skipped. AI Slop: clean/N issues.">
955
+ <If no frontend files changed: "No frontend files changed — design review skipped.">
956
+
957
+ ## Eval Results
958
+ <If evals ran: suite names, pass/fail counts, cost dashboard summary. If skipped: "No prompt-related files changed — evals skipped.">
959
+
960
+ ## Greptile Review
961
+ <If Greptile comments were found: bullet list with [FIXED] / [FALSE POSITIVE] / [ALREADY FIXED] tag + one-line summary per comment>
962
+ <If no Greptile comments found: "No Greptile comments.">
963
+ <If no PR existed during Step 3.75: omit this section entirely>
964
+
965
+ ## TODOS
966
+ <If items marked complete: bullet list of completed items with version>
967
+ <If no items completed: "No TODO items completed in this PR.">
968
+ <If TODOS.md created or reorganized: note that>
969
+ <If TODOS.md doesn't exist and user skipped: omit this section>
970
+
971
+ ## Test plan
972
+ - [x] All Rails tests pass (N runs, 0 failures)
973
+ - [x] All Vitest tests pass (N tests)
974
+
975
+ 🤖 Generated with [Claude Code](https://claude.com/claude-code)
976
+ EOF
977
+ )"
978
+ ```
979
+
980
+ **Output the PR URL** — then proceed to Step 8.5.
981
+
982
+ ---
983
+
984
+ ## Step 8.5: Auto-invoke /document-release
985
+
986
+ After the PR is created, automatically sync project documentation. Read the
987
+ `document-release/SKILL.md` skill file (adjacent to this skill's directory) and
988
+ execute its full workflow:
989
+
990
+ 1. Read the `/document-release` skill: `cat ${CLAUDE_SKILL_DIR}/../document-release/SKILL.md`
991
+ 2. Follow its instructions — it reads all .md files in the project, cross-references
992
+ the diff, and updates anything that drifted (README, ARCHITECTURE, CONTRIBUTING,
993
+ CLAUDE.md, TODOS, etc.)
994
+ 3. If any docs were updated, commit the changes and push to the same branch:
995
+ ```bash
996
+ git add -A && git commit -m "docs: sync documentation with shipped changes" && git push
997
+ ```
998
+ 4. If no docs needed updating, say "Documentation is current — no updates needed."
999
+
1000
+ This step is automatic. Do not ask the user for confirmation. The goal is zero-friction
1001
+ doc updates — the user runs `/ship` and documentation stays current without a separate command.
1002
+
1003
+ ---
1004
+
1005
+ ## Important Rules
1006
+
1007
+ - **Never skip tests.** If tests fail, stop.
1008
+ - **Never skip the pre-landing review.** If checklist.md is unreadable, stop.
1009
+ - **Never force push.** Use regular `git push` only.
1010
+ - **Never ask for trivial confirmations** (e.g., "ready to push?", "create PR?"). DO stop for: version bumps (MINOR/MAJOR), pre-landing review findings (ASK items), and Codex structured review [P1] findings (large diffs only).
1011
+ - **Always use the 4-digit version format** from the VERSION file.
1012
+ - **Date format in CHANGELOG:** `YYYY-MM-DD`
1013
+ - **Split commits for bisectability** — each commit = one logical change.
1014
+ - **TODOS.md completion detection must be conservative.** Only mark items as completed when the diff clearly shows the work is done.
1015
+ - **Use Greptile reply templates from greptile-triage.md.** Every reply includes evidence (inline diff, code references, re-rank suggestion). Never post vague replies.
1016
+ - **Never push without fresh verification evidence.** If code changed after Step 3 tests, re-run before pushing.
1017
+ - **Step 3.4 generates coverage tests.** They must pass before committing. Never commit failing tests.
1018
+ - **The goal is: user says `/ship`, next thing they see is the review + PR URL + auto-synced docs.**