diff --git a/vscode/prompts/brainstorm.md b/vscode/prompts/brainstorm.md index 3921672..98b7f98 100644 --- a/vscode/prompts/brainstorm.md +++ b/vscode/prompts/brainstorm.md @@ -1,7 +1,7 @@ {{#if issueNumber}} /ecc:grilling 讨论下 {{issueNumber}} 号工单 -用 tea 命令找工单,用 `ecc:grilling` 技能讨论细节,用表单形式和我交互,每次只问一个问题(成组的问题也拆成一次一问)。 +先用 `opencli spx issue view --issue {{issueNumber}} --comments` 看工单正文和讨论,再用 `ecc:grilling` 技能讨论细节,用表单形式和我交互,每次只问一个问题(成组的问题也拆成一次一问)。 {{#if prototypeFile}} 工单已有原型插件 {{prototypeFile}},先读它了解已经定下来的界面和交互,在此基础上只对齐还不明确的地方,不要从零重画。 @@ -24,7 +24,7 @@ ## marker 维护(本会话有效) -设计文档 / 计划文件**一律在当前主 worktree(main 分支)创建并提交**(`ecc:spec` 默认不提交,这里要显式提交),每次只提交这两个文件(提交信息形如 `📝 docs: #<工单号> 设计文档` / `📝 docs: #<工单号> 实施计划`),不要为此新建或切换分支。创建后追加对应 marker: +设计文档 / 计划文件**一律在当前主 worktree(仓库默认分支)创建并提交**(`ecc:spec` 默认不提交,这里要显式提交),每次只提交这两个文件(提交信息形如 `📝 docs: #<工单号> 设计文档` / `📝 docs: #<工单号> 实施计划`),不要为此新建或切换分支。创建后追加对应 marker: ``` opencli spx issue marker --issue <工单号> --type spec --value .claude/specs/.md @@ -41,15 +41,15 @@ opencli spx issue marker --issue <工单号> --type plan --value .claude/plans/< - 不要切换分支,包括 `git checkout` / `git switch` - 除设计文档 / 计划文件外不要修改任何文件 - 不要创建 PR -- 不要调用 gitea 其他写操作(除上面的 marker 同步) +- 除上面的 marker 同步外,不要对工单、PR 做任何写操作 {{else}} 接下来我要实现下面这样的功能: {{userRequest}} -你的任务:用 spx CLI 创建一个 Gitea 工单。spx 用法参考 `using-spx-cli` skill。 +你的任务:用 spx CLI 创建工单。spx 用法参考 `using-spx-cli` skill。 ## 工单格式 -先检查仓库的 `.gitea/ISSUE_TEMPLATE/` 目录: +先检查仓库的 `.gitea/ISSUE_TEMPLATE/` 和 `.github/ISSUE_TEMPLATE/` 目录: - 有模板(`.md` 或 `.yaml`)→ 严格按模板填 body:标题前缀、章节标题、必填字段都写齐 - 没有模板 → 用普通 markdown 自由写 @@ -77,7 +77,7 @@ spx 返回工单号 + html_url。记下工单号,后续命令用。 - 设计文档:`.claude/specs/.md` - 计划:`.claude/plans/.md` -`` 取工单标题的英文短横线名(如 `app-entity`),两个文件用同一个 stem,文件名里不要带 `spec` / `plan` 字样。两个文件**一律在当前主 worktree(main 分支)创建并提交**(`ecc:spec` 默认不提交,这里要显式提交),每次只提交这两个文件(提交信息形如 `📝 docs: #<工单号> 设计文档` / `📝 docs: #<工单号> 实施计划`);实施 worktree 从 main 当前提交切出,没提交的文件在那边看不到。 +`` 取工单标题的英文短横线名(如 `app-entity`),两个文件用同一个 stem,文件名里不要带 `spec` / `plan` 字样。两个文件**一律在当前主 worktree(仓库默认分支)创建并提交**(`ecc:spec` 默认不提交,这里要显式提交),每次只提交这两个文件(提交信息形如 `📝 docs: #<工单号> 设计文档` / `📝 docs: #<工单号> 实施计划`);实施 worktree 从默认分支当前提交切出,没提交的文件在那边看不到。 **只有**当你真正创建了设计文档或计划文件后才追加对应 marker: diff --git a/vscode/prompts/implement-plan.md b/vscode/prompts/implement-plan.md index 9b04708..bece775 100644 --- a/vscode/prompts/implement-plan.md +++ b/vscode/prompts/implement-plan.md @@ -1,5 +1,15 @@ /ecc:tdd @{{planFile}} -按计划实施 {{issueNumber}} 号工单:具体编码派子代理去做,全程保持测试绿灯。计划里的验证命令只当意图,落地时用仓库自己的 test / lint / typecheck 命令。提 PR 前先自审并修掉严重问题:把 `git diff origin/main...HEAD` 交给 `ecc:code-reviewer` 子代理(`/ecc:code-review` 的本地模式只看未提交改动,提交过就看不到了)。发起 PR 时务必在 PR body 中包含 "Closes #{{issueNumber}}"。 +按计划实施 {{issueNumber}} 号工单:具体编码派子代理去做,全程保持测试绿灯。计划里的验证命令只当意图,落地时用仓库自己的 test / lint / typecheck 命令。 -**严禁合并 PR**:你的职责只到发起 PR 为止,后续审查反馈到了请继续修复并 push,永远不要执行 `tea pulls merge` 或任何合并操作。 +下面的 `` 是 PR 要合进的分支:计划里写明了就用计划里的,没写就用仓库默认分支(`git remote show origin` 输出里的 `HEAD branch`)。 + +提 PR 前先自审并修掉严重问题:`git fetch origin ` 后,把 `git diff origin/...HEAD` 交给 `ecc:code-reviewer` 子代理(`/ecc:code-review` 的本地模式只看未提交改动,提交过就看不到了)。 + +push 当前分支后用 spx 发起 PR。PR 描述写到 `/tmp/pr-{{issueNumber}}.md`,里面**必须**有 `Closes #{{issueNumber}}` 这一行,看板靠它把 PR 关联到工单: + +``` +opencli spx pr create --title "<标题>" --body-file /tmp/pr-{{issueNumber}}.md --head <当前分支> --base +``` + +**严禁合并 PR**:你的职责只到发起 PR 为止,后续审查反馈到了请继续修复并 push,永远不要执行任何合并 PR 的命令或操作。 diff --git a/vscode/prompts/prototype.md b/vscode/prompts/prototype.md index c3c1216..a742082 100644 --- a/vscode/prompts/prototype.md +++ b/vscode/prompts/prototype.md @@ -1,6 +1,6 @@ /ecc:ui-prototyping 给 {{issueNumber}} 号工单画原型。 -先读工单正文,锁定要确认的界面和状态。画法按这个技能来:工单正文已经指定 Figma 插件或 OpenPencil 就用指定的那个;没指定就先问用哪一个,再按技能里对应的做法画。不要改业务代码。 +先用 `opencli spx issue view --issue {{issueNumber}}` 读工单正文,锁定要确认的界面和状态。画法按这个技能来:工单正文已经指定 Figma 插件或 OpenPencil 就用指定的那个;没指定就先问用哪一个,再按技能里对应的做法画。不要改业务代码。 画完把原型源文件的仓库相对路径挂到工单上: diff --git a/vscode/prompts/review.md b/vscode/prompts/review.md index 2c6d2f0..73fe45e 100644 --- a/vscode/prompts/review.md +++ b/vscode/prompts/review.md @@ -1,10 +1,10 @@ 审查这个仓库的 PR #{{prNumber}}。 -用 `tea pulls {{prNumber}}` 看 PR 元信息(标题/描述/分支)。看代码差异用 git(当前目录就是 PR 分支的 worktree):先 `git fetch origin main`,再 `git diff origin/main...HEAD`(概览可加 --stat)。注意 tea 没有 `diff` 子命令,不要尝试 `tea pulls diff`。 +用 `opencli spx pr view --pr {{prNumber}}` 看 PR 元信息(标题、描述、head → base 分支)。看代码差异用 git(当前目录就是 PR 分支的 worktree):`` 是上面查到的目标分支(加 `--json` 时是 `base.branch`),先 `git fetch origin `,再 `git diff origin/...HEAD`(概览可加 --stat)。 ## 审查方式 -ECC 的 `/ecc:review-pr` 和 `/ecc:code-review` 的 PR 模式都走 `gh`,对 Gitea 不可用,不要调。直接把上面的 diff 喂给 ECC 的审查子代理,按改动涉及的语言挑: +直接把上面的 diff 喂给 ECC 的审查子代理,按改动涉及的语言挑: - `ecc:code-reviewer`(必跑) - `ecc:silent-failure-hunter`、`ecc:pr-test-analyzer`(必跑) @@ -39,7 +39,7 @@ opencli spx issue state merge --issue {{issueNumber}} --state-json '{"reviewPass ## 严禁 - 不要在审查意见里建议"合并 PR"或"merge" -- 不要执行 `tea pulls merge` 或任何合并命令 -- 不要 push 到 main / dev 分支 +- 不要执行任何合并 PR 的命令或操作 +- 不要往 PR 的目标分支或其他共享分支 push 合并权完全在用户手上,你的工作只是指出问题或确认通过。 diff --git a/vscode/prompts/test.md b/vscode/prompts/test.md index cb8f5b9..9c61064 100644 --- a/vscode/prompts/test.md +++ b/vscode/prompts/test.md @@ -2,4 +2,4 @@ 验收目标以工单正文为准,不要再问验收哪个。测出问题就停下报告,不要顺手改代码。 -先看下目前有没有合进main 如果已经手动合过了 就发main到测试服验证 如果没合 就发当前pr对应的分支去测试服验证 +先确认 PR 有没有合并(上面给的是 PR 号时用 `opencli spx pr view --pr ` 看):已经合了就把它的目标分支发到测试服验证,没合就把 PR 对应的分支发到测试服验证。 diff --git a/vscode/src/settings/promptUpdate.test.ts b/vscode/src/settings/promptUpdate.test.ts index 4f77d44..eca98bf 100644 --- a/vscode/src/settings/promptUpdate.test.ts +++ b/vscode/src/settings/promptUpdate.test.ts @@ -1,5 +1,10 @@ -import { describe, expect, it } from 'vitest' -import { promptDigest, promptUpdatesToAsk } from './promptUpdatePlan' +import path from 'node:path' +import { describe, expect, it, vi } from 'vitest' +import { PREVIOUS_DEFAULT_REVIEW_PROMPT } from './previousReviewPrompt' +import { PROMPT_UPDATE_FIELDS, promptDigest, promptUpdatesToAsk } from './promptUpdatePlan' +import { readDefaultPrompt } from './store' + +const EXTENSION_ROOT = path.resolve(__dirname, '../..') describe('promptUpdatesToAsk', () => { it('和自带的不一样就问', () => { @@ -36,3 +41,40 @@ describe('promptUpdatesToAsk', () => { })).toEqual([]) }) }) + +describe('自带提示词不绑定代码托管平台', () => { + // `.gitea/` `.github/` 是工单模板目录,不算点名平台。 + const FORGE_TOOLS = /(? [field.file]))('prompts/%s.md 不提 tea / gh / Gitea,也不写死 origin/main', (file) => { + const text = readDefaultPrompt(EXTENSION_ROOT, file) + expect(text).not.toMatch(FORGE_TOOLS) + expect(text).not.toContain('origin/main') + }) + + it.each(PROMPT_UPDATE_FIELDS.map(field => [field.file]))('%s 的内联兜底同样不提', (file) => { + vi.spyOn(console, 'warn').mockImplementation(() => {}) + const text = readDefaultPrompt(path.join(EXTENSION_ROOT, 'no-such-dir'), file) + expect(text).not.toMatch(FORGE_TOOLS) + expect(text).not.toContain('origin/main') + }) + + it('查工单、查 PR、发起 PR 都走 spx,PR 描述必须关联工单', () => { + expect(readDefaultPrompt(EXTENSION_ROOT, 'brainstorm')).toContain('spx issue view') + expect(readDefaultPrompt(EXTENSION_ROOT, 'review')).toContain('spx pr view') + const implement = readDefaultPrompt(EXTENSION_ROOT, 'implement-plan') + expect(implement).toContain('spx pr create') + expect(implement).toContain('Closes #{{issueNumber}}') + }) + + it('设置里存着旧版自带审查提示词的,激活时会被问要不要换成新版', () => { + const next = readDefaultPrompt(EXTENSION_ROOT, 'review') + const out = promptUpdatesToAsk({ + stored: { reviewPrompt: PREVIOUS_DEFAULT_REVIEW_PROMPT }, + defaults: { reviewPrompt: next }, + decided: { reviewPrompt: promptDigest(PREVIOUS_DEFAULT_REVIEW_PROMPT) }, + }) + expect(out.map(item => item.key)).toEqual(['reviewPrompt']) + expect(out[0].next).toBe(next) + }) +}) diff --git a/vscode/src/settings/store.ts b/vscode/src/settings/store.ts index c882e18..389259f 100644 --- a/vscode/src/settings/store.ts +++ b/vscode/src/settings/store.ts @@ -29,20 +29,20 @@ import { planPromptMigration, planReviewPromptMigration } from './promptMigratio * the extension usable if the file is missing/corrupt. */ const FALLBACK_BRAINSTORM_PROMPT = `{{#if issueNumber}} -/ecc:grilling 讨论下 {{issueNumber}} 号工单。 +/ecc:grilling 讨论下 {{issueNumber}} 号工单,先用 spx issue view 看工单。 {{#if prototypeFile}} 工单已有原型插件 {{prototypeFile}},先读它;原型要改就 ListAgents 找到 issue-{{issueNumber}}-原型 会话{{#if prototypeSessionId}}(id {{prototypeSessionId}}){{/if}}并 SendMessage 给它,不要派子代理、不要自己动插件代码。 {{/if}} -达成共识后用 ecc:spec 写 .claude/specs/.md,我确认后用 ecc:plan 出 .claude/plans/.md,两个文件在 main 上提交并用 spx issue marker 同步 marker。不要 git checkout / 不要写代码 / 不要建 PR。 +达成共识后用 ecc:spec 写 .claude/specs/.md,我确认后用 ecc:plan 出 .claude/plans/.md,两个文件在仓库默认分支上提交并用 spx issue marker 同步 marker。不要 git checkout / 不要写代码 / 不要建 PR。 {{else}} -我现在有这样一个需求 {{userRequest}},你用 spx 命令创建 gitea 工单。工单 body 末尾必须包含 。创建完工单立即停下汇报,不要擅自实施。 +我现在有这样一个需求 {{userRequest}},你用 spx 命令创建工单。工单 body 末尾必须包含 。创建完工单立即停下汇报,不要擅自实施。 {{/if}}` -const FALLBACK_IMPLEMENT_PLAN_PROMPT = `/ecc:tdd @{{planFile}} 按计划实施,编码派子代理,发起 PR 时在 body 中包含 "Closes #{{issueNumber}}"。严禁合并 PR。` +const FALLBACK_IMPLEMENT_PLAN_PROMPT = `/ecc:tdd @{{planFile}} 按计划实施,编码派子代理,用 spx pr create 发起 PR,body 中必须包含 "Closes #{{issueNumber}}"。严禁合并 PR。` const FALLBACK_TEST_PROMPT = `/pr-acceptance-testing 验收 {{issueNumber}} 号工单({{prRef}})。验收目标以工单正文为准,不要再问验收哪个。` -const FALLBACK_REVIEW_PROMPT = `用 tea 拿到 #{{prNumber}} PR,diff 交给 ecc:code-reviewer 子代理审查。审查意见用 spx pr review-comment 发评论,body 第一行写 。` +const FALLBACK_REVIEW_PROMPT = `用 spx pr view 查 #{{prNumber}} PR 的目标分支 ,把 git diff origin/...HEAD 交给 ecc:code-reviewer 子代理审查。审查意见用 spx pr review-comment 发评论。严禁合并 PR。` const FALLBACK_PROTOTYPE_PROMPT = `/ecc:figma-plugin-prototyping 给 {{issueNumber}} 号工单画原型:先读工单正文锁定要画的界面和状态,再写本地 Figma 插件把画板和点击流做出来。画完汇报插件路径和怎么导入,不要改业务代码。