scrum4me-mcp/CLAUDE.md
Janpeter Visser f87b20744b
feat: worker presence layer + batch-loop docs (#7)
* feat: add next_action field to update_job_status response

* docs: add Batch-loop section to README

* feat: presence layer — registerWorker, startHeartbeat, registerShutdownHandlers

* feat: bootstrap worker presence at server startup, remove inline presence from wait-for-job

* docs: document worker presence layer in CLAUDE.md

* docs: refine Batch-loop intro — add 'Hier is de flow:' per implementation plan
2026-05-01 16:39:26 +02:00

72 lines
2.9 KiB
Markdown

# CLAUDE.md — scrum4me-mcp
MCP server that exposes the Scrum4Me dev-flow as native tools for Claude Code.
## Agent worktree-flow
`wait_for_job` creates an isolated git worktree per job so agent changes never touch the user's main checkout.
### How it works
1. On successful claim, `wait_for_job` calls `createWorktreeForJob`:
- Worktree directory: `SCRUM4ME_AGENT_WORKTREE_DIR/<job-id>` (default: `~/.scrum4me-agent-worktrees/<job-id>`)
- Branch: `feat/job-<last-8-chars-of-job-id>` (timestamp-suffixed if branch already exists)
- Base: `origin/main`
2. Tool response includes `worktree_path` and `branch_name`.
3. **Work exclusively in `worktree_path`** — all file edits and commits go there.
4. On `update_job_status(done|failed)`, `removeWorktreeForJob` runs automatically:
- `keepBranch=true` if `done` and a `branch` was reported (agent pushed)
- `keepBranch=false` otherwise (branch deleted with worktree)
### Required configuration
Set env var per product:
```
SCRUM4ME_REPO_ROOT_<productId>=/absolute/path/to/local/clone
```
Or add to `~/.scrum4me-agent-config.json`:
```json
{
"repoRoots": {
"<productId>": "/absolute/path/to/local/clone"
}
}
```
If no repo root is found, `wait_for_job` rolls the claim back to QUEUED and returns an error.
## Manual worktree cleanup
Run `cleanup_my_worktrees` (no arguments) to scan `~/.scrum4me-agent-worktrees/` and remove worktrees for jobs that are in a terminal state (DONE, FAILED, CANCELLED). Worktrees for active jobs (QUEUED, CLAIMED, RUNNING) are left untouched. Returns `{ removed, kept, skipped }`.
## Worker presence
Server-startup registers a `ClaudeWorker` record + starts a 5 s heartbeat; SIGTERM/SIGINT cleans it up. The Scrum4Me NavBar counts active workers via `last_seen_at < now() - 15s`.
| File | Purpose |
|---|---|
| `src/presence/worker.ts` | `registerWorker` (upsert + pg_notify worker_connected) + `unregisterWorker` |
| `src/presence/heartbeat.ts` | `startHeartbeat` — 5 s interval, stops on record-not-found |
| `src/presence/shutdown.ts` | `registerShutdownHandlers` — SIGTERM/SIGINT → stop heartbeat + unregister |
| `src/index.ts` | Bootstrap: calls `getAuth``registerWorker``startHeartbeat``registerShutdownHandlers` |
## Key source files
| File | Purpose |
|---|---|
| `src/git/worktree.ts` | `createWorktreeForJob` + `removeWorktreeForJob` |
| `src/tools/wait-for-job.ts` | `resolveRepoRoot`, `rollbackClaim`, `attachWorktreeToJob` |
| `src/tools/update-job-status.ts` | `cleanupWorktreeForTerminalStatus` |
| `src/tools/cleanup-my-worktrees.ts` | `cleanup_my_worktrees` tool — scans + removes stale worktrees |
## Testing
```bash
npm test # vitest run
npm run typecheck # tsc --noEmit
```
All worktree helpers have unit tests under `__tests__/git/worktree.test.ts`, `__tests__/wait-for-job-worktree.test.ts`, and `__tests__/update-job-status-worktree.test.ts`.