✨ feat(vscode): 新增第五种工单会话「原型会话」

照测试会话那条链路补一份 prototype:

- 消息与路由:session/start-prototype、session/resume-prototype、
  issue/update-prototype-profile-path,都进只读门禁
- 会话:handleStartPrototypeSession / handleResumePrototypeSession,
  终端名 issue-N-原型;cwd 有 worktree 用 worktree、没有退主仓库根
  (原 resolveTestSessionCwd 改名 resolveWorktreeOrRootCwd 两种会话共用)
- 不要求有 PR,任何阶段都能起;前置工单锁仍然拦
- 提示词:新增 prompts/prototype.md,设置里可改,占位符 {issueNumber}
- profile:工单级 prototypeProfilePath > 设置里的原型默认 profile >
  内置默认,与其它会话互不回退
- 状态字段 prototypeSessionId / prototypeProfilePath / prototypeTabOpen
  贯通 gitea、youtrack、本机 state 与移交包
- 详情面板加「原型会话id」「原型配置文件」两行,设置面板加对应两项

Claude-Session: https://claude.ai/code/session_01Kgmb1LvrPmFX3NoUDB4zZC
This commit is contained in:
cruldra committed 2026-09-14 10:20:30 +08:00
1 parent 3fff796a61
commit b62e58d739
27 files changed
+760 -50

No files matched your search

@@ -26,6 +26,7 @@ interface SubmitValues {
autoReview: boolean
reviewPrompt: string
testPrompt: string
prototypePrompt: string
devBranch: string
releaseBranchPrefix: string
jenkinsJob: string
@@ -41,6 +42,7 @@ interface SubmitValues {
defaultBrainstormProfilePath: string
defaultImplementProfilePath: string
defaultTestProfilePath: string
defaultPrototypeProfilePath: string
conflictResolutionProfilePath: string
commitProfilePath: string
prDiffSummaryProfilePath: string
@@ -80,6 +82,7 @@ export interface SettingsModalProps {
initialAutoReview: boolean
initialReviewPrompt: string
initialTestPrompt: string
initialPrototypePrompt: string
initialDevBranch: string
initialReleaseBranchPrefix: string
initialJenkinsJob: string
@@ -95,6 +98,7 @@ export interface SettingsModalProps {
initialDefaultBrainstormProfilePath: string
initialDefaultImplementProfilePath: string
initialDefaultTestProfilePath: string
initialDefaultPrototypeProfilePath: string
initialConflictResolutionProfilePath: string
initialCommitProfilePath: string
initialPrDiffSummaryProfilePath: string
@@ -170,6 +174,7 @@ export function SettingsModal({
initialAutoReview,
initialReviewPrompt,
initialTestPrompt,
initialPrototypePrompt,
initialDevBranch,
initialReleaseBranchPrefix,
initialJenkinsJob,
@@ -185,6 +190,7 @@ export function SettingsModal({
initialDefaultBrainstormProfilePath,
initialDefaultImplementProfilePath,
initialDefaultTestProfilePath,
initialDefaultPrototypeProfilePath,
initialConflictResolutionProfilePath,
initialCommitProfilePath,
initialPrDiffSummaryProfilePath,
@@ -212,6 +218,7 @@ export function SettingsModal({
const [autoReview, setAutoReview] = useState(initialAutoReview)
const [reviewPrompt, setReviewPrompt] = useState(initialReviewPrompt)
const [testPrompt, setTestPrompt] = useState(initialTestPrompt)
const [prototypePrompt, setPrototypePrompt] = useState(initialPrototypePrompt)
const [devBranch, setDevBranch] = useState(initialDevBranch)
const [releaseBranchPrefix, setReleaseBranchPrefix] = useState(initialReleaseBranchPrefix)
const [jenkinsJob, setJenkinsJob] = useState(initialJenkinsJob)
@@ -227,6 +234,7 @@ export function SettingsModal({
const [defaultBrainstormProfilePath, setDefaultBrainstormProfilePath] = useState(initialDefaultBrainstormProfilePath)
const [defaultImplementProfilePath, setDefaultImplementProfilePath] = useState(initialDefaultImplementProfilePath)
const [defaultTestProfilePath, setDefaultTestProfilePath] = useState(initialDefaultTestProfilePath)
const [defaultPrototypeProfilePath, setDefaultPrototypeProfilePath] = useState(initialDefaultPrototypeProfilePath)
const [conflictResolutionProfilePath, setConflictResolutionProfilePath] = useState(initialConflictResolutionProfilePath)
const [commitProfilePath, setCommitProfilePath] = useState(initialCommitProfilePath)
const [prDiffSummaryProfilePath, setPrDiffSummaryProfilePath] = useState(initialPrDiffSummaryProfilePath)
@@ -256,6 +264,7 @@ export function SettingsModal({
setAutoReview(initialAutoReview)
setReviewPrompt(initialReviewPrompt)
setTestPrompt(initialTestPrompt)
setPrototypePrompt(initialPrototypePrompt)
setDevBranch(initialDevBranch)
setReleaseBranchPrefix(initialReleaseBranchPrefix)
setJenkinsJob(initialJenkinsJob)
@@ -271,6 +280,7 @@ export function SettingsModal({
setDefaultBrainstormProfilePath(initialDefaultBrainstormProfilePath)
setDefaultImplementProfilePath(initialDefaultImplementProfilePath)
setDefaultTestProfilePath(initialDefaultTestProfilePath)
setDefaultPrototypeProfilePath(initialDefaultPrototypeProfilePath)
setConflictResolutionProfilePath(initialConflictResolutionProfilePath)
setCommitProfilePath(initialCommitProfilePath)
setPrDiffSummaryProfilePath(initialPrDiffSummaryProfilePath)
@@ -348,6 +358,7 @@ export function SettingsModal({
autoReview,
reviewPrompt,
testPrompt,
prototypePrompt,
devBranch: devBranch.trim(),
releaseBranchPrefix: releaseBranchPrefix.trim(),
jenkinsJob: jenkinsJob.trim(),
@@ -363,10 +374,11 @@ export function SettingsModal({
implTabPreCreateScript: implTabPreCreateScript.trim(),
implTabPostCloseScript: implTabPostCloseScript.trim(),
splitNewTerminals,
// 三个会话默认 profile:空串 = 落到 DEFAULT_PROFILE_PATH
// 四个会话默认 profile:空串 = 落到 DEFAULT_PROFILE_PATH
defaultBrainstormProfilePath: defaultBrainstormProfilePath.trim(),
defaultImplementProfilePath: defaultImplementProfilePath.trim(),
defaultTestProfilePath: defaultTestProfilePath.trim(),
defaultPrototypeProfilePath: defaultPrototypeProfilePath.trim(),
// 冲突解决 profile:空串 = 用 DEFAULT_PROFILE_PATH
conflictResolutionProfilePath: conflictResolutionProfilePath.trim(),
// 提交代码 profile:空串 = 未配置 → 提交严格失败
@@ -625,6 +637,30 @@ export function SettingsModal({
/>
</Field>
<Field
label="原型默认配置文件"
hint={(
<>
原型会话默认用此 profile;工单详情面板里的「原型配置文件」优先级更高。留空用 official。
</>
)}
>
<SelectMenu
value={defaultPrototypeProfilePath}
onChange={setDefaultPrototypeProfilePath}
variant="input"
className={inputClass}
options={[
{ value: '', label: '(默认)' },
...profiles.map(p => ({ value: p.path, label: p.name })),
...(defaultPrototypeProfilePath
&& !profiles.some(p => p.path === defaultPrototypeProfilePath)
? [{ value: defaultPrototypeProfilePath, label: `自定义:${defaultPrototypeProfilePath}` }]
: []),
]}
/>
</Field>
<Field
label="冲突解决配置文件"
hint={(
@@ -1028,6 +1064,23 @@ export function SettingsModal({
className={`${inputClass} resize-y font-mono`}
/>
</Field>
<Field
label="原型提示词"
hint={(
<>
可用占位符:
<code>{'{issueNumber}'}</code>
</>
)}
>
<textarea
rows={4}
value={prototypePrompt}
onChange={e => setPrototypePrompt(e.target.value)}
className={`${inputClass} resize-y font-mono`}
/>
</Field>
</>
)}