feat(PBI-4/ST-006): mirror job-config naar webapp + runbook-fix CLI-flags (#171)

Spiegelt de scrum4me-mcp wijzigingen naar de Scrum4Me web-app zodat
enqueue-laag (lib/job-config-snapshot.ts) en claim-laag dezelfde
defaults gebruiken. Plus runbook-correctie van een eerder gedocumenteerde
maar niet-bestaande Claude CLI-flag.

- T-25: lib/job-config.ts — mapBudgetToEffort export + KIND_DEFAULTS
  .allowed_tools voor TASK/SPRINT/IDEA_GRILL/IDEA_MAKE_PLAN omgezet
  naar expliciete lijsten zonder wait_for_job/check_queue_empty/
  get_idea_context. Comment-block over CLI-flag-mapping en sync met
  scrum4me-mcp.
- T-26: docs/runbooks/worker-idempotency.md sectie "Config doorgeven aan
  Claude Code (PBI-67)" herschreven. --thinking-budget vervangen door
  --effort (mapping-tabel toegevoegd); --max-turns geschrapt (CLI heeft
  die flag niet — audit-only). Sectie "Wie doet wat in de runner-
  architectuur" toegevoegd.
- T-27: docs/runbooks/job-model-selection.md — notes over max_turns,
  thinking_budget en allowed_tools onder de matrix. Nieuwe sectie
  "Runner-architectuur" met verwijzing naar plan + worker-idempotency.
- T-28: __tests__/lib/job-config.test.ts (nieuw) — 22 tests:
  mapBudgetToEffort grenswaarden + KIND_DEFAULTS.allowed_tools structurele
  checks + cascade regression.

Plus: docs/plans/queue-loop-extraction.md (geschreven in plan-mode,
nu gepubliceerd in repo).

Verify: lint OK, typecheck OK, 587 tests in 78 files passed.
Build niet lokaal uitgevoerd (vereist DATABASE_URL voor "Collecting page
data" — diff raakt geen API-route).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-09 07:11:52 +02:00 committed by GitHub
parent 10c52e8b8f
commit 00c5045558
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 602 additions and 27 deletions

View file

@ -3,7 +3,7 @@ title: "Worker idempotency & job-status protocol"
status: active
audience: [ai-agent, contributor]
language: nl
last_updated: 2026-05-05
last_updated: 2026-05-09
when_to_read: "Vóór het implementeren of debuggen van Claude-CLI-worker logica die `update_job_status` aanroept."
---
@ -113,43 +113,71 @@ Drie protocol-overtredingen die we met deze runbook + de nieuwe
## Config doorgeven aan Claude Code (PBI-67)
`wait_for_job` levert sinds PBI-67 een `config`-object mee in de
response. Geef deze door aan `claude` als CLI-flags:
response. **De runner** (`scrum4me-docker/bin/run-one-job.ts`) leest deze
config en bouwt per geclaimde job de juiste Claude CLI-flags. Eén
Claude-invocation per job — niet één lange sessie die zelf claimt.
```bash
claude \
-p "$PROMPT" \
--model "$MODEL" \
--permission-mode "$PERMISSION_MODE" \
--thinking-budget "$THINKING_BUDGET" \
${MAX_TURNS:+--max-turns $MAX_TURNS} \
${ALLOWED_TOOLS:+--allowed-tools "$ALLOWED_TOOLS"}
${EFFORT:+--effort $EFFORT} \
--allowedTools "$ALLOWED_TOOLS" \
--mcp-config /opt/agent/mcp-config.json \
--add-dir /opt/agent \
--output-format text
```
Waar:
| Variabele | Bron in response | Voorbeeld |
|---|---|---|
| `PROMPT` | `getKindPromptText(kind)` met `$PAYLOAD_PATH` vervangen | (kind-prompt-md) |
| `MODEL` | `config.model` | `claude-sonnet-4-6` |
| `PERMISSION_MODE` | `config.permission_mode` | `bypassPermissions` |
| `THINKING_BUDGET` | `config.thinking_budget` (0 = uit) | `12000` |
| `MAX_TURNS` | `config.max_turns` (null = onbegrensd) | `15` of leeg |
| `ALLOWED_TOOLS` | `config.allowed_tools.join(',')` (null = alle) | `Read,Grep,WebSearch` |
| `EFFORT` | `mapBudgetToEffort(config.thinking_budget)` (null = vlag weg) | `medium` |
| `ALLOWED_TOOLS` | `config.allowed_tools.join(',')` | `Read,Edit,…,mcp__scrum4me__update_task_status,…` |
Verwachte CLI-aanroep per kind (kind-defaults zonder overrides):
### Claude CLI 2.1.x flag-correctie
| Kind | Model | thinking | permission_mode | max_turns |
De Claude CLI 2.1.x heeft géén numerieke `--thinking-budget` en géén
`--max-turns`. Mapping:
| `config.thinking_budget` | CLI-flag |
|---|---|
| 0 | (geen `--effort` flag) |
| 1-6000 | `--effort medium` |
| 6001-12000 | `--effort high` |
| 12001-24000 | `--effort xhigh` |
| >24000 | `--effort max` |
`config.max_turns` blijft **audit-only** — wordt gesnapshot in
`ClaudeJob.requested_*` voor cost-attribution maar niet doorgegeven aan
Claude. De resolver in `lib/job-config.ts` exporteert
`mapBudgetToEffort(budget)` voor deze mapping.
### Verwachte CLI-aanroep per kind (defaults zonder overrides)
| Kind | Model | thinking_budget | --effort | permission_mode |
|---|---|---|---|---|
| `IDEA_GRILL` | sonnet-4-6 | 12000 | plan | 15 |
| `IDEA_MAKE_PLAN` | opus-4-7 | 24000 | plan | 20 |
| `PLAN_CHAT` | sonnet-4-6 | 6000 | plan | 5 |
| `TASK_IMPLEMENTATION` | sonnet-4-6 | 6000 | bypassPermissions | 50 |
| `SPRINT_IMPLEMENTATION` | sonnet-4-6 | 6000 | bypassPermissions | (geen) |
| `IDEA_GRILL` | sonnet-4-6 | 12000 | high | plan |
| `IDEA_MAKE_PLAN` | opus-4-7 | 24000 | xhigh | plan |
| `PLAN_CHAT` | sonnet-4-6 | 6000 | medium | plan |
| `TASK_IMPLEMENTATION` | sonnet-4-6 | 6000 | medium | bypassPermissions |
| `SPRINT_IMPLEMENTATION` | sonnet-4-6 | 6000 | medium | bypassPermissions |
**Onbekende flag:** als de huidige Claude Code-versie een vlag niet
kent, log een waarschuwing en sla 'm over — geen hard error. De server
blijft jobs queuen.
### Wie doet wat in de runner-architectuur
| Component | Verantwoordelijkheid |
|---|---|
| `bin/run-agent.sh` | Daemon-loop, exponential backoff, UNHEALTHY-marker, log-rotation, TOKEN_EXPIRED-detectie via exit-code 3 of stdout-regex |
| `bin/run-one-job.ts` | **Claim** (tryClaimJob + LISTEN-fallback 270s), config-resolve (getFullJobContext), payload schrijven, **CLI-flags bouwen**, spawn `claude`, lease-renewal voor SPRINT (setInterval 60s), rollbackClaim bij Claude exit≠0 zonder update_job_status, cleanup |
| `claude` (per invocation) | Voert exclusief de geclaimde job uit. **Mag geen** `wait_for_job`, `check_queue_empty`, of `job_heartbeat` aanroepen — zit niet in `allowed_tools` |
Volledige resolver-uitleg + override-cascade staat in
[job-model-selection.md](./job-model-selection.md).
[job-model-selection.md](./job-model-selection.md). Refactor-plan:
[queue-loop-extraction.md](../plans/queue-loop-extraction.md).
---