@xdevops/issue-auto-finish 1.0.2 → 1.0.4
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/dist/KnowledgeAnalyzer-EZSJT2MJ.js +13 -0
- package/dist/KnowledgeAnalyzer-EZSJT2MJ.js.map +1 -0
- package/dist/KnowledgeStore-4ROC6F56.js +10 -0
- package/dist/KnowledgeStore-4ROC6F56.js.map +1 -0
- package/dist/ai-runner/AIRunner.d.ts +2 -0
- package/dist/ai-runner/AIRunner.d.ts.map +1 -1
- package/dist/ai-runner/BaseAIRunner.d.ts +9 -0
- package/dist/ai-runner/BaseAIRunner.d.ts.map +1 -1
- package/dist/ai-runner-RGAJPOOW.js +16 -0
- package/dist/ai-runner-RGAJPOOW.js.map +1 -0
- package/dist/analyze-ONQDTYCN.js +72 -0
- package/dist/analyze-ONQDTYCN.js.map +1 -0
- package/dist/chunk-3JUHZGX5.js +171 -0
- package/dist/chunk-3JUHZGX5.js.map +1 -0
- package/dist/chunk-5JYCGAU3.js +318 -0
- package/dist/chunk-5JYCGAU3.js.map +1 -0
- package/dist/chunk-5VUB3UUK.js +643 -0
- package/dist/chunk-5VUB3UUK.js.map +1 -0
- package/dist/{chunk-OWVT3Z34.js → chunk-JFYAXNNS.js} +121 -31
- package/dist/chunk-JFYAXNNS.js.map +1 -0
- package/dist/chunk-MH6LHFPB.js +188 -0
- package/dist/chunk-MH6LHFPB.js.map +1 -0
- package/dist/{chunk-TBIEB3JY.js → chunk-N5YK6YVI.js} +592 -767
- package/dist/chunk-N5YK6YVI.js.map +1 -0
- package/dist/{chunk-RIUI4ROA.js → chunk-PECYMYAK.js} +2 -2
- package/dist/{chunk-I3T573SU.js → chunk-PTIL5AY2.js} +65 -2
- package/dist/chunk-PTIL5AY2.js.map +1 -0
- package/dist/chunk-SWG2Y7YX.js +410 -0
- package/dist/chunk-SWG2Y7YX.js.map +1 -0
- package/dist/chunk-TZ6C7HL5.js +59 -0
- package/dist/chunk-TZ6C7HL5.js.map +1 -0
- package/dist/{chunk-IDUKWCC2.js → chunk-VFQYIC6L.js} +1151 -80
- package/dist/chunk-VFQYIC6L.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +8 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli.js +67 -3
- package/dist/cli.js.map +1 -1
- package/dist/clients/GongfengClient.d.ts +5 -0
- package/dist/clients/GongfengClient.d.ts.map +1 -1
- package/dist/config-6GFBDMGD.js +7 -0
- package/dist/config-6GFBDMGD.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/{doctor-B26Q6JWI.js → doctor-ZPGIBA5N.js} +3 -3
- package/dist/events/EventBus.d.ts +1 -1
- package/dist/events/EventBus.d.ts.map +1 -1
- package/dist/git/GitOperations.d.ts +12 -0
- package/dist/git/GitOperations.d.ts.map +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -5
- package/dist/{init-L3VIWCOV.js → init-QDTII4SP.js} +10 -5
- package/dist/init-QDTII4SP.js.map +1 -0
- package/dist/knowledge/KnowledgeAnalyzer.d.ts +31 -0
- package/dist/knowledge/KnowledgeAnalyzer.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeDefaults.d.ts +7 -0
- package/dist/knowledge/KnowledgeDefaults.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeEntry.d.ts +30 -0
- package/dist/knowledge/KnowledgeEntry.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeLoader.d.ts +18 -0
- package/dist/knowledge/KnowledgeLoader.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeStore.d.ts +35 -0
- package/dist/knowledge/KnowledgeStore.d.ts.map +1 -0
- package/dist/knowledge/ProjectKnowledge.d.ts +79 -0
- package/dist/knowledge/ProjectKnowledge.d.ts.map +1 -0
- package/dist/knowledge/analyze-prompt.d.ts +2 -0
- package/dist/knowledge/analyze-prompt.d.ts.map +1 -0
- package/dist/knowledge/importers/GongfengExtractor.d.ts +27 -0
- package/dist/knowledge/importers/GongfengExtractor.d.ts.map +1 -0
- package/dist/knowledge/importers/IwikiImporter.d.ts +21 -0
- package/dist/knowledge/importers/IwikiImporter.d.ts.map +1 -0
- package/dist/knowledge/index.d.ts +12 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/lib.js +19 -10
- package/dist/orchestrator/PipelineOrchestrator.d.ts +5 -1
- package/dist/orchestrator/PipelineOrchestrator.d.ts.map +1 -1
- package/dist/phases/BasePhase.d.ts.map +1 -1
- package/dist/poller/IssuePoller.d.ts +5 -0
- package/dist/poller/IssuePoller.d.ts.map +1 -1
- package/dist/prompts/chat-templates.d.ts +4 -0
- package/dist/prompts/chat-templates.d.ts.map +1 -0
- package/dist/prompts/templates.d.ts +11 -0
- package/dist/prompts/templates.d.ts.map +1 -1
- package/dist/rules/RuleResolver.d.ts +4 -0
- package/dist/rules/RuleResolver.d.ts.map +1 -1
- package/dist/run.js +11 -5
- package/dist/run.js.map +1 -1
- package/dist/services/ChatService.d.ts +39 -0
- package/dist/services/ChatService.d.ts.map +1 -0
- package/dist/shutdown/ShutdownSignal.d.ts +3 -0
- package/dist/shutdown/ShutdownSignal.d.ts.map +1 -0
- package/dist/{start-TVN4SS6E.js → start-EDOZC5WL.js} +1 -1
- package/dist/tracker/IssueState.d.ts +1 -0
- package/dist/tracker/IssueState.d.ts.map +1 -1
- package/dist/tracker/IssueTracker.d.ts +2 -0
- package/dist/tracker/IssueTracker.d.ts.map +1 -1
- package/dist/updater/AutoUpdater.d.ts +33 -0
- package/dist/updater/AutoUpdater.d.ts.map +1 -0
- package/dist/updater/UpdateExecutor.d.ts +7 -0
- package/dist/updater/UpdateExecutor.d.ts.map +1 -0
- package/dist/updater/VersionChecker.d.ts +22 -0
- package/dist/updater/VersionChecker.d.ts.map +1 -0
- package/dist/web/WebServer.d.ts +4 -0
- package/dist/web/WebServer.d.ts.map +1 -1
- package/dist/web/routes/api.d.ts +4 -0
- package/dist/web/routes/api.d.ts.map +1 -1
- package/dist/web/routes/chat.d.ts +7 -0
- package/dist/web/routes/chat.d.ts.map +1 -0
- package/dist/web/routes/knowledge.d.ts +13 -0
- package/dist/web/routes/knowledge.d.ts.map +1 -0
- package/dist/web/routes/setup.d.ts.map +1 -1
- package/dist/webhook/CommandExecutor.d.ts +4 -0
- package/dist/webhook/CommandExecutor.d.ts.map +1 -1
- package/dist/webhook/CommandParser.d.ts +2 -2
- package/dist/webhook/CommandParser.d.ts.map +1 -1
- package/dist/webhook/WebhookHandler.d.ts +8 -0
- package/dist/webhook/WebhookHandler.d.ts.map +1 -1
- package/dist/webhook/WebhookServer.d.ts +2 -0
- package/dist/webhook/WebhookServer.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/web/frontend/dist/assets/index-AcJ0lPIv.js +67 -0
- package/src/web/frontend/dist/assets/index-BbRt5BAr.css +1 -0
- package/src/web/frontend/dist/index.html +2 -2
- package/dist/chunk-I3T573SU.js.map +0 -1
- package/dist/chunk-IDUKWCC2.js.map +0 -1
- package/dist/chunk-OWVT3Z34.js.map +0 -1
- package/dist/chunk-TBIEB3JY.js.map +0 -1
- package/dist/init-L3VIWCOV.js.map +0 -1
- package/src/web/frontend/dist/assets/index-CQdlU9PE.js +0 -65
- package/src/web/frontend/dist/assets/index-CgMEkyZJ.css +0 -1
- /package/dist/{chunk-RIUI4ROA.js.map → chunk-PECYMYAK.js.map} +0 -0
- /package/dist/{doctor-B26Q6JWI.js.map → doctor-ZPGIBA5N.js.map} +0 -0
- /package/dist/{start-TVN4SS6E.js.map → start-EDOZC5WL.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/logger.ts","../src/clients/GongfengClient.ts","../src/git/GitOperations.ts","../src/ai-runner/BaseAIRunner.ts","../src/ai-runner/ClaudeInternalRunner.ts","../src/ai-runner/CodebuddyRunner.ts","../src/ai-runner/CursorAgentRunner.ts","../src/ai-runner/index.ts","../src/pipeline/PipelineDefinition.ts","../src/events/EventBus.ts","../src/tracker/IssueTracker.ts","../src/persistence/PlanPersistence.ts","../src/phases/BasePhase.ts","../src/prompts/templates.ts","../src/rules/RuleResolver.ts","../src/notesync/NoteSyncSettings.ts","../src/phases/AnalysisPhase.ts","../src/phases/DesignPhase.ts","../src/phases/ImplementPhase.ts","../src/phases/VerifyPhase.ts","../src/e2e/E2eSettings.ts","../src/phases/PlanPhase.ts","../src/phases/BuildPhase.ts","../src/phases/PhaseFactory.ts","../src/utils/AsyncMutex.ts","../src/orchestrator/PipelineOrchestrator.ts","../src/utils/MergeRequestHelper.ts","../src/deploy/PortAllocator.ts","../src/deploy/DevServerManager.ts","../src/e2e/ScreenshotCollector.ts","../src/e2e/ScreenshotPublisher.ts","../src/services/BrainstormService.ts","../src/prompts/brainstorm-templates.ts"],"sourcesContent":["import { config as loadDotenv } from 'dotenv';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nfunction resolveEnvPath(): string {\n if (process.env.IAF_CONFIG_PATH) return process.env.IAF_CONFIG_PATH;\n\n const localEnv = path.resolve(__dirname, '../.env');\n if (fs.existsSync(localEnv)) return localEnv;\n\n const cwdEnv = path.resolve(process.cwd(), '.env');\n if (fs.existsSync(cwdEnv)) return cwdEnv;\n\n const globalEnv = path.join(os.homedir(), '.issue-auto-finish', '.env');\n if (fs.existsSync(globalEnv)) return globalEnv;\n\n return localEnv;\n}\n\nlet _dotenvLoaded = false;\nfunction ensureDotenvLoaded(): void {\n if (_dotenvLoaded) return;\n _dotenvLoaded = true;\n loadDotenv({ path: resolveEnvPath() });\n}\n\nexport interface Config {\n gongfeng: {\n apiUrl: string;\n privateToken: string;\n projectPath: string;\n };\n project: {\n workDir: string;\n gitRootDir: string;\n baseBranch: string;\n branchPrefix: string;\n worktreeBaseDir: string;\n projectSubDir: string;\n };\n /** @deprecated Use ai instead */\n claude?: {\n binary: string;\n phaseTimeoutMs: number;\n nvmNodeVersion: string;\n };\n ai: {\n mode: 'claude-internal' | 'cursor-agent' | 'codebuddy';\n binary: string;\n phaseTimeoutMs: number;\n nvmNodeVersion: string;\n model?: string;\n };\n poll: {\n /** @deprecated Use discoveryIntervalMs instead */\n intervalMs: number;\n discoveryIntervalMs: number;\n driveIntervalMs: number;\n maxRetries: number;\n maxConcurrent: number;\n };\n pipeline: {\n mode: 'auto' | 'classic' | 'plan-mode';\n };\n review: {\n enabled: boolean;\n autoApproveLabels: string[];\n };\n web: {\n enabled: boolean;\n port: number;\n frontendDistDir: string;\n };\n issueNoteSync: {\n enabled: boolean;\n webBaseUrl: string;\n };\n webhook: {\n enabled: boolean;\n port: number;\n secret: string;\n /** Use LLM to parse natural-language commands when regex fails */\n llmFallback: boolean;\n /** Binary for LLM intent recognition (defaults to claude-internal, independent of AI_RUNNER_MODE) */\n llmBinary: string;\n };\n e2e: {\n enabled: boolean;\n baseUrl: string;\n backendUrl: string;\n authCookies: string;\n backendPortBase: number;\n frontendPortBase: number;\n };\n preview: {\n enabled: boolean;\n host: string;\n ttlMs: number;\n keepAfterComplete: boolean;\n };\n brainstorm: {\n enabled: boolean;\n maxRefinementRounds: number;\n timeoutMs: number;\n generator: BrainstormAgentConfig;\n reviewer: BrainstormAgentConfig;\n };\n locale: 'zh-CN' | 'en';\n}\n\nexport type AIRunnerMode = 'claude-internal' | 'cursor-agent' | 'codebuddy';\n\nexport interface BrainstormAgentConfig {\n mode: AIRunnerMode;\n binary: string;\n nvmNodeVersion: string;\n model?: string;\n}\n\nconst DEFAULT_AI_MODEL = 'Claude-4.6-Opus';\n\nfunction requireEnv(key: string): string {\n const val = process.env[key];\n if (!val) {\n throw new Error(`Missing required environment variable: ${key}`);\n }\n return val;\n}\n\nfunction optionalEnv(key: string, defaultValue: string): string {\n return process.env[key] || defaultValue;\n}\n\nexport function loadConfig(): Config {\n ensureDotenvLoaded();\n return {\n gongfeng: {\n apiUrl: requireEnv('GONGFENG_API_URL'),\n privateToken: requireEnv('GONGFENG_PRIVATE_TOKEN'),\n projectPath: requireEnv('GONGFENG_PROJECT_PATH'),\n },\n project: {\n workDir: requireEnv('PROJECT_WORK_DIR'),\n gitRootDir: optionalEnv('GIT_ROOT_DIR', requireEnv('PROJECT_WORK_DIR')),\n baseBranch: optionalEnv('BASE_BRANCH', 'master'),\n branchPrefix: optionalEnv('BRANCH_PREFIX', 'feat/issue'),\n worktreeBaseDir: optionalEnv('WORKTREE_BASE_DIR', ''),\n projectSubDir: optionalEnv('PROJECT_SUBDIR', ''),\n },\n claude: {\n binary: optionalEnv('CLAUDE_BINARY', 'claude-internal'),\n phaseTimeoutMs: parseInt(optionalEnv('CLAUDE_PHASE_TIMEOUT_MS', '1800000'), 10),\n nvmNodeVersion: optionalEnv('NVM_NODE_VERSION', '20'),\n },\n ai: buildAIConfig(),\n poll: {\n intervalMs: parseInt(optionalEnv('POLL_INTERVAL_MS', '60000'), 10),\n discoveryIntervalMs: parseInt(\n optionalEnv('POLL_DISCOVERY_INTERVAL_MS', optionalEnv('POLL_INTERVAL_MS', '60000')),\n 10,\n ),\n driveIntervalMs: parseInt(optionalEnv('POLL_DRIVE_INTERVAL_MS', '15000'), 10),\n maxRetries: parseInt(optionalEnv('MAX_RETRIES', '3'), 10),\n maxConcurrent: parseInt(optionalEnv('MAX_CONCURRENT_ISSUES', '3'), 10),\n },\n pipeline: {\n mode: optionalEnv('PIPELINE_MODE', 'auto') as 'auto' | 'classic' | 'plan-mode',\n },\n review: {\n enabled: optionalEnv('REVIEW_ENABLED', 'true') === 'true',\n autoApproveLabels: optionalEnv('REVIEW_AUTO_APPROVE_LABELS', '')\n .split(',').map(s => s.trim()).filter(Boolean),\n },\n web: {\n enabled: optionalEnv('WEB_ENABLED', 'true') === 'true',\n port: parseInt(optionalEnv('WEB_PORT', '3000'), 10),\n frontendDistDir: optionalEnv(\n 'FRONTEND_DIST_DIR',\n path.resolve(process.cwd(), 'src/web/frontend/dist'),\n ),\n },\n issueNoteSync: {\n enabled: optionalEnv('ISSUE_NOTE_SYNC_ENABLED', 'true') === 'true',\n webBaseUrl: optionalEnv(\n 'WEB_BASE_URL',\n `http://localhost:${optionalEnv('WEB_PORT', '3000')}`,\n ),\n },\n webhook: {\n enabled: optionalEnv('WEBHOOK_ENABLED', 'false') === 'true',\n port: parseInt(optionalEnv('WEBHOOK_PORT', '8081'), 10),\n secret: optionalEnv('WEBHOOK_SECRET', ''),\n llmFallback: optionalEnv('WEBHOOK_LLM_FALLBACK', 'true') === 'true',\n llmBinary: optionalEnv('WEBHOOK_LLM_BINARY', 'claude-internal'),\n },\n e2e: {\n enabled: optionalEnv('E2E_UI_ENABLED', 'false') === 'true',\n baseUrl: optionalEnv('E2E_BASE_URL', 'https://localhost:8890'),\n backendUrl: optionalEnv('E2E_BACKEND_URL', 'http://127.0.0.1:3000'),\n authCookies: optionalEnv('E2E_AUTH_COOKIES', '[]'),\n backendPortBase: parseInt(optionalEnv('E2E_BACKEND_PORT_BASE', '4000'), 10),\n frontendPortBase: parseInt(optionalEnv('E2E_FRONTEND_PORT_BASE', '9000'), 10),\n },\n preview: {\n enabled: optionalEnv('PREVIEW_ENABLED', 'false') === 'true',\n host: optionalEnv('PREVIEW_HOST', ''),\n ttlMs: parseInt(optionalEnv('PREVIEW_TTL_MS', String(24 * 60 * 60 * 1000)), 10),\n keepAfterComplete: optionalEnv('PREVIEW_KEEP_AFTER_COMPLETE', 'true') === 'true',\n },\n brainstorm: {\n enabled: optionalEnv('BRAINSTORM_ENABLED', 'true') === 'true',\n maxRefinementRounds: parseInt(optionalEnv('BRAINSTORM_MAX_ROUNDS', '5'), 10),\n timeoutMs: parseInt(optionalEnv('BRAINSTORM_TIMEOUT_MS', '600000'), 10),\n generator: buildBrainstormAgentConfig('GENERATOR'),\n reviewer: buildBrainstormAgentConfig('REVIEWER'),\n },\n locale: (optionalEnv('LOCALE', 'zh-CN') === 'en' ? 'en' : 'zh-CN') as 'zh-CN' | 'en',\n };\n}\n\nfunction resolveAIRunnerMode(raw: string): AIRunnerMode {\n if (raw === 'cursor-agent') return 'cursor-agent';\n if (raw === 'codebuddy') return 'codebuddy';\n return 'claude-internal';\n}\n\nfunction resolveAIBinary(mode: AIRunnerMode): string {\n switch (mode) {\n case 'cursor-agent':\n return optionalEnv('CURSOR_BINARY', 'cursor');\n case 'codebuddy':\n return optionalEnv('CODEBUDDY_BINARY', 'codebuddy');\n default:\n return optionalEnv('CLAUDE_BINARY', 'claude-internal');\n }\n}\n\nfunction buildAIConfig(): Config['ai'] {\n const mode = resolveAIRunnerMode(optionalEnv('AI_RUNNER_MODE', 'claude-internal'));\n return {\n mode,\n binary: resolveAIBinary(mode),\n phaseTimeoutMs: parseInt(optionalEnv('CLAUDE_PHASE_TIMEOUT_MS', '1800000'), 10),\n nvmNodeVersion: optionalEnv('NVM_NODE_VERSION', '20'),\n model: optionalEnv('AI_MODEL', DEFAULT_AI_MODEL),\n };\n}\n\nfunction buildBrainstormAgentConfig(role: 'GENERATOR' | 'REVIEWER'): BrainstormAgentConfig {\n const globalMode = optionalEnv('AI_RUNNER_MODE', 'claude-internal');\n const roleMode = optionalEnv(`BRAINSTORM_${role}_MODE`, globalMode);\n const mode = resolveAIRunnerMode(roleMode);\n\n return {\n mode,\n binary: optionalEnv(`BRAINSTORM_${role}_BINARY`, resolveAIBinary(mode)),\n nvmNodeVersion: optionalEnv('NVM_NODE_VERSION', '20'),\n model: process.env[`BRAINSTORM_${role}_MODEL`] || optionalEnv('AI_MODEL', DEFAULT_AI_MODEL),\n };\n}\n","type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nclass Logger {\n private level: LogLevel = 'info';\n private context?: string;\n\n constructor(context?: string) {\n this.context = context;\n const envLevel = process.env.LOG_LEVEL as LogLevel | undefined;\n if (envLevel && envLevel in LOG_LEVELS) {\n this.level = envLevel;\n }\n }\n\n child(context: string): Logger {\n const child = new Logger(this.context ? `${this.context}:${context}` : context);\n child.level = this.level;\n return child;\n }\n\n private format(level: LogLevel, message: string, meta?: Record<string, unknown>): string {\n const ts = new Date().toISOString();\n const prefix = this.context ? `[${this.context}]` : '';\n const metaStr = meta ? ` ${JSON.stringify(meta)}` : '';\n return `${ts} ${level.toUpperCase().padEnd(5)} ${prefix} ${message}${metaStr}`;\n }\n\n private log(level: LogLevel, message: string, meta?: Record<string, unknown>): void {\n if (LOG_LEVELS[level] < LOG_LEVELS[this.level]) return;\n const line = this.format(level, message, meta);\n if (level === 'error') {\n console.error(line);\n } else if (level === 'warn') {\n console.warn(line);\n } else {\n console.log(line);\n }\n }\n\n debug(message: string, meta?: Record<string, unknown>): void {\n this.log('debug', message, meta);\n }\n\n info(message: string, meta?: Record<string, unknown>): void {\n this.log('info', message, meta);\n }\n\n warn(message: string, meta?: Record<string, unknown>): void {\n this.log('warn', message, meta);\n }\n\n error(message: string, meta?: Record<string, unknown>): void {\n this.log('error', message, meta);\n }\n}\n\nexport const logger = new Logger();\nexport { Logger };\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('GongfengClient');\n\nexport interface GongfengIssue {\n id: number;\n iid: number;\n title: string;\n description: string;\n state: string;\n labels: string[];\n created_at: string;\n updated_at: string;\n author: { username: string; name: string };\n}\n\nexport interface GongfengConfig {\n apiUrl: string;\n privateToken: string;\n projectPath: string;\n}\n\nexport interface CreateMergeRequestOptions {\n sourceBranch: string;\n targetBranch: string;\n title: string;\n description?: string;\n}\n\nexport interface GongfengMergeRequest {\n id: number;\n iid: number;\n title: string;\n web_url: string;\n state: string;\n source_branch?: string;\n target_branch?: string;\n}\n\nexport interface UploadResult {\n alt: string;\n url: string;\n markdown: string;\n}\n\nexport interface GongfengNote {\n id: number;\n body: string;\n author: { username: string; name: string };\n created_at: string;\n}\n\nexport const AGENT_NOTE_MARKER = '\\n\\n<!-- issue-auto-finish-agent -->';\nconst AGENT_NOTE_MARKER_PATTERN = '<!-- issue-auto-finish-agent -->';\n\nexport class GongfengClient {\n private apiUrl: string;\n private token: string;\n private projectPath: string;\n\n constructor(config: GongfengConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '');\n this.token = config.privateToken;\n this.projectPath = config.projectPath;\n }\n\n private get projectApiBase(): string {\n const encoded = encodeURIComponent(this.projectPath);\n return `${this.apiUrl}/api/v3/projects/${encoded}`;\n }\n\n private async requestRaw(path: string, options: RequestInit = {}): Promise<Response> {\n const url = `${this.projectApiBase}${path}`;\n logger.debug('API request', { method: options.method || 'GET', url });\n\n const resp = await fetch(url, {\n ...options,\n headers: {\n 'PRIVATE-TOKEN': this.token,\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n });\n\n if (!resp.ok) {\n const body = await resp.text();\n throw new Error(`Gongfeng API error ${resp.status}: ${body}`);\n }\n\n return resp;\n }\n\n private async request<T>(path: string, options: RequestInit = {}): Promise<T> {\n const resp = await this.requestRaw(path, options);\n return resp.json() as Promise<T>;\n }\n\n async createIssue(\n title: string,\n description: string,\n labels?: string[],\n ): Promise<GongfengIssue> {\n const body: Record<string, string> = { title, description };\n if (labels && labels.length > 0) {\n body.labels = labels.join(',');\n }\n const issue = await this.request<GongfengIssue>('/issues', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n logger.info('Issue created', { id: issue.id, iid: issue.iid, title });\n return issue;\n }\n\n async listIssues(state: string = 'opened', labels?: string): Promise<GongfengIssue[]> {\n const params = new URLSearchParams({ state, per_page: '100' });\n if (labels) {\n params.set('labels', labels);\n }\n return this.request<GongfengIssue[]>(`/issues?${params.toString()}`);\n }\n\n async listIssuesAdvanced(options: {\n state?: string;\n labels?: string;\n search?: string;\n page?: number;\n perPage?: number;\n } = {}): Promise<{ issues: GongfengIssue[]; total: number }> {\n const params = new URLSearchParams({\n state: options.state || 'opened',\n page: String(options.page || 1),\n per_page: String(options.perPage || 20),\n });\n if (options.labels) {\n params.set('labels', options.labels);\n }\n if (options.search) {\n params.set('search', options.search);\n }\n const resp = await this.requestRaw(`/issues?${params.toString()}`);\n const total = parseInt(resp.headers.get('x-total') || '0', 10);\n const issues = (await resp.json()) as GongfengIssue[];\n return { issues, total: total || issues.length };\n }\n\n async getIssueDetail(issueId: number): Promise<GongfengIssue> {\n return this.request<GongfengIssue>(`/issues/${issueId}`);\n }\n\n async createIssueNote(issueId: number, body: string): Promise<void> {\n const markedBody = body + AGENT_NOTE_MARKER;\n await this.request(`/issues/${issueId}/notes`, {\n method: 'POST',\n body: JSON.stringify({ body: markedBody }),\n });\n logger.info('Issue note created', { issueId });\n }\n\n async updateIssueLabels(issueId: number, labels: string[]): Promise<void> {\n await this.request(`/issues/${issueId}`, {\n method: 'PUT',\n body: JSON.stringify({ labels: labels.join(',') }),\n });\n logger.info('Issue labels updated', { issueId, labels });\n }\n\n async createMergeRequest(options: CreateMergeRequestOptions): Promise<GongfengMergeRequest> {\n const mr = await this.request<GongfengMergeRequest>('/merge_requests', {\n method: 'POST',\n body: JSON.stringify({\n source_branch: options.sourceBranch,\n target_branch: options.targetBranch,\n title: options.title,\n description: options.description ?? '',\n }),\n });\n if (!mr.web_url && mr.iid) {\n mr.web_url = this.buildMergeRequestUrl(mr.iid);\n }\n logger.info('Merge request created', { iid: mr.iid, webUrl: mr.web_url });\n return mr;\n }\n\n async findMergeRequestByBranch(\n sourceBranch: string,\n targetBranch: string,\n state: string = 'opened',\n ): Promise<GongfengMergeRequest | null> {\n const params = new URLSearchParams({\n state,\n source_branch: sourceBranch,\n target_branch: targetBranch,\n });\n const mrs = await this.request<GongfengMergeRequest[]>(\n `/merge_requests?${params.toString()}`,\n );\n if (mrs.length === 0) return null;\n const mr = mrs[0];\n if (!mr.web_url && mr.iid) {\n mr.web_url = this.buildMergeRequestUrl(mr.iid);\n }\n return mr;\n }\n\n private buildMergeRequestUrl(mrIid: number): string {\n return `${this.apiUrl}/${this.projectPath}/merge_requests/${mrIid}`;\n }\n\n async uploadFile(filePath: string): Promise<UploadResult> {\n const fileData = fs.readFileSync(filePath);\n const fileName = path.basename(filePath);\n const mimeType = fileName.endsWith('.png') ? 'image/png' : 'application/octet-stream';\n const blob = new Blob([fileData], { type: mimeType });\n\n const formData = new FormData();\n formData.append('file', blob, fileName);\n\n const url = `${this.projectApiBase}/uploads`;\n logger.debug('Upload request', { url, fileName });\n\n const resp = await fetch(url, {\n method: 'POST',\n headers: { 'PRIVATE-TOKEN': this.token },\n body: formData,\n });\n\n if (!resp.ok) {\n const body = await resp.text();\n throw new Error(`Gongfeng upload error ${resp.status}: ${body}`);\n }\n\n const result = (await resp.json()) as UploadResult;\n logger.info('File uploaded', { fileName, url: result.url });\n return result;\n }\n\n async createMergeRequestNote(mrIid: number, body: string): Promise<void> {\n const markedBody = body + AGENT_NOTE_MARKER;\n await this.request(`/merge_requests/${mrIid}/notes`, {\n method: 'POST',\n body: JSON.stringify({ body: markedBody }),\n });\n logger.info('Merge request note created', { mrIid });\n }\n\n async closeMergeRequest(mrIid: number): Promise<void> {\n await this.request(`/merge_requests/${mrIid}`, {\n method: 'PUT',\n body: JSON.stringify({ state_event: 'close' }),\n });\n logger.info('Merge request closed', { mrIid });\n }\n\n async deleteIssue(issueId: number): Promise<void> {\n await this.request(`/issues/${issueId}`, { method: 'DELETE' });\n logger.info('Issue deleted', { issueId });\n }\n\n async closeIssue(issueId: number): Promise<void> {\n await this.request(`/issues/${issueId}`, {\n method: 'PUT',\n body: JSON.stringify({ state_event: 'close', labels: 'auto-finish:e2e-cleaned' }),\n });\n logger.info('Issue closed', { issueId });\n }\n\n async listIssueNotes(issueId: number): Promise<GongfengNote[]> {\n const allNotes: GongfengNote[] = [];\n let page = 1;\n while (true) {\n const params = new URLSearchParams({ per_page: '100', page: String(page) });\n const batch = await this.request<GongfengNote[]>(\n `/issues/${issueId}/notes?${params.toString()}`,\n );\n allNotes.push(...batch);\n if (batch.length < 100) break;\n page++;\n }\n return allNotes;\n }\n\n async deleteIssueNote(issueId: number, noteId: number): Promise<void> {\n await this.request(`/issues/${issueId}/notes/${noteId}`, { method: 'DELETE' });\n logger.debug('Issue note deleted', { issueId, noteId });\n }\n\n async cleanupAgentNotes(issueId: number): Promise<number> {\n const notes = await this.listIssueNotes(issueId);\n const agentNotes = notes.filter(n => n.body.includes(AGENT_NOTE_MARKER_PATTERN));\n for (const note of agentNotes) {\n await this.deleteIssueNote(issueId, note.id);\n }\n if (agentNotes.length > 0) {\n logger.info('Agent notes cleaned up', { issueId, deleted: agentNotes.length });\n }\n return agentNotes.length;\n }\n\n async addLabel(issueId: number, label: string): Promise<void> {\n const issue = await this.getIssueDetail(issueId);\n if (issue.labels.includes(label)) {\n logger.info('Label already exists, skipping', { issueId, label });\n return;\n }\n const newLabels = [...issue.labels, label];\n await this.updateIssueLabels(issueId, newLabels);\n }\n}\n","import { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { logger as rootLogger } from '../logger.js';\n\nconst execFileAsync = promisify(execFile);\nconst logger = rootLogger.child('GitOperations');\n\nexport class GitOperations {\n private workDir: string;\n\n constructor(workDir: string) {\n this.workDir = workDir;\n }\n\n private async exec(args: string[]): Promise<string> {\n logger.debug('git exec', { args });\n const { stdout } = await execFileAsync('git', args, {\n cwd: this.workDir,\n maxBuffer: 10 * 1024 * 1024,\n env: { ...process.env, HUSKY: '0' },\n });\n return stdout.trim();\n }\n\n async fetchAndPull(branch: string): Promise<void> {\n await this.exec(['fetch', 'origin']);\n await this.exec(['checkout', '-f', branch]);\n await this.exec(['pull', 'origin', branch]);\n logger.info('Fetched and pulled', { branch });\n }\n\n async fetch(): Promise<void> {\n await this.exec(['fetch', 'origin']);\n logger.info('Fetched from origin');\n }\n\n async createBranch(name: string, from: string): Promise<void> {\n // Create branch from origin/<from> without needing to checkout <from> first\n // Use -f to force checkout when untracked files conflict with the target\n await this.exec(['checkout', '-f', '-b', name, `origin/${from}`]);\n logger.info('Branch created', { name, from: `origin/${from}` });\n }\n\n async checkout(branch: string): Promise<void> {\n await this.exec(['checkout', '-f', branch]);\n logger.info('Checked out', { branch });\n }\n\n async add(files: string[]): Promise<void> {\n await this.exec(['add', ...files]);\n }\n\n async commit(message: string): Promise<void> {\n await this.exec(['commit', '--no-verify', '-m', message]);\n logger.info('Committed', { message: message.slice(0, 80) });\n }\n\n async push(branch: string): Promise<void> {\n await this.exec(['push', '--no-verify', '-u', 'origin', branch]);\n logger.info('Pushed', { branch });\n }\n\n async branchExists(name: string): Promise<boolean> {\n try {\n await this.exec(['rev-parse', '--verify', name]);\n return true;\n } catch {\n return false;\n }\n }\n\n async remoteBranchExists(name: string): Promise<boolean> {\n try {\n await this.exec(['ls-remote', '--exit-code', '--heads', 'origin', name]);\n return true;\n } catch {\n return false;\n }\n }\n\n async getCurrentBranch(): Promise<string> {\n return this.exec(['rev-parse', '--abbrev-ref', 'HEAD']);\n }\n\n async stash(): Promise<void> {\n await this.exec(['stash']);\n }\n\n async stashPop(): Promise<void> {\n await this.exec(['stash', 'pop']);\n }\n\n async hasChanges(): Promise<boolean> {\n const status = await this.exec(['status', '--porcelain']);\n return status.length > 0;\n }\n\n async addAndCommit(files: string[], message: string): Promise<void> {\n await this.add(files);\n await this.commit(message);\n }\n\n async checkoutTrack(remoteBranch: string): Promise<void> {\n await this.exec(['checkout', '-f', '--track', `origin/${remoteBranch}`]);\n logger.info('Checked out remote tracking branch', { remoteBranch });\n }\n\n async addCommitAndPush(files: string[], message: string, branch: string): Promise<void> {\n await this.add(files);\n await this.commit(message);\n await this.push(branch);\n }\n\n async deleteBranch(name: string): Promise<void> {\n await this.exec(['branch', '-D', name]);\n logger.info('Branch deleted', { name });\n }\n\n async deleteRemoteBranch(name: string): Promise<void> {\n await this.exec(['push', 'origin', '--delete', name]);\n logger.info('Remote branch deleted', { name });\n }\n\n async worktreeAdd(dir: string, newBranch: string, startPoint: string): Promise<void> {\n await this.exec(['worktree', 'add', '-b', newBranch, dir, startPoint]);\n logger.info('Worktree added (new branch)', { dir, newBranch, startPoint });\n }\n\n async worktreeAddExisting(dir: string, branch: string): Promise<void> {\n await this.exec(['worktree', 'add', dir, branch]);\n logger.info('Worktree added (existing branch)', { dir, branch });\n }\n\n async worktreeAddTracking(dir: string, remoteBranch: string): Promise<void> {\n await this.exec(['worktree', 'add', '--track', '-b', remoteBranch, dir, `origin/${remoteBranch}`]);\n logger.info('Worktree added (tracking remote)', { dir, remoteBranch });\n }\n\n async worktreeRemove(dir: string, force = false): Promise<void> {\n const args = ['worktree', 'remove', dir];\n if (force) args.push('--force');\n await this.exec(args);\n logger.info('Worktree removed', { dir, force });\n }\n\n async worktreeList(): Promise<string[]> {\n const output = await this.exec(['worktree', 'list', '--porcelain']);\n return output\n .split('\\n')\n .filter((line) => line.startsWith('worktree '))\n .map((line) => line.replace('worktree ', ''));\n }\n\n async showFile(ref: string, filePath: string): Promise<string | null> {\n try {\n return await this.exec(['show', `${ref}:${filePath}`]);\n } catch {\n return null;\n }\n }\n}\n","import { spawn, type SpawnOptions } from 'node:child_process';\nimport { logger as rootLogger } from '../logger.js';\nimport type { RunOptions, RunResult, StreamEvent } from './AIRunner.js';\n\nconst logger = rootLogger.child('AIRunner');\n\nexport abstract class BaseAIRunner {\n protected abstract getBinary(): string;\n protected abstract buildArgs(options: RunOptions): string[];\n protected abstract getSpawnOptions(options: RunOptions): SpawnOptions;\n\n async run(options: RunOptions): Promise<RunResult> {\n const { prompt, workDir, timeoutMs, sessionId, continueSession, onStreamEvent } = options;\n\n logger.info('Running AI runner', {\n workDir,\n timeoutMs,\n continueSession: !!continueSession,\n sessionId,\n });\n\n return new Promise<RunResult>((resolve) => {\n const chunks: Buffer[] = [];\n const stderrChunks: Buffer[] = [];\n let timedOut = false;\n let lineBuffer = '';\n\n const binary = this.getBinary();\n const args = this.buildArgs(options);\n const spawnOpts = this.getSpawnOptions(options);\n\n const child = spawn(binary, args, {\n ...spawnOpts,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill('SIGTERM');\n logger.warn('AI runner timed out', { timeoutMs });\n }, timeoutMs);\n\n const flushInterval = onStreamEvent\n ? setInterval(() => {\n if (lineBuffer.trim()) {\n onStreamEvent({ type: 'partial', content: lineBuffer.trim(), timestamp: new Date().toISOString() });\n }\n }, 3000)\n : undefined;\n\n child.stdout.on('data', (chunk: Buffer) => {\n chunks.push(chunk);\n\n if (onStreamEvent) {\n lineBuffer += chunk.toString();\n let newlineIdx: number;\n while ((newlineIdx = lineBuffer.indexOf('\\n')) !== -1) {\n const line = lineBuffer.slice(0, newlineIdx).trim();\n lineBuffer = lineBuffer.slice(newlineIdx + 1);\n if (!line) continue;\n this.emitStreamLine(line, onStreamEvent);\n }\n }\n });\n\n child.stderr.on('data', (chunk: Buffer) => {\n stderrChunks.push(chunk);\n const text = chunk.toString();\n logger.debug('AI runner stderr: ' + text);\n if (onStreamEvent) {\n onStreamEvent({ type: 'stderr', content: text, timestamp: new Date().toISOString() });\n }\n });\n\n child.on('close', (code) => {\n clearTimeout(timer);\n if (flushInterval) clearInterval(flushInterval);\n\n if (onStreamEvent && lineBuffer.trim()) {\n this.emitStreamLine(lineBuffer.trim(), onStreamEvent);\n }\n\n const rawOutput = Buffer.concat(chunks as unknown as Uint8Array[]).toString('utf-8');\n const { output, resolvedSessionId } = this.parseOutput(rawOutput, sessionId);\n\n const success = code === 0 && !timedOut;\n logger.info('AI runner finished', { exitCode: code, success, timedOut });\n\n // If output is empty and process failed, use stderr as output for error reporting\n const stderrText = stderrChunks.length > 0 ? Buffer.concat(stderrChunks as unknown as Uint8Array[]).toString('utf-8').trim() : '';\n const finalOutput = (!success && !output.trim() && stderrText) ? stderrText : output;\n\n resolve({\n success,\n output: finalOutput,\n sessionId: resolvedSessionId ?? sessionId,\n exitCode: code,\n });\n });\n\n child.on('error', (err) => {\n clearTimeout(timer);\n if (flushInterval) clearInterval(flushInterval);\n logger.error('AI runner spawn error', { error: err.message });\n resolve({\n success: false,\n output: err.message,\n exitCode: null,\n });\n });\n\n child.stdin.write(prompt);\n child.stdin.end();\n });\n }\n\n private emitStreamLine(line: string, onStreamEvent: (event: StreamEvent) => void): void {\n try {\n const parsed = JSON.parse(line) as Record<string, unknown>;\n onStreamEvent({\n type: (typeof parsed.type === 'string' ? parsed.type : 'raw'),\n content: parsed,\n timestamp: new Date().toISOString(),\n });\n } catch {\n onStreamEvent({ type: 'raw', content: line, timestamp: new Date().toISOString() });\n }\n }\n\n /**\n * Handles both stream-json (one JSON object per line) and legacy single-JSON formats.\n */\n parseOutput(rawOutput: string, _sessionId?: string): { output: string; resolvedSessionId?: string } {\n let output = rawOutput;\n let resolvedSessionId: string | undefined;\n\n const events = this.tryParseStreamJson(rawOutput);\n if (events) {\n output = events\n .filter((item: { type?: string }) => item.type === 'result')\n .map((item: { result?: string }) => item.result ?? '')\n .join('\\n');\n const sessionItem = events.find(\n (item: { type?: string; session_id?: string }) => item.session_id != null,\n );\n if (sessionItem) {\n resolvedSessionId = (sessionItem as { session_id: string }).session_id;\n }\n if (!output) {\n output = this.summarizeStreamEvents(events);\n }\n return { output, resolvedSessionId };\n }\n\n try {\n const parsed = JSON.parse(rawOutput);\n if (Array.isArray(parsed)) {\n output = parsed\n .filter((item: { type?: string }) => item.type === 'result')\n .map((item: { result?: string }) => item.result ?? '')\n .join('\\n');\n const sessionItem = parsed.find(\n (item: { type?: string; session_id?: string }) => item.session_id != null,\n );\n if (sessionItem) {\n resolvedSessionId = sessionItem.session_id;\n }\n } else if (parsed.result != null) {\n output = parsed.result;\n resolvedSessionId = parsed.session_id;\n }\n } catch {\n // raw text output\n }\n\n return { output, resolvedSessionId };\n }\n\n private summarizeStreamEvents(events: Record<string, unknown>[]): string {\n const errorEvents = events.filter(\n (e) => e.type === 'error' || e.subtype === 'error',\n );\n if (errorEvents.length > 0) {\n const messages = errorEvents.map(\n (e) => String(e.message ?? e.error ?? JSON.stringify(e)),\n );\n return `AI runner 错误: ${messages.join('; ')}`;\n }\n\n const types = events.map((e) => String(e.type ?? 'unknown'));\n const typeCounts: Record<string, number> = {};\n for (const t of types) {\n typeCounts[t] = (typeCounts[t] ?? 0) + 1;\n }\n const summary = Object.entries(typeCounts)\n .map(([t, c]) => `${t}(${c})`)\n .join(', ');\n return `AI runner 未返回结果 (收到 ${events.length} 个事件: ${summary})`;\n }\n\n private tryParseStreamJson(raw: string): Record<string, unknown>[] | null {\n const lines = raw.split('\\n').filter((l) => l.trim());\n if (lines.length < 2) return null;\n\n const objects: Record<string, unknown>[] = [];\n for (const line of lines) {\n try {\n objects.push(JSON.parse(line) as Record<string, unknown>);\n } catch {\n return null;\n }\n }\n return objects;\n }\n}\n","import type { SpawnOptions } from 'node:child_process';\nimport { BaseAIRunner } from './BaseAIRunner.js';\nimport type { RunOptions } from './AIRunner.js';\n\nexport class ClaudeInternalRunner extends BaseAIRunner {\n private readonly binary: string;\n private readonly nvmNodeVersion: string;\n private readonly model?: string;\n\n constructor(binary: string, nvmNodeVersion: string, model?: string) {\n super();\n this.binary = binary;\n this.nvmNodeVersion = nvmNodeVersion;\n this.model = model;\n }\n\n protected getBinary(): string {\n return this.binary;\n }\n\n protected buildArgs(options: RunOptions): string[] {\n const args = ['-p', '-', '--output-format', 'stream-json', '--verbose'];\n if (options.mode === 'plan') {\n args.push('--permission-mode', 'plan', '--allowedTools', 'Read,Grep,Glob,WebSearch');\n } else {\n args.push('--dangerously-skip-permissions');\n }\n if (this.model) {\n args.push('--model', this.model);\n }\n if (options.continueSession && options.sessionId) {\n args.push('--resume', options.sessionId);\n }\n return args;\n }\n\n protected getSpawnOptions(options: RunOptions): SpawnOptions {\n const { CLAUDECODE, ...env } = process.env;\n return {\n cwd: options.workDir,\n env: {\n ...env,\n NODE_VERSION: this.nvmNodeVersion,\n },\n };\n }\n}\n","import type { SpawnOptions } from 'node:child_process';\nimport { BaseAIRunner } from './BaseAIRunner.js';\nimport type { RunOptions } from './AIRunner.js';\n\nexport class CodebuddyRunner extends BaseAIRunner {\n private readonly binary: string;\n private readonly nvmNodeVersion: string;\n private readonly model?: string;\n\n constructor(binary: string, nvmNodeVersion: string, model?: string) {\n super();\n this.binary = binary;\n this.nvmNodeVersion = nvmNodeVersion;\n this.model = model;\n }\n\n protected getBinary(): string {\n return this.binary;\n }\n\n protected buildArgs(options: RunOptions): string[] {\n const args = ['-p', '--output-format', 'stream-json', '--verbose'];\n if (options.mode === 'plan') {\n args.push('--permission-mode', 'plan', '--allowedTools', 'Read,Grep,Glob,WebSearch');\n } else {\n args.push('-y');\n }\n if (this.model) {\n args.push('--model', this.model);\n }\n if (options.continueSession && options.sessionId) {\n args.push('--resume', options.sessionId);\n }\n return args;\n }\n\n protected getSpawnOptions(options: RunOptions): SpawnOptions {\n return {\n cwd: options.workDir,\n env: {\n ...process.env,\n NODE_VERSION: this.nvmNodeVersion,\n },\n };\n }\n}\n","import type { SpawnOptions } from 'node:child_process';\nimport { BaseAIRunner } from './BaseAIRunner.js';\nimport type { RunOptions } from './AIRunner.js';\n\nexport class CursorAgentRunner extends BaseAIRunner {\n private readonly binary: string;\n private readonly nvmNodeVersion: string;\n private readonly model?: string;\n\n constructor(binary: string, nvmNodeVersion: string, model?: string) {\n super();\n this.binary = binary;\n this.nvmNodeVersion = nvmNodeVersion;\n this.model = model;\n }\n\n protected getBinary(): string {\n return this.binary;\n }\n\n protected buildArgs(options: RunOptions): string[] {\n const args = [\n 'agent',\n '-p',\n '--force',\n '--trust',\n '--output-format',\n 'stream-json',\n '--workspace',\n options.workDir,\n ];\n if (options.mode === 'plan') {\n args.push('--mode', 'plan');\n }\n if (this.model) {\n args.push('--model', this.model);\n }\n if (options.continueSession && options.sessionId) {\n args.push('--resume', options.sessionId);\n }\n return args;\n }\n\n protected getSpawnOptions(_options: RunOptions): SpawnOptions {\n return {\n cwd: process.cwd(),\n env: {\n ...process.env,\n NODE_VERSION: this.nvmNodeVersion,\n },\n };\n }\n}\n","import type { AIRunner } from './AIRunner.js';\nimport { ClaudeInternalRunner } from './ClaudeInternalRunner.js';\nimport { CodebuddyRunner } from './CodebuddyRunner.js';\nimport { CursorAgentRunner } from './CursorAgentRunner.js';\n\nexport type { AIRunner, RunOptions, RunResult, StreamEvent } from './AIRunner.js';\nexport { BaseAIRunner } from './BaseAIRunner.js';\nexport { ClaudeInternalRunner } from './ClaudeInternalRunner.js';\nexport { CodebuddyRunner } from './CodebuddyRunner.js';\nexport { CursorAgentRunner } from './CursorAgentRunner.js';\n\nexport interface AIConfig {\n mode: 'claude-internal' | 'cursor-agent' | 'codebuddy';\n binary: string;\n phaseTimeoutMs: number;\n nvmNodeVersion: string;\n model?: string;\n}\n\nexport function createAIRunner(ai: AIConfig): AIRunner {\n switch (ai.mode) {\n case 'cursor-agent':\n return new CursorAgentRunner(ai.binary, ai.nvmNodeVersion, ai.model);\n case 'codebuddy':\n return new CodebuddyRunner(ai.binary, ai.nvmNodeVersion, ai.model);\n default:\n return new ClaudeInternalRunner(ai.binary, ai.nvmNodeVersion, ai.model);\n }\n}\n","import { IssueState } from '../tracker/IssueState.js';\nimport { t } from '../i18n/index.js';\n\nexport type PipelineMode = 'classic' | 'plan-mode';\n\nexport interface PhaseSpec {\n name: string;\n label: string;\n startState: IssueState;\n doneState: IssueState;\n kind: 'ai' | 'gate';\n approvedState?: IssueState;\n}\n\nexport interface PlanFileSpec {\n filename: string;\n label: string;\n editable: boolean;\n}\n\nexport interface PipelineDef {\n mode: PipelineMode;\n phases: PhaseSpec[];\n planFiles: PlanFileSpec[];\n}\n\nexport const CLASSIC_PIPELINE: PipelineDef = {\n mode: 'classic',\n phases: [\n { name: 'analysis', label: '分析', startState: IssueState.Analyzing,\n doneState: IssueState.AnalysisDone, kind: 'ai' },\n { name: 'design', label: '设计', startState: IssueState.Designing,\n doneState: IssueState.DesignDone, kind: 'ai' },\n { name: 'implement', label: '实施', startState: IssueState.Implementing,\n doneState: IssueState.ImplementDone, kind: 'ai' },\n { name: 'verify', label: '验证', startState: IssueState.Verifying,\n doneState: IssueState.Completed, kind: 'ai' },\n ],\n planFiles: [\n { filename: '01-analysis.md', label: '需求分析', editable: true },\n { filename: '02-design.md', label: '系统设计', editable: true },\n { filename: '03-todolist.md', label: '实施清单', editable: true },\n { filename: '04-verify-report.md', label: '验证报告', editable: false },\n ],\n};\n\nexport const PLAN_MODE_PIPELINE: PipelineDef = {\n mode: 'plan-mode',\n phases: [\n { name: 'plan', label: '规划', startState: IssueState.Planning,\n doneState: IssueState.PlanDone, kind: 'ai' },\n { name: 'review', label: '审核', startState: IssueState.WaitingForReview,\n doneState: IssueState.WaitingForReview, approvedState: IssueState.ReviewApproved,\n kind: 'gate' },\n { name: 'build', label: '实施', startState: IssueState.Building,\n doneState: IssueState.BuildDone, kind: 'ai' },\n { name: 'verify', label: '验证', startState: IssueState.Verifying,\n doneState: IssueState.Completed, kind: 'ai' },\n ],\n planFiles: [\n { filename: '01-plan.md', label: '实施计划', editable: true },\n { filename: '02-verify-report.md', label: '验证报告', editable: false },\n { filename: 'review-feedback.md', label: '审核反馈', editable: false },\n { filename: 'review-history.json', label: '审核历史', editable: false },\n ],\n};\n\nexport function resolvePipelineMode(aiMode: string, explicit?: string): PipelineMode {\n if (explicit === 'classic' || explicit === 'plan-mode') return explicit;\n return aiMode === 'cursor-agent' ? 'plan-mode' : 'classic';\n}\n\nexport function getPipelineDef(mode: PipelineMode): PipelineDef {\n return mode === 'plan-mode' ? PLAN_MODE_PIPELINE : CLASSIC_PIPELINE;\n}\n\n/**\n * 获取某个 phase 的前驱状态(即重置到该 phase 需要设置的状态)。\n * 第一个 phase 的前驱是 BranchCreated;后续 phase 的前驱是上一个 phase 的 approvedState 或 doneState。\n */\nexport function getPhasePreState(def: PipelineDef, phaseName: string): IssueState | undefined {\n const idx = def.phases.findIndex(p => p.name === phaseName);\n if (idx < 0) return undefined;\n if (idx === 0) return IssueState.BranchCreated;\n const prev = def.phases[idx - 1];\n return prev.approvedState ?? prev.doneState;\n}\n\n/**\n * 从 PipelineDef 收集所有状态及其展示标签,用于前端展示,避免手动维护 STATE_MAP。\n */\nexport function collectStateLabels(def: PipelineDef): Map<string, string> {\n const labels = new Map<string, string>();\n labels.set(IssueState.Pending, t('state.pending'));\n labels.set(IssueState.BranchCreated, t('state.branchCreated'));\n for (const phase of def.phases) {\n labels.set(phase.startState, t('state.phaseDoing', { label: t(`pipeline.phase.${phase.name}`) }));\n if (phase.doneState !== IssueState.Completed) {\n labels.set(phase.doneState, t('state.phaseDone', { label: t(`pipeline.phase.${phase.name}`) }));\n }\n if (phase.approvedState) labels.set(phase.approvedState, t('state.phaseApproved', { label: t(`pipeline.phase.${phase.name}`) }));\n }\n labels.set(IssueState.Completed, t('state.completed'));\n labels.set(IssueState.Failed, t('state.failed'));\n return labels;\n}\n\nexport function getPhaseLabel(phaseName: string): string {\n return t(`pipeline.phase.${phaseName}`);\n}\n\nexport function getPlanFileLabel(filename: string): string {\n return t(`planFile.${filename}`);\n}\n\n/**\n * 根据当前 state 和 PipelineDef,推导每个 phase 的进度状态。\n */\nexport function derivePhaseStatuses(\n def: PipelineDef,\n currentState: string,\n): Record<string, 'pending' | 'in_progress' | 'completed'> {\n const result: Record<string, 'pending' | 'in_progress' | 'completed'> = {};\n let passedCurrent = false;\n\n for (const phase of def.phases) {\n if (passedCurrent) {\n result[phase.name] = 'pending';\n continue;\n }\n if (phase.startState === currentState) {\n result[phase.name] = 'in_progress';\n passedCurrent = true;\n } else if (phase.doneState === currentState || phase.approvedState === currentState) {\n result[phase.name] = 'completed';\n } else {\n result[phase.name] = 'completed';\n }\n }\n return result;\n}\n","import { EventEmitter } from 'node:events';\n\nexport type EventType =\n | 'issue:created'\n | 'issue:stateChanged'\n | 'issue:failed'\n | 'issue:deleted'\n | 'issue:resetForRetry'\n | 'issue:restarted'\n | 'issue:retryFromPhase'\n | 'poll:tick'\n | 'heartbeat'\n | 'agent:output'\n | 'pipeline:progress'\n | 'review:requested'\n | 'review:approved'\n | 'review:rejected';\n\nexport interface EventPayload {\n type: EventType;\n data: unknown;\n timestamp: string;\n}\n\nclass EventBusImpl extends EventEmitter {\n emit(event: string | symbol, ...args: unknown[]): boolean {\n super.emit('*', event, ...args);\n return super.emit(event, ...args);\n }\n\n emitTyped(type: EventType, data: unknown): void {\n const payload: EventPayload = {\n type,\n data,\n timestamp: new Date().toISOString(),\n };\n this.emit(type, payload);\n }\n}\n\nexport const eventBus = new EventBusImpl();\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { IssueRecord, IssueState } from './IssueState.js';\nimport { getPhasePreState, type PipelineDef } from '../pipeline/PipelineDefinition.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { eventBus } from '../events/EventBus.js';\n\nconst logger = rootLogger.child('IssueTracker');\n\ninterface TrackerData {\n issues: Record<string, IssueRecord>;\n}\n\nexport class IssueTracker {\n private filePath: string;\n private data: TrackerData;\n\n constructor(dataDir: string) {\n this.filePath = path.join(dataDir, 'tracker.json');\n this.data = this.load();\n }\n\n private load(): TrackerData {\n try {\n if (fs.existsSync(this.filePath)) {\n const raw = fs.readFileSync(this.filePath, 'utf-8');\n return JSON.parse(raw);\n }\n } catch (err) {\n logger.error('Failed to load tracker data', { error: (err as Error).message });\n }\n return { issues: {} };\n }\n\n private save(): void {\n const dir = path.dirname(this.filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n // Atomic write: temp file + rename prevents corruption on crash\n const tmpPath = path.join(dir, `.tracker-${process.pid}-${Date.now()}.tmp`);\n fs.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2), 'utf-8');\n fs.renameSync(tmpPath, this.filePath);\n }\n\n private key(issueIid: number): string {\n return String(issueIid);\n }\n\n get(issueIid: number): IssueRecord | undefined {\n return this.data.issues[this.key(issueIid)];\n }\n\n create(record: Omit<IssueRecord, 'createdAt' | 'updatedAt' | 'attempts'>): IssueRecord {\n const now = new Date().toISOString();\n const full: IssueRecord = {\n ...record,\n attempts: 0,\n createdAt: now,\n updatedAt: now,\n };\n this.data.issues[this.key(record.issueIid)] = full;\n this.save();\n logger.info('Issue tracked', { issueIid: record.issueIid, state: record.state });\n eventBus.emitTyped('issue:created', full);\n return full;\n }\n\n updateState(issueIid: number, state: IssueState, extra?: Partial<IssueRecord>): void {\n const record = this.data.issues[this.key(issueIid)];\n if (!record) {\n throw new Error(`Issue ${issueIid} not found in tracker`);\n }\n record.state = state;\n record.updatedAt = new Date().toISOString();\n if (state === IssueState.Completed) {\n record.lastError = undefined;\n record.failedAtState = undefined;\n }\n if (extra) {\n Object.assign(record, extra);\n }\n this.save();\n logger.info('Issue state updated', { issueIid, state });\n eventBus.emitTyped('issue:stateChanged', { issueIid, state, record });\n }\n\n markFailed(issueIid: number, error: string, failedAtState: IssueState): void {\n const record = this.data.issues[this.key(issueIid)];\n if (!record) return;\n record.state = IssueState.Failed;\n record.lastError = error;\n record.failedAtState = failedAtState;\n record.attempts += 1;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.warn('Issue marked as failed', { issueIid, error, failedAtState, attempts: record.attempts });\n eventBus.emitTyped('issue:failed', { issueIid, error, failedAtState, record });\n }\n\n private static readonly TERMINAL_STATES = new Set([IssueState.Completed, IssueState.Failed]);\n\n private static readonly PHASE_DONE_STATES = new Set([\n IssueState.AnalysisDone,\n IssueState.DesignDone,\n IssueState.ImplementDone,\n IssueState.PlanDone,\n IssueState.BuildDone,\n ]);\n\n isProcessing(issueIid: number): boolean {\n const record = this.get(issueIid);\n if (!record) return false;\n return !IssueTracker.TERMINAL_STATES.has(record.state);\n }\n\n isCompleted(issueIid: number): boolean {\n const record = this.get(issueIid);\n return record?.state === IssueState.Completed;\n }\n\n canRetry(issueIid: number, maxRetries: number): boolean {\n const record = this.get(issueIid);\n if (!record || record.state !== IssueState.Failed) return false;\n return record.attempts < maxRetries;\n }\n\n getRetryState(issueIid: number): IssueState | undefined {\n const record = this.get(issueIid);\n return record?.failedAtState;\n }\n\n isStalled(issueIid: number, thresholdMs: number = 5 * 60 * 1000): boolean {\n const record = this.get(issueIid);\n if (!record) return false;\n if (record.state === IssueState.WaitingForReview) return false;\n if (!this.isProcessing(issueIid)) return false;\n const elapsed = Date.now() - new Date(record.updatedAt).getTime();\n return elapsed > thresholdMs;\n }\n\n getDrivableIssues(maxRetries: number, stalledThresholdMs?: number): IssueRecord[] {\n return Object.values(this.data.issues).filter((record) => {\n if (record.state === IssueState.WaitingForReview) return false;\n if (record.state === IssueState.Pending) return true;\n if (record.state === IssueState.BranchCreated) return true;\n if (record.state === IssueState.ReviewApproved) return true;\n if (record.state === IssueState.Failed && record.attempts < maxRetries) return true;\n if (IssueTracker.PHASE_DONE_STATES.has(record.state)) return true;\n if (this.isStalled(record.issueIid, stalledThresholdMs)) return true;\n return false;\n });\n }\n\n getAllActive(): IssueRecord[] {\n return Object.values(this.data.issues).filter(\n (r) => r.state !== IssueState.Completed && r.state !== IssueState.Failed\n );\n }\n\n getAll(): IssueRecord[] {\n return Object.values(this.data.issues);\n }\n\n resetFull(issueIid: number): boolean {\n const record = this.data.issues[this.key(issueIid)];\n if (!record) return false;\n record.state = IssueState.Pending;\n record.attempts = 0;\n record.sessionId = undefined;\n record.failedAtState = undefined;\n record.lastError = undefined;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.info('Issue fully reset', { issueIid });\n eventBus.emitTyped('issue:restarted', { issueIid, record });\n return true;\n }\n\n resetToPhase(issueIid: number, phase: string, def: PipelineDef): boolean {\n const record = this.data.issues[this.key(issueIid)];\n if (!record) return false;\n const targetState = getPhasePreState(def, phase);\n if (!targetState) return false;\n record.state = targetState;\n record.sessionId = undefined;\n record.failedAtState = undefined;\n record.lastError = undefined;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.info('Issue reset to phase', { issueIid, phase, state: targetState });\n eventBus.emitTyped('issue:retryFromPhase', { issueIid, phase, record });\n return true;\n }\n\n resetForRetry(issueIid: number): boolean {\n const record = this.data.issues[this.key(issueIid)];\n if (!record || record.state !== IssueState.Failed) return false;\n\n const restoreState = record.failedAtState ?? IssueState.Pending;\n record.state = restoreState;\n record.lastError = undefined;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.info('Issue reset for retry', { issueIid, restoreState });\n eventBus.emitTyped('issue:resetForRetry', { issueIid, restoreState, record });\n return true;\n }\n\n delete(issueIid: number): boolean {\n const key = this.key(issueIid);\n if (!this.data.issues[key]) return false;\n const record = this.data.issues[key];\n delete this.data.issues[key];\n this.save();\n logger.info('Issue deleted from tracker', { issueIid });\n eventBus.emitTyped('issue:deleted', { issueIid, record });\n return true;\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { ProgressData, PhaseProgress } from '../tracker/IssueState.js';\nimport type { PipelineDef } from '../pipeline/PipelineDefinition.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('PlanPersistence');\n\nconst PLAN_DIR = '.claude-plan';\n\nexport interface ReviewRound {\n round: number;\n feedback: string;\n timestamp: string;\n}\n\nexport class PlanPersistence {\n private workDir: string;\n private issueIid: number;\n\n constructor(workDir: string, issueIid: number) {\n this.workDir = workDir;\n this.issueIid = issueIid;\n }\n\n get baseDir(): string {\n return this.workDir;\n }\n\n private get planDir(): string {\n return path.join(this.workDir, PLAN_DIR, `issue-${this.issueIid}`);\n }\n\n ensureDir(): void {\n if (!fs.existsSync(this.planDir)) {\n fs.mkdirSync(this.planDir, { recursive: true });\n }\n }\n\n writeIssueMeta(meta: { id: number; iid: number; title: string; labels: string[]; state: string }): void {\n this.ensureDir();\n const filePath = path.join(this.planDir, 'issue-meta.json');\n fs.writeFileSync(filePath, JSON.stringify(meta, null, 2), 'utf-8');\n logger.info('Issue meta written');\n }\n\n writeProgress(data: ProgressData): void {\n this.ensureDir();\n const filePath = path.join(this.planDir, 'progress.json');\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n logger.debug('Progress written', { currentPhase: data.currentPhase });\n }\n\n readProgress(): ProgressData | null {\n const filePath = path.join(this.planDir, 'progress.json');\n if (!fs.existsSync(filePath)) return null;\n try {\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n } catch {\n return null;\n }\n }\n\n writeAnalysis(content: string): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, '01-analysis.md'), content, 'utf-8');\n logger.info('Analysis document written');\n }\n\n writeDesign(content: string): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, '02-design.md'), content, 'utf-8');\n logger.info('Design document written');\n }\n\n writeTodolist(content: string): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, '03-todolist.md'), content, 'utf-8');\n logger.info('Todolist written');\n }\n\n writeVerifyReport(content: string, filename = '04-verify-report.md'): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, filename), content, 'utf-8');\n logger.info('Verify report written', { filename });\n }\n\n getAllPlanFiles(): string[] {\n if (!fs.existsSync(this.planDir)) return [];\n return fs.readdirSync(this.planDir).map((f) => path.join(PLAN_DIR, `issue-${this.issueIid}`, f));\n }\n\n createInitialProgress(issueId: number, issueTitle: string, branchName: string, def?: PipelineDef): ProgressData {\n const pending: PhaseProgress = { status: 'pending' };\n if (def) {\n const phases: Record<string, PhaseProgress> = {};\n for (const spec of def.phases) {\n phases[spec.name] = { ...pending };\n }\n return {\n issueId,\n issueTitle,\n branchName,\n pipelineMode: def.mode,\n currentPhase: def.phases[0].name,\n phases,\n };\n }\n return {\n issueId,\n issueTitle,\n branchName,\n currentPhase: 'analysis',\n phases: {\n analysis: { ...pending },\n design: { ...pending },\n implement: { ...pending },\n verify: { ...pending },\n },\n };\n }\n\n writePlan(content: string): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, '01-plan.md'), content, 'utf-8');\n logger.info('Plan document written');\n }\n\n writeReviewFeedback(content: string): void {\n this.ensureDir();\n const history = this.readReviewHistory();\n const round: ReviewRound = {\n round: history.length + 1,\n feedback: content,\n timestamp: new Date().toISOString(),\n };\n history.push(round);\n fs.writeFileSync(\n path.join(this.planDir, 'review-history.json'),\n JSON.stringify(history, null, 2),\n 'utf-8',\n );\n fs.writeFileSync(\n path.join(this.planDir, 'review-feedback.md'),\n PlanPersistence.renderReviewHistoryMarkdown(history),\n 'utf-8',\n );\n logger.info('Review feedback appended', { round: round.round });\n }\n\n readReviewFeedback(): string | null {\n const filePath = path.join(this.planDir, 'review-feedback.md');\n if (!fs.existsSync(filePath)) return null;\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n }\n\n readReviewHistory(): ReviewRound[] {\n const filePath = path.join(this.planDir, 'review-history.json');\n if (!fs.existsSync(filePath)) return [];\n try {\n const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n return Array.isArray(data) ? data : [];\n } catch {\n return [];\n }\n }\n\n static renderReviewHistoryMarkdown(history: ReviewRound[]): string {\n if (history.length === 0) return '';\n const lines = ['# 审核反馈历史', ''];\n for (const r of history) {\n lines.push(`## 第 ${r.round} 轮审核反馈`);\n lines.push(`> 时间: ${r.timestamp}`);\n lines.push('');\n lines.push(r.feedback);\n lines.push('');\n }\n return lines.join('\\n');\n }\n\n updatePhaseProgress(\n phaseName: string,\n status: 'in_progress' | 'completed' | 'failed',\n error?: string\n ): void {\n const progress = this.readProgress();\n if (!progress) return;\n\n const now = new Date().toISOString();\n if (!progress.phases[phaseName]) {\n progress.phases[phaseName] = { status: 'pending' };\n }\n const phase = progress.phases[phaseName];\n\n phase.status = status;\n if (status === 'in_progress') {\n phase.startedAt = now;\n progress.currentPhase = phaseName;\n } else if (status === 'completed') {\n phase.completedAt = now;\n } else if (status === 'failed') {\n phase.error = error;\n }\n\n this.writeProgress(progress);\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { AIRunner, RunResult } from '../ai-runner/index.js';\nimport { GitOperations } from '../git/GitOperations.js';\nimport { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { GongfengClient } from '../clients/GongfengClient.js';\nimport { IssueTracker } from '../tracker/IssueTracker.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { issueProgressComment } from '../prompts/templates.js';\nimport { RuleResolver } from '../rules/index.js';\nimport { eventBus } from '../events/EventBus.js';\nimport { Config } from '../config.js';\nimport {\n isNoteSyncEnabledForIssue,\n truncateToSummary,\n buildNoteSyncComment,\n} from '../notesync/NoteSyncSettings.js';\nimport type { PortPair } from '../deploy/PortAllocator.js';\nimport { logger as rootLogger, Logger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nexport interface PhaseContext {\n issueIid: number;\n issueId: number;\n issueTitle: string;\n issueDescription: string;\n branchName: string;\n supplementText?: string;\n pipelineMode?: 'classic' | 'plan-mode';\n ports?: PortPair;\n}\n\nexport abstract class BasePhase {\n protected aiRunner: AIRunner;\n protected git: GitOperations;\n protected plan: PlanPersistence;\n protected gongfeng: GongfengClient;\n protected tracker: IssueTracker;\n protected config: Config;\n protected logger: Logger;\n\n abstract readonly phaseName: string;\n abstract readonly startState: IssueState;\n abstract readonly doneState: IssueState;\n\n constructor(\n aiRunner: AIRunner,\n git: GitOperations,\n plan: PlanPersistence,\n gongfeng: GongfengClient,\n tracker: IssueTracker,\n config: Config,\n ) {\n this.aiRunner = aiRunner;\n this.git = git;\n this.plan = plan;\n this.gongfeng = gongfeng;\n this.tracker = tracker;\n this.config = config;\n this.logger = rootLogger.child(this.constructor.name);\n }\n\n protected abstract buildPrompt(ctx: PhaseContext): string;\n\n protected getRunMode(): 'plan' | 'agent' | undefined {\n return undefined;\n }\n\n protected getResultFiles(_ctx?: PhaseContext): Array<{ filename: string; label: string }> {\n return [];\n }\n\n async execute(ctx: PhaseContext): Promise<RunResult> {\n this.logger.info(`Phase ${this.phaseName} starting`, { issueIid: ctx.issueIid });\n\n // Update tracker state\n this.tracker.updateState(ctx.issueIid, this.startState);\n this.plan.updatePhaseProgress(this.phaseName, 'in_progress');\n\n // Comment on issue\n try {\n await this.gongfeng.createIssueNote(\n ctx.issueId,\n issueProgressComment(this.phaseName, 'in_progress')\n );\n } catch (err) {\n this.logger.warn('Failed to comment on issue', { error: (err as Error).message });\n }\n\n const phaseLabel = t(`phase.${this.phaseName}`) || this.phaseName;\n eventBus.emitTyped('agent:output', {\n issueIid: ctx.issueIid,\n phase: this.phaseName,\n event: {\n type: 'system',\n content: t('basePhase.aiStarting', { label: phaseLabel }),\n timestamp: new Date().toISOString(),\n },\n });\n\n // Build prompt and inject matched MDC rules\n const basePrompt = this.buildPrompt(ctx);\n const matchedRulesText = await this.resolveRules(ctx);\n const prompt = matchedRulesText\n ? `${basePrompt}\\n\\n${t('basePhase.rulesSection', { rules: matchedRulesText })}`\n : basePrompt;\n\n const record = this.tracker.get(ctx.issueIid);\n const result = await this.aiRunner.run({\n prompt,\n workDir: this.plan.baseDir,\n timeoutMs: this.config.ai.phaseTimeoutMs,\n sessionId: record?.sessionId,\n continueSession: !!record?.sessionId,\n mode: this.getRunMode(),\n onStreamEvent: (event) => {\n eventBus.emitTyped('agent:output', {\n issueIid: ctx.issueIid,\n phase: this.phaseName,\n event,\n });\n },\n });\n\n if (!result.success) {\n this.plan.updatePhaseProgress(this.phaseName, 'failed', result.output.slice(0, 500));\n this.tracker.markFailed(ctx.issueIid, result.output.slice(0, 500), this.startState);\n\n try {\n await this.gongfeng.createIssueNote(\n ctx.issueId,\n issueProgressComment(this.phaseName, 'failed', t('basePhase.error', { message: result.output.slice(0, 200) }))\n );\n } catch {\n // ignore comment failure\n }\n\n throw new Error(`Phase ${this.phaseName} failed: ${result.output.slice(0, 200)}`);\n }\n\n if (result.sessionId) {\n this.tracker.updateState(ctx.issueIid, this.startState, { sessionId: result.sessionId });\n }\n\n this.tracker.updateState(ctx.issueIid, this.doneState);\n this.plan.updatePhaseProgress(this.phaseName, 'completed');\n\n await this.commitPlanFiles(ctx);\n\n await this.syncResultToIssue(ctx);\n\n this.logger.info(`Phase ${this.phaseName} completed`, { issueIid: ctx.issueIid });\n return result;\n }\n\n protected async resolveRules(ctx: PhaseContext): Promise<string | null> {\n try {\n const rulesDir = path.join(this.plan.baseDir, '.cursor', 'rules');\n const resolver = new RuleResolver();\n await resolver.loadRules(rulesDir);\n const context = `${ctx.issueTitle} ${ctx.issueDescription} ${ctx.supplementText ?? ''}`;\n const matched = resolver.matchRules(context);\n if (matched.length > 0) {\n this.logger.info(`Matched ${matched.length} MDC rules`, {\n rules: matched.map(r => r.filename),\n });\n return resolver.formatForPrompt(matched);\n }\n } catch (err) {\n this.logger.warn('Failed to resolve MDC rules', { error: (err as Error).message });\n }\n return null;\n }\n\n private async syncResultToIssue(ctx: PhaseContext): Promise<void> {\n try {\n const enabled = isNoteSyncEnabledForIssue(ctx.issueIid, this.tracker, this.config);\n const resultFiles = this.getResultFiles(ctx);\n\n if (!enabled || resultFiles.length === 0) {\n try {\n await this.gongfeng.createIssueNote(\n ctx.issueId,\n issueProgressComment(this.phaseName, 'completed'),\n );\n } catch { /* ignore */ }\n return;\n }\n\n const baseUrl = this.config.issueNoteSync.webBaseUrl.replace(/\\/$/, '');\n const phaseLabel = t(`phase.${this.phaseName}`) || this.phaseName;\n const dashboardUrl = `${baseUrl}/?issue=${ctx.issueIid}`;\n\n for (const file of resultFiles) {\n const content = this.readResultFile(ctx.issueIid, file.filename);\n if (!content) continue;\n\n const summary = truncateToSummary(content);\n const docUrl = `${baseUrl}/doc/${ctx.issueIid}/${file.filename}`;\n const comment = buildNoteSyncComment(\n this.phaseName, file.label || phaseLabel, docUrl, dashboardUrl, summary,\n );\n\n await this.gongfeng.createIssueNote(ctx.issueId, comment);\n this.logger.info('Result synced to issue', { issueIid: ctx.issueIid, file: file.filename });\n }\n } catch (err) {\n this.logger.warn('Failed to sync result to issue', { error: (err as Error).message });\n try {\n await this.gongfeng.createIssueNote(\n ctx.issueId,\n issueProgressComment(this.phaseName, 'completed'),\n );\n } catch { /* ignore */ }\n }\n }\n\n private readResultFile(issueIid: number, filename: string): string | null {\n const planDir = path.join(this.plan.baseDir, '.claude-plan', `issue-${issueIid}`);\n const filePath = path.join(planDir, filename);\n if (!fs.existsSync(filePath)) return null;\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n }\n\n private async commitPlanFiles(ctx: PhaseContext): Promise<void> {\n if (await this.git.hasChanges()) {\n await this.git.add(['.']);\n await this.git.commit(`chore(auto): ${this.phaseName} phase completed for issue #${ctx.issueIid}`);\n await this.git.push(ctx.branchName);\n }\n }\n}\n","import { t } from '../i18n/index.js';\n\nexport interface PromptContext {\n issueTitle: string;\n issueDescription: string;\n issueIid: number;\n supplementText?: string;\n}\n\nfunction planDir(iid: number): string {\n return `.claude-plan/issue-${iid}`;\n}\n\nexport function analysisPrompt(ctx: PromptContext): string {\n const supplementSection = ctx.supplementText ? `\\n\\n${ctx.supplementText}` : '';\n const pd = planDir(ctx.issueIid);\n return t('prompt.analysis', {\n iid: ctx.issueIid,\n title: ctx.issueTitle,\n description: ctx.issueDescription,\n supplement: supplementSection,\n planDir: pd,\n });\n}\n\nexport function designPrompt(ctx: PromptContext): string {\n const supplementSection = ctx.supplementText ? `\\n\\n${ctx.supplementText}` : '';\n const pd = planDir(ctx.issueIid);\n return t('prompt.design', {\n iid: ctx.issueIid,\n title: ctx.issueTitle,\n supplement: supplementSection,\n planDir: pd,\n });\n}\n\nexport function implementPrompt(ctx: PromptContext): string {\n const pd = planDir(ctx.issueIid);\n return t('prompt.implement', {\n iid: ctx.issueIid,\n title: ctx.issueTitle,\n planDir: pd,\n });\n}\n\nexport function verifyPrompt(ctx: PromptContext): string {\n const pd = planDir(ctx.issueIid);\n return t('prompt.verify', {\n iid: ctx.issueIid,\n title: ctx.issueTitle,\n planDir: pd,\n });\n}\n\nexport function planModeVerifyPrompt(ctx: PromptContext): string {\n const pd = planDir(ctx.issueIid);\n return t('prompt.planModeVerify', {\n iid: ctx.issueIid,\n title: ctx.issueTitle,\n planDir: pd,\n });\n}\n\nexport function planPrompt(ctx: PromptContext): string {\n const supplementSection = ctx.supplementText ? `\\n\\n${ctx.supplementText}` : '';\n const pd = planDir(ctx.issueIid);\n return t('prompt.plan', {\n iid: ctx.issueIid,\n title: ctx.issueTitle,\n description: ctx.issueDescription,\n supplement: supplementSection,\n planDir: pd,\n });\n}\n\nexport function buildPrompt(ctx: PromptContext): string {\n const pd = planDir(ctx.issueIid);\n return t('prompt.build', {\n iid: ctx.issueIid,\n title: ctx.issueTitle,\n planDir: pd,\n });\n}\n\nexport interface ReviewRoundForPrompt {\n round: number;\n feedback: string;\n timestamp: string;\n}\n\nexport function rePlanPrompt(ctx: PromptContext, history: ReviewRoundForPrompt[]): string {\n const supplementSection = ctx.supplementText ? `\\n\\n${ctx.supplementText}` : '';\n const pd = planDir(ctx.issueIid);\n const feedbackLines = history.map(\n r => t('prompt.rePlanRound', { round: r.round, timestamp: r.timestamp, feedback: r.feedback })\n ).join('\\n\\n');\n return t('prompt.rePlan', {\n iid: ctx.issueIid,\n title: ctx.issueTitle,\n description: ctx.issueDescription,\n supplement: supplementSection,\n historyCount: history.length,\n feedbackLines,\n planDir: pd,\n });\n}\n\nexport interface E2ePromptPorts {\n backendPort: number;\n frontendPort: number;\n host: string;\n}\n\nexport function e2eVerifyPromptSuffix(ctx: PromptContext, ports?: E2ePromptPorts): string {\n const serverSection = ports\n ? `\n**Preview 环境已启动(由系统管理,无需手动启动):**\n- 后端: http://${ports.host}:${ports.backendPort}\n- 前端: https://${ports.host}:${ports.frontendPort}\n\n执行 E2E 测试时请使用以下环境变量来连接已启动的服务:\n\\`\\`\\`bash\nE2E_PORT=${ports.frontendPort} E2E_HOST=${ports.host} E2E_BASE_URL=https://${ports.host}:${ports.frontendPort} \\\\\n cd frontend && npx playwright test\n\\`\\`\\`\n\n**注意**: 不要使用 pnpm test:e2e(它会尝试自行启动 webServer),直接用 npx playwright test 即可复用已启动的前端。`\n : `\n执行 E2E 测试:\n\\`\\`\\`bash\ncd frontend && pnpm test:e2e\n\\`\\`\\``;\n\n return `\n\n## E2E UI 验证(已启用)\n\n本次变更已开启 E2E UI 自动验收,请额外执行以下步骤:\n\n6. 如果本次变更涉及前端页面(frontend/ 目录有改动),请执行 UI E2E 验证:\n a. 在 frontend/e2e/dynamic/ 目录下编写针对本次变更的 Playwright 测试\n b. ${serverSection.trim()}\n c. 如果测试失败,分析失败原因并尝试修复\n7. 将 E2E 测试结果写入验证报告的 **E2E UI 测试结果** 章节,包括:\n - 冒烟测试通过数 / 总数\n - 专项测试结果列表\n - 失败截图路径(如有)`;\n}\n\nexport function issueProgressComment(phase: string, status: string, detail?: string): string {\n const emoji: Record<string, string> = {\n analysis: '🔍', design: '📐', implement: '💻', verify: '✅',\n plan: '📋', review: '👀', build: '🔨',\n };\n const icon = emoji[phase] || '📋';\n const statusKey = status === 'completed' ? 'progress.completed' : status === 'failed' ? 'progress.failed' : 'progress.inProgress';\n const statusText = t(statusKey);\n let msg = t('progress.comment', { icon, phase, status: statusText });\n if (detail) {\n msg += `\\n\\n${detail}`;\n }\n return msg;\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nexport interface MdcRule {\n filename: string;\n description: string;\n content: string;\n}\n\ninterface RuleTrigger {\n filename: string;\n keywords: string[];\n}\n\nconst RULE_TRIGGERS: RuleTrigger[] = [\n {\n filename: 'session-rule.mdc',\n keywords: ['Session', 'PublishSession', 'SessionData', '会话', 'ActivitySession'],\n },\n {\n filename: 'backend-api-implementation.mdc',\n keywords: ['新增接口', '添加接口', '修改接口', 'Controller', 'ServiceImpl', '路由'],\n },\n {\n filename: 'artifact-publish-rule.mdc',\n keywords: ['制品发布', 'ArtifactPublish', 'lockResource', 'unlockResource', '发布系统'],\n },\n {\n filename: 'activity-realization-rule.mdc',\n keywords: ['活动实现', 'ActivityRealization', 'BaseActivityRealization', 'syncExecuteStatus', 'queryExec'],\n },\n {\n filename: 'appset.mdc',\n keywords: ['AppSet', 'appset', 'ComponentInstance', 'StorageService', 'IDC Set'],\n },\n {\n filename: 'add-artifact-workflow.mdc',\n keywords: ['添加制品', '新增制品', '制品类型', 'ArtifactType', 'ArtifactTypeId'],\n },\n {\n filename: 'add-appset-api-workflow.mdc',\n keywords: ['AppSet接口', 'AppSet API', 'proto', 'protobuf', 'devops-contracts'],\n },\n];\n\nfunction parseFrontmatter(raw: string): { description: string; content: string } {\n const fmRegex = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n/;\n const match = raw.match(fmRegex);\n if (!match) {\n return { description: '', content: raw.trim() };\n }\n\n const yamlBlock = match[1];\n const content = raw.slice(match[0].length).trim();\n\n let description = '';\n const descMatch = yamlBlock.match(/description:\\s*(.+)/);\n if (descMatch) {\n description = descMatch[1].trim();\n }\n\n return { description, content };\n}\n\nexport class RuleResolver {\n private rules: MdcRule[] = [];\n\n public async loadRules(rulesDir: string): Promise<void> {\n this.rules = [];\n let files: string[];\n try {\n files = await readdir(rulesDir);\n } catch {\n return;\n }\n\n const mdcFiles = files.filter(f => f.endsWith('.mdc'));\n\n const loadPromises = mdcFiles.map(async (filename) => {\n try {\n const raw = await readFile(path.join(rulesDir, filename), 'utf-8');\n const { description, content } = parseFrontmatter(raw);\n if (content) {\n this.rules.push({ filename, description, content });\n }\n } catch {\n // skip unreadable files\n }\n });\n\n await Promise.all(loadPromises);\n }\n\n public getRules(): MdcRule[] {\n return this.rules;\n }\n\n public matchRules(text: string): MdcRule[] {\n const lowerText = text.toLowerCase();\n const matched: MdcRule[] = [];\n\n for (const trigger of RULE_TRIGGERS) {\n const isTriggered = trigger.keywords.some(kw => lowerText.includes(kw.toLowerCase()));\n if (!isTriggered) continue;\n\n const rule = this.rules.find(r => r.filename === trigger.filename);\n if (rule) {\n matched.push(rule);\n }\n }\n\n return matched;\n }\n\n public formatForPrompt(rules: MdcRule[]): string {\n if (rules.length === 0) return '';\n\n return rules.map(rule => {\n const header = rule.description\n ? `### ${rule.description} (${rule.filename})`\n : `### ${rule.filename}`;\n return `${header}\\n\\n${rule.content}`;\n }).join('\\n\\n---\\n\\n');\n }\n}\n","import type { Config } from '../config.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\nimport { t } from '../i18n/index.js';\n\nlet noteSyncOverride: boolean | undefined;\n\nexport function getNoteSyncEnabled(cfg: Config): boolean {\n return noteSyncOverride ?? cfg.issueNoteSync.enabled;\n}\n\nexport function setNoteSyncOverride(value: boolean | undefined): void {\n noteSyncOverride = value;\n}\n\nexport function isNoteSyncEnabledForIssue(\n issueIid: number,\n tracker: IssueTracker,\n cfg: Config,\n): boolean {\n const record = tracker.get(issueIid);\n if (record?.issueNoteSyncEnabled !== undefined) return record.issueNoteSyncEnabled;\n return getNoteSyncEnabled(cfg);\n}\n\nconst SUMMARY_MAX_LENGTH = 500;\n\nexport function truncateToSummary(content: string): string {\n if (content.length <= SUMMARY_MAX_LENGTH) return content;\n const cut = content.slice(0, SUMMARY_MAX_LENGTH);\n const lastNewline = cut.lastIndexOf('\\n\\n');\n const boundary = lastNewline > SUMMARY_MAX_LENGTH * 0.3 ? lastNewline : cut.lastIndexOf('\\n');\n const summary = boundary > SUMMARY_MAX_LENGTH * 0.3 ? cut.slice(0, boundary) : cut;\n return summary + '\\n\\n...';\n}\n\nexport interface ResultFileSpec {\n filename: string;\n label: string;\n}\n\nexport function buildNoteSyncComment(\n phaseName: string,\n phaseLabel: string,\n docUrl: string,\n dashboardUrl: string,\n summary: string,\n): string {\n const emoji: Record<string, string> = {\n analysis: '🔍', design: '📐', implement: '💻', verify: '✅',\n plan: '📋', review: '👀', build: '🔨',\n };\n const icon = emoji[phaseName] || '📋';\n return [\n t('notesync.phaseCompleted', { icon, label: phaseLabel }),\n '',\n summary,\n '',\n '---',\n t('notesync.viewDoc', { label: phaseLabel, url: docUrl }),\n t('notesync.viewDashboard', { url: dashboardUrl }),\n ].join('\\n');\n}\n","import { BasePhase, PhaseContext } from './BasePhase.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { analysisPrompt } from '../prompts/templates.js';\n\nexport class AnalysisPhase extends BasePhase {\n readonly phaseName = 'analysis' as const;\n readonly startState = IssueState.Analyzing;\n readonly doneState = IssueState.AnalysisDone;\n\n protected getResultFiles() {\n return [{ filename: '01-analysis.md', label: '需求分析' }];\n }\n\n protected buildPrompt(ctx: PhaseContext): string {\n return analysisPrompt({\n issueTitle: ctx.issueTitle,\n issueDescription: ctx.issueDescription,\n issueIid: ctx.issueIid,\n supplementText: ctx.supplementText,\n });\n }\n}\n","import { BasePhase, PhaseContext } from './BasePhase.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { designPrompt } from '../prompts/templates.js';\n\nexport class DesignPhase extends BasePhase {\n readonly phaseName = 'design' as const;\n readonly startState = IssueState.Designing;\n readonly doneState = IssueState.DesignDone;\n\n protected getResultFiles() {\n return [{ filename: '02-design.md', label: '系统设计' }];\n }\n\n protected buildPrompt(ctx: PhaseContext): string {\n return designPrompt({\n issueTitle: ctx.issueTitle,\n issueDescription: ctx.issueDescription,\n issueIid: ctx.issueIid,\n supplementText: ctx.supplementText,\n });\n }\n}\n","import { BasePhase, PhaseContext } from './BasePhase.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { implementPrompt } from '../prompts/templates.js';\n\nexport class ImplementPhase extends BasePhase {\n readonly phaseName = 'implement' as const;\n readonly startState = IssueState.Implementing;\n readonly doneState = IssueState.ImplementDone;\n\n protected buildPrompt(ctx: PhaseContext): string {\n return implementPrompt({\n issueTitle: ctx.issueTitle,\n issueDescription: ctx.issueDescription,\n issueIid: ctx.issueIid,\n });\n }\n}\n","import os from 'node:os';\nimport { BasePhase, PhaseContext } from './BasePhase.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { verifyPrompt, planModeVerifyPrompt, e2eVerifyPromptSuffix } from '../prompts/templates.js';\nimport { isE2eEnabledForIssue } from '../e2e/E2eSettings.js';\n\nfunction getDefaultHost(): string {\n const interfaces = os.networkInterfaces();\n for (const addrs of Object.values(interfaces)) {\n for (const addr of addrs ?? []) {\n if (addr.family === 'IPv4' && !addr.internal) return addr.address;\n }\n }\n return 'localhost';\n}\n\nexport class VerifyPhase extends BasePhase {\n readonly phaseName = 'verify' as const;\n readonly startState = IssueState.Verifying;\n readonly doneState = IssueState.Completed;\n\n protected getResultFiles(ctx?: PhaseContext) {\n const filename = ctx?.pipelineMode === 'plan-mode' ? '02-verify-report.md' : '04-verify-report.md';\n return [{ filename, label: '验证报告' }];\n }\n\n protected buildPrompt(ctx: PhaseContext): string {\n const promptCtx = {\n issueTitle: ctx.issueTitle,\n issueDescription: ctx.issueDescription,\n issueIid: ctx.issueIid,\n };\n const base = ctx.pipelineMode === 'plan-mode'\n ? planModeVerifyPrompt(promptCtx)\n : verifyPrompt(promptCtx);\n\n if (!isE2eEnabledForIssue(ctx.issueIid, this.tracker, this.config)) {\n return base;\n }\n\n const e2ePorts = ctx.ports\n ? {\n backendPort: ctx.ports.backendPort,\n frontendPort: ctx.ports.frontendPort,\n host: this.config.preview.host || getDefaultHost(),\n }\n : undefined;\n\n return base + e2eVerifyPromptSuffix(promptCtx, e2ePorts);\n }\n}\n","import type { Config } from '../config.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\n\nlet e2eOverride: boolean | undefined;\n\nexport function getE2eEnabled(cfg: Config): boolean {\n return e2eOverride ?? cfg.e2e.enabled;\n}\n\nexport function setE2eOverride(value: boolean | undefined): void {\n e2eOverride = value;\n}\n\nexport function isE2eEnabledForIssue(\n issueIid: number,\n tracker: IssueTracker,\n cfg: Config,\n): boolean {\n const record = tracker.get(issueIid);\n if (record?.e2eEnabled !== undefined) return record.e2eEnabled;\n return getE2eEnabled(cfg);\n}\n","import { BasePhase, PhaseContext } from './BasePhase.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { planPrompt, rePlanPrompt } from '../prompts/templates.js';\n\nexport class PlanPhase extends BasePhase {\n readonly phaseName = 'plan' as const;\n readonly startState = IssueState.Planning;\n readonly doneState = IssueState.PlanDone;\n\n protected getResultFiles() {\n return [{ filename: '01-plan.md', label: '实施计划' }];\n }\n\n protected getRunMode(): 'plan' | 'agent' | undefined {\n return 'plan';\n }\n\n protected buildPrompt(ctx: PhaseContext): string {\n const history = this.plan.readReviewHistory();\n const promptCtx = {\n issueTitle: ctx.issueTitle,\n issueDescription: ctx.issueDescription,\n issueIid: ctx.issueIid,\n supplementText: ctx.supplementText,\n };\n if (history.length > 0) {\n return rePlanPrompt(promptCtx, history);\n }\n return planPrompt(promptCtx);\n }\n}\n","import { BasePhase, PhaseContext } from './BasePhase.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { buildPrompt } from '../prompts/templates.js';\n\nexport class BuildPhase extends BasePhase {\n readonly phaseName = 'build' as const;\n readonly startState = IssueState.Building;\n readonly doneState = IssueState.BuildDone;\n\n protected buildPrompt(ctx: PhaseContext): string {\n return buildPrompt({\n issueTitle: ctx.issueTitle,\n issueDescription: ctx.issueDescription,\n issueIid: ctx.issueIid,\n });\n }\n}\n","import type { AIRunner } from '../ai-runner/index.js';\nimport { GitOperations } from '../git/GitOperations.js';\nimport { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { GongfengClient } from '../clients/GongfengClient.js';\nimport { IssueTracker } from '../tracker/IssueTracker.js';\nimport { Config } from '../config.js';\nimport { BasePhase } from './BasePhase.js';\nimport { AnalysisPhase } from './AnalysisPhase.js';\nimport { DesignPhase } from './DesignPhase.js';\nimport { ImplementPhase } from './ImplementPhase.js';\nimport { VerifyPhase } from './VerifyPhase.js';\nimport { PlanPhase } from './PlanPhase.js';\nimport { BuildPhase } from './BuildPhase.js';\n\ntype PhaseArgs = [AIRunner, GitOperations, PlanPersistence, GongfengClient, IssueTracker, Config];\ntype PhaseConstructor = new (...args: PhaseArgs) => BasePhase;\n\nconst PHASE_REGISTRY: Record<string, PhaseConstructor> = {\n analysis: AnalysisPhase,\n design: DesignPhase,\n implement: ImplementPhase,\n plan: PlanPhase,\n build: BuildPhase,\n verify: VerifyPhase,\n};\n\nexport function createPhase(name: string, ...args: PhaseArgs): BasePhase {\n const Ctor = PHASE_REGISTRY[name];\n if (!Ctor) {\n throw new Error(\n `Unknown phase: ${name}. Registered phases: ${Object.keys(PHASE_REGISTRY).join(', ')}`\n );\n }\n return new Ctor(...args);\n}\n\n/** 校验 PipelineDef 中的所有 AI phase 都已注册,应在启动时调用 */\nexport function validatePhaseRegistry(phaseNames: string[]): void {\n const missing = phaseNames.filter(name => !(name in PHASE_REGISTRY));\n if (missing.length > 0) {\n throw new Error(\n `Pipeline defines unregistered phases: ${missing.join(', ')}. ` +\n `Registered: ${Object.keys(PHASE_REGISTRY).join(', ')}`\n );\n }\n}\n","/**\n * Promise-based async mutex for serializing access to shared resources\n * in a single Node.js process (e.g. mainGit operations, tracker file writes).\n */\nexport class AsyncMutex {\n private queue: Array<() => void> = [];\n private locked = false;\n\n async runExclusive<T>(fn: () => Promise<T>): Promise<T> {\n await this.acquire();\n try {\n return await fn();\n } finally {\n this.release();\n }\n }\n\n private acquire(): Promise<void> {\n if (!this.locked) {\n this.locked = true;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n this.queue.push(resolve);\n });\n }\n\n private release(): void {\n const next = this.queue.shift();\n if (next) {\n next();\n } else {\n this.locked = false;\n }\n }\n\n get isLocked(): boolean {\n return this.locked;\n }\n\n get queueLength(): number {\n return this.queue.length;\n }\n}\n","import path from 'node:path';\nimport os from 'node:os';\nimport fs from 'node:fs/promises';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { Config } from '../config.js';\nimport { GongfengClient, GongfengIssue } from '../clients/GongfengClient.js';\nimport { GitOperations } from '../git/GitOperations.js';\nimport type { AIRunner } from '../ai-runner/index.js';\nimport { IssueTracker } from '../tracker/IssueTracker.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { WorktreeContext } from '../git/WorktreeContext.js';\nimport { PhaseContext } from '../phases/BasePhase.js';\nimport { createPhase } from '../phases/PhaseFactory.js';\nimport { resolvePipelineMode, getPipelineDef, PipelineDef } from '../pipeline/PipelineDefinition.js';\nimport { SupplementStore } from '../supplement/SupplementStore.js';\nimport { eventBus } from '../events/EventBus.js';\nimport { AsyncMutex } from '../utils/AsyncMutex.js';\nimport { extractTapdId, generateMRTitle, generateMRDescription } from '../utils/MergeRequestHelper.js';\nimport { PortAllocator, type PortPair } from '../deploy/PortAllocator.js';\nimport { DevServerManager } from '../deploy/DevServerManager.js';\nimport { isE2eEnabledForIssue } from '../e2e/E2eSettings.js';\nimport { ScreenshotPublisher } from '../e2e/ScreenshotPublisher.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nexport interface MergeRequestResult {\n url: string;\n iid: number;\n}\n\nconst execFileAsync = promisify(execFile);\nconst logger = rootLogger.child('PipelineOrchestrator');\n\nexport class PipelineOrchestrator {\n private config: Config;\n private gongfeng: GongfengClient;\n private mainGit: GitOperations;\n private aiRunner: AIRunner;\n private tracker: IssueTracker;\n private supplementStore?: SupplementStore;\n private mainGitMutex = new AsyncMutex();\n private pipelineDef: PipelineDef;\n private portAllocator: PortAllocator;\n private devServerManager: DevServerManager;\n private screenshotPublisher: ScreenshotPublisher;\n\n constructor(\n config: Config,\n gongfeng: GongfengClient,\n git: GitOperations,\n aiRunner: AIRunner,\n tracker: IssueTracker,\n supplementStore?: SupplementStore,\n ) {\n this.config = config;\n this.gongfeng = gongfeng;\n this.mainGit = git;\n this.aiRunner = aiRunner;\n this.tracker = tracker;\n this.supplementStore = supplementStore;\n\n const mode = resolvePipelineMode(config.ai.mode, config.pipeline?.mode === 'auto' ? undefined : config.pipeline?.mode);\n this.pipelineDef = getPipelineDef(mode);\n logger.info('Pipeline mode resolved', { mode: this.pipelineDef.mode, aiMode: config.ai.mode });\n\n this.portAllocator = new PortAllocator({\n backendPortBase: config.e2e.backendPortBase,\n frontendPortBase: config.e2e.frontendPortBase,\n });\n this.devServerManager = new DevServerManager();\n this.screenshotPublisher = new ScreenshotPublisher(gongfeng);\n\n this.restorePortAllocations();\n }\n\n getPortAllocator(): PortAllocator { return this.portAllocator; }\n getDevServerManager(): DevServerManager { return this.devServerManager; }\n\n private restorePortAllocations(): void {\n for (const record of this.tracker.getAll()) {\n if (record.ports) {\n this.portAllocator.restore(record.issueIid, record.ports);\n }\n }\n }\n\n getPipelineDef(): PipelineDef {\n return this.pipelineDef;\n }\n\n private emitProgress(issueIid: number, step: string, message: string): void {\n eventBus.emitTyped('pipeline:progress', { issueIid, step, message });\n }\n\n private computeWorktreeContext(issueIid: number, branchName: string): WorktreeContext {\n const gitRootDir = path.join(this.config.project.worktreeBaseDir, `issue-${issueIid}`);\n const workDir = path.join(gitRootDir, this.config.project.projectSubDir);\n return { gitRootDir, workDir, branchName, issueIid };\n }\n\n private async ensureWorktree(wtCtx: WorktreeContext): Promise<void> {\n const worktrees = await this.mainGit.worktreeList();\n if (worktrees.includes(wtCtx.gitRootDir)) {\n logger.info('Reusing existing worktree', { dir: wtCtx.gitRootDir });\n return;\n }\n\n const localExists = await this.mainGit.branchExists(wtCtx.branchName);\n if (localExists) {\n await this.mainGit.worktreeAddExisting(wtCtx.gitRootDir, wtCtx.branchName);\n return;\n }\n\n const remoteExists = await this.mainGit.remoteBranchExists(wtCtx.branchName);\n if (remoteExists) {\n await this.mainGit.worktreeAddTracking(wtCtx.gitRootDir, wtCtx.branchName);\n return;\n }\n\n await this.mainGit.worktreeAdd(\n wtCtx.gitRootDir,\n wtCtx.branchName,\n `origin/${this.config.project.baseBranch}`,\n );\n }\n\n private async cleanupWorktree(wtCtx: WorktreeContext): Promise<void> {\n try {\n await this.mainGit.worktreeRemove(wtCtx.gitRootDir, true);\n logger.info('Worktree cleaned up', { dir: wtCtx.gitRootDir });\n } catch (err) {\n logger.warn('Failed to cleanup worktree', { dir: wtCtx.gitRootDir, error: (err as Error).message });\n }\n }\n\n private async installDependencies(workDir: string): Promise<void> {\n logger.info('Installing dependencies in worktree', { workDir });\n\n const seeded = await this.seedNodeModulesFromMain(workDir);\n if (seeded) {\n logger.info('node_modules seeded from main repo — skipping pnpm install');\n return;\n }\n\n try {\n await execFileAsync('pnpm', ['install', '--frozen-lockfile'], {\n cwd: workDir,\n maxBuffer: 10 * 1024 * 1024,\n timeout: 300_000,\n });\n logger.info('Dependencies installed');\n } catch (err) {\n logger.warn('pnpm install --frozen-lockfile failed, retrying with --ignore-scripts', {\n error: (err as Error).message,\n });\n try {\n await execFileAsync('pnpm', ['install', '--frozen-lockfile', '--ignore-scripts'], {\n cwd: workDir,\n maxBuffer: 10 * 1024 * 1024,\n timeout: 300_000,\n });\n logger.info('Dependencies installed (scripts ignored)');\n } catch (retryErr) {\n logger.warn('pnpm install also failed with --ignore-scripts', {\n error: (retryErr as Error).message,\n });\n }\n }\n }\n\n private async seedNodeModulesFromMain(workDir: string): Promise<boolean> {\n const targetBin = path.join(workDir, 'node_modules', '.bin');\n try {\n await fs.access(targetBin);\n logger.info('Worktree node_modules already complete (has .bin/), skipping seed');\n return false;\n } catch {\n // .bin/ missing — dependencies incomplete, need to seed from main repo\n }\n\n const sourceNM = path.join(this.config.project.workDir, 'node_modules');\n const targetNM = path.join(workDir, 'node_modules');\n try {\n await fs.access(sourceNM);\n } catch {\n logger.warn('Main repo node_modules not found, skipping seed', { sourceNM });\n return false;\n }\n\n logger.info('Seeding node_modules from main repo via reflink copy', { sourceNM, targetNM });\n try {\n await execFileAsync('rm', ['-rf', targetNM], { timeout: 60_000 });\n // btrfs reflink: zero-copy CoW, near-instant; falls back to regular copy on non-btrfs\n await execFileAsync('cp', ['-a', '--reflink=auto', sourceNM, targetNM], {\n timeout: 120_000,\n });\n logger.info('node_modules seeded from main repo');\n return true;\n } catch (err) {\n logger.warn('Failed to seed node_modules from main repo', {\n error: (err as Error).message,\n });\n return false;\n }\n }\n\n async restartIssue(issueIid: number): Promise<void> {\n const record = this.tracker.get(issueIid);\n if (!record) throw new Error(`Issue ${issueIid} not found in tracker`);\n\n const wtCtx = this.computeWorktreeContext(issueIid, record.branchName);\n logger.info('Restarting issue — cleaning context', { issueIid, branchName: record.branchName });\n\n this.stopPreviewServers(issueIid);\n\n try {\n const deleted = await this.gongfeng.cleanupAgentNotes(record.issueId);\n logger.info('Agent notes cleaned up', { issueIid, deleted });\n } catch (err) {\n logger.warn('Failed to cleanup agent notes', { issueIid, error: (err as Error).message });\n }\n\n await this.mainGitMutex.runExclusive(async () => {\n await this.cleanupWorktree(wtCtx);\n try { await this.mainGit.deleteBranch(record.branchName); } catch { /* branch may not exist */ }\n try { await this.mainGit.deleteRemoteBranch(record.branchName); } catch { /* remote branch may not exist */ }\n });\n\n this.tracker.resetFull(issueIid);\n logger.info('Issue restarted', { issueIid });\n }\n\n retryFromPhase(issueIid: number, phase: string): void {\n const record = this.tracker.get(issueIid);\n if (!record) throw new Error(`Issue ${issueIid} not found in tracker`);\n\n const issueDef = this.getIssueSpecificPipelineDef(record);\n const spec = issueDef.phases.find(p => p.name === phase);\n if (!spec || spec.kind !== 'ai') {\n throw new Error(`Invalid phase for retry: ${phase}`);\n }\n\n logger.info('Retrying issue from phase', { issueIid, phase });\n this.tracker.resetToPhase(issueIid, phase, issueDef);\n }\n\n private getIssueSpecificPipelineDef(record: { pipelineMode?: string }): PipelineDef {\n if (record.pipelineMode === 'plan-mode' || record.pipelineMode === 'classic') {\n return getPipelineDef(record.pipelineMode);\n }\n return this.pipelineDef;\n }\n\n async processIssue(issue: GongfengIssue): Promise<void> {\n const branchName = `${this.config.project.branchPrefix}-${issue.iid}`;\n const wtCtx = this.computeWorktreeContext(issue.iid, branchName);\n\n logger.info('Processing issue', { iid: issue.iid, title: issue.title, branchName, worktree: wtCtx.gitRootDir });\n\n let record = this.tracker.get(issue.iid);\n const isRetry = record?.state === IssueState.Failed;\n\n if (!record) {\n record = this.tracker.create({\n issueId: issue.id,\n issueIid: issue.iid,\n issueTitle: issue.title,\n state: IssueState.Pending,\n branchName,\n pipelineMode: this.pipelineDef.mode,\n });\n }\n\n if (!record.pipelineMode) {\n this.tracker.updateState(issue.iid, record.state, { pipelineMode: this.pipelineDef.mode } as any);\n record.pipelineMode = this.pipelineDef.mode;\n }\n\n const issuePipelineDef = this.getIssueSpecificPipelineDef(record);\n\n try {\n await this.gongfeng.updateIssueLabels(issue.id, [\n ...issue.labels.filter(l => !l.startsWith('auto-finish:')),\n 'auto-finish:processing',\n ]);\n } catch (err) {\n logger.warn('Failed to update issue labels', { error: (err as Error).message });\n }\n\n try {\n await this.gongfeng.createIssueNote(\n issue.id,\n isRetry\n ? t('orchestrator.retryComment')\n : t('orchestrator.startComment')\n );\n } catch {\n // ignore\n }\n\n const supplementText = this.supplementStore?.toPromptText(issue.iid) ?? '';\n const ctx: PhaseContext = {\n issueIid: issue.iid,\n issueId: issue.id,\n issueTitle: issue.title,\n issueDescription: issue.description || '',\n branchName,\n supplementText: supplementText || undefined,\n pipelineMode: issuePipelineDef.mode,\n };\n\n try {\n await this.mainGitMutex.runExclusive(async () => {\n this.emitProgress(issue.iid, 'fetch', t('orchestrator.fetchProgress'));\n await this.mainGit.fetch();\n this.emitProgress(issue.iid, 'worktree', t('orchestrator.worktreeProgress'));\n await this.ensureWorktree(wtCtx);\n });\n if (record.state === IssueState.Pending) {\n this.tracker.updateState(issue.iid, IssueState.BranchCreated);\n }\n\n this.emitProgress(issue.iid, 'install', t('orchestrator.installProgress'));\n await this.installDependencies(wtCtx.workDir);\n\n this.emitProgress(issue.iid, 'init_plan', t('orchestrator.initPlanProgress'));\n const wtGit = new GitOperations(wtCtx.gitRootDir);\n const wtPlan = new PlanPersistence(wtCtx.workDir, issue.iid);\n\n wtPlan.ensureDir();\n wtPlan.writeIssueMeta({\n id: issue.id,\n iid: issue.iid,\n title: issue.title,\n labels: issue.labels,\n state: issue.state,\n });\n\n const existingProgress = wtPlan.readProgress();\n if (!existingProgress) {\n wtPlan.writeProgress(\n wtPlan.createInitialProgress(issue.id, issue.title, branchName, issuePipelineDef)\n );\n }\n\n const startIdx = this.determineStartIndex(record.state, isRetry ? record.failedAtState : undefined, issuePipelineDef);\n\n this.emitProgress(issue.iid, 'phase_start', t('orchestrator.phaseStartProgress', { phase: issuePipelineDef.phases[startIdx]?.name ?? 'start' }));\n\n const needsDeployment = this.shouldDeployServers(issue.iid);\n let serversStarted = false;\n\n for (let i = startIdx; i < issuePipelineDef.phases.length; i++) {\n const spec = issuePipelineDef.phases[i];\n\n if (spec.kind === 'gate') {\n if (this.shouldAutoApprove(issue.labels)) {\n logger.info('Auto-approving review gate (matched autoApproveLabels)', {\n iid: issue.iid,\n labels: issue.labels,\n autoApproveLabels: this.config.review.autoApproveLabels,\n });\n if (spec.approvedState) {\n this.tracker.updateState(issue.iid, spec.approvedState);\n }\n wtPlan.updatePhaseProgress(spec.name, 'completed');\n try {\n await this.gongfeng.createIssueNote(\n issue.id,\n t('orchestrator.autoApproveComment'),\n );\n } catch { /* ignore */ }\n continue;\n }\n\n this.tracker.updateState(issue.iid, spec.startState);\n wtPlan.updatePhaseProgress(spec.name, 'in_progress');\n eventBus.emitTyped('review:requested', { issueIid: issue.iid });\n logger.info('Review gate reached, pausing', { iid: issue.iid });\n return;\n }\n\n const phase = createPhase(spec.name, this.aiRunner, wtGit, wtPlan, this.gongfeng, this.tracker, this.config);\n await phase.execute(ctx);\n\n if (needsDeployment && !serversStarted && this.isImplementDonePhase(spec.name, spec.doneState)) {\n const ports = await this.startPreviewServers(wtCtx, issue);\n if (ports) {\n ctx.ports = ports;\n wtCtx.ports = ports;\n serversStarted = true;\n }\n }\n }\n\n this.emitProgress(issue.iid, 'create_mr', t('orchestrator.createMrProgress'));\n const previewUrl = this.buildPreviewUrl(issue.iid);\n const mrResult = await this.tryCreateMergeRequest(issue, branchName, wtCtx.workDir, previewUrl);\n const mrUrl = mrResult?.url ?? null;\n\n this.tracker.updateState(issue.iid, IssueState.Completed, mrUrl ? { mrUrl } : undefined);\n\n try {\n await this.gongfeng.updateIssueLabels(issue.id, [\n ...issue.labels.filter(l => !l.startsWith('auto-finish:') && l !== 'auto-finish'),\n 'auto-finish:done',\n ]);\n } catch {\n // ignore\n }\n\n if (isE2eEnabledForIssue(issue.iid, this.tracker, this.config)) {\n this.emitProgress(issue.iid, 'screenshots', t('orchestrator.uploadScreenshotsProgress'));\n try {\n await this.screenshotPublisher.publish({\n workDir: wtCtx.workDir,\n issueIid: issue.iid,\n issueId: issue.id,\n mrIid: mrResult?.iid,\n });\n } catch (err) {\n logger.warn('Failed to publish E2E screenshots', {\n iid: issue.iid,\n error: (err as Error).message,\n });\n }\n }\n\n const mrSection = mrUrl\n ? t('orchestrator.mrSection', { mrUrl })\n : t('orchestrator.mrFailSection');\n const previewSection = previewUrl ? `\\n🌐 Preview: ${previewUrl}` : '';\n try {\n await this.gongfeng.createIssueNote(\n issue.id,\n t('orchestrator.completedComment', { branch: branchName, mrSection, previewSection })\n );\n } catch {\n // ignore\n }\n\n if (serversStarted && this.config.preview.keepAfterComplete) {\n logger.info('Preview servers kept running after completion', { iid: issue.iid });\n } else {\n this.stopPreviewServers(issue.iid);\n await this.mainGitMutex.runExclusive(() => this.cleanupWorktree(wtCtx));\n }\n\n logger.info('Issue processing completed', { iid: issue.iid });\n } catch (err) {\n const errorMsg = (err as Error).message;\n logger.error('Issue processing failed', { iid: issue.iid, error: errorMsg });\n\n const currentRecord = this.tracker.get(issue.iid);\n const failedAtState = currentRecord?.state || IssueState.Pending;\n if (failedAtState !== IssueState.Failed) {\n this.tracker.markFailed(issue.iid, errorMsg.slice(0, 500), failedAtState);\n }\n\n try {\n await this.gongfeng.updateIssueLabels(issue.id, [\n ...issue.labels.filter(l => !l.startsWith('auto-finish:') && l !== 'auto-finish'),\n 'auto-finish', 'auto-finish:failed',\n ]);\n } catch {\n // ignore\n }\n\n try {\n await this.gongfeng.createIssueNote(\n issue.id,\n t('orchestrator.failedComment', { error: errorMsg })\n );\n } catch {\n // ignore\n }\n\n logger.info('Worktree preserved for debugging', { dir: wtCtx.gitRootDir });\n throw err;\n }\n }\n\n private async tryCreateMergeRequest(\n issue: GongfengIssue,\n branchName: string,\n workDir: string,\n previewUrl?: string | null,\n ): Promise<MergeRequestResult | null> {\n try {\n const supplement = this.supplementStore?.get(issue.iid);\n const tapdId = supplement?.tapdId?.trim()\n || extractTapdId(issue.description || '');\n\n const title = generateMRTitle(issue.iid, issue.title, tapdId);\n let description = generateMRDescription({\n issueIid: issue.iid,\n issueTitle: issue.title,\n issueDescription: issue.description || '',\n branchName,\n planDir: workDir,\n });\n\n if (previewUrl) {\n description += `\\n\\n## Preview Environment\\n\\n🌐 ${previewUrl}`;\n }\n\n const mr = await this.gongfeng.createMergeRequest({\n sourceBranch: branchName,\n targetBranch: this.config.project.baseBranch,\n title,\n description,\n });\n\n logger.info('Merge request created successfully', {\n iid: issue.iid, mrIid: mr.iid, mrUrl: mr.web_url,\n });\n return { url: mr.web_url, iid: mr.iid };\n } catch (err) {\n const errorMsg = (err as Error).message;\n logger.warn('Failed to create merge request, trying to find existing one', {\n iid: issue.iid, error: errorMsg,\n });\n\n if (errorMsg.includes('already exists')) {\n return this.tryFindExistingMergeRequest(issue.iid, branchName);\n }\n return null;\n }\n }\n\n private async tryFindExistingMergeRequest(\n issueIid: number,\n branchName: string,\n ): Promise<MergeRequestResult | null> {\n try {\n const existing = await this.gongfeng.findMergeRequestByBranch(\n branchName,\n this.config.project.baseBranch,\n );\n if (existing) {\n logger.info('Found existing merge request', {\n iid: issueIid, mrIid: existing.iid, mrUrl: existing.web_url,\n });\n return { url: existing.web_url, iid: existing.iid };\n }\n } catch (findErr) {\n logger.warn('Failed to find existing merge request', {\n iid: issueIid, error: (findErr as Error).message,\n });\n }\n return null;\n }\n\n private determineStartIndex(\n state: IssueState,\n failedAtState: IssueState | undefined,\n def: PipelineDef,\n ): number {\n const target = failedAtState || state;\n\n for (let i = def.phases.length - 1; i >= 0; i--) {\n const spec = def.phases[i];\n\n if (spec.kind === 'gate' && spec.approvedState === target) {\n return i + 1;\n }\n\n if (spec.startState === target || spec.doneState === target) {\n return spec.doneState === target ? i + 1 : i;\n }\n }\n return 0;\n }\n\n private shouldDeployServers(issueIid: number): boolean {\n return isE2eEnabledForIssue(issueIid, this.tracker, this.config)\n || this.config.preview.enabled;\n }\n\n private shouldAutoApprove(issueLabels: string[]): boolean {\n const autoLabels = this.config.review.autoApproveLabels;\n if (!autoLabels.length) return false;\n return issueLabels.some(l => autoLabels.includes(l));\n }\n\n private isImplementDonePhase(phaseName: string, doneState: IssueState): boolean {\n return doneState === IssueState.ImplementDone\n || doneState === IssueState.BuildDone;\n }\n\n private async startPreviewServers(\n wtCtx: WorktreeContext,\n issue: GongfengIssue,\n ): Promise<PortPair | null> {\n try {\n this.emitProgress(issue.iid, 'deploy', t('orchestrator.deployProgress'));\n const ports = await this.portAllocator.allocate(issue.iid);\n wtCtx.ports = ports;\n\n this.tracker.updateState(issue.iid, this.tracker.get(issue.iid)!.state, {\n ports,\n previewStartedAt: new Date().toISOString(),\n } as any);\n\n await this.devServerManager.startServers(wtCtx, ports);\n\n const previewUrl = this.buildPreviewUrl(issue.iid);\n if (previewUrl) {\n try {\n await this.gongfeng.createIssueNote(\n issue.id,\n this.buildPreviewComment(ports, previewUrl),\n );\n } catch {\n // ignore comment failure\n }\n }\n\n this.emitProgress(issue.iid, 'deploy_done', t('orchestrator.deployDoneProgress', { url: previewUrl ?? 'N/A' }));\n eventBus.emitTyped('pipeline:progress', {\n issueIid: issue.iid,\n step: 'preview_ready',\n message: previewUrl ?? '',\n });\n\n return ports;\n } catch (err) {\n logger.error('Failed to start preview servers', {\n iid: issue.iid,\n error: (err as Error).message,\n });\n return null;\n }\n }\n\n stopPreviewServers(issueIid: number): void {\n this.devServerManager.stopServers(issueIid);\n this.portAllocator.release(issueIid);\n const record = this.tracker.get(issueIid);\n if (record?.ports) {\n this.tracker.updateState(issueIid, record.state, {\n ports: undefined,\n previewStartedAt: undefined,\n } as any);\n }\n }\n\n getPreviewHost(): string {\n if (this.config.preview.host) return this.config.preview.host;\n const interfaces = os.networkInterfaces();\n for (const addrs of Object.values(interfaces)) {\n for (const addr of addrs ?? []) {\n if (addr.family === 'IPv4' && !addr.internal) {\n return addr.address;\n }\n }\n }\n return 'localhost';\n }\n\n buildPreviewUrl(issueIid: number): string | null {\n const ports = this.portAllocator.getPortsForIssue(issueIid);\n if (!ports) return null;\n const host = this.getPreviewHost();\n return `https://${host}:${ports.frontendPort}`;\n }\n\n private buildPreviewComment(ports: PortPair, previewUrl: string): string {\n const host = this.getPreviewHost();\n const ttlHours = Math.round(this.config.preview.ttlMs / (60 * 60 * 1000));\n return [\n t('orchestrator.previewComment.title'),\n '',\n t('orchestrator.previewComment.tableHeader'),\n t('orchestrator.previewComment.tableSep'),\n `| ${t('orchestrator.previewComment.frontend')} | ${previewUrl} |`,\n `| ${t('orchestrator.previewComment.backendApi')} | http://${host}:${ports.backendPort}/api |`,\n '',\n t('orchestrator.previewComment.hint'),\n t('orchestrator.previewComment.expiry', { hours: ttlHours }),\n ].join('\\n');\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { t } from '../i18n/index.js';\n\nconst TAPD_PATTERNS = [\n /--story=(\\d+)/i,\n /--bug=(\\d+)/i,\n /tapd[:\\s-]+(\\d+)/i,\n /tapd单号[:\\s]*(\\d+)/i,\n];\n\nexport function extractTapdId(text: string): string | null {\n for (const pattern of TAPD_PATTERNS) {\n const match = text.match(pattern);\n if (match) return match[1];\n }\n return null;\n}\n\nexport function generateMRTitle(issueIid: number, issueTitle: string, tapdId?: string | null): string {\n const base = `feat(#${issueIid}): ${issueTitle}`;\n if (tapdId) {\n return `${base} --story=${tapdId}`;\n }\n return base;\n}\n\nexport function generateMRDescription(options: {\n issueIid: number;\n issueTitle: string;\n issueDescription: string;\n branchName: string;\n planDir?: string;\n}): string {\n const { issueIid, issueTitle, issueDescription, branchName, planDir } = options;\n\n const sections: string[] = [\n t('mr.relatedIssue'),\n ``,\n `- Issue: #${issueIid}`,\n `- ${t('mr.title')}: ${issueTitle}`,\n `- ${t('mr.branch')}: \\`${branchName}\\``,\n ``,\n t('mr.issueDescription'),\n ``,\n issueDescription || t('mr.noDescription'),\n ];\n\n if (planDir) {\n const summaryFiles = [\n { filename: '01-analysis.md', label: t('mr.summaryFiles.01-analysis.md') },\n { filename: '01-plan.md', label: t('mr.summaryFiles.01-plan.md') },\n { filename: '02-design.md', label: t('mr.summaryFiles.02-design.md') },\n { filename: '04-verify-report.md', label: t('mr.summaryFiles.04-verify-report.md') },\n { filename: '02-verify-report.md', label: t('mr.summaryFiles.02-verify-report.md') },\n ];\n\n const planSections: string[] = [];\n for (const { filename, label } of summaryFiles) {\n const filePath = path.join(planDir, '.claude-plan', `issue-${issueIid}`, filename);\n if (fs.existsSync(filePath)) {\n const content = fs.readFileSync(filePath, 'utf-8');\n const summary = extractSummary(content);\n if (summary) {\n planSections.push(`### ${label}\\n\\n${summary}`);\n }\n }\n }\n\n if (planSections.length > 0) {\n sections.push('', t('mr.aiSummary'), '', ...planSections);\n }\n }\n\n sections.push('', '---', t('mr.autoCreated'));\n return sections.join('\\n');\n}\n\nfunction extractSummary(content: string, maxLines = 20): string {\n const lines = content.split('\\n');\n if (lines.length <= maxLines) return content.trim();\n return lines.slice(0, maxLines).join('\\n').trim() + '\\n\\n' + t('mr.truncated');\n}\n","import net from 'node:net';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('PortAllocator');\n\nexport interface PortPair {\n backendPort: number;\n frontendPort: number;\n}\n\nexport interface PortAllocatorOptions {\n backendPortBase: number;\n frontendPortBase: number;\n maxPorts: number;\n}\n\nconst DEFAULT_OPTIONS: PortAllocatorOptions = {\n backendPortBase: 4000,\n frontendPortBase: 9000,\n maxPorts: 100,\n};\n\nfunction checkPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once('error', () => resolve(false));\n server.once('listening', () => {\n server.close(() => resolve(true));\n });\n server.listen(port, '0.0.0.0');\n });\n}\n\nexport class PortAllocator {\n private allocated = new Map<number, PortPair>();\n private options: PortAllocatorOptions;\n\n constructor(options?: Partial<PortAllocatorOptions>) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n async allocate(issueIid: number): Promise<PortPair> {\n const existing = this.allocated.get(issueIid);\n if (existing) {\n logger.info('Returning already allocated ports', { issueIid, ports: existing });\n return existing;\n }\n\n const usedBackend = new Set([...this.allocated.values()].map((p) => p.backendPort));\n const usedFrontend = new Set([...this.allocated.values()].map((p) => p.frontendPort));\n\n for (let offset = 1; offset <= this.options.maxPorts; offset++) {\n const backendPort = this.options.backendPortBase + offset;\n const frontendPort = this.options.frontendPortBase + offset;\n\n if (usedBackend.has(backendPort) || usedFrontend.has(frontendPort)) {\n continue;\n }\n\n const [beOk, feOk] = await Promise.all([\n checkPortAvailable(backendPort),\n checkPortAvailable(frontendPort),\n ]);\n\n if (beOk && feOk) {\n const pair: PortPair = { backendPort, frontendPort };\n this.allocated.set(issueIid, pair);\n logger.info('Ports allocated', { issueIid, ...pair });\n return pair;\n }\n\n logger.debug('Port pair unavailable, trying next', {\n backendPort,\n frontendPort,\n beOk,\n feOk,\n });\n }\n\n throw new Error(\n `No available port pair found for issue #${issueIid} ` +\n `(scanned ${this.options.maxPorts} offsets from ` +\n `backend=${this.options.backendPortBase} frontend=${this.options.frontendPortBase})`,\n );\n }\n\n release(issueIid: number): void {\n const pair = this.allocated.get(issueIid);\n if (pair) {\n this.allocated.delete(issueIid);\n logger.info('Ports released', { issueIid, ...pair });\n }\n }\n\n getPortsForIssue(issueIid: number): PortPair | undefined {\n return this.allocated.get(issueIid);\n }\n\n getAllAllocated(): Map<number, PortPair> {\n return new Map(this.allocated);\n }\n\n restore(issueIid: number, ports: PortPair): void {\n this.allocated.set(issueIid, ports);\n logger.info('Ports restored from persistence', { issueIid, ...ports });\n }\n}\n","import { spawn, ChildProcess } from 'node:child_process';\nimport path from 'node:path';\nimport https from 'node:https';\nimport http from 'node:http';\nimport type { PortPair } from './PortAllocator.js';\nimport type { WorktreeContext } from '../git/WorktreeContext.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('DevServerManager');\n\ninterface ServerSet {\n backend: ChildProcess;\n frontend: ChildProcess;\n ports: PortPair;\n workDir: string;\n startedAt: string;\n}\n\nexport interface DevServerManagerOptions {\n healthCheckTimeoutMs: number;\n healthCheckIntervalMs: number;\n}\n\nconst DEFAULT_OPTIONS: DevServerManagerOptions = {\n healthCheckTimeoutMs: 120_000,\n healthCheckIntervalMs: 3_000,\n};\n\nfunction waitForPort(\n port: number,\n useTls: boolean,\n timeoutMs: number,\n intervalMs: number,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs;\n\n const check = () => {\n if (Date.now() > deadline) {\n reject(new Error(`Port ${port} not ready after ${timeoutMs}ms`));\n return;\n }\n\n const req = useTls\n ? https.get(\n { hostname: '127.0.0.1', port, path: '/', rejectUnauthorized: false, timeout: 5_000 },\n (res) => { res.resume(); resolve(); },\n )\n : http.get(\n { hostname: '127.0.0.1', port, path: '/', timeout: 5_000 },\n (res) => { res.resume(); resolve(); },\n );\n\n req.on('error', () => {\n setTimeout(check, intervalMs);\n });\n req.on('timeout', () => {\n req.destroy();\n setTimeout(check, intervalMs);\n });\n };\n\n check();\n });\n}\n\nexport class DevServerManager {\n private servers = new Map<number, ServerSet>();\n private options: DevServerManagerOptions;\n\n constructor(options?: Partial<DevServerManagerOptions>) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n async startServers(wtCtx: WorktreeContext, ports: PortPair): Promise<void> {\n if (this.servers.has(wtCtx.issueIid)) {\n logger.info('Servers already running for issue', { issueIid: wtCtx.issueIid });\n return;\n }\n\n logger.info('Starting dev servers', { issueIid: wtCtx.issueIid, ...ports });\n\n const backendEnv: Record<string, string> = {\n ...process.env as Record<string, string>,\n PORT: String(ports.backendPort),\n E2E_PORT_OVERRIDE: '1',\n ENV_PATH: '.env.development.local',\n };\n\n const backend = spawn('node', ['ace', 'serve', '--watch'], {\n cwd: wtCtx.workDir,\n env: backendEnv,\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n backend.stdout?.on('data', (data: Buffer) => {\n logger.debug(`[BE #${wtCtx.issueIid}] ${data.toString().trimEnd()}`);\n });\n backend.stderr?.on('data', (data: Buffer) => {\n logger.debug(`[BE #${wtCtx.issueIid} ERR] ${data.toString().trimEnd()}`);\n });\n backend.on('exit', (code) => {\n logger.info('Backend process exited', { issueIid: wtCtx.issueIid, code });\n });\n\n const frontendDir = path.join(wtCtx.workDir, 'frontend');\n const frontendEnv: Record<string, string> = {\n ...process.env as Record<string, string>,\n BACKEND_PORT: String(ports.backendPort),\n FRONTEND_PORT: String(ports.frontendPort),\n };\n\n const frontend = spawn('pnpm', ['dev', '--', '--port', String(ports.frontendPort)], {\n cwd: frontendDir,\n env: frontendEnv,\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n frontend.stdout?.on('data', (data: Buffer) => {\n logger.debug(`[FE #${wtCtx.issueIid}] ${data.toString().trimEnd()}`);\n });\n frontend.stderr?.on('data', (data: Buffer) => {\n logger.debug(`[FE #${wtCtx.issueIid} ERR] ${data.toString().trimEnd()}`);\n });\n frontend.on('exit', (code) => {\n logger.info('Frontend process exited', { issueIid: wtCtx.issueIid, code });\n });\n\n const serverSet: ServerSet = {\n backend,\n frontend,\n ports,\n workDir: wtCtx.workDir,\n startedAt: new Date().toISOString(),\n };\n this.servers.set(wtCtx.issueIid, serverSet);\n\n logger.info('Waiting for servers to become healthy', { issueIid: wtCtx.issueIid });\n\n try {\n await Promise.all([\n waitForPort(\n ports.backendPort,\n false,\n this.options.healthCheckTimeoutMs,\n this.options.healthCheckIntervalMs,\n ),\n waitForPort(\n ports.frontendPort,\n true,\n this.options.healthCheckTimeoutMs,\n this.options.healthCheckIntervalMs,\n ),\n ]);\n logger.info('Dev servers healthy', { issueIid: wtCtx.issueIid, ...ports });\n } catch (err) {\n logger.error('Dev servers failed health check, cleaning up', {\n issueIid: wtCtx.issueIid,\n error: (err as Error).message,\n });\n this.stopServers(wtCtx.issueIid);\n throw err;\n }\n }\n\n stopServers(issueIid: number): void {\n const set = this.servers.get(issueIid);\n if (!set) return;\n\n logger.info('Stopping dev servers', { issueIid, ports: set.ports });\n\n killProcess(set.backend, `backend #${issueIid}`);\n killProcess(set.frontend, `frontend #${issueIid}`);\n\n this.servers.delete(issueIid);\n }\n\n stopAll(): void {\n for (const [iid] of this.servers) {\n this.stopServers(iid);\n }\n }\n\n getStatus(issueIid: number): { running: boolean; ports?: PortPair; startedAt?: string } {\n const set = this.servers.get(issueIid);\n if (!set) return { running: false };\n return {\n running: true,\n ports: set.ports,\n startedAt: set.startedAt,\n };\n }\n\n getRunningIssues(): number[] {\n return [...this.servers.keys()];\n }\n}\n\nfunction killProcess(proc: ChildProcess, label: string): void {\n try {\n if (proc.killed || proc.exitCode !== null) return;\n proc.kill('SIGTERM');\n setTimeout(() => {\n if (!proc.killed && proc.exitCode === null) {\n logger.warn(`Force killing ${label}`);\n proc.kill('SIGKILL');\n }\n }, 5_000);\n } catch (err) {\n logger.warn(`Failed to kill ${label}`, { error: (err as Error).message });\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('ScreenshotCollector');\n\nconst MAX_SCREENSHOTS = 20;\n\nexport interface ScreenshotFile {\n filePath: string;\n testName: string;\n}\n\nfunction walkDir(dir: string, files: string[] = []): string[] {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkDir(full, files);\n } else if (entry.isFile() && entry.name.endsWith('.png')) {\n files.push(full);\n }\n }\n return files;\n}\n\n/**\n * 从 worktree 的 frontend/test-results/ 目录收集 E2E 截图。\n * Playwright 以 `screenshot: 'on'` 运行时,每个测试的截图保存在\n * `test-results/<project>-<test-name>-<browser>/` 子目录下。\n */\nexport function collectScreenshots(workDir: string): ScreenshotFile[] {\n const testResultsDir = path.join(workDir, 'frontend', 'test-results');\n if (!fs.existsSync(testResultsDir)) {\n logger.debug('test-results directory not found', { dir: testResultsDir });\n return [];\n }\n\n const pngFiles = walkDir(testResultsDir);\n if (pngFiles.length === 0) {\n logger.debug('No screenshots found');\n return [];\n }\n\n const screenshots: ScreenshotFile[] = pngFiles.map((filePath) => {\n const relative = path.relative(testResultsDir, filePath);\n const testName = relative.split(path.sep)[0] || path.basename(filePath, '.png');\n return { filePath, testName };\n });\n\n if (screenshots.length > MAX_SCREENSHOTS) {\n logger.warn('Too many screenshots, truncating', {\n total: screenshots.length,\n max: MAX_SCREENSHOTS,\n });\n return screenshots.slice(0, MAX_SCREENSHOTS);\n }\n\n logger.info('Screenshots collected', { count: screenshots.length });\n return screenshots;\n}\n","import { GongfengClient, UploadResult } from '../clients/GongfengClient.js';\nimport { collectScreenshots, ScreenshotFile } from './ScreenshotCollector.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('ScreenshotPublisher');\n\nexport interface PublishOptions {\n workDir: string;\n issueIid: number;\n issueId: number;\n mrIid?: number;\n}\n\ninterface UploadedScreenshot {\n testName: string;\n markdown: string;\n}\n\nfunction buildComment(uploaded: UploadedScreenshot[], truncated: boolean): string {\n const lines: string[] = [t('screenshot.title'), ''];\n\n for (const item of uploaded) {\n lines.push(`### ${item.testName}`, '', item.markdown, '');\n }\n\n if (truncated) {\n lines.push(t('screenshot.truncated'), '');\n }\n\n return lines.join('\\n');\n}\n\nexport class ScreenshotPublisher {\n constructor(private gongfeng: GongfengClient) {}\n\n async publish(options: PublishOptions): Promise<void> {\n const { workDir, issueIid, issueId, mrIid } = options;\n\n const screenshots = collectScreenshots(workDir);\n if (screenshots.length === 0) {\n logger.info('No E2E screenshots to publish', { issueIid });\n return;\n }\n\n const uploaded = await this.uploadAll(screenshots);\n if (uploaded.length === 0) {\n logger.warn('All screenshot uploads failed', { issueIid });\n return;\n }\n\n const truncated = screenshots.length >= 20;\n const comment = buildComment(uploaded, truncated);\n\n await this.postToIssue(issueId, comment);\n\n if (mrIid) {\n await this.postToMergeRequest(mrIid, comment);\n }\n\n logger.info('E2E screenshots published', {\n issueIid,\n mrIid,\n count: uploaded.length,\n });\n }\n\n private async uploadAll(screenshots: ScreenshotFile[]): Promise<UploadedScreenshot[]> {\n const results: UploadedScreenshot[] = [];\n\n for (const screenshot of screenshots) {\n try {\n const result: UploadResult = await this.gongfeng.uploadFile(screenshot.filePath);\n results.push({\n testName: screenshot.testName,\n markdown: result.markdown,\n });\n } catch (err) {\n logger.warn('Failed to upload screenshot', {\n filePath: screenshot.filePath,\n error: (err as Error).message,\n });\n }\n }\n\n return results;\n }\n\n private async postToIssue(issueId: number, comment: string): Promise<void> {\n try {\n await this.gongfeng.createIssueNote(issueId, comment);\n } catch (err) {\n logger.warn('Failed to post screenshots to issue', {\n issueId,\n error: (err as Error).message,\n });\n }\n }\n\n private async postToMergeRequest(mrIid: number, comment: string): Promise<void> {\n try {\n await this.gongfeng.createMergeRequestNote(mrIid, comment);\n } catch (err) {\n logger.warn('Failed to post screenshots to merge request', {\n mrIid,\n error: (err as Error).message,\n });\n }\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport { logger as rootLogger } from '../logger.js';\nimport type { AIRunner, RunResult, StreamEvent } from '../ai-runner/AIRunner.js';\nimport { createAIRunner, type AIConfig } from '../ai-runner/index.js';\nimport type { BrainstormAgentConfig, Config } from '../config.js';\nimport {\n buildGeneratePrompt,\n buildReviewPrompt,\n buildRefinePrompt,\n} from '../prompts/brainstorm-templates.js';\n\nconst logger = rootLogger.child('Brainstorm');\n\nexport interface BrainstormRound {\n round: number;\n questions: string;\n refinedSdd: string;\n}\n\nexport type BrainstormStatus =\n | 'idle'\n | 'generating'\n | 'reviewing'\n | 'refining'\n | 'done'\n | 'error';\n\nexport interface BrainstormSession {\n id: string;\n transcript: string;\n currentSdd: string;\n rounds: BrainstormRound[];\n status: BrainstormStatus;\n error?: string;\n generatorSessionId?: string;\n createdAt: string;\n}\n\nexport interface BrainstormStreamEvent {\n type: 'sdd:chunk' | 'sdd:complete' | 'review:chunk' | 'review:complete'\n | 'round:start' | 'round:complete' | 'error';\n data: unknown;\n round?: number;\n}\n\nfunction agentConfigToAIConfig(\n agentCfg: BrainstormAgentConfig,\n timeoutMs: number,\n): AIConfig {\n return {\n mode: agentCfg.mode,\n binary: agentCfg.binary,\n phaseTimeoutMs: timeoutMs,\n nvmNodeVersion: agentCfg.nvmNodeVersion,\n model: agentCfg.model,\n };\n}\n\nexport class BrainstormService {\n private sessions = new Map<string, BrainstormSession>();\n private generatorRunner: AIRunner;\n private reviewerRunner: AIRunner;\n private config: Config['brainstorm'];\n private workDir: string;\n\n constructor(config: Config) {\n this.config = config.brainstorm;\n this.workDir = config.project.workDir;\n this.generatorRunner = createAIRunner(\n agentConfigToAIConfig(this.config.generator, this.config.timeoutMs),\n );\n this.reviewerRunner = createAIRunner(\n agentConfigToAIConfig(this.config.reviewer, this.config.timeoutMs),\n );\n }\n\n createSession(transcript: string): BrainstormSession {\n const session: BrainstormSession = {\n id: randomUUID(),\n transcript,\n currentSdd: '',\n rounds: [],\n status: 'idle',\n createdAt: new Date().toISOString(),\n };\n this.sessions.set(session.id, session);\n logger.info('Created brainstorm session', { sessionId: session.id });\n return session;\n }\n\n getSession(id: string): BrainstormSession | undefined {\n return this.sessions.get(id);\n }\n\n async generate(\n sessionId: string,\n onEvent?: (event: BrainstormStreamEvent) => void,\n ): Promise<RunResult> {\n const session = this.requireSession(sessionId);\n session.status = 'generating';\n logger.info('Generating SDD', { sessionId });\n\n const prompt = buildGeneratePrompt(session.transcript);\n const result = await this.generatorRunner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.config.timeoutMs,\n onStreamEvent: (evt: StreamEvent) => {\n onEvent?.({ type: 'sdd:chunk', data: evt });\n },\n });\n\n if (result.success) {\n session.currentSdd = result.output;\n session.generatorSessionId = result.sessionId;\n session.status = 'idle';\n onEvent?.({ type: 'sdd:complete', data: { sdd: result.output } });\n } else {\n session.status = 'error';\n session.error = result.output;\n onEvent?.({ type: 'error', data: { message: result.output } });\n }\n\n return result;\n }\n\n async review(\n sessionId: string,\n onEvent?: (event: BrainstormStreamEvent) => void,\n ): Promise<RunResult> {\n const session = this.requireSession(sessionId);\n const roundNum = session.rounds.length + 1;\n session.status = 'reviewing';\n logger.info('Reviewing SDD', { sessionId, round: roundNum });\n onEvent?.({ type: 'round:start', data: { round: roundNum, phase: 'review' }, round: roundNum });\n\n const prompt = buildReviewPrompt(session.currentSdd, roundNum);\n const result = await this.reviewerRunner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.config.timeoutMs,\n onStreamEvent: (evt: StreamEvent) => {\n onEvent?.({ type: 'review:chunk', data: evt, round: roundNum });\n },\n });\n\n if (result.success) {\n session.rounds.push({\n round: roundNum,\n questions: result.output,\n refinedSdd: '',\n });\n session.status = 'idle';\n onEvent?.({ type: 'review:complete', data: { round: roundNum, questions: result.output }, round: roundNum });\n } else {\n session.status = 'error';\n session.error = result.output;\n onEvent?.({ type: 'error', data: { message: result.output, round: roundNum }, round: roundNum });\n }\n\n return result;\n }\n\n async refine(\n sessionId: string,\n onEvent?: (event: BrainstormStreamEvent) => void,\n ): Promise<RunResult> {\n const session = this.requireSession(sessionId);\n const currentRound = session.rounds[session.rounds.length - 1];\n if (!currentRound) {\n throw new Error('No review round to refine from');\n }\n\n session.status = 'refining';\n logger.info('Refining SDD', { sessionId, round: currentRound.round });\n\n const prompt = buildRefinePrompt(currentRound.questions);\n const result = await this.generatorRunner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.config.timeoutMs,\n sessionId: session.generatorSessionId,\n continueSession: !!session.generatorSessionId,\n onStreamEvent: (evt: StreamEvent) => {\n onEvent?.({ type: 'sdd:chunk', data: evt, round: currentRound.round });\n },\n });\n\n if (result.success) {\n currentRound.refinedSdd = result.output;\n session.currentSdd = result.output;\n session.generatorSessionId = result.sessionId ?? session.generatorSessionId;\n session.status = 'idle';\n onEvent?.({\n type: 'round:complete',\n data: { round: currentRound.round, sdd: result.output },\n round: currentRound.round,\n });\n } else {\n session.status = 'error';\n session.error = result.output;\n onEvent?.({ type: 'error', data: { message: result.output, round: currentRound.round }, round: currentRound.round });\n }\n\n return result;\n }\n\n async autoRefine(\n sessionId: string,\n rounds?: number,\n onEvent?: (event: BrainstormStreamEvent) => void,\n ): Promise<void> {\n const maxRounds = Math.min(rounds ?? this.config.maxRefinementRounds, this.config.maxRefinementRounds);\n const session = this.requireSession(sessionId);\n\n if (!session.currentSdd) {\n await this.generate(sessionId, onEvent);\n if (session.status === 'error') return;\n }\n\n for (let i = 0; i < maxRounds; i++) {\n const reviewResult = await this.review(sessionId, onEvent);\n if (!reviewResult.success) break;\n\n const refineResult = await this.refine(sessionId, onEvent);\n if (!refineResult.success) break;\n }\n\n if (session.status !== 'error') {\n session.status = 'done';\n }\n }\n\n private requireSession(id: string): BrainstormSession {\n const session = this.sessions.get(id);\n if (!session) {\n throw new Error(`Brainstorm session not found: ${id}`);\n }\n return session;\n }\n}\n","export function buildGeneratePrompt(transcript: string): string {\n return `你是一个资深软件架构师。下面是用户通过语音倾倒的一段关于软件需求的想法,内容可能不连贯、有重复、夹杂语气词——这是正常的。\n\n**核心原则——第一性原理思考:**\n- 不要假设用户非常清楚自己想要什么以及该怎么得到。用户往往只有模糊的意图,你的工作是从原始需求和底层问题出发,帮他厘清真正的目标。\n- 如果用户的动机和目标不清晰,在 SDD 中明确标注 [待澄清],说明为什么这里需要进一步讨论,并给出你的理解和建议。\n- 如果目标清晰但用户描述的路径不是最优解,指出来,并建议更好的方案。用 [更优路径] 标注这类建议。\n- 回到问题的本质:先问\"用户真正要解决的问题是什么\",再想\"最简单有效的方案是什么\",避免过度设计。\n\n请你:\n1. 首先使用 Read、Grep、Glob 等工具浏览项目代码库,了解现有架构、技术栈和代码风格\n2. 分析用户想法的底层动机——他要解决什么问题?为什么要解决?现有方案为什么不够?\n3. 基于对代码库的理解和用户的真实需求,生成一份结构化的软件设计文档 (SDD)\n\nSDD 输出要求:\n- 使用 Markdown 格式\n- 包含以下章节:概述、目标与范围、技术方案(含架构设计、数据模型、接口设计)、实施计划、风险与约束\n- 在\"概述\"章节中,先用 2-3 句话阐明你理解的用户核心诉求和底层动机,再展开方案\n- 结合项目现有代码结构给出具体的文件路径和模块建议\n- 如果用户的想法中有模糊或矛盾的地方,先做合理推断并标注 [推断]\n- 如果发现更短的实现路径或更简洁的方案,用 [更优路径] 标注并说明理由\n\n用户的想法原文:\n---\n${transcript}\n---\n\n请直接输出完整的 SDD 文档内容(纯 Markdown 文本),不要输出任何多余解释。`;\n}\n\nexport function buildReviewPrompt(sdd: string, round: number): string {\n return `你是一个严谨的技术评审专家。请你仔细审查以下软件设计文档 (SDD)。\n\n请你:\n1. 使用 Read、Grep、Glob 等工具浏览项目代码库,验证 SDD 中提到的模块、路径、接口是否与现有代码一致\n2. 用第一性原理审视:需求本身是否合理?目标是否清晰?是否存在更简单直接的实现路径被忽略了?\n3. 站在实际实施者的角度,找出文档中**未说清楚、含糊不清、缺失、或可能导致实施困难**的地方\n4. 列出恰好 20 个问题,按严重程度排序(最重要的在前)\n\n这是第 ${round} 轮审查${round > 1 ? ',请关注比之前更细粒度的问题,特别是边界条件、错误处理、性能、安全等方面' : ''}。\n\nSDD 文档:\n---\n${sdd}\n---\n\n输出格式要求:\n每个问题用编号列出,格式为:\n1. [类别] 问题描述\n\n类别包括:[缺失]、[模糊]、[矛盾]、[风险]、[建议]、[动机](需求动机或目标本身需要质疑时)、[过度设计](存在更简单路径时)\n\n请直接输出 20 个问题,不要输出多余解释。`;\n}\n\nexport function buildRefinePrompt(questions: string): string {\n return `一位技术评审专家审查了你之前生成的 SDD,发现了以下问题:\n\n${questions}\n\n请你:\n1. 逐一回应每个问题,在 SDD 中修复或补充对应内容\n2. 如果某个问题需要查看代码来回答,请使用 Read、Grep、Glob 等工具查看项目代码后再作答\n3. 对无法确定的问题,给出多种方案并标注推荐方案\n\n请输出修复后的完整 SDD 文档(纯 Markdown 文本),不要输出对比说明,直接给出最新版本。`;\n}\n"],"mappings":"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","names":["fs","path","logger","path","fs","logger","logger","t","fs","path","logger","path","fs","fs","path","logger","path","fs","fs","path","path","path","planDir","fs","os","os","path","os","fs","execFile","promisify","fs","path","planDir","path","fs","logger","spawn","path","logger","DEFAULT_OPTIONS","spawn","path","fs","path","logger","fs","path","logger","execFileAsync","promisify","execFile","logger","path","fs","os","logger"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/commands/init.ts"],"sourcesContent":["import express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createSetupRouter } from '../../web/routes/setup.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface InitOptions {\n port: number;\n config?: string;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n const app = express();\n app.use(express.json());\n\n let serverRef: ReturnType<typeof app.listen> | null = null;\n\n const setupRouter = createSetupRouter({\n configPath: options.config,\n onComplete: (configPath) => {\n console.log(`\\n Configuration saved to: ${configPath}`);\n console.log(' Run \"issue-auto-finish start\" to start the service.\\n');\n setTimeout(() => {\n serverRef?.close();\n process.exit(0);\n }, 1000);\n },\n });\n\n app.use(setupRouter);\n\n const publicDir = path.resolve(process.cwd(), 'src/web/frontend/dist');\n\n if (fs.existsSync(publicDir)) {\n app.use(express.static(publicDir));\n app.get('{*path}', (_req, res) => {\n res.sendFile(path.join(publicDir, 'index.html'));\n });\n } else {\n app.get('/', (_req, res) => {\n res.type('html').send(`<!DOCTYPE html>\n<html><head><title>Issue Auto-Finish Setup</title></head>\n<body style=\"font-family:system-ui;max-width:600px;margin:60px auto;padding:20px\">\n<h1>Issue Auto-Finish Setup</h1>\n<p>Frontend assets not found. Please build the frontend first:</p>\n<pre>cd issue-auto-finish && pnpm web:build</pre>\n<p>Or use the API directly at <code>/api/setup/*</code></p>\n</body></html>`);\n });\n }\n\n serverRef = app.listen(options.port, async () => {\n const url = `http://localhost:${options.port}`;\n console.log(`\\n Issue Auto-Finish Setup Wizard`);\n console.log(` Open: ${url}\\n`);\n\n try {\n const open = (await import('open')).default;\n await open(url);\n } catch {\n // Browser open failed, user can manually navigate\n }\n });\n}\n"],"mappings":";;;;;;;;AAAA,OAAO,aAAa;AACpB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAG9B,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAO7D,eAAsB,YAAY,SAAqC;AACrE,QAAM,MAAM,QAAQ;AACpB,MAAI,IAAI,QAAQ,KAAK,CAAC;AAEtB,MAAI,YAAkD;AAEtD,QAAM,cAAc,kBAAkB;AAAA,IACpC,YAAY,QAAQ;AAAA,IACpB,YAAY,CAAC,eAAe;AAC1B,cAAQ,IAAI;AAAA,4BAA+B,UAAU,EAAE;AACvD,cAAQ,IAAI,yDAAyD;AACrE,iBAAW,MAAM;AACf,mBAAW,MAAM;AACjB,gBAAQ,KAAK,CAAC;AAAA,MAChB,GAAG,GAAI;AAAA,IACT;AAAA,EACF,CAAC;AAED,MAAI,IAAI,WAAW;AAEnB,QAAM,YAAY,KAAK,QAAQ,QAAQ,IAAI,GAAG,uBAAuB;AAErE,MAAI,GAAG,WAAW,SAAS,GAAG;AAC5B,QAAI,IAAI,QAAQ,OAAO,SAAS,CAAC;AACjC,QAAI,IAAI,WAAW,CAAC,MAAM,QAAQ;AAChC,UAAI,SAAS,KAAK,KAAK,WAAW,YAAY,CAAC;AAAA,IACjD,CAAC;AAAA,EACH,OAAO;AACL,QAAI,IAAI,KAAK,CAAC,MAAM,QAAQ;AAC1B,UAAI,KAAK,MAAM,EAAE,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAOb;AAAA,IACX,CAAC;AAAA,EACH;AAEA,cAAY,IAAI,OAAO,QAAQ,MAAM,YAAY;AAC/C,UAAM,MAAM,oBAAoB,QAAQ,IAAI;AAC5C,YAAQ,IAAI;AAAA,iCAAoC;AAChD,YAAQ,IAAI,WAAW,GAAG;AAAA,CAAI;AAE9B,QAAI;AACF,YAAM,QAAQ,MAAM,OAAO,MAAM,GAAG;AACpC,YAAM,KAAK,GAAG;AAAA,IAChB,QAAQ;AAAA,IAER;AAAA,EACF,CAAC;AACH;","names":[]}
|