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

@@ -74,3 +74,22 @@ class TestGetSuccessorsContract:
assert "error" in result
assert result["error"]["code"] == "NO_FILE_LOADED"
async def test_get_successors_includes_driving_flag(
self, sample_xer_single_project: Path
) -> None:
"""get_successors includes driving flag for each successor."""
from xer_mcp.tools.get_successors import get_successors
from xer_mcp.tools.load_xer import load_xer
await load_xer(file_path=str(sample_xer_single_project))
# A1000 (2001) has one successor: A1010 (2002)
result = await get_successors(activity_id="2001")
assert "successors" in result
assert len(result["successors"]) >= 1
# All successors should have a driving flag
for succ in result["successors"]:
assert "driving" in succ
assert isinstance(succ["driving"], bool)