@intrect/openswarm 0.2.0
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/LICENSE +21 -0
- package/README.md +544 -0
- package/config.example.yaml +107 -0
- package/dist/adapters/base.d.ts +8 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +104 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude.d.ts +13 -0
- package/dist/adapters/claude.d.ts.map +1 -0
- package/dist/adapters/claude.js +318 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex.d.ts +14 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +366 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/cryptoQuantAdapter.d.ts +85 -0
- package/dist/adapters/cryptoQuantAdapter.d.ts.map +1 -0
- package/dist/adapters/cryptoQuantAdapter.js +238 -0
- package/dist/adapters/cryptoQuantAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts +17 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +47 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/processRegistry.d.ts +38 -0
- package/dist/adapters/processRegistry.d.ts.map +1 -0
- package/dist/adapters/processRegistry.js +147 -0
- package/dist/adapters/processRegistry.js.map +1 -0
- package/dist/adapters/streamBuffer.d.ts +59 -0
- package/dist/adapters/streamBuffer.d.ts.map +1 -0
- package/dist/adapters/streamBuffer.js +123 -0
- package/dist/adapters/streamBuffer.js.map +1 -0
- package/dist/adapters/types.d.ts +65 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +6 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/agents/agentBus.d.ts +160 -0
- package/dist/agents/agentBus.d.ts.map +1 -0
- package/dist/agents/agentBus.js +350 -0
- package/dist/agents/agentBus.js.map +1 -0
- package/dist/agents/agentPair.d.ts +210 -0
- package/dist/agents/agentPair.d.ts.map +1 -0
- package/dist/agents/agentPair.js +420 -0
- package/dist/agents/agentPair.js.map +1 -0
- package/dist/agents/auditor.d.ts +27 -0
- package/dist/agents/auditor.d.ts.map +1 -0
- package/dist/agents/auditor.js +237 -0
- package/dist/agents/auditor.js.map +1 -0
- package/dist/agents/cliStreamParser.d.ts +18 -0
- package/dist/agents/cliStreamParser.d.ts.map +1 -0
- package/dist/agents/cliStreamParser.js +156 -0
- package/dist/agents/cliStreamParser.js.map +1 -0
- package/dist/agents/documenter.d.ts +31 -0
- package/dist/agents/documenter.d.ts.map +1 -0
- package/dist/agents/documenter.js +285 -0
- package/dist/agents/documenter.js.map +1 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +10 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/pairMetrics.d.ts +63 -0
- package/dist/agents/pairMetrics.d.ts.map +1 -0
- package/dist/agents/pairMetrics.js +231 -0
- package/dist/agents/pairMetrics.js.map +1 -0
- package/dist/agents/pairPipeline.d.ts +155 -0
- package/dist/agents/pairPipeline.d.ts.map +1 -0
- package/dist/agents/pairPipeline.js +793 -0
- package/dist/agents/pairPipeline.js.map +1 -0
- package/dist/agents/pairWebhook.d.ts +59 -0
- package/dist/agents/pairWebhook.d.ts.map +1 -0
- package/dist/agents/pairWebhook.js +242 -0
- package/dist/agents/pairWebhook.js.map +1 -0
- package/dist/agents/pipelineFormat.d.ts +11 -0
- package/dist/agents/pipelineFormat.d.ts.map +1 -0
- package/dist/agents/pipelineFormat.js +164 -0
- package/dist/agents/pipelineFormat.js.map +1 -0
- package/dist/agents/pipelineGuards.d.ts +23 -0
- package/dist/agents/pipelineGuards.d.ts.map +1 -0
- package/dist/agents/pipelineGuards.js +175 -0
- package/dist/agents/pipelineGuards.js.map +1 -0
- package/dist/agents/reviewer.d.ts +37 -0
- package/dist/agents/reviewer.d.ts.map +1 -0
- package/dist/agents/reviewer.js +213 -0
- package/dist/agents/reviewer.js.map +1 -0
- package/dist/agents/skillDocumenter.d.ts +23 -0
- package/dist/agents/skillDocumenter.d.ts.map +1 -0
- package/dist/agents/skillDocumenter.js +218 -0
- package/dist/agents/skillDocumenter.js.map +1 -0
- package/dist/agents/tester.d.ts +37 -0
- package/dist/agents/tester.d.ts.map +1 -0
- package/dist/agents/tester.js +308 -0
- package/dist/agents/tester.js.map +1 -0
- package/dist/agents/worker.d.ts +30 -0
- package/dist/agents/worker.d.ts.map +1 -0
- package/dist/agents/worker.js +128 -0
- package/dist/agents/worker.js.map +1 -0
- package/dist/automation/autonomousRunner.d.ts +123 -0
- package/dist/automation/autonomousRunner.d.ts.map +1 -0
- package/dist/automation/autonomousRunner.js +1082 -0
- package/dist/automation/autonomousRunner.js.map +1 -0
- package/dist/automation/ciWorker.d.ts +51 -0
- package/dist/automation/ciWorker.d.ts.map +1 -0
- package/dist/automation/ciWorker.js +282 -0
- package/dist/automation/ciWorker.js.map +1 -0
- package/dist/automation/conflictResolver.d.ts +29 -0
- package/dist/automation/conflictResolver.d.ts.map +1 -0
- package/dist/automation/conflictResolver.js +261 -0
- package/dist/automation/conflictResolver.js.map +1 -0
- package/dist/automation/dailyReporter.d.ts +26 -0
- package/dist/automation/dailyReporter.d.ts.map +1 -0
- package/dist/automation/dailyReporter.js +132 -0
- package/dist/automation/dailyReporter.js.map +1 -0
- package/dist/automation/index.d.ts +7 -0
- package/dist/automation/index.d.ts.map +1 -0
- package/dist/automation/index.js +7 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/longRunningMonitor.d.ts +26 -0
- package/dist/automation/longRunningMonitor.d.ts.map +1 -0
- package/dist/automation/longRunningMonitor.js +231 -0
- package/dist/automation/longRunningMonitor.js.map +1 -0
- package/dist/automation/prOwnership.d.ts +18 -0
- package/dist/automation/prOwnership.d.ts.map +1 -0
- package/dist/automation/prOwnership.js +61 -0
- package/dist/automation/prOwnership.js.map +1 -0
- package/dist/automation/prProcessor.d.ts +62 -0
- package/dist/automation/prProcessor.d.ts.map +1 -0
- package/dist/automation/prProcessor.js +700 -0
- package/dist/automation/prProcessor.js.map +1 -0
- package/dist/automation/runnerExecution.d.ts +49 -0
- package/dist/automation/runnerExecution.d.ts.map +1 -0
- package/dist/automation/runnerExecution.js +663 -0
- package/dist/automation/runnerExecution.js.map +1 -0
- package/dist/automation/runnerState.d.ts +170 -0
- package/dist/automation/runnerState.d.ts.map +1 -0
- package/dist/automation/runnerState.js +495 -0
- package/dist/automation/runnerState.js.map +1 -0
- package/dist/automation/runnerTypes.d.ts +46 -0
- package/dist/automation/runnerTypes.d.ts.map +1 -0
- package/dist/automation/runnerTypes.js +5 -0
- package/dist/automation/runnerTypes.js.map +1 -0
- package/dist/automation/scheduler.d.ts +75 -0
- package/dist/automation/scheduler.d.ts.map +1 -0
- package/dist/automation/scheduler.js +394 -0
- package/dist/automation/scheduler.js.map +1 -0
- package/dist/cli/promptHandler.d.ts +13 -0
- package/dist/cli/promptHandler.d.ts.map +1 -0
- package/dist/cli/promptHandler.js +189 -0
- package/dist/cli/promptHandler.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +138 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/config.d.ts +308 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +529 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/eventHub.d.ts +194 -0
- package/dist/core/eventHub.d.ts.map +1 -0
- package/dist/core/eventHub.js +136 -0
- package/dist/core/eventHub.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/service.d.ts +27 -0
- package/dist/core/service.d.ts.map +1 -0
- package/dist/core/service.js +438 -0
- package/dist/core/service.js.map +1 -0
- package/dist/core/traceCollector.d.ts +105 -0
- package/dist/core/traceCollector.d.ts.map +1 -0
- package/dist/core/traceCollector.js +141 -0
- package/dist/core/traceCollector.js.map +1 -0
- package/dist/core/types.d.ts +413 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +5 -0
- package/dist/core/types.js.map +1 -0
- package/dist/discord/discordCore.d.ts +104 -0
- package/dist/discord/discordCore.d.ts.map +1 -0
- package/dist/discord/discordCore.js +698 -0
- package/dist/discord/discordCore.js.map +1 -0
- package/dist/discord/discordHandlers.d.ts +86 -0
- package/dist/discord/discordHandlers.d.ts.map +1 -0
- package/dist/discord/discordHandlers.js +849 -0
- package/dist/discord/discordHandlers.js.map +1 -0
- package/dist/discord/discordPair.d.ts +6 -0
- package/dist/discord/discordPair.d.ts.map +1 -0
- package/dist/discord/discordPair.js +567 -0
- package/dist/discord/discordPair.js.map +1 -0
- package/dist/discord/index.d.ts +4 -0
- package/dist/discord/index.d.ts.map +1 -0
- package/dist/discord/index.js +11 -0
- package/dist/discord/index.js.map +1 -0
- package/dist/github/github.d.ts +236 -0
- package/dist/github/github.d.ts.map +1 -0
- package/dist/github/github.js +535 -0
- package/dist/github/github.js.map +1 -0
- package/dist/github/index.d.ts +2 -0
- package/dist/github/index.d.ts.map +1 -0
- package/dist/github/index.js +2 -0
- package/dist/github/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/analyzer.d.ts +36 -0
- package/dist/knowledge/analyzer.d.ts.map +1 -0
- package/dist/knowledge/analyzer.js +170 -0
- package/dist/knowledge/analyzer.js.map +1 -0
- package/dist/knowledge/gitInfo.d.ts +10 -0
- package/dist/knowledge/gitInfo.d.ts.map +1 -0
- package/dist/knowledge/gitInfo.js +134 -0
- package/dist/knowledge/gitInfo.js.map +1 -0
- package/dist/knowledge/graph.d.ts +45 -0
- package/dist/knowledge/graph.d.ts.map +1 -0
- package/dist/knowledge/graph.js +262 -0
- package/dist/knowledge/graph.js.map +1 -0
- package/dist/knowledge/graphqlExporter.d.ts +64 -0
- package/dist/knowledge/graphqlExporter.d.ts.map +1 -0
- package/dist/knowledge/graphqlExporter.js +333 -0
- package/dist/knowledge/graphqlExporter.js.map +1 -0
- package/dist/knowledge/index.d.ts +58 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +212 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/repository.d.ts +64 -0
- package/dist/knowledge/repository.d.ts.map +1 -0
- package/dist/knowledge/repository.js +250 -0
- package/dist/knowledge/repository.js.map +1 -0
- package/dist/knowledge/riskOnAnalyzer.d.ts +79 -0
- package/dist/knowledge/riskOnAnalyzer.d.ts.map +1 -0
- package/dist/knowledge/riskOnAnalyzer.js +243 -0
- package/dist/knowledge/riskOnAnalyzer.js.map +1 -0
- package/dist/knowledge/scanner.d.ts +14 -0
- package/dist/knowledge/scanner.d.ts.map +1 -0
- package/dist/knowledge/scanner.js +350 -0
- package/dist/knowledge/scanner.js.map +1 -0
- package/dist/knowledge/store.d.ts +23 -0
- package/dist/knowledge/store.d.ts.map +1 -0
- package/dist/knowledge/store.js +86 -0
- package/dist/knowledge/store.js.map +1 -0
- package/dist/knowledge/types.d.ts +288 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +111 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/linear/index.d.ts +3 -0
- package/dist/linear/index.d.ts.map +1 -0
- package/dist/linear/index.js +3 -0
- package/dist/linear/index.js.map +1 -0
- package/dist/linear/linear.d.ts +160 -0
- package/dist/linear/linear.d.ts.map +1 -0
- package/dist/linear/linear.js +983 -0
- package/dist/linear/linear.js.map +1 -0
- package/dist/linear/projectUpdater.d.ts +23 -0
- package/dist/linear/projectUpdater.d.ts.map +1 -0
- package/dist/linear/projectUpdater.js +347 -0
- package/dist/linear/projectUpdater.js.map +1 -0
- package/dist/locale/en.d.ts +3 -0
- package/dist/locale/en.d.ts.map +1 -0
- package/dist/locale/en.js +436 -0
- package/dist/locale/en.js.map +1 -0
- package/dist/locale/index.d.ts +28 -0
- package/dist/locale/index.d.ts.map +1 -0
- package/dist/locale/index.js +89 -0
- package/dist/locale/index.js.map +1 -0
- package/dist/locale/ko.d.ts +3 -0
- package/dist/locale/ko.d.ts.map +1 -0
- package/dist/locale/ko.js +436 -0
- package/dist/locale/ko.js.map +1 -0
- package/dist/locale/prompts/en.d.ts +3 -0
- package/dist/locale/prompts/en.d.ts.map +1 -0
- package/dist/locale/prompts/en.js +278 -0
- package/dist/locale/prompts/en.js.map +1 -0
- package/dist/locale/prompts/ko.d.ts +3 -0
- package/dist/locale/prompts/ko.d.ts.map +1 -0
- package/dist/locale/prompts/ko.js +279 -0
- package/dist/locale/prompts/ko.js.map +1 -0
- package/dist/locale/types.d.ts +407 -0
- package/dist/locale/types.d.ts.map +1 -0
- package/dist/locale/types.js +5 -0
- package/dist/locale/types.js.map +1 -0
- package/dist/memory/codex.d.ts +93 -0
- package/dist/memory/codex.d.ts.map +1 -0
- package/dist/memory/codex.js +366 -0
- package/dist/memory/codex.js.map +1 -0
- package/dist/memory/compaction.d.ts +21 -0
- package/dist/memory/compaction.d.ts.map +1 -0
- package/dist/memory/compaction.js +205 -0
- package/dist/memory/compaction.js.map +1 -0
- package/dist/memory/index.d.ts +13 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +13 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/memoryCore.d.ts +178 -0
- package/dist/memory/memoryCore.d.ts.map +1 -0
- package/dist/memory/memoryCore.js +623 -0
- package/dist/memory/memoryCore.js.map +1 -0
- package/dist/memory/memoryOps.d.ts +90 -0
- package/dist/memory/memoryOps.d.ts.map +1 -0
- package/dist/memory/memoryOps.js +606 -0
- package/dist/memory/memoryOps.js.map +1 -0
- package/dist/orchestration/conflictDetector.d.ts +15 -0
- package/dist/orchestration/conflictDetector.d.ts.map +1 -0
- package/dist/orchestration/conflictDetector.js +130 -0
- package/dist/orchestration/conflictDetector.js.map +1 -0
- package/dist/orchestration/decisionEngine.d.ts +177 -0
- package/dist/orchestration/decisionEngine.d.ts.map +1 -0
- package/dist/orchestration/decisionEngine.js +496 -0
- package/dist/orchestration/decisionEngine.js.map +1 -0
- package/dist/orchestration/index.d.ts +5 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +5 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/taskParser.d.ts +67 -0
- package/dist/orchestration/taskParser.d.ts.map +1 -0
- package/dist/orchestration/taskParser.js +542 -0
- package/dist/orchestration/taskParser.js.map +1 -0
- package/dist/orchestration/taskScheduler.d.ts +141 -0
- package/dist/orchestration/taskScheduler.d.ts.map +1 -0
- package/dist/orchestration/taskScheduler.js +317 -0
- package/dist/orchestration/taskScheduler.js.map +1 -0
- package/dist/orchestration/workflow.d.ts +145 -0
- package/dist/orchestration/workflow.d.ts.map +1 -0
- package/dist/orchestration/workflow.js +301 -0
- package/dist/orchestration/workflow.js.map +1 -0
- package/dist/runners/cliRunner.d.ts +11 -0
- package/dist/runners/cliRunner.d.ts.map +1 -0
- package/dist/runners/cliRunner.js +194 -0
- package/dist/runners/cliRunner.js.map +1 -0
- package/dist/support/apiCache.d.ts +85 -0
- package/dist/support/apiCache.d.ts.map +1 -0
- package/dist/support/apiCache.js +163 -0
- package/dist/support/apiCache.js.map +1 -0
- package/dist/support/chat.d.ts +3 -0
- package/dist/support/chat.d.ts.map +1 -0
- package/dist/support/chat.js +304 -0
- package/dist/support/chat.js.map +1 -0
- package/dist/support/chatBackend.d.ts +25 -0
- package/dist/support/chatBackend.d.ts.map +1 -0
- package/dist/support/chatBackend.js +235 -0
- package/dist/support/chatBackend.js.map +1 -0
- package/dist/support/chatMemory.d.ts +71 -0
- package/dist/support/chatMemory.d.ts.map +1 -0
- package/dist/support/chatMemory.js +119 -0
- package/dist/support/chatMemory.js.map +1 -0
- package/dist/support/chatTui.d.ts +3 -0
- package/dist/support/chatTui.d.ts.map +1 -0
- package/dist/support/chatTui.js +998 -0
- package/dist/support/chatTui.js.map +1 -0
- package/dist/support/costTracker.d.ts +29 -0
- package/dist/support/costTracker.d.ts.map +1 -0
- package/dist/support/costTracker.js +113 -0
- package/dist/support/costTracker.js.map +1 -0
- package/dist/support/dashboardHtml.d.ts +3 -0
- package/dist/support/dashboardHtml.d.ts.map +1 -0
- package/dist/support/dashboardHtml.js +2070 -0
- package/dist/support/dashboardHtml.js.map +1 -0
- package/dist/support/delete-beliefs.d.ts +2 -0
- package/dist/support/delete-beliefs.d.ts.map +1 -0
- package/dist/support/delete-beliefs.js +34 -0
- package/dist/support/delete-beliefs.js.map +1 -0
- package/dist/support/dev.d.ts +55 -0
- package/dist/support/dev.d.ts.map +1 -0
- package/dist/support/dev.js +298 -0
- package/dist/support/dev.js.map +1 -0
- package/dist/support/editParser.d.ts +37 -0
- package/dist/support/editParser.d.ts.map +1 -0
- package/dist/support/editParser.js +365 -0
- package/dist/support/editParser.js.map +1 -0
- package/dist/support/gitStatus.d.ts +21 -0
- package/dist/support/gitStatus.d.ts.map +1 -0
- package/dist/support/gitStatus.js +108 -0
- package/dist/support/gitStatus.js.map +1 -0
- package/dist/support/gitTracker.d.ts +30 -0
- package/dist/support/gitTracker.d.ts.map +1 -0
- package/dist/support/gitTracker.js +143 -0
- package/dist/support/gitTracker.js.map +1 -0
- package/dist/support/index.d.ts +13 -0
- package/dist/support/index.d.ts.map +1 -0
- package/dist/support/index.js +13 -0
- package/dist/support/index.js.map +1 -0
- package/dist/support/planner.d.ts +58 -0
- package/dist/support/planner.d.ts.map +1 -0
- package/dist/support/planner.js +395 -0
- package/dist/support/planner.js.map +1 -0
- package/dist/support/projectMapper.d.ts +46 -0
- package/dist/support/projectMapper.d.ts.map +1 -0
- package/dist/support/projectMapper.js +259 -0
- package/dist/support/projectMapper.js.map +1 -0
- package/dist/support/quotaTracker.d.ts +29 -0
- package/dist/support/quotaTracker.d.ts.map +1 -0
- package/dist/support/quotaTracker.js +89 -0
- package/dist/support/quotaTracker.js.map +1 -0
- package/dist/support/rateLimiter.d.ts +101 -0
- package/dist/support/rateLimiter.d.ts.map +1 -0
- package/dist/support/rateLimiter.js +219 -0
- package/dist/support/rateLimiter.js.map +1 -0
- package/dist/support/rollback.d.ts +61 -0
- package/dist/support/rollback.d.ts.map +1 -0
- package/dist/support/rollback.js +328 -0
- package/dist/support/rollback.js.map +1 -0
- package/dist/support/stuckDetector.d.ts +68 -0
- package/dist/support/stuckDetector.d.ts.map +1 -0
- package/dist/support/stuckDetector.js +174 -0
- package/dist/support/stuckDetector.js.map +1 -0
- package/dist/support/timeWindow.d.ts +60 -0
- package/dist/support/timeWindow.d.ts.map +1 -0
- package/dist/support/timeWindow.js +236 -0
- package/dist/support/timeWindow.js.map +1 -0
- package/dist/support/web.d.ts +11 -0
- package/dist/support/web.d.ts.map +1 -0
- package/dist/support/web.js +938 -0
- package/dist/support/web.js.map +1 -0
- package/dist/support/workflowLinear.d.ts +99 -0
- package/dist/support/workflowLinear.d.ts.map +1 -0
- package/dist/support/workflowLinear.js +257 -0
- package/dist/support/workflowLinear.js.map +1 -0
- package/dist/support/worktreeManager.d.ts +20 -0
- package/dist/support/worktreeManager.d.ts.map +1 -0
- package/dist/support/worktreeManager.js +144 -0
- package/dist/support/worktreeManager.js.map +1 -0
- package/dist/taskState/store.d.ts +101 -0
- package/dist/taskState/store.d.ts.map +1 -0
- package/dist/taskState/store.js +346 -0
- package/dist/taskState/store.js.map +1 -0
- package/package.json +70 -0
- package/templates/AGENTS.md +432 -0
- package/templates/BOOT.md +25 -0
- package/templates/BOOTSTRAP.md +50 -0
- package/templates/CHANGELOG_AUDIT.md +74 -0
- package/templates/HEARTBEAT.md +86 -0
- package/templates/IDENTITY.md +27 -0
- package/templates/ISSUE_ANALYSIS.md +31 -0
- package/templates/PR_LAND.md +75 -0
- package/templates/PR_REVIEW.md +97 -0
- package/templates/SOUL.dev.md +52 -0
- package/templates/SOUL.md +81 -0
- package/templates/TOOLS.md +52 -0
- package/templates/USER.md +22 -0
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// OpenSwarm - PR Auto-Improvement Processor
|
|
3
|
+
// Open PR auto-improvement (Worker-Reviewer iteration loop)
|
|
4
|
+
// ============================================
|
|
5
|
+
import { Cron } from 'croner';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
import { resolve } from 'node:path';
|
|
8
|
+
import { existsSync } from 'node:fs';
|
|
9
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
10
|
+
import { execFile } from 'node:child_process';
|
|
11
|
+
import { promisify } from 'node:util';
|
|
12
|
+
const execFileAsync = promisify(execFile);
|
|
13
|
+
/** Safe git command execution (no shell) */
|
|
14
|
+
async function gitExec(cwd, ...args) {
|
|
15
|
+
const { stdout } = await execFileAsync('git', args, { cwd });
|
|
16
|
+
return stdout;
|
|
17
|
+
}
|
|
18
|
+
import { getOpenPRs, getPRContext, commentOnPR, checkPRConflicts, waitForCICompletion, } from '../github/index.js';
|
|
19
|
+
import { createPipelineFromConfig, } from '../agents/pairPipeline.js';
|
|
20
|
+
import { getScheduler } from '../orchestration/taskScheduler.js';
|
|
21
|
+
import { reportEvent } from '../discord/index.js';
|
|
22
|
+
import { ConflictResolver } from './conflictResolver.js';
|
|
23
|
+
// Constants
|
|
24
|
+
const PR_STATE_PATH = resolve(homedir(), '.openswarm', 'pr-state.json');
|
|
25
|
+
// PR Processor
|
|
26
|
+
export class PRProcessor {
|
|
27
|
+
config;
|
|
28
|
+
cronJob = null;
|
|
29
|
+
processing = false;
|
|
30
|
+
conflictResolver = null;
|
|
31
|
+
currentPR = null;
|
|
32
|
+
lastRun = null;
|
|
33
|
+
nextRun = null;
|
|
34
|
+
constructor(config) {
|
|
35
|
+
this.config = config;
|
|
36
|
+
if (config.conflictResolver?.enabled) {
|
|
37
|
+
this.conflictResolver = new ConflictResolver(config.conflictResolver);
|
|
38
|
+
console.log(`[PRProcessor] ConflictResolver enabled (mode: ${config.conflictResolver.ownershipMode}, maxAttempts: ${config.conflictResolver.maxResolutionAttempts})`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get current status (for dashboard)
|
|
43
|
+
*/
|
|
44
|
+
getStatus() {
|
|
45
|
+
return {
|
|
46
|
+
processing: this.processing,
|
|
47
|
+
currentPR: this.currentPR,
|
|
48
|
+
lastRun: this.lastRun,
|
|
49
|
+
nextRun: this.nextRun,
|
|
50
|
+
schedule: this.config.schedule,
|
|
51
|
+
repos: this.config.repos,
|
|
52
|
+
conflictResolverEnabled: this.conflictResolver?.isEnabled() ?? false,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Start schedule
|
|
57
|
+
*/
|
|
58
|
+
start() {
|
|
59
|
+
console.log(`[PRProcessor] Starting (schedule: ${this.config.schedule})`);
|
|
60
|
+
this.cronJob = new Cron(this.config.schedule, async () => {
|
|
61
|
+
await this.processPRs();
|
|
62
|
+
});
|
|
63
|
+
// Initial run after 30 seconds
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
void this.processPRs().catch((err) => {
|
|
66
|
+
console.error('[PRProcessor] Initial run error:', err);
|
|
67
|
+
});
|
|
68
|
+
}, 30_000);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Stop schedule
|
|
72
|
+
*/
|
|
73
|
+
stop() {
|
|
74
|
+
if (this.cronJob) {
|
|
75
|
+
this.cronJob.stop();
|
|
76
|
+
this.cronJob = null;
|
|
77
|
+
}
|
|
78
|
+
console.log('[PRProcessor] Stopped');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Process open PRs across all repos
|
|
82
|
+
*/
|
|
83
|
+
async processPRs() {
|
|
84
|
+
if (this.processing) {
|
|
85
|
+
console.log('[PRProcessor] Already processing, skipping');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.processing = true;
|
|
89
|
+
this.lastRun = Date.now();
|
|
90
|
+
this.currentPR = null;
|
|
91
|
+
console.log('[PRProcessor] Checking PRs...');
|
|
92
|
+
// Broadcast start event
|
|
93
|
+
const { broadcastEvent } = await import('../core/eventHub.js');
|
|
94
|
+
broadcastEvent({ type: 'pr_processor_start', data: { repos: this.config.repos } });
|
|
95
|
+
try {
|
|
96
|
+
const state = await this.loadState();
|
|
97
|
+
for (const repo of this.config.repos) {
|
|
98
|
+
const prs = await getOpenPRs(repo);
|
|
99
|
+
if (prs.length === 0)
|
|
100
|
+
continue;
|
|
101
|
+
console.log(`[PRProcessor] ${repo}: ${prs.length} open PRs`);
|
|
102
|
+
for (const pr of prs) {
|
|
103
|
+
const key = `${repo}#${pr.number}`;
|
|
104
|
+
// Check for merge conflicts first (always handle conflicts)
|
|
105
|
+
const hasConflicts = await checkPRConflicts(repo, pr.number);
|
|
106
|
+
// Check for review feedback (formal reviews with CHANGES_REQUESTED)
|
|
107
|
+
const { getPRReviews, getPRComments } = await import('../github/github.js');
|
|
108
|
+
const reviews = await getPRReviews(repo, pr.number);
|
|
109
|
+
const latestReviews = new Map();
|
|
110
|
+
for (const review of reviews) {
|
|
111
|
+
const existing = latestReviews.get(review.author);
|
|
112
|
+
if (!existing || new Date(review.createdAt) > new Date(existing.createdAt)) {
|
|
113
|
+
latestReviews.set(review.author, review);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const hasFormalReviewFeedback = Array.from(latestReviews.values()).some(r => r.state === 'CHANGES_REQUESTED');
|
|
117
|
+
// Also check PR comments for review feedback (from claude-review action)
|
|
118
|
+
const comments = await getPRComments(repo, pr.number);
|
|
119
|
+
const criticalKeywords = ['🔴', 'critical', '버그', 'bug', '수정 필요', 'must fix', '필수', 'required'];
|
|
120
|
+
const hasCommentFeedback = comments.some(c => {
|
|
121
|
+
const bodyLower = c.body.toLowerCase();
|
|
122
|
+
return (c.author === 'claude' || c.author.includes('claude')) &&
|
|
123
|
+
criticalKeywords.some(keyword => bodyLower.includes(keyword.toLowerCase()));
|
|
124
|
+
});
|
|
125
|
+
const hasReviewFeedback = hasFormalReviewFeedback || hasCommentFeedback;
|
|
126
|
+
// Cooldown check (skip cooldown for conflicting PRs or PRs with review feedback)
|
|
127
|
+
if (!hasConflicts && !hasReviewFeedback) {
|
|
128
|
+
const existing = state.prs[key];
|
|
129
|
+
if (existing?.lastProcessed) {
|
|
130
|
+
const hoursSince = (Date.now() - new Date(existing.lastProcessed).getTime()) / (1000 * 60 * 60);
|
|
131
|
+
if (hoursSince < this.config.cooldownHours) {
|
|
132
|
+
console.log(`[PRProcessor] ${key}: cooldown (${hoursSince.toFixed(1)}h < ${this.config.cooldownHours}h)`);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (hasConflicts) {
|
|
138
|
+
console.log(`[PRProcessor] ${key}: merge conflicts detected (bypassing cooldown)`);
|
|
139
|
+
}
|
|
140
|
+
else if (hasReviewFeedback) {
|
|
141
|
+
console.log(`[PRProcessor] ${key}: review feedback detected (bypassing cooldown)`);
|
|
142
|
+
}
|
|
143
|
+
// If no conflicts and no review feedback, check CI status — only process PRs with failures
|
|
144
|
+
if (!hasConflicts && !hasReviewFeedback) {
|
|
145
|
+
const { getPRChecks } = await import('../github/index.js');
|
|
146
|
+
const checks = await getPRChecks(repo, pr.number);
|
|
147
|
+
const hasFailure = checks.some((c) => c.conclusion === 'failure' || c.conclusion === 'timed_out');
|
|
148
|
+
if (!hasFailure && checks.length > 0) {
|
|
149
|
+
console.log(`[PRProcessor] ${key}: no conflicts, no review feedback, and CI passing, skipping`);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else if (hasConflicts) {
|
|
154
|
+
console.log(`[PRProcessor] ${key}: merge conflicts detected, will attempt resolution`);
|
|
155
|
+
}
|
|
156
|
+
else if (hasReviewFeedback) {
|
|
157
|
+
console.log(`[PRProcessor] ${key}: review feedback detected, will address feedback`);
|
|
158
|
+
}
|
|
159
|
+
// Map repo to local project path
|
|
160
|
+
const projectPath = this.mapRepoToProject(repo);
|
|
161
|
+
if (!projectPath) {
|
|
162
|
+
console.log(`[PRProcessor] ${key}: no local project found, skipping`);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
// TaskScheduler concurrency check
|
|
166
|
+
try {
|
|
167
|
+
const scheduler = getScheduler();
|
|
168
|
+
if (scheduler.isProjectBusy(projectPath)) {
|
|
169
|
+
console.log(`[PRProcessor] ${key}: project busy (Linear task running)`);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (!scheduler.hasAvailableSlot()) {
|
|
173
|
+
console.log(`[PRProcessor] ${key}: no available slots`);
|
|
174
|
+
break; // No available slots, stop entirely
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// Ignore if scheduler not initialized
|
|
179
|
+
}
|
|
180
|
+
// Process PR
|
|
181
|
+
state.prs[key] = {
|
|
182
|
+
repo,
|
|
183
|
+
prNumber: pr.number,
|
|
184
|
+
status: 'processing',
|
|
185
|
+
iterations: 0,
|
|
186
|
+
lastProcessed: new Date().toISOString(),
|
|
187
|
+
};
|
|
188
|
+
await this.saveState(state);
|
|
189
|
+
// If only review feedback (no conflicts, CI passing), handle review feedback directly
|
|
190
|
+
if (hasReviewFeedback && !hasConflicts) {
|
|
191
|
+
const { getPRChecks } = await import('../github/index.js');
|
|
192
|
+
const checks = await getPRChecks(repo, pr.number);
|
|
193
|
+
const hasFailure = checks.some((c) => c.conclusion === 'failure' || c.conclusion === 'timed_out');
|
|
194
|
+
if (!hasFailure && checks.length > 0) {
|
|
195
|
+
// CI is passing, only need to handle review feedback
|
|
196
|
+
console.log(`[PRProcessor] ${key}: Handling review feedback only (CI passing)`);
|
|
197
|
+
await this.processReviewFeedback(pr, projectPath, state, key, 0);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Otherwise, run full PR processing (handles conflicts, CI failures, then review feedback)
|
|
202
|
+
await this.processPR(pr, projectPath, state, key);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Cascade: check other owned PRs for conflicts after resolution
|
|
206
|
+
if (this.conflictResolver?.cascadeEnabled()) {
|
|
207
|
+
for (const repo of this.config.repos) {
|
|
208
|
+
await this.conflictResolver.checkCascade(repo);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
await this.saveState(state);
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
console.error('[PRProcessor] Error:', err);
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
this.processing = false;
|
|
218
|
+
this.currentPR = null;
|
|
219
|
+
// Calculate next run time
|
|
220
|
+
if (this.cronJob) {
|
|
221
|
+
const next = this.cronJob.nextRun();
|
|
222
|
+
this.nextRun = next ? next.getTime() : null;
|
|
223
|
+
}
|
|
224
|
+
// Broadcast end event
|
|
225
|
+
const { broadcastEvent } = await import('../core/eventHub.js');
|
|
226
|
+
broadcastEvent({ type: 'pr_processor_end', data: { lastRun: this.lastRun, nextRun: this.nextRun } });
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Process a single PR with auto-retry loop
|
|
231
|
+
*/
|
|
232
|
+
async processPR(pr, projectPath, state, key) {
|
|
233
|
+
this.currentPR = key;
|
|
234
|
+
console.log(`[PRProcessor] Processing ${key}: "${pr.title}"`);
|
|
235
|
+
// Broadcast PR processing event
|
|
236
|
+
const { broadcastEvent } = await import('../core/eventHub.js');
|
|
237
|
+
broadcastEvent({ type: 'pr_processor_pr', data: { pr: key, title: pr.title } });
|
|
238
|
+
// Save current branch (for restoration)
|
|
239
|
+
let originalBranch = 'main';
|
|
240
|
+
try {
|
|
241
|
+
originalBranch = (await gitExec(projectPath, 'rev-parse', '--abbrev-ref', 'HEAD')).trim();
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// Fall back to main on failure
|
|
245
|
+
}
|
|
246
|
+
const maxRetries = this.config.maxRetries ?? 3;
|
|
247
|
+
const ciTimeoutMs = this.config.ciTimeoutMs ?? 600_000; // 10 minutes
|
|
248
|
+
const ciPollIntervalMs = this.config.ciPollIntervalMs ?? 30_000; // 30 seconds
|
|
249
|
+
let totalIterations = 0;
|
|
250
|
+
let lastError;
|
|
251
|
+
let retryCount = 0;
|
|
252
|
+
try {
|
|
253
|
+
// 1. Fetch detailed PR context
|
|
254
|
+
const details = await getPRContext(pr.repo, pr.number);
|
|
255
|
+
if (!details) {
|
|
256
|
+
state.prs[key].status = 'failed';
|
|
257
|
+
state.prs[key].lastError = 'Failed to get PR context';
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
// 2. Check for merge conflicts
|
|
261
|
+
const hasConflicts = await checkPRConflicts(pr.repo, pr.number);
|
|
262
|
+
if (hasConflicts) {
|
|
263
|
+
// Try auto-resolution if ConflictResolver is enabled
|
|
264
|
+
if (this.conflictResolver?.isEnabled()) {
|
|
265
|
+
const canResolve = await this.conflictResolver.canResolve(pr);
|
|
266
|
+
if (canResolve) {
|
|
267
|
+
console.log(`[PRProcessor] ${key}: conflicts detected, attempting auto-resolution...`);
|
|
268
|
+
const resolved = await this.conflictResolver.resolve(pr, projectPath);
|
|
269
|
+
if (resolved) {
|
|
270
|
+
console.log(`[PRProcessor] ${key}: conflicts resolved, continuing to CI check...`);
|
|
271
|
+
// Fall through to CI check flow below
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
// Resolution failed — escalation already handled by resolver
|
|
275
|
+
state.prs[key].status = 'failed';
|
|
276
|
+
state.prs[key].lastError = 'Conflict resolution failed';
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
// Cannot resolve (not owned or max attempts)
|
|
282
|
+
const conflictMsg = 'PR has merge conflicts - cannot auto-resolve (not owned or max attempts reached)';
|
|
283
|
+
console.log(`[PRProcessor] ${key}: ${conflictMsg}`);
|
|
284
|
+
await commentOnPR(pr.repo, pr.number, `## ⚠️ ${conflictMsg}\n\nPlease resolve conflicts manually.`);
|
|
285
|
+
state.prs[key].status = 'failed';
|
|
286
|
+
state.prs[key].lastError = conflictMsg;
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
// No resolver available
|
|
292
|
+
const conflictMsg = 'PR has merge conflicts - cannot auto-fix';
|
|
293
|
+
console.log(`[PRProcessor] ${key}: ${conflictMsg}`);
|
|
294
|
+
await commentOnPR(pr.repo, pr.number, `## ⚠️ ${conflictMsg}\n\nPlease resolve conflicts manually.`);
|
|
295
|
+
state.prs[key].status = 'failed';
|
|
296
|
+
state.prs[key].lastError = conflictMsg;
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// 3. git fetch + checkout PR branch
|
|
301
|
+
await gitExec(projectPath, 'fetch', 'origin', pr.branch);
|
|
302
|
+
// Stash local changes before checkout
|
|
303
|
+
try {
|
|
304
|
+
await gitExec(projectPath, 'stash', 'push', '-u', '-m', `PRProcessor auto-stash for ${key}`);
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
// Ignore if nothing to stash
|
|
308
|
+
}
|
|
309
|
+
await gitExec(projectPath, 'checkout', pr.branch);
|
|
310
|
+
// 4. Auto-retry loop
|
|
311
|
+
while (retryCount < maxRetries) {
|
|
312
|
+
retryCount++;
|
|
313
|
+
console.log(`[PRProcessor] ${key}: Attempt ${retryCount}/${maxRetries}`);
|
|
314
|
+
// 4a. Build TaskItem with current PR context
|
|
315
|
+
const currentDetails = retryCount > 1 ? (await getPRContext(pr.repo, pr.number) || details) : details;
|
|
316
|
+
const diffSnippet = currentDetails.diff.slice(0, 5000);
|
|
317
|
+
const failedChecksList = currentDetails.failedChecks
|
|
318
|
+
?.map((c) => `- ${c.name}: ${c.conclusion}`)
|
|
319
|
+
.join('\n') || 'N/A';
|
|
320
|
+
const failedLogsSnippet = currentDetails.failedLogs?.slice(0, 3000) || '';
|
|
321
|
+
const task = {
|
|
322
|
+
id: `pr-${pr.repo}-${pr.number}-${retryCount}`,
|
|
323
|
+
source: 'github_pr',
|
|
324
|
+
title: `Fix PR #${pr.number}: ${pr.title}`,
|
|
325
|
+
description: [
|
|
326
|
+
`## PR Context (Attempt ${retryCount}/${maxRetries})`,
|
|
327
|
+
`**Title:** ${pr.title}`,
|
|
328
|
+
`**Branch:** ${pr.branch}`,
|
|
329
|
+
`**Author:** ${currentDetails.author}`,
|
|
330
|
+
'',
|
|
331
|
+
currentDetails.body ? `**Description:**\n${currentDetails.body}\n` : '',
|
|
332
|
+
`## Failed CI Checks`,
|
|
333
|
+
failedChecksList,
|
|
334
|
+
'',
|
|
335
|
+
failedLogsSnippet ? `## Failed Logs (last 3000 chars)\n\`\`\`\n${failedLogsSnippet}\n\`\`\`\n` : '',
|
|
336
|
+
`## Diff (first 5000 chars)`,
|
|
337
|
+
'```diff',
|
|
338
|
+
diffSnippet,
|
|
339
|
+
'```',
|
|
340
|
+
'',
|
|
341
|
+
'## Instructions',
|
|
342
|
+
'Fix CI failures. Do NOT change the overall approach or architecture.',
|
|
343
|
+
'Focus on: type errors, lint errors, test failures, build errors.',
|
|
344
|
+
'Make minimal changes to get CI passing.',
|
|
345
|
+
retryCount > 1 ? `\n**Previous attempt failed - review the error logs above carefully.**` : '',
|
|
346
|
+
].join('\n'),
|
|
347
|
+
priority: 2,
|
|
348
|
+
projectPath,
|
|
349
|
+
issueId: `pr-${pr.number}`,
|
|
350
|
+
workflowId: undefined,
|
|
351
|
+
createdAt: Date.now(),
|
|
352
|
+
};
|
|
353
|
+
// 4b. Run pipeline
|
|
354
|
+
const pipeline = createPipelineFromConfig(this.config.roles, this.config.maxIterations, undefined, undefined);
|
|
355
|
+
const result = await pipeline.run(task, projectPath);
|
|
356
|
+
totalIterations += result.iterations;
|
|
357
|
+
if (!result.success) {
|
|
358
|
+
// Pipeline failed
|
|
359
|
+
lastError = result.reviewResult?.feedback
|
|
360
|
+
|| result.workerResult?.error
|
|
361
|
+
|| 'Pipeline failed after max iterations';
|
|
362
|
+
console.log(`[PRProcessor] ${key}: Pipeline failed - ${lastError}`);
|
|
363
|
+
if (retryCount >= maxRetries) {
|
|
364
|
+
break; // Max retries reached
|
|
365
|
+
}
|
|
366
|
+
// Retry
|
|
367
|
+
console.log(`[PRProcessor] ${key}: Retrying...`);
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
// 4c. Pipeline succeeded - push changes
|
|
371
|
+
console.log(`[PRProcessor] ${key}: Pipeline succeeded, pushing changes...`);
|
|
372
|
+
await gitExec(projectPath, 'push', 'origin', pr.branch);
|
|
373
|
+
// 4d. Wait for CI completion
|
|
374
|
+
console.log(`[PRProcessor] ${key}: Waiting for CI checks...`);
|
|
375
|
+
const ciStatus = await waitForCICompletion(pr.repo, pr.number, {
|
|
376
|
+
timeoutMs: ciTimeoutMs,
|
|
377
|
+
pollIntervalMs: ciPollIntervalMs,
|
|
378
|
+
onProgress: (status, elapsed) => {
|
|
379
|
+
if (status.status === 'pending') {
|
|
380
|
+
console.log(`[PRProcessor] ${key}: CI pending (${Math.floor(elapsed / 1000)}s elapsed)...`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
// 4e. Check CI result
|
|
385
|
+
if (ciStatus.status === 'success') {
|
|
386
|
+
// SUCCESS - all CI passed
|
|
387
|
+
const summary = result.workerResult?.summary || 'CI issues fixed';
|
|
388
|
+
const filesChanged = result.workerResult?.filesChanged?.join(', ') || 'N/A';
|
|
389
|
+
await commentOnPR(pr.repo, pr.number, [
|
|
390
|
+
`## ✅ Auto-fix completed - CI passing`,
|
|
391
|
+
'',
|
|
392
|
+
`**Summary:** ${summary}`,
|
|
393
|
+
`**Files changed:** ${filesChanged}`,
|
|
394
|
+
`**Total attempts:** ${retryCount}`,
|
|
395
|
+
`**Total iterations:** ${totalIterations}`,
|
|
396
|
+
].join('\n'));
|
|
397
|
+
await reportEvent({
|
|
398
|
+
type: 'pr_improved',
|
|
399
|
+
session: 'pr-processor',
|
|
400
|
+
message: `**${pr.repo}#${pr.number}** "${pr.title}" CI fix completed (${retryCount} attempts)\n${summary}`,
|
|
401
|
+
timestamp: Date.now(),
|
|
402
|
+
url: pr.url,
|
|
403
|
+
});
|
|
404
|
+
// Process review feedback after CI success
|
|
405
|
+
await this.processReviewFeedback(pr, projectPath, state, key, totalIterations);
|
|
406
|
+
state.prs[key].status = 'completed';
|
|
407
|
+
state.prs[key].iterations = totalIterations;
|
|
408
|
+
console.log(`[PRProcessor] ${key}: SUCCESS after ${retryCount} attempt(s)`);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
else if (ciStatus.status === 'failure') {
|
|
412
|
+
// CI failed - prepare for retry
|
|
413
|
+
lastError = `CI checks failed: ${ciStatus.failedChecks.map(c => c.name).join(', ')}`;
|
|
414
|
+
console.log(`[PRProcessor] ${key}: ${lastError}`);
|
|
415
|
+
if (retryCount >= maxRetries) {
|
|
416
|
+
break; // Max retries reached
|
|
417
|
+
}
|
|
418
|
+
// Fetch latest PR state before retry
|
|
419
|
+
console.log(`[PRProcessor] ${key}: Retrying due to CI failure...`);
|
|
420
|
+
await gitExec(projectPath, 'pull', 'origin', pr.branch);
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
// CI timeout
|
|
425
|
+
lastError = 'CI timeout - checks did not complete in time';
|
|
426
|
+
console.log(`[PRProcessor] ${key}: ${lastError}`);
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// Max retries reached or CI timeout
|
|
431
|
+
await commentOnPR(pr.repo, pr.number, [
|
|
432
|
+
`## ❌ Auto-fix failed after ${retryCount} attempt(s)`,
|
|
433
|
+
'',
|
|
434
|
+
`**Total iterations:** ${totalIterations}`,
|
|
435
|
+
`**Last error:** ${lastError || 'Unknown error'}`,
|
|
436
|
+
'',
|
|
437
|
+
'Manual intervention required.',
|
|
438
|
+
].join('\n'));
|
|
439
|
+
await reportEvent({
|
|
440
|
+
type: 'pr_failed',
|
|
441
|
+
session: 'pr-processor',
|
|
442
|
+
message: `**${pr.repo}#${pr.number}** "${pr.title}" auto-fix failed after ${retryCount} attempts\n${lastError || 'Unknown'}`,
|
|
443
|
+
timestamp: Date.now(),
|
|
444
|
+
url: pr.url,
|
|
445
|
+
});
|
|
446
|
+
state.prs[key].status = 'failed';
|
|
447
|
+
state.prs[key].lastError = lastError;
|
|
448
|
+
state.prs[key].iterations = totalIterations;
|
|
449
|
+
console.log(`[PRProcessor] ${key}: FAILED after ${retryCount} attempt(s) - ${lastError}`);
|
|
450
|
+
}
|
|
451
|
+
catch (err) {
|
|
452
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
453
|
+
console.error(`[PRProcessor] ${key} error:`, errorMsg);
|
|
454
|
+
state.prs[key].status = 'failed';
|
|
455
|
+
state.prs[key].lastError = errorMsg;
|
|
456
|
+
}
|
|
457
|
+
finally {
|
|
458
|
+
// Restore branch
|
|
459
|
+
try {
|
|
460
|
+
await gitExec(projectPath, 'checkout', originalBranch);
|
|
461
|
+
}
|
|
462
|
+
catch (restoreErr) {
|
|
463
|
+
console.error(`[PRProcessor] Failed to restore branch ${originalBranch}:`, restoreErr);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Process review feedback and iterate until all reviews are approved
|
|
469
|
+
*/
|
|
470
|
+
async processReviewFeedback(pr, projectPath, state, key, totalIterations) {
|
|
471
|
+
const MAX_REVIEW_ITERATIONS = 5;
|
|
472
|
+
let reviewIteration = 0;
|
|
473
|
+
// Save current branch for restoration
|
|
474
|
+
let originalBranch = 'main';
|
|
475
|
+
try {
|
|
476
|
+
originalBranch = (await gitExec(projectPath, 'rev-parse', '--abbrev-ref', 'HEAD')).trim();
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
// Fall back to main on failure
|
|
480
|
+
}
|
|
481
|
+
try {
|
|
482
|
+
// git fetch + checkout PR branch
|
|
483
|
+
await gitExec(projectPath, 'fetch', 'origin', pr.branch);
|
|
484
|
+
// Stash local changes before checkout
|
|
485
|
+
try {
|
|
486
|
+
await gitExec(projectPath, 'stash', 'push', '-u', '-m', `PRProcessor review feedback for ${key}`);
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
// Ignore if nothing to stash
|
|
490
|
+
}
|
|
491
|
+
await gitExec(projectPath, 'checkout', pr.branch);
|
|
492
|
+
while (reviewIteration < MAX_REVIEW_ITERATIONS) {
|
|
493
|
+
reviewIteration++;
|
|
494
|
+
console.log(`[PRProcessor] ${key}: Checking review feedback (iteration ${reviewIteration}/${MAX_REVIEW_ITERATIONS})...`);
|
|
495
|
+
// Get PR reviews and comments
|
|
496
|
+
const { getPRReviews, getPRReviewComments, getPRComments } = await import('../github/github.js');
|
|
497
|
+
const reviews = await getPRReviews(pr.repo, pr.number);
|
|
498
|
+
const prComments = await getPRComments(pr.repo, pr.number);
|
|
499
|
+
// Find latest reviews per user (only consider latest review from each reviewer)
|
|
500
|
+
const latestReviews = new Map();
|
|
501
|
+
for (const review of reviews) {
|
|
502
|
+
const existing = latestReviews.get(review.author);
|
|
503
|
+
if (!existing || new Date(review.createdAt) > new Date(existing.createdAt)) {
|
|
504
|
+
latestReviews.set(review.author, review);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
// Check if any reviews request changes
|
|
508
|
+
const changesRequested = Array.from(latestReviews.values()).filter(r => r.state === 'CHANGES_REQUESTED');
|
|
509
|
+
// Check for critical feedback in PR comments (from claude-review action)
|
|
510
|
+
const criticalKeywords = ['🔴', 'critical', '버그', 'bug', '수정 필요', 'must fix', '필수', 'required'];
|
|
511
|
+
const criticalComments = prComments.filter(c => {
|
|
512
|
+
const bodyLower = c.body.toLowerCase();
|
|
513
|
+
return (c.author === 'claude' || c.author.includes('claude')) &&
|
|
514
|
+
criticalKeywords.some(keyword => bodyLower.includes(keyword.toLowerCase()));
|
|
515
|
+
});
|
|
516
|
+
if (changesRequested.length === 0 && criticalComments.length === 0) {
|
|
517
|
+
console.log(`[PRProcessor] ${key}: No changes requested - all reviews approved or no critical feedback`);
|
|
518
|
+
state.prs[key].status = 'completed';
|
|
519
|
+
state.prs[key].iterations = totalIterations;
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
console.log(`[PRProcessor] ${key}: Found ${changesRequested.length} review(s) requesting changes, ${criticalComments.length} critical comment(s)`);
|
|
523
|
+
// Get review comments for detailed feedback
|
|
524
|
+
const comments = await getPRReviewComments(pr.repo, pr.number);
|
|
525
|
+
// Build feedback summary
|
|
526
|
+
const feedbackLines = [];
|
|
527
|
+
// Add formal review feedback
|
|
528
|
+
for (const review of changesRequested) {
|
|
529
|
+
feedbackLines.push(`### Review by ${review.author}`);
|
|
530
|
+
if (review.body) {
|
|
531
|
+
feedbackLines.push(review.body);
|
|
532
|
+
}
|
|
533
|
+
// Add specific line comments from this reviewer
|
|
534
|
+
const reviewerComments = comments.filter(c => c.author === review.author);
|
|
535
|
+
if (reviewerComments.length > 0) {
|
|
536
|
+
feedbackLines.push('\n**Specific comments:**');
|
|
537
|
+
for (const comment of reviewerComments) {
|
|
538
|
+
if (comment.path && comment.line) {
|
|
539
|
+
feedbackLines.push(`- \`${comment.path}:${comment.line}\`: ${comment.body}`);
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
feedbackLines.push(`- ${comment.body}`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
feedbackLines.push('');
|
|
547
|
+
}
|
|
548
|
+
// Add critical PR comments feedback
|
|
549
|
+
if (criticalComments.length > 0) {
|
|
550
|
+
feedbackLines.push(`### Critical Feedback from PR Comments`);
|
|
551
|
+
for (const comment of criticalComments) {
|
|
552
|
+
feedbackLines.push(`**Comment by ${comment.author}:**`);
|
|
553
|
+
feedbackLines.push(comment.body);
|
|
554
|
+
feedbackLines.push('');
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
const feedbackSummary = feedbackLines.join('\n');
|
|
558
|
+
// Get current PR context
|
|
559
|
+
const { getPRContext } = await import('../github/github.js');
|
|
560
|
+
const details = await getPRContext(pr.repo, pr.number);
|
|
561
|
+
if (!details) {
|
|
562
|
+
console.log(`[PRProcessor] ${key}: Failed to get PR context for review iteration`);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
const diffSnippet = details.diff.slice(0, 5000);
|
|
566
|
+
// Build TaskItem with review feedback
|
|
567
|
+
const task = {
|
|
568
|
+
id: `pr-review-${pr.repo}-${pr.number}-${reviewIteration}`,
|
|
569
|
+
source: 'github_pr_review',
|
|
570
|
+
title: `Address review feedback for PR #${pr.number}: ${pr.title}`,
|
|
571
|
+
description: [
|
|
572
|
+
`## Review Feedback (Iteration ${reviewIteration}/${MAX_REVIEW_ITERATIONS})`,
|
|
573
|
+
`**PR:** ${pr.repo}#${pr.number} - ${pr.title}`,
|
|
574
|
+
`**Branch:** ${pr.branch}`,
|
|
575
|
+
'',
|
|
576
|
+
`## Requested Changes`,
|
|
577
|
+
feedbackSummary,
|
|
578
|
+
'',
|
|
579
|
+
`## Current Diff (first 5000 chars)`,
|
|
580
|
+
'```diff',
|
|
581
|
+
diffSnippet,
|
|
582
|
+
'```',
|
|
583
|
+
'',
|
|
584
|
+
'## Instructions',
|
|
585
|
+
'Address all review feedback points above.',
|
|
586
|
+
'Make the requested changes while maintaining code quality.',
|
|
587
|
+
'DO NOT change unrelated code or architecture.',
|
|
588
|
+
'Focus on addressing the specific points raised by reviewers.',
|
|
589
|
+
].join('\n'),
|
|
590
|
+
priority: 2,
|
|
591
|
+
projectPath,
|
|
592
|
+
issueId: `pr-${pr.number}`,
|
|
593
|
+
workflowId: undefined,
|
|
594
|
+
createdAt: Date.now(),
|
|
595
|
+
};
|
|
596
|
+
// Run pipeline to address feedback
|
|
597
|
+
console.log(`[PRProcessor] ${key}: Running pipeline to address review feedback...`);
|
|
598
|
+
const pipeline = createPipelineFromConfig(this.config.roles, this.config.maxIterations, undefined, undefined);
|
|
599
|
+
const result = await pipeline.run(task, projectPath);
|
|
600
|
+
totalIterations += result.iterations;
|
|
601
|
+
if (!result.success) {
|
|
602
|
+
const error = result.reviewResult?.feedback || result.workerResult?.error || 'Pipeline failed';
|
|
603
|
+
console.log(`[PRProcessor] ${key}: Failed to address review feedback - ${error}`);
|
|
604
|
+
await commentOnPR(pr.repo, pr.number, [
|
|
605
|
+
`## ⚠️ Failed to address review feedback (iteration ${reviewIteration})`,
|
|
606
|
+
'',
|
|
607
|
+
`**Error:** ${error}`,
|
|
608
|
+
'',
|
|
609
|
+
'Manual intervention required.',
|
|
610
|
+
].join('\n'));
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
// Push changes
|
|
614
|
+
console.log(`[PRProcessor] ${key}: Pushing review feedback changes...`);
|
|
615
|
+
await gitExec(projectPath, 'push', 'origin', pr.branch);
|
|
616
|
+
// Comment on PR
|
|
617
|
+
const summary = result.workerResult?.summary || 'Review feedback addressed';
|
|
618
|
+
const filesChanged = result.workerResult?.filesChanged?.join(', ') || 'N/A';
|
|
619
|
+
await commentOnPR(pr.repo, pr.number, [
|
|
620
|
+
`## 🔄 Review feedback addressed (iteration ${reviewIteration})`,
|
|
621
|
+
'',
|
|
622
|
+
`**Summary:** ${summary}`,
|
|
623
|
+
`**Files changed:** ${filesChanged}`,
|
|
624
|
+
'',
|
|
625
|
+
'Please re-review.',
|
|
626
|
+
].join('\n'));
|
|
627
|
+
console.log(`[PRProcessor] ${key}: Review feedback iteration ${reviewIteration} complete`);
|
|
628
|
+
// Small delay before checking reviews again
|
|
629
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
630
|
+
}
|
|
631
|
+
// Max iterations reached
|
|
632
|
+
console.log(`[PRProcessor] ${key}: Max review iterations (${MAX_REVIEW_ITERATIONS}) reached`);
|
|
633
|
+
await commentOnPR(pr.repo, pr.number, [
|
|
634
|
+
`## ⚠️ Max review feedback iterations reached`,
|
|
635
|
+
'',
|
|
636
|
+
`Attempted to address review feedback ${MAX_REVIEW_ITERATIONS} times.`,
|
|
637
|
+
'Please review manually and provide additional guidance if needed.',
|
|
638
|
+
].join('\n'));
|
|
639
|
+
// Update state
|
|
640
|
+
state.prs[key].status = 'completed';
|
|
641
|
+
state.prs[key].iterations = totalIterations;
|
|
642
|
+
}
|
|
643
|
+
catch (err) {
|
|
644
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
645
|
+
console.error(`[PRProcessor] ${key} review feedback error:`, errorMsg);
|
|
646
|
+
state.prs[key].status = 'failed';
|
|
647
|
+
state.prs[key].lastError = errorMsg;
|
|
648
|
+
}
|
|
649
|
+
finally {
|
|
650
|
+
// Restore branch
|
|
651
|
+
try {
|
|
652
|
+
await gitExec(projectPath, 'checkout', originalBranch);
|
|
653
|
+
}
|
|
654
|
+
catch (restoreErr) {
|
|
655
|
+
console.error(`[PRProcessor] Failed to restore branch ${originalBranch}:`, restoreErr);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Map repo to local project path
|
|
661
|
+
*/
|
|
662
|
+
mapRepoToProject(repo) {
|
|
663
|
+
// Check custom mappings first
|
|
664
|
+
if (this.config.repoMappings?.[repo]) {
|
|
665
|
+
const mapped = this.config.repoMappings[repo].replace(/^~/, homedir());
|
|
666
|
+
if (existsSync(mapped)) {
|
|
667
|
+
return mapped;
|
|
668
|
+
}
|
|
669
|
+
console.log(`[PRProcessor] Custom mapping found but path does not exist: ${repo} → ${mapped}`);
|
|
670
|
+
}
|
|
671
|
+
// Fallback: "Intrect-io/STONKS" → "STONKS"
|
|
672
|
+
const repoName = repo.split('/').pop();
|
|
673
|
+
if (!repoName)
|
|
674
|
+
return null;
|
|
675
|
+
const candidate = resolve(homedir(), 'dev', repoName);
|
|
676
|
+
if (existsSync(candidate)) {
|
|
677
|
+
return candidate;
|
|
678
|
+
}
|
|
679
|
+
console.log(`[PRProcessor] No local directory for ${repo} (tried: ${candidate})`);
|
|
680
|
+
return null;
|
|
681
|
+
}
|
|
682
|
+
// ============================================
|
|
683
|
+
// State Persistence
|
|
684
|
+
// ============================================
|
|
685
|
+
async loadState() {
|
|
686
|
+
try {
|
|
687
|
+
const data = await readFile(PR_STATE_PATH, 'utf-8');
|
|
688
|
+
return JSON.parse(data);
|
|
689
|
+
}
|
|
690
|
+
catch {
|
|
691
|
+
return { prs: {}, updatedAt: new Date().toISOString() };
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
async saveState(state) {
|
|
695
|
+
await mkdir(resolve(homedir(), '.openswarm'), { recursive: true });
|
|
696
|
+
state.updatedAt = new Date().toISOString();
|
|
697
|
+
await writeFile(PR_STATE_PATH, JSON.stringify(state, null, 2));
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
//# sourceMappingURL=prProcessor.js.map
|