@xdevops/issue-auto-finish 1.0.84 → 1.0.85
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/{LockNote-7OF7ADI2.js → LockNote-Z2CLDZNN.js} +3 -3
- package/dist/{ai-runner-MCGEQGXS.js → ai-runner-SVUNA3FX.js} +2 -2
- package/dist/{analyze-ZITN3CSH.js → analyze-SXXPE5XL.js} +3 -3
- package/dist/{braindump-LQU65XND.js → braindump-4E5SDMSZ.js} +6 -6
- package/dist/{chunk-7FLKETBC.js → chunk-4LFNFRCL.js} +13 -1
- package/dist/chunk-4LFNFRCL.js.map +1 -0
- package/dist/{chunk-HKI3BON6.js → chunk-4QV6D34Y.js} +3 -3
- package/dist/{chunk-7YCDMVIF.js → chunk-5UPYA6KH.js} +506 -216
- package/dist/chunk-5UPYA6KH.js.map +1 -0
- package/dist/{chunk-MV2CADMB.js → chunk-FWEW5E3B.js} +2 -2
- package/dist/{chunk-NZ7K73B7.js → chunk-GXFG4JU6.js} +2 -2
- package/dist/{chunk-3V3GQCB7.js → chunk-HDFNMVRQ.js} +2 -2
- package/dist/{chunk-3RNGPMRE.js → chunk-HOFYJEJ4.js} +7 -7
- package/dist/{chunk-PWA46LUR.js → chunk-JINMYD56.js} +3 -3
- package/dist/{chunk-WHFY274N.js → chunk-K2OTLYJI.js} +118 -17
- package/dist/chunk-K2OTLYJI.js.map +1 -0
- package/dist/{chunk-GDTS2J2P.js → chunk-KTYPZTF4.js} +2 -2
- package/dist/{chunk-6S7ERGQ7.js → chunk-P4O4ZXEC.js} +10 -5
- package/dist/chunk-P4O4ZXEC.js.map +1 -0
- package/dist/{chunk-KWODU7HB.js → chunk-YCYVNRLF.js} +15 -1
- package/dist/chunk-YCYVNRLF.js.map +1 -0
- package/dist/cli.js +8 -8
- package/dist/{config-C7AKWCPA.js → config-QLINHCHD.js} +3 -3
- package/dist/{doctor-P2ZH6PFX.js → doctor-37JNBGDN.js} +3 -3
- package/dist/errors/PhaseAbortedError.d.ts +13 -0
- package/dist/errors/PhaseAbortedError.d.ts.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/events/EventBus.d.ts +1 -1
- package/dist/events/EventBus.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.js +11 -11
- package/dist/{init-D2BQIVVD.js → init-TDKDC6YP.js} +7 -7
- package/dist/lib.js +5 -5
- package/dist/lifecycle/ActionLifecycle.d.ts +1 -1
- package/dist/lifecycle/ActionLifecycle.d.ts.map +1 -1
- package/dist/lifecycle/ActionLifecycleManager.d.ts.map +1 -1
- package/dist/orchestrator/IssueProcessingContext.d.ts +2 -0
- package/dist/orchestrator/IssueProcessingContext.d.ts.map +1 -1
- package/dist/orchestrator/PipelineOrchestrator.d.ts +19 -0
- package/dist/orchestrator/PipelineOrchestrator.d.ts.map +1 -1
- package/dist/orchestrator/steps/FailureHandler.d.ts.map +1 -1
- package/dist/orchestrator/steps/PhaseLoopStep.d.ts.map +1 -1
- package/dist/phases/BasePhase.d.ts +10 -8
- package/dist/phases/BasePhase.d.ts.map +1 -1
- package/dist/phases/UatPhase.d.ts +32 -1
- package/dist/phases/UatPhase.d.ts.map +1 -1
- package/dist/pipeline/PipelineDefinition.d.ts.map +1 -1
- package/dist/prompts/templates.d.ts.map +1 -1
- package/dist/{restart-TP5RAFXZ.js → restart-RNXGTDWZ.js} +5 -5
- package/dist/run.js +11 -11
- package/dist/{start-KOBDZ2XN.js → start-27GRO4DP.js} +5 -5
- package/dist/tracker/IssueState.d.ts +4 -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/webhook/CommandExecutor.d.ts +3 -0
- package/dist/webhook/CommandExecutor.d.ts.map +1 -1
- package/dist/webhook/CommandParser.d.ts +1 -1
- package/dist/webhook/CommandParser.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/web/frontend/dist/assets/{index-GfpCL9Wn.js → index-C4NXoH9S.js} +55 -49
- package/src/web/frontend/dist/assets/{index-CPNbFsHB.css → index-C7lorIa0.css} +1 -1
- package/src/web/frontend/dist/index.html +2 -2
- package/dist/chunk-6S7ERGQ7.js.map +0 -1
- package/dist/chunk-7FLKETBC.js.map +0 -1
- package/dist/chunk-7YCDMVIF.js.map +0 -1
- package/dist/chunk-KWODU7HB.js.map +0 -1
- package/dist/chunk-WHFY274N.js.map +0 -1
- /package/dist/{LockNote-7OF7ADI2.js.map → LockNote-Z2CLDZNN.js.map} +0 -0
- /package/dist/{ai-runner-MCGEQGXS.js.map → ai-runner-SVUNA3FX.js.map} +0 -0
- /package/dist/{analyze-ZITN3CSH.js.map → analyze-SXXPE5XL.js.map} +0 -0
- /package/dist/{braindump-LQU65XND.js.map → braindump-4E5SDMSZ.js.map} +0 -0
- /package/dist/{chunk-HKI3BON6.js.map → chunk-4QV6D34Y.js.map} +0 -0
- /package/dist/{chunk-MV2CADMB.js.map → chunk-FWEW5E3B.js.map} +0 -0
- /package/dist/{chunk-NZ7K73B7.js.map → chunk-GXFG4JU6.js.map} +0 -0
- /package/dist/{chunk-3V3GQCB7.js.map → chunk-HDFNMVRQ.js.map} +0 -0
- /package/dist/{chunk-3RNGPMRE.js.map → chunk-HOFYJEJ4.js.map} +0 -0
- /package/dist/{chunk-PWA46LUR.js.map → chunk-JINMYD56.js.map} +0 -0
- /package/dist/{chunk-GDTS2J2P.js.map → chunk-KTYPZTF4.js.map} +0 -0
- /package/dist/{config-C7AKWCPA.js.map → config-QLINHCHD.js.map} +0 -0
- /package/dist/{doctor-P2ZH6PFX.js.map → doctor-37JNBGDN.js.map} +0 -0
- /package/dist/{init-D2BQIVVD.js.map → init-TDKDC6YP.js.map} +0 -0
- /package/dist/{restart-TP5RAFXZ.js.map → restart-RNXGTDWZ.js.map} +0 -0
- /package/dist/{start-KOBDZ2XN.js.map → start-27GRO4DP.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/supplement/SupplementStore.ts","../src/poller/IssuePoller.ts","../src/coordination/IssueClaimer.ts","../src/coordination/StaleClaimRecovery.ts","../src/coordination/NodeIdentity.ts","../src/web/WebServer.ts","../src/web/routes/api.ts","../src/settings/ExperimentalSettings.ts","../src/web/routes/brainstorm.ts","../src/web/routes/chat.ts","../src/web/routes/knowledge.ts","../src/web/routes/distill.ts","../src/web/routes/domain-model.ts","../src/knowledge/DomainModel.ts","../src/web/routes/system-usecase.ts","../src/web/routes/braindump.ts","../src/web/routes/sync.ts","../src/web/routes/knowledge-sync.ts","../src/web/routes/analytics.ts","../src/analytics/SkillMetricsDiscovery.ts","../src/analytics/AnalyticsMetricsCollector.ts","../src/analytics/AnalyticsPrompts.ts","../src/analytics/AnalyticsAnalyzer.ts","../src/knowledge/DomainModelAnalyzer.ts","../src/knowledge/domain-model-prompt.ts","../src/knowledge/SystemUseCaseAnalyzer.ts","../src/knowledge/usecase-prompt.ts","../src/services/ChatService.ts","../src/prompts/chat-templates.ts","../src/webhook/WebhookServer.ts","../src/webhook/WebhookHandler.ts","../src/webhook/CommandParser.ts","../src/webhook/CommandExecutor.ts","../src/webhook/NoteDeduplicator.ts","../src/webhook/IntentRecognizer.ts","../src/web/AgentLogStore.ts","../src/updater/VersionChecker.ts","../src/updater/UpdateExecutor.ts","../src/updater/AutoUpdater.ts","../src/config/ConfigReloader.ts","../src/distill/DiaryCollector.ts","../src/distill/DiaryStore.ts","../src/distill/MemoryDistiller.ts","../src/distill/prompts/memory-distill.ts","../src/distill/AgentRuleDistiller.ts","../src/distill/prompts/rule-distill.ts","../src/distill/VectorStore.ts","../src/distill/VersionStore.ts","../src/distill/DistillScheduler.ts","../src/deploy/PreviewReaper.ts","../src/storage/OrphanBranchManager.ts","../src/index.ts","../src/tenant/TenantConfig.ts","../src/tenant/TenantRegistry.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('SupplementStore');\n\nexport interface SupplementInfo {\n requirements: string;\n acceptanceCriteria: string;\n scope: string;\n constraints: string;\n references: string;\n freeText: string;\n tapdId: string;\n updatedAt: string;\n}\n\nexport class SupplementStore {\n private dir: string;\n\n constructor(dataDir: string) {\n this.dir = path.join(dataDir, 'supplements');\n }\n\n private filePath(issueIid: number): string {\n return path.join(this.dir, `${issueIid}.json`);\n }\n\n private ensureDir(): void {\n if (!fs.existsSync(this.dir)) {\n fs.mkdirSync(this.dir, { recursive: true });\n }\n }\n\n get(issueIid: number): SupplementInfo | null {\n const fp = this.filePath(issueIid);\n if (!fs.existsSync(fp)) return null;\n try {\n const raw = fs.readFileSync(fp, 'utf-8');\n return JSON.parse(raw) as SupplementInfo;\n } catch (err) {\n logger.error('Failed to read supplement', { issueIid, error: (err as Error).message });\n return null;\n }\n }\n\n save(issueIid: number, data: Omit<SupplementInfo, 'updatedAt'>): SupplementInfo {\n this.ensureDir();\n const info: SupplementInfo = {\n ...data,\n updatedAt: new Date().toISOString(),\n };\n fs.writeFileSync(this.filePath(issueIid), JSON.stringify(info, null, 2), 'utf-8');\n logger.info('Supplement saved', { issueIid });\n return info;\n }\n\n delete(issueIid: number): boolean {\n const fp = this.filePath(issueIid);\n if (!fs.existsSync(fp)) return false;\n try {\n fs.unlinkSync(fp);\n logger.info('Supplement deleted', { issueIid });\n return true;\n } catch {\n return false;\n }\n }\n\n toPromptText(issueIid: number): string {\n const info = this.get(issueIid);\n if (!info) return '';\n\n const sections: string[] = [];\n\n if (info.requirements.trim()) {\n sections.push(`### 补充需求说明\\n${info.requirements.trim()}`);\n }\n if (info.acceptanceCriteria.trim()) {\n sections.push(`### 验收标准\\n${info.acceptanceCriteria.trim()}`);\n }\n if (info.scope.trim()) {\n sections.push(`### 变更范围\\n${info.scope.trim()}`);\n }\n if (info.constraints.trim()) {\n sections.push(`### 约束条件\\n${info.constraints.trim()}`);\n }\n if (info.references.trim()) {\n sections.push(`### 参考链接\\n${info.references.trim()}`);\n }\n if (info.freeText.trim()) {\n sections.push(`### 其他补充\\n${info.freeText.trim()}`);\n }\n\n if (sections.length === 0) return '';\n return `## 补充信息\\n\\n${sections.join('\\n\\n')}`;\n }\n}\n","import { Config } from '../config.js';\nimport { GongfengClient, GongfengIssue } from '../clients/GongfengClient.js';\nimport { IssueTracker } from '../tracker/IssueTracker.js';\nimport { IssueRecord, IssueState } from '../tracker/IssueState.js';\nimport { getIid, getExternalId } from '../tracker/IssueRecordHelper.js';\nimport { gongfengIssueToDemandSpec } from '../demand/adapters/GongfengAdapter.js';\nimport { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport { IssueClaimer } from '../coordination/IssueClaimer.js';\nimport { findLockNote } from '../coordination/LockNote.js';\nimport { isShuttingDown } from '../shutdown/ShutdownSignal.js';\nimport { eventBus } from '../events/EventBus.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('IssuePoller');\n\nconst AUTO_FINISH_LABEL = 'auto-finish';\nconst AUTO_APPROVE_CHECK_INTERVAL_MS = 30_000;\n\nexport class IssuePoller {\n private config: Config;\n private gongfeng: GongfengClient;\n private tracker: IssueTracker;\n private orchestrator: PipelineOrchestrator;\n private claimer: IssueClaimer | null;\n private discoveryTimer: ReturnType<typeof setInterval> | null = null;\n private driveTimer: ReturnType<typeof setInterval> | null = null;\n private activeIssues = new Set<number>();\n private lastAutoApproveCheckMs = 0;\n private discoveryPaused = false;\n private isFirstDiscovery = true;\n readonly tenantId: string;\n\n constructor(\n config: Config,\n gongfeng: GongfengClient,\n tracker: IssueTracker,\n orchestrator: PipelineOrchestrator,\n claimer?: IssueClaimer | null,\n tenantId?: string,\n ) {\n this.config = config;\n this.gongfeng = gongfeng;\n this.tracker = tracker;\n this.orchestrator = orchestrator;\n this.claimer = claimer ?? null;\n this.tenantId = tenantId ?? 'default';\n }\n\n start(): void {\n const { discoveryIntervalMs, driveIntervalMs } = this.config.poll;\n logger.info('Issue poller starting', { tenantId: this.tenantId, discoveryIntervalMs, driveIntervalMs });\n\n this.discover();\n this.drive();\n\n this.discoveryTimer = setInterval(() => this.discover(), discoveryIntervalMs);\n this.driveTimer = setInterval(() => this.drive(), driveIntervalMs);\n }\n\n stop(): void {\n if (this.discoveryTimer) {\n clearInterval(this.discoveryTimer);\n this.discoveryTimer = null;\n }\n if (this.driveTimer) {\n clearInterval(this.driveTimer);\n this.driveTimer = null;\n }\n logger.info('Issue poller stopped', { tenantId: this.tenantId });\n }\n\n getActiveIssueIids(): number[] {\n return [...this.activeIssues];\n }\n\n getActiveCount(): number {\n return this.activeIssues.size;\n }\n\n forceReleaseIssue(issueIid: number): boolean {\n const had = this.activeIssues.has(issueIid);\n if (had) {\n this.activeIssues.delete(issueIid);\n logger.info('Force-released issue from activeIssues', { issueIid });\n }\n return had;\n }\n\n pauseDiscovery(): void {\n this.discoveryPaused = true;\n logger.info('Discovery paused (auto-update drain)');\n }\n\n resumeDiscovery(): void {\n this.discoveryPaused = false;\n logger.info('Discovery resumed');\n }\n\n private async discover(): Promise<void> {\n if (isShuttingDown()) return;\n if (this.discoveryPaused) return;\n try {\n logger.debug('Discovering new issues...');\n const issues = await this.gongfeng.listIssues('opened', AUTO_FINISH_LABEL);\n const newIssues = this.filterNewIssues(issues);\n\n if (newIssues.length === 0) {\n logger.debug('No new issues found');\n return;\n }\n\n const initialState = this.isFirstDiscovery ? IssueState.Skipped : IssueState.Pending;\n logger.info('Discovered new issues', { count: newIssues.length, initialState });\n for (const issue of newIssues) {\n this.tracker.create({\n state: initialState,\n branchName: `${this.config.project.branchPrefix}-${issue.iid}`,\n demandSpec: gongfengIssueToDemandSpec(issue),\n });\n }\n } catch (err) {\n logger.error('Discovery cycle failed', { error: (err as Error).message });\n } finally {\n if (this.isFirstDiscovery) {\n this.isFirstDiscovery = false;\n logger.info('First discovery completed — pre-existing issues marked as skipped');\n }\n }\n }\n\n private drive(): void {\n if (isShuttingDown()) return;\n\n this.maybeAutoApproveWaiting();\n\n const maxConcurrent = this.config.poll.maxConcurrent;\n const available = maxConcurrent - this.activeIssues.size;\n if (available <= 0) {\n logger.debug('Skipping drive — at concurrency limit', {\n active: this.activeIssues.size,\n max: maxConcurrent,\n });\n return;\n }\n\n const drivable = this.tracker\n .getDrivableIssues(this.config.poll.maxRetries)\n .filter((r) => !this.activeIssues.has(getIid(r)));\n\n if (drivable.length === 0) {\n return;\n }\n\n const batch = drivable.slice(0, available);\n logger.info('Driving issues', {\n batchSize: batch.length,\n active: this.activeIssues.size,\n max: maxConcurrent,\n });\n\n for (const record of batch) {\n this.activeIssues.add(getIid(record));\n this.processInBackground(record);\n }\n }\n\n private maybeAutoApproveWaiting(): void {\n const autoLabels = this.config.review.autoApproveLabels;\n if (!autoLabels.length) return;\n\n const now = Date.now();\n if (now - this.lastAutoApproveCheckMs < AUTO_APPROVE_CHECK_INTERVAL_MS) return;\n this.lastAutoApproveCheckMs = now;\n\n const waiting = this.tracker\n .getAll()\n .filter((r) => r.state === IssueState.PhaseWaiting);\n if (!waiting.length) return;\n\n this.autoApproveByLabels(waiting, autoLabels).catch((err) => {\n logger.warn('Auto-approve check failed', { error: (err as Error).message });\n });\n }\n\n private async autoApproveByLabels(\n records: IssueRecord[],\n autoLabels: string[],\n ): Promise<void> {\n for (const record of records) {\n try {\n const issue = await this.gongfeng.getIssueDetail(getExternalId(record));\n const matched = issue.labels.filter((l) => autoLabels.includes(l));\n if (matched.length === 0) continue;\n\n const iid = getIid(record);\n logger.info('Auto-approving waiting issue (label matched)', {\n iid,\n matchedLabels: matched,\n });\n this.tracker.updateState(iid, IssueState.PhaseApproved, { currentPhase: 'review' });\n eventBus.emitTyped('review:approved', { issueIid: iid });\n\n try {\n await this.gongfeng.createIssueNote(\n getExternalId(record),\n t('poller.autoApproveComment', { labels: matched.join(', ') }),\n );\n } catch { /* ignore */ }\n } catch (err) {\n logger.warn('Failed to check auto-approve labels', {\n iid: getIid(record),\n error: (err as Error).message,\n });\n }\n }\n }\n\n private async processInBackground(record: IssueRecord): Promise<void> {\n const iid = getIid(record);\n try {\n const issue = await this.resolveIssue(getExternalId(record));\n if (!issue) {\n logger.warn('Could not resolve issue from API, skipping', { iid });\n return;\n }\n\n // 多节点协调:处理前先认领\n if (this.claimer) {\n const notes = await this.gongfeng.listIssueNotes(issue.id);\n const lockInfo = findLockNote(notes);\n const isOwnedByLock = lockInfo?.payload.nodeId === this.claimer.getNodeId();\n\n if (isOwnedByLock) {\n // 有自己的锁 — 真正的断点恢复,直接继续\n logger.debug('Own lock found, resuming', { iid });\n } else {\n // 无锁或锁不是自己的 — 走完整 CAS 认领(包括 assignee-only 的旧 Issue)\n const isRetry = record.state === IssueState.Failed;\n const result = await this.claimer.tryClaim(issue, notes, { isRetry });\n if (!result.success) {\n if (result.reason === 'locked_by_other' || result.reason === 'cas_lost') {\n logger.info('Claim failed (another node owns it), marking as skipped', { iid, reason: result.reason });\n this.tracker.updateState(iid, IssueState.Skipped);\n } else {\n logger.info('Claim failed with transient error, will retry next cycle', { iid });\n }\n return;\n }\n }\n }\n\n await this.orchestrator.processIssue(issue);\n } catch (err) {\n logger.error('Failed to process issue', {\n iid,\n error: (err as Error).message,\n });\n } finally {\n this.activeIssues.delete(iid);\n }\n }\n\n private async resolveIssue(issueId: number): Promise<GongfengIssue | null> {\n try {\n return await this.gongfeng.getIssueDetail(issueId);\n } catch {\n return null;\n }\n }\n\n private filterNewIssues(issues: GongfengIssue[]): GongfengIssue[] {\n return issues.filter((issue) => {\n if (!issue.labels.includes(AUTO_FINISH_LABEL)) return false;\n if (issue.labels.some((l) => l === 'auto-finish:done')) return false;\n\n const record = this.tracker.get(issue.iid);\n if (record) return false;\n\n // 多节点协调:跳过已被其他节点认领的 Issue\n if (this.claimer && this.claimer.isClaimedByOther(issue)) {\n logger.debug('Skipping issue claimed by another node', {\n iid: issue.iid,\n assignee: issue.assignees?.[0]?.username ?? issue.assignee_users?.[0]?.username,\n });\n return false;\n }\n\n return true;\n });\n }\n}\n","import { GongfengClient, GongfengIssue, GongfengNote } from '../clients/GongfengClient.js';\nimport { buildLockNoteBody, buildReleaseNoteBody, findLockNote, findAllLockNotes } from './LockNote.js';\nimport type { ReleaseReason } from './LockNote.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('IssueClaimer');\n\n/** CAS 仲裁等待时间 */\nconst CAS_VERIFY_DELAY_MS = 3_000;\n\nexport interface IssueClaimerOptions {\n /** 当前节点的工蜂用户名 */\n claimUser: string;\n /** 节点唯一标识 */\n nodeId: string;\n /** 工蜂客户端 */\n gongfeng: GongfengClient;\n}\n\n/** 认领失败原因 */\nexport type ClaimFailReason = 'locked_by_other' | 'cas_lost' | 'error';\n\nexport interface ClaimResult {\n success: boolean;\n /** 认领成功时,锁评论的 noteId */\n lockNoteId?: number;\n /** 认领失败时的原因 */\n reason?: ClaimFailReason;\n}\n\nexport class IssueClaimer {\n private claimUser: string;\n private nodeId: string;\n private gongfeng: GongfengClient;\n\n constructor(options: IssueClaimerOptions) {\n this.claimUser = options.claimUser;\n this.nodeId = options.nodeId;\n this.gongfeng = options.gongfeng;\n logger.info('IssueClaimer initialized', {\n claimUser: this.claimUser,\n nodeId: this.nodeId,\n });\n }\n\n /** 当前节点的工蜂用户名 */\n getClaimUser(): string {\n return this.claimUser;\n }\n\n /** 当前节点 ID */\n getNodeId(): string {\n return this.nodeId;\n }\n\n /**\n * 检查 Issue 是否由当前节点持有。\n *\n * 优先检查锁评论中 nodeId;无锁评论时 fallback 到 assignee 检查(向后兼容旧版节点)。\n */\n isOwnedByMe(notes: GongfengNote[], issue?: GongfengIssue): boolean {\n const lock = findLockNote(notes);\n if (lock) {\n return lock.payload.nodeId === this.nodeId;\n }\n // Fallback: 旧版节点(无锁评论),检查 assignee\n if (issue) {\n return this.getAssigneeUsername(issue) === this.claimUser;\n }\n return false;\n }\n\n /** Issue 是否已有负责人(assignee 级别) */\n isClaimed(issue: GongfengIssue): boolean {\n return this.getAssigneeUsername(issue) !== null;\n }\n\n /** Issue 是否已被其他节点认领(有负责人但不是自己) */\n isClaimedByOther(issue: GongfengIssue): boolean {\n const assignee = this.getAssigneeUsername(issue);\n return assignee !== null && assignee !== this.claimUser;\n }\n\n /**\n * 尝试认领 Issue(基于锁评论的 CAS 协议):\n *\n * 1. 查找现有锁评论\n * 2. 存在 + nodeId === 自己 → 断点恢复,返回成功\n * 3. 存在 + nodeId !== 自己 → 返回失败(锁永不自动过期)\n * 4. 不存在 → CAS:创建锁评论(附带可见状态消息)→ 等待 → 仲裁(最小 noteId 胜出)\n * 5. 设置 assignee(视觉标识 + 向后兼容)\n */\n async tryClaim(\n issue: GongfengIssue,\n notes?: GongfengNote[],\n options?: { isRetry?: boolean },\n ): Promise<ClaimResult> {\n const { id: issueId, iid } = issue;\n\n try {\n // Step 1: 获取评论列表(可复用传入的 notes)\n const allNotes = notes ?? await this.gongfeng.listIssueNotes(issueId);\n const existingLock = findLockNote(allNotes);\n\n // Step 2: 检查现有锁\n if (existingLock) {\n if (existingLock.payload.nodeId === this.nodeId) {\n // 断点恢复:自己的锁还在,直接返回成功\n logger.info('Resuming — own lock found', { iid, noteId: existingLock.noteId });\n return { success: true, lockNoteId: existingLock.noteId };\n }\n // 其他节点的锁 — 永不自动过期,直接返回失败\n logger.info('Claim blocked — lock held by another node', {\n iid,\n holder: existingLock.payload.nodeId,\n });\n return { success: false, reason: 'locked_by_other' };\n }\n\n // Step 3: CAS — 创建锁评论(附带可见消息)\n const visibleMessage = options?.isRetry\n ? t('lock.retryMessage')\n : t('lock.startMessage');\n const lockBody = buildLockNoteBody(\n { nodeId: this.nodeId, ts: Date.now() },\n visibleMessage,\n );\n const myNote = await this.gongfeng.createIssueNotePlain(issueId, lockBody);\n logger.info('Lock note created', { iid, noteId: myNote.id });\n\n // Step 4: 等待仲裁窗口\n await this.delay(CAS_VERIFY_DELAY_MS);\n\n // Step 5: 重新查询,检查是否有竞争者\n const freshNotes = await this.gongfeng.listIssueNotes(issueId);\n const allLocks = findAllLockNotes(freshNotes);\n\n if (allLocks.length <= 1) {\n // 无竞争\n await this.setAssigneeSafe(issueId, iid);\n return { success: true, lockNoteId: myNote.id };\n }\n\n // Step 6: 确定性仲裁 — 最小 noteId 胜出\n const sortedLocks = [...allLocks].sort((a, b) => a.noteId - b.noteId);\n const winner = sortedLocks[0];\n\n if (winner.noteId === myNote.id) {\n // 我赢了 — 删除其他自己的锁评论\n for (const lock of sortedLocks.slice(1)) {\n if (lock.payload.nodeId === this.nodeId) {\n await this.safeDeleteNote(issueId, lock.noteId);\n }\n }\n logger.info('Claim won by arbitration', { iid, myNoteId: myNote.id });\n await this.setAssigneeSafe(issueId, iid);\n return { success: true, lockNoteId: myNote.id };\n }\n\n // 我输了 — 删除自己的锁评论(CAS 败者仍用 delete,短暂空评论)\n logger.info('Claim lost by arbitration', {\n iid,\n myNoteId: myNote.id,\n winnerNoteId: winner.noteId,\n winnerNode: winner.payload.nodeId,\n });\n await this.safeDeleteNote(issueId, myNote.id);\n return { success: false, reason: 'cas_lost' };\n } catch (err) {\n logger.error('Claim failed with error', { iid, error: (err as Error).message });\n return { success: false, reason: 'error' };\n }\n }\n\n /**\n * 释放认领:将锁评论原地更新为有意义的状态消息。\n */\n async releaseClaim(issueId: number, iid: number, reason: ReleaseReason = 'completed'): Promise<void> {\n try {\n const notes = await this.gongfeng.listIssueNotes(issueId);\n const allLocks = findAllLockNotes(notes);\n const releaseBody = buildReleaseNoteBody(reason);\n\n for (const lock of allLocks) {\n if (lock.payload.nodeId === this.nodeId) {\n await this.gongfeng.updateIssueNote(issueId, lock.noteId, releaseBody);\n logger.info('Lock note released (updated)', { iid, noteId: lock.noteId, reason });\n }\n }\n } catch (err) {\n logger.warn('Failed to release claim', { iid, error: (err as Error).message });\n }\n }\n\n /** 从 Issue 中提取第一个负责人的 username */\n private getAssigneeUsername(issue: GongfengIssue): string | null {\n const list = issue.assignees ?? issue.assignee_users;\n if (!list || list.length === 0) {\n return null;\n }\n return list[0].username;\n }\n\n private async setAssigneeSafe(issueId: number, iid: number): Promise<void> {\n try {\n await this.gongfeng.setIssueAssignee(issueId, this.claimUser);\n logger.info('Assignee set (visual indicator)', { iid, claimUser: this.claimUser });\n } catch (err) {\n logger.warn('Failed to set assignee — non-blocking', { iid, error: (err as Error).message });\n }\n }\n\n private async safeDeleteNote(issueId: number, noteId: number): Promise<void> {\n try {\n await this.gongfeng.deleteIssueNote(issueId, noteId);\n } catch (err) {\n logger.warn('Failed to delete note', { issueId, noteId, error: (err as Error).message });\n }\n }\n\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n","import { GongfengClient, GongfengIssue } from '../clients/GongfengClient.js';\nimport { IssueClaimer } from './IssueClaimer.js';\nimport { findAllLockNotes, buildReleaseNoteBody } from './LockNote.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('StaleClaimRecovery');\n\nconst AUTO_FINISH_LABEL = 'auto-finish';\n\nexport interface StaleClaimRecoveryOptions {\n gongfeng: GongfengClient;\n claimer: IssueClaimer;\n}\n\n/**\n * 崩溃残留锁清理。\n *\n * 启动时扫描所有 auto-finish 标签的 Issue:\n * 仅清理自己的崩溃残留锁(nodeId === 自己 且不在 activeIids 中)。\n * 不再回收其他节点的过期锁(锁永不自动过期)。\n */\nexport class StaleClaimRecovery {\n private gongfeng: GongfengClient;\n private claimer: IssueClaimer;\n\n constructor(options: StaleClaimRecoveryOptions) {\n this.gongfeng = options.gongfeng;\n this.claimer = options.claimer;\n }\n\n /**\n * 扫描并清理自己的崩溃残留锁。\n * @param activeIids - 当前正在活跃处理的 Issue IID 集合(不清理这些的锁)\n * @returns 被清理的 Issue 数量\n */\n async recover(activeIids?: Set<number>): Promise<number> {\n let recovered = 0;\n const active = activeIids ?? new Set<number>();\n\n try {\n const issues = await this.gongfeng.listIssues('opened', AUTO_FINISH_LABEL);\n logger.info('Scanning for crash-residue locks', { totalIssues: issues.length });\n\n for (const issue of issues) {\n try {\n const cleaned = await this.cleanOwnCrashResidue(issue, active);\n if (cleaned) recovered++;\n } catch (err) {\n logger.error('Failed to check issue', {\n iid: issue.iid,\n error: (err as Error).message,\n });\n }\n }\n\n if (recovered > 0) {\n logger.info('Crash-residue locks cleaned', { count: recovered });\n } else {\n logger.info('No crash-residue locks found');\n }\n } catch (err) {\n logger.error('Crash-residue lock cleanup failed', { error: (err as Error).message });\n }\n return recovered;\n }\n\n private async cleanOwnCrashResidue(issue: GongfengIssue, activeIids: Set<number>): Promise<boolean> {\n const notes = await this.gongfeng.listIssueNotes(issue.id);\n const allLocks = findAllLockNotes(notes);\n\n let cleaned = false;\n for (const lock of allLocks) {\n const isOwnCrashResidue =\n lock.payload.nodeId === this.claimer.getNodeId() && !activeIids.has(issue.iid);\n\n if (isOwnCrashResidue) {\n logger.warn('Cleaning up own crash-residue lock', {\n iid: issue.iid,\n noteId: lock.noteId,\n nodeId: lock.payload.nodeId,\n });\n await this.safeUpdateNote(issue.id, lock.noteId);\n cleaned = true;\n }\n }\n\n // 如果清理了锁评论,也清除 assignee\n if (cleaned) {\n await this.safeClearAssignee(issue);\n }\n\n return cleaned;\n }\n\n private async safeUpdateNote(issueId: number, noteId: number): Promise<void> {\n try {\n const releaseBody = buildReleaseNoteBody('crash-recovery');\n await this.gongfeng.updateIssueNote(issueId, noteId, releaseBody);\n } catch (err) {\n logger.error('Failed to update lock note', {\n issueId,\n noteId,\n error: (err as Error).message,\n });\n }\n }\n\n private async safeClearAssignee(issue: GongfengIssue): Promise<void> {\n try {\n await this.gongfeng.clearIssueAssignee(issue.id);\n logger.info('Stale assignee cleared', { iid: issue.iid });\n } catch (err) {\n logger.error('Failed to clear stale assignee', {\n iid: issue.iid,\n error: (err as Error).message,\n });\n }\n }\n}\n","import { randomBytes } from 'node:crypto';\nimport { hostname } from 'node:os';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('NodeIdentity');\n\nconst NODE_ID_FILE = 'node-id';\n\n/**\n * 生成节点唯一标识。\n *\n * 格式: `${hostname}-${随机8位hex}`\n * 优先级: NODE_ID 环境变量 > 持久化文件 > 自动生成\n *\n * 重启后 ID 不变(能识别自己的旧锁评论),同机器多实例通过随机后缀区分。\n */\nexport function resolveNodeId(dataDir: string): string {\n // 1. 环境变量优先\n const envNodeId = process.env.NODE_ID;\n if (envNodeId) {\n logger.info('Using NODE_ID from environment', { nodeId: envNodeId });\n return envNodeId;\n }\n\n // 2. 尝试从持久化文件读取\n const filePath = path.join(dataDir, NODE_ID_FILE);\n try {\n const stored = fs.readFileSync(filePath, 'utf-8').trim();\n if (stored) {\n logger.info('Loaded node ID from file', { nodeId: stored, path: filePath });\n return stored;\n }\n } catch {\n // 文件不存在或读取失败,继续生成\n }\n\n // 3. 自动生成\n const nodeId = generateNodeId();\n try {\n fs.writeFileSync(filePath, nodeId, 'utf-8');\n logger.info('Generated and persisted new node ID', { nodeId, path: filePath });\n } catch (err) {\n logger.warn('Failed to persist node ID — will regenerate on next startup', {\n nodeId,\n error: (err as Error).message,\n });\n }\n\n return nodeId;\n}\n\n/** 生成格式为 `hostname-xxxxxxxx` 的节点 ID */\nexport function generateNodeId(): string {\n const host = hostname().replace(/[^a-zA-Z0-9-]/g, '').slice(0, 32) || 'unknown';\n const rand = randomBytes(4).toString('hex');\n return `${host}-${rand}`;\n}\n","import express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { resolveDisplayHost } from '../utils/network.js';\nimport { createApiRouter, ApiRouterDeps } from './routes/api.js';\nimport { createSetupRouter } from './routes/setup.js';\nimport { createBrainstormRouter } from './routes/brainstorm.js';\nimport { createChatRouter } from './routes/chat.js';\nimport { createKnowledgeRouter } from './routes/knowledge.js';\nimport { createDistillRouter } from './routes/distill.js';\nimport { createDomainModelRouter } from './routes/domain-model.js';\nimport { createSystemUseCaseRouter } from './routes/system-usecase.js';\nimport { createBraindumpRouter } from './routes/braindump.js';\nimport { createSyncRouter } from './routes/sync.js';\nimport { createKnowledgeSyncRouter } from './routes/knowledge-sync.js';\nimport { createAnalyticsRouter } from './routes/analytics.js';\nimport { DomainModelAnalyzer } from '../knowledge/DomainModelAnalyzer.js';\nimport { SystemUseCaseAnalyzer } from '../knowledge/SystemUseCaseAnalyzer.js';\nimport { BrainstormService } from '../services/BrainstormService.js';\nimport { ChatService } from '../services/ChatService.js';\nimport { KnowledgeStore } from '../knowledge/KnowledgeStore.js';\nimport { IwikiImporter } from '../knowledge/importers/IwikiImporter.js';\nimport { resolveDataDir, ensureDir } from '../paths.js';\nimport { IssueTracker } from '../tracker/IssueTracker.js';\nimport { Config } from '../config.js';\nimport { AgentLogStore } from './AgentLogStore.js';\nimport { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport { GitOperations } from '../git/GitOperations.js';\nimport { GongfengClient } from '../clients/GongfengClient.js';\nimport { SupplementStore } from '../supplement/SupplementStore.js';\nimport { AutoUpdater } from '../updater/AutoUpdater.js';\nimport type { BraindumpOrchestrator } from '../braindump/BraindumpOrchestrator.js';\nimport type { DistillScheduler } from '../distill/DistillScheduler.js';\nimport type { DiaryStore } from '../distill/DiaryStore.js';\nimport type { VectorStore } from '../distill/VectorStore.js';\nimport type { DiaryCollector } from '../distill/DiaryCollector.js';\nimport type { IssueClaimer } from '../coordination/IssueClaimer.js';\nimport type { AIRunner } from '../ai-runner/AIRunner.js';\nimport type { ConfigReloader } from '../config/ConfigReloader.js';\nimport type { OrphanBranchManager } from '../storage/OrphanBranchManager.js';\nimport { metrics } from '../metrics/MetricsCollector.js';\nimport { logger as rootLogger } from '../logger.js';\nimport type { IssuePoller } from '../poller/IssuePoller.js';\nimport type { Server } from 'node:http';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst logger = rootLogger.child('WebServer');\n\nexport interface WebServerDeps {\n tracker: IssueTracker;\n config: Config;\n agentLogStore: AgentLogStore;\n orchestrator: PipelineOrchestrator;\n gongfeng: GongfengClient;\n supplementStore: SupplementStore;\n mainGit?: GitOperations;\n autoUpdater?: AutoUpdater;\n poller?: IssuePoller;\n braindumpOrchestrator?: BraindumpOrchestrator;\n distillScheduler?: DistillScheduler;\n diaryStore?: DiaryStore;\n vectorStore?: VectorStore;\n diaryCollector?: DiaryCollector;\n claimer?: IssueClaimer | null;\n configReloader?: ConfigReloader;\n orphanManager?: OrphanBranchManager;\n aiRunner?: AIRunner;\n wsConfig?: import('../workspace/WorkspaceConfig.js').WorkspaceConfig;\n previewReaper?: import('../deploy/PreviewReaper.js').PreviewReaper;\n}\n\nexport class WebServer {\n private app: express.Application;\n private server: Server | null = null;\n private host: string;\n private port: number;\n\n constructor(deps: WebServerDeps);\n constructor(tracker: IssueTracker, config: Config, agentLogStore: AgentLogStore, orchestrator: PipelineOrchestrator, mainGit?: GitOperations);\n constructor(\n trackerOrDeps: IssueTracker | WebServerDeps,\n config?: Config,\n agentLogStore?: AgentLogStore,\n orchestrator?: PipelineOrchestrator,\n mainGit?: GitOperations,\n ) {\n let apiDeps: ApiRouterDeps;\n\n if (trackerOrDeps instanceof IssueTracker) {\n this.host = config!.web.host;\n this.port = config!.web.port;\n apiDeps = {\n tracker: trackerOrDeps,\n config: config!,\n agentLogStore: agentLogStore!,\n orchestrator: orchestrator!,\n mainGit,\n gongfeng: undefined as unknown as GongfengClient,\n supplementStore: undefined as unknown as SupplementStore,\n };\n } else {\n const deps = trackerOrDeps;\n this.host = deps.config.web.host;\n this.port = deps.config.web.port;\n apiDeps = {\n tracker: deps.tracker,\n config: deps.config,\n agentLogStore: deps.agentLogStore,\n orchestrator: deps.orchestrator,\n mainGit: deps.mainGit,\n gongfeng: deps.gongfeng,\n supplementStore: deps.supplementStore,\n autoUpdater: deps.autoUpdater,\n poller: deps.poller,\n braindumpTracker: deps.braindumpOrchestrator?.getTracker(),\n distillScheduler: deps.distillScheduler,\n diaryCollector: deps.diaryCollector,\n claimer: deps.claimer,\n configReloader: deps.configReloader,\n wsConfig: deps.wsConfig,\n previewReaper: deps.previewReaper,\n };\n }\n\n this.app = express();\n this.app.use(express.json());\n\n // Prometheus metrics endpoint\n this.app.get('/metrics', (_req, res) => {\n res.set('Content-Type', 'text/plain; version=0.0.4; charset=utf-8');\n res.send(metrics.serialize());\n });\n\n const setupRouter = createSetupRouter({ serviceMode: true });\n this.app.use(setupRouter);\n\n const apiRouter = createApiRouter(apiDeps);\n this.app.use(apiRouter);\n\n // Always register feature routes (feature-gate middleware inside each router\n // handles runtime enable/disable, returning 503 when feature is off)\n const brainstormService = new BrainstormService(apiDeps.config);\n const brainstormRouter = createBrainstormRouter({\n brainstormService,\n gongfeng: apiDeps.gongfeng,\n config: apiDeps.config,\n });\n this.app.use(brainstormRouter);\n\n // KnowledgeStore uses the global DATA_DIR (consistent with index.ts)\n const globalKnowledgeDataDir = ensureDir(path.join(resolveDataDir(), 'knowledge'));\n const knowledgeStore = new KnowledgeStore(globalKnowledgeDataDir);\n\n // Migrate knowledge from project workDir to global DATA_DIR if needed\n const projectKnowledgeDir = path.join(apiDeps.config.project.workDir, 'data', 'knowledge');\n const projectKnowledgeIndex = path.join(projectKnowledgeDir, 'index.json');\n const globalKnowledgeIndex = path.join(globalKnowledgeDataDir, 'index.json');\n if (fs.existsSync(projectKnowledgeIndex) && !fs.existsSync(globalKnowledgeIndex)) {\n try {\n WebServer.migrateKnowledgeDir(projectKnowledgeDir, globalKnowledgeDataDir);\n logger.info('Migrated knowledge entries from project to global DATA_DIR', {\n src: projectKnowledgeDir,\n dest: globalKnowledgeDataDir,\n });\n } catch (err) {\n logger.warn('Failed to migrate knowledge entries to global DATA_DIR', {\n error: (err as Error).message,\n });\n }\n }\n\n const chatService = new ChatService(apiDeps.config, knowledgeStore);\n const chatRouter = createChatRouter({ chatService, config: apiDeps.config });\n this.app.use(chatRouter);\n\n const iwikiImporter = new IwikiImporter(knowledgeStore, {\n authCookie: apiDeps.config.iwiki?.authCookie,\n authToken: apiDeps.config.iwiki?.authToken,\n });\n\n // Migrate legacy knowledge.json if present\n const legacyKnowledgePath = path.join(apiDeps.config.project.workDir, 'knowledge.json');\n knowledgeStore.migrateFromLegacy(legacyKnowledgePath);\n\n // Backward-compatible migration: copy knowledge.json from workDir to DATA_DIR if needed\n const dataDirKnowledgePath = path.join(globalKnowledgeDataDir, 'knowledge.json');\n if (fs.existsSync(legacyKnowledgePath) && !fs.existsSync(dataDirKnowledgePath)) {\n try {\n fs.copyFileSync(legacyKnowledgePath, dataDirKnowledgePath);\n logger.info('Migrated knowledge.json from project to DATA_DIR', {\n src: legacyKnowledgePath,\n dest: dataDirKnowledgePath,\n });\n } catch (err) {\n logger.warn('Failed to migrate knowledge.json to DATA_DIR', {\n error: (err as Error).message,\n });\n }\n }\n\n const knowledgeRouter = createKnowledgeRouter({\n knowledgeStore,\n iwikiImporter,\n config: apiDeps.config,\n });\n this.app.use(knowledgeRouter);\n\n // Distill routes — always registered; feature-gate middleware inside handles\n // disabled state and missing components (returning 503)\n const distillDeps = !(trackerOrDeps instanceof IssueTracker)\n ? (trackerOrDeps as WebServerDeps)\n : undefined;\n const distillRouter = createDistillRouter({\n distillScheduler: distillDeps?.distillScheduler,\n diaryStore: distillDeps?.diaryStore,\n vectorStore: distillDeps?.vectorStore,\n config: apiDeps.config,\n });\n this.app.use(distillRouter);\n\n const domainModelAnalyzer = new DomainModelAnalyzer();\n const domainModelRouter = createDomainModelRouter({\n analyzer: domainModelAnalyzer,\n knowledgeStore,\n config: apiDeps.config,\n });\n this.app.use(domainModelRouter);\n\n const systemUseCaseAnalyzer = new SystemUseCaseAnalyzer();\n const systemUseCaseRouter = createSystemUseCaseRouter({\n analyzer: systemUseCaseAnalyzer,\n domainModelAnalyzer,\n knowledgeStore,\n config: apiDeps.config,\n });\n this.app.use(systemUseCaseRouter);\n\n // Braindump routes — orchestrator may be undefined in legacy constructor path\n const braindumpOrc = !(trackerOrDeps instanceof IssueTracker)\n ? (trackerOrDeps as WebServerDeps).braindumpOrchestrator\n : undefined;\n const braindumpRouter = createBraindumpRouter({\n braindumpOrchestrator: braindumpOrc,\n config: apiDeps.config,\n });\n this.app.use(braindumpRouter);\n\n // Sync routes — always available, no feature gate\n const syncRouter = createSyncRouter({ config: apiDeps.config });\n this.app.use(syncRouter);\n\n // Knowledge sync routes (orphan branch publish/restore)\n const orphanMgr = !(trackerOrDeps instanceof IssueTracker)\n ? (trackerOrDeps as WebServerDeps).orphanManager\n : undefined;\n const knowledgeSyncRouter = createKnowledgeSyncRouter({\n orphanManager: orphanMgr,\n config: apiDeps.config,\n });\n this.app.use(knowledgeSyncRouter);\n\n // Analytics routes — always registered; feature-gate middleware inside\n const analyticsAiRunner = !(trackerOrDeps instanceof IssueTracker)\n ? (trackerOrDeps as WebServerDeps).aiRunner\n : undefined;\n if (analyticsAiRunner) {\n const analyticsRouter = createAnalyticsRouter({\n aiRunner: analyticsAiRunner,\n knowledgeStore,\n config: apiDeps.config,\n });\n this.app.use(analyticsRouter);\n }\n\n const publicDir = apiDeps.config.web.frontendDistDir;\n this.app.use(express.static(publicDir));\n\n this.app.get('/{*splat}', (_req, res) => {\n res.sendFile('index.html', { root: publicDir });\n });\n }\n\n start(): Promise<void> {\n return new Promise((resolve) => {\n this.server = this.app.listen(this.port, this.host, () => {\n logger.info(`Web UI available at http://${resolveDisplayHost(this.host)}:${this.port}`);\n resolve();\n });\n });\n }\n\n stop(): void {\n if (this.server) {\n this.server.close();\n this.server = null;\n logger.info('Web server stopped');\n }\n }\n\n /**\n * Migrate knowledge data from a project-local directory to the global DATA_DIR.\n * Copies index.json and all entry files without overwriting existing files.\n */\n private static migrateKnowledgeDir(srcDir: string, destDir: string): void {\n // Copy index.json\n const srcIndex = path.join(srcDir, 'index.json');\n const destIndex = path.join(destDir, 'index.json');\n if (fs.existsSync(srcIndex) && !fs.existsSync(destIndex)) {\n fs.copyFileSync(srcIndex, destIndex);\n }\n\n // Copy entries\n const srcEntries = path.join(srcDir, 'entries');\n if (fs.existsSync(srcEntries)) {\n const destEntries = path.join(destDir, 'entries');\n if (!fs.existsSync(destEntries)) {\n fs.mkdirSync(destEntries, { recursive: true });\n }\n for (const file of fs.readdirSync(srcEntries)) {\n const src = path.join(srcEntries, file);\n const dest = path.join(destEntries, file);\n if (fs.statSync(src).isFile() && !fs.existsSync(dest)) {\n fs.copyFileSync(src, dest);\n }\n }\n }\n\n // Copy knowledge.json (ProjectKnowledge analysis result) if present\n const srcKnowledge = path.join(srcDir, 'knowledge.json');\n const destKnowledge = path.join(destDir, 'knowledge.json');\n if (fs.existsSync(srcKnowledge) && !fs.existsSync(destKnowledge)) {\n fs.copyFileSync(srcKnowledge, destKnowledge);\n }\n }\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { marked } from 'marked';\nimport { IssueTracker } from '../../tracker/IssueTracker.js';\nimport { IssueState } from '../../tracker/IssueState.js';\nimport type { DemandSpec } from '../../demand/DemandSpec.js';\nimport { getIid, getExternalId, getTitle } from '../../tracker/IssueRecordHelper.js';\nimport { Config } from '../../config.js';\nimport { AgentLogStore } from '../AgentLogStore.js';\nimport { PipelineOrchestrator } from '../../orchestrator/PipelineOrchestrator.js';\nimport { GitOperations } from '../../git/GitOperations.js';\nimport { GongfengClient } from '../../clients/GongfengClient.js';\nimport { SupplementStore } from '../../supplement/SupplementStore.js';\nimport { PlanPersistence } from '../../persistence/PlanPersistence.js';\nimport { getPipelineDef, getAllPipelineDefs, createLifecycleManager } from '../../pipeline/PipelineDefinition.js';\nimport type { PipelineDef } from '../../pipeline/PipelineDefinition.js';\nimport { ActionLifecycleManager } from '../../lifecycle/ActionLifecycleManager.js';\nimport { eventBus, EventPayload } from '../../events/EventBus.js';\nimport {\n getNoteSyncEnabled, setNoteSyncOverride, isNoteSyncEnabledForIssue,\n} from '../../notesync/NoteSyncSettings.js';\nimport { getE2eEnabled, setE2eOverride } from '../../e2e/E2eSettings.js';\nimport { getFeatureEnabled, setFeatureOverride } from '../../settings/ExperimentalSettings.js';\nimport type { ExperimentalFeature } from '../../settings/ExperimentalSettings.js';\nimport { isMultiRepo } from '../../workspace/WorkspaceConfig.js';\nimport type { WorkspaceConfig } from '../../workspace/WorkspaceConfig.js';\nimport { logger as rootLogger } from '../../logger.js';\nimport { t } from '../../i18n/index.js';\nimport type { AutoUpdater } from '../../updater/AutoUpdater.js';\nimport type { IssuePoller } from '../../poller/IssuePoller.js';\nimport type { BraindumpTracker } from '../../braindump/BraindumpTracker.js';\nimport type { ExecutableTask } from '../../tracker/ExecutableTask.js';\nimport type { DistillScheduler } from '../../distill/DistillScheduler.js';\nimport type { DiaryCollector } from '../../distill/DiaryCollector.js';\nimport type { IssueClaimer } from '../../coordination/IssueClaimer.js';\nimport type { ConfigReloader } from '../../config/ConfigReloader.js';\nimport type { PreviewReaper } from '../../deploy/PreviewReaper.js';\n\nconst logger = rootLogger.child('ApiRoutes');\n\n/** Stream event types filtered from the SSE stream (protocol-level metadata with no user-facing value). */\nconst DEBUG_SSE_EVENT_TYPES = new Set([\n 'thinking', 'content_block_start', 'content_block_delta',\n 'content_block_stop', 'message_start', 'message_delta',\n 'message_stop', 'ping',\n 'message', // 顶级消息框架 - 含 uuid/session_id 等协议元数据\n]);\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nfunction readPackageVersion(): string {\n try {\n for (let dir = __dirname; dir !== path.dirname(dir); dir = path.dirname(dir)) {\n const candidate = path.join(dir, 'package.json');\n if (fs.existsSync(candidate)) {\n const content = JSON.parse(fs.readFileSync(candidate, 'utf-8'));\n if (content.name === '@xdevops/issue-auto-finish' || content.name === 'issue-auto-finish') {\n return content.version;\n }\n }\n }\n } catch { /* ignore */ }\n return 'unknown';\n}\n\nconst startTime = Date.now();\nconst pkgVersion = readPackageVersion();\n\nexport interface ApiRouterDeps {\n tracker: IssueTracker;\n config: Config;\n agentLogStore: AgentLogStore;\n orchestrator: PipelineOrchestrator;\n gongfeng: GongfengClient;\n supplementStore: SupplementStore;\n mainGit?: GitOperations;\n autoUpdater?: AutoUpdater;\n poller?: IssuePoller;\n braindumpTracker?: BraindumpTracker;\n distillScheduler?: DistillScheduler;\n diaryCollector?: DiaryCollector;\n claimer?: IssueClaimer | null;\n configReloader?: ConfigReloader;\n wsConfig?: WorkspaceConfig;\n previewReaper?: PreviewReaper;\n}\n\nfunction buildPreviewInfo(iid: number, orch: PipelineOrchestrator) {\n const ports = orch.getPortAllocator().getPortsForIssue(iid);\n if (!ports) return null;\n const dsm = orch.getDevServerManager();\n const status = dsm.getStatus(iid);\n return {\n ...status,\n ports,\n previewUrl: orch.buildPreviewUrl(iid),\n host: orch.getPreviewHost(),\n };\n}\n\nexport function createApiRouter(deps: ApiRouterDeps): ReturnType<typeof Router>;\nexport function createApiRouter(tracker: IssueTracker, config: Config, agentLogStore: AgentLogStore, orchestrator: PipelineOrchestrator, mainGit?: GitOperations): ReturnType<typeof Router>;\nexport function createApiRouter(\n trackerOrDeps: IssueTracker | ApiRouterDeps,\n config?: Config,\n agentLogStore?: AgentLogStore,\n orchestrator?: PipelineOrchestrator,\n mainGit?: GitOperations,\n): ReturnType<typeof Router> {\n let tracker: IssueTracker;\n let cfg: Config;\n let logStore: AgentLogStore;\n let orch: PipelineOrchestrator;\n let git: GitOperations | undefined;\n let gongfeng: GongfengClient | undefined;\n let supplementStore: SupplementStore | undefined;\n let autoUpdater: AutoUpdater | undefined;\n let poller: IssuePoller | undefined;\n let braindumpTracker: BraindumpTracker | undefined;\n let distillScheduler: DistillScheduler | undefined;\n let diaryCollector: DiaryCollector | undefined;\n let claimer: IssueClaimer | null | undefined;\n let configReloader: ConfigReloader | undefined;\n let wsConfig: WorkspaceConfig | undefined;\n let previewReaper: PreviewReaper | undefined;\n\n if (config !== undefined) {\n tracker = trackerOrDeps as IssueTracker;\n cfg = config!;\n logStore = agentLogStore!;\n orch = orchestrator!;\n git = mainGit;\n } else {\n const deps = trackerOrDeps as ApiRouterDeps;\n tracker = deps.tracker;\n cfg = deps.config;\n logStore = deps.agentLogStore;\n orch = deps.orchestrator;\n git = deps.mainGit;\n gongfeng = deps.gongfeng;\n supplementStore = deps.supplementStore;\n autoUpdater = deps.autoUpdater;\n poller = deps.poller;\n braindumpTracker = deps.braindumpTracker;\n distillScheduler = deps.distillScheduler;\n diaryCollector = deps.diaryCollector;\n claimer = deps.claimer;\n configReloader = deps.configReloader;\n wsConfig = deps.wsConfig;\n previewReaper = deps.previewReaper;\n }\n\n const router = Router();\n\n function getLifecycleManager(pipelineMode?: string): ActionLifecycleManager {\n return createLifecycleManager(getPipelineDef(pipelineMode ?? 'plan-mode'));\n }\n\n router.get('/api/pipeline-meta', (_req: Request, res: Response) => {\n const allDefs = getAllPipelineDefs();\n const allLMs = allDefs.map(def => ({ def, lm: createLifecycleManager(def) }));\n\n const modes: Record<string, unknown> = {};\n const phaseStatuses: Record<string, Record<string, Record<string, string>>> = {};\n for (const { def, lm } of allLMs) {\n modes[def.mode] = {\n phases: def.phases.map(p => ({ name: p.name, label: p.label, kind: p.kind })),\n artifacts: lm.collectArtifacts().map(a => ({\n filename: a.filename, label: a.label, editable: a.editable,\n })),\n retryablePhases: lm.getRetryablePhases(),\n };\n phaseStatuses[def.mode] = buildPhaseStatusMap(def, lm);\n }\n\n res.json({\n modes,\n stateLabels: Object.fromEntries(new Map(\n allLMs.flatMap(({ lm }) => [...lm.collectStateLabels()]),\n )),\n phaseStatuses,\n stateCategories: buildStateCategoryMap(allLMs.map(({ lm }) => lm)),\n });\n });\n\n router.get('/api/e2e-test-route', (_req: Request, res: Response) => {\n res.json({ ok: true, ts: Date.now() });\n });\n\n router.get('/api/issues', (_req: Request, res: Response) => {\n const issues = tracker.getAll();\n const enriched = issues.map(r => {\n const lm = getLifecycleManager(r.pipelineMode);\n let stateCategory: string;\n if (lm.isTerminal(r.state)) {\n if (r.state === IssueState.Failed) stateCategory = 'failed';\n else if (r.state === IssueState.Deployed) stateCategory = 'deployed';\n else if (r.state === IssueState.Completed) stateCategory = 'completed';\n else stateCategory = 'skipped';\n } else if (lm.isBlocked(r.state)) {\n stateCategory = 'blocked';\n } else {\n stateCategory = 'active';\n }\n return { ...r, stateCategory };\n });\n res.json(enriched);\n });\n\n router.get('/api/tasks', (req: Request, res: Response) => {\n // 收集所有 Issue 任务\n const issueTasks = tracker.toExecutableTasks();\n\n // 收集所有 Braindump 任务\n const braindumpTasks: ExecutableTask[] = [];\n if (braindumpTracker) {\n for (const batch of braindumpTracker.getAll()) {\n braindumpTasks.push(...braindumpTracker.toExecutableTasks(batch.id));\n }\n }\n\n let allTasks = [...issueTasks, ...braindumpTasks];\n\n // 可选过滤\n const kindFilter = req.query.kind as string | undefined;\n const statusFilter = req.query.status as string | undefined;\n if (kindFilter) {\n allTasks = allTasks.filter(t => t.kind === kindFilter);\n }\n if (statusFilter) {\n const statuses = new Set(statusFilter.split(','));\n allTasks = allTasks.filter(t => statuses.has(t.status));\n }\n\n // 按 updatedAt 降序排列\n allTasks.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());\n\n res.json(allTasks);\n });\n\n router.get('/api/issues/:iid', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const progress = await readProgress(iid, cfg, tracker, git);\n const preview = buildPreviewInfo(iid, orch);\n res.json({ ...record, progress, preview });\n });\n\n function getIssuePipelineDef(iid: number): PipelineDef {\n const record = tracker.get(iid);\n const mode = record?.pipelineMode ?? orch.getPipelineDef().mode;\n return getPipelineDef(mode);\n }\n\n router.get('/api/issues/:iid/plans/:filename', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const filename = req.params.filename;\n const def = getIssuePipelineDef(iid);\n const lm = createLifecycleManager(def);\n const allowed = [\n ...lm.collectArtifacts().map(f => f.filename),\n 'progress.json', 'issue-meta.json',\n ];\n if (!allowed.includes(filename)) {\n res.status(400).json({ error: 'Invalid filename' });\n return;\n }\n const content = await readPlanFile(iid, filename, cfg, tracker, git);\n if (content === null) {\n res.status(404).json({ error: 'Plan file not found' });\n return;\n }\n if (filename.endsWith('.json')) {\n res.json(JSON.parse(content));\n return;\n }\n if (req.query.format === 'html') {\n const html = await marked(content);\n res.type('html').send(html);\n return;\n }\n res.type('text/markdown').send(content);\n });\n\n router.post('/api/issues/:iid/start', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const ok = tracker.startSkipped(iid);\n if (!ok) {\n res.status(400).json({ error: 'Issue is not in skipped state or not found' });\n return;\n }\n res.json({ success: true, message: `Issue #${iid} started` });\n });\n\n router.post('/api/issues/:iid/retry', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const ok = tracker.resetForRetry(iid);\n if (!ok) {\n res.status(400).json({ error: 'Issue is not in failed state or not found' });\n return;\n }\n res.json({ success: true, message: `Issue #${iid} reset for retry` });\n });\n\n router.post('/api/issues/:iid/cancel', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found in tracker' });\n return;\n }\n\n try {\n // 释放锁评论\n if (claimer) {\n try {\n await claimer.releaseClaim(getExternalId(record), iid, 'cancelled');\n } catch (err) {\n logger.warn('Failed to release lock on cancel', { iid, error: (err as Error).message });\n }\n }\n\n // 释放 poller 并发槽位\n poller?.forceReleaseIssue(iid);\n\n // 统一取消:终止 AI → 停预览 → 移标签 → 清 worktree/分支 → 删 tracker\n await orch.cancelIssue(iid);\n\n res.json({ success: true, message: `Issue #${iid} cancelled and cleaned up` });\n } catch (err) {\n res.status(400).json({ error: (err as Error).message });\n }\n });\n\n router.post('/api/issues/:iid/restart', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n try {\n // 释放锁评论\n if (claimer) {\n const record = tracker.get(iid);\n if (record) {\n await claimer.releaseClaim(getExternalId(record), iid, 'cancelled');\n }\n }\n\n poller?.forceReleaseIssue(iid);\n await orch.restartIssue(iid);\n res.json({ success: true, message: `Issue #${iid} restarted` });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Restart failed', { iid, error: msg });\n res.status(400).json({ error: msg });\n }\n });\n\n router.post('/api/issues/:iid/retry-from-phase', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const { phase } = req.body as { phase?: string };\n const def = getIssuePipelineDef(iid);\n const lm = createLifecycleManager(def);\n const validPhases = lm.getRetryablePhases();\n if (!phase || !validPhases.includes(phase)) {\n res.status(400).json({ error: `Invalid phase. Must be one of: ${validPhases.join(', ')}` });\n return;\n }\n try {\n orch.retryFromPhase(iid, phase);\n res.json({ success: true, message: `Issue #${iid} reset to phase: ${phase}` });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Retry-from-phase failed', { iid, phase, error: msg });\n res.status(400).json({ error: msg });\n }\n });\n\n router.put('/api/issues/:iid/plans/:filename', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const filename = req.params.filename;\n const def = getIssuePipelineDef(iid);\n const lm = createLifecycleManager(def);\n const editableFiles = lm.collectArtifacts().filter(f => f.editable).map(f => f.filename);\n if (!editableFiles.includes(filename)) {\n res.status(400).json({ error: `File not editable. Allowed: ${editableFiles.join(', ')}` });\n return;\n }\n const { content } = req.body as { content?: string };\n if (typeof content !== 'string') {\n res.status(400).json({ error: 'Request body must contain a \"content\" string field' });\n return;\n }\n const planDir = getWorktreePlanDir(iid, cfg);\n const filePath = path.join(planDir, filename);\n if (!fs.existsSync(planDir)) {\n res.status(404).json({ error: 'Plan directory not found (worktree may have been cleaned)' });\n return;\n }\n fs.writeFileSync(filePath, content, 'utf-8');\n logger.info('Plan file updated', { iid, filename });\n res.json({ success: true, message: `Plan file ${filename} saved` });\n });\n\n router.get('/api/issues/:iid/logs', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const logs = logStore.getLogs(iid);\n res.json(logs);\n });\n\n // --- Supplement endpoints ---\n\n router.get('/api/issues/:iid/supplement', (req: Request, res: Response) => {\n if (!supplementStore) {\n res.status(501).json({ error: 'Supplement store not available' });\n return;\n }\n const iid = parseInt(req.params.iid, 10);\n const info = supplementStore.get(iid);\n res.json(info);\n });\n\n router.put('/api/issues/:iid/supplement', (req: Request, res: Response) => {\n if (!supplementStore) {\n res.status(501).json({ error: 'Supplement store not available' });\n return;\n }\n const iid = parseInt(req.params.iid, 10);\n const body = req.body as Record<string, unknown>;\n const data = {\n requirements: String(body.requirements || ''),\n acceptanceCriteria: String(body.acceptanceCriteria || ''),\n scope: String(body.scope || ''),\n constraints: String(body.constraints || ''),\n references: String(body.references || ''),\n freeText: String(body.freeText || ''),\n tapdId: String(body.tapdId || ''),\n };\n const saved = supplementStore.save(iid, data);\n res.json({ success: true, data: saved });\n });\n\n // --- Gongfeng issue browsing ---\n\n router.get('/api/gongfeng/issues', async (req: Request, res: Response) => {\n if (!gongfeng) {\n res.status(501).json({ error: 'Gongfeng client not available' });\n return;\n }\n try {\n const search = (req.query.search as string) || '';\n const page = parseInt(req.query.page as string, 10) || 1;\n const perPage = parseInt(req.query.per_page as string, 10) || 20;\n\n const result = await gongfeng.listIssuesAdvanced({\n state: 'opened',\n search: search || undefined,\n page,\n perPage,\n });\n\n const trackedIids = new Set(tracker.getAll().map((r) => getIid(r)));\n\n res.json({\n issues: result.issues,\n total: result.total,\n trackedIids: Array.from(trackedIids),\n });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Failed to fetch gongfeng issues', { error: msg });\n res.status(500).json({ error: msg });\n }\n });\n\n // --- Start processing an issue ---\n\n router.post('/api/issues/start', async (req: Request, res: Response) => {\n if (!gongfeng) {\n res.status(501).json({ error: 'Gongfeng client not available' });\n return;\n }\n const body = req.body as {\n issueId?: number;\n issueIid?: number;\n issueTitle?: string;\n supplement?: Record<string, string>;\n };\n if (!body.issueId || !body.issueIid || !body.issueTitle) {\n res.status(400).json({ error: 'issueId, issueIid, and issueTitle are required' });\n return;\n }\n\n const existing = tracker.get(body.issueIid);\n if (existing) {\n res.status(409).json({ error: `Issue #${body.issueIid} is already being tracked` });\n return;\n }\n\n try {\n await gongfeng.addLabel(body.issueId, 'auto-finish');\n } catch (err) {\n logger.warn('Failed to add auto-finish label', { error: (err as Error).message });\n }\n\n const branchName = `${cfg.project.branchPrefix}-${body.issueIid}`;\n const demandSpec: DemandSpec = {\n demandId: `gf-${body.issueIid}`,\n sourceRef: {\n source: 'gongfeng-issue',\n externalId: String(body.issueId),\n displayId: String(body.issueIid),\n },\n title: body.issueTitle,\n description: '',\n createdAt: new Date().toISOString(),\n };\n const record = tracker.create({\n state: IssueState.Pending,\n branchName,\n demandSpec,\n });\n\n if (supplementStore && body.supplement) {\n supplementStore.save(body.issueIid, {\n requirements: String(body.supplement.requirements || ''),\n acceptanceCriteria: String(body.supplement.acceptanceCriteria || ''),\n scope: String(body.supplement.scope || ''),\n constraints: String(body.supplement.constraints || ''),\n references: String(body.supplement.references || ''),\n freeText: String(body.supplement.freeText || ''),\n tapdId: String(body.supplement.tapdId || ''),\n });\n }\n\n res.json({ success: true, record });\n });\n\n // --- Review Gate endpoints ---\n\n router.post('/api/issues/:iid/approve-plan', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n if (record.state !== IssueState.PhaseWaiting) {\n res.status(400).json({ error: `Issue is not waiting for review (current state: ${record.state})` });\n return;\n }\n tracker.updateState(iid, IssueState.PhaseApproved, { currentPhase: 'review' });\n const def = getIssuePipelineDef(iid);\n const lm = createLifecycleManager(def);\n const reviewSpec = lm.getGatePhase();\n if (reviewSpec) {\n const workDir = getWorktreeWorkDir(iid, cfg);\n const planPersistence = new PlanPersistence(workDir, iid);\n planPersistence.updatePhaseProgress(reviewSpec.name, 'completed');\n }\n eventBus.emitTyped('review:approved', { issueIid: iid });\n logger.info('Plan approved', { iid });\n res.json({ success: true, message: `Issue #${iid} plan approved, will resume on next drive cycle` });\n });\n\n router.post('/api/issues/:iid/reject-plan', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n if (record.state !== IssueState.PhaseWaiting) {\n res.status(400).json({ error: `Issue is not waiting for review (current state: ${record.state})` });\n return;\n }\n const { feedback } = req.body as { feedback?: string };\n if (!feedback || typeof feedback !== 'string') {\n res.status(400).json({ error: 'Feedback is required' });\n return;\n }\n const workDir = getWorktreeWorkDir(iid, cfg);\n if (fs.existsSync(workDir)) {\n const planPersistence = new PlanPersistence(workDir, iid);\n planPersistence.writeReviewFeedback(feedback);\n }\n tracker.updateState(iid, IssueState.BranchCreated);\n eventBus.emitTyped('review:rejected', { issueIid: iid, feedback });\n logger.info('Plan rejected', { iid, feedback: feedback.slice(0, 100) });\n\n if (gongfeng && isNoteSyncEnabledForIssue(iid, tracker, cfg)) {\n const baseUrl = cfg.issueNoteSync.webBaseUrl.replace(/\\/$/, '');\n const planFile = record.pipelineMode === 'plan-mode' ? '01-plan.md' : '02-design.md';\n const history = fs.existsSync(workDir)\n ? new PlanPersistence(workDir, iid).readReviewHistory()\n : [];\n const round = history.length;\n const note = [\n t('api.reviewFeedback', { round }),\n '',\n feedback,\n '',\n '---',\n t('api.viewPlan', { url: `${baseUrl}/doc/${iid}/${planFile}` }),\n t('api.viewDetail', { url: `${baseUrl}/?issue=${iid}` }),\n ].join('\\n');\n gongfeng.createIssueNote(getExternalId(record), note).catch((err) => {\n logger.warn('Failed to sync review feedback to issue', { error: (err as Error).message });\n });\n }\n\n res.json({ success: true, message: `Issue #${iid} plan rejected, will re-plan on next drive cycle` });\n });\n\n router.post('/api/issues/:iid/skip-review', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n if (record.state !== IssueState.PhaseWaiting) {\n res.status(400).json({ error: `Issue is not waiting for review (current state: ${record.state})` });\n return;\n }\n tracker.updateState(iid, IssueState.PhaseApproved, { currentPhase: 'review' });\n const def = getIssuePipelineDef(iid);\n const lm = createLifecycleManager(def);\n const reviewSpec = lm.getGatePhase();\n if (reviewSpec) {\n const workDir = getWorktreeWorkDir(iid, cfg);\n const planPersistence = new PlanPersistence(workDir, iid);\n planPersistence.updatePhaseProgress(reviewSpec.name, 'completed');\n }\n eventBus.emitTyped('review:approved', { issueIid: iid });\n logger.info('Review skipped', { iid });\n res.json({ success: true, message: `Issue #${iid} review skipped` });\n });\n\n router.get('/api/issues/:iid/review-history', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const workDir = getWorktreeWorkDir(iid, cfg);\n if (!fs.existsSync(workDir)) {\n res.json([]);\n return;\n }\n const planPersistence = new PlanPersistence(workDir, iid);\n res.json(planPersistence.readReviewHistory());\n });\n\n // --- Note Sync toggle endpoints ---\n\n router.put('/api/issues/:iid/note-sync', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const { enabled } = req.body as { enabled?: boolean | null };\n const value = enabled === null ? undefined : enabled;\n tracker.updateState(iid, record.state, { issueNoteSyncEnabled: value } as any);\n logger.info('Issue note-sync toggled', { iid, enabled: value });\n res.json({ success: true, issueNoteSyncEnabled: value ?? null });\n });\n\n router.put('/api/system/note-sync', (req: Request, res: Response) => {\n const { enabled } = req.body as { enabled?: boolean };\n if (typeof enabled !== 'boolean') {\n res.status(400).json({ error: 'enabled must be a boolean' });\n return;\n }\n setNoteSyncOverride(enabled);\n logger.info('System note-sync toggled', { enabled });\n res.json({ success: true, issueNoteSyncEnabled: enabled });\n });\n\n // --- Preview endpoints ---\n\n router.get('/api/issues/:iid/preview', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const preview = buildPreviewInfo(iid, orch);\n res.json(preview ?? { running: false });\n });\n\n router.post('/api/issues/:iid/stop-preview', (_req: Request, res: Response) => {\n const iid = parseInt(_req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n orch.stopPreviewServers(iid);\n res.json({ success: true });\n });\n\n router.post('/api/issues/:iid/mark-deployed', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n try {\n if (claimer) {\n const record = tracker.get(iid);\n if (record) {\n const externalId = getExternalId(record);\n await claimer.releaseClaim(externalId, iid, 'deployed');\n }\n }\n poller?.forceReleaseIssue(iid);\n await orch.markDeployed(iid);\n res.json({ success: true });\n } catch (e) {\n res.status(400).json({ error: (e as Error).message });\n }\n });\n\n router.post('/api/issues/:iid/restart-preview', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n try {\n const previewUrl = await orch.restartPreview(iid);\n res.json({ success: true, previewUrl });\n } catch (e) {\n res.status(400).json({ error: (e as Error).message });\n }\n });\n\n router.get('/api/issues/:iid/preview-logs/:type', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const logType = req.params.type;\n if (logType !== 'backend' && logType !== 'frontend') {\n res.status(400).json({ error: 'type must be \"backend\" or \"frontend\"' });\n return;\n }\n const logPath = orch.getDevServerManager().getLogPath(iid, logType);\n if (!logPath) {\n res.status(404).json({ error: 'Log file not found' });\n return;\n }\n const tail = parseInt(req.query.tail as string, 10);\n if (tail > 0) {\n const content = fs.readFileSync(logPath, 'utf-8');\n const lines = content.split('\\n');\n // 保留末尾可能的空行\n const start = Math.max(0, lines.length - tail);\n res.type('text/plain').send(lines.slice(start).join('\\n'));\n return;\n }\n res.type('text/plain').sendFile(logPath);\n });\n\n router.get('/api/preview-reaper/status', (_req: Request, res: Response) => {\n if (!previewReaper) {\n res.json({ enabled: false });\n return;\n }\n res.json({ enabled: true, ...previewReaper.getStatus() });\n });\n\n // --- E2E UI toggle endpoints ---\n\n router.put('/api/issues/:iid/e2e', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const { enabled } = req.body as { enabled?: boolean | null };\n const value = enabled === null ? undefined : enabled;\n tracker.updateState(iid, record.state, { e2eEnabled: value } as any);\n logger.info('Issue e2e toggled', { iid, enabled: value });\n res.json({ success: true, e2eEnabled: value ?? null });\n });\n\n router.put('/api/system/e2e', (req: Request, res: Response) => {\n const { enabled } = req.body as { enabled?: boolean };\n if (typeof enabled !== 'boolean') {\n res.status(400).json({ error: 'enabled must be a boolean' });\n return;\n }\n setE2eOverride(enabled);\n logger.info('System e2e toggled', { enabled });\n res.json({ success: true, e2eEnabled: enabled });\n });\n\n // --- Experimental feature toggle endpoint ---\n\n router.put('/api/system/feature-toggle', (req: Request, res: Response) => {\n const { feature, enabled } = req.body as { feature?: string; enabled?: boolean };\n const validFeatures: ExperimentalFeature[] = ['brainstorm', 'chat', 'braindump', 'knowledge', 'distill'];\n if (!feature || !validFeatures.includes(feature as ExperimentalFeature) || typeof enabled !== 'boolean') {\n res.status(400).json({ error: 'Invalid feature or enabled value' });\n return;\n }\n setFeatureOverride(feature as ExperimentalFeature, enabled);\n\n // Distill has background processing that needs to be started/stopped at runtime\n if (feature === 'distill') {\n if (enabled) {\n distillScheduler?.start();\n diaryCollector?.start();\n } else {\n distillScheduler?.stop();\n diaryCollector?.stop();\n }\n }\n\n logger.info('Experimental feature toggled', { feature, enabled });\n res.json({ success: true, feature, enabled });\n });\n\n router.get('/api/system/status', (_req: Request, res: Response) => {\n const runningPreviews = orch.getDevServerManager().getRunningIssues();\n const allIssues = tracker.getAll();\n const failedCount = allIssues.filter(r => r.state === IssueState.Failed).length;\n res.json({\n uptime: Date.now() - startTime,\n startedAt: new Date(startTime).toISOString(),\n pid: process.pid,\n version: pkgVersion,\n config: {\n discoveryIntervalMs: cfg.poll.discoveryIntervalMs,\n driveIntervalMs: cfg.poll.driveIntervalMs,\n maxRetries: cfg.poll.maxRetries,\n maxConcurrent: cfg.poll.maxConcurrent,\n aiMode: cfg.ai.mode,\n aiModel: cfg.ai.model,\n pipelineMode: orch.getPipelineDef().mode,\n baseBranch: cfg.project.baseBranch,\n projectPath: cfg.gongfeng.projectPath,\n gongfengBaseUrl: cfg.gongfeng.apiUrl.replace(/\\/$/, ''),\n webHost: cfg.web.host,\n webPort: cfg.web.port,\n issueNoteSyncEnabled: getNoteSyncEnabled(cfg),\n e2eEnabled: getE2eEnabled(cfg),\n previewEnabled: cfg.preview.enabled,\n releaseEnabled: cfg.release.enabled,\n locale: cfg.locale,\n brainstormEnabled: getFeatureEnabled('brainstorm', cfg),\n chatEnabled: getFeatureEnabled('chat', cfg),\n braindumpEnabled: getFeatureEnabled('braindump', cfg),\n knowledgeEnabled: getFeatureEnabled('knowledge', cfg),\n distillEnabled: getFeatureEnabled('distill', cfg),\n knowledgeSyncEnabled: true,\n multiRepoEnabled: wsConfig ? isMultiRepo(wsConfig) : false,\n linkedRepos: wsConfig?.associates.map(a => ({\n name: a.name,\n projectPath: a.projectPath,\n baseBranch: a.baseBranch,\n })) ?? [],\n },\n issues: {\n total: allIssues.length,\n active: tracker.getAllActive().length,\n failed: failedCount,\n },\n preview: {\n runningCount: runningPreviews.length,\n runningIssues: runningPreviews,\n },\n });\n });\n\n router.post('/api/system/reload-config', async (_req: Request, res: Response) => {\n if (!configReloader) {\n res.status(503).json({ error: 'Config reloader not available' });\n return;\n }\n try {\n const result = await configReloader.reload();\n if (result.success) {\n res.json({ success: true, message: 'Config reloaded successfully' });\n } else {\n res.status(409).json({ success: false, reason: result.reason });\n }\n } catch (err) {\n logger.error('Config reload failed', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.post('/api/system/shutdown', (_req: Request, res: Response) => {\n res.json({ success: true, message: 'Shutdown initiated' });\n // Delay to allow the response to be sent\n setTimeout(() => {\n logger.info('Shutdown requested via API');\n process.kill(process.pid, 'SIGTERM');\n }, 200);\n });\n\n router.get('/api/events', (req: Request, res: Response) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n const heartbeat = setInterval(() => {\n res.write(`event: heartbeat\\ndata: ${JSON.stringify({ time: new Date().toISOString() })}\\n\\n`);\n }, 15_000);\n\n const handler = (_eventName: string | symbol, payload: EventPayload) => {\n try {\n // Filter debug-level stream events from agent output to reduce SSE noise\n if (payload.type === 'agent:output') {\n const d = payload.data as { event?: { type?: string } };\n if (d?.event?.type && DEBUG_SSE_EVENT_TYPES.has(d.event.type)) return;\n }\n res.write(`event: ${payload.type}\\ndata: ${JSON.stringify(payload)}\\n\\n`);\n } catch {\n logger.warn('Failed to write SSE event');\n }\n };\n\n eventBus.on('*', handler);\n res.write(`event: connected\\ndata: ${JSON.stringify({ time: new Date().toISOString() })}\\n\\n`);\n\n req.on('close', () => {\n clearInterval(heartbeat);\n eventBus.off('*', handler);\n });\n });\n\n // --- Standalone document viewer (linked from issue notes) ---\n\n router.get('/doc/:iid/:filename', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const filename = req.params.filename;\n const record = tracker.get(iid);\n const title = record ? getTitle(record) : `Issue #${iid}`;\n\n const def = getIssuePipelineDef(iid);\n const lm = createLifecycleManager(def);\n const allowed = lm.collectArtifacts().map(f => f.filename);\n if (!allowed.includes(filename)) {\n res.status(400).type('html').send(renderDocPage(iid, title, t('api.invalidFilename'), filename));\n return;\n }\n\n const content = await readPlanFile(iid, filename, cfg, tracker, git);\n if (content === null) {\n res.status(404).type('html').send(renderDocPage(iid, title, t('api.docNotGenerated'), filename));\n return;\n }\n\n const htmlBody = await marked(content);\n res.type('html').send(renderDocPage(iid, title, htmlBody, filename));\n });\n\n // --- Auto-update endpoints ---\n\n router.get('/api/system/update-status', (_req: Request, res: Response) => {\n if (!autoUpdater) {\n res.status(501).json({ error: 'Auto-updater not available' });\n return;\n }\n res.json(autoUpdater.getStatus());\n });\n\n router.post('/api/system/update-check', async (_req: Request, res: Response) => {\n if (!autoUpdater) {\n res.status(501).json({ error: 'Auto-updater not available' });\n return;\n }\n try {\n const result = await autoUpdater.checkForUpdate();\n res.json(result);\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Manual update check failed', { error: msg });\n res.status(500).json({ error: msg });\n }\n });\n\n router.post('/api/system/update', async (_req: Request, res: Response) => {\n if (!autoUpdater) {\n res.status(501).json({ error: 'Auto-updater not available' });\n return;\n }\n try {\n res.json({ success: true, message: 'Update triggered' });\n // Fire and forget — the process will be restarted by PM2\n autoUpdater.triggerUpdate().catch((err) => {\n logger.error('Manual update failed', { error: (err as Error).message });\n });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Failed to trigger update', { error: msg });\n res.status(500).json({ error: msg });\n }\n });\n\n // --- Coordination lock management endpoints ---\n\n router.post('/api/coordination/migrate-locks', async (_req: Request, res: Response) => {\n if (!claimer) {\n res.status(501).json({ error: 'Claimer not available (multi-node coordination disabled)' });\n return;\n }\n try {\n const allRecords = tracker.getAll();\n const terminalStates = new Set([\n IssueState.Completed, IssueState.Failed, IssueState.Skipped,\n ]);\n const activeRecords = allRecords.filter(r => !terminalStates.has(r.state));\n\n let migrated = 0;\n for (const record of activeRecords) {\n try {\n const issueId = getExternalId(record);\n const iid = getIid(record);\n const notes = await gongfeng!.listIssueNotes(issueId);\n const { findLockNote } = await import('../../coordination/LockNote.js');\n const existingLock = findLockNote(notes);\n if (!existingLock) {\n const result = await claimer.tryClaim(\n { id: issueId, iid, labels: [], title: '', state: '', updated_at: '' } as any,\n notes,\n );\n if (result.success) {\n migrated++;\n logger.info('Migrated lock for issue', { iid });\n }\n }\n } catch (err) {\n logger.warn('Failed to migrate lock for issue', {\n iid: getIid(record),\n error: (err as Error).message,\n });\n }\n }\n\n res.json({ success: true, migrated, total: activeRecords.length });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Lock migration failed', { error: msg });\n res.status(500).json({ error: msg });\n }\n });\n\n router.post('/api/coordination/release-locks', async (_req: Request, res: Response) => {\n if (!claimer) {\n res.status(501).json({ error: 'Claimer not available (multi-node coordination disabled)' });\n return;\n }\n try {\n const allRecords = tracker.getAll();\n const terminalStates = new Set([\n IssueState.Completed, IssueState.Failed, IssueState.Skipped,\n ]);\n const activeRecords = allRecords.filter(r => !terminalStates.has(r.state));\n\n let released = 0;\n for (const record of activeRecords) {\n try {\n const issueId = getExternalId(record);\n const iid = getIid(record);\n await claimer.releaseClaim(issueId, iid, 'cancelled');\n released++;\n } catch (err) {\n logger.warn('Failed to release lock', {\n iid: getIid(record),\n error: (err as Error).message,\n });\n }\n }\n\n res.json({ success: true, released, total: activeRecords.length });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Lock release failed', { error: msg });\n res.status(500).json({ error: msg });\n }\n });\n\n // -----------------------------------------------------------------------\n // E2E Artifacts — browse screenshots / videos from oa_pc_uat outputs\n // -----------------------------------------------------------------------\n\n function isE2eConfigured(): boolean {\n return !!cfg.e2e.uatVendorDir;\n }\n\n function resolveE2eOutputsDir(issueIid?: string): string | null {\n const vendorDir = cfg.e2e.uatVendorDir;\n if (!vendorDir) return null;\n\n const abs = path.isAbsolute(vendorDir)\n ? vendorDir\n : path.resolve(cfg.project.workDir, vendorDir);\n\n const outputsDir = issueIid\n ? path.join(abs, 'outputs', `issue-${issueIid}`)\n : path.join(abs, 'outputs');\n return fs.existsSync(outputsDir) ? outputsDir : null;\n }\n\n const IMAGE_EXTS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.webp']);\n const VIDEO_EXTS = new Set(['.webm', '.mp4', '.mkv', '.avi']);\n const DOC_EXTS = new Set(['.md', '.json', '.jsonl', '.log', '.py', '.html', '.har', '.txt']);\n const ALL_ARTIFACT_EXTS = new Set([...IMAGE_EXTS, ...VIDEO_EXTS, ...DOC_EXTS]);\n\n const RUN_DIR_PATTERN = /^\\d{8}-\\d{6}/;\n\n router.get('/api/e2e-artifacts', (req: Request, res: Response) => {\n const issueIid = req.query.issueIid as string | undefined;\n if (!isE2eConfigured()) {\n res.json({ configured: false, runs: [], scenarios: [] });\n return;\n }\n const outputsDir = resolveE2eOutputsDir(issueIid);\n if (!outputsDir) {\n res.json({ configured: true, runs: [], scenarios: [] });\n return;\n }\n try {\n const allDirs = fs.readdirSync(outputsDir, { withFileTypes: true })\n .filter(e => e.isDirectory());\n\n const runs = allDirs\n .filter(e => RUN_DIR_PATTERN.test(e.name))\n .map(e => {\n const runDir = path.join(outputsDir, e.name);\n const resultFile = path.join(runDir, 'result.json');\n let metadata: Record<string, unknown> | null = null;\n if (fs.existsSync(resultFile)) {\n try { metadata = JSON.parse(fs.readFileSync(resultFile, 'utf-8')); } catch { /* skip */ }\n }\n const counts = countArtifactFiles(runDir);\n return {\n runId: e.name,\n timestamp: e.name,\n imageCount: counts.images,\n videoCount: counts.videos,\n documentCount: counts.documents,\n metadata,\n };\n })\n .filter(r => r.imageCount > 0 || r.videoCount > 0 || r.documentCount > 0)\n .sort((a, b) => b.runId.localeCompare(a.runId));\n\n const scenariosDir = path.join(outputsDir, 'scenarios');\n let scenarios: Array<{ name: string; relativePath: string; type: ArtifactType; size: number }> = [];\n if (fs.existsSync(scenariosDir) && fs.statSync(scenariosDir).isDirectory()) {\n scenarios = collectArtifactFiles(scenariosDir, scenariosDir);\n }\n\n res.json({ configured: true, runs, scenarios });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n function countArtifactFiles(dir: string): { images: number; videos: number; documents: number } {\n let images = 0;\n let videos = 0;\n let documents = 0;\n try {\n const walk = (d: string) => {\n for (const entry of fs.readdirSync(d, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n walk(path.join(d, entry.name));\n } else {\n const ext = path.extname(entry.name).toLowerCase();\n if (IMAGE_EXTS.has(ext)) images++;\n else if (VIDEO_EXTS.has(ext)) videos++;\n else if (DOC_EXTS.has(ext)) documents++;\n }\n }\n };\n walk(dir);\n } catch { /* skip */ }\n return { images, videos, documents };\n }\n\n type ArtifactType = 'image' | 'video' | 'document';\n\n function classifyExt(ext: string): ArtifactType | null {\n if (IMAGE_EXTS.has(ext)) return 'image';\n if (VIDEO_EXTS.has(ext)) return 'video';\n if (DOC_EXTS.has(ext)) return 'document';\n return null;\n }\n\n function collectArtifactFiles(dir: string, base: string): Array<{ name: string; relativePath: string; type: ArtifactType; size: number }> {\n const result: Array<{ name: string; relativePath: string; type: ArtifactType; size: number }> = [];\n try {\n const walk = (d: string) => {\n for (const entry of fs.readdirSync(d, { withFileTypes: true })) {\n const fullPath = path.join(d, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n } else {\n const ext = path.extname(entry.name).toLowerCase();\n const fileType = classifyExt(ext);\n if (fileType) {\n const stat = fs.statSync(fullPath);\n result.push({\n name: entry.name,\n relativePath: path.relative(base, fullPath),\n type: fileType,\n size: stat.size,\n });\n }\n }\n }\n };\n walk(dir);\n } catch { /* skip */ }\n return result;\n }\n\n router.get('/api/e2e-artifacts/:runId/files', (req: Request, res: Response) => {\n const issueIid = req.query.issueIid as string | undefined;\n const outputsDir = resolveE2eOutputsDir(issueIid);\n if (!outputsDir) {\n res.status(404).json({ error: 'E2E outputs not configured' });\n return;\n }\n const runDir = path.join(outputsDir, req.params.runId);\n if (!fs.existsSync(runDir)) {\n res.status(404).json({ error: 'Run not found' });\n return;\n }\n // Prevent path traversal\n if (!runDir.startsWith(outputsDir)) {\n res.status(400).json({ error: 'Invalid run ID' });\n return;\n }\n\n const files = collectArtifactFiles(runDir, runDir);\n res.json({ runId: req.params.runId, files });\n });\n\n router.get('/api/e2e-scenarios/file/{*filePath}', (req: Request, res: Response) => {\n const issueIid = req.query.issueIid as string | undefined;\n const outputsDir = resolveE2eOutputsDir(issueIid);\n if (!outputsDir) {\n res.status(404).json({ error: 'E2E outputs not configured' });\n return;\n }\n const scenariosDir = path.join(outputsDir, 'scenarios');\n const rawFilePath = (req.params as Record<string, unknown>).filePath;\n const filePath = Array.isArray(rawFilePath) ? rawFilePath.join('/') : String(rawFilePath);\n const fullPath = path.resolve(scenariosDir, filePath);\n\n if (!fullPath.startsWith(scenariosDir)) {\n res.status(400).json({ error: 'Invalid path' });\n return;\n }\n if (!fs.existsSync(fullPath)) {\n res.status(404).json({ error: 'File not found' });\n return;\n }\n\n const ext = path.extname(fullPath).toLowerCase();\n const mimeMap: Record<string, string> = {\n '.md': 'text/markdown; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.jsonl': 'application/x-ndjson; charset=utf-8',\n '.log': 'text/plain; charset=utf-8',\n '.py': 'text/x-python; charset=utf-8',\n '.html': 'text/html; charset=utf-8',\n '.txt': 'text/plain; charset=utf-8',\n };\n res.setHeader('Content-Type', mimeMap[ext] ?? 'application/octet-stream');\n res.setHeader('Cache-Control', 'public, max-age=86400');\n fs.createReadStream(fullPath).pipe(res);\n });\n\n router.get('/api/e2e-artifacts/:runId/file/{*filePath}', (req: Request, res: Response) => {\n const issueIid = req.query.issueIid as string | undefined;\n const outputsDir = resolveE2eOutputsDir(issueIid);\n if (!outputsDir) {\n res.status(404).json({ error: 'E2E outputs not configured' });\n return;\n }\n const rawFilePath = (req.params as Record<string, unknown>).filePath;\n const filePath = Array.isArray(rawFilePath) ? rawFilePath.join('/') : String(rawFilePath);\n const fullPath = path.resolve(path.join(outputsDir, req.params.runId), filePath);\n\n // Prevent path traversal\n if (!fullPath.startsWith(outputsDir)) {\n res.status(400).json({ error: 'Invalid path' });\n return;\n }\n if (!fs.existsSync(fullPath)) {\n res.status(404).json({ error: 'File not found' });\n return;\n }\n\n const ext = path.extname(fullPath).toLowerCase();\n const mimeMap: Record<string, string> = {\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.webm': 'video/webm',\n '.mp4': 'video/mp4',\n '.mkv': 'video/x-matroska',\n '.avi': 'video/x-msvideo',\n '.md': 'text/markdown; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.jsonl': 'application/x-ndjson; charset=utf-8',\n '.log': 'text/plain; charset=utf-8',\n '.py': 'text/x-python; charset=utf-8',\n '.html': 'text/html; charset=utf-8',\n '.har': 'application/json; charset=utf-8',\n '.txt': 'text/plain; charset=utf-8',\n };\n res.setHeader('Content-Type', mimeMap[ext] ?? 'application/octet-stream');\n res.setHeader('Cache-Control', 'public, max-age=86400');\n fs.createReadStream(fullPath).pipe(res);\n });\n\n return router;\n}\n\nconst DOC_LABELS_FUNC = (filename: string): string => t(`docLabel.${filename}`) || filename;\n\nfunction renderDocPage(iid: number, issueTitle: string, htmlBody: string, filename: string): string {\n const docLabel = DOC_LABELS_FUNC(filename);\n return `<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Issue #${iid} — ${docLabel}</title>\n<style>\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif; margin: 0; padding: 0; color: #24292f; background: #f6f8fa; }\n .header { background: #fff; border-bottom: 1px solid #d0d7de; padding: 12px 24px; display: flex; align-items: center; gap: 12px; }\n .header .crumb { font-size: 14px; color: #57606a; }\n .header .crumb a { color: #0969da; text-decoration: none; }\n .header .crumb a:hover { text-decoration: underline; }\n .header .crumb .sep { margin: 0 4px; color: #8b949e; }\n .container { max-width: 900px; margin: 24px auto; background: #fff; border: 1px solid #d0d7de; border-radius: 6px; padding: 32px 40px; }\n .markdown-body h1 { font-size: 1.6em; border-bottom: 1px solid #d0d7de; padding-bottom: .3em; }\n .markdown-body h2 { font-size: 1.3em; border-bottom: 1px solid #d0d7de; padding-bottom: .3em; }\n .markdown-body h3 { font-size: 1.1em; }\n .markdown-body pre { background: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 16px; overflow-x: auto; }\n .markdown-body code { background: #f6f8fa; border-radius: 3px; padding: 0.2em 0.4em; font-size: 85%; }\n .markdown-body pre code { background: none; padding: 0; }\n .markdown-body table { border-collapse: collapse; width: 100%; }\n .markdown-body th, .markdown-body td { border: 1px solid #d0d7de; padding: 6px 13px; }\n .markdown-body th { background: #f6f8fa; }\n .markdown-body blockquote { margin: 0; padding: 0 1em; color: #57606a; border-left: 3px solid #d0d7de; }\n .markdown-body ul, .markdown-body ol { padding-left: 2em; }\n .markdown-body li { margin-top: 0.25em; }\n .markdown-body p { margin: 8px 0; }\n .markdown-body a { color: #0969da; }\n</style>\n</head>\n<body>\n <div class=\"header\">\n <div class=\"crumb\">\n <a href=\"/?issue=${iid}\">Issue #${iid}</a>\n <span class=\"sep\">/</span>\n <strong>${docLabel}</strong>\n <span class=\"sep\">·</span>\n <span style=\"font-size:12px;color:#57606a\">${escapeHtml(issueTitle)}</span>\n <span class=\"sep\">·</span>\n <a href=\"/?issue=${iid}\" style=\"font-size:12px\">${t('api.viewInDashboard')}</a>\n </div>\n </div>\n <div class=\"container\">\n <div class=\"markdown-body\">${htmlBody}</div>\n </div>\n</body>\n</html>`;\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\nfunction getWorktreeWorkDir(issueIid: number, config: Config): string {\n return path.join(\n config.project.worktreeBaseDir,\n `issue-${issueIid}`,\n config.project.projectSubDir,\n );\n}\n\nfunction getWorktreePlanDir(issueIid: number, config: Config): string {\n return path.join(getWorktreeWorkDir(issueIid, config), '.claude-plan', `issue-${issueIid}`);\n}\n\nfunction getPlanGitPath(issueIid: number, filename: string, config: Config): string {\n return path.posix.join(config.project.projectSubDir, '.claude-plan', `issue-${issueIid}`, filename);\n}\n\nasync function readPlanFileFromGit(\n issueIid: number,\n filename: string,\n config: Config,\n tracker: IssueTracker,\n mainGit?: GitOperations,\n): Promise<string | null> {\n if (!mainGit) return null;\n const record = tracker.get(issueIid);\n if (!record) return null;\n const gitPath = getPlanGitPath(issueIid, filename, config);\n return mainGit.showFile(record.branchName, gitPath);\n}\n\nconst VERIFY_REPORT_FALLBACKS: Record<string, string> = {\n '02-verify-report.md': '04-verify-report.md',\n};\n\nasync function readPlanFile(\n issueIid: number,\n filename: string,\n config: Config,\n tracker: IssueTracker,\n mainGit?: GitOperations,\n): Promise<string | null> {\n const planDir = getWorktreePlanDir(issueIid, config);\n const filePath = path.join(planDir, filename);\n if (fs.existsSync(filePath)) {\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n }\n const content = await readPlanFileFromGit(issueIid, filename, config, tracker, mainGit);\n if (content !== null) return content;\n\n const fallback = VERIFY_REPORT_FALLBACKS[filename];\n if (fallback) {\n return readPlanFile(issueIid, fallback, config, tracker, mainGit);\n }\n return null;\n}\n\nasync function readProgress(\n issueIid: number,\n config: Config,\n tracker: IssueTracker,\n mainGit?: GitOperations,\n): Promise<unknown | null> {\n // 刚重启的 Issue(Pending + 0 次尝试)不应返回旧进度数据\n const record = tracker.get(issueIid);\n if (record?.state === 'pending' && record.attempts === 0) {\n return null;\n }\n const content = await readPlanFile(issueIid, 'progress.json', config, tracker, mainGit);\n if (!content) return null;\n try {\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\n/**\n * 遍历所有 IssueState,调用 lm.derivePhaseStatuses 生成 { state → { phase → status } } 映射。\n * 为通用状态 PhaseRunning/PhaseDone,生成每个阶段的复合 key 条目。\n */\nfunction buildPhaseStatusMap(\n def: PipelineDef,\n lm: ActionLifecycleManager,\n): Record<string, Record<string, string>> {\n const result: Record<string, Record<string, string>> = {};\n for (const state of Object.values(IssueState)) {\n result[state] = lm.derivePhaseStatuses(state);\n }\n // Generate composite key entries for generic PhaseRunning/PhaseDone per phase\n for (const phase of def.phases) {\n if (phase.startState === IssueState.PhaseRunning) {\n const compositeKey = `phase_running:${phase.name}`;\n result[compositeKey] = lm.derivePhaseStatuses(IssueState.PhaseRunning, phase.name);\n }\n if (phase.doneState === IssueState.PhaseDone) {\n const compositeKey = `phase_done:${phase.name}`;\n result[compositeKey] = lm.derivePhaseStatuses(IssueState.PhaseDone, phase.name);\n }\n // Generate composite key entries for generic PhaseWaiting/PhaseApproved per phase\n if (phase.startState === IssueState.PhaseWaiting) {\n const compositeKey = `phase_waiting:${phase.name}`;\n result[compositeKey] = lm.derivePhaseStatuses(IssueState.PhaseWaiting, phase.name);\n }\n if (phase.doneState === IssueState.PhaseApproved) {\n const compositeKey = `phase_approved:${phase.name}`;\n result[compositeKey] = lm.derivePhaseStatuses(IssueState.PhaseApproved, phase.name);\n }\n // Generate composite key entries for Failed per phase\n {\n const failedKey = `failed:${phase.name}`;\n result[failedKey] = lm.derivePhaseStatuses(IssueState.Failed, phase.name);\n }\n }\n return result;\n}\n\n/**\n * 合并所有模式的状态分类映射:{ state → ActionStatus }。\n */\nfunction buildStateCategoryMap(\n lifecycleManagers: ActionLifecycleManager[],\n): Record<string, string> {\n const result: Record<string, string> = {};\n const [first, ...rest] = lifecycleManagers;\n if (!first) return result;\n for (const state of Object.values(IssueState)) {\n const resolved = first.resolve(state);\n // 如果第一个 LM 映射不到具体阶段(fallback to idle),尝试其余 LM\n if (resolved.action === 'init' && resolved.status === 'idle' && state !== IssueState.Pending) {\n let found = false;\n for (const lm of rest) {\n const altResolved = lm.resolve(state);\n if (altResolved.action !== 'init' || altResolved.status !== 'idle') {\n result[state] = altResolved.status;\n found = true;\n break;\n }\n }\n if (!found) {\n result[state] = resolved.status;\n }\n } else {\n result[state] = resolved.status;\n }\n }\n return result;\n}\n","import type { Config } from '../config.js';\n\nexport type ExperimentalFeature = 'brainstorm' | 'chat' | 'braindump' | 'knowledge' | 'distill' | 'analytics';\n\nconst overrides: Record<string, boolean | undefined> = {};\n\nexport function getFeatureEnabled(key: ExperimentalFeature, cfg: Config): boolean {\n return overrides[key] ?? cfg[key].enabled;\n}\n\nexport function setFeatureOverride(key: ExperimentalFeature, value: boolean): void {\n overrides[key] = value;\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { BrainstormService, type BrainstormStreamEvent } from '../../services/BrainstormService.js';\nimport { GongfengClient } from '../../clients/GongfengClient.js';\nimport type { Config } from '../../config.js';\nimport { getFeatureEnabled } from '../../settings/ExperimentalSettings.js';\nimport { logger as rootLogger } from '../../logger.js';\n\nconst logger = rootLogger.child('BrainstormRoutes');\n\nexport interface BrainstormRouterDeps {\n brainstormService: BrainstormService;\n gongfeng: GongfengClient;\n config: Config;\n}\n\nfunction sseWriter(res: Response) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n return (event: BrainstormStreamEvent) => {\n try {\n res.write(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`);\n } catch {\n logger.warn('Failed to write SSE brainstorm event');\n }\n };\n}\n\nexport function createBrainstormRouter(deps: BrainstormRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { brainstormService, gongfeng, config } = deps;\n\n // Feature-gate middleware: return 503 when brainstorm is disabled\n router.use('/api/brainstorm', (_req, res, next) => {\n if (!getFeatureEnabled('brainstorm', config)) {\n res.status(503).json({ error: 'Brainstorm feature is disabled' });\n return;\n }\n next();\n });\n\n router.post('/api/brainstorm/sessions', (req: Request, res: Response) => {\n try {\n const { transcript } = req.body as { transcript?: string };\n if (!transcript?.trim()) {\n res.status(400).json({ error: 'transcript is required' });\n return;\n }\n const session = brainstormService.createSession(transcript.trim());\n res.json({ success: true, session });\n } catch (err) {\n logger.error('Failed to create brainstorm session', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.get('/api/brainstorm/sessions/:id', (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n res.json({ success: true, session });\n });\n\n router.post('/api/brainstorm/sessions/:id/generate', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const write = sseWriter(res);\n try {\n await brainstormService.generate(req.params.id, write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n router.post('/api/brainstorm/sessions/:id/review', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const write = sseWriter(res);\n try {\n await brainstormService.review(req.params.id, write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n router.post('/api/brainstorm/sessions/:id/refine', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const write = sseWriter(res);\n try {\n await brainstormService.refine(req.params.id, write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n router.post('/api/brainstorm/sessions/:id/auto-refine', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const { rounds } = req.body as { rounds?: number };\n const write = sseWriter(res);\n try {\n await brainstormService.autoRefine(req.params.id, rounds, write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n router.post('/api/brainstorm/sessions/:id/create-issue', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n if (!session.currentSdd) {\n res.status(400).json({ error: 'No SDD generated yet' });\n return;\n }\n\n try {\n const { title, addAutoFinishLabel } = req.body as {\n title?: string;\n addAutoFinishLabel?: boolean;\n };\n const issueTitle = title?.trim() || extractTitle(session.currentSdd);\n const labels = addAutoFinishLabel !== false ? ['auto-finish'] : [];\n const issue = await gongfeng.createIssue(issueTitle, session.currentSdd, labels);\n logger.info('Issue created from brainstorm', { issueIid: issue.iid, sessionId: session.id });\n res.json({ success: true, issue });\n } catch (err) {\n logger.error('Failed to create issue from brainstorm', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n\nfunction extractTitle(sdd: string): string {\n const firstLine = sdd.split('\\n').find(l => l.trim());\n if (firstLine) {\n return firstLine.replace(/^#+\\s*/, '').trim().slice(0, 200);\n }\n return '脑暴生成的需求';\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { ChatService, type ChatStreamEvent } from '../../services/ChatService.js';\nimport type { Config } from '../../config.js';\nimport { getFeatureEnabled } from '../../settings/ExperimentalSettings.js';\nimport { logger as rootLogger } from '../../logger.js';\n\nconst logger = rootLogger.child('ChatRoutes');\n\nexport interface ChatRouterDeps {\n chatService: ChatService;\n config: Config;\n}\n\nfunction sseWriter(res: Response) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n return (event: ChatStreamEvent) => {\n try {\n res.write(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`);\n } catch {\n logger.warn('Failed to write SSE chat event');\n }\n };\n}\n\nexport function createChatRouter(deps: ChatRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { chatService, config } = deps;\n\n // Feature-gate middleware: return 503 when chat is disabled\n router.use('/api/chat', (_req, res, next) => {\n if (!getFeatureEnabled('chat', config)) {\n res.status(503).json({ error: 'Chat feature is disabled' });\n return;\n }\n next();\n });\n\n // Create session\n router.post('/api/chat/sessions', (req: Request, res: Response) => {\n try {\n const { title } = req.body as { title?: string };\n const session = chatService.createSession(title?.trim());\n res.json({ success: true, session });\n } catch (err) {\n logger.error('Failed to create chat session', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // List sessions\n router.get('/api/chat/sessions', (_req: Request, res: Response) => {\n try {\n const sessions = chatService.listSessions();\n res.json({ success: true, sessions });\n } catch (err) {\n logger.error('Failed to list chat sessions', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // Get session\n router.get('/api/chat/sessions/:id', (req: Request, res: Response) => {\n const session = chatService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n res.json({ success: true, session });\n });\n\n // Delete session\n router.delete('/api/chat/sessions/:id', (req: Request, res: Response) => {\n const deleted = chatService.deleteSession(req.params.id);\n if (!deleted) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n res.json({ success: true });\n });\n\n // Send message (SSE streaming response)\n router.post('/api/chat/sessions/:id/messages', async (req: Request, res: Response) => {\n const session = chatService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const { content } = req.body as { content?: string };\n if (!content?.trim()) {\n res.status(400).json({ error: 'content is required' });\n return;\n }\n\n const write = sseWriter(res);\n try {\n await chatService.sendMessage(req.params.id, content.trim(), write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n return router;\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { logger as rootLogger } from '../../logger.js';\nimport type { KnowledgeStore } from '../../knowledge/KnowledgeStore.js';\nimport type { IwikiImporter } from '../../knowledge/importers/IwikiImporter.js';\nimport type { GongfengExtractor } from '../../knowledge/importers/GongfengExtractor.js';\nimport type { KnowledgeEntryType } from '../../knowledge/KnowledgeEntry.js';\nimport type { Config } from '../../config.js';\nimport { getFeatureEnabled } from '../../settings/ExperimentalSettings.js';\n\nconst logger = rootLogger.child('KnowledgeRoutes');\n\nexport interface KnowledgeRouterDeps {\n knowledgeStore: KnowledgeStore;\n iwikiImporter: IwikiImporter;\n gongfengExtractor?: GongfengExtractor;\n config: Config;\n}\n\nexport function createKnowledgeRouter(deps: KnowledgeRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { knowledgeStore, iwikiImporter, gongfengExtractor, config } = deps;\n\n // Feature-gate middleware: return 503 when knowledge is disabled\n router.use('/api/knowledge', (_req, res, next) => {\n if (!getFeatureEnabled('knowledge', config)) {\n res.status(503).json({ error: 'Knowledge feature is disabled' });\n return;\n }\n next();\n });\n\n // GET /api/knowledge/entries - list entries\n router.get('/api/knowledge/entries', (req: Request, res: Response) => {\n try {\n const type = req.query.type as KnowledgeEntryType | undefined;\n const q = req.query.q as string | undefined;\n\n let entries;\n if (q) {\n entries = knowledgeStore.search(q);\n } else {\n entries = knowledgeStore.list(type || undefined);\n }\n res.json({ success: true, entries });\n } catch (err) {\n logger.error('Failed to list knowledge entries', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // GET /api/knowledge/entries/:id - get single entry with content\n router.get('/api/knowledge/entries/:id', (req: Request, res: Response) => {\n try {\n const entry = knowledgeStore.get(req.params.id);\n if (!entry) {\n res.status(404).json({ error: 'Entry not found' });\n return;\n }\n res.json({ success: true, entry });\n } catch (err) {\n logger.error('Failed to get knowledge entry', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/knowledge/entries - create custom entry\n router.post('/api/knowledge/entries', (req: Request, res: Response) => {\n try {\n const { title, content, tags, type } = req.body as {\n title?: string;\n content?: string;\n tags?: string[];\n type?: KnowledgeEntryType;\n };\n if (!title?.trim() || !content?.trim()) {\n res.status(400).json({ error: 'title and content are required' });\n return;\n }\n const entry = knowledgeStore.create({\n type: type || 'custom',\n title: title.trim(),\n content: content.trim(),\n tags: tags || [],\n });\n res.json({ success: true, entry });\n } catch (err) {\n logger.error('Failed to create knowledge entry', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // PUT /api/knowledge/entries/:id - update entry\n router.put('/api/knowledge/entries/:id', (req: Request, res: Response) => {\n try {\n const { title, content, tags } = req.body as {\n title?: string;\n content?: string;\n tags?: string[];\n };\n const entry = knowledgeStore.update(req.params.id, { title, content, tags });\n if (!entry) {\n res.status(404).json({ error: 'Entry not found' });\n return;\n }\n res.json({ success: true, entry });\n } catch (err) {\n logger.error('Failed to update knowledge entry', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // DELETE /api/knowledge/entries/:id\n router.delete('/api/knowledge/entries/:id', (req: Request, res: Response) => {\n try {\n const deleted = knowledgeStore.delete(req.params.id);\n if (!deleted) {\n res.status(404).json({ error: 'Entry not found' });\n return;\n }\n res.json({ success: true });\n } catch (err) {\n logger.error('Failed to delete knowledge entry', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/knowledge/analyze - full analysis (SSE with progress)\n router.post('/api/knowledge/analyze', (req: Request, res: Response) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n const workDir = config.project.workDir;\n const startedAt = new Date().toISOString();\n const total = 4;\n let heartbeat: ReturnType<typeof setInterval> | undefined;\n let closed = false;\n\n function sendProgress(data: Record<string, unknown>) {\n if (closed) return;\n try { res.write('data: ' + JSON.stringify({ ...data, startedAt }) + '\\n\\n'); } catch { /* client gone */ }\n }\n\n (async () => {\n try {\n sendProgress({ step: 'collecting', current: 1, total, message: '收集项目信息...' });\n const { collectStaticInfo } = await import('../../knowledge/KnowledgeAnalyzer.js');\n await collectStaticInfo(workDir);\n\n sendProgress({ step: 'analyzing', current: 2, total, message: 'AI 分析中...' });\n const aiStart = Date.now();\n heartbeat = setInterval(() => {\n sendProgress({ step: 'analyzing', current: 2, total, message: 'AI 分析中...', elapsed: Date.now() - aiStart });\n }, 3000);\n\n const { createAIRunner } = await import('../../ai-runner/index.js');\n const runner = createAIRunner(config.ai);\n const { analyze } = await import('../../knowledge/KnowledgeAnalyzer.js');\n const knowledge = await analyze({ workDir, aiRunner: runner, syncToProject: config.sync.knowledgeToProject });\n clearInterval(heartbeat);\n heartbeat = undefined;\n\n sendProgress({ step: 'saving', current: 3, total, message: '保存分析结果...' });\n const { projectKnowledgeToMarkdown } = await import('../../knowledge/KnowledgeStore.js');\n const markdown = projectKnowledgeToMarkdown(knowledge);\n knowledgeStore.upsertProjectMeta(markdown, knowledge);\n knowledgeStore.setLastAnalyzedAt(knowledge.generatedAt);\n\n sendProgress({ step: 'done', current: 4, total, message: '分析完成' });\n } catch (err) {\n if (heartbeat) clearInterval(heartbeat);\n sendProgress({ step: 'error', error: (err as Error).message });\n } finally {\n res.end();\n }\n })();\n\n req.on('close', () => {\n closed = true;\n if (heartbeat) clearInterval(heartbeat);\n res.end();\n });\n });\n\n // POST /api/knowledge/analyze-incremental - incremental analysis (SSE with progress)\n router.post('/api/knowledge/analyze-incremental', (req: Request, res: Response) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n const startedAt = new Date().toISOString();\n const total = 3;\n let heartbeat: ReturnType<typeof setInterval> | undefined;\n let closed = false;\n\n function sendProgress(data: Record<string, unknown>) {\n if (closed) return;\n try { res.write('data: ' + JSON.stringify({ ...data, startedAt }) + '\\n\\n'); } catch { /* client gone */ }\n }\n\n (async () => {\n try {\n sendProgress({ step: 'collecting', current: 1, total, message: '检测变更并收集信息...' });\n\n const { createAIRunner } = await import('../../ai-runner/index.js');\n const { analyzeIncremental } = await import('../../knowledge/KnowledgeAnalyzer.js');\n const runner = createAIRunner(config.ai);\n\n sendProgress({ step: 'analyzing', current: 2, total, message: '增量分析中...' });\n const aiStart = Date.now();\n heartbeat = setInterval(() => {\n sendProgress({ step: 'analyzing', current: 2, total, message: '增量分析中...', elapsed: Date.now() - aiStart });\n }, 3000);\n\n const result = await analyzeIncremental({\n workDir: config.project.workDir,\n aiRunner: runner,\n store: knowledgeStore,\n syncToProject: config.sync.knowledgeToProject,\n });\n clearInterval(heartbeat);\n heartbeat = undefined;\n\n if (!result) {\n sendProgress({ step: 'no_changes', current: total, total, message: '自上次分析以来无变更' });\n } else {\n sendProgress({ step: 'done', current: 3, total, message: '增量分析完成', changedFiles: result.changedFiles });\n }\n } catch (err) {\n if (heartbeat) clearInterval(heartbeat);\n sendProgress({ step: 'error', error: (err as Error).message });\n } finally {\n res.end();\n }\n })();\n\n req.on('close', () => {\n closed = true;\n if (heartbeat) clearInterval(heartbeat);\n res.end();\n });\n });\n\n // POST /api/knowledge/import/iwiki - import iwiki page\n router.post('/api/knowledge/import/iwiki', async (req: Request, res: Response) => {\n try {\n const { url } = req.body as { url?: string };\n if (!url?.trim()) {\n res.status(400).json({ error: 'url is required' });\n return;\n }\n const entry = await iwikiImporter.importFromUrl(url.trim());\n res.json({ success: true, entry });\n } catch (err) {\n logger.error('Failed to import iwiki page', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/knowledge/import/gongfeng - extract from gongfeng\n router.post('/api/knowledge/import/gongfeng', async (req: Request, res: Response) => {\n try {\n if (!gongfengExtractor) {\n res.status(400).json({ error: 'Gongfeng extractor not available' });\n return;\n }\n const { type, iid } = req.body as { type?: 'issue' | 'mr'; iid?: number };\n if (!type || !iid) {\n res.status(400).json({ error: 'type and iid are required' });\n return;\n }\n const workDir = config.project.workDir;\n const entry = type === 'issue'\n ? await gongfengExtractor.extractFromIssue(iid, workDir)\n : await gongfengExtractor.extractFromMR(iid, workDir);\n res.json({ success: true, entry });\n } catch (err) {\n logger.error('Failed to extract from gongfeng', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/knowledge/entries/:id/sync - re-sync iwiki/gongfeng entry\n router.post('/api/knowledge/entries/:id/sync', async (req: Request, res: Response) => {\n try {\n const entry = knowledgeStore.get(req.params.id);\n if (!entry) {\n res.status(404).json({ error: 'Entry not found' });\n return;\n }\n if (entry.type === 'iwiki') {\n const updated = await iwikiImporter.sync(req.params.id);\n res.json({ success: true, entry: updated });\n } else {\n res.status(400).json({ error: 'Only iwiki entries support sync' });\n }\n } catch (err) {\n logger.error('Failed to sync entry', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // GET /api/knowledge/stats\n router.get('/api/knowledge/stats', (_req: Request, res: Response) => {\n try {\n const stats = knowledgeStore.getStats();\n res.json({ success: true, stats });\n } catch (err) {\n logger.error('Failed to get knowledge stats', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { logger as rootLogger } from '../../logger.js';\nimport type { DistillScheduler } from '../../distill/DistillScheduler.js';\nimport type { DiaryStore } from '../../distill/DiaryStore.js';\nimport type { VectorStore } from '../../distill/VectorStore.js';\nimport type { Config } from '../../config.js';\nimport { getFeatureEnabled } from '../../settings/ExperimentalSettings.js';\n\nconst logger = rootLogger.child('DistillRoutes');\n\nexport interface DistillRouterDeps {\n distillScheduler?: DistillScheduler;\n diaryStore?: DiaryStore;\n vectorStore?: VectorStore;\n config: Config;\n}\n\nexport function createDistillRouter(deps: DistillRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { distillScheduler, diaryStore, vectorStore, config } = deps;\n\n // Feature-gate middleware: return 503 when distill is disabled or components unavailable\n router.use('/api/distill', (_req, res, next) => {\n if (!getFeatureEnabled('distill', config)) {\n res.status(503).json({ error: 'Distill feature is disabled' });\n return;\n }\n if (!distillScheduler || !diaryStore || !vectorStore) {\n res.status(503).json({ error: 'Distill components are not initialized' });\n return;\n }\n next();\n });\n\n // GET /api/distill/status — distillation status overview\n router.get('/api/distill/status', (_req: Request, res: Response) => {\n try {\n const status = distillScheduler!.getStatus();\n res.json({ status });\n } catch (err) {\n logger.error('Failed to get distill status', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/distill/run — manually trigger distillation (SSE stream)\n router.post('/api/distill/run', (req: Request, res: Response) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n let closed = false;\n\n function send(data: Record<string, unknown>) {\n if (closed) return;\n try { res.write('data: ' + JSON.stringify(data) + '\\n\\n'); } catch { /* client gone */ }\n }\n\n (async () => {\n try {\n send({ step: 'started' });\n\n const result = await distillScheduler!.runDistill({ force: true });\n\n send({\n step: 'memory',\n processedDiaries: result.memory.processedDiaries,\n actions: result.memory.actions,\n });\n\n send({\n step: 'rule',\n processedMemories: result.rule.processedMemories,\n actions: result.rule.actions,\n });\n\n send({\n step: 'vector',\n indexed: result.vectorIndexed,\n });\n\n send({\n step: 'done',\n summary: result,\n });\n } catch (err) {\n send({ step: 'error', error: (err as Error).message });\n } finally {\n res.end();\n }\n })();\n\n req.on('close', () => {\n closed = true;\n res.end();\n });\n });\n\n // GET /api/distill/diaries — list diaries (paginated + filtered)\n router.get('/api/distill/diaries', (req: Request, res: Response) => {\n try {\n const outcome = req.query.outcome as 'completed' | 'failed' | undefined;\n const distilled = req.query.distilled as string | undefined;\n const limit = Math.min(parseInt(req.query.limit as string, 10) || 20, 100);\n const offset = parseInt(req.query.offset as string, 10) || 0;\n\n let all = diaryStore!.getAll();\n\n // Sort by createdAt descending (newest first)\n all.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n\n // Apply filters\n if (outcome) {\n all = all.filter(d => d.outcome === outcome);\n }\n if (distilled === 'true') {\n all = all.filter(d => d.distilled);\n } else if (distilled === 'false') {\n all = all.filter(d => !d.distilled);\n }\n\n const total = all.length;\n const diaries = all.slice(offset, offset + limit);\n\n res.json({ diaries, total });\n } catch (err) {\n logger.error('Failed to list diaries', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // GET /api/distill/diaries/:id — diary detail\n router.get('/api/distill/diaries/:id', (req: Request, res: Response) => {\n try {\n const diary = diaryStore!.get(req.params.id);\n if (!diary) {\n res.status(404).json({ error: 'Diary not found' });\n return;\n }\n res.json({ diary });\n } catch (err) {\n logger.error('Failed to get diary', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // DELETE /api/distill/diaries/:id — delete diary\n router.delete('/api/distill/diaries/:id', (req: Request, res: Response) => {\n try {\n const deleted = diaryStore!.delete(req.params.id);\n if (!deleted) {\n res.status(404).json({ error: 'Diary not found' });\n return;\n }\n res.json({ success: true });\n } catch (err) {\n logger.error('Failed to delete diary', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/distill/search — vector semantic search\n router.post('/api/distill/search', async (req: Request, res: Response) => {\n try {\n const { query, topK } = req.body as { query?: string; topK?: number };\n if (!query?.trim()) {\n res.status(400).json({ error: 'query is required' });\n return;\n }\n const results = await vectorStore!.search(query.trim(), topK ?? 5);\n res.json({ results });\n } catch (err) {\n logger.error('Failed to search vectors', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { logger as rootLogger } from '../../logger.js';\nimport type { DomainModelAnalyzer } from '../../knowledge/DomainModelAnalyzer.js';\nimport type { KnowledgeStore } from '../../knowledge/KnowledgeStore.js';\nimport type { Config } from '../../config.js';\nimport type { DomainModel, DomainElement, DomainRelationship } from '../../knowledge/DomainModel.js';\nimport { domainModelToConcepts } from '../../knowledge/DomainModel.js';\nimport { getFeatureEnabled } from '../../settings/ExperimentalSettings.js';\n\nconst logger = rootLogger.child('DomainModelRoutes');\n\nexport interface DomainModelRouterDeps {\n analyzer: DomainModelAnalyzer;\n knowledgeStore: KnowledgeStore;\n config: Config;\n}\n\nexport function createDomainModelRouter(deps: DomainModelRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { analyzer, knowledgeStore, config } = deps;\n\n // Feature-gate middleware: domain-model follows knowledge toggle\n router.use('/api/domain-model', (_req, res, next) => {\n if (!getFeatureEnabled('knowledge', config)) {\n res.status(503).json({ error: 'Knowledge feature is disabled' });\n return;\n }\n next();\n });\n\n // POST /api/domain-model/analyze - trigger analysis (SSE stream)\n router.post('/api/domain-model/analyze', (req: Request, res: Response) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n const refine = req.query.refine === 'true';\n const startedAt = new Date().toISOString();\n let closed = false;\n\n function send(data: Record<string, unknown>) {\n if (closed) return;\n try { res.write('data: ' + JSON.stringify({ ...data, startedAt }) + '\\n\\n'); } catch { /* client gone */ }\n }\n\n (async () => {\n try {\n const { createAIRunner } = await import('../../ai-runner/index.js');\n const runner = createAIRunner(config.ai);\n\n const model = await analyzer.analyze({\n workDir: config.project.workDir,\n aiRunner: runner,\n refineRounds: refine ? 2 : 0,\n onProgress: (event) => {\n if (event.type === 'agent-log') {\n const streamEvent = event.data as Record<string, unknown>;\n send({\n type: 'agent-log',\n streamType: streamEvent.type,\n content: streamEvent.content,\n timestamp: streamEvent.timestamp,\n });\n } else {\n send({ type: event.type, ...event.data as Record<string, unknown> });\n }\n },\n });\n\n send({ type: 'complete', model });\n } catch (err) {\n send({ type: 'error', error: (err as Error).message });\n } finally {\n if (!closed) res.end();\n }\n })();\n\n req.on('close', () => { closed = true; });\n });\n\n // GET /api/domain-model - get current model\n router.get('/api/domain-model', (_req: Request, res: Response) => {\n try {\n let model = analyzer.getCurrentModel();\n if (!model) {\n model = analyzer.loadFromStore(knowledgeStore) ?? undefined as unknown as DomainModel;\n }\n if (!model) {\n res.json({ success: true, model: null });\n return;\n }\n res.json({ success: true, model });\n } catch (err) {\n logger.error('Failed to get domain model', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // PUT /api/domain-model - save full model\n router.put('/api/domain-model', (req: Request, res: Response) => {\n try {\n const model = req.body as DomainModel;\n if (!model || !model.elements) {\n res.status(400).json({ error: 'Invalid domain model' });\n return;\n }\n model.updatedAt = new Date().toISOString();\n analyzer.setCurrentModel(model);\n res.json({ success: true, model });\n } catch (err) {\n logger.error('Failed to save domain model', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // PATCH /api/domain-model/elements/:id - update single element\n router.patch('/api/domain-model/elements/:id', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No domain model loaded' });\n return;\n }\n const idx = model.elements.findIndex((e) => e.id === req.params.id);\n if (idx === -1) {\n res.status(404).json({ error: 'Element not found' });\n return;\n }\n model.elements[idx] = { ...model.elements[idx], ...req.body as Partial<DomainElement> };\n model.updatedAt = new Date().toISOString();\n res.json({ success: true, element: model.elements[idx] });\n } catch (err) {\n logger.error('Failed to update element', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/domain-model/elements - add element\n router.post('/api/domain-model/elements', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No domain model loaded' });\n return;\n }\n const element = req.body as DomainElement;\n if (!element.id || !element.name) {\n res.status(400).json({ error: 'Element id and name are required' });\n return;\n }\n model.elements.push(element);\n model.updatedAt = new Date().toISOString();\n res.json({ success: true, element });\n } catch (err) {\n logger.error('Failed to add element', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // DELETE /api/domain-model/elements/:id - delete element\n router.delete('/api/domain-model/elements/:id', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No domain model loaded' });\n return;\n }\n const before = model.elements.length;\n model.elements = model.elements.filter((e) => e.id !== req.params.id);\n // Also remove relationships referencing this element\n model.relationships = model.relationships.filter(\n (r) => r.sourceId !== req.params.id && r.targetId !== req.params.id,\n );\n if (model.elements.length === before) {\n res.status(404).json({ error: 'Element not found' });\n return;\n }\n model.updatedAt = new Date().toISOString();\n res.json({ success: true });\n } catch (err) {\n logger.error('Failed to delete element', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/domain-model/relationships - add relationship\n router.post('/api/domain-model/relationships', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No domain model loaded' });\n return;\n }\n const relationship = req.body as DomainRelationship;\n if (!relationship.id || !relationship.sourceId || !relationship.targetId) {\n res.status(400).json({ error: 'Relationship id, sourceId and targetId are required' });\n return;\n }\n model.relationships.push(relationship);\n model.updatedAt = new Date().toISOString();\n res.json({ success: true, relationship });\n } catch (err) {\n logger.error('Failed to add relationship', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // DELETE /api/domain-model/relationships/:id - delete relationship\n router.delete('/api/domain-model/relationships/:id', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No domain model loaded' });\n return;\n }\n const before = model.relationships.length;\n model.relationships = model.relationships.filter((r) => r.id !== req.params.id);\n if (model.relationships.length === before) {\n res.status(404).json({ error: 'Relationship not found' });\n return;\n }\n model.updatedAt = new Date().toISOString();\n res.json({ success: true });\n } catch (err) {\n logger.error('Failed to delete relationship', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/domain-model/confirm - persist to knowledge store\n router.post('/api/domain-model/confirm', (_req: Request, res: Response) => {\n try {\n analyzer.confirmToStore(knowledgeStore);\n\n // Also update domainConcepts in project-meta if available\n const model = analyzer.getCurrentModel();\n if (model) {\n const concepts = domainModelToConcepts(model);\n logger.info('Domain model confirmed', { conceptsCount: concepts.length });\n }\n\n res.json({ success: true });\n } catch (err) {\n logger.error('Failed to confirm domain model', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n","import type { DomainConceptConfig } from './ProjectKnowledge.js';\n\n// ── Domain element types ──\n\nexport type DomainElementType =\n | 'entity'\n | 'value-object'\n | 'aggregate-root'\n | 'domain-service'\n | 'domain-event'\n | 'repository'\n | 'factory';\n\nexport interface DomainElementProperty {\n name: string;\n type: string;\n description?: string;\n}\n\nexport interface DomainElementMethod {\n name: string;\n description: string;\n isCommand?: boolean;\n}\n\nexport interface DomainElement {\n id: string;\n type: DomainElementType;\n name: string;\n displayName: string;\n description: string;\n properties: DomainElementProperty[];\n methods: DomainElementMethod[];\n sourceFiles: string[];\n boundedContextId: string;\n position?: { x: number; y: number };\n}\n\n// ── Relationship types ──\n\nexport type RelationshipType =\n | 'association'\n | 'aggregation'\n | 'composition'\n | 'inheritance'\n | 'implementation'\n | 'dependency'\n | 'event-publish'\n | 'event-subscribe';\n\nexport interface DomainRelationship {\n id: string;\n type: RelationshipType;\n sourceId: string;\n targetId: string;\n label?: string;\n description?: string;\n}\n\n// ── Bounded context ──\n\nexport interface BoundedContext {\n id: string;\n name: string;\n displayName: string;\n description: string;\n color?: string;\n position?: { x: number; y: number };\n dimensions?: { width: number; height: number };\n}\n\n// ── Top-level domain model ──\n\nexport interface DomainModel {\n version: number;\n projectPath: string;\n analyzedAt: string;\n updatedAt: string;\n boundedContexts: BoundedContext[];\n elements: DomainElement[];\n relationships: DomainRelationship[];\n notes?: string;\n}\n\n/**\n * Convert a DomainModel into the flat DomainConceptConfig[] format\n * used by ProjectKnowledge.domainConcepts for backward compatibility.\n */\nexport function domainModelToConcepts(model: DomainModel): DomainConceptConfig[] {\n return model.elements.map((el) => ({\n term: el.displayName || el.name,\n definition: [\n `[${el.type}]`,\n el.description,\n el.sourceFiles.length > 0 ? `(${el.sourceFiles.join(', ')})` : '',\n ].filter(Boolean).join(' '),\n }));\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { logger as rootLogger } from '../../logger.js';\nimport type { SystemUseCaseAnalyzer } from '../../knowledge/SystemUseCaseAnalyzer.js';\nimport type { DomainModelAnalyzer } from '../../knowledge/DomainModelAnalyzer.js';\nimport type { KnowledgeStore } from '../../knowledge/KnowledgeStore.js';\nimport type { Config } from '../../config.js';\nimport type { SystemUseCaseModel, SystemUseCase, UseCaseRelationship } from '../../knowledge/SystemUseCase.js';\nimport { getFeatureEnabled } from '../../settings/ExperimentalSettings.js';\n\nconst logger = rootLogger.child('SystemUseCaseRoutes');\n\nexport interface SystemUseCaseRouterDeps {\n analyzer: SystemUseCaseAnalyzer;\n domainModelAnalyzer: DomainModelAnalyzer;\n knowledgeStore: KnowledgeStore;\n config: Config;\n}\n\nexport function createSystemUseCaseRouter(deps: SystemUseCaseRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { analyzer, domainModelAnalyzer, knowledgeStore, config } = deps;\n\n // Feature-gate middleware: reuse knowledge toggle\n router.use('/api/system-usecase', (_req, res, next) => {\n if (!getFeatureEnabled('knowledge', config)) {\n res.status(503).json({ error: 'Knowledge feature is disabled' });\n return;\n }\n next();\n });\n\n // POST /api/system-usecase/analyze — SSE stream analysis\n router.post('/api/system-usecase/analyze', (req: Request, res: Response) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n const refine = req.query.refine === 'true';\n const startedAt = new Date().toISOString();\n let closed = false;\n\n function send(data: Record<string, unknown>) {\n if (closed) return;\n try { res.write('data: ' + JSON.stringify({ ...data, startedAt }) + '\\n\\n'); } catch { /* client gone */ }\n }\n\n (async () => {\n try {\n const { createAIRunner } = await import('../../ai-runner/index.js');\n const runner = createAIRunner(config.ai);\n\n const model = await analyzer.analyze({\n workDir: config.project.workDir,\n aiRunner: runner,\n refineRounds: refine ? 2 : 0,\n onProgress: (event) => {\n if (event.type === 'agent-log') {\n const streamEvent = event.data as Record<string, unknown>;\n send({\n type: 'agent-log',\n streamType: streamEvent.type,\n content: streamEvent.content,\n timestamp: streamEvent.timestamp,\n });\n } else {\n send({ type: event.type, ...event.data as Record<string, unknown> });\n }\n },\n });\n\n send({ type: 'complete', model });\n } catch (err) {\n send({ type: 'error', error: (err as Error).message });\n } finally {\n if (!closed) res.end();\n }\n })();\n\n req.on('close', () => { closed = true; });\n });\n\n // GET /api/system-usecase — get current model\n router.get('/api/system-usecase', (_req: Request, res: Response) => {\n try {\n let model = analyzer.getCurrentModel();\n if (!model) {\n model = analyzer.loadFromStore(knowledgeStore) ?? undefined as unknown as SystemUseCaseModel;\n }\n if (!model) {\n res.json({ success: true, model: null });\n return;\n }\n res.json({ success: true, model });\n } catch (err) {\n logger.error('Failed to get use case model', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // PUT /api/system-usecase — save full model\n router.put('/api/system-usecase', (req: Request, res: Response) => {\n try {\n const model = req.body as SystemUseCaseModel;\n if (!model || !model.useCases) {\n res.status(400).json({ error: 'Invalid use case model' });\n return;\n }\n model.updatedAt = new Date().toISOString();\n analyzer.setCurrentModel(model);\n res.json({ success: true, model });\n } catch (err) {\n logger.error('Failed to save use case model', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // PATCH /api/system-usecase/usecases/:id — update single use case\n router.patch('/api/system-usecase/usecases/:id', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No use case model loaded' });\n return;\n }\n const idx = model.useCases.findIndex((uc) => uc.id === req.params.id);\n if (idx === -1) {\n res.status(404).json({ error: 'Use case not found' });\n return;\n }\n model.useCases[idx] = { ...model.useCases[idx], ...req.body as Partial<SystemUseCase> };\n model.updatedAt = new Date().toISOString();\n res.json({ success: true, useCase: model.useCases[idx] });\n } catch (err) {\n logger.error('Failed to update use case', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/system-usecase/usecases — add use case\n router.post('/api/system-usecase/usecases', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No use case model loaded' });\n return;\n }\n const useCase = req.body as SystemUseCase;\n if (!useCase.id || !useCase.name) {\n res.status(400).json({ error: 'Use case id and name are required' });\n return;\n }\n model.useCases.push(useCase);\n model.updatedAt = new Date().toISOString();\n res.json({ success: true, useCase });\n } catch (err) {\n logger.error('Failed to add use case', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // DELETE /api/system-usecase/usecases/:id — delete use case\n router.delete('/api/system-usecase/usecases/:id', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No use case model loaded' });\n return;\n }\n const before = model.useCases.length;\n model.useCases = model.useCases.filter((uc) => uc.id !== req.params.id);\n // Also remove relationships referencing this use case\n model.relationships = model.relationships.filter(\n (r) => r.sourceId !== req.params.id && r.targetId !== req.params.id,\n );\n if (model.useCases.length === before) {\n res.status(404).json({ error: 'Use case not found' });\n return;\n }\n model.updatedAt = new Date().toISOString();\n res.json({ success: true });\n } catch (err) {\n logger.error('Failed to delete use case', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/system-usecase/relationships — add relationship\n router.post('/api/system-usecase/relationships', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No use case model loaded' });\n return;\n }\n const relationship = req.body as UseCaseRelationship;\n if (!relationship.id || !relationship.sourceId || !relationship.targetId) {\n res.status(400).json({ error: 'Relationship id, sourceId and targetId are required' });\n return;\n }\n model.relationships.push(relationship);\n model.updatedAt = new Date().toISOString();\n res.json({ success: true, relationship });\n } catch (err) {\n logger.error('Failed to add relationship', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // DELETE /api/system-usecase/relationships/:id — delete relationship\n router.delete('/api/system-usecase/relationships/:id', (req: Request, res: Response) => {\n try {\n const model = analyzer.getCurrentModel();\n if (!model) {\n res.status(404).json({ error: 'No use case model loaded' });\n return;\n }\n const before = model.relationships.length;\n model.relationships = model.relationships.filter((r) => r.id !== req.params.id);\n if (model.relationships.length === before) {\n res.status(404).json({ error: 'Relationship not found' });\n return;\n }\n model.updatedAt = new Date().toISOString();\n res.json({ success: true });\n } catch (err) {\n logger.error('Failed to delete relationship', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/system-usecase/confirm — persist to knowledge store\n router.post('/api/system-usecase/confirm', (_req: Request, res: Response) => {\n try {\n analyzer.confirmToStore(knowledgeStore);\n const model = analyzer.getCurrentModel();\n if (model) {\n logger.info('Use case model confirmed', { useCasesCount: model.useCases.length });\n }\n res.json({ success: true });\n } catch (err) {\n logger.error('Failed to confirm use case model', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/system-usecase/suggest-associations — AI suggest domain associations\n router.post('/api/system-usecase/suggest-associations', async (req: Request, res: Response) => {\n try {\n const useCaseModel = analyzer.getCurrentModel();\n if (!useCaseModel) {\n res.status(404).json({ error: 'No use case model loaded' });\n return;\n }\n\n const domainModel = domainModelAnalyzer.getCurrentModel();\n if (!domainModel) {\n res.status(404).json({ error: 'No domain model loaded — run domain analysis first' });\n return;\n }\n\n const { createAIRunner } = await import('../../ai-runner/index.js');\n const runner = createAIRunner(config.ai);\n\n const associations = await analyzer.suggestDomainAssociations(\n useCaseModel,\n domainModel,\n runner,\n config.project.workDir,\n );\n\n // Convert Map to plain object for JSON serialization\n const result: Record<string, string[]> = {};\n for (const [ucId, elementIds] of associations) {\n result[ucId] = elementIds;\n }\n\n res.json({ success: true, associations: result });\n } catch (err) {\n logger.error('Failed to suggest domain associations', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport type { BraindumpOrchestrator } from '../../braindump/BraindumpOrchestrator.js';\nimport type { BraindumpTask } from '../../braindump/BraindumpState.js';\nimport type { Config } from '../../config.js';\nimport { getFeatureEnabled } from '../../settings/ExperimentalSettings.js';\nimport { eventBus, type EventType } from '../../events/EventBus.js';\nimport { logger as rootLogger } from '../../logger.js';\n\nconst logger = rootLogger.child('BraindumpRoutes');\n\nexport interface BraindumpRouterDeps {\n braindumpOrchestrator?: BraindumpOrchestrator;\n config: Config;\n}\n\nexport function createBraindumpRouter(deps: BraindumpRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { braindumpOrchestrator, config } = deps;\n\n // Feature-gate middleware: return 503 when braindump is disabled or orchestrator unavailable\n router.use('/api/braindump', (_req, res, next) => {\n if (!getFeatureEnabled('braindump', config)) {\n res.status(503).json({ error: 'Braindump feature is disabled' });\n return;\n }\n if (!braindumpOrchestrator) {\n res.status(503).json({ error: 'Braindump orchestrator is not available' });\n return;\n }\n next();\n });\n\n // Create a new batch\n router.post('/api/braindump/batches', (req: Request, res: Response) => {\n try {\n const { rawInput, targetBranch, maxConcurrent, defaultAiRunnerMode } = req.body;\n if (!rawInput?.trim()) {\n res.status(400).json({ error: 'rawInput is required' });\n return;\n }\n const batch = braindumpOrchestrator!.createBatch(rawInput.trim(), {\n targetBranch,\n maxConcurrent,\n defaultAiRunnerMode,\n });\n res.json({ success: true, batch });\n } catch (err) {\n logger.error('Failed to create batch', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // List all batches\n router.get('/api/braindump/batches', (_req: Request, res: Response) => {\n try {\n const batches = braindumpOrchestrator!.getTracker().getAll();\n res.json({ success: true, batches });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // Get batch details\n router.get('/api/braindump/batches/:id', (req: Request, res: Response) => {\n const batch = braindumpOrchestrator!.getTracker().getBatch(req.params.id);\n if (!batch) {\n res.status(404).json({ error: 'Batch not found' });\n return;\n }\n res.json({ success: true, batch });\n });\n\n // Split batch (SSE stream)\n router.post('/api/braindump/batches/:id/split', async (req: Request, res: Response) => {\n const batchId = req.params.id;\n const batch = braindumpOrchestrator!.getTracker().getBatch(batchId);\n if (!batch) {\n res.status(404).json({ error: 'Batch not found' });\n return;\n }\n\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n try {\n const result = await braindumpOrchestrator!.splitBatch(batchId, (event) => {\n try {\n res.write(`event: agent\\ndata: ${JSON.stringify(event)}\\n\\n`);\n } catch { /* client disconnected */ }\n });\n\n res.write(`event: done\\ndata: ${JSON.stringify({ batch: result })}\\n\\n`);\n } catch (err) {\n res.write(`event: error\\ndata: ${JSON.stringify({ error: (err as Error).message })}\\n\\n`);\n } finally {\n res.end();\n }\n });\n\n // Update task list (user adjustments)\n router.patch('/api/braindump/batches/:id/tasks', (req: Request, res: Response) => {\n try {\n const { tasks } = req.body as { tasks: BraindumpTask[] };\n braindumpOrchestrator!.getTracker().updateBatch(req.params.id, { tasks });\n const updated = braindumpOrchestrator!.getTracker().getBatch(req.params.id);\n res.json({ success: true, batch: updated });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // Confirm and execute\n router.post('/api/braindump/batches/:id/confirm', async (req: Request, res: Response) => {\n try {\n const batchId = req.params.id;\n braindumpOrchestrator!.confirmBatch(batchId);\n\n // Fire-and-forget execution\n braindumpOrchestrator!.executeBatch(batchId).catch((err) => {\n logger.error('Batch execution error', { batchId, error: (err as Error).message });\n });\n\n res.json({ success: true, message: 'Execution started' });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // Cancel batch\n router.post('/api/braindump/batches/:id/cancel', async (req: Request, res: Response) => {\n try {\n await braindumpOrchestrator!.cancelBatch(req.params.id);\n res.json({ success: true });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // Retry failed tasks\n router.post('/api/braindump/batches/:id/retry', async (req: Request, res: Response) => {\n try {\n braindumpOrchestrator!.retryFailed(req.params.id).catch((err) => {\n logger.error('Batch retry error', { batchId: req.params.id, error: (err as Error).message });\n });\n res.json({ success: true, message: 'Retry started' });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // SSE progress stream\n router.get('/api/braindump/batches/:id/stream', (req: Request, res: Response) => {\n const batchId = req.params.id;\n const batch = braindumpOrchestrator!.getTracker().getBatch(batchId);\n if (!batch) {\n res.status(404).json({ error: 'Batch not found' });\n return;\n }\n\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n // Send current state\n res.write(`event: state\\ndata: ${JSON.stringify(batch)}\\n\\n`);\n\n const BRAINDUMP_EVENTS: EventType[] = [\n 'braindump:task:started',\n 'braindump:task:completed',\n 'braindump:task:merging',\n 'braindump:task:merged',\n 'braindump:task:failed',\n 'braindump:completed',\n 'braindump:failed',\n ];\n\n const listener = (eventType: string | symbol, payload: unknown) => {\n const p = payload as { data?: { batchId?: string } };\n if (typeof eventType === 'string' && BRAINDUMP_EVENTS.includes(eventType as EventType)) {\n if (p?.data && (p.data as Record<string, unknown>).batchId === batchId) {\n try {\n res.write(`event: ${eventType}\\ndata: ${JSON.stringify(p)}\\n\\n`);\n } catch { /* client disconnected */ }\n }\n }\n };\n\n eventBus.on('*', listener);\n\n req.on('close', () => {\n eventBus.off('*', listener);\n });\n });\n\n // Delete batch\n router.delete('/api/braindump/batches/:id', (req: Request, res: Response) => {\n try {\n const deleted = braindumpOrchestrator!.getTracker().deleteBatch(req.params.id);\n res.json({ success: true, deleted });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { readdir } from 'node:fs/promises';\nimport { logger as rootLogger } from '../../logger.js';\nimport { resolveDataDir, ensureDir } from '../../paths.js';\nimport type { Config } from '../../config.js';\n\nconst logger = rootLogger.child('SyncRoutes');\n\nexport interface SyncRouterDeps {\n config: Config;\n}\n\n/**\n * Sync knowledge.json from DATA_DIR to project workDir.\n * Returns true if sync happened, false if source not found.\n */\nexport function syncKnowledgeToProject(workDir: string): boolean {\n const src = path.join(resolveDataDir(), 'knowledge', 'knowledge.json');\n if (!fs.existsSync(src)) return false;\n const dest = path.join(workDir, 'knowledge.json');\n fs.copyFileSync(src, dest);\n logger.info('Synced knowledge.json to project', { src, dest });\n return true;\n}\n\n/**\n * Sync distilled-*.mdc files from DATA_DIR/rules/ to project .cursor/rules/.\n * Returns number of files synced.\n */\nexport async function syncRulesToProject(workDir: string): Promise<number> {\n const srcDir = path.join(resolveDataDir(), 'rules');\n if (!fs.existsSync(srcDir)) return 0;\n\n const destDir = ensureDir(path.join(workDir, '.cursor', 'rules'));\n const files = await readdir(srcDir);\n const mdcFiles = files.filter(f => f.startsWith('distilled-') && f.endsWith('.mdc'));\n\n for (const file of mdcFiles) {\n fs.copyFileSync(path.join(srcDir, file), path.join(destDir, file));\n }\n\n logger.info('Synced rules to project', { count: mdcFiles.length, destDir });\n return mdcFiles.length;\n}\n\nexport function createSyncRouter(deps: SyncRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { config } = deps;\n\n // POST /api/sync/knowledge — sync knowledge.json to project\n router.post('/api/sync/knowledge', (_req: Request, res: Response) => {\n try {\n const synced = syncKnowledgeToProject(config.project.workDir);\n if (!synced) {\n res.status(404).json({ error: 'No knowledge.json found in DATA_DIR' });\n return;\n }\n res.json({ success: true, message: 'Knowledge synced to project' });\n } catch (err) {\n logger.error('Failed to sync knowledge', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/sync/rules — sync distilled rules to project\n router.post('/api/sync/rules', async (_req: Request, res: Response) => {\n try {\n const count = await syncRulesToProject(config.project.workDir);\n if (count === 0) {\n res.status(404).json({ error: 'No distilled rules found in DATA_DIR' });\n return;\n }\n res.json({ success: true, message: `Synced ${count} rule(s) to project` });\n } catch (err) {\n logger.error('Failed to sync rules', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/sync/all — sync both knowledge and rules\n router.post('/api/sync/all', async (_req: Request, res: Response) => {\n try {\n const knowledgeSynced = syncKnowledgeToProject(config.project.workDir);\n const rulesCount = await syncRulesToProject(config.project.workDir);\n res.json({\n success: true,\n knowledge: knowledgeSynced,\n rules: rulesCount,\n });\n } catch (err) {\n logger.error('Failed to sync all', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { logger as rootLogger } from '../../logger.js';\nimport type { OrphanBranchManager } from '../../storage/OrphanBranchManager.js';\nimport type { Config } from '../../config.js';\nimport { resolveDataDir } from '../../paths.js';\n\nconst logger = rootLogger.child('KnowledgeSyncRoutes');\n\nexport interface KnowledgeSyncRouterDeps {\n orphanManager?: OrphanBranchManager;\n config: Config;\n}\n\nexport function createKnowledgeSyncRouter(deps: KnowledgeSyncRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { orphanManager, config } = deps;\n\n // Gate middleware: always registered, checks component availability inside\n router.use('/api/knowledge-sync', (_req, res, next) => {\n if (!orphanManager) {\n res.status(503).json({ error: 'Knowledge sync is not initialized' });\n return;\n }\n next();\n });\n\n // POST /api/knowledge-sync/publish — publish global knowledge to orphan branch\n router.post('/api/knowledge-sync/publish', async (_req: Request, res: Response) => {\n try {\n const dataDir = resolveDataDir();\n const result = await orphanManager!.publish(dataDir);\n res.json({\n success: true,\n commitSha: result.commitSha,\n branch: config.knowledge.orphanBranch,\n });\n } catch (err) {\n logger.error('Failed to publish knowledge', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // POST /api/knowledge-sync/restore — restore knowledge from orphan branch\n router.post('/api/knowledge-sync/restore', async (_req: Request, res: Response) => {\n try {\n const dataDir = resolveDataDir();\n const result = await orphanManager!.restore(dataDir);\n res.json({\n success: true,\n entriesCount: result.entriesCount,\n branch: config.knowledge.orphanBranch,\n });\n } catch (err) {\n logger.error('Failed to restore knowledge', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // GET /api/knowledge-sync/status — sync status (branch exists? last sync time?)\n router.get('/api/knowledge-sync/status', async (_req: Request, res: Response) => {\n try {\n const [branchExists, metadata] = await Promise.all([\n orphanManager!.exists(),\n orphanManager!.getMetadata(),\n ]);\n\n res.json({\n branch: config.knowledge.orphanBranch,\n branchExists,\n lastSyncedAt: metadata?.lastSyncedAt ?? null,\n entriesCount: metadata?.entriesCount ?? 0,\n syncVectors: config.knowledge.syncVectors,\n });\n } catch (err) {\n logger.error('Failed to get knowledge sync status', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../../logger.js';\nimport type { Config } from '../../config.js';\nimport type { AIRunner } from '../../ai-runner/AIRunner.js';\nimport { SkillMetricsDiscovery } from '../../analytics/SkillMetricsDiscovery.js';\nimport { AnalyticsMetricsCollector } from '../../analytics/AnalyticsMetricsCollector.js';\nimport { AnalyticsAnalyzer } from '../../analytics/AnalyticsAnalyzer.js';\nimport type { KnowledgeStore } from '../../knowledge/KnowledgeStore.js';\nimport type { AnalyzeRequest, DiscoverMetricsRequest, FetchMetricsRequest } from '../../analytics/types/analytics.js';\n\nconst logger = rootLogger.child('AnalyticsRoutes');\n\nexport interface AnalyticsRouterDeps {\n aiRunner: AIRunner;\n knowledgeStore: KnowledgeStore;\n config: Config;\n}\n\n/**\n * Recursively collect SKILL.md files from a directory.\n */\nasync function collectSkillContent(dir: string): Promise<string> {\n const sections: string[] = [];\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n const sub = await collectSkillContent(fullPath);\n if (sub) sections.push(sub);\n } else if (entry.name === 'SKILL.md') {\n const content = await readFile(fullPath, 'utf-8');\n sections.push(`## ${path.basename(dir)}\\n\\n${content}`);\n }\n }\n } catch { /* skip inaccessible dirs */ }\n return sections.join('\\n\\n---\\n\\n');\n}\n\nexport function createAnalyticsRouter(deps: AnalyticsRouterDeps): ReturnType<typeof Router> {\n const router = Router();\n const { aiRunner, knowledgeStore, config } = deps;\n\n const discovery = new SkillMetricsDiscovery();\n const collector = new AnalyticsMetricsCollector();\n const analyzer = new AnalyticsAnalyzer(knowledgeStore);\n\n // Feature-gate middleware\n router.use('/api/analytics', (_req, res, next) => {\n if (!(config as Record<string, unknown>).analytics) {\n // Analytics config not present — feature disabled\n res.status(503).json({ error: 'Analytics feature is not configured' });\n return;\n }\n next();\n });\n\n // -----------------------------------------------------------------------\n // GET /api/analytics/discover-metrics\n // Analyze target project SKILL.md files and discover metric dimensions.\n // -----------------------------------------------------------------------\n router.get('/api/analytics/discover-metrics', async (req: Request, res: Response) => {\n try {\n const body = req.query as unknown as DiscoverMetricsRequest;\n\n // Gather SKILL.md content\n let skillContent = body.skillContent || '';\n if (!skillContent) {\n const agentsDir = path.join(config.project.workDir, '.agents');\n skillContent = await collectSkillContent(agentsDir);\n }\n\n if (!skillContent.trim()) {\n res.status(404).json({\n error: 'No SKILL.md files found in target project .agents/ directory',\n discoveredMetrics: [],\n });\n return;\n }\n\n const analyticsConfig = (config as unknown as Record<string, Record<string, unknown>>).analytics ?? {};\n const cacheTtl = (analyticsConfig.cacheTtlMs as number) ?? 300_000;\n\n const result = await discovery.analyzeTargetProjectSkill(\n skillContent,\n aiRunner,\n config,\n cacheTtl,\n );\n\n res.json({\n discoveredMetrics: result.discoveredMetrics,\n skillAnalysisResult: result,\n });\n } catch (err) {\n logger.error('Failed to discover metrics', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // -----------------------------------------------------------------------\n // POST /api/analytics/fetch-metrics\n // Fetch metric values from the target project's API endpoints.\n // -----------------------------------------------------------------------\n router.post('/api/analytics/fetch-metrics', async (req: Request, res: Response) => {\n try {\n const { metrics } = req.body as FetchMetricsRequest;\n if (!metrics?.length) {\n res.status(400).json({ error: 'metrics array is required' });\n return;\n }\n\n const analyticsConfig = (config as unknown as Record<string, Record<string, unknown>>).analytics ?? {};\n const apiUrl = (analyticsConfig.targetApiUrl as string) ?? '';\n const apiToken = (analyticsConfig.targetApiToken as string) ?? '';\n\n if (!apiUrl) {\n res.status(400).json({ error: 'ANALYTICS_TARGET_API_URL is not configured' });\n return;\n }\n\n const data = await collector.fetchMetrics(metrics, apiUrl, apiToken);\n const failed = collector.getFailedMetrics(data);\n\n res.json({\n data,\n timestamp: Date.now(),\n failed: failed.length > 0 ? failed : undefined,\n });\n } catch (err) {\n logger.error('Failed to fetch metrics', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n // -----------------------------------------------------------------------\n // POST /api/analytics/analyze (SSE streaming)\n // AI-driven analysis of operational metrics with knowledge distillation.\n // -----------------------------------------------------------------------\n router.post('/api/analytics/analyze', (req: Request, res: Response) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n let closed = false;\n\n function send(data: Record<string, unknown>) {\n if (closed) return;\n try { res.write('data: ' + JSON.stringify(data) + '\\n\\n'); } catch { /* client gone */ }\n }\n\n const { preference, discoveredMetrics, metricsData } = req.body as AnalyzeRequest;\n\n (async () => {\n try {\n if (!preference?.focus) {\n send({ step: 'error', error: 'preference.focus is required' });\n return;\n }\n\n send({ step: 'started', preference });\n\n const result = await analyzer.analyzeWithPreference(\n preference,\n discoveredMetrics ?? [],\n metricsData ?? {},\n aiRunner,\n config,\n (event) => {\n send({ step: 'stream', event });\n },\n );\n\n send({\n step: 'done',\n result: {\n markdown: result.markdown,\n structured: result.structured,\n },\n });\n } catch (err) {\n send({ step: 'error', error: (err as Error).message });\n } finally {\n if (!closed) res.end();\n }\n })();\n\n req.on('close', () => {\n closed = true;\n });\n });\n\n // -----------------------------------------------------------------------\n // POST /api/analytics/invalidate-cache\n // Force refresh of cached skill analysis and metrics data.\n // -----------------------------------------------------------------------\n router.post('/api/analytics/invalidate-cache', (_req: Request, res: Response) => {\n discovery.invalidateCache();\n collector.invalidateCache();\n res.json({ success: true, message: 'Cache invalidated' });\n });\n\n return router;\n}\n","/**\n * SkillMetricsDiscovery: Analyzes target project SKILL.md files to dynamically\n * discover operational metrics dimensions using AI.\n */\n\nimport { logger as rootLogger } from '../logger.js';\nimport type { AIRunner, RunOptions } from '../ai-runner/AIRunner.js';\nimport type { Config } from '../config-schema.js';\nimport type {\n DiscoveredMetric,\n SkillAnalysisResult,\n CachedSkillAnalysis,\n} from './types/analytics.js';\n\nconst logger = rootLogger.child('SkillMetricsDiscovery');\n\nexport class SkillMetricsDiscovery {\n private cache: CachedSkillAnalysis | null = null;\n\n /**\n * Analyze target project SKILL.md content and discover operational metrics.\n */\n async analyzeTargetProjectSkill(\n skillContent: string,\n aiRunner: AIRunner,\n config: Config,\n cacheTtlMs: number = 300_000,\n ): Promise<SkillAnalysisResult> {\n // Check cache\n if (this.cache && Date.now() - this.cache.timestamp < this.cache.ttl) {\n logger.debug('Returning cached skill analysis');\n return this.cache.result;\n }\n\n logger.info('Starting skill analysis for metrics discovery');\n\n const prompt = this.buildSkillAnalysisPrompt(skillContent);\n\n const runOptions: RunOptions = {\n prompt,\n workDir: config.project.workDir,\n timeoutMs: 60_000,\n };\n\n const runResult = await aiRunner.run(runOptions);\n\n if (!runResult.success) {\n logger.warn('AI skill analysis failed', { error: runResult.errorMessage });\n return {\n targetProjectSkill: skillContent,\n discoveredMetrics: [],\n analysisPrompt: prompt,\n aiInsight: runResult.errorMessage ?? 'AI analysis failed',\n timestamp: Date.now(),\n };\n }\n\n const metrics = this.parseMetricsFromAIOutput(runResult.output);\n\n const result: SkillAnalysisResult = {\n targetProjectSkill: skillContent,\n discoveredMetrics: metrics,\n analysisPrompt: prompt,\n aiInsight: runResult.output,\n timestamp: Date.now(),\n };\n\n // Cache result\n this.cache = { result, timestamp: Date.now(), ttl: cacheTtlMs };\n\n logger.info('Skill analysis completed', { metricsCount: metrics.length });\n return result;\n }\n\n /**\n * Invalidate the cached analysis result.\n */\n invalidateCache(): void {\n this.cache = null;\n }\n\n private buildSkillAnalysisPrompt(skillContent: string): string {\n return `你是一位资深的技术架构师和产品运营分析师。请分析以下目标项目的 SKILL.md 文档,发现其中蕴含的运营指标维度。\n\n【SKILL.md 内容】\n${skillContent.slice(0, 8000)}\n\n【分析任务】\n请识别该项目通常关心的以下方面的指标:\n1. 效率(efficiency)—— 完成速度、处理时间、吞吐量等\n2. 质量(quality)—— 代码质量评分、错误率、测试覆盖等\n3. 成本(cost)—— AI 调用成本、人力成本、资源占用等\n4. AI 表现(ai-performance)—— AI 完成度、重复率、干预频率等\n\n【输出格式】\n严格 JSON 格式,不要输出任何其他文本:\n{\n \"metrics\": [\n {\n \"name\": \"completion_rate\",\n \"label\": \"完成率\",\n \"description\": \"项目自动完成的 Issue 占总 Issue 的比例\",\n \"category\": \"efficiency\",\n \"unit\": \"percentage\",\n \"apiPath\": \"/api/metrics/completion-rate\"\n }\n ],\n \"summary\": \"简要分析该项目的运营关注点\"\n}\n\n【注意】\n- 尽可能从 SKILL.md 的功能描述推导指标\n- apiPath 需要符合 RESTful 风格\n- category 只能是: efficiency, quality, cost, ai-performance\n- unit 只能是: count, percentage, duration, score, ratio\n- 只输出 JSON,不输出其他文本`;\n }\n\n private parseMetricsFromAIOutput(aiOutput: string): DiscoveredMetric[] {\n try {\n // Try to extract JSON from the output (may be wrapped in markdown code blocks)\n let jsonStr = aiOutput;\n\n const codeBlockMatch = aiOutput.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n if (codeBlockMatch) {\n jsonStr = codeBlockMatch[1].trim();\n }\n\n const parsed = JSON.parse(jsonStr);\n if (!parsed.metrics || !Array.isArray(parsed.metrics)) {\n logger.warn('AI output has no metrics array');\n return [];\n }\n\n return parsed.metrics\n .filter((m: Record<string, unknown>) =>\n m.name && m.label && m.description && m.category && m.unit && m.apiPath,\n )\n .map((m: Record<string, unknown>) => ({\n name: String(m.name),\n label: String(m.label),\n description: String(m.description),\n category: String(m.category) as DiscoveredMetric['category'],\n unit: String(m.unit) as DiscoveredMetric['unit'],\n apiPath: String(m.apiPath),\n confidence: 0.85, // Default confidence from AI analysis\n }));\n } catch (err) {\n logger.warn('Failed to parse AI metrics output', { error: (err as Error).message });\n return [];\n }\n }\n}\n","/**\n * AnalyticsMetricsCollector: Fetches operational metric values from the target\n * project's API endpoints discovered by SkillMetricsDiscovery.\n */\n\nimport { logger as rootLogger } from '../logger.js';\nimport type { DiscoveredMetric, MetricValue, MetricsDataSnapshot } from './types/analytics.js';\n\nconst logger = rootLogger.child('AnalyticsMetricsCollector');\n\nexport class AnalyticsMetricsCollector {\n private cache: { data: MetricsDataSnapshot; timestamp: number } | null = null;\n\n /**\n * Fetch metric values for all discovered metrics in parallel.\n */\n async fetchMetrics(\n discoveredMetrics: DiscoveredMetric[],\n apiBaseUrl: string,\n apiToken: string,\n cacheTtlMs: number = 60_000,\n fetchTimeoutMs: number = 10_000,\n ): Promise<MetricsDataSnapshot> {\n // Check cache\n if (this.cache && Date.now() - this.cache.timestamp < cacheTtlMs) {\n logger.debug('Returning cached metrics data');\n return this.cache.data;\n }\n\n logger.info('Fetching metrics data', { count: discoveredMetrics.length });\n\n const results: MetricsDataSnapshot = {};\n\n // Fetch all metrics in parallel with individual error handling\n const promises = discoveredMetrics.map(async (metric) => {\n try {\n const url = `${apiBaseUrl.replace(/\\/$/, '')}${metric.apiPath}`;\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), fetchTimeoutMs);\n\n const response = await fetch(url, {\n headers: {\n Authorization: `Bearer ${apiToken}`,\n Accept: 'application/json',\n },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n results[metric.name] = {\n value: 0,\n unit: metric.unit,\n timestamp: Date.now(),\n error: `HTTP ${response.status}: ${response.statusText}`,\n };\n return;\n }\n\n const data = (await response.json()) as Record<string, unknown>;\n results[metric.name] = {\n value: (data.value ?? data) as string | number | boolean,\n unit: metric.unit,\n timestamp: Date.now(),\n fetchTime: data.timestamp as number | undefined,\n };\n } catch (err) {\n const errorMessage =\n err instanceof Error && err.name === 'AbortError'\n ? 'Request timeout'\n : (err as Error).message;\n\n results[metric.name] = {\n value: 0,\n unit: metric.unit,\n timestamp: Date.now(),\n error: errorMessage,\n };\n\n logger.debug('Failed to fetch metric', { metric: metric.name, error: errorMessage });\n }\n });\n\n await Promise.allSettled(promises);\n\n // Cache results\n this.cache = { data: results, timestamp: Date.now() };\n\n const successCount = Object.values(results).filter((v) => !v.error).length;\n logger.info('Metrics fetch completed', {\n total: discoveredMetrics.length,\n success: successCount,\n failed: discoveredMetrics.length - successCount,\n });\n\n return results;\n }\n\n /**\n * Invalidate the cached metrics data.\n */\n invalidateCache(): void {\n this.cache = null;\n }\n\n /**\n * Get the list of failed metric names from a snapshot.\n */\n getFailedMetrics(snapshot: MetricsDataSnapshot): string[] {\n return Object.entries(snapshot)\n .filter(([, v]) => v.error)\n .map(([k]) => k);\n }\n}\n","/**\n * Prompt templates for analytics AI analysis.\n */\n\nimport type { AnalysisPreference, DiscoveredMetric, MetricsDataSnapshot } from './types/analytics.js';\n\nconst FORMAT_GUIDE: Record<AnalysisPreference['format'], string> = {\n summary: '简要总结(200-300 字),突出关键结论和 1-2 条核心建议',\n detailed: '详细分析(800+ 字),包括数据解读、趋势分析、根因推断、3-5 条改进建议',\n executive: '高管视图,仅展示关键指标、状态红绿灯、最高优先级行动项',\n};\n\n/**\n * Build the analysis prompt with metrics data and user preferences.\n */\nexport function buildAnalysisPrompt(\n preference: AnalysisPreference,\n metrics: DiscoveredMetric[],\n data: MetricsDataSnapshot,\n): string {\n const metricsMarkdown = metrics\n .map((m) => {\n const val = data[m.name];\n const valueStr = val?.error ? `获取失败 (${val.error})` : `${val?.value ?? 'N/A'} ${m.unit}`;\n return `- **${m.label}** (${m.name}): ${valueStr}\\n ${m.description}`;\n })\n .join('\\n');\n\n const formatGuide = FORMAT_GUIDE[preference.format] ?? FORMAT_GUIDE.detailed;\n\n return `你是一位资深的 DevOps/产品运营分析师。请根据以下数据和用户偏好进行深度分析。\n\n【用户关注点】\n${preference.focus}\n\n【数据格式要求】\n${formatGuide}\n\n【时间范围】\n${preference.timeRange}\n\n${preference.comparePrevious ? '【对比要求】请对比上个周期的数据,说明趋势变化。\\n' : ''}${preference.highlightAnomalies ? '【异常检测】请突出任何异常或值得关注的数据点。\\n' : ''}\n【发现的关键指标】\n${metricsMarkdown}\n\n【分析要求】\n1. 总结当前运营现状\n2. 识别主要挑战和机遇\n3. 提供改进建议(每条建议包含行动、预期影响、工作量)\n4. 如有数据缺失,说明可能的原因和补充建议\n\n【输出格式】\n先用 Markdown 输出分析正文,然后在文末输出以下 JSON 结构(放在代码块中):\n\\`\\`\\`json\n{\n \"status\": \"当前状态一句话总结\",\n \"challenges\": [\"挑战1\", \"挑战2\"],\n \"opportunities\": [\"机遇1\", \"机遇2\"],\n \"recommendations\": [\n { \"action\": \"建议行动\", \"expectedImpact\": \"预期影响\", \"effort\": \"easy|medium|hard\" }\n ]\n}\n\\`\\`\\``;\n}\n","/**\n * AnalyticsAnalyzer: Performs AI-driven analysis of operational metrics,\n * then distills insights into the knowledge system (Diary → Memory → Rule).\n */\n\nimport { logger as rootLogger } from '../logger.js';\nimport type { AIRunner, StreamEvent } from '../ai-runner/AIRunner.js';\nimport type { Config } from '../config-schema.js';\nimport type { KnowledgeStore } from '../knowledge/KnowledgeStore.js';\nimport type {\n AnalysisPreference,\n AnalysisResult,\n AnalysisStructured,\n DiscoveredMetric,\n MetricsDataSnapshot,\n} from './types/analytics.js';\nimport { buildAnalysisPrompt } from './AnalyticsPrompts.js';\n\nconst logger = rootLogger.child('AnalyticsAnalyzer');\n\nexport class AnalyticsAnalyzer {\n constructor(\n private knowledgeStore: KnowledgeStore,\n ) {}\n\n /**\n * Analyze metrics based on user preference, stream output, and distill to knowledge.\n */\n async analyzeWithPreference(\n preference: AnalysisPreference,\n discoveredMetrics: DiscoveredMetric[],\n metricsData: MetricsDataSnapshot,\n aiRunner: AIRunner,\n config: Config,\n onStreamEvent?: (event: StreamEvent) => void,\n ): Promise<AnalysisResult> {\n logger.info('Starting analytics analysis', { focus: preference.focus, format: preference.format });\n\n // 1. Build prompt\n const prompt = buildAnalysisPrompt(preference, discoveredMetrics, metricsData);\n\n // 2. Call AIRunner with streaming support\n const runResult = await aiRunner.run({\n prompt,\n workDir: config.project.workDir,\n timeoutMs: 90_000,\n onStreamEvent,\n });\n\n if (!runResult.success) {\n logger.warn('Analytics analysis failed', { error: runResult.errorMessage });\n return {\n markdown: `## 分析失败\\n\\n${runResult.errorMessage ?? '未知错误'}`,\n };\n }\n\n // 3. Parse structured result from AI output\n const structured = this.parseStructuredResult(runResult.output);\n const result: AnalysisResult = {\n markdown: runResult.output,\n structured,\n };\n\n // 4. Distill to knowledge (fire-and-forget, don't block response)\n this.distillToKnowledge(result, discoveredMetrics, metricsData, preference).catch((err) => {\n logger.warn('Failed to distill analytics to knowledge', { error: (err as Error).message });\n });\n\n logger.info('Analytics analysis completed', {\n hasStructured: !!structured,\n recommendationCount: structured?.recommendations.length ?? 0,\n });\n\n return result;\n }\n\n /**\n * Extract the structured JSON block from the AI's markdown output.\n */\n private parseStructuredResult(markdown: string): AnalysisStructured | undefined {\n try {\n const match = markdown.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n if (!match) return undefined;\n\n const parsed = JSON.parse(match[1].trim());\n if (!parsed.status || !Array.isArray(parsed.challenges)) return undefined;\n\n return {\n status: String(parsed.status),\n challenges: (parsed.challenges ?? []).map(String),\n opportunities: (parsed.opportunities ?? []).map(String),\n recommendations: (parsed.recommendations ?? []).map((r: Record<string, string>) => ({\n action: String(r.action ?? ''),\n expectedImpact: String(r.expectedImpact ?? ''),\n effort: (['easy', 'medium', 'hard'].includes(r.effort) ? r.effort : 'medium') as 'easy' | 'medium' | 'hard',\n })),\n };\n } catch {\n logger.debug('Could not parse structured result from AI output');\n return undefined;\n }\n }\n\n /**\n * Create a Diary entry in KnowledgeStore for the analysis, enabling\n * the distillation pipeline (Diary → Memory → AgentRule) to process it.\n */\n private async distillToKnowledge(\n analysis: AnalysisResult,\n metrics: DiscoveredMetric[],\n data: MetricsDataSnapshot,\n preference: AnalysisPreference,\n ): Promise<void> {\n const diaryContent = JSON.stringify({\n type: 'analytics-analysis',\n timestamp: Date.now(),\n source: 'analytics-panel',\n content: {\n metricsSnapshot: data,\n discoveredMetricsCount: metrics.length,\n analysisResult: analysis.structured,\n recommendations: analysis.structured?.recommendations ?? [],\n focusArea: preference.focus,\n timeRange: preference.timeRange,\n },\n tags: ['analytics', 'operational-insights'],\n }, null, 2);\n\n const dateStr = new Date().toLocaleDateString('zh-CN');\n\n this.knowledgeStore.create({\n type: 'diary',\n title: `运营分析 - ${dateStr} - ${preference.focus.slice(0, 30)}`,\n content: diaryContent,\n tags: ['analytics', 'operational-insights', preference.timeRange],\n });\n\n logger.info('Analytics diary entry created for distillation');\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { readdir, readFile } from 'node:fs/promises';\nimport { logger as rootLogger } from '../logger.js';\nimport type { AIRunner } from '../ai-runner/index.js';\nimport type {\n DomainModel,\n DomainElement,\n DomainRelationship,\n BoundedContext,\n} from './DomainModel.js';\nimport { collectStaticInfo } from './KnowledgeAnalyzer.js';\nimport { buildDomainAnalysisPrompt, buildDomainRefinePrompt } from './domain-model-prompt.js';\nimport type { KnowledgeStore } from './KnowledgeStore.js';\n\nconst logger = rootLogger.child('DomainModelAnalyzer');\n\nexport interface DomainAnalyzeOptions {\n workDir: string;\n aiRunner: AIRunner;\n timeoutMs?: number;\n refineRounds?: number;\n onProgress?: (event: DomainAnalysisEvent) => void;\n}\n\nexport interface DomainAnalysisEvent {\n type: 'progress' | 'partial-model' | 'refine-round' | 'complete' | 'error' | 'agent-log';\n data: unknown;\n}\n\n// ── Helpers ──\n\nconst IGNORED_DIRS = new Set([\n 'node_modules', 'dist', '.git', 'coverage', '.next', '.nuxt',\n 'build', 'out', '__pycache__', '.cache', '.turbo',\n]);\n\nconst CODE_EXTENSIONS = new Set(['.ts', '.js', '.tsx', '.jsx', '.mts', '.mjs']);\n\nconst DECLARATION_RE = /^(?:export\\s+)?(?:abstract\\s+)?(?:class|interface|type|enum)\\s+\\w+/;\nconst IMPORT_RE = /^import\\s/;\n\n/**\n * Collect code structure information: class/interface/type/enum declarations\n * with surrounding imports, suitable for domain analysis.\n */\nexport async function collectCodeStructure(workDir: string): Promise<string> {\n const srcDir = path.join(workDir, 'src');\n const rootToScan = fs.existsSync(srcDir) ? srcDir : workDir;\n\n const fileEntries = await scanCodeFiles(rootToScan, workDir);\n\n // Limit: skip test/spec files\n const relevantFiles = fileEntries.filter(\n (f) => !f.relativePath.includes('.test.') && !f.relativePath.includes('.spec.'),\n );\n\n if (relevantFiles.length === 0) {\n return '(未找到源代码文件)';\n }\n\n const sections: string[] = [];\n let totalSize = 0;\n const MAX_TOTAL_SIZE = 60_000;\n\n for (const file of relevantFiles) {\n if (totalSize >= MAX_TOTAL_SIZE) break;\n\n try {\n const content = await readFile(file.absolutePath, 'utf-8');\n const lines = content.split('\\n');\n const extracted = extractDeclarations(lines);\n\n if (extracted.length === 0) continue;\n\n const snippet = extracted.join('\\n');\n if (totalSize + snippet.length > MAX_TOTAL_SIZE) continue;\n\n sections.push(`### ${file.relativePath}`);\n sections.push('```typescript');\n sections.push(snippet);\n sections.push('```');\n totalSize += snippet.length;\n } catch { /* skip unreadable */ }\n }\n\n return sections.join('\\n\\n');\n}\n\ninterface CodeFile {\n relativePath: string;\n absolutePath: string;\n}\n\nasync function scanCodeFiles(\n dir: string,\n rootDir: string,\n result: CodeFile[] = [],\n): Promise<CodeFile[]> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (IGNORED_DIRS.has(entry.name)) continue;\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await scanCodeFiles(full, rootDir, result);\n } else if (CODE_EXTENSIONS.has(path.extname(entry.name))) {\n result.push({\n relativePath: path.relative(rootDir, full),\n absolutePath: full,\n });\n }\n }\n } catch { /* skip */ }\n return result;\n}\n\n/**\n * Extract import lines + declaration lines (first ~60 lines) from a file.\n */\nfunction extractDeclarations(lines: string[]): string[] {\n const result: string[] = [];\n const maxLines = Math.min(lines.length, 60);\n\n for (let i = 0; i < maxLines; i++) {\n const trimmed = lines[i].trimStart();\n if (IMPORT_RE.test(trimmed) || DECLARATION_RE.test(trimmed)) {\n result.push(lines[i]);\n }\n }\n\n // Also scan the rest of the file for declarations (just the declaration line)\n for (let i = maxLines; i < lines.length; i++) {\n const trimmed = lines[i].trimStart();\n if (DECLARATION_RE.test(trimmed)) {\n result.push(lines[i]);\n }\n }\n\n return result;\n}\n\nfunction parseJsonFromOutput(output: string): Record<string, unknown> | null {\n const jsonBlockMatch = output.match(/```json\\s*\\n([\\s\\S]*?)```/);\n if (jsonBlockMatch) {\n try {\n return JSON.parse(jsonBlockMatch[1].trim());\n } catch { /* fall through */ }\n }\n try {\n return JSON.parse(output.trim());\n } catch { /* fall through */ }\n return null;\n}\n\nlet idCounter = 0;\n\nfunction nextId(prefix: string): string {\n return `${prefix}-${Date.now().toString(36)}-${(++idCounter).toString(36)}`;\n}\n\nfunction ensureIds(parsed: Record<string, unknown>): void {\n const contexts = (parsed.boundedContexts ?? []) as BoundedContext[];\n for (const ctx of contexts) {\n if (!ctx.id) ctx.id = nextId('ctx');\n }\n\n const elements = (parsed.elements ?? []) as DomainElement[];\n for (const el of elements) {\n if (!el.id) el.id = nextId('el');\n if (!el.properties) el.properties = [];\n if (!el.methods) el.methods = [];\n if (!el.sourceFiles) el.sourceFiles = [];\n }\n\n const relationships = (parsed.relationships ?? []) as DomainRelationship[];\n for (const rel of relationships) {\n if (!rel.id) rel.id = nextId('rel');\n }\n}\n\n// ── DomainModelAnalyzer class ──\n\nexport class DomainModelAnalyzer {\n private currentModel: DomainModel | null = null;\n\n getCurrentModel(): DomainModel | null {\n return this.currentModel;\n }\n\n setCurrentModel(model: DomainModel | null): void {\n this.currentModel = model;\n }\n\n /**\n * Run domain model analysis (single-shot or multi-round refinement).\n */\n async analyze(options: DomainAnalyzeOptions): Promise<DomainModel> {\n const {\n workDir,\n aiRunner,\n timeoutMs = 600_000,\n refineRounds = 0,\n onProgress,\n } = options;\n\n const emit = (event: DomainAnalysisEvent) => onProgress?.(event);\n\n // Step 1: Collect info\n emit({ type: 'progress', data: { step: 'collecting', message: '收集项目信息和代码结构...' } });\n const [staticInfo, codeStructure] = await Promise.all([\n collectStaticInfo(workDir),\n collectCodeStructure(workDir),\n ]);\n\n // Step 2: Initial analysis\n emit({ type: 'progress', data: { step: 'analyzing', message: 'AI 分析领域模型...' } });\n const prompt = buildDomainAnalysisPrompt(staticInfo, codeStructure);\n const result = await aiRunner.run({\n prompt,\n workDir,\n timeoutMs,\n onStreamEvent: (streamEvent) => {\n emit({ type: 'agent-log', data: streamEvent });\n },\n });\n\n if (!result.success) {\n const errMsg = `AI analysis failed: ${result.output.slice(0, 500)}`;\n emit({ type: 'error', data: { error: errMsg } });\n throw new Error(errMsg);\n }\n\n const parsed = parseJsonFromOutput(result.output);\n if (!parsed) {\n const errMsg = 'Failed to parse AI output as JSON';\n emit({ type: 'error', data: { error: errMsg } });\n throw new Error(errMsg);\n }\n\n ensureIds(parsed);\n\n const now = new Date().toISOString();\n let model: DomainModel = {\n version: 1,\n projectPath: workDir,\n analyzedAt: now,\n updatedAt: now,\n boundedContexts: (parsed.boundedContexts as BoundedContext[]) || [],\n elements: (parsed.elements as DomainElement[]) || [],\n relationships: (parsed.relationships as DomainRelationship[]) || [],\n };\n\n emit({ type: 'partial-model', data: model });\n\n // Step 3: Optional refinement rounds\n for (let round = 1; round <= refineRounds; round++) {\n emit({\n type: 'refine-round',\n data: { round, total: refineRounds, message: `AI 精炼分析(第 ${round}/${refineRounds} 轮)...` },\n });\n\n const autoFeedback = [\n '请审查当前领域模型并改进:',\n '1. 是否有遗漏的核心领域元素?',\n '2. 元素类型分类是否准确?',\n '3. 关系是否完整且正确?',\n '4. 限界上下文的划分是否合理?',\n '5. 属性和方法是否充分体现业务含义?',\n ].join('\\n');\n\n const refinePrompt = buildDomainRefinePrompt(JSON.stringify(model, null, 2), autoFeedback);\n const refineResult = await aiRunner.run({\n prompt: refinePrompt,\n workDir,\n timeoutMs,\n onStreamEvent: (streamEvent) => {\n emit({ type: 'agent-log', data: streamEvent });\n },\n });\n\n if (refineResult.success) {\n const refinedParsed = parseJsonFromOutput(refineResult.output);\n if (refinedParsed) {\n ensureIds(refinedParsed);\n model = {\n ...model,\n updatedAt: new Date().toISOString(),\n boundedContexts: (refinedParsed.boundedContexts as BoundedContext[]) || model.boundedContexts,\n elements: (refinedParsed.elements as DomainElement[]) || model.elements,\n relationships: (refinedParsed.relationships as DomainRelationship[]) || model.relationships,\n };\n emit({ type: 'partial-model', data: model });\n }\n }\n }\n\n this.currentModel = model;\n emit({ type: 'complete', data: model });\n logger.info('Domain model analysis complete', {\n contexts: model.boundedContexts.length,\n elements: model.elements.length,\n relationships: model.relationships.length,\n });\n\n return model;\n }\n\n /**\n * Persist the current domain model into KnowledgeStore.\n */\n confirmToStore(store: KnowledgeStore): void {\n const model = this.currentModel;\n if (!model) throw new Error('No domain model to confirm');\n\n const content = JSON.stringify(model, null, 2);\n const title = `领域模型 — ${path.basename(model.projectPath)}`;\n\n // Check for existing domain-model entry\n const existing = store.list('domain-model');\n if (existing.length > 0) {\n store.update(existing[0].id, { title, content, tags: ['domain-model', 'auto-generated'] });\n } else {\n store.create({\n type: 'domain-model',\n title,\n content,\n tags: ['domain-model', 'auto-generated'],\n });\n }\n\n logger.info('Domain model confirmed to knowledge store');\n }\n\n /**\n * Load a previously stored domain model from KnowledgeStore.\n */\n loadFromStore(store: KnowledgeStore): DomainModel | null {\n const entries = store.list('domain-model');\n if (entries.length === 0) return null;\n\n const full = store.get(entries[0].id);\n if (!full) return null;\n\n try {\n const model = JSON.parse(full.content) as DomainModel;\n this.currentModel = model;\n return model;\n } catch {\n logger.warn('Failed to parse stored domain model');\n return null;\n }\n }\n}\n","/**\n * Prompts for AI-driven domain model analysis.\n */\n\n/**\n * Build the primary analysis prompt that identifies bounded contexts,\n * domain elements and their relationships from the project's code structure.\n */\nexport function buildDomainAnalysisPrompt(\n staticInfo: string,\n codeStructure: string,\n existingKnowledge?: string,\n): string {\n const knowledgeSection = existingKnowledge\n ? `\\n## 已有项目知识\\n${existingKnowledge}\\n`\n : '';\n\n return `你是一个领域驱动设计(DDD)专家。请分析以下项目信息和代码结构,识别其中的领域模型。\n\n## 项目基础信息\n${staticInfo}\n${knowledgeSection}\n## 代码结构(类/接口/类型声明摘要)\n${codeStructure}\n\n## 分析要求\n\n请按照 DDD 战术设计模式分析项目代码,识别以下内容:\n\n### 1. 限界上下文(Bounded Contexts)\n- 识别项目中的业务边界划分\n- 每个上下文应有清晰的职责范围\n\n### 2. 领域元素\n按以下类型分类:\n- **aggregate-root**: 聚合根 — 作为聚合的入口点,管理内部一致性\n- **entity**: 实体 — 有唯一标识的业务对象\n- **value-object**: 值对象 — 无唯一标识,通过属性值判等\n- **domain-service**: 领域服务 — 不属于任何实体的业务逻辑\n- **domain-event**: 领域事件 — 记录业务中发生的事情\n- **repository**: 仓储 — 持久化和查询聚合\n- **factory**: 工厂 — 创建复杂对象\n\n### 3. 关系\n识别元素之间的关系:\n- **composition**: 组合(强生命周期依赖)\n- **aggregation**: 聚合(弱生命周期依赖)\n- **association**: 关联(一般引用)\n- **inheritance**: 继承\n- **implementation**: 实现(接口实现)\n- **dependency**: 依赖\n- **event-publish**: 事件发布\n- **event-subscribe**: 事件订阅\n\n### 注意事项\n- **聚焦业务核心**:忽略纯工具类(logger、utils、config loader 等),关注业务逻辑和核心流程\n- **中文命名**:displayName 使用中文\n- **来源追溯**:每个元素必须标注源文件路径\n- **属性和方法**:列出关键的属性和方法(不需要全部,选择最能体现业务含义的)\n\n## 输出格式\n\n请严格输出以下 JSON 格式(不要添加任何额外文字或注释):\n\n\\`\\`\\`json\n{\n \"boundedContexts\": [\n {\n \"id\": \"ctx-xxx\",\n \"name\": \"ContextName\",\n \"displayName\": \"中文名\",\n \"description\": \"描述\",\n \"color\": \"#hex\"\n }\n ],\n \"elements\": [\n {\n \"id\": \"el-xxx\",\n \"type\": \"entity\",\n \"name\": \"ClassName\",\n \"displayName\": \"中文名\",\n \"description\": \"描述\",\n \"properties\": [\n { \"name\": \"propName\", \"type\": \"string\", \"description\": \"描述\" }\n ],\n \"methods\": [\n { \"name\": \"methodName\", \"description\": \"描述\", \"isCommand\": true }\n ],\n \"sourceFiles\": [\"src/path/to/file.ts\"],\n \"boundedContextId\": \"ctx-xxx\"\n }\n ],\n \"relationships\": [\n {\n \"id\": \"rel-xxx\",\n \"type\": \"association\",\n \"sourceId\": \"el-xxx\",\n \"targetId\": \"el-yyy\",\n \"label\": \"关系说明\",\n \"description\": \"详细描述\"\n }\n ]\n}\n\\`\\`\\``;\n}\n\n/**\n * Build a refinement prompt to let the AI improve an existing domain model\n * based on review feedback.\n */\nexport function buildDomainRefinePrompt(\n currentModelJson: string,\n feedback: string,\n): string {\n return `你是一个领域驱动设计(DDD)专家。请根据审核反馈改进以下领域模型。\n\n## 当前领域模型\n\\`\\`\\`json\n${currentModelJson}\n\\`\\`\\`\n\n## 审核反馈\n${feedback}\n\n## 要求\n1. 保留正确的部分不变\n2. 根据反馈修正错误的分类或关系\n3. 补充缺失的元素或关系\n4. 移除不合理的内容\n5. 确保所有 id 保持稳定(已有元素的 id 不变,新增元素用新 id)\n\n请直接输出改进后的完整 JSON(格式与输入相同):\n\n\\`\\`\\`json\n{\n \"boundedContexts\": [...],\n \"elements\": [...],\n \"relationships\": [...]\n}\n\\`\\`\\``;\n}\n","import path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\nimport type { AIRunner } from '../ai-runner/index.js';\nimport type {\n SystemUseCaseModel,\n SystemUseCase,\n UseCaseRelationship,\n} from './SystemUseCase.js';\nimport type { DomainModel } from './DomainModel.js';\nimport { collectStaticInfo } from './KnowledgeAnalyzer.js';\nimport { collectCodeStructure } from './DomainModelAnalyzer.js';\nimport {\n buildUseCaseAnalysisPrompt,\n buildUseCaseRefinePrompt,\n buildDomainAssociationPrompt,\n} from './usecase-prompt.js';\nimport type { KnowledgeStore } from './KnowledgeStore.js';\n\nconst logger = rootLogger.child('SystemUseCaseAnalyzer');\n\nexport interface UseCaseAnalyzeOptions {\n workDir: string;\n aiRunner: AIRunner;\n timeoutMs?: number;\n refineRounds?: number;\n onProgress?: (event: UseCaseAnalysisEvent) => void;\n}\n\nexport interface UseCaseAnalysisEvent {\n type: 'progress' | 'partial-model' | 'refine-round' | 'complete' | 'error' | 'agent-log';\n data: unknown;\n}\n\n// ── Helpers ──\n\nfunction parseJsonFromOutput(output: string): Record<string, unknown> | null {\n const jsonBlockMatch = output.match(/```json\\s*\\n([\\s\\S]*?)```/);\n if (jsonBlockMatch) {\n try {\n return JSON.parse(jsonBlockMatch[1].trim());\n } catch { /* fall through */ }\n }\n try {\n return JSON.parse(output.trim());\n } catch { /* fall through */ }\n return null;\n}\n\nlet idCounter = 0;\n\nfunction nextId(prefix: string): string {\n return `${prefix}-${Date.now().toString(36)}-${(++idCounter).toString(36)}`;\n}\n\nfunction ensureIds(parsed: Record<string, unknown>): void {\n const useCases = (parsed.useCases ?? []) as SystemUseCase[];\n for (const uc of useCases) {\n if (!uc.id) uc.id = nextId('uc');\n }\n\n const relationships = (parsed.relationships ?? []) as UseCaseRelationship[];\n for (const rel of relationships) {\n if (!rel.id) rel.id = nextId('ucrel');\n }\n}\n\n// ── SystemUseCaseAnalyzer class ──\n\nexport class SystemUseCaseAnalyzer {\n private currentModel: SystemUseCaseModel | null = null;\n\n getCurrentModel(): SystemUseCaseModel | null {\n return this.currentModel;\n }\n\n setCurrentModel(model: SystemUseCaseModel | null): void {\n this.currentModel = model;\n }\n\n /**\n * Run use case analysis (single-shot or multi-round refinement).\n */\n async analyze(options: UseCaseAnalyzeOptions): Promise<SystemUseCaseModel> {\n const {\n workDir,\n aiRunner,\n timeoutMs = 600_000,\n refineRounds = 0,\n onProgress,\n } = options;\n\n const emit = (event: UseCaseAnalysisEvent) => onProgress?.(event);\n\n // Step 1: Collect info\n emit({ type: 'progress', data: { step: 'collecting', message: '收集项目信息和代码结构...' } });\n const [staticInfo, codeStructure] = await Promise.all([\n collectStaticInfo(workDir),\n collectCodeStructure(workDir),\n ]);\n\n // Step 2: Initial analysis\n emit({ type: 'progress', data: { step: 'analyzing', message: 'AI 分析系统用例...' } });\n const prompt = buildUseCaseAnalysisPrompt(staticInfo, codeStructure);\n const result = await aiRunner.run({\n prompt,\n workDir,\n timeoutMs,\n onStreamEvent: (streamEvent) => {\n emit({ type: 'agent-log', data: streamEvent });\n },\n });\n\n if (!result.success) {\n const errMsg = `AI analysis failed: ${result.output.slice(0, 500)}`;\n emit({ type: 'error', data: { error: errMsg } });\n throw new Error(errMsg);\n }\n\n const parsed = parseJsonFromOutput(result.output);\n if (!parsed) {\n const errMsg = 'Failed to parse AI output as JSON';\n emit({ type: 'error', data: { error: errMsg } });\n throw new Error(errMsg);\n }\n\n ensureIds(parsed);\n\n const now = new Date().toISOString();\n let model: SystemUseCaseModel = {\n version: 1,\n projectPath: workDir,\n analyzedAt: now,\n updatedAt: now,\n actors: (parsed.actors as string[]) || [],\n useCases: (parsed.useCases as SystemUseCase[]) || [],\n relationships: (parsed.relationships as UseCaseRelationship[]) || [],\n };\n\n emit({ type: 'partial-model', data: model });\n\n // Step 3: Optional refinement rounds\n for (let round = 1; round <= refineRounds; round++) {\n emit({\n type: 'refine-round',\n data: { round, total: refineRounds, message: `AI 精炼分析(第 ${round}/${refineRounds} 轮)...` },\n });\n\n const autoFeedback = [\n '请审查当前用例模型并改进:',\n '1. 用例命名是否符合「主执行者-动作+对象」格式?',\n '2. 是否有遗漏的核心用例或场景?',\n '3. 主路径步骤类型是否正确?',\n '4. 扩展步骤是否完整覆盖异常和分支?',\n '5. 补充约束是否充分(字段列表、业务规则、质量、设计)?',\n ].join('\\n');\n\n const refinePrompt = buildUseCaseRefinePrompt(JSON.stringify(model, null, 2), autoFeedback);\n const refineResult = await aiRunner.run({\n prompt: refinePrompt,\n workDir,\n timeoutMs,\n onStreamEvent: (streamEvent) => {\n emit({ type: 'agent-log', data: streamEvent });\n },\n });\n\n if (refineResult.success) {\n const refinedParsed = parseJsonFromOutput(refineResult.output);\n if (refinedParsed) {\n ensureIds(refinedParsed);\n model = {\n ...model,\n updatedAt: new Date().toISOString(),\n useCases: (refinedParsed.useCases as SystemUseCase[]) || model.useCases,\n relationships: (refinedParsed.relationships as UseCaseRelationship[]) || model.relationships,\n };\n emit({ type: 'partial-model', data: model });\n }\n }\n }\n\n this.currentModel = model;\n emit({ type: 'complete', data: model });\n logger.info('Use case analysis complete', {\n useCases: model.useCases.length,\n relationships: model.relationships.length,\n });\n\n return model;\n }\n\n /**\n * Suggest associations between use cases and domain model elements via AI.\n */\n async suggestDomainAssociations(\n useCaseModel: SystemUseCaseModel,\n domainModel: DomainModel,\n aiRunner: AIRunner,\n workDir: string,\n ): Promise<Map<string, string[]>> {\n const prompt = buildDomainAssociationPrompt(\n JSON.stringify(useCaseModel, null, 2),\n JSON.stringify(domainModel, null, 2),\n );\n\n const result = await aiRunner.run({\n prompt,\n workDir,\n timeoutMs: 300_000,\n });\n\n const associations = new Map<string, string[]>();\n\n if (!result.success) {\n logger.warn('AI domain association failed', { output: result.output.slice(0, 200) });\n return associations;\n }\n\n const parsed = parseJsonFromOutput(result.output);\n if (!parsed || !parsed.associations) {\n logger.warn('Failed to parse domain association output');\n return associations;\n }\n\n const rawAssociations = parsed.associations as Record<string, string[]>;\n for (const [ucId, elementIds] of Object.entries(rawAssociations)) {\n if (Array.isArray(elementIds)) {\n associations.set(ucId, elementIds);\n }\n }\n\n return associations;\n }\n\n /**\n * Persist the current use case model into KnowledgeStore.\n */\n confirmToStore(store: KnowledgeStore): void {\n const model = this.currentModel;\n if (!model) throw new Error('No use case model to confirm');\n\n const content = JSON.stringify(model, null, 2);\n const title = `系统用例 — ${path.basename(model.projectPath)}`;\n\n const existing = store.list('system-usecase');\n if (existing.length > 0) {\n store.update(existing[0].id, { title, content, tags: ['system-usecase', 'auto-generated'] });\n } else {\n store.create({\n type: 'system-usecase',\n title,\n content,\n tags: ['system-usecase', 'auto-generated'],\n });\n }\n\n logger.info('Use case model confirmed to knowledge store');\n }\n\n /**\n * Load a previously stored use case model from KnowledgeStore.\n */\n loadFromStore(store: KnowledgeStore): SystemUseCaseModel | null {\n const entries = store.list('system-usecase');\n if (entries.length === 0) return null;\n\n const full = store.get(entries[0].id);\n if (!full) return null;\n\n try {\n const model = JSON.parse(full.content) as SystemUseCaseModel;\n this.currentModel = model;\n return model;\n } catch {\n logger.warn('Failed to parse stored use case model');\n return null;\n }\n }\n}\n","/**\n * Prompts for AI-driven use case analysis following the code2usecase specification.\n */\n\n/**\n * Build the primary analysis prompt that identifies system use cases\n * from the project's code structure, following XUC platform conventions.\n */\nexport function buildUseCaseAnalysisPrompt(\n staticInfo: string,\n codeStructure: string,\n existingDomainModel?: string,\n): string {\n const domainModelSection = existingDomainModel\n ? `\\n## 已有领域模型\\n请参考以下领域模型,将用例与领域元素关联:\\n\\`\\`\\`json\\n${existingDomainModel}\\n\\`\\`\\`\\n`\n : '';\n\n return `你是一个系统用例分析专家,熟悉微信支付规范和 XUC(系统用例规约管理平台)的撰写标准。请分析以下项目信息和代码结构,识别其中的系统用例。\n\n## 项目基础信息\n${staticInfo}\n${domainModelSection}\n## 代码结构(类/接口/类型声明摘要)\n${codeStructure}\n\n## 分析要求\n\n请按照微信支付系统用例规范分析项目代码,识别系统用例。\n\n### 1. 用例命名规范\n\n用例名格式:**\\`主执行者-动作+对象\\`**\n\n动词选择规则:\n- 投诉/申请/提交 → 用**受理**,不用\"提交、发起\"\n- 查看信息 → 用**展示**,不用\"获取\"\n- 指定某对象 → 用**指定**,不用\"该\"\n- 系统间通知 → 用**接收**,不用\"处理\"\n- 定时同步结果 → 用**接收xx结果**,不用\"同步xx结果\"\n- 审核/审批 → 用**记录xx审批结果**,不用\"审批xx\"\n- 定时任务 → 主执行者为「时间」,用**时间-生成/发送xx**\n\n### 2. 步骤类型\n\n主路径由多个回合组成,每个回合包含以下 6 种步骤类型:\n\n| 类型标识 | 说明 |\n|---------|------|\n| request | 执行者向系统发出请求 |\n| validate | 系统对请求进行验证 |\n| change | 系统执行状态变更 |\n| feedback | 系统向执行者返回结果 |\n| request-auxiliary | 系统向辅助执行者发出请求 |\n| validate-auxiliary | 系统验证辅助执行者的响应 |\n\n### 3. 场景划分原则\n\n- **按执行者预期划分**:不同执行者对同一流程有不同预期时,拆分为独立用例\n- **申请与审批分离**:申请/受理与审批是不同执行者的独立行为,必须拆分\n- **定时任务独立**:定时触发的场景,主执行者为「时间」\n- **发送凭证 vs 展示凭证**:发送凭证在步骤中用规则约束,展示凭证内容单独用例\n- **对账场景**:业务逻辑对账有用例,系统内一致性对账无用例\n\n### 4. 补充约束四类型\n\n每个步骤可关联补充约束:\n\n| 类型标识 | 说明 |\n|---------|------|\n| field-list | 步骤涉及的数据字段(支持嵌套) |\n| business-rule | 业务判断逻辑(检查点+结果值) |\n| quality | 安全性、易用性、可维护性、性能要求 |\n| design | 技术实现层面的约束条件 |\n\n### 注意事项\n- 聚焦业务核心,忽略纯工具类\n- 中文命名:displayName 和步骤描述使用中文\n- 来源追溯:每个用例标注相关源文件路径\n- 识别主执行者和辅助执行者\n\n## 输出格式\n\n请严格输出以下 JSON 格式(不要添加任何额外文字或注释):\n\n\\`\\`\\`json\n{\n \"useCases\": [\n {\n \"id\": \"uc-xxx\",\n \"name\": \"主执行者-动作+对象\",\n \"displayName\": \"中文用例名\",\n \"description\": \"用例描述\",\n \"importance\": \"high|medium|low\",\n \"primaryActor\": {\n \"name\": \"主执行者名称\",\n \"type\": \"person|system|time\"\n },\n \"auxiliaryActors\": [\n { \"name\": \"辅助执行者名称\", \"type\": \"person|system\" }\n ],\n \"preconditions\": [\"前置条件\"],\n \"postconditions\": [\"后置条件\"],\n \"stakeholderInterests\": [\n { \"stakeholder\": \"涉众\", \"interest\": \"利益诉求\" }\n ],\n \"mainPath\": {\n \"rounds\": [\n {\n \"roundNumber\": 1,\n \"steps\": [\n {\n \"stepNumber\": 1,\n \"type\": \"request|validate|change|feedback|request-auxiliary|validate-auxiliary\",\n \"description\": \"步骤描述\",\n \"constraints\": [\n {\n \"type\": \"field-list|business-rule|quality|design\",\n \"description\": \"约束描述\"\n }\n ]\n }\n ]\n }\n ]\n },\n \"extensions\": [\n {\n \"stepRef\": \"1a\",\n \"condition\": \"触发条件\",\n \"steps\": [\n {\n \"stepNumber\": 1,\n \"type\": \"validate\",\n \"description\": \"扩展步骤描述\"\n }\n ]\n }\n ],\n \"sourceFiles\": [\"src/path/to/file.ts\"],\n \"boundedContextId\": \"ctx-xxx\"\n }\n ],\n \"actors\": [\n {\n \"id\": \"actor-xxx\",\n \"name\": \"执行者名称\",\n \"type\": \"person|system|time\",\n \"description\": \"执行者描述\"\n }\n ]\n}\n\\`\\`\\``;\n}\n\n/**\n * Build a refinement prompt to let the AI improve an existing use case model\n * based on review feedback.\n */\nexport function buildUseCaseRefinePrompt(\n currentModelJson: string,\n feedback: string,\n): string {\n return `你是一个系统用例分析专家,熟悉微信支付规范和 XUC 平台标准。请根据审核反馈改进以下用例模型。\n\n## 当前用例模型\n\\`\\`\\`json\n${currentModelJson}\n\\`\\`\\`\n\n## 审核反馈\n${feedback}\n\n## 要求\n1. 保留正确的部分不变\n2. 根据反馈修正用例命名、步骤类型或场景划分\n3. 补充缺失的用例、步骤或补充约束\n4. 移除不合理的内容\n5. 确保所有 id 保持稳定(已有元素的 id 不变,新增元素用新 id)\n6. 确保命名遵循 \\`主执行者-动作+对象\\` 格式\n7. 确保步骤类型为 request/validate/change/feedback/request-auxiliary/validate-auxiliary 之一\n8. 确保补充约束类型为 field-list/business-rule/quality/design 之一\n\n请直接输出改进后的完整 JSON(格式与输入相同):\n\n\\`\\`\\`json\n{\n \"useCases\": [...],\n \"actors\": [...]\n}\n\\`\\`\\``;\n}\n\n/**\n * Build a prompt to associate use cases with domain model elements,\n * generating a mapping from use case IDs to related domain element IDs.\n */\nexport function buildDomainAssociationPrompt(\n useCaseJson: string,\n domainModelJson: string,\n): string {\n return `你是一个领域驱动设计和系统用例分析专家。请分析以下用例模型和领域模型,建立它们之间的关联关系。\n\n## 用例模型\n\\`\\`\\`json\n${useCaseJson}\n\\`\\`\\`\n\n## 领域模型\n\\`\\`\\`json\n${domainModelJson}\n\\`\\`\\`\n\n## 分析要求\n\n对每个用例,识别它涉及的领域元素(实体、聚合根、值对象、领域服务、领域事件等)。\n\n关联原则:\n- 用例的主路径步骤中操作或引用的领域元素\n- 用例的前置条件和后置条件涉及的领域元素\n- 用例的补充约束(字段列表、业务规则)关联的领域元素\n- 优先关联聚合根和实体,其次是值对象和领域服务\n\n## 输出格式\n\n请严格输出以下 JSON 格式(不要添加任何额外文字或注释):\n\n\\`\\`\\`json\n{\n \"associations\": {\n \"uc-xxx\": [\"el-xxx\", \"el-yyy\"],\n \"uc-yyy\": [\"el-zzz\"]\n }\n}\n\\`\\`\\`\n\n其中 key 是用例 ID,value 是关联的领域元素 ID 数组(按相关性从高到低排序)。`;\n}\n","import { randomUUID } from 'node:crypto';\nimport { logger as rootLogger } from '../logger.js';\nimport { SessionLimitError, SessionNotFoundError } from '../errors/index.js';\nimport type { AIRunner, StreamEvent } from '../ai-runner/AIRunner.js';\nimport { createAIRunner, type AIConfig } from '../ai-runner/index.js';\nimport type { ChatAgentConfig, Config } from '../config.js';\nimport { buildChatSystemPrompt } from '../prompts/chat-templates.js';\nimport { getProjectKnowledge } from '../knowledge/index.js';\nimport type { KnowledgeStore } from '../knowledge/KnowledgeStore.js';\nimport type { VectorStore } from '../distill/VectorStore.js';\n\nconst logger = rootLogger.child('Chat');\n\nexport interface ChatMessage {\n id: string;\n role: 'user' | 'assistant';\n content: string;\n timestamp: string;\n}\n\nexport type ChatSessionStatus = 'idle' | 'thinking' | 'error';\n\nexport interface ChatSession {\n id: string;\n title: string;\n messages: ChatMessage[];\n status: ChatSessionStatus;\n error?: string;\n aiSessionId?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ChatStreamEvent {\n type: 'message:chunk' | 'message:complete' | 'message:thinking' | 'error' | 'done';\n data: unknown;\n messageId?: string;\n}\n\nfunction agentConfigToAIConfig(\n agentCfg: ChatAgentConfig,\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 ChatService {\n private sessions = new Map<string, ChatSession>();\n private runner: AIRunner;\n private config: Config['chat'];\n private workDir: string;\n private knowledgeStore?: KnowledgeStore;\n private vectorStore?: VectorStore;\n\n constructor(config: Config, knowledgeStore?: KnowledgeStore, vectorStore?: VectorStore) {\n this.config = config.chat;\n this.workDir = config.project.workDir;\n this.knowledgeStore = knowledgeStore;\n this.vectorStore = vectorStore;\n this.runner = createAIRunner(\n agentConfigToAIConfig(this.config.agent, this.config.timeoutMs),\n );\n }\n\n createSession(title?: string): ChatSession {\n const session: ChatSession = {\n id: randomUUID(),\n title: title || '新对话',\n messages: [],\n status: 'idle',\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n this.sessions.set(session.id, session);\n logger.info('Created chat session', { sessionId: session.id });\n return session;\n }\n\n getSession(id: string): ChatSession | undefined {\n return this.sessions.get(id);\n }\n\n listSessions(): ChatSession[] {\n return Array.from(this.sessions.values())\n .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n\n deleteSession(id: string): boolean {\n return this.sessions.delete(id);\n }\n\n async sendMessage(\n sessionId: string,\n content: string,\n onEvent?: (event: ChatStreamEvent) => void,\n ): Promise<ChatMessage> {\n const session = this.requireSession(sessionId);\n\n if (session.messages.length >= this.config.maxSessionMessages) {\n throw new SessionLimitError(this.config.maxSessionMessages);\n }\n\n const userMessage: ChatMessage = {\n id: randomUUID(),\n role: 'user',\n content,\n timestamp: new Date().toISOString(),\n };\n session.messages.push(userMessage);\n session.status = 'thinking';\n session.updatedAt = new Date().toISOString();\n\n const assistantMessageId = randomUUID();\n let assistantContent = '';\n\n try {\n // Immediately emit thinking event before spawning AI CLI\n onEvent?.({\n type: 'message:thinking',\n data: { status: 'connecting' },\n messageId: assistantMessageId,\n });\n\n const isFirstMessage = session.messages.length === 1;\n const knowledgeEntries = this.knowledgeStore?.getAllEntries();\n\n // 语义搜索相关知识片段\n let vectorContext = '';\n if (isFirstMessage && this.vectorStore) {\n try {\n const results = await this.vectorStore.search(content, 5);\n if (results.length > 0) {\n vectorContext = '\\n\\n## 相关知识片段\\n\\n' + results\n .map(r => `### [${r.sourceType}] (相关度: ${(r.score * 100).toFixed(0)}%)\\n${r.content.slice(0, 500)}`)\n .join('\\n\\n');\n }\n } catch (err) {\n logger.debug('Vector search failed, continuing without', { error: (err as Error).message });\n }\n }\n\n const prompt = isFirstMessage\n ? `${buildChatSystemPrompt(getProjectKnowledge(), knowledgeEntries)}${vectorContext}\\n\\n用户问题:${content}`\n : content;\n\n const result = await this.runner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.config.timeoutMs,\n sessionId: session.aiSessionId,\n continueSession: !!session.aiSessionId,\n onStreamEvent: (evt: StreamEvent) => {\n // Accumulate actual AI text from assistant and text events only\n if (evt.content && typeof evt.content === 'object') {\n const content = evt.content as Record<string, unknown>;\n if (content.type === 'assistant') {\n const message = content.message as { content?: Array<{ type?: string; text?: string }> } | undefined;\n if (message?.content && Array.isArray(message.content)) {\n for (const block of message.content) {\n if (block.type === 'text' && block.text) {\n assistantContent += block.text;\n }\n }\n }\n }\n } else if (evt.content && typeof evt.content === 'string') {\n // raw/partial text events\n if (evt.type === 'partial' || evt.type === 'raw') {\n assistantContent += evt.content;\n }\n }\n // Always forward all events to frontend for streaming display\n onEvent?.({\n type: 'message:chunk',\n data: evt,\n messageId: assistantMessageId,\n });\n },\n });\n\n // Prefer accumulated assistant text (actual AI reply) over result.output (may be summary)\n const finalContent = assistantContent.trim()\n ? assistantContent\n : (result.success ? result.output : (result.output || 'AI 未返回内容'));\n\n const assistantMessage: ChatMessage = {\n id: assistantMessageId,\n role: 'assistant',\n content: finalContent,\n timestamp: new Date().toISOString(),\n };\n session.messages.push(assistantMessage);\n session.aiSessionId = result.sessionId ?? session.aiSessionId;\n session.status = result.success ? 'idle' : 'error';\n if (!result.success) {\n session.error = result.output;\n }\n session.updatedAt = new Date().toISOString();\n\n if (session.title === '新对话' && session.messages.length >= 2) {\n session.title = content.slice(0, 50) + (content.length > 50 ? '...' : '');\n }\n\n onEvent?.({\n type: 'message:complete',\n data: { message: assistantMessage },\n messageId: assistantMessageId,\n });\n\n return assistantMessage;\n } catch (err) {\n session.status = 'error';\n session.error = (err as Error).message;\n session.updatedAt = new Date().toISOString();\n\n onEvent?.({\n type: 'error',\n data: { message: (err as Error).message },\n messageId: assistantMessageId,\n });\n\n throw err;\n }\n }\n\n private requireSession(id: string): ChatSession {\n const session = this.sessions.get(id);\n if (!session) {\n throw new SessionNotFoundError(id);\n }\n return session;\n }\n}\n","import type { ProjectKnowledge } from '../knowledge/ProjectKnowledge.js';\nimport type { KnowledgeEntry } from '../knowledge/KnowledgeEntry.js';\n\nconst SUMMARY_MAX_CHARS = 500;\n\nexport function buildChatSystemPrompt(\n knowledge: ProjectKnowledge | null,\n knowledgeEntries?: KnowledgeEntry[],\n): string {\n let knowledgeSection = '';\n\n if (knowledge) {\n const parts: string[] = [];\n if (knowledge.structure) {\n parts.push(`- 主要语言:${knowledge.structure.primaryLanguage}`);\n if (knowledge.structure.frameworks.length > 0) {\n parts.push(`- 框架:${knowledge.structure.frameworks.join(', ')}`);\n }\n if (knowledge.structure.description) {\n parts.push(`- 描述:${knowledge.structure.description}`);\n }\n }\n if (knowledge.toolchain) {\n parts.push(`- 包管理器:${knowledge.toolchain.packageManager}`);\n }\n if (parts.length > 0) {\n knowledgeSection = `\\n**项目知识库:**\\n${parts.join('\\n')}\\n`;\n }\n }\n\n let entriesSection = '';\n if (knowledgeEntries && knowledgeEntries.length > 0) {\n const entryParts = knowledgeEntries.map(e => {\n const typeLabel = ({ 'project-meta': '项目分析', custom: '自定义', iwiki: 'iwiki文档', gongfeng: '工蜂提炼', 'domain-model': '领域模型' } as Record<string, string>)[e.type] || e.type;\n const summary = e.content.length > SUMMARY_MAX_CHARS\n ? e.content.slice(0, SUMMARY_MAX_CHARS) + '...'\n : e.content;\n return `### [${typeLabel}] ${e.title}\\n${summary}`;\n });\n entriesSection = `\\n**知识条目(共 ${knowledgeEntries.length} 条):**\\n\\n${entryParts.join('\\n\\n')}\\n`;\n }\n\n return `你是一个智能助手,专注于为开发者提供技术咨询和项目帮助。\n\n你的职责:\n1. 解答技术问题(编程语言、框架、工具链等)\n2. 提供项目相关的使用指南和最佳实践\n3. 帮助分析和解决开发中遇到的问题\n4. 给出代码示例和实现建议\n\n回复原则:\n- 使用清晰简洁的语言\n- 给出具体可操作的建议\n- 必要时提供代码示例\n- 如果不确定,明确说明并给出可能的方向\n- 使用 Markdown 格式组织回复\n${knowledgeSection}${entriesSection}\n请直接回答用户的问题,不要输出多余的寒暄。`;\n}\n","import express from 'express';\nimport { createWebhookRouter, WebhookHandlerDeps } from './WebhookHandler.js';\nimport { IntentRecognizer } from './IntentRecognizer.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\nimport type { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport type { SupplementStore } from '../supplement/SupplementStore.js';\nimport type { GongfengClient } from '../clients/GongfengClient.js';\nimport type { Config } from '../config.js';\nimport type { IssuePoller } from '../poller/IssuePoller.js';\nimport type { IssueClaimer } from '../coordination/IssueClaimer.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { resolveDisplayHost } from '../utils/network.js';\nimport { resolveModelForRunner } from '../ai-runner/ModelMapping.js';\nimport type { Server } from 'node:http';\n\nconst logger = rootLogger.child('WebhookServer');\n\nexport interface WebhookServerDeps {\n tracker: IssueTracker;\n orchestrator: PipelineOrchestrator;\n supplementStore: SupplementStore;\n gongfeng: GongfengClient;\n config: Config;\n poller?: IssuePoller;\n claimer?: IssueClaimer | null;\n}\n\nexport class WebhookServer {\n private app: express.Application;\n private server: Server | null = null;\n private host: string;\n private port: number;\n\n constructor(deps: WebhookServerDeps) {\n this.host = deps.config.webhook.host;\n this.port = deps.config.webhook.port;\n\n // 使用 webhook.llmBinary(默认 claude-internal)而非 ai.binary,\n // 因为意图识别需要轻量级 CLI stdin/stdout 接口,cursor CLI 不支持此模式。\n // 详见 IntentRecognizer.ts 类注释。\n const intentRecognizer = deps.config.webhook.llmFallback\n ? new IntentRecognizer({\n binary: deps.config.webhook.llmBinary,\n nvmNodeVersion: deps.config.ai.nvmNodeVersion,\n model: deps.config.ai.model\n ? resolveModelForRunner(deps.config.webhook.llmBinary, deps.config.ai.model)\n : undefined,\n })\n : undefined;\n\n const handlerDeps: WebhookHandlerDeps = {\n tracker: deps.tracker,\n orchestrator: deps.orchestrator,\n supplementStore: deps.supplementStore,\n gongfeng: deps.gongfeng,\n config: deps.config,\n intentRecognizer,\n poller: deps.poller,\n claimer: deps.claimer,\n };\n\n this.app = express();\n this.app.use(express.json());\n this.app.use(createWebhookRouter(handlerDeps));\n\n this.app.get('/health', (_req, res) => {\n res.json({ status: 'ok', service: 'webhook' });\n });\n }\n\n start(): Promise<void> {\n return new Promise((resolve) => {\n this.server = this.app.listen(this.port, this.host, () => {\n logger.info(`Webhook server listening on http://${resolveDisplayHost(this.host)}:${this.port}`);\n resolve();\n });\n });\n }\n\n stop(): void {\n if (this.server) {\n this.server.close();\n this.server = null;\n logger.info('Webhook server stopped');\n }\n }\n}\n","import express, { type Request, type Response } from 'express';\nconst { Router } = express;\nimport { containsTrigger, extractCommandText, parseExact } from './CommandParser.js';\nimport { IntentRecognizer } from './IntentRecognizer.js';\nimport { CommandExecutor, CommandExecutorDeps } from './CommandExecutor.js';\nimport { NoteDeduplicator } from './NoteDeduplicator.js';\nimport { getIid, getExternalId } from '../tracker/IssueRecordHelper.js';\nimport type { Config } from '../config.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('WebhookHandler');\n\nexport interface NoteEvent {\n object_kind: string;\n event_type?: string;\n user: { username: string; name: string; user_id?: number };\n object_attributes: {\n id: number;\n note: string;\n noteable_type: string;\n noteable_id: number | string;\n };\n issue?: {\n id: number | null;\n iid: number;\n title: string;\n };\n merge_request?: {\n id: number;\n iid: number;\n title: string;\n source_branch: string;\n target_branch: string;\n state: string;\n };\n}\n\nexport interface WebhookHandlerDeps extends CommandExecutorDeps {\n config: Config;\n intentRecognizer?: IntentRecognizer;\n}\n\nexport function createWebhookRouter(deps: WebhookHandlerDeps): ReturnType<typeof Router> {\n const router = Router();\n const executor = new CommandExecutor(deps);\n const dedup = new NoteDeduplicator();\n const { config, intentRecognizer } = deps;\n\n const selfToken = config.gongfeng.privateToken;\n\n router.post('/webhook/gongfeng', async (req: Request, res: Response) => {\n if (!config.webhook.enabled) {\n res.status(403).json({ error: 'Webhook is disabled' });\n return;\n }\n\n if (config.webhook.secret) {\n const token = req.headers['x-gitlab-token'] as string | undefined;\n if (token !== config.webhook.secret) {\n logger.warn('Webhook token mismatch');\n res.status(401).json({ error: 'Invalid token' });\n return;\n }\n }\n\n const event = req.body as NoteEvent;\n\n const noteBody = event.object_attributes.note;\n if (!containsTrigger(noteBody)) {\n res.json({ ignored: true, reason: 'no trigger found' });\n return;\n }\n\n if (isSelfNote(event, selfToken)) {\n res.json({ ignored: true, reason: 'self-posted note' });\n return;\n }\n\n const noteId = event.object_attributes.id;\n if (dedup.isDuplicate(noteId)) {\n logger.debug('Duplicate note, skipping', { noteId });\n res.json({ ignored: true, reason: 'duplicate' });\n return;\n }\n\n if (isNoteOnIssue(event)) {\n const issueIid = event.issue?.iid;\n const issueId = event.issue?.id;\n if (!issueIid) {\n res.status(400).json({ error: 'Missing issue iid in webhook payload' });\n return;\n }\n if (!issueId) {\n logger.info('Webhook received with null issue id (likely a test ping)', { issueIid });\n res.json({ accepted: true, noteId, issueIid, test: true });\n return;\n }\n\n res.json({ accepted: true, noteId, issueIid });\n\n processCommandAsync(\n noteBody, issueIid, issueId, executor, intentRecognizer, config,\n deps.tracker, deps.gongfeng,\n );\n } else if (isNoteOnMergeRequest(event)) {\n const mr = event.merge_request!;\n res.json({ accepted: true, noteId, mrIid: mr.iid });\n\n processMRCommandAsync(\n noteBody, mr, executor, deps.tracker, deps.gongfeng,\n );\n } else {\n res.json({ ignored: true, reason: 'not a note on issue or MR' });\n }\n });\n\n return router;\n}\n\nconst HELP_TEXT_FUNC = () => t('webhook.helpText');\n\nasync function processCommandAsync(\n noteBody: string,\n issueIid: number,\n issueId: number,\n executor: CommandExecutor,\n intentRecognizer: IntentRecognizer | undefined,\n config: Config,\n tracker: { get(iid: number): { state: string } | undefined },\n gongfeng: { createIssueNote(issueId: number, body: string): Promise<void> },\n): Promise<void> {\n try {\n const cmdText = extractCommandText(noteBody);\n if (!cmdText) return;\n\n let command = parseExact(cmdText);\n\n if (!command && intentRecognizer && config.webhook.llmFallback) {\n const record = tracker.get(issueIid);\n const state = record?.state;\n logger.info('Falling back to LLM intent recognition', { issueIid });\n command = await intentRecognizer.recognize(cmdText, state);\n }\n\n if (!command) {\n logger.info('Could not parse command from note', { issueIid, text: cmdText.slice(0, 100) });\n await gongfeng.createIssueNote(issueId, HELP_TEXT_FUNC()).catch((e) =>\n logger.warn('Failed to reply help text', { error: (e as Error).message }),\n );\n return;\n }\n\n await executor.execute(issueIid, issueId, command);\n } catch (err) {\n logger.error('Failed to process webhook command', {\n issueIid,\n error: (err as Error).message,\n });\n }\n}\n\nfunction isNoteOnIssue(event: NoteEvent): boolean {\n return (\n event.object_kind === 'note' &&\n event.object_attributes?.noteable_type?.toLowerCase() === 'issue' &&\n !!event.issue\n );\n}\n\nfunction isNoteOnMergeRequest(event: NoteEvent): boolean {\n return (\n event.object_kind === 'note' &&\n (event.object_attributes?.noteable_type?.toLowerCase() === 'review'\n || event.object_attributes?.noteable_type?.toLowerCase() === 'mergerequest') &&\n !!event.merge_request\n );\n}\n\nconst MR_SUPPORTED_INTENTS = new Set(['fix-conflict', 'status']);\n\nasync function processMRCommandAsync(\n noteBody: string,\n mr: NonNullable<NoteEvent['merge_request']>,\n executor: CommandExecutor,\n tracker: { get(iid: number): { state: string; branchName: string; demandSpec?: { sourceRef: { externalId: string; displayId?: string } } } | undefined; getAll(): Array<{ branchName: string; demandSpec?: { sourceRef: { externalId: string; displayId?: string } } }> },\n gongfeng: { createIssueNote(issueId: number, body: string): Promise<void>; createMergeRequestNote(mrIid: number, body: string): Promise<void> },\n): Promise<void> {\n try {\n const cmdText = extractCommandText(noteBody);\n if (!cmdText) return;\n\n const command = parseExact(cmdText);\n if (!command) {\n await gongfeng.createMergeRequestNote(mr.iid, HELP_TEXT_FUNC()).catch((e) =>\n logger.warn('Failed to reply help text on MR', { error: (e as Error).message }),\n );\n return;\n }\n\n if (!MR_SUPPORTED_INTENTS.has(command.intent)) {\n await gongfeng.createMergeRequestNote(\n mr.iid,\n `\\`${command.intent}\\` command is not supported on MR comments. Please use Issue comments instead.`,\n ).catch((e) =>\n logger.warn('Failed to reply on MR', { error: (e as Error).message }),\n );\n return;\n }\n\n // Find issue by source branch\n const allRecords = tracker.getAll();\n const record = allRecords.find(r => r.branchName === mr.source_branch);\n if (!record) {\n await gongfeng.createMergeRequestNote(\n mr.iid,\n `Could not find a tracked issue for branch \\`${mr.source_branch}\\`.`,\n ).catch((e) =>\n logger.warn('Failed to reply on MR', { error: (e as Error).message }),\n );\n return;\n }\n\n const result = await executor.execute(Number(record.demandSpec?.sourceRef.displayId), Number(record.demandSpec?.sourceRef.externalId), command);\n\n // Also reply on the MR\n try {\n const prefix = result.success ? '' : '> **Failed**\\n>\\n> ';\n await gongfeng.createMergeRequestNote(mr.iid, `${prefix}${result.message}`);\n } catch (err) {\n logger.warn('Failed to reply on MR', { mrIid: mr.iid, error: (err as Error).message });\n }\n } catch (err) {\n logger.error('Failed to process MR webhook command', {\n mrIid: mr.iid,\n error: (err as Error).message,\n });\n }\n}\n\n/**\n * Heuristic to avoid processing notes posted by the bot itself.\n * We check if the note author username matches the token owner.\n * This is imperfect but works for most setups.\n */\nfunction isSelfNote(_event: NoteEvent, _selfToken: string): boolean {\n // Gongfeng webhook payloads include user info but not a direct token mapping.\n // For now, we rely on the fact that bot-posted notes won't contain @issue-auto.\n // A more robust check can be added by comparing event.user.username against\n // a configured bot username (WEBHOOK_BOT_USERNAME env var).\n return false;\n}\n","export type CommandIntent =\n | 'retry'\n | 'retry-from'\n | 'supplement'\n | 'approve'\n | 'reject'\n | 'status'\n | 'restart'\n | 'cancel'\n | 'preview'\n | 'stop-preview'\n | 'clean-notes'\n | 'fix-conflict'\n | 'distill'\n | 'knowledge'\n | 'sync';\n\nexport interface ParsedCommand {\n intent: CommandIntent;\n phase?: string;\n context?: string;\n feedback?: string;\n /** For sync commands: 'knowledge' | 'rules' | 'all' */\n syncTarget?: string;\n}\n\nconst TRIGGERS = ['@issue-auto', '@iaf'];\n\nconst PHASE_ALIAS: Record<string, string> = {\n '分析': 'analysis', '需求分析': 'analysis',\n '设计': 'design', '系统设计': 'design',\n '实现': 'implement', '实施': 'implement', '编码': 'implement',\n '验证': 'verify', '测试': 'verify',\n '规划': 'plan', '构建': 'build',\n 'uat': 'uat', 'e2e': 'uat', '验收': 'uat', '验收测试': 'uat', 'ui验证': 'uat',\n};\n\nfunction resolvePhase(raw: string): string {\n const lower = raw.toLowerCase();\n return PHASE_ALIAS[lower] ?? lower;\n}\n\nconst EXACT_PATTERNS: Array<{\n regex: RegExp;\n build: (match: RegExpMatchArray) => ParsedCommand;\n}> = [\n {\n regex: /retry-from\\s+(\\S+)/i,\n build: (m) => ({ intent: 'retry-from', phase: resolvePhase(m[1]) }),\n },\n {\n regex: /(?:从|回到)\\s*(\\S+?)\\s*(?:阶段)?(?:重[试来做新]|开始)/,\n build: (m) => ({ intent: 'retry-from', phase: resolvePhase(m[1]) }),\n },\n {\n regex: /retry\\b/i,\n build: () => ({ intent: 'retry' }),\n },\n {\n regex: /重试|再试/,\n build: () => ({ intent: 'retry' }),\n },\n {\n regex: /restart\\b/i,\n build: () => ({ intent: 'restart' }),\n },\n {\n regex: /(?:重新开始|从头(?:开始|来|做)|重做)/,\n build: () => ({ intent: 'restart' }),\n },\n {\n regex: /cancel\\b/i,\n build: () => ({ intent: 'cancel' }),\n },\n {\n regex: /(?:取消|中止|停止处理)/,\n build: () => ({ intent: 'cancel' }),\n },\n {\n regex: /approve\\b/i,\n build: () => ({ intent: 'approve' }),\n },\n {\n regex: /(?:批准|通过|同意|LGTM)/i,\n build: () => ({ intent: 'approve' }),\n },\n {\n regex: /reject\\s+([\\s\\S]+)/i,\n build: (m) => ({ intent: 'reject', feedback: m[1].trim() }),\n },\n {\n regex: /(?:驳回|拒绝|打回)[::\\s]*([\\s\\S]+)/,\n build: (m) => ({ intent: 'reject', feedback: m[1].trim() }),\n },\n {\n regex: /supplement\\s+([\\s\\S]+)/i,\n build: (m) => ({ intent: 'supplement', context: m[1].trim() }),\n },\n {\n regex: /(?:补充)[::\\s]*([\\s\\S]+)/,\n build: (m) => ({ intent: 'supplement', context: m[1].trim() }),\n },\n {\n regex: /status\\b/i,\n build: () => ({ intent: 'status' }),\n },\n {\n regex: /(?:状态|什么状态|进度|查询)/,\n build: () => ({ intent: 'status' }),\n },\n {\n regex: /stop-preview\\b/i,\n build: () => ({ intent: 'stop-preview' }),\n },\n {\n regex: /(?:停止预览|关闭预览|停止体验)/,\n build: () => ({ intent: 'stop-preview' }),\n },\n {\n regex: /preview\\b/i,\n build: () => ({ intent: 'preview' }),\n },\n {\n regex: /(?:预览|体验|preview环境)/,\n build: () => ({ intent: 'preview' }),\n },\n {\n regex: /clean-notes\\b/i,\n build: () => ({ intent: 'clean-notes' }),\n },\n {\n regex: /(?:清理评论|清除评论|删除评论)/,\n build: () => ({ intent: 'clean-notes' }),\n },\n {\n regex: /fix-conflict\\b/i,\n build: () => ({ intent: 'fix-conflict' }),\n },\n {\n regex: /(?:修复冲突|解决冲突|处理冲突|冲突修复|fix\\s*冲突)/,\n build: () => ({ intent: 'fix-conflict' }),\n },\n {\n regex: /sync[-\\s]?(knowledge|rules|all)\\b/i,\n build: (m) => ({ intent: 'sync', syncTarget: m[1].toLowerCase() }),\n },\n {\n regex: /同步(?:知识|knowledge)/,\n build: () => ({ intent: 'sync', syncTarget: 'knowledge' }),\n },\n {\n regex: /同步(?:规则|rules)/,\n build: () => ({ intent: 'sync', syncTarget: 'rules' }),\n },\n {\n regex: /同步(?:全部|所有|all)/,\n build: () => ({ intent: 'sync', syncTarget: 'all' }),\n },\n {\n regex: /distill\\b/i,\n build: () => ({ intent: 'distill' }),\n },\n {\n regex: /(?:蒸馏|总结经验|知识蒸馏|提炼经验)/,\n build: () => ({ intent: 'distill' }),\n },\n {\n regex: /knowledge\\b/i,\n build: () => ({ intent: 'knowledge' }),\n },\n {\n regex: /(?:知识|知识库|知识统计)/,\n build: () => ({ intent: 'knowledge' }),\n },\n];\n\nexport function containsTrigger(text: string): boolean {\n const lower = text.toLowerCase();\n return TRIGGERS.some(t => lower.includes(t));\n}\n\n/**\n * Extract the portion of text after the trigger (@issue-auto or @IAF).\n * Returns null if trigger is not found.\n */\nexport function extractCommandText(text: string): string | null {\n const lower = text.toLowerCase();\n for (const trigger of TRIGGERS) {\n const idx = lower.indexOf(trigger);\n if (idx >= 0) return text.slice(idx + trigger.length).trim();\n }\n return null;\n}\n\n/**\n * Try to parse an exact command from the text after the trigger.\n * Returns null if no pattern matches (caller should fall back to LLM).\n */\nexport function parseExact(commandText: string): ParsedCommand | null {\n for (const { regex, build } of EXACT_PATTERNS) {\n const match = commandText.match(regex);\n if (match) return build(match);\n }\n return null;\n}\n\n/**\n * Full parse pipeline: extract trigger text, then try exact match.\n * Returns null if trigger not found or no exact match.\n */\nexport function parseCommand(fullText: string): ParsedCommand | null {\n const commandText = extractCommandText(fullText);\n if (commandText === null) return null;\n return parseExact(commandText);\n}\n","import type { ParsedCommand } from './CommandParser.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\nimport type { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport type { SupplementStore } from '../supplement/SupplementStore.js';\nimport type { GongfengClient } from '../clients/GongfengClient.js';\nimport type { Config } from '../config.js';\nimport type { IssuePoller } from '../poller/IssuePoller.js';\nimport type { IssueClaimer } from '../coordination/IssueClaimer.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport type { PipelineModeView } from '../tracker/IssueViews.js';\nimport { getExternalId } from '../tracker/IssueRecordHelper.js';\nimport { getPipelineDef, createLifecycleManager } from '../pipeline/PipelineDefinition.js';\nimport { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { eventBus } from '../events/EventBus.js';\nimport { syncKnowledgeToProject, syncRulesToProject } from '../web/routes/sync.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('CommandExecutor');\n\nexport interface CommandExecutorDeps {\n tracker: IssueTracker;\n orchestrator: PipelineOrchestrator;\n supplementStore: SupplementStore;\n gongfeng: GongfengClient;\n config: Config;\n poller?: IssuePoller;\n claimer?: IssueClaimer | null;\n}\n\nexport interface ExecutionResult {\n success: boolean;\n message: string;\n}\n\nexport class CommandExecutor {\n private tracker: IssueTracker;\n private orchestrator: PipelineOrchestrator;\n private supplementStore: SupplementStore;\n private gongfeng: GongfengClient;\n private config: Config;\n private poller?: IssuePoller;\n private claimer?: IssueClaimer | null;\n\n constructor(deps: CommandExecutorDeps) {\n this.tracker = deps.tracker;\n this.orchestrator = deps.orchestrator;\n this.supplementStore = deps.supplementStore;\n this.gongfeng = deps.gongfeng;\n this.config = deps.config;\n this.poller = deps.poller;\n this.claimer = deps.claimer;\n }\n\n async execute(\n issueIid: number,\n issueId: number,\n command: ParsedCommand,\n ): Promise<ExecutionResult> {\n logger.info('Executing webhook command', { issueIid, command });\n\n let result: ExecutionResult;\n try {\n result = await this.dispatch(issueIid, command);\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Webhook command failed', { issueIid, error: msg });\n result = { success: false, message: msg };\n }\n\n await this.replyToIssue(issueId, result);\n return result;\n }\n\n private async dispatch(iid: number, cmd: ParsedCommand): Promise<ExecutionResult> {\n switch (cmd.intent) {\n case 'retry': return this.handleRetry(iid);\n case 'retry-from': return this.handleRetryFrom(iid, cmd.phase, cmd.context);\n case 'supplement': return this.handleSupplement(iid, cmd.context);\n case 'approve': return this.handleApprove(iid);\n case 'reject': return this.handleReject(iid, cmd.feedback);\n case 'status': return this.handleStatus(iid);\n case 'restart': return this.handleRestart(iid);\n case 'cancel': return this.handleCancel(iid);\n case 'preview': return this.handlePreview(iid);\n case 'stop-preview': return this.handleStopPreview(iid);\n case 'clean-notes': return this.handleCleanNotes(iid);\n case 'fix-conflict': return this.handleFixConflict(iid);\n case 'sync': return this.handleSync(cmd.syncTarget);\n default: return { success: false, message: 'Unknown command' };\n }\n }\n\n private handleRetry(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n if (record.state !== IssueState.Failed) {\n return this.fail(`Issue not in failed state (current: ${record.state})`);\n }\n const ok = this.tracker.resetForRetry(iid);\n if (!ok) return this.fail('Reset for retry failed');\n return this.ok(`Issue #${iid} has been reset and will retry on the next drive cycle.`);\n }\n\n private handleRetryFrom(iid: number, phase?: string, ctx?: string): ExecutionResult {\n if (!phase) return this.fail('Phase is required for retry-from (e.g. design, implement)');\n if (ctx) this.saveSupplement(iid, ctx);\n\n try {\n this.orchestrator.retryFromPhase(iid, phase);\n } catch (err) {\n return this.fail((err as Error).message);\n }\n\n const extra = ctx ? '\\nSupplement info recorded.' : '';\n return this.ok(`Issue #${iid} will restart from **${phase}** phase.${extra}`);\n }\n\n private handleSupplement(iid: number, ctx?: string): ExecutionResult {\n if (!ctx?.trim()) return this.fail('Supplement content cannot be empty');\n this.saveSupplement(iid, ctx);\n return this.ok('Supplement info recorded. AI will reference it on next execution.');\n }\n\n private handleApprove(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n if (record.state !== IssueState.PhaseWaiting) {\n return this.fail(`Issue not waiting for review (current: ${record.state})`);\n }\n\n this.tracker.updateState(iid, IssueState.PhaseApproved, { currentPhase: 'review' });\n const def = this.getIssuePipelineDef(record);\n const lm = createLifecycleManager(def);\n const gate = lm.getGatePhase();\n if (gate) {\n const workDir = this.getWorktreeWorkDir(iid);\n if (fs.existsSync(workDir)) {\n new PlanPersistence(workDir, iid).updatePhaseProgress(gate.name, 'completed');\n }\n }\n eventBus.emitTyped('review:approved', { issueIid: iid });\n return this.ok('Plan approved. Continuing to next phases.');\n }\n\n private handleReject(iid: number, feedback?: string): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n if (record.state !== IssueState.PhaseWaiting) {\n return this.fail(`Issue not waiting for review (current: ${record.state})`);\n }\n if (!feedback?.trim()) return this.fail('Feedback is required when rejecting');\n\n const workDir = this.getWorktreeWorkDir(iid);\n if (fs.existsSync(workDir)) {\n new PlanPersistence(workDir, iid).writeReviewFeedback(feedback);\n }\n this.tracker.updateState(iid, IssueState.BranchCreated);\n eventBus.emitTyped('review:rejected', { issueIid: iid, feedback });\n return this.ok('Plan rejected. Will re-plan based on feedback.');\n }\n\n private handleStatus(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n const def = this.getIssuePipelineDef(record);\n const stateLabel = createLifecycleManager(def).resolveLabel(record.state, record.currentPhase);\n\n const lines = [\n `**Issue #${iid} Status**`,\n '',\n `- State: **${stateLabel}**`,\n `- Branch: \\`${record.branchName}\\``,\n `- Attempts: ${record.attempts}`,\n `- Pipeline: ${record.pipelineMode ?? 'N/A'}`,\n ];\n if (record.lastError) lines.push(`- Last error: ${record.lastError.slice(0, 200)}`);\n if (record.mrUrl) lines.push(`- MR: ${record.mrUrl}`);\n\n const previewUrl = this.orchestrator.buildPreviewUrl(iid);\n if (previewUrl) {\n const dsm = this.orchestrator.getDevServerManager();\n const status = dsm.getStatus(iid);\n lines.push(`- Preview: ${status.running ? `🌐 ${previewUrl}` : t('cmd.previewStopped')}`);\n }\n\n const baseUrl = this.config.issueNoteSync.webBaseUrl.replace(/\\/$/, '');\n lines.push('', `[View in dashboard](${baseUrl}/?issue=${iid})`);\n return this.ok(lines.join('\\n'));\n }\n\n private async handleRestart(iid: number): Promise<ExecutionResult> {\n try {\n this.poller?.forceReleaseIssue(iid);\n // 释放锁评论\n if (this.claimer) {\n const record = this.tracker.get(iid);\n if (record) {\n const externalId = getExternalId(record);\n await this.claimer.releaseClaim(externalId, iid, 'cancelled');\n }\n }\n await this.orchestrator.restartIssue(iid);\n } catch (err) {\n return this.fail((err as Error).message);\n }\n return this.ok(`Issue #${iid} has been fully reset and will restart from scratch.`);\n }\n\n private async handleCancel(iid: number): Promise<ExecutionResult> {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n try {\n // 释放 poller 并发槽位\n this.poller?.forceReleaseIssue(iid);\n\n // 释放锁评论\n if (this.claimer) {\n try {\n const externalId = getExternalId(record);\n await this.claimer.releaseClaim(externalId, iid, 'cancelled');\n } catch (err) {\n logger.warn('Failed to release lock on cancel', { iid, error: (err as Error).message });\n }\n }\n\n // 统一取消:终止 AI → 停预览 → 移标签 → 清 worktree/分支 → 删 tracker\n await this.orchestrator.cancelIssue(iid);\n\n return this.ok(`Issue #${iid} has been cancelled. All resources cleaned up.`);\n } catch (err) {\n return this.fail((err as Error).message);\n }\n }\n\n private handlePreview(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n const previewUrl = this.orchestrator.buildPreviewUrl(iid);\n if (!previewUrl) {\n return this.ok(\n t('cmd.previewNotStarted', { iid }),\n );\n }\n\n const dsm = this.orchestrator.getDevServerManager();\n const status = dsm.getStatus(iid);\n const ports = this.orchestrator.getPortAllocator().getPortsForIssue(iid);\n const host = this.orchestrator.getPreviewHost();\n\n const lines = [\n '🌐 **Preview Environment**',\n '',\n `| ${t('cmd.previewTable.component')} | ${t('cmd.previewTable.address')} |`,\n `|------|------|`,\n `| ${t('cmd.previewTable.frontend')} | ${previewUrl} |`,\n `| ${t('cmd.previewTable.backendApi')} | http://${host}:${ports!.backendPort}/api |`,\n '',\n `${t('cmd.previewTable.status')}: ${status.running ? t('cmd.previewRunning') : t('cmd.previewStopped')}`,\n ];\n if (status.startedAt) lines.push(`${t('cmd.previewTable.startedAt')}: ${status.startedAt}`);\n\n return this.ok(lines.join('\\n'));\n }\n\n private handleStopPreview(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n const dsm = this.orchestrator.getDevServerManager();\n const status = dsm.getStatus(iid);\n if (!status.running && !record.previewStartedAt) {\n return this.ok(t('cmd.noPreview', { iid }));\n }\n\n this.orchestrator.stopPreviewServers(iid);\n return this.ok(t('cmd.previewStopped', { iid }));\n }\n\n private async handleCleanNotes(iid: number): Promise<ExecutionResult> {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n try {\n const deleted = await this.gongfeng.cleanupAgentNotes(getExternalId(record));\n return this.ok(t('cmd.cleanNotesSuccess', { count: deleted }));\n } catch (err) {\n return this.fail((err as Error).message);\n }\n }\n\n private handleFixConflict(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n // Only allow in Completed state or Failed with failedAtState=ResolvingConflict\n const isCompleted = record.state === IssueState.Completed;\n const isConflictRetry = record.state === IssueState.Failed\n && record.failedAtState === IssueState.ResolvingConflict;\n\n if (!isCompleted && !isConflictRetry) {\n return this.fail(t('conflict.invalidState', { state: record.state }));\n }\n\n if (!record.mrUrl) {\n return this.fail(t('conflict.noMr', { iid }));\n }\n\n // Fire-and-forget: trigger conflict resolution asynchronously\n this.orchestrator.resolveConflict(iid).catch((err) => {\n logger.error('Async conflict resolution failed', { iid, error: (err as Error).message });\n });\n\n return this.ok(t('conflict.startedMsg'));\n }\n\n private async handleSync(target?: string): Promise<ExecutionResult> {\n const workDir = this.config.project.workDir;\n const results: string[] = [];\n\n if (target === 'knowledge' || target === 'all') {\n const synced = syncKnowledgeToProject(workDir);\n results.push(synced ? 'Knowledge synced to project' : 'No knowledge.json in DATA_DIR');\n }\n if (target === 'rules' || target === 'all') {\n const count = await syncRulesToProject(workDir);\n results.push(count > 0 ? `Synced ${count} rule(s) to project` : 'No distilled rules in DATA_DIR');\n }\n if (!target) {\n return this.fail('Sync target required: knowledge, rules, or all');\n }\n\n return this.ok(results.join('\\n'));\n }\n\n private saveSupplement(iid: number, context: string): void {\n const existing = this.supplementStore.get(iid);\n const prev = existing?.freeText?.trim() ?? '';\n const merged = prev ? `${prev}\\n\\n---\\n${context}` : context;\n this.supplementStore.save(iid, {\n requirements: existing?.requirements ?? '',\n acceptanceCriteria: existing?.acceptanceCriteria ?? '',\n scope: existing?.scope ?? '',\n constraints: existing?.constraints ?? '',\n references: existing?.references ?? '',\n freeText: merged,\n tapdId: existing?.tapdId ?? '',\n });\n }\n\n private async replyToIssue(issueId: number, result: ExecutionResult): Promise<void> {\n try {\n const prefix = result.success ? '' : '> **Failed**\\n>\\n> ';\n await this.gongfeng.createIssueNote(issueId, `${prefix}${result.message}`);\n } catch (err) {\n logger.warn('Failed to reply', { issueId, error: (err as Error).message });\n }\n }\n\n private ok(message: string): ExecutionResult {\n return { success: true, message };\n }\n\n private fail(message: string): ExecutionResult {\n return { success: false, message };\n }\n\n private notTracked(iid: number): ExecutionResult {\n return this.fail(`Issue #${iid} is not tracked. Add the auto-finish label to start.`);\n }\n\n private getIssuePipelineDef(record: PipelineModeView) {\n return getPipelineDef(record.pipelineMode ?? 'plan-mode');\n }\n\n private getWorktreeWorkDir(iid: number): string {\n return path.join(\n this.config.project.worktreeBaseDir,\n `issue-${iid}`,\n this.config.project.projectSubDir,\n );\n }\n}\n","/**\n * LRU-based deduplication for webhook note IDs.\n * Prevents the same note from being processed twice\n * (e.g. due to webhook retries or duplicate deliveries).\n */\nexport class NoteDeduplicator {\n private seen: Map<number, number>;\n private maxSize: number;\n\n constructor(maxSize: number = 1000) {\n this.seen = new Map();\n this.maxSize = maxSize;\n }\n\n /**\n * Returns true if this noteId has already been processed.\n * If not, marks it as processed and returns false.\n */\n isDuplicate(noteId: number): boolean {\n if (this.seen.has(noteId)) return true;\n this.seen.set(noteId, Date.now());\n this.evictIfNeeded();\n return false;\n }\n\n get size(): number {\n return this.seen.size;\n }\n\n private evictIfNeeded(): void {\n if (this.seen.size <= this.maxSize) return;\n const oldest = this.seen.keys().next().value;\n if (oldest !== undefined) {\n this.seen.delete(oldest);\n }\n }\n}\n","import { spawn } from 'node:child_process';\nimport type { ParsedCommand, CommandIntent } from './CommandParser.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('IntentRecognizer');\n\nconst VALID_INTENTS: CommandIntent[] = [\n 'retry', 'retry-from', 'supplement', 'approve', 'reject', 'status', 'restart', 'fix-conflict',\n];\n\nconst VALID_PHASES = [\n 'analysis', 'design', 'implement', 'verify', 'plan', 'build',\n];\n\nconst SYSTEM_PROMPT_FUNC = () => t('intent.systemPrompt');\n\nexport interface IntentRecognizerConfig {\n binary: string;\n nvmNodeVersion: string;\n model?: string;\n timeoutMs?: number;\n}\n\n/**\n * 通过 LLM 将自然语言评论解析为结构化指令。\n *\n * **为什么默认使用 claude-internal / codebuddy 而非跟随 AI_RUNNER_MODE?**\n *\n * - `cursor` CLI 不支持 `-p`(stdin prompt)、`--output-format`、`--model` 等参数,\n * 且需要连接 VS Code Server,无法在 PM2 无头进程中运行。\n * - `cursor-agent` 是面向多步骤编码任务的完整 IDE agent,对简单的意图分类来说过重。\n * - `claude-internal` 和 `codebuddy` 都提供轻量级 CLI 接口,支持 stdin 传入 prompt\n * 并返回纯文本,适合在后台服务中做短文本意图识别。\n *\n * 因此 `WEBHOOK_LLM_BINARY` 配置独立于 `AI_RUNNER_MODE`,默认值为 `claude-internal`。\n *\n * @see WebhookServer.ts — 构造 IntentRecognizer 时使用 config.webhook.llmBinary\n * @see config.ts — WEBHOOK_LLM_BINARY 环境变量定义\n */\nexport class IntentRecognizer {\n private binary: string;\n private nvmNodeVersion: string;\n private model?: string;\n private timeoutMs: number;\n\n constructor(config: IntentRecognizerConfig) {\n this.binary = config.binary;\n this.nvmNodeVersion = config.nvmNodeVersion;\n this.model = config.model;\n this.timeoutMs = config.timeoutMs ?? 30_000;\n }\n\n async recognize(userComment: string, issueState?: string): Promise<ParsedCommand | null> {\n const stateHint = issueState ? `\\n当前 Issue 状态: ${issueState}` : '';\n const userPrompt = `${SYSTEM_PROMPT_FUNC()}\\n\\n用户评论:${stateHint}\\n${userComment}`;\n\n try {\n const rawOutput = await this.runLLM(userPrompt);\n return this.parseResponse(rawOutput);\n } catch (err) {\n logger.error('Intent recognition failed', { error: (err as Error).message });\n return null;\n }\n }\n\n /** Visible for testing */\n parseResponse(raw: string): ParsedCommand | null {\n const jsonMatch = raw.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) {\n logger.warn('No JSON found in LLM response', { raw: raw.slice(0, 200) });\n return null;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(jsonMatch[0]);\n } catch {\n logger.warn('Failed to parse JSON from LLM', { raw: jsonMatch[0].slice(0, 200) });\n return null;\n }\n\n if (parsed.intent === null || parsed.intent === 'null') return null;\n\n const intent = String(parsed.intent) as CommandIntent;\n if (!VALID_INTENTS.includes(intent)) {\n logger.warn('Invalid intent from LLM', { intent });\n return null;\n }\n\n const result: ParsedCommand = { intent };\n\n if (parsed.phase && parsed.phase !== 'null') {\n const phase = String(parsed.phase).toLowerCase();\n if (VALID_PHASES.includes(phase)) {\n result.phase = phase;\n }\n }\n\n if (parsed.context && parsed.context !== 'null') {\n result.context = String(parsed.context).trim();\n }\n\n if (parsed.feedback && parsed.feedback !== 'null') {\n result.feedback = String(parsed.feedback).trim();\n }\n\n return result;\n }\n\n private runLLM(prompt: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const args = ['-p', '-', '--output-format', 'text', '--verbose'];\n if (this.model) args.push('--model', this.model);\n\n const { CLAUDECODE, ...env } = process.env;\n const child = spawn(this.binary, args, {\n env: { ...env, NODE_VERSION: this.nvmNodeVersion },\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout.on('data', (d) => { stdout += d.toString(); });\n child.stderr.on('data', (d) => { stderr += d.toString(); });\n\n const timer = setTimeout(() => {\n child.kill('SIGTERM');\n reject(new Error(`Intent recognition timed out after ${this.timeoutMs}ms`));\n }, this.timeoutMs);\n\n child.on('close', (code) => {\n clearTimeout(timer);\n if (code !== 0) {\n logger.warn('LLM process exited with non-zero code', { code, stderr: stderr.slice(0, 300) });\n }\n resolve(stdout);\n });\n\n child.on('error', (err) => {\n clearTimeout(timer);\n reject(err);\n });\n\n child.stdin.write(prompt);\n child.stdin.end();\n });\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { eventBus, EventPayload } from '../events/EventBus.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('AgentLogStore');\n\nexport interface AgentLogEntry {\n type: string;\n phase?: string;\n timestamp: string;\n summary: string;\n}\n\nconst MAX_LOGS_PER_ISSUE = 20000;\n\nconst DEBUG_EVENT_TYPES = new Set([\n 'thinking', 'content_block_start', 'content_block_delta',\n 'content_block_stop', 'message_start', 'message_delta',\n 'message_stop', 'ping',\n 'message', // 顶级消息框架 - 含 uuid/session_id 等协议元数据,无文本内容\n]);\n\nexport class AgentLogStore {\n private logDir: string;\n\n constructor(dataDir: string) {\n this.logDir = path.join(dataDir, 'agent-logs');\n if (!fs.existsSync(this.logDir)) {\n fs.mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n public startListening(): void {\n eventBus.on('agent:output', (payload: EventPayload) => {\n this.handleAgentOutput(payload);\n });\n\n eventBus.on('pipeline:progress', (payload: EventPayload) => {\n this.handlePipelineProgress(payload);\n });\n\n logger.info('AgentLogStore listening for events');\n }\n\n public getLogs(issueIid: number): AgentLogEntry[] {\n const filePath = this.logFilePath(issueIid);\n if (!fs.existsSync(filePath)) return [];\n\n try {\n const raw = fs.readFileSync(filePath, 'utf-8').trim();\n if (!raw) return [];\n return raw.split('\\n').map(line => JSON.parse(line) as AgentLogEntry);\n } catch (err) {\n logger.warn('Failed to read agent logs', { issueIid, error: (err as Error).message });\n return [];\n }\n }\n\n public clearLogs(issueIid: number): void {\n const filePath = this.logFilePath(issueIid);\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n }\n\n private logFilePath(issueIid: number): string {\n return path.join(this.logDir, `${issueIid}.jsonl`);\n }\n\n private appendLog(issueIid: number, entry: AgentLogEntry): void {\n const filePath = this.logFilePath(issueIid);\n try {\n fs.appendFileSync(filePath, `${JSON.stringify(entry)}\\n`, 'utf-8');\n this.trimIfNeeded(issueIid, filePath);\n } catch (err) {\n logger.warn('Failed to write agent log', { issueIid, error: (err as Error).message });\n }\n }\n\n private trimIfNeeded(issueIid: number, filePath: string): void {\n try {\n const raw = fs.readFileSync(filePath, 'utf-8').trim();\n if (!raw) return;\n const lines = raw.split('\\n');\n if (lines.length > MAX_LOGS_PER_ISSUE) {\n const trimmed = lines.slice(-MAX_LOGS_PER_ISSUE);\n fs.writeFileSync(filePath, `${trimmed.join('\\n')}\\n`, 'utf-8');\n logger.info('Agent logs trimmed', { issueIid, from: lines.length, to: trimmed.length });\n }\n } catch {\n // best-effort trimming\n }\n }\n\n private handleAgentOutput(payload: EventPayload): void {\n const d = payload.data as { issueIid?: number; phase?: string; event?: { type?: string; content?: unknown; timestamp?: string } };\n if (!d?.issueIid || !d.event) return;\n\n const eventType = d.event.type || 'raw';\n if (DEBUG_EVENT_TYPES.has(eventType)) return;\n\n const entry: AgentLogEntry = {\n type: eventType,\n phase: d.phase,\n timestamp: d.event.timestamp || payload.timestamp,\n summary: this.summarizeContent(d.event),\n };\n this.appendLog(d.issueIid, entry);\n }\n\n private handlePipelineProgress(payload: EventPayload): void {\n const d = payload.data as { issueIid?: number; step?: string; message?: string };\n if (!d?.issueIid) return;\n\n const entry: AgentLogEntry = {\n type: 'system',\n phase: d.step,\n timestamp: payload.timestamp,\n summary: d.message || '',\n };\n this.appendLog(d.issueIid, entry);\n }\n\n private summarizeContent(event: { type?: string; content?: unknown; timestamp?: string }): string {\n const { content } = event;\n if (!content || typeof content === 'string') return String(content || '');\n\n if (event.type === 'assistant') {\n return this.extractAssistantText(content);\n }\n if (event.type === 'tool_use') {\n return this.extractToolUseText(content);\n }\n if (event.type === 'tool_result') {\n const text = typeof (content as Record<string, unknown>).content === 'string'\n ? (content as Record<string, unknown>).content as string\n : JSON.stringify((content as Record<string, unknown>).content || '');\n return text.slice(0, 150);\n }\n if (event.type === 'result') {\n const r = content as Record<string, unknown>;\n return ((r.result as string) || JSON.stringify(content)).slice(0, 200);\n }\n\n return JSON.stringify(content).slice(0, 150);\n }\n\n private extractAssistantText(content: unknown): string {\n const msg = (content as Record<string, unknown>).message || content;\n if (typeof msg === 'string') return msg.slice(0, 200);\n const m = msg as Record<string, unknown>;\n if (m.text) return (m.text as string).slice(0, 200);\n if (m.content) {\n const parts = Array.isArray(m.content) ? m.content : [m.content];\n const texts = parts\n .filter((c: Record<string, unknown>) => c.type === 'text')\n .map((c: Record<string, unknown>) => c.text)\n .join(' ');\n if (texts) return texts.slice(0, 200);\n }\n // No meaningful text extracted – treat as protocol metadata\n return '';\n }\n\n private extractToolUseText(content: unknown): string {\n const c = content as Record<string, unknown>;\n const tool = c.tool as Record<string, unknown> | undefined;\n const name = tool?.name || c.name || '?';\n const input = (tool?.input || c.input || {}) as Record<string, unknown>;\n const detail = input.path || input.command || input.file_path || '';\n return name + (detail ? `: ${detail}` : '');\n }\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { logger as rootLogger } from '../logger.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst logger = rootLogger.child('VersionChecker');\n\nexport interface VersionCheckResult {\n currentVersion: string;\n latestVersion: string;\n hasUpdate: boolean;\n}\n\n/**\n * Compare two semver version strings (major.minor.patch).\n * Returns: 1 if a > b, -1 if a < b, 0 if equal.\n */\nexport function compareSemver(a: string, b: string): number {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < 3; i++) {\n const va = pa[i] ?? 0;\n const vb = pb[i] ?? 0;\n if (va > vb) return 1;\n if (va < vb) return -1;\n }\n return 0;\n}\n\nexport class VersionChecker {\n private registry: string;\n private packageName: string;\n private currentVersion: string;\n\n constructor(registry: string) {\n this.registry = registry.replace(/\\/$/, '');\n const pkg = this.readPackageJson();\n this.packageName = pkg.name;\n this.currentVersion = pkg.version;\n }\n\n getCurrentVersion(): string {\n return this.currentVersion;\n }\n\n getPackageName(): string {\n return this.packageName;\n }\n\n async check(): Promise<VersionCheckResult> {\n const latestVersion = await this.fetchLatestVersion();\n const hasUpdate = compareSemver(latestVersion, this.currentVersion) > 0;\n\n logger.info('Version check completed', {\n current: this.currentVersion,\n latest: latestVersion,\n hasUpdate,\n });\n\n return {\n currentVersion: this.currentVersion,\n latestVersion,\n hasUpdate,\n };\n }\n\n private async fetchLatestVersion(): Promise<string> {\n const url = `${this.registry}/${encodeURIComponent(this.packageName)}`;\n const response = await fetch(url, {\n signal: AbortSignal.timeout(15_000),\n headers: { Accept: 'application/json' },\n });\n\n if (!response.ok) {\n throw new Error(`Registry returned HTTP ${response.status} for ${this.packageName}`);\n }\n\n const data = (await response.json()) as { 'dist-tags'?: { latest?: string } };\n const latest = data['dist-tags']?.latest;\n if (!latest) {\n throw new Error(`No latest version found in dist-tags for ${this.packageName}`);\n }\n\n return latest;\n }\n\n private readPackageJson(): { name: string; version: string } {\n for (let dir = __dirname; dir !== path.dirname(dir); dir = path.dirname(dir)) {\n const candidate = path.join(dir, 'package.json');\n if (existsSync(candidate)) {\n try {\n const content = JSON.parse(readFileSync(candidate, 'utf-8'));\n if (content.name && content.version) return content;\n } catch { /* skip */ }\n }\n }\n throw new Error('Could not find package.json');\n }\n}\n","import { execFile } from 'node:child_process';\nimport { cpSync, existsSync, rmSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { logger as rootLogger } from '../logger.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst logger = rootLogger.child('UpdateExecutor');\n\nfunction findProjectRoot(): string {\n for (let dir = __dirname; dir !== path.dirname(dir); dir = path.dirname(dir)) {\n if (existsSync(path.join(dir, 'package.json'))) {\n return dir;\n }\n }\n throw new Error('Could not find project root');\n}\n\nfunction run(cmd: string, args: string[], cwd: string, timeoutMs: number): Promise<string> {\n return new Promise((resolve, reject) => {\n execFile(cmd, args, { cwd, timeout: timeoutMs, maxBuffer: 10 * 1024 * 1024 }, (err, stdout, stderr) => {\n if (err) {\n reject(new Error(`${cmd} ${args.join(' ')} failed: ${stderr || err.message}`));\n return;\n }\n resolve(stdout);\n });\n });\n}\n\nexport class UpdateExecutor {\n private packageName: string;\n private projectRoot: string;\n\n constructor(packageName: string) {\n this.packageName = packageName;\n this.projectRoot = findProjectRoot();\n }\n\n async execute(targetVersion: string): Promise<void> {\n const distDir = path.join(this.projectRoot, 'dist');\n const backupDir = path.join(this.projectRoot, 'dist.backup');\n\n // Step 1: Backup dist/\n logger.info('Backing up dist directory...');\n if (existsSync(backupDir)) {\n rmSync(backupDir, { recursive: true, force: true });\n }\n if (existsSync(distDir)) {\n cpSync(distDir, backupDir, { recursive: true });\n }\n\n try {\n // Step 2: update package\n logger.info('Running package update...', { package: this.packageName, targetVersion, bin: 'npm' });\n await run('npm', ['update', this.packageName], this.projectRoot, 120_000);\n\n // Step 3: build\n logger.info('Running build...', { bin: 'npm' });\n await run('npm', ['run', 'build'], this.projectRoot, 120_000);\n } catch (err) {\n // Rollback: restore dist from backup\n logger.error('Update failed, rolling back dist...', { error: (err as Error).message });\n if (existsSync(backupDir)) {\n if (existsSync(distDir)) {\n rmSync(distDir, { recursive: true, force: true });\n }\n cpSync(backupDir, distDir, { recursive: true });\n }\n throw err;\n } finally {\n if (existsSync(backupDir)) {\n rmSync(backupDir, { recursive: true, force: true });\n }\n }\n\n // Step 4: pm2 reload\n logger.info('Reloading via PM2...');\n try {\n await run('pm2', ['reload', 'issue-auto-finish'], this.projectRoot, 30_000);\n } catch (err) {\n logger.warn('PM2 reload failed, the process may need manual restart', {\n error: (err as Error).message,\n });\n throw err;\n }\n\n logger.info('Update completed successfully', { version: targetVersion });\n }\n}\n","import { Config } from '../config.js';\nimport { IssuePoller } from '../poller/IssuePoller.js';\nimport { VersionChecker, VersionCheckResult } from './VersionChecker.js';\nimport { UpdateExecutor } from './UpdateExecutor.js';\nimport { eventBus } from '../events/EventBus.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('AutoUpdater');\n\nexport type UpdaterState = 'idle' | 'checking' | 'update-available' | 'draining' | 'updating' | 'completed' | 'failed';\n\nexport interface UpdateStatus {\n state: UpdaterState;\n enabled: boolean;\n currentVersion: string;\n latestVersion: string | null;\n lastCheckAt: string | null;\n lastError: string | null;\n}\n\nconst INITIAL_DELAY_MS = 30_000;\n\nexport class AutoUpdater {\n private config: Config;\n private poller: IssuePoller;\n private versionChecker: VersionChecker;\n private updateExecutor: UpdateExecutor;\n\n private state: UpdaterState = 'idle';\n private latestVersion: string | null = null;\n private lastCheckAt: string | null = null;\n private lastError: string | null = null;\n private updateInProgress = false;\n\n private checkTimer: ReturnType<typeof setInterval> | null = null;\n private initialTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(config: Config, poller: IssuePoller) {\n this.config = config;\n this.poller = poller;\n this.versionChecker = new VersionChecker(config.autoUpdate.registry);\n this.updateExecutor = new UpdateExecutor(this.versionChecker.getPackageName());\n }\n\n start(): void {\n if (!this.config.autoUpdate.enabled) {\n logger.info('Auto-update is disabled');\n return;\n }\n\n logger.info('Auto-updater starting', {\n intervalMs: this.config.autoUpdate.intervalMs,\n registry: this.config.autoUpdate.registry,\n });\n\n // Delay first check to let the service stabilize\n this.initialTimer = setTimeout(() => {\n this.initialTimer = null;\n this.performCheck();\n this.checkTimer = setInterval(() => this.performCheck(), this.config.autoUpdate.intervalMs);\n }, INITIAL_DELAY_MS);\n }\n\n stop(): void {\n if (this.initialTimer) {\n clearTimeout(this.initialTimer);\n this.initialTimer = null;\n }\n if (this.checkTimer) {\n clearInterval(this.checkTimer);\n this.checkTimer = null;\n }\n logger.info('Auto-updater stopped');\n }\n\n getStatus(): UpdateStatus {\n return {\n state: this.state,\n enabled: this.config.autoUpdate.enabled,\n currentVersion: this.versionChecker.getCurrentVersion(),\n latestVersion: this.latestVersion,\n lastCheckAt: this.lastCheckAt,\n lastError: this.lastError,\n };\n }\n\n async checkForUpdate(): Promise<VersionCheckResult> {\n this.state = 'checking';\n eventBus.emitTyped('update:checking', {});\n\n try {\n const result = await this.versionChecker.check();\n this.latestVersion = result.latestVersion;\n this.lastCheckAt = new Date().toISOString();\n this.lastError = null;\n\n if (result.hasUpdate) {\n this.state = 'update-available';\n eventBus.emitTyped('update:available', {\n currentVersion: result.currentVersion,\n latestVersion: result.latestVersion,\n });\n } else {\n this.state = 'idle';\n }\n\n return result;\n } catch (err) {\n const message = (err as Error).message;\n this.lastError = message;\n this.state = 'failed';\n eventBus.emitTyped('update:failed', { error: message });\n throw err;\n }\n }\n\n async triggerUpdate(): Promise<void> {\n if (this.updateInProgress) {\n logger.warn('Update already in progress, skipping');\n return;\n }\n this.updateInProgress = true;\n\n try {\n // Check for update if we haven't yet\n if (!this.latestVersion) {\n const result = await this.checkForUpdate();\n if (!result.hasUpdate) {\n logger.info('No update available');\n return;\n }\n }\n\n const targetVersion = this.latestVersion!;\n\n // Drain: pause discovery and wait for active issues\n this.state = 'draining';\n logger.info('Draining active issues before update...');\n this.poller.pauseDiscovery();\n\n const drainStart = Date.now();\n const drainTimeout = this.config.autoUpdate.drainTimeoutMs;\n while (this.poller.getActiveCount() > 0 && Date.now() - drainStart < drainTimeout) {\n logger.info('Waiting for active issues to complete...', {\n active: this.poller.getActiveCount(),\n });\n await new Promise(resolve => setTimeout(resolve, 5_000));\n }\n\n if (this.poller.getActiveCount() > 0) {\n logger.warn('Drain timeout reached, proceeding with update', {\n active: this.poller.getActiveCount(),\n });\n }\n\n // Execute update\n this.state = 'updating';\n eventBus.emitTyped('update:downloading', { version: targetVersion });\n logger.info('Executing update...', { targetVersion });\n\n await this.updateExecutor.execute(targetVersion);\n\n this.state = 'completed';\n eventBus.emitTyped('update:completed', { version: targetVersion });\n logger.info('Update completed', { version: targetVersion });\n } catch (err) {\n const message = (err as Error).message;\n this.lastError = message;\n this.state = 'failed';\n eventBus.emitTyped('update:failed', { error: message });\n logger.error('Update failed', { error: message });\n\n // Resume discovery on failure\n this.poller.resumeDiscovery();\n } finally {\n this.updateInProgress = false;\n }\n }\n\n private async performCheck(): Promise<void> {\n if (this.updateInProgress) return;\n\n try {\n const result = await this.checkForUpdate();\n if (result.hasUpdate) {\n logger.info('New version available, starting update', {\n current: result.currentVersion,\n latest: result.latestVersion,\n });\n await this.triggerUpdate();\n }\n } catch (err) {\n logger.warn('Periodic version check failed', { error: (err as Error).message });\n }\n }\n}\n","import type { Config } from '../config.js';\nimport { reloadConfig } from '../config.js';\nimport { createAIRunner, type AIRunner } from '../ai-runner/index.js';\nimport type { GongfengClient } from '../clients/GongfengClient.js';\nimport type { IssuePoller } from '../poller/IssuePoller.js';\nimport type { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('ConfigReloader');\n\nexport interface ReloadResult {\n success: boolean;\n reason?: 'active-issues-timeout';\n}\n\nexport interface ConfigReloaderOptions {\n onAIRunnerChanged?: (runner: AIRunner) => void;\n}\n\nexport class ConfigReloader {\n private config: Config;\n private poller: IssuePoller;\n private orchestrator: PipelineOrchestrator;\n private gongfeng: GongfengClient;\n private options: ConfigReloaderOptions;\n\n constructor(\n config: Config,\n poller: IssuePoller,\n orchestrator: PipelineOrchestrator,\n gongfeng: GongfengClient,\n options: ConfigReloaderOptions = {},\n ) {\n this.config = config;\n this.poller = poller;\n this.orchestrator = orchestrator;\n this.gongfeng = gongfeng;\n this.options = options;\n }\n\n async reload(opts?: { waitTimeoutMs?: number }): Promise<ReloadResult> {\n const timeoutMs = opts?.waitTimeoutMs ?? 60_000;\n logger.info('Config reload requested', { timeoutMs });\n\n // 1. Pause discovery to stop picking up new issues\n this.poller.pauseDiscovery();\n\n // 2. Wait for active issues to finish\n const drained = await this.waitForDrain(timeoutMs);\n if (!drained) {\n logger.warn('Active issues did not drain within timeout, aborting reload', {\n active: this.poller.getActiveCount(),\n timeoutMs,\n });\n this.poller.resumeDiscovery();\n return { success: false, reason: 'active-issues-timeout' };\n }\n\n // 3. Stop poller timers\n this.poller.stop();\n\n try {\n // 4. Reload config from .env\n const newConfig = reloadConfig();\n\n // 5. Update config object in-place (keep the reference)\n Object.assign(this.config, newConfig);\n\n // 6. Rebuild AI Runner\n const newRunner = createAIRunner(this.config.ai);\n this.orchestrator.setAIRunner(newRunner);\n this.options.onAIRunnerChanged?.(newRunner);\n\n // 7. Update GongfengClient\n this.gongfeng.updateConfig(this.config.gongfeng);\n\n logger.info('Config reloaded successfully', {\n aiMode: this.config.ai.mode,\n aiModel: this.config.ai.model,\n discoveryIntervalMs: this.config.poll.discoveryIntervalMs,\n });\n } finally {\n // 8. Restart poller (uses new interval values from updated config)\n this.poller.start();\n }\n\n return { success: true };\n }\n\n private async waitForDrain(timeoutMs: number): Promise<boolean> {\n const start = Date.now();\n while (this.poller.getActiveCount() > 0 && Date.now() - start < timeoutMs) {\n await new Promise(r => setTimeout(r, 500));\n }\n return this.poller.getActiveCount() === 0;\n }\n}\n","/**\n * DiaryCollector — Layer 1: 自动采集 Issue 经验日记。\n *\n * 监听 EventBus 的 issue:stateChanged 事件,当 Issue 进入 Completed 或 Failed\n * 状态时,采集 tracker + plan persistence 数据写入 DiaryStore。\n *\n * fire-and-forget:不阻塞主流程,失败只打日志。\n */\nimport { randomUUID } from 'node:crypto';\nimport { eventBus, type EventPayload } from '../events/EventBus.js';\nimport { logger as rootLogger } from '../logger.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\nimport type { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { IssueState, type ProgressData } from '../tracker/IssueState.js';\nimport type { DiaryStore } from './DiaryStore.js';\nimport type { DiaryEntry, DiaryPhaseTiming, DiaryHumanIntervention } from './types.js';\n\nconst logger = rootLogger.child('DiaryCollector');\n\nexport interface DiaryCollectorDeps {\n tracker: IssueTracker;\n diaryStore: DiaryStore;\n /** 工厂函数:给定 issueIid 返回对应的 PlanPersistence(或 null) */\n createPlanPersistence?: (issueIid: number) => PlanPersistence | null;\n}\n\nexport class DiaryCollector {\n private tracker: IssueTracker;\n private diaryStore: DiaryStore;\n private createPlanPersistence?: (issueIid: number) => PlanPersistence | null;\n\n /** Saved handler references for cleanup in stop() */\n private stateChangedHandler: ((payload: EventPayload) => void) | null = null;\n private failedHandler: ((payload: EventPayload) => void) | null = null;\n\n constructor(deps: DiaryCollectorDeps) {\n this.tracker = deps.tracker;\n this.diaryStore = deps.diaryStore;\n this.createPlanPersistence = deps.createPlanPersistence;\n }\n\n /** 开始监听事件(幂等:已启动时直接 return) */\n start(): void {\n if (this.stateChangedHandler) return;\n\n this.stateChangedHandler = (payload: EventPayload) => {\n this.handleStateChanged(payload).catch((err) => {\n logger.warn('DiaryCollector failed to handle stateChanged event', {\n error: (err as Error).message,\n });\n });\n };\n\n this.failedHandler = (payload: EventPayload) => {\n this.handleFailed(payload).catch((err) => {\n logger.warn('DiaryCollector failed to handle failed event', {\n error: (err as Error).message,\n });\n });\n };\n\n eventBus.on('issue:stateChanged', this.stateChangedHandler);\n eventBus.on('issue:failed', this.failedHandler);\n\n logger.info('DiaryCollector started');\n }\n\n /** 停止监听事件 */\n stop(): void {\n if (this.stateChangedHandler) {\n eventBus.off('issue:stateChanged', this.stateChangedHandler);\n this.stateChangedHandler = null;\n }\n if (this.failedHandler) {\n eventBus.off('issue:failed', this.failedHandler);\n this.failedHandler = null;\n }\n logger.info('DiaryCollector stopped');\n }\n\n /** 处理 issue:stateChanged 事件 */\n private async handleStateChanged(payload: EventPayload): Promise<void> {\n const data = payload.data as Record<string, unknown>;\n const state = data.state as string | undefined;\n\n // 只在进入 Completed 时触发日记采集\n if (state !== IssueState.Completed) return;\n\n const issueIid = data.issueIid as number | undefined;\n if (!issueIid) return;\n\n // 避免重复采集\n const existing = this.diaryStore.getByIssueIid(issueIid);\n if (existing.some(d => d.outcome === 'completed')) {\n logger.debug('Diary already exists for completed issue', { issueIid });\n return;\n }\n\n await this.collectDiary(issueIid, 'completed');\n }\n\n /** 处理 issue:failed 事件 */\n private async handleFailed(payload: EventPayload): Promise<void> {\n const data = payload.data as Record<string, unknown>;\n const issueIid = data.issueIid as number | undefined;\n if (!issueIid) return;\n\n await this.collectDiary(issueIid, 'failed');\n }\n\n /** 核心采集逻辑 */\n async collectDiary(issueIid: number, outcome: 'completed' | 'failed'): Promise<DiaryEntry | null> {\n try {\n const record = this.tracker.get(issueIid);\n if (!record) {\n logger.warn('Cannot collect diary: issue record not found', { issueIid });\n return null;\n }\n\n // 从 PlanPersistence 读取阶段进度\n const plan = this.createPlanPersistence?.(issueIid);\n const progress = plan?.readProgress() ?? null;\n\n const timing = this.buildTiming(record, progress);\n const failure = outcome === 'failed' ? this.buildFailure(record) : undefined;\n const interventions = this.buildInterventions(record, progress);\n\n const diary: DiaryEntry = {\n id: randomUUID(),\n issueIid,\n issueTitle: record.demandSpec?.title ?? `Issue #${issueIid}`,\n branchName: record.branchName,\n pipelineMode: record.pipelineMode ?? 'unknown',\n outcome,\n mrUrl: record.mrUrl,\n timing,\n failure,\n humanInterventions: interventions,\n distilled: false,\n createdAt: new Date().toISOString(),\n };\n\n this.diaryStore.create(diary);\n eventBus.emitTyped('distill:diary:created', { issueIid, diaryId: diary.id, outcome });\n logger.info('Diary collected', { issueIid, diaryId: diary.id, outcome });\n\n return diary;\n } catch (err) {\n logger.warn('Failed to collect diary', {\n issueIid,\n outcome,\n error: (err as Error).message,\n });\n return null;\n }\n }\n\n /** 构建执行计时信息 */\n private buildTiming(\n record: { createdAt: string; updatedAt: string },\n progress: ProgressData | null,\n ): DiaryEntry['timing'] {\n const startedAt = record.createdAt;\n const finishedAt = record.updatedAt;\n const totalDurationMs = new Date(finishedAt).getTime() - new Date(startedAt).getTime();\n\n const phaseTimings: DiaryPhaseTiming[] = [];\n if (progress?.phases) {\n for (const [phaseName, phaseProgress] of Object.entries(progress.phases)) {\n if (phaseProgress.startedAt) {\n const endTime = phaseProgress.completedAt ?? finishedAt;\n const durationMs = new Date(endTime).getTime() - new Date(phaseProgress.startedAt).getTime();\n phaseTimings.push({\n phase: phaseName,\n durationMs: Math.max(0, durationMs),\n retries: 0, // 重试信息在 tracker 层面,phase 层面不详细区分\n });\n }\n }\n }\n\n return {\n totalDurationMs: Math.max(0, totalDurationMs),\n phaseTimings,\n startedAt,\n finishedAt,\n };\n }\n\n /** 构建失败信息 */\n private buildFailure(\n record: { lastError?: string; failedAtState?: IssueState; attempts: number; currentPhase?: string },\n ): DiaryEntry['failure'] {\n return {\n failedAtPhase: record.currentPhase ?? record.failedAtState ?? 'unknown',\n error: record.lastError ?? 'Unknown error',\n attempts: record.attempts,\n };\n }\n\n /** 构建人工介入记录 */\n private buildInterventions(\n record: { attempts: number },\n progress: ProgressData | null,\n ): DiaryHumanIntervention[] {\n const interventions: DiaryHumanIntervention[] = [];\n\n // 如果尝试次数大于 1,说明有重试\n if (record.attempts > 1) {\n interventions.push({\n type: 'retry',\n detail: `Issue 经过 ${record.attempts} 次尝试`,\n timestamp: new Date().toISOString(),\n });\n }\n\n // 如果有 review 阶段且已通过,说明有人工审核\n if (progress?.phases) {\n const reviewPhase = progress.phases['review'];\n if (reviewPhase?.status === 'completed') {\n interventions.push({\n type: 'review-approve',\n detail: '方案审核通过',\n timestamp: reviewPhase.completedAt ?? new Date().toISOString(),\n });\n }\n }\n\n return interventions;\n }\n}\n","/**\n * DiaryStore — 日记持久化存储。\n *\n * 继承 BaseTracker<DiaryEntry>,JSON 文件持久化到 data/distill/diaries.json。\n */\nimport { BaseTracker } from '../tracker/BaseTracker.js';\nimport type { DiaryEntry } from './types.js';\n\nexport class DiaryStore extends BaseTracker<DiaryEntry> {\n constructor(dataDir: string) {\n super(dataDir, 'diaries.json', 'diaries', 'diary-store');\n }\n\n /** 创建新日记条目 */\n create(entry: DiaryEntry): void {\n this.setRecord(entry.id, entry);\n this.save();\n }\n\n /** 按 ID 获取日记 */\n get(id: string): DiaryEntry | undefined {\n return this.getByKey(id);\n }\n\n /** 获取所有日记 */\n getAll(): DiaryEntry[] {\n return this.getAllRecords();\n }\n\n /** 获取未蒸馏的日记列表 */\n getUndistilled(): DiaryEntry[] {\n return this.getAllRecords().filter(d => !d.distilled);\n }\n\n /** 按 Issue IID 获取日记 */\n getByIssueIid(issueIid: number): DiaryEntry[] {\n return this.getAllRecords().filter(d => d.issueIid === issueIid);\n }\n\n /** 标记日记已蒸馏 */\n markDistilled(ids: string[]): void {\n let changed = false;\n for (const id of ids) {\n const entry = this.getByKey(id);\n if (entry && !entry.distilled) {\n entry.distilled = true;\n changed = true;\n }\n }\n if (changed) this.save();\n }\n\n /** 删除日记 */\n delete(id: string): boolean {\n return this.deleteByKey(id);\n }\n\n /** 获取日记总数 */\n count(): number {\n return this.getAllRecords().length;\n }\n\n /** 获取未蒸馏日记数 */\n undistilledCount(): number {\n return this.getUndistilled().length;\n }\n}\n","/**\n * MemoryDistiller — Layer 2: 批量分析日记,提取共性模式。\n *\n * 从 DiaryStore 获取未蒸馏的日记,通过 AI 识别模式并生成/更新 memory 条目。\n * memory 条目存储在 KnowledgeStore 中(type='memory')。\n */\nimport { randomUUID } from 'node:crypto';\nimport { logger as rootLogger } from '../logger.js';\nimport type { AIRunner } from '../ai-runner/AIRunner.js';\nimport type { KnowledgeStore } from '../knowledge/KnowledgeStore.js';\nimport type { DiaryStore } from './DiaryStore.js';\nimport type { VersionStore } from './VersionStore.js';\nimport type { MemoryEntry, MemoryDistillAction } from './types.js';\nimport { buildMemoryDistillPrompt } from './prompts/memory-distill.js';\n\nconst logger = rootLogger.child('MemoryDistiller');\n\nexport interface MemoryDistillerDeps {\n aiRunner: AIRunner;\n diaryStore: DiaryStore;\n knowledgeStore: KnowledgeStore;\n versionStore: VersionStore;\n workDir: string;\n timeoutMs: number;\n minDiariesForDistill: number;\n}\n\nexport class MemoryDistiller {\n private aiRunner: AIRunner;\n private diaryStore: DiaryStore;\n private knowledgeStore: KnowledgeStore;\n private versionStore: VersionStore;\n private workDir: string;\n private timeoutMs: number;\n private minDiariesForDistill: number;\n\n constructor(deps: MemoryDistillerDeps) {\n this.aiRunner = deps.aiRunner;\n this.diaryStore = deps.diaryStore;\n this.knowledgeStore = deps.knowledgeStore;\n this.versionStore = deps.versionStore;\n this.workDir = deps.workDir;\n this.timeoutMs = deps.timeoutMs;\n this.minDiariesForDistill = deps.minDiariesForDistill;\n }\n\n /**\n * 执行记忆蒸馏。\n * @returns 处理的日记数和创建/更新的 memory 数。\n */\n async distill(options?: { force?: boolean }): Promise<{ processedDiaries: number; actions: number }> {\n const undistilled = this.diaryStore.getUndistilled();\n\n // force 模式跳过阈值检查(手动触发)\n if (!options?.force && undistilled.length < this.minDiariesForDistill) {\n logger.info('Not enough undistilled diaries, skipping memory distillation', {\n count: undistilled.length,\n threshold: this.minDiariesForDistill,\n });\n return { processedDiaries: 0, actions: 0 };\n }\n\n // force 模式下,如果没有任何日记,也要提前返回\n if (undistilled.length === 0) {\n logger.info('No undistilled diaries available');\n return { processedDiaries: 0, actions: 0 };\n }\n\n logger.info('Starting memory distillation', { diaryCount: undistilled.length });\n\n // 获取现有 memory 列表\n const existingMemories = this.loadExistingMemories();\n\n // 构建 prompt\n const prompt = buildMemoryDistillPrompt(undistilled, existingMemories);\n\n // 调用 AI\n const result = await this.aiRunner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.timeoutMs,\n });\n\n if (!result.success) {\n logger.error('AI distillation failed', { output: result.output.slice(0, 500) });\n throw new Error(`Memory distillation AI call failed: ${result.output.slice(0, 200)}`);\n }\n\n // 解析 AI 输出\n const actions = this.parseActions(result.output);\n if (actions.length === 0) {\n logger.info('No distillation actions returned by AI');\n // 仍然标记日记为已蒸馏\n this.diaryStore.markDistilled(undistilled.map(d => d.id));\n return { processedDiaries: undistilled.length, actions: 0 };\n }\n\n // 执行 actions\n let actionCount = 0;\n for (const action of actions) {\n try {\n this.executeAction(action, existingMemories);\n actionCount++;\n } catch (err) {\n logger.warn('Failed to execute distill action', {\n action: action.type,\n error: (err as Error).message,\n });\n }\n }\n\n // 标记日记为已蒸馏\n this.diaryStore.markDistilled(undistilled.map(d => d.id));\n\n logger.info('Memory distillation complete', {\n processedDiaries: undistilled.length,\n actions: actionCount,\n });\n\n return { processedDiaries: undistilled.length, actions: actionCount };\n }\n\n /** 从 KnowledgeStore 加载现有 memory 条目 */\n private loadExistingMemories(): MemoryEntry[] {\n const entries = this.knowledgeStore.list('memory');\n return entries.map(meta => {\n const full = this.knowledgeStore.get(meta.id);\n if (!full) return null;\n try {\n return JSON.parse(full.content) as MemoryEntry;\n } catch {\n return null;\n }\n }).filter((m): m is MemoryEntry => m !== null);\n }\n\n /** 解析 AI 输出的 actions */\n private parseActions(output: string): MemoryDistillAction[] {\n try {\n // 提取 JSON 块\n const jsonMatch = output.match(/```json\\s*([\\s\\S]*?)```/) ?? output.match(/\\{[\\s\\S]*\"actions\"[\\s\\S]*\\}/);\n if (!jsonMatch) {\n logger.warn('No JSON found in AI output');\n return [];\n }\n const jsonStr = jsonMatch[1] ?? jsonMatch[0];\n const parsed = JSON.parse(jsonStr) as { actions: MemoryDistillAction[] };\n if (!Array.isArray(parsed.actions)) {\n logger.warn('Invalid actions format in AI output');\n return [];\n }\n return parsed.actions;\n } catch (err) {\n logger.warn('Failed to parse AI distillation output', {\n error: (err as Error).message,\n output: output.slice(0, 300),\n });\n return [];\n }\n }\n\n /** 执行单个 action */\n private executeAction(action: MemoryDistillAction, existingMemories: MemoryEntry[]): void {\n switch (action.type) {\n case 'CREATE':\n this.createMemory(action);\n break;\n case 'MERGE':\n this.mergeMemory(action, existingMemories);\n break;\n case 'SUPERSEDE':\n this.supersedeMemory(action, existingMemories);\n break;\n default:\n logger.warn('Unknown distill action type', { type: (action as { type: string }).type });\n }\n }\n\n /** 创建新 memory */\n private createMemory(action: Extract<MemoryDistillAction, { type: 'CREATE' }>): void {\n const memoryEntry: MemoryEntry = {\n id: randomUUID(),\n theme: action.theme,\n title: action.title,\n content: action.content,\n evidence: action.diaryIds,\n confidence: Math.min(1, action.diaryIds.length * 0.2),\n version: 1,\n promotedToRule: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n\n this.knowledgeStore.create({\n type: 'memory',\n title: action.title,\n content: JSON.stringify(memoryEntry),\n tags: [action.theme],\n });\n\n this.versionStore.append({\n entryId: memoryEntry.id,\n version: 1,\n content: action.content,\n action: 'created',\n timestamp: new Date().toISOString(),\n });\n\n logger.info('Created new memory', { id: memoryEntry.id, theme: action.theme, title: action.title });\n }\n\n /** 合并新证据到已有 memory */\n private mergeMemory(\n action: Extract<MemoryDistillAction, { type: 'MERGE' }>,\n existingMemories: MemoryEntry[],\n ): void {\n const existing = existingMemories.find(m => m.id === action.memoryId);\n if (!existing) {\n logger.warn('Cannot merge: memory not found', { memoryId: action.memoryId });\n return;\n }\n\n // 更新 memory 数据\n existing.evidence = [...new Set([...existing.evidence, ...action.newEvidence])];\n existing.confidence = Math.min(1, existing.evidence.length * 0.2);\n if (action.updatedContent) {\n existing.content = action.updatedContent;\n }\n existing.version++;\n existing.updatedAt = new Date().toISOString();\n\n // 通过 KnowledgeStore 更新(查找对应的 knowledge entry)\n const knEntries = this.knowledgeStore.list('memory');\n for (const meta of knEntries) {\n const full = this.knowledgeStore.get(meta.id);\n if (!full) continue;\n try {\n const parsed = JSON.parse(full.content) as MemoryEntry;\n if (parsed.id === action.memoryId) {\n this.knowledgeStore.update(meta.id, {\n content: JSON.stringify(existing),\n });\n break;\n }\n } catch { /* skip */ }\n }\n\n this.versionStore.append({\n entryId: existing.id,\n version: existing.version,\n content: existing.content,\n action: 'merged',\n reason: `Merged ${action.newEvidence.length} new evidence(s)`,\n timestamp: new Date().toISOString(),\n });\n\n logger.info('Merged memory', { id: existing.id, newEvidence: action.newEvidence.length });\n }\n\n /** 用新 memory 替代旧 memory */\n private supersedeMemory(\n action: Extract<MemoryDistillAction, { type: 'SUPERSEDE' }>,\n existingMemories: MemoryEntry[],\n ): void {\n const oldMemory = existingMemories.find(m => m.id === action.oldMemoryId);\n\n // 记录旧版本\n if (oldMemory) {\n this.versionStore.append({\n entryId: oldMemory.id,\n version: oldMemory.version,\n content: oldMemory.content,\n action: 'superseded',\n reason: 'Superseded by new memory',\n timestamp: new Date().toISOString(),\n });\n }\n\n // 创建新 memory\n const newMemory: MemoryEntry = {\n id: randomUUID(),\n theme: action.theme,\n title: action.title,\n content: action.content,\n evidence: action.diaryIds,\n confidence: Math.min(1, action.diaryIds.length * 0.2),\n version: 1,\n supersedes: action.oldMemoryId,\n promotedToRule: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n\n this.knowledgeStore.create({\n type: 'memory',\n title: action.title,\n content: JSON.stringify(newMemory),\n tags: [action.theme, 'supersedes:' + action.oldMemoryId],\n });\n\n this.versionStore.append({\n entryId: newMemory.id,\n version: 1,\n content: action.content,\n action: 'created',\n reason: `Supersedes ${action.oldMemoryId}`,\n timestamp: new Date().toISOString(),\n });\n\n logger.info('Superseded memory', {\n oldId: action.oldMemoryId,\n newId: newMemory.id,\n theme: action.theme,\n });\n }\n}\n","/**\n * 记忆蒸馏 prompt — Layer 2: 从日记批次中提取共性模式。\n */\nimport type { DiaryEntry, MemoryEntry } from '../types.js';\n\nexport function buildMemoryDistillPrompt(\n diaries: DiaryEntry[],\n existingMemories: MemoryEntry[],\n): string {\n const diarySection = diaries.map((d, i) => {\n const lines = [\n `### 日记 ${i + 1} (ID: ${d.id})`,\n `- Issue: #${d.issueIid} — ${d.issueTitle}`,\n `- 结果: ${d.outcome}`,\n `- 流水线: ${d.pipelineMode}`,\n `- 总耗时: ${Math.round(d.timing.totalDurationMs / 1000 / 60)}分钟`,\n ];\n if (d.timing.phaseTimings.length > 0) {\n lines.push('- 各阶段耗时:');\n for (const pt of d.timing.phaseTimings) {\n lines.push(` - ${pt.phase}: ${Math.round(pt.durationMs / 1000 / 60)}分钟`);\n }\n }\n if (d.failure) {\n lines.push(`- 失败阶段: ${d.failure.failedAtPhase}`);\n lines.push(`- 失败原因: ${d.failure.error}`);\n lines.push(`- 尝试次数: ${d.failure.attempts}`);\n }\n if (d.humanInterventions.length > 0) {\n lines.push('- 人工介入:');\n for (const h of d.humanInterventions) {\n lines.push(` - ${h.type}: ${h.detail}`);\n }\n }\n if (d.artifactSummary) {\n lines.push(`- 产物摘要: ${d.artifactSummary}`);\n }\n return lines.join('\\n');\n }).join('\\n\\n');\n\n const memorySection = existingMemories.length > 0\n ? existingMemories.map((m, i) => {\n return [\n `### 现有记忆 ${i + 1} (ID: ${m.id})`,\n `- 主题: ${m.theme}`,\n `- 标题: ${m.title}`,\n `- 信心度: ${m.confidence}`,\n `- 证据数: ${m.evidence.length}`,\n `- 内容摘要: ${m.content.slice(0, 200)}${m.content.length > 200 ? '...' : ''}`,\n ].join('\\n');\n }).join('\\n\\n')\n : '(暂无现有记忆)';\n\n return `你是经验分析专家。请分析以下 Issue 执行日记,识别共性模式,并输出结构化的操作指令。\n\n## 待分析的日记\n\n${diarySection}\n\n## 现有记忆库\n\n${memorySection}\n\n## 分析维度\n\n请从以下四个维度分析日记:\n1. **failure-pattern** — 失败模式与解法:哪些类型的错误频繁出现?是否有共同的根因?\n2. **efficiency-insight** — 执行效率洞察:哪些阶段耗时异常?有哪些性能瓶颈?\n3. **intervention-pattern** — 人工介入模式:什么情况下需要人工介入?能否自动化?\n4. **optimization-suggestion** — 流程优化建议:结合业界最佳实践,有哪些改进方向?\n\n## 输出格式\n\n请严格按以下 JSON 格式输出操作数组,不要添加任何其他文字:\n\n\\`\\`\\`json\n{\n \"actions\": [\n {\n \"type\": \"CREATE\",\n \"theme\": \"failure-pattern|efficiency-insight|intervention-pattern|optimization-suggestion\",\n \"title\": \"简短标题\",\n \"content\": \"Markdown 格式的详细描述,包括:现象、原因分析、建议解法\",\n \"diaryIds\": [\"关联的日记ID\"]\n },\n {\n \"type\": \"MERGE\",\n \"memoryId\": \"已有 memory 的 ID\",\n \"newEvidence\": [\"新增的日记ID\"],\n \"updatedContent\": \"如果内容需要更新,提供新内容(可选)\"\n },\n {\n \"type\": \"SUPERSEDE\",\n \"oldMemoryId\": \"被替代的旧 memory ID\",\n \"theme\": \"新主题分类\",\n \"title\": \"新标题\",\n \"content\": \"新的完整内容\",\n \"diaryIds\": [\"关联的日记ID\"]\n }\n ]\n}\n\\`\\`\\`\n\n## 规则\n- 如果新日记提供了新的证据支持已有记忆,使用 MERGE\n- 如果新日记推翻了旧的认知,使用 SUPERSEDE\n- 只有确实发现新模式时才使用 CREATE\n- 每个 action 必须关联至少一个日记 ID\n- confidence 由系统自动计算,无需在输出中提供`;\n}\n","/**\n * AgentRuleDistiller — Layer 3: 从成熟 memory 提取可执行的 Agent 规则。\n *\n * 筛选满足条件的 memory,通过 AI 判断哪些可以升级为 MDC 规则,\n * 并同步到 .cursor/rules/ 目录。\n */\nimport { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\nimport type { AIRunner } from '../ai-runner/AIRunner.js';\nimport type { KnowledgeStore } from '../knowledge/KnowledgeStore.js';\nimport type { VersionStore } from './VersionStore.js';\nimport type { MemoryEntry, AgentRuleEntry, RuleDistillAction } from './types.js';\nimport { buildRuleDistillPrompt } from './prompts/rule-distill.js';\nimport { resolveDataDir, ensureDir } from '../paths.js';\n\nconst logger = rootLogger.child('AgentRuleDistiller');\n\nexport interface AgentRuleDistillerDeps {\n aiRunner: AIRunner;\n knowledgeStore: KnowledgeStore;\n versionStore: VersionStore;\n workDir: string;\n timeoutMs: number;\n confidenceThreshold: number;\n /** .cursor/rules/ 目录路径(可选,默认基于 workDir) */\n rulesDir?: string;\n /** 是否同步规则文件到目标项目 */\n syncToProject?: boolean;\n /** 同步目标路径,默认 {workDir}/.cursor/rules */\n projectRulesDir?: string;\n}\n\nexport class AgentRuleDistiller {\n private aiRunner: AIRunner;\n private knowledgeStore: KnowledgeStore;\n private versionStore: VersionStore;\n private workDir: string;\n private timeoutMs: number;\n private confidenceThreshold: number;\n private rulesDir: string;\n private syncToProject: boolean;\n private projectRulesDir: string;\n\n constructor(deps: AgentRuleDistillerDeps) {\n this.aiRunner = deps.aiRunner;\n this.knowledgeStore = deps.knowledgeStore;\n this.versionStore = deps.versionStore;\n this.workDir = deps.workDir;\n this.timeoutMs = deps.timeoutMs;\n this.confidenceThreshold = deps.confidenceThreshold;\n this.rulesDir = deps.rulesDir ?? path.join(resolveDataDir(), 'rules');\n this.syncToProject = deps.syncToProject ?? false;\n this.projectRulesDir = deps.projectRulesDir ?? path.join(deps.workDir, '.cursor', 'rules');\n }\n\n /**\n * 执行规则蒸馏。\n * @returns 处理的 memory 数和创建/更新的 rule 数。\n */\n async distill(): Promise<{ processedMemories: number; actions: number }> {\n // 筛选成熟的 memory\n const matureMemories = this.getMatureMemories();\n if (matureMemories.length === 0) {\n logger.info('No mature memories ready for rule distillation');\n return { processedMemories: 0, actions: 0 };\n }\n\n // 获取现有 rules\n const existingRules = this.loadExistingRules();\n\n logger.info('Starting rule distillation', {\n matureMemories: matureMemories.length,\n existingRules: existingRules.length,\n });\n\n // 构建 prompt\n const prompt = buildRuleDistillPrompt(matureMemories, existingRules);\n\n // 调用 AI\n const result = await this.aiRunner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.timeoutMs,\n });\n\n if (!result.success) {\n logger.error('AI rule distillation failed', { output: result.output.slice(0, 500) });\n throw new Error(`Rule distillation AI call failed: ${result.output.slice(0, 200)}`);\n }\n\n // 解析 actions\n const actions = this.parseActions(result.output);\n if (actions.length === 0) {\n logger.info('No rule distillation actions returned by AI');\n return { processedMemories: matureMemories.length, actions: 0 };\n }\n\n // 执行 actions\n let actionCount = 0;\n for (const action of actions) {\n try {\n this.executeAction(action, existingRules);\n actionCount++;\n } catch (err) {\n logger.warn('Failed to execute rule distill action', {\n action: action.type,\n error: (err as Error).message,\n });\n }\n }\n\n logger.info('Rule distillation complete', {\n processedMemories: matureMemories.length,\n actions: actionCount,\n });\n\n return { processedMemories: matureMemories.length, actions: actionCount };\n }\n\n /** 筛选成熟的 memory:confidence >= threshold, 未被 superseded, 未提升为 rule */\n private getMatureMemories(): MemoryEntry[] {\n const entries = this.knowledgeStore.list('memory');\n const memories: MemoryEntry[] = [];\n\n for (const meta of entries) {\n const full = this.knowledgeStore.get(meta.id);\n if (!full) continue;\n try {\n const memory = JSON.parse(full.content) as MemoryEntry;\n if (\n memory.confidence >= this.confidenceThreshold &&\n !memory.promotedToRule &&\n !memory.supersedes // 不处理已经 supersede 别人的(这些是最新的,但我们检查它们是否未被 superseded)\n ) {\n // 检查是否被其他 memory superseded\n const isSuperseded = entries.some(e => {\n if (e.id === meta.id) return false;\n const f = this.knowledgeStore.get(e.id);\n if (!f) return false;\n try {\n const m = JSON.parse(f.content) as MemoryEntry;\n return m.supersedes === memory.id;\n } catch { return false; }\n });\n if (!isSuperseded) {\n memories.push(memory);\n }\n }\n } catch { /* skip */ }\n }\n\n return memories;\n }\n\n /** 加载现有 agent-rule 条目 */\n private loadExistingRules(): AgentRuleEntry[] {\n const entries = this.knowledgeStore.list('agent-rule');\n return entries.map(meta => {\n const full = this.knowledgeStore.get(meta.id);\n if (!full) return null;\n try {\n return JSON.parse(full.content) as AgentRuleEntry;\n } catch { return null; }\n }).filter((r): r is AgentRuleEntry => r !== null);\n }\n\n /** 解析 AI 输出 */\n private parseActions(output: string): RuleDistillAction[] {\n try {\n const jsonMatch = output.match(/```json\\s*([\\s\\S]*?)```/) ?? output.match(/\\{[\\s\\S]*\"actions\"[\\s\\S]*\\}/);\n if (!jsonMatch) {\n logger.warn('No JSON found in AI rule distill output');\n return [];\n }\n const jsonStr = jsonMatch[1] ?? jsonMatch[0];\n const parsed = JSON.parse(jsonStr) as { actions: RuleDistillAction[] };\n if (!Array.isArray(parsed.actions)) return [];\n return parsed.actions;\n } catch (err) {\n logger.warn('Failed to parse AI rule distill output', {\n error: (err as Error).message,\n });\n return [];\n }\n }\n\n /** 执行单个 action */\n private executeAction(action: RuleDistillAction, existingRules: AgentRuleEntry[]): void {\n switch (action.type) {\n case 'CREATE':\n this.createRule(action);\n break;\n case 'UPDATE':\n this.updateRule(action, existingRules);\n break;\n case 'DEPRECATE':\n this.deprecateRule(action, existingRules);\n break;\n default:\n logger.warn('Unknown rule distill action type', { type: (action as { type: string }).type });\n }\n }\n\n /** 创建新规则 */\n private createRule(action: Extract<RuleDistillAction, { type: 'CREATE' }>): void {\n const ruleEntry: AgentRuleEntry = {\n id: randomUUID(),\n ruleName: action.ruleName,\n title: action.title,\n content: action.content,\n sourceMemoryIds: action.sourceMemoryIds,\n keywords: action.keywords,\n alwaysApply: action.alwaysApply,\n version: 1,\n deprecated: false,\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n\n // 存储到 KnowledgeStore\n this.knowledgeStore.create({\n type: 'agent-rule',\n title: action.title,\n content: JSON.stringify(ruleEntry),\n tags: [...action.keywords, 'rule:' + action.ruleName],\n });\n\n // 同步 MDC 文件\n this.syncMdcFile(ruleEntry);\n\n // 标记来源 memory 为已提升\n this.markMemoriesPromoted(action.sourceMemoryIds);\n\n // 版本记录\n this.versionStore.append({\n entryId: ruleEntry.id,\n version: 1,\n content: action.content,\n action: 'created',\n timestamp: new Date().toISOString(),\n });\n\n logger.info('Created agent rule', { id: ruleEntry.id, ruleName: action.ruleName });\n }\n\n /** 更新已有规则 */\n private updateRule(\n action: Extract<RuleDistillAction, { type: 'UPDATE' }>,\n existingRules: AgentRuleEntry[],\n ): void {\n const existing = existingRules.find(r => r.id === action.ruleId);\n if (!existing) {\n logger.warn('Cannot update: rule not found', { ruleId: action.ruleId });\n return;\n }\n\n existing.content = action.content;\n if (action.keywords) existing.keywords = action.keywords;\n existing.version++;\n existing.updatedAt = new Date().toISOString();\n\n // 更新 KnowledgeStore\n const knEntries = this.knowledgeStore.list('agent-rule');\n for (const meta of knEntries) {\n const full = this.knowledgeStore.get(meta.id);\n if (!full) continue;\n try {\n const parsed = JSON.parse(full.content) as AgentRuleEntry;\n if (parsed.id === action.ruleId) {\n this.knowledgeStore.update(meta.id, {\n content: JSON.stringify(existing),\n });\n break;\n }\n } catch { /* skip */ }\n }\n\n // 同步 MDC 文件\n this.syncMdcFile(existing);\n\n // 版本记录\n this.versionStore.append({\n entryId: existing.id,\n version: existing.version,\n content: action.content,\n action: 'merged',\n timestamp: new Date().toISOString(),\n });\n\n logger.info('Updated agent rule', { id: existing.id, ruleName: existing.ruleName });\n }\n\n /** 废弃规则 */\n private deprecateRule(\n action: Extract<RuleDistillAction, { type: 'DEPRECATE' }>,\n existingRules: AgentRuleEntry[],\n ): void {\n const existing = existingRules.find(r => r.id === action.ruleId);\n if (!existing) {\n logger.warn('Cannot deprecate: rule not found', { ruleId: action.ruleId });\n return;\n }\n\n existing.deprecated = true;\n existing.updatedAt = new Date().toISOString();\n\n // 更新 KnowledgeStore\n const knEntries = this.knowledgeStore.list('agent-rule');\n for (const meta of knEntries) {\n const full = this.knowledgeStore.get(meta.id);\n if (!full) continue;\n try {\n const parsed = JSON.parse(full.content) as AgentRuleEntry;\n if (parsed.id === action.ruleId) {\n this.knowledgeStore.update(meta.id, {\n content: JSON.stringify(existing),\n });\n break;\n }\n } catch { /* skip */ }\n }\n\n // 删除 MDC 文件\n this.removeMdcFile(existing.ruleName);\n\n // 版本记录\n this.versionStore.append({\n entryId: existing.id,\n version: existing.version,\n content: existing.content,\n action: 'deprecated',\n reason: action.reason,\n timestamp: new Date().toISOString(),\n });\n\n logger.info('Deprecated agent rule', { id: existing.id, reason: action.reason });\n }\n\n /** 同步规则到 DATA_DIR/rules/ MDC 文件,可选同步到项目 */\n private syncMdcFile(rule: AgentRuleEntry): void {\n const mdcContent = [\n '---',\n `description: ${rule.title}`,\n `alwaysApply: ${rule.alwaysApply}`,\n '---',\n '',\n rule.content,\n ].join('\\n');\n\n // Write to DATA_DIR/rules/\n try {\n ensureDir(this.rulesDir);\n const filePath = path.join(this.rulesDir, `distilled-${rule.ruleName}.mdc`);\n fs.writeFileSync(filePath, mdcContent, 'utf-8');\n logger.debug('Synced MDC file', { path: filePath });\n } catch (err) {\n logger.warn('Failed to sync MDC file', {\n ruleName: rule.ruleName,\n error: (err as Error).message,\n });\n }\n\n // Optionally sync to project directory\n if (this.syncToProject) {\n try {\n ensureDir(this.projectRulesDir);\n const projectFilePath = path.join(this.projectRulesDir, `distilled-${rule.ruleName}.mdc`);\n fs.writeFileSync(projectFilePath, mdcContent, 'utf-8');\n logger.debug('Synced MDC file to project', { path: projectFilePath });\n } catch (err) {\n logger.warn('Failed to sync MDC file to project', {\n ruleName: rule.ruleName,\n error: (err as Error).message,\n });\n }\n }\n }\n\n /** 删除 MDC 文件(DATA_DIR 和项目目录) */\n private removeMdcFile(ruleName: string): void {\n const fileName = `distilled-${ruleName}.mdc`;\n\n // Remove from DATA_DIR/rules/\n try {\n const filePath = path.join(this.rulesDir, fileName);\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n logger.debug('Removed MDC file', { path: filePath });\n }\n } catch (err) {\n logger.warn('Failed to remove MDC file', {\n ruleName,\n error: (err as Error).message,\n });\n }\n\n // Also remove from project directory if sync is enabled\n if (this.syncToProject) {\n try {\n const projectFilePath = path.join(this.projectRulesDir, fileName);\n if (fs.existsSync(projectFilePath)) {\n fs.unlinkSync(projectFilePath);\n logger.debug('Removed MDC file from project', { path: projectFilePath });\n }\n } catch (err) {\n logger.warn('Failed to remove MDC file from project', {\n ruleName,\n error: (err as Error).message,\n });\n }\n }\n }\n\n /** 标记来源 memory 为已提升为规则 */\n private markMemoriesPromoted(memoryIds: string[]): void {\n const knEntries = this.knowledgeStore.list('memory');\n for (const meta of knEntries) {\n const full = this.knowledgeStore.get(meta.id);\n if (!full) continue;\n try {\n const memory = JSON.parse(full.content) as MemoryEntry;\n if (memoryIds.includes(memory.id) && !memory.promotedToRule) {\n memory.promotedToRule = true;\n memory.updatedAt = new Date().toISOString();\n this.knowledgeStore.update(meta.id, {\n content: JSON.stringify(memory),\n });\n }\n } catch { /* skip */ }\n }\n }\n}\n","/**\n * 规则蒸馏 prompt — Layer 3: 从成熟记忆中提取可执行的 Agent 规则。\n */\nimport type { MemoryEntry, AgentRuleEntry } from '../types.js';\n\nexport function buildRuleDistillPrompt(\n matureMemories: MemoryEntry[],\n existingRules: AgentRuleEntry[],\n): string {\n const memorySection = matureMemories.map((m, i) => {\n return [\n `### 成熟记忆 ${i + 1} (ID: ${m.id})`,\n `- 主题: ${m.theme}`,\n `- 标题: ${m.title}`,\n `- 信心度: ${m.confidence}`,\n `- 证据数: ${m.evidence.length}`,\n `- 已提升为规则: ${m.promotedToRule ? '是' : '否'}`,\n '',\n m.content,\n ].join('\\n');\n }).join('\\n\\n---\\n\\n');\n\n const ruleSection = existingRules.length > 0\n ? existingRules.map((r, i) => {\n return [\n `### 现有规则 ${i + 1} (ID: ${r.id})`,\n `- 规则名: ${r.ruleName}`,\n `- 标题: ${r.title}`,\n `- 关键词: ${r.keywords.join(', ')}`,\n `- 已废弃: ${r.deprecated ? '是' : '否'}`,\n '',\n r.content.slice(0, 300) + (r.content.length > 300 ? '...' : ''),\n ].join('\\n');\n }).join('\\n\\n')\n : '(暂无现有规则)';\n\n return `你是 AI Agent 规范制定专家。请分析以下成熟的经验记忆,判断哪些可以升级为 Agent 开发规则。\n\n## 成熟记忆\n\n${memorySection}\n\n## 现有规则\n\n${ruleSection}\n\n## 任务\n\n1. 评估每条成熟记忆是否适合转化为 Agent 规则\n2. 如果适合,生成 MDC (Markdown Comment) 规则内容\n3. 如果现有规则需要更新(因为有新的记忆支持),输出更新操作\n4. 如果现有规则已经过时(被新记忆推翻),输出废弃操作\n\n## 规则内容格式\n\n规则内容应该是可操作的指导,包含:\n- 问题场景描述\n- 具体的操作步骤或代码规范\n- 必要时附带代码示例\n- 使用中文\n\n## 输出格式\n\n请严格按以下 JSON 格式输出,不要添加任何其他文字:\n\n\\`\\`\\`json\n{\n \"actions\": [\n {\n \"type\": \"CREATE\",\n \"ruleName\": \"kebab-case-rule-name\",\n \"title\": \"规则标题\",\n \"content\": \"MDC 规则的正文内容(Markdown 格式)\",\n \"keywords\": [\"触发关键词\"],\n \"alwaysApply\": false,\n \"sourceMemoryIds\": [\"来源 memory ID\"]\n },\n {\n \"type\": \"UPDATE\",\n \"ruleId\": \"已有 rule 的 ID\",\n \"content\": \"更新后的内容\",\n \"keywords\": [\"更新后的关键词,可选\"]\n },\n {\n \"type\": \"DEPRECATE\",\n \"ruleId\": \"需废弃的 rule ID\",\n \"reason\": \"废弃原因\"\n }\n ]\n}\n\\`\\`\\`\n\n## 判断标准\n- 只有具体、可操作的模式才适合转为规则\n- 过于宽泛的建议(如\"提高代码质量\")不适合作为规则\n- alwaysApply 只对非常通用的规则设为 true\n- ruleName 使用 kebab-case,简短有意义`;\n}\n","/**\n * VectorStore — Layer 4: 知识向量语义搜索。\n *\n * 使用 TF-IDF 伪向量方案实现语义搜索:\n * - 将文本分词 → 构建词频向量\n * - 存储到 JSON 文件(轻量级,无需 native 依赖)\n * - 查询时计算余弦相似度 → 返回 TopK 结果\n *\n * 后续可升级为 better-sqlite3 或本地 transformer 模型。\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\nimport type { VectorSearchResult } from './types.js';\n\nconst logger = rootLogger.child('VectorStore');\n\ninterface StoredVector {\n id: string;\n sourceId: string;\n sourceType: string;\n content: string;\n /** 词频向量:词 → 频率 */\n termFreqs: Record<string, number>;\n updatedAt: string;\n}\n\ninterface VectorData {\n /** 全局文档频率:词 → 出现在多少文档中 */\n documentFreqs: Record<string, number>;\n /** 全部向量条目 */\n vectors: StoredVector[];\n /** 总文档数 */\n totalDocs: number;\n}\n\n// 停用词(中英文常见)\nconst STOP_WORDS = new Set([\n // 英文\n 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',\n 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',\n 'should', 'may', 'might', 'can', 'shall', 'to', 'of', 'in', 'for',\n 'on', 'with', 'at', 'by', 'from', 'as', 'into', 'through', 'during',\n 'before', 'after', 'above', 'below', 'and', 'but', 'or', 'not', 'no',\n 'if', 'then', 'else', 'when', 'up', 'out', 'about', 'it', 'its',\n 'this', 'that', 'these', 'those', 'he', 'she', 'they', 'we', 'you',\n 'i', 'my', 'your', 'our', 'their', 'his', 'her', 'me', 'him', 'us',\n 'them', 'what', 'which', 'who', 'whom', 'how', 'where', 'why',\n // 中文\n '的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都',\n '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会',\n '着', '没有', '看', '好', '自己', '这', '他', '她', '它', '们',\n '那', '被', '把', '让', '以', '所', '而', '但', '对', '从',\n]);\n\nexport class VectorStore {\n private filePath: string;\n private data: VectorData;\n\n constructor(dataDir: string) {\n this.filePath = path.join(dataDir, 'vectors.json');\n this.data = this.load();\n }\n\n /** 索引一个知识条目 */\n async index(entry: { id: string; sourceId: string; sourceType: string; content: string }): Promise<void> {\n // 移除已有的同 sourceId 条目\n this.data.vectors = this.data.vectors.filter(v => v.sourceId !== entry.sourceId);\n\n const termFreqs = this.tokenize(entry.content);\n\n const stored: StoredVector = {\n id: entry.id,\n sourceId: entry.sourceId,\n sourceType: entry.sourceType,\n content: entry.content,\n termFreqs,\n updatedAt: new Date().toISOString(),\n };\n\n this.data.vectors.push(stored);\n this.rebuildDocumentFreqs();\n this.save();\n }\n\n /** 语义搜索 */\n async search(query: string, topK: number = 5): Promise<VectorSearchResult[]> {\n if (this.data.vectors.length === 0) return [];\n\n const queryTerms = this.tokenize(query);\n const queryVec = this.toTfIdfVector(queryTerms);\n\n const scored: Array<{ vector: StoredVector; score: number }> = [];\n\n for (const vector of this.data.vectors) {\n const docVec = this.toTfIdfVector(vector.termFreqs);\n const score = this.cosineSimilarity(queryVec, docVec);\n if (score > 0) {\n scored.push({ vector, score });\n }\n }\n\n scored.sort((a, b) => b.score - a.score);\n\n return scored.slice(0, topK).map(({ vector, score }) => ({\n id: vector.id,\n sourceId: vector.sourceId,\n sourceType: vector.sourceType,\n content: vector.content,\n score,\n }));\n }\n\n /** 移除条目 */\n async remove(sourceId: string): Promise<void> {\n const before = this.data.vectors.length;\n this.data.vectors = this.data.vectors.filter(v => v.sourceId !== sourceId);\n if (this.data.vectors.length < before) {\n this.rebuildDocumentFreqs();\n this.save();\n }\n }\n\n /** 全量重建索引 */\n async reindex(): Promise<void> {\n this.rebuildDocumentFreqs();\n this.save();\n logger.info('Vector index rebuilt', { count: this.data.vectors.length });\n }\n\n /** 获取索引条目数 */\n count(): number {\n return this.data.vectors.length;\n }\n\n /** 文本分词 → 词频统计 */\n private tokenize(text: string): Record<string, number> {\n const freqs: Record<string, number> = {};\n\n // 英文分词:按空格/标点分割,转小写\n const englishTokens = text.toLowerCase()\n .replace(/[^\\w\\u4e00-\\u9fff]/g, ' ')\n .split(/\\s+/)\n .filter(t => t.length > 1 && !STOP_WORDS.has(t));\n\n // 中文分词:简单 bigram + unigram\n const chineseChars = text.replace(/[^\\u4e00-\\u9fff]/g, '');\n const chineseTokens: string[] = [];\n for (let i = 0; i < chineseChars.length; i++) {\n const char = chineseChars[i];\n if (!STOP_WORDS.has(char)) {\n chineseTokens.push(char);\n }\n if (i + 1 < chineseChars.length) {\n const bigram = chineseChars[i] + chineseChars[i + 1];\n chineseTokens.push(bigram);\n }\n }\n\n const allTokens = [...englishTokens, ...chineseTokens];\n for (const token of allTokens) {\n freqs[token] = (freqs[token] || 0) + 1;\n }\n\n return freqs;\n }\n\n /** 词频 → TF-IDF 向量 */\n private toTfIdfVector(termFreqs: Record<string, number>): Map<string, number> {\n const vec = new Map<string, number>();\n const totalTerms = Object.values(termFreqs).reduce((a, b) => a + b, 0);\n if (totalTerms === 0) return vec;\n\n for (const [term, freq] of Object.entries(termFreqs)) {\n const tf = freq / totalTerms;\n const df = this.data.documentFreqs[term] || 1;\n const idf = Math.log(1 + this.data.totalDocs / df);\n vec.set(term, tf * idf);\n }\n\n return vec;\n }\n\n /** 余弦相似度 */\n private cosineSimilarity(a: Map<string, number>, b: Map<string, number>): number {\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n for (const [term, val] of a) {\n normA += val * val;\n const bVal = b.get(term);\n if (bVal !== undefined) {\n dotProduct += val * bVal;\n }\n }\n\n for (const [, val] of b) {\n normB += val * val;\n }\n\n if (normA === 0 || normB === 0) return 0;\n return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));\n }\n\n /** 重建文档频率 */\n private rebuildDocumentFreqs(): void {\n const df: Record<string, number> = {};\n for (const vec of this.data.vectors) {\n for (const term of Object.keys(vec.termFreqs)) {\n df[term] = (df[term] || 0) + 1;\n }\n }\n this.data.documentFreqs = df;\n this.data.totalDocs = this.data.vectors.length;\n }\n\n private load(): VectorData {\n try {\n if (fs.existsSync(this.filePath)) {\n const raw = fs.readFileSync(this.filePath, 'utf-8');\n return JSON.parse(raw) as VectorData;\n }\n } catch (err) {\n logger.warn('Failed to load vector store', { error: (err as Error).message });\n }\n return { documentFreqs: {}, vectors: [], totalDocs: 0 };\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 const tmpPath = path.join(dir, `.vectors-${process.pid}-${Date.now()}.tmp`);\n fs.writeFileSync(tmpPath, JSON.stringify(this.data), 'utf-8');\n fs.renameSync(tmpPath, this.filePath);\n }\n}\n","/**\n * VersionStore — 知识条目版本历史管理。\n *\n * 为 memory 和 agent-rule 条目保留版本历史,支持知识退役追溯。\n * 简单 JSON 文件持久化到 data/distill/versions.json。\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\nimport type { VersionRecord } from './types.js';\n\nconst logger = rootLogger.child('VersionStore');\n\ninterface VersionData {\n records: VersionRecord[];\n}\n\nexport class VersionStore {\n private filePath: string;\n private data: VersionData;\n\n constructor(dataDir: string) {\n this.filePath = path.join(dataDir, 'versions.json');\n this.data = this.load();\n }\n\n /** 追加版本记录 */\n append(record: VersionRecord): void {\n this.data.records.push(record);\n this.save();\n }\n\n /** 按条目 ID 获取版本历史 */\n getByEntryId(entryId: string): VersionRecord[] {\n return this.data.records\n .filter(r => r.entryId === entryId)\n .sort((a, b) => a.version - b.version);\n }\n\n /** 获取所有版本记录 */\n getAll(): VersionRecord[] {\n return [...this.data.records];\n }\n\n /** 获取记录总数 */\n count(): number {\n return this.data.records.length;\n }\n\n private load(): VersionData {\n try {\n if (fs.existsSync(this.filePath)) {\n const raw = fs.readFileSync(this.filePath, 'utf-8');\n return JSON.parse(raw) as VersionData;\n }\n } catch (err) {\n logger.warn('Failed to load version store', { error: (err as Error).message });\n }\n return { records: [] };\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 const tmpPath = path.join(dir, `.versions-${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","/**\n * DistillScheduler — 定时调度蒸馏流水线。\n *\n * 定时执行 Layer 2→3→4 的顺序蒸馏:\n * MemoryDistiller → AgentRuleDistiller → VectorIndexer\n *\n * 支持手动触发(CLI/Webhook)和自动定时触发。\n */\nimport { logger as rootLogger } from '../logger.js';\nimport { eventBus } from '../events/EventBus.js';\nimport type { MemoryDistiller } from './MemoryDistiller.js';\nimport type { AgentRuleDistiller } from './AgentRuleDistiller.js';\nimport type { VectorStore } from './VectorStore.js';\nimport type { DiaryStore } from './DiaryStore.js';\nimport type { KnowledgeStore } from '../knowledge/KnowledgeStore.js';\nimport type { DistillStatus } from './types.js';\n\nconst logger = rootLogger.child('DistillScheduler');\n\nexport interface DistillSchedulerDeps {\n diaryStore: DiaryStore;\n memoryDistiller: MemoryDistiller;\n agentRuleDistiller: AgentRuleDistiller;\n vectorStore: VectorStore;\n knowledgeStore: KnowledgeStore;\n intervalMs: number;\n vectorEnabled: boolean;\n}\n\nexport class DistillScheduler {\n private diaryStore: DiaryStore;\n private memoryDistiller: MemoryDistiller;\n private agentRuleDistiller: AgentRuleDistiller;\n private vectorStore: VectorStore;\n private knowledgeStore: KnowledgeStore;\n private intervalMs: number;\n private vectorEnabled: boolean;\n\n private timer: ReturnType<typeof setInterval> | null = null;\n private running = false;\n private lastRunAt?: string;\n\n constructor(deps: DistillSchedulerDeps) {\n this.diaryStore = deps.diaryStore;\n this.memoryDistiller = deps.memoryDistiller;\n this.agentRuleDistiller = deps.agentRuleDistiller;\n this.vectorStore = deps.vectorStore;\n this.knowledgeStore = deps.knowledgeStore;\n this.intervalMs = deps.intervalMs;\n this.vectorEnabled = deps.vectorEnabled;\n }\n\n /** 启动定时调度 */\n start(): void {\n if (this.timer) return;\n\n this.timer = setInterval(() => {\n this.runDistill().catch(err => {\n logger.error('Scheduled distillation failed', { error: (err as Error).message });\n });\n }, this.intervalMs);\n\n logger.info('DistillScheduler started', { intervalMs: this.intervalMs });\n }\n\n /** 停止定时调度 */\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n logger.info('DistillScheduler stopped');\n }\n }\n\n /** 手动触发蒸馏 */\n async runDistill(options?: { force?: boolean }): Promise<{ memory: { processedDiaries: number; actions: number }; rule: { processedMemories: number; actions: number }; vectorIndexed: number }> {\n if (this.running) {\n logger.info('Distillation already in progress, skipping');\n return { memory: { processedDiaries: 0, actions: 0 }, rule: { processedMemories: 0, actions: 0 }, vectorIndexed: 0 };\n }\n\n this.running = true;\n eventBus.emitTyped('distill:started', {});\n\n try {\n logger.info('Starting distillation pipeline');\n\n // Layer 2: Memory Distillation\n const memoryResult = await this.memoryDistiller.distill({ force: options?.force });\n if (memoryResult.actions > 0) {\n eventBus.emitTyped('distill:memory:updated', {\n processedDiaries: memoryResult.processedDiaries,\n actions: memoryResult.actions,\n });\n }\n\n // Layer 3: Agent Rule Distillation\n const ruleResult = await this.agentRuleDistiller.distill();\n if (ruleResult.actions > 0) {\n eventBus.emitTyped('distill:rule:generated', {\n processedMemories: ruleResult.processedMemories,\n actions: ruleResult.actions,\n });\n }\n\n // Layer 4: Vector Indexing\n let vectorIndexed = 0;\n if (this.vectorEnabled) {\n vectorIndexed = await this.indexAllKnowledge();\n }\n\n this.lastRunAt = new Date().toISOString();\n eventBus.emitTyped('distill:completed', {\n memory: memoryResult,\n rule: ruleResult,\n vectorIndexed,\n });\n\n logger.info('Distillation pipeline complete', {\n memoryActions: memoryResult.actions,\n ruleActions: ruleResult.actions,\n vectorIndexed,\n });\n\n return { memory: memoryResult, rule: ruleResult, vectorIndexed };\n } catch (err) {\n eventBus.emitTyped('distill:failed', { error: (err as Error).message });\n throw err;\n } finally {\n this.running = false;\n }\n }\n\n /** 获取蒸馏状态 */\n getStatus(): DistillStatus {\n return {\n enabled: true,\n lastRunAt: this.lastRunAt,\n nextRunAt: this.timer\n ? new Date(Date.now() + this.intervalMs).toISOString()\n : undefined,\n diaryCount: this.diaryStore.count(),\n undistilledDiaryCount: this.diaryStore.undistilledCount(),\n memoryCount: this.knowledgeStore.list('memory').length,\n ruleCount: this.knowledgeStore.list('agent-rule').length,\n vectorCount: this.vectorStore.count(),\n };\n }\n\n /** 将所有知识条目索引到向量库 */\n private async indexAllKnowledge(): Promise<number> {\n let indexed = 0;\n\n // 索引所有 KnowledgeStore 条目\n const entries = this.knowledgeStore.getAllEntries();\n for (const entry of entries) {\n // 对于 memory 和 agent-rule,解析内部 JSON 取实际内容\n let content = entry.content;\n if (entry.type === 'memory' || entry.type === 'agent-rule') {\n try {\n const parsed = JSON.parse(entry.content) as { content?: string; title?: string };\n content = `${parsed.title ?? entry.title}\\n\\n${parsed.content ?? ''}`;\n } catch { /* use raw content */ }\n }\n\n await this.vectorStore.index({\n id: `kn-${entry.id}`,\n sourceId: entry.id,\n sourceType: entry.type,\n content: `${entry.title}\\n\\n${content}`,\n });\n indexed++;\n }\n\n // 索引日记\n const diaries = this.diaryStore.getAll();\n for (const diary of diaries) {\n const content = [\n `Issue #${diary.issueIid}: ${diary.issueTitle}`,\n `结果: ${diary.outcome}`,\n `流水线: ${diary.pipelineMode}`,\n diary.failure ? `失败阶段: ${diary.failure.failedAtPhase}, 错误: ${diary.failure.error}` : '',\n diary.artifactSummary ?? '',\n ].filter(Boolean).join('\\n');\n\n await this.vectorStore.index({\n id: `diary-${diary.id}`,\n sourceId: diary.id,\n sourceType: 'diary',\n content,\n });\n indexed++;\n }\n\n logger.info('Vector indexing complete', { indexed });\n return indexed;\n }\n}\n","/**\n * PreviewReaper -- TTL-based automatic stop for preview servers.\n *\n * Periodically scans the tracker for completed/failed issues with expired\n * preview environments and stops their dev servers. Worktrees are preserved\n * so users can restart previews or inspect code until they mark the issue\n * as deployed.\n */\nimport { logger as rootLogger } from '../logger.js';\nimport { eventBus as defaultEventBus } from '../events/EventBus.js';\nimport { isShuttingDown } from '../shutdown/ShutdownSignal.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { getIid } from '../tracker/IssueRecordHelper.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\nimport type { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport type { EventBus } from '../events/EventBus.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('PreviewReaper');\n\nconst TERMINAL_STATES = new Set<string>([IssueState.Completed, IssueState.Failed, IssueState.Deployed]);\n\nexport interface PreviewReaperDeps {\n tracker: IssueTracker;\n orchestrator: PipelineOrchestrator;\n intervalMs: number;\n ttlMs: number;\n eventBus?: EventBus;\n}\n\nexport interface ReapResult {\n reaped: number;\n iids: number[];\n}\n\nexport interface PreviewReaperStatus {\n running: boolean;\n lastScanAt?: string;\n totalReaped: number;\n intervalMs: number;\n ttlMs: number;\n}\n\nexport class PreviewReaper {\n private tracker: IssueTracker;\n private orchestrator: PipelineOrchestrator;\n private intervalMs: number;\n private ttlMs: number;\n private bus: EventBus;\n\n private timer: ReturnType<typeof setInterval> | null = null;\n private running = false;\n private lastScanAt?: string;\n private totalReaped = 0;\n\n constructor(deps: PreviewReaperDeps) {\n this.tracker = deps.tracker;\n this.orchestrator = deps.orchestrator;\n this.intervalMs = deps.intervalMs;\n this.ttlMs = deps.ttlMs;\n this.bus = deps.eventBus ?? defaultEventBus;\n }\n\n start(): void {\n if (this.timer) return;\n\n this.timer = setInterval(() => {\n this.reap().catch(err => {\n logger.error('Scheduled preview reap failed', { error: (err as Error).message });\n });\n }, this.intervalMs);\n\n logger.info('PreviewReaper started', { intervalMs: this.intervalMs, ttlMs: this.ttlMs });\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n logger.info('PreviewReaper stopped');\n }\n }\n\n async reap(): Promise<ReapResult> {\n if (this.running || isShuttingDown()) {\n return { reaped: 0, iids: [] };\n }\n\n this.running = true;\n const reaped: number[] = [];\n\n try {\n const now = Date.now();\n const records = this.tracker.getAll();\n\n for (const record of records) {\n if (!TERMINAL_STATES.has(record.state)) continue;\n if (!record.previewStartedAt) continue;\n\n const age = now - new Date(record.previewStartedAt).getTime();\n if (age < this.ttlMs) continue;\n\n const iid = getIid(record);\n const hours = Math.round(age / (60 * 60 * 1000));\n\n try {\n this.orchestrator.stopPreviewServers(iid);\n reaped.push(iid);\n logger.info(t('reaper.reaped', { iid, hours }));\n } catch (err) {\n logger.warn('Failed to reap preview', { iid, error: (err as Error).message });\n }\n }\n\n if (reaped.length > 0) {\n logger.info(t('reaper.summary', { count: reaped.length }));\n this.bus.emitTyped('preview:reaped', { iids: reaped, count: reaped.length });\n }\n\n this.lastScanAt = new Date().toISOString();\n this.totalReaped += reaped.length;\n } finally {\n this.running = false;\n }\n\n return { reaped: reaped.length, iids: reaped };\n }\n\n getStatus(): PreviewReaperStatus {\n return {\n running: this.running,\n lastScanAt: this.lastScanAt,\n totalReaped: this.totalReaped,\n intervalMs: this.intervalMs,\n ttlMs: this.ttlMs,\n };\n }\n}\n","/**\n * OrphanBranchManager — manages an orphan branch for knowledge persistence.\n *\n * The orphan branch (`iaf/knowledge` by default) is used purely as a\n * cross-machine propagation mechanism. Runtime reads/writes always go through\n * the global DATA_DIR paths; this manager provides explicit publish / restore\n * operations triggered via Web UI or CLI.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport type { AsyncMutex } from '../utils/AsyncMutex.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst execFileAsync = promisify(execFile);\nconst logger = rootLogger.child('OrphanBranchManager');\n\n/** Metadata stored at the root of the orphan branch. */\nexport interface SyncMetadata {\n lastSyncedAt: string;\n nodeId?: string;\n entriesCount: number;\n version: number;\n}\n\nexport interface OrphanBranchManagerDeps {\n /** Git root directory (main repo). */\n gitRootDir: string;\n /** Shared mutex that serialises mainGit operations. */\n mutex: AsyncMutex;\n /** Orphan branch name (default `iaf/knowledge`). */\n branch?: string;\n /** Whether to include vectors.json when publishing. */\n syncVectors?: boolean;\n}\n\n/**\n * Files (relative to DATA_DIR) that are synced to the orphan branch.\n * Globs are resolved at publish time; `vectors.json` is controlled by config.\n */\nconst SYNC_MANIFEST: readonly string[] = [\n 'knowledge/index.json',\n 'knowledge/knowledge.json',\n 'distill/diaries.json',\n 'distill/versions.json',\n];\n\nconst KNOWLEDGE_ENTRIES_DIR = 'knowledge/entries';\n\n/** Max push-retry attempts when remote has diverged. */\nconst MAX_PUSH_RETRIES = 3;\n\nexport class OrphanBranchManager {\n private readonly branch: string;\n private readonly gitRootDir: string;\n private readonly mutex: AsyncMutex;\n private readonly syncVectors: boolean;\n\n constructor(deps: OrphanBranchManagerDeps) {\n this.branch = deps.branch ?? 'iaf/knowledge';\n this.gitRootDir = deps.gitRootDir;\n this.mutex = deps.mutex;\n this.syncVectors = deps.syncVectors ?? false;\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /** Check whether the orphan branch exists on the remote. */\n async exists(): Promise<boolean> {\n return this.mutex.runExclusive(async () => {\n return this.remoteBranchExists();\n });\n }\n\n /**\n * Publish local DATA_DIR knowledge to the orphan branch.\n *\n * Flow:\n * 1. Create temporary worktree for the orphan branch\n * 2. Copy relevant files from dataDir → worktree\n * 3. Commit & push (with --force-with-lease + retry)\n * 4. Cleanup temporary worktree\n */\n async publish(dataDir: string): Promise<{ commitSha: string }> {\n return this.mutex.runExclusive(async () => {\n const tmpDir = path.join(os.tmpdir(), `iaf-sync-${randomUUID().slice(0, 8)}`);\n\n try {\n // Ensure we have latest remote refs\n await this.git(['fetch', 'origin']);\n\n const branchExists = await this.remoteBranchExists();\n\n if (branchExists) {\n // Checkout existing branch into temporary worktree\n // First ensure local branch tracking is set up\n const localExists = await this.localBranchExists();\n if (!localExists) {\n await this.git(['branch', '--track', this.branch, `origin/${this.branch}`]);\n } else {\n // Reset local branch to remote to avoid divergence\n await this.git(['branch', '-f', this.branch, `origin/${this.branch}`]);\n }\n await this.git(['worktree', 'add', tmpDir, this.branch]);\n } else {\n // Create new orphan branch in a temporary worktree\n await this.git(['worktree', 'add', '--detach', tmpDir]);\n await this.gitIn(tmpDir, ['checkout', '--orphan', this.branch]);\n // Remove any files inherited from the detached HEAD\n await this.gitIn(tmpDir, ['rm', '-rf', '.']);\n }\n\n // Copy files from DATA_DIR to the temporary worktree\n const copied = await this.copyToWorktree(dataDir, tmpDir);\n\n // Write metadata\n const metadata: SyncMetadata = {\n lastSyncedAt: new Date().toISOString(),\n entriesCount: copied,\n version: 1,\n };\n fs.writeFileSync(\n path.join(tmpDir, '.metadata.json'),\n JSON.stringify(metadata, null, 2),\n 'utf-8',\n );\n\n // Stage everything\n await this.gitIn(tmpDir, ['add', '-A']);\n\n // Check if there are changes to commit\n const status = await this.gitIn(tmpDir, ['status', '--porcelain']);\n if (!status.trim()) {\n logger.info('No changes to publish');\n return { commitSha: await this.gitIn(tmpDir, ['rev-parse', 'HEAD']) };\n }\n\n // Commit\n await this.gitIn(tmpDir, [\n 'commit', '--no-verify', '-m',\n `chore: sync knowledge (${new Date().toISOString()})`,\n ]);\n\n const commitSha = await this.gitIn(tmpDir, ['rev-parse', 'HEAD']);\n\n // Push with retry on conflict\n await this.pushWithRetry(tmpDir);\n\n logger.info('Knowledge published to orphan branch', {\n branch: this.branch,\n commitSha: commitSha.slice(0, 8),\n entriesCount: copied,\n });\n\n return { commitSha: commitSha.trim() };\n } finally {\n // Cleanup temporary worktree\n await this.cleanupWorktree(tmpDir);\n }\n });\n }\n\n /**\n * Restore knowledge from orphan branch to local DATA_DIR.\n *\n * Uses `git show <branch>:<path>` to extract files without a worktree,\n * which is lighter-weight for the restore case.\n */\n async restore(dataDir: string): Promise<{ entriesCount: number }> {\n return this.mutex.runExclusive(async () => {\n await this.git(['fetch', 'origin']);\n\n const branchExists = await this.remoteBranchExists();\n if (!branchExists) {\n throw new Error(`Orphan branch '${this.branch}' does not exist on remote`);\n }\n\n // Ensure local tracking branch is up to date\n const localExists = await this.localBranchExists();\n if (!localExists) {\n await this.git(['branch', '--track', this.branch, `origin/${this.branch}`]);\n } else {\n await this.git(['branch', '-f', this.branch, `origin/${this.branch}`]);\n }\n\n const ref = this.branch;\n let entriesCount = 0;\n\n // Restore files from the manifest\n for (const relPath of SYNC_MANIFEST) {\n const content = await this.showFile(ref, relPath);\n if (content !== null) {\n const dest = path.join(dataDir, relPath);\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.writeFileSync(dest, content, 'utf-8');\n }\n }\n\n // Restore vectors.json if configured\n if (this.syncVectors) {\n const vectorContent = await this.showFile(ref, 'distill/vectors.json');\n if (vectorContent !== null) {\n const dest = path.join(dataDir, 'distill', 'vectors.json');\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.writeFileSync(dest, vectorContent, 'utf-8');\n }\n }\n\n // Restore knowledge entries (*.md files)\n const entriesList = await this.listTreeFiles(ref, KNOWLEDGE_ENTRIES_DIR);\n for (const entryFile of entriesList) {\n const relPath = `${KNOWLEDGE_ENTRIES_DIR}/${entryFile}`;\n const content = await this.showFile(ref, relPath);\n if (content !== null) {\n const dest = path.join(dataDir, relPath);\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.writeFileSync(dest, content, 'utf-8');\n entriesCount++;\n }\n }\n\n // Restore metadata\n const metaContent = await this.showFile(ref, '.metadata.json');\n if (metaContent !== null) {\n try {\n const meta = JSON.parse(metaContent) as SyncMetadata;\n entriesCount = entriesCount || meta.entriesCount;\n } catch { /* ignore parse errors */ }\n }\n\n logger.info('Knowledge restored from orphan branch', {\n branch: this.branch,\n entriesCount,\n });\n\n return { entriesCount };\n });\n }\n\n /** Get sync metadata from the orphan branch (last sync time, counts, etc). */\n async getMetadata(): Promise<SyncMetadata | null> {\n return this.mutex.runExclusive(async () => {\n try {\n await this.git(['fetch', 'origin']);\n } catch {\n // fetch may fail if offline; try to use local branch\n }\n\n const branchExists = await this.remoteBranchExists();\n if (!branchExists) return null;\n\n // Ensure local tracking\n const localExists = await this.localBranchExists();\n if (!localExists) {\n try {\n await this.git(['branch', '--track', this.branch, `origin/${this.branch}`]);\n } catch {\n return null;\n }\n }\n\n const content = await this.showFile(this.branch, '.metadata.json');\n if (!content) return null;\n\n try {\n return JSON.parse(content) as SyncMetadata;\n } catch {\n return null;\n }\n });\n }\n\n // -----------------------------------------------------------------------\n // Private helpers\n // -----------------------------------------------------------------------\n\n private async git(args: string[]): Promise<string> {\n logger.debug('git exec (main)', { args });\n const { stdout } = await execFileAsync('git', args, {\n cwd: this.gitRootDir,\n maxBuffer: 10 * 1024 * 1024,\n env: { ...process.env, HUSKY: '0' },\n });\n return stdout.trim();\n }\n\n private async gitIn(cwd: string, args: string[]): Promise<string> {\n logger.debug('git exec (worktree)', { cwd: path.basename(cwd), args });\n const { stdout } = await execFileAsync('git', args, {\n cwd,\n maxBuffer: 10 * 1024 * 1024,\n env: { ...process.env, HUSKY: '0' },\n });\n return stdout.trim();\n }\n\n private async remoteBranchExists(): Promise<boolean> {\n try {\n await this.git(['ls-remote', '--exit-code', '--heads', 'origin', this.branch]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async localBranchExists(): Promise<boolean> {\n try {\n await this.git(['rev-parse', '--verify', this.branch]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async showFile(ref: string, filePath: string): Promise<string | null> {\n try {\n return await this.git(['show', `${ref}:${filePath}`]);\n } catch {\n return null;\n }\n }\n\n /** List files in a tree path on the orphan branch. */\n private async listTreeFiles(ref: string, treePath: string): Promise<string[]> {\n try {\n const output = await this.git(['ls-tree', '--name-only', `${ref}:${treePath}`]);\n if (!output.trim()) return [];\n return output.split('\\n').filter(Boolean);\n } catch {\n return [];\n }\n }\n\n /**\n * Copy knowledge files from DATA_DIR into the temporary worktree.\n * Returns count of knowledge entry files copied.\n */\n private async copyToWorktree(dataDir: string, wtDir: string): Promise<number> {\n let entriesCount = 0;\n\n // Copy manifest files\n for (const relPath of SYNC_MANIFEST) {\n const src = path.join(dataDir, relPath);\n if (fs.existsSync(src)) {\n const dest = path.join(wtDir, relPath);\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.copyFileSync(src, dest);\n }\n }\n\n // Copy vectors.json if configured\n if (this.syncVectors) {\n const vectorSrc = path.join(dataDir, 'distill', 'vectors.json');\n if (fs.existsSync(vectorSrc)) {\n const dest = path.join(wtDir, 'distill', 'vectors.json');\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n fs.copyFileSync(vectorSrc, dest);\n }\n }\n\n // Copy knowledge entry files\n const entriesSrc = path.join(dataDir, KNOWLEDGE_ENTRIES_DIR);\n if (fs.existsSync(entriesSrc)) {\n const entriesDest = path.join(wtDir, KNOWLEDGE_ENTRIES_DIR);\n fs.mkdirSync(entriesDest, { recursive: true });\n\n const files = fs.readdirSync(entriesSrc);\n for (const file of files) {\n const src = path.join(entriesSrc, file);\n if (fs.statSync(src).isFile()) {\n fs.copyFileSync(src, path.join(entriesDest, file));\n entriesCount++;\n }\n }\n }\n\n return entriesCount;\n }\n\n /**\n * Push with --force-with-lease and retry on conflict.\n * On failure, pull --rebase and try again (up to MAX_PUSH_RETRIES times).\n */\n private async pushWithRetry(wtDir: string): Promise<void> {\n for (let attempt = 1; attempt <= MAX_PUSH_RETRIES; attempt++) {\n try {\n await this.gitIn(wtDir, [\n 'push', '--no-verify', '--force-with-lease',\n '-u', 'origin', this.branch,\n ]);\n return;\n } catch (err) {\n if (attempt >= MAX_PUSH_RETRIES) {\n throw new Error(\n `Failed to push to orphan branch after ${MAX_PUSH_RETRIES} attempts: ${(err as Error).message}`,\n );\n }\n logger.warn('Push failed, pulling and retrying', {\n attempt,\n error: (err as Error).message,\n });\n await this.gitIn(wtDir, ['pull', '--rebase', 'origin', this.branch]);\n }\n }\n }\n\n /** Clean up a temporary worktree, ignoring errors. */\n private async cleanupWorktree(wtDir: string): Promise<void> {\n try {\n await this.git(['worktree', 'remove', wtDir, '--force']);\n } catch {\n // Worktree may not exist if creation failed partway\n logger.debug('Worktree cleanup skipped (may not exist)', { dir: wtDir });\n }\n // Also prune stale entries\n try {\n await this.git(['worktree', 'prune']);\n } catch { /* ignore */ }\n }\n}\n","import { loadConfig } from './config.js';\nimport { setLocale, t } from './i18n/index.js';\nimport { loadKnowledge } from './knowledge/index.js';\nimport { logger } from './logger.js';\nimport { resolveDisplayHost } from './utils/network.js';\nimport { GongfengClient } from './clients/GongfengClient.js';\nimport { GitOperations } from './git/GitOperations.js';\nimport { createAIRunner, validateRunnerRegistry, isRegisteredRunner, getDefaultBinary, isBinaryAvailable } from './ai-runner/index.js';\nimport type { AIRunner } from './ai-runner/index.js';\nimport { IssueTracker } from './tracker/IssueTracker.js';\nimport { SupplementStore } from './supplement/SupplementStore.js';\nimport { PipelineOrchestrator } from './orchestrator/PipelineOrchestrator.js';\nimport { validatePhaseRegistry } from './phases/PhaseFactory.js';\nimport { getAllPipelineDefs, createLifecycleManager } from './pipeline/PipelineDefinition.js';\nimport { IssuePoller } from './poller/IssuePoller.js';\nimport { IssueClaimer } from './coordination/IssueClaimer.js';\nimport { StaleClaimRecovery } from './coordination/StaleClaimRecovery.js';\nimport { resolveNodeId } from './coordination/NodeIdentity.js';\nimport { WebServer } from './web/WebServer.js';\nimport { WebhookServer } from './webhook/WebhookServer.js';\nimport { AgentLogStore } from './web/AgentLogStore.js';\nimport { AutoUpdater } from './updater/AutoUpdater.js';\nimport { AsyncMutex } from './utils/AsyncMutex.js';\nimport { BraindumpOrchestrator } from './braindump/BraindumpOrchestrator.js';\nimport { BraindumpTracker } from './braindump/BraindumpTracker.js';\nimport { setShuttingDown } from './shutdown/ShutdownSignal.js';\nimport { ConfigReloader } from './config/ConfigReloader.js';\nimport { DiaryCollector } from './distill/DiaryCollector.js';\nimport { DiaryStore } from './distill/DiaryStore.js';\nimport { MemoryDistiller } from './distill/MemoryDistiller.js';\nimport { AgentRuleDistiller } from './distill/AgentRuleDistiller.js';\nimport { VectorStore } from './distill/VectorStore.js';\nimport { VersionStore } from './distill/VersionStore.js';\nimport { DistillScheduler } from './distill/DistillScheduler.js';\nimport { PreviewReaper } from './deploy/PreviewReaper.js';\nimport { resolveDataDir, ensureDir } from './paths.js';\nimport { OrphanBranchManager } from './storage/OrphanBranchManager.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { loadWorkspaceConfig, buildSingleRepoWorkspace, persistWorkspaceConfig } from './workspace/index.js';\nimport type { WorkspaceConfig } from './workspace/index.js';\nimport { loadTenantsConfig, buildDefaultTenant, TenantRegistry } from './tenant/index.js';\nimport type { TenantDef } from './tenant/index.js';\n\nexport async function main(): Promise<void> {\n logger.info('Issue Auto-Finish service starting...');\n\n const config = loadConfig();\n setLocale(config.locale);\n loadKnowledge(config.knowledge.path);\n\n // Build lifecycle managers from all registered pipeline definitions\n const allDefs = getAllPipelineDefs();\n const lifecycleManagers = new Map(\n allDefs.map(def => [def.mode, createLifecycleManager(def)] as const),\n );\n\n const allAiPhaseNames = [...new Set(\n [...lifecycleManagers.values()].flatMap(lm => lm.getExecutablePhaseNames()),\n )];\n validatePhaseRegistry(allAiPhaseNames);\n validateRunnerRegistry([config.ai.mode]);\n\n // Shared components (used across all tenants)\n const aiRunner = createAIRunner(config.ai);\n\n // E2E 验证阶段专用 Runner(成本更低)\n let e2eAiRunner: AIRunner | undefined;\n const e2eRunnerMode = config.e2e.aiRunnerMode;\n if (e2eRunnerMode && e2eRunnerMode !== config.ai.mode && isRegisteredRunner(e2eRunnerMode)) {\n const e2eBinary = getDefaultBinary(e2eRunnerMode);\n if (await isBinaryAvailable(e2eBinary)) {\n e2eAiRunner = createAIRunner({\n mode: e2eRunnerMode,\n binary: e2eBinary,\n phaseTimeoutMs: config.ai.phaseTimeoutMs,\n nvmNodeVersion: config.ai.nvmNodeVersion,\n model: config.e2e.aiModel ?? config.ai.model,\n });\n logger.info(t('e2e.runnerCreated'), { mode: e2eRunnerMode });\n } else {\n logger.warn(t('e2e.runnerFallback'), { mode: e2eRunnerMode, binary: e2eBinary });\n }\n }\n\n const dataDir = ensureDir(resolveDataDir());\n\n const pidFile = path.join(dataDir, 'iaf.pid');\n fs.writeFileSync(pidFile, String(process.pid), 'utf-8');\n\n const supplementStore = new SupplementStore(dataDir);\n const agentLogStore = new AgentLogStore(dataDir);\n agentLogStore.startListening();\n\n // ---------------------------------------------------------------------------\n // Tenant resolution\n // ---------------------------------------------------------------------------\n const tenantsConfig = loadTenantsConfig(config.tenants.configPath);\n const tenantDefs: TenantDef[] = tenantsConfig\n ? tenantsConfig.tenants\n : [buildDefaultTenant(config)];\n\n logger.info('Tenants resolved', {\n count: tenantDefs.length,\n ids: tenantDefs.map(t => t.id),\n });\n\n const tenantRegistry = new TenantRegistry();\n\n // The default/primary tenant's tracker — used by shared components (WebServer, DiaryCollector, etc.)\n let primaryTracker: IssueTracker | null = null;\n\n // ---------------------------------------------------------------------------\n // Per-tenant component initialization\n // ---------------------------------------------------------------------------\n for (const tenantDef of tenantDefs) {\n const tid = tenantDef.id;\n const isDefault = tid === 'default';\n\n // GongfengClient — per-tenant (different token/projectPath)\n const gongfengConfig = isDefault\n ? config.gongfeng\n : {\n apiUrl: tenantDef.gongfeng.apiUrl,\n privateToken: tenantDef.gongfeng.privateToken,\n projectPath: tenantDef.gongfeng.projectPath,\n };\n const gongfeng = new GongfengClient(gongfengConfig);\n\n // GitOperations — per-tenant (may point to different git root)\n const gitRootDir = tenantDef.overrides?.gitRootDir\n ?? (isDefault ? config.project.gitRootDir : config.project.gitRootDir);\n const git = new GitOperations(gitRootDir);\n\n // Per-tenant git mutex (each tenant's main repo operations are independent)\n const mainGitMutex = new AsyncMutex();\n\n // IssueTracker — per-tenant file (default uses tracker.json, others use tracker-{tid}.json)\n const tracker = new IssueTracker(dataDir, lifecycleManagers, tid);\n if (!primaryTracker) primaryTracker = tracker;\n\n // WorkspaceConfig — per-tenant (always non-null: file → fallback to single-repo)\n const projectForTenant = {\n workDir: tenantDef.overrides?.workDir ?? config.project.workDir,\n gitRootDir,\n baseBranch: tenantDef.overrides?.baseBranch ?? config.project.baseBranch,\n branchPrefix: tenantDef.overrides?.branchPrefix ?? config.project.branchPrefix,\n projectSubDir: tenantDef.overrides?.projectSubDir ?? config.project.projectSubDir,\n };\n const wsConfigFromFile = tenantDef.workspace\n ? loadWorkspaceConfig(tenantDef.workspace)\n : (isDefault ? loadWorkspaceConfig(config.workspace.configPath) : null);\n let wsConfig: WorkspaceConfig;\n if (wsConfigFromFile) {\n wsConfig = wsConfigFromFile;\n } else {\n const project = isDefault ? config.project : projectForTenant;\n wsConfig = buildSingleRepoWorkspace(project, gongfengConfig.projectPath);\n const wsPath = isDefault\n ? (config.workspace.configPath || path.join(dataDir, 'workspace.json'))\n : path.join(dataDir, `workspace-${tid}.json`);\n persistWorkspaceConfig(wsConfig, wsPath);\n }\n\n // PipelineOrchestrator — per-tenant\n const orchestrator = new PipelineOrchestrator(\n config, gongfeng, git, aiRunner, tracker, supplementStore,\n mainGitMutex, undefined, wsConfig, tid, e2eAiRunner,\n );\n\n // IssueClaimer — per-tenant (different gongfeng client)\n let claimer: IssueClaimer | null = null;\n try {\n const currentUser = await gongfeng.getCurrentUser();\n if (isDefault) {\n logger.info('Current Gongfeng user identified', {\n tenantId: tid,\n username: currentUser.username,\n name: currentUser.name,\n userId: currentUser.id,\n });\n }\n\n const nodeId = config.coordination.nodeId ?? resolveNodeId(dataDir);\n claimer = new IssueClaimer({\n claimUser: currentUser.username,\n nodeId,\n gongfeng,\n });\n orchestrator.setClaimer(claimer);\n\n const staleRecovery = new StaleClaimRecovery({ gongfeng, claimer });\n const staleRecovered = await staleRecovery.recover();\n if (staleRecovered > 0) {\n logger.info('Crash-residue locks cleaned on startup', { tenantId: tid, count: staleRecovered });\n }\n } catch (err) {\n logger.warn('Failed to get current Gongfeng user — multi-node claiming disabled', {\n tenantId: tid,\n error: (err as Error).message,\n });\n }\n\n // IssuePoller — per-tenant\n const poller = new IssuePoller(config, gongfeng, tracker, orchestrator, claimer, tid);\n\n // Startup recovery — per-tenant tracker\n const recoveredCount = tracker.recoverInterruptedIssues();\n if (recoveredCount > 0) {\n logger.info('Recovered interrupted issues on startup', { tenantId: tid, count: recoveredCount });\n }\n await orchestrator.cleanupStaleState();\n\n tenantRegistry.register({\n def: tenantDef,\n gongfeng,\n mainGit: git,\n mainGitMutex,\n orchestrator,\n poller,\n wsConfig: wsConfig!,\n claimer,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Shared infrastructure (unchanged, uses default/primary tenant for legacy deps)\n // ---------------------------------------------------------------------------\n const allTenants = tenantRegistry.getAll();\n const primaryTenant = allTenants[0]!;\n\n // OrphanBranchManager uses the first/default tenant's git\n const orphanManager = new OrphanBranchManager({\n gitRootDir: config.project.gitRootDir,\n mutex: primaryTenant.mainGitMutex,\n branch: config.knowledge.orphanBranch,\n syncVectors: config.knowledge.syncVectors,\n });\n\n // Auto-restore knowledge from orphan branch\n if (config.knowledge.autoRestore) {\n const knowledgeIndexPath = path.join(dataDir, 'knowledge', 'index.json');\n const isKnowledgeEmpty = !fs.existsSync(knowledgeIndexPath);\n\n if (isKnowledgeEmpty) {\n const projectKnowledgeDir = path.join(config.project.workDir, 'data', 'knowledge');\n const projectKnowledgeIndex = path.join(projectKnowledgeDir, 'index.json');\n if (fs.existsSync(projectKnowledgeIndex)) {\n try {\n migrateKnowledgeDir(projectKnowledgeDir, ensureDir(path.join(dataDir, 'knowledge')));\n logger.info('Migrated knowledge from project workDir to global DATA_DIR', {\n src: projectKnowledgeDir,\n });\n } catch (err) {\n logger.warn('Failed to migrate knowledge from project workDir', {\n error: (err as Error).message,\n });\n }\n }\n }\n\n const isStillEmpty = !fs.existsSync(path.join(dataDir, 'knowledge', 'index.json'));\n if (isStillEmpty) {\n try {\n const branchExists = await orphanManager.exists();\n if (branchExists) {\n logger.info('Global knowledge empty, restoring from orphan branch...');\n const result = await orphanManager.restore(dataDir);\n logger.info('Knowledge restored from orphan branch', { entriesCount: result.entriesCount });\n }\n } catch (err) {\n logger.warn('Failed to auto-restore knowledge from orphan branch', {\n error: (err as Error).message,\n });\n }\n }\n }\n\n // Braindump — uses primary tenant's git\n const braindumpTracker = new BraindumpTracker(dataDir);\n const braindumpOrchestrator = new BraindumpOrchestrator(\n config, primaryTenant.mainGit, primaryTenant.mainGitMutex, aiRunner, braindumpTracker,\n );\n\n // Config hot-reloader — pauses/resumes all pollers\n const configReloader = new ConfigReloader(config, primaryTenant.poller, primaryTenant.orchestrator, primaryTenant.gongfeng, {\n onAIRunnerChanged: (runner) => {\n braindumpOrchestrator.setAIRunner(runner);\n for (const t of allTenants) {\n t.orchestrator.setAIRunner(runner);\n }\n },\n });\n\n // AutoUpdater — pauses/resumes primary poller (all pollers would need Phase 2 support)\n const autoUpdater = new AutoUpdater(config, primaryTenant.poller);\n\n // Distill (knowledge distillation)\n const distillDataDir = path.join(dataDir, 'distill');\n if (!fs.existsSync(distillDataDir)) {\n fs.mkdirSync(distillDataDir, { recursive: true });\n }\n\n const diaryStore = new DiaryStore(distillDataDir);\n const versionStore = new VersionStore(distillDataDir);\n const vectorStore = new VectorStore(distillDataDir);\n\n const { KnowledgeStore } = await import('./knowledge/KnowledgeStore.js');\n const knowledgeDataDir = path.join(dataDir, 'knowledge');\n const knowledgeStore = new KnowledgeStore(knowledgeDataDir);\n\n const diaryCollector = new DiaryCollector({\n tracker: primaryTracker!,\n diaryStore,\n });\n\n const memoryDistiller = new MemoryDistiller({\n aiRunner,\n diaryStore,\n knowledgeStore,\n versionStore,\n workDir: config.project.workDir,\n timeoutMs: config.ai.phaseTimeoutMs,\n minDiariesForDistill: config.distill.minDiariesForDistill,\n });\n\n const agentRuleDistiller = new AgentRuleDistiller({\n aiRunner,\n knowledgeStore,\n versionStore,\n workDir: config.project.workDir,\n timeoutMs: config.ai.phaseTimeoutMs,\n confidenceThreshold: config.distill.memoryConfidenceThreshold,\n syncToProject: config.sync.rulesToProject,\n });\n\n const distillScheduler = new DistillScheduler({\n diaryStore,\n memoryDistiller,\n agentRuleDistiller,\n vectorStore,\n knowledgeStore,\n intervalMs: config.distill.intervalMs,\n vectorEnabled: config.distill.vectorEnabled,\n });\n\n if (config.distill.enabled) {\n diaryCollector.start();\n distillScheduler.start();\n logger.info('Knowledge distillation pipeline initialized');\n }\n\n // Preview TTL reaper\n const previewReaper = new PreviewReaper({\n tracker: primaryTracker!,\n orchestrator: primaryTenant.orchestrator,\n intervalMs: config.preview.reapIntervalMs,\n ttlMs: config.preview.ttlMs,\n });\n\n // WebServer — uses primary tenant components for backward compat\n let webServer: WebServer | null = null;\n if (config.web.enabled) {\n webServer = new WebServer({\n tracker: primaryTracker!,\n config,\n agentLogStore,\n orchestrator: primaryTenant.orchestrator,\n gongfeng: primaryTenant.gongfeng,\n supplementStore,\n mainGit: primaryTenant.mainGit,\n autoUpdater,\n poller: primaryTenant.poller,\n braindumpOrchestrator,\n distillScheduler,\n diaryStore,\n vectorStore,\n diaryCollector,\n claimer: primaryTenant.claimer,\n configReloader,\n orphanManager,\n wsConfig: primaryTenant.wsConfig,\n previewReaper,\n });\n await webServer.start();\n }\n\n // WebhookServer — uses primary tenant\n let webhookServer: WebhookServer | null = null;\n if (config.webhook.enabled) {\n webhookServer = new WebhookServer({\n tracker: primaryTracker!,\n config,\n orchestrator: primaryTenant.orchestrator,\n gongfeng: primaryTenant.gongfeng,\n supplementStore,\n poller: primaryTenant.poller,\n claimer: primaryTenant.claimer,\n });\n await webhookServer.start();\n }\n\n // Braindump recovery\n const braindumpRecovered = braindumpOrchestrator.recoverInterrupted();\n if (braindumpRecovered > 0) {\n logger.info('Recovered interrupted braindump batches on startup', { count: braindumpRecovered });\n }\n\n // ---------------------------------------------------------------------------\n // Graceful shutdown — handles all tenants\n // ---------------------------------------------------------------------------\n let shutdownInProgress = false;\n const shutdown = async (): Promise<void> => {\n if (shutdownInProgress) return;\n shutdownInProgress = true;\n\n logger.info('Graceful shutdown initiated');\n\n setShuttingDown();\n autoUpdater.stop();\n previewReaper.stop();\n distillScheduler.stop();\n diaryCollector.stop();\n\n // Stop all pollers\n for (const t of allTenants) {\n t.poller.stop();\n }\n\n aiRunner.killAll();\n e2eAiRunner?.killAll();\n\n // Stop all dev servers\n for (const t of allTenants) {\n t.orchestrator.getDevServerManager().stopAll();\n }\n\n // Drain all pollers\n const drainStart = Date.now();\n const DRAIN_TIMEOUT_MS = 5_000;\n const totalActive = () => allTenants.reduce((sum, t) => sum + t.poller.getActiveCount(), 0);\n while (totalActive() > 0 && Date.now() - drainStart < DRAIN_TIMEOUT_MS) {\n logger.info('Waiting for active issues to drain...', { active: totalActive() });\n await new Promise(resolve => setTimeout(resolve, 500));\n }\n if (totalActive() > 0) {\n logger.warn('Drain timeout reached, proceeding with shutdown', { active: totalActive() });\n }\n\n webServer?.stop();\n webhookServer?.stop();\n\n try { fs.unlinkSync(pidFile); } catch { /* ignore */ }\n\n logger.info('Graceful shutdown complete');\n process.exit(0);\n };\n\n process.on('SIGINT', () => { shutdown(); });\n process.on('SIGTERM', () => { shutdown(); });\n\n // ---------------------------------------------------------------------------\n // Start all pollers in parallel\n // ---------------------------------------------------------------------------\n for (const t of allTenants) {\n t.poller.start();\n }\n autoUpdater.start();\n\n // Start preview reaper (scan once on startup for crash recovery, then periodic)\n previewReaper.reap().catch(err => {\n logger.warn('Startup preview reap failed', { error: (err as Error).message });\n });\n previewReaper.start();\n\n logger.info('Issue Auto-Finish service started', {\n tenants: tenantDefs.map(t => t.id),\n tenantCount: tenantDefs.length,\n discoveryIntervalMs: config.poll.discoveryIntervalMs,\n driveIntervalMs: config.poll.driveIntervalMs,\n webUI: config.web.enabled ? `http://${resolveDisplayHost(config.web.host)}:${config.web.port}` : 'disabled',\n webhook: config.webhook.enabled ? `http://${resolveDisplayHost(config.webhook.host)}:${config.webhook.port}/webhook/gongfeng` : 'disabled',\n });\n}\n\n/**\n * Migrate knowledge data from a project-local directory to the global DATA_DIR.\n * Copies index.json, entry files, and knowledge.json without overwriting existing files.\n */\nfunction migrateKnowledgeDir(srcDir: string, destDir: string): void {\n const srcIndex = path.join(srcDir, 'index.json');\n const destIndex = path.join(destDir, 'index.json');\n if (fs.existsSync(srcIndex) && !fs.existsSync(destIndex)) {\n fs.copyFileSync(srcIndex, destIndex);\n }\n\n const srcEntries = path.join(srcDir, 'entries');\n if (fs.existsSync(srcEntries)) {\n const destEntries = path.join(destDir, 'entries');\n if (!fs.existsSync(destEntries)) {\n fs.mkdirSync(destEntries, { recursive: true });\n }\n for (const file of fs.readdirSync(srcEntries)) {\n const src = path.join(srcEntries, file);\n const dest = path.join(destEntries, file);\n if (fs.statSync(src).isFile() && !fs.existsSync(dest)) {\n fs.copyFileSync(src, dest);\n }\n }\n }\n\n const srcKnowledge = path.join(srcDir, 'knowledge.json');\n const destKnowledge = path.join(destDir, 'knowledge.json');\n if (fs.existsSync(srcKnowledge) && !fs.existsSync(destKnowledge)) {\n fs.copyFileSync(srcKnowledge, destKnowledge);\n }\n}\n","import { z } from 'zod';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('TenantConfig');\n\n// ---------------------------------------------------------------------------\n// Schema\n// ---------------------------------------------------------------------------\n\nexport const tenantGongfengSchema = z.object({\n apiUrl: z.string().url('apiUrl must be a valid URL'),\n privateToken: z.string().min(1, 'privateToken is required'),\n projectPath: z.string().min(1, 'projectPath is required'),\n});\n\nexport const tenantOverridesSchema = z.object({\n baseBranch: z.string().optional(),\n branchPrefix: z.string().optional(),\n worktreeBaseDir: z.string().optional(),\n projectSubDir: z.string().optional(),\n gitRootDir: z.string().optional(),\n workDir: z.string().optional(),\n}).optional();\n\nexport const tenantDefSchema = z.object({\n id: z.string().min(1, 'Tenant id is required').regex(/^[a-zA-Z0-9_-]+$/, 'Tenant id must be alphanumeric with dashes/underscores'),\n gongfeng: tenantGongfengSchema,\n workspace: z.string().optional(),\n overrides: tenantOverridesSchema,\n});\n\nexport const tenantsConfigSchema = z.object({\n tenants: z.array(tenantDefSchema).min(1, 'At least one tenant is required'),\n});\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type TenantGongfengConfig = z.infer<typeof tenantGongfengSchema>;\nexport type TenantOverrides = z.infer<typeof tenantOverridesSchema>;\nexport type TenantDef = z.infer<typeof tenantDefSchema>;\nexport type TenantsConfig = z.infer<typeof tenantsConfigSchema>;\n\n/** Default tenant ID used when no tenants.json is configured. */\nexport const DEFAULT_TENANT_ID = 'default';\n\n// ---------------------------------------------------------------------------\n// Loader\n// ---------------------------------------------------------------------------\n\n/**\n * Load tenants configuration from a JSON file.\n * Returns null if the path is not provided or the file does not exist.\n */\nexport function loadTenantsConfig(configPath?: string): TenantsConfig | null {\n if (!configPath) return null;\n\n if (!fs.existsSync(configPath)) {\n logger.warn('Tenants config file not found, falling back to single-tenant mode', {\n path: configPath,\n });\n return null;\n }\n\n try {\n const raw = fs.readFileSync(configPath, 'utf-8');\n const json = JSON.parse(raw);\n const result = tenantsConfigSchema.safeParse(json);\n if (!result.success) {\n const issues = result.error.issues\n .map(i => ` - ${i.path.join('.')}: ${i.message}`)\n .join('\\n');\n logger.error(`Tenants config validation failed:\\n${issues}`);\n return null;\n }\n\n // Validate unique IDs\n const ids = result.data.tenants.map(t => t.id);\n const dupes = ids.filter((id, i) => ids.indexOf(id) !== i);\n if (dupes.length > 0) {\n logger.error('Duplicate tenant IDs found', { duplicates: [...new Set(dupes)] });\n return null;\n }\n\n // Resolve relative workspace paths\n const baseDir = path.dirname(configPath);\n for (const tenant of result.data.tenants) {\n if (tenant.workspace && !path.isAbsolute(tenant.workspace)) {\n tenant.workspace = path.resolve(baseDir, tenant.workspace);\n }\n }\n\n logger.info('Tenants config loaded', {\n tenants: result.data.tenants.map(t => t.id),\n });\n return result.data;\n } catch (err) {\n logger.error('Failed to parse tenants config', {\n path: configPath,\n error: (err as Error).message,\n });\n return null;\n }\n}\n\n/**\n * Build a single-tenant config from the existing global .env Config.\n * Used when no tenants.json is configured — preserves backward compatibility.\n */\nexport function buildDefaultTenant(config: {\n gongfeng: { apiUrl: string; privateToken: string; projectPath: string };\n}): TenantDef {\n return {\n id: DEFAULT_TENANT_ID,\n gongfeng: {\n apiUrl: config.gongfeng.apiUrl,\n privateToken: config.gongfeng.privateToken,\n projectPath: config.gongfeng.projectPath,\n },\n };\n}\n","import type { GongfengClient } from '../clients/GongfengClient.js';\nimport type { GitOperations } from '../git/GitOperations.js';\nimport type { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport type { IssuePoller } from '../poller/IssuePoller.js';\nimport type { AsyncMutex } from '../utils/AsyncMutex.js';\nimport type { WorkspaceConfig } from '../workspace/index.js';\nimport type { IssueClaimer } from '../coordination/IssueClaimer.js';\nimport type { TenantDef } from './TenantConfig.js';\n\n/**\n * Runtime container for all per-tenant components.\n */\nexport interface TenantInstance {\n def: TenantDef;\n gongfeng: GongfengClient;\n mainGit: GitOperations;\n mainGitMutex: AsyncMutex;\n orchestrator: PipelineOrchestrator;\n poller: IssuePoller;\n wsConfig: WorkspaceConfig;\n claimer: IssueClaimer | null;\n}\n\n/**\n * Registry holding all tenant instances, indexed by tenant ID.\n */\nexport class TenantRegistry {\n private tenants = new Map<string, TenantInstance>();\n\n register(instance: TenantInstance): void {\n this.tenants.set(instance.def.id, instance);\n }\n\n get(tenantId: string): TenantInstance | undefined {\n return this.tenants.get(tenantId);\n }\n\n getAll(): TenantInstance[] {\n return [...this.tenants.values()];\n }\n\n getAllIds(): string[] {\n return [...this.tenants.keys()];\n }\n\n size(): number {\n return this.tenants.size;\n }\n\n /** Get all pollers (for start/stop). */\n getPollers(): IssuePoller[] {\n return this.getAll().map(t => t.poller);\n }\n\n /** Get all orchestrators (for cleanup/shutdown). */\n getOrchestrators(): PipelineOrchestrator[] {\n return this.getAll().map(t => t.orchestrator);\n }\n\n /** Find which tenant owns a given issue IID (by checking tracker). */\n findTenantByIssueIid(_issueIid: number, _tracker: { get(iid: number): unknown }): TenantInstance | undefined {\n return undefined;\n }\n}\n"],"mappings":"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","names":["logger","logger","logger","logger","AUTO_FINISH_LABEL","fs","path","logger","path","fs","express","fs","path","fileURLToPath","fs","path","logger","path","fs","t","findLockNote","express","Router","express","logger","express","Router","express","logger","sseWriter","express","Router","express","logger","collectStaticInfo","createAIRunner","express","Router","express","logger","express","Router","express","logger","createAIRunner","express","Router","express","logger","createAIRunner","express","Router","express","logger","express","fs","path","Router","express","logger","path","fs","express","Router","express","logger","express","readdir","path","logger","metrics","logger","metrics","logger","metrics","Router","express","logger","readdir","path","metrics","fs","path","readdir","readFile","logger","path","fs","readFile","readdir","path","logger","parseJsonFromOutput","idCounter","nextId","ensureIds","path","logger","content","__dirname","path","fileURLToPath","logger","express","fs","express","express","t","path","fs","logger","fs","path","Router","express","logger","logger","logger","express","fs","path","logger","path","fs","path","fileURLToPath","__dirname","path","fileURLToPath","logger","existsSync","path","fileURLToPath","__dirname","path","fileURLToPath","logger","existsSync","logger","logger","randomUUID","logger","randomUUID","randomUUID","logger","randomUUID","randomUUID","fs","path","logger","path","randomUUID","fs","fs","path","logger","path","t","fs","fs","path","logger","path","fs","logger","logger","fs","path","randomUUID","execFile","execFile","logger","path","randomUUID","fs","path","fs","fs","path","logger","fs","t","path","t","path","fs","t","KnowledgeStore"]}
|