86f1676721
Per the 4-criteria decision rule (C1=cross-system, C3=tests, C4=substantial);
FileItem is the canonical per-file data structure used by aggregate,
app_controller, gui_2, presets, context_presets, and tests. Preset /
ContextPreset / ContextFileEntry / NamedViewPreset are the preset/view
data structures that round-trip through TOML.
This commit:
1. Creates src/project_files.py with FileItem + Preset + ContextPreset +
ContextFileEntry + NamedViewPreset (full class bodies copied verbatim
from src/models.py including __post_init__, to_dict, from_dict, and
the [C: ...] caller-docstring tags).
2. Removes the 5 class definitions from src/models.py.
3. Adds backward-compat re-exports in src/models.py (the same pattern
used by Phase 3a mma.py + Phase 3b project.py + Phase 3g personas.py).
4. Updates the 4 consumer files to import from src.project_files directly:
src/orchestrator_pm.py, src/presets.py, src/context_presets.py,
src/ai_client.py (3 sites of the banned 'local import + as _FIC alias'
pattern updated to use src.project_files.FileItem; the aliasing
anti-pattern is preserved for now - a follow-up track will remove
the local imports and the aliasing).
Verification: VC7
from src.project_files import FileItem, Preset, ContextPreset,
ContextFileEntry, NamedViewPreset # OK
from src.models import FileItem, Preset, ... # OK
(re-exports work; identity check: FileItem is FileItem returns True)
Tests verified (20/20 PASS):
tests/test_file_item_model.py (4 tests)
tests/test_view_presets.py (4 tests)
tests/test_context_presets_models.py (3 tests)
tests/test_custom_slices_annotations.py (3 tests)
tests/test_presets.py (5 tests)
Decorator-orphan pitfall caught and fixed: after removing the 3 classes
between WorkspaceProfile and the MCP Config region, the @dataclass
decorator was orphaned on a comment line. Removed the orphan.
32 lines
1.4 KiB
Python
32 lines
1.4 KiB
Python
from typing import Dict, Any
|
|
|
|
from src.project_files import ContextPreset
|
|
from src.result_types import Result, ErrorInfo, ErrorKind
|
|
|
|
|
|
class ContextPresetManager:
|
|
"""Manages context presets within the project dictionary (manual_slop.toml)."""
|
|
|
|
def load_all(self, project_dict: Dict[str, Any]) -> Result[Dict[str, ContextPreset]]:
|
|
"""Loads all context presets from the project dictionary."""
|
|
presets: Dict[str, ContextPreset] = {}
|
|
errors: list[ErrorInfo] = []
|
|
presets_data = project_dict.get("context_presets", {})
|
|
for name, data in presets_data.items():
|
|
try:
|
|
presets[name] = ContextPreset.from_dict(name, data)
|
|
except (ValueError, KeyError, TypeError) as e:
|
|
errors.append(ErrorInfo(kind=ErrorKind.INTERNAL, message=str(e), source=f"context_presets.load_all[{name}]", original=e))
|
|
return Result(data=presets, errors=errors)
|
|
|
|
def save_preset(self, project_dict: Dict[str, Any], preset: ContextPreset) -> None:
|
|
"""Saves a context preset into the project dictionary."""
|
|
if "context_presets" not in project_dict:
|
|
project_dict["context_presets"] = {}
|
|
project_dict["context_presets"][preset.name] = preset.to_dict()
|
|
|
|
def delete_preset(self, project_dict: Dict[str, Any], name: str) -> None:
|
|
"""Deletes a context preset from the project dictionary."""
|
|
if "context_presets" in project_dict and name in project_dict["context_presets"]:
|
|
del project_dict["context_presets"][name]
|