Files
QiuSWandClaude Opus 5 421c865ad2 feat(tasks): adopt Vikunja as task authority with one-way export
把任务的协调状态迁到自建 Vikunja 的 cmbuyer 项目,git 保留单向投影,
并把「活跃任务写路径不得重叠」从自然语言规则变成机器门禁。

- scripts/vikunja_export.py:单向导出(只发 GET),stdlib-only 的
  HTML→Markdown,只覆盖标记区块内,幂等,含 --selftest
- scripts/vikunja-mcp.sh:MCP 启动包装从家目录迁入仓库,版本写死 1.1.1
- scripts/validate_agent_context.py:新增四项离线检查——DOING 任务写路径
  互斥、通配不得圈走共享文档、导出区块 sha256、连接键一致性
- docs/agent-context.json:新增 shared_documents 与 tracker,schema_version 2
- vikunja.env 比照 gitea.env 加入 gitignore,提交 vikunja.env.example

write_paths、## 边界与安全边界条目的权威留在 git,不迁往 Vikunja:
安全边界能否收紧靠 git diff 逐条复核,权威搬到远端会切断审计链。

门禁上线即报出存量违规:T-005 与 T-006 同为 DOING,在 06-tasks.md、
08-interaction-checklist.md、routes.md、current-state.md 四处重叠。
按 T-008 规定不得绕过,须由两者所有者收窄写路径或人工确认后转 DONE。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 17:00:41 +08:00

68 lines
2.4 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Vikunja MCP 启动包装。
#
# 存在理由:
# 1. 凭据只留在 vikunja.env(已 gitignore),不进 .mcp.json、不进仓库、不进 shell 历史。
# 2. @0xk3vin/vikunja-mcp 内部自己拼 /api/v1(dist/vikunja-client.js:128),
# 而 vikunja.env 里的 apiurl 是带 /api/v1 的完整地址。直接透传会请求
# /api/v1/api/v1/... 并 404,所以这里必须剥掉一次。
# 3. 版本写死。上游改了工具名或行为会直接改变 agent 行为,与
# 「交付产物新旧以 SHA-256 判断」同源,不接受静默升级。
# 4. 优先用全局安装的二进制,起得快且不依赖网络;缺失时才回退 npx。
#
# 本脚本不含凭据,必须提交进仓库:其他 agent 与其他机器都靠它接入同一套配置。
set -euo pipefail
MCP_VERSION="${VIKUNJA_MCP_VERSION:-1.1.1}"
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# 凭据查找顺序:显式指定 > 仓库根目录 > 旧的家目录位置(向后兼容)。
find_env_file() {
if [ -n "${VIKUNJA_ENV_FILE:-}" ]; then
printf '%s\n' "$VIKUNJA_ENV_FILE"
return
fi
for candidate in "$REPO_ROOT/vikunja.env" "$HOME/.config/vikunja/env" "$HOME/.claude/vikunja.env"; do
if [ -r "$candidate" ]; then
printf '%s\n' "$candidate"
return
fi
done
printf '%s\n' "$REPO_ROOT/vikunja.env"
}
ENV_FILE="$(find_env_file)"
if [ ! -r "$ENV_FILE" ]; then
echo "vikunja-mcp: 读不到凭据文件 $ENV_FILE(参照 vikunja.env.example 创建)" >&2
exit 1
fi
# 只取需要的两个键,忽略文件里其余内容;tr -d '\r' 兼容 Windows 侧写出的 CRLF。
read_key() {
sed -n "s/^[[:space:]]*$1[[:space:]]*=[[:space:]]*//Ip" "$ENV_FILE" | tr -d '\r' | tail -n1
}
apiurl="$(read_key apiurl)"
apikey="$(read_key apikey)"
if [ -z "$apiurl" ] || [ -z "$apikey" ]; then
echo "vikunja-mcp: $ENV_FILE 缺少 apiurl 或 apikey" >&2
exit 1
fi
VIKUNJA_URL="${apiurl%/}"
VIKUNJA_URL="${VIKUNJA_URL%/api/v1}"
export VIKUNJA_URL
export VIKUNJA_API_TOKEN="$apikey"
# 全局安装存在且版本相符时直接用它;否则回退 npx(首次启动会联网拉包)。
if command -v vikunja-mcp >/dev/null 2>&1 &&
[ "$(npm ls -g --depth=0 --json @0xk3vin/vikunja-mcp 2>/dev/null |
sed -n 's/.*"version": *"\([^"]*\)".*/\1/p' | tail -n1)" = "$MCP_VERSION" ]; then
exec vikunja-mcp "$@"
fi
exec npx -y "@0xk3vin/vikunja-mcp@${MCP_VERSION}" "$@"