feat(sdm): inject structural dependency mapping tags across codebase

Adds [C: caller] tags to functions/methods and [M: mutation] / [U: usage] tags to class variables based on cross-module call analysis.
This commit is contained in:
2026-05-13 22:35:41 -04:00
parent 5bb3a9026f
commit b5e512f483
110 changed files with 1673 additions and 1008 deletions
+48 -30
View File
@@ -30,7 +30,8 @@ def parse_ts(s: str) -> Optional[datetime.datetime]:
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", "")
@@ -50,7 +51,8 @@ def entry_to_str(entry: dict[str, Any]) -> str:
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 = ""
@@ -91,13 +93,13 @@ def get_git_commit(git_dir: str) -> str:
def default_discussion() -> dict[str, Any]:
"""
[C: tests/test_discussion_takes.py:TestDiscussionTakes.test_promote_take_renames_discussion]
[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]
[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": "", "execution_mode": "native"},
@@ -152,7 +154,8 @@ def default_project(name: str = "unnamed") -> dict[str, Any]:
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)
@@ -161,8 +164,9 @@ def get_history_path(project_path: Union[str, Path]) -> Path:
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:
@@ -185,7 +189,8 @@ def load_project(path: Union[str, Path]) -> dict[str, Any]:
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)
@@ -196,7 +201,8 @@ def load_history(project_path: Union[str, Path]) -> dict[str, Any]:
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):
@@ -208,8 +214,9 @@ 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)
@@ -270,7 +277,8 @@ def flat_config(proj: dict[str, Any], disc_name: Optional[str] = None, track_id:
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:
@@ -282,7 +290,8 @@ 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"]:
@@ -291,7 +300,8 @@ def load_context_preset(project_dict: dict, preset_name: str) -> dict:
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:
@@ -301,7 +311,8 @@ def delete_context_preset(project_dict: dict, preset_name: str) -> None:
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))
@@ -314,7 +325,8 @@ 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
@@ -328,8 +340,9 @@ 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:
@@ -346,8 +359,9 @@ 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:
@@ -360,11 +374,12 @@ 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))
@@ -428,8 +443,9 @@ 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)
@@ -463,8 +479,9 @@ 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"]:
@@ -483,7 +500,8 @@ def branch_discussion(project_dict: dict, source_id: str, new_id: str, message_i
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"]: