diff --git a/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_parse_history_entries.py b/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_parse_history_entries.py new file mode 100644 index 00000000..21956fea --- /dev/null +++ b/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_parse_history_entries.py @@ -0,0 +1,72 @@ +"""Fix parse_history_entries references in app_controller.py + gui_2.py. + +Phase 2.3 of the de-cruft track removed the __getattr__ lazy-load entries +from models.py. The migration scripts (migrate_imports.py, +migrate_models_attr.py) covered the 11 dataclasses but missed the 5 +config-IO functions. This script does the safe in-place substitution +of 'models.parse_history_entries' -> 'parse_history_entries' in the +2 affected files. + +The script adds 'parse_history_entries' to the existing +'from src.project import' line in app_controller.py (next to the +load_config_from_disk / save_config_to_disk imports added by the +prior commit de9dd3c1). It also adds a new +'from src.project import parse_history_entries' line in gui_2.py +(gui_2.py didn't import from src.project before). + +Idempotent: running the script twice does the same work (the 'from +src.project import' line is replaced with the same line, the +'models.parse_history_entries' is replaced with the bare name). +""" +from __future__ import annotations + +import re +import sys +from pathlib import Path + + +def migrate(path: Path, import_line: str) -> int: + content = path.read_text(encoding="utf-8") + original = content + count = content.count("models.parse_history_entries") + if count == 0: + return 0 + content = content.replace("models.parse_history_entries", "parse_history_entries") + has_import = bool(re.search(r"^from src\.project import ", content, re.MULTILINE)) + if not has_import: + content = re.sub( + r"^(from __future__ import annotations\n)", + rf"\1{import_line}\n", + content, + count=1, + ) + else: + content = re.sub( + r"^(from src\.project import [^\n]+)$", + r"\1, parse_history_entries", + content, + count=1, + flags=re.MULTILINE, + ) + path.write_text(content, encoding="utf-8", newline="") + return count + + +def main() -> int: + total = 0 + files = { + "src/app_controller.py": "from src.project import load_config_from_disk, parse_history_entries, save_config_to_disk", + "src/gui_2.py": "from src.project import parse_history_entries", + } + for rel, import_line in files.items(): + path = Path(rel) + n = migrate(path, import_line) + if n > 0: + print(f" {rel}: replaced {n} 'models.parse_history_entries' reference(s)") + total += n + print(f"\nTotal: {total} reference(s) replaced") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/app_controller.py b/src/app_controller.py index 3920ea24..95e8a2e2 100644 --- a/src/app_controller.py +++ b/src/app_controller.py @@ -4,7 +4,7 @@ from src.mma import Ticket, Track, TrackState from src.personas import Persona from src.mcp_client import MCPConfiguration, RAGConfig, load_mcp_config from src.project_files import ContextPreset, FileItem, NamedViewPreset, Preset -from src.project import load_config_from_disk, save_config_to_disk +from src.project import load_config_from_disk, save_config_to_disk, parse_history_entries from src.tool_bias import BiasProfile import copy @@ -2017,7 +2017,7 @@ class AppController: self.active_discussion = disc_sec.get("active", "main") disc_data = disc_sec.get("discussions", {}).get(self.active_discussion, {}) - with self._disc_entries_lock: self.disc_entries[:] = models.parse_history_entries(disc_data.get("history", []), self.disc_roles) + with self._disc_entries_lock: self.disc_entries[:] = parse_history_entries(disc_data.get("history", []), self.disc_roles) # UI state self.ui_output_dir = self.project.get("output", {}).get("output_dir", "./md_gen") @@ -3261,7 +3261,7 @@ class AppController: self.active_discussion = disc_sec.get("active", "main") disc_data = disc_sec.get("discussions", {}).get(self.active_discussion, {}) with self._disc_entries_lock: - self.disc_entries[:] = models.parse_history_entries(disc_data.get("history", []), self.disc_roles) + self.disc_entries[:] = parse_history_entries(disc_data.get("history", []), self.disc_roles) proj = self.project self.ui_output_dir = proj.get("output", {}).get("output_dir", "./md_gen") self.ui_files_base_dir = proj.get("files", {}).get("base_dir", ".") @@ -3308,7 +3308,7 @@ class AppController: track_history = project_manager.load_track_history(self.active_track.id, self.active_project_root) if track_history: with self._disc_entries_lock: - self.disc_entries[:] = models.parse_history_entries(track_history, self.disc_roles) + self.disc_entries[:] = parse_history_entries(track_history, self.disc_roles) self.preset_manager.project_root = Path(self.active_project_root) self.presets = self.preset_manager.load_all() self.tool_preset_manager.project_root = Path(self.active_project_root) @@ -3778,7 +3778,7 @@ class AppController: disc_sec["active"] = name disc_data = discussions[name] with self._disc_entries_lock: - self.disc_entries[:] = models.parse_history_entries(disc_data.get("history", []), self.disc_roles) + self.disc_entries[:] = parse_history_entries(disc_data.get("history", []), self.disc_roles) self.discussion_sent_markdown = disc_data.get("sent_markdown", "") self.discussion_sent_system_prompt = disc_data.get("sent_system_prompt", "") if "context_snapshot" in disc_data: @@ -5052,7 +5052,7 @@ class AppController: history = project_manager.load_track_history(track_id, self.active_project_root) with self._disc_entries_lock: if history: - self.disc_entries[:] = models.parse_history_entries(history, self.disc_roles) + self.disc_entries[:] = parse_history_entries(history, self.disc_roles) else: self.disc_entries.clear() self._recalculate_session_usage() diff --git a/src/gui_2.py b/src/gui_2.py index bd1b1769..478c690c 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -5489,7 +5489,7 @@ def render_discussion_selector(app: App) -> None: if app._track_discussion_active: app._flush_disc_entries_to_project() history_strings = project_manager.load_track_history(app.active_track.id, app.active_project_root) - with app._disc_entries_lock: app.disc_entries = models.parse_history_entries(history_strings, app.disc_roles) + with app._disc_entries_lock: app.disc_entries = parse_history_entries(history_strings, app.disc_roles) app.ai_status = f"track discussion: {app.active_track.id}" else: app._flush_disc_entries_to_project(); app._switch_discussion(app.active_discussion); app.ai_status = "track discussion disabled" render_discussion_metadata(app)