{
  "openapi": "3.1.0",
  "info": {
    "title": "Homeboard / 在家 — Agent API",
    "version": "1.0.0",
    "description": "私人电视信息面板的授权数据接口。读取本定义不授予写入权限；必须由用户提供凭证并授权操作。JSON 请求体最多 8192 字节。成功后电视自动同步；不要编造个人数据。"
  },
  "servers": [
    {
      "url": "https://homeboard-yijun.pages.dev",
      "description": "正式个人面板。不要自行改用预览域名。"
    }
  ],
  "externalDocs": {
    "description": "Agent 操作指南",
    "url": "https://homeboard-yijun.pages.dev/agent-guide.md"
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/api/snapshot": {
      "get": {
        "operationId": "getBoardSnapshot",
        "summary": "读取当前面板",
        "description": "读取数据以定位记录、确认结果。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/todos": {
      "post": {
        "operationId": "addReminder",
        "summary": "新增短提醒",
        "description": "建议提供 id 以避免网络重试产生重复；同 ID 内容冲突返回 409。最多 500 条，包括已完成项。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReminderInput"
              }
            }
          }
        }
      }
    },
    "/api/todos/{id}": {
      "patch": {
        "operationId": "setReminderDone",
        "summary": "完成或重新打开提醒",
        "description": "完成使用 done=true；不要默认永久删除。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReminderStatusInput"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "先读取快照取得准确 ID，不能仅凭名称猜测。"
          }
        ]
      },
      "delete": {
        "operationId": "deleteReminder",
        "summary": "永久删除提醒",
        "description": "只在用户请求永久删除时执行；不存在返回 404。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "先读取快照取得准确 ID，不能仅凭名称猜测。"
          }
        ]
      }
    },
    "/api/sleep": {
      "put": {
        "operationId": "upsertSleepRecord",
        "summary": "按日期保存真实睡眠",
        "description": "同日期覆盖。时长是实际睡眠分钟数，不是卧床时间。当前 source 固定为 manual。最多保留最近 90 个日期。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SleepInput"
              }
            }
          }
        }
      }
    },
    "/api/sleep/{date}": {
      "delete": {
        "operationId": "deleteSleepRecord",
        "summary": "删除睡眠记录",
        "description": "不存在的日期也可成功；先核实用户意图。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "date",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ]
      }
    },
    "/api/content": {
      "post": {
        "operationId": "addExplorationItem",
        "summary": "加入书影音内容",
        "description": "最多 12 项。主动收藏 origin=saved；Agent 推荐 origin=agent 且必须附具体 reason。同 id 与相同内容可安全重试。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExplorationInput"
              }
            }
          }
        }
      }
    },
    "/api/content/{id}": {
      "delete": {
        "operationId": "deleteExplorationItem",
        "summary": "移除书影音内容",
        "description": "不存在也可成功；不能为腾空间自行删除用户收藏。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "先读取快照取得准确 ID，不能仅凭名称猜测。"
          }
        ]
      }
    },
    "/api/presentation": {
      "put": {
        "operationId": "setPresentationFocus",
        "summary": "切换已有展示重点",
        "description": "旧版兼容设置。新版原生电视固定显示总览，不据此隐藏模块。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PresentationInput"
              }
            }
          }
        }
      }
    },
    "/api/help": {
      "get": {
        "operationId": "getAgentHelp",
        "summary": "公开能力与接入说明",
        "security": [],
        "responses": {
          "200": {
            "description": "公开指南链接和能力列表，不含私人数据或密钥。",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "checkService",
        "summary": "检查服务可达性",
        "security": [],
        "responses": {
          "200": {
            "description": "就绪状态，不含私人数据。",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "service": {
                      "type": "string"
                    },
                    "version": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/events/{id}": {
      "put": {
        "operationId": "upsertEvent",
        "summary": "保存或更新近期日程",
        "description": "8–80 字符稳定 ID，同一 ID 覆盖；同请求重试幂等。最多 200 项，不会自动删除过期项。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]{8,80}$"
            },
            "description": "新日程生成 UUID；更新和重试复用原 ID。"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventInput"
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteEvent",
        "summary": "删除指定日程",
        "description": "不存在也成功；需要用户授权。",
        "responses": {
          "200": {
            "description": "最新完整快照。应检查 ID 和字段以确认操作成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Snapshot"
                }
              }
            }
          },
          "400": {
            "description": "参数错误，查看 error。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "需要有效 Bearer 凭证。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "凭证只读或请求 Origin 不允许。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "接口或提醒 ID 不存在。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "容量上限或 ID 冲突。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "服务暂时不可用，不得报告成功。",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "先读取快照取得准确 ID，不能仅凭名称猜测。"
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "用户提供的管理访问码。只读电视码不能写入。不是 Cloudflare token；不要放进 URL。"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "ReminderInput": {
        "type": "object",
        "required": [
          "text"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{8,80}$",
            "description": "建议生成 UUID。同一次新增重试时必须复用同一 ID。"
          },
          "text": {
            "type": "string",
            "maxLength": 300,
            "minLength": 1,
            "description": "用户的一句短提醒；无需日期或优先级。"
          }
        }
      },
      "ReminderStatusInput": {
        "type": "object",
        "required": [
          "done"
        ],
        "additionalProperties": false,
        "properties": {
          "done": {
            "type": "boolean"
          }
        }
      },
      "SleepInput": {
        "type": "object",
        "required": [
          "date",
          "durationMinutes"
        ],
        "additionalProperties": false,
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "description": "起床所在用户本地日期；同日期 PUT 将覆盖。"
          },
          "durationMinutes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1440,
            "description": "真实睡眠分钟数，不能从卧床间隔推断。"
          },
          "bedtime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "带明确时区的 ISO 8601 时间；存储时规范化为 UTC。"
          },
          "wakeTime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "带明确时区的 ISO 8601 时间；存储时规范化为 UTC。"
          },
          "note": {
            "type": "string",
            "maxLength": 300
          }
        }
      },
      "ExplorationInput": {
        "type": "object",
        "required": [
          "title",
          "kind"
        ],
        "additionalProperties": false,
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{8,80}$",
            "description": "建议生成 UUID。同一次新增重试时必须复用同一 ID。"
          },
          "title": {
            "type": "string",
            "maxLength": 120,
            "minLength": 1
          },
          "kind": {
            "type": "string",
            "enum": [
              "book",
              "film",
              "series",
              "other"
            ]
          },
          "imageUrl": {
            "type": "string",
            "maxLength": 2048,
            "pattern": "^https://",
            "description": "可省略；不得包含用户名密码。使用真实封面，不猜测地址。"
          },
          "note": {
            "type": "string",
            "maxLength": 300
          },
          "origin": {
            "type": "string",
            "enum": [
              "saved",
              "agent"
            ],
            "default": "saved",
            "description": "用户主动选择用 saved；Agent 独立推荐用 agent。"
          },
          "reason": {
            "type": "string",
            "maxLength": 300,
            "description": "origin=agent 时必须提供 1–300 字的具体推荐理由。"
          }
        },
        "allOf": [
          {
            "if": {
              "required": [
                "origin"
              ],
              "properties": {
                "origin": {
                  "const": "agent"
                }
              }
            },
            "then": {
              "required": [
                "reason"
              ],
              "properties": {
                "reason": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 300
                }
              }
            }
          }
        ]
      },
      "PresentationInput": {
        "type": "object",
        "required": [
          "focus"
        ],
        "additionalProperties": false,
        "properties": {
          "focus": {
            "type": "string",
            "enum": [
              "auto",
              "reminders",
              "sleep",
              "explore"
            ]
          }
        }
      },
      "Todo": {
        "type": "object",
        "required": [
          "id",
          "text",
          "done",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "done": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SleepRecord": {
        "type": "object",
        "required": [
          "date",
          "durationMinutes",
          "source",
          "updatedAt"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "description": "起床所在用户本地日期；同日期 PUT 将覆盖。"
          },
          "durationMinutes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1440,
            "description": "真实睡眠分钟数，不能从卧床间隔推断。"
          },
          "bedtime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "带明确时区的 ISO 8601 时间；存储时规范化为 UTC。"
          },
          "wakeTime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "带明确时区的 ISO 8601 时间；存储时规范化为 UTC。"
          },
          "note": {
            "type": "string",
            "maxLength": 300
          },
          "source": {
            "type": "string",
            "enum": [
              "manual"
            ]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ExplorationItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "book",
              "film",
              "series",
              "other"
            ]
          },
          "imageUrl": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "origin": {
            "type": "string",
            "enum": [
              "saved",
              "agent"
            ]
          },
          "reason": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Snapshot": {
        "type": "object",
        "required": [
          "todos",
          "sleep",
          "content",
          "presentation",
          "updatedAt",
          "serverTime",
          "events"
        ],
        "properties": {
          "todos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Todo"
            },
            "maxItems": 500
          },
          "sleep": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SleepRecord"
            },
            "maxItems": 90
          },
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExplorationItem"
            },
            "maxItems": 12
          },
          "presentation": {
            "$ref": "#/components/schemas/PresentationInput"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "serverTime": {
            "type": "string",
            "format": "date-time"
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "display"
            ],
            "description": "仅 GET snapshot 返回。"
          },
          "events": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/Event"
            }
          }
        }
      },
      "EventInput": {
        "type": "object",
        "required": [
          "date",
          "title"
        ],
        "additionalProperties": false,
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "description": "事件在电视本地的日期，不自动重复。"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          }
        }
      },
      "Event": {
        "type": "object",
        "required": [
          "id",
          "date",
          "title",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date",
            "description": "事件在电视本地的日期，不自动重复。"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}
