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

@ -9,6 +9,13 @@
// 2. job.requested_* (snapshot bij enqueue, ingevuld door deze module)
// 3. product.preferred_*
// 4. KIND_DEFAULTS hieronder
//
// CLI-flag-mapping (Claude CLI 2.1.x):
// - thinking_budget (number) → mapBudgetToEffort() → --effort {low,medium,high,xhigh,max}
// (de CLI heeft geen --thinking-budget flag — alleen --effort)
// - max_turns blijft audit-only: de CLI heeft géén --max-turns flag.
// De waarde wordt gesnapshot voor cost-attribution maar niet doorgegeven.
// - allowed_tools → --allowedTools (komma-gescheiden lijst)
export type ClaudeModel =
| 'claude-opus-4-7'
@ -42,20 +49,52 @@ export type TaskInput = {
requires_opus?: boolean | null
}
// Tool-allowlists per kind. Bewust géén `wait_for_job`, `check_queue_empty`
// of `get_idea_context` — de runner (scrum4me-docker/bin/run-one-job.ts)
// claimt voor Claude. Vangrail tegen recursieve claims binnen één invocation.
const TASK_TOOLS = [
'Read', 'Edit', 'Write', 'Bash', 'Grep', 'Glob',
'mcp__scrum4me__get_claude_context',
'mcp__scrum4me__update_task_status',
'mcp__scrum4me__update_task_plan',
'mcp__scrum4me__log_implementation',
'mcp__scrum4me__log_test_result',
'mcp__scrum4me__log_commit',
'mcp__scrum4me__verify_task_against_plan',
'mcp__scrum4me__update_job_status',
'mcp__scrum4me__ask_user_question',
'mcp__scrum4me__get_question_answer',
'mcp__scrum4me__list_open_questions',
'mcp__scrum4me__cancel_question',
'mcp__scrum4me__worker_heartbeat',
]
const KIND_DEFAULTS: Record<string, JobConfig> = {
IDEA_GRILL: {
model: 'claude-sonnet-4-6',
thinking_budget: 12000,
permission_mode: 'plan',
max_turns: 15,
allowed_tools: ['Read', 'Grep', 'Glob', 'WebSearch', 'AskUserQuestion'],
allowed_tools: [
'Read', 'Grep', 'Glob', 'WebSearch', 'AskUserQuestion',
'mcp__scrum4me__update_idea_grill_md',
'mcp__scrum4me__log_idea_decision',
'mcp__scrum4me__update_job_status',
'mcp__scrum4me__ask_user_question',
'mcp__scrum4me__get_question_answer',
],
},
IDEA_MAKE_PLAN: {
model: 'claude-opus-4-7',
thinking_budget: 24000,
permission_mode: 'plan',
max_turns: 20,
allowed_tools: ['Read', 'Grep', 'Glob', 'WebSearch', 'AskUserQuestion', 'Write'],
allowed_tools: [
'Read', 'Grep', 'Glob', 'WebSearch', 'AskUserQuestion', 'Write',
'mcp__scrum4me__update_idea_plan_md',
'mcp__scrum4me__log_idea_decision',
'mcp__scrum4me__update_job_status',
],
},
PLAN_CHAT: {
model: 'claude-sonnet-4-6',
@ -69,14 +108,20 @@ const KIND_DEFAULTS: Record<string, JobConfig> = {
thinking_budget: 6000,
permission_mode: 'bypassPermissions',
max_turns: 50,
allowed_tools: null,
allowed_tools: TASK_TOOLS,
},
SPRINT_IMPLEMENTATION: {
model: 'claude-sonnet-4-6',
thinking_budget: 6000,
permission_mode: 'bypassPermissions',
max_turns: null,
allowed_tools: null,
// Geen `mcp__scrum4me__job_heartbeat` — de runner verlengt de lease
// automatisch via setInterval (zie scrum4me-docker/bin/run-one-job.ts).
allowed_tools: [
...TASK_TOOLS,
'mcp__scrum4me__update_task_execution',
'mcp__scrum4me__verify_sprint_task',
],
},
}
@ -123,6 +168,23 @@ export function resolveJobConfig(
}
}
// Map numeriek thinking_budget naar de Claude CLI 2.1.x --effort flag.
// Returns null als de flag niet meegegeven moet worden (budget = 0).
//
// Mapping (sync met scrum4me-mcp/src/lib/job-config.ts):
// 0 → null (geen --effort flag)
// 1..6000 → "medium"
// 6001..12000 → "high"
// 12001..24000→ "xhigh"
// >24000 → "max"
export function mapBudgetToEffort(budget: number): string | null {
if (budget <= 0) return null
if (budget <= 6000) return 'medium'
if (budget <= 12000) return 'high'
if (budget <= 24000) return 'xhigh'
return 'max'
}
// Snapshot-velden voor ClaudeJob.requested_*. Bij elke enqueue laden we
// product (voor preferred_*) en optioneel task (voor requires_opus), draaien
// de resolver, en schrijven het resultaat als auditspoor in de job-rij.