Files
Orchestrator/bahn/teamlandkarte-mcp/.kiro/specs/task-name-column/tasks.md
T
ankn a5f8fb49ab 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.
2026-06-30 20:39:52 +02:00

108 lines
5.0 KiB
Markdown

# Implementation Plan: Task Name Column
## Overview
Add the `name__c` database column to the Task model and all task queries, enabling users to see and look up tasks by their short human-readable name. Changes span model, database layer, protocol, and MCP tool output.
## Tasks
- [x] 1. Add name field to Task model and update TrinoClient queries
- [x] 1.1 Add `name: Optional[str]` field to the Task dataclass in `models.py`
- Insert `name: Optional[str]` after `id` field
- Field must be Optional since `name__c` can be NULL in the database
- _Requirements: 1.1, 1.4_
- [x] 1.2 Update `get_open_tasks` SQL queries in `trino_client.py` to SELECT `t.name__c`
- Add `t.name__c` to the unlimited query SELECT clause
- Add `t.name__c` to the CTE inner SELECT and outer SELECT in the limited query
- Update row unpacking to extract the name value
- Populate `name` field in Task construction (map NULL to None)
- _Requirements: 1.2, 1.4_
- [x] 1.3 Update `get_task_by_id` SQL query in `trino_client.py` to SELECT `t.name__c`
- Add `t.name__c` to the SELECT clause
- Update row unpacking to extract the name value
- Populate `name` field in Task construction (map NULL to None)
- _Requirements: 1.3, 1.4_
- [ ]* 1.4 Write property test: Task name field preserves database value
- **Property 1: Task name field preserves database value**
- Generate random `(name__c_value | None)` values using Hypothesis
- Construct Task objects via the row-mapping pattern, assert `task.name == input_value`
- **Validates: Requirements 1.1, 1.2, 1.3, 1.4**
- [x] 2. Add `get_task_by_name` to protocol and TrinoClient
- [x] 2.1 Add `get_task_by_name` method to `DBClient` protocol in `database/types.py`
- Method signature: `def get_task_by_name(self, name: str) -> Task | None`
- Include docstring: "Fetch one published task by its short name (name__c)."
- _Requirements: 3.1_
- [x] 2.2 Implement `get_task_by_name` in `TrinoClient`
- SQL query selects same columns as `get_task_by_id` plus `t.name__c`
- WHERE clause filters on `t.name__c = ?` and `t.status__c = ?`
- ORDER BY `t.createddate DESC` to handle duplicates (return first match)
- Reuse same row-assembly logic as `get_task_by_id`
- Return None for empty string input or no matching rows
- _Requirements: 3.1, 3.2, 3.3_
- [ ]* 2.3 Write property test: Name lookup returns correct task
- **Property 3: Name lookup returns correct task**
- Generate random tasks with unique names, mock DB cursor
- Call `get_task_by_name(name)`, assert returned task's name matches
- **Validates: Requirements 3.2**
- [x] 3. Checkpoint
- Ensure all tests pass, ask the user if questions arise.
- [x] 4. Update MCP tool output formatting
- [x] 4.1 Add "Name" column to `list_open_tasks` output table
- Add "Name" to the header list (between task_id and Title)
- Add `str(task.name or "")` to each row
- Update the empty-row fallback to include the extra column
- _Requirements: 2.1_
- [x] 4.2 Add "Name" to `get_task_details` summary table
- Add "Name" to the header list
- Add `str(task.name or "")` to the row data
- _Requirements: 2.2_
- [ ]* 4.3 Write property test: Task output contains name
- **Property 2: Task output contains name**
- Generate random Task objects with non-None names using `st.text(min_size=1)`
- Format through output functions, assert name appears as substring
- **Validates: Requirements 2.1, 2.2**
- [x] 5. Update `get_task_details` resolution logic
- [x] 5.1 Add name-based fallback resolution in `get_task_details` tool
- After `get_task_by_id` returns None, call `db_client.get_task_by_name(task_id)`
- If both return None, return "Task not found or not published: {task_id}"
- _Requirements: 3.4, 3.5_
- [ ]* 5.2 Write property test: Name resolution equivalence
- **Property 4: Name resolution equivalence**
- Generate a task with non-None name, mock both lookup methods
- Call `get_task_details` with name and with ID, assert outputs identical
- **Validates: Requirements 3.4**
- [ ]* 5.3 Write property test: Unknown identifier returns not-found
- **Property 5: Unknown identifier returns not-found**
- Generate random strings not matching any known task ID or name
- Call `get_task_details`, assert output contains "not found"
- **Validates: Requirements 3.3, 3.5**
- [x] 6. Update FakeDBClient in tests and add `get_task_by_name` stub
- Add `name` field to `FakeTask` in existing test files
- Add `get_task_by_name` method to `FakeDBClient`
- Update existing test assertions that check table headers (add "Name" column)
- _Requirements: 3.1_
- [x] 7. Final checkpoint
- Ensure all tests pass, ask the user if questions arise.
## Notes
- Tasks marked with `*` are optional and can be skipped for faster MVP
- Each task references specific requirements for traceability
- Property tests use Hypothesis with `@settings(max_examples=100)`
- The implementation language is Python (matching the existing codebase)