← 交接首页 工具首页 线上入口 → Harrow 学习辅导系统 · Project Handoff
Doodle 子系统 · Harrow International School Bangkok 学习辅导

Harrow 学习辅导系统 — 项目交接

目标:孩子(Cordelia,Year 7,用户名 coco)每天按课表自动生成复习任务,AI 多轮对话判定是否讲清楚, 数学额外配套现场出题,家长收欠账/告警通知,孩子收任务提醒;另外把学校的课表、校历、(未来)邮件都汇总展示。 需求文档是仓库根目录的 HARROW_SPEC.md / HARROW_IMPL.md,开发顺序按 IMPL §7 走。

时间规划 + 弹性配额任务 Review 多轮判定(5科) 数学配套测试 + 告警队列 孩子日历 / 家长日历 双通道通知 + 5 条 crontab(时区已修) Review 记录查询页 Gmail 同步未接(缺凭证) 家长管理界面未做(只有 API)

已做 / 未做

✅ 已完成(全部用真实数据/真实 LLM 调用/真实浏览器操作验证过)

  • 时间规划主干HarrowTaskTemplate/HarrowDailyTask/HarrowMainSubjectConfig,模板展开、按课表自动定 review 科目、欠账结转、幂等保护。
  • 弹性配额任务(比如"跑步 2km 每周 2 次"):周一一次性生成本周全部实例,孩子可以用延迟按钮挪到周五之前任意一天,周一到周五都没处理会持续在"今日任务"露出,周六强制变成正式欠账。
  • 通知:家长走 ClawBot 主 + Telegram 兜底,孩子走她自己的 Telegram(coco 的 chat_id 已配置);到点未完成提醒,16-20 点每 30 分钟一次,其余时段 2 小时一次。
  • 课表批量同步:一次登录抓未来 30 天(避免频繁登录触发学校反自动化检测),每天晚上跟数据库比对差异,有变化同时通知孩子+家长。
  • Review 判定:数学/英语/科学(生物+化学+物理)/历史/地理五科通用机制,5 轮自动放行;数学额外触发配套非选择题现场出题判分;英语可传图片走 Gemini 多模态语法分析。
  • 告警队列:数学知识点错题 + 英语语法问题,FIFO 复测。
  • 孩子日历:日视图默认入口,课表 + 固定课外班 + 孩子自己安排了时间的任务,合并成一条时间线;周视图显示每天完成情况徽章。
  • 家长日历calendar.harrowschool.ac.th(免登录公开网站)抓校历,按 SR5 标签近似过滤 Year 7 相关事项,已抓到 92 条真实数据并翻译。
  • 每周汇总报告:数学告警 + 英语语法问题 + 科学 review 记录,一份报告三科都有。
  • 前端/doodle/harrow.html 枢纽页 + tasks.html/day.html/week.html/review.html/parent-calendar.html/review-log.html,首页已加导航入口。
  • Review 记录查询页(新,2026-08-25):GET /doodle/api/harrow/reviews 按科目/按周(可组合)查历史 review,review-log.html 列表点开看完整对话,"上一条/下一条"在当前筛选结果内翻页。真实数据验证:孩子已经在真实使用 review(8/24 数学"角的分类"、英语"自我介绍PPT"都通关,生物那次 5 轮没通关走了自动放行)。
  • crontab:5 条新增任务,见下方"环境信息";2026-08-25 修正了时区错位(详见下方"已知坑")。

🚫 被阻塞 / 没做

  • Gmail 学校邮件同步:doodle .env 没有任何 Gmail API 凭证。已经和用户讨论了两个方案:① 用户自己去 Google Cloud Console 走一遍 OAuth 授权(一次性,在有浏览器的机器上做,不能在 VPS 上做);② 用户提议让 Mac 上的 cowork(另一个有 Gmail 访问权限的会话)定期把邮件摘要 POST 过来。倾向方案②,已经设计了接收端点 POST /doodle/api/harrow/emails/ingest + Authorization: Bearer 鉴权,但还没写代码——需要先确认鉴权 token 怎么定、cowork 推送的是原文还是摘要。
  • 家长管理界面:任务模板 / 主课清单配置 / 固定课外班的 CRUD API 都有了(/doodle/api/harrow/templates/main-subjects),但没做可视化编辑页面,现在改配置只能直接调 API 或改数据库。
  • 科学大纲准确性data/harrow_curriculum/science_biology.json/science_chemistry.json/science_physics.json 是 AI 根据公开的英国 KS3 课程框架整理的,不是官方文档摘录,建议找老师或官方资料核对一遍覆盖面和准确性。
  • 思辨讨论题前端:API 有了(/discussion-topics/discussion/{id}/message),没做页面——SPEC 里这块本来就是"低优先级,兴趣向"。
  • 睡前总结:SPEC 自己标注"占位,细节留待下一轮讨论",不是遗漏,是按 SPEC 原意暂缓。

环境信息

线上入口/doodle/harrow.html(枢纽页)→ tasks.html / day.html / week.html / review.html / parent-calendar.html / review-log.html,都在 /var/www/edmund-home/doodle/harrow/
后端路由routers/harrow.py,前缀 /doodle/api/harrow,main.py 已挂载
核心服务模块services/harrow_tasks.py(任务生成/欠账/配额)、harrow_review.py(Review 判定)、harrow_review_quiz.py(数学配套测试)、harrow_kp_alerts.py(告警队列)、harrow_timetable_month.py(课表批量同步+差异)、harrow_diary_scraper.py(校历抓取)、harrow_weekly_report.py
数据表storage/models.py 里所有 Harrow* 开头的类;迁移脚本 tools/migrate_v17.pyv21.py(v17 课表、v18 任务模板、v19 固定作息、v20 Review/告警/日历、v21 弹性配额)
课程大纲数据data/harrow_curriculum/*.json(math 复用已有 knowledge_points.json;science_* 是 AI 整理,见上方"未做")
账号密码.envHARROW_ISAMS_USER/HARROW_ISAMS_PASS(课表+校历抓取共用,已配置);Gmail 凭证未配置
孩子/家长 Telegramuserscoco/dad 两条记录各自的 telegram_chat_id 字段,已配置

crontab(本次新增的 5 条,都已确认没有影响其他项目原有任务)

# 下面的钟点是 crontab 实际写的值(VPS 系统时区 Asia/Tokyo),注释里的
# "曼谷 xx:xx" 才是这些任务真正想要触发的曼谷时刻——已经是"曼谷时刻+2小时"换算过的
5 2 * * *      harrow_task_rollover.py       # 曼谷 00:05,生成当天任务 + 结转欠账
*/15 * * * *   harrow_reminder_check.py      # 每 15 分钟检查到点未完成(纯频率型,不受时区影响)
30 23 * * *    harrow_timetable_month_sync.py # 曼谷 21:30,抓未来 30 天课表 + 差异通知
0 */2 * * *    harrow_diary_gmail_sync.py    # 每 2 小时同步校历(纯频率型;Gmail 部分待接)
30 23 * * 0    harrow_weekly_report.py       # 曼谷周日 21:30,每周汇总报告

常用命令

cd /home/ubuntu/doodle
git status --short
pm2 restart doodle && pm2 logs doodle --lines 20 --nostream

# 查看某个学生今天的任务
sqlite3 data/doodle.db "SELECT task_type, label, subject, status, is_debt FROM harrow_daily_tasks WHERE owner='coco' ORDER BY task_type;"

# 手动跑一次任务生成(补数据用)
.venv/bin/python -c "
from datetime import date
from storage.db import SessionLocal
from services.harrow_tasks import generate_daily_tasks
db = SessionLocal()
print(generate_daily_tasks(db, 'coco', date.today()))
db.close()
"

curl -s http://127.0.0.1:8090/doodle/api/harrow/tasks/today?owner=coco

已知坑(详见 LESSONS.md 的 "Harrow" 相关章节)

反自动化检测calendar.harrowschool.ac.th/socscms.com 默认 headless UA 会 ERR_TOO_MANY_REDIRECTS,必须 --disable-blink-features=AutomationControlled + 桌面 UA
抓一个月课表不能循环登录fetch_range_timetable() 一次登录内连续翻页,不要循环调用单日版本
Gemini max_tokens 太小会截断 JSONthinkingConfig.thinkingBudget=1024 也占用 max_tokens 预算,结构化输出场景至少留 800-1500
Review 判定的 kp_ids大纲片段必须显式标注 id(如 [id=ks3_num_05]),否则 LLM 会自己编中文名字回填,覆盖度追踪对不上
前端日期字符串不要用 d.toISOString().slice(0,10) 取本地日期——会先转 UTC,时区一偏移就跨天错位;统一用本地 getFullYear/getMonth/getDate 拼(toDateStr()
SR5 ≠ Year 7校历只有 School Section 标签(Early Years/Pre Prep/Prep/SR5/Sixth Form),没有精确到年级,SR5 是近似值
VPS 系统时区是东京不是曼谷(重要)系统时区 Asia/Tokyo(UTC+9),应用逻辑全用 Asia/Bangkok(UTC+7),差 2 小时。crontab 按系统时区触发,且这个 cron 版本不支持 CRON_TZ已踩过一次坑harrow_task_rollover.py 原定"曼谷00:05"写成 5 0 * * *,实际在曼谷 22:05(前一天)触发,导致每天任务永远生成不出来。已修正为"目标曼谷时刻 + 2 小时",见 crontab 注释。新增任何要求"曼谷几点触发"的定点任务,先 timedatectl 确认系统时区再换算wealth_daily_accrual.py 的 crontab 同日已核实并修正为 0 23 * * *,详见 Wealth 交接页 →

下一步建议

  1. 敲定 Gmail 同步方案:跟用户确认走 cowork 推送还是 OAuth,如果是 cowork 推送,需要生成鉴权 token 并实现 /emails/ingest 端点。
  2. 家长管理界面:任务模板 / 主课清单 / 固定课外班的可视化编辑页,API 都现成,工作量主要在前端。
  3. 找人核对科学大纲:三个 science_*.json 文件的知识点覆盖面和准确性。
  4. 观察真实使用几周后,SPEC §8 里的几个"临时默认规则"(5 轮自动放行、16-20点30分钟冷却、弹性配额延迟窗口)看是否需要调整。
本页对应 2026-08-24 的一次超长 session(从 HARROW_SPEC.md/HARROW_IMPL.md 起步,一路做完时间规划、Review、数学测试、告警、两份日历、通知、crontab,外加弹性配额任务重新设计)。 2026-08-25 追加:修了 crontab 时区错位的 bug(VPS 系统时区是东京不是曼谷),新增了 Review 记录查询页。 详细过程记录在仓库根目录 CODING-LOG.md(搜"Harrow")和 LESSONS.md