Guard task-start against reusing a merged branch name
Why: 合入后再 task-start 同名分支会从新 main 长出第二段历史并覆盖已合入任务卡 (2026-10-05 EXT-1 复核轮实测,两轮证据差点丢失);原校验只看本地分支能否创建。 Evidence: bash -n 通过;功能负例——start feature/ext-1-inproc-handler 被拒且无 worktree 副作用;make test 全链 exit 0;task-sync 基线 43d33aa。 Impact: 仅 scripts/task.sh cmd_start 增加已合入同名分支检查,其余子命令行为不变。 Refs: EXT-1 任务卡复核轮记录(.task/archive/feature-ext-1-inproc-handler.md)。
This commit is contained in:
@@ -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 |
|
||||
|
||||
<!-- evidence:run 2026-10-05T12:28:53Z -->
|
||||
```
|
||||
$ 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 |
|
||||
|
||||
<!-- evidence:run 2026-10-05T12:28:53Z -->
|
||||
```
|
||||
$ 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 |
|
||||
|
||||
<!-- evidence:run 2026-10-05T12:29:05Z -->
|
||||
```
|
||||
$ 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 |
|
||||
|
||||
<!-- evidence:run 2026-10-05T12:30:24Z -->
|
||||
```
|
||||
$ 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'
|
||||
```
|
||||
|
||||
+10
-1
@@ -102,9 +102,18 @@ cmd_precheck() {
|
||||
|
||||
cmd_start() {
|
||||
need_repo
|
||||
local name="${1:-}"; [ -n "$name" ] || die "usage: task.sh start <feature|fix|hotfix>/<slug>"
|
||||
local name="${1:-}"; [ -n "$name" ] || die "usage: task.sh start <feature|fix|hotfix|release>/<slug>"
|
||||
echo "$name" | grep -qE '^(feature|fix|hotfix|release)/[A-Za-z0-9._-]+$' || die "branch name must match (feature|fix|hotfix|release)/<slug>"
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user