Last active
February 7, 2026 19:59
-
-
Save Ladas/ca102327fc0af2d5d8a7b4b8d2d4f910 to your computer and use it in GitHub Desktop.
blog/claude-code-agent-ops/01/tdd-ci-loop-animated
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 460" font-family="system-ui, -apple-system, sans-serif"> | |
| <defs> | |
| <filter id="shadow" x="-2%" y="-2%" width="104%" height="108%"> | |
| <feDropShadow dx="1" dy="2" stdDeviation="3" flood-opacity="0.08"/> | |
| </filter> | |
| <marker id="arrow-blue" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"> | |
| <polygon points="0 0, 10 3.5, 0 7" fill="#4a9eff"/> | |
| </marker> | |
| <marker id="arrow-red" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"> | |
| <polygon points="0 0, 10 3.5, 0 7" fill="#ee5a24"/> | |
| </marker> | |
| <marker id="arrow-green" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"> | |
| <polygon points="0 0, 10 3.5, 0 7" fill="#00b894"/> | |
| </marker> | |
| <marker id="arrow-purple" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"> | |
| <polygon points="0 0, 10 3.5, 0 7" fill="#8854d0"/> | |
| </marker> | |
| </defs> | |
| <style> | |
| @keyframes flowDash { to { stroke-dashoffset: -16; } } | |
| .flow { stroke-dasharray: 8; animation: flowDash 0.8s linear infinite; } | |
| @keyframes pulse { 0%,100% { stroke-width: 1.5; } 50% { stroke-width: 3; } } | |
| .active { animation: pulse 2s ease-in-out infinite; } | |
| @keyframes travel { | |
| 0% { offset-distance: 0%; opacity: 1; } | |
| 100% { offset-distance: 100%; opacity: 1; } | |
| } | |
| </style> | |
| <!-- Title --> | |
| <text x="400" y="28" text-anchor="middle" fill="#1a1a2e" font-size="20" font-weight="bold">tdd:ci — Agent-Managed CI Loop</text> | |
| <text x="400" y="48" text-anchor="middle" fill="#666" font-size="12">Automated feedback loop with escalation</text> | |
| <!-- Node: Write Code --> | |
| <rect x="40" y="80" width="150" height="60" rx="10" fill="#f0f7ff" stroke="#4a9eff" stroke-width="1.5" filter="url(#shadow)" class="active"/> | |
| <text x="115" y="107" text-anchor="middle" fill="#4a9eff" font-size="14" font-weight="bold">Write Code</text> | |
| <text x="115" y="127" text-anchor="middle" fill="#888" font-size="11">Claude Code</text> | |
| <!-- Node: Local Checks --> | |
| <rect x="250" y="80" width="150" height="60" rx="10" fill="#f0f7ff" stroke="#4a9eff" stroke-width="1.5" filter="url(#shadow)"/> | |
| <text x="325" y="107" text-anchor="middle" fill="#4a9eff" font-size="14" font-weight="bold">Local Checks</text> | |
| <text x="325" y="127" text-anchor="middle" fill="#888" font-size="11">pre-commit, ruff</text> | |
| <!-- Node: Push --> | |
| <rect x="460" y="80" width="150" height="60" rx="10" fill="#f0f7ff" stroke="#4a9eff" stroke-width="1.5" filter="url(#shadow)"/> | |
| <text x="535" y="107" text-anchor="middle" fill="#4a9eff" font-size="14" font-weight="bold">Push to PR</text> | |
| <text x="535" y="127" text-anchor="middle" fill="#888" font-size="11">git push</text> | |
| <!-- Node: CI Runs --> | |
| <rect x="600" y="190" width="170" height="70" rx="10" fill="#fffbf0" stroke="#e8a817" stroke-width="1.5" filter="url(#shadow)"/> | |
| <text x="685" y="218" text-anchor="middle" fill="#c48a00" font-size="14" font-weight="bold">CI Runs</text> | |
| <text x="685" y="238" text-anchor="middle" fill="#888" font-size="11">12+ checks</text> | |
| <text x="685" y="253" text-anchor="middle" fill="#aaa" font-size="10">gh pr checks --watch</text> | |
| <!-- Node: MERGE --> | |
| <rect x="625" y="315" width="120" height="45" rx="22" fill="#00b894" filter="url(#shadow)"/> | |
| <text x="685" y="344" text-anchor="middle" fill="#fff" font-size="16" font-weight="bold">MERGE</text> | |
| <!-- Node: RCA Analyze --> | |
| <rect x="290" y="295" width="190" height="70" rx="10" fill="#fef5f5" stroke="#ee5a24" stroke-width="1.5" filter="url(#shadow)"/> | |
| <text x="385" y="322" text-anchor="middle" fill="#ee5a24" font-size="14" font-weight="bold">rca:ci Analyze</text> | |
| <text x="385" y="342" text-anchor="middle" fill="#888" font-size="11">5-phase investigation</text> | |
| <text x="385" y="357" text-anchor="middle" fill="#888" font-size="11">→ propose fix</text> | |
| <!-- Node: Human Review --> | |
| <rect x="50" y="295" width="170" height="60" rx="10" fill="#faf5ff" stroke="#8854d0" stroke-width="1.5" filter="url(#shadow)"/> | |
| <text x="135" y="322" text-anchor="middle" fill="#8854d0" font-size="14" font-weight="bold">Human Review</text> | |
| <text x="135" y="342" text-anchor="middle" fill="#888" font-size="11">approve fix, iterate</text> | |
| <!-- Arrows: Happy path --> | |
| <line x1="190" y1="110" x2="248" y2="110" stroke="#4a9eff" stroke-width="2" class="flow" marker-end="url(#arrow-blue)"/> | |
| <line x1="400" y1="110" x2="458" y2="110" stroke="#4a9eff" stroke-width="2" class="flow" marker-end="url(#arrow-blue)"/> | |
| <path d="M 610 110 Q 685 110 685 188" fill="none" stroke="#4a9eff" stroke-width="2" class="flow" marker-end="url(#arrow-blue)"/> | |
| <!-- Arrow: Pass --> | |
| <line x1="685" y1="260" x2="685" y2="313" stroke="#00b894" stroke-width="2" marker-end="url(#arrow-green)"/> | |
| <text x="700" y="288" fill="#00b894" font-size="12" font-weight="bold">Pass</text> | |
| <!-- Arrow: Fail --> | |
| <path d="M 598 225 L 482 320" fill="none" stroke="#ee5a24" stroke-width="2" class="flow" marker-end="url(#arrow-red)"/> | |
| <text x="535" y="270" fill="#ee5a24" font-size="12" font-weight="bold">Fail</text> | |
| <!-- Arrow: RCA → Human --> | |
| <line x1="288" y1="330" x2="222" y2="330" stroke="#8854d0" stroke-width="2" class="flow" marker-end="url(#arrow-purple)"/> | |
| <!-- Arrow: Human → back to Code --> | |
| <path d="M 135 293 Q 135 200 115 142" fill="none" stroke="#8854d0" stroke-width="2" class="flow" marker-end="url(#arrow-purple)"/> | |
| <text x="95" y="218" fill="#8854d0" font-size="11" font-weight="bold" transform="rotate(-90 95 218)">iterate</text> | |
| <!-- Traveling dot on happy path --> | |
| <circle r="5" fill="#4a9eff" opacity="0.8"> | |
| <animateMotion dur="5s" repeatCount="indefinite" path="M 115,110 L 325,110 L 535,110 Q 685,110 685,225 L 685,340"/> | |
| <animate attributeName="r" values="4;6;4" dur="1.2s" repeatCount="indefinite"/> | |
| </circle> | |
| <!-- Traveling dot on failure path --> | |
| <circle r="4" fill="#ee5a24" opacity="0.6"> | |
| <animateMotion dur="5s" repeatCount="indefinite" begin="2.5s" path="M 600,225 L 385,330 L 135,325 Q 135,200 115,140 L 325,110 L 535,110 Q 685,110 685,225"/> | |
| </circle> | |
| <!-- Escalation note --> | |
| <rect x="50" y="400" width="700" height="48" rx="10" fill="#faf5ff" stroke="#8854d0" stroke-width="1" filter="url(#shadow)"/> | |
| <text x="400" y="422" text-anchor="middle" fill="#8854d0" font-size="13" font-weight="bold">After 3 failures → escalate to tdd:hypershift (live cluster debugging)</text> | |
| <text x="400" y="440" text-anchor="middle" fill="#888" font-size="11">Or use tdd:kind for quick local iteration</text> | |
| </svg> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment