--- name: ship-loop description: > Run a chained buildβ†’shipβ†’verifyβ†’notify pipeline for multi-segment feature work. Use when implementing multiple features in sequence, each as a coding agent task that gets committed, deployed, and verified before moving to the next. Prevents dropped handoffs between segments. metadata: openclaw: emoji: "🚒" version: "5.0.0" requires: bins: ["git", "python3"] python: ["pyyaml>=6.0", "pydantic>=2.0"] trigger_phrases: - "ship loop" - "keep building" - "run the next segment" - "build these features" - "multi-feature pipeline" - "ship these segments" --- # Ship Loop v5.0 β€” TARS Convergence 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. ## Architecture: Three Loops + Event Queue + Verdict Router ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 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 β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## Security Notice > **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. ## When to Use - Building multiple features for a project in sequence - Any work that follows: code β†’ preflight β†’ commit β†’ deploy β†’ verify β†’ next - When you need checkpointing so progress survives session restarts - When you want self-healing: failures auto-repair before asking humans - When you want cost visibility and learning from past runs ## Prerequisites - Python 3.10+ with `pyyaml` and `pydantic` installed - A git repository with a remote - A deployment pipeline triggered by push (Vercel, Netlify, etc.) - A coding agent CLI configured via `agent_command` in SHIPLOOP.yml ## Installation ```bash pip install pyyaml pydantic ``` ## CLI Usage ```bash # 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 # 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 # 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) ``` ## Pipeline Definition (SHIPLOOP.yml) ```yaml 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: [] ``` ## SQLite State Backend (v5.0) State is now stored in `.shiploop/tars.db` (SQLite, WAL mode). SHIPLOOP.yml is config-only. ### Tables | 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 Types | 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. ## Verdict Router (v5.0) The orchestrator no longer uses `if/else` chains. Every outcome maps to a `Verdict`, and a `VerdictRouter` maps verdicts to `Action` values. ### Default Routing Table | 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). ## Meta-Reflection Loop (v5.0) Runs automatically after pipeline completion (when `reflection.auto_run: true`) or manually via `shiploop reflect`. ### What It Analyzes 1. **Repeat failures** β€” same error_signature across multiple segments/runs 2. **Repair-heavy segments** β€” segments that needed >1 repair loop (same error type) 3. **Efficiency trends** β€” cost/time per segment trending up or down 4. **Stale learnings** β€” learnings with score < 0.3 that haven't helped 5. **Decision gaps** β€” situations that triggered `MISSING_DECISION_BRANCH` ### Auto-creates learnings from patterns If an error signature appears 3+ times across runs, the reflect loop auto-generates a `AUTO-` learning flagging it for human review. ```bash 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! ═════════════════════════════════════════════════════ ``` ## Playbook Evolution (v5.0) When a repair fails with an error that doesn't match any existing learning, the system records a `decision_gap`: ```python 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. ## Convergence Detection (v5.0 Enhanced) **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. ## Learnings Scoring (v5.0) ``` 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. ```bash shiploop learnings list # shows all learnings with scores ``` ## State Machine ``` 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. ## Deploy Providers | 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 | ## Budget Tracking Token usage and estimated costs tracked per agent invocation in SQLite (falls back to `metrics.json`). ```bash 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 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ``` ## Critical Rules 1. **Never break the chain** β€” after a segment ships, immediately start the next 2. **Preflight is mandatory** β€” no exceptions, no "ship now fix later" 3. **Explicit staging only** β€” never `git add -A`, only changed files from `git diff` 4. **Prompts via file** β€” never shell arguments (prevents injection) 5. **SQLite is source of truth** β€” SHIPLOOP.yml config-only; runtime state in `tars.db` 6. **Agent command from config** β€” always read from `agent_command`, never hardcode 7. **Budget-aware** β€” track costs, enforce limits, fail gracefully ## Project Structure ``` skills/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 └── ... ``` ## Changelog ### v5.0.0 (2026-03-27) β€” TARS Convergence - **SQLite state backend**: `tars.db` replaces `metrics.json` + `learnings.yml` for runtime state - **Event queue**: all phase transitions emit events; unprocessed events enable crash recovery - **Verdict router**: configurable `Verdict β†’ Action` table replaces if/else chains in orchestrator - **Meta-reflection loop**: `shiploop reflect` analyzes run history, finds patterns, auto-generates learnings - **Playbook evolution**: `MISSING_DECISION_BRANCH` detection β†’ `decision_gaps` table - **Cross-segment convergence**: `touched_paths` tracked per segment for overlap warnings - **Learnings scoring**: score field (+0.1 on success, -0.2 on failure), sorted by score - **New CLI commands**: `reflect`, `events`, `history` - **New config sections**: `reflection`, `router` ### v4.0.0 - Python CLI replaces bash scripts - Pydantic v2 config validation - Budget tracking with per-segment and per-run limits - Error convergence detection (hash-based) - Deploy provider plugins (Vercel, Netlify, Custom)