✨ 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:
1 parent
3fff796a61
commit
b62e58d739
27 files changed
+760
-50
No files matched your search
@@ -1,15 +1,17 @@
|
||||
export type ClaudeSessionKind = 'brainstorm' | 'implement' | 'test'
|
||||
export type ClaudeSessionKind = 'brainstorm' | 'implement' | 'test' | 'prototype'
|
||||
|
||||
export const CLAUDE_SESSION_FIELDS = [
|
||||
{ field: 'sessionId', kind: 'brainstorm' },
|
||||
{ field: 'implementSessionId', kind: 'implement' },
|
||||
{ field: 'testSessionId', kind: 'test' },
|
||||
] as const satisfies ReadonlyArray<{ field: 'sessionId' | 'implementSessionId' | 'testSessionId', kind: ClaudeSessionKind }>
|
||||
{ field: 'prototypeSessionId', kind: 'prototype' },
|
||||
] as const satisfies ReadonlyArray<{ field: 'sessionId' | 'implementSessionId' | 'testSessionId' | 'prototypeSessionId', kind: ClaudeSessionKind }>
|
||||
|
||||
export interface HandoffSessions {
|
||||
sessionId?: string
|
||||
implementSessionId?: string
|
||||
testSessionId?: string
|
||||
prototypeSessionId?: string
|
||||
reviewSessionId?: string
|
||||
}
|
||||
|
||||
@@ -17,6 +19,7 @@ export interface HandoffProfiles {
|
||||
profilePath?: string
|
||||
brainstormProfilePath?: string
|
||||
testProfilePath?: string
|
||||
prototypeProfilePath?: string
|
||||
}
|
||||
|
||||
export interface HandoffManifest {
|
||||
@@ -38,7 +41,7 @@ export function handoffAttachmentName(issueNumber: number): string {
|
||||
return `spx-handoff-issue-${issueNumber}.tgz`
|
||||
}
|
||||
|
||||
const KINDS: ReadonlySet<string> = new Set<ClaudeSessionKind>(['brainstorm', 'implement', 'test'])
|
||||
const KINDS: ReadonlySet<string> = new Set<ClaudeSessionKind>(['brainstorm', 'implement', 'test', 'prototype'])
|
||||
|
||||
// Claude / Codex 会话 id 都是 UUID;顺手挡掉路径穿越(如 `../x`)之类的伪造条目。
|
||||
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
||||
@@ -80,13 +83,13 @@ export function parseHandoffManifest(json: string, expectedIssue: number): Hando
|
||||
return { id, relPath }
|
||||
})
|
||||
const sessions: HandoffSessions = {}
|
||||
for (const k of ['sessionId', 'implementSessionId', 'testSessionId', 'reviewSessionId'] as const) {
|
||||
for (const k of ['sessionId', 'implementSessionId', 'testSessionId', 'prototypeSessionId', 'reviewSessionId'] as const) {
|
||||
const v = optString(sessionsRaw[k])
|
||||
if (v)
|
||||
sessions[k] = v
|
||||
}
|
||||
const profiles: HandoffProfiles = {}
|
||||
for (const k of ['profilePath', 'brainstormProfilePath', 'testProfilePath'] as const) {
|
||||
for (const k of ['profilePath', 'brainstormProfilePath', 'testProfilePath', 'prototypeProfilePath'] as const) {
|
||||
const v = optString(profilesRaw[k])
|
||||
if (v)
|
||||
profiles[k] = v
|
||||
|
||||
Reference in new issue
Block a user