# Qship

> Full Jira-ticket → PR pipeline (plan, implement, review, test, ship). Supports parallel and epic-mode execution. Two independent engine knobs — `provider=claude|codex` chooses the Step 7 implementer (default Claude Opus 4.7 1M, medium reasoning), and `reviewer=claude|codex` chooses the Phase 2 reviewer (default Claude). Most useful combination beyond defaults is `provider=claude reviewer=codex` (…

- **Type:** Skill
- **Install:** `agentstack add skill-3awny-qship-qship`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [3awny](https://agentstack.voostack.com/s/3awny)
- **Installs:** 0
- **Category:** [Productivity](https://agentstack.voostack.com/c/productivity)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [3awny](https://github.com/3awny)
- **Source:** https://github.com/3awny/qship/tree/main/templates/skills/qship

## Install

```sh
agentstack add skill-3awny-qship-qship
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

> **Issue source — `tracker = {{TRACKER_TYPE}}`** (chosen at onboarding). Follow the issue-source protocol in `$SKILLS_ROOT/qship/references/tracker-contract.md` — it defines, per tracker, how to FETCH / CHILDREN / CREATE / TRANSITION / READ-TRD. For `none`: treat `$ARGUMENTS` as the spec (pasted text or a local file path) and skip all tracker MCP calls.

# qship -- Full Development Pipeline

Orchestrates the complete development lifecycle for one or more Jira tickets. Takes ticket IDs, fetches details from Jira, creates branches, plans implementation, writes code, reviews, hunts for bugs, fixes issues, and creates pull requests.

## ⛔ Read first — autonomy contract & hook enforcement

**Before doing anything, read [references/autonomy-contract.md](references/autonomy-contract.md) in full.** It defines persistence rules, the read-before-execute rule, the no-skip rule, and local-DB pre-authorisation. Every section below assumes you've internalised it. Sub-agents you spawn must read it too — pass them a one-line pointer, never paste the contract verbatim.

A skill is a prompt; prompts can be hallucinated past. qship backs the soft rules with three hard layers: `PreToolUse` blocks PR-create/push without evidence, `Stop`/`SubagentStop` blocks termination while progress files have PENDING rows, and `qship-persist.sh` is the outer ralph loop that keeps re-invoking until `/qshipcheck` says PASSED. Without those hooks the contract is advisory — verify they're wired with `jq '.hooks | keys' ~/.claude/settings.json` (expect PreToolUse, Stop, SubagentStop).

### The three enforcement layers

1. **`PreToolUse` hook — `require-phase3-evidence.sh`** (already wired in `~/.claude/settings.json`)
   Blocks `gh pr create`, `git push ... {{JIRA_PROJECT_KEY}}-*`, and `gh pr comment` when `{{STATE_ROOT}}/worktrees//phase3-evidence.md` is missing, empty, or lacks HTTP/curl output + a "no network surface" rationale. Keeps Phase 4 from running with fake Phase 3 evidence.

2. **`Stop` + `SubagentStop` hooks — `require-pipeline-complete.sh`** (wired in `~/.claude/settings.json`)
   On every attempted termination, the hook reads `{{STATE_ROOT}}/worktrees/*/phase2-progress.md`, `phase3-evidence.md`, and `trd-coverage.json` (modified within the last `QSHIP_FRESHNESS_MIN=240` minutes) and returns `{"decision":"block","reason":"..."}` whenever:
   - a `phase2-progress.md` row is still `PENDING`, or
   - `phase3-evidence.md` is empty / lacks HTTP evidence / lacks "no network surface" rationale, or
   - `trd-coverage.json` has any row with `passes: false`.
   Includes a `stop_hook_active` guard to prevent infinite loops. Stale worktrees (>4h untouched) are treated as abandoned and do NOT block — delete them to clear stuck blocks. **This is what stops the orchestrator hallucinating completion mid-pipeline** — the LLM no longer decides whether to continue; the progress files do.

3. **Outer persistence loop — `qship-persist.sh`** (ralph pattern wrapper)
   For fully unattended runs, launch qship via:
   ```bash
   bash {{USER_HOME}}/.claude/skills/qship/hooks/qship-persist.sh {{JIRA_PROJECT_KEY}}-42
   # or for a batch:
   MAX_ITERS=15 bash {{USER_HOME}}/.claude/skills/qship/hooks/qship-persist.sh {{JIRA_PROJECT_KEY}}-1 {{JIRA_PROJECT_KEY}}-2 {{JIRA_PROJECT_KEY}}-3
   ```
   This bash loop re-invokes `claude -p "/qship $TICKET"` with a fresh context each iteration until `claude -p "/qshipcheck $TICKET"` prints `PASSED`. State lives in the filesystem (`{{STATE_ROOT}}/worktrees//`), so each iteration resumes exactly where the previous one left off. Survives context compaction, dropped connections, and rogue "I'm done" completion reports. Logs per-ticket to `{{STATE_ROOT}}/persist-logs/`.

**Permission allowlist (3rd layer of physical unblocking).** The project `.claude/settings.local.json` pre-authorises the bash patterns qship routinely runs (alembic, migration runners, `{{STATE_ROOT}}/worktrees/*` scripts, worktree `cp` commands, `claude -p /qship*`). The text in SKILL.md that says "local DB writes are pre-authorised" now has an actual allowlist backing it — prompts do not auto-approve anything; the JSON file does.

### How the three layers compose

| Failure mode | What catches it |
|---|---|
| Orchestrator says "pipeline complete" with Phase 3 unrun | `PreToolUse` blocks the push/PR |
| Orchestrator tries to yield to user with PENDING rows | `Stop` hook blocks termination, feeds back the specific PENDING steps |
| Context compaction drops the autonomy contract from prompt | `qship-persist.sh` restarts a fresh session and the `Stop` hook immediately picks up the pending state |
| Sub-agent reports "skipped for time" | Orchestrator's progress file still shows PENDING → next iteration continues that step |
| `alembic upgrade head` triggers a permission prompt | Allowlist entry pre-authorises — no pause |

### Hook files

- `~/.claude/skills/qship/hooks/qship-evidence-lib.sh` — shared evidence validator (sourced by the two hooks below)
- `~/.claude/skills/qship/hooks/require-phase3-evidence.sh` — PreToolUse (Phase 4 gate on PR create / epic push)
- `~/.claude/skills/qship/hooks/require-pre-pr-test-pass.sh` — PreToolUse (Step 12.0 gate: blocks `gh pr create` until full test suite is fresh-green per repo via `phase4-tests-passed..flag` files)
- `~/.claude/skills/qship/hooks/require-pipeline-complete.sh` — Stop + SubagentStop (anti-yield gate)
- `~/.claude/skills/qship/hooks/qship-compute-context.sh` — classifies the diff into API/UI booleans (run by Phase 1)
- `~/.claude/skills/qship/hooks/qship-persist.sh` — outer loop (ralph wrapper)
- `~/.claude/skills/qship/hooks/qship-watchdog.sh` — one-shot stall detector (file mtime + commit age + suspicious-idle-child sniff). Orchestrator runs this every ~5 min while a Phase 1/2/3/4 worker is in background. See "Worker stall watchdog" below.

### Worker stall watchdog (orchestrator-side loop)

Background workers can wedge mid-step (the canonical failure: an xhigh planner subprocess held open stdio and stalled the worker's Bash tool for 2+ hours on {{JIRA_PROJECT_KEY}}-EX11 — see [feedback_qship_worker_stall_watchdog.md](file://{{USER_HOME}}/.claude/projects/-Users-{{LOCAL_DB_USER}}-work-{{GH_ORG}}-{{COMPANY_SLUG}}-codebase/memory/feedback_qship_worker_stall_watchdog.md)). The harness reports the agent as "running" indefinitely because the agent never finishes a tool call. Without a watchdog the orchestrator silently waits forever.

**Rule for every background worker dispatch:** after `Agent(... run_in_background: true)`, the orchestrator MUST poll progress every 5 minutes via the watchdog. The cheapest mechanism depends on how you were invoked:

| Invocation | Recommended cadence mechanism |
|---|---|
| `/loop 5m /qship ` (preferred for unattended) | The /loop interval is itself the watchdog tick — every fire, run `qship-watchdog.sh` and react. |
| In-session `/qship ` | After each background dispatch, schedule a re-entry via `ScheduleWakeup delaySeconds=300` (when in /loop dynamic mode) OR manually run `bash ~/.claude/skills/qship/hooks/qship-watchdog.sh  --strict` on each turn before sending control back to the user. |
| `qship-persist.sh` outer loop | The persist loop already re-enters every iteration; add a watchdog call near the top of each iteration. |

**Watchdog mechanics** (`qship-watchdog.sh ` — exits 0=OK / 1=STALL):
1. **File-mtime check**: newest non-noise file under `{{STATE_ROOT}}/worktrees//` was modified within `STALL_FILE_MIN` minutes (default 12). A worker actively writing code touches a file at least every few minutes.
2. **Commit-age check**: at least one new commit on the branch within `STALL_COMMIT_MIN` minutes (default 25). Only counts as a stall signal when files are ALSO stale — a worker may be deep in a long edit without committing.
3. **Suspicious-idle-child sniff**: scans for child processes whose argv contains `claude -p` / `codex exec --model` / `--effort xhigh` AND has been alive > `STALL_BG_MIN` minutes (default 30) AND is using  -o etime,pcpu,command` — if it's been idle 30+ min with no output, it's hung.
2. **`SendMessage` the worker** by agent ID (NOT by name — the name binding may be stale after session resume) telling it to: (a) `BashOutput`/`KillShell` the hung shell, (b) stop re-planning at xhigh (the Step 5/6 plan is already authoritative), (c) resume from the current branch tip per `phase2-progress.md` PENDING rows, (d) write `phase1-blocker.md` instead of silently hanging if genuinely blocked. The exact recovery prompt is recorded in the memory lesson.
3. **Do NOT redispatch a new worker** unless the SendMessage returns "no agent with that ID" (truly gone) — two workers on the same worktree will rewrite each other's commits.
4. **Re-run the watchdog 5 min later.** If still STALL on a different reason, escalate to the user.

**False-positive defense:** the watchdog is read-only — it never kills processes or touches the worktree. It only reports. The orchestrator is the decision-maker. Tune `STALL_FILE_MIN` / `STALL_COMMIT_MIN` / `STALL_BG_MIN` via env vars for tickets where long-running tests or codex review rounds legitimately take more time than the defaults.

If any of these are missing or not registered in `~/.claude/settings.json`, treat every soft gate below as advisory. Verify with:
```bash
jq '.hooks | keys' ~/.claude/settings.json
# should include: PreToolUse, Stop, SubagentStop
```

> **Evidence format** — the split-evidence (API + UI) contract, Playwright reporter setup, escape rationales, and how to debug a hook block live in [references/evidence-format.md](references/evidence-format.md).

---

## Autonomy contract — see [references/autonomy-contract.md](references/autonomy-contract.md)

The contract is intentionally factored into a separate file so it can be linked (not pasted) into sub-agent prompts. Read it once at the start of an iteration; the rules apply to every step below.

The orchestrator's TL;DR for the rules in that file:
- Don't stop until `/qshipcheck` returns PASSED. Compaction is automatic; persist state to `phase2-progress.md` / `phase3-evidence.md` / `trd-coverage.json`.
- Read referenced skills/files in full before executing. Skimming produces silent failures (e.g., missing `qmanualt` DEV_MODE patches).
- No step may be skipped or substituted. `/qshipcheck` flags violations and re-runs from the first skip.
- Local writes to `{{LOCAL_DEV_DB_NAME}}` are auto-approved; staging/prod still prompt.

## Local development — Python version

qship assumes **pyenv** is on PATH. The codebase requires Python 3.10+ (uses `dict | None` PEP 604 syntax, `match` statements, etc.). The system `python3` on macOS is 3.9.6 and will fail with `TypeError: unsupported operand type(s) for |` on import.

When workers or the orchestrator invoke `pytest`, `alembic`, `python -m black`, or any other Python tool manually, prepend pyenv shims to PATH or use `pyenv exec`:

```bash
export PATH="{{USER_HOME}}/.pyenv/shims:$PATH"
# or:
pyenv exec pytest tests/ -v
# or use the per-repo venv (always 3.11+):
{{CODEBASE_ROOT}}//venv/bin/python -m pytest tests/ -v
```

Failure {{JIRA_PROJECT_KEY}}-EX01: orchestrator ran `python -m alembic upgrade head` and hit `SyntaxError: invalid syntax` because `python` resolved to 3.9.6.

## Pipeline Overview

The pipeline runs in 5 phases:

| Phase | Steps | Owner | Purpose |
|-------|-------|-------|---------|
| **Phase 1: Build** | 1–7.4 | Opus sub-agent | Plan, implement, clean up |
| **Phase 1.5: TRD Mirror** | 7.45 | Opus sub-agent (audited by orchestrator) | Line-by-line TRD vs code gap analysis + fix all gaps |
| **Phase 2: Review** | 7.5–11.5 | Opus sub-agents (dispatched by orchestrator) | Simplify, review, bug hunt, fix, verify |
| **Phase 3: Accept** | 14 | Opus sub-agent runs `/qe2etest` (audited by orchestrator) | E2E testing with coverage audit loop |
| **Phase 4: Deliver** | 12–13, 15 | Opus sub-agent (dispatched by orchestrator) | Create PRs, final review, pipeline check |

**All phases use Opus sub-agents** for maximum quality. The orchestrator never executes work itself — it dispatches, monitors, audits, and redispatches.

### All Steps

> **Step numbers are stable identifiers, not a chronological order.** External skills (`qshipcheck`, `qshipphasecheck`, `qshipmaster`, `qshipp2`) reference them by name, so they can't be renumbered without coordinated cross-skill edits. The actual execution order is the **Phase** column: 1 → 1.5 → 2 → 3 → 4. Inside Phase 4, the order is 12 → 13 → 15 (Step 14 is Phase 3). Step 7's *internal* sub-steps (memory search, TDD loop, migration handling, completion check) use unnumbered headings inside `pipeline-steps.md` to avoid colliding with the top-level Steps 7.3/7.4 below.

| # | Phase | Step | What it does |
|---|-------|------|-------------|
| 1 | 1 | Jira Fetch | Retrieve ticket details from Jira via Atlassian MCP |
| 2 | 1 | Repo Detection | Determine which repos are affected (read from repos.json) |
| 3 | 1 | Pull Latest | Fetch and checkout latest `develop` in each affected repo |
| 4 | 1 | Create Branch | Create a feature branch from develop (`-`) |
| 4.1 | 1 | Baseline Verify | Run full test suite on clean branch to confirm green baseline |
| 5 | 1 | Write Plan | Generate a detailed implementation plan using the writing-plans skill |
| 6 | 1 | Plan Review | Validate plan against codebase patterns, analogous code, and CLAUDE.md |
| 7 | 1 | Implement (TDD) | Execute the plan with red-green-refactor TDD cycle; batch checkpoints for 5+ task plans |
| 7.3 | 1 | Directory Check | Verify new files are in correct directories; fix misplaced files |
| 7.4 | 1 | Clean Defensive Code | Remove unneeded try/except blocks and redundant null checks |
| **G1** | **Gate** | **Phase 1 Gate** | **Orchestrator audits Phase 1 output for stubs/TODOs before proceeding** |
| 7.45 | 1.5 | TRD Mirror Review + Fix | Opus sub-agent does line-by-line TRD vs code comparison, implements all gaps |
| 7.5 | 2 | Simplify | Run code simplifier agent on all changed code; **§7.5.3 verifies suggestions were APPLIED, not just listed** |
| 8 | 2 | Code Review | **§8.0 complexity tier first** (T1=0 / T2=1 / T3=2 / T4=3 reviewers). Up to four parallel reviewers + qmigrationdevcheck (§8.5.1, alembic) + qauthtrailingslash (§8.6.5, routes) → unified `phase2-findings.md`. T1–T3 mark unused reviewer rows `SKIPPED [tier T]`. |
| 9 | 2 | Bug Hunt | **Fan-out scales with §8.0 tier** — T1=0 / T2=2 / T3=3 / T4=5 bug hunters against the diff |
| 10 | 2 | Bug Validation | Validate qbug findings — filter false positives, confirm real bugs |
| 11 | 2 | Fix Issues | Read `phase2-findings.md`; tick every MUST FIX or move to `Rejected with rationale`. **Universal no-drop rule: NO finding from ANY source may be silently skipped — applies equally to qcheckt, simplifier, Agent 1/2, qauthtrailingslash, qmigrationdevcheck, cross-branch, etc.** |
| 11.5 | 2 | Verification Gate | Fresh test run + formatting check + `phase2-findings.md` closure audit — **hard gate** before Phase 3 |
| 11.6 | 2 | Quick E2E (`/qe2etest`) | Per-worker smoke against the change — fast, cheap, before the full Phase 3 `/qe2etest` run (which uses the complete scenario matrix and delegates UI to `/qmanualt`) |
| 11.7 | 2 | Memory Capture (`/qmemory`) | Persist any reusable lesson from this ticket before Phase 3 |
| **G2** | **Gate** | **Phase 2 Gate** | **Run `/qshipphasecheck phase2` — BLOCKS Phase 3 if ANY step missing** |
| 14 | 3 | E2E Testing | Opus sub-agent runs full E2E, orchestrator audits coverage, redispatches for gaps |
| **G3** | **Gate** | **Phase 3 Gate** | **Run `/qshipphasecheck phase3` — BLOCKS Phase 4 if E2E not done** |
| 12.0 | 4 | Final Test Pass | Full `pytest tests/ -v` per affected repo with fix loop. Drops `phase4-tests-passed..flag`. **Enforced by `PreToolUse` hook on `gh pr create`** — no flag → no PR. |
| 12 | 4 | Create PR | Commit, push, and open pull requests targeting `develop` |
| 12.5 | 4 | Watch CI | `gh pr checks --wat

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [3awny](https://github.com/3awny)
- **Source:** [3awny/qship](https://github.com/3awny/qship)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-3awny-qship-qship
- Seller: https://agentstack.voostack.com/s/3awny
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
