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,230 @@
## 1. Project Setup
- [x] 1.1 Update `pyproject.toml` with required dependencies (mcp, trino, cachetools)
- [x] 1.2 Create `database.toml` with connection configuration structure (template only, no real credentials)
- [x] 1.3 Create project structure: `src/`, `src/database/`, `src/matching/`, `src/cache/`
- [x] 1.4 Add `.gitignore` entry for `database.toml` to prevent credential exposure
## 2. Configuration Management
- [x] 2.1 Create `src/config.py` to load database and matching configuration
- [x] 2.2 Implement configuration validation (ensure required fields present)
- [x] 2.3 Add configurable scoring thresholds (Top: ≥80%, Good: 60-79%, Partial: 40-59%, Low: <40%)
- [x] 2.4 Add configurable matching weights (competence: 0.8, role: 0.2)
- [x] 2.5 Validate that weights sum to 1.0
- [x] 2.6 Support two cache TTL settings: db_ttl_hours (12h), search_ttl_minutes (60min)
- [x] 2.7 Add fuzzy matching configuration: min_similarity (default: 0.7)
## 3. Database Layer
- [x] 3.1 Create Trino client with connection handling
- [x] 3.2 Implement connection pooling/management
- [x] 3.3 **VERIFY SCHEMA**: Confirm database schema and field names with actual Open Data Lake tables (via Trino)
- [x] 3.4 Implement single join query method:
- [x] 3.4.1 `get_all_capacities_with_competences()` - Single query joining all 3 tables
- [x] 3.4.2 Filter: deletion_reason IS NULL
- [x] 3.4.3 Use proper parameterized queries (no string interpolation)
- [x] 3.4.4 Group results by capacity_id in Python to build List[Capacity]
- [x] 3.5 Ensure read-only operations (no INSERT/UPDATE/DELETE queries)
- [x] 3.6 Add error handling for connection failures with retry logic (3x, exponential backoff)
- [x] 3.7 Add query logging for debugging (without sensitive data)
- [x] 3.8 **NEW**: Implement task database queries:
- [x] 3.8.1 Create `Task` dataclass with fields: id, title__c, description__c, startdate__c, enddate__c, createddate, skills
- [x] 3.8.2 `get_open_tasks(limit)` - Fetch published tasks sorted by createddate DESC
- [x] 3.8.3 JOIN task table with task skills table (task.id = skill.task__c)
- [x] 3.8.4 Filter: status__c = "Veröffentlicht"
- [x] 3.8.5 Group results by task_id in Python to build List[Task]
- [x] 3.8.6 `get_task_by_id(task_id)` - Fetch single task with skills by ID
- [x] 3.8.7 Use parameterized queries for task_id parameter
## 4. Caching Layer
- [x] 4.1 Create `src/cache/query_cache.py` for database cache (12h TTL)
- [x] 4.2 Create `src/cache/search_cache.py` for search results cache (60min TTL)
- [x] 4.3 Implement QueryCache with cachetools.TTLCache:
- [x] 4.3.1 Key: "all_capacities_with_competences"
- [x] 4.3.2 TTL: 12 hours
- [x] 4.3.3 Cache statistics (hits/misses)
- [x] 4.4 Implement SearchCache with cachetools.TTLCache:
- [x] 4.4.1 Key: search_id (UUID)
- [x] 4.4.2 Value: JSON-serialized search results with task_id (null or task ID), filters dict
- [x] 4.4.3 TTL: 60 minutes
- [x] 4.4.4 Methods: store_search() returns search_id, get_search(search_id) returns dict, update_search() for adding filters
- [x] 4.5 Ensure thread-safe cache operations
## 5. Matching Engine
- [x] 5.1 Create `src/matching/matcher.py` for matching logic
- [x] 5.2 Implement task analysis using Azure OpenAI (chat completion):
- [x] 5.2.1 **NEW**: Create common internal function `_extract_requirements_from_description(description)` as single source of truth
- [x] 5.2.2 Free-text mode: `analyze_free_text()` delegates to common extraction function
- [x] 5.2.3 Structured mode: Parse provided parameters directly
- [x] 5.2.4 Generate and return task analysis summary for free-text mode
- [x] 5.2.5 Handle Azure API errors (timeouts, invalid JSON) with retry logic
- [x] 5.2.6 **NEW**: Implement internal helper `extract_requirements_from_task(task_id)` - fetches task from DB and uses common extraction
- [x] 5.2.7 **UPDATED**: Implement internal helper `extract_roles_from_task(description)` - returns ranked role list; primary role is roles[0] (if any)
- [x] 5.3 Implement matching algorithm:
- [x] 5.3.1 Semantic competence matching via Azure OpenAI embeddings
- [x] 5.3.2 Role name matching (exact and similarity)
- [x] 5.3.3 Availability date range filtering (open-ended capacities: missing end_date means available without limit)
- [x] 5.3.4 Availability is NOT scored. If date_start/date_end are provided, availability is used as a filter only.
- [x] 5.3.5 Apply configured weights (competence + role) to calculate overall score
- [x] 5.4 Create `src/matching/scorer.py` for scoring logic
- [x] 5.5 Implement categorical scoring (Top/Good/Partial/Low) with configurable thresholds
- [x] 5.6 Generate match score and category for each capacity
- [x] 5.7 Group results by category for storage
## 6. MCP Server Implementation
- [x] 6.1 Create `src/mcp_server.py` with MCP SDK integration
- [x] 6.2 Integrate Azure OpenAI client for LLM access (chat + embeddings)
- [x] 6.3 Implement session state management (in-memory, per client session)
- [x] 6.3.1 Store `last_requirements` for use with update_requirements
- [x] 6.3.2 Clear session state when new search is executed
- [x] 6.4 **NEW**: Implement MCP tool: `list_open_tasks` (Phase 0)
- [x] 6.4.1 Tool parameters: limit (default: 20)
- [x] 6.4.2 Query database for published tasks (status = "Veröffentlicht")
- [x] 6.4.3 Sort by createddate DESC (newest first)
- [x] 6.4.4 Format as markdown table: Task ID, Title, Created Date, Start/End Dates, Skills Count
- [x] 6.4.5 Return table with next steps hints
- [x] 6.5 **NEW**: Implement MCP tool: `get_task_details` (Phase 0)
- [x] 6.5.1 Tool parameters: task_id (required)
- [x] 6.5.2 Fetch task from database by ID
- [x] 6.5.3 Extract ranked roles from description using `extract_roles_from_task()` helper; assign primary role as roles[0]
- [x] 6.5.4 Format task details with metadata, description, DB skills, extracted role
- [x] 6.5.5 Return formatted details with next steps hints
- [x] 6.6 **NEW**: Implement MCP tool: `validate_task_requirements` (Phase 0)
- [x] 6.6.1 Tool parameters: task_id (required)
- [x] 6.6.2 Fetch task from database
- [x] 6.6.3 Extract requirements from description using `extract_requirements_from_task()` helper
- [x] 6.6.4 Compare DB skills vs extracted skills (set operations)
- [x] 6.6.5 Compare DB dates vs extracted dates
- [x] 6.6.6 Build comparison table: Type, In Description, In Database, Status
- [x] 6.6.7 Generate summary with matched/missing counts
- [x] 6.6.8 Return validation table (informational only, no modifications)
- [x] 6.7 **NEW**: Implement MCP tool: `find_capacities_for_task` (Phase 0)
- [x] 6.7.1 Tool parameters: task_id (required)
- [x] 6.7.2 Fetch task from database
- [x] 6.7.3 Extract requirements for validation display
- [x] 6.7.4 Run validation internally (build comparison table)
- [x] 6.7.5 Build search requirements using DB skills, extracted role, DB dates
- [x] 6.7.6 Execute capacity search (same as find_matching_capacities)
- [x] 6.7.7 Store in search cache with task_id field set to task ID
- [x] 6.7.8 Return validation table + search results (combined response)
- [x] 6.8 **EXISTING**: Implement MCP tool: `extract_requirements` (Phase 1)
- [x] 6.8.1 Tool parameters: task_description (required), confirm_requirements (default: True)
- [x] 6.8.2 Use Azure OpenAI (chat completion) to extract structured requirements from free text
- [x] 6.8.3 Store extracted requirements in session state
- [x] 6.8.4 Return JSON-formatted requirements
- [x] 6.8.5 Include confirmation prompt if confirm_requirements=True
- [x] 6.9 **EXISTING**: Implement MCP tool: `collect_structured_requirement_data` (Phase 1)
- [x] 6.9.1 Tool parameters: role_name, competences, date_start, date_end (all optional), confirm_requirements (default: True)
- [x] 6.9.2 Check completeness: require at least role_name AND competences
- [x] 6.9.3 Prompt for missing required parameters with examples
- [x] 6.9.4 Store collected requirements in session state
- [x] 6.9.5 Return JSON-formatted requirements with confirmation prompt
- [x] 6.10 **EXISTING**: Implement MCP tool: `update_requirements` (Phase 1)
- [x] 6.10.1 Tool parameters: change_description (required), confirm_requirements (default: True)
- [x] 6.10.2 Check if requirements exist in session state
- [x] 6.10.3 Use Azure OpenAI (chat completion) to interpret change and update requirements
- [x] 6.10.4 Update session state with modified requirements
- [x] 6.10.5 Return updated JSON-formatted requirements with confirmation prompt
- [x] 6.11 **EXISTING**: Implement MCP tool: `find_matching_capacities` (Phase 2)
- [x] 6.11.1 Tool parameters: role_name (required), competences (required), date_start (optional), date_end (optional)
- [x] 6.11.2 **NO extraction or interpretation** - accept only explicit structured parameters
- [x] 6.11.3 Execute matching algorithm (uses Azure OpenAI embeddings for competence matching; score uses competences+role only; availability is filter-only)
- [x] 6.11.4 Generate summary table with count by score category (markdown format)
- [x] 6.11.5 Store complete results in SearchCache with task_id=null, empty filters dict
- [x] 6.11.6 Return search_id + summary + Top category results (markdown table)
- [x] 6.11.7 Clear session state after successful search
- [x] 6.12 **EXISTING**: Implement MCP tool: `filter_search_results` (Phase 3)
- [x] 6.12.1 Ensure fuzzywuzzy dependency is installed
- [x] 6.12.2 Tool parameters: search_id (required), role_filter (optional), competence_filter (optional List[str]), availability_date_start (optional), availability_date_end (optional), min_similarity (default: 0.7)
- [x] 6.12.3 **ALWAYS use original search_id as input** (not filtered search_id)
- [x] 6.12.4 Validate at least one filter is provided
- [x] 6.12.5 Retrieve original search results from SearchCache
- [x] 6.12.6 Collect all results across all categories
- [x] 6.12.7 Apply fuzzy matching: role_filter (fuzzy match on role_name), competence_filter (ALL competences must match at least one capacity competence)
- [x] 6.12.8 Combine filters with AND logic
- [x] 6.12.9 Re-categorize filtered results using Scorer
- [x] 6.12.10 Generate unique filter_id (e.g., "filter-1", "filter-2")
- [x] 6.12.11 Store filtered results under search_data["filters"][filter_id]
- [x] 6.12.12 Update search cache with filter data
- [x] 6.12.13 Return filter_id + search_id + filter summary + Top category results
- [x] 6.13 **EXISTING**: Implement MCP tool: `get_results_by_category` (Phase 3)
- [x] 6.13.1 Tool parameters: search_id (required), filter_id (optional), category (default: "Top"), page (default: 1), page_size (default: 20)
- [x] 6.13.2 Retrieve search results from SearchCache by search_id
- [x] 6.13.3 If filter_id provided, retrieve filtered results from search_data["filters"][filter_id]
- [x] 6.13.4 If filter_id not provided, use original search results
- [x] 6.13.5 Extract category results, apply pagination
- [x] 6.13.6 Format as markdown table with full competence lists
- [x] 6.13.7 Return paginated results with page info and next page hint
- [x] 6.14 Format results as markdown tables with fields: id, owner_name, role_name, role_level, begin_date, end_date, competences
- [x] 6.15 Show full competence lists (no truncation)
- [x] 6.16 Add tool descriptions and parameter schemas for MCP client
> **Update (2026-02)**: Items previously described as "via MCP sampling" are now
> implemented with **Azure OpenAI** (chat + embeddings) as part of the change
> `replace-heuristics-with-azure-openai`.
>
> There is **no runtime MCP sampling dependency** and **no heuristic fallback**
> path in the current implementation.
## 7. Integration & Entry Point
- [x] 7.1 Update `main.py` to launch MCP server
- [x] 7.2 Add command-line arguments for server configuration (port, debug mode, etc.)
- [x] 7.3 Implement graceful startup and shutdown
- [x] 7.4 Add logging configuration
## 8. Testing & Validation
- [x] 8.1 Manual testing with sample task descriptions
- [x] 8.2 Verify database connection and single join query execution
- [x] 8.3 Test both input modes (free-text via Azure OpenAI and structured)
- [x] 8.4 **NEW**: Test incremental structured mode (partial parameters with prompts)
- [x] 8.5 Validate scoring and categorization with updated weights (0.8/0.2)
- [x] 8.6 Test that availability does not affect score and is only applied as an optional filter
- [x] 8.7 Test two-tier caching behavior (DB cache 12h, search cache 60min)
- [x] 8.8 Verify read-only constraint (no writes to database)
- [x] 8.9 Test error handling (database unavailable, Azure OpenAI timeout, invalid search_id)
- [x] 8.10 Test search session management (search_id creation and retrieval)
- [x] 8.11 Test pagination in get_results_by_category
- [x] 8.12 Verify markdown table formatting and full competence display
- [x] 8.13 **NEW**: Test filter_search_results with role filter only
- [x] 8.14 **NEW**: Test filter_search_results with competence filter only
- [x] 8.15 **NEW**: Test filter_search_results with combined filters
- [x] 8.16 **NEW**: Test multi-step filtering (filter a filtered search)
- [x] 8.17 **NEW**: Test fuzzy matching with various similarity thresholds
## 9. Documentation
- [x] 9.1 Update `README.md` with project description and setup instructions
- [x] 9.2 Document `database.toml` structure and required fields
- [x] 9.3 Document three MCP tools and their parameters (find_matching_capacities, get_results_by_category, filter_search_results)
- [x] 9.4 Add usage examples for both input modes (free-text and incremental structured)
- [x] 9.5 Document configuration options (weights, thresholds, cache TTLs, fuzzy matching)
- [x] 9.6 Add troubleshooting guide
- [x] 9.7 Document Azure OpenAI architecture and client-side LLM requirement
- [x] 9.8 Document pagination and search session workflow
- [x] 9.9 Document availability behavior (display + date-range filtering; open-ended capacities)
- [x] 9.10 **NEW**: Document fuzzy filtering workflow and multi-step filtering
- [x] 9.11 **NEW**: Add examples of filter_search_results usage
## 10. Security & Configuration
- [x] 10.1 Ensure `database.toml` is in `.gitignore`
- [x] 10.2 Create `database.toml.example` as template (already done)
- [x] 10.3 Validate secure credential handling
- [x] 10.4 Document security best practices
- [x] 10.5 Add warning about credential rotation if database.toml was committed
## 11. Architecture Documentation
- [x] 11.1 Review architecture.md (Arc42 format) - already created with 9 ADRs
- [x] 11.2 Validate ADRs (Architecture Decision Records) align with implementation
- [x] 11.3 Update component diagrams if needed during implementation
- [x] 11.4 Verify ADR-007 (Availability is a Filter, Not a Scoring Criterion) implementation
- [x] 11.5 **NEW**: Verify ADR-008 (Incremental Structured Mode) implementation
- [x] 11.6 **NEW**: Verify ADR-009 (Fuzzy Filtering) implementation
- [x] 11.7 Document any additional architectural decisions made during development
## Notes
- All database operations must be read-only
- LLM access only via Azure OpenAI (chat + embeddings)
- Two separate caches with different TTLs (DB: 12h, Search: 60min)
- Single join query for all data retrieval
- Markdown tables for all output
- Full competence lists (no truncation)
- Search sessions via search_id (60min expiry)
- Initial implementation focuses on core functionality; refinements in future stages
- Total: tracked via `openspec list` (this markdown count is not authoritative)