Skip to content

全局数据、系统日志模块接口设计草案 #75

Description

@gac0812

1. 模块职责说明

成员3负责两个公共基础模块:全局数据模块、系统日志模块。核心边界是“数据库事实由成员3统一读写,AI 推理和前端确认卡片不放进成员3”。

模块 负责什么 不负责什么 主要调用方 关联数据库表
全局数据模块 查询数据库事实;查询候选事项;校验用户归属、存在性、版本和写入前提;创建待确认写入请求;保存重排候选与画像原始观察等非业务事实工作流记录;用户确认后在事务中写入、修改或软删除业务事实 不做意图识别、参数补全、反问、LLM 调用、Prompt 管理、前端确认卡片展示;不允许子 Agent 直接调用本模块 母 AI 编排模块、基础业务模块、弹窗确认机制 userslong_goalstask_itemsfeedback_recordsconversation_messageswrite_requestsoperation_confirmationsreplan_proposalsreplan_proposal_changesreplan_applicationsuser_profilestask_profile_observationstask_profile_snapshots
系统日志模块 记录 Agent 运行摘要,包括组件、函数、运行状态、错误码、开始与结束时间以及可选链路 ID 不保存完整 Prompt、模型原文、完整 LLM 调用链;不替代 LangSmith 等可观测平台 母 AI 编排模块、全局数据模块、前端交互与展示模块 agent_run_records

统一约束:

  1. AI 驱动写入只能由母 AI 编排模块发起,最终调用全局数据模块落盘。
  2. 业务界面和母 AI 编排模块可调用同一套全局数据模块;写操作也必须走统一确认与校验。
  3. 子 Agent 只能生成候选结果或结构化建议,不能直接读写数据库,也不能直接调用全局数据模块。
  4. 不能把前端传入的 is_confirmed = true 当作写入凭证;必须使用 write_requests + operation_confirmations + payload_hash
  5. 删除操作使用软删除,必须维护 is_deleteddeleted_at
  6. 成功业务写入与写入请求状态 applied 必须在同一个事务中完成;任一步失败都先回滚,再使用独立短事务将请求标记为 failed。系统日志模块只记录 Agent 运行摘要,不参与业务写入事务。
  7. 校验类能力(归属、存在性、目标唯一性、写入前提)作为进程内对外函数提供,供母 AI 编排模块与基础业务模块调用;不单独暴露 HTTP,可嵌入查询 / 写入路径复用。
  8. HTTP 接口中的当前用户必须从登录态解析,禁止信任前端随意传入的 user_id 做越权查询。
  9. 对话原文统一由全局数据模块写入 conversation_messages;媒体二进制不进库,只存 OSS 返回的 source_url

2. 事务校验与软删除

2.1 事务校验

事务校验不是提前执行一次的普通查询,而是“事务校验并应用写入”内部不可跳过的步骤。公共数据模块必须按以下顺序执行:

BEGIN
→ 调用 assert_confirmed_write(user_id, write_request_id, payload_hash)
→ 校验目标仍存在、属于当前用户且 version 与 base_version / expected_item_version 一致
→ 校验 action 和 payload 字段在业务白名单内
→ 执行业务写入(含软删除、反馈追加、画像快照、重排应用等)
→ 将 `write_requests.status` 更新为 `applied`
COMMIT

成功路径中,业务写入和 write_requests.status=applied 必须一起提交。任一步失败都先 ROLLBACK,不得留下部分业务数据。回滚完成后,另开一个短事务将请求标记为 failed。幂等键用于阻止同一写入请求被重复执行;前端传入的单独布尔值不能替代确认记录。

assert_confirmed_write 只解决确认状态、用户归属、精确载荷和过期时间;它不替代身份认证、业务白名单和目标版本校验。

2.2 时间范围查询规则

以下规则是成员 3 对 Wiki“按时间范围查询”要求的字段级补充,所有事项时间范围查询必须复用同一谓词。查询窗口统一使用左闭右开区间 [from_time, to_time)

  1. schedule 按日程区间与查询窗口重叠匹配:start_at < to_time AND end_at > from_time
  2. todo / subtask 按截止时间落入窗口匹配:due_at >= from_time AND due_at < to_time
  3. due_at IS NULL 的待办或子任务不属于任何确定时间窗口,因此在传入时间范围时排除;不带时间范围的全量查询仍可返回。
  4. “今日事项”先按 users.timezone 将本地日期换算成 UTC 起止时刻,再应用同一谓词,不能直接按数据库会话时区截取日期。
  5. 查询事项列表、今日事项、候选反馈目标和复盘关联数据必须使用相同规则,避免四个入口返回不一致的事项集合。

2.3 软删除

事项和长任务禁止物理删除。确认删除后只更新 is_deleted=truedeleted_at=now(),并将 version 加一。删除前必须校验用户归属、未删除状态和 base_version;重复删除、越权或版本冲突均应拒绝并回滚。

普通查询默认附带 is_deleted=false,但已删除记录仍保留主键及其关联反馈,保证既有业务事实可以追溯。

长任务与子任务策略:

  1. 创建 delete_goal 写入请求时,由服务端读取当前全部未软删子任务,将每个 item_id + expected_item_version 写入 payload 的 cascade_subtasks;该完整 payload 参与 payload_hash,确认卡片展示级联数量和明细。
  2. 应用确认请求时先锁定长任务,再锁定并读取当前未软删子任务;只有当前 ID/版本集合与 cascade_subtasks 完全一致,才在同一事务内软删除长任务和清单内子任务。确认后新增、删除、改版或改变归属的任一子任务都会触发版本冲突并整单回滚。
  3. 软删除长任务时,禁止物理删除子任务;子任务只更新 is_deleted=truedeleted_at=now()version+1
  4. 子任务行与其 feedback_records 关联仍保留,仅对普通查询不可见(默认 is_deleted=false 即可过滤),无需再靠 JOIN 父目标判断可见性。
  5. 查询长任务及子任务:若目标已软删或越权,直接返回错误,不返回其子任务列表。
  6. 级联软删在应用层同事务完成,不依赖库层 ON DELETE 物理级联;不在 MVP 引入单独的数据库软删触发器(避免与确认写入路径分叉)。

2.4 工作流记录与业务事实

类型 是否需要用户确认 示例
业务事实 task_itemslong_goalsfeedback_recordsuser_profilestask_profile_snapshots 的创建/更新/软删除
工作流候选 否(但真正改事项时仍需确认) write_requestsreplan_proposalsreplan_proposal_changes
系统运行记录 conversation_messagestask_profile_observationsagent_run_records

重排方案可在确认前保存;真正修改事项必须通过 write_requests.action = apply(兼容历史枚举 apply_replan)并完成确认。

2.5 复盘数据查询边界

复盘不查询历史完整报告,而是在用户发起复盘时实时读取已经落库的业务事实:事项来自 task_items,执行反馈来自 feedback_records,关联长任务来自 long_goals。复盘 Agent 生成的完整报告只返回前端展示,不写入数据库;从报告中提炼的长任务简洁复盘摘要可以作为成员 3 的补充业务字段 long_goals.review_summary 保存。

查询步骤:

  1. user_idfrom_timeto_time 和可选 goal_id 查询时间范围内未软删除的事项;日程按区间重叠,待办/子任务按 due_at 落入 [from_time, to_time),无截止时间的事项不进入本次复盘数据集。
  2. 查询该用户在时间范围内产生、且关联上述事项的 feedback_records;同一事项允许返回多条不可变反馈。
  3. 根据事项的 long_goal_id 查询未软删除的关联长任务;传入 goal_id 时只返回该目标范围内的数据。
  4. 将三组事实组装成 ReviewDataResponse(items, feedbacks, goals),交给母 AI 编排模块,再传给复盘 Agent。
  5. 复盘 Agent 输出完整报告和不超过 500 字的 review_summary 候选;完整报告只展示,摘要写入候选必须走 action=update_goal 的确认链,应用后覆盖该长任务的最新摘要,不保存摘要历史版本。
  6. 没有匹配事实时返回三个空列表,不创建复盘记录,也不把“无数据”视为数据库错误。

MVP 只返回复盘原始数据集,不在全局数据模块计算完成率;允许额外保存长任务最新简洁复盘摘要,但不保存完整报告或摘要历史。若后续需要结构化统计,必须先明确多次反馈、部分完成和无反馈事项的计算规则,再扩展独立统计 DTO。

2.6 update_goal payload 契约(成员 3 补充)

Wiki 和数据库只固定 action + payload 外壳;以下字段级结构是成员 3 为避免普通字段、宏观规划与简洁复盘摘要修改歧义而补充的契约。action=update_goal 时,修改内容全部放入 payload,允许以下四种结构:

  1. 普通字段修改:包含 long_goal_idchanges
  2. 仅更新宏观规划:changes 只包含 plan_overview
  3. 仅保存简洁复盘:changes 只包含 review_summary
  4. 组合修改:changes 同时包含普通字段、plan_overviewreview_summary 中的多项,用于用户明确要求一次修改多项内容。

changes 只允许 titledescriptionplan_overviewreview_summarystart_atdeadline_atstatus,且至少包含一个字段;review_summary 为空白或超过 500 字时拒绝;未知字段或空修改也应拒绝。

四种结构都使用同一个 write_action=update_goal。目标的 base_version 使用 write_requests.base_version 顶层字段承载,不在 payload 内重复。完整 payload 由数据库生成 payload_hash,确认卡片必须展示全部变更;组合修改在同一个事务中一次完成,任一字段失败则整体回滚,成功后 version 只递增一次。

3. 前后端 API 表

说明:

  1. 本模块对外首先是进程内函数能力;下列 HTTP API 是前端只读页与确认链路需要的后端入口,承接模块为全局数据模块。
  2. 基础业务模块可以做页面聚合,但最终仍应调用本模块函数,不允许另开一套直连数据库的写入通道。
  3. 请求中的 user_id 仅作文档字段说明;实现时必须从登录态注入,忽略或拒绝客户端伪造值。
页面 / 场景 API 名称 HTTP 方法 路径建议 承接模块 请求参数 响应数据 数据来源 是否写入 是否需要确认 数据库缺口 数据流转说明
今日事项页 / 时间顺序 Tab 查询今日事项 GET /api/items/today 全局数据模块 date(登录态推导 user_id items: list[TaskItemDTO] task_itemsusers.timezone 需补 due_at 部分索引 前端传入日期;按用户时区换算当天 [from_time, to_time);日程按区间重叠,待办/子任务按 due_at 落入窗口;默认排除软删和无截止时间事项
事项详情页 查询事项详情 GET /api/items/{item_id} 全局数据模块 item_id item: TaskItemDTO task_items 用登录用户 + item_id 限定归属;不存在或越权分别返回 404 / 403
长任务目标管理 Tab 查询长任务列表 GET /api/goals 全局数据模块 status?(登录态推导 user_id goals: list[LongGoalDTO] long_goals 默认查询当前用户未软删除长任务;可按状态过滤,按 updated_at DESC 返回
长任务详情页 查询长任务及子任务 GET /api/goals/{goal_id} 全局数据模块 goal_id goal: LongGoalDTOitems: list[TaskItemDTO] long_goalstask_items 返回长任务宏观规划文本和 item_type=subtask 子任务列表;plan_overview 仅展示
业务页面 / 确认卡片 创建写入请求 POST /api/write-requests 全局数据模块 WriteRequestDraft(无前端伪造确认字段) WriteRequestDTO write_requests 是,写候选 否,后续确认 基础业务模块或母 AI 编排模块提交已完成字段校验的结构化候选;服务端保存完整 action + payload,此时不改业务事实
确认卡片 提交确认事件 POST /api/confirmations 全局数据模块 write_request_idpayload_hashdecisionclient_event_id? ConfirmWriteResponse write_requestsoperation_confirmations 是,写确认 弹窗确认机制把用户决定落成确认记录;确认成功不直接写业务表
确认后落盘编排 应用已确认写入 POST /api/write-requests/{write_request_id}/apply 全局数据模块 write_request_idpayload_hash ApplyConfirmedWriteResponse 目标业务表、write_requests 见查缺补漏 母 AI 编排模块或基础业务模块在确认后调用;成功路径同事务完成校验、业务写入和请求状态更新;失败时回滚业务事务,再标记请求失败

AI 对话主链路本身不额外增加成员3专属聊天 API;对话入口由母 AI 编排模块承接,本模块只提供其调用的查询与落盘函数。

长任务简洁复盘摘要不新增独立 HTTP 接口:母 AI 将 review_summary 放入 action=update_goalchanges,经确认后写回当前长任务;查询长任务列表、详情和复盘关联数据时随 LongGoalDTO 返回。完整复盘报告仍只展示,不写入数据库。

4. 模块对外函数表

所属模块 函数中文名称 函数类型 调用方 输入参数 返回值 依赖数据 依赖模块 是否写入 是否需要确认 失败处理 数据库缺口 数据流转说明
全局数据模块 查询事项列表 查询 母 AI 编排模块、基础业务模块 user_idfrom_time?to_time?item_types?status?include_deleted=false items: list[TaskItemDTO] task_items 用户不存在返回空列表或 404;时间范围非法返回参数错误 due_at 部分索引 有时间范围时使用 [from_time,to_time):日程按 start_at < to_time AND end_at > from_time,待办/子任务按 due_at >= from_time AND due_at < to_time,无截止时间者排除;默认 is_deleted=false
全局数据模块 查询事项详情 查询 母 AI 编排模块、基础业务模块 user_iditem_id item: TaskItemDTO task_items 不存在返回 404;不属于当前用户返回 403;已软删视为不存在 user_id + item_id 限定归属;只返回未软删除事项;不做指代推理
全局数据模块 查询长任务列表 查询 母 AI 编排模块、基础业务模块 user_idstatus?include_deleted=false goals: list[LongGoalDTO] long_goals 非法状态返回参数错误;无数据返回空列表 支撑长任务目标管理 Tab 首屏;默认仅返回当前用户未软删除目标,按 updated_at DESC 排序;include_deleted=true 仅供恢复管理内部调用
全局数据模块 查询长任务及子任务 查询 母 AI 编排模块、基础业务模块 user_idgoal_id goal: LongGoalDTOitems: list[TaskItemDTO] long_goalstask_items 长任务不存在、已删除或越权时返回错误 返回长任务基本信息、plan_overview 和子任务事实;母 AI 再把结果传给子 Agent
全局数据模块 查询用户画像 查询 母 AI 编排模块、全局用户画像管理模块的上游编排 user_id profile: UserProfileDTO or None user_profiles 未填写画像时返回空值,不阻塞主流程 只返回用户主动画像事实,不做 AI 归纳
全局数据模块 查询任务级画像 查询 母 AI 编排模块、任务级画像管理模块的上游编排 user_idlong_goal_id observations: list[TaskProfileObservationDTO]current_snapshot: TaskProfileSnapshotDTO or None task_profile_observationstask_profile_snapshots 长任务不存在返回错误;没有画像时返回空列表 原始观察与 AI 归纳快照分开返回
全局数据模块 查询候选反馈目标 查询 母 AI 编排模块 user_idfrom_timeto_timeitem_types? candidates: list[CandidateItemDTO] task_items 无候选时由母 AI 触发反问;多候选时返回列表 due_at 部分索引 复用事项时间谓词:日程按区间重叠,待办/子任务按 due_at 落入 [from_time,to_time);默认排除软删和无截止时间事项,再交给反馈 Agent
全局数据模块 查询复盘关联数据 查询 母 AI 编排模块 user_idfrom_timeto_timereview_type?goal_id? ReviewDataResponse,含 itemsfeedbacksgoals task_itemsfeedback_recordslong_goals 时间范围非法时返回参数错误;没有匹配事实时返回三个空列表 due_at 部分索引 实时查询已保存事实;事项复用同一时间谓词,再查询关联反馈和目标;默认排除软删及无截止时间的待办/子任务;不查询或保存完整复盘报告,可返回已保存的 review_summary;不计算完成率
全局数据模块 查询最近对话消息 查询 母 AI 编排模块 user_idlimit=20 messages: list[ConversationMessageDTO] conversation_messages 超出上限时截断到 MVP 固定窗口 message_index 倒序取最近 N 条,再正序返回;支撑“最近 20 条对话 + 当前请求数据库事实”
全局数据模块 保存对话消息 记录 母 AI 编排模块、基础业务模块 SaveConversationMessageRequest ConversationMessageDTO conversation_messages 是,写系统运行记录 message_index 冲突、modalitysource_url 不一致、用户不存在时拒绝 保存原文与可选 source_url;不存媒体二进制;不需要用户确认
全局数据模块 查询重排方案详情 查询 母 AI 编排模块、基础业务模块 user_idproposal_id ReplanProposalDTOchanges: list[ReplanChangeDTO] replan_proposalsreplan_proposal_changes 方案不存在或越权时返回错误 供确认卡片展示候选变更;不修改事项
全局数据模块 校验事项归属 校验 母 AI 编排模块、基础业务模块 user_iditem_id owned: bool task_items 事项不存在时返回 owned=false 或明确错误码 进程内函数,防越权;不暴露 HTTP
全局数据模块 校验事项存在性 校验 母 AI 编排模块、基础业务模块 user_iditem_id exists: bool task_items 已软删视为不存在 修改、删除、反馈前检查;is_deleted=false
全局数据模块 校验目标唯一性 校验 母 AI 编排模块 user_idcandidate_condition unique_target / candidates / none task_items 0 候选或 ≥2 候选时由母 AI 反问,本函数不猜主键 反馈定位与重排对象选择;可复用查询候选结果
全局数据模块 校验写入前提 校验 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hash allowed: bool、拒绝原因 write_requestsoperation_confirmations、目标表 未确认、过期、越权、版本冲突时返回不可写 封装 assert_confirmed_write + 归属 + 版本 + 白名单预检;真正写入仍走事务入口
全局数据模块 创建写入请求 生成候选 母 AI 编排模块、基础业务模块 WriteRequestDraft WriteRequestDTO write_requests 是,写候选请求 否,后续确认 非法 action、payload 字段不在白名单、幂等键重复时返回错误 保存已完成字段校验的结构化候选;数据库触发器根据完整 payload 生成 hash;此时尚未改动业务事实
全局数据模块 保存重排候选方案 生成候选 母 AI 编排模块 SaveReplanProposalRequest ReplanProposalDTO replan_proposalsreplan_proposal_changes 是,写工作流候选 变更缺少 expected_item_version(update/delete)时拒绝 入参 changes 使用 ReplanChangeDraft(无 id/proposal_id);模块根据 input_snapshot 生成 input_snapshot_hash,调用方不得伪造;确认前可保存,真正改事项必须再走 apply
全局数据模块 追加任务级画像原始观察 记录 母 AI 编排模块 AppendTaskProfileObservationRequest TaskProfileObservationDTO task_profile_observations 是,只追加观察 长任务不存在或越权时拒绝 原始观察属系统运行记录,可自动追加;不覆盖历史观察
全局数据模块 记录确认事件 确认 弹窗确认机制、母 AI 编排模块、基础业务模块 ConfirmWriteRequest ConfirmWriteResponse write_requestsoperation_confirmations 是,写确认记录 请求不存在、已过期、payload_hash 不一致、重复确认时返回错误 确认成功只改变请求状态,不直接写业务事实
全局数据模块 事务校验并应用写入 确认落盘 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hash ApplyResult write_requestsoperation_confirmations、目标业务表 是,写业务事实 成功路径同事务提交;失败先回滚,再用短事务标记请求失败 见查缺补漏 统一入口:按 action 分派到具体确认后写入函数;业务写入与请求状态更新同事务
全局数据模块 确认后新增长任务 确认落盘 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hash;payload 含 titledescription?start_at?deadline_at? ApplyResult,含新增 long_goal_id write_requestsoperation_confirmationslong_goals action 不匹配或字段非法时拒绝 执行已确认的 create_goal
全局数据模块 确认后修改长任务 确认落盘 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hashaction=update_goal;payload 含 long_goal_id、非空 changes;请求顶层 base_version 必填 ApplyResult write_requestsoperation_confirmationslong_goals 越权、已删除、版本冲突、空修改或未知字段时拒绝 changes 可同时包含普通字段与 plan_overview;完整变更一次确认并在同一事务执行,成功后版本只递增一次
全局数据模块 确认后软删除长任务 确认落盘 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hash;payload 含 long_goal_idcascade_subtasks: list[{item_id, expected_item_version}];请求顶层 base_version 必填 ApplyResult,含实际级联清单与数量 write_requestsoperation_confirmationslong_goalstask_items 目标已删除/越权/版本冲突,或当前子任务 ID/版本集合与确认清单不一致时整单拒绝 确认卡片展示完整级联范围;应用时锁定目标与子任务并逐项校验,只软删确认清单内对象;反馈外键仍指向保留行
全局数据模块 确认后新增事项 确认落盘 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hash;payload 含 item_typetitlestart_at?end_at?due_at?long_goal_id? ApplyResult,含新增 item_id write_requestsoperation_confirmationstask_items 日程缺时间范围、子任务缺长任务、关系不合法时拒绝 执行已确认的新增日程、待办或子任务
全局数据模块 确认后修改事项 确认落盘 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hash;payload 含 item_idchanges;请求顶层 base_version 必填 ApplyResult write_requestsoperation_confirmationstask_items 目标不存在、越权、版本冲突或字段不在白名单时拒绝 只修改白名单字段,并递增 version
全局数据模块 确认后软删除事项 确认落盘 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hash;payload 含 item_id;请求顶层 base_version 必填 ApplyResult write_requestsoperation_confirmationstask_items 已删除、越权或版本冲突时拒绝并整体回滚 只更新删除标记、删除时间和版本,保留关联反馈
全局数据模块 确认后追加执行反馈 确认落盘 母 AI 编排模块 user_idwrite_request_idpayload_hash;payload 含 item_idexecution_statusraw_feedbacknormalized_feedbackoccurred_atduration_minutes? ApplyResult,含 feedback_id write_requestsoperation_confirmationsfeedback_recordstask_items 反馈目标不匹配确认请求或目标事项不存在时拒绝 反馈是不可变事件,不直接修改 task_items.status
全局数据模块 确认后更新用户画像 确认落盘 母 AI 编排模块、基础业务模块 user_idwrite_request_idpayload_hash;payload 含 profile_datasource;如需乐观锁,使用请求顶层 base_version ApplyResult write_requestsoperation_confirmationsuser_profiles source 非法或版本冲突时拒绝 只保存用户主动填写或明确输入的画像;sourceuser_form / user_explicit_input
全局数据模块 确认后保存任务级画像 确认落盘 母 AI 编排模块 user_idwrite_request_idpayload_hash;payload 含 long_goal_idprofile_summaryversion ApplyResult,含 snapshot_id write_requestsoperation_confirmationstask_profile_snapshots 长任务不存在、确认动作不匹配或版本冲突时拒绝 AI 归纳快照必须经确认;写入时把旧快照 is_current=false
全局数据模块 确认后更新长任务宏观规划 确认落盘 母 AI 编排模块 user_idwrite_request_idpayload_hashaction=update_goal;payload 含 long_goal_idchanges.plan_overview;请求顶层 base_version 必填 ApplyResult write_requestsoperation_confirmationslong_goals 规划文本为空、长任务不存在、越权或版本冲突时拒绝 宏观规划单独修改时使用 changes.plan_overview;若还包含普通字段,由「确认后修改长任务」按组合 payload 同事务处理;可执行任务仍来自 task_items(item_type=subtask)
全局数据模块 确认后应用重排方案 确认落盘 母 AI 编排模块 user_idwrite_request_idpayload_hash;payload 含 proposal_idaction=apply(兼容 apply_replan ApplyResult,含 application_id replan_proposalsreplan_proposal_changesreplan_applicationstask_items 任一变更版本冲突则整单回滚;方案状态非法时拒绝 同事务按 sort_order 应用全部变更,写入 replan_applications,并校验每条 expected_item_version
系统日志模块 开始 Agent 运行记录 记录 母 AI 编排模块、全局数据模块、前端交互与展示模块 StartAgentRunRequest agent_run_id agent_run_records 组件名为空或用户不存在时返回错误 创建请求级运行摘要
系统日志模块 结束 Agent 运行记录 记录 母 AI 编排模块、全局数据模块、前端交互与展示模块 FinishAgentRunRequest ok: bool agent_run_records 运行记录不存在或不属于当前用户时返回错误 更新终态、错误码和结束时间;不保存完整模型响应

说明:

  1. 校验四类对应模块拆分 7.2.4,列入对外函数表供汇总发现提供方;不单独暴露 HTTP。
  2. 复盘接口只查询原始事实;复盘 Agent 生成的完整文本只展示、不入库;长任务最新 review_summary 需经确认后单独写回 long_goals
  3. 长任务普通字段、宏观规划和最新简洁复盘摘要共用 write_action=update_goal;payload 可只含其中一类,也可在用户明确要求时组合多类,所有字段必须通过白名单并完整展示在同一确认卡片中。

5. 模块依赖函数表

本表只填写本模块主动依赖的其他模块能力,不填写「谁依赖本模块」。被依赖关系见第 4 节对外函数表的「调用方」列。

所属模块 依赖模块 需要的函数中文名称 依赖原因 输入参数 返回值 是否强依赖 缺失时处理
全局数据模块 用户账号模块 获取当前用户 ID / 校验登录态 所有查询和写入必须限定当前用户,防止越权 登录态、business_user_id? user_id、用户状态 无法确定用户时拒绝查询和写入
系统日志模块 用户账号模块 校验运行记录归属用户 Agent 运行摘要必须关联真实用户 user_id 用户存在性和状态 用户不存在时拒绝写入运行摘要
系统日志模块 LangSmith 等可观测平台 关联 trace_id(可选) 运行摘要只保存链路 ID,不保存完整 Prompt 和模型原文 trace_id 外部链路地址或 ID 没有 trace_id 时仍可写入运行摘要,但无法跳转完整调用链

6. 模块内部函数表

所属模块 内部函数中文名称 上游函数 下游函数 上游输入 内部处理 下游输出 依赖数据 是否调用 LLM 是否写入 失败处理 数据流转说明
全局数据模块 规范化查询时间范围 查询事项列表 / 查询今日事项 API 事项查询 SQL datefrom_timeto_time、用户时区 将日期转换为当天 [from_time,to_time);校验开始时间小于结束时间;日程使用 start_at < to_time AND end_at > from_time,待办/子任务使用 due_at >= from_time AND due_at < to_time 标准化范围与类型谓词 users.timezonetask_items 时间格式错误返回参数错误 不查业务表,只做时间规范化;无时间范围不附加时间谓词
全局数据模块 组装复盘原始数据 查询复盘关联数据 返回 ReviewDataResponse user_id、标准化时间范围、goal_id? 查询未软删除事项并复用类型时间谓词;查询与事项关联的不可变反馈;查询关联的未软删除长任务 itemsfeedbacksgoals task_itemsfeedback_recordslong_goals 无数据返回三个空列表;查询失败返回内部错误 只读取已保存事实,不读取历史复盘文本,不计算完成率,不产生写入
全局数据模块 组装事项 DTO 各查询函数 对外返回 数据库行 过滤软删除字段;转换枚举、时间和版本字段 TaskItemDTOLongGoalDTO task_itemslong_goals 字段缺失时记录内部错误 不返回 is_deleted 给普通只读页;内部校验仍使用该字段
全局数据模块 校验写入动作白名单 创建写入请求 / 事务校验并应用写入 创建候选或分派写入 actionpayload 按 action 校验字段;update_goal 要求 long_goal_id 和非空 changes,字段使用长任务白名单;delete_goal 要求 long_goal_id 和完整 cascade_subtasks 条目;禁止外部传入表名或任意 SQL 字段 合法 payload write_action 枚举 空修改、重复级联 ID、版本非正或非白名单字段直接拒绝 不执行业务写入
全局数据模块 分配对话 message_index 保存对话消息 插入 conversation_messages user_id 未提供序号时,在事务内对用户行加锁后计算 max(message_index)+1;调用方提供序号时校验唯一 下一个序号 conversation_messages 序号冲突时回滚并重试或返回冲突 数据库唯一约束保证 (user_id, message_index) 唯一;不能用无锁的简单 max+1 保证并发安全
全局数据模块 预计算长任务级联删除范围 创建写入请求 校验写入动作白名单 / write_requests 插入 user_idlong_goal_idbase_version 锁定并读取未软删目标及其所有未软删子任务,生成按 item_id 排序的 cascade_subtasks(含各自版本);目标或版本不匹配时拒绝创建请求 完整 delete_goal payload long_goalstask_items 目标不存在、版本冲突或越权时不创建候选 读取不改变业务事实;生成的清单纳入 payload hash
全局数据模块 创建候选写入请求 创建写入请求 返回 WriteRequestDTO WriteRequestDraft 写入 write_requests,由数据库触发器根据完整 payload 生成 payload_hash,设置数据库默认过期时间和幂等约束 WriteRequestDTO write_requests 幂等键重复时返回已有请求或冲突 不改业务事实表;确认卡片展示该 payload 的实际变更范围
全局数据模块 校验确认凭证 事务校验并应用写入 / 校验写入前提 校验目标归属和版本 user_idwrite_request_idpayload_hash 调用 assert_confirmed_write 可执行确认凭证 write_requestsoperation_confirmations 未确认、过期或 hash 不一致时拒绝写入 不替代版本校验和白名单
全局数据模块 校验目标归属和版本 事务校验并应用写入 分派具体写入动作 target_typetarget_idbase_version 使用 user_id + id + version + is_deleted=false 检查目标;长任务删除另锁定并逐项比对 payload 中每个 cascade_subtasks.expected_item_version 可写目标对象 task_itemslong_goals 越权、已删除、版本变化或级联集合变化时返回冲突 重排场景改为校验每条 expected_item_version
全局数据模块 分派具体写入动作 事务校验并应用写入 各确认后写入函数 已确认写入请求 action 与 payload 白名单分派 create/update/delete/feedback/profile/apply;update_goal 直接应用 changesdelete_goal 应用完整级联清单 业务写入结果 对应业务表 任一动作失败则事务回滚 不允许动态拼接表名
全局数据模块 执行软删除 确认后软删除事项 / 长任务 更新写入请求状态 target_typetarget_idbase_version 普通事项更新删除标记;长任务先校验确认 payload 的完整级联集合,再更新目标和清单内子任务 is_deleted=truedeleted_at=now()version+1 删除结果(含级联明细与数量) task_itemslong_goals 已删除、版本冲突或级联集合变化时拒绝并整单回滚 不物理删除;反馈外键仍有效
全局数据模块 级联软删长任务子任务 执行软删除(长任务) 更新写入请求状态 user_idlong_goal_idcascade_subtasks FOR UPDATE 锁定当前未软删子任务;要求当前 ID/版本集合与确认 payload 完全一致;逐项更新清单内子任务 级联软删明细与数量 task_items 新增、删除、改版或归属变化任一发生则整单回滚 仅软删标记;不碰 feedback_records;父目标锁阻止并发绕过确认范围
全局数据模块 应用重排变更集 确认后应用重排方案 更新写入请求状态 proposal_id、确认请求 sort_order 依次 create/update/soft-delete,并写 replan_applications 应用摘要 replan_*task_items 任一变更冲突则整单回滚 不接受前端直接传变更列表绕过方案表
全局数据模块 更新写入请求状态 各确认后写入函数 对外 ApplyResult 写入结果或失败原因 成功路径在当前业务事务中更新为 applied;失败路径先回滚,再开短事务更新为 failed ApplyResult 或错误 write_requests 状态更新失败时回滚对应事务并返回内部错误 成功状态与业务写入同事务提交;失败状态不复用已回滚事务
系统日志模块 创建运行摘要 开始 Agent 运行记录 后续业务调用 Agent 调用上下文 插入 agent_run_records,状态默认 started agent_run_id agent_run_records 缺少组件名时拒绝 不保存 Prompt
系统日志模块 更新运行终态 结束 Agent 运行记录 agent_run_idstatuserror_code? 更新状态、错误码和 finished_at ok: bool agent_run_records 不存在或越权时返回错误 不保存模型原文

7. Python 数据结构声明

以下结构用于对齐接口字段,不要求作为独立 Python 文件提交。

from datetime import date, datetime
from enum import Enum
from typing import Any, Literal
from uuid import UUID

from pydantic import BaseModel, Field


class ItemType(str, Enum):
    schedule = "schedule"
    todo = "todo"
    subtask = "subtask"


class ItemStatus(str, Enum):
    planned = "planned"
    in_progress = "in_progress"
    completed = "completed"
    cancelled = "cancelled"
    deferred = "deferred"


class GoalStatus(str, Enum):
    active = "active"
    completed = "completed"
    paused = "paused"
    cancelled = "cancelled"
    archived = "archived"


class FeedbackStatus(str, Enum):
    completed = "completed"
    not_completed = "not_completed"
    partially_completed = "partially_completed"
    deferred = "deferred"
    cancelled = "cancelled"


class MessageRole(str, Enum):
    user = "user"
    assistant = "assistant"
    system = "system"
    tool = "tool"


class InputModality(str, Enum):
    text = "text"
    voice_asr = "voice_asr"
    image_ocr = "image_ocr"


class WriteAction(str, Enum):
    create_goal = "create_goal"
    update_goal = "update_goal"
    delete_goal = "delete_goal"
    create_item = "create_item"
    update_item = "update_item"
    delete_item = "delete_item"
    append_feedback = "append_feedback"
    update_user_profile = "update_user_profile"
    save_task_profile_snapshot = "save_task_profile_snapshot"
    apply = "apply"
    apply_replan = "apply_replan"  # 历史兼容;新接口优先 apply


class WriteRequestStatus(str, Enum):
    pending = "pending"
    confirmed = "confirmed"
    rejected = "rejected"
    expired = "expired"
    applied = "applied"
    failed = "failed"


class ProposalStatus(str, Enum):
    draft = "draft"
    pending_confirmation = "pending_confirmation"
    confirmed = "confirmed"
    applied = "applied"
    rejected = "rejected"
    expired = "expired"
    conflict = "conflict"
    failed = "failed"


class ConfirmationDecision(str, Enum):
    confirmed = "confirmed"
    rejected = "rejected"


class AgentRunStatus(str, Enum):
    started = "started"
    succeeded = "succeeded"
    failed = "failed"
    blocked = "blocked"


class ProposalChangeAction(str, Enum):
    create = "create"
    update = "update"
    delete = "delete"


class TaskItemDTO(BaseModel):
    id: UUID
    user_id: UUID
    item_type: ItemType
    title: str
    description: str | None = None
    start_at: datetime | None = None
    end_at: datetime | None = None
    due_at: datetime | None = None
    status: ItemStatus
    long_goal_id: UUID | None = None
    version: int


class CandidateItemDTO(TaskItemDTO):
    match_reason: str | None = None


class LongGoalDTO(BaseModel):
    id: UUID
    user_id: UUID
    title: str
    description: str | None = None
    plan_overview: str | None = None
    review_summary: str | None = None
    start_at: datetime | None = None
    deadline_at: datetime | None = None
    status: GoalStatus
    version: int


class UserProfileDTO(BaseModel):
    user_id: UUID
    profile_data: dict[str, Any]
    source: Literal["user_form", "user_explicit_input"]
    version: int
    updated_at: datetime


class TaskProfileObservationDTO(BaseModel):
    id: UUID
    user_id: UUID
    long_goal_id: UUID
    source: Literal["user_explicit_input", "replan_reason"]
    raw_text: str
    structured_observation: dict[str, Any]
    source_message_id: UUID | None = None
    created_at: datetime


class TaskProfileSnapshotDTO(BaseModel):
    id: UUID
    user_id: UUID
    long_goal_id: UUID
    profile_summary: dict[str, Any]
    version: int
    confirmation_id: UUID
    is_current: bool
    created_at: datetime


class FeedbackRecordDTO(BaseModel):
    id: UUID
    user_id: UUID
    item_id: UUID
    execution_status: FeedbackStatus
    raw_feedback: str
    normalized_feedback: str
    duration_minutes: int | None = None
    occurred_at: datetime
    confirmation_id: UUID
    created_at: datetime


class ConversationMessageDTO(BaseModel):
    id: UUID
    user_id: UUID
    message_index: int
    role: MessageRole
    modality: InputModality | None = None
    raw_content: str
    source_url: str | None = None
    metadata: dict[str, Any]
    created_at: datetime


class SaveConversationMessageRequest(BaseModel):
    user_id: UUID  # 实现时由登录态或母 AI 上下文注入
    role: MessageRole
    raw_content: str
    modality: InputModality | None = None
    source_url: str | None = None
    metadata: dict[str, Any] = Field(default_factory=dict)
    message_index: int | None = None  # 为空则由模块分配下一个序号


class ReplanChangeDraft(BaseModel):
    """创建重排方案时使用;尚无 id / proposal_id。"""

    item_id: UUID | None = None
    action: ProposalChangeAction
    expected_item_version: int | None = None
    before_snapshot: dict[str, Any] | None = None
    after_snapshot: dict[str, Any]
    sort_order: int


class ReplanChangeDTO(BaseModel):
    id: UUID
    proposal_id: UUID
    item_id: UUID | None = None
    action: ProposalChangeAction
    expected_item_version: int | None = None
    before_snapshot: dict[str, Any] | None = None
    after_snapshot: dict[str, Any]
    sort_order: int


class ReplanProposalDTO(BaseModel):
    id: UUID
    user_id: UUID
    long_goal_id: UUID | None = None
    input_snapshot_hash: str
    proposal_summary: dict[str, Any]
    status: ProposalStatus
    created_at: datetime
    updated_at: datetime


class QueryTodayItemsRequest(BaseModel):
    user_id: UUID  # 实现时由登录态注入
    date: date


class QueryTodayItemsResponse(BaseModel):
    items: list[TaskItemDTO]


class QueryGoalsRequest(BaseModel):
    user_id: UUID
    status: GoalStatus | None = None
    include_deleted: bool = False


class QueryGoalsResponse(BaseModel):
    goals: list[LongGoalDTO]


class QueryGoalWithItemsRequest(BaseModel):
    user_id: UUID
    goal_id: UUID


class QueryGoalWithItemsResponse(BaseModel):
    goal: LongGoalDTO
    items: list[TaskItemDTO]


class QueryUserProfileRequest(BaseModel):
    user_id: UUID


class QueryUserProfileResponse(BaseModel):
    profile: UserProfileDTO | None = None


class QueryTaskProfileRequest(BaseModel):
    user_id: UUID
    long_goal_id: UUID


class QueryTaskProfileResponse(BaseModel):
    observations: list[TaskProfileObservationDTO]
    current_snapshot: TaskProfileSnapshotDTO | None = None


class ReviewDataRequest(BaseModel):
    user_id: UUID
    from_time: datetime
    to_time: datetime
    review_type: str | None = None
    goal_id: UUID | None = None


class ReviewDataResponse(BaseModel):
    """实时查询得到的复盘原始事实,不包含复盘报告文本。"""

    items: list[TaskItemDTO]
    feedbacks: list[FeedbackRecordDTO]
    goals: list[LongGoalDTO]


class SaveReplanProposalRequest(BaseModel):
    user_id: UUID
    long_goal_id: UUID | None = None
    trigger_request_id: UUID | None = None
    input_snapshot: dict[str, Any]
    proposal_summary: dict[str, Any]
    changes: list[ReplanChangeDraft]


class AppendTaskProfileObservationRequest(BaseModel):
    user_id: UUID
    long_goal_id: UUID
    source: Literal["user_explicit_input", "replan_reason"]
    raw_text: str
    structured_observation: dict[str, Any]
    source_message_id: UUID | None = None


class UpdateGoalPayload(BaseModel):
    """action=update_goal 的完整操作内容;changes 至少包含一个白名单字段。"""

    long_goal_id: UUID
    changes: dict[str, Any]


class GoalCascadeSubtask(BaseModel):
    item_id: UUID
    expected_item_version: int = Field(gt=0)


class DeleteGoalPayload(BaseModel):
    """服务端生成并写入 hash 的完整长任务删除范围。"""

    long_goal_id: UUID
    cascade_subtasks: list[GoalCascadeSubtask]


class WriteRequestDraft(BaseModel):
    user_id: UUID
    action: WriteAction
    payload: dict[str, Any]
    idempotency_key: str
    target_type: str | None = None
    target_id: UUID | None = None
    base_version: int | None = None
    trace_id: str | None = None


class WriteRequestDTO(BaseModel):
    id: UUID
    user_id: UUID
    action: WriteAction
    target_type: str | None = None
    target_id: UUID | None = None
    payload: dict[str, Any]
    payload_hash: str
    idempotency_key: str
    status: WriteRequestStatus
    base_version: int | None = None
    trace_id: str | None = None
    expires_at: datetime


class ConfirmWriteRequest(BaseModel):
    user_id: UUID
    write_request_id: UUID
    payload_hash: str
    decision: ConfirmationDecision
    client_event_id: str | None = None


class ConfirmWriteResponse(BaseModel):
    confirmation_id: UUID
    write_request_id: UUID
    status: WriteRequestStatus


class ApplyConfirmedWriteRequest(BaseModel):
    user_id: UUID
    write_request_id: UUID
    payload_hash: str


class ApplyResult(BaseModel):
    write_request_id: UUID
    action: WriteAction
    target_type: str | None = None
    target_id: UUID | None = None
    result: dict[str, Any]


class ApplyConfirmedWriteResponse(BaseModel):
    result: ApplyResult


class ValidateItemOwnershipRequest(BaseModel):
    user_id: UUID
    item_id: UUID


class ValidateItemOwnershipResponse(BaseModel):
    owned: bool


class ValidateItemExistsRequest(BaseModel):
    user_id: UUID
    item_id: UUID


class ValidateItemExistsResponse(BaseModel):
    exists: bool


class ValidateTargetUniquenessRequest(BaseModel):
    user_id: UUID
    candidate_condition: dict[str, Any]


class ValidateTargetUniquenessResponse(BaseModel):
    result: Literal["unique", "multiple", "none"]
    candidates: list[CandidateItemDTO] = Field(default_factory=list)


class ValidateWritePrerequisiteRequest(BaseModel):
    user_id: UUID
    write_request_id: UUID
    payload_hash: str


class ValidateWritePrerequisiteResponse(BaseModel):
    allowed: bool
    reason: str | None = None


class StartAgentRunRequest(BaseModel):
    user_id: UUID
    correlation_id: UUID
    component_name: str
    function_name: str | None = None
    source_message_id: UUID | None = None
    trace_id: str | None = None


class FinishAgentRunRequest(BaseModel):
    user_id: UUID
    agent_run_id: UUID
    status: AgentRunStatus
    error_code: str | None = None


class AgentRunRecordDTO(BaseModel):
    id: UUID
    user_id: UUID
    correlation_id: UUID
    trace_id: str | None = None
    component_name: str
    function_name: str | None = None
    status: AgentRunStatus
    error_code: str | None = None
    started_at: datetime
    finished_at: datetime | None = None

8. 数据库查缺补漏表

对照《架构设计MVP阶段数据库设计初稿》逐项检查。结论:核心业务表、确认链路、软删除、重排工作流、画像双表和 Agent 运行摘要表已具备;当前剩余事项主要是成员 3 的实现约定与事务边界,不是 Wiki 或数据库缺表缺字段。

接口 / 函数名称 需要的数据 当前来源 是否可直接获得 是否可推导 缺口类型 建议补充 风险等级
查询今日事项 当前用户当天未删除事项;用户时区 task_items 时间字段;users.timezonetask_items_user_time_idxtask_items_user_due_idx 是,由 date + timezone 推导当天范围 实现时必须用用户时区;日程使用时间索引,待办/子任务使用 due_at 部分索引;默认 is_deleted=false 即可排除已级联软删的子任务
查询事项列表 时间范围、事项类型、状态、软删除过滤条件 task_itemstask_items_user_time_idx;成员 3 统一时间谓词 索引补充 日程使用区间重叠谓词;待办/子任务使用 due_at 窗口谓词;实现迁移新增 (user_id, due_at) 部分索引(仅 todo/subtask 且未软删)
查询事项详情 事项 ID、用户归属、软删除状态、版本 task_items(user_id, id) 复合唯一 HTTP 层从登录态取 user_id;已软删返回 404
查询长任务列表 当前用户长任务、状态、软删除过滤条件 long_goalslong_goals_user_status_idx 提供 list_goals(user_id, status?, include_deleted=false)/api/goals,按 updated_at DESC 返回
查询长任务及子任务 长任务信息、宏观规划、子任务列表 long_goalstask_items_goal_idx 子任务仅通过 long_goal_id 归属,不设计父子树
查询用户画像 画像 JSON、来源、版本 user_profiles 未填写时返回空,不阻塞主流程
查询任务级画像 原始观察 + 当前快照 task_profile_observationstask_profile_snapshots 查询时过滤 is_current=true 快照
查询候选反馈目标 时间范围内可反馈事项 task_items 是,可按时间/类型过滤 索引补充 复用统一时间谓词;todo/subtask 使用 due_at;实现迁移新增 (user_id, due_at) 部分索引
查询复盘关联数据 时间范围内已保存的事项、执行反馈和关联目标 task_itemsfeedback_recordslong_goals 否,MVP 不计算完成率 过滤规则补充 每次复盘实时查询三表;事项按日程重叠或 due_at 落窗筛选;无数据返回空列表;完整复盘报告不入库,目标可返回已保存的 review_summary
查询最近对话消息 最近 N 条原文与 source_url conversation_messagesconversation_messages_window_idx message_index 倒序取、正序返回;媒体二进制不进库
保存对话消息 role、raw_content、modality、source_url、message_index conversation_messages 及 modality/source_url 一致性约束 未提供时可在事务内加锁后分配下一个序号 系统运行记录,无需用户确认;由全局数据模块统一写入;不能用无锁的简单 max+1 处理并发
查询重排方案详情 方案摘要与变更列表 replan_proposalsreplan_proposal_changes 变更修改/删除必须带 expected_item_version
创建写入请求 action、完整 payload、幂等键、过期时间、base_version write_requests;触发器根据完整 payload 生成 payload_hash(user_id, idempotency_key) 唯一 payload_hash 可推导;过期时间由数据库默认值生成 前端不得自造 hash 或过期时间;服务端接收已经完成字段校验的完整 action + payload,再保存候选请求;update_goal 使用 long_goal_id + changes
保存重排候选方案 输入快照及其哈希、变更集 Draft、方案状态 replan_proposalsreplan_proposal_changes input_snapshot_hash 由输入快照推导 入参用 ReplanChangeDraft;模块生成并保存 input_snapshot_hash;确认前可写工作流表;真正改事项必须再走 apply
追加任务级画像原始观察 原始文本、结构化观察、来源 task_profile_observations 只追加不覆盖;不需要确认
记录确认事件 确认请求、hash、decision、client_event_id operation_confirmationswrite_request_id 唯一 一对一约束防重复确认
事务校验并应用写入 已确认请求、目标归属、版本、请求状态 assert_confirmed_write + 目标表 + write_requests 成功路径将业务写入与请求状态 applied 同事务提交;失败先回滚,再开短事务标记请求 failed
确认后新增/修改/软删除事项 事项字段、版本、软删除标记 task_items 及关系触发器 日程时间、子任务归属由数据库触发器兜底
确认后新增长任务/修改/软删除 长任务字段、版本、软删除标记;级联子任务 ID 与版本 long_goalstask_items 成员 3 应用契约 delete_goal 应用时锁定目标和当前子任务,要求集合/版本与确认 payload 完全一致;同事务软删下属 subtask;不物理删除,反馈外键仍有效
确认后追加执行反馈 反馈事件、confirmation_id feedback_records 反馈不直接改 task_items.status
确认后更新用户画像 profile_data、source、version user_profilesprofile_source 枚举 source 仅允许 user_form / user_explicit_input
确认后保存任务级画像 profile_summary、confirmation_id、is_current task_profile_snapshots 新快照确认后需把旧快照 is_current=false;建议应用层同事务处理
确认后更新宏观规划 plan_overview、version;可选同时修改普通长任务字段 long_goals.plan_overview、长任务普通字段 单独或组合修改均使用 update_goal;组合修改一次确认、同事务执行、版本只递增一次
确认后应用重排方案 proposal、changes、application、write_request replan_* + task_items payload 必须含 proposal_id;新接口用 action=apply,兼容 apply_replan
校验事项归属/存在性/唯一性/写入前提 归属、未删除、候选数量、确认状态 task_itemswrite_requestsoperation_confirmations 进程内对外函数;不暴露 HTTP
开始/结束 Agent 运行记录 组件名、状态、trace、correlation agent_run_records 不保存完整 Prompt
保存长任务简洁复盘 long_goal_idreview_summarybase_version 当前数据库初稿的 long_goals 尚无 review_summary 缺字段 long_goals 增加可空 review_summary 文本字段及 500 字限制;通过 update_goal 确认写入,只保留最新摘要
生产数据库权限 运行账号不能直接 DML 业务表 部署配置;SQL 初稿只声明原则 缺部署授权规则 部署时收敛应用账号权限,只允许 repository/service 或受控函数写入

8.1 长任务简洁复盘字段(成员 3 补充)

long_goals.review_summary 是成员 3 针对“长任务保留一条简洁复盘”的新增字段级契约,不是三份 Wiki 已定义的固定字段。字段允许为空,最多 500 字;每个长任务只保留最新摘要,更新时覆盖旧值,不保存完整复盘报告和摘要历史。

该字段属于长任务业务事实,写入必须使用现有 action=update_goalchanges.review_summarybase_version 和用户确认链。数据库设计落地时需在 long_goals 增加可空文本字段及长度/非空校验,并在 LongGoalDTO、长任务详情/列表和复盘关联数据中返回;三份 Wiki 原文保持不变。

9. 风险说明

风险 表现 处理方式
前端伪造确认 只传 is_confirmed=true 就直接写入业务表 禁止布尔确认;必须校验 write_request_idoperation_confirmationspayload_hash、过期时间和用户归属
前端伪造用户 ID 请求体携带他人 user_id 读数据 HTTP 层从登录态注入用户;查询默认带当前用户范围
LLM 猜错数据库主键 用户说“把刚才那个任务删掉”,模型直接猜一个 ID 母 AI 必须先调用全局数据模块查候选 / 校验目标唯一性;单候选才继续,多候选触发反问,无候选要求补充信息
并发修改导致覆盖 用户确认前,目标事项已被其他操作改过 更新和删除必须带 base_version;重排变更带 expected_item_version;冲突时返回 version_conflict
重复点击确认或重复提交 同一个请求被应用多次 operation_confirmations.write_request_id 唯一;write_requests.idempotency_key 对同一用户唯一;已应用请求不可再次应用
重排部分成功 十条变更写到一半失败 同事务应用;任一条版本冲突则整单回滚,方案标记冲突并要求重新生成
软删除实现不完整 删除时漏写 deleted_atversion;普通查询仍返回已删除对象;误删关联反馈 删除操作只更新 is_deleted=truedeleted_atversion,不物理删除业务对象,也不修改关联反馈;普通查询默认过滤 is_deleted=false
长任务软删后子任务仍可见 只软删目标、忘记级联子任务,今日事项仍出现旧子任务 确认后软删除长任务必须同事务调用「级联软删长任务子任务」;任一步失败整单回滚
update_goal 变更范围不透明 AI 额外加入用户未要求的普通字段、宏观规划或简洁复盘摘要;组合修改未完整展示 payload 只允许 long_goal_id 和白名单 changes;确认卡片逐项展示全部差异;hash 覆盖完整 payload;组合修改同事务执行
简洁复盘误存完整报告 review_summary 过长、包含完整报告,或覆盖用户未确认的旧摘要 限制为不超过 500 字;写入前展示新旧摘要差异并确认;只保存最新摘要,不保存完整报告或历史版本
运行摘要泄露隐私 把完整 Prompt、模型响应或敏感原文写入业务库 agent_run_records 只保存组件、函数、状态、错误码、时间和链路 ID;完整调用链交给 LangSmith
数据库权限过大 应用账号绕过全局数据模块直接改表 部署时限制运行账号,不授予核心业务表直接 INSERT/UPDATE/DELETE 权限

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions