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:
2026-06-30 20:39:52 +02:00
parent 2f2b295531
commit a5f8fb49ab
1717 changed files with 447332 additions and 0 deletions
@@ -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.01.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
@@ -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 (35 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