Files
xer-mcp/specs/001-schedule-tools/tasks.md
Bill Ballou af8cdc1d31 feat: add driving flag to relationship query responses
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
2026-01-07 07:21:58 -05:00

7.5 KiB

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

  • 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

  • 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

  • T003 Update TASK table handler to parse early_start_date and early_end_date in src/xer_mcp/parser/table_handlers/task.py
  • 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

  • T005 [P] [US3] Update contract test to verify driving flag in list_relationships response in tests/contract/test_list_relationships.py
  • T006 [P] [US3] Update contract test to verify driving flag in get_predecessors response in tests/contract/test_get_predecessors.py
  • T007 [P] [US3] Update contract test to verify driving flag in get_successors response in tests/contract/test_get_successors.py
  • 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

  • T009 [US3] Create is_driving_relationship helper function in src/xer_mcp/db/queries.py (implements date comparison logic from research.md)
  • T010 [US3] Update query_relationships function to JOIN on activity early dates and compute driving flag in src/xer_mcp/db/queries.py
  • T011 [US3] Update get_predecessors function to JOIN on activity early dates and compute driving flag in src/xer_mcp/db/queries.py
  • 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

  • T013 Integration test validating driving flag against sample XER data in tests/integration/test_xer_parsing.py
  • T014 Run all tests to verify no regressions: pytest tests/
  • T015 Run quickstart.md validation - verify driving flag examples match actual output
  • 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):

# 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):

# 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

# 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:

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

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