PBI-58: Developer manual + in-app /manual page (#148)
* docs(PBI-58): add developer manual chapters under docs/manual/ Adds a 7-file English-language manual targeted at new human contributors: index, overview, statuses & transitions (with mermaid state diagrams), git workflow, MCP integration, docker, and troubleshooting. The manual is the *map* — it cross-references existing runbooks/ADRs/architecture docs rather than duplicating their content. Regenerates docs/INDEX.md and validates with check-doc-links.mjs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(PBI-58): add markdown rendering deps + manual:build script Adds mermaid, rehype-slug, rehype-autolink-headings for the in-app /manual page. Wires manual:build into prebuild so production builds always regenerate the chapter TOC. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(PBI-58): codegen script for in-app manual TOC scripts/build-manual.mjs walks docs/manual/, parses YAML front-matter, strips it from the body, and emits lib/manual.generated.ts with a typed ManualEntry[] containing slug, title, description, filePath, and the embedded markdown body. Pure Node 20, mirrors generate-docs-index.mjs. Inlining the markdown at build time keeps runtime serverless functions free of filesystem reads, which avoids whole-project NFT tracing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(PBI-58): /manual route renders developer manual chapters in-app Catch-all route at app/(app)/manual/[[...slug]]/page.tsx with generateStaticParams covering every TOC entry. Server-side MarkdownView uses react-markdown with remark-gfm, rehype-slug, and rehype-autolink-headings; mermaid code blocks are routed to a client-only MermaidBlock that dynamic-imports mermaid on mount. ManualSidebar (client) reads the typed TOC and highlights the active chapter via usePathname. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(PBI-58): add Manual link to main nav bar Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d750676f5e
commit
bd7478861b
19 changed files with 2239 additions and 105 deletions
121
docs/manual/04-mcp-integration.md
Normal file
121
docs/manual/04-mcp-integration.md
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
---
|
||||
title: "MCP Integration"
|
||||
status: active
|
||||
audience: [contributor]
|
||||
language: en
|
||||
last_updated: 2026-05-07
|
||||
when_to_read: "Whenever Claude Code is interacting with Scrum4Me — opening a story, claiming a job, asking the user a question."
|
||||
---
|
||||
|
||||
# 04 — MCP Integration
|
||||
|
||||
Scrum4Me exposes its REST API as native Claude Code tools through a dedicated **MCP server** living in [`madhura68/scrum4me-mcp`](https://github.com/madhura68/scrum4me-mcp). Schemas are shared via a git submodule (`vendor/scrum4me`) so there's exactly one definition of every type. From the agent's perspective, Scrum4Me looks like a set of native tools prefixed `mcp__scrum4me__*`.
|
||||
|
||||
This chapter is the **onboarding tour**. The full tool reference (all 18 tools, their parameters, and edge cases) is in [`docs/runbooks/mcp-integration.md`](../runbooks/mcp-integration.md).
|
||||
|
||||
## Three ways the agent works
|
||||
|
||||
| Mode | Triggered by | Loop |
|
||||
|---|---|---|
|
||||
| **Track A — MCP-driven** | User says *"implement the next story"* | `get_claude_context` → execute tasks → `update_task_status` → commit per layer → repeat until queue empty → push + PR |
|
||||
| **Track B — Manual** | User describes a one-off change in chat | Read pattern + styling → edit → verify → wait for `commit it` → commit |
|
||||
| **Worker — Queue-driven** | Background worker container running on a Mac/NAS | `wait_for_job` (blocks ≤600s) → switch on `kind` → execute → `update_job_status` → loop forever |
|
||||
|
||||
CLAUDE.md describes Track A and Track B; this manual focuses on the **Worker** mode because it's the most novel and the most likely to surprise a new contributor reading server logs.
|
||||
|
||||
## A typical Track A run
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant C as Claude
|
||||
participant M as MCP server
|
||||
participant DB as Postgres
|
||||
|
||||
U->>C: "implement the next story"
|
||||
C->>M: get_claude_context(product_id)
|
||||
M->>DB: SELECT product, sprint, next story, tasks
|
||||
M-->>C: { story, tasks[], pbi, sprint }
|
||||
loop per task in sort_order
|
||||
C->>M: update_task_status(task_id, 'in_progress')
|
||||
C->>C: read pattern + styling, edit files
|
||||
C->>M: log_implementation(story_id, content)
|
||||
C->>M: update_task_status(task_id, 'review')
|
||||
C->>M: log_test_result(story_id, 'PASSED')
|
||||
C->>M: update_task_status(task_id, 'done')
|
||||
end
|
||||
C->>U: "milestone ready for your test"
|
||||
U->>C: "looks good, push it"
|
||||
C->>C: git push + gh pr create
|
||||
```
|
||||
|
||||
The contract every step relies on:
|
||||
|
||||
- All inputs are **lowercase API enums** (`'in_progress'`, never `'IN_PROGRESS'`); the MCP server applies [`lib/task-status.ts`](../../lib/task-status.ts) under the hood.
|
||||
- Status writes are **forbidden for demo accounts** — they return `403`. See [02 — Statuses](./02-statuses-and-transitions.md#db-vs-api-mapping) and [`docs/adr/0006-demo-user-three-layer-policy.md`](../adr/0006-demo-user-three-layer-policy.md).
|
||||
- Bearer tokens are bound to a product. `list_products` returns only what the token can see; `get_claude_context` is product-scoped.
|
||||
|
||||
## Idea jobs vs task implementation
|
||||
|
||||
The worker `wait_for_job` returns a payload with a `kind` discriminator. The agent must switch on it:
|
||||
|
||||
| `kind` | Behaviour |
|
||||
|---|---|
|
||||
| `TASK_IMPLEMENTATION` | Default. Execute the `implementation_plan`, follow the [git workflow](./03-git-workflow.md), end with `update_job_status('done')`. |
|
||||
| `IDEA_GRILL` | Read embedded `prompt_text` + existing `idea.grill_md`. Iterate with `ask_user_question` / `get_question_answer`. End with `update_idea_grill_md(markdown)`. |
|
||||
| `IDEA_MAKE_PLAN` | Read `prompt_text` + `idea.grill_md`. **Do not ask questions** — single-pass output in strict YAML-frontmatter. End with `update_idea_plan_md(markdown)`. Server-side parser may reject → `PLAN_FAILED`. |
|
||||
| `PLAN_CHAT` | Conversational refinement loop on an existing plan (M12+). |
|
||||
| `SPRINT_IMPLEMENTATION` | Sprint-level run that cascades through every task; `update_task_status` calls must include the `sprint_run_id`. |
|
||||
|
||||
For the full Idea state machine (DRAFT → GRILLING → … → PLANNED) see [02 — Statuses & Transitions § Idea](./02-statuses-and-transitions.md#idea).
|
||||
|
||||
## The Q&A channel
|
||||
|
||||
When Claude needs a human decision mid-run, it doesn't block silently — it posts a question through the MCP and either polls or returns control:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Claude
|
||||
participant M as MCP
|
||||
participant DB as Postgres
|
||||
participant U as User (NavBar bell)
|
||||
C->>M: ask_user_question({ story_id, question, wait_seconds: 600 })
|
||||
M->>DB: INSERT user_question; NOTIFY user_question_created
|
||||
DB-->>U: SSE event → bell pulses
|
||||
U->>M: POST /api/questions/:id/answer
|
||||
M->>DB: UPDATE user_question; NOTIFY user_question_answered
|
||||
DB-->>C: ask_user_question returns { answer }
|
||||
C->>C: continue execution
|
||||
```
|
||||
|
||||
Key facts:
|
||||
|
||||
- `wait_seconds` is capped at 600. If the user doesn't answer in time, `ask_user_question` returns with status `pending`; Claude can resume later via `get_question_answer(question_id)`.
|
||||
- Idea questions (`{ idea_id }` instead of `{ story_id }`) are **user-private** — they bypass `productAccessFilter`, so collaborators don't see them.
|
||||
- A question can be cancelled by the asker via `cancel_question`.
|
||||
|
||||
The persistent design (table + `LISTEN/NOTIFY`) is documented in [`docs/architecture/claude-question-channel.md`](../architecture/claude-question-channel.md).
|
||||
|
||||
## The worker's pre-flight quota check
|
||||
|
||||
The worker doesn't blindly call `wait_for_job`. Each iteration it first checks Anthropic API quota via `bin/worker-quota-probe.sh` so it doesn't burn a 10-minute block on a queue it can't actually process. The full algorithm — settings, `worker_heartbeat` SSE event, sleep-until-reset — is in [`docs/runbooks/mcp-integration.md`](../runbooks/mcp-integration.md#pre-flight-quota-check-m13). The Docker chapter ([05](./05-docker.md#quota-probe)) shows how to test it locally.
|
||||
|
||||
## Schema-drift watchdog
|
||||
|
||||
If Scrum4Me's Prisma schema changes but `scrum4me-mcp` isn't synced, the MCP server will fail at runtime — not at deploy. To prevent that, a remote agent runs every Monday at 08:00 Amsterdam time, syncs `vendor/scrum4me`, and runs `prisma:generate` + `tsc --noEmit` in `scrum4me-mcp`. Drift reports must be resolved **before** any Scrum4Me PR with schema changes can merge. See [`docs/runbooks/mcp-integration.md`](../runbooks/mcp-integration.md#schema-drift-bewaking).
|
||||
|
||||
## Deep links
|
||||
|
||||
| Topic | Authoritative source |
|
||||
|---|---|
|
||||
| Tool reference (all 18 tools) | [`docs/runbooks/mcp-integration.md`](../runbooks/mcp-integration.md) |
|
||||
| Worker idempotency & job-status protocol | [`docs/runbooks/worker-idempotency.md`](../runbooks/worker-idempotency.md) |
|
||||
| Q&A channel architecture (table + LISTEN/NOTIFY) | [`docs/architecture/claude-question-channel.md`](../architecture/claude-question-channel.md) |
|
||||
| Idea-laag plan & prompts | [`docs/plans/M12-ideas.md`](../plans/M12-ideas.md) |
|
||||
| Sprint execution modes (PER_TASK vs SPRINT_BATCH) | [`docs/architecture/sprint-execution-modes.md`](../architecture/sprint-execution-modes.md) |
|
||||
| Realtime NOTIFY payload contract | [`docs/patterns/realtime-notify-payload.md`](../patterns/realtime-notify-payload.md) |
|
||||
| Demo-user write protection | [`docs/adr/0006-demo-user-three-layer-policy.md`](../adr/0006-demo-user-three-layer-policy.md) |
|
||||
|
||||
## What's next
|
||||
|
||||
→ [05 — Docker](./05-docker.md) covers how the worker container is run, debugged, and operated.
|
||||
Loading…
Add table
Add a link
Reference in a new issue