refactor(db): split db/schedules.py into a 10-mixin package (#1481) - #1693
Merged
Merged
Conversation
#1481) Pure mechanical move of the 4,139-line src/backend/db/schedules.py into a ten-mixin db/schedules/ package composed into ScheduleOperations — the sanctioned db/agent_settings/ shape (Invariant #2). Zero behavior change, zero schema change (0 DDL in the file, Invariant #3 untouched), zero WHERE clause edits, zero signature edits. - __init__.py composes ScheduleOperations from ScheduleCommonMixin / Crud / Webhooks / Executions / Queue / Cleanup / Analytics / Stats / GitConfig / Retention and re-exports the class + _norm_ts + _TRIGGER_BUCKETS so the facade import `from db.schedules import ScheduleOperations` is unchanged (both prod sites: database.py, db/__init__.py). No import edges between mixin files; cross-slice refs resolve via the composed class's MRO. - find_soft_deleted_schedules_past_retention moves to retention.py so its caller, count_soft_deleted_schedules_past_retention, and the shared _soft_deleted_schedules_predicate module-global are co-located (a bare-name module-global does not resolve via MRO — would NameError on the #834 purge). - The three fat signatures (create_task_execution / update_execution_status / create_schedule_execution) are byte-identical (reserved for #1482). - The 20 #1082 status-CAS writers and all pull/backlog/lease seams (#1081/#1550, BACKLOG-001) moved verbatim; every WHERE precondition preserved. - Only allowlisted text deviations: relative-import depth (.->..), logger name pinned to the literal getLogger("db.schedules") in the 3 logging modules, and the _PERCENTILE_ROWSET_CAP monkeypatch doc-comment retargeted to db.schedules.analytics. Lockstep test edits forced by the move (the only non-move work): - test_schedule_status_observability.py: writer discovery now rglob-scans the db/schedules/ package (was one hardcoded file) with an in-function `assert sites` non-empty tripwire so the CAS-precondition guard can never pass vacuously; found == _EXPECTED_UPDATE_SITES (20) both ways. - test_agent_analytics.py / test_schedule_analytics.py: _PERCENTILE_ROWSET_CAP monkeypatch retargeted to db.schedules.analytics (module-identity trap). - conftest.py + test_agent_analytics.py: sys.modules eviction/baseline widened to db.schedules.* children (prefix match, future-sub-split-proof). Proof: symbol-set diff (103 functions, none added/dropped/renamed) + AST source-segment body diff (all 103 bodies byte-identical) vs origin/dev. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…exemplar (#1481) Records ScheduleOperations' composition from ten concern-scoped mixins in db/schedules/__init__.py alongside the existing db/agent_settings/ exemplar, noting the preserved facade import path and the MRO-not-imports cross-slice contract. Pure doc delta for the #1481 mechanical split; no behavior change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Resolve by running |
vybe
approved these changes
Jul 19, 2026
vybe
left a comment
Contributor
There was a problem hiding this comment.
Validated via /validate-pr: mechanical split with facade re-export preserved, 103/103 AST-byte-identical bodies, writer-inventory tripwire now rglob-scans the package (no vacuous pass), all checks green incl. regression-diff. No schema change, no packaging impact (db/ COPYed wholesale, prod-image-smoke green). Approving.
vybe
pushed a commit
that referenced
this pull request
Jul 19, 2026
- db/schedules.py deleted by the #1693 package split: re-apply the two #1296 bucket lines (reminder → Reminders) to db/schedules/analytics.py - retarget test_reminder_bucket_is_reminders import to db.schedules.analytics (package __init__ re-exports the facade surface only — #1693 lockstep pattern) - compose files: keep both #1632 OPERATOR_QUEUE_* and #1296 REMINDER_* blocks - architecture.md: keep #1296 Cleanup row + #1632 Operator Queue Sync row - feature-flows.md: keep both rows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1481
Summary
Pure mechanical split of the 4,139-line
src/backend/db/schedules.pyinto a 10-mixindb/schedules/package composed intoScheduleOperations— the sanctioneddb/agent_settings/shape (Invariant #2). The facade import pathfrom db.schedules import ScheduleOperationsis preserved by the package re-export, sodatabase.pyanddb/__init__.pyare unchanged. Zero behavior change, zero schema change, zero WHERE-clause edits, zero signature edits.Mixins:
ScheduleCommonMixin/Crud/Webhooks/Executions/Queue/Cleanup/Analytics/Stats/GitConfig/Retention. No import edges between mixin files — every cross-slice reference resolves via the composed class's MRO (self.<method>()); the only intra-package import is the bare_norm_tsmodule-global from_common.py.Proof (mechanical-move invariance)
dev(symbol-set diff: 103 functions, none added / dropped / renamed; AST source-segment body diff: all 103 bodies byte-identical).rglob-scans the wholedb/schedules/package (was one hardcoded file) with an in-functionassert sitesnon-empty guard so the CAS-precondition check can never pass vacuously;found == _EXPECTED_UPDATE_SITESboth ways.create_task_execution/update_execution_status/create_schedule_execution) — byte-identical, reserved for refactor(db): reduce database.py facade signature width — param objects for execution/chat writers #1482..→..), thegetLogger("db.schedules")literal pinned in the 3 logging modules, and the_PERCENTILE_ROWSET_CAPmonkeypatch doc-comment retargeted todb.schedules.analytics.Lockstep test edits (the only non-move work): writer-discovery
rglobrework +db.schedules.*sys.modules eviction widening (conftest +test_agent_analytics.py) +_PERCENTILE_ROWSET_CAPmonkeypatch retarget (module-identity trap).Verification
tests/unit/test_schedule_status_observability.py: 19 passed, 1 skipped; the writer inventory found exactly_EXPECTED_UPDATE_SITES(20 update sites) with no missing / stale entries.test_agent_analytics.py+test_schedule_analytics.py: 25 passed.from db.schedules import ScheduleOperationsresolves cleanly (95 methods).--skip-agent: PASS including import-smoke, proving thedb/schedules/package ships in the prod image (docker/backend/DockerfileCOPYsdb/wholesale). 1 red = pre-existingtest_1474ondev, proven identical on base (not introduced by this PR).Follow-ups (for Andrii)
docs/memory/feature-flows/scheduling.mdrefresh — path/line refs todb/schedules.pywere already stale pre-PR; ~30 flow docs cite the physical path (the import path is unchanged).FAILED_STATESin the analytics slice (analytics-dedup).db/schedules.pyprose comments referencing the old single-file layout.Sequencing: #1482 (facade param-objects) rebases on this.
🤖 Generated with Claude Code