Add runtime boundary and verification state summaries
- SHA
d193644f6eb04578eafc7d56daba8c9aae58fd01- Parents
-
cc0fe04 - Tree
d46f5bf
d193644
d193644f6eb04578eafc7d56daba8c9aae58fd01cc0fe04
d46f5bf| Status | File | + | - |
|---|---|---|---|
| M |
src/loader/cli/main.py
|
14 | 0 |
| M |
src/loader/runtime/inspection.py
|
78 | 3 |
| M |
src/loader/runtime/owner_metadata.py
|
28 | 0 |
| M |
tests/test_inspection.py
|
40 | 0 |
src/loader/cli/main.pymodified@@ -1398,6 +1398,8 @@ def _print_status_snapshot(snapshot: StatusSnapshot) -> None: | ||
| 1398 | 1398 | or "none" |
| 1399 | 1399 | ), |
| 1400 | 1400 | ) |
| 1401 | + if snapshot.runtime_boundary_summary: | |
| 1402 | + table.add_row("Boundary", snapshot.runtime_boundary_summary) | |
| 1401 | 1403 | table.add_row("Workflow", snapshot.workflow_mode) |
| 1402 | 1404 | if snapshot.workflow_decision_kind: |
| 1403 | 1405 | table.add_row("Decision Kind", snapshot.workflow_decision_kind) |
@@ -1472,6 +1474,8 @@ def _print_status_snapshot(snapshot: StatusSnapshot) -> None: | ||
| 1472 | 1474 | table.add_row("DoD", snapshot.dod_status or "none") |
| 1473 | 1475 | table.add_row("Pending", str(snapshot.dod_pending_items_count)) |
| 1474 | 1476 | table.add_row("Last Verify", snapshot.last_verification_result or "none") |
| 1477 | + if snapshot.verification_state_summary: | |
| 1478 | + table.add_row("Verification State", snapshot.verification_state_summary) | |
| 1475 | 1479 | if snapshot.usage: |
| 1476 | 1480 | table.add_row( |
| 1477 | 1481 | "Usage", |
@@ -1592,6 +1596,8 @@ def _session_list_main() -> None: | ||
| 1592 | 1596 | or "none" |
| 1593 | 1597 | ), |
| 1594 | 1598 | ) |
| 1599 | + if entry.runtime_boundary_summary: | |
| 1600 | + table.add_row("Boundary", entry.runtime_boundary_summary) | |
| 1595 | 1601 | table.add_row("Workflow", entry.workflow_mode) |
| 1596 | 1602 | if entry.workflow_decision_kind: |
| 1597 | 1603 | table.add_row("Decision Kind", entry.workflow_decision_kind) |
@@ -1657,6 +1663,8 @@ def _session_show_main(session_id: str) -> None: | ||
| 1657 | 1663 | or "none" |
| 1658 | 1664 | ), |
| 1659 | 1665 | ) |
| 1666 | + if detail.runtime_boundary_summary: | |
| 1667 | + table.add_row("Boundary", detail.runtime_boundary_summary) | |
| 1660 | 1668 | table.add_row("Workflow", snapshot.workflow_mode) |
| 1661 | 1669 | if snapshot.workflow_decision_kind: |
| 1662 | 1670 | table.add_row("Decision Kind", snapshot.workflow_decision_kind) |
@@ -1725,6 +1733,8 @@ def _session_show_main(session_id: str) -> None: | ||
| 1725 | 1733 | table.add_row("Rules Source", snapshot.permission_rules_source or "none") |
| 1726 | 1734 | table.add_row("Task", snapshot.current_task or "none") |
| 1727 | 1735 | table.add_row("Active DoD", snapshot.active_dod_path or "none") |
| 1736 | + if detail.verification_state_summary: | |
| 1737 | + table.add_row("Verification State", detail.verification_state_summary) | |
| 1728 | 1738 | if snapshot.usage: |
| 1729 | 1739 | table.add_row( |
| 1730 | 1740 | "Usage", |
@@ -1848,8 +1858,12 @@ def _workflow_show_main( | ||
| 1848 | 1858 | or "none" |
| 1849 | 1859 | ), |
| 1850 | 1860 | ) |
| 1861 | + if snapshot.runtime_boundary_summary: | |
| 1862 | + table.add_row("Boundary", snapshot.runtime_boundary_summary) | |
| 1851 | 1863 | table.add_row("Workflow", snapshot.workflow_mode) |
| 1852 | 1864 | table.add_row("Task", snapshot.current_task or "none") |
| 1865 | + if snapshot.verification_state_summary: | |
| 1866 | + table.add_row("Verification State", snapshot.verification_state_summary) | |
| 1853 | 1867 | table.add_row("Entries", f"{len(snapshot.entries)} shown / {snapshot.total_entries} total") |
| 1854 | 1868 | if snapshot.latest_policy_summary: |
| 1855 | 1869 | table.add_row("Latest Policy", snapshot.latest_policy_summary) |
src/loader/runtime/inspection.pymodified@@ -16,6 +16,7 @@ from ..runtime.capabilities import CapabilityProfile, resolve_capability_profile | ||
| 16 | 16 | from ..tools.base import ToolRegistry, create_default_registry |
| 17 | 17 | from .dod import DefinitionOfDone, DefinitionOfDoneStore, VerificationEvidence |
| 18 | 18 | from .explore_state import ExploreStateStore |
| 19 | +from .owner_metadata import format_runtime_boundary_label | |
| 19 | 20 | from .permissions import ( |
| 20 | 21 | PermissionConfigStatus, |
| 21 | 22 | PermissionDecision, |
@@ -165,6 +166,7 @@ class StatusSnapshot: | ||
| 165 | 166 | model: str |
| 166 | 167 | capability_profile: CapabilityProfile |
| 167 | 168 | active_session_id: str | None |
| 169 | + runtime_boundary_summary: str | None | |
| 168 | 170 | workflow_mode: str |
| 169 | 171 | workflow_reason_code: str | None |
| 170 | 172 | workflow_reason_summary: str | None |
@@ -192,6 +194,7 @@ class StatusSnapshot: | ||
| 192 | 194 | dod_status: str | None |
| 193 | 195 | dod_pending_items_count: int |
| 194 | 196 | last_verification_result: str | None |
| 197 | + verification_state_summary: str | None | |
| 195 | 198 | recent_verification: list[VerificationSummary] |
| 196 | 199 | latest_policy_supporting_evidence: list[str] = field(default_factory=list) |
| 197 | 200 | latest_policy_blocking_evidence: list[str] = field(default_factory=list) |
@@ -232,6 +235,7 @@ class SessionSummary: | ||
| 232 | 235 | created_at: str |
| 233 | 236 | updated_at: str |
| 234 | 237 | message_count: int |
| 238 | + runtime_boundary_summary: str | None | |
| 235 | 239 | workflow_mode: str |
| 236 | 240 | workflow_reason_code: str | None |
| 237 | 241 | workflow_reason_summary: str | None |
@@ -260,6 +264,8 @@ class SessionDetail: | ||
| 260 | 264 | snapshot: SessionSnapshot |
| 261 | 265 | is_current: bool |
| 262 | 266 | definition_of_done: DefinitionOfDone | None |
| 267 | + runtime_boundary_summary: str | None = None | |
| 268 | + verification_state_summary: str | None = None | |
| 263 | 269 | recent_verification: list[VerificationSummary] = field(default_factory=list) |
| 264 | 270 | |
| 265 | 271 | |
@@ -290,8 +296,10 @@ class WorkflowTimelineSnapshot: | ||
| 290 | 296 | project_root: Path |
| 291 | 297 | session_id: str | None |
| 292 | 298 | is_current: bool |
| 299 | + runtime_boundary_summary: str | None | |
| 293 | 300 | workflow_mode: str |
| 294 | 301 | current_task: str | None |
| 302 | + verification_state_summary: str | None = None | |
| 295 | 303 | total_entries: int = 0 |
| 296 | 304 | latest_policy_summary: str | None = None |
| 297 | 305 | latest_policy_supporting_evidence: list[str] = field(default_factory=list) |
@@ -461,6 +469,7 @@ def collect_status_snapshot( | ||
| 461 | 469 | model=resolved_model, |
| 462 | 470 | capability_profile=capability_profile, |
| 463 | 471 | active_session_id=None, |
| 472 | + runtime_boundary_summary=None, | |
| 464 | 473 | runtime_owner_type=None, |
| 465 | 474 | runtime_owner_path=None, |
| 466 | 475 | workflow_mode="execute", |
@@ -498,6 +507,7 @@ def collect_status_snapshot( | ||
| 498 | 507 | dod_status=None, |
| 499 | 508 | dod_pending_items_count=0, |
| 500 | 509 | last_verification_result=None, |
| 510 | + verification_state_summary=None, | |
| 501 | 511 | recent_verification=[], |
| 502 | 512 | usage={}, |
| 503 | 513 | compaction_count=0, |
@@ -535,6 +545,10 @@ def collect_status_snapshot( | ||
| 535 | 545 | model=resolved_model, |
| 536 | 546 | capability_profile=capability_profile, |
| 537 | 547 | active_session_id=snapshot.session_id, |
| 548 | + runtime_boundary_summary=_runtime_boundary_summary( | |
| 549 | + snapshot.runtime_owner_type, | |
| 550 | + snapshot.runtime_owner_path, | |
| 551 | + ), | |
| 538 | 552 | runtime_owner_type=snapshot.runtime_owner_type, |
| 539 | 553 | runtime_owner_path=snapshot.runtime_owner_path, |
| 540 | 554 | workflow_mode=snapshot.workflow_mode, |
@@ -582,6 +596,12 @@ def collect_status_snapshot( | ||
| 582 | 596 | dod=dod, |
| 583 | 597 | recent_verification=recent_verification, |
| 584 | 598 | ), |
| 599 | + verification_state_summary=_verification_state_summary( | |
| 600 | + recent_verification, | |
| 601 | + fallback_status=( | |
| 602 | + dod.last_verification_result if dod is not None else None | |
| 603 | + ), | |
| 604 | + ), | |
| 585 | 605 | recent_verification=recent_verification, |
| 586 | 606 | usage=dict(snapshot.usage), |
| 587 | 607 | compaction_count=(snapshot.compaction.count if snapshot.compaction else 0), |
@@ -648,6 +668,10 @@ def list_session_summaries(project_root: Path | str | None = None) -> list[Sessi | ||
| 648 | 668 | session_id=snapshot.session_id, |
| 649 | 669 | created_at=snapshot.created_at, |
| 650 | 670 | updated_at=snapshot.updated_at, |
| 671 | + runtime_boundary_summary=_runtime_boundary_summary( | |
| 672 | + snapshot.runtime_owner_type, | |
| 673 | + snapshot.runtime_owner_path, | |
| 674 | + ), | |
| 651 | 675 | runtime_owner_type=snapshot.runtime_owner_type, |
| 652 | 676 | runtime_owner_path=snapshot.runtime_owner_path, |
| 653 | 677 | message_count=len(snapshot.messages), |
@@ -689,14 +713,23 @@ def load_session_detail( | ||
| 689 | 713 | snapshot = store.load(session_id) |
| 690 | 714 | current_session_id = _current_session_id(store) |
| 691 | 715 | dod = _load_dod(snapshot.active_dod_path, project_root=resolved_root) |
| 716 | + recent_verification = _recent_verification_summaries( | |
| 717 | + timeline=snapshot.workflow_timeline, | |
| 718 | + evidence=dod.evidence if dod else [], | |
| 719 | + ) | |
| 692 | 720 | return SessionDetail( |
| 693 | 721 | snapshot=snapshot, |
| 694 | 722 | is_current=snapshot.session_id == current_session_id, |
| 695 | 723 | definition_of_done=dod, |
| 696 | - recent_verification=_recent_verification_summaries( | |
| 697 | - timeline=snapshot.workflow_timeline, | |
| 698 | - evidence=dod.evidence if dod else [], | |
| 724 | + runtime_boundary_summary=_runtime_boundary_summary( | |
| 725 | + snapshot.runtime_owner_type, | |
| 726 | + snapshot.runtime_owner_path, | |
| 727 | + ), | |
| 728 | + verification_state_summary=_verification_state_summary( | |
| 729 | + recent_verification, | |
| 730 | + fallback_status=(dod.last_verification_result if dod is not None else None), | |
| 699 | 731 | ), |
| 732 | + recent_verification=recent_verification, | |
| 700 | 733 | ) |
| 701 | 734 | |
| 702 | 735 | |
@@ -943,10 +976,12 @@ def collect_workflow_timeline( | ||
| 943 | 976 | project_root=resolved_root, |
| 944 | 977 | session_id=None, |
| 945 | 978 | is_current=False, |
| 979 | + runtime_boundary_summary=None, | |
| 946 | 980 | runtime_owner_type=None, |
| 947 | 981 | runtime_owner_path=None, |
| 948 | 982 | workflow_mode="execute", |
| 949 | 983 | current_task=None, |
| 984 | + verification_state_summary=None, | |
| 950 | 985 | total_entries=0, |
| 951 | 986 | latest_policy_summary=None, |
| 952 | 987 | latest_policy_supporting_evidence=[], |
@@ -969,15 +1004,29 @@ def collect_workflow_timeline( | ||
| 969 | 1004 | accountability_only=accountability_only, |
| 970 | 1005 | limit=limit, |
| 971 | 1006 | ) |
| 1007 | + dod = _load_dod(snapshot.active_dod_path, project_root=resolved_root) | |
| 1008 | + recent_verification = _recent_verification_summaries( | |
| 1009 | + timeline=snapshot.workflow_timeline, | |
| 1010 | + evidence=dod.evidence if dod else [], | |
| 1011 | + limit=1, | |
| 1012 | + ) | |
| 972 | 1013 | |
| 973 | 1014 | return WorkflowTimelineSnapshot( |
| 974 | 1015 | project_root=resolved_root, |
| 975 | 1016 | session_id=snapshot.session_id, |
| 976 | 1017 | is_current=snapshot.session_id == current_session_id, |
| 1018 | + runtime_boundary_summary=_runtime_boundary_summary( | |
| 1019 | + snapshot.runtime_owner_type, | |
| 1020 | + snapshot.runtime_owner_path, | |
| 1021 | + ), | |
| 977 | 1022 | runtime_owner_type=snapshot.runtime_owner_type, |
| 978 | 1023 | runtime_owner_path=snapshot.runtime_owner_path, |
| 979 | 1024 | workflow_mode=snapshot.workflow_mode, |
| 980 | 1025 | current_task=snapshot.current_task, |
| 1026 | + verification_state_summary=_verification_state_summary( | |
| 1027 | + recent_verification, | |
| 1028 | + fallback_status=(dod.last_verification_result if dod is not None else None), | |
| 1029 | + ), | |
| 981 | 1030 | total_entries=projection.total_entries, |
| 982 | 1031 | latest_policy_summary=projection.latest_policy_summary, |
| 983 | 1032 | latest_policy_supporting_evidence=( |
@@ -1658,6 +1707,32 @@ def _verification_summaries_from_evidence( | ||
| 1658 | 1707 | return summaries |
| 1659 | 1708 | |
| 1660 | 1709 | |
| 1710 | +def _runtime_boundary_summary( | |
| 1711 | + owner_type: str | None, | |
| 1712 | + owner_path: str | None, | |
| 1713 | +) -> str | None: | |
| 1714 | + return format_runtime_boundary_label(owner_type, owner_path) | |
| 1715 | + | |
| 1716 | + | |
| 1717 | +def _verification_state_summary( | |
| 1718 | + recent_verification: list[VerificationSummary], | |
| 1719 | + *, | |
| 1720 | + fallback_status: str | None = None, | |
| 1721 | +) -> str | None: | |
| 1722 | + if recent_verification: | |
| 1723 | + item = recent_verification[0] | |
| 1724 | + parts = [item.status] | |
| 1725 | + if item.attempt: | |
| 1726 | + parts.append(f"({item.attempt})") | |
| 1727 | + summary = " ".join(parts) | |
| 1728 | + if item.command: | |
| 1729 | + summary += f" for {item.command}" | |
| 1730 | + return summary | |
| 1731 | + if fallback_status: | |
| 1732 | + return fallback_status | |
| 1733 | + return None | |
| 1734 | + | |
| 1735 | + | |
| 1661 | 1736 | def _last_verification_result( |
| 1662 | 1737 | *, |
| 1663 | 1738 | dod: DefinitionOfDone | None, |
src/loader/runtime/owner_metadata.pymodified@@ -62,6 +62,34 @@ def format_runtime_owner_label( | ||
| 62 | 62 | return normalized_path or normalized_type |
| 63 | 63 | |
| 64 | 64 | |
| 65 | +def classify_runtime_owner_boundary( | |
| 66 | + owner_type: str | None, | |
| 67 | + owner_path: str | None, | |
| 68 | +) -> str | None: | |
| 69 | + """Classify the persisted owner boundary for operator surfaces.""" | |
| 70 | + | |
| 71 | + normalized_type = normalize_runtime_owner_type(owner_type) | |
| 72 | + normalized_path = normalize_runtime_owner_path(owner_path, owner_type=normalized_type) | |
| 73 | + if normalized_path == "runtime-handle" or normalized_type == "RuntimeHandle": | |
| 74 | + return "runtime-first" | |
| 75 | + if normalized_path == "public-agent" or normalized_type == "Agent": | |
| 76 | + return "public-compat" | |
| 77 | + return None | |
| 78 | + | |
| 79 | + | |
| 80 | +def format_runtime_boundary_label( | |
| 81 | + owner_type: str | None, | |
| 82 | + owner_path: str | None, | |
| 83 | +) -> str | None: | |
| 84 | + """Render one concise operator-facing runtime boundary label.""" | |
| 85 | + | |
| 86 | + boundary = classify_runtime_owner_boundary(owner_type, owner_path) | |
| 87 | + owner = format_runtime_owner_label(owner_type, owner_path) | |
| 88 | + if boundary and owner: | |
| 89 | + return f"{boundary} via {owner}" | |
| 90 | + return boundary or owner | |
| 91 | + | |
| 92 | + | |
| 65 | 93 | def _camel_to_kebab(value: str) -> str: |
| 66 | 94 | """Convert one CamelCase-ish class name into kebab-case.""" |
| 67 | 95 | |
tests/test_inspection.pymodified@@ -732,6 +732,7 @@ def test_status_and_session_surfaces_reflect_persisted_state(temp_dir: Path) -> | ||
| 732 | 732 | assert snapshot.last_verification_result == "failed" |
| 733 | 733 | assert snapshot.active_dod_path == dod_path |
| 734 | 734 | assert snapshot.permission_mode == "prompt" |
| 735 | + assert snapshot.runtime_boundary_summary == "runtime-first via runtime-handle (RuntimeHandle)" | |
| 735 | 736 | assert snapshot.runtime_owner_type == "RuntimeHandle" |
| 736 | 737 | assert snapshot.runtime_owner_path == "runtime-handle" |
| 737 | 738 | assert snapshot.permission_rule_counts == {"allow": 1, "deny": 2, "ask": 1} |
@@ -769,12 +770,16 @@ def test_status_and_session_surfaces_reflect_persisted_state(temp_dir: Path) -> | ||
| 769 | 770 | assert [item.status for item in snapshot.recent_verification] == ["failed"] |
| 770 | 771 | assert [item.command for item in snapshot.recent_verification] == ["pytest -q"] |
| 771 | 772 | assert [item.detail for item in snapshot.recent_verification] == ["1 failed"] |
| 773 | + assert snapshot.verification_state_summary == "failed for pytest -q" | |
| 772 | 774 | |
| 773 | 775 | assert len(sessions) == 1 |
| 774 | 776 | assert sessions[0].session_id == session_id |
| 775 | 777 | assert sessions[0].is_current is True |
| 776 | 778 | assert sessions[0].runtime_owner_type == "RuntimeHandle" |
| 777 | 779 | assert sessions[0].runtime_owner_path == "runtime-handle" |
| 780 | + assert sessions[0].runtime_boundary_summary == ( | |
| 781 | + "runtime-first via runtime-handle (RuntimeHandle)" | |
| 782 | + ) | |
| 778 | 783 | assert sessions[0].dod_status == "fixing" |
| 779 | 784 | assert sessions[0].permission_prompting_enabled is True |
| 780 | 785 | assert sessions[0].permission_rule_counts == {"allow": 1, "deny": 2, "ask": 1} |
@@ -799,6 +804,10 @@ def test_status_and_session_surfaces_reflect_persisted_state(temp_dir: Path) -> | ||
| 799 | 804 | assert detail.is_current is True |
| 800 | 805 | assert detail.snapshot.runtime_owner_type == "RuntimeHandle" |
| 801 | 806 | assert detail.snapshot.runtime_owner_path == "runtime-handle" |
| 807 | + assert detail.runtime_boundary_summary == ( | |
| 808 | + "runtime-first via runtime-handle (RuntimeHandle)" | |
| 809 | + ) | |
| 810 | + assert detail.verification_state_summary == "failed for pytest -q" | |
| 802 | 811 | assert detail.definition_of_done is not None |
| 803 | 812 | assert detail.definition_of_done.status == "fixing" |
| 804 | 813 | assert detail.snapshot.permission_rules_source == str( |
@@ -830,8 +839,12 @@ def test_collect_workflow_timeline_reflects_persisted_history(temp_dir: Path) -> | ||
| 830 | 839 | assert snapshot.is_current is True |
| 831 | 840 | assert snapshot.runtime_owner_type == "RuntimeHandle" |
| 832 | 841 | assert snapshot.runtime_owner_path == "runtime-handle" |
| 842 | + assert snapshot.runtime_boundary_summary == ( | |
| 843 | + "runtime-first via runtime-handle (RuntimeHandle)" | |
| 844 | + ) | |
| 833 | 845 | assert snapshot.workflow_mode == "execute" |
| 834 | 846 | assert snapshot.current_task == "Fix the failing tests" |
| 847 | + assert snapshot.verification_state_summary == "failed for pytest -q" | |
| 835 | 848 | assert snapshot.total_entries == 2 |
| 836 | 849 | assert [entry.kind for entry in snapshot.entries] == ["handoff", "reentry"] |
| 837 | 850 | assert snapshot.entries[-1].reason_code == "verification_failed_reentry" |
@@ -939,6 +952,9 @@ def test_collect_status_snapshot_surfaces_pending_verification( | ||
| 939 | 952 | "uv run pytest -q" |
| 940 | 953 | ] |
| 941 | 954 | assert [item.attempt for item in snapshot.recent_verification] == ["attempt 2"] |
| 955 | + assert snapshot.verification_state_summary == ( | |
| 956 | + "pending (attempt 2) for uv run pytest -q" | |
| 957 | + ) | |
| 942 | 958 | |
| 943 | 959 | |
| 944 | 960 | def test_collect_status_snapshot_surfaces_planned_verification( |
@@ -964,6 +980,9 @@ def test_collect_status_snapshot_surfaces_planned_verification( | ||
| 964 | 980 | assert [item.detail for item in snapshot.recent_verification] == [ |
| 965 | 981 | "write changed src/loader/runtime/tool_batches.py" |
| 966 | 982 | ] |
| 983 | + assert snapshot.verification_state_summary == ( | |
| 984 | + "planned (attempt 3) for uv run pytest -q" | |
| 985 | + ) | |
| 967 | 986 | |
| 968 | 987 | |
| 969 | 988 | def test_collect_status_snapshot_surfaces_stale_verification( |
@@ -991,6 +1010,9 @@ def test_collect_status_snapshot_surfaces_stale_verification( | ||
| 991 | 1010 | assert [item.detail for item in snapshot.recent_verification] == [ |
| 992 | 1011 | "write changed src/loader/runtime/finalization.py" |
| 993 | 1012 | ] |
| 1013 | + assert snapshot.verification_state_summary == ( | |
| 1014 | + "stale (attempt 1 -> attempt 2) for uv run pytest -q" | |
| 1015 | + ) | |
| 994 | 1016 | |
| 995 | 1017 | |
| 996 | 1018 | def test_collect_prompt_diff_uses_persisted_prompt_history(temp_dir: Path) -> None: |
@@ -1051,7 +1073,9 @@ def test_status_and_session_commands_render_persisted_state( | ||
| 1051 | 1073 | assert session_id in status_result.output |
| 1052 | 1074 | assert "fixing" in status_result.output |
| 1053 | 1075 | assert "Runtime Owner" in status_result.output |
| 1076 | + assert "Boundary" in status_result.output | |
| 1054 | 1077 | assert "runtime-handle (RuntimeHandle)" in status_result.output |
| 1078 | + assert "runtime-first via runtime-handle (RuntimeHandle)" in status_result.output | |
| 1055 | 1079 | assert "1 allow / 2 deny / 1 ask" in status_result.output |
| 1056 | 1080 | assert "native" in status_result.output |
| 1057 | 1081 | assert "Runtime Config, Workflow Context, Mode Guidance" in status_result.output |
@@ -1066,11 +1090,15 @@ def test_status_and_session_commands_render_persisted_state( | ||
| 1066 | 1090 | assert "What file did you mention?" in status_result.output |
| 1067 | 1091 | assert "pytest -q" in status_result.output |
| 1068 | 1092 | assert "1 failed" in status_result.output |
| 1093 | + assert "Verification State" in status_result.output | |
| 1094 | + assert "failed for pytest -q" in status_result.output | |
| 1069 | 1095 | |
| 1070 | 1096 | assert list_result.exit_code == 0 |
| 1071 | 1097 | assert session_id in list_result.output |
| 1072 | 1098 | assert "Runtime Owner" in list_result.output |
| 1099 | + assert "Boundary" in list_result.output | |
| 1073 | 1100 | assert "runtime-handle (RuntimeHandle)" in list_result.output |
| 1101 | + assert "runtime-first via runtime-handle (RuntimeHandle)" in list_result.output | |
| 1074 | 1102 | assert "1 allow / 2 deny / 1 ask" in list_result.output |
| 1075 | 1103 | assert "prompting enabled" in list_result.output |
| 1076 | 1104 | assert "native" in list_result.output |
@@ -1082,7 +1110,9 @@ def test_status_and_session_commands_render_persisted_state( | ||
| 1082 | 1110 | assert show_result.exit_code == 0 |
| 1083 | 1111 | assert session_id in show_result.output |
| 1084 | 1112 | assert "Runtime Owner" in show_result.output |
| 1113 | + assert "Boundary" in show_result.output | |
| 1085 | 1114 | assert "runtime-handle (RuntimeHandle)" in show_result.output |
| 1115 | + assert "runtime-first via runtime-handle (RuntimeHandle)" in show_result.output | |
| 1086 | 1116 | assert "Patch the broken parser" in show_result.output |
| 1087 | 1117 | assert "1 allow / 2 deny / 1 ask" in show_result.output |
| 1088 | 1118 | assert "enabled" in show_result.output |
@@ -1092,6 +1122,8 @@ def test_status_and_session_commands_render_persisted_state( | ||
| 1092 | 1122 | assert "Completion Decision" in show_result.output |
| 1093 | 1123 | assert "Completion Trace" in show_result.output |
| 1094 | 1124 | assert "Recent Verification" in show_result.output |
| 1125 | + assert "Verification State" in show_result.output | |
| 1126 | + assert "failed for pytest -q" in show_result.output | |
| 1095 | 1127 | assert "continuation_check" in show_result.output |
| 1096 | 1128 | assert "completion -> finalize" in show_result.output |
| 1097 | 1129 | assert "Finalizing completed turn" in show_result.output |
@@ -1107,7 +1139,11 @@ def test_status_and_session_commands_render_persisted_state( | ||
| 1107 | 1139 | assert "Workflow Timeline" in workflow_result.output |
| 1108 | 1140 | assert session_id in workflow_result.output |
| 1109 | 1141 | assert "Runtime Owner" in workflow_result.output |
| 1142 | + assert "Boundary" in workflow_result.output | |
| 1110 | 1143 | assert "runtime-handle (RuntimeHandle)" in workflow_result.output |
| 1144 | + assert "runtime-first via runtime-handle (RuntimeHandle)" in workflow_result.output | |
| 1145 | + assert "Verification State" in workflow_result.output | |
| 1146 | + assert "failed for pytest -q" in workflow_result.output | |
| 1111 | 1147 | assert "handoff" in workflow_result.output |
| 1112 | 1148 | assert "next=verify" in workflow_result.output |
| 1113 | 1149 | |
@@ -1170,6 +1206,8 @@ def test_workflow_command_renders_stale_verification_context( | ||
| 1170 | 1206 | assert "verification_stale" in result.output |
| 1171 | 1207 | assert "policy-outcome=stale" in result.output |
| 1172 | 1208 | assert "Observed Verification" in result.output |
| 1209 | + assert "Verification State" in result.output | |
| 1210 | + assert "stale (attempt 1 -> attempt 2) for uv run pytest -q" in result.output | |
| 1173 | 1211 | assert "uv run pytest -q" in result.output |
| 1174 | 1212 | assert "new mutating work" in result.output |
| 1175 | 1213 | |
@@ -1193,6 +1231,8 @@ def test_workflow_command_renders_planned_verification_context( | ||
| 1193 | 1231 | assert "verification_planned" in result.output |
| 1194 | 1232 | assert "policy-outcome=planned" in result.output |
| 1195 | 1233 | assert "Observed Verification" in result.output |
| 1234 | + assert "Verification State" in result.output | |
| 1235 | + assert "planned (attempt 3) for uv run pytest -q" in result.output | |
| 1196 | 1236 | assert "verification planned for `uv run pytest -q`" in result.output |
| 1197 | 1237 | assert "uv run pytest -q" in result.output |
| 1198 | 1238 | |