Skip to content

Proposal:Schedule 与 Todo 基础模块 #82

Description

@znnnnnnn-wil

Issue:Schedule 与 Todo 基础模块

1. 功能描述

Schedule 与 Todo 基础模块负责 TimeFlow 中日程和待办两类核心业务对象的定义、创建、查询、修改、删除及状态管理,并向单页日历首页、语音 Agent、提醒模块提供统一、确定性的公共业务能力。

Schedule 表示在明确时间段内发生的安排,例如会议、上课、预约和出行。正式 Schedule 必须具有明确的开始时间和结束时间。

Todo 表示需要完成的事项,例如提交报告、购买物品和缴费。正式 Todo 必须具有标题和完成状态,可以设置计划日期、截止时间和提醒,也允许暂时不指定日期。

本模块保留 Schedule 与 Todo 的业务语义差异,但为二者提供一致的访问方式:

  • 创建。

  • 查询。

  • 修改。

  • 删除。

  • 归属校验。

  • 版本与并发校验。

  • Reminder 关联。

  • 首页展示投影。

  • AI 候选确认后的确定性写入。

本模块不负责语音识别、自然语言意图解析、候选确认界面、提醒实际触发和页面具体样式。

2. 用户 / 用户故事

目标用户:需要管理有明确时间安排的日程,以及需要完成但不一定占用固定时间段的待办用户。

用户通过语音说:

明天下午三点到四点开项目会议。

系统确认后创建一条 Schedule,并在明天的日期下展示。

用户通过语音说:

明天提交产品设计报告。

系统确认后创建一条计划日期为明天的 Todo,并在明天的待办区域展示。

用户说:

周五之前提交产品设计报告。

系统可以创建具有截止时间的 Todo。是否同时设置计划日期,需要根据用户表达和确认候选确定。

用户说:

把明天下午三点的项目会议改到四点。

系统需要定位对应 Schedule,展示修改前后值,用户确认后修改正式数据。

用户在首页勾选 Todo 后,系统将 Todo 标记为已完成,并取消该 Todo 尚未触发的一次性提醒。

用户删除一个 Schedule 或 Todo 后,系统同时取消该事项关联的有效 Reminder,但不删除必要的提醒执行历史和业务审计记录。

3. 现有做法及不足

如果使用一个统一的“事项”对象同时表示 Schedule 和 Todo,虽然可以减少表数量,但会导致大量条件字段和语义混乱。

例如:

  • Schedule 必须具有起止时间,Todo 不一定有。

  • Schedule 表示时间占用,Todo 表示完成责任。

  • Todo 具有完成状态,Schedule 不应默认以“完成”作为核心状态。

  • Schedule 通常按照开始时间展示,Todo 更关注计划日期、截止时间和完成状态。

  • 日程冲突只适用于 Schedule,不应套用到全部 Todo。

如果完全独立实现 Schedule 和 Todo,又容易产生重复的权限、CRUD、版本控制、Reminder 关联和首页查询逻辑。

本模块采用“对象分开、业务能力一致”的方式:

  • Schedule 与 Todo 使用独立的数据模型。

  • 两者保留不同字段和校验规则。

  • 对外提供风格一致的公共业务能力。

  • 首页和 Agent 不直接操作数据库。

  • Reminder 可以统一绑定 Schedule 或 Todo。

4. 本期范围

Schedule

  1. 创建 Schedule。

  2. 按 ID 查询 Schedule。

  3. 按日期范围查询 Schedule。

  4. 按标题、时间范围等条件查找 Schedule。

  5. 修改 Schedule。

  6. 删除 Schedule。

  7. 校验 Schedule 所属用户。

  8. 校验开始时间和结束时间。

  9. 检测时间冲突并返回提示信息。

  10. 支持绑定 Place。

  11. 支持绑定零个或多个 Reminder。

  12. 支持生成首页展示投影。

  13. 支持语音候选确认后的确定性写入。

  14. 修改时间、地点或状态后通知 Reminder 模块同步规则。

  15. 删除时取消关联 Reminder。

Todo

  1. 创建 Todo。

  2. 按 ID 查询 Todo。

  3. 按计划日期查询 Todo。

  4. 查询未完成 Todo。

  5. 查询已完成 Todo。

  6. 查询已逾期 Todo。

  7. 按标题、日期和状态查找 Todo。

  8. 修改 Todo。

  9. 删除 Todo。

  10. 标记 Todo 已完成。

  11. 将 Todo 恢复为未完成。

  12. 支持计划日期。

  13. 支持截止时间。

  14. 支持优先级。

  15. 支持绑定 Place。

  16. 支持绑定零个或多个 Reminder。

  17. 支持生成首页展示投影。

  18. 支持语音候选确认后的确定性写入。

  19. 完成或删除时取消尚未触发的有效 Reminder。

公共能力

  1. Schedule 与 Todo 的数据归属校验。

  2. 版本和并发修改校验。

  3. 创建和更新时间记录。

  4. 软删除或等价的可追踪删除机制。

  5. 向首页提供指定日期的数据。

  6. 向主 Agent 提供对象检索能力。

  7. 向候选确认模块提供确定性写能力。

  8. 向 Reminder 模块提供事项生命周期事件。

  9. 保留最小必要业务审计信息。

  10. 防止客户端和 Agent 绕过公共业务能力直接写库。

5. 明确不做

  • 不在本模块实现语音录音和 ASR。

  • 不在本模块识别自然语言意图。

  • 不在本模块生成 AI 候选。

  • 不在本模块实现用户确认界面。

  • 不在本模块注册本地通知。

  • 不在本模块注册地理围栏。

  • 不在本模块实现 Place 搜索和地图确认。

  • 不做自动排期。

  • 不做智能重排。

  • 不做日程自动冲突解决。

  • 不自动移动其他 Schedule。

  • 不自动拆分 Todo。

  • 不自动将 Todo 安排到空闲时间。

  • 不做 Goal 与长期目标管理。

  • 不做项目、清单、标签体系。

  • 不做子任务。

  • 不做 Todo 依赖关系。

  • 不做 Schedule 参与人和邀请。

  • 不做多人共享日程。

  • 不做会议室和资源预订。

  • 不做第三方日历同步。

  • 不做循环日程和复杂重复规则。

  • 不做循环 Todo。

  • 不做全天事件的复杂跨时区处理。

  • 不做 Schedule 自动完成。

  • 不将 Reminder 触发等同于 Todo 完成。

  • 不因 Reminder 失败回滚 Schedule 或 Todo。

  • 不允许一个正式对象同时既是 Schedule 又是 Todo。

  • 不在删除业务对象时物理清除必须保留的审计信息。

6. 关键决策

决策点 备选方案 选择 理由
对象建模 统一事项对象 / Schedule 与 Todo 分开 分开建模 二者时间、状态和展示语义不同
公共能力 每类对象完全独立 / 统一接口风格 独立模型、统一能力风格 保留语义并减少上层使用复杂度
Schedule 时间 开始时间可选 / 起止时间必填 起止时间必填 Schedule 表示明确时间占用
Todo 时间 日期必填 / 日期可选 日期和截止时间可选 Todo 可以先记录、后安排
Todo 完成状态 删除表示完成 / 独立完成状态 独立完成状态 完成和删除是不同业务事实
Todo 日期字段 只有截止时间 / 计划日期与截止时间分开 分开 “计划哪天做”和“最晚何时完成”语义不同
首页展示 所有 Todo 都显示 / 仅有计划日期的 Todo 显示 仅有计划日期的 Todo 日期首页只展示归属于该日期的事项
日程冲突 禁止创建 / 自动调整 / 提示但允许 提示但允许 第一版不替用户做时间决策
删除方式 直接物理删除 / 可追踪删除 可追踪删除 支持审计、同步和异常恢复
Reminder 关联 事项表固定提醒字段 / 独立 Reminder 独立 Reminder 支持多个提醒和多种触发类型
完成 Todo 后提醒 保留全部 / 取消未触发提醒 取消未触发提醒 已完成事项通常不再需要提醒
恢复 Todo 后提醒 自动恢复 / 用户重新确认 用户重新确认或显式恢复 防止过期提醒被静默重新激活
Schedule 状态 使用 Todo 完成状态 / 独立生命周期 独立生命周期 Schedule 不以勾选完成为核心
AI 写入 Agent 直接写库 / 公共业务能力写入 公共业务能力写入 保证权限、校验和事务一致
并发控制 后写覆盖 / 版本校验 版本校验 防止旧候选覆盖新数据
时间存储 本地无时区时间 / 标准时间加时区 标准时间加用户时区语义 保证提醒和跨时区行为可解释
删除关联 Reminder 保留 active / 自动取消 自动取消 不允许已删除事项继续提醒
业务与提醒事务 完全独立 / 同一业务事务提交规则变化 同一业务操作中保证一致结果 避免事项成功但关联规则状态未知

7. 边界与异常

Schedule 边界

  • Schedule 标题不得为空。

  • Schedule 必须具有开始时间和结束时间。

  • 结束时间必须晚于开始时间。

  • 开始时间与结束时间必须能够转换为明确时区下的时间点。

  • 时间表达仅有日期但没有具体时间时,不创建普通 Schedule;全天日程不属于本期核心范围。

  • 创建过去时间的 Schedule 时,业务能力应返回明确警告或拒绝,具体由调用方根据产品策略处理。

  • Schedule 与其他 Schedule 时间冲突时,返回冲突信息,但不自动修改任何对象。

  • 冲突提示不是创建失败,用户确认后允许继续创建。

  • Place 不存在或不属于当前用户时,不允许绑定。

  • Schedule 修改时间后,Reminder 模块必须接收到更新事件。

  • Schedule 删除后,其 active、pending_sync 状态 Reminder 必须取消。

  • 已删除 Schedule 不得出现在正常查询和首页投影中。

  • 已删除 Schedule 的历史 Reminder Execution 可以保留。

  • Schedule 不支持通过勾选方式完成。

  • Schedule 结束时间已过不等于对象自动删除。

Todo 边界

  • Todo 标题不得为空。

  • Todo 可以没有 planned_date。

  • Todo 可以没有 due_at。

  • due_at 存在时必须是明确时间点。

  • planned_date 与 due_at 可以同时存在。

  • planned_date 晚于 due_at 时,应拒绝或要求调用方确认纠正。

  • 没有 planned_date 的 Todo 不展示在具体日期首页中。

  • Todo 已完成后仍可查询,但默认不作为未完成事项返回。

  • 重复完成一个已经完成的 Todo 应保持幂等。

  • 恢复未完成需要记录新的状态变更。

  • 已完成 Todo 的未触发 Reminder 应取消。

  • 恢复 Todo 时,不自动恢复已经过期或取消的 Reminder。

  • Todo 删除后不得继续出现在任何正常列表。

  • 删除已完成 Todo 仍属于删除业务事实,不等同于保持完成。

  • Reminder 触发不得自动将 Todo 标记完成。

  • Todo 逾期不得自动顺延 planned_date 或 due_at。

公共异常

  • 查询不存在对象时返回明确的不存在结果。

  • 查询到已删除对象时,不作为正常对象返回。

  • 对象不属于当前用户时,不泄露其存在性和字段内容。

  • 修改时版本不一致,应拒绝写入并返回最新版本。

  • Agent 候选生成后,正式对象被其他操作修改时,旧候选不得直接覆盖。

  • 创建、修改和删除必须具有幂等边界,避免客户端重试产生重复对象。

  • 一个请求产生多个 Schedule 或 Todo 不属于本期默认能力。

  • 创建事项和 Reminder 的联合操作失败时,不得产生无法解释的半完成状态。

  • Reminder 创建失败时,可以保留事项,但必须返回明确提醒失败结果;如果候选定义为原子操作,则整体按候选规则回滚。

  • 首页缓存不得作为业务事实来源。

  • 客户端离线修改的冲突合并不在本期自动解决。

  • 时间计算必须使用用户时区,不能直接使用服务端本地时区。

  • 更新对象后必须刷新 updated_at 和版本号。

  • 删除操作必须记录执行用户、对象类型和对象 ID。

  • 业务模块不得根据自然语言自行猜测缺失字段。

  • 非法字段不得静默丢弃,应返回校验错误。

  • 不允许 Schedule 与 Todo 相互直接转换;如后续需要,应定义独立 Proposal。

8. 基本概念与信息结构

概念 含义
Schedule 具有明确开始和结束时间的日程安排
Todo 以完成状态为核心的待办事项
PlannedDate Todo 计划执行或归属的日期
DueAt Todo 最晚应完成的时间
ScheduleStatus Schedule 的业务生命周期状态
TodoStatus Todo 的完成和删除状态
ScheduleConflict 新建或修改 Schedule 与其他日程的时间重叠信息
BusinessVersion 用于并发修改校验的对象版本
ScheduleProjection Schedule 在首页和列表中的只读展示投影
TodoProjection Todo 在首页和列表中的只读展示投影
ReminderBinding Schedule/Todo 与 Reminder 的关联关系
SoftDelete 对正常业务查询不可见,但保留必要记录的删除方式
BusinessEvent 对象创建、修改、删除、完成等变化事件
User
├─ Schedule
│  ├─ Place(可选)
│  ├─ Reminder[]
│  └─ BusinessEvent[]
└─ Todo
   ├─ Place(可选)
   ├─ Reminder[]
   └─ BusinessEvent[]

Schedule 数据结构

Schedule
├─ id
├─ user_id
├─ title
├─ start_at
├─ end_at
├─ timezone
├─ place_id
├─ location_text
├─ description
├─ status
├─ version
├─ created_at
├─ updated_at
└─ deleted_at

字段约束:

  • id:Schedule 唯一标识。

  • user_id:所属用户。

  • title:必填。

  • start_at:必填。

  • end_at:必填,且晚于 start_at

  • timezone:时间语义所属时区。

  • place_id:可选,关联用户确认的 Place。

  • location_text:可选,展示用途;不能替代确认后的 Place 坐标。

  • description:可选。

  • status:P0 至少支持 active、cancelled。

  • version:并发控制版本。

  • deleted_at:为空表示未删除。

Todo 数据结构

Todo
├─ id
├─ user_id
├─ title
├─ planned_date
├─ due_at
├─ timezone
├─ priority
├─ place_id
├─ description
├─ completed
├─ completed_at
├─ version
├─ created_at
├─ updated_at
└─ deleted_at

字段约束:

  • id:Todo 唯一标识。

  • user_id:所属用户。

  • title:必填。

  • planned_date:可选,决定是否展示在具体日期首页。

  • due_at:可选。

  • timezone:due_at 使用的时区语义。

  • priority:可选,P0 可以只提供有限枚举。

  • place_id:可选。

  • description:可选。

  • completed:必填布尔状态。

  • completed_at:完成时记录。

  • version:并发控制版本。

  • deleted_at:为空表示未删除。

ScheduleProjection

ScheduleProjection
├─ id
├─ title
├─ start_at
├─ end_at
├─ location_text
├─ reminder_summary
└─ version

TodoProjection

TodoProjection
├─ id
├─ title
├─ planned_date
├─ due_at
├─ priority
├─ completed
├─ reminder_summary
└─ version

对象关系约束

  • 一个 Schedule 可以绑定零个或多个 Reminder。

  • 一个 Todo 可以绑定零个或多个 Reminder。

  • 一个 Reminder 必须且只能绑定一个 Schedule 或 Todo。

  • 一个 Schedule 最多绑定一个 Place。

  • 一个 Todo 最多绑定一个 Place。

  • Place 删除前必须检查关联事项和 Reminder。

  • 删除事项后,Reminder 关联不得继续处于 active 状态。

9. Agent 输入输出约束

  • Agent 可以通过公共查询能力读取 Schedule 和 Todo。

  • Agent 不直接访问数据库表。

  • Agent 不自行生成正式对象 ID、版本号和审计字段。

  • Agent 可以生成 Schedule 或 Todo 的结构化操作候选。

  • 创建候选至少明确对象类型和标题。

  • Schedule 创建候选必须明确开始时间和结束时间。

  • Todo 创建候选可以缺少 planned_date 和 due_at,但候选中必须明确展示“未设置”。

  • Agent 不得将没有完整起止时间的候选直接作为 Schedule 写入。

  • Agent 无法区分 Schedule 和 Todo 时必须追问。

  • 用户说“开会”“上课”“预约”等明确时间占用内容时,可以优先建议 Schedule。

  • 用户说“提交”“购买”“完成”等完成型内容时,可以优先建议 Todo。

  • 对象类型仍需在候选中明确展示。

  • Agent 查询对象时可以按标题、时间、日期和状态组合检索。

  • 修改或删除匹配多个对象时,Agent 必须要求用户选择。

  • Agent 不得根据列表顺序静默选择对象。

  • 查询操作可以直接返回正式业务数据。

  • 创建、修改、删除、完成和恢复操作必须经过候选确认。

  • Agent 修改候选必须携带对象 ID 和读取时的版本号。

  • 候选确认时版本已变化,业务能力必须拒绝旧候选。

  • Agent 不自行判断日程冲突是否可以忽略;业务能力返回冲突信息后,由用户确认。

  • Agent 不自动将 Todo 转为 Schedule。

  • Agent 不自动为无日期 Todo 补充 SelectedDate,除非作为明确候选展示。

  • 当前首页 selected_date 可以作为候选上下文,但不能覆盖用户自然语言中的明确日期。

  • Agent 不自动标记 Todo 完成,除非用户表达了明确完成意图。

  • Reminder 触发信息不能被 Agent 解释为 Todo 已完成。

  • Agent 写入成功后只使用公共业务能力返回的正式对象。

  • Agent 不通过自由文本声称写入成功;必须以确定性业务结果为准。

  • 创建事项和 Reminder 属于同一次用户候选时,应明确是否采用原子提交。

  • Agent 输出中不得包含客户端内部排序和 DateMarker 计算逻辑。

10. 验收标准

Schedule

  • 可以创建具有标题、开始时间和结束时间的 Schedule。

  • 标题为空时创建失败。

  • 缺少开始时间时创建失败。

  • 缺少结束时间时创建失败。

  • 结束时间早于或等于开始时间时创建失败。

  • 创建成功后返回正式 ID、版本号和时间字段。

  • 可以按 ID 查询属于当前用户的 Schedule。

  • 无权访问其他用户 Schedule。

  • 可以按日期范围查询 Schedule。

  • 查询结果按照开始时间稳定排序。

  • 可以修改标题。

  • 可以修改开始和结束时间。

  • 可以修改地点和备注。

  • 修改后版本号更新。

  • 使用旧版本修改时被拒绝。

  • 时间冲突时返回冲突信息。

  • 时间冲突不会自动修改其他 Schedule。

  • 用户确认后允许创建或保存冲突 Schedule。

  • 可以删除 Schedule。

  • 删除后不再出现在正常查询中。

  • 删除后关联有效 Reminder 被取消。

  • 删除后必要历史记录仍可追踪。

  • Schedule 不支持 Todo 式勾选完成。

  • Schedule 修改时间后发出 Reminder 同步事件。

  • 首页可以获得指定日期的 ScheduleProjection。

  • ScheduleProjection 不暴露不必要内部字段。

Todo

  • 可以创建只包含标题的 Todo。

  • 标题为空时创建失败。

  • Todo 可以不设置 planned_date。

  • Todo 可以不设置 due_at。

  • 可以同时设置 planned_date 和 due_at。

  • planned_date 晚于 due_at 所在日期时返回校验错误或明确冲突。

  • 可以按 ID 查询 Todo。

  • 可以查询指定 planned_date 的 Todo。

  • 可以查询未完成 Todo。

  • 可以查询已完成 Todo。

  • 可以查询已逾期 Todo。

  • 未指定 planned_date 的 Todo 不出现在具体日期首页。

  • 可以修改标题、planned_date、due_at、优先级、地点和备注。

  • 修改后版本号更新。

  • 旧版本修改被拒绝。

  • 可以将未完成 Todo 标记为完成。

  • 完成操作重复调用保持幂等。

  • 完成后记录 completed_at。

  • 完成后尚未触发的有效 Reminder 被取消。

  • 可以恢复 Todo 为未完成。

  • 恢复后 completed_at 清空或按统一状态规则处理。

  • 恢复 Todo 不自动恢复过期 Reminder。

  • 可以删除 Todo。

  • 删除后不再出现在正常查询和首页中。

  • 首页可以获得指定日期的 TodoProjection。

  • TodoProjection 正确展示完成状态。

公共业务边界

  • Schedule 和 Todo 使用独立正式数据模型。

  • 一个正式对象不能同时作为 Schedule 和 Todo。

  • 所有写操作校验对象所属用户。

  • AI 和客户端不能绕过公共业务能力直接写库。

  • 创建、修改、删除具有幂等边界。

  • 正式写入失败时不产生不可解释的半完成对象。

  • 查询不到对象时返回明确结果。

  • 非法字段返回明确校验错误,不静默丢弃。

  • 时间统一按照用户时区解释。

  • 业务对象变化后首页可以重新读取最新数据。

  • 首页缓存不作为业务事实。

  • 对象删除后 DateMarker 可以正确更新。

  • 创建、修改和删除可记录最小业务审计事件。

  • Agent 未确认的候选不得改变 Schedule 或 Todo。

  • 旧候选不得覆盖已经更新的正式对象。

  • Reminder 失败不自动删除 Schedule 或 Todo。

  • Schedule/Todo 删除后不允许关联 Reminder 继续触发。

Metadata

Metadata

Assignees

No one assigned

    Labels

    FullSpec完整规格提案:影响面较大,需要写清楚动机、范围、不做、备选方案、接口/数据结构、原型、验收标准Proposal-Accepted

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions