feat(scheduler): capability-aware tryClaimJob + registerWorker #31

Merged
janpeter merged 6 commits from feat/worker-capability-scheduler into main 2026-06-01 17:27:11 +02:00
Owner

Phase A.3 of 5 (final mcp-side change). Bumps scrum4me-shared submodule to PR #6 merge (96612d4) which adds the WorkerCapability enum + ClaudeWorker.capability field. Adds buildHigherTierIdleFragment helper (Prisma.Sql NOT EXISTS clause) and wires it into tryClaimJob: a worker only claims if no other alive idle worker exists with strictly higher capability for the same user+runtime. registerWorker now accepts the capability so scrum4me-docker can pass WORKER_CAPABILITY in Phase B.

Backwards-compatible: capability field is nullable, the NOT EXISTS uses NULL semantics so unpopulated workers behave as today.

DEPENDENCY for merge: Scrum4Me PR #62 (Phase A.2 — the Prisma migration) must be deployed to Neon prod before this PR can safely be released to workers in production. Until then, queries reference a column that does not exist.

Spec/plan: scrum4me-docker docs/superpowers/specs/2026-05-31-worker-capability-scheduling-design.md and docs/superpowers/plans/2026-05-31-worker-capability-scheduling.md (Phase A.3).

Phase A.3 of 5 (final mcp-side change). Bumps scrum4me-shared submodule to PR #6 merge (96612d4) which adds the WorkerCapability enum + ClaudeWorker.capability field. Adds buildHigherTierIdleFragment helper (Prisma.Sql NOT EXISTS clause) and wires it into tryClaimJob: a worker only claims if no other alive idle worker exists with strictly higher capability for the same user+runtime. registerWorker now accepts the capability so scrum4me-docker can pass WORKER_CAPABILITY in Phase B. Backwards-compatible: capability field is nullable, the NOT EXISTS uses NULL semantics so unpopulated workers behave as today. DEPENDENCY for merge: Scrum4Me PR #62 (Phase A.2 — the Prisma migration) must be deployed to Neon prod before this PR can safely be released to workers in production. Until then, queries reference a column that does not exist. Spec/plan: scrum4me-docker docs/superpowers/specs/2026-05-31-worker-capability-scheduling-design.md and docs/superpowers/plans/2026-05-31-worker-capability-scheduling.md (Phase A.3).
Commit e19cee6 added a path mapping for @prisma/client as a workaround
for type resolution in the sparse worktree node_modules. That workaround
was never necessary in the final code — worker.ts uses a local string-union
type for WorkerCapability instead of importing from @prisma/client.
Reverting per Phase A.3 spec which forbade tsconfig changes.

The worktree-local @prisma/client wrapper that makes types resolve cleanly
is created on developer machines by 'npm install --no-save @prisma/client'
in the worktree (or 'npm ci'), not by a committed config change.
Previously `opts.capability ?? undefined` collapsed null and undefined
to the same outcome, so callers passing null (to clear the field) had
no effect on the UPDATE branch — the existing DB value persisted. This
bites in the Phase B rollout window: a worker container restarting
without WORKER_CAPABILITY env-var receives null, but the DB silently
keeps its previous tier, so the claim filter routes against stale
data.

Distinguish null (clear) from undefined (omit) explicitly. Adds a
regression test for the null path.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/scrum4me-mcp!31
No description provided.