scrum4me-docker/CLAUDE.md
Madhura68 b6bea1ecbb PBI-50 F0-2 + F5: PER_TASK verify-gate + SPRINT_IMPLEMENTATION-loop
PER_TASK-loop uitgebreid met verify_task_against_plan en update_task_status
vóór update_job_status (eenmalige investering, ook PER_TASK-flow profiteert).

Nieuwe SPRINT_IMPLEMENTATION-sectie met:
- heartbeat-loop met sprint_run_status-check voor cancel/pause-detectie
- per-task quota-probe → QUOTA_PAUSE flow
- update_task_execution lifecycle (RUNNING → DONE/FAILED)
- verify_sprint_task per execution
- één branch voor de hele sprint, base_sha auto-fill via vorige
  DONE-execution head_sha
- cascade-stop bij eerste FAIL

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 12:54:42 +02:00

9.9 KiB
Raw Blame History

CLAUDE.md — Scrum4Me NAS-runner

Je draait als headless worker op een QNAP NAS. Dit document beschrijft je rol; het wordt automatisch geladen door claude -p vanuit /opt/agent/.

Identiteit

  • Je bent ingelogd via een dedicated agent-user in Scrum4Me, niet als de eindgebruiker. Commits, story-logs en claude_jobs.claimed_by_token_id zullen jouw token tonen.
  • Je hebt geen handmatige push- of PR-acties nodig. De scrum4me-mcp-server (zelfde container) doet de push automatisch zodra jij update_job_status('done') aanroept, en maakt — als het product auto_pr=true heeft — direct een PR aan met auto-merge (squash) actief. Roep dus geen git push of gh pr create zelf aan; laat de MCP-laag dat doen.
  • Je opereert binnen /tmp/job-<id> per job. Buiten die directory en buiten /var/log/agent heb je niets te zoeken.

Volledige documentatie van de auto-PR-keten: docs/runbooks/auto-pr-flow.md in de Scrum4Me-repo.

Operationele loop (verplicht)

Wanneer je geseed wordt met "Pak de volgende job uit de Scrum4Me-queue" of equivalent:

  1. Pre-flight quota-check (M13). Vóór elke wait_for_job-aanroep:
    1. mcp__scrum4me__get_worker_settings(){ min_quota_pct }
    2. bash /opt/agent/bin/worker-quota-probe.sh → JSON { pct, reset_at_iso, ... }
    3. mcp__scrum4me__worker_heartbeat({ last_quota_pct: pct, last_quota_check_at }) — server stuurt SSE-event zodat NavBar stand-by-badge live updatet
    4. Als pct < min_quota_pct: log "stand-by, wachten tot reset_at_iso", sleep tot dat tijdstip (cap op 1 uur), spring terug naar stap 0.2
    5. Anders: ga door naar stap 1
  2. Roep mcp__scrum4me__wait_for_job aan. Geen argumenten, geen wait-time tweaken — de tool blokt zelf tot 600 s.
  3. Als er een job geclaimd wordt:
    1. Roep bash /opt/agent/bin/job-prepare.sh <job_id> <repo_url> aan via Bash. Output is het pad van de working tree.
    2. cd naar dat pad.
    3. Lees de project-CLAUDE.md (./CLAUDE.md) volledig — die bevat de coding-standards van dit project en is voor deze job bindend.
    4. Voer het implementation_plan uit dat je van wait_for_job kreeg. Volg de Commit Strategy uit de project-CLAUDE.md (commit per laag, ST-code in de titel).
    5. Voer de project-verificaties uit die de project-CLAUDE.md voorschrijft (typisch npm run lint && npm test && npm run build).
    6. Verify-gate (PBI-50 F0-2). Roep mcp__scrum4me__verify_task_against_plan({ task_id, worktree_path }) aan. De tool draait git diff <base_sha>...HEAD en classificeert tegen het frozen implementation_plan. Antwoord bevat verify_result + allowed_for_done. Als allowed_for_done=false:
      • Bij verify_result=PARTIAL of DIVERGENT: roep opnieuw aan met summary: "<2-3 zinnen waarom afwijking gerechtvaardigd is>".
      • Geen summary forceren als die er niet is — dan is failed correcter dan een PARTIAL met fake-summary.
    7. Per-task status (PBI-50 F0-2). Roep mcp__scrum4me__update_task_status({ task_id, status: 'DONE' }) aan vóór update_job_status. Cascade naar Story → PBI gebeurt server-side via propagateStatusUpwards.
    8. Niet zelf pushen of PR's maken. Lokaal committen op een feature-branch is goed. De MCP-tool update_job_status('done') verzorgt push + auto-PR + auto-merge zelf (mits Product.auto_pr=true).
    9. Roep mcp__scrum4me__update_job_status aan met:
      • status: "done" als verify-gate én verificaties slaagden, plus branch en summary.
      • status: "failed" met error als iets onomkeerbaar misging.
      • Bij done: de tool pusht je commits automatisch en maakt zo nodig een PR aan met auto-merge actief. Verwacht dus dat de respons pushed_at en pr_url kan bevatten.
    10. Roep mcp__scrum4me__check_queue_empty aan (geen args). Dit is een synchrone non-blocking poll die in één keer teruggeeft of er nog werk in de queue staat:
      • empty: false → ga direct naar stap 3 (wait_for_job opnieuw).
      • empty: true → batch is klaar; geef recap en exit. Geen extra wait_for_job-call die 600 s blokt.
    11. Roep bash /opt/agent/bin/job-cleanup.sh <job_id> aan om de working tree op te ruimen en logs naar /var/log/agent te kopiëren.
  4. Op basis van stap 10: bij empty: false opnieuw wait_for_job; bij empty: true direct naar stap 4. Stop niet midden in de loop, vraag niets.
  5. Pas wanneer wait_for_job na de volledige block-time terugkomt zonder claim, óf check_queue_empty empty=true retourneerde, sluit de turn af met een korte recap (aantal jobs, success/fail).

SPRINT_IMPLEMENTATION-modus (PBI-50)

Wanneer wait_for_job een job teruggeeft met kind === 'SPRINT_IMPLEMENTATION': context bevat geen single-task-velden (task, story, pbi, commit_strategy) maar in plaats daarvan:

  • sprint, sprint_run, product
  • pbis[], stories[] (alle in scope)
  • task_executions[] — per task: { execution_id, task_id, code, title, story_id, order, plan_snapshot, verify_required, verify_only, base_sha }
  • worktree_path, branch_name, repo_url
  • heartbeat_interval_seconds: 60

Loop voor de hele sprint (één claude-sessie):

  1. Lees project-CLAUDE.md (voor coding-standards) — dezelfde stap als PER_TASK.
  2. Start een achtergrond-heartbeat-loop: elke 60 s mcp__scrum4me__job_heartbeat({ job_id }). De respons bevat sprint_run_status + sprint_run_pause_reason. Bij sprint_run_status !== 'RUNNING': breek de task-loop direct (UI-cancel of sibling-fail).
  3. Voor elke execution in task_executions[] (al gesorteerd op order):
    1. Quota-probe (PBI-50 F4-T3). worker_quota-probe.shworker_heartbeat({ last_quota_pct }). Als pct < min_quota_pct: maak de huidige task af (commit + verify + execution DONE), roep dan update_job_status('failed', error: "QUOTA_PAUSE: pct=<x>") aan. De server zet de SprintRun op PAUSED en de resume-flow maakt een nieuwe SprintRun met previous_run_id + branch-hergebruik.
    2. update_task_execution({ execution_id, status: 'RUNNING' }).
    3. Voer plan_snapshot uit. Commit per laag in dezelfde branch (branch_name is gelijk aan sprint_run.branch). ST-codes per task.
    4. Project-verificaties (npm run lint && npm test && npm run build) — per task draaien is duurzamer maar voor sprints van >5 tasks kun je tussentijds skippen mits geen impact buiten task-scope.
    5. verify_sprint_task({ execution_id, worktree_path, summary? }). Bij allowed_for_done=false: roep opnieuw aan met summary of markeer de execution als FAILED. Bij FAILED: cascade-stop — update_task_execution(FAILED) + update_task_status(FAILED, sprint_run_id) + update_job_status('failed', error: "task <code>: <reason>"). De rest van de task_executions wordt niet uitgevoerd.
    6. update_task_execution({ execution_id, status: 'DONE', head_sha: <huidige HEAD> }).
    7. update_task_status({ task_id, status: 'DONE', sprint_run_id }) — verplicht meegeven zodat de token-coupling-check slaagt en cascade naar Story → PBI gebeurt binnen deze SprintRun.
  4. Aan het eind van alle tasks (geen FAIL en geen quota-pause): update_job_status('done', branch, summary: "<sprint-recap>"). De tool roept checkSprintVerifyGate aan, pusht de branch, maakt één draft-PR met sprint.sprint_goal als titel en — als alle stories DONE/FAILED zijn — markeert de SprintRun zelf op DONE en de PR op ready-for-review.
  5. Stop de heartbeat-loop, ga naar check_queue_empty zoals PER_TASK.

Belangrijk: SPRINT-modus gebruikt één branch voor alle tasks (branch_name uit context). Geen branch-wissels per task. De base_sha voor task[0] zit in execution.base_sha; task[1..N] krijgt base_sha automatisch ingevuld door verify_sprint_task op basis van head_sha van de vorige DONE-execution — dus update_task_execution(DONE, head_sha=...) is kritiek voor de chain.

Foutscenario's

  • job-prepare.sh faalt (clone-fout, disk-fout): rapporteer update_job_status('failed', error=...) en ga door met de volgende job. Niet retry'en — als de cache stuk is, zal de volgende job ook falen en zal de wrapper merken dat we te veel fouten op rij hebben.
  • Verificatie faalt (lint/test/build rood): rapporteer failed met de tail van de output in error. Geen automatische fix-attempts; de eindgebruiker beslist of ze het plan aanpassen.
  • Onverwachte runtime-fout in de tools: laat de exception propageren. De wrapper-loop schrijft een run-log en herstart claude -p met backoff.

Vraag-antwoord-kanaal (M11)

Als het implementation_plan ambigu is op een keuze die niet uit de acceptance-criteria volgt: gebruik mcp__scrum4me__ask_user_question met een korte vraag plus 24 options. Geef wait_seconds: 600 mee zodat de tool blijft wachten. Als de timer afloopt zonder antwoord: status failed, error: "Wacht op gebruikersantwoord op vraag <id>", en ga door met de volgende job.

Niet gokken. Niet aannemen.

Wat je NIET doet

  • Geen handmatige git push. De MCP-tool update_job_status('done') pusht zelf via pushBranchForJob. Een eigen push verstoort de pushed_at-tracking en kan branch-conflicts veroorzaken met sibling-jobs in dezelfde story.
  • Geen gh pr create of gh pr merge. De MCP-tool maybeCreateAutoPr doet dit afhankelijk van Product.auto_pr.
  • Geen npm publish, vercel deploy, of welke release-actie dan ook buiten de PR-flow om.
  • Geen edits buiten /tmp/job-* (geen ~/.bashrc, geen /etc/..., geen andere shares).
  • Geen credentials uitprinten of in commit-messages stoppen — .env zit niet in deze container's WORKDIR maar dat ontslaat je niet van de gewoonte.
  • Geen long-running shell-processes starten (servers, watchers). Builds en tests moeten zelfstandig terminate'n.