← 返回
未分类

大学生内阁

你的大学生深度个人管家。管课表、管日程(事件+事项)、理账本、追进度、便签备忘、习惯库,大学生活全包。
你的大学生深度个人管家。管课表、管日程(事件+事项)、理账本、追进度、便签备忘、习惯库,大学生活全包。
user_2e5cec3f
未分类 community v2.6.5 10 版本 100000 Key: 无需
★ 0
Stars
📥 114
下载
💾 0
安装
10
版本
#latest

概述

大学生内阁 — 你的深度个人管家

管课表、管日程(事件+事项)、理账本、追进度、便签备忘、习惯库。一个 skill,五个 JSON,一份习惯文档。

> 前身为「课搭子(Course Buddy)」。从课搭子 v1.x 迁移的用户,将 skills/course-buddy/data/ 下 JSON 移至 skills/college-cabinet-data/ 即可无缝升级(学习计划和便签为后续新增文件,旧版无对应文件则跳过)。数据格式完全兼容。

目录

基础

模块

系统

这是什么

大学不止上课。课表轮换、实验分组、DDL 追命、通知轰炸、账目乱飞——靠脑袋记早晚崩。

大学生内阁做的事:课表、日程(含事件和事项)、账本、学习计划、便签各一个 JSON,外加一份习惯文档(habits.md)。查课表自动算周次、过假期、理补课;实验轮换自动展开,只显示你那一组。日程(含事件和事项)统一从 schedule.json 读出,event 按时段筛选,longterm 按截止日显示,逾期着重标注。记账自动更新余额,转账双记防漏。学习计划自定义 task,每日量化追踪。习惯库用自然语言记录条件规则,LLM 在简报时自动判断。通知原文粘贴进来,自动提取事项、判断人群归属、写入。

> v2.0.0 日程重构为事件+事项两种类型、新增 alert 按时提醒、学习计划全新 task 量化模型、weekday 0→1 基、课表查询压缩、防幻觉与日期锚定、自定义简报模块。旧数据自动迁移。

日期校准

所有涉及日期、星期、课程、简报的操作,第一步必须调用 current_status(action=get, key=time) 获取服务器实时时间,以此为唯一基准。后续所有日期计算基于此结果,不得沿用对话历史或上下文中的日期快照。

当天是周几的判断:weekday = isoweekday(日期),1=周一~7=周日。

重复事件展开

所有涉及日程查询的操作(简报或对话),读取 schedule.json events 时,必须同时检查所有 status=active 的 repeat 事件,按当前日期展开为具体实例。events 数组中的单次条目不足以代表当日全部日程。

展开规则:

  • 按 repeat.type(daily/weekly/interval)和当前日期计算是否命中
  • 命中日检查 overrides:status=cancelled 则跳过,含 time/location/note 则覆盖母体对应字段
  • 展开结果与 events 中的单次条目合并,按 time_start 排序
  • 未命中或无 repeat → 仅使用 events 中的单次条目

版本检查(必读)

每次本 skill 被加载时,在响应用户任何请求之前,必须先完成以下检查。涉及数据安全的步骤必须完成,不得跳过。

步骤

  1. 读取 _meta.json,获取 skill 当前版本号
  2. 检查 ../college-cabinet-data/ 目录是否存在:
    • 目录不存在 → 创建目录并初始化全部空模板文件(见下方「数据文件」表),然后执行新手引导流程(见下方「新手引导」)
    • 目录存在但缺文件 → 补建缺失的空模板
    • 有数据文件 → 继续下一步
  3. 读取各数据文件,检查格式版本是否与当前 skill 版本匹配:
    • 数据版本落后 → 执行自动迁移(见"升级与兼容→自动迁移")
    • 迁移完成 → 继续下一步
  4. 若 skill 版本高于用户数据中的记录版本(即发生了升级),向用户展示本次更新内容:
    • 读取 README.md 中最新的版本号对应的 changelog 条目
    • 用一两句话概括告知用户
    • 示例:「大学生内阁已升级至 v2.4.0。主要更新:模块统一命名、事项逾期着重显示、便签备忘、日程机动时间。」

以上步骤完成后,再处理用户的正常请求。

禁止行为:跳过版本检查直接响应用户请求。用户说"今天有什么课"不代表可以跳过迁移——先查版本、再回答。

新手引导

当版本检查发现无数据文件时,按以下顺序逐模块引导用户完成初始化。每完成或跳过一个模块再进入下一个,不要一次抛出所有。用户说「不用了」「先跳过」「以后再说」即终止引导流程。

引导规则

开场(发现无数据时先说这一句)

> 我是大学生内阁,帮你管课表、日程、记账、学习进度和便签。你现在还没数据,我带你搭起来?

按顺序引导

  1. 课表:一切的基础。有了课表才能查今天有什么课、简报才能自动推。

> 课表是基础,你有课表截图或文字吗?发给我录进去。录好以后自动算周次、跳过假期、实验分组只显示你那一组。

> 试试:「解析我的课表」+ 贴过来

  1. 记账:建账户后说「午饭食堂 12 块 校园卡」自动记账扣款。

> 你有几个常用支付渠道?校园卡、微信、银行卡,告诉我名字和余额,我帮你建好。

> 试试:「建两个账户:校园卡余额 500,微信余额 300」

  1. 日程:有时段的叫事件(按时提醒),有截止日的叫事项(逾期会标出来)。

> 日程分两种。有时段的活动直接说时间地点,有截止日的作业说哪天前交。到点提醒,逾期了在简报里标 ⚠️。

> 试试:「5月20日 14:00 排练 化一教室」或者「下周三交无机作业」

  1. 学习计划:自定义目标,每天追进度。

> 要备考或者刷网课?设个目标,系统每天帮你追进度。

> 试试:「我要备考英语四级,每天背 50 个单词」

  1. 便签:放不进上面任何一类的碎碎片备忘,随手贴。

> 还有一些零碎的备忘——老师提了篇文献、同学说了个选课技巧——随手记在便签板上就行。

> 试试:「记一下:张珉上课提了篇 JACS 文献」

  1. 习惯库:条件规则和行为模式,LLM 自动判断触发。

> 有些规律不是简单的定时重复——考试周跳过组会、下雨提前出门、实验课当天提醒带实验服。这些写在习惯库里,AI 每次简报时自动判断。

> 试试:「记住:实验课当天早上提醒我带实验服和护目镜」

  1. 简报:课表已经录了就问要不要设自动推送。没录课表则跳过。

> 课表录好了,要不要每天早上自动推今日课表和日程?也可以午间推下午课、晚上推明天安排。

> 试试:「设置提醒」

终止条件

  • 用户说「不用了」「先跳过」「以后再说」→ 停止引导,告知「随时说『设置提醒』就能配置」
  • 引导过程中用户提出其他请求(如直接查课、记账)→ 先处理请求,当前模块引导暂停
  • 全部模块引导完毕 → 不额外总结,告知「以上几个是核心模块,随时说你要做什么就行」

快速上手

  1. 创建 skills/college-cabinet-data/ 目录(与 skill 目录平级,不在 skill 目录内)
  2. 初始化五个 JSON 和一个 Markdown:
    • schedule.json{"version":"4.0","reminder":{"briefings":[{"id":"morning","time":"06:40","modules":["courses","schedule","insight"]},{"id":"noon","time":"12:40","modules":[{"id":"courses","range":"remaining"},{"id":"schedule","range":"remaining"},"insight"]},{"id":"evening","time":"19:00","modules":[{"id":"courses","range":"tomorrow"},{"id":"schedule","range":"tomorrow"},"insight"]},{"id":"night","time":"22:00","modules":["schedule","ledger","notes","insight"]}],"advance":{"longterm":{"urgent_days":3}},"custom_modules":[]},"events":[]}
    • ledger.json{"version":"1.0","accounts":[],"transactions":[]}
    • courses.json → 见下方课表章节
    • study_plans.json{"version":"2.0","plans":[]}
    • notes.json{"version":"1.0","notes":[]}
    • habits.md → 见下方习惯库章节(含模板内容,复制到文件中即可)
  3. 把课表文本或文件发给 AI,让它解析并写入 courses.json
  4. 问一句"今天有什么课"验证

> 从课搭子迁移:直接将原 skills/course-buddy/data/ 下 JSON 复制到 skills/college-cabinet-data/,无需格式转换。学习计划和便签为后续新增,旧版无对应文件则跳过。

数据文件

文件内容
------------
../college-cabinet-data/schedule.json日程(事件+事项)
../college-cabinet-data/ledger.json账户与交易
../college-cabinet-data/courses.json学期课表(含实验轮换和调停课)
../college-cabinet-data/study_plans.json学习计划(自定义 task,量化进度追踪)
../college-cabinet-data/notes.json便签(纯文本碎片备忘)
../college-cabinet-data/habits.md习惯库(条件规则和行为模式,LLM 读取解释)

五个 JSON 是各自领域的唯一数据源。habits.md 是 LLM 的行动指南,不替代任何数据文件。数据目录位于 skill 目录外,随版本更新不丢失。memory 文件只记对话摘要,不从中提取结构化数据。


一、学习

课表和学习计划统一管理。课表是学校安排的课程,学习计划是自己定制的备考、网课等。

课表(courses.json)

学期课程,含单双周、实验轮换、调停课。

完整结构

{
  "version": "2.0",
  "semester": "2026年春季学期",
  "first_week_date": "2026-03-09",
  "total_weeks": 16,
  "time_slots": [
    {"slot": "1-2", "start": "08:00", "end": "09:30"},
    {"slot": "3-4", "start": "10:00", "end": "11:30"},
    {"slot": "5-6", "start": "13:30", "end": "15:00"},
    {"slot": "7-8", "start": "15:30", "end": "17:00"},
    {"slot": "9-10", "start": "17:30", "end": "19:00"},
    {"slot": "11-12", "start": "19:30", "end": "21:00"}
  ],
  "holidays": [
    {"name": "劳动节", "start": "2026-05-01", "end": "2026-05-05"}
  ],
  "makeup_days": [
    {"date": "2026-05-09", "replace_weekday": 2}
  ],
  "courses": [
    {
      "name": "大学物理实验B",
      "weekday": 3,
      "time_start": "08:00",
      "time_end": "11:30",
      "weeks": [2,3,4,5,6,7,8,9,10,11,12,13],
      "location": "分组实验",
      "teacher": "",
      "parallel": true,
      "group": 1,
      "schedule": {
        "2": {"topic": "基本力学量测量", "location": "201室", "teacher": "高志华"},
        "3": {"topic": "单摆运动", "location": "229室", "teacher": "周亚洲"}
      },
      "overrides": {
        "11": {"status": "cancelled", "note": "临时停课"},
        "5": {"linked_notes": ["n-015"]}
      },
      "linked_notes": ["n-003", "n-007"]
    }
  ]
}

字段说明

必填:name、weekday(1=周一~7=周日)、time_start、time_end、weeks、location、teacher。

可选:parallel(分组实验)、group(组号)、schedule(每周不同内容,键为周次编号)、overrides(单周例外,键为周次编号)、linked_notes(关联便签 id 列表)。

linked_notes:存放 notes.json 中的便签 id。课程级的 linked_notes 每节实验课都显示,overrides 级的 linked_notes 仅在对应周显示。典型用法:实验课每节都要带实验服 → 课程级;某周代交报告 → overrides 级。字段可选,缺省即无关联便签。

顶层可选:time_slots(课节映射表)。每条含 slot(显示名如 "1-2")、start(起始时间)、end(结束时间)。配置后输出优先用课节名,未匹配时回退到时段时间。

overrides.status 合法值:

  • cancelled:该周不上课
  • room_change:教室变更(仅覆盖 location)

顺延不是 override 打补丁。用户说"本周顺延到下周"时,直接改数据:本周标 cancelled,下周的 schedule 写入顺延过来的内容(若下周已有同名课程则追加为第二条记录)

查询课表时的优先级

对周次 W,确定具体内容的优先级:

  1. overrides[W].status = "cancelled" → 该周不上课,跳过
  2. overrides[W].status = "room_change" → 教室替换为 overrides 中的值
  3. schedule[W] 有值 → 使用 schedule 中的 topic、location、teacher
  4. 否则 → 使用 course 默认的 location、teacher

查询特定周的课时,同时读取关联便签:课程级 linked_notes + overrides[W].linked_notes 合并去重(课程级先、overrides 级后),从 notes.json 读取对应 content。overrides 级的便签在输出中标注「仅本周」以区分常驻便签。

计算当前周次

当前周 = floor((今天 - first_week_date) / 7) + 1

查询某一天的课表

核心原则:课程信息仅来自 courses.json,绝不推测或编造。无匹配则输出"这天没有课"。

  1. 日期锚定:确认今天日期(年-月-日 + 星期几,1=周一~7=周日)。计算当前周次
  2. 筛选:假期→全部跳过。补课日→替换 weekday。筛选 weekday 匹配且 weeks 包含当前周次的课程。weeks 不含→跳过,不保留
  3. 优先级:overrides → schedule → 默认值
  4. 排序:按 time_start
  5. 验证:输出前逐条确认课程名、时间、地点均来自 courses.json。结果为空→"这天没有课"

实验课轮换

当用户提供轮换表、分组名单、或每周具体安排时:

  1. 确认用户组号
  2. 解析轮换规则(每组每周对应的教师/题目/教室)
  3. 为每门实验课生成整学期的 schedule
  4. 将 schedule 写入 courses.json
  5. 临时变动写入 overrides

同一时段同名课程有多条记录时,标注 parallel: true。查询时合并显示为一行。用户告知分组后只显示对应那组的内容。

学期切换

新课表来了 → 解析生成新的 courses.json 覆盖。旧文件改名为 courses-上赛季名称.json 备份。


学习计划(study_plans.json)

管理备考、网课、阅读等学习计划。字段全部由用户自定义,无预设分类。

结构

{
  "version": "2.0",
  "plans": [
    {
      "id": "cet4",
      "title": "英语四级",
      "deadline": "2026-06-13",
      "status": "active",
      "tasks": [
        {
          "id": "word",
          "name": "单词速刷",
          "goal": 55,
          "unit": "组",
          "per_day": 3,
          "done": 15,
          "log": [
            {"date": "2026-05-22", "count": 3},
            {"date": "2026-05-23", "count": 2}
          ]
        },
        {
          "id": "essay",
          "name": "范文背诵",
          "goal": 30,
          "unit": "篇",
          "per_day": 2,
          "done": 0,
          "log": []
        }
      ],
      "note": ""
    }
  ]
}

字段说明

plan

字段必填说明
------------------
id唯一标识,英文
title计划名称
deadline截止/考试日期,仅作参考
statusactive / paused / done
tasks任务数组,每个计划至少一个 task
note备注

task

字段必填说明
------------------
id唯一标识,英文
name任务名称。用户自定,如 单词速刷 每日阅读 刷题
goal目标总量
unit单位。用户自定,如 min
per_day每日标准量。不填则无固定节奏
done累计完成量。等于 log[].count 之和,由 AI 自动维护
log每日完成记录数组

log 条目

字段必填说明
------------------
date日期,YYYY-MM-DD
count当天完成量

创建计划

用户描述学习计划时,AI 创建 plan 并定义 tasks:

  • "我要备考六级,每天背 50 个单词,总共 2000 个" → plan: id=六级, task: name=背单词, goal=2000, unit=个, per_day=50
  • "再加一个每日听力 30 分钟" → 同名 plan 下追加 task: name=听力, goal=∞?, unit=min, per_day=30

用户完全自定义 task 的名称、单位、目标量、每日量。无预设模板。

更新进度

用户报告进度时,AI 追加 log 条目并更新 done:

用户说做什么
----------------
"单词背了 3 组"追加 log {date:今天, count:3},done+=3
"今天单词只背了 1 组"同上,count=1
"单词到 15 组了"若累计 done 不符,追加差异条目使 done=15
"四级进度怎么样"列出所有 tasks:name done/goal unit
"今天单词做了没"查 log 中今日是否有记录

每日待办量 = per_day − 今日 log 中已记录 count。若正数则为待办,若零或负则今日已完成。done 达 goal 时 AI 主动提示完成。

简报输出

study 模块分两段:

📚 今日学习
10:00-11:30 无机化学 化一教室
▸ 英语四级:单词×3组 · 听力×1

📊 学习进度
英语四级:单词 15/55组 · 听力 3/24套

今日任务段:课表课程 + 学习计划中 per_day>0 且今日未完成的 tasks。进度段:所有 active 计划的 tasks 进度概览。

已存在的 .md 格式学习计划(如 课程学习计划/英语四级.md),用户说"把这个导入学习计划" → AI 解析 .md 内容并结构化写入。


二、日程(schedule.json)

术语锚定:日程 = schedule.json 的全部内容。日程下分两种子类型:事件(type=event)和事项(type=longterm)。type 字段只有这两个值,禁止其他任何值。

type中文名特征提醒方式
------------------------
event事件时段或时刻简报提醒(按 range 窗口)+ 按时提醒(默认准时,可选提前)
longterm事项日期(可选时刻)简报提醒(按 range 窗口),无按时提醒

课程不进入 schedule,课表由 courses.json 独立管理。

结构

{
  "version": "4.0",
  "events": [
    {
      "id": "s-20260517-001",
      "date": "2026-05-17",
      "title": "排练",
      "type": "event",
      "time": "14:00-16:00",
      "location": "化一教室",
      "status": "active",
      "pinned": false,
      "alert": {"on_time": true, "advance_minutes": 10},
      "note": ""
    },
    {
      "id": "s-20260518-001",
      "date": "2026-05-18",
      "title": "组会",
      "type": "event",
      "time": "14:00-16:00",
      "location": "化学楼301",
      "status": "active",
      "pinned": false,
      "repeat": {
        "type": "weekly",
        "weekdays": [3],
        "end_date": "2026-07-01"
      },
      "note": ""
    },
    {
      "id": "s-20260518-042",
      "date": "2026-05-18",
      "title": "家教",
      "type": "event",
      "time": "10:00-12:00",
      "lead_min": 30,
      "trail_min": 30,
      "location": "南湖",
      "status": "active",
      "pinned": false,
      "note": ""
    },
    {
      "id": "s-20260613-001",
      "date": "2026-06-13",
      "title": "英语四级考试",
      "type": "longterm",
      "time": "09:00",
      "location": "",
      "status": "active",
      "pinned": true,
      "note": "带准考证和耳机",
      "linked_notes": ["n-010"]
    }
  ]
}

字段说明

字段必填说明
------------------
id唯一标识,格式 s-YYYYMMDD-序号
date日期,YYYY-MM-DD
title事件名称
typeeventlongterm。禁止其他任何值
time看 typeevent 用时段 HH:MM-HH:MM 或时刻 HH:MM;longterm 用时刻 HH:MM(选填,不填为全天)
location地点
statusactive / cancelled / done
pinned是否置顶,默认 false。置顶事件无视 range 窗口和日期过期限制无条件读取,但 cancelled 的仍排除
alertevent 专用按时提醒配置。on_time(准时提醒,默认 true)、advance_minutes(提前 N 分钟,默认 0)。longterm 无此字段
note备注。禁止存储原始自然语言中的相对时间表述(如"这周二""明天""下个月"),所有时间信息必须以绝对日期存在 date 和 time 字段中
lead_min前置机动时间(分钟),event 专用。用于记录出发/准备时间。存分钟而非绝对时间,改 time 自动跟随
trail_min后置机动时间(分钟),event 专用。用于记录返程/收尾时间。存分钟而非绝对时间,改 time 自动跟随
linked_notes关联便签 id 列表。典型用法:作业 deadline 关联「提交前给导师检查」便签、考试事件关联「带准考证」便签。字段可选,缺省即无关联
repeat重复规则。仅 event 支持,longterm 不支持。缺省为单次事件

repeat 结构

字段说明
------------
repeat.typedaily(每天)/ weekly(每周指定几天)/ interval(每隔 N 天)
repeat.weekdaysweekly 专用。数字数组,1=周一~7=周日。如 [3,5] 即每周三五
repeat.interval_daysinterval 专用。如 3 即每三天
repeat.count可选。重复 N 次后停止。与 end_date 二选一
repeat.end_date可选。指定日期后不再产生重复(含当天)。与 count 二选一

count 和 end_date 都不填即无限重复。创建无限重复时 Agent 反问一句:「这个重复要到什么时候?可以设个截止日期或次数,也可以不设。」用户说不设就过。

重复事件的 overrides:存储在母体的 overrides 字段中,键为日期。与课程侧 overrides 逻辑一致,用于停改单次发生而不动母体:

"overrides": {
  "2026-05-28": {"status": "cancelled", "note": "这周放假"},
  "2026-06-04": {"time": "15:00-17:00", "location": "化一教室"}
}

overrides 中可改的字段:statustimelocationnote。其他字段(title、type、repeat、alert)不从 overrides 读取,以母体为准。

time 字段

格式自动判断:含 - 为时段,不含为时刻。

  • event:时段(如 "14:00-16:00")或时刻(如 "10:00")。按时提醒以 time_start 或时刻为触发点
  • longterm:时刻(选填)。不填表示全天。如 "09:00"

lead_min / trail_min 机动时间(event 专用)

物理移动时间与正式时间的分离。以家教为例:10:00-12:00 上课,但 9:30 出发、12:30 到宿舍。存 lead_min: 30, trail_min: 30,显示时会自动拼出机动段。

存分钟数而非绝对时间的原因:改 time 时自动跟随,不用手动重算两个字段。两个字段独立可选,大部分日程不需要。

显示规则

情况显示
------------
无机动10:00-12:00
只有前9:30~10:00-12:00
只有后10:00-12:00~12:30
前后都有9:30~10:00-12:00~12:30

机动段用 与正式时间段区分,暗示"这一段是缓冲"。- 仍只连接正式起止。

alert 按时提醒(event 专用)

event 除了在简报中出现,还有独立的按时提醒:

  • on_time: true:在 time 时刻(或 time_start)准时推送一次提醒
  • advance_minutes: N:提前 N 分钟再推送一次。设为 0 则不提前

创建 event 时,AI 默认 on_time=true, advance_minutes=0。主动询问用户:"需要提前提醒吗?"用户可口头设定("提前 15 分钟叫我"→ advance_minutes=15)。

心跳或短周期定时任务负责触发按时提醒(检查所有 status=active 的 event,当前时间 = time - advance_minutes 或 = time 时推送)。

status 三态

  • active → 需要提醒
  • cancelled → 已取消,永久不再提醒
  • done → 已完成

操作

用户说做什么
----------------
"5月17日 14:00 排练 化一"添加 type=event,默认准时提醒,询问是否提前
"十点提醒我给张三打电话"添加 type=event,time=10:00
"6月13日英语四级考试"添加 type=longterm,date=2026-06-13
"下周五前交分析化学报告"添加 type=longterm,date=下周五
"明天的排练取消了"对应 event status → cancelled
"排练搞完了"对应 event status → done
"置顶英语四级"对应 event pinned → true
"取消置顶英语四级"对应 event pinned → false
"今天有什么"查今天所有 active 日程(事件+事项)
"这周有什么"查未来 7 天所有 active 日程
"每周三五下午排练,到期末"添加重复事件。type=weekly, weekdays=[3,5], end_date=推算学期结束
"每天打卡,坚持 30 天"添加重复事件。type=daily, count=30
"每三天浇一次花"添加重复事件。type=interval, interval_days=3。无结束条件则反问
"下周三排练取消"找到对应 repeat 事件 → overrides["对应日期"] = {status:cancelled}
"这周三排练改到四点"找到对应 repeat 事件 → overrides["对应日期"] = {time:"16:00-..."}
"取消每周的组会"对应 repeat 事件 status → cancelled,后面所有重复停止

重复事件(repeat)

仅 event 支持重复,longterm 不支持。

展开规则:每次查询或简报生成时,对含 repeat 的事件按 range 窗口展开为具体日期:

  1. date 起始,按 repeat.type 计算出窗口内所有命中日
  2. 跳过 overrides 中 status=cancelled 的日期
  3. 每命中日读取 overrides 中的 time/location/note 覆盖母体值
  4. 展开后的每个独立日期作为一条事件参与后续筛选和输出

三种 type 的命中小节:

  • daily:date 起每天
  • weekly:date 起,仅 weekdays 中包含的周几
  • interval:date 起,每隔 interval_days 天

停止条件:count 或 end_date 先到为准。无限重复的事件展开不受窗口大小影响——today 窗口只展开今天,tomorrow 只展开明天,不会失控。

交互原则:创建重复事件时,Agent 尽量推断结束时间。用户说「到期末」→ 推算学期结束日。说「坚持 30 天」→ count=30。什么都不说也不设截止 → 反问一句再创建。

修改单次:用户说「这周排练取消」「下周三排练改到四点」→ Agent 找到对应 repeat 事件,在当前发生日写 overrides。不碰母体 repeat 规则。

取消整条:用户说「取消每周的组会」→ 母体 status → cancelled,所有后续展开停止。

自动操作

v2.6.0 起,schedule.json 不再包含 automations 字段。定时自动创建日程/交易的需求由习惯库(habits.md)覆盖——用自然语言描述规则,LLM 在简报时判断并执行。

典型映射:

旧 automation 用例习惯库写法
------
每周四自动创建三天后截止的作业- [学期中] 每周四自动在 schedule.json 中创建一条 longterm:标题「交英语作业」,截止日=本周日 23:59
每月 15 号自动记 50 元话费- [长期] 每月 15 号自动在 ledger.json 中记一笔:支出 50 元,类别「通讯」,备注「手机话费」
停止自动创建「忘掉那条习惯」或修改有效期

和 JSON automation 相比,习惯库的优势在于:条件可以叠加上下文(「考试周不创建作业」「余额低于 100 时不自动记话费」),不需要改 schema。


三、记账(ledger.json)

多账户收支管理。每次交易自动更新余额,转账强制双记防漏。

结构

{
  "version": "1.0",
  "accounts": [
    {"id": "campus_card", "name": "校园卡", "balance": 579.25},
    {"id": "wechat", "name": "微信", "balance": 320.00}
  ],
  "transactions": [
    {
      "id": "txn-001",
      "date": "2026-05-17",
      "time": "12:30",
      "account": "校园卡",
      "amount": -9.50,
      "type": "expense",
      "category": "餐饮",
      "item": "午餐",
      "note": ""
    }
  ]
}

字段说明

accounts

字段说明
------------
id账户唯一标识(英文)
name账户显示名
balance当前余额

transactions

字段必填说明
------------------
id唯一标识,格式 txn-序号。序号基于所有已有交易的编号最大值 +1,禁止用 len+1
date日期,YYYY-MM-DD
time时间,HH:MM
account账户名(对应 accounts[].name)
amount金额。支出为负数,收入为正数
typeexpense / income / transfer
category用户自定义分类。建议:餐饮 交通 购物 居住 娱乐 教育 医疗 其他
item项目/商品名
note备注

转账规则

转账(type=transfer)必须双记:一条从源账户出(负数),一条入目标账户(正数)。写入后立即验证两账户余额变动是否匹配,不匹配则回滚。

修正与退款

不修改、不删除原始交易。修正方式:

  • 记错金额 → 追加修正记录,note 标注"修正 txn-xxx"
  • 退款 → 追加反向记录,note 标注"退款 txn-xxx"

操作

用户说做什么
----------------
"午饭校园卡 9.5"添加 expense,校园卡余额 -9.5
"微信收入 32"添加 income,微信余额 +32
"校园卡转微信 400"两条 transfer,更新双方余额
"查余额"列出所有账户及余额
"这周花了多少"汇总本周支出
"这个月餐饮花了多少"按 category 筛选汇总

四、通知处理

用户说"处理通知"并粘贴通知原文时,从原文中提取事项并写入对应的数据文件。

处理流程

  1. 逐条解析通知中的事项,提取:日期、时间、事项描述、地点、人群限定、类型
  2. 判断类型(type 仅允许 eventlongterm,禁止发明新值):
    • 含截止/提交/上交/前完成 → longterm(事项)
    • 含具体时刻且无持续时段(如"10:00 开会"但无结束时间)→ event(事件)
    • 其余有日期和时段 → event(事件)
    • 涉及调停课/换教室 → 写入 courses.json 对应课程的 overrides
    • 以上规则均不匹配 → 默认归为 longterm,不发明新 type
  3. 人群判断:
    • 通知描述了人群限定(如"第 X 组"、"学号尾号 Y"、"班长/学委"等),先查 memory 是否有用户身份信息
    • 能确定用户属于该人群 → 直接添加,标注 note: "[来自通知] 人群: xxx"
    • 无法确定 → 列出人群条件,反问用户是否属于该人群,确认后再添加
    • 通知未限定人群(全体通知)→ 直接添加
  4. 提取结果整理为列表,展示给用户确认后再写入

通知类型识别示例

通知原文片段提取结果
----------------------
"5月20日前提交实验报告"type=longterm, date=2026-05-20, title=提交实验报告
"周三下午2:00在化一教室开班会"type=event, date=下周三, time=14:00-15:00, title=班会, location=化一教室
"明天上午10:00各组负责人到办公室"先判断用户是否为负责人,不是则跳过
"本周四物理实验停课一次"写入 courses.json → overrides,status=cancelled
"提醒大家今晚12点前填表格"type=longterm, date=今天, title=填表格
"9:20到教室 9:30-11:30考试"type=event, time=9:30-11:30, lead_min=10, title=考试
"5月15日交实验报告"type=longterm, date=2026-05-15, title=交实验报告

操作

用户说做什么
----------------
"处理通知" + 粘贴原文按上述流程解析并确认后写入

五、便签(notes.json)

收纳放不进课表、日程、记账、学习计划任何现有结构的纯文本碎片。物理隐喻:软木板上的便利贴。

与现有 JSON 的分工

用户说进哪个文件理由
-------------------------
"下周三交无机作业"schedule.json有明确日期,事项(longterm)
"贾老师说可以用另一种方法算"notes.json碎片备忘,无日期无结构
"校园卡又扣了 9.5"ledger.json有金额
"今天背了 3 组单词"study_plans.json有进度量
"张珉提了篇 JACS 文献名忘了搜一下"notes.json提醒自己的待办,但不带日期

能进结构的绝不进便签。便签是兜底,不是捷径。

创建门槛

便签的创建必须由用户明确触发。仅当用户话语中出现「记一下」「便签」「贴个」「备忘」等关键词时才创建便签。其他场景——即使语义上像备忘——Agent 不得主动创建便签,否则会和日程、记账等其他模块产生冲突。

唯一例外是 linked_notes:用户在某门课或某个事件的语境下说「物理实验课每节都要带实验服」,Agent 直接在课程的 linked_notes 中写条目,不走「记一下」的创建门槛。

关联便签(linked_notes)

便签可以通过 linked_notes 挂载到课程和日程上。课程侧支持课程级(每节显示)和 overrides 级(仅指定周显示)两层。日程侧只支持条目级。

创建 linked_notes 的交互规则

用户说写入位置判断逻辑
-------------------------
「物理实验课每次都要带实验服」课程级 linked_notes「每次」「每节」「都要」→ 课程级
「这周物理实验课帮张三代交报告」overrides 当前周 linked_notes「这周」→ 判断当前周次 → overrides 级
「下周实验课别忘带 U 盘」overrides 指定周 linked_notes「下周」→ 计算目标周次 → overrides 级
「四级考试记得带准考证」该 event linked_notes当前语境中明确指向某个已有日程条目
「交无机作业前给导师看一下」该 longterm linked_notes同上,明确指向已有事项

模糊时反问:Agent 无法从语境中判断是课程级还是 overrides 级、或不确定指向哪个已有条目时,反问一句确认。不要猜。「物理实验课带实验服——是每节都要带,还是就这一次?」

删除联动:删除某条便签时,同时从所有模块的 linked_notes 中移除该 id。删除课程或日程条目时,linked_notes 中的 id 不删除(便签本身仍存在于软木板上),仅链接失效不报错。

结构

{
  "version": "1.0",
  "notes": [
    {
      "id": "n-001",
      "content": "张珉上课提到一篇JACS,记得搜出来看看",
      "created_at": "2026-05-28T22:30:00",
      "status": "active"
    }
  ]
}

字段说明

字段必填说明
------------------
id唯一标识,格式 n-序号。序号基于所有已有便签(含 archived)的最大编号 +1,禁止用 len+1
content纯文本内容,不做任何结构化解析
created_at创建时间,ISO 8601
statusactive(贴在板上)/ archived(收进抽屉)

不设 updated_at:便签不修改,想改就摘掉重写一条。

状态流转

创建 → active(贴在板上)
  ├─ "摘掉" → 追问 → archived(收进抽屉)或 物理删除
  ├─ "拿出来" ← archived → active
  ├─ "删掉/扔掉" → 物理删除(active 和 archived 均可,不追问)
  └─ "丢掉" ← archived → 物理删除(不追问)

操作

用户说行为
--------------
"记一下:xxx"创建,status=active
"我的便签" / "便签板"列出所有 active,按 created_at 倒序
"搜一下 JACS"全文模糊搜索 content,active 和 archived 都搜
"摘掉那条 JACS 便签"追问:"收起来还是丢掉?" → archived / 物理删除
"删掉/扔掉/不要了"直接物理删除,不追问
"之前收起来的便签"列出所有 archived
"把那条归档便签拿出来"archived → active

删除原则:"摘掉"是犹豫态 → 追问。"删掉/扔掉"是终局态 → 直接执行。archived 便签被说"扔掉"同样直接删除,二次确认没必要。

简报模块

notes 模块:显示所有 status=active 的便签。格式 📌 {content} [id],ID 格式 [n-NNN]。无便签时整个模块跳过不占位(不用空占位提示)。

便签没有时间维度,不接受 range 参数。在 normalize→resolve→validate 管线中走"不支持 range"分支,与 ledger 同。


六、习惯库(habits.md)

条件性的、依赖上下文的行为规则,用自然语言描述,由 LLM 在简报生成时读取并解释。不替代任何 JSON 文件,是 LLM 的行动指南。

定位

JSON 管确定性数据(课表、日程、账本),习惯库管模糊的行为模式。判断标准:需要读取外部上下文才能决定行为?不需要 → JSON repeat;需要 → 习惯库。

文件结构

../college-cabinet-data/habits.md,纯 Markdown。章节按生活领域分段:

# 习惯库

> 最后更新:YYYY-MM-DD
> 这里是你的生活规律和条件规则。AI 在生成简报时读取。
> 有新的习惯直接说「记住:xxx」,我会加进来。

## 日程习惯

- [学期中] **考试周**自动跳过组会(组会本身用 repeat 录入,这里只写条件例外)
- [学期中] **实验课当天**推送携带清单:实验服、护目镜、实验报告、预习报告
- [长期] 逾期超过 7 天的事项在简报中降级显示,前缀「📦 归档:」

## 记账习惯

- [长期] 每月 1 号在简报中提醒查校园卡余额,低于 50 元提示充值

## 学习习惯

- [学期中] 四级备考:每天至少背 50 个单词,连续 3 天未达标时在简报中语气加重

## 便签习惯

- [长期] 便签中带有「本周」字样的条目,周一简报中自动显示

## 上下文感知

- [长期] 天气预报有雨时,出行事件提醒提前 20 分钟
- [学期中] 当天课表超过 4 节课时,午间简报中追加一句「今天课多,中午休息一下」

格式约定

  • 每条一个 -,以 [有效期] 开头。有效期取 学期中 / 假期 / 长期 / 具体日期范围(如 2026-05-01 ~ 2026-05-31
  • 条件部分用粗体标出触发条件(条件),帮助 LLM 快速定位
  • 行为部分紧跟条件,自然语言描述
  • 章节按模块分段,但上下文感知章节跨模块生效
  • 学期中/假期的判定依赖 courses.json 的 semester 和当前日期

触发机制

习惯检查不建独立的定时任务。它附着在现有简报基础设施上:

有简报时:每次简报生成前,读完数据文件后,读取 habits.md 并逐条匹配。匹配的习惯注入对应模块输出:

习惯章节输出归入
------
日程习惯schedule 模块(跳过事件、追加携带提醒、调整显示)
记账习惯ledger 模块(追加余额检查)
学习习惯study 模块(调整语气)
便签习惯notes 模块(筛选显示)
上下文感知insight 模块(跨模块建议、环境提醒)

没有匹配的习惯 → 静默跳过,不输出占位。

无简报时reminder.briefings 为空数组):自动创建一条 cron 兜底任务:

cron: 0 1 0 * * *    (每天 00:01)
prompt: 执行习惯库每日检查

Agent 被唤醒后校准日期 → 读 habits.md → 匹配则推通知 → 无匹配则静默。用户配置了第一档简报后,这条兜底任务自动删除。删光简报后自动重建。

口头操作

用户说行为
------
「记住:每周三下午去图书馆」追加到习惯库,有效期默认「学期中」
「忘掉那条浇花」模糊匹配删除对应条目
「这个习惯只适用于 5 月」更新有效期
「改一下组会那条,教室改成 302」定位条目并修改
「关掉习惯检查」简报中跳过习惯库步骤,删除兜底任务(如有)

创建习惯时 Agent 需判断:这条该放 JSON repeat 还是习惯库?→ 需要外部上下文判断 → 习惯库;纯时间重复 → 反问用户确认。有效期默认:学业相关默认「学期中」,生活相关默认「长期」。

冲突处理

优先级:courses.json / schedule.json 的显式数据 > 习惯库 > LLM 缺省判断。以数据文件为准,冲突时在 insight 中提一句差异,不自动修改数据文件。

解释策略

Agent 读习惯库时理解语义而非匹配关键词:

  1. 有效期筛选:当前日期是否匹配?
  2. 条件匹配:条件在当前上下文是否成立?(今天有实验课吗?天气有雨吗?)
  3. 行为执行:条件成立 → 执行描述的行为。追加提醒、调整显示、推送通知
  4. 不成立跳过:不输出「今天不适用」提示

拿不准时(条件模糊、两个习惯冲突)在 insight 中提一句,不静默跳过。


提醒规则

提醒分两层:定时简报(cron 触发,推送摘要)和实时提醒(心跳/定时任务触发,即时推送)。

日期锚定规则:每次生成简报前执行日期校准(见顶部→日期校准),以此为唯一基准。同一天内的多次简报对日期/星期的判断必须一致。简报之间不共享上下文,每次独立校准。

定时简报

简报档位、时间、模块均可自由设定。默认提供四档,用户可增删。

简报生成前:读取各模块数据文件,然后读取 ../college-cabinet-data/habits.md 执行习惯检查(见六、习惯库)。习惯匹配结果注入对应模块。习惯条目中如有要求创建日程/交易的(如「每月15号自动记话费」),当场写入数据文件。最后生成各模块内容 + insight。习惯检查不占用简报输出篇幅,无匹配则静默跳过。

默认简报(仅含内置模块,天气等外部模块需先创建自定义模块后手动加入):

id标签默认时间默认模块
--------------------------------
morning晨间简报06:40courses, schedule, insight
noon午间简报12:40{"id":"courses","range":"remaining"}, {"id":"schedule","range":"remaining"}, insight
evening晚间简报19:00{"id":"courses","range":"tomorrow"}, {"id":"schedule","range":"tomorrow"}, insight
night睡前简报22:00schedule, ledger, notes, insight

预设模块(来自大学生内阁自身数据,无需额外配置):

模块内容标题行格式空占位
----------------------------------
courses课程📚 课表:{slot_or_time} {name} {location} {teacher},time_slots 存在时优先用课节名(如"第1-2节"),无匹配则用时段时间无课。
schedule日程📋 日程: + ⏰ 事项: 两段事件段:{time} {title} {location} [id],含机动段时按 lead_min/trail_min 规则展开。事项段:{date} {title}(余{days}天) [id],已逾期标 ⚠️ {date} {title}(逾期{days}天) [id],距日期≤urgent_days 前缀加 ⚠️ 临近:。无事件时事件段显示 无日程。,无活跃事项时事项段跳过不占位。每条事件和事项必须在行尾附带 ID,格式 [s-YYYYMMDD-NNN]无日程。
ledger各账户余额💰 账户余额:{账户名}:¥{余额}。余额总览不显示交易 ID,但用户要求列出交易明细时每条交易行尾追加 [txn-NNN]
notes便签📌 便签:{content} [id]。每条便签行尾附带 ID,格式 [n-NNN]无便签则跳过
study学习进度两段:📚 今日学习 + 📊 学习进度今日任务:课表 + 待办 / 进度:{name} {done}/{goal} {unit}。任务条目行尾附带 [task-id]无活跃学习计划。
insightAI 洞察无标题,在所有模块输出后空一行直接写无固定格式,AI 看完整简报后自由输出 1-2 句。方向约束见下方 insight 模块说明无输出则跳过(不占空位)

除上述预设模块外,用户可定义自定义模块。自定义模块在 reminder.custom_modules 中配置,可在 briefings[].modules 中像预设模块一样使用。

搭建简报

用自然语言配置即可,无需手动编辑 JSON:

效果这样说
--------------
早起看一眼今天有什么「早上 7:00 推今日课表和今日日程」
中午只看下午的课「午间只要下午课表」
下午课程、日程一起看「午间推下午课程和下午日程」
放学收到明天的安排「下午 5:00 推明日课表和明日日程」
睡前确认最后事项「睡前推账户余额和近期事项」
课、日程、余额、进度全要「早上 7:00 推课表、日程、余额、学习进度」
加个天气「早上加天气模块,调天气 skill」
某档不想收了「不要午间简报了」

不指定模块只调时间也行:「早上改成 7:30 推送」。

各模块默认范围:课程/日程/学习进度 → today,可换成 remainingtomorrowweek 或自定义窗口。

insight 模块

insight 是 AI 原生模块,不读数据文件。Agent 生成完所有正常模块后,扫一眼整体内容,在末尾空一行直接输出 1-2 句。无固定格式,无标题行,纯由模型能力驱动。

内容方向(Agent 自行判断,不强制):

简报里有什么可以说什么
------------
课表很满 + 相邻时段不同地点提醒赶路 or 建议提前走
有未完成的逾期事项轻推一句别拖了
有考试或重要日程简短鼓励 or 提醒准备
全天清闲一句轻量日记感的话
消费较高或余额偏低消费提醒
没什么特别可跳过不输出

约束

  • 不重复简报中已有的事实性内容(不报菜名)
  • 不废话,不用「总的来说」「希望」等收尾句式
  • 不说教,不用「你应该」「你必须」
  • 拿不准输出什么 → 不输出,宁可空白也不硬凑

用户说「不要每日小结」→ 从各简报 modules 中移除 insight。

模块范围

每个模块可以附加一个时间窗口,指定读取数据的时间范围。范围用 fromto 描述起止点。

时间点描述

含义
------------
"now"当前时刻
"today.start"今日 00:00
"today.end"今日 23:59
{"offset": N, "time": "HH:MM"}以今天为 0,N 天后某时刻。time 缺省值:作起点时 "00:00",作终点时 "23:59"

内置别名(等价窗口的快捷方式):

别名等价窗口含义
----------------------
"today"{from: "today.start", to: "today.end"}今日全天
"remaining"{from: "now", to: "today.end"}从此刻到今日结束
"tomorrow"{from: {offset:1}, to: {offset:1}}明日全天
"week"{from: "today.start", to: {offset:7}}未来七天

各模块默认范围

模块默认
------------
courses"today"
schedule"today"
study"today"
ledger—(无时间窗口概念)
notes—(无时间窗口概念)

模块语法modules 数组中每个元素可以是字符串(走默认范围)或对象(自定义范围):

"modules": [
  "courses",
  {"id": "schedule", "range": "remaining"},
  {"id": "schedule", "from": "now", "to": {"offset": 1, "time": "12:00"}}
]

解释:课表全天,日程(事件+事项)今天剩余,另外加一个自定义窗口(从现在到明天中午前)。

解析管线:模块配置依次经过三段处理:

  1. normalize(结构统一):纯字符串转对象 "courses"{"id":"courses","range":"default"}
  2. resolve(语义落地):"default" → 模块对应的具体范围值。from/to 描述解析为绝对时间戳。接收可选 now?: number 参数用于测试时钟注入
  3. validate(合法性校验):检查范围对该模块是否有意义。如 ledger 不接受 range,{"id":"ledger","range":"week"} 应忽略 range

三段均为纯函数,独立导出,方便单测。

remaining 语义{from:"now", to:"today.end"} 指示滤条件为 startTime > now(严格大于)。即只保留尚未开始的条目。

输出规则:模块按 briefings[].modules 顺序依次输出。每个模块与其标题不空行,模块之间空一行。列表按时间升序排列。无数据时用空占位,不跳过。时间比较:只比较结束时间是否已过。

简报模块映射

用户自然语言 → 模块名对应:

用户说模块+范围
------------
今日课表courses + today
下午课表courses + remaining
明日课表courses + tomorrow
今日日程schedule + today
下午日程schedule + remaining
明日日程schedule + tomorrow
余额 / 账户ledger
学习进度study
便签 / 备忘录notes

schedule 模块输出策略

schedule 模块统一从 schedule.json 读取,按 type 分两段输出。每条事件和事项行尾必须附带 ID(格式 [s-YYYYMMDD-NNN])。如有 linked_notes,在对应条目下缩进显示关联便签内容,前缀 📌,ID 放在事件/事项行尾,linked_notes 不重复显示 ID。

事件(type=event):按 range 窗口时间筛选。若事件含 repeat 字段,先按窗口展开为具体日期列表(跳过 overrides 中 status=cancelled 的日期),每命中日读取 overrides 中的 time/location/note 覆盖。无 repeat 的事件直接按 date 筛选。today 窗口显示今日全部事件(含已过期),remaining 窗口只显示尚未开始的事件(startTime > now)。过期事件标 ⚠️ 已过期

事项(type=longterm):按 range 窗口截止日筛选。事项没有"开始时间",只有截止日期。

  • today / remaining:显示 date ≤ today 的所有未完成事项(过去逾期 + 今天到期)。已逾期标 ⚠️(逾期{days}天)
  • tomorrow / week 等未来窗口:只显示 date 在窗口内的事项(不含逾期)
  • pinned 置顶:pinned=true 的事件和事项无条件读取(无视 range 和过期),status=cancelled 除外

实时提醒(event 按时提醒)

心跳或短周期定时任务(建议每 5 分钟)检查所有 status=active 且 type=event 的事件。pinned 事件不受日期窗口限制,过期仍扫描。

重复事件:先按当前至明日 23:59 的窗口展开所有命中日,每个命中日独立继承母体的 alert 配置(含 overrides 中对该日的时间覆盖)。无 repeat 的事件直接按 date+time 检查。

检查窗口:当前时刻至明日 23:59(不无限扫描所有未来事件)。

  • 当前时间 = time − advance_minutes → 推送提前提醒
  • 当前时间 = time(或 time_start)→ 推送准时提醒
  • 当前时间 > time_end(或单时刻 time)→ 停止跟踪,不标 done(留给简报层判断显示 ⚠️ 已过期)

longterm 无按时提醒,仅通过简报覆盖。

可配置参数

schedule.json 顶层 reminder 字段覆盖默认值。默认配置见快速上手。

参数默认说明
------------------
briefings四档简报列表,每条含 id、time、label(选填)、modules。可增减档位、调时间、自由组合模块
briefings[].modules见上表每档简报包含的模块。字符串走默认范围,对象可自定义
advance.longterm.urgent_days3longterm 距日期 ≤ N 天时语气加重,标注"临近"
custom_modules[]用户自定义模块列表。每条含 id、label、source、format

用户口头调整("早上改成 7:00 推送"、"晚间只保留近期事项和课表"、"去掉午间简报")→ AI 更新 reminder 配置。

简报格式规范

简报标题格式:📅 {日期中文} · 第{周次}周 {星期}。示例:📅 5月20日 · 第11周 周三

各模块标题和行格式见上方预设模块表。格式为用户口头调整的基准(如"天气改成一句话""近期事项不要倒计时"→ AI 更新对应条目)。

自定义模块

天气、API 余额查询等依赖外部 skill 的功能不作为预设模块,而是通过自定义模块实现。用户可定义任意新模块,关联外部文件或其他 skill。

推荐创建的自定义模块

推荐模块用途创建指令
------------------------
天气在简报中显示今日/明日天气"加一个天气模块,调天气 skill"
API余额显示各 AI 平台余额"加一个 API 余额模块,调 balance-checker"

定义方式:在 reminder.custom_modules 数组中添加条目,或口头告诉 AI(AI 自动生成配置并加入对应简报)。

字段

字段必填说明
------------------
id唯一标识,用于 modules 数组中引用。如 library
label模块标题,在简报中显示。如 📖 图书馆借阅
source数据来源描述。AI 据此获取数据。格式:文件:{路径}skill:{skill名}、或自然语言描述
format输出格式模板。用 {字段} 占位,每行一条数据。如 {书名} 到期 {日期}
empty无数据时的占位文本,默认 无。

示例

用户说:"睡前简报加一个图书馆模块,数据在 ../college-cabinet-data/library.txt,格式跟近期事项类似"

AI 生成:

{
  "id": "library",
  "label": "📖 图书馆借阅",
  "source": "读取 ../college-cabinet-data/library.txt,每行格式:书名 | 到期日期",
  "format": "{书名} 到期 {日期}(余{days}天)",
  "empty": "无限期借阅。"
}

并在 briefings[].modules 中加入 "library"。生成简报时,AI 按 source 获取数据,按 format 格式化输出。

创建定时任务

定时任务由 cron 触发,每条任务对应一次简报生成或按时提醒扫描。

message 必须极简,只写一句话触发指令。 skill 内部是配置驱动的,agent 自己读 JSON 生成内容,不要在 message 里写生成步骤。

正确:

  • 生成晨间简报
  • 生成午间简报
  • 扫描按时提醒

错误:

  • 第一步读 schedule.json,第二步获取天气,第三步筛选今天课程,第四步... ← 硬编码生成流程,skill 一更新就坏

超时建议:冷启动 session 需读取多个文件 + 可能调天气/API 等外部 skill,设置不少于 300 秒超时。纯内存操作(如按时提醒扫描)可设 60 秒。


数据完整性

所有输出必须来自数据文件,严禁推测或编造。

查询时

  • 每次独立读取数据文件,不依赖对话历史中的信息
  • 日期锚定:先确认年-月-日 + 星期几(见提醒规则→日期锚定规则)
  • weeks 不含当前周次 → 不得以任何理由保留
  • 无匹配 → "这天没有课",不填充
  • 输出日程只使用 date/time 中的绝对日期,禁止将绝对日期转述为相对时间("这周二""下个月"等),也禁止回显用户录入时的原始相对措辞
  • 每条日程、事项、便签、学习任务在输出时必须附带其唯一 ID,格式为行尾 [id]。ID 来自数据文件,不可编造或缩写。课程名和账户名无需 ID
  • 新建条目的 ID 必须基于同类型所有已有条目(含 archived/cancelled)的最大编号 +1,严禁用 数组长度+1。编号空洞时 len+1 会导致 ID 碰撞
  • 已过期的 type=event 不自动标 done,留给简报层判断,超时标 ⚠️ 而不是静默移除

引用时

  • 用户指令中含 ID 格式字符串(s-xxxn-xxxtxn-xxx)→ 优先按 ID 精确匹配,回读数据文件确认该条目存在
  • ID 匹配不到 → 回退到自然语言模糊匹配,并告知用户该 ID 未找到
  • 同一条指令中混合 ID 和自然语言 → ID 部分精确匹配,其余模糊匹配

质疑时

  • 用户质疑 → 立即重新读文件验证,不辩解
  • 发现输出与文件不一致 → 立即更正并告知原因

写入时

  • 修改前备份至 ../college-cabinet-data/backups/文件名-YYYY-MM-DD.json(保留 7 个)
  • 写入后验证 JSON 格式,失败回滚
  • 回读文件确认写入结果与意图一致("已录入"≠已写入)
  • 禁止物理删除:取消修改 status,修正追加新条目

升级与兼容

每次大版本变化的迁移路径在此记录。AI 读取数据时自动检测版本并执行迁移,用户无感知。

数据格式版本对照

schedule.json version对应 skill主要变化
------------------------------------------
2.0课搭子 v1.0.0初始版本。type 含 7 种枚举(course/exam/ddl/meeting/activity/lecture/personal),有 weekday 字段
3.0课搭子 v1.1.0 ~ v1.2.0 / 大学生内阁 v1.0.0课搭子: type 重构为 event/ddl/moment。大学生内阁 v1.0.0: 品牌升级,新增通知处理
3.0大学生内阁 v2.0.0 ~ v2.4.0v2.0.0: type event/longterm、weekday 1 基、alert 按时提醒、学习计划(见上方详细列表)。v2.1.0-v2.4.0: 模块表合并、日期校准、模块范围重构、便签 notes.json、event 机动时间、模块统一命名、事项逾期着重显示
3.0大学生内阁 v2.5.0新手引导流程、关联便签 linked_notes、便签创建门槛、AI 洞察 insight 模块
4.0大学生内阁 v2.6.0+重复事件 repeat(daily/weekly/interval + overrides)。习惯库(habits.md)。ID 序号输出。v2.6.1: 展开强制化。v2.6.5: 数据目录外置、type 术语锚定

从课搭子迁移

大学生内阁是课搭子的品牌升级版,数据格式完全兼容。迁移只需一步:

原路径: skills/course-buddy/data/*.json
新路径: skills/college-cabinet-data/*.json

将 JSON 文件复制到新路径即可(学习计划为 v1.1.0 新增,旧版无此文件则跳过)。schedule.json、courses.json、ledger.json 无需任何格式转换。

自动迁移

AI 读取数据文件时自动检查版本并执行迁移。

schedule.json 迁移

  • version < 3.0:旧七种 type 映射(ddl→longterm,其余→event),删除 weekday 和 category 字段
  • 缺 reminder 字段:写入默认四档简报 + advance 参数
  • reminder.briefings 为对象:转数组
  • type=ddl/moment:ddl→longterm,moment→event + alert
  • v2.3.0 迁移:
  • 所有 events 补 pinned: false(若字段不存在)
  • reminder.advance.event.briefings → 删除(event 改用模块 range 控制窗口)
  • 旧模块名自动映射(briefings[].modules 中的纯字符串):
  • courses_pm{"id":"courses","range":"remaining"}
  • courses_tomorrow{"id":"courses","range":"tomorrow"}
  • events_pm{"id":"schedule","range":"remaining"}
  • events_tonight{"id":"schedule","range":"remaining"}
  • events_tomorrow{"id":"schedule","range":"tomorrow"}
  • courses / schedule / ledger / study → 保持
  • events / focus / balanceschedule / ledger(v2.4.0 自动映射)
  • 映射后去重:同一档简报中 id+range 完全相同的条目合并
  • v2.4.0 迁移:
  • 无 notes.json → 自动创建 {"version":"1.0","notes":[]}
  • notes 中残留 pinned 字段 → 删除(v2.3.x 设计错误,v2.4.0 移除)
  • events 无 lead_min / trail_min → 不自动添加(缺省即无机动,无需冗余字段),AI 读取时判空即可
  • 模块名变更eventsschedulefocus → 删除(并入 schedule),balanceledgerbackup → 删除(系统功能不入简报)。旧名出现在 briefings[].modules 时自动替换
  • advance.longterm.briefings → 删除(v2.4.0 longterm 改为按 range 筛选,不再有独立的"提前 N 天出现"窗口)
  • v2.6.0 迁移:
  • schedule.json version < 4.0 → 升级 version 为 "4.0"
  • schedule.json 含 automations 字段 → 删除(该字段从未在发布版中使用,残留即清理)
  • 无 habits.md → 自动创建,写入习惯库模板内容(见六、习惯库→文件结构)
  • 无简报配置reminder.briefings 为空)→ 自动创建 00:01 兜底 cron 任务
  • type 字段修正(任意版本均执行):
  • 遍历 events 数组中每条记录,检查 type 字段是否为 eventlongterm
  • 若 type 不是这两个值,按以下规则修正:
  • type 含 ddl / deadline / exam / 考试 / 提交 / 截止 / 到期 → 改为 longterm
  • type 含 meeting / activity / course / lecture / 会议 / 活动 / 课 → 改为 event
  • type 含 daily / weekly / interval(误用了 repeat.type)→ 改为 event
  • 不含 title 或仅有占位文本且无 date → 删除该条目(空记录)
  • 以上均不匹配 → 保留 type 不变,在 note 中追加 [⚠️ type字段非标准值: 原值],Agent 读到后询问用户
  • 修正后回写文件
  • v2.6.5 迁移:
  • 数据目录从 data/ 迁移至 ../college-cabinet-data/:旧版数据在 skill 目录内的 data/ 下,更新前需手动将整个 data/ 目录移动到 skill 目录的兄弟路径 skills/college-cabinet-data/。如果 skill 目录内仍有 data/,AI 检测到后应提示用户执行移动,并给出具体命令
  • 无数据目录../college-cabinet-data/ 不存在)→ 自动创建并初始化空模板

courses.json 迁移

  • weekday 含 0:全部 +1

study_plans.json 迁移

  • version < 2.0:tracks→tasks(goal=target, done=progress, log=[]),per_day=0,删除 phases/resources/category

迁移后备份 + 格式验证。失败则回滚并告知用户。

版本历史

共 10 个版本

  • v2.6.5 【修复】 数据目录外置——用户数据从 skill 目录移出,更新时不再丢失。从 2.6.x 升级需手动将 data/ 目录移至 skills/college-cabinet-data/,首次运行会提示 日程术语锚定——日程、事件、事项三者的关系和 type 枚举值一句说死,Agent 不再混用或自创 type 值。历史错误 type 自动迁移修正 当前
    2026-06-06 23:04 安全 安全
  • v2.6.1 【修复】 修复了围绕日程进行问答时偶尔漏掉重复日程(组会、打卡等)的问题
    2026-06-06 19:23 安全 安全
  • v2.6.0 【新增】 重复事件——支持每日、每周指定日、每隔 N 天三种模式,可设结束日期或次数。组会、打卡类事件录入一次即自动展开,单次变更走 overrides 覆盖,不动母体规则 习惯库——新增 habits.md,上下文相关的条件规则用自然语言描述。考试周跳过组会、实验课当天推送携带物品、连续未达标加重提醒,简报时自动匹配执行,不再需要 JSON 字段硬编码 序号输出——日程、事项、便签在简报和对话中附带唯一 ID,用户可直接用 ID 定位条目
    2026-06-06 16:18 安全 安全
  • v2.5.0 【新增】 新手引导流程——无数据时逐模块交互式引导,按课表→记账→日程→学习计划→便签→简报的顺序,每步说明能做什么再给一句试例,可随时跳过 关联便签——课程和日程可以挂载便签,课程侧支持每节通用的课程级和单周专用的一次性两级,查课时自动带出来 便签创建门槛——只有用户明确说「记一下」「便签」「贴个」才创建,防止 Agent 把备忘和日程搞混。拿不准时反问确认 AI 洞察模块——每档简报末尾自动追加一句 AI 临场判断,不读数据、不设模板,可能是提醒、鼓励或什么都不说 【改进】 简报搭建指南从新手区移入提醒规则下,和定时简报、模块范围放一起
    2026-06-01 23:23 安全 安全
  • v2.4.0 【新增】 1.日程机动时间——出发准备和返程收尾分开记,不混进正式时间段。显示自动拼出缓冲段,改时间自动跟随 2.逾期事项着力显示——过去的 deadline 不会悄悄消失。未完成的事项持续挂着,逾期几天标几天 【改进】 1.便签完善——去掉不属于它的置顶逻辑,贴上的全部显示、摘下的收进抽屉、丢掉就彻底删除。更纯粹的软木板体验 2.日程术语分离——事件(原短期日程)管时段和提醒,事项(原长期日程)管截止日。不再用"日程"一词同时指代整体和子集 3.过期事件不自动标完成——提醒停止推送,事件保留在简报中告诉你今天错过了什么 4.备份移出简报——数据自动备份是系统功能,不再占一个简报坑位
    2026-05-31 13:04 安全 安全
  • v2.3.0 新增 简报模块范围自由组合——「看什么」和「看多久」分开选,不再需要死记模块名 事件置顶——重要事项挂在简报里绝不落下,过期了照样提醒,取消置顶再停 便签板——随手记一句话备忘,贴上去、摘下来收好、或者直接丢掉,三种处理 课节显示——课表按「第 1-2 节」而不是「08:00-09:30」来显示 装好新版本自动提示更新内容,旧数据自动升级,不用手动改 改进 实时提醒只扫当天到明天的事,不再无意义扫描遥远的日程 停课顺延不再留备注补丁,直接改课表数据,下周课表自动添上 迁移 旧格式自动转换,原有配置无缝升级
    2026-05-28 23:34 安全 安全
  • v2.2.0 新增 安装引导:装好 skill 就能看到从哪开始 简报搭建指南:选档位配模块,示例覆盖常见场景 简报模块映射规则:说「近期事项」AI 就知道是 focus 日期校准:每次操作调服务器实时时间,不再漂星期 改进 日程 category 字段移除,不再有多余的 [] 输出 简报表合并,读一处就够 防幻觉与安全规则合并为「数据完整性」 迁移规则精简约 40% 文档整体压缩,阅读效率提升 兼容性 v2.0.0、v2.1.0 用户无感升级
    2026-05-23 23:23 安全 安全
  • v2.1.0 文档精简与结构优化,功能无变化。 简报模块说明合并为一张表,查看更方便 迁移说明精简约 40% 整体压缩 200+ 行,阅读效率提升
    2026-05-23 00:13 安全 安全
  • v2.0.0 新增 学习计划:自定义任务,设定总量和每日量,自动算待办,完成记录可追溯 按时提醒:到点准时推送,可选提前 N 分钟 自定义简报模块:天气、API 余额等按需接入 明日日程简报模块 改进 日程类型重构:七种分类简化为短期日程 + 长期日程两种 长期日程从创建起就在简报持续出现,越临近越频繁 修复了课表日期偏移 bug,不会把周二当周一 简报格式规范化,新增防幻觉规则 兼容性 旧数据自动迁移,无需手动操作
    2026-05-22 23:20 安全 安全
  • v1.0.0 Initial release
    2026-05-19 23:10 安全 安全

安全检测

腾讯云安全 (Keen)

安全,无风险
查看报告

腾讯云安全 (Sanbu)

安全,无风险
查看报告

🔗 相关推荐

life-service

Weather

steipete
获取当前天气和预报(无需API密钥)
★ 458 📥 229,518
life-service

healthcheck

stellarhold170nt
使用 JSON 文件存储追踪饮水和睡眠
★ 11 📥 30,211
life-service

Sonoscli

steipete
控制Sonos音箱(发现/状态/播放/音量/分组)
★ 56 📥 85,240