docs(T-575): worker-idempotency runbook + CLAUDE.md verwijzing
Beschrijft beslissingsboom verify_result × diff-staat × branch-staat → JobStatus, met SKIPPED gereserveerd voor al-gemergd werk en FAILED voor échte fouten. Plus StoryLog-verplichting (log_implementation, log_commit, log_test_result) en idempotency-protocol vóór schrijven. PBI-33 batch (5-5 22:22) gedocumenteerd als case-study: drie protocol-overtredingen die deze runbook + de nieuwe SKIPPED-status aanpakken. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ca1a89ca04
commit
084ca81090
3 changed files with 125 additions and 0 deletions
|
|
@ -115,3 +115,5 @@ PBI (niet: Feature/Epic) · Story (niet: Ticket) · Sprint Goal (niet: Objective
|
|||
```bash
|
||||
npm run lint && npm test && npm run build
|
||||
```
|
||||
|
||||
Worker job-status protocol (wanneer `DONE` / `SKIPPED` / `FAILED`): zie [docs/runbooks/worker-idempotency.md](./docs/runbooks/worker-idempotency.md).
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ Auto-generated on 2026-05-05 from front-matter and headings.
|
|||
| [Vercel Deployment](./runbooks/deploy-vercel.md) | `runbooks/deploy-vercel.md` | active | 2026-05-03 |
|
||||
| [MCP Integration — Scrum4Me Tools](./runbooks/mcp-integration.md) | `runbooks/mcp-integration.md` | active | 2026-05-03 |
|
||||
| [v1.0 Smoke Test Checklist](./runbooks/v1-smoke-test.md) | `runbooks/v1-smoke-test.md` | active | 2026-05-04 |
|
||||
| [Worker idempotency & job-status protocol](./runbooks/worker-idempotency.md) | `runbooks/worker-idempotency.md` | active | 2026-05-05 |
|
||||
| [StoryDialog Profiel](./story-dialog.md) | `story-dialog.md` | active | 2026-05-03 |
|
||||
| [TaskDialog Profiel](./task-dialog.md) | `task-dialog.md` | active | 2026-05-03 |
|
||||
| [Scrum4Me — API Test Plan](./test-plan.md) | `test-plan.md` | active | 2026-05-03 |
|
||||
|
|
|
|||
122
docs/runbooks/worker-idempotency.md
Normal file
122
docs/runbooks/worker-idempotency.md
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
---
|
||||
title: "Worker idempotency & job-status protocol"
|
||||
status: active
|
||||
audience: [ai-agent, contributor]
|
||||
language: nl
|
||||
last_updated: 2026-05-05
|
||||
when_to_read: "Vóór het implementeren of debuggen van Claude-CLI-worker logica die `update_job_status` aanroept."
|
||||
---
|
||||
|
||||
# Worker idempotency & job-status protocol
|
||||
|
||||
Beschrijft hoe de Scrum4Me-worker `ClaudeJob.status` moet zetten op basis
|
||||
van `VerifyResult` × git-diff-staat × branch-staat. Doel: voorkom
|
||||
status-divergentie zoals geconstateerd in de **PBI-33 batch (5-5-2026
|
||||
22:22)** waarin werk dat al gemerged was via PR #102/#103/#104 leidde
|
||||
tot inconsistente combinaties van `verify=EMPTY → FAILED` en
|
||||
`verify=DIVERGENT → DONE`.
|
||||
|
||||
---
|
||||
|
||||
## Beslissingsboom
|
||||
|
||||
Aan het einde van een story-job, ná `verify`-pass:
|
||||
|
||||
| `verify_result` | netto diff t.o.v. `origin/main` | branch al gemerged | → `ClaudeJob.status` | `Task.status` |
|
||||
|---|---|---|---|---|
|
||||
| `ALIGNED` of `PARTIAL` | nieuwe commit aanwezig | n.v.t. | **`DONE`** | `DONE` |
|
||||
| `EMPTY` | leeg (niets gewijzigd) | werk zit al op `origin/main` | **`SKIPPED`** | `DONE` |
|
||||
| `EMPTY` | leeg, maar werk staat **niet** op origin | n.v.t. | **`FAILED`** (`error: "verify produced no output"`) | `IN_PROGRESS` (handmatig onderzoeken) |
|
||||
| `DIVERGENT` | aanwezig, maar identiek aan al-gemergde branch | ja (PR closed/merged) | **`SKIPPED`** | `DONE` |
|
||||
| `DIVERGENT` | aanwezig, niet matchend met main | nee | **`FAILED`** (`error: "verify divergent — handmatige review"`) | `IN_PROGRESS` |
|
||||
| (compile-fail, test-fail, push-fail, exception) | n.v.t. | n.v.t. | **`FAILED`** met concrete `error` | `IN_PROGRESS` |
|
||||
| (gebruiker drukt cancel) | n.v.t. | n.v.t. | **`CANCELLED`** | `TO_DO` |
|
||||
|
||||
### Vuistregels
|
||||
|
||||
- **`SKIPPED`** = "geen netto-output, maar geen fout" — werk was al
|
||||
gedaan vóór deze job draaide. Task mag op `DONE` omdat het beoogde
|
||||
resultaat in main aanwezig is.
|
||||
- **`FAILED`** is gereserveerd voor échte fouten: code-fouten,
|
||||
test-failures, push-fouten, onverklaarde diff. Niet voor
|
||||
"implementatie was al gedaan".
|
||||
- **`DONE`** alleen bij `ALIGNED`/`PARTIAL` mét nieuwe commit op de
|
||||
feature-branch. Een lege `DIVERGENT` op een al-gemergde branch is
|
||||
géén `DONE`.
|
||||
|
||||
---
|
||||
|
||||
## StoryLog-verplichting
|
||||
|
||||
Tijdens elke job moet de worker `story_logs`-entries schrijven via de
|
||||
MCP-tools, anders is de Sync-tab leeg:
|
||||
|
||||
| Wanneer | MCP-tool | Inhoud |
|
||||
|---|---|---|
|
||||
| Bij claim | `log_implementation` | "Start implementatie van T-XXX. Branch X. Plan: …" |
|
||||
| Per commit | `log_commit` | hash + message + samenvatting van wijzigingen |
|
||||
| Na verify | `log_test_result` | status `PASSED` of `FAILED` + samenvatting van checks |
|
||||
|
||||
In **PBI-33 batch** zijn deze tools **niet** aangeroepen — `story_logs`
|
||||
voor ST-1208/1209/1210 is leeg. Worker MAG geen job afronden zonder
|
||||
minimaal één `log_implementation` (start) en één `log_test_result`
|
||||
(eind).
|
||||
|
||||
---
|
||||
|
||||
## Idempotency-protocol (vóór schrijven)
|
||||
|
||||
Bij claim van een job:
|
||||
|
||||
1. Lees `Task.implementation_plan` — beschrijft expliciet welke files
|
||||
gewijzigd moeten worden.
|
||||
2. Vergelijk de huidige `origin/main`-staat met die plan-instructies:
|
||||
- Bestaat het bestand al met de beoogde inhoud?
|
||||
- Bestaat de migratie al?
|
||||
- Bevat de relevante codepad de nieuwe symbolen/types?
|
||||
3. Bij **volledige hit**: roep `log_implementation` met inhoud "Werk
|
||||
reeds aanwezig op origin/main vanaf commit X (Y)." Sla
|
||||
verify-stap over en zet `JobStatus.SKIPPED`. Task naar `DONE`.
|
||||
4. Bij **gedeeltelijke hit**: log de bevindingen via
|
||||
`log_implementation` en doe alleen het resterende werk. Eindig met
|
||||
`DONE` (`ALIGNED` of `PARTIAL`) als je netto-output hebt.
|
||||
|
||||
Dit voorkomt dubbele commits op al-gemergde branches en houdt
|
||||
`pushed_at` semantisch correct (alleen gevuld als er werkelijk
|
||||
gepusht is).
|
||||
|
||||
---
|
||||
|
||||
## Case-study: PBI-33 (5-5-2026 22:22)
|
||||
|
||||
PBI-33 ("PLAN_CHAT — gebruikersvragen over plan") werd opnieuw aangemaakt
|
||||
nadat de feature al via een eerdere batch was gemerged onder cuid-style
|
||||
story-codes (`ST-bsjoqjnr`, `ST-p6d1odh0`, …). De worker draaide om
|
||||
22:22 en zag:
|
||||
|
||||
- **T-533** (`ST-1208` schema-werk): diff = leeg → `verify=EMPTY` →
|
||||
`Job.FAILED` met error "Implementatie reeds voltooid en gemerged".
|
||||
Volgens het nieuwe protocol had dit **`SKIPPED`** moeten zijn.
|
||||
- **T-534…538**: diff niet leeg op feature-branches `feat/story-7pl4dsb6`
|
||||
en `feat/story-0vtnydpi` (al-gemergde branches uit eerdere PR's) →
|
||||
`verify=DIVERGENT` → `Job.DONE` met `pushed_at=now()`. Volgens het
|
||||
nieuwe protocol had dit ook **`SKIPPED`** moeten zijn — branch was
|
||||
al closed/merged, geen nieuwe commit.
|
||||
- **`story_logs` voor ST-1208/1209/1210 is leeg** — geen
|
||||
`log_implementation`, geen `log_commit`, geen `log_test_result`.
|
||||
|
||||
Drie protocol-overtredingen die we met deze runbook + de nieuwe
|
||||
`SKIPPED`-status aanpakken.
|
||||
|
||||
---
|
||||
|
||||
## Referenties
|
||||
|
||||
- Enum: `prisma/schema.prisma` → `enum ClaudeJobStatus`
|
||||
- Mapping: `lib/job-status.ts` (DB↔API) en
|
||||
`components/shared/job-status.ts` (label + kleur)
|
||||
- Status-data-cleanup: `app/api/cron/cleanup-agent-artifacts/route.ts`
|
||||
- KPI-aggregatie: `lib/insights/agent-throughput.ts` (terminal_7d
|
||||
inclusief SKIPPED)
|
||||
- Gerelateerd plan: `docs/plans/auto-pr-deploy-sync.md` Deel D
|
||||
(Sync-tab toont per-Story job-status incl. SKIPPED)
|
||||
Loading…
Add table
Add a link
Reference in a new issue