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,163 @@
# Design Document: Capacity Details Enrichment
## Overview
This feature enriches the existing `get_capacity_details` MCP tool to display additional information about a capacity: its description, references (partner + projects), and certifications. The data is already available in the database and exposed through existing `DBClient` methods (`get_capacity_description`, `get_capacity_references`, `get_capacity_certificates`). The change is purely in the tool's output formatting layer.
The tool currently returns a Markdown table with basic capacity fields (ID, Owner, Role, Competences, Availability) followed by a "Next steps" section. After this enhancement, it will include three additional sections between the table and the next steps: Beschreibung, Referenzen, and Zertifizierungen.
## Architecture
The change is localized to the `get_capacity_details` tool function inside `build_server()` in `src/teamlandkarte_mcp/mcp_server.py`. No new modules, classes, or external dependencies are needed.
```mermaid
sequenceDiagram
participant Client as MCP Client
participant Tool as get_capacity_details
participant DB as DBClient
Client->>Tool: call(capacity_id)
Tool->>DB: get_capacity_by_id(capacity_id)
DB-->>Tool: Capacity | None
Tool->>DB: get_capacity_description(capacity_id)
DB-->>Tool: str | None
Tool->>DB: get_capacity_references(capacity_id)
DB-->>Tool: list[CapacityReferenceRow]
Tool->>DB: get_capacity_certificates(capacity_id)
DB-->>Tool: list[str]
Tool-->>Client: Formatted Markdown string
```
### Design Decisions
1. **Sequential DB calls** The three additional queries are simple key lookups on indexed views. Parallelizing them would add complexity (async conversion of the tool) for negligible latency gain. Keep the tool synchronous.
2. **Formatting inline** The formatting logic is simple string concatenation. No need for a separate formatter class.
3. **Empty-state handling** Each section shows a "(keine)" placeholder when data is absent, keeping the output structure predictable for LLM consumers.
## Components and Interfaces
### Modified Component: `get_capacity_details` tool
**Current signature** (unchanged):
```python
def get_capacity_details(capacity_id: int | str) -> str:
```
**New internal calls added:**
```python
description: str | None = db_client.get_capacity_description(capacity_id)
references: list[CapacityReferenceRow] = db_client.get_capacity_references(capacity_id)
certificates: list[str] = db_client.get_capacity_certificates(capacity_id)
```
**Output format** (Markdown string):
```
| ID | Owner | Role | Competences | Availability |
| ... |
## Beschreibung
<description text or "(keine)">
## Referenzen
- **Partner A**: Projekt X, Projekt Y
- Projekt Z (no partner)
*or* Referenzen: (keine)
## Zertifizierungen
- Zertifikat 1
- Zertifikat 2
*or* Zertifizierungen: (keine)
## Next steps
Call find_matching_tasks(capacity_id=...) to see matching open tasks.
```
### Existing Interfaces Used (no changes)
| Method | Returns | Source |
|--------|---------|--------|
| `DBClient.get_capacity_description(capacity_id)` | `str \| None` | `teamlandkarte_v_capacities_latest.description` |
| `DBClient.get_capacity_references(capacity_id)` | `list[CapacityReferenceRow]` | `teamlandkarte_v_capacity_references_latest` joined with partners |
| `DBClient.get_capacity_certificates(capacity_id)` | `list[str]` | `teamlandkarte_v_capacity_certificates_latest.description` |
## Data Models
### CapacityReferenceRow (existing, unchanged)
```python
class CapacityReferenceRow(TypedDict):
partner_name: str # May be empty string when partner_id is NULL
projects: str # Project text from the references view
```
No new data models are introduced.
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system — essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: All enrichment data is fetched for any capacity
*For any* valid capacity ID that resolves to an existing capacity, the tool SHALL invoke `get_capacity_description`, `get_capacity_references`, and `get_capacity_certificates` with that capacity ID.
**Validates: Requirements 1.1, 2.1, 3.1**
### Property 2: Non-empty data appears in output
*For any* capacity with a non-empty description, a non-empty list of references, and a non-empty list of certificates, the formatted output SHALL contain the description text, every reference's projects text, and every certificate string.
**Validates: Requirements 1.2, 2.2, 3.2**
### Property 3: Section ordering is fixed
*For any* capacity (regardless of which fields are empty or populated), the output string SHALL contain the section markers in the order: capacity table first, then "Beschreibung", then "Referenzen", then "Zertifizierungen", then "Next steps" — and each section SHALL be separated by at least one blank line.
**Validates: Requirements 4.1, 4.2**
## Error Handling
| Scenario | Behaviour |
|----------|-----------|
| `get_capacity_by_id` returns `None` | Return `"Capacity not found: {capacity_id}"` (existing behaviour, unchanged) |
| `get_capacity_description` returns `None` | Display `"Beschreibung: (keine)"` |
| `get_capacity_references` returns `[]` | Display `"Referenzen: (keine)"` |
| `get_capacity_certificates` returns `[]` | Display `"Zertifizierungen: (keine)"` |
| `get_capacity_references` returns a row with empty `partner_name` | Display only the `projects` text (no bold partner prefix) |
| Any DB call raises an exception | Let it propagate (existing error handling in the MCP framework catches and reports it) |
## Testing Strategy
### Unit Tests
- Test `get_capacity_details` with a mock DB client returning known data for all three new fields → verify output contains expected sections and content.
- Test empty-state: description=None, references=[], certificates=[] → verify "(keine)" placeholders appear.
- Test edge case: reference with empty `partner_name` → verify only projects text is shown.
- Test that capacity-not-found still returns the error message unchanged.
### Property-Based Tests
Library: **Hypothesis** (Python)
Each property test runs a minimum of 100 iterations.
- **Property 1 test**: Generate random capacity IDs and mock DB responses. Verify all three DB methods are called with the correct ID.
- Tag: `Feature: capacity-details-enrichment, Property 1: All enrichment data is fetched for any capacity`
- **Property 2 test**: Generate random non-empty descriptions (text strategy), random lists of `CapacityReferenceRow` dicts with non-empty `projects` and `partner_name`, and random lists of non-empty certificate strings. Call the formatting logic and assert all generated data appears in the output.
- Tag: `Feature: capacity-details-enrichment, Property 2: Non-empty data appears in output`
- **Property 3 test**: Generate random combinations of present/absent data (description: str|None, references: list of 0-5 items, certificates: list of 0-5 items). Call the formatting logic and assert section headers appear in the correct order with blank-line separation.
- Tag: `Feature: capacity-details-enrichment, Property 3: Section ordering is fixed`
### Test Configuration
- Property-based testing library: `hypothesis` (already available in the project's test dependencies)
- Minimum iterations: 100 per property (`@settings(max_examples=100)`)
- Each test tagged with a comment referencing the design property