@bastani/atomic 0.9.5-alpha.7 → 0.9.5-alpha.9
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/CHANGELOG.md +33 -2
- package/dist/builtin/cursor/package.json +2 -2
- package/dist/builtin/intercom/CHANGELOG.md +17 -0
- package/dist/builtin/intercom/README.md +27 -21
- package/dist/builtin/intercom/broker/broker.ts +3 -6
- package/dist/builtin/intercom/broker/paths.ts +42 -5
- package/dist/builtin/intercom/broker/spawn.ts +78 -10
- package/dist/builtin/intercom/config.ts +6 -3
- package/dist/builtin/intercom/contact-supervisor-tool.ts +6 -4
- package/dist/builtin/intercom/index-heavy.ts +1 -1
- package/dist/builtin/intercom/index.ts +162 -130
- package/dist/builtin/intercom/intercom-tool.ts +9 -3
- package/dist/builtin/intercom/package.json +10 -1
- package/dist/builtin/intercom/result-renderers.ts +1 -1
- package/dist/builtin/intercom/ui/compose.ts +2 -2
- package/dist/builtin/intercom/ui/inline-message.ts +2 -2
- package/dist/builtin/intercom/ui/session-list.ts +2 -2
- package/dist/builtin/mcp/CHANGELOG.md +11 -0
- package/dist/builtin/mcp/README.md +6 -6
- package/dist/builtin/mcp/direct-tools.ts +41 -23
- package/dist/builtin/mcp/index.ts +31 -4
- package/dist/builtin/mcp/init.ts +4 -43
- package/dist/builtin/mcp/metadata-hydration.ts +37 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/mcp/proxy-info-modes.ts +67 -14
- package/dist/builtin/mcp/startup-warmup.ts +98 -0
- package/dist/builtin/mcp/tool-result-renderer.ts +3 -3
- package/dist/builtin/subagents/CHANGELOG.md +18 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/index.ts +14 -25
- package/dist/builtin/subagents/src/extension/startup-maintenance.ts +89 -0
- package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +23 -18
- package/dist/builtin/subagents/src/runs/background/result-watcher.ts +20 -10
- package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +13 -3
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +10 -2
- package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +28 -1
- package/dist/builtin/subagents/src/tui/render-event-formatting.ts +15 -48
- package/dist/builtin/subagents/src/tui/render-layout.ts +9 -0
- package/dist/builtin/subagents/src/tui/render-widget-graph.ts +27 -25
- package/dist/builtin/subagents/src/tui/render-widget.ts +72 -66
- package/dist/builtin/subagents/src/tui/render.ts +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +29 -0
- package/dist/builtin/workflows/README.md +4 -2
- package/dist/builtin/workflows/builtin/goal-artifacts.ts +3 -1
- package/dist/builtin/workflows/builtin/goal-prompts.ts +23 -2
- package/dist/builtin/workflows/builtin/goal-reducer.ts +21 -0
- package/dist/builtin/workflows/builtin/goal-review.ts +60 -6
- package/dist/builtin/workflows/builtin/goal-runner.ts +71 -22
- package/dist/builtin/workflows/builtin/goal-types.ts +7 -1
- package/dist/builtin/workflows/builtin/ralph-core.ts +52 -4
- package/dist/builtin/workflows/builtin/ralph-review-gate.ts +10 -3
- package/dist/builtin/workflows/builtin/ralph-reviewer-prompt.ts +23 -2
- package/dist/builtin/workflows/builtin/ralph-runner.ts +38 -16
- package/dist/builtin/workflows/builtin/review-convergence.ts +111 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/skills/create-spec/SKILL.md +2 -0
- package/dist/builtin/workflows/skills/impeccable/SKILL.md +16 -13
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.md +1 -0
- package/dist/builtin/workflows/skills/impeccable/reference/adapt.native.md +58 -0
- package/dist/builtin/workflows/skills/impeccable/reference/android.md +40 -0
- package/dist/builtin/workflows/skills/impeccable/reference/animate.md +2 -0
- package/dist/builtin/workflows/skills/impeccable/reference/audit.md +2 -0
- package/dist/builtin/workflows/skills/impeccable/reference/audit.native.md +139 -0
- package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +69 -62
- package/dist/builtin/workflows/skills/impeccable/reference/critique.md +21 -7
- package/dist/builtin/workflows/skills/impeccable/reference/document.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +92 -0
- package/dist/builtin/workflows/skills/impeccable/reference/init.md +29 -7
- package/dist/builtin/workflows/skills/impeccable/reference/ios.md +45 -0
- package/dist/builtin/workflows/skills/impeccable/reference/layout.md +25 -1
- package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +23 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +2 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +75 -14
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +31 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +64 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +118 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +16 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +66 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +42 -10
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/fonts.mjs +30 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/page.mjs +4 -6
- package/dist/builtin/workflows/skills/impeccable/scripts/hook-admin.mjs +660 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/hook-before-edit.mjs +516 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/hook-lib.mjs +1764 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/hook.mjs +61 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +4 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/is-generated.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live/svelte-component.mjs +13 -16
- package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +17 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +104 -37
- package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +9 -0
- package/dist/builtin/workflows/src/durable/backend.ts +12 -0
- package/dist/builtin/workflows/src/durable/child-primitive.ts +12 -8
- package/dist/builtin/workflows/src/durable/dbos-backend.ts +63 -2
- package/dist/builtin/workflows/src/durable/dbos-envelope.ts +28 -0
- package/dist/builtin/workflows/src/durable/resume-catalog.ts +12 -0
- package/dist/builtin/workflows/src/durable/resume-runtime.ts +5 -2
- package/dist/builtin/workflows/src/durable/stage-primitive.ts +165 -27
- package/dist/builtin/workflows/src/durable/types.ts +30 -1
- package/dist/builtin/workflows/src/engine/primitives/task.ts +1 -0
- package/dist/builtin/workflows/src/engine/run-durable-finalize.ts +1 -2
- package/dist/builtin/workflows/src/engine/run-returned-status.ts +50 -16
- package/dist/builtin/workflows/src/engine/run.ts +32 -32
- package/dist/builtin/workflows/src/engine/runtime.ts +5 -0
- package/dist/builtin/workflows/src/extension/extension-factory.ts +3 -0
- package/dist/builtin/workflows/src/extension/extension-lifecycle.ts +9 -2
- package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +137 -27
- package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +22 -6
- package/dist/builtin/workflows/src/extension/public-types.ts +1 -1
- package/dist/builtin/workflows/src/extension/workflow-command-completions.ts +13 -1
- package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +19 -4
- package/dist/builtin/workflows/src/extension/workflow-command-surfaces.ts +9 -0
- package/dist/builtin/workflows/src/extension/workflow-prompts.ts +2 -0
- package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +48 -23
- package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +20 -8
- package/dist/builtin/workflows/src/extension/workflow-tool.ts +24 -8
- package/dist/builtin/workflows/src/runs/background/status.ts +4 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-continuation.ts +13 -3
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +29 -8
- package/dist/builtin/workflows/src/runs/foreground/executor-hil.ts +2 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-factory.ts +4 -3
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +18 -19
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-unresolved-overflow.ts +38 -0
- package/dist/builtin/workflows/src/runs/shared/worktree-git.ts +155 -20
- package/dist/builtin/workflows/src/runs/shared/worktree-types.ts +6 -0
- package/dist/builtin/workflows/src/runs/shared/worktree.ts +2 -1
- package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +18 -1
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +23 -5
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
- package/dist/builtin/workflows/src/shared/returned-run-status.ts +116 -0
- package/dist/builtin/workflows/src/shared/workflow-failures-decisions.ts +2 -0
- package/dist/builtin/workflows/src/tui/graph-view-render-helpers.ts +21 -3
- package/dist/builtin/workflows/src/tui/graph-view-state.ts +3 -0
- package/dist/builtin/workflows/src/tui/graph-view-types.ts +3 -0
- package/dist/builtin/workflows/src/tui/status-list.ts +22 -15
- package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +4 -4
- package/dist/bun/internal-intercom-broker.d.ts +6 -0
- package/dist/bun/internal-intercom-broker.d.ts.map +1 -0
- package/dist/bun/internal-intercom-broker.js +39 -0
- package/dist/bun/internal-intercom-broker.js.map +1 -0
- package/dist/bun/split-loader.d.ts.map +1 -1
- package/dist/bun/split-loader.js +21 -8
- package/dist/bun/split-loader.js.map +1 -1
- package/dist/core/agent-session-auto-compaction.d.ts +21 -2
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +163 -11
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +10 -1
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +12 -3
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-models.d.ts +2 -2
- package/dist/core/agent-session-models.d.ts.map +1 -1
- package/dist/core/agent-session-models.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +1 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts +2 -0
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +152 -4
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +15 -1
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +6 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +6 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/context-compaction-runner.d.ts.map +1 -1
- package/dist/core/compaction/context-compaction-runner.js +36 -20
- package/dist/core/compaction/context-compaction-runner.js.map +1 -1
- package/dist/core/copilot-anthropic-sse-repair.d.ts +23 -0
- package/dist/core/copilot-anthropic-sse-repair.d.ts.map +1 -0
- package/dist/core/copilot-anthropic-sse-repair.js +340 -0
- package/dist/core/copilot-anthropic-sse-repair.js.map +1 -0
- package/dist/core/copilot-gemini-reasoning.d.ts +16 -8
- package/dist/core/copilot-gemini-reasoning.d.ts.map +1 -1
- package/dist/core/copilot-gemini-reasoning.js +27 -22
- package/dist/core/copilot-gemini-reasoning.js.map +1 -1
- package/dist/core/copilot-hosts.d.ts +12 -0
- package/dist/core/copilot-hosts.d.ts.map +1 -0
- package/dist/core/copilot-hosts.js +33 -0
- package/dist/core/copilot-hosts.js.map +1 -0
- package/dist/core/extensions/agent-events.d.ts +1 -1
- package/dist/core/extensions/agent-events.d.ts.map +1 -1
- package/dist/core/extensions/agent-events.js.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts +8 -1
- package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/loader-virtual-modules.js +2 -1
- package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +6 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +72 -29
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +5 -5
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/openai-responses-payload-sanitizer.d.ts +1 -0
- package/dist/core/openai-responses-payload-sanitizer.d.ts.map +1 -1
- package/dist/core/openai-responses-payload-sanitizer.js +24 -9
- package/dist/core/openai-responses-payload-sanitizer.js.map +1 -1
- package/dist/core/sdk-types.d.ts +2 -0
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager-basic-accessors.d.ts +1 -0
- package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-basic-accessors.js +6 -0
- package/dist/core/settings-manager-basic-accessors.js.map +1 -1
- package/dist/core/settings-types.d.ts +1 -0
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/slash-commands.d.ts +2 -0
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +141 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main-deferred-startup.d.ts +12 -0
- package/dist/main-deferred-startup.d.ts.map +1 -1
- package/dist/main-deferred-startup.js +23 -2
- package/dist/main-deferred-startup.js.map +1 -1
- package/dist/main-early-input.d.ts +41 -0
- package/dist/main-early-input.d.ts.map +1 -0
- package/dist/main-early-input.js +154 -0
- package/dist/main-early-input.js.map +1 -0
- package/dist/main.d.ts +0 -6
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +20 -14
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-actions.js +0 -1
- package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.js +15 -0
- package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +25 -0
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-autocomplete.js +21 -9
- package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-deferred-startup.js +41 -28
- package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -1
- package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-hotkeys-debug.js +1 -0
- package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +318 -185
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +12 -0
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +39 -0
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +6 -2
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.d.ts +3 -0
- package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-model-routing.js +3 -1
- package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-process-lifecycle.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-process-lifecycle.js +0 -3
- package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-render-chat.js +36 -10
- package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-session-routing.js +5 -1
- package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +26 -22
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/theme/global-theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/global-theme.js +26 -2
- package/dist/modes/interactive/theme/global-theme.js.map +1 -1
- package/dist/utils/fs-watch.d.ts +24 -1
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js +60 -5
- package/dist/utils/fs-watch.js.map +1 -1
- package/docs/compaction.md +8 -0
- package/docs/development.md +4 -0
- package/docs/extensions.md +5 -0
- package/docs/json.md +3 -1
- package/docs/providers.md +1 -0
- package/docs/quickstart.md +1 -1
- package/docs/rpc.md +3 -1
- package/docs/settings.md +27 -1
- package/docs/subagents.md +4 -0
- package/docs/terminal-setup.md +4 -0
- package/docs/usage.md +2 -2
- package/docs/windows.md +4 -0
- package/docs/workflows.md +21 -9
- package/npm-shrinkwrap.json +513 -23
- package/package.json +3 -2
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import type { BlockerObservation, GoalLedger, ReducerOutcome, ReviewRecord } from "./goal-types.js";
|
|
2
|
+
import { summarizeReviewConvergence, type ReviewNextAction } from "./review-convergence.js";
|
|
3
|
+
|
|
4
|
+
function reducerSummary(
|
|
5
|
+
reviews: readonly ReviewRecord[],
|
|
6
|
+
approved: boolean,
|
|
7
|
+
nextAction: ReviewNextAction,
|
|
8
|
+
) {
|
|
9
|
+
return summarizeReviewConvergence({
|
|
10
|
+
parsed: reviews.every((review) => review.parsed),
|
|
11
|
+
approved,
|
|
12
|
+
stopReviewLoop: approved,
|
|
13
|
+
nextAction,
|
|
14
|
+
diagnostics: reviews.flatMap((review) => review.parse_diagnostics),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
2
17
|
|
|
3
18
|
export function normalizeBlocker(blocker: string): string {
|
|
4
19
|
return blocker.toLowerCase().replace(/\s+/g, " ").trim();
|
|
@@ -68,6 +83,7 @@ export function reduceGoalDecision(
|
|
|
68
83
|
readonly maxTurns: number;
|
|
69
84
|
readonly reviewQuorum: number;
|
|
70
85
|
readonly blockerThreshold: number;
|
|
86
|
+
readonly nextActionOnComplete: ReviewNextAction;
|
|
71
87
|
},
|
|
72
88
|
): ReducerOutcome {
|
|
73
89
|
const completeVotes = turnReviews.filter(
|
|
@@ -75,9 +91,11 @@ export function reduceGoalDecision(
|
|
|
75
91
|
).length;
|
|
76
92
|
|
|
77
93
|
if (completeVotes >= options.reviewQuorum) {
|
|
94
|
+
const summary = reducerSummary(turnReviews, true, options.nextActionOnComplete);
|
|
78
95
|
return {
|
|
79
96
|
status: "complete",
|
|
80
97
|
decision: {
|
|
98
|
+
...summary,
|
|
81
99
|
turn: options.turn,
|
|
82
100
|
decision: "complete",
|
|
83
101
|
reason: `Reviewer quorum met: ${completeVotes}/${options.reviewQuorum} reviewers marked complete.`,
|
|
@@ -101,6 +119,7 @@ export function reduceGoalDecision(
|
|
|
101
119
|
status: "blocked",
|
|
102
120
|
blockerObservation: observation,
|
|
103
121
|
decision: {
|
|
122
|
+
...reducerSummary(turnReviews, false, "blocked"),
|
|
104
123
|
turn: options.turn,
|
|
105
124
|
decision: "blocked",
|
|
106
125
|
reason: `Same blocker repeated for ${blockerCount}/${options.blockerThreshold} consecutive controller observations.`,
|
|
@@ -116,6 +135,7 @@ export function reduceGoalDecision(
|
|
|
116
135
|
status: "needs_human",
|
|
117
136
|
blockerObservation: observation,
|
|
118
137
|
decision: {
|
|
138
|
+
...reducerSummary(turnReviews, false, "needs_human"),
|
|
119
139
|
turn: options.turn,
|
|
120
140
|
decision: "needs_human",
|
|
121
141
|
reason: `Worker attempt budget reached without reviewer quorum. Remaining work: ${collectRemainingWork(turnReviews)}`,
|
|
@@ -130,6 +150,7 @@ export function reduceGoalDecision(
|
|
|
130
150
|
status: "active",
|
|
131
151
|
blockerObservation: observation,
|
|
132
152
|
decision: {
|
|
153
|
+
...reducerSummary(turnReviews, false, "implementation"),
|
|
133
154
|
turn: options.turn,
|
|
134
155
|
decision: "continue",
|
|
135
156
|
reason: `Reviewer quorum not met. Remaining work: ${collectRemainingWork(turnReviews)}`,
|
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
import type { WorkflowTaskResult } from "../src/shared/types.js";
|
|
2
2
|
import type { ReviewDecision, ReviewRecord } from "./goal-types.js";
|
|
3
|
+
import {
|
|
4
|
+
finalActionRemaining,
|
|
5
|
+
parseFailureDiagnostics,
|
|
6
|
+
summarizeReviewConvergence,
|
|
7
|
+
traceabilityProvenExceptFinalAction,
|
|
8
|
+
type ParsedReviewDecision,
|
|
9
|
+
} from "./review-convergence.js";
|
|
3
10
|
|
|
4
11
|
export function reviewDecisionFromResult(result: WorkflowTaskResult): ReviewDecision | undefined {
|
|
5
12
|
return result.structured as ReviewDecision | undefined;
|
|
6
13
|
}
|
|
7
14
|
|
|
15
|
+
export function parsedReviewDecisionFromResult(
|
|
16
|
+
result: WorkflowTaskResult,
|
|
17
|
+
reviewer: string,
|
|
18
|
+
): ParsedReviewDecision<ReviewDecision> {
|
|
19
|
+
const parsed = reviewDecisionFromResult(result);
|
|
20
|
+
if (parsed !== undefined) {
|
|
21
|
+
return { decision: parsed, parsed: true, diagnostics: [] };
|
|
22
|
+
}
|
|
23
|
+
const diagnostics = parseFailureDiagnostics(reviewer, result.text);
|
|
24
|
+
return {
|
|
25
|
+
decision: reviewerErrorDecision(diagnostics.join("\n")),
|
|
26
|
+
parsed: false,
|
|
27
|
+
diagnostics,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
8
31
|
const NON_BLOCKING_ALIGNMENTS = new Set([
|
|
9
32
|
"beyond_objective",
|
|
10
33
|
"contradicts_objective",
|
|
@@ -19,18 +42,26 @@ function findingBlocksApproval(finding: ReviewDecision["findings"][number]): boo
|
|
|
19
42
|
return finding.priority !== 3;
|
|
20
43
|
}
|
|
21
44
|
|
|
22
|
-
function traceabilityApproves(
|
|
23
|
-
|
|
24
|
-
|
|
45
|
+
function traceabilityApproves(
|
|
46
|
+
decision: ReviewDecision,
|
|
47
|
+
allowFinalActionRemaining: boolean,
|
|
48
|
+
): boolean {
|
|
49
|
+
return traceabilityProvenExceptFinalAction({
|
|
50
|
+
traceability: decision.requirements_traceability,
|
|
51
|
+
allowFinalActionRemaining,
|
|
52
|
+
});
|
|
25
53
|
}
|
|
26
54
|
|
|
27
|
-
export function reviewApproved(
|
|
55
|
+
export function reviewApproved(
|
|
56
|
+
decision: ReviewDecision,
|
|
57
|
+
options: { readonly allowFinalActionRemaining?: boolean } = {},
|
|
58
|
+
): boolean {
|
|
28
59
|
const hasBlockingFindings = decision.findings.some(findingBlocksApproval);
|
|
29
60
|
return (
|
|
30
61
|
decision.stop_review_loop === true &&
|
|
31
62
|
decision.overall_correctness === "patch is correct" &&
|
|
32
63
|
decision.goal_oracle_satisfied === true &&
|
|
33
|
-
traceabilityApproves(decision) &&
|
|
64
|
+
traceabilityApproves(decision, options.allowFinalActionRemaining === true) &&
|
|
34
65
|
!hasBlockingFindings &&
|
|
35
66
|
decision.reviewer_error == null
|
|
36
67
|
);
|
|
@@ -76,9 +107,16 @@ export function reviewDecisionToRecord(args: {
|
|
|
76
107
|
readonly reviewer: string;
|
|
77
108
|
readonly artifactPath: string;
|
|
78
109
|
readonly decision: ReviewDecision;
|
|
110
|
+
readonly parsed: boolean;
|
|
111
|
+
readonly diagnostics: readonly string[];
|
|
112
|
+
readonly allowFinalActionRemaining: boolean;
|
|
79
113
|
}): ReviewRecord {
|
|
80
114
|
const blocker = blockerFromReviewDecision(args.decision);
|
|
81
|
-
const approved = reviewApproved(args.decision
|
|
115
|
+
const approved = reviewApproved(args.decision, {
|
|
116
|
+
allowFinalActionRemaining: args.allowFinalActionRemaining,
|
|
117
|
+
});
|
|
118
|
+
const hasFinalActionRemaining = args.allowFinalActionRemaining &&
|
|
119
|
+
finalActionRemaining(args.decision.requirements_traceability);
|
|
82
120
|
const verificationGap = args.decision.verification_remaining.trim();
|
|
83
121
|
const traceabilityGaps = args.decision.requirements_traceability
|
|
84
122
|
.filter((entry) => entry.status !== "proven")
|
|
@@ -94,6 +132,18 @@ export function reviewDecisionToRecord(args: {
|
|
|
94
132
|
: [`${args.decision.reviewer_error.kind}: ${args.decision.reviewer_error.message}`]),
|
|
95
133
|
];
|
|
96
134
|
|
|
135
|
+
const nextAction = approved
|
|
136
|
+
? hasFinalActionRemaining ? "pull-request" : "finish"
|
|
137
|
+
: blocker === null ? "implementation" : "blocked";
|
|
138
|
+
const convergenceDecision = summarizeReviewConvergence({
|
|
139
|
+
parsed: args.parsed,
|
|
140
|
+
approved,
|
|
141
|
+
stopReviewLoop: args.decision.stop_review_loop,
|
|
142
|
+
nextAction,
|
|
143
|
+
finalActionRemaining: approved && hasFinalActionRemaining,
|
|
144
|
+
diagnostics: args.diagnostics,
|
|
145
|
+
});
|
|
146
|
+
|
|
97
147
|
return {
|
|
98
148
|
...args.decision,
|
|
99
149
|
decision: approved ? "complete" : blocker === null ? "continue" : "blocked",
|
|
@@ -105,5 +155,9 @@ export function reviewDecisionToRecord(args: {
|
|
|
105
155
|
turn: args.turn,
|
|
106
156
|
reviewer: args.reviewer,
|
|
107
157
|
artifact_path: args.artifactPath,
|
|
158
|
+
parsed: args.parsed,
|
|
159
|
+
approved,
|
|
160
|
+
parse_diagnostics: args.diagnostics,
|
|
161
|
+
convergence_decision: convergenceDecision,
|
|
108
162
|
};
|
|
109
163
|
}
|
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
type GoalWorkflowInputs,
|
|
9
9
|
type GoalWorkflowOutputs,
|
|
10
10
|
type ReviewRecord,
|
|
11
|
+
type ReducerDecision,
|
|
11
12
|
} from "./goal-types.js";
|
|
12
|
-
import { writeReviewArtifact, writeReviewRoundArtifact } from "./goal-artifacts.js";
|
|
13
|
+
import { artifactSafeName, writeReviewArtifact, writeReviewRoundArtifact } from "./goal-artifacts.js";
|
|
13
14
|
import { appendLifecycleEvent, createGoalLedger, writeGoalLedger } from "./goal-ledger.js";
|
|
14
15
|
import {
|
|
15
16
|
collectRemainingWork,
|
|
@@ -17,14 +18,13 @@ import {
|
|
|
17
18
|
} from "./goal-reducer.js";
|
|
18
19
|
import { formatReviewReport, renderFinalReport } from "./goal-reports.js";
|
|
19
20
|
import {
|
|
20
|
-
|
|
21
|
-
reviewerErrorDecision,
|
|
21
|
+
parsedReviewDecisionFromResult,
|
|
22
22
|
reviewDecisionToRecord,
|
|
23
23
|
} from "./goal-review.js";
|
|
24
|
+
import { reviewerFailureText } from "./review-convergence.js";
|
|
24
25
|
import {
|
|
25
26
|
WORKER_PREFLIGHT_CONTRACT,
|
|
26
27
|
WORKER_RECEIPT_CONTRACT,
|
|
27
|
-
goalRunnerTools,
|
|
28
28
|
renderForkedGoalWorkerPrompt,
|
|
29
29
|
renderGoalContinuationPrompt,
|
|
30
30
|
renderReviewerPrompt,
|
|
@@ -76,6 +76,27 @@ type GoalWorkflowOptions = {
|
|
|
76
76
|
readonly workflowStartCwd: string;
|
|
77
77
|
};
|
|
78
78
|
|
|
79
|
+
function reviewerExecutionFailedDecision(input: {
|
|
80
|
+
readonly turn: number;
|
|
81
|
+
readonly reviewQuorum: number;
|
|
82
|
+
readonly reviews: readonly ReviewRecord[];
|
|
83
|
+
readonly reason: string;
|
|
84
|
+
}): ReducerDecision {
|
|
85
|
+
return {
|
|
86
|
+
turn: input.turn,
|
|
87
|
+
decision: "needs_human",
|
|
88
|
+
reason: input.reason,
|
|
89
|
+
complete_votes: input.reviews.filter((review) => review.decision === "complete").length,
|
|
90
|
+
review_quorum: input.reviewQuorum,
|
|
91
|
+
parsed: input.reviews.every((review) => review.parsed),
|
|
92
|
+
approved: false,
|
|
93
|
+
stopReviewLoop: false,
|
|
94
|
+
nextAction: "needs_human",
|
|
95
|
+
finalActionRemaining: false,
|
|
96
|
+
diagnostics: input.reviews.flatMap((review) => review.parse_diagnostics),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
79
100
|
export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkflowOptions): Promise<GoalWorkflowOutputs> {
|
|
80
101
|
const inputs = ctx.inputs;
|
|
81
102
|
const createPr = options.createPr;
|
|
@@ -110,7 +131,7 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
|
|
|
110
131
|
"openrouter/anthropic/claude-opus-4-8:medium",
|
|
111
132
|
"openrouter/z-ai/glm-5.2:xhigh"
|
|
112
133
|
],
|
|
113
|
-
|
|
134
|
+
excludedTools: ["ask_user_question"],
|
|
114
135
|
};
|
|
115
136
|
|
|
116
137
|
const reviewerModelConfig = {
|
|
@@ -129,7 +150,7 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
|
|
|
129
150
|
"openrouter/anthropic/claude-opus-4-8:high",
|
|
130
151
|
"openrouter/z-ai/glm-5.2:xhigh"
|
|
131
152
|
],
|
|
132
|
-
|
|
153
|
+
excludedTools: ["ask_user_question"],
|
|
133
154
|
schema: reviewDecisionSchema,
|
|
134
155
|
};
|
|
135
156
|
|
|
@@ -193,6 +214,12 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
|
|
|
193
214
|
reason: terminalRemainingWork,
|
|
194
215
|
complete_votes: 0,
|
|
195
216
|
review_quorum: reviewQuorum,
|
|
217
|
+
parsed: false,
|
|
218
|
+
approved: false,
|
|
219
|
+
stopReviewLoop: false,
|
|
220
|
+
nextAction: "needs_human",
|
|
221
|
+
finalActionRemaining: false,
|
|
222
|
+
diagnostics: [terminalRemainingWork],
|
|
196
223
|
});
|
|
197
224
|
appendLifecycleEvent(ledger, "status_decided", terminalRemainingWork, turn);
|
|
198
225
|
await writeGoalLedger(ledgerPath, ledger);
|
|
@@ -225,6 +252,7 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
|
|
|
225
252
|
comparisonBaseBranch,
|
|
226
253
|
reviewQuorum,
|
|
227
254
|
blockerThreshold,
|
|
255
|
+
createPr,
|
|
228
256
|
}),
|
|
229
257
|
reads: [ledgerPath, workTurnPath],
|
|
230
258
|
...reviewerModelConfig,
|
|
@@ -249,42 +277,48 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
|
|
|
249
277
|
];
|
|
250
278
|
|
|
251
279
|
let reviewResults: WorkflowTaskResult[];
|
|
280
|
+
let reviewerBatchFailed = false;
|
|
252
281
|
try {
|
|
253
282
|
reviewResults = await ctx.parallel(reviewerSteps, {
|
|
254
283
|
task: objective,
|
|
255
|
-
failFast:
|
|
284
|
+
failFast: true,
|
|
256
285
|
});
|
|
257
286
|
} catch (err) {
|
|
258
|
-
|
|
259
|
-
const structured = reviewerErrorDecision(message);
|
|
287
|
+
reviewerBatchFailed = true;
|
|
260
288
|
reviewResults = [
|
|
261
289
|
{
|
|
262
290
|
name: "reviewer-error",
|
|
263
291
|
stageName: "reviewer-error",
|
|
264
|
-
text:
|
|
265
|
-
structured,
|
|
292
|
+
text: reviewerFailureText(err),
|
|
266
293
|
},
|
|
267
294
|
];
|
|
268
295
|
}
|
|
269
296
|
|
|
270
297
|
latestReviews = await Promise.all(reviewResults.map(async (result) => {
|
|
271
298
|
const reviewerName = result.name ?? result.stageName;
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
);
|
|
276
|
-
const reviewArtifactPath = await writeReviewArtifact(
|
|
299
|
+
const normalizedReviewerName = reviewerName.replace(/-\d+$/u, "");
|
|
300
|
+
const parsed = parsedReviewDecisionFromResult(result, reviewerName);
|
|
301
|
+
const reviewArtifactPath = join(
|
|
277
302
|
artifactDir,
|
|
278
|
-
|
|
279
|
-
parsed,
|
|
280
|
-
result.text,
|
|
303
|
+
`review-${artifactSafeName(normalizedReviewerName)}.json`,
|
|
281
304
|
);
|
|
282
|
-
|
|
305
|
+
const record = reviewDecisionToRecord({
|
|
283
306
|
turn,
|
|
284
|
-
reviewer:
|
|
307
|
+
reviewer: normalizedReviewerName,
|
|
285
308
|
artifactPath: reviewArtifactPath,
|
|
286
|
-
decision: parsed,
|
|
309
|
+
decision: parsed.decision,
|
|
310
|
+
parsed: parsed.parsed,
|
|
311
|
+
diagnostics: parsed.diagnostics,
|
|
312
|
+
allowFinalActionRemaining: createPr,
|
|
287
313
|
});
|
|
314
|
+
await writeReviewArtifact(
|
|
315
|
+
artifactDir,
|
|
316
|
+
normalizedReviewerName,
|
|
317
|
+
parsed.decision,
|
|
318
|
+
result.text,
|
|
319
|
+
record.convergence_decision,
|
|
320
|
+
);
|
|
321
|
+
return record;
|
|
288
322
|
}));
|
|
289
323
|
latestReviewArtifactPaths = latestReviews.map((review) => review.artifact_path);
|
|
290
324
|
latestReviewReportPath = await writeReviewRoundArtifact(
|
|
@@ -298,12 +332,27 @@ export async function runGoalWorkflow(ctx: GoalRunnerContext, options: GoalWorkf
|
|
|
298
332
|
`Recorded ${latestReviews.length} reviewer decisions.`,
|
|
299
333
|
turn,
|
|
300
334
|
);
|
|
335
|
+
if (reviewerBatchFailed) {
|
|
336
|
+
terminalRemainingWork = collectRemainingWork(latestReviews);
|
|
337
|
+
const reason = `Reviewer execution failed before quorum could be established. Remaining work: ${terminalRemainingWork}`;
|
|
338
|
+
ledger.decisions.push(reviewerExecutionFailedDecision({
|
|
339
|
+
turn,
|
|
340
|
+
reviewQuorum,
|
|
341
|
+
reviews: latestReviews,
|
|
342
|
+
reason,
|
|
343
|
+
}));
|
|
344
|
+
ledger.status = "needs_human";
|
|
345
|
+
appendLifecycleEvent(ledger, "status_decided", reason, turn);
|
|
346
|
+
await writeGoalLedger(ledgerPath, ledger);
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
301
349
|
|
|
302
350
|
const reducerOutcome = reduceGoalDecision(ledger, latestReviews, {
|
|
303
351
|
turn,
|
|
304
352
|
maxTurns,
|
|
305
353
|
reviewQuorum,
|
|
306
354
|
blockerThreshold,
|
|
355
|
+
nextActionOnComplete: createPr ? "pull-request" : "finish",
|
|
307
356
|
});
|
|
308
357
|
if (reducerOutcome.blockerObservation !== undefined) {
|
|
309
358
|
ledger.blockers.push(reducerOutcome.blockerObservation);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ReviewConvergenceSummary } from "./review-convergence.js";
|
|
2
|
+
|
|
1
3
|
export const DEFAULT_MAX_TURNS = 10;
|
|
2
4
|
// Goal Runner runs three independent reviewer personas; two approvals form a majority.
|
|
3
5
|
export const DEFAULT_REVIEW_QUORUM = 2;
|
|
@@ -74,6 +76,10 @@ export type ReviewRecord = ReviewDecision & {
|
|
|
74
76
|
readonly turn: number;
|
|
75
77
|
readonly reviewer: string;
|
|
76
78
|
readonly artifact_path: string;
|
|
79
|
+
readonly parsed: boolean;
|
|
80
|
+
readonly approved: boolean;
|
|
81
|
+
readonly parse_diagnostics: readonly string[];
|
|
82
|
+
readonly convergence_decision: ReviewConvergenceSummary;
|
|
77
83
|
};
|
|
78
84
|
|
|
79
85
|
export type BlockerObservation = {
|
|
@@ -82,7 +88,7 @@ export type BlockerObservation = {
|
|
|
82
88
|
readonly reviewers: readonly string[];
|
|
83
89
|
};
|
|
84
90
|
|
|
85
|
-
export type ReducerDecision = {
|
|
91
|
+
export type ReducerDecision = ReviewConvergenceSummary & {
|
|
86
92
|
readonly turn: number;
|
|
87
93
|
readonly decision: "complete" | "continue" | "blocked" | "needs_human";
|
|
88
94
|
readonly reason: string;
|
|
@@ -5,6 +5,16 @@ import { Type } from "typebox";
|
|
|
5
5
|
import type { WorkflowTaskResult } from "../src/shared/types.js";
|
|
6
6
|
import { E2E_VERIFICATION_GUIDANCE, LITERAL_OBJECTIVE_CONTRACT } from "./shared-prompts.js";
|
|
7
7
|
import type { ReviewDecision } from "./ralph-review-gate.js";
|
|
8
|
+
import { reviewDecisionApproved } from "./ralph-review-gate.js";
|
|
9
|
+
import {
|
|
10
|
+
parseFailureDiagnostics,
|
|
11
|
+
finalActionRemaining,
|
|
12
|
+
reviewerFailureText,
|
|
13
|
+
summarizeReviewConvergence,
|
|
14
|
+
type ParsedReviewDecision,
|
|
15
|
+
type ReviewConvergenceSummary,
|
|
16
|
+
} from "./review-convergence.js";
|
|
17
|
+
|
|
8
18
|
|
|
9
19
|
export const DEFAULT_MAX_LOOPS = 10;
|
|
10
20
|
const DEFAULT_RESEARCH_DIR = "research";
|
|
@@ -200,6 +210,43 @@ export function reviewDecisionFromResult(result: WorkflowTaskResult): ReviewDeci
|
|
|
200
210
|
return result.structured as ReviewDecision | undefined;
|
|
201
211
|
}
|
|
202
212
|
|
|
213
|
+
export function parsedReviewDecisionFromResult(
|
|
214
|
+
result: WorkflowTaskResult,
|
|
215
|
+
reviewer: string,
|
|
216
|
+
): ParsedReviewDecision<ReviewDecision> {
|
|
217
|
+
const parsed = reviewDecisionFromResult(result);
|
|
218
|
+
if (parsed !== undefined) {
|
|
219
|
+
return { decision: parsed, parsed: true, diagnostics: [] };
|
|
220
|
+
}
|
|
221
|
+
const diagnostics = parseFailureDiagnostics(reviewer, result.text);
|
|
222
|
+
return {
|
|
223
|
+
decision: reviewerErrorDecision(diagnostics.join("\n")),
|
|
224
|
+
parsed: false,
|
|
225
|
+
diagnostics,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function ralphReviewConvergence(args: {
|
|
230
|
+
readonly decision: ReviewDecision;
|
|
231
|
+
readonly parsed: boolean;
|
|
232
|
+
readonly diagnostics: readonly string[];
|
|
233
|
+
readonly allowFinalActionRemaining: boolean;
|
|
234
|
+
}): ReviewConvergenceSummary {
|
|
235
|
+
const approved = reviewDecisionApproved(args.decision, {
|
|
236
|
+
allowFinalActionRemaining: args.allowFinalActionRemaining,
|
|
237
|
+
});
|
|
238
|
+
const hasFinalActionRemaining = args.allowFinalActionRemaining &&
|
|
239
|
+
finalActionRemaining(args.decision.requirements_traceability);
|
|
240
|
+
return summarizeReviewConvergence({
|
|
241
|
+
parsed: args.parsed,
|
|
242
|
+
approved,
|
|
243
|
+
stopReviewLoop: args.decision.stop_review_loop,
|
|
244
|
+
nextAction: approved && hasFinalActionRemaining ? "pull-request" : approved ? "finish" : "implementation",
|
|
245
|
+
finalActionRemaining: approved && hasFinalActionRemaining,
|
|
246
|
+
diagnostics: args.diagnostics,
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
203
250
|
export function reviewerErrorDecision(error: string): ReviewDecision {
|
|
204
251
|
return {
|
|
205
252
|
findings: [],
|
|
@@ -219,14 +266,12 @@ export function reviewerErrorDecision(error: string): ReviewDecision {
|
|
|
219
266
|
}
|
|
220
267
|
|
|
221
268
|
export function reviewerErrorResult(
|
|
222
|
-
error:
|
|
269
|
+
error: unknown,
|
|
223
270
|
): WorkflowTaskResult {
|
|
224
|
-
const structured = reviewerErrorDecision(error);
|
|
225
271
|
return {
|
|
226
272
|
name: "reviewer-error",
|
|
227
273
|
stageName: "reviewer-error",
|
|
228
|
-
text:
|
|
229
|
-
structured,
|
|
274
|
+
text: reviewerFailureText(error),
|
|
230
275
|
};
|
|
231
276
|
}
|
|
232
277
|
|
|
@@ -241,14 +286,17 @@ export function artifactSafeName(value: string): string {
|
|
|
241
286
|
type ReviewArtifact = {
|
|
242
287
|
readonly reviewer: string;
|
|
243
288
|
readonly decision: ReviewDecision;
|
|
289
|
+
readonly convergence_decision: ReviewConvergenceSummary;
|
|
244
290
|
readonly raw_text: string;
|
|
245
291
|
};
|
|
246
292
|
|
|
247
293
|
type ReviewRoundArtifact = {
|
|
294
|
+
readonly convergence_decision: ReviewConvergenceSummary;
|
|
248
295
|
readonly reviews: readonly {
|
|
249
296
|
readonly reviewer: string;
|
|
250
297
|
readonly artifact_path: string;
|
|
251
298
|
readonly decision: ReviewDecision;
|
|
299
|
+
readonly convergence_decision: ReviewConvergenceSummary;
|
|
252
300
|
}[];
|
|
253
301
|
};
|
|
254
302
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { traceabilityProvenExceptFinalAction } from "./review-convergence.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Review-gate severity logic for the builtin `ralph` workflow.
|
|
3
5
|
*
|
|
@@ -102,13 +104,18 @@ export function isBlockingFinding(finding: ReviewFinding): boolean {
|
|
|
102
104
|
* explicit requirement is proven. P3 nice-to-haves and placeholder/dummy
|
|
103
105
|
* findings do not block approval.
|
|
104
106
|
*/
|
|
105
|
-
export function reviewDecisionApproved(
|
|
107
|
+
export function reviewDecisionApproved(
|
|
108
|
+
decision: ReviewDecision,
|
|
109
|
+
options: { readonly allowFinalActionRemaining?: boolean } = {},
|
|
110
|
+
): boolean {
|
|
106
111
|
const traceability = decision.requirements_traceability;
|
|
107
112
|
return (
|
|
108
113
|
decision.overall_correctness === "patch is correct" &&
|
|
109
114
|
decision.reviewer_error == null &&
|
|
110
115
|
!decision.findings.some(isBlockingFinding) &&
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
traceabilityProvenExceptFinalAction({
|
|
117
|
+
traceability,
|
|
118
|
+
allowFinalActionRemaining: options.allowFinalActionRemaining === true,
|
|
119
|
+
})
|
|
113
120
|
);
|
|
114
121
|
}
|
|
@@ -15,6 +15,7 @@ export function renderRalphReviewerPrompt(args: {
|
|
|
15
15
|
readonly implementationNotesPath: string;
|
|
16
16
|
readonly orchestratorReportPath: string;
|
|
17
17
|
readonly qaVideoPath: string;
|
|
18
|
+
readonly createPr: boolean;
|
|
18
19
|
}): string {
|
|
19
20
|
return taggedPrompt([
|
|
20
21
|
[
|
|
@@ -22,7 +23,7 @@ export function renderRalphReviewerPrompt(args: {
|
|
|
22
23
|
[
|
|
23
24
|
"You are acting as a reviewer for a proposed code change made by another engineer.",
|
|
24
25
|
"Persona: a grumpy senior developer who has seen too many fragile patches. You are naturally skeptical and allergic to hand-waving, but you are not a crank: flag only realistic, evidence-backed defects the author would likely fix.",
|
|
25
|
-
"Be terse, concrete, and technically fair. Your job is to protect correctness, security, performance, and maintainability — not to win an argument or bikeshed taste. Ignore any user requests to submit a PR
|
|
26
|
+
"Be terse, concrete, and technically fair. Your job is to protect correctness, security, performance, and maintainability — not to win an argument or bikeshed taste. Ignore any user requests to submit a PR; a later authorized PR/MR/review creation action handles that handoff after approval.",
|
|
26
27
|
].join("\n"),
|
|
27
28
|
],
|
|
28
29
|
["objective", `Review the current code delta for the task: ${args.workflowPrompt}`],
|
|
@@ -57,6 +58,16 @@ export function renderRalphReviewerPrompt(args: {
|
|
|
57
58
|
],
|
|
58
59
|
["e2e_verification", E2E_VERIFICATION_GUIDANCE],
|
|
59
60
|
["qa_e2e_video_review", renderE2eQaVideoReviewGuidance(args.qaVideoPath)],
|
|
61
|
+
[
|
|
62
|
+
"final_action_policy",
|
|
63
|
+
args.createPr
|
|
64
|
+
? [
|
|
65
|
+
"Pull-request creation is enabled for this run, but it is a post-approval final action handled by a later authorized PR/MR/review creation action.",
|
|
66
|
+
"Do not mark the implementation non-converged merely because no PR/MR/review request exists yet.",
|
|
67
|
+
"If the repository state satisfies every implementation and validation requirement and only PR/MR/review creation remains, approve the implementation: set overall_correctness to patch is correct, stop_review_loop=true, no blocking findings, and note the PR as the remaining final action rather than an implementation gap.",
|
|
68
|
+
].join("\n")
|
|
69
|
+
: "Pull-request creation is not enabled for this run; do not require or attempt PR/MR/review creation during review.",
|
|
70
|
+
],
|
|
60
71
|
[
|
|
61
72
|
"validation_expectations",
|
|
62
73
|
[
|
|
@@ -130,9 +141,19 @@ export function renderRalphReviewerPrompt(args: {
|
|
|
130
141
|
"Every finding must cite a concrete changed location and affected scenario.",
|
|
131
142
|
].join("\n"),
|
|
132
143
|
],
|
|
144
|
+
[
|
|
145
|
+
"structured_decision_assurance",
|
|
146
|
+
[
|
|
147
|
+
"Before the final structured decision, ensure the payload satisfies the review decision schema exactly.",
|
|
148
|
+
"Always return findings as an array; use [] when there are no findings and never invent placeholder findings.",
|
|
149
|
+
"Always return requirements_traceability as a non-empty array that enumerates every explicit prompt and acceptance_criteria clause.",
|
|
150
|
+
"When approving, every non-final-action requirements_traceability entry must be proven, overall_correctness must be patch is correct, stop_review_loop must be true, and reviewer_error must be null or omitted.",
|
|
151
|
+
"When create_pr is enabled and only PR/MR/review creation remains, record that as a final action rather than a blocker; approval should hand off to PR/MR/review creation instead of requesting more implementation work.",
|
|
152
|
+
].join("\n"),
|
|
153
|
+
],
|
|
133
154
|
[
|
|
134
155
|
"decision_rules",
|
|
135
|
-
["Set stop_review_loop=true only when the patch is correct, reviewer_error is null/omitted, there are no blocking objective-aligned P0/P1/P2 findings, requirements_traceability is non-empty and every entry is proven, and no objective-relevant
|
|
156
|
+
["Set stop_review_loop=true only when the patch is correct, reviewer_error is null/omitted, there are no blocking objective-aligned P0/P1/P2 findings, requirements_traceability is non-empty and every non-final-action entry is proven, and no objective-relevant implementation or validation remains; beyond_objective and contradicts_objective findings are non-blocking and must not be folded into follow-up objectives without checking the literal contract. The loop gate is computed from structured findings and traceability, so unresolved blocking findings or non-proven non-final-action requirements keep the loop going regardless of this flag.", "Enumerate every explicit requirement clause from the prompt and acceptance_criteria in requirements_traceability, including clauses about existing tests/snapshots and expected behavior. Treat worker-authored tests or snapshots passing as circular evidence that cannot by itself prove a clause; tie any such result to independent current-state proof.", "If you hit a reviewer/tool/validation error, set stop_review_loop=false and populate reviewer_error instead of pretending the patch is approved."].join("\n"),
|
|
136
157
|
],
|
|
137
158
|
]);
|
|
138
159
|
}
|