Slice 132: Sync Evaluation Boundaries
Scope#
Keep codealmanac sync and codealmanac sync status behavior unchanged while
splitting sync candidate evaluation out of the SyncWorkflow facade.
Out of scope#
- No sync cursor policy changes.
- No ledger schema changes.
- No foreground/background execution changes.
- No transcript discovery adapter changes.
Design#
Cosmic Python chapter 4 describes the service layer as "a single place to
capture all the use cases" (docs/reference/cosmic-python/chapter_04_service_layer.md),
while chapter 13 argues for explicit dependencies over "an implicit dependency
on a specific detail" (docs/reference/cosmic-python/chapter_13_dependency_injection.md).
For this slice, SyncWorkflow remains the explicit use-case facade, and the
candidate evaluator becomes a named collaborator composed by the facade.
Slices 103 and 109 already split deterministic sync policy and execution
effects; the remaining pressure is the SyncWorkflow.evaluate(...) loop, which
still performs discovery, scoping, ledger reads, pending-run reconciliation,
cursor decisions, and summary assembly in one service file.
The split is:
workflows.sync.service # SyncWorkflow facade: status/run orchestration
-> evaluation.py # SyncEvaluator: discovery/scoping/evaluation
-> execution.py # SyncRunExecutor: foreground/background effects
-> policy.py # deterministic sync rules facadeSyncWorkflow keeps the public status, run, and evaluate methods. The
evaluate method delegates to SyncEvaluator so tests and future callers can
still use the workflow as the entrypoint.
Verification#
- Existing sync workflow tests.
- Existing sync CLI tests through the full test suite.
- Architecture guard that keeps candidate evaluation mechanics out of
service.pyand execution effects out ofevaluation.py. - Public CLI dogfood for
codealmanac sync status --jsonin this checkout. - Full pytest, Ruff, and diff checks.