diff --git a/.task/feature-task-start-merged-guard.md b/.task/feature-task-start-merged-guard.md index 00df6e21..fdde936f 100644 --- a/.task/feature-task-start-merged-guard.md +++ b/.task/feature-task-start-merged-guard.md @@ -6,11 +6,13 @@ - 权威仓:ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/Agent-System-Dev.git;目标分支:main;R0(initial_base_sha)= 43d33aa4921078bc202393b99cba017d7f731b98 - 工作区:/home/weichen/projects/Agent-System-Dev-wt-feature-task-start-merged-guard(worktree);分支:feature/task-start-merged-guard -- 授权与交付终点:<本次允许的动作与终点;未授权事项写明> +- 授权与交付终点:owner 2026-10-05 授权立项(决策清单 #7);改 scripts/task.sh 加守护 + 测试 + PR 合入为本卡终点;不改 task.sh 其他行为。 ## 目标与非目标 -<预期结果、受影响入口/模块/契约;明确不做什么。> +- **目标**:`cmd_start` 在分支名校验后新增守护——本地或远端存在同名分支且已包含于 `origin/main` 时拒绝启动(exit 非零),提示「沿用原分支或换新 slug」。 +- **背景**:2026-10-05 EXT-1 复核轮实测,合入后再 `task-start` 同名分支会从新 main 长出第二段历史、空卡覆盖已合入任务卡(两轮证据差点丢失,靠 git show 恢复);旧逻辑只校验本地分支能否创建,不查是否刚合入。 +- **非目标**:不改 precheck/task-sync/finish 等其他子命令;不做「恢复原卡」的自动修复(拒绝即可,恢复留给人工);不引入新依赖。 ## 同步记录 @@ -29,3 +31,58 @@ - 结果: - 验证:<结论摘要 PASS/FAIL/SKIP/NOT_RUN 逐项;逐条证据由 make evidence 写入上方证据表> - 影响与剩余项: +| 2026-10-05T12:28:53Z | `bash -n scripts/task.sh` | 94f8d4760b | 0 | SELF | e3b0c44298fc1c14 | + + +``` +$ bash -n scripts/task.sh +[exit 0 | HEAD 94f8d4760b | sha256:e3b0c44298fc1c14] 输出尾部 15 行: + +``` +| 2026-10-05T12:28:53Z | `bash scripts/task.sh start feature/ext-1-inproc-handler && exit 1 \|\| echo 'guard refused merged branch as expected'` | 94f8d4760b | 0 | SELF | 937f2c0a1987b4f7 | + + +``` +$ bash scripts/task.sh start feature/ext-1-inproc-handler && exit 1 || echo 'guard refused merged branch as expected' +[exit 0 | HEAD 94f8d4760b | sha256:937f2c0a1987b4f7] 输出尾部 15 行: +ERROR: branch feature/ext-1-inproc-handler already merged into origin/main — reuse the original branch or pick a new slug (task-start must not recreate merged cards) +guard refused merged branch as expected +``` +| 2026-10-05T12:29:05Z | `make test` | 94f8d4760b | 0 | SELF | 84092b2ad053ee79 | + + +``` +$ make test +[exit 0 | HEAD 94f8d4760b | sha256:84092b2ad053ee79] 输出尾部 20 行: + + ✓ test/ui.test.tsx (6 tests) 66ms + ✓ test/toolblock.test.tsx (4 tests) 76ms + ✓ test/overlay-host.test.tsx (6 tests) 68ms + ✓ test/file-preview.test.tsx (9 tests) 89ms + ✓ test/inbox.test.tsx (13 tests) 93ms + ✓ test/card-anchor.test.tsx (4 tests) 96ms + ✓ test/inline-confirm.test.tsx (7 tests) 107ms + ✓ test/capability.test.tsx (14 tests) 153ms + + Test Files 14 passed (14) + Tests 103 passed (103) + Start at 12:29:37 + Duration 619ms (transform 415ms, setup 0ms, import 1.36s, tests 955ms, environment 3.25s) + +knip unused exports 55 <= 55 +cd deps/agent-command && go vet ./... && go test -count=1 ./... +ok agent-command 0.002s +ok agent-command/conformance 0.002s +make[1]: Leaving directory '/home/weichen/projects/Agent-System-Dev-wt-feature-task-start-merged-guard' +``` +| 2026-10-05T12:30:24Z | `make task-sync` | 94f8d4760b | 2 | SELF | c59e97420676c4fa | + + +``` +$ make task-sync +[exit 2 | HEAD 94f8d4760b | sha256:c59e97420676c4fa] 输出尾部 15 行: +make[1]: Entering directory '/home/weichen/projects/Agent-System-Dev-wt-feature-task-start-merged-guard' +ERROR: dirty tree — 先显式提交;不隐式 stash(collaboration.md:11) +make[1]: *** [Makefile:36: task-sync] Error 1 +make[1]: Leaving directory '/home/weichen/projects/Agent-System-Dev-wt-feature-task-start-merged-guard' +``` diff --git a/scripts/task.sh b/scripts/task.sh index 8a31e3ab..5505f5ba 100755 --- a/scripts/task.sh +++ b/scripts/task.sh @@ -102,9 +102,18 @@ cmd_precheck() { cmd_start() { need_repo - local name="${1:-}"; [ -n "$name" ] || die "usage: task.sh start /" + local name="${1:-}"; [ -n "$name" ] || die "usage: task.sh start /" echo "$name" | grep -qE '^(feature|fix|hotfix|release)/[A-Za-z0-9._-]+$' || die "branch name must match (feature|fix|hotfix|release)/" git fetch -q origin "${TARGET_BRANCH}" 2>/dev/null || true + # 已合入的同名分支不得重建(2026-10-05 实测:合入后再 task-start 同名会从新 main 长出 + # 第二段历史,空卡覆盖已合入任务卡,两轮证据差点丢失)。复核/追加沿用原分支或换新 slug。 + local guard_ref + for guard_ref in "refs/heads/${name}" "refs/remotes/origin/${name}"; do + if git rev-parse -q --verify "${guard_ref}" >/dev/null \ + && git merge-base --is-ancestor "${guard_ref}" "origin/${TARGET_BRANCH}"; then + die "branch ${name} already merged into origin/${TARGET_BRANCH} — reuse the original branch or pick a new slug (task-start must not recreate merged cards)" + fi + done [ "$(git status --porcelain | { grep -v '^.. \.zcode/' || true; } | wc -l)" -eq 0 ] || die "dirty tree — resolve first (precheck verdict BUSY)" [ "$(git submodule status --recursive 2>/dev/null | { grep -cE '^\+|^U' || true; })" -eq 0 ] || die "submodule drift/conflict — resolve first (precheck verdict BUSY)" git merge-base --is-ancestor "origin/${TARGET_BRANCH}" HEAD || die "local ${TARGET_BRANCH} behind origin — pull --ff-only first"