Files
superwork/vscode/README.md
T
cruldra fcee4143d4 ✨ feat(vscode): 会话交接改走阿里云 OSS 收件箱、换 xz 压缩,另加从 env 文件配置移交存储的 URI
- 会话包传到 OSS 上收件人的收件箱 spx-handoff/<owner>/<repo>/session/<收件人>/<sid>!<发送人>!<会话名>.tar.xz,对象私有;owner/repo/收件人转小写
- 待接收列表就是列自己的收件箱;同一会话再交给同一人先删旧包;接收后删包,包已被别处收走时提示并刷新
- 打包换成 xz 1 级,和工单移交共用 packHandoff / unpackHandoff,删掉 gzip 版
- 删掉邮箱工单整套(mailboxIssue、MAILBOX_*、isMailboxIssue 及看板 / webhook 里的过滤、附件名编解码)和不再用的 Gitea 附件、标签、建工单接口
- session-handoff/accept 与待接收项改用 OSS 对象 key 标识
- 没配移交存储时发送、接收、刷新都提示去配,刷新回空列表
- 进度提示照工单移交:同一条提示依次显示打包、上传、下载多少 MB、解包、装会话
- 新增 URI configure-handoff-store?envFile=<绝对路径>:读 OSS_ENDPOINT / OSS_BUCKET_NAME / OSS_ACCESS_KEY / OSS_SECRET_KEY 保存,和命令共用 saveHandoffStore;URI 入口按 path 统一分发,未知 path 报错
2026-10-08 07:17:26 +08:00

212 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Superpowers-clurdra
把 Gitea 工单变成 VS Code 里的看板,每张卡片背后挂着一组 AI 会话(头脑风暴 → 实施 → 审查 → 测试),从建工单到合并 PR 全程在编辑器里完成。
- 数据源:**Gitea** 工单(主)+ **YouTrack** 工单(可选镜像)
- 执行者:`claude` CLI 负责规划 / 实施 / 测试 / 提交,`codex` 负责审查
- 状态存放:工单评论里的一段 state JSON,多人、多机共享;本机专属字段(会话 id、worktree 路径等)留在本机
- 联动:Gitea webhook 推回本机,PR 开了自动审查、审查意见自动注入实施终端、合并后自动清 worktree 和分支
## 工作流
```
待办 ──拖到进行中──▶ 进行中 ──PR 打开──▶ 审查 ──拖到完成──▶ 完成
│ │ │ │
头脑风暴会话 实施会话 审查会话(codex) 插件代为合并 PR
产出 spec / plan 独立 worktree 意见注入实施终端 关工单 · 删 worktree · 删分支
+ feature 分支 测试会话可随时开
```
1. **新建工单**:待办列头的 `+` → 写需求(可粘贴截图)→ 开一个 `claude` 头脑风暴会话,它用 `spx issue create` 建工单,再经 `/ecc:grilling` + `/ecc:spec` + `/ecc:plan` 写出设计文档 / 计划并回填两者路径。
2. **实施**:把卡拖到「进行中」(或点计划文件行的 ▶)。插件创建 `feature/<slug>` 分支 + git worktree,在里面开 `issue-N-实施` 终端并发实施 prompt,实施方对计划跑 `/ecc:tdd`,在 PR body 里写 `Closes #N`。
3. **审查**:PR opened / synchronize 的 webhook 到达后,插件自动开 `issue-N-审查`(codex);审查意见通过 `spx pr review-comment` 发到 PR,webhook 再把意见注入实施终端形成闭环。
4. **测试**:工单面板里 ▶ 开 `issue-N-测试` 会话(`/pr-acceptance-testing`)。
5. **完成**:拖到「完成」列。有 PR 就由插件合并(冲突时开 `issue-N-冲突解决` 会话,解决后再拖一次),然后关工单、把会话记录拷回主仓库、删 worktree、删 feature 分支。
6. **回退**:进行中 / 审查中的卡可「重置为待办」,关 PR、删 worktree、清分支和实施痕迹,spec / plan 保留。
7. **移交**:前置条件:两台机器的 spx 都已 `cd cli && make install` 到含 `handoffBundleKey` 的版本,否则移交期间旧 spx 的 state 写入会被 schema 拒绝;两台机器都在命令面板跑过「Superpowers: 配置移交存储」(阿里云 OSS 的 endpoint、bucket、AccessKey ID / Secret,AccessKey 存在 VS Code 的密钥存储里),没配的话移交和接管都会直接提示去配。工单 tab 头部「移交」→ 选同事。插件校验 worktree 已全部 push,关掉该工单的终端,把头脑风暴 / 实施 / 测试的 claude 会话(jsonl + 子目录)和 codex 审查会话打成 xz 压缩的 `issue-N-<时间>.tar.xz`,以私有权限传到 OSS 的 `spx-handoff/<owner>/<repo>/` 下,写 `handoffBundleKey` / `handoffFrom`,把工单指派给对方,最后删本机 worktree 与本地分支(远端分支保留)。对方看板上该卡显示「待接管」,工单 tab 点「接管」:从 OSS 下载会话包、从 origin 重建 worktree(`git worktree add -B <branch> … origin/<branch>`)、把会话文件装到本机 `~/.claude/projects/` 对应目录(先清同 sid 副本)与 `~/.codex/sessions/`、写本机字段、清移交字段并删掉 OSS 上的会话包。两边的进度提示会一步步显示打包 / 上传 / 下载了多少 MB。之后 resume / 合并 / 冲突解决 / 测试与本机实施的工单无异。
8. **发布**:工具栏「发布」按钮下拉三项。「切新发布」从 `origin/<devBranch>` 切当天的 `<releaseBranchPrefix>YYYY-MM-DD` 并推远端(纯远端,不建本地分支),配了 `jenkinsJob` 会顺带问要不要立刻部署。「摘修复到当期发布」列出 `devBranch` 上还没进发布分支的提交(按文件改动指纹比对,另认 `cherry-pick -x` 留下的「cherry picked from commit」尾注,所以解过冲突、内容已变的复制品也算已摘;手工 pick 请带 `-x`),多选后在发布 worktree(`worktreeDirectory` 模板,目录名为分支名把 `/` 换成 `-`)里按序 `cherry-pick -x` 并推远端,成功后删 worktree。中途冲突则保留冲突现场、远端不变,开 `<发布分支>-冲突解决` 会话让 claude 解冲突、`cherry-pick --continue`、按序摘完剩余提交再推远端;上次冲突还没处理完时再摘会被拒绝。「部署到正式服」选一个发布分支(默认当期,选旧的即回滚)执行 `opencli jks build <jenkinsJob> -p REF=<分支> -p REMOTE_HOST=<jenkinsProdHost>`。
其他看板规则:
- 待办列里卡片拖到另一张卡上 = 设前置依赖,拖回列头 = 清依赖。前置未完成的卡显示 🔒,不能拖出待办、不能开会话。待办列按依赖链渲染成缩进树。
- 完成列按合并时间倒序,其余列按工单号倒序。
- 每张卡首次开会话时随机分配一个颜色,之后该工单所有终端 tab 用同色圆点。
- 选中卡片会聚焦它的终端(新建 > 实施 > 规划 > 审查 > 测试);点终端 tab 也会反向选中卡片。
- 键盘:`↑↓←→` 移动选中,`Enter` 恢复实施会话(没有则头脑风暴会话),`Esc` 取消选中。
- 看板范围:工具栏 👤/👥 在「我创建或指派给我的」与「仓库全部」之间切换。
## 环境要求
| 工具 | 用途 |
|---|---|
| `git` | worktree、分支、fetch / merge |
| `claude` | 规划、实施、测试、冲突解决、提交、PR 摘要(找不到时会提示常见位置 `~/.local/bin`) |
| ECC 插件(`ecc@ecc`) | Claude Code 插件,头脑风暴 / 实施会话用它的 `/ecc:grilling` `/ecc:spec` `/ecc:plan` `/ecc:tdd` 和审查子代理 |
| `codex` | 审查会话(开启自动审查时必需) |
| `tea` | `spx` 从 `~/.config/tea/config.yml` 读取 Gitea host + token;审查 prompt 也用 `tea pulls` 看 PR |
| `spx` | 本仓库 `cli/` 里的 Go CLI,见下文 |
| `opencli` | prompts 里统一以 `opencli spx ...` 调用 spx |
| `tar` | 移交时打包 / 解包会话文件 |
| `bash` | 执行钩子脚本 |
- 仅支持 Gitea(`https://<host>/api/v1`),不支持 GitHub。
- POSIX 环境。删 worktree 前扫 `/proc` 杀占用进程只在 Linux 生效,macOS 上降级为直接删。
- 依赖内置 `vscode.git` 扩展检测工作区改动(提交按钮)。
### 安装 spx
```bash
cd cli && make install # 编译到 bin/spx 并安装到 ~/.local/bin/
```
`spx` 命令:
| 命令 | 作用 |
|---|---|
| `spx issue create --title ... [--body-file F] [--spec P] [--plan P] [--state-json J]` | 建工单并认领;spec / plan 同时写 body marker 和 state JSON |
| `spx issue marker --issue N --type spec\|plan --value P` | 更新 body 里的 `<!-- spx:spec=... -->` / `<!-- spx:plan=... -->` 并同步 state |
| `spx issue state get --issue N` | 读 state JSON |
| `spx issue state merge --issue N --state-json J` | 浅合并写回(按 schema 校验) |
| `spx pr review-comment --pr N --body-file F` | 发审查评论,自动加 `<!-- spx:review=1 -->` 标记 |
全局 flag:`--repo OWNER/REPO`(默认从 origin 推断)、`--host`、`--json`、`--cwd`。tea 用 keyring 存 token 时需设 `GITEA_TOKEN` 环境变量。
### Gitea 配置
1. 打开看板 → 设置 → 认证,填 Gitea host 和 Personal Access Token(存 VS Code SecretStorage)。状态栏会常驻显示当前身份 `spx: <login>`,token 失效变红;Gitea 邮箱和 `git config user.email` 不一致时会警告。
2. 在仓库上配一个 webhook 指向本机的 `http://<公网地址>/webhook`(本机默认监听 `17421`,通常经 frp 之类反代暴露),事件至少勾选 **Issues、Issue Comment、Pull Request、Push**。建议设置 secret 并在插件设置里同填,否则不校验签名。
3. webhook 会广播到每个开发者的机器,只有工单 assignee 所在的机器执行副作用(写状态、触发审查、注入终端),其他机器只刷新 UI。实施即认领,所以正常情况下不用手动指派。
### YouTrack(可选)
设置 → YouTrack 填 base URL、Permanent Token、项目 shortName 后,工具栏出现「导入 YouTrack 工单」,QuickPick 多选后镜像到看板(卡片 id 形如 `youtrack:LXF-12`)。状态同样以评论形式存在 YouTrack 工单上;拖到完成列执行 `youtrackCloseCommand`(留空则自动取项目第一个已解决状态)。
## 面板
编辑器主区的 webview = 顶部工具栏 + 四列看板 + 底部四个 tab。
**工具栏**:发布(切发布分支 · 摘修复 · 触发正式服部署,见工作流第 8 条;角标 = `devBranch` 上未发布的提交数)· `.env*` 文件锁(批量 chmod 只读,首次启动默认锁定)· 提交代码(有未提交改动时才显示,后台跑无头 `claude` 提交)· 导入 YouTrack 工单 · 看板范围 · 刷新 · 设置。
**工单 tab**:state JSON 的属性网格。会话 id 行双击恢复会话、▶ 新开、✕ 关 tab;spec / plan 行双击打开文件,plan 行 ▶ 实施;PR 行双击打开浏览器、▶ 生成 PR 变更摘要(写到 `docs/pr-diff/`);分支行 🔀 本地预合并;工作树行双击用 VS Code / PyCharm 打开、🗑 删除。顶部有重置为待办、移交 / 接管(见上文工作流第 7 条)、关闭工单、删除工单(关 tab → 删 worktree → 关 PR → 删分支 → 删 issue)、查看日志。
**Profile tab**:工作区级 KV 表(行 = key,列 = dev / prod 等),值可多行、可贴图,落盘 `.spx/profiles.json`。
**会话 tab**:项目级 Claude 会话管理器——新建(可指定 profile 和首条 prompt)、重命名、恢复、导入已 `/rename` 的会话。落盘 `.spx/session-names.json`。单个会话可以「交接」给同事:会话包打成 xz 包、以私有权限传到移交存储(同工单移交,没配会直接提示去跑「配置移交存储」)里对方的收件箱 `spx-handoff/<owner>/<repo>/session/<对方>/`;对方会话 tab 顶部「待接收」列出自己收件箱里的包,点「接收」下载装好会话、删掉 OSS 上的包。同一会话再交给同一人只保留最新一份;两边进度提示一步步显示打包 / 上传 / 下载了多少 MB。
**改动 tab**:PR 文件审阅。左侧文件树 + 统计(可过滤 `tests/`),右侧内联 diff(统一 / 分栏),「已查看」按文件变更指纹失效,每个文件可用 deepseek 生成一句话改动说明。
也可以从外部拉起会话:`vscode://clurdra.superpowers-vscode-clurdra/create-session?profile=<名>&name=<tab名>&prompt=<提示词>&cwd=<路径>`(参数需两层 urlencode)。
从 env 文件配置移交存储:`vscode://clurdra.superpowers-vscode-clurdra/configure-handoff-store?envFile=<env 文件绝对路径>`(参数同样两层 urlencode),读文件里的 `OSS_ENDPOINT` / `OSS_BUCKET_NAME` / `OSS_ACCESS_KEY` / `OSS_SECRET_KEY`,四项齐了就保存,缺项或读不到只报错、什么都不改。
## 会话与 profile
| 会话 | 终端名 | CLI | 工作目录 | profile |
|---|---|---|---|---|
| 新建工单 | `issue-new-<nonce>-规划` | claude | 主仓库 | 弹窗里选 |
| 头脑风暴(续) | `issue-N-规划` | claude | 主仓库 | 工单 `brainstormProfilePath` |
| 实施 | `issue-N-实施` | claude `--effort high` | worktree | 工单 `profilePath` |
| 审查 | `issue-N-审查` | codex | worktree | 设置里的 `codexModel` / `codexReasoningEffort` |
| 测试 | `issue-N-测试` | claude | worktree | 工单 `testProfilePath` |
| 冲突解决 | `issue-N-冲突解决` | claude `--effort high` | worktree | 设置 `conflictResolutionProfilePath` |
| 摘修复冲突解决 | `<发布分支>-冲突解决` | claude `--effort high` | 发布 worktree | 设置 `conflictResolutionProfilePath` |
所有终端固定开在编辑器第二分组。claude 会话统一以 `--settings <profile.json> --dangerously-skip-permissions` 启动,后台无头调用会剥掉 `ANTHROPIC_*` 环境变量,让 profile 成为唯一鉴权来源。
profile 是 Claude 的 settings JSON 文件。目录按 `$SUPERPOWERS_PROFILES_DIR` → 设置 `profilesDirectory` → `~/Sources/cruldra-profile/claude-config/profiles` / `~/.claude/profile-settings` / `~/.claude/profiles` 顺序探测;三种会话 profile 留空时各自回落默认 profile(`offical.json` / `official.json`),互不回退。跨机器的绝对路径按文件名重新映射。
prompts 在 `prompts/*.md`,随 VSIX 一起安装,改完即生效,也可在设置 → 提示词里覆盖。模板走 Handlebars:变量写 `{{name}}`,分支写 `{{#if name}}…{{else}}…{{/if}}`。上下文是工单 state JSON 的全部字段(`planFile` `specFile` `prototypeFile` `branch` `pr` `worktreePath` `prototypeSessionId` …)外加下表这几个:
| 文件 | 额外变量 |
|---|---|
| `brainstorm.md` | `issueNumber`(有 = 续聊已有工单,无 = 新建工单)、`userRequest`、`nonce` |
| `implement-plan.md` | `issueNumber`、`planFile` |
| `review.md` | `issueNumber`、`prNumber` |
| `test.md` | `issueNumber`、`prRef` |
| `prototype.md` | `issueNumber` |
`brainstorm.md` 一份管三件事:`{{#if issueNumber}}` 走续聊(其中 `{{#if prototypeFile}}` 嵌原型段落),`{{else}}` 走新建工单。老版本里 `{issueNumber}` 这种单花括号写法不再支持;升级后首次启动会自动把存量自定义提示词改写成双花括号,并把「续聊」「续聊·原型段落」两份并进 `brainstormPrompt`,改写前会把 `settings.json` 备份成 `settings.json.bak-<时间戳>`。
## 设置
全部在看板的设置弹窗里(存 globalState),不走 VS Code 原生 settings。
| 分组 | 键 | 默认 | 说明 |
|---|---|---|---|
| 认证 | `devBranch` | `main` | 日常开发分支 |
| | `releaseBranchPrefix` | `release/` | 发布分支前缀;远端该前缀下名字最大的分支即当期发布点 |
| | `jenkinsJob` | 空 | 正式服部署的 Jenkins 任务名;空 = 不显示「部署到正式服」 |
| | `jenkinsProdHost` | `正式服` | 触发 Jenkins 时 `REMOTE_HOST` 参数的值 |
| | `conflictResolutionProfilePath` | 空 | 冲突解决会话 profile |
| | `commitProfilePath` | `deepseek-v4-pro` | 「提交代码」用的 profile;未配置时提交直接失败 |
| | `prDiffSummaryProfilePath` | `deepseek-v4-pro` | 「改动」说明 / PR 变更摘要用的 profile;未配置时生成失败 |
| | `codexModel` / `codexReasoningEffort` | 空 | 审查会话的 codex `-c` 覆盖;空 = 用 codex 自己的 config |
| 网络 | `webhookPort` | `17421` | 本机 webhook 端口 |
| | `webhookSecret` | 空 | Gitea webhook secret,空 = 不校验签名 |
| | `autoReview` | `true` | 全局自动审查;工单级 `autoReview` 可覆盖 |
| | `profilesDirectory` | 空 | Claude profiles 目录,空 = 自动探测 |
| YouTrack | `youtrackBaseUrl` / `youtrackProjectShortName` / `youtrackCloseCommand` | 空 | 见上文 |
| 钩子 | `worktreeDirectory` | `~/Sources/worktree/$project_name/$feature_name` | 占位符 `$project_root` `$project_name` `$feature_name` |
| | `worktreeOpenWith` / `pycharmCommand` | `vscode` / `pycharm` | 工作树行双击的打开方式 |
| | `worktreePostCreateScript` | `.spx/worktree-post-create.sh` | worktree 创建后 |
| | `worktreePreRemoveScript` | `.spx/worktree-pre-remove.sh` | worktree 删除前 |
| | `implTabPreCreateScript` | `.spx/impl-tab-pre-create.sh` | 实施 / 测试 / 冲突解决 tab 创建前(复用 tab 不触发) |
| | `implTabPostCloseScript` | `.spx/impl-tab-post-close.sh` | 实施 tab 关闭后 |
钩子用 `bash <script>` 执行,cwd 为 worktree,超时 30s,脚本不存在静默跳过,失败只告警不阻断。可用环境变量:`WORKTREE_PATH` `WORKSPACE_ROOT` `BRANCH` `ISSUE_NUMBER` `MAIN_BRANCH`。
## 工单上的 state JSON
以工单最后一条 state 评论为准,写入是读 → 浅合并 → 追加新评论,带一次乐观并发重放。schema 在 `schemas/state-json.schema.json`(`spx` 写入前按它校验)。
| 字段 | 说明 |
|---|---|
| `column` | `todo` / `in-progress` / `review` / `done` |
| `specFile` / `planFile` | 相对主仓库的 md 路径 |
| `branch` / `pr` / `prMerged` / `prMergedAt` | 实施分支与 PR 状态 |
| `implementStatus` | `running` / `done` / `failed` |
| `color` | 终端 tab 颜色 |
| `autoReview` | 工单级自动审查开关 |
| `handoffBundleKey` / `handoffFrom` | 移交中:会话包在 OSS 上的对象 key 与发起人;接管后清空 |
| `sessionId` / `implementSessionId` / `reviewSessionId` / `testSessionId` | 各会话 id |
| `profilePath` / `brainstormProfilePath` / `testProfilePath` | 各会话 profile |
| `worktreePath` / `prDiffFile` | 本机路径 |
最后两行(会话 id、profile、路径共 9 个字段)是**本机字段**,只存在 VS Code workspaceState 里,不写进共享评论,所以同一工单在不同机器上可以各自有会话。
## 工作区约定
```
.claude/specs/<stem>.md # 设计文档,即工单的 spec marker
.claude/plans/<stem>.md # 实施计划,即 plan marker
docs/pr-diff/pr-<pr>-issue-<n>.md # PR 变更摘要
.spx/profiles.json # Profile tab
.spx/session-names.json # 会话 tab
.spx/pr-review-confirmed.json # 改动 tab 已查看态
.spx/pr-file-summaries.json # 改动 tab 文件说明
.spx/youtrack-imported.json # YouTrack 导入集
.spx/profile-assets/ # Profile 值里粘贴的图片
.spx/*.sh # 钩子脚本
```
实施分支名 `feature/<slug>`,slug 取计划文件名的 stem(`.claude/plans/<stem>.md` 里的 stem),与设计文档同名。
## 开发
```bash
pnpm install
pnpm dev # webview (Vite) + 扩展 (esbuild) 双 watch,配合 .vscode/launch.json 的 Extension 调试
pnpm test # vitest,只测不依赖 vscode API 的纯逻辑模块
pnpm lint
pnpm typecheck
pnpm ext:package # 构建并打 VSIX,产物在本目录
```
安装本地包:`code --install-extension superpowers-vscode-clurdra-<ver>.vsix --force`(用了 VS Code profile 的窗口要加 `--profile <name>`)。
技术栈:TypeScript、VS Code Extension API、React 19 + Tailwind 4(webview)、esbuild、Vitest;CLI 为 Go + cobra。
## 许可证
MIT