@intrect/openswarm 0.9.3 → 0.10.1
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/README.md +76 -1
- package/config.example.yaml +6 -0
- package/dist/adapters/agenticLoop.d.ts +24 -0
- package/dist/adapters/agenticLoop.d.ts.map +1 -1
- package/dist/adapters/agenticLoop.js +130 -11
- package/dist/adapters/agenticLoop.js.map +1 -1
- package/dist/adapters/applyPatch.d.ts +21 -0
- package/dist/adapters/applyPatch.d.ts.map +1 -0
- package/dist/adapters/applyPatch.js +175 -0
- package/dist/adapters/applyPatch.js.map +1 -0
- package/dist/adapters/base.d.ts.map +1 -1
- package/dist/adapters/base.js +7 -0
- package/dist/adapters/base.js.map +1 -1
- package/dist/adapters/codex.js +10 -0
- package/dist/adapters/codex.js.map +1 -1
- package/dist/adapters/codexResponses.d.ts +8 -0
- package/dist/adapters/codexResponses.d.ts.map +1 -1
- package/dist/adapters/codexResponses.js +86 -8
- package/dist/adapters/codexResponses.js.map +1 -1
- package/dist/adapters/errorClassification.d.ts +8 -0
- package/dist/adapters/errorClassification.d.ts.map +1 -0
- package/dist/adapters/errorClassification.js +54 -0
- package/dist/adapters/errorClassification.js.map +1 -0
- package/dist/adapters/gpt.d.ts.map +1 -1
- package/dist/adapters/gpt.js +12 -1
- package/dist/adapters/gpt.js.map +1 -1
- package/dist/adapters/local.d.ts.map +1 -1
- package/dist/adapters/local.js +9 -1
- package/dist/adapters/local.js.map +1 -1
- package/dist/adapters/openrouter.d.ts.map +1 -1
- package/dist/adapters/openrouter.js +9 -1
- package/dist/adapters/openrouter.js.map +1 -1
- package/dist/adapters/rateLimitError.d.ts +29 -0
- package/dist/adapters/rateLimitError.d.ts.map +1 -0
- package/dist/adapters/rateLimitError.js +64 -0
- package/dist/adapters/rateLimitError.js.map +1 -0
- package/dist/adapters/resultParsing.d.ts.map +1 -1
- package/dist/adapters/resultParsing.js +18 -0
- package/dist/adapters/resultParsing.js.map +1 -1
- package/dist/adapters/tools.d.ts +3 -0
- package/dist/adapters/tools.d.ts.map +1 -1
- package/dist/adapters/tools.js +148 -11
- package/dist/adapters/tools.js.map +1 -1
- package/dist/adapters/types.d.ts +15 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/webTools.d.ts.map +1 -1
- package/dist/adapters/webTools.js +44 -21
- package/dist/adapters/webTools.js.map +1 -1
- package/dist/agents/agentPair.d.ts +9 -0
- package/dist/agents/agentPair.d.ts.map +1 -1
- package/dist/agents/agentPair.js.map +1 -1
- package/dist/agents/auditor.d.ts.map +1 -1
- package/dist/agents/auditor.js +3 -0
- package/dist/agents/auditor.js.map +1 -1
- package/dist/agents/documenter.d.ts.map +1 -1
- package/dist/agents/documenter.js +3 -0
- package/dist/agents/documenter.js.map +1 -1
- package/dist/agents/draftAnalyzer.d.ts +30 -7
- package/dist/agents/draftAnalyzer.d.ts.map +1 -1
- package/dist/agents/draftAnalyzer.js +181 -30
- package/dist/agents/draftAnalyzer.js.map +1 -1
- package/dist/agents/multiLensReview.d.ts +49 -0
- package/dist/agents/multiLensReview.d.ts.map +1 -0
- package/dist/agents/multiLensReview.js +148 -0
- package/dist/agents/multiLensReview.js.map +1 -0
- package/dist/agents/pairPipeline.d.ts +7 -1
- package/dist/agents/pairPipeline.d.ts.map +1 -1
- package/dist/agents/pairPipeline.js +110 -66
- package/dist/agents/pairPipeline.js.map +1 -1
- package/dist/agents/pipelineFormat.d.ts.map +1 -1
- package/dist/agents/pipelineFormat.js +4 -0
- package/dist/agents/pipelineFormat.js.map +1 -1
- package/dist/agents/reviewer.d.ts +16 -0
- package/dist/agents/reviewer.d.ts.map +1 -1
- package/dist/agents/reviewer.js +30 -0
- package/dist/agents/reviewer.js.map +1 -1
- package/dist/agents/skillDocumenter.d.ts.map +1 -1
- package/dist/agents/skillDocumenter.js +3 -0
- package/dist/agents/skillDocumenter.js.map +1 -1
- package/dist/agents/tester.d.ts.map +1 -1
- package/dist/agents/tester.js +3 -0
- package/dist/agents/tester.js.map +1 -1
- package/dist/agents/worker.d.ts +14 -0
- package/dist/agents/worker.d.ts.map +1 -1
- package/dist/agents/worker.js +123 -22
- package/dist/agents/worker.js.map +1 -1
- package/dist/automation/autonomousRunner.d.ts +12 -0
- package/dist/automation/autonomousRunner.d.ts.map +1 -1
- package/dist/automation/autonomousRunner.js +218 -29
- package/dist/automation/autonomousRunner.js.map +1 -1
- package/dist/automation/runnerExecution.d.ts +15 -0
- package/dist/automation/runnerExecution.d.ts.map +1 -1
- package/dist/automation/runnerExecution.js +77 -1
- package/dist/automation/runnerExecution.js.map +1 -1
- package/dist/automation/runnerState.d.ts +7 -0
- package/dist/automation/runnerState.d.ts.map +1 -1
- package/dist/automation/runnerState.js +23 -1
- package/dist/automation/runnerState.js.map +1 -1
- package/dist/automation/runnerTypes.d.ts +2 -0
- package/dist/automation/runnerTypes.d.ts.map +1 -1
- package/dist/automation/scheduler.d.ts +12 -0
- package/dist/automation/scheduler.d.ts.map +1 -1
- package/dist/automation/scheduler.js +29 -2
- package/dist/automation/scheduler.js.map +1 -1
- package/dist/automation/taskSource.d.ts +9 -1
- package/dist/automation/taskSource.d.ts.map +1 -1
- package/dist/automation/taskSource.js +13 -2
- package/dist/automation/taskSource.js.map +1 -1
- package/dist/cli/auditPM.d.ts +40 -0
- package/dist/cli/auditPM.d.ts.map +1 -0
- package/dist/cli/auditPM.js +152 -0
- package/dist/cli/auditPM.js.map +1 -0
- package/dist/cli/designPipeline.d.ts +30 -0
- package/dist/cli/designPipeline.d.ts.map +1 -0
- package/dist/cli/designPipeline.js +113 -0
- package/dist/cli/designPipeline.js.map +1 -0
- package/dist/cli/mcpCommand.d.ts +22 -0
- package/dist/cli/mcpCommand.d.ts.map +1 -0
- package/dist/cli/mcpCommand.js +93 -0
- package/dist/cli/mcpCommand.js.map +1 -0
- package/dist/cli/projectHandler.d.ts.map +1 -1
- package/dist/cli/projectHandler.js +4 -2
- package/dist/cli/projectHandler.js.map +1 -1
- package/dist/cli/reviewAudit.d.ts +130 -0
- package/dist/cli/reviewAudit.d.ts.map +1 -0
- package/dist/cli/reviewAudit.js +283 -0
- package/dist/cli/reviewAudit.js.map +1 -0
- package/dist/cli/reviewCommand.d.ts +53 -0
- package/dist/cli/reviewCommand.d.ts.map +1 -0
- package/dist/cli/reviewCommand.js +207 -0
- package/dist/cli/reviewCommand.js.map +1 -0
- package/dist/cli/reviewMaxCommand.d.ts +35 -0
- package/dist/cli/reviewMaxCommand.d.ts.map +1 -0
- package/dist/cli/reviewMaxCommand.js +278 -0
- package/dist/cli/reviewMaxCommand.js.map +1 -0
- package/dist/cli/reviewProgress.d.ts +34 -0
- package/dist/cli/reviewProgress.d.ts.map +1 -0
- package/dist/cli/reviewProgress.js +109 -0
- package/dist/cli/reviewProgress.js.map +1 -0
- package/dist/cli/scheduleCommand.d.ts +15 -0
- package/dist/cli/scheduleCommand.d.ts.map +1 -0
- package/dist/cli/scheduleCommand.js +68 -0
- package/dist/cli/scheduleCommand.js.map +1 -0
- package/dist/cli.js +182 -26
- package/dist/cli.js.map +1 -1
- package/dist/core/config.d.ts +24 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +42 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/providerOverride.d.ts.map +1 -1
- package/dist/core/providerOverride.js +16 -13
- package/dist/core/providerOverride.js.map +1 -1
- package/dist/core/service.d.ts.map +1 -1
- package/dist/core/service.js +11 -0
- package/dist/core/service.js.map +1 -1
- package/dist/core/types.d.ts +38 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/discord/discordHandlers.d.ts.map +1 -1
- package/dist/discord/discordHandlers.js +1 -0
- package/dist/discord/discordHandlers.js.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/linear/linear.d.ts +21 -0
- package/dist/linear/linear.d.ts.map +1 -1
- package/dist/linear/linear.js +109 -4
- package/dist/linear/linear.js.map +1 -1
- package/dist/linear/projectUpdater.js +3 -1
- package/dist/linear/projectUpdater.js.map +1 -1
- package/dist/locale/prompts/en.d.ts.map +1 -1
- package/dist/locale/prompts/en.js +104 -11
- package/dist/locale/prompts/en.js.map +1 -1
- package/dist/locale/prompts/ko.d.ts.map +1 -1
- package/dist/locale/prompts/ko.js +103 -11
- package/dist/locale/prompts/ko.js.map +1 -1
- package/dist/locale/types.d.ts +12 -0
- package/dist/locale/types.d.ts.map +1 -1
- package/dist/mcp/mcpClient.d.ts +28 -1
- package/dist/mcp/mcpClient.d.ts.map +1 -1
- package/dist/mcp/mcpClient.js +74 -3
- package/dist/mcp/mcpClient.js.map +1 -1
- package/dist/orchestration/decisionEngine.d.ts +20 -0
- package/dist/orchestration/decisionEngine.d.ts.map +1 -1
- package/dist/orchestration/decisionEngine.js +23 -0
- package/dist/orchestration/decisionEngine.js.map +1 -1
- package/dist/orchestration/taskScheduler.d.ts.map +1 -1
- package/dist/orchestration/taskScheduler.js +12 -1
- package/dist/orchestration/taskScheduler.js.map +1 -1
- package/dist/support/chatBackend.d.ts +18 -0
- package/dist/support/chatBackend.d.ts.map +1 -1
- package/dist/support/chatBackend.js +92 -8
- package/dist/support/chatBackend.js.map +1 -1
- package/dist/support/chatSession.d.ts +51 -0
- package/dist/support/chatSession.d.ts.map +1 -0
- package/dist/support/chatSession.js +134 -0
- package/dist/support/chatSession.js.map +1 -0
- package/dist/support/chatTui.d.ts.map +1 -1
- package/dist/support/chatTui.js +6 -75
- package/dist/support/chatTui.js.map +1 -1
- package/dist/support/concurrencyPool.d.ts +18 -0
- package/dist/support/concurrencyPool.d.ts.map +1 -0
- package/dist/support/concurrencyPool.js +46 -0
- package/dist/support/concurrencyPool.js.map +1 -0
- package/dist/support/dashboardHtml.d.ts +1 -1
- package/dist/support/dashboardHtml.d.ts.map +1 -1
- package/dist/support/dashboardHtml.js +0 -28
- package/dist/support/dashboardHtml.js.map +1 -1
- package/dist/support/editParser.d.ts +26 -0
- package/dist/support/editParser.d.ts.map +1 -1
- package/dist/support/editParser.js +43 -0
- package/dist/support/editParser.js.map +1 -1
- package/dist/support/goalCommand.d.ts +35 -0
- package/dist/support/goalCommand.d.ts.map +1 -0
- package/dist/support/goalCommand.js +112 -0
- package/dist/support/goalCommand.js.map +1 -0
- package/dist/support/index.d.ts +0 -1
- package/dist/support/index.d.ts.map +1 -1
- package/dist/support/index.js +0 -1
- package/dist/support/index.js.map +1 -1
- package/dist/support/web.d.ts.map +1 -1
- package/dist/support/web.js +0 -7
- package/dist/support/web.js.map +1 -1
- package/dist/taskState/store.d.ts +5 -0
- package/dist/taskState/store.d.ts.map +1 -1
- package/dist/taskState/store.js +16 -0
- package/dist/taskState/store.js.map +1 -1
- package/dist/telemetry/telemetry.d.ts +42 -0
- package/dist/telemetry/telemetry.d.ts.map +1 -0
- package/dist/telemetry/telemetry.js +138 -0
- package/dist/telemetry/telemetry.js.map +1 -0
- package/dist/tui/App.d.ts +20 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +52 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/chatModel.d.ts +81 -0
- package/dist/tui/chatModel.d.ts.map +1 -0
- package/dist/tui/chatModel.js +129 -0
- package/dist/tui/chatModel.js.map +1 -0
- package/dist/tui/components/AuditBoard.d.ts +10 -0
- package/dist/tui/components/AuditBoard.d.ts.map +1 -0
- package/dist/tui/components/AuditBoard.js +50 -0
- package/dist/tui/components/AuditBoard.js.map +1 -0
- package/dist/tui/components/ChatInput.d.ts +14 -0
- package/dist/tui/components/ChatInput.d.ts.map +1 -0
- package/dist/tui/components/ChatInput.js +46 -0
- package/dist/tui/components/ChatInput.js.map +1 -0
- package/dist/tui/components/ChatLog.d.ts +12 -0
- package/dist/tui/components/ChatLog.d.ts.map +1 -0
- package/dist/tui/components/ChatLog.js +47 -0
- package/dist/tui/components/ChatLog.js.map +1 -0
- package/dist/tui/components/CommandPalette.d.ts +6 -0
- package/dist/tui/components/CommandPalette.d.ts.map +1 -0
- package/dist/tui/components/CommandPalette.js +14 -0
- package/dist/tui/components/CommandPalette.js.map +1 -0
- package/dist/tui/components/ContextBar.d.ts +9 -0
- package/dist/tui/components/ContextBar.d.ts.map +1 -0
- package/dist/tui/components/ContextBar.js +18 -0
- package/dist/tui/components/ContextBar.js.map +1 -0
- package/dist/tui/components/DataTable.d.ts +6 -0
- package/dist/tui/components/DataTable.d.ts.map +1 -0
- package/dist/tui/components/DataTable.js +13 -0
- package/dist/tui/components/DataTable.js.map +1 -0
- package/dist/tui/components/HelpBar.d.ts +2 -0
- package/dist/tui/components/HelpBar.d.ts.map +1 -0
- package/dist/tui/components/HelpBar.js +8 -0
- package/dist/tui/components/HelpBar.js.map +1 -0
- package/dist/tui/components/LiveLog.d.ts +6 -0
- package/dist/tui/components/LiveLog.d.ts.map +1 -0
- package/dist/tui/components/LiveLog.js +10 -0
- package/dist/tui/components/LiveLog.js.map +1 -0
- package/dist/tui/components/LogLine.d.ts +4 -0
- package/dist/tui/components/LogLine.d.ts.map +1 -0
- package/dist/tui/components/LogLine.js +8 -0
- package/dist/tui/components/LogLine.js.map +1 -0
- package/dist/tui/components/SelectList.d.ts +6 -0
- package/dist/tui/components/SelectList.d.ts.map +1 -0
- package/dist/tui/components/SelectList.js +15 -0
- package/dist/tui/components/SelectList.js.map +1 -0
- package/dist/tui/components/StageTimeline.d.ts +7 -0
- package/dist/tui/components/StageTimeline.d.ts.map +1 -0
- package/dist/tui/components/StageTimeline.js +18 -0
- package/dist/tui/components/StageTimeline.js.map +1 -0
- package/dist/tui/components/StatusBar.d.ts +7 -0
- package/dist/tui/components/StatusBar.d.ts.map +1 -0
- package/dist/tui/components/StatusBar.js +8 -0
- package/dist/tui/components/StatusBar.js.map +1 -0
- package/dist/tui/components/SubagentTree.d.ts +10 -0
- package/dist/tui/components/SubagentTree.d.ts.map +1 -0
- package/dist/tui/components/SubagentTree.js +12 -0
- package/dist/tui/components/SubagentTree.js.map +1 -0
- package/dist/tui/components/TabBar.d.ts +5 -0
- package/dist/tui/components/TabBar.d.ts.map +1 -0
- package/dist/tui/components/TabBar.js +9 -0
- package/dist/tui/components/TabBar.js.map +1 -0
- package/dist/tui/components/WorkingIndicator.d.ts +6 -0
- package/dist/tui/components/WorkingIndicator.d.ts.map +1 -0
- package/dist/tui/components/WorkingIndicator.js +20 -0
- package/dist/tui/components/WorkingIndicator.js.map +1 -0
- package/dist/tui/hooks/useMonitor.d.ts +8 -0
- package/dist/tui/hooks/useMonitor.d.ts.map +1 -0
- package/dist/tui/hooks/useMonitor.js +42 -0
- package/dist/tui/hooks/useMonitor.js.map +1 -0
- package/dist/tui/hooks/usePipelineEvents.d.ts +6 -0
- package/dist/tui/hooks/usePipelineEvents.d.ts.map +1 -0
- package/dist/tui/hooks/usePipelineEvents.js +21 -0
- package/dist/tui/hooks/usePipelineEvents.js.map +1 -0
- package/dist/tui/hooks/useTerminalSize.d.ts +6 -0
- package/dist/tui/hooks/useTerminalSize.d.ts.map +1 -0
- package/dist/tui/hooks/useTerminalSize.js +26 -0
- package/dist/tui/hooks/useTerminalSize.js.map +1 -0
- package/dist/tui/index.d.ts +22 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +18 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/inputDebug.d.ts +20 -0
- package/dist/tui/inputDebug.d.ts.map +1 -0
- package/dist/tui/inputDebug.js +42 -0
- package/dist/tui/inputDebug.js.map +1 -0
- package/dist/tui/loadingMessages.d.ts +11 -0
- package/dist/tui/loadingMessages.d.ts.map +1 -0
- package/dist/tui/loadingMessages.js +39 -0
- package/dist/tui/loadingMessages.js.map +1 -0
- package/dist/tui/logFormat.d.ts +10 -0
- package/dist/tui/logFormat.d.ts.map +1 -0
- package/dist/tui/logFormat.js +86 -0
- package/dist/tui/logFormat.js.map +1 -0
- package/dist/tui/markdown.d.ts +3 -0
- package/dist/tui/markdown.d.ts.map +1 -0
- package/dist/tui/markdown.js +33 -0
- package/dist/tui/markdown.js.map +1 -0
- package/dist/tui/monitorApi.d.ts +6 -0
- package/dist/tui/monitorApi.d.ts.map +1 -0
- package/dist/tui/monitorApi.js +35 -0
- package/dist/tui/monitorApi.js.map +1 -0
- package/dist/tui/monitorRows.d.ts +43 -0
- package/dist/tui/monitorRows.d.ts.map +1 -0
- package/dist/tui/monitorRows.js +65 -0
- package/dist/tui/monitorRows.js.map +1 -0
- package/dist/tui/panels/ChatPanel.d.ts +16 -0
- package/dist/tui/panels/ChatPanel.d.ts.map +1 -0
- package/dist/tui/panels/ChatPanel.js +305 -0
- package/dist/tui/panels/ChatPanel.js.map +1 -0
- package/dist/tui/panels/LogsPanel.d.ts +8 -0
- package/dist/tui/panels/LogsPanel.d.ts.map +1 -0
- package/dist/tui/panels/LogsPanel.js +19 -0
- package/dist/tui/panels/LogsPanel.js.map +1 -0
- package/dist/tui/panels/MonitorPanel.d.ts +8 -0
- package/dist/tui/panels/MonitorPanel.d.ts.map +1 -0
- package/dist/tui/panels/MonitorPanel.js +19 -0
- package/dist/tui/panels/MonitorPanel.js.map +1 -0
- package/dist/tui/panels/PipelinePanel.d.ts +6 -0
- package/dist/tui/panels/PipelinePanel.d.ts.map +1 -0
- package/dist/tui/panels/PipelinePanel.js +22 -0
- package/dist/tui/panels/PipelinePanel.js.map +1 -0
- package/dist/tui/pipelineEvents.d.ts +21 -0
- package/dist/tui/pipelineEvents.d.ts.map +1 -0
- package/dist/tui/pipelineEvents.js +30 -0
- package/dist/tui/pipelineEvents.js.map +1 -0
- package/dist/tui/sse.d.ts +24 -0
- package/dist/tui/sse.d.ts.map +1 -0
- package/dist/tui/sse.js +78 -0
- package/dist/tui/sse.js.map +1 -0
- package/dist/tui/subagentTree.d.ts +10 -0
- package/dist/tui/subagentTree.d.ts.map +1 -0
- package/dist/tui/subagentTree.js +30 -0
- package/dist/tui/subagentTree.js.map +1 -0
- package/dist/tui/tabs.d.ts +10 -0
- package/dist/tui/tabs.d.ts.map +1 -0
- package/dist/tui/tabs.js +26 -0
- package/dist/tui/tabs.js.map +1 -0
- package/dist/tui/theme.d.ts +29 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +34 -0
- package/dist/tui/theme.js.map +1 -0
- package/package.json +13 -3
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// OpenSwarm - Multi-Lens Reviewer Fan-out (INT-2230)
|
|
3
|
+
// ============================================
|
|
4
|
+
//
|
|
5
|
+
// PoC: verify one worker result through several independent review "lenses" in
|
|
6
|
+
// parallel, then merge into a single ReviewResult. Each lens is just a focused
|
|
7
|
+
// prompt injected into `taskDescription` — no extra adapter/infra needed — so the
|
|
8
|
+
// existing reviewer agent runs N times, each told to concentrate on one concern
|
|
9
|
+
// (correctness / security / regression-risk). The merge takes the WORST decision
|
|
10
|
+
// and unions the issues/suggestions/recommendedActions so nothing a lens caught
|
|
11
|
+
// is dropped. Gated + opt-in (config.review.multiLens.enabled, default false) to
|
|
12
|
+
// avoid multiplying usage on every task.
|
|
13
|
+
import { runReviewer } from './reviewer.js';
|
|
14
|
+
import { runPool } from '../support/concurrencyPool.js';
|
|
15
|
+
import { RateLimitError } from '../adapters/rateLimitError.js';
|
|
16
|
+
/** The three default lenses a fan-out review runs in parallel. */
|
|
17
|
+
export const REVIEW_LENSES = [
|
|
18
|
+
{
|
|
19
|
+
key: 'correctness',
|
|
20
|
+
focus: 'logic errors, unhandled edge cases, off-by-one, wrong assumptions, error handling',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: 'security',
|
|
24
|
+
focus: 'injection, unsafe input, leaked secrets/keys, auth gaps, unsafe deserialization',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
key: 'regression-risk',
|
|
28
|
+
focus: 'breaks existing behavior, changes a shared contract, missing/!updated tests, side effects on callers',
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
/**
|
|
32
|
+
* Append a lens directive to the base task description so the reviewer
|
|
33
|
+
* concentrates on one concern. Other concerns are explicitly delegated to the
|
|
34
|
+
* sibling lenses so a single reviewer doesn't try to cover everything.
|
|
35
|
+
*/
|
|
36
|
+
export function buildLensTaskDescription(base, lens) {
|
|
37
|
+
return `${base}\n\n## Review lens: ${lens.key}\nFocus your review specifically on: ${lens.focus}. Other concerns are secondary — another reviewer covers them.`;
|
|
38
|
+
}
|
|
39
|
+
// Merge
|
|
40
|
+
/** Severity ordering: reject is worst, approve is best. */
|
|
41
|
+
const DECISION_RANK = {
|
|
42
|
+
approve: 0,
|
|
43
|
+
revise: 1,
|
|
44
|
+
reject: 2,
|
|
45
|
+
};
|
|
46
|
+
/** First non-empty line of a feedback blob, trimmed (one-line lens summary). */
|
|
47
|
+
function firstLine(text) {
|
|
48
|
+
if (!text)
|
|
49
|
+
return '';
|
|
50
|
+
for (const line of text.split('\n')) {
|
|
51
|
+
const trimmed = line.trim();
|
|
52
|
+
if (trimmed)
|
|
53
|
+
return trimmed;
|
|
54
|
+
}
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
/** Stable dedup of strings by trimmed/lowercased value, keeping first original. */
|
|
58
|
+
function dedupStrings(values) {
|
|
59
|
+
const seen = new Set();
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const v of values) {
|
|
62
|
+
const key = v.trim().toLowerCase();
|
|
63
|
+
if (!key || seen.has(key))
|
|
64
|
+
continue;
|
|
65
|
+
seen.add(key);
|
|
66
|
+
out.push(v);
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Combine several lens reviews into one verdict:
|
|
72
|
+
* - decision = the WORST across lenses (reject > revise > approve)
|
|
73
|
+
* - issues / suggestions / recommendedActions = deduped union
|
|
74
|
+
* - feedback = one line per lens result, joined
|
|
75
|
+
* Empty input yields a clean approve (nothing flagged).
|
|
76
|
+
*/
|
|
77
|
+
export function mergeReviewResults(results) {
|
|
78
|
+
if (results.length === 0) {
|
|
79
|
+
return { decision: 'approve', feedback: '', issues: [], suggestions: [], recommendedActions: [] };
|
|
80
|
+
}
|
|
81
|
+
let decision = 'approve';
|
|
82
|
+
for (const r of results) {
|
|
83
|
+
if (DECISION_RANK[r.decision] > DECISION_RANK[decision])
|
|
84
|
+
decision = r.decision;
|
|
85
|
+
}
|
|
86
|
+
const issues = dedupStrings(results.flatMap((r) => r.issues ?? []));
|
|
87
|
+
const suggestions = dedupStrings(results.flatMap((r) => r.suggestions ?? []));
|
|
88
|
+
const actionSeen = new Set();
|
|
89
|
+
const recommendedActions = [];
|
|
90
|
+
for (const action of results.flatMap((r) => r.recommendedActions ?? [])) {
|
|
91
|
+
const key = `${action.type}|${action.location ?? ''}|${action.title}`;
|
|
92
|
+
if (actionSeen.has(key))
|
|
93
|
+
continue;
|
|
94
|
+
actionSeen.add(key);
|
|
95
|
+
recommendedActions.push(action);
|
|
96
|
+
}
|
|
97
|
+
const feedback = results
|
|
98
|
+
.map((r) => firstLine(r.feedback))
|
|
99
|
+
.filter(Boolean)
|
|
100
|
+
.join('\n');
|
|
101
|
+
return { decision, feedback, issues, suggestions, recommendedActions };
|
|
102
|
+
}
|
|
103
|
+
// Gating
|
|
104
|
+
/**
|
|
105
|
+
* Decide whether a task is worth the extra cost of multi-lens fan-out. Triggers
|
|
106
|
+
* on a wide change surface, high priority (1=Urgent, 2=High), or an explicit
|
|
107
|
+
* `deep-review` label. Threshold defaults to 3 changed files.
|
|
108
|
+
*/
|
|
109
|
+
export function shouldFanoutReview(task, opts) {
|
|
110
|
+
const fileThreshold = opts?.fileThreshold ?? 3;
|
|
111
|
+
const fileCount = task.filesChanged?.length ?? 0;
|
|
112
|
+
if (fileCount >= fileThreshold)
|
|
113
|
+
return true;
|
|
114
|
+
if (task.priority != null && task.priority <= 2)
|
|
115
|
+
return true;
|
|
116
|
+
return !!task.labels?.includes('deep-review');
|
|
117
|
+
}
|
|
118
|
+
// Fan-out
|
|
119
|
+
/**
|
|
120
|
+
* Run every lens in parallel and merge. Each lens calls the reviewer with a
|
|
121
|
+
* lens-scoped task description. A lens that fails for a non-rate-limit reason is
|
|
122
|
+
* skipped (its slot carries an error from the pool). A RateLimitError from ANY
|
|
123
|
+
* lens propagates so the pipeline's existing usage-limit handling / claude
|
|
124
|
+
* fallback can take over (INT-2192) instead of silently dropping a lens.
|
|
125
|
+
* `deps` is injectable for tests.
|
|
126
|
+
*/
|
|
127
|
+
export async function runMultiLensReview(options, deps) {
|
|
128
|
+
const review = deps?.review ?? runReviewer;
|
|
129
|
+
const lenses = deps?.lenses ?? REVIEW_LENSES;
|
|
130
|
+
const concurrency = deps?.concurrency ?? lenses.length;
|
|
131
|
+
const settled = await runPool(lenses, concurrency, async (lens) => {
|
|
132
|
+
const result = await review({
|
|
133
|
+
...options,
|
|
134
|
+
taskDescription: buildLensTaskDescription(options.taskDescription, lens),
|
|
135
|
+
});
|
|
136
|
+
// Tag the feedback with the lens so the merged summary reads "[correctness] …".
|
|
137
|
+
return { ...result, feedback: `[${lens.key}] ${firstLine(result.feedback)}` };
|
|
138
|
+
});
|
|
139
|
+
// A rate limit on any lens means the quota is exhausted — propagate so the
|
|
140
|
+
// pipeline pauses / falls back rather than merging a partial review.
|
|
141
|
+
for (const s of settled) {
|
|
142
|
+
if (s.error instanceof RateLimitError)
|
|
143
|
+
throw s.error;
|
|
144
|
+
}
|
|
145
|
+
const ok = settled.filter((s) => s.value !== undefined).map((s) => s.value);
|
|
146
|
+
return mergeReviewResults(ok);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=multiLensReview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiLensReview.js","sourceRoot":"","sources":["../../src/agents/multiLensReview.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,6 +51,8 @@ export interface PipelineConfig {
|
|
|
51
51
|
relevantFiles: string[];
|
|
52
52
|
suggestedApproach: string;
|
|
53
53
|
projectStats?: string;
|
|
54
|
+
completionCriteria?: string[];
|
|
55
|
+
sufficient?: boolean;
|
|
54
56
|
impactAnalysis?: import('../knowledge/types.js').ImpactAnalysis;
|
|
55
57
|
registrySnapshot?: Array<{
|
|
56
58
|
filePath: string;
|
|
@@ -76,7 +78,9 @@ export interface PipelineResult {
|
|
|
76
78
|
success: boolean;
|
|
77
79
|
sessionId: string;
|
|
78
80
|
stages: StageResult[];
|
|
79
|
-
finalStatus: 'approved' | 'rejected' | 'failed' | 'cancelled' | 'decomposed';
|
|
81
|
+
finalStatus: 'approved' | 'rejected' | 'failed' | 'cancelled' | 'decomposed' | 'rate_limited' | 'infra_error';
|
|
82
|
+
/** Unix timestamp (ms) when the rate-limit quota resets — set when finalStatus is 'rate_limited'. */
|
|
83
|
+
rateLimitResetsAt?: number;
|
|
80
84
|
totalDuration: number;
|
|
81
85
|
/** Total number of completed iterations */
|
|
82
86
|
iterations: number;
|
|
@@ -146,6 +150,8 @@ export declare class PairPipeline extends EventEmitter {
|
|
|
146
150
|
private matchesProfile;
|
|
147
151
|
private getProfileForTask;
|
|
148
152
|
private getModelForRole;
|
|
153
|
+
/** Reasoning effort from the matched jobProfile (heavy tasks reason harder). */
|
|
154
|
+
private getEffortForTask;
|
|
149
155
|
/**
|
|
150
156
|
* Run pipeline
|
|
151
157
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairPipeline.d.ts","sourceRoot":"","sources":["../../src/agents/pairPipeline.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,KAAK,QAAQ,EAA8B,MAAM,2BAA2B,CAAC;AAKtF,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EACL,KAAK,eAAe,EAOrB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"pairPipeline.d.ts","sourceRoot":"","sources":["../../src/agents/pairPipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,8 @@ import * as documenterAgent from './documenter.js';
|
|
|
19
19
|
import * as auditorAgent from './auditor.js';
|
|
20
20
|
import * as skillDocumenterAgent from './skillDocumenter.js';
|
|
21
21
|
import { createStuckDetector } from '../support/stuckDetector.js';
|
|
22
|
+
import { RateLimitError } from '../adapters/rateLimitError.js';
|
|
23
|
+
import { isInfraError } from '../adapters/errorClassification.js';
|
|
22
24
|
/**
|
|
23
25
|
* Build a consistent task prefix for logging across all pipeline stages.
|
|
24
26
|
* Format: "ProjectName | INT-XXX | worktree/abc123" or "ProjectName | INT-XXX"
|
|
@@ -94,6 +96,10 @@ export class PairPipeline extends EventEmitter {
|
|
|
94
96
|
const profile = this.getProfileForTask(task);
|
|
95
97
|
return profile?.roles?.[stage] || this.config.roles?.[stage]?.model;
|
|
96
98
|
}
|
|
99
|
+
/** Reasoning effort from the matched jobProfile (heavy tasks reason harder). */
|
|
100
|
+
getEffortForTask(task) {
|
|
101
|
+
return this.getProfileForTask(task)?.effort;
|
|
102
|
+
}
|
|
97
103
|
// ============================================
|
|
98
104
|
// Main Execution
|
|
99
105
|
// ============================================
|
|
@@ -187,9 +193,23 @@ export class PairPipeline extends EventEmitter {
|
|
|
187
193
|
// Cancellation (project disable / manual stop) is not a failure — surface it
|
|
188
194
|
// as 'cancelled' so the scheduler doesn't count it failed or trigger a retry.
|
|
189
195
|
const cancelled = error instanceof PipelineCancelledError || !!this.abortSignal?.aborted;
|
|
196
|
+
// A 429/usage-limit propagates up here from any stage (worker/reviewer/…).
|
|
197
|
+
// Surface it as its own finalStatus so the runner pauses until quota resets
|
|
198
|
+
// instead of counting a failure and spamming Linear comments. (INT-1906)
|
|
199
|
+
const rateLimited = !cancelled && error instanceof RateLimitError;
|
|
200
|
+
// An infra/CLI failure (worker/reviewer never ran: non-zero exit, auth,
|
|
201
|
+
// spawn, timeout) is not a task failure — surface it distinctly so the
|
|
202
|
+
// runner does a backoff retry instead of counting it toward STUCK. (INT-2010)
|
|
203
|
+
const infra = !cancelled && !rateLimited && isInfraError(error);
|
|
190
204
|
if (cancelled) {
|
|
191
205
|
console.log(`[${context.taskPrefix}] Pipeline cancelled`);
|
|
192
206
|
}
|
|
207
|
+
else if (rateLimited) {
|
|
208
|
+
console.warn(`[${context.taskPrefix}] Pipeline rate-limited: ${error.message}`);
|
|
209
|
+
}
|
|
210
|
+
else if (infra) {
|
|
211
|
+
console.warn(`[${context.taskPrefix}] Pipeline infra error (not counted toward STUCK): ${error instanceof Error ? error.message : String(error)}`);
|
|
212
|
+
}
|
|
193
213
|
else {
|
|
194
214
|
console.error('[%s] Error:', context.taskPrefix, error);
|
|
195
215
|
}
|
|
@@ -198,7 +218,10 @@ export class PairPipeline extends EventEmitter {
|
|
|
198
218
|
success: false,
|
|
199
219
|
sessionId: session.id,
|
|
200
220
|
stages,
|
|
201
|
-
finalStatus: cancelled ? 'cancelled' : 'failed',
|
|
221
|
+
finalStatus: cancelled ? 'cancelled' : rateLimited ? 'rate_limited' : infra ? 'infra_error' : 'failed',
|
|
222
|
+
rateLimitResetsAt: rateLimited && error.resetsAt
|
|
223
|
+
? error.resetsAt * 1000
|
|
224
|
+
: undefined,
|
|
202
225
|
totalDuration: Date.now() - startTime,
|
|
203
226
|
iterations: context.currentIteration,
|
|
204
227
|
workerResult: context.workerResult,
|
|
@@ -233,6 +256,8 @@ export class PairPipeline extends EventEmitter {
|
|
|
233
256
|
relevantFiles: draft.relevantFiles,
|
|
234
257
|
suggestedApproach: draft.suggestedApproach,
|
|
235
258
|
projectStats: draft.projectStats,
|
|
259
|
+
completionCriteria: draft.completionCriteria,
|
|
260
|
+
sufficient: draft.sufficient,
|
|
236
261
|
};
|
|
237
262
|
if (draft.impactAnalysis) {
|
|
238
263
|
wc.impactAnalysis = draft.impactAnalysis;
|
|
@@ -352,11 +377,15 @@ export class PairPipeline extends EventEmitter {
|
|
|
352
377
|
this.emit('log', { line: `[verbose] Worker context: ${modCount} affected modules, ${briefCount} file briefs` });
|
|
353
378
|
}
|
|
354
379
|
// Self-repair feedback: objective lint/test errors (reflection trail)
|
|
355
|
-
// are always carried forward —
|
|
356
|
-
//
|
|
357
|
-
// context
|
|
380
|
+
// are always carried forward — ground truth that survives a fresh-context
|
|
381
|
+
// reset. The reviewer's revision prompt is ALSO preserved across fresh
|
|
382
|
+
// context (INT-1705): it carries the task requirement (e.g. "wire it into
|
|
383
|
+
// the heartbeat / add the call site"), not chat pollution — dropping it
|
|
384
|
+
// made the worker repeat the same partial impl forever. Fresh context
|
|
385
|
+
// still clears the worker's own chat history; only the reviewer's task
|
|
386
|
+
// signal is kept.
|
|
358
387
|
const reflectionPart = buildReflectionFeedback(context.reflection);
|
|
359
|
-
const includeReview =
|
|
388
|
+
const includeReview = context.feedbackSource === 'review' && !!context.reviewResult;
|
|
360
389
|
const reviewPart = includeReview
|
|
361
390
|
? reviewerAgent.buildRevisionPrompt(context.reviewResult)
|
|
362
391
|
: undefined;
|
|
@@ -367,9 +396,20 @@ export class PairPipeline extends EventEmitter {
|
|
|
367
396
|
projectPath: context.projectPath,
|
|
368
397
|
previousFeedback: combinedFeedback,
|
|
369
398
|
timeoutMs: this.config.roles?.worker?.timeoutMs ?? 0,
|
|
370
|
-
|
|
399
|
+
// getModelForRole gives the matched jobProfile's model precedence (config's
|
|
400
|
+
// light/heavy → gpt-5.5/5.4), falling back to roles.worker.model. Reading
|
|
401
|
+
// roles.worker.model directly here silently dropped the jobProfile model, so a
|
|
402
|
+
// codex worker fell through to the CLI's config.toml default (Codex-Spark). (INT-1599)
|
|
403
|
+
model: overrides?.model ?? this.getModelForRole('worker', context.task),
|
|
371
404
|
maxTurns: this.config.roles?.worker?.maxTurns,
|
|
372
405
|
adapterName: this.config.roles?.worker?.adapter,
|
|
406
|
+
reasoningEffort: this.getEffortForTask(context.task),
|
|
407
|
+
// No-edit guard (re-applied from stranded feat/v0.7.0 commit 2eea3bc):
|
|
408
|
+
// reasoning workers frequently end with analysis only and never call
|
|
409
|
+
// edit_file. Without this the guard defaults to 0 (disabled) — measured:
|
|
410
|
+
// codex spark AND gpt-5.5 both read 30-37× and shipped 0 edits. Push the
|
|
411
|
+
// worker to actually edit before concluding.
|
|
412
|
+
nudgeMaxOnNoEdit: 3,
|
|
373
413
|
issueIdentifier: context.task.issueIdentifier || context.task.issueId,
|
|
374
414
|
projectName: context.task.linearProject?.name,
|
|
375
415
|
onLog,
|
|
@@ -413,24 +453,25 @@ export class PairPipeline extends EventEmitter {
|
|
|
413
453
|
throw new Error('Worker result required for reviewer');
|
|
414
454
|
}
|
|
415
455
|
// Pre-check disabled - Haiku format compliance issues causing false rejections
|
|
416
|
-
// Proceed directly to full
|
|
417
|
-
//
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
console.log(`[${prefix}] Running full review (Sonnet)...`);
|
|
456
|
+
// Proceed directly to full review for reliability.
|
|
457
|
+
// NOTE: the old "high worker confidence → fewer reviewer turns" shortcut was
|
|
458
|
+
// removed (INT-1914): worker confidence is self-reported, so a confidently
|
|
459
|
+
// scaffolded task was getting LESS review — exactly the wrong incentive. The
|
|
460
|
+
// completion-criteria hard gate is the real check now.
|
|
461
|
+
const reviewerMaxTurns = this.config.roles?.reviewer?.maxTurns;
|
|
462
|
+
console.log(`[${prefix}] Running full review...`);
|
|
425
463
|
result = await reviewerAgent.runReviewer({
|
|
426
464
|
taskTitle: context.task.title,
|
|
427
465
|
taskDescription: context.task.description || '',
|
|
428
466
|
workerResult: context.workerResult,
|
|
429
467
|
projectPath: context.projectPath,
|
|
430
468
|
timeoutMs: this.config.roles?.reviewer?.timeoutMs ?? 0,
|
|
431
|
-
model
|
|
469
|
+
// jobProfile model precedence (see worker stage above). (INT-1599)
|
|
470
|
+
model: this.getModelForRole('reviewer', context.task),
|
|
432
471
|
maxTurns: reviewerMaxTurns,
|
|
433
472
|
adapterName: this.config.roles?.reviewer?.adapter,
|
|
473
|
+
reasoningEffort: this.getEffortForTask(context.task),
|
|
474
|
+
completionCriteria: this.config.draftAnalysis?.completionCriteria,
|
|
434
475
|
processContext: { taskId: context.task.id, stage: 'reviewer' },
|
|
435
476
|
signal: this.abortSignal,
|
|
436
477
|
});
|
|
@@ -777,6 +818,58 @@ export class PairPipeline extends EventEmitter {
|
|
|
777
818
|
continue;
|
|
778
819
|
}
|
|
779
820
|
}
|
|
821
|
+
// ========== TESTER (before reviewer — INT-1703) ==========
|
|
822
|
+
// Run the tester first so the reviewer judges code + test outcomes
|
|
823
|
+
// together, and so a failing test drives INT-1679 self-repair WITHOUT
|
|
824
|
+
// spending a reviewer pass. Runs exactly once per iteration.
|
|
825
|
+
if (hasTester) {
|
|
826
|
+
// Skip tester if no code files changed (configurable, default true)
|
|
827
|
+
const skipIfNoCode = this.config.skipTesterIfNoCodeChange ?? true;
|
|
828
|
+
const codeExtensions = /\.(ts|tsx|js|jsx|py|rs|go|java|rb|c|cpp|h|hpp)$/;
|
|
829
|
+
const changedFiles = context.workerResult?.filesChanged || [];
|
|
830
|
+
const hasCodeChange = changedFiles.some(f => codeExtensions.test(f));
|
|
831
|
+
if (skipIfNoCode && !hasCodeChange) {
|
|
832
|
+
console.log(`[${context.taskPrefix}] Skipping tester: no code files changed (${changedFiles.length} files: ${changedFiles.join(', ') || 'none'})`);
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
const testerResult = await this.runStage('tester', context);
|
|
836
|
+
stages.push(testerResult);
|
|
837
|
+
if (!testerResult.success && !this.config.continueOnTestFail) {
|
|
838
|
+
// Test failure is objective ground truth → record into the reflection
|
|
839
|
+
// trail and drive a bounded self-repair retry (INT-1679).
|
|
840
|
+
console.log(`[${context.taskPrefix}] Tester failed, retrying...`);
|
|
841
|
+
agentPair.trackFailure(context.session.id); // Track for fresh context decision
|
|
842
|
+
const failedTests = context.testerResult?.failedTests ?? [];
|
|
843
|
+
const testErrors = failedTests.length > 0
|
|
844
|
+
? failedTests
|
|
845
|
+
: [context.testerResult?.error || `Tests failed (${context.testerResult?.testsFailed ?? 0} failing)`];
|
|
846
|
+
const { progressed } = recordReflection(context.reflection, {
|
|
847
|
+
iteration: context.currentIteration,
|
|
848
|
+
source: 'test',
|
|
849
|
+
errors: testErrors,
|
|
850
|
+
});
|
|
851
|
+
if (context.testerResult) {
|
|
852
|
+
context.reviewResult = {
|
|
853
|
+
decision: 'revise',
|
|
854
|
+
feedback: testerAgent.buildTestFixPrompt(context.testerResult),
|
|
855
|
+
issues: context.testerResult.failedTests,
|
|
856
|
+
suggestions: context.testerResult.suggestions,
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
context.feedbackSource = 'objective';
|
|
860
|
+
this.emit('iteration:fail', {
|
|
861
|
+
iteration: context.currentIteration,
|
|
862
|
+
stage: 'tester',
|
|
863
|
+
context,
|
|
864
|
+
});
|
|
865
|
+
agentPair.updateSessionStatus(context.session.id, 'revising');
|
|
866
|
+
if (this.shouldAbortSelfRepair(context, progressed, 'test')) {
|
|
867
|
+
return { success: false };
|
|
868
|
+
}
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
} // end else (has code change)
|
|
872
|
+
}
|
|
780
873
|
// ========== REVIEWER ==========
|
|
781
874
|
if (hasReviewer) {
|
|
782
875
|
agentPair.updateSessionStatus(context.session.id, 'reviewing');
|
|
@@ -825,58 +918,9 @@ export class PairPipeline extends EventEmitter {
|
|
|
825
918
|
agentPair.updateSessionStatus(context.session.id, 'revising');
|
|
826
919
|
continue;
|
|
827
920
|
}
|
|
828
|
-
// approve →
|
|
921
|
+
// approve → done (tester already ran before the reviewer — INT-1703)
|
|
829
922
|
agentPair.resetFailureStreak(context.session.id); // Reset on approval
|
|
830
923
|
}
|
|
831
|
-
// ========== TESTER ==========
|
|
832
|
-
if (hasTester) {
|
|
833
|
-
// Skip tester if no code files changed (configurable, default true)
|
|
834
|
-
const skipIfNoCode = this.config.skipTesterIfNoCodeChange ?? true;
|
|
835
|
-
const codeExtensions = /\.(ts|tsx|js|jsx|py|rs|go|java|rb|c|cpp|h|hpp)$/;
|
|
836
|
-
const changedFiles = context.workerResult?.filesChanged || [];
|
|
837
|
-
const hasCodeChange = changedFiles.some(f => codeExtensions.test(f));
|
|
838
|
-
if (skipIfNoCode && !hasCodeChange) {
|
|
839
|
-
console.log(`[${context.taskPrefix}] Skipping tester: no code files changed (${changedFiles.length} files: ${changedFiles.join(', ') || 'none'})`);
|
|
840
|
-
}
|
|
841
|
-
else {
|
|
842
|
-
const testerResult = await this.runStage('tester', context);
|
|
843
|
-
stages.push(testerResult);
|
|
844
|
-
if (!testerResult.success && !this.config.continueOnTestFail) {
|
|
845
|
-
// Test failure is objective ground truth → record into the reflection
|
|
846
|
-
// trail and drive a bounded self-repair retry.
|
|
847
|
-
console.log(`[${context.taskPrefix}] Tester failed, retrying...`);
|
|
848
|
-
agentPair.trackFailure(context.session.id); // Track for fresh context decision
|
|
849
|
-
const failedTests = context.testerResult?.failedTests ?? [];
|
|
850
|
-
const testErrors = failedTests.length > 0
|
|
851
|
-
? failedTests
|
|
852
|
-
: [context.testerResult?.error || `Tests failed (${context.testerResult?.testsFailed ?? 0} failing)`];
|
|
853
|
-
const { progressed } = recordReflection(context.reflection, {
|
|
854
|
-
iteration: context.currentIteration,
|
|
855
|
-
source: 'test',
|
|
856
|
-
errors: testErrors,
|
|
857
|
-
});
|
|
858
|
-
if (context.testerResult) {
|
|
859
|
-
context.reviewResult = {
|
|
860
|
-
decision: 'revise',
|
|
861
|
-
feedback: testerAgent.buildTestFixPrompt(context.testerResult),
|
|
862
|
-
issues: context.testerResult.failedTests,
|
|
863
|
-
suggestions: context.testerResult.suggestions,
|
|
864
|
-
};
|
|
865
|
-
}
|
|
866
|
-
context.feedbackSource = 'objective';
|
|
867
|
-
this.emit('iteration:fail', {
|
|
868
|
-
iteration: context.currentIteration,
|
|
869
|
-
stage: 'tester',
|
|
870
|
-
context,
|
|
871
|
-
});
|
|
872
|
-
agentPair.updateSessionStatus(context.session.id, 'revising');
|
|
873
|
-
if (this.shouldAbortSelfRepair(context, progressed, 'test')) {
|
|
874
|
-
return { success: false };
|
|
875
|
-
}
|
|
876
|
-
continue;
|
|
877
|
-
}
|
|
878
|
-
} // end else (has code change)
|
|
879
|
-
}
|
|
880
924
|
// ========== ALL PASSED ==========
|
|
881
925
|
console.log(`[${context.taskPrefix}] Iteration ${context.currentIteration} completed successfully`);
|
|
882
926
|
this.emit('iteration:complete', {
|