feat(investigation): preserve cumulative reference graphs

Accumulate investigation paths and preserve failed attempts across rounds. Keep graph annotations separate from execution state, synchronize the API contract, and consolidate documentation.
This commit is contained in:
2026-11-11 19:10:41 +08:00
parent e47c61c121
commit b853b61a0b
38 changed files with 2445 additions and 147 deletions
@@ -0,0 +1,48 @@
"""Generated fixtures keep executable examples and publication semantics aligned across repositories."""
import json
from pathlib import Path
import pytest
from pydantic import ValidationError
from app.domain.domain_errors import DomainError
from app.domain.schemas.operational_task import TaskPresentationEventCommand, TaskSafeChart
from app.services.time_comparison_chart import validate_time_comparison_chart
FIXTURES = Path(__file__).parents[1] / "fixtures"
CASES = json.loads((FIXTURES / "chart-publication-cases.json").read_text())
@pytest.mark.parametrize("case", CASES, ids=lambda case: case["name"])
def test_chart_publication_matches_frontend_and_agent(case):
def validate():
chart = TaskSafeChart.model_validate(case["chart"]).model_dump(mode="json")
validate_time_comparison_chart(chart)
if case["accepted"]:
validate()
else:
with pytest.raises((DomainError, ValidationError)):
validate()
def test_historical_mixed_charts_remain_structurally_readable():
chart = next(case["chart"] for case in CASES if case["name"] == "old mixed charts are read only")
TaskSafeChart.model_validate(chart)
def test_exported_command_examples_use_the_current_publication_contract():
for line in (FIXTURES / "unified-presentation.jsonl").read_text().splitlines():
record = json.loads(line)
if record["record_type"] != "presentation":
continue
event = TaskPresentationEventCommand.model_validate({
"request_id": "95000000-0000-4000-8000-000000000001",
"run_id": "95000000-0000-4000-8000-000000000002",
"source_session_id": "synthetic-chart-contract",
"command": record["command"],
})
command = event.command
if command.action == "open_chart":
validate_time_comparison_chart(command.chart.model_dump(mode="json"))