Migrate all repos into monorepo context folders
Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)
Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
---
|
||||
description: Add a new MCP tool to the Teamlandkarte server following established patterns.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
## Adding a New MCP Tool
|
||||
|
||||
When adding a new MCP tool to `src/teamlandkarte_mcp/mcp_server.py`, follow these patterns:
|
||||
|
||||
### Naming Convention
|
||||
- Use `verb_noun` pattern (e.g., `find_matching_capacities`, `get_task_details`, `list_open_tasks`)
|
||||
- Prefix with `mcp_` in the function name for the decorator
|
||||
|
||||
### Required Structure
|
||||
1. Define the tool function with `@mcp.tool()` decorator
|
||||
2. Add clear parameter schemas with descriptions and types
|
||||
3. Return Markdown-formatted output (tables for structured data)
|
||||
4. Include proper error messages for invalid inputs
|
||||
5. Produce deterministic outputs (same input → same output, modulo cache)
|
||||
|
||||
### Checklist
|
||||
- [ ] Tool function defined in `mcp_server.py` with `@mcp.tool()` decorator
|
||||
- [ ] Parameters have type hints and descriptions
|
||||
- [ ] Output uses Markdown tables for structured data
|
||||
- [ ] Error handling for invalid inputs (return helpful error messages)
|
||||
- [ ] No secrets or credentials in output
|
||||
- [ ] Read-only database access (never write to Trino)
|
||||
- [ ] Add corresponding test in `tests/`
|
||||
- [ ] Run `uv run ruff check src/ tests/` and `uv run mypy src/`
|
||||
- [ ] Update `docs/assistant_system_prompt.md` with the new tool documentation
|
||||
|
||||
### Example Pattern
|
||||
```python
|
||||
@mcp.tool()
|
||||
async def mcp_my_new_tool(
|
||||
param1: str,
|
||||
param2: int = 10,
|
||||
) -> str:
|
||||
"""Short description of what this tool does.
|
||||
|
||||
Args:
|
||||
param1: Description of param1.
|
||||
param2: Description of param2 (default: 10).
|
||||
"""
|
||||
# Implementation
|
||||
result = await some_operation(param1, param2)
|
||||
# Format as Markdown table
|
||||
return format_as_markdown_table(result)
|
||||
```
|
||||
|
||||
### Security
|
||||
- Never expose credentials in tool output
|
||||
- Never write to the database
|
||||
- Validate all inputs before processing
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
description: Help configure the Teamlandkarte matching system — weights, thresholds, similarity strategy, caching, and Azure OpenAI settings.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
## Configuration Guide
|
||||
|
||||
All runtime configuration lives in `config.toml`. See `config.toml.example` for the full schema.
|
||||
|
||||
### Key Sections
|
||||
|
||||
**`[database]`** — Trino connection
|
||||
- `host`, `port`, `catalog`, `schema`
|
||||
- Credentials are in `.env` (DATA_LAKE_USERNAME, DATA_LAKE_PASSWORD)
|
||||
|
||||
**`[matching]`** — Scoring and behavior
|
||||
- `role_weight` / `competence_weight` — how much each contributes to overall score
|
||||
- `require_confirmation` — whether the confirmation gate is enforced (default: true)
|
||||
- `category_thresholds` — score boundaries for Top/Good/Partial/Low/Irrelevant
|
||||
|
||||
**`[matching.similarity]`** — Similarity strategy
|
||||
- `use_bm25_search` — false = embeddings (default), true = BM25+RRF
|
||||
- `use_auto_tagging` — LLM-based synonym expansion for BM25 mode (requires `use_bm25_search = true`)
|
||||
|
||||
**`[cache]`** — TTL settings
|
||||
- `db_cache_ttl` — Trino query cache (default: 12h)
|
||||
- `search_cache_ttl` — Search session cache (default: 60min)
|
||||
|
||||
**`[embedding_cache]`** — Persistent SQLite cache
|
||||
- `db_path` — SQLite file path
|
||||
- `ttl_days` — How long embeddings are cached (default: 30)
|
||||
|
||||
**`[azure_openai]`** — Azure OpenAI embeddings
|
||||
- `endpoint`, `deployment`, `api_version`
|
||||
- `embedding_batch_size` — Batch size for embedding requests (default: 128)
|
||||
- API key in `.env` (AZURE_OPENAI_EMBEDDING_API_KEY)
|
||||
|
||||
### Common Tuning Scenarios
|
||||
|
||||
**"Results are too broad"** → Increase category thresholds or add more specific competences
|
||||
**"Missing valid matches"** → Lower thresholds, or switch from BM25 to embeddings for semantic matching
|
||||
**"Slow responses"** → Check cache TTLs, increase embedding batch size, verify network to Azure
|
||||
**"BM25 misses synonyms"** → Enable `use_auto_tagging = true` (requires LLM API key)
|
||||
|
||||
### Security Reminder
|
||||
- Never put credentials in `config.toml`
|
||||
- All secrets go in `.env` only
|
||||
- `config.toml` is not in version control (see `.gitignore`)
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
description: Debug matching issues — investigate why capacity matching produces unexpected results (wrong scores, missing candidates, expired searches).
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
## Debugging Matching Issues
|
||||
|
||||
### Common Issues
|
||||
|
||||
**1. Unexpected scores (too high/low)**
|
||||
- Check `config.toml` weights: `[matching]` section has `role_weight` and `competence_weight`
|
||||
- Check similarity strategy: `matching.similarity.use_bm25_search` (BM25 vs embeddings)
|
||||
- BM25 scores 0.0 for non-overlapping tokens (not semantic — "ML" ≠ "Machine Learning")
|
||||
- Embedding similarity is cosine-based (0.0–1.0 range)
|
||||
|
||||
**2. Missing candidates**
|
||||
- Check availability filtering: `date_start`/`date_end` may exclude valid candidates
|
||||
- Check `is_fully_available` filter — partial overlap candidates are excluded
|
||||
- Verify the candidate has a published capacity in the database
|
||||
|
||||
**3. Expired/invalid search sessions**
|
||||
- Search cache TTL: 60 minutes (configurable in `[cache]`)
|
||||
- If `status=unknown_or_expired`: rerun `find_matching_capacities(...)` for fresh results
|
||||
- Never retry with a guessed search_id
|
||||
|
||||
**4. Embedding failures**
|
||||
- Check Azure OpenAI connectivity and API key in `.env`
|
||||
- Check `azure_openai.embedding_batch_size` in config (default: 128)
|
||||
- Failure is strict: no heuristic fallback
|
||||
|
||||
### Diagnostic Steps
|
||||
|
||||
1. Check config: `cat config.toml` — verify weights, thresholds, similarity strategy
|
||||
2. Check logs: server logs show embedding calls, cache hits, query execution
|
||||
3. Validate requirements: use `validate_task_requirements(task_id)` to compare DB vs inferred
|
||||
4. Check cache state: SQLite embedding cache at path configured in `[embedding_cache]`
|
||||
5. Run with verbose: `uv run pytest -v tests/test_similarity.py` for similarity logic tests
|
||||
|
||||
### Key Files
|
||||
- `src/teamlandkarte_mcp/matching/scorer.py` — scoring logic
|
||||
- `src/teamlandkarte_mcp/matching/similarity.py` — similarity computation
|
||||
- `src/teamlandkarte_mcp/matching/matcher.py` — orchestration
|
||||
- `src/teamlandkarte_mcp/cache/` — all cache layers
|
||||
- `config.toml` — runtime configuration
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
description: Implement an approved OpenSpec change and keep tasks in sync.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
<!-- OPENSPEC:START -->
|
||||
**Guardrails**
|
||||
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
|
||||
- Keep changes tightly scoped to the requested outcome.
|
||||
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
|
||||
|
||||
**Steps**
|
||||
Track these steps as TODOs and complete them one by one.
|
||||
1. Read `changes/<id>/proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria.
|
||||
2. Work through tasks sequentially, keeping edits minimal and focused on the requested change.
|
||||
3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished.
|
||||
4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality.
|
||||
5. Reference `openspec list` or `openspec show <item>` when additional context is required.
|
||||
|
||||
**Reference**
|
||||
- Use `openspec show <id> --json --deltas-only` if you need additional context from the proposal while implementing.
|
||||
<!-- OPENSPEC:END -->
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: Archive a deployed OpenSpec change and update specs.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
<!-- OPENSPEC:START -->
|
||||
**Guardrails**
|
||||
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
|
||||
- Keep changes tightly scoped to the requested outcome.
|
||||
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
|
||||
|
||||
**Steps**
|
||||
1. Determine the change ID to archive:
|
||||
- If this prompt already includes a specific change ID (for example inside a `<ChangeId>` block populated by slash-command arguments), use that value after trimming whitespace.
|
||||
- If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends.
|
||||
- Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding.
|
||||
- If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet.
|
||||
2. Validate the change ID by running `openspec list` (or `openspec show <id>`) and stop if the change is missing, already archived, or otherwise not ready to archive.
|
||||
3. Run `openspec archive <id> --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work).
|
||||
4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`.
|
||||
5. Validate with `openspec validate --strict` and inspect with `openspec show <id>` if anything looks off.
|
||||
|
||||
**Reference**
|
||||
- Use `openspec list` to confirm change IDs before archiving.
|
||||
- Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off.
|
||||
<!-- OPENSPEC:END -->
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: Scaffold a new OpenSpec change and validate strictly.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
<!-- OPENSPEC:START -->
|
||||
**Guardrails**
|
||||
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
|
||||
- Keep changes tightly scoped to the requested outcome.
|
||||
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
|
||||
- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
|
||||
|
||||
**Steps**
|
||||
1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification.
|
||||
2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes/<id>/`.
|
||||
3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing.
|
||||
4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
|
||||
5. Draft spec deltas in `changes/<id>/specs/<capability>/spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant.
|
||||
6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
|
||||
7. Validate with `openspec validate <id> --strict` and resolve every issue before sharing the proposal.
|
||||
|
||||
**Reference**
|
||||
- Use `openspec show <id> --json --deltas-only` or `openspec show <spec> --type spec` to inspect details when validation fails.
|
||||
- Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones.
|
||||
- Explore the codebase with `rg <keyword>`, `ls`, or direct file reads so proposals align with current implementation realities.
|
||||
<!-- OPENSPEC:END -->
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
description: Refactor Teamlandkarte code safely — maintain behavior while improving structure, following project conventions.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
## Safe Refactoring Guidelines
|
||||
|
||||
### Before Refactoring
|
||||
1. Run the full test suite: `uv run pytest` — establish baseline (all green)
|
||||
2. Run type check: `uv run mypy src/` — no existing errors
|
||||
3. Understand the scope: read related code and identify all callers/consumers
|
||||
|
||||
### Constraints
|
||||
- **Never break the MCP tool interface** — tool names, parameter schemas, and output formats are public API
|
||||
- **Never break the confirmation gate** — the show → ask → confirm flow is a hard requirement
|
||||
- **Maintain read-only DB access** — no writes to Trino, ever
|
||||
- **Keep Markdown table output format** — clients depend on it
|
||||
- **Preserve cache semantics** — TTLs, invalidation, and layering must remain consistent
|
||||
|
||||
### Refactoring Checklist
|
||||
- [ ] Tests pass before changes: `uv run pytest`
|
||||
- [ ] Make incremental changes (one logical change per commit)
|
||||
- [ ] Tests pass after each change: `uv run pytest`
|
||||
- [ ] Lint passes: `uv run ruff check src/ tests/`
|
||||
- [ ] Types pass: `uv run mypy src/`
|
||||
- [ ] No new warnings introduced
|
||||
- [ ] If renaming public symbols: update `docs/assistant_system_prompt.md` and `.kiro/agents/teamlandkarte.md`
|
||||
|
||||
### Code Style Reminders
|
||||
- Line length: 110 characters
|
||||
- Type hints on all function signatures
|
||||
- Async/await for I/O operations
|
||||
- Dataclasses or Pydantic for structured data
|
||||
- Docstrings on public APIs
|
||||
|
||||
### For Significant Refactors
|
||||
If the refactor changes architecture or public interfaces, follow the OpenSpec workflow:
|
||||
1. Create a proposal in `openspec/changes/<change-id>/`
|
||||
2. Get approval before implementing
|
||||
3. See `openspec/AGENTS.md` for details
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
description: Review and update the assistant system prompt (docs/assistant_system_prompt.md) to ensure it stays consistent with the actual MCP server implementation.
|
||||
---
|
||||
|
||||
## System Prompt Maintenance
|
||||
|
||||
The file `docs/assistant_system_prompt.md` defines how AI assistants interact with the Teamlandkarte MCP server. It must stay in sync with the actual implementation.
|
||||
|
||||
### What to Check
|
||||
|
||||
1. **Tool inventory**: Every `@mcp.tool()` in `src/teamlandkarte_mcp/mcp_server.py` must be documented in the "Tools and when to use them" section.
|
||||
2. **Parameter schemas**: Tool parameters in the prompt must match actual function signatures.
|
||||
3. **Workflow steps**: Default workflows must reference only existing tools (no stale/removed tool names).
|
||||
4. **Confirmation gate**: The confirmation workflow must match the actual `require_confirmation` behavior in `src/teamlandkarte_mcp/matching/`.
|
||||
5. **Scoring/similarity**: BM25, embeddings, and auto-tagging documentation must reflect current `config.toml.example` options.
|
||||
6. **Consistency with Kiro agent**: `.kiro/agents/teamlandkarte.md` should mirror the system prompt content.
|
||||
|
||||
### Sync Targets
|
||||
|
||||
When updating the system prompt, also update:
|
||||
- `.kiro/agents/teamlandkarte.md` (Kiro agent definition)
|
||||
- `.github/prompts/teamlandkarte-matching-assistant.prompt.md` (Copilot skill)
|
||||
|
||||
### Validation Steps
|
||||
|
||||
1. Read `src/teamlandkarte_mcp/mcp_server.py` — list all `@mcp.tool()` functions
|
||||
2. Compare against the "Tools and when to use them" section in the prompt
|
||||
3. Check for stale references (tools that were removed or renamed)
|
||||
4. Check for missing tools (new tools not yet documented)
|
||||
5. Verify parameter names and types match
|
||||
6. Run `uv run pytest` to confirm nothing is broken
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
---
|
||||
description: Act as the Teamlandkarte capacity matching assistant — help users find matching capacities for tasks using the MCP tools.
|
||||
---
|
||||
|
||||
# Teamlandkarte Capacity Matching Assistant
|
||||
|
||||
You are a task-to-capacity matching assistant for the Teamlandkarte MCP server.
|
||||
|
||||
## Goals
|
||||
|
||||
- Help the user find matching capacities for a task.
|
||||
- Provide a predictable workflow.
|
||||
- Prefer safe, deterministic behavior.
|
||||
- Default language: respond in **German** (tools/tables may be English if returned). If the user writes in English, you may respond in English.
|
||||
- Unless the user explicitly asks otherwise, always operate on the **latest** search.
|
||||
|
||||
## When the user request does not map to a tool
|
||||
|
||||
Output a numbered list of available next actions and ask the user to choose:
|
||||
|
||||
1. Bestehende Aufgaben ansehen (Liste öffentlicher Aufgaben)
|
||||
2. Details zu einer konkreten Aufgabe ansehen
|
||||
3. Anforderungen einer Aufgabe prüfen (Validierung)
|
||||
4. Passende Kapazitäten zu einer bestehenden Aufgabe finden
|
||||
5. Neue Aufgabe / Anforderungen definieren (geführte Abfrage oder manuell)
|
||||
6. Freie Kapazitäten ansehen (neueste Einträge)
|
||||
7. Details zu einer konkreten Kapazität ansehen
|
||||
8. Passende Aufgaben für eine konkrete Kapazität finden
|
||||
|
||||
Do not call tools until the user picks a path.
|
||||
|
||||
## After each successful request
|
||||
|
||||
End your message with a short numbered list (3–5 items) of sensible next actions adapted to the current context.
|
||||
|
||||
## Mandatory requirement capture
|
||||
|
||||
Before calling `find_matching_capacities(...)`, you MUST have:
|
||||
|
||||
- `role_name` (or `"Beliebige Rolle"` if user refuses)
|
||||
- `competences` (non-empty list)
|
||||
- `date_start` / `date_end` (ask for time range; open-ended allowed)
|
||||
- A **concrete topic/goal description** (not just a single skill)
|
||||
|
||||
If any are missing, ask targeted follow-up questions. Do NOT run matching yet.
|
||||
|
||||
## Confirmation workflow (strict)
|
||||
|
||||
Never auto-confirm. Assume confirmation is enabled unless told otherwise.
|
||||
|
||||
1. After requirements captured: call `show_pending_requirements()`
|
||||
2. Ask: "Soll ich diese Anforderungen so übernehmen und die Suche starten?" (Ja/Nein)
|
||||
3. Only on "Ja": call `confirm_requirements(confirm=true)`
|
||||
4. On "Nein": call `confirm_requirements(confirm=false)` and continue capture
|
||||
|
||||
Do NOT call `confirm_requirements(confirm=true)` in the same turn as requirement capture.
|
||||
|
||||
## Guided capture (for incomplete ad-hoc requests)
|
||||
|
||||
Use guided capture when the user provides incomplete info (missing scope/goal, fewer than 2 competences, or no time range):
|
||||
|
||||
1. `start_guided_capture()`
|
||||
2. `guided_set_description(...)` — ask for missing context
|
||||
3. `guided_set_role(...)`
|
||||
4. `guided_set_time_range(date_start?, date_end?)`
|
||||
5. `guided_set_competences([...])`
|
||||
6. `show_pending_requirements()`
|
||||
7. Ask user for confirmation
|
||||
8. `confirm_requirements(confirm=true)` (if confirmed)
|
||||
9. `find_matching_capacities(...)`
|
||||
|
||||
## Search ID tracking
|
||||
|
||||
- Track `LATEST_SEARCH_ID` from the most recent tool output.
|
||||
- After `find_matching_capacities`: echo `Using SEARCH_ID=<uuid>` and the Summary table.
|
||||
- Before calling `get_results_by_category` or `filter_search_results`: write `Using SEARCH_ID=<LATEST_SEARCH_ID>`.
|
||||
- On expired/invalid search: rerun `find_matching_capacities(...)` for a fresh search.
|
||||
|
||||
## Default workflows
|
||||
|
||||
### Workflow A: User has a DB task id
|
||||
1. `get_task_details(task_id)`
|
||||
2. If role unclear: `infer_primary_role(task_id=...)`
|
||||
3. Capture requirements via `collect_structured_requirement_data(...)` or `extract_requirements(...)`
|
||||
4. `show_pending_requirements()` → ask confirmation → `confirm_requirements()`
|
||||
5. `find_matching_capacities(role_name, competences, date_start?, date_end?)`
|
||||
|
||||
### Workflow B: User provides free-text description
|
||||
1. `extract_requirements(task_description, confirm_requirements=true)`
|
||||
2. Ask for missing fields (especially date range)
|
||||
3. `show_pending_requirements()` → ask confirmation → `confirm_requirements()`
|
||||
4. `find_matching_capacities(...)`
|
||||
|
||||
### Workflow C: Capacity-driven matching
|
||||
1. `list_free_capacities(limit=...)`
|
||||
2. `get_capacity_details(capacity_id)`
|
||||
3. `find_matching_tasks(capacity_id)`
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
description: Write tests for Teamlandkarte MCP server components following project conventions.
|
||||
---
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
## Writing Tests
|
||||
|
||||
Follow these patterns when writing tests for this project.
|
||||
|
||||
### Setup
|
||||
- Framework: pytest + pytest-asyncio
|
||||
- Test directory: `tests/`
|
||||
- Run: `uv run pytest` or `uv run pytest -v`
|
||||
|
||||
### Conventions
|
||||
- Use `@pytest.mark.asyncio` for async test functions
|
||||
- Mock external services (Trino, Azure OpenAI) — never call real APIs in tests
|
||||
- Use `unittest.mock.AsyncMock` for async mocks
|
||||
- Test file naming: `tests/test_<module>.py`
|
||||
- Test function naming: `test_<what_is_being_tested>`
|
||||
|
||||
### Key Test Areas
|
||||
- **Confirmation gating**: Verify matching refuses to run without confirmation
|
||||
- **Search robustness**: Empty results, invalid inputs, expired sessions
|
||||
- **Filtering/pagination**: Category browsing, filter application, page boundaries
|
||||
- **Cache behavior**: TTL expiry, cache hits/misses
|
||||
- **Schema validation**: Invalid parameters, missing required fields
|
||||
- **Edge cases**: Empty competence lists, very long descriptions, special characters
|
||||
|
||||
### Mocking Patterns
|
||||
```python
|
||||
from unittest.mock import AsyncMock, patch, MagicMock
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_something():
|
||||
mock_client = AsyncMock()
|
||||
mock_client.execute_query.return_value = [{"id": "1", "title": "Test"}]
|
||||
|
||||
with patch("src.teamlandkarte_mcp.database.db_client.TrinoClient", return_value=mock_client):
|
||||
result = await function_under_test()
|
||||
assert result is not None
|
||||
```
|
||||
|
||||
### After Writing Tests
|
||||
1. Run: `uv run pytest` — all tests must pass
|
||||
2. Run: `uv run ruff check tests/` — no lint errors
|
||||
3. Run: `uv run mypy src/` — type check still passes
|
||||
Reference in New Issue
Block a user