gabriel / muse public
feat BREAKING harmony task/harmony-phase4 #1 / 1
AI Agent gabriel · 162 days ago · Apr 17, 2026 · Diff

feat(harmony): Phase 4 — Escalation Records + operator dashboard

- harmony.py: EscalationStatus (OPEN/RESOLVED), AuditEventType.ESCALATION_RESOLVED, EscalationRecord (frozen dataclass), _EscalationDict wire-format, compute_escalation_id (deterministic SHA-256(pattern_id:reason)), escalations_dir, record_escalation (atomic+idempotent), load_escalation, list_escalations (status filter, newest-first, symlink-safe, size-capped), resolve_escalation (OPEN→RESOLVED atomic update) - harmony.py CLI: _HarmonyEscalateJson, _HarmonyEscalationEntryJson, _HarmonyEscalationsJson, _HarmonyResolveEscalationJson TypedDicts; escalate / escalations / resolve-escalation subcommands; engine --auto-escalate flag (auto-records on Tier 4 trigger) - 482/482 tests green (Phases 1–4)

sha256:15f45fc12a3a99673d091797077c30b1ff75ecce7a6b1de4a1e2f6c90cc33622 sha
+218 ~32 symbols
sha256:e88c2f3c4e2647e214ae159b663a8286ce7ffa2dab89034182175a4590daa8a7 snapshot
+218
symbols added
~32
symbols modified
0
dead code introduced
Semantic Changes 250 symbols
~ tests/test_harmony_cli_phase4.py .py 82 symbols added
+ TestDataIntegrity class class TestDataIntegrity L476–517
+ test_escalate_all_fields_present method method test_escalate_all_fields_present L479–484
+ test_escalation_id_is_hex64 method method test_escalation_id_is_hex64 L495–500
+ test_escalations_empty_list_not_null method method test_escalations_empty_list_not_null L514–517
+ test_escalations_entry_all_fields_present method method test_escalations_entry_all_fields_present L486–493
+ test_resolve_escalation_all_fields_present method method test_resolve_escalation_all_fields_present L502–512
+ TestEndToEnd class class TestEndToEnd L407–468
+ test_engine_auto_escalate_then_resolve method method test_engine_auto_escalate_then_resolve L437–451
+ test_escalate_resolve_escalation_audit method method test_escalate_resolve_escalation_audit L410–435
+ test_multiple_escalate_filter_independently method method test_multiple_escalate_filter_independently L453–468
+ TestEngineAutoEscalate class class TestEngineAutoEscalate L328–358
+ test_auto_escalate_creates_record method method test_auto_escalate_creates_record L331–336
+ test_auto_escalate_only_on_escalated method method test_auto_escalate_only_on_escalated L338–344
+ test_auto_escalate_pattern_id_in_record method method test_auto_escalate_pattern_id_in_record L346–351
+ test_engine_without_flag_no_escalation_record method method test_engine_without_flag_no_escalation_record L353–358
+ TestEscalateErrors class class TestEscalateErrors L366–375
+ test_invalid_id_exits_1 method method test_invalid_id_exits_1 L369–371
+ test_traversal_id_exits_1 method method test_traversal_id_exits_1 L373–375
+ TestEscalateSuccess class class TestEscalateSuccess L159–226
+ test_escalate_already_existed_false_on_first method method test_escalate_already_existed_false_on_first L176–179
+ test_escalate_custom_reason method method test_escalate_custom_reason L196–204
+ test_escalate_idempotent_already_existed_true method method test_escalate_idempotent_already_existed_true L181–186
+ test_escalate_returns_escalation_id method method test_escalate_returns_escalation_id L162–168
+ test_escalate_returns_pattern_id method method test_escalate_returns_pattern_id L170–174
+ test_escalate_same_id_both_calls method method test_escalate_same_id_both_calls L188–194
+ test_escalate_text_output method method test_escalate_text_output L206–210
+ test_escalate_unknown_pattern_still_works method method test_escalate_unknown_pattern_still_works L212–217
+ test_escalate_with_agent_id method method test_escalate_with_agent_id L219–226
+ TestEscalationsSuccess class class TestEscalationsSuccess L229–279
+ test_empty_store_returns_zero method method test_empty_store_returns_zero L232–237
+ test_filter_open method method test_filter_open L248–262
+ test_filter_resolved method method test_filter_resolved L264–273
+ test_lists_all_by_default method method test_lists_all_by_default L239–246
+ test_text_output method method test_text_output L275–279
+ TestPerformance class class TestPerformance L557–583
+ test_escalate_under_300ms method method test_escalate_under_300ms L560–565
+ test_escalations_under_300ms method method test_escalations_under_300ms L567–571
+ test_resolve_escalation_under_300ms method method test_resolve_escalation_under_300ms L573–583
+ TestRegistration class class TestRegistration L138–151
+ test_escalate_help method method test_escalate_help L141–143
+ test_escalations_help method method test_escalations_help L145–147
+ test_resolve_escalation_help method method test_resolve_escalation_help L149–151
+ TestResolveEscalationErrors class class TestResolveEscalationErrors L378–399
+ test_invalid_escalation_id_exits_1 method method test_invalid_escalation_id_exits_1 L381–386
+ test_invalid_resolution_id_exits_1 method method test_invalid_resolution_id_exits_1 L388–394
+ test_missing_resolution_id_flag_exits_non_zero method method test_missing_resolution_id_flag_exits_non_zero L396–399
+ TestResolveEscalationSuccess class class TestResolveEscalationSuccess L282–325
+ test_resolve_escalation_id_in_response method method test_resolve_escalation_id_in_response L297–305
+ test_resolved_false_when_not_found method method test_resolved_false_when_not_found L307–315
+ test_resolved_true_when_found method method test_resolved_true_when_found L285–295
+ test_text_output method method test_text_output L317–325
+ TestSecurity class class TestSecurity L525–549
+ test_escalate_null_byte_rejected method method test_escalate_null_byte_rejected L532–534
+ test_escalate_traversal_rejected method method test_escalate_traversal_rejected L528–530
+ test_resolve_escalation_traversal_eid method method test_resolve_escalation_traversal_eid L536–541
+ test_resolve_escalation_traversal_res_id method method test_resolve_escalation_traversal_res_id L543–549
+ TestTypedDictSchemas class class TestTypedDictSchemas L99–135
+ _hints method method _hints L102–105
+ test_escalate_json_has_already_existed method method test_escalate_json_has_already_existed L113–114
+ test_escalate_json_has_escalation_id method method test_escalate_json_has_escalation_id L107–108
+ test_escalate_json_has_pattern_id method method test_escalate_json_has_pattern_id L110–111
+ test_escalation_entry_has_escalation_id method method test_escalation_entry_has_escalation_id L119–120
+ test_escalation_entry_has_pattern_id method method test_escalation_entry_has_pattern_id L122–123
+ test_escalation_entry_has_status method method test_escalation_entry_has_status L116–117
+ test_escalations_json_has_escalations method method test_escalations_json_has_escalations L128–129
+ test_escalations_json_has_total method method test_escalations_json_has_total L125–126
+ test_resolve_escalation_json_has_escalation_id method method test_resolve_escalation_json_has_escalation_id L131–132
+ test_resolve_escalation_json_has_resolved method method test_resolve_escalation_json_has_resolved L134–135
+ _escalate function function _escalate L84–91
+ _fake_id function function _fake_id L39–40
+ _record_pattern function function _record_pattern L52–68
+ _save_resolution function function _save_resolution L71–81
+ CliRunner import import CliRunner L29–29
+ annotations import import annotations L19–19
+ hashlib import import hashlib L21–21
+ json import import json L22–22
+ pathlib import import pathlib L23–23
+ pytest import import pytest L27–27
+ time import import time L24–24
+ typing import import typing L25–25
+ repo function function repo L44–49
+ runner variable variable runner L31–31
~ tests/test_harmony_phase4.py .py 108 symbols added
+ TestAuditEventTypeEscalationResolved class class TestAuditEventTypeEscalationResolved L116–123
+ test_escalation_recorded_still_present method method test_escalation_recorded_still_present L122–123
+ test_escalation_resolved_constant method method test_escalation_resolved_constant L119–120
+ TestComputeEscalationId class class TestComputeEscalationId L163–184
+ test_deterministic_same_inputs method method test_deterministic_same_inputs L166–170
+ test_different_pattern_ids_differ method method test_different_pattern_ids_differ L172–175
+ test_different_reasons_differ method method test_different_reasons_differ L177–179
+ test_returns_hex64 method method test_returns_hex64 L181–184
+ TestDataIntegrity class class TestDataIntegrity L536–585
+ test_escalated_at_is_utc_aware method method test_escalated_at_is_utc_aware L580–585
+ test_escalation_record_is_frozen method method test_escalation_record_is_frozen L568–572
+ test_json_round_trip_open method method test_json_round_trip_open L539–550
+ test_json_round_trip_resolved method method test_json_round_trip_resolved L552–566
+ test_no_temp_files_in_escalations_dir method method test_no_temp_files_in_escalations_dir L574–578
+ TestEndToEnd class class TestEndToEnd L432–492
+ test_escalate_list_resolve_audit method method test_escalate_list_resolve_audit L435–474
+ test_multiple_patterns_independent_escalations method method test_multiple_patterns_independent_escalations L476–492
+ TestEscalationRecordFields class class TestEscalationRecordFields L126–160
+ test_frozen method method test_frozen L154–157
+ test_is_dataclass class method test_is_dataclass L159–160
+ test_optional_fields_default_none method method test_optional_fields_default_none L148–152
+ test_required_fields_present method method test_required_fields_present L129–142
+ test_status_defaults_to_open method method test_status_defaults_to_open L144–146
+ TestEscalationStatusConstants class class TestEscalationStatusConstants L102–113
+ test_constants_are_strings method method test_constants_are_strings L111–113
+ test_open_value method method test_open_value L105–106
+ test_resolved_value method method test_resolved_value L108–109
+ TestEscalationsDir class class TestEscalationsDir L192–201
+ test_does_not_create_dir method method test_does_not_create_dir L199–201
+ test_path_structure method method test_path_structure L195–197
+ TestListEscalations class class TestListEscalations L287–343
+ test_empty_store_returns_empty method method test_empty_store_returns_empty L290–291
+ test_filter_open_only method method test_filter_open_only L299–311
+ test_filter_resolved_only method method test_filter_resolved_only L313–325
+ test_returns_all_by_default method method test_returns_all_by_default L293–297
+ test_skips_symlinks method method test_skips_symlinks L336–343
+ test_sorted_newest_first method method test_sorted_newest_first L327–334
+ TestLoadEscalation class class TestLoadEscalation L251–284
+ test_escalated_by_agent_round_trips method method test_escalated_by_agent_round_trips L275–280
+ test_escalated_by_human_round_trips method method test_escalated_by_human_round_trips L268–273
+ test_returns_none_for_missing method method test_returns_none_for_missing L254–256
+ test_round_trips_required_fields method method test_round_trips_required_fields L258–266
+ test_validates_id_rejects_traversal method method test_validates_id_rejects_traversal L282–284
+ TestPerformance class class TestPerformance L654–694
+ test_compute_escalation_id_under_1ms method method test_compute_escalation_id_under_1ms L689–694
+ test_list_100_escalations_under_50ms method method test_list_100_escalations_under_50ms L681–687
+ test_load_escalation_under_50ms method method test_load_escalation_under_50ms L664–670
+ test_record_escalation_under_50ms method method test_record_escalation_under_50ms L657–662
+ test_resolve_escalation_under_50ms method method test_resolve_escalation_under_50ms L672–679
+ TestRecordEscalation class class TestRecordEscalation L204–248
+ test_atomic_write_no_temp_files method method test_atomic_write_no_temp_files L243–248
+ test_creates_escalation_file method method test_creates_escalation_file L207–211
+ test_idempotent_returns_false_on_second_write method method test_idempotent_returns_false_on_second_write L220–225
+ test_idempotent_second_write_no_error method method test_idempotent_second_write_no_error L213–218
+ test_json_contains_expected_keys method method test_json_contains_expected_keys L227–234
+ test_status_stored_as_open method method test_status_stored_as_open L236–241
+ TestResolveEscalation class class TestResolveEscalation L346–424
+ test_no_temp_files_after_resolve method method test_no_temp_files_after_resolve L416–424
+ test_resolution_id_stored method method test_resolution_id_stored L377–387
+ test_resolved_at_stored method method test_resolved_at_stored L399–407
+ test_resolved_by_stored method method test_resolved_by_stored L389–397
+ test_returns_false_when_not_found method method test_returns_false_when_not_found L358–364
+ test_returns_true_when_found method method test_returns_true_when_found L349–356
+ test_status_updated_to_resolved method method test_status_updated_to_resolved L366–375
+ test_validates_escalation_id method method test_validates_escalation_id L409–414
+ TestSecurity class class TestSecurity L593–646
+ test_list_skips_non_json_files method method test_list_skips_non_json_files L619–626
+ test_load_null_byte_rejected method method test_load_null_byte_rejected L607–609
+ test_load_too_short_rejected method method test_load_too_short_rejected L611–613
+ test_load_traversal_rejected method method test_load_traversal_rejected L596–598
+ test_load_uppercase_hex_rejected method method test_load_uppercase_hex_rejected L615–617
+ test_oversized_escalation_file_skipped method method test_oversized_escalation_file_skipped L628–637
+ test_resolve_traversal_rejected method method test_resolve_traversal_rejected L600–605
+ test_symlinks_in_escalations_dir_skipped method method test_symlinks_in_escalations_dir_skipped L639–646
+ TestStress class class TestStress L500–528
+ test_concurrent_record_same_id_idempotent method method test_concurrent_record_same_id_idempotent L510–528
+ test_list_200_escalations method method test_list_200_escalations L503–508
+ _fake_id function function _fake_id L65–66
+ _make_record function function _make_record L79–94
+ _utc_now function function _utc_now L69–70
+ AgentProvenance import import AgentProvenance L39–39
+ AuditEventType import import AuditEventType L39–39
+ EscalationRecord import import EscalationRecord L39–39
+ EscalationStatus import import EscalationStatus L39–39
+ Resolution import import Resolution L39–39
+ annotations import import annotations L26–26
+ append_audit import import append_audit L39–39
+ blob_fingerprint import import blob_fingerprint L39–39
+ compute_escalation_id import import compute_escalation_id L39–39
+ compute_pattern_id import import compute_pattern_id L39–39
+ compute_resolution_id import import compute_resolution_id L39–39
+ futures import import concurrent.futures L28–28
+ dataclasses class import dataclasses L29–29
+ datetime import import datetime L30–30
+ escalations_dir import import escalations_dir L39–39
+ h import import h L38–38
+ hashlib import import hashlib L31–31
+ json import import json L32–32
+ list_audit import import list_audit L39–39
+ list_escalations import import list_escalations L39–39
+ load_escalation import import load_escalation L39–39
+ pathlib import import pathlib L33–33
+ pytest import import pytest L36–36
+ record_escalation import import record_escalation L39–39
+ resolve_escalation import import resolve_escalation L39–39
+ save_resolution import import save_resolution L39–39
+ time import import time L34–34
+ repo function function repo L74–76
~ muse/cli/commands/harmony.py .py 15 symbols added, 31 symbols modified
+ _HarmonyEscalateJson class class _HarmonyEscalateJson L346–351
+ _HarmonyEscalationEntryJson class class _HarmonyEscalationEntryJson L354–365
+ _HarmonyEscalationsJson class class _HarmonyEscalationsJson L368–372
+ _HarmonyResolveEscalationJson class class _HarmonyResolveEscalationJson L375–379
+ _escalation_to_entry function function _escalation_to_entry L2077–2088
+ EscalationRecord import import EscalationRecord L153–153
+ EscalationStatus import import EscalationStatus L153–153
+ compute_escalation_id import import compute_escalation_id L153–153
+ list_escalations import import list_escalations L153–153
+ load_escalation import import load_escalation L153–153
+ record_escalation import import record_escalation L153–153
+ resolve_escalation import import resolve_escalation L153–153
+ run_escalate function function run_escalate L2091–2161
+ run_escalations function function run_escalations L2169–2208
+ run_resolve_escalation function function run_resolve_escalation L2216–2275
~ Policy
~ muse/core/harmony.py .py 13 symbols added, 1 symbol modified
+ EscalationRecord class class EscalationRecord L437–463
+ EscalationStatus class class EscalationStatus L238–246
+ _ESCALATIONS variable variable _ESCALATIONS L106–106
+ _EscalationDict class class _EscalationDict L532–541
+ _MAX_ESCALATION_BYTES variable variable _MAX_ESCALATION_BYTES L124–124
+ _dict_to_escalation function function _dict_to_escalation L1644–1676
+ _escalation_to_dict function function _escalation_to_dict L1630–1641
+ compute_escalation_id function function compute_escalation_id L1606–1622
+ escalations_dir function function escalations_dir L569–571
+ list_escalations function function list_escalations L1747–1792
+ load_escalation function function load_escalation L1714–1744
+ record_escalation function function record_escalation L1679–1711
+ resolve_escalation function function resolve_escalation L1795–1844
← Older Oldest on task/harmony-phase4
All commits
Newer → Latest on task/harmony-phase4

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:15f45fc12a3a99673d091797077c30b1ff75ecce7a6b1de4a1e2f6c90cc33622 --body "your comment"