@aipper/aiws-spec 0.0.23 → 0.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/workspace/.agents/skills/ws-bugfix/SKILL.md +30 -7
- package/templates/workspace/.agents/skills/ws-commit/SKILL.md +3 -1
- package/templates/workspace/.agents/skills/ws-deliver/SKILL.md +24 -9
- package/templates/workspace/.agents/skills/ws-dev/SKILL.md +46 -5
- package/templates/workspace/.agents/skills/ws-finish/SKILL.md +77 -60
- package/templates/workspace/.agents/skills/ws-plan/SKILL.md +36 -1
- package/templates/workspace/.claude/commands/ws-bugfix.md +11 -6
- package/templates/workspace/.claude/commands/ws-commit.md +2 -1
- package/templates/workspace/.claude/commands/ws-deliver.md +6 -2
- package/templates/workspace/.claude/commands/ws-dev.md +5 -2
- package/templates/workspace/.claude/commands/ws-finish.md +19 -19
- package/templates/workspace/.claude/commands/ws-plan.md +9 -5
- package/templates/workspace/.codex/prompts/ws-dev.md +5 -1
- package/templates/workspace/.githooks/commit-msg +109 -0
- package/templates/workspace/.iflow/commands/ws-commit.toml +2 -1
- package/templates/workspace/.iflow/commands/ws-deliver.toml +6 -2
- package/templates/workspace/.iflow/commands/ws-finish.toml +19 -19
- package/templates/workspace/.opencode/command/ws-bugfix.md +11 -6
- package/templates/workspace/.opencode/command/ws-commit.md +2 -1
- package/templates/workspace/.opencode/command/ws-deliver.md +6 -2
- package/templates/workspace/.opencode/command/ws-dev.md +5 -2
- package/templates/workspace/.opencode/command/ws-finish.md +19 -19
- package/templates/workspace/.opencode/command/ws-plan.md +9 -5
- package/templates/workspace/AGENTS.md +1 -0
- package/templates/workspace/AI_WORKSPACE.md +4 -4
- package/templates/workspace/changes/README.md +8 -2
- package/templates/workspace/manifest.json +2 -0
- package/templates/workspace/tools/ws_change_check.py +1 -1
- package/templates/workspace/tools/ws_resolve_sub_target.sh +1 -0
package/package.json
CHANGED
|
@@ -19,12 +19,34 @@ description: 缺陷修复(通过禅道 MCP 拉取 bug 与附件,下载图片
|
|
|
19
19
|
前置:
|
|
20
20
|
1) 先运行 `$ws-preflight`。
|
|
21
21
|
2) 准备 `change-id`(建议:`bug-<bug-id>` 或 `bugfix-<bug-id>-<slug>`)。
|
|
22
|
-
3)
|
|
22
|
+
3) 建立 change 上下文(推荐先于任何落盘):
|
|
23
|
+
- 若当前还不在 `change/<change-id>` 分支 / worktree,先调用 `aiws change start`
|
|
24
|
+
- 工作区必须先干净;否则不要先写 `changes/<change-id>/bug/` 或 `issues/fix_bus_issues.csv`,避免后续切 worktree 时工件留在原工作区
|
|
25
|
+
- 仓库已有提交:优先 `--worktree`
|
|
26
|
+
- superproject + submodule:优先 `--worktree --submodules`
|
|
27
|
+
- 仓库尚无提交 / 不满足 worktree 前置条件:回退 `--no-switch`
|
|
23
28
|
```bash
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
if [[ -n "$(git status --porcelain)" ]]; then
|
|
30
|
+
echo "error: working tree dirty before ws-bugfix creates change context"
|
|
31
|
+
exit 2
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if git rev-parse --verify HEAD >/dev/null 2>&1; then
|
|
35
|
+
if [[ -f .gitmodules ]] && git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' >/dev/null 2>&1; then
|
|
36
|
+
aiws change start <change-id> --hooks --worktree --submodules
|
|
37
|
+
else
|
|
38
|
+
aiws change start <change-id> --hooks --worktree
|
|
39
|
+
fi
|
|
40
|
+
else
|
|
41
|
+
aiws change start <change-id> --hooks --no-switch
|
|
42
|
+
fi
|
|
27
43
|
```
|
|
44
|
+
- 若上一步创建了 worktree:后续 bug 证据、CSV 更新、`$ws-dev` 修复都必须在该 worktree 中继续;不要回原工作区重复创建 change
|
|
45
|
+
- 若该 change 涉及 submodule:
|
|
46
|
+
- 优先复用 `$ws-dev` 的 `submodules.targets` 生成/确认流程
|
|
47
|
+
- detached HEAD 时默认建议取 `.gitmodules` 声明的分支
|
|
48
|
+
- 已附着在某个本地分支时默认建议取当前分支
|
|
49
|
+
- 以上都只是建议值,最终必须显式写入 `changes/<change-id>/submodules.targets`
|
|
28
50
|
|
|
29
51
|
建议流程(按顺序):
|
|
30
52
|
|
|
@@ -36,7 +58,7 @@ aiws change start <change-id> --hooks --worktree --submodules
|
|
|
36
58
|
- 若当前环境没有 zentao MCP 工具:立即停止并提示用户先配置,不要猜数据。
|
|
37
59
|
|
|
38
60
|
## 2) 证据落盘(强制)
|
|
39
|
-
|
|
61
|
+
在当前 active change 上下文的 `changes/<change-id>/bug/` 下落盘:
|
|
40
62
|
- `zentao-bug-<bug-id>.json`:原始字段快照(避免信息丢失)
|
|
41
63
|
- `zentao-bug-<bug-id>.md`:人类可读摘要(复现步骤/期望/实际/风险)
|
|
42
64
|
- `images/<bug-id>/...`:下载的图片附件(保留原扩展名)
|
|
@@ -50,7 +72,7 @@ changes/<change-id>/bug/
|
|
|
50
72
|
```
|
|
51
73
|
|
|
52
74
|
## 3) 汇总到 issues/fix_bus_issues.csv(upsert)
|
|
53
|
-
-
|
|
75
|
+
- 目标文件:当前 active change 上下文中的 `issues/fix_bus_issues.csv`
|
|
54
76
|
- 若文件不存在,先创建表头:
|
|
55
77
|
```csv
|
|
56
78
|
Bug_ID,Title,Severity,Module,Status,Assigned_To,Change_ID,Image_Count,Image_Paths,Evidence_Path,Verify_Command,Fix_Status,Updated_At,Notes
|
|
@@ -66,7 +88,7 @@ Bug_ID,Title,Severity,Module,Status,Assigned_To,Change_ID,Image_Count,Image_Path
|
|
|
66
88
|
- `Fix_Status`:`TODO|DOING|DONE|BLOCKED`
|
|
67
89
|
|
|
68
90
|
## 4) 修复执行与回填
|
|
69
|
-
- 进入 `$ws-dev`
|
|
91
|
+
- 进入 `$ws-dev` 做最小改动修复;若 `ws-bugfix` 创建了 worktree,则必须在该 worktree 中继续。
|
|
70
92
|
- 完成后回填 `issues/fix_bus_issues.csv`:
|
|
71
93
|
- `Fix_Status`
|
|
72
94
|
- `Verify_Command`
|
|
@@ -83,6 +105,7 @@ aiws validate . --stamp
|
|
|
83
105
|
|
|
84
106
|
输出要求:
|
|
85
107
|
- `Change_ID:` `<change-id>`
|
|
108
|
+
- `Change context:` `<当前分支或 worktree 路径>`
|
|
86
109
|
- `CSV:` `issues/fix_bus_issues.csv` 中对应 `Bug_ID` 行的关键字段
|
|
87
110
|
- `Evidence:` `changes/<change-id>/bug/zentao-bug-<bug-id>.md` + 图片目录
|
|
88
111
|
- `Verify:` 实际运行命令与结果(未运行不声称已运行)
|
|
@@ -18,7 +18,8 @@ description: 提交(当前分支可直提;submodule 感知;先审计/门
|
|
|
18
18
|
- 不自动 push
|
|
19
19
|
- 不写入任何 secrets
|
|
20
20
|
- 检测到 submodule 有未提交改动时,不允许直接提交 superproject(先处理 submodule)
|
|
21
|
-
- commit message
|
|
21
|
+
- commit message 优先使用中文(命令/路径/代码标识符保持原样不翻译);格式建议:`<类型>: <简述>`(例如 `修复: 登录页空指针`、`功能: 新增 submodule targets 校验`、`重构: 提取共享脚本`)
|
|
22
|
+
- 若启用了 `.githooks/commit-msg`:默认会提示优先中文;只有在 `git config aiws.commitMessagePolicy strict` 时才会拒绝全英文首行(`Merge/Revert/fixup!/squash!` 例外)
|
|
22
23
|
|
|
23
24
|
执行步骤(建议):
|
|
24
25
|
1) 运行 `$ws-preflight`(确保真值文件就绪)。
|
|
@@ -87,6 +88,7 @@ git diff --staged --submodule=short
|
|
|
87
88
|
- 类型参考:`功能` / `修复` / `重构` / `文档` / `测试` / `构建` / `杂项`
|
|
88
89
|
- 简述用一句话概括本次改动的"为什么"而非"改了什么"
|
|
89
90
|
- 命令/路径/代码标识符保持原样不翻译
|
|
91
|
+
- 若用户给出全英文 message:优先改写成中文;若用户明确要求保留英文,也可以提交(但 strict 模式下会被 hook 拒绝)
|
|
90
92
|
10) 执行提交(不带 `--no-verify`):
|
|
91
93
|
```bash
|
|
92
94
|
git commit -m "<message>"
|
|
@@ -29,7 +29,8 @@ description: 交付(submodules + superproject 分步提交,并安全合并
|
|
|
29
29
|
|
|
30
30
|
## 0) submodule branch 真值检查(减少 detached 与人为差异)
|
|
31
31
|
如果存在 `.gitmodules` 但缺少 `submodule.<name>.branch`,先运行 `$ws-submodule-setup` 并提交 `.gitmodules`,否则后续 `aiws validate .` 会失败,且 `ws-pull/ws-finish` 无法确定性工作。
|
|
32
|
-
> 说明:若同一 superproject
|
|
32
|
+
> 说明:若同一 superproject 分支内存在多渠道 submodule 目标分支的交付需求,可在 `changes/<change-id>/submodules.targets` 额外声明本次 change 的目标分支;交付时会优先使用该文件(不改变 `.gitmodules` 的团队默认真值)。
|
|
33
|
+
> 生成该文件时,可以按当前状态做默认预填,但必须显式说明来源并让用户确认:detached HEAD 默认建议取 `.gitmodules` 声明分支;已附着在某个本地分支时默认建议取当前分支;finish/push 最终只认 `submodules.targets`。
|
|
33
34
|
```bash
|
|
34
35
|
if [[ -f .gitmodules ]]; then
|
|
35
36
|
missing=0
|
|
@@ -85,15 +86,29 @@ sub_path="<path>"
|
|
|
85
86
|
git -C "$sub_path" branch --show-current
|
|
86
87
|
git -C "$sub_path" status --porcelain
|
|
87
88
|
```
|
|
88
|
-
2)
|
|
89
|
+
2) 先确定该 submodule 的目标分支来源,并显式说明给用户:
|
|
90
|
+
- `branch --show-current` 非空:默认建议用当前分支
|
|
91
|
+
- `branch --show-current` 为空(detached HEAD):默认建议用 `.gitmodules` 的 `submodule.<name>.branch`
|
|
92
|
+
- 若建议值与 `changes/<change-id>/submodules.targets` 已落盘值不一致:以 `submodules.targets` 为准,并先提示差异
|
|
93
|
+
3) 若 submodule 处于 detached HEAD(`branch --show-current` 为空):
|
|
89
94
|
- 说明:这通常是因为 superproject 的 gitlink checkout(例如 `git submodule update`)导致 detached。
|
|
90
|
-
- 不要直接切 `change/<change-id>` / `main` / `master`
|
|
95
|
+
- 不要直接切 `change/<change-id>` / `main` / `master` 来解 detached。
|
|
91
96
|
- 若你要在该 submodule 里提交:先按目标分支挂到 pin 分支 `aiws/pin/<target-branch>`,再在其上提交:
|
|
92
97
|
- 目标分支真值优先级:`changes/<change-id>/submodules.targets`(若存在)> `.gitmodules submodule.<name>.branch`
|
|
93
98
|
```bash
|
|
94
99
|
change_id="<change-id>"
|
|
95
100
|
targets="changes/${change_id}/submodules.targets"
|
|
96
|
-
|
|
101
|
+
sub_name="$(git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' 2>/dev/null | awk -v p="${sub_path}" '$2==p { name=$1; sub(/^submodule\\./,"",name); sub(/\\.path$/,"",name); print name; exit }')"
|
|
102
|
+
base_branch="$(python3 - <<'PY'
|
|
103
|
+
import json, pathlib
|
|
104
|
+
change_id = "<change-id>"
|
|
105
|
+
meta = pathlib.Path("changes") / change_id / ".ws-change.json"
|
|
106
|
+
data = json.loads(meta.read_text(encoding="utf-8"))
|
|
107
|
+
print((data.get("base_branch") or "").strip())
|
|
108
|
+
PY
|
|
109
|
+
)"
|
|
110
|
+
test -n "${sub_name}"
|
|
111
|
+
test -n "${base_branch}"
|
|
97
112
|
|
|
98
113
|
source tools/ws_resolve_sub_target.sh
|
|
99
114
|
ws_resolve_sub_target "${sub_path}" "${sub_name}" "${targets}" "${base_branch}" || exit 2
|
|
@@ -109,18 +124,18 @@ git -C "$sub_path" checkout -B "aiws/pin/${target_branch}" HEAD
|
|
|
109
124
|
git -C "$sub_path" branch --set-upstream-to "${remote}/${target_branch}" "aiws/pin/${target_branch}" >/dev/null 2>&1 || true
|
|
110
125
|
```
|
|
111
126
|
- 若 `origin/<target-branch>` 不存在,或用户明确不想使用 pin 分支:停止,解释风险(提交可能不可追溯/难以推送)。
|
|
112
|
-
|
|
127
|
+
4) 选择性 staging(默认用 `-p` 更安全):
|
|
113
128
|
```bash
|
|
114
129
|
git -C "$sub_path" add -p
|
|
115
130
|
git -C "$sub_path" diff --staged --stat
|
|
116
131
|
git -C "$sub_path" diff --staged
|
|
117
132
|
```
|
|
118
|
-
|
|
119
|
-
|
|
133
|
+
5) AI 生成该 submodule 的 commit message(标题+可选 body),并让用户确认(每个 repo 单独确认)。
|
|
134
|
+
6) 执行提交(不带 `--no-verify`):
|
|
120
135
|
```bash
|
|
121
136
|
git -C "$sub_path" commit -m "<message>"
|
|
122
137
|
```
|
|
123
|
-
|
|
138
|
+
7) 若该 submodule 没有 staged changes:跳过(不要硬提交空 commit)。
|
|
124
139
|
|
|
125
140
|
## C) 提交 superproject(更新 gitlinks + 自身改动 + changes 工件)
|
|
126
141
|
1) 先检查 submodule 指针差异(gitlinks):
|
|
@@ -138,7 +153,7 @@ git add -p
|
|
|
138
153
|
git diff --staged --stat
|
|
139
154
|
git diff --staged
|
|
140
155
|
```
|
|
141
|
-
3) AI 生成 superproject 的 commit message(应包含
|
|
156
|
+
3) AI 生成 superproject 的 commit message(应包含 `bump submodule <name> -> <sha>` 等关键信息),并让用户确认。
|
|
142
157
|
4) 提交:
|
|
143
158
|
```bash
|
|
144
159
|
git commit -m "<message>"
|
|
@@ -11,9 +11,14 @@ description: 开发(按需求实现并验证;适用于任何需要修改代
|
|
|
11
11
|
1) 先做 preflight:定位项目根目录,读取 `AI_PROJECT.md` / `REQUIREMENTS.md` / `AI_WORKSPACE.md`,输出约束摘要。
|
|
12
12
|
- 若是中大型任务:建议先用 `$ws-plan` 生成 `plan/` 工件,再进入实现(便于可回放与对齐验证入口)。
|
|
13
13
|
- 若已有 `plan/` 工件:先执行 `$ws-plan-verify`;通过后再进入实现(防止计划过长/跑偏)。
|
|
14
|
+
- 若 `$ws-plan` 刚创建了 `change/<change-id>` worktree:后续实现必须在该 worktree 中继续;不要回到原工作区重复 `aiws change start ...`
|
|
14
15
|
2) 建立变更归因(推荐):
|
|
15
|
-
- ⚠️
|
|
16
|
-
-
|
|
16
|
+
- ⚠️ 若你准备执行 `aiws change start ... --switch/--worktree` 或手工 `git switch ...` 改变 checkout 上下文,先确认工作区状态:`git status --porcelain`。否则切分支/创建 worktree 后,未提交改动可能看起来丢了(worktree 只从 `HEAD` checkout,未提交内容会留在原目录)。
|
|
17
|
+
- 若当前目录已经是 `change/<change-id>` worktree(例如由 `$ws-plan` 创建):直接在这里继续,不要再创建第二个 worktree,也不要回原工作区写代码。
|
|
18
|
+
- 若 `git status --porcelain` 非空仅因为上一轮 `$ws-plan` / `aiws change new|sync` 生成了 `plan/...`、`changes/<change-id>/proposal.md`、`tasks.md`、`design.md`、`submodules.targets`,这是预期行为,不等于流程出错。处理方式:
|
|
19
|
+
- 已经在 `change/<change-id>` 分支:直接继续实现,并把这些文件作为计划/证据工件保留。
|
|
20
|
+
- 还没进入 `change/<change-id>`:先运行 `aiws change start <change-id> --hooks --no-switch` 建立 change 上下文;若你仍要 `--switch/--worktree`,先提交这些规划工件,再切换上下文。
|
|
21
|
+
- 强制(当你准备执行 `aiws change start ... --worktree/--switch` 创建新 change 时):先同步线上代码(含 submodules),避免基线过旧导致的 rebase/冲突与别人已更新但本地没拉的协作摩擦。
|
|
17
22
|
- 若你已经在 `change/<change-id>` 上继续开发:不要在此处强制 pull(避免把远端变动拉进变更分支);改为按需 `git fetch`/rebase,并保持门禁与验证可复现。
|
|
18
23
|
- 在 AI 工具中运行:`$ws-pull`(推荐;会在工作区不干净时阻断)
|
|
19
24
|
- 或等价手工(必须工作区干净;失败则停止并人工处理):
|
|
@@ -31,11 +36,15 @@ else
|
|
|
31
36
|
fi
|
|
32
37
|
```
|
|
33
38
|
- 推荐更安全(默认):`aiws change start <change-id> --hooks --no-switch`(只创建分支/工件 + 启用 hooks;不切分支)
|
|
34
|
-
-
|
|
35
|
-
-
|
|
39
|
+
- 准备进入实现时:若当前已在 `change/<change-id>` 直接继续;若需切换到该分支,先确认除规划工件外无额外未提交改动,再执行:`git switch change/<change-id>`
|
|
40
|
+
- 若你明确要一键切分支(不推荐,且 dirty 会被拦截):`aiws change start <change-id> --hooks --switch`
|
|
36
41
|
- superproject + submodule(推荐):`aiws change start <change-id> --hooks --worktree --submodules`(创建独立 worktree;当前目录分支保持不变;会在新 worktree 内初始化 submodules;若忘了 `--submodules` 也会强制初始化)
|
|
37
42
|
- 若后续需要在 detached submodule 内提交:先挂到 `aiws/pin/<target-branch>`;不要直接切 `change/<change-id>` / `main` / `master`
|
|
38
|
-
- 若仓库存在 submodule(`.gitmodules` 声明了 submodule 条目):进入编码前必须准备好 `changes/<change-id>/submodules.targets`,并把每个 submodule 挂到对应的 `aiws/pin/<target_branch>`(必要时切到 `<remote>/<target_branch>`;这可能会改变 superproject 的 gitlink
|
|
43
|
+
- 若仓库存在 submodule(`.gitmodules` 声明了 submodule 条目):进入编码前必须准备好 `changes/<change-id>/submodules.targets`,并把每个 submodule 挂到对应的 `aiws/pin/<target_branch>`(必要时切到 `<remote>/<target_branch>`;这可能会改变 superproject 的 gitlink 指针,属于预期的选渠道行为;缺失该文件会被门禁阻断)
|
|
44
|
+
- 允许用当前 submodule 状态来做默认预填,但必须显式说明来源,并最终落盘到 `submodules.targets`:
|
|
45
|
+
- detached HEAD:默认建议取 `.gitmodules` 中声明的 `submodule.<name>.branch`
|
|
46
|
+
- 已附着在某个本地分支:默认建议取该 submodule 的当前分支名
|
|
47
|
+
- 上述两条都只是建议值,不是运行时真值;真正的 finish/push 只认 `changes/<change-id>/submodules.targets`
|
|
39
48
|
```bash
|
|
40
49
|
change_id="<change-id>"
|
|
41
50
|
targets="changes/${change_id}/submodules.targets"
|
|
@@ -47,6 +56,7 @@ if [[ -f .gitmodules ]]; then
|
|
|
47
56
|
fi
|
|
48
57
|
if [[ "${has_submodules}" -eq 1 && ! -f "${targets}" ]]; then
|
|
49
58
|
echo "error: missing ${targets} (required when .gitmodules declares submodules)"
|
|
59
|
+
echo "hint: create it first; defaults may be inferred, but the final truth must be written explicitly"
|
|
50
60
|
exit 2
|
|
51
61
|
fi
|
|
52
62
|
|
|
@@ -73,6 +83,37 @@ if [[ -f "${targets}" ]]; then
|
|
|
73
83
|
# 检查 superproject 的 gitlink 是否发生变化(预期:若切了不同渠道,会看到差异)
|
|
74
84
|
git diff --submodule
|
|
75
85
|
fi
|
|
86
|
+
```
|
|
87
|
+
- 若你还没写 `submodules.targets`,可按下面方式先生成建议值,再人工确认后落盘:
|
|
88
|
+
```bash
|
|
89
|
+
change_id="<change-id>"
|
|
90
|
+
targets="changes/${change_id}/submodules.targets"
|
|
91
|
+
: > "${targets}"
|
|
92
|
+
|
|
93
|
+
git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' 2>/dev/null | while read -r key sub_path; do
|
|
94
|
+
name="${key#submodule.}"; name="${name%.path}"
|
|
95
|
+
current_branch="$(git -C "${sub_path}" branch --show-current 2>/dev/null || true)"
|
|
96
|
+
declared_branch="$(git config --file .gitmodules --get "submodule.${name}.branch" 2>/dev/null || true)"
|
|
97
|
+
|
|
98
|
+
if [[ -n "${current_branch}" ]]; then
|
|
99
|
+
inferred_branch="${current_branch}"
|
|
100
|
+
inferred_from="current branch"
|
|
101
|
+
else
|
|
102
|
+
inferred_branch="${declared_branch}"
|
|
103
|
+
inferred_from=".gitmodules"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
if [[ -z "${inferred_branch}" ]]; then
|
|
107
|
+
echo "error: cannot infer target branch for ${sub_path}; set it manually"
|
|
108
|
+
exit 2
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
printf "%s %s\n" "${sub_path}" "${inferred_branch}" >> "${targets}"
|
|
112
|
+
echo "info: ${sub_path} -> ${inferred_branch} (inferred from ${inferred_from}; remote defaults to origin unless you edit ${targets})"
|
|
113
|
+
done
|
|
114
|
+
|
|
115
|
+
echo "review required: ${targets}"
|
|
116
|
+
cat "${targets}"
|
|
76
117
|
```
|
|
77
118
|
- 若你明确要在 superproject 直接切分支:`aiws change start <change-id> --hooks --switch`(仅在存在 `.gitmodules` 时有意义;会尝试让 submodules 工作区跟随 superproject 指针)
|
|
78
119
|
- 或手工:`git switch -c change/<change-id>`,并创建 `changes/<change-id>/proposal.md` 与 `changes/<change-id>/tasks.md`(参考 `changes/README.md`)
|
|
@@ -8,13 +8,13 @@ description: 收尾(门禁 + 安全合并 + submodule→主仓库顺序 push
|
|
|
8
8
|
目标:
|
|
9
9
|
- 在结束一次变更交付时,用 fast-forward 安全合并 `change/<change-id>` 回目标分支,减少手输分支名导致的错误
|
|
10
10
|
- 合并成功后,按 `submodule -> superproject` 顺序 push,避免遗漏导致其它仓库拉取异常
|
|
11
|
-
- 不自动删分支;push
|
|
12
|
-
|
|
11
|
+
- 不自动删分支;AI 入口执行前应先向用户说明将要 push 的 remote/branch,显式传入 `--push` 即视为确认
|
|
12
|
+
- 若团队希望减少 submodule detached 的人为差异:建议在 `.gitmodules` 配置 `submodule.<name>.branch`,并在日常拉取时使用 `$ws-pull`
|
|
13
13
|
|
|
14
14
|
前置(必须):
|
|
15
15
|
- 工作区是干净的:`git status --porcelain` 无输出(若有未提交改动:先 commit 或 stash)
|
|
16
16
|
- change 分支已存在:`change/<change-id>`(也支持 `changes/`、`ws/`、`ws-change/`)
|
|
17
|
-
- 若使用 worktree
|
|
17
|
+
- 若使用 worktree:在目标分支所在 worktree 执行(`aiws change finish` 会提示正确的 worktree)
|
|
18
18
|
- 若存在 `.gitmodules`:必须为每个 submodule 配置 `submodule.<name>.branch`(否则无法确定性减少 detached;先运行 `$ws-submodule-setup` 并提交 `.gitmodules`)
|
|
19
19
|
|
|
20
20
|
建议步骤:
|
|
@@ -61,23 +61,41 @@ fi
|
|
|
61
61
|
```bash
|
|
62
62
|
aiws change state "${change_id}" --write
|
|
63
63
|
```
|
|
64
|
-
2)
|
|
64
|
+
2) 若不存在 `.gitmodules`,或 submodules 已按顺序处理完成,优先直接使用最小收尾闭环:
|
|
65
65
|
```bash
|
|
66
66
|
# 若当前就在 change/<change-id> 分支上,可省略 <change-id>
|
|
67
67
|
change_id="<change-id>"
|
|
68
68
|
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
69
|
-
./node_modules/.bin/aiws change finish "${change_id}"
|
|
69
|
+
./node_modules/.bin/aiws change finish "${change_id}" --push
|
|
70
70
|
elif command -v aiws >/dev/null 2>&1; then
|
|
71
|
-
aiws change finish "${change_id}"
|
|
71
|
+
aiws change finish "${change_id}" --push
|
|
72
72
|
else
|
|
73
|
-
npx @aipper/aiws change finish "${change_id}"
|
|
73
|
+
npx @aipper/aiws change finish "${change_id}" --push
|
|
74
74
|
fi
|
|
75
75
|
```
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
说明:
|
|
77
|
+
- 该命令会在 fast-forward 合并成功后 push 目标分支。
|
|
78
|
+
- 默认会优先使用当前分支的 upstream 配置(`branch.<name>.remote` + `branch.<name>.merge`);只有在你明确知道要推向别的 remote 时,才追加 `--remote <name>`。
|
|
79
|
+
- 若 `change/<change-id>` 位于独立 worktree,且该 worktree 干净,则会在 push 成功后自动执行 `git worktree remove` + `git worktree prune`。
|
|
80
|
+
- AI 工具内执行前,应先向用户说明将要 push 的 remote/branch;CLI 本身只有在显式传入 `--push` 时才会真正执行 push。
|
|
81
|
+
|
|
82
|
+
3) 若你需要先处理 submodules,则不要依赖当前分支名推断目标分支,先显式解析 `base_branch`,再执行 submodule 步骤,最后回到主仓库执行 `aiws change finish --push`:
|
|
83
|
+
```bash
|
|
84
|
+
change_id="<change-id>"
|
|
85
|
+
base_branch="$(python3 - <<'PY'
|
|
86
|
+
import json, pathlib
|
|
87
|
+
change_id = "<change-id>"
|
|
88
|
+
meta = pathlib.Path("changes") / change_id / ".ws-change.json"
|
|
89
|
+
data = json.loads(meta.read_text(encoding="utf-8"))
|
|
90
|
+
print((data.get("base_branch") or "").strip())
|
|
91
|
+
PY
|
|
92
|
+
)"
|
|
93
|
+
test -n "$base_branch"
|
|
94
|
+
```
|
|
95
|
+
4) 若 fast-forward 失败(提示需要 rebase):先在 change 分支(或对应 worktree)里 `git rebase <target-branch>`,再重试 `aiws change finish --push`。
|
|
96
|
+
5) 若存在 `.gitmodules`,先把每个 submodule 的 gitlink commit 合并回其目标分支(解决 detached HEAD),并按顺序 push:
|
|
78
97
|
```bash
|
|
79
|
-
#
|
|
80
|
-
base_branch="$(git branch --show-current)"
|
|
98
|
+
# 不要用当前分支名代替目标分支;这里显式使用 .ws-change.json 的 base_branch
|
|
81
99
|
change_id="<change-id>"
|
|
82
100
|
targets="changes/${change_id}/submodules.targets"
|
|
83
101
|
|
|
@@ -86,85 +104,84 @@ git config --file .gitmodules --get-regexp '^submodule\..*\.path$' 2>/dev/null |
|
|
|
86
104
|
|
|
87
105
|
# 对每个 submodule.<name>.path <sub_path>:
|
|
88
106
|
# 说明:`git submodule update` 会把 submodule checkout 到固定 gitlink commit,导致 detached HEAD。
|
|
89
|
-
#
|
|
90
|
-
# -
|
|
91
|
-
# -
|
|
107
|
+
# 为减少游离状态的协作摩擦,本步骤采用 pin 分支策略:
|
|
108
|
+
# - `changes/<change-id>/submodules.targets` 是本次 finish/push 的真值;每个 submodule path 都必须在该文件中声明目标分支(可选 remote)
|
|
109
|
+
# - `.gitmodules` 的 `submodule.<name>.branch` 仍建议保留,用于团队默认配置与校验,但不再作为 finish/push 的 fallback
|
|
110
|
+
# - 生成/检查 `submodules.targets` 时可显式说明默认来源:
|
|
111
|
+
# - detached HEAD:默认建议取 `.gitmodules` 的 `submodule.<name>.branch`
|
|
112
|
+
# - 已附着在某个本地分支:默认建议取当前分支
|
|
113
|
+
# - 以上仅为预填建议;真正执行 finish/push 时仍只认 `submodules.targets`
|
|
114
|
+
# - 不要直接切 `change/<change-id>` / `main` / `master` 等业务分支来解 detached
|
|
92
115
|
# - 不改动 submodule 现有分支指针(例如不强行移动 main/master)
|
|
93
116
|
# - 创建/更新本地 pin 分支:`aiws/pin/<target_branch>` 指向 gitlink commit,并将其 upstream 设为 `origin/<target_branch>`
|
|
94
117
|
if git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' >/dev/null 2>&1; then
|
|
95
|
-
if [[ ! -f
|
|
96
|
-
echo
|
|
118
|
+
if [[ ! -f "${targets}" ]]; then
|
|
119
|
+
echo "error: missing ${targets} (required when .gitmodules declares submodules)"
|
|
97
120
|
exit 2
|
|
98
121
|
fi
|
|
99
122
|
|
|
100
123
|
source tools/ws_resolve_sub_target.sh
|
|
101
124
|
|
|
102
125
|
while read -r key sub_path; do
|
|
103
|
-
name
|
|
104
|
-
[[ -z
|
|
105
|
-
echo
|
|
126
|
+
name="${key#submodule.}"; name="${name%.path}"
|
|
127
|
+
[[ -z "${sub_path:-}" ]] && continue
|
|
128
|
+
echo "== submodule: ${sub_path} (${name}) =="
|
|
129
|
+
|
|
130
|
+
current_branch="$(git -C "${sub_path}" branch --show-current 2>/dev/null || true)"
|
|
131
|
+
declared_branch="$(git config --file .gitmodules --get "submodule.${name}.branch" 2>/dev/null || true)"
|
|
132
|
+
if [[ -n "${current_branch}" ]]; then
|
|
133
|
+
echo "info: ${sub_path} default suggestion would be current branch: ${current_branch}"
|
|
134
|
+
elif [[ -n "${declared_branch}" ]]; then
|
|
135
|
+
echo "info: ${sub_path} default suggestion would be .gitmodules branch: ${declared_branch}"
|
|
136
|
+
else
|
|
137
|
+
echo "warn: ${sub_path} has no current branch and no .gitmodules branch; submodules.targets must be filled manually"
|
|
138
|
+
fi
|
|
106
139
|
|
|
107
|
-
sub_sha
|
|
140
|
+
sub_sha="$(git rev-parse "HEAD:${sub_path}")"
|
|
108
141
|
|
|
109
|
-
ws_resolve_sub_target
|
|
110
|
-
target_branch
|
|
111
|
-
remote
|
|
112
|
-
pin_branch
|
|
142
|
+
ws_resolve_sub_target "${sub_path}" "${name}" "${targets}" "${base_branch}" || exit 2
|
|
143
|
+
target_branch="${_resolved_branch}"
|
|
144
|
+
remote="${_resolved_remote}"
|
|
145
|
+
pin_branch="aiws/pin/${target_branch}"
|
|
113
146
|
|
|
114
|
-
git -C
|
|
115
|
-
if ! git -C
|
|
116
|
-
echo
|
|
147
|
+
git -C "${sub_path}" fetch "${remote}" --prune
|
|
148
|
+
if ! git -C "${sub_path}" show-ref --verify --quiet "refs/remotes/${remote}/${target_branch}"; then
|
|
149
|
+
echo "error: ${sub_path}: missing ${remote}/${target_branch}; refusing to push superproject (would break gitlink fetchability)"
|
|
117
150
|
exit 2
|
|
118
151
|
fi
|
|
119
152
|
|
|
120
|
-
# 仅当 gitlink commit 属于 <remote>/<target_branch>
|
|
121
|
-
if ! git -C
|
|
122
|
-
echo
|
|
153
|
+
# 仅当 gitlink commit 属于 <remote>/<target_branch> 的历史时才挂回分支
|
|
154
|
+
if ! git -C "${sub_path}" merge-base --is-ancestor "${sub_sha}" "${remote}/${target_branch}"; then
|
|
155
|
+
echo "[warn] ${sub_path}: ${sub_sha} is not in ${remote}/${target_branch}; keep detached and stop (need manual reconcile)"
|
|
123
156
|
exit 1
|
|
124
157
|
fi
|
|
125
158
|
|
|
126
|
-
git -C
|
|
127
|
-
git -C
|
|
128
|
-
git -C
|
|
159
|
+
git -C "${sub_path}" checkout -B "${pin_branch}" "${sub_sha}"
|
|
160
|
+
git -C "${sub_path}" branch --set-upstream-to "${remote}/${target_branch}" "${pin_branch}" >/dev/null 2>&1 || true
|
|
161
|
+
git -C "${sub_path}" status -sb
|
|
129
162
|
|
|
130
163
|
# push:只允许 fast-forward(若远端分叉会被拒绝;此时必须人工处理)
|
|
131
|
-
git -C
|
|
164
|
+
git -C "${sub_path}" push "${remote}" "${sub_sha}:refs/heads/${target_branch}"
|
|
132
165
|
done < <(git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' 2>/dev/null || true)
|
|
133
166
|
fi
|
|
134
167
|
```
|
|
135
168
|
规则:
|
|
136
|
-
- 每个 submodule
|
|
169
|
+
- 每个 submodule 必须先执行 pin 分支挂回 + fast-forward push,再 push 主仓库。
|
|
137
170
|
- 若任一 submodule 的 gitlink commit 不在 `<remote>/<target_branch>` 历史中:立即停止,先人工处理分叉,再继续。
|
|
138
171
|
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
git branch --show-current
|
|
142
|
-
git status -sb
|
|
143
|
-
git push
|
|
144
|
-
```
|
|
145
|
-
6) push 成功后,清理 `change/<change-id>` 对应 worktree(若存在且不是当前 worktree):
|
|
172
|
+
6) 仅当 submodules 全部成功后,再在 superproject 当前分支执行最小收尾闭环:
|
|
146
173
|
```bash
|
|
147
174
|
change_id="<change-id>"
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if [[ -n "${change_wt:-}" && "$change_wt" != "$main_wt" ]]; then
|
|
156
|
-
if [[ -n "$(git -C "$change_wt" status --porcelain 2>/dev/null)" ]]; then
|
|
157
|
-
echo "[warn] worktree not clean, skip remove: $change_wt"
|
|
158
|
-
echo "hint: clean it first, then run: git worktree remove \"$change_wt\""
|
|
159
|
-
else
|
|
160
|
-
git worktree remove "$change_wt"
|
|
161
|
-
git worktree prune
|
|
162
|
-
fi
|
|
175
|
+
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
176
|
+
./node_modules/.bin/aiws change finish "${change_id}" --push
|
|
177
|
+
elif command -v aiws >/dev/null 2>&1; then
|
|
178
|
+
aiws change finish "${change_id}" --push
|
|
179
|
+
else
|
|
180
|
+
npx @aipper/aiws change finish "${change_id}" --push
|
|
163
181
|
fi
|
|
164
182
|
```
|
|
165
|
-
|
|
166
|
-
-
|
|
167
|
-
- 仅使用 `git worktree remove`(不带 `--force`)。
|
|
183
|
+
说明:
|
|
184
|
+
- 该命令内部已经包含主仓库 push 成功后安全清理独立 change worktree 的逻辑。
|
|
168
185
|
|
|
169
186
|
7) (可选)归档变更工件(完成交付后推荐):
|
|
170
187
|
```bash
|
|
@@ -7,6 +7,7 @@ description: 规划(生成可落盘 plan/ 工件;供 ws-dev 执行)
|
|
|
7
7
|
|
|
8
8
|
目标:
|
|
9
9
|
- 对齐真值文件(`AI_PROJECT.md` / `REQUIREMENTS.md` / `AI_WORKSPACE.md`)
|
|
10
|
+
- 若尚未进入本次 change 的工作上下文:先建立 `change/<change-id>` 分支 / worktree,再生成计划
|
|
10
11
|
- 为当前任务生成一份可追踪的执行计划文件:`plan/<timestamp>-<slug>.md`
|
|
11
12
|
- 计划必须包含可复现验证命令(优先引用 `AI_WORKSPACE.md`)
|
|
12
13
|
- 计划必须包含“主索引绑定”:`Change_ID` / (`Req_ID` or `Problem_ID`) / `Contract_Row` / `Plan_File` / `Evidence_Path`
|
|
@@ -21,13 +22,46 @@ description: 规划(生成可落盘 plan/ 工件;供 ws-dev 执行)
|
|
|
21
22
|
1) 先运行 `$ws-preflight`(读取真值文件并输出约束摘要)。
|
|
22
23
|
2) 若用户任务描述不清:先问 1-3 个关键澄清问题(不要猜)。
|
|
23
24
|
3) 判断复杂度:`simple / medium / complex`(给出一句理由),并估算步骤数。
|
|
24
|
-
4)
|
|
25
|
+
4) 识别或建立主索引 / change 上下文:
|
|
25
26
|
- 若存在 `changes/<change-id>/proposal.md`:读取其中 `Change_ID` / `Req_ID` / `Problem_ID` / `Contract_Row` / `Evidence_Path`
|
|
26
27
|
- 若缺失关键绑定:先补齐 proposal(至少 `Change_ID`、`Req_ID|Problem_ID`、`Contract_Row`)再继续生成计划
|
|
28
|
+
- 若当前不在 `change/<change-id>` 分支 / worktree,且本次任务需要新建 change:先调用 `aiws change start` 建立上下文,再继续写 plan
|
|
29
|
+
- 推荐顺序:
|
|
30
|
+
- 工作区已存在未提交改动:不要先写 `plan/...`;先停下来说明原因,并要求用户先 commit/stash,或改用已有 change 上下文
|
|
31
|
+
- 仓库已有提交:优先创建独立 worktree;若仓库声明了 submodules,加上 `--submodules`
|
|
32
|
+
- 仓库尚无提交 / 不满足 worktree 前置条件:回退为 `--no-switch`
|
|
33
|
+
```bash
|
|
34
|
+
change_id="<change-id>"
|
|
35
|
+
if [[ -n "$(git status --porcelain)" ]]; then
|
|
36
|
+
echo "error: working tree dirty before ws-plan creates change context"
|
|
37
|
+
echo "hint: commit/stash first, or continue inside an existing change/<change-id> context"
|
|
38
|
+
exit 2
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
has_commits=0
|
|
42
|
+
git rev-parse --verify HEAD >/dev/null 2>&1 && has_commits=1
|
|
43
|
+
|
|
44
|
+
has_submodules=0
|
|
45
|
+
if [[ -f .gitmodules ]] && git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' >/dev/null 2>&1; then
|
|
46
|
+
has_submodules=1
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
if [[ "${has_commits}" -eq 1 ]]; then
|
|
50
|
+
if [[ "${has_submodules}" -eq 1 ]]; then
|
|
51
|
+
aiws change start "${change_id}" --hooks --worktree --submodules
|
|
52
|
+
else
|
|
53
|
+
aiws change start "${change_id}" --hooks --worktree
|
|
54
|
+
fi
|
|
55
|
+
else
|
|
56
|
+
aiws change start "${change_id}" --hooks --no-switch
|
|
57
|
+
fi
|
|
58
|
+
```
|
|
59
|
+
- 若上一步创建了 worktree:后续所有读取/写入都必须切到 `aiws change start` 输出的 `worktree:` 路径中进行;不要把 `plan/...` 写回原工作区
|
|
27
60
|
5) 生成计划文件:
|
|
28
61
|
- 文件名:`plan/YYYY-MM-DD_HH-MM-SS-<slug>.md`(`<slug>` 用 kebab-case;同一任务调整计划时尽量复用同一文件)
|
|
29
62
|
- 若 `plan/` 不存在先创建
|
|
30
63
|
- 必须实际写入到磁盘(不要只在对话里输出);如因权限/策略无法写盘,必须明确说明原因并输出可复制的完整内容
|
|
64
|
+
- 计划必须写在当前 active change 上下文内:若当前已进入 `change/<change-id>` worktree,则 `plan/...`、`proposal.md`、`tasks.md` 都应写在该 worktree 中
|
|
31
65
|
6) 计划内容至少包含(不要留空):
|
|
32
66
|
- `Bindings`:`Change_ID` / `Req_ID` / `Problem_ID` / `Contract_Row` / `Plan_File` / `Evidence_Path`
|
|
33
67
|
- `Goal`:要达成什么
|
|
@@ -76,4 +110,5 @@ echo "ok: wrote ${targets}"
|
|
|
76
110
|
|
|
77
111
|
输出要求:
|
|
78
112
|
- `Plan file:` <实际写入的路径>
|
|
113
|
+
- `Change context:` <当前 change 分支或 worktree 路径;若新建了 worktree 需明确写出>
|
|
79
114
|
- `Next:` 推荐下一步(先 `$ws-plan-verify`,通过后再 `$ws-dev`;或 `aiws change start <change-id> --hooks`,superproject + submodule 可用 `--worktree`)
|
|
@@ -8,15 +8,20 @@
|
|
|
8
8
|
|
|
9
9
|
建议流程:
|
|
10
10
|
1) 先运行 `/ws-preflight`。
|
|
11
|
-
2)
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
2) 若当前不在 `change/<change-id>` 分支 / worktree,先建立 change 上下文:
|
|
12
|
+
- 工作区先保持干净
|
|
13
|
+
- 仓库已有提交:优先 `aiws change start <change-id> --hooks --worktree`
|
|
14
|
+
- superproject + submodule:优先 `aiws change start <change-id> --hooks --worktree --submodules`
|
|
15
|
+
- 仓库尚无提交 / 不满足 worktree 前置条件:回退 `aiws change start <change-id> --hooks --no-switch`
|
|
16
|
+
3) 若上一步创建了 worktree:后续 bug 证据、CSV 更新、`/ws-dev` 修复都必须在该 worktree 中继续。
|
|
17
|
+
4) 通过已配置 zentao MCP 拉取 bug 字段与附件列表。
|
|
18
|
+
5) 落盘证据到当前 active change 上下文的 `changes/<change-id>/bug/`:
|
|
14
19
|
- `zentao-bug-<bug-id>.json`
|
|
15
20
|
- `zentao-bug-<bug-id>.md`
|
|
16
21
|
- `images/<bug-id>/...`
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
6) upsert 当前 active change 上下文中的 `issues/fix_bus_issues.csv`(主键 `Bug_ID`)。
|
|
23
|
+
7) 进入 `/ws-dev` 修复并回填状态字段 `Fix_Status/Verify_Command/Updated_At`。
|
|
24
|
+
8) 质量门:`aiws change validate <change-id> --strict` + `aiws validate . --stamp`。
|
|
20
25
|
|
|
21
26
|
强制约束:
|
|
22
27
|
- 不自动 commit / push。
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
- 不使用 `--no-verify` 绕过 hooks
|
|
12
12
|
- 不自动 push
|
|
13
13
|
- 不打印 secrets
|
|
14
|
+
- commit message 优先使用中文;若启用了 `.githooks/commit-msg`,默认仅提示,只有 strict 模式才会拒绝全英文首行(`Merge/Revert/fixup!/squash!` 例外)
|
|
14
15
|
|
|
15
16
|
步骤(建议):
|
|
16
17
|
1) 先运行 `/ws-preflight`。
|
|
@@ -51,7 +52,7 @@ git status --porcelain
|
|
|
51
52
|
git diff --staged --submodule=short
|
|
52
53
|
```
|
|
53
54
|
7) 若没有 staged changes:停止并提示用户先明确要提交哪些文件(例如 `git add -p` 或 `git add <path>`)。
|
|
54
|
-
8)
|
|
55
|
+
8) 优先生成并确认中文 commit message(格式建议:`<类型>: <简述>`;若用户明确要求英文也可保留,但 strict 模式下会被 hook 拒绝)。
|
|
55
56
|
9) 执行提交(不带 `--no-verify`):
|
|
56
57
|
```bash
|
|
57
58
|
git commit -m "<message>"
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
用中文输出(命令/路径/代码标识符保持原样不翻译)。
|
|
5
5
|
|
|
6
|
-
目标:适配 superproject + submodule
|
|
6
|
+
目标:适配 superproject + submodule(数量不固定)的交付收尾,降低提交顺序和合并回 base 分支的出错概率:
|
|
7
7
|
1) 先逐个提交 submodule(每个 repo 单独确认 commit message;默认 `git add -p`)
|
|
8
8
|
2) 再提交 superproject(包含 submodule gitlink 指针更新 + 自身改动/变更工件)
|
|
9
9
|
3) 最后 fast-forward 合并回目标分支(复用 `aiws change finish`;建议用 `/ws-finish`)
|
|
@@ -16,11 +16,15 @@
|
|
|
16
16
|
建议流程(按顺序):
|
|
17
17
|
1) 先运行 `/ws-preflight`。
|
|
18
18
|
2) 如果存在 `.gitmodules` 但缺少 `submodule.<name>.branch`,先运行 `/ws-submodule-setup` 并提交 `.gitmodules`(否则 `aiws validate .` 会失败,且 submodule 工作流会产生人为差异)。
|
|
19
|
+
2.1) 若存在 submodule:必须准备 `changes/<change-id>/submodules.targets`,并覆盖所有 submodule path;这是本次交付的目标分支真值。
|
|
20
|
+
- 生成该文件时可先做默认预填:detached HEAD 默认建议取 `.gitmodules` 声明分支;已附着在本地分支时默认建议取当前分支。
|
|
21
|
+
- 上述都只是建议值;真正的 deliver/finish 只认 `submodules.targets`。
|
|
19
22
|
2) 发现 submodules:
|
|
20
23
|
- `git submodule status --recursive`
|
|
21
24
|
3) 逐个提交 submodules(按上一步顺序):
|
|
22
25
|
- `git -C "<sub_path>" status --porcelain`
|
|
23
|
-
-
|
|
26
|
+
- 先说明该 submodule 目标分支的来源:attached branch 默认建议取当前分支;detached HEAD 默认建议取 `.gitmodules`;若与 `submodules.targets` 已落盘值冲突,则以 `submodules.targets` 为准
|
|
27
|
+
- 若当前为 detached HEAD:不要直接切 `change/<change-id>` / `main` / `master`;先按 `submodules.targets`(若分支为 `.` 则展开为 `.ws-change.json` 的 `base_branch`)挂到 `aiws/pin/<target-branch>`
|
|
24
28
|
- `git -C "<sub_path>" add -p`
|
|
25
29
|
- `git -C "<sub_path>" diff --staged --stat`
|
|
26
30
|
- 生成并让用户确认该 submodule 的 commit message(每个 repo 单独确认)
|
|
@@ -7,10 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
建议流程:
|
|
9
9
|
1) 先运行 `/ws-preflight`(读真值文件并输出约束摘要)。
|
|
10
|
+
- 若 `/ws-plan` 刚创建了 `change/<change-id>` worktree:后续实现必须在该 worktree 中继续;不要回原工作区重复 `aiws change start ...`
|
|
10
11
|
2) 建立变更归因(推荐):
|
|
11
|
-
- ⚠️
|
|
12
|
+
- ⚠️ 若准备切分支/创建 worktree,先看 `git status --porcelain`;否则切换上下文后,未提交改动可能“看起来丢了”。
|
|
13
|
+
- 若当前目录已经是 `change/<change-id>` worktree(例如由 `/ws-plan` 创建):直接在这里继续,不要再创建第二个 worktree,也不要回原工作区写代码。
|
|
14
|
+
- 若非空仅因为 `/ws-plan` 生成了 `plan/...` 或 `changes/<change-id>/...`,这是预期行为;此时优先 `aiws change start <change-id> --hooks --no-switch`,若仍要 `--switch/--worktree`,先提交这些规划工件。
|
|
12
15
|
- 推荐更安全(默认):`aiws change start <change-id> --hooks --no-switch`(只创建分支/工件 + 启用 hooks;不切分支)
|
|
13
|
-
-
|
|
16
|
+
- 准备进入实现时:若当前已在 `change/<change-id>` 直接继续;若需切换到该分支,先确认除规划工件外无额外未提交改动,再执行:`git switch change/<change-id>`
|
|
14
17
|
- 若你明确要“一键切分支”(不推荐,且 dirty 会被拦截):`aiws change start <change-id> --hooks --switch`
|
|
15
18
|
- superproject + submodule(推荐):`aiws change start <change-id> --hooks --worktree --submodules`
|
|
16
19
|
- 若后续需要在 detached submodule 内提交:先挂到 `aiws/pin/<target-branch>`;不要直接切 `change/<change-id>` / `main` / `master`
|