adScaile-Workflow ersetzt pipeline-crank und ralph-single-story
1. Kontext
Seit ADR-0037 (Ralph-Loop-Architektur, Mai 2026) hat sich der Workflow-Bestand für die autonome Abarbeitung von Jira-P2503-Tickets organisch vergrößert. Drei Skripte standen gleichzeitig im Repo:
scripts/ralph.sh— Bash-Original, Mass-Loop überready-for-agent-Stories, Plan→Contract→Implement→Review→Merge.scripts/workflows/pipeline-crank.mjs— Spalten-Driver (Jira-Status ist die Phase): „Zu erledigen" → „In Arbeit" → „Zu Review" → „Fertig", eine Crank-Umdrehung pro Run. Designed für inkrementelles Vorrücken über Stakeholder-Reviews zwischen den Spalten.scripts/workflows/ralph-single-story.mjs— In-Session-Variante für genau eine Story, mit Contract-Eval-Skeptiker-Schleife und parallelem solcom-review +/code-review --fixin der Review-Phase.
Parallel hat der User darauf gezeigt, dass der
mattpocock-.sandcastle/main.ts-Workflow
(drei Phasen pro Outer-Iteration: Plan → Execute+Review → Merge, mit echtem
Dependency-Graph-Planning statt Status-getriebenem Crank) als Vorbild dienen soll
— 1:1-Nachbau, nicht eine weitere Variante daneben. Die existierende
Design-Doc docs/agents/adscaile.html (vormals
pipeline-sandcastle.html) hatte den Adaptions-Pfad bereits
ausgeschrieben.
Drei Workflows nebeneinander sind aus zwei Gründen schädlich: (a) die
kognitive Last steigt — jeder Lauf braucht eine Entscheidung „welcher
Workflow passt jetzt?", obwohl die drei sich in der Sache überlappen;
(b) die Prompts scripts/prompts/*.md sind Source-of-truth für
alle drei, was bei jeder Prompt-Änderung Cross-Workflow-Tests erzwingt.
2. Entscheidung
adScaile wird der einzige Workflow-Eintrittspunkt für autonome
Story-Abarbeitung. pipeline-crank.mjs und
ralph-single-story.mjs werden gelöscht. scripts/ralph.sh
bleibt als historisches Bash-Original für Notfall-Recovery-Läufe stehen, ist
aber nicht mehr der default Pfad.
2.1 1:1-Choreographie-Mapping mit main.ts
Drei Phasen pro Outer-Iteration, bis zu 10 Iterationen:
- Phase 1 Plan — Story-Picker mit Dependency-Graph-Heuristik
(Datei-Overlap, Parent-Link, blocked-by). Output:
<plan>{stories:[...]}</plan>per Regex-Tag-Match (identisch zum Original). Exit wenn Liste leer. - Phase 2 Execute — Pro Story sequenziell: Setup
(Branch + DB-Snapshot + Jira-Transition) → Implementer (Sub-Task-Loop mit
TDD-Discipline) → Reviewer (gated auf
commits_count > 0wie das Original aufresult.commits.length). - Phase 3 Merge — Batch-Phase: alle Branches mit erfolgreichem
Review werden via Azure-DevOps-REST als PR geöffnet, CI-Status gepollt, dann
via
PATCH /pullrequests/<ID>gemerged.
2.2 Drei bewusste Deviations vom Original
| Aspekt | main.ts | adScaile | Grund |
|---|---|---|---|
MAX_PARALLEL |
4 |
1 |
DDEV ist Singleton — parallele Stories würden auf der Snapshot-DB kollidieren. ADR-0030 hatte den Worktree-Pfad eröffnet (separate DDEV-Sites pro Worktree); im tatsächlichen Betrieb hat sich gezeigt, dass der Setup-Overhead pro Worktree nicht durch den Parallelism-Gewinn aufgewogen wird, solange die Story-Pipeline überhaupt funktioniert. Wir nehmen die einfachere Sequenziell-Variante und lassen ADR-0030 als optionaler Pfad stehen (nicht widerrufen, nur nicht der Default). |
| Isolation | Docker-Sandbox pro Issue | Primary-Workspace, git checkout |
Folgt aus 1:1 mit MAX_PARALLEL=1 — sequentielle Stories
brauchen keine Sandbox-Isolation. Branch-Switch reicht.
|
| Issue-Tracker | GitHub-Issues + gh |
Jira P2503 + acli; Azure-DevOps-REST für Merge |
Reines Tooling-Swap, keine Choreographie-Änderung. gh issue list
→ acli jira workitem search; gh pr merge
→ POST/PATCH Azure-DevOps-REST (Memory
reference_azure_devops_pr_merge_api).
|
2.3 Model-Strategie (Audit aus Design-Doc Section 9)
Das Original nutzt einheitlich opus. adScaile differenziert:
- Plan: sonnet — Story-Pick + Dependency-Graph ist regelbasierte Heuristik, kein Trade-off-Judgement.
- Setup: haiku — pure Mechanics (
git,ddev,acli), kein Judgement. - Implementer: sonnet — SOLCOM-Default für Coding-Aufgaben.
- Reviewer: opus — unverhandelbar, weil
Standards/Canvas/Spec-Findings-Detection Judgement und Cross-Reference braucht.
Memory
feedback_subagent_trust_but_verifywarnt explizit vor billigen Reviewern. - Merger: sonnet — strukturiertes Tool-Use (PR-Open + CI-Polling + REST-PATCH), kein Judgement.
- Block-Discipline: haiku —
acli edit+ draft.
Single Opus-Call-Rolle (Reviewer) statt mehreren — der Reviewer-Opus läuft 1× pro Story, alle anderen Calls auf Sonnet oder Haiku.
2.4 Wiederverwendung der existierenden Prompts
Die existierenden scripts/prompts/{plan,implement,review,merge}-prompt.md
bleiben unverändert und werden vom adScaile-Sub-Agenten per Read
geladen. adScaile schiebt nur Wrapper-Strings als Header vor den Sub-Agent-Call,
die die mattpocock-spezifischen Args (<plan>-Tag-Output-Kontrakt,
BRANCH, JIRA_KEY, BRANCHES-Liste) liefern.
Das hält die Prompts als Source-of-truth zentral und vermeidet Drift.
3. Rejected alternatives
3.1 Drei Workflows nebeneinander erhalten
Hätte den Vorteil, dass die Spalten-Driver-Mechanik aus pipeline-crank
(frühe PR-Open für Stakeholder-Sichtbarkeit, dann später Merge nach Approval)
weiterhin verfügbar wäre. Verworfen, weil (a) die kognitive Auswahl-Last bei
jedem Lauf den Workflow blockiert, (b) Cross-Workflow-Test bei jeder Prompt-Änderung
einen 3× Aufwand erzeugt, (c) der Spalten-Crank-Bedarf in der Praxis durch die
Block-Discipline (labels-remove ready-for-agent + Draft) und durch
Single-Story-Modus (args:'P2503-XXX') bereits abgedeckt ist.
3.2 Worktree-basierte parallele adScaile-Variante
Hätte die mattpocock-MAX_PARALLEL=4 näher am Original abgebildet
und den AFK-Throughput vervierfacht. Verworfen, weil der Setup-Overhead pro
Worktree (eigenes DDEV, eigene Datenbank, eigenes Snapshot-Restore) den
Parallelism-Gewinn in der bisherigen Beobachtung nicht aufwiegt. ADR-0030
bleibt als Option stehen, falls die Sequenziell-Variante in den vollen
AFK-Läufen am Durchsatz scheitert — dann ist die parallele Variante eine
kontrollierte Eskalation, kein Initial-Default.
3.3 Neue scripts/prompts/sandcastle/-Prompt-Files
Die Design-Doc hatte ursprünglich 4 separate Sandcastle-Prompts vorgesehen
(plan-sandcastle-prompt.md etc.), parallel zur mattpocock-Struktur.
Verworfen zugunsten von Wiederverwendung der existierenden Prompts plus
Wrapper-Header-Strings im .mjs-File. Vorteil: weniger Prompt-Drift,
weil Plan/Implement/Review/Merge an einer Stelle gepflegt werden.
3.4 opus für alle Rollen wie im Original
Hätte 1:1-Treue auf der Model-Achse erhalten. Verworfen wegen der Token-Kosten — vor allem Plan-Phase läuft 1× pro Iter (bis zu 10× pro AFK-Lauf), und die Dependency-Graph-Heuristik ist regelbasiert genug, dass Sonnet sie verlässlich liefert. Quality-Risk ist gering, weil ein Sonnet-Planner mit schlechtem Output sofort in Phase 2 als Story-Konflikt oder Implementer-Block auffällt.
4. Consequences
Positiv
- Ein einziger Workflow-Eintrittspunkt für autonome P2503-Abarbeitung.
Eingang in jeden Run:
Workflow({scriptPath:'scripts/workflows/adscaile.mjs'}). - Single-Story-Modus, Trockenlauf-Modus, AFK-Lauf-Modus über
argsgewählt — keine Cross-Workflow-Auswahl-Entscheidung. - Token-Profil deutlich günstiger als 1:1-Original — nur Reviewer auf
opus, Plan und Setup runter aufsonnetbzw.haiku. - Prompts
scripts/prompts/*.mdbleiben Source-of-truth für alle vier Rollen, gepflegt an einer Stelle.
Negativ / Risiko
- Throughput-Cap:
MAX_PARALLEL=1begrenzt den AFK-Lauf auf eine Story-Pipeline gleichzeitig. Bei 6 Stories pro Iteration und ~30min pro Story landet ein voller 10-Iter-Lauf bei 30 Stunden seriell. Falls das real zum Engpass wird → Eskalations-Pfad ist ADR-0030 (Worktree-basiert parallel). - Verlust der Spalten-Driver-Semantik:
pipeline-crank's früher PR-Open-für-Stakeholder-Review-Pattern fällt weg. Falls der Use-Case zurückkommt, ist die saubere Reintroduktion ein separaterargs.openPrAfterImpl=true-Toggle im Implementer. - Sonnet-Planner-Quality-Drift: falls Sonnet schlechtere
Dependency-Graphen liefert als Opus, fällt das in Phase 2 als
Story-Reihenfolge-Problem auf. Rollback ist 1-Line-Change
(
model:'opus'in der Plan-agent-Call). Quality-Monitoring über die Story-Hub-Worklogs.
Folgeschritte
scripts/workflows/pipeline-crank.mjs+ralph-single-story.mjssind bereits gelöscht (untracked, kein History-Verlust).docs/agents/pipeline-sandcastle.htmlumbenannt zudocs/agents/adscaile.htmlmit Model-Strategie-Section + Code-Skelett-Sync.- Test-Pfad: Trockenlauf der Plan-Phase
(
args:{phasesOnly:['plan']}) als erste Validierung, dann Single-Story-Lauf gegen eine kontrollierte Test-Story, dann voller AFK-Lauf. - Skill-Inventar in
docs/agents/skills.htmlreviewn — falls dort Skills wiesolcom-implement-storyaufralph-single-story.mjsoderralph.shverweisen, auf adScaile umstellen.