@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,793 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// OpenSwarm - Pair Pipeline
|
|
3
|
+
// Worker → Reviewer → Tester → Documenter pipeline
|
|
4
|
+
// ============================================
|
|
5
|
+
import { EventEmitter } from 'node:events';
|
|
6
|
+
import { aggregateCosts, formatCost } from '../support/costTracker.js';
|
|
7
|
+
import { broadcastEvent } from '../core/eventHub.js';
|
|
8
|
+
import { CONFIDENCE_THRESHOLDS } from './agentPair.js';
|
|
9
|
+
import * as agentPair from './agentPair.js';
|
|
10
|
+
import { runGuards } from './pipelineGuards.js';
|
|
11
|
+
import { hasRepoSnapshot, scanAndCache } from '../knowledge/index.js';
|
|
12
|
+
import * as workerAgent from './worker.js';
|
|
13
|
+
import * as reviewerAgent from './reviewer.js';
|
|
14
|
+
import * as testerAgent from './tester.js';
|
|
15
|
+
import * as documenterAgent from './documenter.js';
|
|
16
|
+
import * as auditorAgent from './auditor.js';
|
|
17
|
+
import * as skillDocumenterAgent from './skillDocumenter.js';
|
|
18
|
+
import { createStuckDetector } from '../support/stuckDetector.js';
|
|
19
|
+
/**
|
|
20
|
+
* Build a consistent task prefix for logging across all pipeline stages.
|
|
21
|
+
* Format: "ProjectName | INT-XXX | worktree/abc123" or "ProjectName | INT-XXX"
|
|
22
|
+
*/
|
|
23
|
+
export function buildTaskPrefix(task, projectPath) {
|
|
24
|
+
const parts = [];
|
|
25
|
+
const projectName = task.linearProject?.name || projectPath.split('/').pop() || 'unknown';
|
|
26
|
+
parts.push(projectName);
|
|
27
|
+
if (task.issueIdentifier) {
|
|
28
|
+
parts.push(task.issueIdentifier);
|
|
29
|
+
}
|
|
30
|
+
else if (task.issueId) {
|
|
31
|
+
parts.push(task.issueId.slice(0, 8));
|
|
32
|
+
}
|
|
33
|
+
// Detect worktree path
|
|
34
|
+
const worktreeMatch = projectPath.match(/worktree\/([a-f0-9-]+)/);
|
|
35
|
+
if (worktreeMatch) {
|
|
36
|
+
parts.push(`worktree/${worktreeMatch[1].slice(0, 8)}`);
|
|
37
|
+
}
|
|
38
|
+
return parts.join(' | ');
|
|
39
|
+
}
|
|
40
|
+
// Pair Pipeline
|
|
41
|
+
export class PairPipeline extends EventEmitter {
|
|
42
|
+
config;
|
|
43
|
+
stuckDetector;
|
|
44
|
+
jobProfiles;
|
|
45
|
+
constructor(config) {
|
|
46
|
+
super();
|
|
47
|
+
this.config = {
|
|
48
|
+
continueOnTestFail: false,
|
|
49
|
+
skipDocumenterIfNoChange: true,
|
|
50
|
+
maxIterations: 3,
|
|
51
|
+
...config,
|
|
52
|
+
};
|
|
53
|
+
// Initialize stuck detector
|
|
54
|
+
this.stuckDetector = createStuckDetector({
|
|
55
|
+
sameErrorRepeat: 2,
|
|
56
|
+
revisionLoop: 4,
|
|
57
|
+
});
|
|
58
|
+
this.jobProfiles = config.jobProfiles ?? [];
|
|
59
|
+
}
|
|
60
|
+
matchesProfile(task, profile) {
|
|
61
|
+
const estimate = task.estimatedMinutes ?? 0;
|
|
62
|
+
if (profile.minMinutes != null && estimate < profile.minMinutes)
|
|
63
|
+
return false;
|
|
64
|
+
if (profile.maxMinutes != null && estimate > profile.maxMinutes)
|
|
65
|
+
return false;
|
|
66
|
+
if (profile.priority != null && task.priority !== profile.priority)
|
|
67
|
+
return false;
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
getProfileForTask(task) {
|
|
71
|
+
if (!this.jobProfiles || this.jobProfiles.length === 0)
|
|
72
|
+
return undefined;
|
|
73
|
+
return this.jobProfiles.find((profile) => this.matchesProfile(task, profile));
|
|
74
|
+
}
|
|
75
|
+
getModelForRole(stage, task) {
|
|
76
|
+
const profile = this.getProfileForTask(task);
|
|
77
|
+
return profile?.roles?.[stage] || this.config.roles?.[stage]?.model;
|
|
78
|
+
}
|
|
79
|
+
// ============================================
|
|
80
|
+
// Main Execution
|
|
81
|
+
// ============================================
|
|
82
|
+
/**
|
|
83
|
+
* Run pipeline
|
|
84
|
+
*
|
|
85
|
+
* 1 iteration = full pass through Worker → Reviewer → Tester
|
|
86
|
+
* On failure at any stage, returns to Worker (up to maxIterations)
|
|
87
|
+
*/
|
|
88
|
+
async run(task, projectPath) {
|
|
89
|
+
const startTime = Date.now();
|
|
90
|
+
const stages = [];
|
|
91
|
+
const maxIterations = this.config.maxIterations ?? 3;
|
|
92
|
+
// Reset stuck detector (new pipeline run)
|
|
93
|
+
this.stuckDetector.reset();
|
|
94
|
+
// Ensure repo graph snapshot exists (first-time scan if needed)
|
|
95
|
+
if (!hasRepoSnapshot(projectPath)) {
|
|
96
|
+
console.log(`[Pipeline] No repo snapshot found, scanning ${projectPath}...`);
|
|
97
|
+
try {
|
|
98
|
+
await scanAndCache(projectPath);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
console.warn(`[Pipeline] Repo scan failed (non-blocking):`, e);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Create session
|
|
105
|
+
const session = agentPair.createPairSession({
|
|
106
|
+
taskId: task.issueIdentifier || task.issueId || task.id,
|
|
107
|
+
taskTitle: task.title,
|
|
108
|
+
taskDescription: task.description || '',
|
|
109
|
+
projectPath,
|
|
110
|
+
maxAttempts: maxIterations,
|
|
111
|
+
models: {
|
|
112
|
+
worker: this.config.roles?.worker?.model,
|
|
113
|
+
reviewer: this.config.roles?.reviewer?.model,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
const taskPrefix = buildTaskPrefix(task, projectPath);
|
|
117
|
+
const context = {
|
|
118
|
+
task,
|
|
119
|
+
projectPath,
|
|
120
|
+
session,
|
|
121
|
+
config: this.config,
|
|
122
|
+
currentIteration: 0,
|
|
123
|
+
taskPrefix,
|
|
124
|
+
};
|
|
125
|
+
try {
|
|
126
|
+
// Full iteration loop: Worker → Reviewer → Tester
|
|
127
|
+
const iterationResult = await this.runFullIterationLoop(context, stages);
|
|
128
|
+
if (!iterationResult.success) {
|
|
129
|
+
return this.buildResult(context, stages, startTime);
|
|
130
|
+
}
|
|
131
|
+
// Run Documenter after all stages pass
|
|
132
|
+
if (this.hasStage('documenter') && context.workerResult?.success) {
|
|
133
|
+
if (this.config.skipDocumenterIfNoChange &&
|
|
134
|
+
(!context.workerResult.filesChanged || context.workerResult.filesChanged.length === 0)) {
|
|
135
|
+
console.log(`[${context.taskPrefix}] Skipping documenter: no files changed`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const documenterResult = await this.runStage('documenter', context);
|
|
139
|
+
stages.push(documenterResult);
|
|
140
|
+
// Documenter failure does not cause overall failure
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Auditor (post-success, non-blocking)
|
|
144
|
+
if (this.hasStage('auditor') && context.workerResult?.success) {
|
|
145
|
+
const auditorFileThreshold = this.config.skipAuditorUnderFileCount ?? 3;
|
|
146
|
+
const auditorChangedFiles = context.workerResult.filesChanged || [];
|
|
147
|
+
if (auditorChangedFiles.length < auditorFileThreshold) {
|
|
148
|
+
console.log(`[${context.taskPrefix}] Skipping auditor: ${auditorChangedFiles.length} files changed (threshold: ${auditorFileThreshold})`);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
const auditorResult = await this.runStage('auditor', context);
|
|
152
|
+
stages.push(auditorResult);
|
|
153
|
+
// Auditor failure does not affect overall success
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Skill Documenter (post-success, non-blocking)
|
|
157
|
+
if (this.hasStage('skill-documenter') && context.workerResult?.success) {
|
|
158
|
+
const sdResult = await this.runStage('skill-documenter', context);
|
|
159
|
+
stages.push(sdResult);
|
|
160
|
+
// Skill Documenter failure does not affect overall success
|
|
161
|
+
}
|
|
162
|
+
// Success
|
|
163
|
+
agentPair.updateSessionStatus(session.id, 'approved');
|
|
164
|
+
return this.buildResult(context, stages, startTime);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error(`[${context.taskPrefix}] Error:`, error);
|
|
168
|
+
agentPair.updateSessionStatus(session.id, 'failed');
|
|
169
|
+
return {
|
|
170
|
+
success: false,
|
|
171
|
+
sessionId: session.id,
|
|
172
|
+
stages,
|
|
173
|
+
finalStatus: 'failed',
|
|
174
|
+
totalDuration: Date.now() - startTime,
|
|
175
|
+
iterations: context.currentIteration,
|
|
176
|
+
workerResult: context.workerResult,
|
|
177
|
+
reviewResult: context.reviewResult,
|
|
178
|
+
testerResult: context.testerResult,
|
|
179
|
+
documenterResult: context.documenterResult,
|
|
180
|
+
taskContext: {
|
|
181
|
+
issueIdentifier: context.task.issueIdentifier || context.task.issueId,
|
|
182
|
+
projectName: context.task.linearProject?.name,
|
|
183
|
+
projectPath: context.projectPath,
|
|
184
|
+
taskTitle: context.task.title,
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// ============================================
|
|
190
|
+
// Stage Execution
|
|
191
|
+
// ============================================
|
|
192
|
+
/**
|
|
193
|
+
* Check if a stage is enabled
|
|
194
|
+
*/
|
|
195
|
+
hasStage(stage) {
|
|
196
|
+
return this.config.stages.includes(stage);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Run a single stage
|
|
200
|
+
*/
|
|
201
|
+
async runStage(stage, context, overrides) {
|
|
202
|
+
const startTime = Date.now();
|
|
203
|
+
const stageModel = overrides?.model ?? this.getModelForRole(stage, context.task);
|
|
204
|
+
const prefix = context.taskPrefix;
|
|
205
|
+
console.log(`[${prefix}] Stage starting: ${stage}`);
|
|
206
|
+
this.emit('stage:start', { stage, context });
|
|
207
|
+
broadcastEvent({ type: 'pipeline:stage', data: { taskId: context.task.id, stage, status: 'start', model: stageModel } });
|
|
208
|
+
if (this.config.verbose) {
|
|
209
|
+
this.emit('log', { line: `[verbose] Stage: ${stage} | model: ${stageModel ?? 'default'} | iteration: ${context.currentIteration}` });
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
let result;
|
|
213
|
+
switch (stage) {
|
|
214
|
+
case 'worker': {
|
|
215
|
+
agentPair.updateSessionStatus(context.session.id, 'working');
|
|
216
|
+
const taskId = context.task.id;
|
|
217
|
+
const onLog = (line) => broadcastEvent({ type: 'log', data: { taskId, stage: 'worker', line: `[${prefix}] ${line}` } });
|
|
218
|
+
// Check if fresh context should be used (after N failures)
|
|
219
|
+
const useFreshContext = agentPair.shouldUseFreshContext(context.session.id);
|
|
220
|
+
if (useFreshContext) {
|
|
221
|
+
console.log(`[${prefix}] Using fresh context for worker (retry with clean slate)`);
|
|
222
|
+
agentPair.consumeFreshContext(context.session.id);
|
|
223
|
+
onLog('🔄 Using fresh context (previous attempts failed)');
|
|
224
|
+
}
|
|
225
|
+
result = await workerAgent.runWorker({
|
|
226
|
+
taskTitle: context.task.title,
|
|
227
|
+
taskDescription: context.task.description || '',
|
|
228
|
+
projectPath: context.projectPath,
|
|
229
|
+
previousFeedback: useFreshContext
|
|
230
|
+
? undefined // Fresh context: no previous feedback
|
|
231
|
+
: (context.reviewResult
|
|
232
|
+
? reviewerAgent.buildRevisionPrompt(context.reviewResult)
|
|
233
|
+
: undefined),
|
|
234
|
+
timeoutMs: this.config.roles?.worker?.timeoutMs ?? 0,
|
|
235
|
+
model: overrides?.model ?? this.config.roles?.worker?.model,
|
|
236
|
+
maxTurns: this.config.roles?.worker?.maxTurns,
|
|
237
|
+
adapterName: this.config.roles?.worker?.adapter,
|
|
238
|
+
issueIdentifier: context.task.issueIdentifier || context.task.issueId,
|
|
239
|
+
projectName: context.task.linearProject?.name,
|
|
240
|
+
onLog,
|
|
241
|
+
processContext: { taskId: context.task.id, stage: 'worker' },
|
|
242
|
+
});
|
|
243
|
+
agentPair.saveWorkerResult(context.session.id, result);
|
|
244
|
+
context.workerResult = result;
|
|
245
|
+
// Verbose: emit detailed worker result info
|
|
246
|
+
if (this.config.verbose) {
|
|
247
|
+
const wr = result;
|
|
248
|
+
if (wr.filesChanged?.length) {
|
|
249
|
+
this.emit('log', { line: `[verbose] Files changed: ${wr.filesChanged.join(', ')}` });
|
|
250
|
+
}
|
|
251
|
+
if (wr.commands?.length) {
|
|
252
|
+
this.emit('log', { line: `[verbose] Commands executed: ${wr.commands.join('; ')}` });
|
|
253
|
+
}
|
|
254
|
+
if (wr.confidencePercent != null) {
|
|
255
|
+
this.emit('log', { line: `[verbose] Worker confidence: ${wr.confidencePercent}%` });
|
|
256
|
+
}
|
|
257
|
+
if (wr.haltReason) {
|
|
258
|
+
this.emit('log', { line: `[verbose] Worker halt reason: ${wr.haltReason}` });
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// Track confidence and check for degradation
|
|
262
|
+
const attempt = context.session.worker.attempts;
|
|
263
|
+
agentPair.updateConfidenceTracker(context.session.id, result, attempt);
|
|
264
|
+
// Check if confidence intervention is needed
|
|
265
|
+
if (agentPair.needsConfidenceIntervention(context.session.id)) {
|
|
266
|
+
console.warn(`[${prefix}] Confidence intervention needed - early review triggered`);
|
|
267
|
+
const summary = agentPair.getConfidenceSummary(context.session.id);
|
|
268
|
+
this.emit('log', { line: `⚠️ Low confidence detected: ${summary}` });
|
|
269
|
+
// Continue to review, but reviewer should be aware of low confidence
|
|
270
|
+
}
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
case 'reviewer':
|
|
274
|
+
agentPair.updateSessionStatus(context.session.id, 'reviewing');
|
|
275
|
+
if (!context.workerResult) {
|
|
276
|
+
throw new Error('Worker result required for reviewer');
|
|
277
|
+
}
|
|
278
|
+
// Pre-check disabled - Haiku format compliance issues causing false rejections
|
|
279
|
+
// Proceed directly to full Sonnet review for reliability
|
|
280
|
+
// Reduce review depth when worker confidence is very high
|
|
281
|
+
let reviewerMaxTurns = this.config.roles?.reviewer?.maxTurns;
|
|
282
|
+
if (context.workerResult?.confidencePercent && context.workerResult.confidencePercent > 90) {
|
|
283
|
+
const cappedTurns = Math.min(reviewerMaxTurns ?? 10, 5);
|
|
284
|
+
console.log(`[${prefix}] High worker confidence (${context.workerResult.confidencePercent}%), limiting reviewer to ${cappedTurns} turns`);
|
|
285
|
+
reviewerMaxTurns = cappedTurns;
|
|
286
|
+
}
|
|
287
|
+
console.log(`[${prefix}] Running full review (Sonnet)...`);
|
|
288
|
+
result = await reviewerAgent.runReviewer({
|
|
289
|
+
taskTitle: context.task.title,
|
|
290
|
+
taskDescription: context.task.description || '',
|
|
291
|
+
workerResult: context.workerResult,
|
|
292
|
+
projectPath: context.projectPath,
|
|
293
|
+
timeoutMs: this.config.roles?.reviewer?.timeoutMs ?? 0,
|
|
294
|
+
model: this.config.roles?.reviewer?.model,
|
|
295
|
+
maxTurns: reviewerMaxTurns,
|
|
296
|
+
adapterName: this.config.roles?.reviewer?.adapter,
|
|
297
|
+
processContext: { taskId: context.task.id, stage: 'reviewer' },
|
|
298
|
+
});
|
|
299
|
+
agentPair.saveReviewerResult(context.session.id, result);
|
|
300
|
+
context.reviewResult = result;
|
|
301
|
+
// Verbose: emit reviewer decision details
|
|
302
|
+
if (this.config.verbose) {
|
|
303
|
+
const rr = result;
|
|
304
|
+
this.emit('log', { line: `[verbose] Reviewer decision: ${rr.decision}` });
|
|
305
|
+
if (rr.feedback) {
|
|
306
|
+
const lines = rr.feedback.split('\n').slice(0, 10);
|
|
307
|
+
for (const line of lines) {
|
|
308
|
+
this.emit('log', { line: `[verbose] ${line}` });
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
break;
|
|
313
|
+
case 'tester':
|
|
314
|
+
if (!context.workerResult) {
|
|
315
|
+
throw new Error('Worker result required for tester');
|
|
316
|
+
}
|
|
317
|
+
result = await testerAgent.runTester({
|
|
318
|
+
taskTitle: context.task.title,
|
|
319
|
+
taskDescription: context.task.description || '',
|
|
320
|
+
workerResult: context.workerResult,
|
|
321
|
+
projectPath: context.projectPath,
|
|
322
|
+
timeoutMs: this.config.roles?.tester?.timeoutMs ?? 0,
|
|
323
|
+
model: this.config.roles?.tester?.model,
|
|
324
|
+
maxTurns: this.config.roles?.tester?.maxTurns,
|
|
325
|
+
adapterName: this.config.roles?.tester?.adapter,
|
|
326
|
+
});
|
|
327
|
+
context.testerResult = result;
|
|
328
|
+
// Verbose: emit tester details
|
|
329
|
+
if (this.config.verbose) {
|
|
330
|
+
const tr = result;
|
|
331
|
+
this.emit('log', { line: `[verbose] Tests passed: ${tr.testsPassed}, failed: ${tr.testsFailed}${tr.coverage != null ? `, coverage: ${tr.coverage}%` : ''}` });
|
|
332
|
+
}
|
|
333
|
+
break;
|
|
334
|
+
case 'documenter':
|
|
335
|
+
if (!context.workerResult) {
|
|
336
|
+
throw new Error('Worker result required for documenter');
|
|
337
|
+
}
|
|
338
|
+
result = await documenterAgent.runDocumenter({
|
|
339
|
+
taskTitle: context.task.title,
|
|
340
|
+
taskDescription: context.task.description || '',
|
|
341
|
+
workerResult: context.workerResult,
|
|
342
|
+
projectPath: context.projectPath,
|
|
343
|
+
timeoutMs: this.config.roles?.documenter?.timeoutMs ?? 0,
|
|
344
|
+
model: this.config.roles?.documenter?.model,
|
|
345
|
+
maxTurns: this.config.roles?.documenter?.maxTurns,
|
|
346
|
+
adapterName: this.config.roles?.documenter?.adapter,
|
|
347
|
+
});
|
|
348
|
+
context.documenterResult = result;
|
|
349
|
+
break;
|
|
350
|
+
case 'auditor':
|
|
351
|
+
if (!context.workerResult) {
|
|
352
|
+
throw new Error('Worker result required for auditor');
|
|
353
|
+
}
|
|
354
|
+
result = await auditorAgent.runAuditor({
|
|
355
|
+
taskTitle: context.task.title,
|
|
356
|
+
taskDescription: context.task.description || '',
|
|
357
|
+
workerResult: context.workerResult,
|
|
358
|
+
projectPath: context.projectPath,
|
|
359
|
+
timeoutMs: this.config.roles?.auditor?.timeoutMs ?? 0,
|
|
360
|
+
model: this.config.roles?.auditor?.model,
|
|
361
|
+
maxTurns: this.config.roles?.auditor?.maxTurns,
|
|
362
|
+
adapterName: this.config.roles?.auditor?.adapter,
|
|
363
|
+
});
|
|
364
|
+
context.auditorResult = result;
|
|
365
|
+
break;
|
|
366
|
+
case 'skill-documenter':
|
|
367
|
+
if (!context.workerResult) {
|
|
368
|
+
throw new Error('Worker result required for skill-documenter');
|
|
369
|
+
}
|
|
370
|
+
result = await skillDocumenterAgent.runSkillDocumenter({
|
|
371
|
+
taskTitle: context.task.title,
|
|
372
|
+
taskDescription: context.task.description || '',
|
|
373
|
+
workerResult: context.workerResult,
|
|
374
|
+
projectPath: context.projectPath,
|
|
375
|
+
timeoutMs: this.config.roles?.['skill-documenter']?.timeoutMs ?? 0,
|
|
376
|
+
model: this.config.roles?.['skill-documenter']?.model,
|
|
377
|
+
maxTurns: this.config.roles?.['skill-documenter']?.maxTurns,
|
|
378
|
+
adapterName: this.config.roles?.['skill-documenter']?.adapter,
|
|
379
|
+
});
|
|
380
|
+
context.skillDocumenterResult = result;
|
|
381
|
+
break;
|
|
382
|
+
default:
|
|
383
|
+
throw new Error(`Unknown stage: ${stage}`);
|
|
384
|
+
}
|
|
385
|
+
const completedAt = Date.now();
|
|
386
|
+
const stageResult = {
|
|
387
|
+
stage,
|
|
388
|
+
success: this.isStageSuccess(stage, result),
|
|
389
|
+
result,
|
|
390
|
+
duration: completedAt - startTime,
|
|
391
|
+
startedAt: startTime,
|
|
392
|
+
completedAt,
|
|
393
|
+
};
|
|
394
|
+
console.log(`[${prefix}] ${stage} completed (${(stageResult.duration / 1000).toFixed(1)}s)`);
|
|
395
|
+
this.emit('stage:complete', { stage, result: stageResult, context });
|
|
396
|
+
const costInfo = result.costInfo;
|
|
397
|
+
if (this.config.verbose) {
|
|
398
|
+
this.emit('log', { line: `[verbose] Stage ${stage} completed in ${(stageResult.duration / 1000).toFixed(1)}s${costInfo ? ` | cost: $${costInfo.costUsd.toFixed(4)} (${costInfo.inputTokens}in/${costInfo.outputTokens}out)` : ''}` });
|
|
399
|
+
}
|
|
400
|
+
broadcastEvent({ type: 'pipeline:stage', data: {
|
|
401
|
+
taskId: context.task.id, stage, status: 'complete',
|
|
402
|
+
model: costInfo?.model,
|
|
403
|
+
inputTokens: costInfo?.inputTokens,
|
|
404
|
+
outputTokens: costInfo?.outputTokens,
|
|
405
|
+
costUsd: costInfo?.costUsd,
|
|
406
|
+
} });
|
|
407
|
+
return stageResult;
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
const completedAt = Date.now();
|
|
411
|
+
const stageResult = {
|
|
412
|
+
stage,
|
|
413
|
+
success: false,
|
|
414
|
+
result: {
|
|
415
|
+
success: false,
|
|
416
|
+
error: error instanceof Error ? error.message : String(error),
|
|
417
|
+
},
|
|
418
|
+
duration: completedAt - startTime,
|
|
419
|
+
startedAt: startTime,
|
|
420
|
+
completedAt,
|
|
421
|
+
};
|
|
422
|
+
console.log(`[${prefix}] ${stage} failed (${(stageResult.duration / 1000).toFixed(1)}s)`);
|
|
423
|
+
this.emit('stage:fail', { stage, result: stageResult, context, error });
|
|
424
|
+
broadcastEvent({ type: 'pipeline:stage', data: { taskId: context.task.id, stage, status: 'fail' } });
|
|
425
|
+
return stageResult;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Determine stage success
|
|
430
|
+
*/
|
|
431
|
+
isStageSuccess(stage, result) {
|
|
432
|
+
switch (stage) {
|
|
433
|
+
case 'worker':
|
|
434
|
+
return result.success;
|
|
435
|
+
case 'reviewer':
|
|
436
|
+
return result.decision === 'approve';
|
|
437
|
+
case 'tester':
|
|
438
|
+
return result.success;
|
|
439
|
+
case 'documenter':
|
|
440
|
+
return result.success;
|
|
441
|
+
case 'auditor':
|
|
442
|
+
return result.success;
|
|
443
|
+
case 'skill-documenter':
|
|
444
|
+
return result.success;
|
|
445
|
+
default:
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// ============================================
|
|
450
|
+
// Full Iteration Loop
|
|
451
|
+
// ============================================
|
|
452
|
+
/**
|
|
453
|
+
* Full iteration loop
|
|
454
|
+
*
|
|
455
|
+
* 1 iteration = full pass through Worker → Reviewer → Tester
|
|
456
|
+
* On failure (revise) at any stage, restart from Worker in next iteration
|
|
457
|
+
* reject = immediate termination
|
|
458
|
+
*/
|
|
459
|
+
async runFullIterationLoop(context, stages) {
|
|
460
|
+
const maxIterations = this.config.maxIterations ?? 3;
|
|
461
|
+
const hasWorker = this.hasStage('worker');
|
|
462
|
+
const hasReviewer = this.hasStage('reviewer');
|
|
463
|
+
const hasTester = this.hasStage('tester');
|
|
464
|
+
// No point without a worker
|
|
465
|
+
if (!hasWorker) {
|
|
466
|
+
console.log(`[${context.taskPrefix}] No worker stage configured`);
|
|
467
|
+
return { success: false };
|
|
468
|
+
}
|
|
469
|
+
while (context.currentIteration < maxIterations) {
|
|
470
|
+
context.currentIteration++;
|
|
471
|
+
// Stuck detection check (before iteration starts)
|
|
472
|
+
const stuckCheck = this.stuckDetector.check();
|
|
473
|
+
if (stuckCheck.isStuck) {
|
|
474
|
+
console.error(`[${context.taskPrefix}] STUCK DETECTED: ${stuckCheck.reason}`);
|
|
475
|
+
console.error(`[${context.taskPrefix}] Suggestion: ${stuckCheck.suggestion}`);
|
|
476
|
+
this.emit('stuck', {
|
|
477
|
+
reason: stuckCheck.reason,
|
|
478
|
+
suggestion: stuckCheck.suggestion,
|
|
479
|
+
context,
|
|
480
|
+
});
|
|
481
|
+
agentPair.updateSessionStatus(context.session.id, 'failed');
|
|
482
|
+
return { success: false };
|
|
483
|
+
}
|
|
484
|
+
this.emit('iteration:start', {
|
|
485
|
+
iteration: context.currentIteration,
|
|
486
|
+
maxIterations,
|
|
487
|
+
context,
|
|
488
|
+
});
|
|
489
|
+
broadcastEvent({ type: 'pipeline:iteration', data: { taskId: context.task.id, iteration: context.currentIteration } });
|
|
490
|
+
console.log(`[${context.taskPrefix}] Iteration ${context.currentIteration}/${maxIterations}`);
|
|
491
|
+
// ========== WORKER (with escalation) ==========
|
|
492
|
+
const workerCfg = this.config.roles?.worker;
|
|
493
|
+
const escalateThreshold = workerCfg?.escalateAfterIteration ?? 3;
|
|
494
|
+
const shouldEscalate = context.currentIteration >= escalateThreshold && !!workerCfg?.escalateModel;
|
|
495
|
+
const baseWorkerModel = this.getModelForRole('worker', context.task);
|
|
496
|
+
const workerOverrides = shouldEscalate
|
|
497
|
+
? { model: workerCfg.escalateModel }
|
|
498
|
+
: (baseWorkerModel ? { model: baseWorkerModel } : undefined);
|
|
499
|
+
if (shouldEscalate) {
|
|
500
|
+
console.log(`[${context.taskPrefix}] Escalating worker model → ${workerCfg.escalateModel} (iteration ${context.currentIteration})`);
|
|
501
|
+
broadcastEvent({ type: 'pipeline:escalation', data: {
|
|
502
|
+
taskId: context.task.id,
|
|
503
|
+
iteration: context.currentIteration,
|
|
504
|
+
fromModel: workerCfg?.model,
|
|
505
|
+
toModel: workerCfg.escalateModel,
|
|
506
|
+
} });
|
|
507
|
+
}
|
|
508
|
+
agentPair.updateSessionStatus(context.session.id, 'working');
|
|
509
|
+
const workerResult = await this.runStage('worker', context, workerOverrides);
|
|
510
|
+
stages.push(workerResult);
|
|
511
|
+
// Record Worker result in stuck detector
|
|
512
|
+
this.stuckDetector.addEntry({
|
|
513
|
+
stage: 'worker',
|
|
514
|
+
success: workerResult.success,
|
|
515
|
+
output: workerResult.result.summary,
|
|
516
|
+
error: workerResult.result.error,
|
|
517
|
+
timestamp: Date.now(),
|
|
518
|
+
});
|
|
519
|
+
if (!workerResult.success) {
|
|
520
|
+
console.log(`[${context.taskPrefix}] Worker failed, retrying...`);
|
|
521
|
+
agentPair.trackFailure(context.session.id); // Track for fresh context decision
|
|
522
|
+
this.emit('iteration:fail', {
|
|
523
|
+
iteration: context.currentIteration,
|
|
524
|
+
stage: 'worker',
|
|
525
|
+
context,
|
|
526
|
+
});
|
|
527
|
+
continue; // Next iteration
|
|
528
|
+
}
|
|
529
|
+
// ========== PIPELINE GUARDS (post-worker, pre-reviewer) ==========
|
|
530
|
+
if (this.config.guards && context.workerResult) {
|
|
531
|
+
console.log(`[${context.taskPrefix}] Running pipeline guards...`);
|
|
532
|
+
const guardsResult = await runGuards(context.workerResult, context.projectPath, this.config.guards);
|
|
533
|
+
context.guardsResult = guardsResult;
|
|
534
|
+
if (!guardsResult.allPassed) {
|
|
535
|
+
// Blocking guard failed → inject revise, skip reviewer
|
|
536
|
+
console.log(`[${context.taskPrefix}] Blocking guard failed: ${guardsResult.combinedIssues.join('; ')}`);
|
|
537
|
+
context.reviewResult = {
|
|
538
|
+
decision: 'revise',
|
|
539
|
+
feedback: `Pipeline guard failed: ${guardsResult.combinedIssues.join('; ')}`,
|
|
540
|
+
issues: guardsResult.combinedIssues,
|
|
541
|
+
suggestions: ['Fix the issues flagged by quality guards'],
|
|
542
|
+
};
|
|
543
|
+
agentPair.trackFailure(context.session.id);
|
|
544
|
+
this.emit('iteration:fail', {
|
|
545
|
+
iteration: context.currentIteration,
|
|
546
|
+
stage: 'worker',
|
|
547
|
+
context,
|
|
548
|
+
});
|
|
549
|
+
agentPair.updateSessionStatus(context.session.id, 'revising');
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
// Log non-blocking guard warnings
|
|
553
|
+
const warnings = guardsResult.results.filter(r => !r.passed && !r.blocking);
|
|
554
|
+
if (warnings.length > 0) {
|
|
555
|
+
console.log(`[${context.taskPrefix}] Guard warnings: ${warnings.map(w => w.guard).join(', ')}`);
|
|
556
|
+
this.emit('log', {
|
|
557
|
+
line: `⚠️ Guard warnings: ${warnings.flatMap(w => w.issues).join('; ')}`,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
// ========== HALT CHECK (confidence too low) ==========
|
|
562
|
+
if (context.workerResult) {
|
|
563
|
+
const confidence = agentPair.calculateConfidence(context.workerResult);
|
|
564
|
+
if (confidence < CONFIDENCE_THRESHOLDS.HALT) {
|
|
565
|
+
const haltReason = context.workerResult.haltReason
|
|
566
|
+
|| `Low confidence: ${confidence}%`;
|
|
567
|
+
console.warn(`[${context.taskPrefix}] HALT triggered: confidence=${confidence}%, reason=${haltReason}`);
|
|
568
|
+
this.emit('halt', {
|
|
569
|
+
confidence,
|
|
570
|
+
haltReason,
|
|
571
|
+
sessionId: context.session.id,
|
|
572
|
+
iteration: context.currentIteration,
|
|
573
|
+
context,
|
|
574
|
+
});
|
|
575
|
+
// Inject revise to retry
|
|
576
|
+
context.reviewResult = {
|
|
577
|
+
decision: 'revise',
|
|
578
|
+
feedback: `[HALT] Confidence too low (${confidence}%). ${haltReason}`,
|
|
579
|
+
issues: [haltReason],
|
|
580
|
+
suggestions: ['Review task requirements', 'Provide additional context', 'Break into sub-tasks'],
|
|
581
|
+
};
|
|
582
|
+
agentPair.trackFailure(context.session.id);
|
|
583
|
+
this.emit('iteration:fail', {
|
|
584
|
+
iteration: context.currentIteration,
|
|
585
|
+
stage: 'worker',
|
|
586
|
+
context,
|
|
587
|
+
});
|
|
588
|
+
agentPair.updateSessionStatus(context.session.id, 'revising');
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
// ========== REVIEWER ==========
|
|
593
|
+
if (hasReviewer) {
|
|
594
|
+
agentPair.updateSessionStatus(context.session.id, 'reviewing');
|
|
595
|
+
const reviewerResult = await this.runStage('reviewer', context);
|
|
596
|
+
stages.push(reviewerResult);
|
|
597
|
+
const decision = reviewerResult.result.decision;
|
|
598
|
+
// Record Reviewer result in stuck detector
|
|
599
|
+
this.stuckDetector.addEntry({
|
|
600
|
+
stage: 'reviewer',
|
|
601
|
+
success: reviewerResult.success,
|
|
602
|
+
decision: decision,
|
|
603
|
+
output: reviewerResult.result.feedback,
|
|
604
|
+
timestamp: Date.now(),
|
|
605
|
+
});
|
|
606
|
+
if (decision === 'reject') {
|
|
607
|
+
// reject = terminate immediately
|
|
608
|
+
console.log(`[${context.taskPrefix}] Reviewer rejected`);
|
|
609
|
+
agentPair.updateSessionStatus(context.session.id, 'rejected');
|
|
610
|
+
return { success: false };
|
|
611
|
+
}
|
|
612
|
+
if (decision === 'revise') {
|
|
613
|
+
// revise = next iteration
|
|
614
|
+
console.log(`[${context.taskPrefix}] Reviewer requested revision`);
|
|
615
|
+
agentPair.trackFailure(context.session.id); // Track for fresh context decision
|
|
616
|
+
this.emit('iteration:fail', {
|
|
617
|
+
iteration: context.currentIteration,
|
|
618
|
+
stage: 'reviewer',
|
|
619
|
+
context,
|
|
620
|
+
});
|
|
621
|
+
agentPair.updateSessionStatus(context.session.id, 'revising');
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
// approve → proceed to Tester
|
|
625
|
+
agentPair.resetFailureStreak(context.session.id); // Reset on approval
|
|
626
|
+
}
|
|
627
|
+
// ========== TESTER ==========
|
|
628
|
+
if (hasTester) {
|
|
629
|
+
// Skip tester if no code files changed (configurable, default true)
|
|
630
|
+
const skipIfNoCode = this.config.skipTesterIfNoCodeChange ?? true;
|
|
631
|
+
const codeExtensions = /\.(ts|tsx|js|jsx|py|rs|go|java|rb|c|cpp|h|hpp)$/;
|
|
632
|
+
const changedFiles = context.workerResult?.filesChanged || [];
|
|
633
|
+
const hasCodeChange = changedFiles.some(f => codeExtensions.test(f));
|
|
634
|
+
if (skipIfNoCode && !hasCodeChange) {
|
|
635
|
+
console.log(`[${context.taskPrefix}] Skipping tester: no code files changed (${changedFiles.length} files: ${changedFiles.join(', ') || 'none'})`);
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
const testerResult = await this.runStage('tester', context);
|
|
639
|
+
stages.push(testerResult);
|
|
640
|
+
if (!testerResult.success && !this.config.continueOnTestFail) {
|
|
641
|
+
// Test failed → set feedback then next iteration
|
|
642
|
+
console.log(`[${context.taskPrefix}] Tester failed, retrying...`);
|
|
643
|
+
agentPair.trackFailure(context.session.id); // Track for fresh context decision
|
|
644
|
+
if (context.testerResult) {
|
|
645
|
+
context.reviewResult = {
|
|
646
|
+
decision: 'revise',
|
|
647
|
+
feedback: testerAgent.buildTestFixPrompt(context.testerResult),
|
|
648
|
+
issues: context.testerResult.failedTests,
|
|
649
|
+
suggestions: context.testerResult.suggestions,
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
this.emit('iteration:fail', {
|
|
653
|
+
iteration: context.currentIteration,
|
|
654
|
+
stage: 'tester',
|
|
655
|
+
context,
|
|
656
|
+
});
|
|
657
|
+
agentPair.updateSessionStatus(context.session.id, 'revising');
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
} // end else (has code change)
|
|
661
|
+
}
|
|
662
|
+
// ========== ALL PASSED ==========
|
|
663
|
+
console.log(`[${context.taskPrefix}] Iteration ${context.currentIteration} completed successfully`);
|
|
664
|
+
this.emit('iteration:complete', {
|
|
665
|
+
iteration: context.currentIteration,
|
|
666
|
+
context,
|
|
667
|
+
});
|
|
668
|
+
return { success: true };
|
|
669
|
+
}
|
|
670
|
+
// maxIterations exceeded
|
|
671
|
+
console.log(`[${context.taskPrefix}] Max iterations (${maxIterations}) exceeded`);
|
|
672
|
+
agentPair.updateSessionStatus(context.session.id, 'failed');
|
|
673
|
+
return { success: false };
|
|
674
|
+
}
|
|
675
|
+
// ============================================
|
|
676
|
+
// Result Building
|
|
677
|
+
// ============================================
|
|
678
|
+
/**
|
|
679
|
+
* Build pipeline result
|
|
680
|
+
*/
|
|
681
|
+
buildResult(context, stages, startTime) {
|
|
682
|
+
// Use context.session directly — do NOT re-fetch from store.
|
|
683
|
+
// updateSessionStatus('approved') archives the session (deletes from Map),
|
|
684
|
+
// so getPairSession() would return undefined → finalStatus = 'failed'.
|
|
685
|
+
const session = context.session;
|
|
686
|
+
const finalStatus = session.status || 'failed';
|
|
687
|
+
const success = finalStatus === 'approved';
|
|
688
|
+
// Aggregate costs from all stages
|
|
689
|
+
const stageCosts = [];
|
|
690
|
+
if (context.workerResult?.costInfo)
|
|
691
|
+
stageCosts.push(context.workerResult.costInfo);
|
|
692
|
+
if (context.reviewResult?.costInfo)
|
|
693
|
+
stageCosts.push(context.reviewResult.costInfo);
|
|
694
|
+
if (context.testerResult?.costInfo)
|
|
695
|
+
stageCosts.push(context.testerResult.costInfo);
|
|
696
|
+
if (context.documenterResult?.costInfo)
|
|
697
|
+
stageCosts.push(context.documenterResult.costInfo);
|
|
698
|
+
if (context.auditorResult?.costInfo)
|
|
699
|
+
stageCosts.push(context.auditorResult.costInfo);
|
|
700
|
+
if (context.skillDocumenterResult?.costInfo)
|
|
701
|
+
stageCosts.push(context.skillDocumenterResult.costInfo);
|
|
702
|
+
const totalCost = stageCosts.length > 0 ? aggregateCosts(stageCosts) : undefined;
|
|
703
|
+
if (totalCost) {
|
|
704
|
+
console.log(`[${context.taskPrefix}] Total cost: ${formatCost(totalCost)}`);
|
|
705
|
+
broadcastEvent({ type: 'task:cost', data: { taskId: context.task.id, cost: totalCost } });
|
|
706
|
+
}
|
|
707
|
+
const result = {
|
|
708
|
+
success,
|
|
709
|
+
sessionId: context.session.id,
|
|
710
|
+
stages,
|
|
711
|
+
finalStatus,
|
|
712
|
+
totalDuration: Date.now() - startTime,
|
|
713
|
+
iterations: context.currentIteration,
|
|
714
|
+
workerResult: context.workerResult,
|
|
715
|
+
reviewResult: context.reviewResult,
|
|
716
|
+
testerResult: context.testerResult,
|
|
717
|
+
documenterResult: context.documenterResult,
|
|
718
|
+
auditorResult: context.auditorResult,
|
|
719
|
+
skillDocumenterResult: context.skillDocumenterResult,
|
|
720
|
+
taskContext: {
|
|
721
|
+
issueIdentifier: context.task.issueIdentifier || context.task.issueId,
|
|
722
|
+
projectName: context.task.linearProject?.name,
|
|
723
|
+
projectPath: context.projectPath,
|
|
724
|
+
taskTitle: context.task.title,
|
|
725
|
+
},
|
|
726
|
+
totalCost,
|
|
727
|
+
};
|
|
728
|
+
if (success) {
|
|
729
|
+
this.emit('pipeline:complete', result);
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
this.emit('pipeline:fail', result);
|
|
733
|
+
}
|
|
734
|
+
return result;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
// Factory Functions
|
|
738
|
+
/**
|
|
739
|
+
* Create default pipeline (Worker + Reviewer)
|
|
740
|
+
*/
|
|
741
|
+
export function createDefaultPipeline(maxIterations = 3) {
|
|
742
|
+
return new PairPipeline({
|
|
743
|
+
stages: ['worker', 'reviewer'],
|
|
744
|
+
maxIterations,
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Create full pipeline (Worker + Reviewer + Tester + Documenter)
|
|
749
|
+
*/
|
|
750
|
+
export function createFullPipeline(config) {
|
|
751
|
+
return new PairPipeline({
|
|
752
|
+
stages: ['worker', 'reviewer', 'tester', 'documenter'],
|
|
753
|
+
maxIterations: 3,
|
|
754
|
+
continueOnTestFail: false,
|
|
755
|
+
skipDocumenterIfNoChange: true,
|
|
756
|
+
...config,
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Create pipeline from configuration
|
|
761
|
+
*/
|
|
762
|
+
export function createPipelineFromConfig(roles, maxIterations = 3, guards, jobProfiles) {
|
|
763
|
+
const stages = [];
|
|
764
|
+
if (roles?.worker?.enabled !== false) {
|
|
765
|
+
stages.push('worker');
|
|
766
|
+
}
|
|
767
|
+
if (roles?.reviewer?.enabled !== false) {
|
|
768
|
+
stages.push('reviewer');
|
|
769
|
+
}
|
|
770
|
+
if (roles?.tester?.enabled) {
|
|
771
|
+
stages.push('tester');
|
|
772
|
+
}
|
|
773
|
+
if (roles?.documenter?.enabled) {
|
|
774
|
+
stages.push('documenter');
|
|
775
|
+
}
|
|
776
|
+
if (roles?.auditor?.enabled) {
|
|
777
|
+
stages.push('auditor');
|
|
778
|
+
}
|
|
779
|
+
if (roles?.['skill-documenter']?.enabled) {
|
|
780
|
+
stages.push('skill-documenter');
|
|
781
|
+
}
|
|
782
|
+
return new PairPipeline({
|
|
783
|
+
stages,
|
|
784
|
+
maxIterations,
|
|
785
|
+
roles,
|
|
786
|
+
guards,
|
|
787
|
+
jobProfiles,
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
// Helpers
|
|
791
|
+
// Re-export formatting functions (extracted to pipelineFormat.ts)
|
|
792
|
+
export { formatPipelineResult, formatPipelineResultEmbed } from './pipelineFormat.js';
|
|
793
|
+
//# sourceMappingURL=pairPipeline.js.map
|