Add task-card autoclose wiring: close subcommand, post-merge hook, gate reports

Why: 11 merged branches had left their task cards open (bookkeeping debt found on 2026-09-30); closure was manual and never triggered, so card status rotted after each merge.
Evidence: dogfood run of `task.sh close --fold` closed and archived the 11 cards (previous commit); temp-repo matrix 33/33 PASS covering detection, pending-branch idempotence, dirty/no-fold refusals, post-merge auto-close on merge-type pulls, worktree guard, and the full lifecycle (closure PR merge archives cards on main).
Impact: scripts/task.sh (+close, precheck [cards] report, finish-tail trigger), scripts/hooks/post-merge (new), Makefile (+task-close target, setup chmod), AGENTS.md rule; archive fixes correct PR links missed by the first dogfood run; no module or gitlink change.
Refs: task card feature/card-autoclose-r1
This commit is contained in:
2026-09-30 07:12:54 +00:00
parent 6f6b670e55
commit beaefb7549
15 changed files with 185 additions and 26 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
# feature/delivery-mechanism 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge ef89fc8281);状态:已完成(回填);owner:weichen
任务主记录:PR #1 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/1(merge ef89fc8281);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -37,6 +37,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge ef89fc8281761eb64413ad5fd9be68a0bd08755e(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge ef89fc8281761eb64413ad5fd9be68a0bd08755e(PR #1)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Add the task-startup gate: precheck/task-start/task-sync/task-finish and local hooks' (#1) from feature/delivery-mechanism into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
+2 -2
View File
@@ -1,6 +1,6 @@
# feature/adopt-draft9 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge 05a5ae1e1a);状态:已完成(回填);owner:weichen
任务主记录:PR #10 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/10(merge 05a5ae1e1a);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge 05a5ae1e1ac8ef8d341170c236e9b38570e48947(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge 05a5ae1e1ac8ef8d341170c236e9b38570e48947(PR #10)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Adopt the draft.9 hierarchy and memory rules; pin the records archive' (#10) from feature/adopt-draft9 into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
@@ -1,6 +1,6 @@
# feature/core-cards-commands-r1 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge 69fd335dea);状态:已完成(回填);owner:weichen
任务主记录:PR #15 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/15(merge 69fd335dea);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge 69fd335deac237f5291298cb06a50bf03d11add7(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge 69fd335deac237f5291298cb06a50bf03d11add7(PR #15)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'T1: pin contracts combo (core cards/commands, agent-command v0) and guard task-finish' (#15) from feature/core-cards-commands-r1 into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
+2 -2
View File
@@ -1,6 +1,6 @@
# feature/gate-hardening 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge 8f7cf2d9b9);状态:已完成(回填);owner:weichen
任务主记录:PR #8 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/8(merge 8f7cf2d9b9);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge 8f7cf2d9b9f45ab7c498b753e436e38fbc7726b1(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge 8f7cf2d9b9f45ab7c498b753e436e38fbc7726b1(PR #8)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Harden the gate: uninitialized-submodule detection and platform protection registration' (#8) from feature/gate-hardening into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
+2 -2
View File
@@ -1,6 +1,6 @@
# feature/hardening-batch 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge dca932c6da);状态:已完成(回填);owner:weichen
任务主记录:PR #11 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/11(merge dca932c6da);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge dca932c6da3aea34af722f2a6772e621cf6143f5(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge dca932c6da3aea34af722f2a6772e621cf6143f5(PR #11)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Add CI, version stamping, and the high-consequence two-key rule' (#11) from feature/hardening-batch into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
+2 -2
View File
@@ -1,6 +1,6 @@
# feature/pin-config-surface 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge a58f85e0d0);状态:已完成(回填);owner:weichen
任务主记录:PR #12 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/12(merge a58f85e0d0);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge a58f85e0d0ade6e8b4da3afe9985985a38bae47a(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge a58f85e0d0ade6e8b4da3afe9985985a38bae47a(PR #12)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Pin backend with the configuration pipe and documents with its design' (#12) from feature/pin-config-surface into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
@@ -1,6 +1,6 @@
# feature/pin-documents-lessons 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge e85d1ee49f);状态:已完成(回填);owner:weichen
任务主记录:PR #9 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/9(merge e85d1ee49f);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge e85d1ee49f5fb6659d83a3ed3c17ba42a93d5926(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge e85d1ee49f5fb6659d83a3ed3c17ba42a93d5926(PR #9)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Pin the documents gitlink to the delivery lessons; align gate guards' (#9) from feature/pin-documents-lessons into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
@@ -1,6 +1,6 @@
# feature/tool-adaptation-standard 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge ff931e5f70);状态:已完成(回填);owner:weichen
任务主记录:PR #5 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/5(merge ff931e5f70);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge ff931e5f70cdf4d725d86f7925b067261a70c8bd(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge ff931e5f70cdf4d725d86f7925b067261a70c8bd(PR #5)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Adopt the tool adaptation standard and register the first instance matrix' (#5) from feature/tool-adaptation-standard into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
+1 -1
View File
@@ -32,6 +32,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge 69e9471dafd275f98928ff005732b94c4b18b638(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge 69e9471dafd275f98928ff005732b94c4b18b638(PR #14)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Wire Agent-System-UI and Agent-Command into the Dev combo (T0)' (#14) from feature/ui-foundation-r0 into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
+2 -2
View File
@@ -1,6 +1,6 @@
# feature/zcode-hooks 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge 20727a8fd3);状态:已完成(回填);owner:weichen
任务主记录:PR #7 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/7(merge 20727a8fd3);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge 20727a8fd3adeafee6fb37383948e2a9c5a004b0(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge 20727a8fd3adeafee6fb37383948e2a9c5a004b0(PR #7)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Add the zcode write-path guard instance with its adaptation matrix' (#7) from feature/zcode-hooks into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
+2 -2
View File
@@ -1,6 +1,6 @@
# fix/empty-list-json 任务卡
任务主记录:PR #unknown https://git-home.u1680832.nyat.app:30319/pulls/unknown(merge 36d1393bd2);状态:已完成(回填);owner:weichen
任务主记录:PR #3 https://git-panel.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/3(merge 36d1393bd2);状态:已完成(回填);owner:weichen
## 基线与授权
@@ -26,6 +26,6 @@
## 闭合记录(card-autoclose 回填)
- 依据:merge 36d1393bd2806e8dddb69b1fc8850b5dbc3982d2(PR #unknown)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 依据:merge 36d1393bd2806e8dddb69b1fc8850b5dbc3982d2(PR #3)已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:Merge pull request 'Advance the backend gitlink with the empty-list serialization fix' (#3) from fix/empty-list-json into main
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
+5
View File
@@ -14,6 +14,11 @@
- 合入后**在 worktree 内**运行 `make task-finish` 回收 worktree 与分支(脚本会把
当前目录当 worktree 回收——在主检出运行会误删主检出,已加防护);放弃未合入
工作用 `make task-finish ABANDON="--abandon <原因>"` 并记录原因。
- **任务卡闭合(防欠账)**:分支合入 main 后,其任务卡须回填"已完成"+主记录 PR 链接并
归档至 `.task/archive/`。自动路径:`make task-finish` 收尾触发、主检出 merge 型 pull 触发
post-merge 钩子(ff-only 不触发,由前两者兜底);手动为 `make task-close`(主检出运行→建
`feature/card-close-*` 分支+PR,任务分支内加 `FOLD=--fold` 随当前 PR 合入)。
precheck 的 `[cards]` 行报告欠账,验收前应清零;闭合 PR 由所有者合入。
## 提交与 PR
+6 -3
View File
@@ -13,7 +13,7 @@ PLUGINS := plugins
COMBO := core=$(shell git -C $(CORE) rev-parse --short HEAD 2>/dev/null)+backend=$(shell git -C $(BACKEND) rev-parse --short HEAD 2>/dev/null)+frontend=$(shell git -C $(FRONTEND) rev-parse --short HEAD 2>/dev/null)+ui=$(shell git -C $(UI) rev-parse --short HEAD 2>/dev/null)+agentcmd=$(shell git -C deps/agent-command rev-parse --short HEAD 2>/dev/null)+documents=$(shell git -C modules/documents rev-parse --short HEAD 2>/dev/null)
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null)+$(COMBO)
.PHONY: help sync status build frontend test test-backend test-frontend test-ui test-core test-agentcmd dev pin clean setup precheck task-start task-sync task-finish version
.PHONY: help sync status build frontend test test-backend test-frontend test-ui test-core test-agentcmd dev pin clean setup precheck task-start task-sync task-close task-finish version
version:
@echo "agent-system $(VERSION)"
@@ -22,8 +22,8 @@ TASK := scripts/task.sh
setup:
git config core.hooksPath scripts/hooks
chmod +x scripts/hooks/pre-commit scripts/task.sh
@echo "OK: pre-commit 钩子已启用(core.hooksPath=scripts/hooks)"
chmod +x scripts/hooks/pre-commit scripts/hooks/post-merge scripts/task.sh
@echo "OK: pre-commit/post-merge 钩子已启用(core.hooksPath=scripts/hooks)"
precheck:
@bash $(TASK) precheck
@@ -35,6 +35,9 @@ task-start:
task-sync:
@bash $(TASK) sync
task-close:
@bash $(TASK) close $(FOLD)
task-finish:
@bash $(TASK) finish $(ABANDON)
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# 本地钩子(post-merge):merge 型 pull/merge 落地后自动闭合已合入任务卡(ff-only 不触发
# 本钩子——由 task-finish 收尾与 precheck [cards] 报告兜底)。
# 触发条件收紧到"主检出 + 集成分支 main"——任务 worktree 里 task-sync 的 merge 不触发,
# 防止把卡片闭合混进任务分支现场。失败只警告,绝不阻断 pull。
# 注意:task.sh close 在主检出会另建 feature/card-close-* 分支提交(集成分支不直推),
# 结束后切回 main;PR 由所有者合入。
common=$(git rev-parse --git-common-dir) && common=$(cd "$common" 2>/dev/null && pwd) || exit 0
mainrepo=$(dirname "$common")
[ "$mainrepo" = "$PWD" ] || exit 0
[ "$(git rev-parse --abbrev-ref HEAD)" = "main" ] || exit 0
[ -f "$mainrepo/scripts/task.sh" ] || exit 0
bash "$mainrepo/scripts/task.sh" close \
|| echo "[warn] post-merge 卡片自动闭合失败——在主检出手动运行 make task-close" >&2
exit 0
+138 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# 任务启动门禁:precheck / start / sync / finish(配套 Makefile 同名目标)。
# 任务启动门禁:precheck / start / sync / close / finish(配套 Makefile 同名目标)。
# 规范依据:collaboration.md 共同基线与同步节点、治理清理;delivery.md §1/§5。
set -euo pipefail
@@ -31,6 +31,17 @@ cmd_precheck() {
[ "${sub_uninit:-0}" -gt 0 ] && echo "[warn] ${sub_uninit} 个子模块未初始化——构建/测试前需物化(不阻断写入)"
echo "[worktrees] linked=${wt}"
[ -n "$merged" ] && echo "[recycle] merged un-recycled branches: $(echo $merged)"
local open_cards="" pc pb pst
for pc in .task/*.md; do
[ -f "$pc" ] || continue
pb=$(card_of_branch "$pc"); [ -n "$pb" ] || continue
pst=$(card_status "$pc"); case "$pst" in 已完成*) continue ;; esac
card_pending "${pc##*/}" && continue
if git log --merges --format='%s' "origin/${TARGET_BRANCH}" 2>/dev/null | grep -qF " from $pb into ${TARGET_BRANCH}"; then
open_cards="${open_cards} ${pc##*/}"
fi
done
[ -n "$open_cards" ] && echo "[cards] 已合入未闭合任务卡:$(echo $open_cards)——make task-close 回填归档(主检出运行)"
echo "[required-reading] core/baseline.md, workflows/delivery.md §1$([ "$dirty" -gt 0 ] && echo ", standards/collaboration.md(树脏=他人或未收尾现场,不得写入)")"
echo "[R0] $(echo "$rmain" | cut -c1-10)(完整:$rmain)"
if [ "$dirty" -gt 0 ] || [ "${sub_drift:-0}" -gt 0 ]; then
@@ -110,6 +121,127 @@ cmd_sync() {
echo "[next] 跑正式验收(make test 等),证据写入任务卡"
}
# ---- 卡片闭合(防欠账)----
# 依据:delivery.md §5 治理清理;机制化 2026-09-30 治理缺口(11 张已合入卡片未闭合)。
# 检测 .task/*.md 中"分支已合入 origin/<target> 但状态非已完成"的卡片:回填状态、主记录
# (PR 链接+合并 SHA)与闭合记录,并 git mv 到 .task/archive/。变更落点:主检出运行→
# 新建 feature/card-close-* 分支推送(集成分支受保护,不直推);任务分支内运行须 --fold
# (随当前任务 PR 合入)。合并判定用合并提交主题(分支删除后仍可追溯),不依赖分支存活。
card_of_branch() { sed -n 's/^- 工作区:.*分支:\([A-Za-z0-9._/-]\+\).*/\1/p' "$1" | head -1; }
card_status() { sed -n 's/^.*;状态:\([^;]*\).*/\1/p' "$1" | head -1; }
card_merge() { # $1=branch → "sha|subject"(该分支合入 origin/<target> 的合并提交)
git log --merges --format='%H|%s' "origin/${TARGET_BRANCH}" 2>/dev/null \
| grep -F " from $1 into ${TARGET_BRANCH}" | head -1
}
card_pending() { # $1=卡片文件名——闭合是否已在某 origin/feature/card-close-* 分支待合入
local cb
for cb in $(git for-each-ref --format='%(refname:short)' "refs/remotes/origin/feature/card-close-*"); do
git cat-file -e "${cb}:.task/archive/$1" 2>/dev/null && return 0
done
return 1
}
card_backfill() { # $1=card $2=pr_num $3=merge_sha $4=merge_subject $5=web_base(原地改写)
python3 - "$1" "$2" "$3" "$4" "$5" <<'PY'
import re, sys
path, pr, sha, subject, base = sys.argv[1:6]
s = open(path, encoding='utf-8').read()
s = re.sub(r'状态:[^;\n]*', '状态:已完成(回填)', s, count=1)
m = re.search(r'任务主记录:([^;\n]*)', s)
if m and 'pulls/' not in m.group(1):
s = s.replace(m.group(1), f'PR #{pr} {base}/pulls/{pr}(merge {sha[:10]})', 1)
s = s.replace('## 结果与验证(完成后填写)', '## 结果与验证', 1)
s = s.rstrip('\n') + f'''
## 闭合记录(card-autoclose 回填)
- 依据:merge {sha}(PR #{pr})已包含于 origin/main,分支成果已落盘;本段为合入后回填。
- 合并主题:{subject}
- 归档:随闭合移入 .task/archive/;任务执行期的过程证据见原任务记录与 PR。
'''
open(path, 'w', encoding='utf-8').write(s)
PY
}
cmd_close() {
need_repo
local fold=0
[ "${1:-}" = "--fold" ] && fold=1
git fetch -q origin "${TARGET_BRANCH}" 2>/dev/null || true
# 默认值取远端通告的 Web 面(git push 输出的 PR 建议链接);可用 TASK_CARD_WEB_BASE 覆盖
local web_base="${TASK_CARD_WEB_BASE:-https://git-panel.u1680832.nyat.app:30319}"
local url owner repo
url=$(git remote get-url origin); url="${url%.git}"
repo=$(basename "$url"); owner=$(basename "$(dirname "$url")")
local branch c b st m cards=""
branch=$(git rev-parse --abbrev-ref HEAD)
for c in .task/*.md; do
[ -f "$c" ] || continue
b=$(card_of_branch "$c"); [ -n "$b" ] || continue
st=$(card_status "$c"); case "$st" in 已完成*) continue ;; esac
if card_pending "${c##*/}"; then
echo "[close] ${c##*/} 已有待合入的闭合分支,跳过(等其 PR 合入)"
continue
fi
m=$(card_merge "$b") || m=""
[ -n "$m" ] || continue
cards="$cards
$c|$b|$m"
done
[ -n "$cards" ] || { echo "[close] 无已合入未闭合的任务卡"; exit 0; }
# 落点:主检出→feature/card-close-* 分支(提交过 pre-commit 分支闸);任务分支须显式 --fold
local newbranch=""
if [ "$branch" = "${TARGET_BRANCH}" ]; then
[ -z "$(git status --porcelain | grep -v '^.. \.zcode/' || true)" ] || die "主检出树脏——先收尾再 close(防混入未提交现场)"
newbranch="feature/card-close-$(date -u +%Y%m%d-%H%M%SZ)"
git rev-parse --verify -q "refs/heads/${newbranch}" >/dev/null && die "分支已存在:${newbranch}"
git checkout -q -b "$newbranch" "origin/${TARGET_BRANCH}"
elif [ "$fold" != "1" ]; then
die "close 在任务分支内须加 --fold(并入当前任务 PR);或到主检出运行(将建 feature/card-close-* 分支+PR)"
fi
local n=0 sha subject pr closed_list=""
while IFS='|' read -r c b m; do
[ -n "$c" ] || continue
sha="${m%%|*}"; subject="${m#*|}"
pr=$(printf '%s' "$subject" | sed -n 's/.*(#\([0-9]\+\)) from.*/\1/p')
[ -n "$pr" ] || pr=unknown
card_backfill "$c" "$pr" "$sha" "$subject" "${web_base}/${owner}/${repo}"
mkdir -p .task/archive
git mv "$c" ".task/archive/${c##*/}"
closed_list="$closed_list ${c##*/}(PR#${pr})"
n=$((n+1))
done <<EOF
$cards
EOF
local msg; msg=$(mktemp)
{ echo "Close ${n} merged task card(s) and archive them"
echo
echo "Why: branches merged into ${TARGET_BRANCH} had left their task cards open; backfill status and archive to prevent bookkeeping debt."
echo "Evidence: $(echo $closed_list) — merges verified via git log --merges against origin/${TARGET_BRANCH}."
echo "Impact: .task/*.md moved to .task/archive/ with status backfilled; no code or submodule change."
echo "Refs: task.sh close (card-autoclose-r1)"
} > "$msg"
git add .task
git commit -q -F "$msg"; rm -f "$msg"
git push -q -u origin HEAD
local headbr pr_url=""
headbr=$(git rev-parse --abbrev-ref HEAD)
if [ -n "${GITEA_TOKEN:-}" ]; then
local resp
resp=$(curl -sS -X POST -H "Authorization: token ${GITEA_TOKEN}" -H 'Content-Type: application/json' \
"${web_base}/api/v1/repos/${owner}/${repo}/pulls" \
-d "{\"head\":\"${headbr}\",\"base\":\"${TARGET_BRANCH}\",\"title\":\"Close merged task cards (${headbr})\",\"body\":\"Auto-generated by task.sh close; see commit message for evidence.\"}" 2>/dev/null || true)
pr_url=$(printf '%s' "$resp" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("html_url",""))' 2>/dev/null || true)
fi
if [ -n "$newbranch" ]; then git checkout -q "${TARGET_BRANCH}"; fi
if [ -n "$pr_url" ]; then
echo "[pr] ${pr_url}(合入权在所有者)"
else
echo "[next] 建 PR:${web_base}/${owner}/${repo}/pulls/new?head=${headbr}(合入权在所有者)"
fi
echo "[closed] ${n} 张已合入卡片已回填归档,提交于 ${headbr} 并推送"
}
cmd_finish() {
need_repo
local abandon="${1:-}"
@@ -140,12 +272,16 @@ cmd_finish() {
git -C "$mainrepo" worktree prune
git push -q --delete origin "$branch" 2>/dev/null || true
echo "[recycled] worktree 与分支 ${branch} 已回收(本地+远端,$(date -u +%FT%TZ))"
# 合入成功→自动闭合任务卡(含本任务卡;经 feature/card-close-* 分支+PR,合入权在所有者)
( cd "$mainrepo" && bash scripts/task.sh close ) \
|| echo "[next] 卡片自动闭合未完成——在主检出运行 make task-close"
}
case "${1:-}" in
precheck) shift; cmd_precheck "$@" ;;
start) shift; cmd_start "$@" ;;
sync) shift; cmd_sync "$@" ;;
close) shift; cmd_close "$@" ;;
finish) shift; cmd_finish "$@" ;;
*) echo "usage: task.sh <precheck|start|sync|finish> [args]"; exit 2 ;;
*) echo "usage: task.sh <precheck|start|sync|close|finish> [args]"; exit 2 ;;
esac