Commit graph

94 commits

Author SHA1 Message Date
e63ea7026b feat: verify_task_against_plan calls classifyDiffAgainstPlan + saves verify_result to DB
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 12:59:17 +02:00
24e933fc2f chore: sync VerifyResult enum + verify_only + verify_result from main Scrum4Me schema
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 12:59:08 +02:00
1e264ed521 feat: classifyDiffAgainstPlan — pure diff vs plan classifier (VerifyResult)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 12:55:47 +02:00
8ebf4ff895 feat: integrate push into update_job_status DONE transition
On status=done, calls pushBranchForJob before DB write:
- pushed=true → DONE + pushed_at + branch set + worktree cleanup (keepBranch=true)
- no-changes → DONE without pushed_at + worktree cleanup
- push failure → FAILED with error message + worktree preserved for manual inspection

Also adds pushed_at to vendored prisma schema + regenerates client.
6 unit tests for prepareDoneUpdate covering all push outcomes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 12:00:30 +02:00
fbfaf905c8 feat: add pushBranchForJob helper (src/git/push.ts)
Runs git push -u origin <branch> in the worktree. Detects no-changes
(HEAD = origin/main) before pushing. Classifies push failures into
no-credentials, conflict, or unknown via stderr pattern matching.
5 unit tests covering all paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 11:57:14 +02:00
48b67444cc docs: agent worktree-flow documentation + CLAUDE.md
README: updated wait_for_job/update_job_status tool descriptions,
added 'Agent worktree-flow' section with env vars, config-file fallback,
and smoke-test checklist. New CLAUDE.md with worktree-flow summary and
key source file index.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 11:53:45 +02:00
ce4afa1928 feat: cleanup worktree in update_job_status on terminal transitions
On DONE/FAILED, resolves repoRoot and calls removeWorktreeForJob (best-effort).
keepBranch=true when status=done and agent reported a branch (push assumed);
false otherwise. Cleanup failures are logged as warnings — DB status is preserved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 11:52:16 +02:00
6ee55e79b6 feat: integrate createWorktreeForJob into wait_for_job tool
After claiming a job, resolves repoRoot (env SCRUM4ME_REPO_ROOT_<productId>
or ~/.scrum4me-agent-config.json), creates a git worktree, and returns
worktree_path + branch_name in the response. Rolls back claim to QUEUED
on failure. Tool description updated to instruct agent to work in worktree.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 11:50:51 +02:00
b20e297851 feat: add removeWorktreeForJob helper
Removes worktree dir via `git worktree remove --force` and deletes
the local branch by default; keepBranch=true preserves the branch.
Returns { removed: false } when the worktree path doesn't exist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 11:46:31 +02:00
e7bb3c82ba feat: createWorktreeForJob helper — isolate agent per job in git worktree
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 11:34:19 +02:00
3efebe21f3 chore: update vendor/scrum4me submodule to merged main (794f7af)
Points to the merge commit of PR #23 on Scrum4Me/main so the submodule
tracks origin instead of the local-only pre-merge commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 19:46:46 +02:00
c2ca29d52b
Merge pull request #4 from madhura68/feat/plan-snapshot-verify-tool
feat: plan_snapshot capture in wait_for_job + verify_task_against_plan tool
2026-04-30 19:42:33 +02:00
d9f3a7ea40 test+docs: verify-plan tests and README for verify_task_against_plan
23 unit tests covering parseAcceptanceCriteria, extractKeywords,
checkACStatus, computeDriftScore, lineDiff, and 4 end-to-end scenarios
(plan unchanged, edited, AC missed, no baseline). README documents the
tool with example output and heuristic limitations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 19:36:43 +02:00
f51b7a6178 feat: verify_task_against_plan MCP tool
Read-only tool that compares frozen plan_snapshot against current
task.implementation_plan + story logs + commits. Returns markdown report
with per-AC ✓/✗/? keyword heuristic, drift-score, and plan diff.
Demo users allowed (readOnlyHint: true).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 19:36:37 +02:00
de7803a370 chore: add plan_snapshot to local prisma schema copy
Keeps prisma/schema.prisma in sync with vendor/scrum4me so
prisma:generate produces the updated ClaudeJob client types.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 19:36:30 +02:00
54ace839f8 test: snapshot capture + stale reset in wait_for_job
Verifies: claim writes plan_snapshot from task.implementation_plan;
NULL plan becomes '' snapshot; no job returns null; stale reset SQL
includes plan_snapshot = NULL; product_id scoping passes correct param.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 19:27:56 +02:00
ddc773d20a feat: capture plan_snapshot at job claim in wait_for_job
- resetStaleClaimedJobs: also sets plan_snapshot = NULL on reset
- tryClaimJob: JOINs tasks table to read implementation_plan in the
  same atomic transaction, writes it to claude_jobs.plan_snapshot
- Empty-plan edge case: NULL becomes '' (non-null) in snapshot
- Exports both functions for unit testing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 19:27:52 +02:00
5ecb9903e6 chore: bump vendor/scrum4me to plan_snapshot migration commit
Points submodule to Scrum4Me a3af2dd which adds ClaudeJob.plan_snapshot
field; regenerated Prisma client includes the new column.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 19:27:45 +02:00
fd452d229e
Merge pull request #3 from madhura68/feat/story-promotion-filter
feat: story-promotion + done-stories filter in get_claude_context
2026-04-30 18:25:38 +02:00
3564070bbe test: add unit tests for tasks-status-update helper and get-claude-context filter
tasks-status-update.test.ts: 7 tests covering promote, idempotent
promote, partial-siblings no-promote, demote, no-demote-when-not-done,
task-always-updated, and custom tx client pass-through.

get-claude-context-filter.test.ts: 3 tests verifying the OR tasks
filter is passed, sprint_id/status filter is present, and no story
query fires when there is no active sprint.
2026-04-30 18:22:55 +02:00
5dfca22fe6 chore: add vitest to devDependencies with config
Adds vitest as test runner for the MCP repo. Config targets
__tests__/**/*.test.ts and excludes vendor/ and node_modules/.
2026-04-30 18:22:51 +02:00
e2c86eb4d9 feat: wire story-promotion into update_task_status + filter done stories from get_claude_context
update_task_status now delegates to updateTaskStatusWithStoryPromotion
and surfaces story_status_change ('promoted' | 'demoted' | null) in the
response so Claude Code can act on story completion without a separate
read call.

get_claude_context adds an OR-filter on tasks so stories where every
task is DONE are skipped — only surfaces stories that still have work to
do (no tasks, or at least one non-DONE task).
2026-04-30 18:22:47 +02:00
7425584921 feat: add updateTaskStatusWithStoryPromotion helper
Ported transactional story-promotion logic from Scrum4Me app. Promotes
parent story to DONE when all sibling tasks transition to DONE; demotes
back to IN_SPRINT when a task is re-opened on a DONE story. Accepts an
optional tx client to support existing transaction contexts.
2026-04-30 18:22:41 +02:00
d6423ffc24 feat: add wait_for_job and update_job_status tools (M13 agent worker mode)
- wait_for_job: blocks ≤600s, claims QUEUED job atomically via FOR UPDATE
  SKIP LOCKED, resets stale CLAIMED jobs (>30min), registers ClaudeWorker
  presence with heartbeat, emits worker_connected/disconnected via NOTIFY
- update_job_status: agent reports running|done|failed, validates token
  ownership (claimed_by_token_id), emits claude_job_status via NOTIFY
- auth.ts extended with tokenId so tools can set claimed_by_token_id

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 20:05:09 +02:00
d4536b0f96 chore: bump vendor/scrum4me to M13 (ClaudeJob + ClaudeWorker) and sync schema 2026-04-29 20:05:02 +02:00
11c27662d4 chore: bump vendor/scrum4me to include ClaudeJob + ClaudeWorker 2026-04-29 19:46:12 +02:00
68a286da70
Merge pull request #2 from madhura68/feat/mcp-authoring-tools
feat: add 3 authoring tools — create_pbi / create_story / create_task
2026-04-29 15:54:50 +02:00
6fd2cc83de feat: add 3 authoring tools — create_pbi / create_story / create_task
Tot nu toe konden MCP-tools alleen bestaande stories/tasks bewerken
(update_task_status, log_*). Met deze drie tools kan Claude Code een
volledige backlog vanaf nul opbouwen — handig voor nieuwe projecten waar
het Scrum4Me-product nog leeg is.

- create_pbi: { product_id, title, description?, priority, sort_order? }
  Auto sort_order = last+1 binnen prio-groep. Code-veld blijft null
  (Scrum4Me-app genereert auto-codes via UI/seed).
- create_story: { pbi_id, title, description?, acceptance_criteria?, priority,
  sort_order? } — product_id afgeleid uit PBI (denormalized FK conform CLAUDE.md
  convention; nooit op client-input vertrouwen). Status='OPEN' default →
  landt in product-backlog, niet auto in een sprint.
- create_task: { story_id, title, description?, implementation_plan?, priority,
  sort_order? } — sprint_id geërfd van story. Status='TO_DO' default.

Alle drie achter `requireWriteAccess` (PERMISSION_DENIED voor demo) +
`userCanAccessProduct` op de relevante parent-product. Mirror van het
create-todo-patroon.

scripts/smoke-test.ts: tool-count check 13 → 16. README.md: tool-tabel
uitgebreid.

Quality gates: typecheck clean, build success, smoke-test toont 16 tools.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 15:52:15 +02:00
4088ae2692
Merge pull request #1 from madhura68/feat/M11-question-tools
M11 ST-1102: add 4 question-channel MCP tools
2026-04-29 11:44:28 +02:00
c5c931a074 chore: bump vendor/scrum4me submodule to merge commit on main
Was: 79367dd (M11 ST-1101 op feature-branch — niet meer reachable na squash-merge)
Nu: 9587ff4 (M11 squash-merge op origin/main — stabiele referentie)

prisma/schema.prisma is byte-identical (geen schema-drift; alleen submodule-
pointer gewijzigd zodat de pin verwijst naar een commit die op origin reachable
blijft).

npm run sync-schema + npm run typecheck beide clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:43:16 +02:00
7b955d31ac feat(ST-1102): add 4 question-channel MCP tools (M11)
Vier nieuwe tools voor het Claude vraag-antwoord-kanaal:
- ask_user_question (write): post een gestructureerde vraag aan de actieve
  Scrum4Me-gebruiker over een story; default async (returnt direct met
  question_id + status='open'); optionele wait_seconds (max 600) polt elke 2s
  tot het antwoord er is of timeout — daarna status='pending' zodat Claude met
  get_question_answer later kan ophalen
- get_question_answer (read): huidige status + antwoord van een eerder
  gestelde vraag
- list_open_questions (read): eigen vragen met status open/answered, max 50,
  meest recente eerst
- cancel_question (write, asker-only): atomic UPDATE WHERE asked_by + status=
  'open' zodat alleen eigen open vragen geannuleerd worden

Allemaal achter access-check via userCanAccessStory/Product en demo-blok via
requireWriteAccess (volgt patroon van create-todo en bestaande log-tools).

Submodule vendor/scrum4me bumpt naar Scrum4Me commit 79367dd (M11 ST-1101) —
bevat het ClaudeQuestion-model en notify_question_change-trigger waar deze
tools tegen werken.

scripts/smoke-test.ts: 13 tools verwacht (was 9); list_open_questions
toegevoegd als read-tool-coverage. Build + tools/list groen — verdere e2e via
MCP Inspector na PR-merge omdat de seed een nieuwe API-token heeft
gegenereerd en .env een nieuwe waarde nodig heeft.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 01:00:59 +02:00
2f82241696 chore: sync schema with scrum4me@7461643 (M9 + M10)
Bumps vendor/scrum4me submodule from 43a4294 (ST-509/511/512/513) naar 7461643
en daarmee picks de schema-wijzigingen op uit:
- M8 (ST-801): notify_solo_change-trigger op tasks/stories
- M9 (ST-901): User.active_product_id + UserActiveProduct relation
- M10 (ST-1001): LoginPairing model + login_pairings_notify-trigger op
  scrum4me_pairing channel; User.login_pairings back-relation

Verificatie: npm run sync-schema + npm run prisma:generate + npm run typecheck
allemaal groen. Sluit de wekelijkse drift-check (trig_015FFUnxjz9WMuhhWNGBQKFD)
voor deze drie milestones.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:04:41 +02:00
008fda1019 chore: sync schema with scrum4me@43a4294 + write metadata in log tools
PR #2 merged, so the StoryLog.metadata JSONB column is live. Sync
the vendored schema and wire `metadata` through to prisma.create in
log_implementation, log_test_result and log_commit. Cast via
Prisma.InputJsonValue because Zod parses the input as a generic
record while Prisma's JSON input type is invariant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:44:33 +02:00
ea1c94b05b fix: wrap non-object values in toolJson, add e2e smoke test
The MCP SDK rejects tools/call results where structuredContent is not a
record — array returns from list_products triggered an MCP error code
-32602. toolJson now wraps arrays/primitives as { result: <value> }.

scripts/smoke-test.ts spawns the built server over stdio, calls each
read-side tool against the live DB and asserts shape — surfaces this
bug class before regressions ship.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:38:39 +02:00
56448559c7 docs(ST-710): README with setup, tool catalogue and Claude Code config
Documents the 9 tools, 1 prompt, environment variables, schema-sync
workflow, mcp_servers.json snippet and known risks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:10:42 +02:00
83706bb6a8 feat(ST-709): implement_next_story prompt
End-to-end workflow prompt for Claude Code: fetch context, log a plan,
walk the tasks (in_progress → done), run tests, log result, commit.

Takes product_id as the only argument.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:09:19 +02:00
010238b2fc feat(ST-708): create_todo tool
Adds a todo for the authenticated user with optional description (max
2000) and optional product scope. Verifies product access if a
product_id is given. Demo accounts get PERMISSION_DENIED.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:08:05 +02:00
c39b337fcc feat(ST-707): log tools — implementation, test_result, commit
Three write tools that append StoryLog entries:
- log_implementation: type=IMPLEMENTATION_PLAN
- log_test_result: type=TEST_RESULT, status PASSED|FAILED
- log_commit: type=COMMIT with hash and message

All accept optional metadata in input but skip writing it for now —
the StoryLog.metadata JSONB column lands with Scrum4Me PR #2.
After that PR merges, run sync-schema and add `metadata` to each
prisma.create's data field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:06:50 +02:00
e3f9476568 feat(ST-706): task write tools — update_task_status and update_task_plan
- src/access.ts: shared product/story/task access checks via product
  ownership or membership
- update_task_status accepts lowercase API values, converts to DB
  enum, rejects unknown values
- update_task_plan replaces implementation_plan on a task
- Both call requireWriteAccess() so demo accounts get
  PERMISSION_DENIED before any DB write

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:05:49 +02:00
e9d87dd8ff feat(ST-705): read tools — health, list_products, get_claude_context
- health: pings DB via SELECT 1 and returns status/version/time
- list_products: active products owned or shared with the auth user
- get_claude_context: bundled product + active sprint + next story
  (with tasks, status mapped to lowercase) + 50 open todos

prisma.ts switches to a lazy proxy so the server bootstrap doesn't
crash before tools fire when DATABASE_URL is unset.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:04:51 +02:00
f5a630c143 feat(ST-704): status mappers and shared error helpers
- src/status.ts: bidirectional Task/Story status mappers — DB stays
  UPPER_SNAKE, MCP tools expose lowercase (matches REST API contract)
- src/errors.ts: formatZodError, toolError, toolJson and the
  withToolErrors() wrapper so each tool turns thrown exceptions
  (PermissionDenied, ZodError, generic) into structured MCP errors

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:02:05 +02:00
2b52b1cedd feat(ST-703): auth and Prisma client singleton
- src/prisma.ts: PrismaClient via PrismaPg adapter and pg.Pool,
  same pattern as Scrum4Me's lib/prisma.ts
- src/auth.ts: getAuth() resolves SCRUM4ME_TOKEN once, caches
  { userId, username, isDemo }. requireWriteAccess() throws
  PermissionDeniedError for demo tokens — write tools call this
  before any DB mutation

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:01:22 +02:00
992a4ad5e1 feat(ST-702): vendor Scrum4Me schema via submodule + sync script
- Add vendor/scrum4me as a git submodule (read-only source of truth)
- scripts/sync-schema.sh copies schema.prisma into prisma/, stripping
  the upstream prisma-erd-generator block we don't ship
- Track the synced schema in git so a fresh clone works after
  'git submodule update --init && npm install'
- postinstall runs 'prisma generate' so @prisma/client is ready

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:00:29 +02:00
ea00736a13 feat(ST-701): scrum4me-mcp repo skeleton
Initial repo with TypeScript strict, MCP SDK 1.29, Prisma 7,
zod and tsx. Stdio-transport bootstrap in src/index.ts boots
without crashing. Tools and prompts to be added in ST-705..ST-709.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:57:27 +02:00