Speksilähtöiset toimitussilmukat
Tehtaan korkein taso on automaattinen toimitussilmukka: agentti lukee speksin, toteuttaa, testaa ja katselmoi iteroiden kunnes laatuportit menevät läpi. Tämä on ohjelmistotehtaan ydin.
Automaattisilmukan rakenne
Spec-driven delivery loop
Speksilähtöinen toimitussilmukka on automaattinen prosessi, jossa: 1) Agentti lukee speksin (tavoite, tarkistukset, rajoitteet), 2) Toteuttaa muutoksen, 3) Ajaa tarkistukset (testit, lint, tyypit), 4) Jos tarkistukset menevät läpi → katselmointi, 5) Jos eivät → korjaus ja uusi kierros. Silmukkaa toistetaan kunnes hyväksytty tai iteraatioraja saavutettu.
┌─────────────┐
│ READ SPEC │ ← goal, checks, constraints
└──────┬──────┘
▼
┌─────────────┐
│ IMPLEMENT │ ← Build agent toteuttaa
└──────┬──────┘
▼
┌─────────────┐ ┌──────────────┐
│ RUN CHECKS │────▶│ ALL PASS? │
└─────────────┘ └──────┬───────┘
│ │
YES NO
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│ REVIEW │ │ FIX │──┐
└────┬─────┘ └──────────┘ │
│ │
▼ │
┌──────────┐ │
│ APPROVED?│ │
└────┬─────┘ ┌──────────┐│
YES│ NO────▶│MAX ITER? ││
│ └────┬─────┘│
▼ │ │
┌──────────┐ YES │ NO──┘
│ RELEASE │ ▼ │
└──────────┘ STOP │
│spec.json — Silmukan ohjaus
Speksi-tiedosto ohjaa koko silmukkaa:
{
"goal": "Add rate limiting to the coach API endpoint",
"implement_instructions": "Add rate limiting using the existing rateLimiter pattern in lib/coach/. Limit to 60 messages per hour per user. Return 429 status with retry-after header when limit exceeded.",
"checks": [
{
"name": "TypeScript",
"command": "npx tsc --noEmit",
"required": true
},
{
"name": "Tests",
"command": "npm test -- --run",
"required": true
},
{
"name": "Lint",
"command": "npm run lint",
"required": true
}
],
"review_instructions": "Verify rate limit is per-user, not global. Check that 429 response includes retry-after header. Ensure existing coach functionality is not broken.",
"max_iterations": 5,
"constraints": [
"Don't modify existing API contract",
"Use in-memory rate limiting (no Redis)",
"Add tests for rate limit behavior"
]
}Silmukan toteutus
import json
import subprocess
def run_spec_loop(spec_path: str, backend: str = "claude"):
"""Suorita speksilähtöinen toimitussilmukka."""
# 1. Lue speksi
with open(spec_path) as f:
spec = json.load(f)
goal = spec["goal"]
checks = spec["checks"]
max_iter = spec.get("max_iterations", 5)
print(f"🏭 Factory: {goal}")
print(f" Checks: {len(checks)}")
print(f" Max iterations: {max_iter}")
for iteration in range(1, max_iter + 1):
print(f"\n--- Iteration {iteration}/{max_iter} ---")
# 2. Implement
implement_prompt = f"""
Goal: {goal}
Instructions: {spec.get('implement_instructions', '')}
Constraints: {json.dumps(spec.get('constraints', []))}
"""
run_agent(backend, "fixer", implement_prompt)
# 3. Run checks
all_passed = True
for check in checks:
result = subprocess.run(
check["command"],
shell=True,
capture_output=True,
text=True,
)
passed = result.returncode == 0
status = "✅" if passed else "❌"
print(f" {status} {check['name']}")
if not passed and check.get("required", True):
all_passed = False
print(f" Error: {result.stderr[:200]}")
if all_passed:
# 4. Review
review_prompt = f"""
Review the changes made for: {goal}
{spec.get('review_instructions', '')}
Verdict: APPROVE or REQUEST_CHANGES
"""
verdict = run_agent(backend, "reviewer", review_prompt)
if "APPROVE" in verdict:
print(f"\n🎉 Factory complete in {iteration} iterations!")
return True
else:
print(" 📝 Changes requested, iterating...")
else:
print(" 🔧 Checks failed, fixing...")
print(f"\n⚠️ Max iterations ({max_iter}) reached")
return FalseSilmukan pysähtymisehdot
| Ehto | Kuvaus | Toimenpide |
|---|---|---|
| Kaikki portit läpi + APPROVE | Tehtävä valmis | Julkaise |
| Iteraatioraja | Max kierrokset ylitetty | Pysähdy ja raportoi |
| Kriittinen virhe | Rikkoontuminen jota ei voi korjata | Pysähdy ja ilmoita |
| Ihmisen interventio | Tarvitaan päätös | Odota ohjausta |
Pro-vinkki
Aseta max_iterations realistisesti: 3–5 on yleensä hyvä lähtökohta. Jos tehdas tarvitsee yli 5 iteraatiota, speksi on todennäköisesti liian epätarkka tai tehtävä liian laaja — pilko se pienempiin osiin.
Monivaiheinen tehdas
Todellisissa projekteissa tehdas voi koostua useista peräkkäisistä silmukoista:
Vaihe 1: Dokumentaatio
spec: "Update docs for the changed module"
checks: [markdown-lint]
Vaihe 2: Toteutus
spec: "Implement the feature per AC1-AC3"
checks: [tsc, vitest, eslint]
Vaihe 3: Integraatiotestit
spec: "Write E2E tests for the new feature"
checks: [playwright]
Vaihe 4: Katselmointi
spec: "Final 6-pass review"
checks: [all-pass, no-blockers]Tehtaan mittarit
Seuraa näitä mittareita tehtaan parantamiseksi:
| Mittari | Tavoite | Miksi tärkeä |
|---|---|---|
| Iteraatiot / tehtävä | < 3 keskimäärin | Speksien laatu |
| Porttien läpäisyaste | > 80% ensimmäisellä | Toteutuksen laatu |
| Sykliaika | Vähenee ajan myötä | Prosessin tehokkuus |
| Regressiot | 0 | Testikattavuus |
Mikä on toimitussilmukan tärkein pysähtymisehto?
Rakenna oma spec.json
Kirjoita spec.json omalle projektillesi: 1) Valitse todellinen tehtävä (bugikorjaus tai pieni feature), 2) Määrittele goal ja implement_instructions, 3) Listaa checks (vähintään 3), 4) Kirjoita review_instructions, 5) Aseta max_iterations ja constraints. Testaa ajamalla silmukka.
Yhteenveto
- Toimitussilmukka: Read Spec → Implement → Check → Review → Release
- spec.json ohjaa koko silmukkaa: tavoite, tarkistukset, rajoitteet
- Pysähtyminen: kaikki portit + review APPROVE tai max_iterations
- Mittaa iteraatioita, läpäisyastetta ja sykliaikaa
- Seuraavaksi: retro ja oppimiset — miten tehdas parantaa itseään