@aipper/aiws-spec 0.0.28 → 0.0.30
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/docs/cli-interface.md +10 -12
- package/docs/opencode-autonomous-swarm.md +178 -0
- package/docs/opencode-omo-adapter.md +123 -4
- package/docs/opencode-omo-validation-checklist.md +47 -0
- package/docs/opencode-subagent-first.md +187 -0
- package/docs/workflow-delegation-context-injection.md +217 -0
- package/docs/workflow-delegation-contracts.json +108 -2
- package/docs/workflow-delegation-contracts.md +13 -0
- package/docs/workflow-delegation-contracts.schema.json +152 -0
- package/docs/workflow-governance-rules.json +47 -6
- package/docs/workflow-governance-rules.md +8 -7
- package/docs/workflow-governance-rules.schema.json +39 -1
- package/docs/workflow-review-gates.json +6 -0
- package/docs/workflow-review-gates.md +14 -5
- package/docs/workflow-review-gates.schema.json +4 -0
- package/docs/workflow-router-rules.json +72 -8
- package/docs/workflow-router-rules.md +21 -14
- package/docs/workflow-router-rules.schema.json +4 -0
- package/docs/workflow-stage-contracts.json +24 -5
- package/docs/workflow-stage-contracts.md +16 -15
- package/docs/workflow-stage-contracts.schema.json +12 -1
- package/package.json +1 -1
- package/templates/workspace/.agents/skills/using-aiws/SKILL.md +16 -10
- package/templates/workspace/.agents/skills/ws-commit/SKILL.md +6 -118
- package/templates/workspace/.agents/skills/ws-deliver/SKILL.md +6 -218
- package/templates/workspace/.agents/skills/ws-dev/SKILL.md +82 -141
- package/templates/workspace/.agents/skills/ws-finish/SKILL.md +9 -204
- package/templates/workspace/.agents/skills/ws-handoff/SKILL.md +10 -44
- package/templates/workspace/.agents/skills/ws-migrate/SKILL.md +6 -42
- package/templates/workspace/.agents/skills/ws-plan-verify/SKILL.md +6 -58
- package/templates/workspace/.agents/skills/ws-pull/SKILL.md +8 -109
- package/templates/workspace/.agents/skills/ws-push/SKILL.md +8 -100
- package/templates/workspace/.agents/skills/ws-review/SKILL.md +6 -1
- package/templates/workspace/.agents/skills/ws-submodule-setup/SKILL.md +10 -57
- package/templates/workspace/.agents/skills/ws-verify-before-complete/SKILL.md +12 -53
- package/templates/workspace/{changes → .aiws/changes}/README.md +20 -23
- package/templates/workspace/{changes → .aiws/changes}/templates/proposal.md +12 -12
- package/templates/workspace/{changes → .aiws/changes}/templates/tasks.md +8 -8
- package/templates/workspace/{issues → .aiws/issues}/problem-issues.csv +1 -1
- package/templates/workspace/.aiws/journal/.gitkeep +1 -0
- package/templates/workspace/{requirements → .aiws/requirements}/requirements-issues.csv +1 -1
- package/templates/workspace/.aiws/tmp/.gitkeep +0 -0
- package/templates/workspace/{tools → .aiws/tools}/requirements_contract.py +2 -2
- package/templates/workspace/{tools → .aiws/tools}/requirements_contract_sync.py +2 -2
- package/templates/workspace/{tools → .aiws/tools}/requirements_flow_gen.py +1 -1
- package/templates/workspace/{tools → .aiws/tools}/server_test_runner.py +10 -10
- package/templates/workspace/{tools → .aiws/tools}/ws_change_check.py +23 -23
- package/templates/workspace/{tools → .aiws/tools}/ws_resolve_sub_target.sh +2 -2
- package/templates/workspace/{tools → .aiws/tools}/ws_tasks_plan.py +3 -3
- package/templates/workspace/.claude/commands/ws-review.md +5 -1
- package/templates/workspace/.claude/settings.json.example +26 -0
- package/templates/workspace/.claude/skills/ws-commit/SKILL.md +6 -118
- package/templates/workspace/.claude/skills/ws-deliver/SKILL.md +6 -218
- package/templates/workspace/.claude/skills/ws-dev/SKILL.md +52 -141
- package/templates/workspace/.claude/skills/ws-finish/SKILL.md +9 -204
- package/templates/workspace/.claude/skills/ws-handoff/SKILL.md +10 -44
- package/templates/workspace/.claude/skills/ws-migrate/SKILL.md +6 -42
- package/templates/workspace/.claude/skills/ws-plan-verify/SKILL.md +6 -49
- package/templates/workspace/.claude/skills/ws-pull/SKILL.md +8 -109
- package/templates/workspace/.claude/skills/ws-push/SKILL.md +8 -100
- package/templates/workspace/.claude/skills/ws-review/SKILL.md +6 -1
- package/templates/workspace/.claude/skills/ws-submodule-setup/SKILL.md +10 -57
- package/templates/workspace/.claude/skills/ws-verify-before-complete/SKILL.md +12 -53
- package/templates/workspace/.githooks/pre-commit +13 -0
- package/templates/workspace/.githooks/pre-push +7 -0
- package/templates/workspace/.opencode/command/ws-auto.md +33 -0
- package/templates/workspace/.opencode/command/ws-autonomy.md +25 -0
- package/templates/workspace/.opencode/command/ws-review.md +5 -1
- package/templates/workspace/.opencode/commands/ws-auto.md +33 -0
- package/templates/workspace/.opencode/commands/ws-autonomy.md +25 -0
- package/templates/workspace/.opencode/commands/ws-commit.md +4 -56
- package/templates/workspace/.opencode/commands/ws-deliver.md +10 -50
- package/templates/workspace/.opencode/commands/ws-finish.md +11 -3
- package/templates/workspace/.opencode/commands/ws-handoff.md +9 -17
- package/templates/workspace/.opencode/commands/ws-migrate.md +10 -17
- package/templates/workspace/.opencode/commands/ws-plan-verify.md +5 -15
- package/templates/workspace/.opencode/commands/ws-pull.md +6 -75
- package/templates/workspace/.opencode/commands/ws-push.md +7 -82
- package/templates/workspace/.opencode/commands/ws-review.md +5 -1
- package/templates/workspace/.opencode/commands/ws-submodule-setup.md +8 -47
- package/templates/workspace/.opencode/commands/ws-verify-before-complete.md +10 -19
- package/templates/workspace/.opencode/helpers/approval-whitelist-check.sh +148 -0
- package/templates/workspace/.opencode/helpers/approval-whitelist-run.sh +82 -0
- package/templates/workspace/.opencode/helpers/approval-whitelist-watchdog.sh +144 -0
- package/templates/workspace/.opencode/helpers/tmux-swarm-rescue.sh +56 -0
- package/templates/workspace/.opencode/helpers/tmux-swarm-scan.sh +46 -0
- package/templates/workspace/.opencode/lib/aiws-context.js +953 -0
- package/templates/workspace/.opencode/oh-my-opencode.json.example +64 -4
- package/templates/workspace/.opencode/plugins/aiws-inject-context.js +201 -0
- package/templates/workspace/.opencode/plugins/aiws-session-start.js +86 -0
- package/templates/workspace/.opencode/plugins/aiws-workflow-state.js +116 -0
- package/templates/workspace/.opencode/scripts/ws-plan-gen-submodule-targets.sh +27 -0
- package/templates/workspace/.opencode/scripts/ws-plan-setup-worktree.sh +31 -0
- package/templates/workspace/.opencode/skills/using-aiws/SKILL.md +130 -77
- package/templates/workspace/.opencode/skills/ws-analyze/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-auto/SKILL.md +46 -0
- package/templates/workspace/.opencode/skills/ws-autonomy/SKILL.md +62 -0
- package/templates/workspace/.opencode/skills/ws-bugfix/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-commit/SKILL.md +6 -118
- package/templates/workspace/.opencode/skills/ws-delegate/SKILL.md +115 -40
- package/templates/workspace/.opencode/skills/ws-deliver/SKILL.md +6 -218
- package/templates/workspace/.opencode/skills/ws-dev/SKILL.md +105 -146
- package/templates/workspace/.opencode/skills/ws-dev-lite/SKILL.md +23 -7
- package/templates/workspace/.opencode/skills/ws-finish/SKILL.md +9 -204
- package/templates/workspace/.opencode/skills/ws-frontend-design/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-handoff/SKILL.md +10 -44
- package/templates/workspace/.opencode/skills/ws-intake/SKILL.md +43 -4
- package/templates/workspace/.opencode/skills/ws-migrate/SKILL.md +6 -42
- package/templates/workspace/.opencode/skills/ws-plan/SKILL.md +15 -55
- package/templates/workspace/.opencode/skills/ws-plan-verify/SKILL.md +6 -49
- package/templates/workspace/.opencode/skills/ws-preflight/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-pull/SKILL.md +8 -109
- package/templates/workspace/.opencode/skills/ws-push/SKILL.md +8 -100
- package/templates/workspace/.opencode/skills/ws-quality-review/SKILL.md +7 -2
- package/templates/workspace/.opencode/skills/ws-req-change/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-req-contract-sync/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-req-contract-validate/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-req-flow-sync/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-req-review/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-review/SKILL.md +35 -4
- package/templates/workspace/.opencode/skills/ws-rule/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-spec-review/SKILL.md +1 -1
- package/templates/workspace/.opencode/skills/ws-submodule-setup/SKILL.md +10 -57
- package/templates/workspace/.opencode/skills/ws-verify-before-complete/SKILL.md +45 -55
- package/templates/workspace/AGENTS.md +32 -84
- package/templates/workspace/AI_PROJECT.md +5 -5
- package/templates/workspace/AI_WORKSPACE.md +1 -1
- package/templates/workspace/REQUIREMENTS.md +1 -1
- package/templates/workspace/gitignore +1 -1
- package/templates/workspace/manifest.json +215 -395
- /package/templates/workspace/{changes → .aiws/changes}/templates/design.md +0 -0
- /package/templates/workspace/{memory-bank → .aiws/memory-bank}/README.md +0 -0
- /package/templates/workspace/{memory-bank → .aiws/memory-bank}/architecture.md +0 -0
- /package/templates/workspace/{memory-bank → .aiws/memory-bank}/implementation-plan.md +0 -0
- /package/templates/workspace/{memory-bank → .aiws/memory-bank}/progress.md +0 -0
- /package/templates/workspace/{memory-bank → .aiws/memory-bank}/tech-stack.md +0 -0
- /package/templates/workspace/{requirements → .aiws/requirements}/CHANGELOG.md +0 -0
- /package/templates/workspace/{secrets → .aiws/secrets}/test-accounts.example.json +0 -0
|
@@ -1,217 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ws-finish
|
|
3
|
-
description:
|
|
3
|
+
description: `aiws finish` 的收尾入口(finish_resume_required)
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# ws-finish
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- 在结束一次变更交付时,用 fast-forward 安全合并 `change/<change-id>` 回目标分支,减少手输分支名导致的错误
|
|
10
|
-
- 合并成功后,按 `submodule -> superproject` 顺序 push,避免遗漏导致其它仓库拉取异常
|
|
11
|
-
- 不自动删分支;AI 入口执行前应先向用户说明将要 push 的 remote/branch,显式传入 `--push` 即视为确认
|
|
12
|
-
- 若团队希望减少 submodule detached 的人为差异:建议在 `.gitmodules` 配置 `submodule.<name>.branch`,并在日常拉取时使用 `$ws-pull`
|
|
8
|
+
`aiws finish` 的收尾入口。
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
- 若使用 worktree:普通 finish 的 `validate/evidence/state` 先在 `change/<change-id>` worktree 完成;真正执行 `aiws change finish` 时再切到目标分支所在 worktree(命令会提示正确的 worktree)
|
|
18
|
-
- 若 `aiws change status <change-id>` 输出 `governance_rule: finish_resume_required`:说明 merge 已发生,只剩 push / archive / cleanup closeout;直接在该 worktree 运行 `aiws change finish <change-id> --push`,不要先跑 `aiws validate . --stamp`
|
|
19
|
-
- 若存在 `.gitmodules`:必须为每个 submodule 配置 `submodule.<name>.branch`(否则无法确定性减少 detached;先运行 `$ws-submodule-setup` 并提交 `.gitmodules`)
|
|
10
|
+
关键契约:
|
|
11
|
+
- 若 `aiws change status <change-id>` 输出 `governance_rule: finish_resume_required`,继续执行 `aiws change finish <change-id> --push`
|
|
12
|
+
- 普通 finish 的 `validate/evidence/state` 仍应在 `change/<change-id>` worktree 完成,不要在目标 worktree 里跑 `aiws validate . --stamp`
|
|
20
13
|
|
|
21
|
-
阶段定位:
|
|
22
|
-
- finish 阶段;负责把已提交的 change 安全合并回目标分支,并按约束完成 push / worktree cleanup。
|
|
23
|
-
|
|
24
|
-
必需输入:
|
|
25
|
-
- 干净的当前工作区
|
|
26
|
-
- 已提交完成的 `change/<change-id>`
|
|
27
|
-
- 若存在 submodule:`.gitmodules` 与 `changes/<change-id>/submodules.targets`
|
|
28
|
-
- 当前 push 目标说明(remote / branch)
|
|
29
|
-
|
|
30
|
-
必需输出:
|
|
31
|
-
- `Merge:` `aiws change finish` 的结果(from / into)
|
|
32
|
-
- `Push:` 实际 remote / branch 或未 push 原因
|
|
33
|
-
- `Worktree cleanup:` 清理结果
|
|
34
|
-
- `Evidence:` validate stamp / evidence / state 路径
|
|
35
|
-
|
|
36
|
-
阻断条件:
|
|
37
|
-
- 工作区不干净
|
|
38
|
-
- 缺失 submodule branch / targets 真值
|
|
39
|
-
- fast-forward 失败
|
|
40
|
-
- 子模块目标分支无法安全 push
|
|
41
|
-
|
|
42
|
-
完成判定:
|
|
43
|
-
- change 已安全合并回目标分支,必要的 push 与 worktree cleanup 已完成或明确说明未完成原因。
|
|
44
|
-
|
|
45
|
-
建议步骤:
|
|
46
|
-
0) 若存在 `.gitmodules`,先检查 submodule branch 配置是否齐全(缺失则停止并提示 setup):
|
|
47
|
-
```bash
|
|
48
|
-
if [[ -f .gitmodules ]]; then
|
|
49
|
-
missing=0
|
|
50
|
-
while read -r key sub_path; do
|
|
51
|
-
name="${key#submodule.}"; name="${name%.path}"
|
|
52
|
-
b="$(git config --file .gitmodules --get "submodule.${name}.branch" 2>/dev/null || true)"
|
|
53
|
-
if [[ -z "${b:-}" ]]; then
|
|
54
|
-
echo "error: missing .gitmodules submodule.${name}.branch (path=${sub_path})"
|
|
55
|
-
missing=1
|
|
56
|
-
fi
|
|
57
|
-
done < <(git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' 2>/dev/null || true)
|
|
58
|
-
if [[ "$missing" -ne 0 ]]; then
|
|
59
|
-
echo "hint: run $ws-submodule-setup (and commit .gitmodules), then retry"
|
|
60
|
-
exit 2
|
|
61
|
-
fi
|
|
62
|
-
fi
|
|
63
|
-
```
|
|
64
|
-
0.5) 先运行 `aiws change status <change-id>`,优先看稳定字段 `governance_rule:`:
|
|
65
|
-
- 若为 `finish_resume_required`:直接跳到步骤 2 执行 `aiws change finish <change-id> --push`
|
|
66
|
-
- 若不是该值:按普通 finish 继续;不要依赖自然语言提示句做分支判断
|
|
67
|
-
|
|
68
|
-
1) (推荐,仅适用于普通 finish,且应在 `change/<change-id>` worktree 执行)先跑一次门禁并落盘证据:
|
|
69
|
-
```bash
|
|
70
|
-
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
71
|
-
./node_modules/.bin/aiws validate . --stamp
|
|
72
|
-
elif command -v aiws >/dev/null 2>&1; then
|
|
73
|
-
aiws validate . --stamp
|
|
74
|
-
else
|
|
75
|
-
npx @aipper/aiws validate . --stamp
|
|
76
|
-
fi
|
|
77
|
-
```
|
|
78
|
-
若你已经位于目标分支 worktree,且 `governance_rule` 不是 `finish_resume_required`:
|
|
79
|
-
- 不要在这里跑 `aiws validate . --stamp`
|
|
80
|
-
- 先回 `change/<change-id>` worktree 补齐 finish gate,或先跑 `$ws-verify-before-complete`
|
|
81
|
-
1.1) (强烈建议,仅适用于普通 finish)收敛持久证据并回填 `Evidence_Path`:
|
|
82
|
-
```bash
|
|
83
|
-
change_id="<change-id>"
|
|
84
|
-
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
85
|
-
./node_modules/.bin/aiws change evidence "${change_id}"
|
|
86
|
-
elif command -v aiws >/dev/null 2>&1; then
|
|
87
|
-
aiws change evidence "${change_id}"
|
|
88
|
-
else
|
|
89
|
-
npx @aipper/aiws change evidence "${change_id}"
|
|
90
|
-
fi
|
|
91
|
-
```
|
|
92
|
-
1.2) (可选,仅适用于普通 finish)生成状态快照(建议):
|
|
93
|
-
```bash
|
|
94
|
-
aiws change state "${change_id}" --write
|
|
95
|
-
```
|
|
96
|
-
2) 若不存在 `.gitmodules`,或 submodules 已按顺序处理完成,优先直接使用最小收尾闭环:
|
|
97
|
-
```bash
|
|
98
|
-
# 若当前就在 change/<change-id> 分支上,可省略 <change-id>
|
|
99
|
-
change_id="<change-id>"
|
|
100
|
-
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
101
|
-
./node_modules/.bin/aiws change finish "${change_id}" --push
|
|
102
|
-
elif command -v aiws >/dev/null 2>&1; then
|
|
103
|
-
aiws change finish "${change_id}" --push
|
|
104
|
-
else
|
|
105
|
-
npx @aipper/aiws change finish "${change_id}" --push
|
|
106
|
-
fi
|
|
107
|
-
```
|
|
108
|
-
说明:
|
|
109
|
-
- 该命令会在 fast-forward 合并成功后 push 目标分支。
|
|
110
|
-
- 默认会优先使用当前分支的 upstream 配置(`branch.<name>.remote` + `branch.<name>.merge`);只有在你明确知道要推向别的 remote 时,才追加 `--remote <name>`。
|
|
111
|
-
- 若 `change/<change-id>` 位于独立 worktree,且该 worktree 干净,则会在 push 成功后自动执行 `git worktree remove` + `git worktree prune`。
|
|
112
|
-
- AI 工具内执行前,应先向用户说明将要 push 的 remote/branch;CLI 本身只有在显式传入 `--push` 时才会真正执行 push。
|
|
113
|
-
|
|
114
|
-
3) 若你需要先处理 submodules,则不要依赖当前分支名推断目标分支,先显式解析 `base_branch`,再执行 submodule 步骤,最后回到主仓库执行 `aiws change finish --push`:
|
|
115
|
-
```bash
|
|
116
|
-
change_id="<change-id>"
|
|
117
|
-
base_branch="$(python3 - <<'PY'
|
|
118
|
-
import json, pathlib
|
|
119
|
-
change_id = "<change-id>"
|
|
120
|
-
meta = pathlib.Path("changes") / change_id / ".ws-change.json"
|
|
121
|
-
data = json.loads(meta.read_text(encoding="utf-8"))
|
|
122
|
-
print((data.get("base_branch") or "").strip())
|
|
123
|
-
PY
|
|
124
|
-
)"
|
|
125
|
-
test -n "$base_branch"
|
|
126
|
-
```
|
|
127
|
-
4) 若 fast-forward 失败(提示需要 rebase):先在 change 分支(或对应 worktree)里 `git rebase <target-branch>`,再重试 `aiws change finish --push`。
|
|
128
|
-
5) 若存在 `.gitmodules`,先把每个 submodule 的 gitlink commit 合并回其目标分支(解决 detached HEAD),并按顺序 push:
|
|
129
|
-
```bash
|
|
130
|
-
# 不要用当前分支名代替目标分支;这里显式使用 .ws-change.json 的 base_branch
|
|
131
|
-
change_id="<change-id>"
|
|
132
|
-
targets="changes/${change_id}/submodules.targets"
|
|
133
|
-
|
|
134
|
-
# 子模块清单(没有则跳过)
|
|
135
|
-
git config --file .gitmodules --get-regexp '^submodule\..*\.path$' 2>/dev/null || true
|
|
136
|
-
|
|
137
|
-
# 对每个 submodule.<name>.path <sub_path>:
|
|
138
|
-
# 说明:`git submodule update` 会把 submodule checkout 到固定 gitlink commit,导致 detached HEAD。
|
|
139
|
-
# 为减少游离状态的协作摩擦,本步骤采用 pin 分支策略:
|
|
140
|
-
# - `changes/<change-id>/submodules.targets` 是本次 finish/push 的真值;每个 submodule path 都必须在该文件中声明目标分支(可选 remote)
|
|
141
|
-
# - `.gitmodules` 的 `submodule.<name>.branch` 仍建议保留,用于团队默认配置与校验,但不再作为 finish/push 的 fallback
|
|
142
|
-
# - 生成/检查 `submodules.targets` 时可显式说明默认来源:
|
|
143
|
-
# - detached HEAD:默认建议取 `.gitmodules` 的 `submodule.<name>.branch`
|
|
144
|
-
# - 已附着在某个本地分支:默认建议取当前分支
|
|
145
|
-
# - 以上仅为预填建议;真正执行 finish/push 时仍只认 `submodules.targets`
|
|
146
|
-
# - 不要直接切 `change/<change-id>` / `main` / `master` 等业务分支来解 detached
|
|
147
|
-
# - 不改动 submodule 现有分支指针(例如不强行移动 main/master)
|
|
148
|
-
# - 创建/更新本地 pin 分支:`aiws/pin/<target_branch>` 指向 gitlink commit,并将其 upstream 设为 `origin/<target_branch>`
|
|
149
|
-
if git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' >/dev/null 2>&1; then
|
|
150
|
-
if [[ ! -f "${targets}" ]]; then
|
|
151
|
-
echo "error: missing ${targets} (required when .gitmodules declares submodules)"
|
|
152
|
-
exit 2
|
|
153
|
-
fi
|
|
154
|
-
|
|
155
|
-
source tools/ws_resolve_sub_target.sh
|
|
156
|
-
|
|
157
|
-
while read -r key sub_path; do
|
|
158
|
-
name="${key#submodule.}"; name="${name%.path}"
|
|
159
|
-
[[ -z "${sub_path:-}" ]] && continue
|
|
160
|
-
echo "== submodule: ${sub_path} (${name}) =="
|
|
161
|
-
|
|
162
|
-
current_branch="$(git -C "${sub_path}" branch --show-current 2>/dev/null || true)"
|
|
163
|
-
declared_branch="$(git config --file .gitmodules --get "submodule.${name}.branch" 2>/dev/null || true)"
|
|
164
|
-
if [[ -n "${current_branch}" ]]; then
|
|
165
|
-
echo "info: ${sub_path} default suggestion would be current branch: ${current_branch}"
|
|
166
|
-
elif [[ -n "${declared_branch}" ]]; then
|
|
167
|
-
echo "info: ${sub_path} default suggestion would be .gitmodules branch: ${declared_branch}"
|
|
168
|
-
else
|
|
169
|
-
echo "warn: ${sub_path} has no current branch and no .gitmodules branch; submodules.targets must be filled manually"
|
|
170
|
-
fi
|
|
171
|
-
|
|
172
|
-
sub_sha="$(git rev-parse "HEAD:${sub_path}")"
|
|
173
|
-
|
|
174
|
-
ws_resolve_sub_target "${sub_path}" "${name}" "${targets}" "${base_branch}" || exit 2
|
|
175
|
-
target_branch="${_resolved_branch}"
|
|
176
|
-
remote="${_resolved_remote}"
|
|
177
|
-
pin_branch="aiws/pin/${target_branch}"
|
|
178
|
-
|
|
179
|
-
git -C "${sub_path}" fetch "${remote}" --prune
|
|
180
|
-
if ! git -C "${sub_path}" show-ref --verify --quiet "refs/remotes/${remote}/${target_branch}"; then
|
|
181
|
-
echo "error: ${sub_path}: missing ${remote}/${target_branch}; refusing to push superproject (would break gitlink fetchability)"
|
|
182
|
-
exit 2
|
|
183
|
-
fi
|
|
184
|
-
|
|
185
|
-
# 仅当 gitlink commit 属于 <remote>/<target_branch> 的历史时才挂回分支
|
|
186
|
-
if ! git -C "${sub_path}" merge-base --is-ancestor "${sub_sha}" "${remote}/${target_branch}"; then
|
|
187
|
-
echo "[warn] ${sub_path}: ${sub_sha} is not in ${remote}/${target_branch}; keep detached and stop (need manual reconcile)"
|
|
188
|
-
exit 1
|
|
189
|
-
fi
|
|
190
|
-
|
|
191
|
-
git -C "${sub_path}" checkout -B "${pin_branch}" "${sub_sha}"
|
|
192
|
-
git -C "${sub_path}" branch --set-upstream-to "${remote}/${target_branch}" "${pin_branch}" >/dev/null 2>&1 || true
|
|
193
|
-
git -C "${sub_path}" status -sb
|
|
194
|
-
|
|
195
|
-
# push:只允许 fast-forward(若远端分叉会被拒绝;此时必须人工处理)
|
|
196
|
-
git -C "${sub_path}" push "${remote}" "${sub_sha}:refs/heads/${target_branch}"
|
|
197
|
-
done < <(git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' 2>/dev/null || true)
|
|
198
|
-
fi
|
|
199
|
-
```
|
|
200
|
-
规则:
|
|
201
|
-
- 每个 submodule 必须先执行 pin 分支挂回 + fast-forward push,再 push 主仓库。
|
|
202
|
-
- 若任一 submodule 的 gitlink commit 不在 `<remote>/<target_branch>` 历史中:立即停止,先人工处理分叉,再继续。
|
|
203
|
-
|
|
204
|
-
6) 仅当 submodules 全部成功后,再在 superproject 当前分支执行最小收尾闭环:
|
|
205
14
|
```bash
|
|
206
|
-
change_id="<change-id>"
|
|
207
15
|
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
208
|
-
./node_modules/.bin/aiws
|
|
16
|
+
./node_modules/.bin/aiws finish
|
|
209
17
|
elif command -v aiws >/dev/null 2>&1; then
|
|
210
|
-
aiws
|
|
18
|
+
aiws finish
|
|
211
19
|
else
|
|
212
|
-
npx @aipper/aiws
|
|
20
|
+
npx @aipper/aiws finish
|
|
213
21
|
fi
|
|
214
22
|
```
|
|
215
|
-
说明:
|
|
216
|
-
- 该命令内部已经包含主仓库 push 成功后安全清理独立 change worktree 的逻辑。
|
|
217
|
-
- 当 `--push` 完整成功时,还会自动把 `changes/<change-id>/` 归档到 `changes/archive/...`,生成 `handoff.md`,并补一个 `归档: <change-id>` commit。
|
|
@@ -1,52 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ws-handoff
|
|
3
|
-
description:
|
|
3
|
+
description: `aiws handoff` 的薄包装入口
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# ws-handoff
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- 让 change 的交接信息可回放:`handoff.md`(包含:本次完成/改动文件/关键决策/下一步建议/绑定)
|
|
10
|
-
- 若存在协同工件:在 handoff 中一并概述 `analysis/`、`patches/`、`review/`、`evidence/`
|
|
11
|
-
- 指引在归档与依赖场景下如何使用 handoff
|
|
8
|
+
`aiws handoff` 的薄包装入口。
|
|
12
9
|
|
|
13
|
-
说明:
|
|
14
|
-
- `handoff.md` 默认由 `aiws change finish --push` 自动归档时生成:`changes/archive/<date>-<change-id>/handoff.md`
|
|
15
|
-
- `Depends_On` 依赖若已归档,`aiws change start` 会尝试读取依赖的 `handoff.md` 并输出摘要
|
|
16
|
-
|
|
17
|
-
阶段定位:
|
|
18
|
-
- handoff / archive 阶段;负责查看或补充已归档 change 的交接说明。
|
|
19
|
-
|
|
20
|
-
必需输入:
|
|
21
|
-
- 已归档的 `change/<change-id>`
|
|
22
|
-
- 对应 archive 目录
|
|
23
|
-
|
|
24
|
-
必需输出:
|
|
25
|
-
- `Change_ID:` 当前交接对象
|
|
26
|
-
- `Handoff:` `changes/archive/.../handoff.md`
|
|
27
|
-
- `Next:` 推荐后续 change / `Depends_On` 关系
|
|
28
|
-
|
|
29
|
-
阻断条件:
|
|
30
|
-
- 无法定位目标 change
|
|
31
|
-
- `handoff.md` 无法生成或读取
|
|
32
|
-
|
|
33
|
-
完成判定:
|
|
34
|
-
- 下一位协作者可以只依赖 `handoff.md` 和绑定信息继续工作,而不需要回溯整段会话。
|
|
35
|
-
|
|
36
|
-
执行建议:
|
|
37
|
-
1) 先运行 `$ws-preflight`。
|
|
38
|
-
2) 先确认本 change 已通过 `aiws change finish <change-id> --push` 完成自动归档。
|
|
39
|
-
3) 查看 handoff:
|
|
40
10
|
```bash
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
11
|
+
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
12
|
+
./node_modules/.bin/aiws handoff
|
|
13
|
+
elif command -v aiws >/dev/null 2>&1; then
|
|
14
|
+
aiws handoff
|
|
15
|
+
else
|
|
16
|
+
npx @aipper/aiws handoff
|
|
17
|
+
fi
|
|
44
18
|
```
|
|
45
|
-
4) 若是历史/异常场景,尚未归档且需要手工恢复,再运行 `aiws change archive <change-id>`。
|
|
46
|
-
5) 若要让后续 change 可接力:在 `proposal.md` 里声明 `Blocks`(下一步建议会据此生成)。
|
|
47
|
-
6) 若本 change 使用了外部 / 子 agent 协作:确认关键结论已经进入 `review/` 或 `evidence/`,避免 handoff 只留下原始 patch/分析文件而没有最终结论。
|
|
48
|
-
|
|
49
|
-
输出要求:
|
|
50
|
-
- `Change_ID:` <change-id>
|
|
51
|
-
- `Handoff:` `changes/archive/.../handoff.md`
|
|
52
|
-
- `Next:` 若还有后续工作,建议创建新 change 并在其 `Depends_On` 引用本 change
|
|
@@ -1,54 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ws-migrate
|
|
3
|
-
description:
|
|
3
|
+
description: `aiws migrate` 的薄包装入口
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# ws-migrate
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
`aiws migrate` 的薄包装入口。
|
|
9
9
|
|
|
10
|
-
执行(在项目根目录):
|
|
11
|
-
```bash
|
|
12
|
-
if [[ -f ".aiws/manifest.json" ]]; then
|
|
13
|
-
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
14
|
-
./node_modules/.bin/aiws update .
|
|
15
|
-
elif command -v aiws >/dev/null 2>&1; then
|
|
16
|
-
aiws update .
|
|
17
|
-
else
|
|
18
|
-
npx @aipper/aiws update .
|
|
19
|
-
fi
|
|
20
|
-
else
|
|
21
|
-
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
22
|
-
./node_modules/.bin/aiws init .
|
|
23
|
-
elif command -v aiws >/dev/null 2>&1; then
|
|
24
|
-
aiws init .
|
|
25
|
-
else
|
|
26
|
-
npx @aipper/aiws init .
|
|
27
|
-
fi
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
31
|
-
./node_modules/.bin/aiws validate .
|
|
32
|
-
elif command -v aiws >/dev/null 2>&1; then
|
|
33
|
-
aiws validate .
|
|
34
|
-
else
|
|
35
|
-
npx @aipper/aiws validate .
|
|
36
|
-
fi
|
|
37
|
-
|
|
38
|
-
git config core.hooksPath .githooks
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
回滚(恢复最近一次快照):
|
|
42
10
|
```bash
|
|
43
11
|
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
44
|
-
./node_modules/.bin/aiws
|
|
12
|
+
./node_modules/.bin/aiws migrate
|
|
45
13
|
elif command -v aiws >/dev/null 2>&1; then
|
|
46
|
-
aiws
|
|
14
|
+
aiws migrate
|
|
47
15
|
else
|
|
48
|
-
npx @aipper/aiws
|
|
16
|
+
npx @aipper/aiws migrate
|
|
49
17
|
fi
|
|
50
18
|
```
|
|
51
|
-
|
|
52
|
-
约束:
|
|
53
|
-
- 不写入任何 secrets。
|
|
54
|
-
- 不执行破坏性命令。
|
|
@@ -1,61 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ws-plan-verify
|
|
3
|
-
description:
|
|
3
|
+
description: `aiws plan-verify` 的薄包装入口
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# ws-plan-verify
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- 在进入 `$ws-dev` 前,对 `plan/...` 与 `changes/<change-id>/proposal.md` 做一次“硬约束”质检
|
|
10
|
-
- 避免计划过长、步骤不够具体、验证不可复现、与需求合同绑定不一致
|
|
11
|
-
- 失败时只给最小修正项,修完后再进入实现
|
|
8
|
+
`aiws plan-verify` 的薄包装入口。
|
|
12
9
|
|
|
13
|
-
适用时机:
|
|
14
|
-
- 已执行过 `$ws-plan`,且准备开始编码
|
|
15
|
-
- 或用户反馈“计划太长/容易跑偏”,需要先压缩并对齐
|
|
16
|
-
|
|
17
|
-
阶段定位:
|
|
18
|
-
- planning gate;负责在编码前检查计划是否满足 change 严格契约。
|
|
19
|
-
|
|
20
|
-
必需输入:
|
|
21
|
-
- 当前 `plan/...`
|
|
22
|
-
- `changes/<change-id>/proposal.md`
|
|
23
|
-
- 当前 change 上下文
|
|
24
|
-
|
|
25
|
-
必需输出:
|
|
26
|
-
- `Quality gate:` pass/fail
|
|
27
|
-
- `Fix list:` 最小修正项
|
|
28
|
-
- `Next:` 通过则 `$ws-dev`,未通过则继续修正并复跑
|
|
29
|
-
|
|
30
|
-
阻断条件:
|
|
31
|
-
- 无法定位当前 change 或计划文件
|
|
32
|
-
- `aiws change validate <change-id> --strict` 未通过
|
|
33
|
-
|
|
34
|
-
完成判定:
|
|
35
|
-
- 计划满足严格门禁,且后续实现可以在不补需求/补绑定的情况下直接开始。
|
|
36
|
-
|
|
37
|
-
执行步骤(建议):
|
|
38
|
-
1) 先运行 `$ws-preflight`。
|
|
39
|
-
2) 识别 change 上下文:
|
|
40
|
-
- 优先从当前分支推断 `change/<change-id>`
|
|
41
|
-
- 若无法推断:读取 `changes/*/proposal.md` 中的 `Change_ID`,并让用户确认本次要质检的 change
|
|
42
|
-
3) 运行严格门禁(这是硬约束入口):
|
|
43
10
|
```bash
|
|
44
11
|
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
45
|
-
./node_modules/.bin/aiws
|
|
12
|
+
./node_modules/.bin/aiws plan-verify
|
|
46
13
|
elif command -v aiws >/dev/null 2>&1; then
|
|
47
|
-
aiws
|
|
14
|
+
aiws plan-verify
|
|
48
15
|
else
|
|
49
|
-
npx @aipper/aiws
|
|
16
|
+
npx @aipper/aiws plan-verify
|
|
50
17
|
fi
|
|
51
18
|
```
|
|
52
|
-
4) 若失败:按报错逐条修正 `proposal.md` / `plan/...`,优先级如下:
|
|
53
|
-
- 先修绑定:`Change_ID` / `Req_ID|Problem_ID` / `Contract_Row` / `Plan_File` / `Evidence_Path`
|
|
54
|
-
- 再修计划质量:必需章节、步骤数量、步骤具体性、验证命令与预期
|
|
55
|
-
5) 复跑 strict 校验,直到通过。
|
|
56
|
-
6) 输出“可执行最小计划摘要”(3-8 步),再进入 `$ws-dev`。
|
|
57
|
-
|
|
58
|
-
输出要求:
|
|
59
|
-
- `Quality gate:` pass/fail
|
|
60
|
-
- `Fix list:` 仅保留必须修改项(按阻断级别排序)
|
|
61
|
-
- `Next:` 通过后建议 `$ws-dev`;未通过则继续修正并复跑 strict
|
|
@@ -1,119 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ws-pull
|
|
3
|
-
description:
|
|
3
|
+
description: `aiws pull` 的薄包装入口
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# ws-pull
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- Git submodule 在别的电脑 `git submodule update` 后常见现象是子模块处于 detached HEAD(因为主仓库记录的是固定 gitlink commit)。
|
|
10
|
-
- detached 本身不一定是错,但会增加“需要手动切分支/容易忘”的操作差异。
|
|
8
|
+
`aiws pull` 的薄包装入口。
|
|
11
9
|
|
|
12
|
-
目标:
|
|
13
|
-
- 安全拉取 superproject(默认只允许 fast-forward)
|
|
14
|
-
- 初始化/同步 submodules(`--init --recursive`)
|
|
15
|
-
- 在**不改动 superproject gitlink commit** 的前提下,尽量把每个 submodule 从 detached HEAD “挂回”到一个**确定的目标分支**(仅当该分支包含 gitlink commit 时)
|
|
16
|
-
- 若未配置 `.gitmodules` 的 `submodule.<name>.branch`:保持 detached,并提示先运行 `$ws-submodule-setup`
|
|
17
|
-
|
|
18
|
-
安全约束(强制):
|
|
19
|
-
- 不执行破坏性命令(不 `reset --hard` 主仓库;不改动远端)
|
|
20
|
-
- 不自动提交/不自动 push
|
|
21
|
-
- 若工作区不干净:停止并要求用户先 commit 或 stash(不要自动处理)
|
|
22
|
-
|
|
23
|
-
执行步骤(建议):
|
|
24
|
-
0) 输出上下文:
|
|
25
10
|
```bash
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
若 `git status --porcelain` 非空:停止,要求用户先清理工作区(commit 或 stash)。
|
|
31
|
-
|
|
32
|
-
1) 拉取 superproject(默认只允许 fast-forward,避免隐式 merge/rebase):
|
|
33
|
-
```bash
|
|
34
|
-
git pull --ff-only
|
|
35
|
-
```
|
|
36
|
-
若失败(需要 merge/rebase):停止并向用户解释原因,让用户明确选择 `git pull --rebase` 或手动处理。
|
|
37
|
-
|
|
38
|
-
2) 同步并更新 submodules 到 superproject 记录的 gitlink commit:
|
|
39
|
-
```bash
|
|
40
|
-
if [[ -f .gitmodules ]]; then
|
|
41
|
-
git submodule sync --recursive
|
|
42
|
-
git submodule update --init --recursive
|
|
11
|
+
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
12
|
+
./node_modules/.bin/aiws pull
|
|
13
|
+
elif command -v aiws >/dev/null 2>&1; then
|
|
14
|
+
aiws pull
|
|
43
15
|
else
|
|
44
|
-
|
|
16
|
+
npx @aipper/aiws pull
|
|
45
17
|
fi
|
|
46
18
|
```
|
|
47
|
-
|
|
48
|
-
3) (可选但推荐)把 submodule 从 detached HEAD 尽量“挂回分支”,减少手工操作差异:
|
|
49
|
-
|
|
50
|
-
说明:
|
|
51
|
-
- 该步骤不会改变 superproject 的 gitlink commit(也不会让主仓库出现“submodule modified”)。
|
|
52
|
-
- 只在目标分支包含该 gitlink commit 时才执行“挂回”;否则保持 detached 并提示原因。
|
|
53
|
-
- 为了避免 origin 分支较多时“猜错分支”,本步骤**只在** `.gitmodules` 明确配置了 `submodule.<name>.branch` 时才执行“挂回分支”;否则保持 detached 并提示先运行 `$ws-submodule-setup` 对齐配置。
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
if [[ -f .gitmodules ]]; then
|
|
57
|
-
base_branch="$(git branch --show-current)"
|
|
58
|
-
git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' 2>/dev/null \
|
|
59
|
-
| while read -r key sub_path; do
|
|
60
|
-
[[ -z "${sub_path:-}" ]] && continue
|
|
61
|
-
name="${key#submodule.}"
|
|
62
|
-
name="${name%.path}"
|
|
63
|
-
echo "== submodule: ${sub_path} (${name}) =="
|
|
64
|
-
|
|
65
|
-
sub_sha="$(git rev-parse "HEAD:${sub_path}" 2>/dev/null || true)"
|
|
66
|
-
if [[ -z "${sub_sha:-}" ]]; then
|
|
67
|
-
echo "[warn] failed to read gitlink sha for ${sub_path}"
|
|
68
|
-
continue
|
|
69
|
-
fi
|
|
70
|
-
|
|
71
|
-
cfg_branch="$(git config --file .gitmodules --get "submodule.${name}.branch" 2>/dev/null || true)"
|
|
72
|
-
if [[ "${cfg_branch:-}" == "." ]]; then cfg_branch="$base_branch"; fi
|
|
73
|
-
if [[ -z "${cfg_branch:-}" ]]; then
|
|
74
|
-
echo "[warn] ${sub_path}: missing .gitmodules submodule.${name}.branch; keep detached (run ws-submodule-setup to set it)"
|
|
75
|
-
continue
|
|
76
|
-
fi
|
|
77
|
-
|
|
78
|
-
target_branch="${cfg_branch}"
|
|
79
|
-
pin_branch="aiws/pin/${target_branch}"
|
|
80
|
-
|
|
81
|
-
git -C "${sub_path}" fetch origin --prune || true
|
|
82
|
-
|
|
83
|
-
if git -C "${sub_path}" show-ref --verify --quiet "refs/remotes/origin/${target_branch}"; then
|
|
84
|
-
if git -C "${sub_path}" merge-base --is-ancestor "${sub_sha}" "origin/${target_branch}"; then
|
|
85
|
-
# 不改动现有分支(避免把已有 main/master 等分支强行指回旧 commit)
|
|
86
|
-
# 仅创建/更新一个 AIWS 专用 pin 分支指向 gitlink commit,从 detached “挂回分支”。
|
|
87
|
-
git -C "${sub_path}" checkout -B "${pin_branch}" "${sub_sha}"
|
|
88
|
-
git -C "${sub_path}" branch --set-upstream-to "origin/${target_branch}" "${pin_branch}" >/dev/null 2>&1 || true
|
|
89
|
-
echo "[ok] attached ${sub_path} to ${pin_branch} (upstream=origin/${target_branch}) at ${sub_sha}"
|
|
90
|
-
else
|
|
91
|
-
echo "[warn] ${sub_path}: ${sub_sha} is not in origin/${target_branch}; keep detached"
|
|
92
|
-
fi
|
|
93
|
-
else
|
|
94
|
-
echo "[warn] ${sub_path}: origin/${target_branch} not found; keep detached"
|
|
95
|
-
fi
|
|
96
|
-
|
|
97
|
-
git -C "${sub_path}" rev-parse --abbrev-ref HEAD 2>/dev/null || true
|
|
98
|
-
git -C "${sub_path}" status -sb || true
|
|
99
|
-
done
|
|
100
|
-
fi
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
4) 一次性配置(方案 2):为每个 submodule 写入跟踪分支,便于团队统一(需要用户确认,会改动 `.gitmodules`):
|
|
104
|
-
```bash
|
|
105
|
-
# 示例:把某个 submodule 固定跟踪 main(会写入 .gitmodules 的 submodule.<name>.branch)
|
|
106
|
-
git submodule set-branch --branch main <sub_path>
|
|
107
|
-
|
|
108
|
-
# 提示:该变更需要提交到 superproject
|
|
109
|
-
git add .gitmodules
|
|
110
|
-
git commit -m "chore(submodule): set tracking branch"
|
|
111
|
-
```
|
|
112
|
-
建议:
|
|
113
|
-
- 只有当团队明确希望“子模块按分支滚动”(而不是锁定固定 commit)时,才采用方案 2。
|
|
114
|
-
- 若只是想避免 detached 但仍锁定 gitlink commit:优先使用步骤 3(不改 `.gitmodules`)。
|
|
115
|
-
- 推荐用 `$ws-submodule-setup` 交互式对齐所有 submodules 的 branch,并提交 `.gitmodules`。
|
|
116
|
-
|
|
117
|
-
输出要求:
|
|
118
|
-
- `Context:` 当前分支 + 是否存在 `.gitmodules` + submodule 列表
|
|
119
|
-
- `Result:` pull 是否 fast-forward;每个 submodule 是否成功“挂回分支”,失败原因是什么
|
|
@@ -1,110 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ws-push
|
|
3
|
-
description:
|
|
3
|
+
description: `aiws push` 的薄包装入口
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# ws-push
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- 在不自动提交的前提下,安全 push 当前仓库
|
|
10
|
-
- 若仓库包含 submodules:按 `submodules -> superproject` 顺序 push,减少“别人拉取后子模块 detached/分叉”的协作摩擦
|
|
11
|
-
- 若不包含 submodules:按普通 git 仓库的规则 push
|
|
8
|
+
`aiws push` 的薄包装入口。
|
|
12
9
|
|
|
13
|
-
安全约束(强制):
|
|
14
|
-
- 不自动提交、不自动 `git add -A`
|
|
15
|
-
- 不使用 `--force` / `--force-with-lease`
|
|
16
|
-
- 默认只允许 fast-forward push(发现分叉则停止并提示人工处理)
|
|
17
|
-
- 若工作区不干净:停止并要求先 commit 或 stash
|
|
18
|
-
|
|
19
|
-
执行步骤(建议):
|
|
20
|
-
0) 输出上下文:
|
|
21
|
-
```bash
|
|
22
|
-
git branch --show-current
|
|
23
|
-
git status --porcelain
|
|
24
|
-
git status -sb
|
|
25
|
-
```
|
|
26
|
-
若 `git status --porcelain` 非空:停止。
|
|
27
|
-
|
|
28
|
-
1) 判断是否存在 submodules:
|
|
29
10
|
```bash
|
|
30
|
-
if [[ -
|
|
31
|
-
|
|
11
|
+
if [[ -x "./node_modules/.bin/aiws" ]]; then
|
|
12
|
+
./node_modules/.bin/aiws push
|
|
13
|
+
elif command -v aiws >/dev/null 2>&1; then
|
|
14
|
+
aiws push
|
|
32
15
|
else
|
|
33
|
-
|
|
34
|
-
fi
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
2) 若不存在 `.gitmodules` 或没有 submodule 条目:按普通仓库 push(仍需用户确认):
|
|
38
|
-
```bash
|
|
39
|
-
git remote -v
|
|
40
|
-
git push
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
3) 若存在 submodules:先检查 `.gitmodules` 的 branch 真值是否齐全(缺失则停止并提示 setup):
|
|
44
|
-
```bash
|
|
45
|
-
missing=0
|
|
46
|
-
while read -r key sub_path; do
|
|
47
|
-
name="${key#submodule.}"; name="${name%.path}"
|
|
48
|
-
b="$(git config --file .gitmodules --get "submodule.${name}.branch" 2>/dev/null || true)"
|
|
49
|
-
if [[ -z "${b:-}" ]]; then
|
|
50
|
-
echo "error: missing .gitmodules submodule.${name}.branch (path=${sub_path})"
|
|
51
|
-
missing=1
|
|
52
|
-
fi
|
|
53
|
-
done < <(git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' 2>/dev/null || true)
|
|
54
|
-
if [[ "$missing" -ne 0 ]]; then
|
|
55
|
-
echo "hint: run $ws-submodule-setup (and commit .gitmodules), then retry"
|
|
56
|
-
exit 2
|
|
16
|
+
npx @aipper/aiws push
|
|
57
17
|
fi
|
|
58
18
|
```
|
|
59
|
-
|
|
60
|
-
4) 逐个 push submodules(fast-forward only),再 push superproject:
|
|
61
|
-
```bash
|
|
62
|
-
base_branch="$(git branch --show-current)"
|
|
63
|
-
change_id="$(echo "${base_branch}" | sed -n 's|^change/||p')"
|
|
64
|
-
targets="changes/${change_id}/submodules.targets"
|
|
65
|
-
# Note: if not on a change/ branch, change_id is empty and targets file won't exist;
|
|
66
|
-
# resolution falls back to .gitmodules submodule.<name>.branch via ws_resolve_sub_target.
|
|
67
|
-
|
|
68
|
-
source tools/ws_resolve_sub_target.sh
|
|
69
|
-
|
|
70
|
-
git config --file .gitmodules --get-regexp '^submodule\\..*\\.path$' 2>/dev/null \
|
|
71
|
-
| while read -r key sub_path; do
|
|
72
|
-
name="${key#submodule.}"; name="${name%.path}"
|
|
73
|
-
echo "== submodule: ${sub_path} (${name}) =="
|
|
74
|
-
|
|
75
|
-
# submodule 工作区必须干净
|
|
76
|
-
if [[ -n "$(git -C "${sub_path}" status --porcelain 2>/dev/null || true)" ]]; then
|
|
77
|
-
echo "error: submodule dirty: ${sub_path}"
|
|
78
|
-
exit 2
|
|
79
|
-
fi
|
|
80
|
-
|
|
81
|
-
ws_resolve_sub_target "${sub_path}" "${name}" "${targets}" "${base_branch}" || exit 2
|
|
82
|
-
target_branch="${_resolved_branch}"
|
|
83
|
-
remote="${_resolved_remote}"
|
|
84
|
-
|
|
85
|
-
git -C "${sub_path}" fetch "${remote}" --prune
|
|
86
|
-
if ! git -C "${sub_path}" show-ref --verify --quiet "refs/remotes/${remote}/${target_branch}"; then
|
|
87
|
-
echo "error: missing ${remote}/${target_branch} for ${sub_path}"
|
|
88
|
-
exit 2
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
# fast-forward only: <remote>/<branch> 必须是 HEAD 的祖先
|
|
92
|
-
if ! git -C "${sub_path}" merge-base --is-ancestor "${remote}/${target_branch}" HEAD; then
|
|
93
|
-
echo "error: non-fast-forward (submodule=${sub_path}, remote=${remote}, branch=${target_branch})"
|
|
94
|
-
echo "hint: rebase/merge in submodule, then retry"
|
|
95
|
-
exit 2
|
|
96
|
-
fi
|
|
97
|
-
|
|
98
|
-
# push HEAD -> <remote>/<branch>(不 force)
|
|
99
|
-
git -C "${sub_path}" push "${remote}" "HEAD:refs/heads/${target_branch}"
|
|
100
|
-
done
|
|
101
|
-
|
|
102
|
-
# 最后 push superproject(仍需用户确认远端/分支)
|
|
103
|
-
git remote -v
|
|
104
|
-
git push
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
输出要求:
|
|
108
|
-
- `Context:` 当前分支 + 是否有 submodules
|
|
109
|
-
- `Submodules:` 每个 submodule push 的目标分支与结果(成功/阻断原因)
|
|
110
|
-
- `Superproject:` push 结果
|