diff --git a/src/operator_control_center.py b/src/operator_control_center.py index 087393e..7272240 100644 --- a/src/operator_control_center.py +++ b/src/operator_control_center.py @@ -590,6 +590,7 @@ def build_operator_snapshot( ), evidence_events=evidence_bundle.get("events") or [], ) + queue = _operator_resolution_trend._attach_portfolio_catalog_context(queue, report_data) resolution_trend = _operator_resolution_trend._build_resolution_trend( queue, history, @@ -612,7 +613,6 @@ def build_operator_snapshot( resolution_trend=resolution_trend, current_generated_at=report_data.get("generated_at", ""), ) - queue = _operator_resolution_trend._attach_portfolio_catalog_context(queue, report_data) from src.action_sync_automation import build_action_sync_automation_bundle from src.action_sync_outcomes import load_action_sync_outcomes_bundle from src.action_sync_packets import build_action_sync_packets_bundle diff --git a/src/operator_follow_through.py b/src/operator_follow_through.py index 0d2cb5a..4cfd194 100644 --- a/src/operator_follow_through.py +++ b/src/operator_follow_through.py @@ -557,6 +557,7 @@ def _build_follow_through_with_queue(resolution_trend: dict, queue: list[dict]) status_counts["resolved"] += resolution_trend.get("confirmed_resolved_count", 0) follow_through_checkpoint_summary = _follow_through_checkpoint_summary( status_counts, + checkpoint_counts, top_unattempted_items, top_stale_follow_through_items, ) @@ -820,6 +821,7 @@ def _project_queue_follow_through( if (snapshot.get("items", {}).get(key) or {}).get("lane") in ATTENTION_LANES ) follow_through_age_runs = appearance_count + quiet_maintain_monitor = _is_quiet_maintain_monitor(item) follow_through_status = _queue_item_follow_through_status( item, memory, @@ -848,6 +850,7 @@ def _project_queue_follow_through( follow_through_status=follow_through_status, follow_through_checkpoint_status=follow_through_checkpoint_status, follow_through_age_runs=follow_through_age_runs, + quiet_maintain_monitor=quiet_maintain_monitor, ) follow_through_escalation_reason = _follow_through_escalation_reason( item, @@ -1037,6 +1040,60 @@ def _project_queue_follow_through( follow_through_recovery_freshness_status=follow_through_recovery_freshness_status, follow_through_recovery_decay_status=follow_through_recovery_decay_status, ) + if quiet_maintain_monitor: + neutral_recovery_reason = ( + f"{_target_label(item)} is an aligned on-track maintain monitor, " + "so no recovery follow-through is needed." + ) + neutral_recovery_summary = ( + f"{_target_label(item)} is already quiet under the maintain contract." + ) + follow_through_recovery_age_runs = 0 + follow_through_recovery_status = "none" + follow_through_recovery_reason = neutral_recovery_reason + follow_through_recovery_summary = neutral_recovery_summary + follow_through_recovery_persistence_age_runs = 0 + follow_through_recovery_persistence_status = "none" + follow_through_recovery_persistence_reason = neutral_recovery_reason + follow_through_recovery_persistence_summary = neutral_recovery_summary + follow_through_relapse_churn_status = "none" + follow_through_relapse_churn_reason = neutral_recovery_reason + follow_through_relapse_churn_summary = neutral_recovery_summary + follow_through_recovery_freshness_age_runs = 0 + follow_through_recovery_freshness_status = "none" + follow_through_recovery_freshness_reason = neutral_recovery_reason + follow_through_recovery_freshness_summary = neutral_recovery_summary + follow_through_recovery_decay_status = "none" + follow_through_recovery_decay_reason = neutral_recovery_reason + follow_through_recovery_decay_summary = neutral_recovery_summary + follow_through_recovery_memory_reset_status = "none" + follow_through_recovery_memory_reset_reason = neutral_recovery_reason + follow_through_recovery_memory_reset_summary = neutral_recovery_summary + follow_through_recovery_rebuild_strength_age_runs = 0 + follow_through_recovery_rebuild_strength_status = "none" + follow_through_recovery_rebuild_strength_reason = neutral_recovery_reason + follow_through_recovery_rebuild_strength_summary = neutral_recovery_summary + follow_through_recovery_reacquisition_status = "none" + follow_through_recovery_reacquisition_reason = neutral_recovery_reason + follow_through_recovery_reacquisition_summary = neutral_recovery_summary + follow_through_recovery_reacquisition_durability_age_runs = 0 + follow_through_recovery_reacquisition_durability_status = "none" + follow_through_recovery_reacquisition_durability_reason = neutral_recovery_reason + follow_through_recovery_reacquisition_durability_summary = neutral_recovery_summary + follow_through_recovery_reacquisition_consolidation_status = "none" + follow_through_recovery_reacquisition_consolidation_reason = neutral_recovery_reason + follow_through_recovery_reacquisition_consolidation_summary = neutral_recovery_summary + follow_through_reacquisition_softening_decay_age_runs = 0 + follow_through_reacquisition_softening_decay_status = "none" + follow_through_reacquisition_softening_decay_reason = neutral_recovery_reason + follow_through_reacquisition_softening_decay_summary = neutral_recovery_summary + follow_through_reacquisition_confidence_retirement_status = "none" + follow_through_reacquisition_confidence_retirement_reason = neutral_recovery_reason + follow_through_reacquisition_confidence_retirement_summary = neutral_recovery_summary + follow_through_reacquisition_revalidation_recovery_age_runs = 0 + follow_through_reacquisition_revalidation_recovery_status = "none" + follow_through_reacquisition_revalidation_recovery_reason = neutral_recovery_reason + follow_through_reacquisition_revalidation_recovery_summary = neutral_recovery_summary follow_through_summary = _follow_through_item_summary( item, memory, @@ -1135,6 +1192,8 @@ def _queue_item_follow_through_status( ) if not item.get("source_run_id") and not has_intervention and not previous_match: return "unknown" + if _is_quiet_maintain_monitor(item): + return "resolved" if has_intervention and ( lane == "deferred" or ( @@ -1163,6 +1222,29 @@ def _queue_item_follow_through_status( return "unknown" +def _is_quiet_maintain_monitor(item: dict) -> bool: + if item.get("lane") != "deferred": + return False + raw_catalog_entry = item.get("portfolio_catalog") + catalog_entry = raw_catalog_entry if isinstance(raw_catalog_entry, dict) else {} + raw_scorecard = item.get("scorecard") + scorecard = raw_scorecard if isinstance(raw_scorecard, dict) else {} + if not scorecard: + raw_catalog_scorecard = catalog_entry.get("scorecard") + scorecard = raw_catalog_scorecard if isinstance(raw_catalog_scorecard, dict) else {} + summary = str(item.get("summary") or "").lower() + material_change_text = "material changes" in summary and "no material changes" not in summary + return ( + str(item.get("intent_alignment") or catalog_entry.get("intent_alignment") or "").lower() + == "aligned" + and str(catalog_entry.get("intended_disposition") or "").lower() == "maintain" + and str(scorecard.get("status") or "").lower() == "on-track" + and not scorecard.get("failed_rule_keys") + and not scorecard.get("top_gaps") + and not material_change_text + ) + + def _has_follow_through_intervention(event: dict | None) -> bool: if not event: return False @@ -1218,6 +1300,8 @@ def _follow_through_next_checkpoint( follow_through_status: str, ) -> str: recommended_action = item.get("recommended_action") or "Review the latest state." + if _is_quiet_maintain_monitor(item): + return "No stronger follow-through needed while the maintain scorecard stays on track and no material changes surface." if follow_through_status == "untouched": return f"Take the recommended action next and record a visible follow-up after: {recommended_action}" if follow_through_status == "attempted": @@ -1267,9 +1351,12 @@ def _follow_through_escalation_status( follow_through_status: str, follow_through_checkpoint_status: str, follow_through_age_runs: int, + quiet_maintain_monitor: bool = False, ) -> str: if follow_through_status == "unknown": return "unknown" + if quiet_maintain_monitor: + return "none" if follow_through_status == "resolved": return "none" if follow_through_age_runs <= 1 else "resolved-watch" if ( @@ -3346,6 +3433,23 @@ def _follow_through_summary( return f"{status_counts.get('waiting-on-evidence', 0)} item(s) have recent follow-up recorded and are now waiting for later evidence to confirm movement." if status_counts.get("attempted", 0): return f"{status_counts.get('attempted', 0)} item(s) show recorded follow-up, but the underlying pressure is still visible in the current queue." + if ( + checkpoint_counts.get("satisfied", 0) + and not checkpoint_counts.get("due-soon", 0) + and not checkpoint_counts.get("overdue", 0) + and not escalation_counts.get("watch", 0) + and not escalation_counts.get("nudge", 0) + and not escalation_counts.get("escalate-now", 0) + and not escalation_counts.get("resolved-watch", 0) + and not recovery_counts.get("recovering", 0) + and not recovery_counts.get("retiring-watch", 0) + and not recovery_counts.get("relapsing", 0) + and not recovery_freshness_counts.get("fresh", 0) + and not recovery_freshness_counts.get("holding-fresh", 0) + and not recovery_freshness_counts.get("mixed-age", 0) + and not recovery_freshness_counts.get("stale", 0) + ): + return "The current operator queue is quiet; maintain monitors can stay deferred while their scorecards remain on track." if status_counts.get("resolved", 0): return f"{status_counts.get('resolved', 0)} item(s) now look calmer or resolved after recent follow-through, but they still need one more confirming read before they fully disappear from memory." if legacy_summary: @@ -3359,6 +3463,7 @@ def _follow_through_summary( def _follow_through_checkpoint_summary( status_counts: dict[str, int], + checkpoint_counts: dict[str, int], top_unattempted_items: list[dict], top_stale_follow_through_items: list[dict], ) -> str: @@ -3374,6 +3479,12 @@ def _follow_through_checkpoint_summary( return "Recent follow-up is in flight, so the next checkpoint is whether the next run confirms quieter pressure." if status_counts.get("attempted", 0): return "Follow-up is recorded, but the next checkpoint is whether the pressure actually drops on the next run." + if ( + checkpoint_counts.get("satisfied", 0) + and not checkpoint_counts.get("due-soon", 0) + and not checkpoint_counts.get("overdue", 0) + ): + return "No stronger follow-through checkpoint is needed while the current queue stays satisfied." if status_counts.get("resolved", 0): return "Some items already look calmer, so the next checkpoint is whether that calmer state holds for another run." return "Use the next run or linked artifact to confirm whether the current recommendation actually moved." diff --git a/tests/test_operator_control_center.py b/tests/test_operator_control_center.py index a2247c5..7ff4a05 100644 --- a/tests/test_operator_control_center.py +++ b/tests/test_operator_control_center.py @@ -1306,6 +1306,67 @@ def test_project_queue_follow_through_marks_overdue_untouched_items_for_escalati assert "resurfaced now" in item["follow_through_escalation_summary"] +def test_project_queue_follow_through_keeps_aligned_on_track_maintain_items_quiet(): + queue = [ + { + "item_id": "review-target:RepoD:No material changes crossed the current threshold.", + "lane": "deferred", + "age_days": 0, + "repo": "RepoD", + "title": "Review RepoD", + "summary": "No material changes crossed the current threshold.", + "recommended_action": "Safe to defer.", + "source_run_id": "testuser:2026-03-29T12:00:00+00:00", + "intent_alignment": "aligned", + "portfolio_catalog": { + "intended_disposition": "maintain", + "intent_alignment": "aligned", + }, + "scorecard": { + "status": "on-track", + "failed_rule_keys": [], + "top_gaps": [], + }, + } + ] + key = operator_control_center._queue_identity(queue[0]) + recent_runs = [ + {"items": {key: queue[0]}, "has_attention": False}, + {"items": {key: {"lane": "deferred", "age_days": 0}}, "has_attention": False}, + {"items": {key: {"lane": "deferred", "age_days": 0}}, "has_attention": False}, + {"items": {key: {"lane": "deferred", "age_days": 0}}, "has_attention": False}, + {"items": {key: {"lane": "deferred", "age_days": 0}}, "has_attention": False}, + ] + + enriched = operator_follow_through._project_queue_follow_through( + queue, + recent_runs=recent_runs, + resolution_trend={"decision_memory_map": {}}, + current_generated_at="2026-03-29T12:00:00+00:00", + ) + + item = enriched[0] + assert item["follow_through_status"] == "resolved" + assert item["follow_through_checkpoint_status"] == "satisfied" + assert item["follow_through_escalation_status"] == "none" + assert item["follow_through_recovery_status"] == "none" + assert item["follow_through_recovery_freshness_status"] == "none" + assert item["follow_through_recovery_reacquisition_status"] == "none" + assert "No stronger follow-through needed" in item["follow_through_next_checkpoint"] + assert "stale" not in item["follow_through_summary"] + + follow_through = operator_follow_through._build_follow_through_with_queue( + {"confirmed_resolved_count": 182, "quiet_streak_runs": 5}, + enriched, + ) + + assert "current operator queue is quiet" in follow_through["follow_through_summary"] + assert "182 item" not in follow_through["follow_through_summary"] + assert "No stronger follow-through checkpoint" in follow_through[ + "follow_through_checkpoint_summary" + ] + + def test_project_queue_follow_through_keeps_recent_waiting_items_on_watch(): queue = [ {