Skip to content

feat(schedule): add PostgreSQL and SQLite storage - #191

Closed
znnnnnnn-wil wants to merge 11 commits into
1024XEngineer:mainfrom
znnnnnnn-wil:feat/schedule-storage
Closed

feat(schedule): add PostgreSQL and SQLite storage#191
znnnnnnn-wil wants to merge 11 commits into
1024XEngineer:mainfrom
znnnnnnn-wil:feat/schedule-storage

Conversation

@znnnnnnn-wil

Copy link
Copy Markdown
Contributor

Summary

  • align PostgreSQL schedules and schedule_occurrence_overrides storage with the v3.10 schedule contracts
  • add account-scoped SQLAlchemy repository primitives, including optimistic revision updates and occurrence override ownership checks
  • add versioned Expo SQLite tables and local repository primitives for schedules, occurrence overrides, and device-only reminder runtime state
  • keep cloud confirmed disposition separate from the client-only snoozed state
  • Part of feat(schedule): 实现日程聚合、PostgreSQL/SQLite 与日历读取闭环 #176

Verification

  • uv run ruff check .
  • uv run ruff format --check .
  • uv run mypy
  • uv run pytest (79 passed)
  • uv run alembic heads
  • Alembic offline upgrade and downgrade SQL generation
  • npm run lint
  • npm run typecheck
  • npx prettier --check .
  • SQLite migration SQL executed against an in-memory SQLite database
  • npx expo export --platform android --output-dir dist

Scope

This PR only adds PostgreSQL and SQLite persistence foundations. It does not implement the five Agent business operations, RRULE expansion, recurring deletion behavior, stale snapshot decisions, or snapshot transaction orchestration.

account_id is non-null, indexed, and enforced by repository queries. Its physical foreign key is deferred until the shared accounts table migration lands.

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
timeflow Ready Ready Preview Aug 11, 2026 5:47am

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found two high-confidence storage consistency issues; details are inline.

updated_at, deleted_at
)
SELECT
left(id, 64),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Preserve legacy identifiers during migration

left(id, 64) silently truncates the legacy primary key before inserting it into the new table. The old column is unbounded Text, so any existing identifier longer than 64 characters is changed, and two IDs sharing the first 64 characters will collide and abort the migration. Please validate/reject overlong IDs or migrate the full value rather than truncating it (the same concern applies to user_id on the next line).

OR (schedule_type = 'time' AND start_time IS NOT NULL AND end_time IS NOT NULL)
),
CHECK (
(reminder_type IS NULL

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Require disposition state to be absent without a reminder

The cloud Schedule constraint requires reminder_disposition_state to be NULL whenever reminder_type is NULL, but this local presence check omits that column from the first branch. SQLite therefore accepts rows with no reminder configuration and a confirmed/snoozed disposition, creating a local state that cannot satisfy the backend schema. Include reminder_disposition_state IS NULL in this branch to keep the two storage contracts aligned.

@znnnnnnn-wil

Copy link
Copy Markdown
Contributor Author

This combined PR has been split into smaller, independently reviewable changes:

Closing this PR in favor of those two replacements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant