Add computed driving flag to all relationship queries (list_relationships, get_predecessors, get_successors). A relationship is marked as driving when the predecessor's early end date plus lag determines the successor's early start date. Changes: - Add early_start_date and early_end_date columns to activities schema - Parse early dates from TASK table in XER files - Implement is_driving_relationship() helper with 24hr tolerance for calendar gaps - Update all relationship queries to compute and return driving flag - Add contract and unit tests for driving flag functionality - Update spec, contracts, and documentation
240 lines
7.5 KiB
Markdown
240 lines
7.5 KiB
Markdown
# Tasks: Add Driving Flag to Relationships
|
|
|
|
**Input**: Design documents from `/specs/001-schedule-tools/`
|
|
**Prerequisites**: plan.md (required), spec.md (required), research.md, data-model.md, contracts/
|
|
|
|
**Tests**: TDD is mandated by constitution - tests MUST be written and fail before implementation.
|
|
|
|
**Scope**: Enhancement to existing implementation - add computed `driving` flag to relationship query responses.
|
|
|
|
## Format: `[ID] [P?] [Story] Description`
|
|
|
|
- **[P]**: Can run in parallel (different files, no dependencies)
|
|
- **[Story]**: Which user story this task belongs to (US3 = Query Activity Relationships)
|
|
- Include exact file paths in descriptions
|
|
|
|
## Path Conventions
|
|
|
|
- **Source**: `src/xer_mcp/`
|
|
- **Tests**: `tests/`
|
|
- **Config**: `pyproject.toml`
|
|
|
|
---
|
|
|
|
## Phase 1: Setup (Schema Enhancement)
|
|
|
|
**Purpose**: Add early date columns needed for driving flag computation
|
|
|
|
- [x] T001 Update activities table schema to add early_start_date and early_end_date columns in src/xer_mcp/db/schema.py
|
|
|
|
---
|
|
|
|
## Phase 2: Foundational (Parser Enhancement)
|
|
|
|
**Purpose**: Parse early dates from TASK table and store in database
|
|
|
|
**⚠️ CRITICAL**: Must complete before relationship queries can compute driving flag
|
|
|
|
### Tests
|
|
|
|
- [x] T002 [P] Unit test for TASK handler parsing early dates in tests/unit/test_table_handlers.py (verify early_start_date, early_end_date extracted)
|
|
|
|
### Implementation
|
|
|
|
- [x] T003 Update TASK table handler to parse early_start_date and early_end_date in src/xer_mcp/parser/table_handlers/task.py
|
|
- [x] T004 Update database loader to store early dates when inserting activities in src/xer_mcp/db/loader.py
|
|
|
|
**Checkpoint**: Early dates are now parsed and stored - driving computation can begin
|
|
|
|
---
|
|
|
|
## Phase 3: User Story 3 - Add Driving Flag to Relationships (Priority: P2) 🎯 FOCUS
|
|
|
|
**Goal**: Compute and return `driving` flag in all relationship query responses
|
|
|
|
**Independent Test**: Load XER file, query relationships, verify driving flag is present and correctly computed
|
|
|
|
### Tests for User Story 3
|
|
|
|
> **NOTE: Write these tests FIRST, ensure they FAIL before implementation**
|
|
|
|
- [x] T005 [P] [US3] Update contract test to verify driving flag in list_relationships response in tests/contract/test_list_relationships.py
|
|
- [x] T006 [P] [US3] Update contract test to verify driving flag in get_predecessors response in tests/contract/test_get_predecessors.py
|
|
- [x] T007 [P] [US3] Update contract test to verify driving flag in get_successors response in tests/contract/test_get_successors.py
|
|
- [x] T008 [P] [US3] Unit test for driving flag computation logic in tests/unit/test_db_queries.py (test is_driving_relationship function)
|
|
|
|
### Implementation for User Story 3
|
|
|
|
- [x] T009 [US3] Create is_driving_relationship helper function in src/xer_mcp/db/queries.py (implements date comparison logic from research.md)
|
|
- [x] T010 [US3] Update query_relationships function to JOIN on activity early dates and compute driving flag in src/xer_mcp/db/queries.py
|
|
- [x] T011 [US3] Update get_predecessors function to JOIN on activity early dates and compute driving flag in src/xer_mcp/db/queries.py
|
|
- [x] T012 [US3] Update get_successors function to JOIN on activity early dates and compute driving flag in src/xer_mcp/db/queries.py
|
|
|
|
**Checkpoint**: Driving flag now included in all relationship responses
|
|
|
|
---
|
|
|
|
## Phase 4: Polish & Validation
|
|
|
|
**Purpose**: Verify integration and documentation alignment
|
|
|
|
- [x] T013 Integration test validating driving flag against sample XER data in tests/integration/test_xer_parsing.py
|
|
- [x] T014 Run all tests to verify no regressions: pytest tests/
|
|
- [x] T015 Run quickstart.md validation - verify driving flag examples match actual output
|
|
- [x] T016 Run ruff check and fix any linting issues: ruff check src/
|
|
|
|
---
|
|
|
|
## Dependencies & Execution Order
|
|
|
|
### Phase Dependencies
|
|
|
|
```
|
|
Phase 1 (Schema)
|
|
│
|
|
▼
|
|
Phase 2 (Parser)
|
|
│
|
|
▼
|
|
Phase 3 (Queries) ← MAIN WORK
|
|
│
|
|
▼
|
|
Phase 4 (Polish)
|
|
```
|
|
|
|
### Task Dependencies Within Phase 3
|
|
|
|
```
|
|
T005, T006, T007, T008 (Tests) ← Write first, verify FAIL
|
|
│
|
|
▼
|
|
T009 (Helper function)
|
|
│
|
|
├── T010 (query_relationships)
|
|
├── T011 (get_predecessors)
|
|
└── T012 (get_successors)
|
|
│
|
|
▼
|
|
All tests now PASS
|
|
```
|
|
|
|
### Parallel Opportunities
|
|
|
|
**Phase 2 Tests + Phase 3 Tests** (can write all tests in parallel):
|
|
```bash
|
|
# All test tasks can run in parallel:
|
|
Task T002: "Unit test for TASK handler parsing early dates"
|
|
Task T005: "Update contract test for list_relationships"
|
|
Task T006: "Update contract test for get_predecessors"
|
|
Task T007: "Update contract test for get_successors"
|
|
Task T008: "Unit test for driving flag computation"
|
|
```
|
|
|
|
**Phase 3 Query Updates** (after T009 is complete):
|
|
```bash
|
|
# These can run in parallel once helper function exists:
|
|
Task T010: "Update query_relationships"
|
|
Task T011: "Update get_predecessors"
|
|
Task T012: "Update get_successors"
|
|
```
|
|
|
|
---
|
|
|
|
## Parallel Example: Phase 3
|
|
|
|
```bash
|
|
# First: Write all tests in parallel
|
|
Task: "Update contract test for list_relationships in tests/contract/test_list_relationships.py"
|
|
Task: "Update contract test for get_predecessors in tests/contract/test_get_predecessors.py"
|
|
Task: "Update contract test for get_successors in tests/contract/test_get_successors.py"
|
|
Task: "Unit test for driving flag computation in tests/unit/test_db_queries.py"
|
|
|
|
# Verify all tests FAIL (driving flag not yet implemented)
|
|
|
|
# Then: Implement helper function
|
|
Task: "Create is_driving_relationship helper in src/xer_mcp/db/queries.py"
|
|
|
|
# Then: Update all queries in parallel
|
|
Task: "Update query_relationships in src/xer_mcp/db/queries.py"
|
|
Task: "Update get_predecessors in src/xer_mcp/db/queries.py"
|
|
Task: "Update get_successors in src/xer_mcp/db/queries.py"
|
|
|
|
# Verify all tests PASS
|
|
```
|
|
|
|
---
|
|
|
|
## Implementation Strategy
|
|
|
|
### Driving Flag Computation (from research.md)
|
|
|
|
The driving flag is computed at query time by comparing dates:
|
|
|
|
```python
|
|
def is_driving_relationship(
|
|
pred_early_end: str | None,
|
|
succ_early_start: str | None,
|
|
lag_hours: float,
|
|
pred_type: str
|
|
) -> bool:
|
|
"""Determine if relationship is driving based on early dates."""
|
|
if pred_early_end is None or succ_early_start is None:
|
|
return False
|
|
|
|
# For FS: pred_end + lag = succ_start means driving
|
|
if pred_type == "FS":
|
|
# Parse dates, add lag, compare with 1-hour tolerance
|
|
...
|
|
|
|
# Similar logic for SS, FF, SF
|
|
return False
|
|
```
|
|
|
|
### SQL Query Pattern
|
|
|
|
```sql
|
|
SELECT r.*,
|
|
pred.early_end_date,
|
|
succ.early_start_date,
|
|
-- Compute driving in Python after fetch, or use CASE in SQL
|
|
FROM relationships r
|
|
JOIN activities pred ON r.pred_task_id = pred.task_id
|
|
JOIN activities succ ON r.task_id = succ.task_id
|
|
```
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
| Phase | Tasks | Focus |
|
|
|-------|-------|-------|
|
|
| Setup | 1 | Schema update |
|
|
| Foundational | 3 | Parser enhancement |
|
|
| US3 Implementation | 8 | Driving flag computation |
|
|
| Polish | 4 | Validation |
|
|
| **Total** | **16** | |
|
|
|
|
### Task Distribution by Type
|
|
|
|
| Type | Count | IDs |
|
|
|------|-------|-----|
|
|
| Schema | 1 | T001 |
|
|
| Tests | 5 | T002, T005-T008 |
|
|
| Implementation | 6 | T003-T004, T009-T012 |
|
|
| Validation | 4 | T013-T016 |
|
|
|
|
### MVP Scope
|
|
|
|
Complete through T012 for minimal viable driving flag implementation.
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- [P] tasks = different files, no dependencies on incomplete tasks
|
|
- [US3] = User Story 3 (Query Activity Relationships)
|
|
- Constitution mandates TDD: write tests first, verify they fail, then implement
|
|
- Driving flag is COMPUTED at query time, not stored in database
|
|
- Use 1-hour tolerance for floating-point date arithmetic
|
|
- Commit after each task or logical group
|