refactor(sdm): Global pass with refined 'External Only' SDM tags. Pruned redundant internal references and fixed indentation logic in injector. Verified full project compilation.

This commit is contained in:
2026-05-09 14:32:44 -04:00
parent 696c08692e
commit 8c06c1767b
142 changed files with 2352 additions and 990 deletions
+85 -36
View File
@@ -29,7 +29,10 @@ def parse_ts(s: str) -> Optional[datetime.datetime]:
# ── entry serialisation ──────────────────────────────────────────────────────
def entry_to_str(entry: dict[str, Any]) -> str:
"""Serialise a disc entry dict -> stored string."""
"""
Serialise a disc entry dict -> stored string.
[C: tests/test_thinking_persistence.py:test_entry_to_str_with_thinking]
"""
ts = entry.get("ts", "")
role = entry.get("role", "User")
content = entry.get("content", "")
@@ -46,7 +49,10 @@ def entry_to_str(entry: dict[str, Any]) -> str:
return f"{role}:\n{content}"
def str_to_entry(raw: str, roles: list[str]) -> dict[str, Any]:
"""Parse a stored string back to a disc entry dict."""
"""
Parse a stored string back to a disc entry dict.
[C: tests/test_thinking_persistence.py:test_str_to_entry_with_thinking]
"""
ts = ""
rest = raw
if rest.startswith("@"):
@@ -93,9 +99,15 @@ def get_git_log(git_dir: str, n: int = 5) -> str:
# ── default structures ───────────────────────────────────────────────────────
def default_discussion() -> dict[str, Any]:
"""
[C: tests/test_discussion_takes.py:TestDiscussionTakes.test_promote_take_renames_discussion]
"""
return {"git_commit": "", "last_updated": now_ts(), "history": []}
def default_project(name: str = "unnamed") -> dict[str, Any]:
"""
[C: tests/test_deepseek_infra.py:test_default_project_includes_reasoning_role, tests/test_discussion_takes.py:TestDiscussionTakes.setUp, tests/test_history_management.py:test_history_persistence_across_turns, tests/test_history_management.py:test_save_separation, tests/test_project_manager_modes.py:test_default_project_execution_mode, tests/test_project_manager_modes.py:test_load_save_execution_mode, tests/test_project_serialization.py:TestProjectSerialization.test_default_roles_include_context, tests/test_project_serialization.py:TestProjectSerialization.test_fileitem_roundtrip]
"""
return {
"project": {"name": name, "git_dir": "", "system_prompt": "", "main_context": "", "execution_mode": "native"},
"output": {"output_dir": "./md_gen"},
@@ -148,15 +160,20 @@ def default_project(name: str = "unnamed") -> dict[str, Any]:
# ── load / save ──────────────────────────────────────────────────────────────
def get_history_path(project_path: Union[str, Path]) -> Path:
"""Return the Path to the sibling history TOML file for a given project."""
"""
Return the Path to the sibling history TOML file for a given project.
[C: tests/test_history_management.py:test_save_separation]
"""
p = Path(project_path)
return p.parent / f"{p.stem}_history.toml"
def load_project(path: Union[str, Path]) -> dict[str, Any]:
"""
Load a project TOML file.
Automatically migrates legacy 'discussion' keys to a sibling history file.
"""
Load a project TOML file.
Automatically migrates legacy 'discussion' keys to a sibling history file.
[C: tests/test_history_management.py:test_history_persistence_across_turns, tests/test_history_management.py:test_migration_on_load, tests/test_project_manager_modes.py:test_load_save_execution_mode, tests/test_project_serialization.py:TestProjectSerialization.test_backward_compatibility_strings, tests/test_project_serialization.py:TestProjectSerialization.test_fileitem_roundtrip]
"""
with open(path, "rb") as f:
proj = tomllib.load(f)
# Deserialise FileItems in files.paths
@@ -176,7 +193,10 @@ def load_project(path: Union[str, Path]) -> dict[str, Any]:
return proj
def load_history(project_path: Union[str, Path]) -> dict[str, Any]:
"""Load the segregated discussion history from its dedicated TOML file."""
"""
Load the segregated discussion history from its dedicated TOML file.
[C: tests/test_thinking_persistence.py:test_save_and_load_history_with_thinking_segments]
"""
hist_path = get_history_path(project_path)
if hist_path.exists():
with open(hist_path, "rb") as f:
@@ -184,7 +204,10 @@ def load_history(project_path: Union[str, Path]) -> dict[str, Any]:
return {}
def clean_nones(data: Any) -> Any:
"""Recursively remove None values from a dictionary/list."""
"""
Recursively remove None values from a dictionary/list.
[C: tests/test_thinking_persistence.py:test_clean_nones_removes_thinking]
"""
if isinstance(data, dict):
return {k: clean_nones(v) for k, v in data.items() if v is not None}
elif isinstance(data, list):
@@ -193,9 +216,11 @@ def clean_nones(data: Any) -> Any:
def save_project(proj: dict[str, Any], path: Union[str, Path], disc_data: Optional[dict[str, Any]] = None) -> None:
"""
Save the project TOML.
If 'discussion' is present in proj, it is moved to the sibling history file.
"""
Save the project TOML.
If 'discussion' is present in proj, it is moved to the sibling history file.
[C: tests/test_history_management.py:test_history_persistence_across_turns, tests/test_history_management.py:test_save_separation, tests/test_project_manager_modes.py:test_load_save_execution_mode, tests/test_project_serialization.py:TestProjectSerialization.test_fileitem_roundtrip, tests/test_thinking_persistence.py:test_save_and_load_history_with_thinking_segments]
"""
proj = clean_nones(proj)
# Serialise FileItems
if "files" in proj and "paths" in proj["files"]:
@@ -253,7 +278,10 @@ def flat_config(proj: dict[str, Any], disc_name: Optional[str] = None, track_id:
# ── context presets ──────────────────────────────────────────────────────────
def save_context_preset(project_dict: dict, preset_name: str, files: list[str], screenshots: list[str]) -> None:
"""Save a named context preset (files + screenshots) into the project dict."""
"""
Save a named context preset (files + screenshots) into the project dict.
[C: tests/test_context_presets.py:test_save_context_preset]
"""
if "context_presets" not in project_dict:
project_dict["context_presets"] = {}
project_dict["context_presets"][preset_name] = {
@@ -262,21 +290,29 @@ def save_context_preset(project_dict: dict, preset_name: str, files: list[str],
}
def load_context_preset(project_dict: dict, preset_name: str) -> dict:
"""Return the files and screenshots for a named preset."""
"""
Return the files and screenshots for a named preset.
[C: tests/test_context_presets.py:test_load_context_preset, tests/test_context_presets.py:test_load_nonexistent_preset]
"""
if "context_presets" not in project_dict or preset_name not in project_dict["context_presets"]:
raise KeyError(f"Preset '{preset_name}' not found in project context_presets.")
return project_dict["context_presets"][preset_name]
def delete_context_preset(project_dict: dict, preset_name: str) -> None:
"""Remove a named preset if it exists."""
"""
Remove a named preset if it exists.
[C: tests/test_context_presets.py:test_delete_context_preset, tests/test_context_presets.py:test_delete_nonexistent_preset_no_error]
"""
if "context_presets" in project_dict:
project_dict["context_presets"].pop(preset_name, None)
# ── track state persistence ─────────────────────────────────────────────────
def save_track_state(track_id: str, state: 'TrackState', base_dir: Union[str, Path] = ".") -> None:
"""
Saves a TrackState object to conductor/tracks/<track_id>/state.toml.
"""
Saves a TrackState object to conductor/tracks/<track_id>/state.toml.
[C: tests/test_project_manager_tracks.py:test_get_all_tracks_with_state, tests/test_track_state_persistence.py:test_track_state_persistence]
"""
track_dir = paths.get_track_state_dir(track_id, project_path=str(base_dir))
track_dir.mkdir(parents=True, exist_ok=True)
state_file = track_dir / "state.toml"
@@ -286,8 +322,10 @@ def save_track_state(track_id: str, state: 'TrackState', base_dir: Union[str, Pa
def load_track_state(track_id: str, base_dir: Union[str, Path] = ".") -> Optional['TrackState']:
"""
Loads a TrackState object from conductor/tracks/<track_id>/state.toml.
"""
Loads a TrackState object from conductor/tracks/<track_id>/state.toml.
[C: tests/test_track_state_persistence.py:test_track_state_persistence]
"""
from src.models import TrackState
state_file = paths.get_track_state_dir(track_id, project_path=str(base_dir)) / 'state.toml'
if not state_file.exists():
@@ -298,9 +336,10 @@ def load_track_state(track_id: str, base_dir: Union[str, Path] = ".") -> Optiona
def load_track_history(track_id: str, base_dir: Union[str, Path] = ".") -> list[str]:
"""
Loads the discussion history for a specific track from its state.toml.
Returns a list of entry strings formatted with @timestamp.
"""
Loads the discussion history for a specific track from its state.toml.
Returns a list of entry strings formatted with @timestamp.
"""
state = load_track_state(track_id, base_dir)
if not state:
return []
@@ -315,9 +354,10 @@ def load_track_history(track_id: str, base_dir: Union[str, Path] = ".") -> list[
def save_track_history(track_id: str, history: list[str], base_dir: Union[str, Path] = ".") -> None:
"""
Saves the discussion history for a specific track to its state.toml.
'history' is expected to be a list of formatted strings.
"""
Saves the discussion history for a specific track to its state.toml.
'history' is expected to be a list of formatted strings.
"""
state = load_track_state(track_id, base_dir)
if not state:
return
@@ -328,12 +368,14 @@ def save_track_history(track_id: str, history: list[str], base_dir: Union[str, P
def get_all_tracks(base_dir: Union[str, Path] = ".") -> list[dict[str, Any]]:
"""
Scans the conductor/tracks/ directory and returns a list of dictionaries
containing track metadata: 'id', 'title', 'status', 'complete', 'total',
and 'progress' (0.0 to 1.0).
Handles missing or malformed metadata.json or state.toml by falling back
to available info or defaults.
"""
Scans the conductor/tracks/ directory and returns a list of dictionaries
containing track metadata: 'id', 'title', 'status', 'complete', 'total',
and 'progress' (0.0 to 1.0).
Handles missing or malformed metadata.json or state.toml by falling back
to available info or defaults.
[C: tests/test_project_manager_tracks.py:test_get_all_tracks_empty, tests/test_project_manager_tracks.py:test_get_all_tracks_malformed, tests/test_project_manager_tracks.py:test_get_all_tracks_with_metadata_json, tests/test_project_manager_tracks.py:test_get_all_tracks_with_state, tests/test_project_paths.py:test_get_all_tracks_project_specific]
"""
tracks_dir = paths.get_tracks_dir(project_path=str(base_dir))
if not tracks_dir.exists():
return []
@@ -394,8 +436,10 @@ def get_all_tracks(base_dir: Union[str, Path] = ".") -> list[dict[str, Any]]:
def calculate_track_progress(tickets: list) -> dict:
"""
Calculates track progress based on ticket statuses.
percentage (float), completed (int), total (int), in_progress (int), blocked (int), todo (int)
Calculates track progress based on ticket statuses.
percentage (float), completed (int), total (int), in_progress (int), blocked (int), todo (int)
[C: tests/test_progress_viz.py:test_calculate_track_progress_all_completed, tests/test_progress_viz.py:test_calculate_track_progress_all_todo, tests/test_progress_viz.py:test_calculate_track_progress_empty, tests/test_progress_viz.py:test_calculate_track_progress_mixed]
"""
total = len(tickets)
if total == 0:
@@ -427,8 +471,10 @@ def calculate_track_progress(tickets: list) -> dict:
def branch_discussion(project_dict: dict, source_id: str, new_id: str, message_index: int) -> None:
"""
Creates a new discussion in project_dict['discussion']['discussions'] by copying
the history from source_id up to (and including) message_index, and sets active to new_id.
Creates a new discussion in project_dict['discussion']['discussions'] by copying
the history from source_id up to (and including) message_index, and sets active to new_id.
[C: tests/test_discussion_takes.py:TestDiscussionTakes.test_branch_discussion_creates_new_take]
"""
if "discussion" not in project_dict or "discussions" not in project_dict["discussion"]:
return
@@ -445,7 +491,10 @@ def branch_discussion(project_dict: dict, source_id: str, new_id: str, message_i
project_dict["discussion"]["active"] = new_id
def promote_take(project_dict: dict, take_id: str, new_id: str) -> None:
"""Renames a take_id to new_id in the discussions dict."""
"""
Renames a take_id to new_id in the discussions dict.
[C: tests/test_discussion_takes.py:TestDiscussionTakes.test_promote_take_renames_discussion]
"""
if "discussion" not in project_dict or "discussions" not in project_dict["discussion"]:
return
if take_id not in project_dict["discussion"]["discussions"]:
@@ -456,4 +505,4 @@ def promote_take(project_dict: dict, take_id: str, new_id: str) -> None:
# If the take was active, update the active pointer
if project_dict["discussion"].get("active") == take_id:
project_dict["discussion"]["active"] = new_id
project_dict["discussion"]["active"] = new_id