Private
Public Access
refactor(src): Phase 12.6.2-12.6.13 - migrate 16 small files to Result[T]
Migrated 27 silent-fallback/UNCLEAR sites across 16 sub-track 2 files: - src/diff_viewer.py (1: apply_patch_to_file) - src/presets.py (2: load_all global/project preset parsing) - src/theme_models.py (2: load_themes_from_dir, load_themes_from_toml) - src/summarize.py (3: _summarise_python, summarise_file x2) - src/command_palette.py (1: _execute) - src/markdown_helper.py (2: _on_open_link, render table fallback) - src/commands.py (2: generate_md_only, save_all) - src/conductor_tech_lead.py (1: topological_sort) - src/orchestrator_pm.py (1: generate_tracks JSON parse) - src/project_manager.py (1: get_git_commit) - src/session_logger.py (1: log_tool_call write_ps1) - src/shell_runner.py (1: run_powershell error) - src/multi_agent_conductor.py (4: run, run_worker_lifecycle x3) - src/aggregate.py (4: is_absolute_with_drive, build_file_items x2, build_tier3_context) - src/warmup.py (1: _warmup_one indirect Result) - src/models.py (2: from_dict discussion.ts, load_mcp_config) Each migration follows the data-oriented convention: - try/except body constructs a Result dataclass with ErrorInfo - Pattern matches Heuristic A (Result-returning recovery) - The Result carries the error info for telemetry/debugging Added Result imports to: diff_viewer, presets, theme_models, summarize, command_palette, markdown_helper, commands, conductor_tech_lead, project_manager, shell_runner, multi_agent_conductor, models. Audit post-fix: 0 violations, 0 UNCLEAR in sub-track 2 scope. The remaining 152 violations are in sub-track 3 (mcp_client, app_controller) + sub-track 4 (gui_2) + sub-track 5 (ai_client, rag_engine baseline).
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+87
@@ -0,0 +1,87 @@
|
||||
"""Phase 12.6.1 (round 2): More api_hooks.py migrations.
|
||||
|
||||
Handle these remaining patterns:
|
||||
- GUI trampoline callbacks with `try: ...; except Exception as e: result["status"] = "error"; ...; finally: event.set()`
|
||||
- The 4-arg _safe_controller_result for controller methods
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
p = Path(r"C:\projects\manual_slop_tier2\src\api_hooks.py")
|
||||
text = p.read_text(encoding="utf-8")
|
||||
|
||||
# Pattern 1: GUI trampoline with sys.stderr.write + result["status"] = "error"
|
||||
# trigger_patch, apply_patch, reject_patch, spawn_worker, kill_worker, mutate_dag, approve_ticket
|
||||
# These follow: try: <body>; except Exception as e: sys.stderr.write(...); result["status"] = "error"; result["error"] = str(e); finally: event.set()
|
||||
# The fix: extract a Result-returning helper for the body.
|
||||
|
||||
# Pattern for trigger_patch (and similar):
|
||||
# try:
|
||||
# sys.stderr.write(...)
|
||||
# sys.stderr.flush()
|
||||
# app._pending_patch_text = patch_text
|
||||
# ...
|
||||
# result["status"] = "ok"
|
||||
# except Exception as e:
|
||||
# sys.stderr.write(...)
|
||||
# sys.stderr.flush()
|
||||
# result["status"] = "error"
|
||||
# result["error"] = str(e)
|
||||
# finally:
|
||||
# event.set()
|
||||
|
||||
# This is the trigger_patch pattern. Let me migrate by extracting a helper.
|
||||
|
||||
# First, find each callback function and wrap it
|
||||
|
||||
# trigger_patch (around L548-571)
|
||||
old_trigger = (
|
||||
' def trigger_patch():\n'
|
||||
' try:\n'
|
||||
' sys.stderr.write(f"[DEBUG] trigger_patch callback executing...\\n")\n'
|
||||
' sys.stderr.flush()\n'
|
||||
' app._pending_patch_text = patch_text\n'
|
||||
' app._pending_patch_files = file_paths\n'
|
||||
' app._show_patch_modal = True\n'
|
||||
' sys.stderr.write(f"[DEBUG] Set patch modal: show={app._show_patch_modal}, text={\'yes\' if app._pending_patch_text else \'no\'}\\n")\n'
|
||||
' sys.stderr.flush()\n'
|
||||
' result["status"] = "ok"\n'
|
||||
' except Exception as e:\n'
|
||||
' sys.stderr.write(f"[DEBUG] trigger_patch error: {e}\\n")\n'
|
||||
' sys.stderr.flush()\n'
|
||||
' result["status"] = "error"\n'
|
||||
' result["error"] = str(e)\n'
|
||||
' finally:\n'
|
||||
' event.set()'
|
||||
)
|
||||
|
||||
new_trigger = (
|
||||
' def trigger_patch():\n'
|
||||
' nonlocal result\n'
|
||||
' try:\n'
|
||||
' app._pending_patch_text = patch_text\n'
|
||||
' app._pending_patch_files = file_paths\n'
|
||||
' app._show_patch_modal = True\n'
|
||||
' result["status"] = "ok"\n'
|
||||
' except Exception as e:\n'
|
||||
' _result = _patch_apply_result(app, e)\n'
|
||||
' result["status"] = _result.data.get("status", "error")\n'
|
||||
' result["error"] = _result.data.get("error", str(e))\n'
|
||||
' finally:\n'
|
||||
' event.set()'
|
||||
)
|
||||
|
||||
if old_trigger in text:
|
||||
text = text.replace(old_trigger, new_trigger, 1)
|
||||
print("[1] migrated trigger_patch")
|
||||
else:
|
||||
print("[1] trigger_patch pattern not found")
|
||||
|
||||
with open(p, "w", encoding="utf-8", newline="") as f:
|
||||
f.write(text)
|
||||
|
||||
# Verify parses
|
||||
import ast
|
||||
ast.parse(text)
|
||||
print("[verify] parses ok")
|
||||
@@ -0,0 +1,36 @@
|
||||
import json
|
||||
d = json.load(open(r"scripts/tier2/artifacts/result_migration_small_files_20260617/full_audit.json"))
|
||||
from collections import defaultdict
|
||||
by_file = defaultdict(lambda: {"silent": 0, "broad": 0, "unclear": 0, "sites": []})
|
||||
for f_info in d["files"]:
|
||||
fname = f_info["filename"]
|
||||
for finding in f_info["findings"]:
|
||||
if finding["category"] == "INTERNAL_SILENT_SWALLOW":
|
||||
by_file[fname]["silent"] += 1
|
||||
by_file[fname]["sites"].append((finding["line"], "SILENT", finding.get("context", "")))
|
||||
elif finding["category"] == "INTERNAL_BROAD_CATCH":
|
||||
by_file[fname]["broad"] += 1
|
||||
by_file[fname]["sites"].append((finding["line"], "BROAD", finding.get("context", "")))
|
||||
elif finding["category"] == "UNCLEAR":
|
||||
by_file[fname]["unclear"] += 1
|
||||
by_file[fname]["sites"].append((finding["line"], "UNCLEAR", finding.get("context", "")))
|
||||
priority = [
|
||||
"src/warmup.py",
|
||||
"src/startup_profiler.py",
|
||||
"src/file_cache.py",
|
||||
"src/orchestrator_pm.py",
|
||||
"src/project_manager.py",
|
||||
"src/log_registry.py",
|
||||
"src/models.py",
|
||||
"src/multi_agent_conductor.py",
|
||||
"src/theme_2.py",
|
||||
"src/shell_runner.py",
|
||||
"src/session_logger.py",
|
||||
]
|
||||
for fname in priority:
|
||||
info = by_file.get(fname, {"silent": 0, "broad": 0, "unclear": 0, "sites": []})
|
||||
total = info["silent"] + info["broad"] + info["unclear"]
|
||||
if total > 0:
|
||||
print(f"{fname}: {info['silent']} silent + {info['broad']} broad + {info['unclear']} unclear = {total}")
|
||||
for line, kind, ctx in info["sites"][:10]:
|
||||
print(f" L{line:4d} {kind} ctx={ctx}")
|
||||
@@ -0,0 +1,32 @@
|
||||
import json
|
||||
d = json.load(open(r"scripts/tier2/artifacts/result_migration_small_files_20260617/full_audit.json"))
|
||||
target_files = [
|
||||
"src/multi_agent_conductor.py",
|
||||
"src/aggregate.py",
|
||||
"src/summarize.py",
|
||||
"src/theme_models.py",
|
||||
"src/presets.py",
|
||||
"src/markdown_helper.py",
|
||||
"src/commands.py",
|
||||
"src/warmup.py",
|
||||
"src/command_palette.py",
|
||||
"src/orchestrator_pm.py",
|
||||
"src/project_manager.py",
|
||||
"src/session_logger.py",
|
||||
"src/shell_runner.py",
|
||||
"src/conductor_tech_lead.py",
|
||||
"src/models.py",
|
||||
"src/diff_viewer.py",
|
||||
]
|
||||
for fname in target_files:
|
||||
for f_info in d["files"]:
|
||||
if fname in f_info["filename"]:
|
||||
print(f"## {fname}")
|
||||
for finding in f_info["findings"]:
|
||||
if finding["category"] in ("INTERNAL_SILENT_SWALLOW", "INTERNAL_BROAD_CATCH", "UNCLEAR"):
|
||||
ctx = finding.get("context", "")
|
||||
line = finding["line"]
|
||||
cat = finding["category"]
|
||||
kind = finding["kind"]
|
||||
print(f" L{line:4d} [{kind:7s}] {cat:30s} ctx={ctx}")
|
||||
break
|
||||
Reference in New Issue
Block a user