对话笔记直发:8.10 vikunja-任务-计划。分类:AI工程。
date: 2026-08-10 tags: [计划, Vikunja, 任务管理, 实施中] status: draft
Vikunja 每日任务闭环 — 实施方案(v3)
版本:v3(已吸收子代理首轮 FAIL 清单修订、二次评审 PASS、双客户端并存决策与已实施 Phase 回填) 日期:2026-08-10 服务器:jp(
局域网IP(已脱敏),aarch64 / RK3566,Docker host) 评审状态:v1 → FAIL(按清单修订);v2 → PASS(可进入实施);v3 = 实施中增量修订(双客户端并存 + 已实施 Phase 回填),无需重审 实施状态:Phase 0/1/2/4/5/12 已完成并通过实测;Phase 1.5 CalDAV 双向、Phase 4 真实回写、Phase 3 双客户端并存登录均经验收(用户手机实测勾选回写 ✓);余下:连续两天闭环观测(#5)、双客户端适应期判定(#8)、退役 Radicale(#11)
1. 背景与决策依据
现状(Radicale 闭环已上线,见 8.8 radicale-tasks-计划):Hermes 凌晨聚合 → Obsidian 01_工作台 → 脚本A推 Radicale(VTODO)→ 手机 Tasks.org 勾选 → 脚本B回写 Obsidian [x]。
用户痛点:管理方案过于简单——工作台是扁平 - [ ] 列表,缺「大计划→小计划」层级、缺时间追踪、缺执行复盘。经第一性原理头脑风暴 + 用户拍板,选定路径A:
- 任务库:Vikunja(服务端应用,Hermes 可编程全权限,全免费,arm64 官方镜像,CalDAV 双向)
- 手机端(v3 决策:双客户端并存):Vikunja 官方安卓 app + Tasks.org + CalDAV 并行安装,适应期观察后定主用。原「淘汰官方 app」结论(alpha/提醒不稳/无时间块)经第一性原理复核后修正——官方 app 未覆盖时间盒,故 Tasks.org 保留为时间盒主客户端;官方 app 作为层级/看板浏览辅助。详见 §3 冲突分析与 §8。
- 时间追踪:先用时间块替代(Tasks.org Schedule 拖块 = 时间盒),不做 Vikunja Pro 计时
2. 目标闭环
Hermes(宿主机进程 /opt/hermes)
│ ① 凌晨拆好层级:大计划→子任务
│ ② 脚本A' → Vikunja REST API v2 建 项目/任务/子任务/start+due/reminder(UID 幂等)
▼
Vikunja(NAS docker :3456,SQLite 单用户,web 看板/甘特/列表)
│ CalDAV(每个项目=一个日历,双向)· 防线 = 密码 + CF Tunnel HTTPS
▼
手机双客户端并存(v3):
├─ Tasks.org(CalDAV)→ Schedule 拖块(时间盒 = start→due)+ Android 本地闹钟
└─ Vikunja 官方安卓 app(JWT API)→ 层级/看板浏览 + 勾选 done(无时间格)
▼
脚本B'(NAS cron 每8分钟)→ 拉 Vikunja done 任务 → FNS MCP 翻 Obsidian [x] → 确认后清理
▼
Obsidian ← Hermes 次日读含 [x] 的昨日文件 → 滚动生成今日计划
3. 关键事实(已核实,v2 更新)
- 服务器 aarch64/RK3566,Docker host;cloudflared 为宿主机进程,ingress 用
http://127.0.0.1:<port>直连。 - cloudflared 现有 tunnel 名
vaultwarden-3566(id74dd8243-...),config/etc/cloudflared/config.yml,已含 radicale/notes/pan/ha 等子域。 - domain 根:
unixcs.eu.org;CF Tunnel 走cloudflared tunnel route dns建子域。 - Vikunja 版本与镜像:
- 当前稳定版 2.5.0(2026-08-04,105 个修复,含一个 share-link 越权安全修复)。Docker tag 原则:
latest= 最新 stable、unstable= 每 commit 开发版;本方案显式 pinvikunja/vikunja:2.5.0(评审要求,不用浮动 latest)。 - 官方镜像 linux/arm64 官方支持,服务端口 3456;容器默认以 UID 1000 运行 → 宿主
files、db目录必须先chown 1000(官方 full-docker-example 已确认该前提)。 - 镜像预设
VIKUNJA_DATABASE_PATH=/db/vikunja.db,数据落在挂载的./db;env 优先级高于 config.yml。
- 当前稳定版 2.5.0(2026-08-04,105 个修复,含一个 share-link 越权安全修复)。Docker tag 原则:
- 时区(评审高危#2):Go scratch 容器内
TZenv 无效,必须设VIKUNJA_SERVICE_TIMEZONE: Asia/Shanghai(config optionservice.timezone,默认 GMT),否则全链差 8h。脚本侧还需显式做上海↔UTC 换算。 - 手机端官方安卓 app(v3 核实):
- 登录方式 = 用户名+密码(JWT,同 web UI 同一套 API),服务器填
Use a custom server→https://vikunja.unixcs.eu.org。与 Tasks.org 的 CalDAV(token 当密码)走完全独立通道。 - 官方 README 明示 alpha pre-release(“you must absolutely expect things to not work, and sometimes even break something in the backend”),官方不建议放在重要后端;社区问题:通知随机失效(需 Android 12+ 精确闹钟权限)、版本兼容误报。
- iOS/Android app 仅支持维库基本功能(官方 installing 文档明示)。
- 冲突分析(结论:无致命冲突):两客户端独立连接同一后端 —— 官方 app 走 JWT API 写 done、Tasks.org 走 CalDAV 写 done,都落到同一服务端状态;脚本B’ 从服务端 API 读 done,无论哪个客户端勾选都能被捕获回写 Obsidian,互不覆盖。差别仅:时间盒唯 Tasks.org 有(官方 app 无 day-grid 时间格)、提醒各自独立(可能双提醒,适应期观察取舍)。
- 登录方式 = 用户名+密码(JWT,同 web UI 同一套 API),服务器填
- REST API 两代(v2.4.0 起并存):
- v1:PUT=创建、POST=更新,列表返回裸数组 +
x-pagination-*头;v3.0 弃用、v4.0(约 2027)移除。新脚本一律不依赖 v1。 - v2(
/api/v2,标准 REST + OpenAPI 3.1):POST=创建(201)/GET/PATCH/DELETE(204 空体);列表返回 envelope{"items":…,"total":…},分页page/per_page;错误 RFC 9457 problem+json,校验失败 422;/api/v2/docs交互文档。 - 认证:Bearer API token(
tk_前缀,Settings > API Tokens)优先;或/api/v1/login得 JWT(v2 同样接受)。
- v1:PUT=创建、POST=更新,列表返回裸数组 +
- done 过滤(评审中危#6):用 filter 查询参数而非裸
?done=true:GET .../tasks?filter=done = true(URL 编码filter=done%20%3D%20true)。filter 日期数学(now,now-1d等)按服务器时区解析。 - CalDAV(评审高危#3):
- 根路径
/dav;客户端连https://<host>/dav/principals/<username>/(Tasks.org 也吃/.well-known/caldavredirect);每个项目=一个日历。 - 凭据:可用于账号密码、CalDAV tab 专用 token、或带 caldav 权限组的 API token(
tk_,v2.3.0+)当密码——与 API 脚本同源,推荐。 - 官方将 CalDAV 标为实验性(early alpha / has bugs);社区曾报 Tasks.org 同步回归(dav/projects 发现失败,2024-11 已修,后续版本含修复)。→ 双向 done 回写必须做独立前置 spike + GO/NO-GO 门,通过后才写脚本B’。
- v3 缓和:因双客户端并存,即使 CalDAV 双向不稳(NO-GO),官方安卓 app 的 API 写 done 仍可闭环 → CalDAV spike 从「生死门」降为「时间盒客户端的可用性确认」。
- 根路径
- 无默认用户;首用户唯一可靠入口 = CLI
docker exec <容器> /app/vikunja/vikunja user create -u feng -p <pw> -e <email>(不用注册开关;user set-admin需 Pro license,勿依赖)。 - 时间追踪为 Pro 付费(Homelab license)→ 不用,用 Tasks.org Schedule 时间块。
- 脚本现状(可复用改造):
/opt/radicale/scripts/{push_tasks.py, writeback_tasks.py, fns_mcp.py},state/opt/radicale/state/pushed_uids.json,cron 两行。 - 工作台文件:
000_Raw/00_plan/01_工作台/<YYYY-MM-DD>.md,行格式- [ ] 任务(HH:MM-HH:MM)。
4. Phase 0 — 部署 Vikunja(✓ 已实施,见验收)
实施记录:目录/compose/env/
.userpass/.apitoken已就位;chown 1000 files db;pinvikunja:2.5.0;用户feng已建;token id=2 权限含 caldav+projects+tasks;注册禁用;时区 Asia/Shanghai;公开 URLhttps://vikunja.unixcs.eu.org/;附件禁用。 验收:#1 达成(/api/v1/info 200、openapi.json 200、v2 envelope、时区 UTC 回读正确)。
先建目录并修权(评审中危#5:容器默认 UID 1000):
mkdir -p /opt/vikunja/{files,db,config,scripts,logs}
chown 1000 /opt/vikunja/files /opt/vikunja/db/opt/vikunja/compose.yml(pin 稳定 tag,不再用 latest):
services:
vikunja:
image: vikunja/vikunja:2.5.0
container_name: vikunja
restart: unless-stopped
ports:
- "3456:3456"
environment:
VIKUNJA_SERVICE_PUBLICURL: https://vikunja.unixcs.eu.org/
VIKUNJA_SERVICE_SECRET: <openssl rand -hex 32>
VIKUNJA_SERVICE_ENABLEREGISTRATION: "false"
VIKUNJA_SERVICE_TIMEZONE: Asia/Shanghai # ★ TZ env 无效,必须用这个
VIKUNJA_DATABASE_TYPE: sqlite
# VIKUNJA_DATABASE_PATH 官方镜像已预设 /db/vikunja.db,无需写
VIKUNJA_SERVICE_ENABLETASKATTACHMENTS: "false"
volumes:
- ./files:/app/vikunja/files
- ./db:/db- 建首用户(唯一可靠入口):
docker compose up -d docker exec vikunja /app/vikunja/vikunja user create -u feng -p "<强随机>" -e feng@unixcs.eu.org chmod 600 /opt/vikunja/config/.userpass # 存 用户名:密码,脚本读取,与 radicale 同模式 - 登录 web → Settings > API Tokens 建
注:本文涉及的服务器公网 IP / Tailnet / 局域网 IP 已脱敏,请替换为你自己的地址。