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
This commit is contained in:
2026-01-07 07:21:58 -05:00
parent 2255b65ef6
commit af8cdc1d31
17 changed files with 654 additions and 324 deletions

View File

@@ -87,6 +87,76 @@ class TestTaskHandler:
handler = TaskHandler()
assert handler.table_name == "TASK"
def test_parse_early_dates(self) -> None:
"""Handler should parse early_start_date and early_end_date from TASK row."""
from xer_mcp.parser.table_handlers.task import TaskHandler
handler = TaskHandler()
fields = [
"task_id",
"proj_id",
"wbs_id",
"task_code",
"task_name",
"task_type",
"status_code",
"target_start_date",
"target_end_date",
"early_start_date",
"early_end_date",
"total_float_hr_cnt",
"driving_path_flag",
]
values = [
"2001",
"1001",
"100",
"A1000",
"Site Prep",
"TT_Task",
"TK_NotStart",
"2026-01-02 07:00",
"2026-01-08 15:00",
"2026-01-02 07:00",
"2026-01-08 15:00",
"0",
"Y",
]
result = handler.parse_row(fields, values)
assert result is not None
assert result["early_start_date"] == "2026-01-02T07:00:00"
assert result["early_end_date"] == "2026-01-08T15:00:00"
def test_parse_missing_early_dates(self) -> None:
"""Handler should handle missing early dates gracefully."""
from xer_mcp.parser.table_handlers.task import TaskHandler
handler = TaskHandler()
fields = [
"task_id",
"proj_id",
"task_code",
"task_name",
"task_type",
]
values = [
"2001",
"1001",
"A1000",
"Site Prep",
"TT_Task",
]
result = handler.parse_row(fields, values)
assert result is not None
assert result["early_start_date"] is None
assert result["early_end_date"] is None
class TestTaskpredHandler:
"""Tests for TASKPRED table handler."""