# Dayline — Agent 接入说明

Dayline 是一个 Agent-native 的每日时间安排器。用户在网页上查看时间线；Agent 通过 MCP 或 REST 读取上下文并写入日程。

- MCP 端点：`https://day.gongzhui.me/api/mcp`（Streamable HTTP，无状态）
- REST 基址：`https://day.gongzhui.me/api/v1`
- 鉴权：`Authorization: Bearer dl_...`，在「设置 → Agent 访问令牌」创建。一个 Agent 一个令牌，写入会标注来源。
- 时间：一律使用用户时区（profile.timezone）的本地 24 小时制 `HH:MM`；日期 `YYYY-MM-DD`。

## 推荐流程

1. `get_context` —— 一次拿到：当前时间、作息窗口、偏好、目标日已有安排、任务池、近 7 天完成情况、规划指南。
2. 在对话里给用户看草案（可选）。
3. `set_day_plan` 写入整天（mode=replace）。检查返回的 `warnings`，用 `update_block` 修正。
4. 当天执行中：`update_block` 标记 active/done/skipped；落后时调用 `reflow_day`。

## 数据模型

**Block（时间块）**

| 字段 | 说明 |
|---|---|
| start / end | `HH:MM`，end > start |
| title / notes | 标题 / 细节与理由 |
| kind | focus 深度工作 · task 普通任务 · event 会议课程等 · routine 吃饭通勤运动 · break 休息 · buffer 缓冲 |
| flex | fixed 固定不动 · movable 可顺延、可压缩 · optional 放不下时最先推迟（event 默认 fixed，buffer 默认 optional） |
| min_duration | 可压缩到的最短分钟数，留空=不可压缩 |
| priority | 1 高 · 2 中 · 3 低 |
| status | planned · active · done · skipped · deferred |
| task_id | 关联任务池条目；block 完成时任务自动完成 |

**Task（任务池）**：title, notes, estimate_min, priority, due_date, status(open/done/dropped)。

**Profile**：timezone, day_start, day_end, preferences（自由文本，Agent 规划前必读）。

## 弹性机制（reflow）

`reflow_day` 从「现在」起重排当天剩余部分：

- 只往后推，不往前拉；提前完成就是多出来的空闲。
- 已过开始时间但未开始的块顺延到现在；进行中的块若超时则延长到现在。
- buffer 块先被吃掉，吸收延误，不会继续把后面的块往后推。
- fixed 块不动；可移动块遇到 fixed 块时，能压缩到 min_duration 就压缩，否则跳到它之后。
- 超出 day_end 时，先推迟 optional（低优先级、较晚的先走），仍放不下的可移动块标记为 deferred。

## MCP 工具

| 工具 | 作用 |
|---|---|
| get_context(date?) | 规划所需的全部上下文（从这里开始） |
| get_day(date) | 某天的块、说明、统计、警告 |
| set_day_plan(date, blocks[], summary?, mode?) | 写入整天安排 |
| add_block(date, …block) | 追加一个块 |
| update_block(id, …patch) | 修改块的任意字段 / 状态 |
| delete_block(id) | 删除块（更推荐 status=skipped） |
| reflow_day(date, at?) | 弹性重排 |
| list_tasks(status?) / create_task / update_task | 任务池 |
| update_profile | 修改作息与偏好（仅在用户要求记住时） |

Prompt：`plan_day(date?, notes?)`。

## REST 接口

| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/v1/context?date= | 同 get_context |
| GET | /api/v1/days/{date} | 同 get_day |
| PUT | /api/v1/days/{date} | body 同 set_day_plan：`{summary, blocks, mode}` |
| PATCH | /api/v1/days/{date} | `{summary}` |
| POST | /api/v1/days/{date}/blocks | 新增块 |
| POST | /api/v1/days/{date}/reflow | `{at?}` |
| PATCH / DELETE | /api/v1/blocks/{id} | 修改 / 删除块 |
| GET / POST | /api/v1/tasks?status= | 列表 / 新建任务 |
| PATCH / DELETE | /api/v1/tasks/{id} | 修改 / 删除任务 |
| GET / PATCH | /api/v1/profile | 作息与偏好 |

错误统一返回 `{error, message?, issues?}`，状态码 400 / 401 / 404。

### 示例

```bash
curl -X PUT https://day.gongzhui.me/api/v1/days/2026-09-28 \
  -H "Authorization: Bearer $DAYLINE_TOKEN" -H "Content-Type: application/json" \
  -d '{
    "summary": "上午写论文，下午组会后做仿真；跑步设为可选。",
    "blocks": [
      {"start":"09:00","end":"11:00","title":"论文第三节","kind":"focus","min_duration":60},
      {"start":"11:00","end":"11:20","title":"缓冲","kind":"buffer"},
      {"start":"14:00","end":"15:00","title":"组会","kind":"event"},
      {"start":"19:30","end":"20:15","title":"跑步","kind":"break","flex":"optional"}
    ]
  }'
```

## 规划指南

How to plan a Dayline day:
1. Respect profile.day_start/day_end and profile.preferences. Times are local (profile.timezone), 24h HH:MM.
2. Put hard commitments in first as kind "event" with flex "fixed".
3. Schedule the most demanding work ("focus") in the user's energy peak; keep focus blocks 50–120 min.
4. After every 2–3 hours of work add a "buffer" block (15–30 min). Buffers absorb overruns when the day is reflowed.
5. Mark nice-to-haves flex "optional"; give movable blocks a min_duration if they can be shortened.
6. Pull from open_tasks (set task_id) and carry over recent_days[].unfinished when still relevant.
7. Leave ~20% of the window unplanned. Include meals/breaks as "routine"/"break".
8. Write a 1–3 sentence summary explaining the plan's intent and what was left out.
9. Submit with set_day_plan (mode "replace"). Check the returned warnings and fix overlaps.
