Orchestrate multi-segment feature work as a self-healing pipeline. Three nested loops ensure maximum autonomy: Loop 1 runs the standard code→preflight→ship→verify chain, Loop 2 auto-repairs failures via the coding agent, Loop 3 spawns experiment branches when repairs stall. A SQLite state backend provides crash recovery and cross-run analytics. A verdict router replaces hardcoded branching with a configurable decision table. A reflection loop audits historical effectiveness and auto-generates learnings.
┌───────────────────────────────────────────────────────────┐
│ SHIP LOOP v5.0 │
│ │
│ LOOP 1: Ship Loop │
│ code → preflight → ship → verify → emit(segment_shipped)│
│ │ │
│ on fail (verdict → action via VerdictRouter) │
│ ▼ │
│ LOOP 2: Repair Loop │
│ capture context → agent fix → re-preflight (max N) │
│ ↳ emit events: repair_done | repair_failed │
│ ↳ convergence detected → CONVERGED verdict → META │
│ ↳ unknown error → record_decision_gap() │
│ │ │
│ exhausted │
│ ▼ │
│ LOOP 3: Meta Loop │
│ meta-analysis → N experiment branches → winner → merge │
│ ↳ emit: meta_done │
│ │
│ 🗄 SQLite (tars.db): runs, segments, events, learnings │
│ 📋 Event Queue: crash recovery via unprocessed events │
│ 🔀 Verdict Router: configurable verdict→action table │
│ 📚 Learnings Engine: scored lessons (score tracks use) │
│ 🪞 Reflect Loop: post-run analysis + recommendations │
│ 💰 Budget Tracker: token/cost tracking per run │
└───────────────────────────────────────────────────────────┘
> SHIPLOOP.yml is equivalent to running a script. The agent_command, all preflight commands (build, lint, test), and custom deploy scripts execute with your full user privileges. Ship Loop does not sandbox these commands. Never use on untrusted repos without reviewing the config. Treat SHIPLOOP.yml with the same caution as a Makefile or CI pipeline.
pyyaml and pydantic installedagent_command in SHIPLOOP.ymlpip install pyyaml pydantic
# Core pipeline
shiploop run # Start or resume the pipeline
shiploop run --dry-run # Preview what would happen
shiploop status # Show segment states (reads from DB)
shiploop reset <segment> # Reset a segment to pending
# Learnings
shiploop learnings list
shiploop learnings search "dark mode theme toggle"
# Budget
shiploop budget # Show cost summary
# v5.0 NEW
shiploop reflect # Run meta-reflection on recent run history
shiploop reflect --depth 20 # Analyze last 20 runs
shiploop events # View event history for latest run
shiploop events <run_id> # View event history for specific run
shiploop history # View past run history from DB
# Options
shiploop -c /path/to/SHIPLOOP.yml run
shiploop -v run # Verbose logging
shiploop --version # Show version (5.0.0)
project: "Project Name"
repo: /absolute/path/to/project
site: https://production-url.com
branch: pr # direct-to-main | per-segment | pr
mode: solo
agent_command: "claude --print --permission-mode bypassPermissions"
preflight:
build: "npm run build"
lint: "npm run lint"
test: "npm run test"
deploy:
provider: vercel # vercel | netlify | custom
routes: [/, /api/health]
marker: "data-version"
health_endpoint: /api/health
deploy_header: x-vercel-deployment-url
timeout: 300
repair:
max_attempts: 3
meta:
enabled: true
experiments: 3
budget:
max_usd_per_segment: 10.0
max_usd_per_run: 50.0
max_tokens_per_segment: 500000
halt_on_breach: true
# v5.0 NEW: Reflection config
reflection:
enabled: true # run reflect loop after pipeline
auto_run: true # automatically run, not just on CLI command
history_depth: 10 # how many past runs to analyze
# v5.0 NEW: Custom verdict routing
router:
agent_fail: retry # override default (fail) with retry
deploy_fail: fail # override default (retry) with fail
segments:
- name: "feature-name"
status: pending
prompt: |
Your coding agent prompt here.
depends_on: []
State is now stored in .shiploop/tars.db (SQLite, WAL mode). SHIPLOOP.yml is config-only.
| Table | Purpose |
|---|---|
| ------- | --------- |
runs | Pipeline execution records (id, project, started_at, status, cost) |
segments | Segment execution records per run (status, commit, touched_paths) |
run_events | Event queue for crash recovery and audit trail |
learnings | Failure/success lessons with effectiveness scores |
usage | Token and cost records per agent invocation |
decision_gaps | Situations the system didn't know how to handle |
| Event | When emitted |
|---|---|
| ------- | ------------- |
agent_started | Agent invocation begins |
preflight_passed | All preflight steps pass |
preflight_failed | Any preflight step fails |
repair_done | Repair loop succeeded |
repair_failed | Repair loop failed or exhausted |
meta_done | Meta loop winner merged |
segment_shipped | Segment fully complete |
segment_failed | Segment permanently failed |
deploy_failed | Deploy or verification failed |
file_overlap_warning | Segment may touch files changed by prior segment |
Crash recovery: On startup, unprocessed events are replayed to restore pipeline state.
The orchestrator no longer uses if/else chains. Every outcome maps to a Verdict, and a VerdictRouter maps verdicts to Action values.
| Verdict | Default Action |
|---|---|
| --------- | --------------- |
success | ship |
preflight_fail | repair |
agent_fail | fail |
deploy_fail | retry |
repair_success | ship |
repair_exhausted | meta |
meta_success | ship |
meta_exhausted | fail |
budget_exceeded | fail |
converged | meta ← skip remaining repairs, jump to meta |
no_changes | fail |
unknown | pause_and_alert |
Override via router: section in SHIPLOOP.yml (see above).
Runs automatically after pipeline completion (when reflection.auto_run: true) or manually via shiploop reflect.
MISSING_DECISION_BRANCHIf an error signature appears 3+ times across runs, the reflect loop auto-generates a AUTO- learning flagging it for human review.
shiploop reflect --depth 20
═════════════════════════════════════════════════════
🪞 Ship Loop Reflection Report
Generated: 2026-03-27T06:30:00Z
Runs analyzed: 10
═════════════════════════════════════════════════════
📊 Efficiency
Total cost: $12.4200
Segments run: 8
Avg/segment: $1.5525
🔁 Repeat Failures (2)
abc123def456… × 3
...
💡 Recommendations
⚠️ Error signature abc123de… repeated 3× across segments: auth, api, db.
📉 2 stale learning(s) (score < 0.3): L002, L004.
✅ No issues detected in recent history. Pipeline looks healthy!
═════════════════════════════════════════════════════
When a repair fails with an error that doesn't match any existing learning, the system records a decision_gap:
learnings.record_decision_gap(
segment="auth",
context="Repair exhausted with unmatched error: ...",
verdict="repair_exhausted_unknown_error",
run_id="...",
)
Decision gaps surface in shiploop reflect output and the decision_gaps DB table. Operators use them to add new learnings or router overrides.
Same-segment: if two consecutive repair attempts produce the same error hash → CONVERGED verdict → router jumps to META (skipping remaining repair attempts).
Cross-segment: before starting a segment, the orchestrator checks if any already-shipped segment touched the same files (via touched_paths in DB). If overlap detected, a file_overlap_warning event is emitted.
score (default 1.0)
+0.1 when injected and segment succeeds first-try
-0.2 when injected and segment fails the same way
Search results are sorted by combined keyword-relevance × score. Learnings with score < 0.3 are flagged as stale in reflection.
shiploop learnings list # shows all learnings with scores
States per segment:
pending → coding → preflight → shipping → verifying → shipped
↘ repairing (Loop 2) → preflight
↘ experimenting (Loop 3) → preflight → shipping
↘ failed
SHIPLOOP.yml checkpointed after every transition (for backward compat). SQLite is the primary state store.
| Provider | How it works |
|---|---|
| ---------- | ------------- |
vercel | Polls routes for HTTP 200, checks x-vercel-deployment-url header |
netlify | Polls routes for HTTP 200, checks x-nf-request-id header |
custom | Runs deploy.script with SHIPLOOP_COMMIT and SHIPLOOP_SITE env vars |
Token usage and estimated costs tracked per agent invocation in SQLite (falls back to metrics.json).
shiploop budget
💰 Budget Summary: Portfolio
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total cost: $3.84
Budget remaining: $46.16
Total records: 12
By segment:
dark-mode: $0.42
contact-form: $3.42
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
git add -A, only changed files from git difftars.dbagent_command, never hardcodeskills/ship-loop/
├── SKILL.md # This file
├── pyproject.toml
├── shiploop/
│ ├── __init__.py # __version__ = "5.0.0"
│ ├── cli.py # CLI (run, status, reset, reflect, events, history, ...)
│ ├── config.py # SHIPLOOP.yml parsing + validation (Pydantic v2)
│ ├── orchestrator.py # Main state machine + event queue + verdict routing
│ ├── db.py # NEW: SQLite state backend (tars.db)
│ ├── router.py # NEW: Verdict→Action router
│ ├── learnings.py # Learnings engine (SQLite + scoring + decision gaps)
│ ├── budget.py # Cost/token tracking (SQLite backend)
│ ├── git_ops.py # git operations + get_touched_paths()
│ ├── agent.py # Agent runner
│ ├── deploy.py # Deploy verification
│ ├── preflight.py # Build + lint + test runner
│ ├── reporting.py # Status messages + reports
│ ├── ship_utils.py # Ship and verify helper
│ └── loops/
│ ├── ship.py # Loop 1: code → preflight → ship
│ ├── repair.py # Loop 2: repair + decision gap detection
│ ├── meta.py # Loop 3: meta-analysis + experiments
│ ├── reflect.py # NEW: post-run reflection + recommendations
│ └── optimize.py # Optimization loop
├── providers/
│ ├── vercel.py
│ ├── netlify.py
│ └── custom.py
└── tests/
├── test_config.py
├── test_orchestrator.py
├── test_git_ops.py
├── test_budget.py
├── test_learnings.py
└── ...
tars.db replaces metrics.json + learnings.yml for runtime stateVerdict → Action table replaces if/else chains in orchestratorshiploop reflect analyzes run history, finds patterns, auto-generates learningsMISSING_DECISION_BRANCH detection → decision_gaps tabletouched_paths tracked per segment for overlap warningsreflect, events, historyreflection, router共 1 个版本