@kenkaiiii/ggcoder 4.3.231 → 4.3.233
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 +1 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -89
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -1
- package/dist/config.js.map +1 -1
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +29 -0
- package/dist/config.test.js.map +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/ideal-review.d.ts +20 -0
- package/dist/core/ideal-review.d.ts.map +1 -0
- package/dist/core/ideal-review.js +55 -0
- package/dist/core/ideal-review.js.map +1 -0
- package/dist/core/ideal-review.test.d.ts +2 -0
- package/dist/core/ideal-review.test.d.ts.map +1 -0
- package/dist/core/ideal-review.test.js +59 -0
- package/dist/core/ideal-review.test.js.map +1 -0
- package/dist/core/prompt-commands.d.ts.map +1 -1
- package/dist/core/prompt-commands.js +8 -16
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/prompt-commands.test.js +14 -44
- package/dist/core/prompt-commands.test.js.map +1 -1
- package/dist/core/runtime-mode.d.ts +0 -11
- package/dist/core/runtime-mode.d.ts.map +1 -1
- package/dist/core/runtime-mode.js +0 -9
- package/dist/core/runtime-mode.js.map +1 -1
- package/dist/core/session-restore-display.test.js +4 -110
- package/dist/core/session-restore-display.test.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +2 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/interactive.d.ts.map +1 -1
- package/dist/interactive.js +1 -1
- package/dist/interactive.js.map +1 -1
- package/dist/system-prompt.d.ts +1 -2
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +11 -58
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +3 -158
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/bash.d.ts +1 -4
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +3 -12
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/checkpoint-hook.test.js +3 -3
- package/dist/tools/checkpoint-hook.test.js.map +1 -1
- package/dist/tools/edit.d.ts +1 -4
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +5 -13
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/enter-plan.js +1 -1
- package/dist/tools/enter-plan.js.map +1 -1
- package/dist/tools/html-extract.d.ts +58 -0
- package/dist/tools/html-extract.d.ts.map +1 -0
- package/dist/tools/html-extract.js +130 -0
- package/dist/tools/html-extract.js.map +1 -0
- package/dist/tools/html-extract.test.d.ts +2 -0
- package/dist/tools/html-extract.test.d.ts.map +1 -0
- package/dist/tools/html-extract.test.js +60 -0
- package/dist/tools/html-extract.test.js.map +1 -0
- package/dist/tools/index.d.ts +0 -9
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -8
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/pdf-extract.d.ts +18 -0
- package/dist/tools/pdf-extract.d.ts.map +1 -0
- package/dist/tools/pdf-extract.js +43 -0
- package/dist/tools/pdf-extract.js.map +1 -0
- package/dist/tools/pdf-extract.test.d.ts +2 -0
- package/dist/tools/pdf-extract.test.d.ts.map +1 -0
- package/dist/tools/pdf-extract.test.js +15 -0
- package/dist/tools/pdf-extract.test.js.map +1 -0
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +2 -3
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/screenshot.d.ts +1 -1
- package/dist/tools/subagent.d.ts +1 -4
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +2 -5
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/web-fetch.d.ts +16 -1
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +357 -45
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-fetch.test.js +263 -2
- package/dist/tools/web-fetch.test.js.map +1 -1
- package/dist/tools/web-search.d.ts +14 -0
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +321 -35
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools/web-search.test.js +144 -1
- package/dist/tools/web-search.test.js.map +1 -1
- package/dist/tools/write.d.ts +1 -4
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +5 -13
- package/dist/tools/write.js.map +1 -1
- package/dist/ui/App.d.ts +7 -20
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +124 -309
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/app-items.d.ts +36 -25
- package/dist/ui/app-items.d.ts.map +1 -1
- package/dist/ui/app-items.js +39 -0
- package/dist/ui/app-items.js.map +1 -1
- package/dist/ui/app-items.test.d.ts +2 -0
- package/dist/ui/app-items.test.d.ts.map +1 -0
- package/dist/ui/app-items.test.js +38 -0
- package/dist/ui/app-items.test.js.map +1 -0
- package/dist/ui/app-state-persistence.test.js +14 -318
- package/dist/ui/app-state-persistence.test.js.map +1 -1
- package/dist/ui/chat-layout-pinning.test.js +74 -4
- package/dist/ui/chat-layout-pinning.test.js.map +1 -1
- package/dist/ui/components/AssistantMessage.test.js +6 -9
- package/dist/ui/components/AssistantMessage.test.js.map +1 -1
- package/dist/ui/components/Banner.js +1 -1
- package/dist/ui/components/Banner.js.map +1 -1
- package/dist/ui/components/ChatFooterPane.d.ts +1 -5
- package/dist/ui/components/ChatFooterPane.d.ts.map +1 -1
- package/dist/ui/components/ChatFooterPane.js +3 -4
- package/dist/ui/components/ChatFooterPane.js.map +1 -1
- package/dist/ui/components/ChatInputStack.d.ts +3 -1
- package/dist/ui/components/ChatInputStack.d.ts.map +1 -1
- package/dist/ui/components/ChatInputStack.js +4 -3
- package/dist/ui/components/ChatInputStack.js.map +1 -1
- package/dist/ui/components/ChatScreen.d.ts +3 -16
- package/dist/ui/components/ChatScreen.d.ts.map +1 -1
- package/dist/ui/components/ChatScreen.js +2 -3
- package/dist/ui/components/ChatScreen.js.map +1 -1
- package/dist/ui/components/Footer.d.ts +3 -8
- package/dist/ui/components/Footer.d.ts.map +1 -1
- package/dist/ui/components/Footer.js +5 -25
- package/dist/ui/components/Footer.js.map +1 -1
- package/dist/ui/components/IdealHookMessage.d.ts +12 -0
- package/dist/ui/components/IdealHookMessage.d.ts.map +1 -0
- package/dist/ui/components/IdealHookMessage.js +24 -0
- package/dist/ui/components/IdealHookMessage.js.map +1 -0
- package/dist/ui/components/InputArea.d.ts +1 -9
- package/dist/ui/components/InputArea.d.ts.map +1 -1
- package/dist/ui/components/InputArea.js +2 -44
- package/dist/ui/components/InputArea.js.map +1 -1
- package/dist/ui/components/LiveToolPanel.d.ts +30 -0
- package/dist/ui/components/LiveToolPanel.d.ts.map +1 -0
- package/dist/ui/components/LiveToolPanel.js +66 -0
- package/dist/ui/components/LiveToolPanel.js.map +1 -0
- package/dist/ui/components/ToolExecution.js +0 -2
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/components/TranscriptViewport.d.ts +1 -1
- package/dist/ui/components/TranscriptViewport.js +1 -1
- package/dist/ui/footer-jump-regression.test.js +12 -2
- package/dist/ui/footer-jump-regression.test.js.map +1 -1
- package/dist/ui/footer-status-layout.test.js +4 -12
- package/dist/ui/footer-status-layout.test.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.d.ts +2 -0
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +45 -1
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/hooks/useChatLayoutMeasurements.d.ts +3 -4
- package/dist/ui/hooks/useChatLayoutMeasurements.d.ts.map +1 -1
- package/dist/ui/hooks/useChatLayoutMeasurements.js +26 -4
- package/dist/ui/hooks/useChatLayoutMeasurements.js.map +1 -1
- package/dist/ui/hooks/useModeState.d.ts +4 -19
- package/dist/ui/hooks/useModeState.d.ts.map +1 -1
- package/dist/ui/hooks/useModeState.js +5 -45
- package/dist/ui/hooks/useModeState.js.map +1 -1
- package/dist/ui/hooks/usePixelFixFlow.js +2 -2
- package/dist/ui/layout-decisions.d.ts +11 -34
- package/dist/ui/layout-decisions.d.ts.map +1 -1
- package/dist/ui/layout-decisions.js +15 -42
- package/dist/ui/layout-decisions.js.map +1 -1
- package/dist/ui/live-area-height.d.ts.map +1 -1
- package/dist/ui/live-area-height.js +6 -1
- package/dist/ui/live-area-height.js.map +1 -1
- package/dist/ui/live-frame-height.test.js +26 -1
- package/dist/ui/live-frame-height.test.js.map +1 -1
- package/dist/ui/plan-overlay.test.js +1 -1
- package/dist/ui/plan-overlay.test.js.map +1 -1
- package/dist/ui/prompt-routing.d.ts +1 -19
- package/dist/ui/prompt-routing.d.ts.map +1 -1
- package/dist/ui/prompt-routing.js +1 -79
- package/dist/ui/prompt-routing.js.map +1 -1
- package/dist/ui/render.d.ts +6 -18
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +2 -10
- package/dist/ui/render.js.map +1 -1
- package/dist/ui/scroll-stabilization.test.js +1 -7
- package/dist/ui/scroll-stabilization.test.js.map +1 -1
- package/dist/ui/slash-command-images.test.js +11 -86
- package/dist/ui/slash-command-images.test.js.map +1 -1
- package/dist/ui/streaming-flush-bounce.test.d.ts +2 -0
- package/dist/ui/streaming-flush-bounce.test.d.ts.map +1 -0
- package/dist/ui/streaming-flush-bounce.test.js +156 -0
- package/dist/ui/streaming-flush-bounce.test.js.map +1 -0
- package/dist/ui/submit-prompt-command.d.ts +1 -16
- package/dist/ui/submit-prompt-command.d.ts.map +1 -1
- package/dist/ui/submit-prompt-command.js +4 -54
- package/dist/ui/submit-prompt-command.js.map +1 -1
- package/dist/ui/submit-slash-commands.d.ts +0 -1
- package/dist/ui/submit-slash-commands.d.ts.map +1 -1
- package/dist/ui/submit-slash-commands.js +0 -4
- package/dist/ui/submit-slash-commands.js.map +1 -1
- package/dist/ui/terminal-history-status-renderers.d.ts +0 -1
- package/dist/ui/terminal-history-status-renderers.d.ts.map +1 -1
- package/dist/ui/terminal-history-status-renderers.js +0 -3
- package/dist/ui/terminal-history-status-renderers.js.map +1 -1
- package/dist/ui/terminal-history.d.ts.map +1 -1
- package/dist/ui/terminal-history.js +19 -56
- package/dist/ui/terminal-history.js.map +1 -1
- package/dist/ui/terminal-history.test.js +6 -33
- package/dist/ui/terminal-history.test.js.map +1 -1
- package/dist/ui/tool-line-summary.d.ts +29 -0
- package/dist/ui/tool-line-summary.d.ts.map +1 -0
- package/dist/ui/tool-line-summary.js +153 -0
- package/dist/ui/tool-line-summary.js.map +1 -0
- package/dist/ui/transcript/TranscriptRenderer.d.ts +1 -1
- package/dist/ui/transcript/TranscriptRenderer.d.ts.map +1 -1
- package/dist/ui/transcript/TranscriptRenderer.js +21 -12
- package/dist/ui/transcript/TranscriptRenderer.js.map +1 -1
- package/dist/ui/transcript/presentation.d.ts +1 -17
- package/dist/ui/transcript/presentation.d.ts.map +1 -1
- package/dist/ui/transcript/presentation.js +0 -26
- package/dist/ui/transcript/presentation.js.map +1 -1
- package/dist/ui/transcript/spacing.d.ts +2 -2
- package/dist/ui/transcript/spacing.d.ts.map +1 -1
- package/dist/ui/transcript/spacing.js +15 -9
- package/dist/ui/transcript/spacing.js.map +1 -1
- package/dist/ui/transcript/spacing.test.js +7 -8
- package/dist/ui/transcript/spacing.test.js.map +1 -1
- package/dist/ui/transcript/tool-presentation.js +1 -1
- package/dist/ui/transcript/tool-presentation.js.map +1 -1
- package/dist/ui/transcript/transcript-lines.d.ts.map +1 -1
- package/dist/ui/transcript/transcript-lines.js +4 -0
- package/dist/ui/transcript/transcript-lines.js.map +1 -1
- package/dist/ui/tui-history-parity.test.js +8 -47
- package/dist/ui/tui-history-parity.test.js.map +1 -1
- package/dist/ui/tui-simulation.test.js +2 -1
- package/dist/ui/tui-simulation.test.js.map +1 -1
- package/dist/utils/format.js +7 -0
- package/dist/utils/format.js.map +1 -1
- package/package.json +11 -5
- package/dist/core/goal-controller.d.ts +0 -82
- package/dist/core/goal-controller.d.ts.map +0 -1
- package/dist/core/goal-controller.js +0 -838
- package/dist/core/goal-controller.js.map +0 -1
- package/dist/core/goal-controller.test.d.ts +0 -2
- package/dist/core/goal-controller.test.d.ts.map +0 -1
- package/dist/core/goal-controller.test.js +0 -1279
- package/dist/core/goal-controller.test.js.map +0 -1
- package/dist/core/goal-engine.d.ts +0 -61
- package/dist/core/goal-engine.d.ts.map +0 -1
- package/dist/core/goal-engine.js +0 -123
- package/dist/core/goal-engine.js.map +0 -1
- package/dist/core/goal-engine.test.d.ts +0 -2
- package/dist/core/goal-engine.test.d.ts.map +0 -1
- package/dist/core/goal-engine.test.js +0 -295
- package/dist/core/goal-engine.test.js.map +0 -1
- package/dist/core/goal-integration.d.ts +0 -80
- package/dist/core/goal-integration.d.ts.map +0 -1
- package/dist/core/goal-integration.js +0 -296
- package/dist/core/goal-integration.js.map +0 -1
- package/dist/core/goal-integration.test.d.ts +0 -2
- package/dist/core/goal-integration.test.d.ts.map +0 -1
- package/dist/core/goal-integration.test.js +0 -369
- package/dist/core/goal-integration.test.js.map +0 -1
- package/dist/core/goal-lifecycle-smoke.test.d.ts +0 -2
- package/dist/core/goal-lifecycle-smoke.test.d.ts.map +0 -1
- package/dist/core/goal-lifecycle-smoke.test.js +0 -248
- package/dist/core/goal-lifecycle-smoke.test.js.map +0 -1
- package/dist/core/goal-overhead-harness.d.ts +0 -33
- package/dist/core/goal-overhead-harness.d.ts.map +0 -1
- package/dist/core/goal-overhead-harness.js +0 -268
- package/dist/core/goal-overhead-harness.js.map +0 -1
- package/dist/core/goal-prerequisites.d.ts +0 -23
- package/dist/core/goal-prerequisites.d.ts.map +0 -1
- package/dist/core/goal-prerequisites.js +0 -114
- package/dist/core/goal-prerequisites.js.map +0 -1
- package/dist/core/goal-prerequisites.test.d.ts +0 -2
- package/dist/core/goal-prerequisites.test.d.ts.map +0 -1
- package/dist/core/goal-prerequisites.test.js +0 -154
- package/dist/core/goal-prerequisites.test.js.map +0 -1
- package/dist/core/goal-references.d.ts +0 -14
- package/dist/core/goal-references.d.ts.map +0 -1
- package/dist/core/goal-references.js +0 -153
- package/dist/core/goal-references.js.map +0 -1
- package/dist/core/goal-references.test.d.ts +0 -2
- package/dist/core/goal-references.test.d.ts.map +0 -1
- package/dist/core/goal-references.test.js +0 -77
- package/dist/core/goal-references.test.js.map +0 -1
- package/dist/core/goal-store.d.ts +0 -289
- package/dist/core/goal-store.d.ts.map +0 -1
- package/dist/core/goal-store.js +0 -1156
- package/dist/core/goal-store.js.map +0 -1
- package/dist/core/goal-store.test.d.ts +0 -2
- package/dist/core/goal-store.test.d.ts.map +0 -1
- package/dist/core/goal-store.test.js +0 -530
- package/dist/core/goal-store.test.js.map +0 -1
- package/dist/core/goal-verifier.d.ts +0 -17
- package/dist/core/goal-verifier.d.ts.map +0 -1
- package/dist/core/goal-verifier.js +0 -87
- package/dist/core/goal-verifier.js.map +0 -1
- package/dist/core/goal-verifier.test.d.ts +0 -2
- package/dist/core/goal-verifier.test.d.ts.map +0 -1
- package/dist/core/goal-verifier.test.js +0 -131
- package/dist/core/goal-verifier.test.js.map +0 -1
- package/dist/core/goal-worker-dev-server-lifecycle.test.d.ts +0 -2
- package/dist/core/goal-worker-dev-server-lifecycle.test.d.ts.map +0 -1
- package/dist/core/goal-worker-dev-server-lifecycle.test.js +0 -68
- package/dist/core/goal-worker-dev-server-lifecycle.test.js.map +0 -1
- package/dist/core/goal-worker.d.ts +0 -61
- package/dist/core/goal-worker.d.ts.map +0 -1
- package/dist/core/goal-worker.js +0 -467
- package/dist/core/goal-worker.js.map +0 -1
- package/dist/core/goal-worker.test.d.ts +0 -2
- package/dist/core/goal-worker.test.d.ts.map +0 -1
- package/dist/core/goal-worker.test.js +0 -493
- package/dist/core/goal-worker.test.js.map +0 -1
- package/dist/core/goal-worktree.d.ts +0 -108
- package/dist/core/goal-worktree.d.ts.map +0 -1
- package/dist/core/goal-worktree.js +0 -300
- package/dist/core/goal-worktree.js.map +0 -1
- package/dist/core/goal-worktree.test.d.ts +0 -2
- package/dist/core/goal-worktree.test.d.ts.map +0 -1
- package/dist/core/goal-worktree.test.js +0 -448
- package/dist/core/goal-worktree.test.js.map +0 -1
- package/dist/tools/goal-mode.test.d.ts +0 -2
- package/dist/tools/goal-mode.test.d.ts.map +0 -1
- package/dist/tools/goal-mode.test.js +0 -121
- package/dist/tools/goal-mode.test.js.map +0 -1
- package/dist/tools/goals.d.ts +0 -143
- package/dist/tools/goals.d.ts.map +0 -1
- package/dist/tools/goals.js +0 -1038
- package/dist/tools/goals.js.map +0 -1
- package/dist/tools/goals.test.d.ts +0 -2
- package/dist/tools/goals.test.d.ts.map +0 -1
- package/dist/tools/goals.test.js +0 -1444
- package/dist/tools/goals.test.js.map +0 -1
- package/dist/ui/components/GoalOverlay.d.ts +0 -83
- package/dist/ui/components/GoalOverlay.d.ts.map +0 -1
- package/dist/ui/components/GoalOverlay.js +0 -710
- package/dist/ui/components/GoalOverlay.js.map +0 -1
- package/dist/ui/components/GoalPickerMenu.d.ts +0 -9
- package/dist/ui/components/GoalPickerMenu.d.ts.map +0 -1
- package/dist/ui/components/GoalPickerMenu.js +0 -37
- package/dist/ui/components/GoalPickerMenu.js.map +0 -1
- package/dist/ui/components/GoalStatusBar.d.ts +0 -26
- package/dist/ui/components/GoalStatusBar.d.ts.map +0 -1
- package/dist/ui/components/GoalStatusBar.js +0 -130
- package/dist/ui/components/GoalStatusBar.js.map +0 -1
- package/dist/ui/components/GoalStatusBar.test.d.ts +0 -2
- package/dist/ui/components/GoalStatusBar.test.d.ts.map +0 -1
- package/dist/ui/components/GoalStatusBar.test.js +0 -17
- package/dist/ui/components/GoalStatusBar.test.js.map +0 -1
- package/dist/ui/goal-events.d.ts +0 -125
- package/dist/ui/goal-events.d.ts.map +0 -1
- package/dist/ui/goal-events.js +0 -407
- package/dist/ui/goal-events.js.map +0 -1
- package/dist/ui/goal-events.test.d.ts +0 -2
- package/dist/ui/goal-events.test.d.ts.map +0 -1
- package/dist/ui/goal-events.test.js +0 -416
- package/dist/ui/goal-events.test.js.map +0 -1
- package/dist/ui/goal-lifecycle-orchestration.test.d.ts +0 -2
- package/dist/ui/goal-lifecycle-orchestration.test.d.ts.map +0 -1
- package/dist/ui/goal-lifecycle-orchestration.test.js +0 -555
- package/dist/ui/goal-lifecycle-orchestration.test.js.map +0 -1
- package/dist/ui/goal-overlay.test.d.ts +0 -2
- package/dist/ui/goal-overlay.test.d.ts.map +0 -1
- package/dist/ui/goal-overlay.test.js +0 -384
- package/dist/ui/goal-overlay.test.js.map +0 -1
- package/dist/ui/goal-progress.d.ts +0 -31
- package/dist/ui/goal-progress.d.ts.map +0 -1
- package/dist/ui/goal-progress.js +0 -149
- package/dist/ui/goal-progress.js.map +0 -1
- package/dist/ui/goal-run-helpers.d.ts +0 -12
- package/dist/ui/goal-run-helpers.d.ts.map +0 -1
- package/dist/ui/goal-run-helpers.js +0 -42
- package/dist/ui/goal-run-helpers.js.map +0 -1
- package/dist/ui/goal-status-bar.test.d.ts +0 -2
- package/dist/ui/goal-status-bar.test.d.ts.map +0 -1
- package/dist/ui/goal-status-bar.test.js +0 -174
- package/dist/ui/goal-status-bar.test.js.map +0 -1
- package/dist/ui/goal-summary.d.ts +0 -14
- package/dist/ui/goal-summary.d.ts.map +0 -1
- package/dist/ui/goal-summary.js +0 -194
- package/dist/ui/goal-summary.js.map +0 -1
- package/dist/ui/hooks/useGoalOrchestration.d.ts +0 -82
- package/dist/ui/hooks/useGoalOrchestration.d.ts.map +0 -1
- package/dist/ui/hooks/useGoalOrchestration.js +0 -863
- package/dist/ui/hooks/useGoalOrchestration.js.map +0 -1
- package/dist/ui/hooks/useGoalPickerController.d.ts +0 -22
- package/dist/ui/hooks/useGoalPickerController.d.ts.map +0 -1
- package/dist/ui/hooks/useGoalPickerController.js +0 -35
- package/dist/ui/hooks/useGoalPickerController.js.map +0 -1
- package/dist/ui/prompt-routing.test.d.ts +0 -2
- package/dist/ui/prompt-routing.test.d.ts.map +0 -1
- package/dist/ui/prompt-routing.test.js +0 -48
- package/dist/ui/prompt-routing.test.js.map +0 -1
- package/dist/ui/transcript/GoalRows.d.ts +0 -10
- package/dist/ui/transcript/GoalRows.d.ts.map +0 -1
- package/dist/ui/transcript/GoalRows.js +0 -35
- package/dist/ui/transcript/GoalRows.js.map +0 -1
package/dist/tools/goals.test.js
DELETED
|
@@ -1,1444 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import os from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { createGoalsTool } from "./goals.js";
|
|
6
|
-
import { decideGoalNextAction } from "../core/goal-controller.js";
|
|
7
|
-
import { getActiveGoalRun, getGoalRun, upsertGoalRun, } from "../core/goal-store.js";
|
|
8
|
-
let tmpBase;
|
|
9
|
-
let tmpProject;
|
|
10
|
-
async function executeGoals(args) {
|
|
11
|
-
return createGoalsTool(tmpProject).execute(args, {
|
|
12
|
-
signal: new AbortController().signal,
|
|
13
|
-
toolCallId: "test-call",
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
beforeEach(async () => {
|
|
17
|
-
tmpBase = await fs.mkdtemp(path.join(os.tmpdir(), "goals-tool-test-base-"));
|
|
18
|
-
tmpProject = await fs.mkdtemp(path.join(os.tmpdir(), "goals-tool-test-project-"));
|
|
19
|
-
process.env.GG_GOALS_BASE = tmpBase;
|
|
20
|
-
});
|
|
21
|
-
afterEach(async () => {
|
|
22
|
-
delete process.env.GG_GOALS_BASE;
|
|
23
|
-
await fs.rm(tmpBase, { recursive: true, force: true });
|
|
24
|
-
await fs.rm(tmpProject, { recursive: true, force: true });
|
|
25
|
-
});
|
|
26
|
-
describe("goals tool state guards", () => {
|
|
27
|
-
it("checks runnable prerequisites during create before marking the Goal ready", async () => {
|
|
28
|
-
await fs.writeFile(path.join(tmpProject, "fixture.txt"), "ready", "utf-8");
|
|
29
|
-
await executeGoals({
|
|
30
|
-
action: "create",
|
|
31
|
-
run_id: "checked-create",
|
|
32
|
-
title: "Checked create",
|
|
33
|
-
goal: "Do not defer cheap prerequisite checks",
|
|
34
|
-
success_criteria: ["fixture exists"],
|
|
35
|
-
evidence_plan: [
|
|
36
|
-
{
|
|
37
|
-
id: "fixture-proof",
|
|
38
|
-
label: "Fixture proof",
|
|
39
|
-
mechanism: "command",
|
|
40
|
-
description: "Check fixture file",
|
|
41
|
-
status: "ready",
|
|
42
|
-
command: "test -f fixture.txt",
|
|
43
|
-
evidence: "checked",
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
verifier_command: "test -f fixture.txt",
|
|
47
|
-
prerequisites: [
|
|
48
|
-
{
|
|
49
|
-
id: "fixture",
|
|
50
|
-
label: "Fixture file exists",
|
|
51
|
-
status: "unknown",
|
|
52
|
-
check_command: "test -f fixture.txt",
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
});
|
|
56
|
-
const run = await getGoalRun(tmpProject, "checked-create");
|
|
57
|
-
expect(run?.status).toBe("ready");
|
|
58
|
-
expect(run?.prerequisites[0]).toMatchObject({
|
|
59
|
-
id: "fixture",
|
|
60
|
-
status: "met",
|
|
61
|
-
checkCommand: "test -f fixture.txt",
|
|
62
|
-
});
|
|
63
|
-
expect(run?.prerequisites[0]?.evidence).toContain("exited 0");
|
|
64
|
-
});
|
|
65
|
-
it("persists prerequisite kind and keeps a create with an unmet external prerequisite blocked", async () => {
|
|
66
|
-
await executeGoals({
|
|
67
|
-
action: "create",
|
|
68
|
-
run_id: "kind-create",
|
|
69
|
-
title: "Kind create",
|
|
70
|
-
goal: "Prerequisite kind must round-trip",
|
|
71
|
-
success_criteria: ["kind persisted"],
|
|
72
|
-
evidence_plan: [
|
|
73
|
-
{
|
|
74
|
-
id: "kind-proof",
|
|
75
|
-
label: "Kind proof",
|
|
76
|
-
mechanism: "command",
|
|
77
|
-
description: "Confirm kind",
|
|
78
|
-
status: "ready",
|
|
79
|
-
command: "true",
|
|
80
|
-
evidence: "ok",
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
verifier_command: "true",
|
|
84
|
-
prerequisites: [
|
|
85
|
-
{
|
|
86
|
-
id: "secret",
|
|
87
|
-
label: "Production secret",
|
|
88
|
-
status: "missing",
|
|
89
|
-
kind: "external",
|
|
90
|
-
instructions: "Provide PROD_SECRET.",
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
});
|
|
94
|
-
const run = await getGoalRun(tmpProject, "kind-create");
|
|
95
|
-
expect(run?.prerequisites[0]).toMatchObject({ id: "secret", kind: "external" });
|
|
96
|
-
expect(run?.status).toBe("blocked");
|
|
97
|
-
});
|
|
98
|
-
it("rejects unsafe prerequisite check commands without executing them", async () => {
|
|
99
|
-
const marker = path.join(tmpProject, "unsafe-marker.txt");
|
|
100
|
-
await executeGoals({
|
|
101
|
-
action: "create",
|
|
102
|
-
run_id: "unsafe-prereq",
|
|
103
|
-
title: "Unsafe prereq",
|
|
104
|
-
goal: "Unsafe prerequisite commands must not mutate the project",
|
|
105
|
-
success_criteria: ["unsafe command is blocked"],
|
|
106
|
-
evidence_plan: [
|
|
107
|
-
{
|
|
108
|
-
id: "unsafe-proof",
|
|
109
|
-
label: "Unsafe command proof",
|
|
110
|
-
mechanism: "command",
|
|
111
|
-
description: "Confirm unsafe command was rejected",
|
|
112
|
-
status: "ready",
|
|
113
|
-
command: "test ! -e unsafe-marker.txt",
|
|
114
|
-
evidence: "marker absent",
|
|
115
|
-
},
|
|
116
|
-
],
|
|
117
|
-
verifier_command: "test ! -e unsafe-marker.txt",
|
|
118
|
-
prerequisites: [
|
|
119
|
-
{
|
|
120
|
-
id: "unsafe",
|
|
121
|
-
label: "Unsafe check",
|
|
122
|
-
status: "unknown",
|
|
123
|
-
check_command: "echo unsafe > unsafe-marker.txt",
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
});
|
|
127
|
-
const run = await getGoalRun(tmpProject, "unsafe-prereq");
|
|
128
|
-
await expect(fs.stat(marker)).rejects.toMatchObject({ code: "ENOENT" });
|
|
129
|
-
// A check_command implies a locally-resolvable prerequisite, so an unmet one
|
|
130
|
-
// no longer blocks the run; the controller schedules a resolve task instead.
|
|
131
|
-
expect(run?.status).toBe("ready");
|
|
132
|
-
expect(run?.prerequisites[0]).toMatchObject({
|
|
133
|
-
id: "unsafe",
|
|
134
|
-
status: "missing",
|
|
135
|
-
checkCommand: "echo unsafe > unsafe-marker.txt",
|
|
136
|
-
});
|
|
137
|
-
expect(run?.prerequisites[0]?.evidence).toContain("rejected as unsafe");
|
|
138
|
-
expect(run?.prerequisites[0]?.evidence).toContain("Command was not executed");
|
|
139
|
-
});
|
|
140
|
-
it("blocks create when a prerequisite has not been checked or evidenced", async () => {
|
|
141
|
-
const result = await executeGoals({
|
|
142
|
-
action: "create",
|
|
143
|
-
run_id: "unchecked-create",
|
|
144
|
-
title: "Unchecked create",
|
|
145
|
-
goal: "Do not accept lazy met prereqs",
|
|
146
|
-
success_criteria: ["tooling checked"],
|
|
147
|
-
evidence_plan: [
|
|
148
|
-
{
|
|
149
|
-
id: "tooling-proof",
|
|
150
|
-
label: "Tooling proof",
|
|
151
|
-
mechanism: "command",
|
|
152
|
-
description: "Check tooling",
|
|
153
|
-
status: "ready",
|
|
154
|
-
command: "node --version",
|
|
155
|
-
evidence: "checked",
|
|
156
|
-
},
|
|
157
|
-
],
|
|
158
|
-
verifier_command: "node --version",
|
|
159
|
-
prerequisites: [{ id: "tooling", label: "Local tooling", status: "met" }],
|
|
160
|
-
});
|
|
161
|
-
const run = await getGoalRun(tmpProject, "unchecked-create");
|
|
162
|
-
expect(result).toContain("blocked");
|
|
163
|
-
expect(run?.status).toBe("blocked");
|
|
164
|
-
expect(run?.prerequisites[0]).toMatchObject({
|
|
165
|
-
id: "tooling",
|
|
166
|
-
status: "met",
|
|
167
|
-
instructions: "Check Local tooling locally and record non-secret evidence before workers can start.",
|
|
168
|
-
});
|
|
169
|
-
expect(run?.prerequisites[0]?.evidence).toBeUndefined();
|
|
170
|
-
});
|
|
171
|
-
it("creates minimal goals as draft with setup blockers", async () => {
|
|
172
|
-
const result = await executeGoals({
|
|
173
|
-
action: "create",
|
|
174
|
-
run_id: "minimal-create",
|
|
175
|
-
title: "Minimal create",
|
|
176
|
-
goal: "Missing proof gates stay draft",
|
|
177
|
-
});
|
|
178
|
-
const run = await getGoalRun(tmpProject, "minimal-create");
|
|
179
|
-
expect(result).toContain("draft");
|
|
180
|
-
expect(run?.status).toBe("draft");
|
|
181
|
-
expect(run?.blockers).toEqual(expect.arrayContaining([
|
|
182
|
-
"Goal setup incomplete: success criteria are required.",
|
|
183
|
-
"Goal setup incomplete: evidence_plan is required.",
|
|
184
|
-
"Goal setup incomplete: verifier_command is required.",
|
|
185
|
-
]));
|
|
186
|
-
});
|
|
187
|
-
it("clears stale setup blockers after create update supplies required setup", async () => {
|
|
188
|
-
await executeGoals({
|
|
189
|
-
action: "create",
|
|
190
|
-
run_id: "draft-then-ready",
|
|
191
|
-
title: "Draft then ready",
|
|
192
|
-
goal: "Replace setup draft with complete Goal metadata",
|
|
193
|
-
});
|
|
194
|
-
const result = await executeGoals({
|
|
195
|
-
action: "create",
|
|
196
|
-
run_id: "draft-then-ready",
|
|
197
|
-
title: "Draft then ready",
|
|
198
|
-
goal: "Replace setup draft with complete Goal metadata",
|
|
199
|
-
success_criteria: ["Ready setup has no stale blockers"],
|
|
200
|
-
evidence_plan: [
|
|
201
|
-
{
|
|
202
|
-
id: "ready-proof",
|
|
203
|
-
label: "Ready proof",
|
|
204
|
-
mechanism: "test",
|
|
205
|
-
description: "Focused test proves stale setup blockers clear",
|
|
206
|
-
status: "ready",
|
|
207
|
-
evidence: "configured",
|
|
208
|
-
},
|
|
209
|
-
],
|
|
210
|
-
verifier_command: "pnpm test",
|
|
211
|
-
});
|
|
212
|
-
const run = await getGoalRun(tmpProject, "draft-then-ready");
|
|
213
|
-
expect(result).toContain("ready");
|
|
214
|
-
expect(run?.status).toBe("ready");
|
|
215
|
-
expect(run?.blockers).toEqual([]);
|
|
216
|
-
});
|
|
217
|
-
it("preserves earlier evidence when create update records planner GOAL_PLAN", async () => {
|
|
218
|
-
await executeGoals({
|
|
219
|
-
action: "create",
|
|
220
|
-
run_id: "planner-evidence-merge",
|
|
221
|
-
title: "Planner evidence merge",
|
|
222
|
-
goal: "Keep preexisting evidence across setup updates",
|
|
223
|
-
success_criteria: ["initial criterion"],
|
|
224
|
-
evidence_plan: [
|
|
225
|
-
{
|
|
226
|
-
id: "initial-proof",
|
|
227
|
-
label: "Initial proof",
|
|
228
|
-
mechanism: "command",
|
|
229
|
-
description: "Initial evidence plan",
|
|
230
|
-
status: "ready",
|
|
231
|
-
evidence: "configured",
|
|
232
|
-
},
|
|
233
|
-
],
|
|
234
|
-
verifier_command: "pnpm test",
|
|
235
|
-
});
|
|
236
|
-
await executeGoals({
|
|
237
|
-
action: "evidence",
|
|
238
|
-
run_id: "planner-evidence-merge",
|
|
239
|
-
evidence_label: "Preexisting audit note",
|
|
240
|
-
evidence_content: "must survive setup update",
|
|
241
|
-
});
|
|
242
|
-
await executeGoals({
|
|
243
|
-
action: "create",
|
|
244
|
-
run_id: "planner-evidence-merge",
|
|
245
|
-
title: "Planner evidence merge",
|
|
246
|
-
goal: "Keep preexisting evidence across setup updates GOAL_PLAN research=none success=ready",
|
|
247
|
-
summary: "GOAL_PLAN\nresearch=none\nsuccess=ready\nEND_GOAL_PLAN",
|
|
248
|
-
});
|
|
249
|
-
const run = await getGoalRun(tmpProject, "planner-evidence-merge");
|
|
250
|
-
expect(run?.evidence).toEqual(expect.arrayContaining([
|
|
251
|
-
expect.objectContaining({ label: "Preexisting audit note" }),
|
|
252
|
-
expect.objectContaining({ label: "Planner GOAL_PLAN" }),
|
|
253
|
-
]));
|
|
254
|
-
});
|
|
255
|
-
it("routes worker goal tool writes to the original project path from isolated worktrees", async () => {
|
|
256
|
-
const workerCwd = await fs.mkdtemp(path.join(os.tmpdir(), "goals-tool-worker-cwd-"));
|
|
257
|
-
const previousProjectPath = process.env.GG_GOAL_PROJECT_PATH;
|
|
258
|
-
try {
|
|
259
|
-
process.env.GG_GOAL_PROJECT_PATH = tmpProject;
|
|
260
|
-
await upsertGoalRun(tmpProject, {
|
|
261
|
-
id: "worker-env-goal",
|
|
262
|
-
title: "Worker env goal",
|
|
263
|
-
goal: "Persist from isolated worker cwd",
|
|
264
|
-
status: "ready",
|
|
265
|
-
successCriteria: [],
|
|
266
|
-
prerequisites: [],
|
|
267
|
-
harness: [],
|
|
268
|
-
evidencePlan: [],
|
|
269
|
-
tasks: [],
|
|
270
|
-
evidence: [],
|
|
271
|
-
blockers: [],
|
|
272
|
-
});
|
|
273
|
-
const tool = createGoalsTool(workerCwd);
|
|
274
|
-
const result = await tool.execute({
|
|
275
|
-
action: "evidence",
|
|
276
|
-
evidence_kind: "summary",
|
|
277
|
-
evidence_label: "Worker isolated evidence",
|
|
278
|
-
evidence_content: "stored on original project",
|
|
279
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
280
|
-
const projectRun = await getGoalRun(tmpProject, "worker-env-goal");
|
|
281
|
-
const workerRun = await getActiveGoalRun(workerCwd);
|
|
282
|
-
expect(result).toBe('Evidence added to "Worker env goal".');
|
|
283
|
-
expect(workerRun).toBeNull();
|
|
284
|
-
expect(projectRun?.evidence).toEqual(expect.arrayContaining([
|
|
285
|
-
expect.objectContaining({
|
|
286
|
-
label: "Worker isolated evidence",
|
|
287
|
-
content: "stored on original project",
|
|
288
|
-
}),
|
|
289
|
-
]));
|
|
290
|
-
}
|
|
291
|
-
finally {
|
|
292
|
-
if (previousProjectPath === undefined) {
|
|
293
|
-
delete process.env.GG_GOAL_PROJECT_PATH;
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
process.env.GG_GOAL_PROJECT_PATH = previousProjectPath;
|
|
297
|
-
}
|
|
298
|
-
await fs.rm(workerCwd, { recursive: true, force: true });
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
it("updates an explicit run_id task and evidence when no active goal exists in the caller cwd", async () => {
|
|
302
|
-
const runProject = await fs.mkdtemp(path.join(os.tmpdir(), "goals-tool-explicit-run-project-"));
|
|
303
|
-
try {
|
|
304
|
-
await upsertGoalRun(runProject, {
|
|
305
|
-
id: "099c9f7f-bce7-475c-93b8-d9b3f88a0569",
|
|
306
|
-
title: "Explicit run",
|
|
307
|
-
goal: "Update from worker cwd",
|
|
308
|
-
status: "passed",
|
|
309
|
-
});
|
|
310
|
-
const tool = createGoalsTool(tmpProject);
|
|
311
|
-
const taskResult = await tool.execute({
|
|
312
|
-
action: "task",
|
|
313
|
-
run_id: "099c9f7f-bce7-475c-93b8-d9b3f88a0569",
|
|
314
|
-
task_id: "worker-task",
|
|
315
|
-
task_title: "Worker callback",
|
|
316
|
-
task_prompt: "Persist callback",
|
|
317
|
-
task_status: "done",
|
|
318
|
-
summary: "callback complete",
|
|
319
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
320
|
-
const evidenceResult = await tool.execute({
|
|
321
|
-
action: "evidence",
|
|
322
|
-
run_id: "099c9f7f",
|
|
323
|
-
evidence_kind: "summary",
|
|
324
|
-
evidence_label: "Worker evidence",
|
|
325
|
-
evidence_content: "same discovered run",
|
|
326
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
327
|
-
const run = await getGoalRun(runProject, "099c9f7f");
|
|
328
|
-
expect(taskResult).toBe('Goal task added: "Worker callback" (id: worker-task). Reference this id (or the exact title) in another task\'s depends_on.');
|
|
329
|
-
expect(evidenceResult).toBe('Evidence added to "Explicit run".');
|
|
330
|
-
expect(run?.tasks).toEqual(expect.arrayContaining([
|
|
331
|
-
expect.objectContaining({
|
|
332
|
-
id: "worker-task",
|
|
333
|
-
status: "done",
|
|
334
|
-
lastSummary: "callback complete",
|
|
335
|
-
}),
|
|
336
|
-
]));
|
|
337
|
-
expect(run?.evidence).toEqual(expect.arrayContaining([
|
|
338
|
-
expect.objectContaining({ label: "Worker evidence", content: "same discovered run" }),
|
|
339
|
-
]));
|
|
340
|
-
}
|
|
341
|
-
finally {
|
|
342
|
-
await fs.rm(runProject, { recursive: true, force: true });
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
it("persists active Goal references and requires worker task prompts to name them", async () => {
|
|
346
|
-
const reference = {
|
|
347
|
-
id: "repo-reference",
|
|
348
|
-
kind: "repo",
|
|
349
|
-
label: "Reference repository https://github.com/acme/reference-ui",
|
|
350
|
-
value: "https://github.com/acme/reference-ui",
|
|
351
|
-
};
|
|
352
|
-
const documentReference = {
|
|
353
|
-
id: "doc-reference",
|
|
354
|
-
kind: "text",
|
|
355
|
-
label: "Attached text reference requirements.md",
|
|
356
|
-
path: ".gg/goal-references/doc-reference-requirements.md",
|
|
357
|
-
};
|
|
358
|
-
const tool = createGoalsTool(tmpProject, undefined, () => [reference, documentReference]);
|
|
359
|
-
await tool.execute({
|
|
360
|
-
action: "create",
|
|
361
|
-
run_id: "reference-goal",
|
|
362
|
-
title: "Match reference repo",
|
|
363
|
-
goal: "Implement the UI from the reference repository",
|
|
364
|
-
success_criteria: [
|
|
365
|
-
"Implementation matches repo-reference and doc-reference visual and interaction patterns",
|
|
366
|
-
],
|
|
367
|
-
evidence_plan: [
|
|
368
|
-
{
|
|
369
|
-
id: "reference-comparison",
|
|
370
|
-
label: "repo-reference and doc-reference comparison",
|
|
371
|
-
mechanism: "source",
|
|
372
|
-
description: "Compare against repo-reference and doc-reference before completion",
|
|
373
|
-
status: "ready",
|
|
374
|
-
evidence: "reference captured",
|
|
375
|
-
},
|
|
376
|
-
],
|
|
377
|
-
verifier_command: "pnpm test",
|
|
378
|
-
verifier_description: "Verifier compares output against repo-reference and doc-reference",
|
|
379
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
380
|
-
const missingReferenceResult = await tool.execute({
|
|
381
|
-
action: "task",
|
|
382
|
-
run_id: "reference-goal",
|
|
383
|
-
task_id: "generic-task",
|
|
384
|
-
task_title: "Implement UI",
|
|
385
|
-
task_prompt: "Build the requested UI.",
|
|
386
|
-
task_status: "pending",
|
|
387
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
388
|
-
const referencedTaskResult = await tool.execute({
|
|
389
|
-
action: "task",
|
|
390
|
-
run_id: "reference-goal",
|
|
391
|
-
task_id: "reference-task",
|
|
392
|
-
task_title: "Implement UI from repo-reference and doc-reference",
|
|
393
|
-
task_prompt: "Use repo-reference / https://github.com/acme/reference-ui and doc-reference at .gg/goal-references/doc-reference-requirements.md as the source of truth while implementing.",
|
|
394
|
-
task_status: "pending",
|
|
395
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
396
|
-
const run = await getGoalRun(tmpProject, "reference-goal");
|
|
397
|
-
expect(missingReferenceResult).toContain("task_prompt must explicitly include");
|
|
398
|
-
expect(missingReferenceResult).toContain("repo-reference, doc-reference");
|
|
399
|
-
expect(referencedTaskResult).toBe('Goal task added: "Implement UI from repo-reference and doc-reference" (id: reference-task). Reference this id (or the exact title) in another task\'s depends_on.');
|
|
400
|
-
expect(run?.status).toBe("ready");
|
|
401
|
-
expect(run?.references).toEqual(expect.arrayContaining([
|
|
402
|
-
expect.objectContaining(reference),
|
|
403
|
-
expect.objectContaining(documentReference),
|
|
404
|
-
]));
|
|
405
|
-
expect(run?.tasks).toEqual(expect.arrayContaining([expect.objectContaining({ id: "reference-task" })]));
|
|
406
|
-
});
|
|
407
|
-
it("persists worker-worktree verifier cwd through setup and verifier results", async () => {
|
|
408
|
-
await executeGoals({
|
|
409
|
-
action: "create",
|
|
410
|
-
run_id: "worktree-verifier-goal",
|
|
411
|
-
title: "Worktree verifier",
|
|
412
|
-
goal: "Verify from a worker worktree",
|
|
413
|
-
success_criteria: ["Verifier runs"],
|
|
414
|
-
evidence_plan: [
|
|
415
|
-
{
|
|
416
|
-
id: "proof",
|
|
417
|
-
label: "Proof",
|
|
418
|
-
mechanism: "command",
|
|
419
|
-
description: "Run worker-built verifier",
|
|
420
|
-
status: "ready",
|
|
421
|
-
evidence: "configured",
|
|
422
|
-
},
|
|
423
|
-
],
|
|
424
|
-
verifier_command: ".goal-evidence/noop/audit.sh",
|
|
425
|
-
verifier_description: "Worker-built verifier",
|
|
426
|
-
verifier_cwd: "/tmp/project-goal-worktrees/task-worker",
|
|
427
|
-
});
|
|
428
|
-
await executeGoals({
|
|
429
|
-
action: "verify",
|
|
430
|
-
run_id: "worktree-verifier-goal",
|
|
431
|
-
verification_status: "pass",
|
|
432
|
-
summary: "Verifier passed in worker worktree",
|
|
433
|
-
exit_code: 0,
|
|
434
|
-
});
|
|
435
|
-
const run = await getGoalRun(tmpProject, "worktree-verifier-goal");
|
|
436
|
-
expect(run?.verifier).toMatchObject({
|
|
437
|
-
command: ".goal-evidence/noop/audit.sh",
|
|
438
|
-
cwd: "/tmp/project-goal-worktrees/task-worker",
|
|
439
|
-
lastResult: {
|
|
440
|
-
status: "pass",
|
|
441
|
-
command: ".goal-evidence/noop/audit.sh",
|
|
442
|
-
summary: "Verifier passed in worker worktree",
|
|
443
|
-
},
|
|
444
|
-
});
|
|
445
|
-
});
|
|
446
|
-
it("rejects passing final audits that omit mandatory Goal references", async () => {
|
|
447
|
-
const reference = {
|
|
448
|
-
id: "image-reference",
|
|
449
|
-
kind: "image",
|
|
450
|
-
label: "Attached image reference mockup.png",
|
|
451
|
-
path: ".gg/goal-references/image-reference-mockup.png",
|
|
452
|
-
};
|
|
453
|
-
const tool = createGoalsTool(tmpProject, undefined, () => [reference]);
|
|
454
|
-
await tool.execute({
|
|
455
|
-
action: "create",
|
|
456
|
-
run_id: "reference-audit-goal",
|
|
457
|
-
title: "Match screenshot",
|
|
458
|
-
goal: "Implement UI from screenshot",
|
|
459
|
-
success_criteria: ["UI matches image-reference"],
|
|
460
|
-
evidence_plan: [
|
|
461
|
-
{
|
|
462
|
-
id: "image-reference-proof",
|
|
463
|
-
label: "image-reference comparison",
|
|
464
|
-
mechanism: "screenshot",
|
|
465
|
-
description: "Compare output with image-reference",
|
|
466
|
-
status: "ready",
|
|
467
|
-
evidence: "comparison configured",
|
|
468
|
-
},
|
|
469
|
-
],
|
|
470
|
-
verifier_command: "pnpm test",
|
|
471
|
-
verifier_description: "Verifier checks image-reference",
|
|
472
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
473
|
-
await tool.execute({
|
|
474
|
-
action: "verify",
|
|
475
|
-
run_id: "reference-audit-goal",
|
|
476
|
-
verification_status: "pass",
|
|
477
|
-
summary: "Verifier passed for image-reference",
|
|
478
|
-
exit_code: 0,
|
|
479
|
-
output_path: "artifacts/verifier.log",
|
|
480
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
481
|
-
const checkedAt = (await getGoalRun(tmpProject, "reference-audit-goal"))?.verifier?.lastResult
|
|
482
|
-
?.checkedAt;
|
|
483
|
-
const missingReferenceAudit = await tool.execute({
|
|
484
|
-
action: "audit",
|
|
485
|
-
run_id: "reference-audit-goal",
|
|
486
|
-
verification_status: "pass",
|
|
487
|
-
summary: `FINAL_AUDIT_PASS verifier_checked_at=${checkedAt}; output=artifacts/verifier.log`,
|
|
488
|
-
output_path: "artifacts/verifier.log",
|
|
489
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
490
|
-
const referencedAudit = await tool.execute({
|
|
491
|
-
action: "audit",
|
|
492
|
-
run_id: "reference-audit-goal",
|
|
493
|
-
verification_status: "pass",
|
|
494
|
-
summary: `FINAL_AUDIT_PASS verifier_checked_at=${checkedAt}; image-reference output=artifacts/verifier.log`,
|
|
495
|
-
output_path: "artifacts/verifier.log",
|
|
496
|
-
}, { signal: new AbortController().signal, toolCallId: "test-call" });
|
|
497
|
-
expect(missingReferenceAudit).toContain("must explicitly reference every non-prompt Goal reference");
|
|
498
|
-
expect(referencedAudit).toBe('Completion audit recorded for "Match screenshot": pass.');
|
|
499
|
-
});
|
|
500
|
-
it("persists typed Goal task DAG metadata and preserves it on status updates", async () => {
|
|
501
|
-
await executeGoals({
|
|
502
|
-
action: "create",
|
|
503
|
-
run_id: "dag-goal",
|
|
504
|
-
title: "Typed DAG",
|
|
505
|
-
goal: "Persist Goal task dependency metadata",
|
|
506
|
-
success_criteria: ["DAG metadata survives updates"],
|
|
507
|
-
prerequisites: [],
|
|
508
|
-
verifier_command: "pnpm test",
|
|
509
|
-
evidence_plan: [
|
|
510
|
-
{
|
|
511
|
-
id: "dag-proof",
|
|
512
|
-
label: "DAG metadata proof",
|
|
513
|
-
mechanism: "test",
|
|
514
|
-
description: "Focused tests prove typed Goal task metadata is durable.",
|
|
515
|
-
status: "ready",
|
|
516
|
-
evidence: "configured",
|
|
517
|
-
},
|
|
518
|
-
],
|
|
519
|
-
});
|
|
520
|
-
await executeGoals({
|
|
521
|
-
action: "task",
|
|
522
|
-
run_id: "dag-goal",
|
|
523
|
-
task_id: "schema-task",
|
|
524
|
-
task_title: "Build schema candidate",
|
|
525
|
-
task_prompt: "Build only the schema candidate in an isolated worktree.",
|
|
526
|
-
task_status: "done",
|
|
527
|
-
});
|
|
528
|
-
const addResult = await executeGoals({
|
|
529
|
-
action: "task",
|
|
530
|
-
run_id: "dag-goal",
|
|
531
|
-
task_id: "ui-task",
|
|
532
|
-
task_title: "Build UI candidate",
|
|
533
|
-
task_prompt: "Build only the UI candidate in an isolated worktree.",
|
|
534
|
-
task_status: "pending",
|
|
535
|
-
depends_on: ["schema-task"],
|
|
536
|
-
parallel_group: "frontend",
|
|
537
|
-
expected_changed_scope: ["packages/ggcoder/src/ui/**"],
|
|
538
|
-
integration: "candidate",
|
|
539
|
-
});
|
|
540
|
-
const updateResult = await executeGoals({
|
|
541
|
-
action: "task",
|
|
542
|
-
run_id: "dag-goal",
|
|
543
|
-
task_id: "ui-task",
|
|
544
|
-
task_status: "done",
|
|
545
|
-
summary: "UI candidate complete",
|
|
546
|
-
});
|
|
547
|
-
const updated = await getGoalRun(tmpProject, "dag-goal");
|
|
548
|
-
expect(addResult).toBe('Goal task added: "Build UI candidate" (id: ui-task). Reference this id (or the exact title) in another task\'s depends_on.');
|
|
549
|
-
expect(updateResult).toBe('Goal task updated: "Build UI candidate" (id: ui-task). Reference this id (or the exact title) in another task\'s depends_on.');
|
|
550
|
-
expect(updated?.tasks.find((task) => task.id === "ui-task")).toEqual(expect.objectContaining({
|
|
551
|
-
id: "ui-task",
|
|
552
|
-
title: "Build UI candidate",
|
|
553
|
-
prompt: "Build only the UI candidate in an isolated worktree.",
|
|
554
|
-
status: "done",
|
|
555
|
-
lastSummary: "UI candidate complete",
|
|
556
|
-
dependsOn: ["schema-task"],
|
|
557
|
-
parallelGroup: "frontend",
|
|
558
|
-
expectedChangedScope: ["packages/ggcoder/src/ui/**"],
|
|
559
|
-
integration: "candidate",
|
|
560
|
-
}));
|
|
561
|
-
const status = await executeGoals({ action: "status", run_id: "dag-goal" });
|
|
562
|
-
expect(status).toContain("[ready] Typed DAG (id: dag-goal) — no prereqs, 2/2 tasks done, verifier configured");
|
|
563
|
-
expect(status).not.toContain("DAG:");
|
|
564
|
-
expect(status).not.toContain("expected_changed_scope=");
|
|
565
|
-
});
|
|
566
|
-
it("keeps status output compact without verbose reference or DAG detail blocks", async () => {
|
|
567
|
-
await executeGoals({
|
|
568
|
-
action: "create",
|
|
569
|
-
run_id: "compact-status-goal",
|
|
570
|
-
title: "Compact status",
|
|
571
|
-
goal: "Show compact Goal status",
|
|
572
|
-
success_criteria: ["Status is one line"],
|
|
573
|
-
prerequisites: [],
|
|
574
|
-
verifier_command: "pnpm test",
|
|
575
|
-
evidence_plan: [
|
|
576
|
-
{
|
|
577
|
-
id: "status-proof",
|
|
578
|
-
label: "Status proof",
|
|
579
|
-
mechanism: "test",
|
|
580
|
-
description: "Focused tests prove status output does not wrap with verbose metadata.",
|
|
581
|
-
status: "ready",
|
|
582
|
-
evidence: "configured",
|
|
583
|
-
},
|
|
584
|
-
],
|
|
585
|
-
});
|
|
586
|
-
await executeGoals({
|
|
587
|
-
action: "task",
|
|
588
|
-
run_id: "compact-status-goal",
|
|
589
|
-
task_id: "audit-task",
|
|
590
|
-
task_title: "Audit /goal efficiency hotspots",
|
|
591
|
-
task_prompt: "Audit the /goal system.",
|
|
592
|
-
task_status: "done",
|
|
593
|
-
parallel_group: "analysis",
|
|
594
|
-
expected_changed_scope: ["packages/ggcoder/src/tools/goals.ts"],
|
|
595
|
-
integration: "manual",
|
|
596
|
-
});
|
|
597
|
-
const result = await executeGoals({ action: "status", run_id: "compact-status-goal" });
|
|
598
|
-
expect(result).toContain("[ready] Compact status (id: compact-) — no prereqs, 1/1 tasks done, verifier configured");
|
|
599
|
-
expect(result).not.toContain("\nReferences:");
|
|
600
|
-
expect(result).not.toContain("\nTasks:");
|
|
601
|
-
expect(result).not.toContain("DAG:");
|
|
602
|
-
expect(result).not.toContain("expected_changed_scope=");
|
|
603
|
-
});
|
|
604
|
-
it("resolves task title dependencies to ids and rejects missing dependencies", async () => {
|
|
605
|
-
await executeGoals({
|
|
606
|
-
action: "create",
|
|
607
|
-
run_id: "dag-title-goal",
|
|
608
|
-
title: "Title dependencies",
|
|
609
|
-
goal: "Normalize Goal task dependencies",
|
|
610
|
-
success_criteria: ["Dependencies are stored as task ids"],
|
|
611
|
-
prerequisites: [],
|
|
612
|
-
verifier_command: "pnpm test",
|
|
613
|
-
evidence_plan: [
|
|
614
|
-
{
|
|
615
|
-
id: "dependency-proof",
|
|
616
|
-
label: "Dependency proof",
|
|
617
|
-
mechanism: "test",
|
|
618
|
-
description: "Focused tests prove depends_on cannot create permanently blocked runs.",
|
|
619
|
-
status: "ready",
|
|
620
|
-
evidence: "configured",
|
|
621
|
-
},
|
|
622
|
-
],
|
|
623
|
-
});
|
|
624
|
-
await executeGoals({
|
|
625
|
-
action: "task",
|
|
626
|
-
run_id: "dag-title-goal",
|
|
627
|
-
task_id: "audit-task",
|
|
628
|
-
task_title: "Audit /goal efficiency hotspots",
|
|
629
|
-
task_prompt: "Audit the /goal system.",
|
|
630
|
-
task_status: "done",
|
|
631
|
-
});
|
|
632
|
-
const missingResult = await executeGoals({
|
|
633
|
-
action: "task",
|
|
634
|
-
run_id: "dag-title-goal",
|
|
635
|
-
task_id: "blocked-task",
|
|
636
|
-
task_title: "Blocked task",
|
|
637
|
-
task_prompt: "This should not be persisted with an invalid dependency.",
|
|
638
|
-
depends_on: ["Missing task title"],
|
|
639
|
-
});
|
|
640
|
-
const titleResult = await executeGoals({
|
|
641
|
-
action: "task",
|
|
642
|
-
run_id: "dag-title-goal",
|
|
643
|
-
task_id: "implementation-task",
|
|
644
|
-
task_title: "Simplify goal routing/controller",
|
|
645
|
-
task_prompt: "Implement the audited /goal simplification.",
|
|
646
|
-
depends_on: ["Audit /goal efficiency hotspots"],
|
|
647
|
-
});
|
|
648
|
-
const run = await getGoalRun(tmpProject, "dag-title-goal");
|
|
649
|
-
expect(missingResult).toContain('depends_on entry "Missing task title" does not match an existing task id, id prefix, or exact title');
|
|
650
|
-
expect(titleResult).toBe('Goal task added: "Simplify goal routing/controller" (id: implementation-task). Reference this id (or the exact title) in another task\'s depends_on.');
|
|
651
|
-
expect(run?.tasks.find((task) => task.id === "blocked-task")).toBeUndefined();
|
|
652
|
-
expect(run?.tasks.find((task) => task.id === "implementation-task")?.dependsOn).toEqual([
|
|
653
|
-
"audit-task",
|
|
654
|
-
]);
|
|
655
|
-
expect(run ? decideGoalNextAction(run) : null).toMatchObject({
|
|
656
|
-
kind: "start_worker",
|
|
657
|
-
task: expect.objectContaining({ id: "implementation-task" }),
|
|
658
|
-
});
|
|
659
|
-
});
|
|
660
|
-
it("returns the generated task id so dependents can reference it by id", async () => {
|
|
661
|
-
await executeGoals({
|
|
662
|
-
action: "create",
|
|
663
|
-
run_id: "dag-id-goal",
|
|
664
|
-
title: "Returned ids",
|
|
665
|
-
goal: "Adding a task returns its id for depends_on wiring",
|
|
666
|
-
success_criteria: ["task id is returned"],
|
|
667
|
-
prerequisites: [],
|
|
668
|
-
verifier_command: "pnpm test",
|
|
669
|
-
evidence_plan: [
|
|
670
|
-
{
|
|
671
|
-
id: "id-proof",
|
|
672
|
-
label: "Id proof",
|
|
673
|
-
mechanism: "test",
|
|
674
|
-
description: "Adding a task echoes its id.",
|
|
675
|
-
status: "ready",
|
|
676
|
-
evidence: "configured",
|
|
677
|
-
},
|
|
678
|
-
],
|
|
679
|
-
});
|
|
680
|
-
// No task_id supplied -> the tool generates one and must echo it back.
|
|
681
|
-
const added = await executeGoals({
|
|
682
|
-
action: "task",
|
|
683
|
-
run_id: "dag-id-goal",
|
|
684
|
-
task_title: "Baseline investigation",
|
|
685
|
-
task_prompt: "Investigate first.",
|
|
686
|
-
task_status: "done",
|
|
687
|
-
});
|
|
688
|
-
const match = /\(id: ([^)]+)\)/.exec(String(added));
|
|
689
|
-
expect(match).not.toBeNull();
|
|
690
|
-
const baselineId = match[1];
|
|
691
|
-
// The dependent task can wire depends_on using the returned id.
|
|
692
|
-
await executeGoals({
|
|
693
|
-
action: "task",
|
|
694
|
-
run_id: "dag-id-goal",
|
|
695
|
-
task_id: "dependent-task",
|
|
696
|
-
task_title: "Dependent work",
|
|
697
|
-
task_prompt: "Runs after baseline.",
|
|
698
|
-
depends_on: [baselineId],
|
|
699
|
-
});
|
|
700
|
-
const run = await getGoalRun(tmpProject, "dag-id-goal");
|
|
701
|
-
expect(run?.tasks.find((task) => task.id === "dependent-task")?.dependsOn).toEqual([
|
|
702
|
-
baselineId,
|
|
703
|
-
]);
|
|
704
|
-
});
|
|
705
|
-
it("status resolves full UUID, short ID, and completed latest fallback", async () => {
|
|
706
|
-
await executeGoals({
|
|
707
|
-
action: "create",
|
|
708
|
-
run_id: "099c9f7f-bce7-475c-93b8-d9b3f88a0569",
|
|
709
|
-
title: "Status target",
|
|
710
|
-
goal: "Status lookup",
|
|
711
|
-
prerequisites: [],
|
|
712
|
-
});
|
|
713
|
-
await executeGoals({
|
|
714
|
-
action: "verify",
|
|
715
|
-
run_id: "099c9f7f",
|
|
716
|
-
verification_status: "fail",
|
|
717
|
-
summary: "failed",
|
|
718
|
-
});
|
|
719
|
-
await expect(executeGoals({ action: "status", run_id: "099c9f7f-bce7-475c-93b8-d9b3f88a0569" })).resolves.toContain("Status target");
|
|
720
|
-
await expect(executeGoals({ action: "status", run_id: "099c9f7f" })).resolves.toContain("[ready] Status target");
|
|
721
|
-
await expect(executeGoals({
|
|
722
|
-
action: "evidence",
|
|
723
|
-
evidence_label: "Latest failed",
|
|
724
|
-
evidence_content: "fallback",
|
|
725
|
-
})).resolves.toBe('Evidence added to "Status target".');
|
|
726
|
-
});
|
|
727
|
-
it("persists evidence plans on create and preserves them on metadata updates", async () => {
|
|
728
|
-
await executeGoals({
|
|
729
|
-
action: "create",
|
|
730
|
-
run_id: "goal-evidence-plan",
|
|
731
|
-
title: "Proof plan",
|
|
732
|
-
goal: "Verify real browser behavior",
|
|
733
|
-
success_criteria: ["Browser flow passes"],
|
|
734
|
-
prerequisites: [],
|
|
735
|
-
evidence_plan: [
|
|
736
|
-
{
|
|
737
|
-
id: "browser-proof",
|
|
738
|
-
label: "Browser smoke proof",
|
|
739
|
-
mechanism: "browser",
|
|
740
|
-
description: "Run Playwright locally and capture screenshot/log evidence.",
|
|
741
|
-
status: "planned",
|
|
742
|
-
},
|
|
743
|
-
{
|
|
744
|
-
id: "file-proof",
|
|
745
|
-
label: "File artifact proof",
|
|
746
|
-
mechanism: "file",
|
|
747
|
-
description: "Inspect a durable generated artifact file.",
|
|
748
|
-
status: "ready",
|
|
749
|
-
path: "artifacts/proof.json",
|
|
750
|
-
evidence: "artifact schema captured",
|
|
751
|
-
},
|
|
752
|
-
],
|
|
753
|
-
});
|
|
754
|
-
await executeGoals({
|
|
755
|
-
action: "create",
|
|
756
|
-
run_id: "goal-evidence-plan",
|
|
757
|
-
title: "Proof plan updated",
|
|
758
|
-
goal: "Verify real browser behavior",
|
|
759
|
-
success_criteria: ["Browser flow passes"],
|
|
760
|
-
prerequisites: [],
|
|
761
|
-
verifier_command: "pnpm test:e2e",
|
|
762
|
-
});
|
|
763
|
-
const run = await getGoalRun(tmpProject, "goal-evidence-plan");
|
|
764
|
-
expect(run?.evidencePlan).toEqual(expect.arrayContaining([
|
|
765
|
-
expect.objectContaining({
|
|
766
|
-
id: "browser-proof",
|
|
767
|
-
mechanism: "browser",
|
|
768
|
-
status: "planned",
|
|
769
|
-
}),
|
|
770
|
-
expect.objectContaining({
|
|
771
|
-
id: "file-proof",
|
|
772
|
-
mechanism: "file",
|
|
773
|
-
status: "ready",
|
|
774
|
-
path: "artifacts/proof.json",
|
|
775
|
-
}),
|
|
776
|
-
]));
|
|
777
|
-
expect(run?.verifier?.command).toBe("pnpm test:e2e");
|
|
778
|
-
});
|
|
779
|
-
it("adds new evidence-plan items directly after minimal Goal creation", async () => {
|
|
780
|
-
await executeGoals({
|
|
781
|
-
action: "create",
|
|
782
|
-
run_id: "goal-evidence-plan-add",
|
|
783
|
-
title: "Proof plan add",
|
|
784
|
-
goal: "Add proof paths after initial Goal creation",
|
|
785
|
-
success_criteria: ["Evidence plan can be added after create"],
|
|
786
|
-
verifier_command: "pnpm test",
|
|
787
|
-
});
|
|
788
|
-
const result = await executeGoals({
|
|
789
|
-
action: "evidence_plan",
|
|
790
|
-
run_id: "goal-evidence-plan-add",
|
|
791
|
-
evidence_plan: [
|
|
792
|
-
{
|
|
793
|
-
id: "manual-proof",
|
|
794
|
-
label: "Manual setup proof",
|
|
795
|
-
mechanism: "manual",
|
|
796
|
-
description: "Manual inspection proves setup worked.",
|
|
797
|
-
status: "planned",
|
|
798
|
-
},
|
|
799
|
-
],
|
|
800
|
-
});
|
|
801
|
-
const run = await getGoalRun(tmpProject, "goal-evidence-plan-add");
|
|
802
|
-
expect(result).toBe('Evidence-plan item added for "Proof plan add": "Manual setup proof".');
|
|
803
|
-
expect(run?.status).toBe("ready");
|
|
804
|
-
expect(run?.blockers).toEqual([]);
|
|
805
|
-
expect(run?.evidencePlan).toEqual([
|
|
806
|
-
expect.objectContaining({
|
|
807
|
-
id: "manual-proof",
|
|
808
|
-
label: "Manual setup proof",
|
|
809
|
-
mechanism: "manual",
|
|
810
|
-
status: "planned",
|
|
811
|
-
}),
|
|
812
|
-
]);
|
|
813
|
-
});
|
|
814
|
-
it("upserts evidence-plan items from evidence_plan arrays", async () => {
|
|
815
|
-
await executeGoals({
|
|
816
|
-
action: "create",
|
|
817
|
-
run_id: "goal-evidence-plan-upsert",
|
|
818
|
-
title: "Proof plan upsert",
|
|
819
|
-
goal: "Update proof paths from an array call",
|
|
820
|
-
success_criteria: ["Evidence plan can be upserted"],
|
|
821
|
-
verifier_command: "pnpm test",
|
|
822
|
-
evidence_plan: [
|
|
823
|
-
{
|
|
824
|
-
id: "manual-proof",
|
|
825
|
-
label: "Manual setup proof",
|
|
826
|
-
mechanism: "manual",
|
|
827
|
-
description: "Manual inspection proves setup worked.",
|
|
828
|
-
status: "planned",
|
|
829
|
-
},
|
|
830
|
-
],
|
|
831
|
-
});
|
|
832
|
-
const result = await executeGoals({
|
|
833
|
-
action: "evidence_plan",
|
|
834
|
-
run_id: "goal-evidence-plan-upsert",
|
|
835
|
-
evidence_plan: [
|
|
836
|
-
{
|
|
837
|
-
id: "manual-proof",
|
|
838
|
-
label: "Manual setup proof updated",
|
|
839
|
-
mechanism: "manual",
|
|
840
|
-
description: "Manual inspection now has durable evidence.",
|
|
841
|
-
status: "ready",
|
|
842
|
-
evidence: "inspection recorded",
|
|
843
|
-
},
|
|
844
|
-
{
|
|
845
|
-
id: "log-proof",
|
|
846
|
-
label: "Log proof",
|
|
847
|
-
mechanism: "log",
|
|
848
|
-
description: "Inspect durable setup log.",
|
|
849
|
-
status: "planned",
|
|
850
|
-
path: "artifacts/setup.log",
|
|
851
|
-
},
|
|
852
|
-
],
|
|
853
|
-
});
|
|
854
|
-
const run = await getGoalRun(tmpProject, "goal-evidence-plan-upsert");
|
|
855
|
-
expect(result).toBe('Evidence-plan items upserted for "Proof plan upsert": 1 added, 1 updated.');
|
|
856
|
-
expect(run?.evidencePlan).toEqual([
|
|
857
|
-
expect.objectContaining({
|
|
858
|
-
id: "manual-proof",
|
|
859
|
-
label: "Manual setup proof updated",
|
|
860
|
-
status: "ready",
|
|
861
|
-
evidence: "inspection recorded",
|
|
862
|
-
}),
|
|
863
|
-
expect.objectContaining({ id: "log-proof", label: "Log proof", path: "artifacts/setup.log" }),
|
|
864
|
-
]);
|
|
865
|
-
});
|
|
866
|
-
it("updates evidence-plan items directly for post-verifier reconciliation", async () => {
|
|
867
|
-
await executeGoals({
|
|
868
|
-
action: "create",
|
|
869
|
-
run_id: "goal-evidence-reconcile",
|
|
870
|
-
title: "Proof reconciliation",
|
|
871
|
-
goal: "Reconcile proof bookkeeping after verifier pass",
|
|
872
|
-
success_criteria: ["Verifier pass with evidence-plan ready"],
|
|
873
|
-
prerequisites: [],
|
|
874
|
-
evidence_plan: [
|
|
875
|
-
{
|
|
876
|
-
id: "slash-proof",
|
|
877
|
-
label: "/goal slash wrapper evidence",
|
|
878
|
-
mechanism: "test",
|
|
879
|
-
description: "Prompt command tests prove slash wrapper behavior.",
|
|
880
|
-
status: "planned",
|
|
881
|
-
command: "pnpm --filter @kenkaiiii/ggcoder test -- prompt-commands.test.ts",
|
|
882
|
-
},
|
|
883
|
-
],
|
|
884
|
-
verifier_command: "pnpm test",
|
|
885
|
-
});
|
|
886
|
-
await upsertGoalRun(tmpProject, {
|
|
887
|
-
id: "goal-evidence-reconcile",
|
|
888
|
-
title: "Proof reconciliation",
|
|
889
|
-
goal: "Reconcile proof bookkeeping after verifier pass",
|
|
890
|
-
status: "blocked",
|
|
891
|
-
blockers: ["stale evidence-plan mismatch"],
|
|
892
|
-
verifier: {
|
|
893
|
-
description: "Full check",
|
|
894
|
-
command: "pnpm test",
|
|
895
|
-
lastResult: {
|
|
896
|
-
status: "pass",
|
|
897
|
-
summary: "Verifier passed before reconciliation.",
|
|
898
|
-
checkedAt: "2024-01-01T00:00:00.000Z",
|
|
899
|
-
},
|
|
900
|
-
},
|
|
901
|
-
});
|
|
902
|
-
const result = await executeGoals({
|
|
903
|
-
action: "evidence_plan",
|
|
904
|
-
run_id: "goal-evidence-reconcile",
|
|
905
|
-
evidence_plan_item_id: "slash-proof",
|
|
906
|
-
evidence_plan_status: "ready",
|
|
907
|
-
evidence_content: "prompt-commands.test.ts passed as part of focused Goal coverage.",
|
|
908
|
-
});
|
|
909
|
-
const run = await getGoalRun(tmpProject, "goal-evidence-reconcile");
|
|
910
|
-
expect(result).toBe('Evidence-plan item updated for "Proof reconciliation": "/goal slash wrapper evidence" is ready.');
|
|
911
|
-
expect(run?.status).toBe("ready");
|
|
912
|
-
expect(run?.blockers).toEqual([]);
|
|
913
|
-
expect(run?.evidencePlan[0]).toMatchObject({
|
|
914
|
-
id: "slash-proof",
|
|
915
|
-
status: "ready",
|
|
916
|
-
evidence: "prompt-commands.test.ts passed as part of focused Goal coverage.",
|
|
917
|
-
});
|
|
918
|
-
expect(run ? decideGoalNextAction(run) : null).toMatchObject({
|
|
919
|
-
kind: "create_task",
|
|
920
|
-
title: "Audit Goal completion evidence",
|
|
921
|
-
reason: "Verifier passed; creating final read-only completion audit before the Goal can pass (1/3).",
|
|
922
|
-
});
|
|
923
|
-
});
|
|
924
|
-
it("persists evidence-plan evidence and path aliases used by coordinator calls", async () => {
|
|
925
|
-
await executeGoals({
|
|
926
|
-
action: "create",
|
|
927
|
-
run_id: "goal-evidence-aliases",
|
|
928
|
-
title: "Alias reconciliation",
|
|
929
|
-
goal: "Persist coordinator evidence-plan aliases",
|
|
930
|
-
success_criteria: ["Evidence plan is durable"],
|
|
931
|
-
prerequisites: [],
|
|
932
|
-
evidence_plan: [
|
|
933
|
-
{
|
|
934
|
-
id: "setup-plan",
|
|
935
|
-
label: "GOAL_PLAN setup evidence",
|
|
936
|
-
mechanism: "log",
|
|
937
|
-
description: "Planner output must be durable.",
|
|
938
|
-
status: "planned",
|
|
939
|
-
},
|
|
940
|
-
],
|
|
941
|
-
verifier_command: "pnpm test",
|
|
942
|
-
});
|
|
943
|
-
await executeGoals({
|
|
944
|
-
action: "evidence_plan",
|
|
945
|
-
run_id: "goal-evidence-aliases",
|
|
946
|
-
evidence_plan_item_id: "setup-plan",
|
|
947
|
-
evidence_plan_status: "ready",
|
|
948
|
-
evidence: "Exact GOAL_PLAN evidence was recorded.",
|
|
949
|
-
path: "artifacts/goal-plan.log",
|
|
950
|
-
});
|
|
951
|
-
const run = await getGoalRun(tmpProject, "goal-evidence-aliases");
|
|
952
|
-
expect(run?.evidencePlan[0]).toMatchObject({
|
|
953
|
-
status: "ready",
|
|
954
|
-
evidence: "Exact GOAL_PLAN evidence was recorded.",
|
|
955
|
-
path: "artifacts/goal-plan.log",
|
|
956
|
-
});
|
|
957
|
-
});
|
|
958
|
-
it("does not complete without passing verifier evidence", async () => {
|
|
959
|
-
await executeGoals({
|
|
960
|
-
action: "create",
|
|
961
|
-
run_id: "goal-a",
|
|
962
|
-
title: "Guard completion",
|
|
963
|
-
goal: "Only complete after proof",
|
|
964
|
-
success_criteria: ["Verifier passes"],
|
|
965
|
-
prerequisites: [],
|
|
966
|
-
verifier_command: "pnpm test",
|
|
967
|
-
evidence_plan: [
|
|
968
|
-
{
|
|
969
|
-
id: "verifier-proof",
|
|
970
|
-
label: "Verifier proof",
|
|
971
|
-
mechanism: "command",
|
|
972
|
-
description: "Run verifier command",
|
|
973
|
-
status: "ready",
|
|
974
|
-
command: "pnpm test",
|
|
975
|
-
evidence: "configured",
|
|
976
|
-
},
|
|
977
|
-
],
|
|
978
|
-
});
|
|
979
|
-
const result = await executeGoals({ action: "complete", run_id: "goal-a" });
|
|
980
|
-
const run = await getGoalRun(tmpProject, "goal-a");
|
|
981
|
-
expect(result).toBe("Error: cannot complete goal: Goal has no verifier evidence.");
|
|
982
|
-
expect(run?.status).toBe("ready");
|
|
983
|
-
});
|
|
984
|
-
it("records verifier pass as ready when tasks remain incomplete", async () => {
|
|
985
|
-
await executeGoals({
|
|
986
|
-
action: "create",
|
|
987
|
-
run_id: "goal-a",
|
|
988
|
-
title: "Guard verifier",
|
|
989
|
-
goal: "Verifier pass alone is not enough",
|
|
990
|
-
success_criteria: ["Task and verifier pass"],
|
|
991
|
-
prerequisites: [],
|
|
992
|
-
verifier_command: "pnpm test",
|
|
993
|
-
});
|
|
994
|
-
await executeGoals({
|
|
995
|
-
action: "task",
|
|
996
|
-
run_id: "goal-a",
|
|
997
|
-
task_id: "task-a",
|
|
998
|
-
task_title: "Pending work",
|
|
999
|
-
task_prompt: "Do the work",
|
|
1000
|
-
});
|
|
1001
|
-
await executeGoals({
|
|
1002
|
-
action: "verify",
|
|
1003
|
-
run_id: "goal-a",
|
|
1004
|
-
verification_status: "pass",
|
|
1005
|
-
summary: "Verifier passed",
|
|
1006
|
-
exit_code: 0,
|
|
1007
|
-
});
|
|
1008
|
-
const run = await getGoalRun(tmpProject, "goal-a");
|
|
1009
|
-
expect(run?.status).toBe("ready");
|
|
1010
|
-
expect(run?.verifier?.lastResult?.status).toBe("pass");
|
|
1011
|
-
});
|
|
1012
|
-
it("clears stale transient blockers but waits for final audit when verifier pass satisfies planned evidence", async () => {
|
|
1013
|
-
await executeGoals({
|
|
1014
|
-
action: "create",
|
|
1015
|
-
run_id: "goal-blocked-after-pass",
|
|
1016
|
-
title: "Blocked after pass",
|
|
1017
|
-
goal: "Recover from stale verifier interruption",
|
|
1018
|
-
success_criteria: ["Verifier pass with durable evidence completes"],
|
|
1019
|
-
prerequisites: [],
|
|
1020
|
-
evidence_plan: [
|
|
1021
|
-
{
|
|
1022
|
-
id: "planned-command-proof",
|
|
1023
|
-
label: "Targeted regression tests",
|
|
1024
|
-
mechanism: "test",
|
|
1025
|
-
description: "Run the focused local regression command.",
|
|
1026
|
-
status: "planned",
|
|
1027
|
-
command: "pnpm vitest run src/core/goal-controller.test.ts",
|
|
1028
|
-
},
|
|
1029
|
-
{
|
|
1030
|
-
id: "planned-log-proof",
|
|
1031
|
-
label: "Verifier log artifact",
|
|
1032
|
-
mechanism: "log",
|
|
1033
|
-
description: "Persist the verifier output log.",
|
|
1034
|
-
status: "planned",
|
|
1035
|
-
path: ".goal-evidence/blocked-after-pass.log",
|
|
1036
|
-
},
|
|
1037
|
-
],
|
|
1038
|
-
verifier_command: "pnpm vitest run src/core/goal-controller.test.ts",
|
|
1039
|
-
});
|
|
1040
|
-
await executeGoals({
|
|
1041
|
-
action: "task",
|
|
1042
|
-
run_id: "goal-blocked-after-pass",
|
|
1043
|
-
task_id: "task-a",
|
|
1044
|
-
task_title: "Done work",
|
|
1045
|
-
task_prompt: "Do the work",
|
|
1046
|
-
task_status: "done",
|
|
1047
|
-
});
|
|
1048
|
-
await upsertGoalRun(tmpProject, {
|
|
1049
|
-
id: "goal-blocked-after-pass",
|
|
1050
|
-
title: "Blocked after pass",
|
|
1051
|
-
goal: "Recover from stale verifier interruption",
|
|
1052
|
-
status: "blocked",
|
|
1053
|
-
blockers: ["Verifier was interrupted; rerun or continue the Goal to verify again."],
|
|
1054
|
-
});
|
|
1055
|
-
await executeGoals({
|
|
1056
|
-
action: "evidence",
|
|
1057
|
-
run_id: "goal-blocked-after-pass",
|
|
1058
|
-
evidence_kind: "log",
|
|
1059
|
-
evidence_label: "Verifier log artifact",
|
|
1060
|
-
evidence_path: ".goal-evidence/blocked-after-pass.log",
|
|
1061
|
-
evidence_content: "Verifier passed after interruption.",
|
|
1062
|
-
});
|
|
1063
|
-
const result = await executeGoals({
|
|
1064
|
-
action: "verify",
|
|
1065
|
-
run_id: "goal-blocked-after-pass",
|
|
1066
|
-
verification_status: "pass",
|
|
1067
|
-
summary: "Targeted regression tests passed and wrote Verifier log artifact.",
|
|
1068
|
-
verifier_command: "pnpm vitest run src/core/goal-controller.test.ts",
|
|
1069
|
-
exit_code: 0,
|
|
1070
|
-
output_path: ".goal-evidence/blocked-after-pass.log",
|
|
1071
|
-
});
|
|
1072
|
-
const run = await getGoalRun(tmpProject, "goal-blocked-after-pass");
|
|
1073
|
-
expect(result).toBe('Verifier recorded for "Blocked after pass": pass.');
|
|
1074
|
-
expect(run?.status).toBe("ready");
|
|
1075
|
-
expect(run?.blockers).toEqual([]);
|
|
1076
|
-
expect(run?.evidencePlan.map((item) => item.status)).toEqual(["planned", "planned"]);
|
|
1077
|
-
expect(run?.completionAudit).toMatchObject({ status: "unknown" });
|
|
1078
|
-
expect(run ? decideGoalNextAction(run) : null).toMatchObject({
|
|
1079
|
-
kind: "create_task",
|
|
1080
|
-
title: "Audit Goal completion evidence",
|
|
1081
|
-
});
|
|
1082
|
-
});
|
|
1083
|
-
it("records verifier failure as persisted command evidence and keeps the run recoverable", async () => {
|
|
1084
|
-
await executeGoals({
|
|
1085
|
-
action: "create",
|
|
1086
|
-
run_id: "goal-a",
|
|
1087
|
-
title: "Verifier fails",
|
|
1088
|
-
goal: "Persist failure evidence",
|
|
1089
|
-
success_criteria: ["Verifier passes"],
|
|
1090
|
-
prerequisites: [],
|
|
1091
|
-
verifier_command: "pnpm test",
|
|
1092
|
-
});
|
|
1093
|
-
await executeGoals({
|
|
1094
|
-
action: "task",
|
|
1095
|
-
run_id: "goal-a",
|
|
1096
|
-
task_id: "task-a",
|
|
1097
|
-
task_title: "Done work",
|
|
1098
|
-
task_prompt: "Do the work",
|
|
1099
|
-
task_status: "done",
|
|
1100
|
-
});
|
|
1101
|
-
const result = await executeGoals({
|
|
1102
|
-
action: "verify",
|
|
1103
|
-
run_id: "goal-a",
|
|
1104
|
-
verification_status: "fail",
|
|
1105
|
-
summary: "expected failure output",
|
|
1106
|
-
exit_code: 1,
|
|
1107
|
-
output_path: "artifacts/verifier.log",
|
|
1108
|
-
});
|
|
1109
|
-
const run = await getGoalRun(tmpProject, "goal-a");
|
|
1110
|
-
expect(result).toBe('Verifier recorded for "Verifier fails": fail.');
|
|
1111
|
-
expect(run?.status).toBe("ready");
|
|
1112
|
-
expect(run?.verifier?.lastResult).toMatchObject({
|
|
1113
|
-
status: "fail",
|
|
1114
|
-
summary: "expected failure output",
|
|
1115
|
-
exitCode: 1,
|
|
1116
|
-
outputPath: "artifacts/verifier.log",
|
|
1117
|
-
});
|
|
1118
|
-
expect(run?.evidence).toEqual(expect.arrayContaining([
|
|
1119
|
-
expect.objectContaining({
|
|
1120
|
-
kind: "command",
|
|
1121
|
-
label: "Verifier result",
|
|
1122
|
-
content: "expected failure output",
|
|
1123
|
-
path: "artifacts/verifier.log",
|
|
1124
|
-
}),
|
|
1125
|
-
]));
|
|
1126
|
-
});
|
|
1127
|
-
it("allows corrective next task to be added after verifier failure evidence", async () => {
|
|
1128
|
-
await executeGoals({
|
|
1129
|
-
action: "create",
|
|
1130
|
-
run_id: "goal-a",
|
|
1131
|
-
title: "Correct verifier failure",
|
|
1132
|
-
goal: "Create corrective task",
|
|
1133
|
-
success_criteria: ["Verifier passes"],
|
|
1134
|
-
prerequisites: [],
|
|
1135
|
-
verifier_command: "pnpm test",
|
|
1136
|
-
});
|
|
1137
|
-
await executeGoals({
|
|
1138
|
-
action: "verify",
|
|
1139
|
-
run_id: "goal-a",
|
|
1140
|
-
verification_status: "fail",
|
|
1141
|
-
summary: "failing assertion",
|
|
1142
|
-
exit_code: 1,
|
|
1143
|
-
});
|
|
1144
|
-
const result = await executeGoals({
|
|
1145
|
-
action: "task",
|
|
1146
|
-
run_id: "goal-a",
|
|
1147
|
-
task_id: "repair-a",
|
|
1148
|
-
task_title: "Repair verifier failure",
|
|
1149
|
-
task_prompt: "Use Verifier result evidence to fix failing assertion",
|
|
1150
|
-
task_status: "pending",
|
|
1151
|
-
});
|
|
1152
|
-
const run = await getGoalRun(tmpProject, "goal-a");
|
|
1153
|
-
expect(result).toBe('Goal task added: "Repair verifier failure" (id: repair-a). Reference this id (or the exact title) in another task\'s depends_on.');
|
|
1154
|
-
expect(run?.status).toBe("ready");
|
|
1155
|
-
expect(run?.tasks).toEqual(expect.arrayContaining([
|
|
1156
|
-
expect.objectContaining({
|
|
1157
|
-
id: "repair-a",
|
|
1158
|
-
status: "pending",
|
|
1159
|
-
prompt: "Use Verifier result evidence to fix failing assertion",
|
|
1160
|
-
}),
|
|
1161
|
-
]));
|
|
1162
|
-
expect(run ? decideGoalNextAction(run) : null).toMatchObject({
|
|
1163
|
-
kind: "start_worker",
|
|
1164
|
-
task: expect.objectContaining({ id: "repair-a" }),
|
|
1165
|
-
});
|
|
1166
|
-
});
|
|
1167
|
-
it("records pause evidence after repeated non-progress", async () => {
|
|
1168
|
-
await executeGoals({
|
|
1169
|
-
action: "create",
|
|
1170
|
-
run_id: "goal-a",
|
|
1171
|
-
title: "Pause loop",
|
|
1172
|
-
goal: "Stop repeated non-progress",
|
|
1173
|
-
success_criteria: ["No infinite loop"],
|
|
1174
|
-
prerequisites: [],
|
|
1175
|
-
});
|
|
1176
|
-
await executeGoals({
|
|
1177
|
-
action: "task",
|
|
1178
|
-
run_id: "goal-a",
|
|
1179
|
-
task_id: "task-a",
|
|
1180
|
-
task_title: "Flaky work",
|
|
1181
|
-
task_prompt: "Try again",
|
|
1182
|
-
task_status: "failed",
|
|
1183
|
-
attempts: 6,
|
|
1184
|
-
summary: "same failure repeated",
|
|
1185
|
-
});
|
|
1186
|
-
await executeGoals({
|
|
1187
|
-
action: "evidence",
|
|
1188
|
-
run_id: "goal-a",
|
|
1189
|
-
evidence_kind: "summary",
|
|
1190
|
-
evidence_label: "Paused after repeated non-progress",
|
|
1191
|
-
evidence_content: "Attempt limit reached for Flaky work.",
|
|
1192
|
-
});
|
|
1193
|
-
const result = await executeGoals({ action: "pause", run_id: "goal-a" });
|
|
1194
|
-
const run = await getGoalRun(tmpProject, "goal-a");
|
|
1195
|
-
expect(result).toBe('Goal "Pause loop" is now paused.');
|
|
1196
|
-
expect(run?.status).toBe("paused");
|
|
1197
|
-
expect(run?.evidence).toEqual(expect.arrayContaining([
|
|
1198
|
-
expect.objectContaining({
|
|
1199
|
-
kind: "summary",
|
|
1200
|
-
label: "Paused after repeated non-progress",
|
|
1201
|
-
content: "Attempt limit reached for Flaky work.",
|
|
1202
|
-
}),
|
|
1203
|
-
]));
|
|
1204
|
-
});
|
|
1205
|
-
it("resume-immediate records continuation intent and next action", async () => {
|
|
1206
|
-
await executeGoals({
|
|
1207
|
-
action: "create",
|
|
1208
|
-
run_id: "goal-resume",
|
|
1209
|
-
title: "Resume now",
|
|
1210
|
-
goal: "Continue",
|
|
1211
|
-
prerequisites: [],
|
|
1212
|
-
});
|
|
1213
|
-
await executeGoals({
|
|
1214
|
-
action: "task",
|
|
1215
|
-
run_id: "goal-resume",
|
|
1216
|
-
task_id: "task-a",
|
|
1217
|
-
task_title: "Work",
|
|
1218
|
-
task_prompt: "Do it",
|
|
1219
|
-
});
|
|
1220
|
-
const result = await executeGoals({ action: "resume", run_id: "goal-resume" });
|
|
1221
|
-
const run = await getGoalRun(tmpProject, "goal-resume");
|
|
1222
|
-
expect(result).toBe('Goal "Resume now" resume requested; next action: start_worker.');
|
|
1223
|
-
expect(run?.status).toBe("ready");
|
|
1224
|
-
expect(run?.continueRequestedAt).toBeTruthy();
|
|
1225
|
-
expect(run?.evidence).toEqual(expect.arrayContaining([
|
|
1226
|
-
expect.objectContaining({ label: "Goal resume requested" }),
|
|
1227
|
-
expect.objectContaining({ label: "Goal decision: resume" }),
|
|
1228
|
-
]));
|
|
1229
|
-
});
|
|
1230
|
-
it("resume-queued-behind-active-worker persists continuation intent", async () => {
|
|
1231
|
-
await executeGoals({
|
|
1232
|
-
action: "create",
|
|
1233
|
-
run_id: "goal-queued",
|
|
1234
|
-
title: "Queued resume",
|
|
1235
|
-
goal: "Continue later",
|
|
1236
|
-
prerequisites: [],
|
|
1237
|
-
});
|
|
1238
|
-
await executeGoals({
|
|
1239
|
-
action: "task",
|
|
1240
|
-
run_id: "goal-queued",
|
|
1241
|
-
task_id: "task-a",
|
|
1242
|
-
task_title: "Work",
|
|
1243
|
-
task_prompt: "Do it",
|
|
1244
|
-
task_status: "running",
|
|
1245
|
-
worker_id: "worker-a",
|
|
1246
|
-
});
|
|
1247
|
-
const result = await executeGoals({ action: "resume", run_id: "goal-queued" });
|
|
1248
|
-
const run = await getGoalRun(tmpProject, "goal-queued");
|
|
1249
|
-
expect(result).toBe('Goal "Queued resume" resume queued: Goal task "Work" is already running.');
|
|
1250
|
-
expect(run?.continueRequestedAt).toBeTruthy();
|
|
1251
|
-
expect(run?.evidence).toEqual(expect.arrayContaining([
|
|
1252
|
-
expect.objectContaining({ label: "Goal resume requested" }),
|
|
1253
|
-
expect.objectContaining({ label: "Goal decision: resume" }),
|
|
1254
|
-
]));
|
|
1255
|
-
});
|
|
1256
|
-
it("resume-blocked-prerequisite keeps exact missing instructions", async () => {
|
|
1257
|
-
await executeGoals({
|
|
1258
|
-
action: "create",
|
|
1259
|
-
run_id: "goal-blocked",
|
|
1260
|
-
title: "Blocked resume",
|
|
1261
|
-
goal: "Needs input",
|
|
1262
|
-
prerequisites: [
|
|
1263
|
-
{ id: "key", label: "API key", status: "missing", instructions: "Set API_KEY locally." },
|
|
1264
|
-
],
|
|
1265
|
-
});
|
|
1266
|
-
const result = await executeGoals({ action: "resume", run_id: "goal-blocked" });
|
|
1267
|
-
const run = await getGoalRun(tmpProject, "goal-blocked");
|
|
1268
|
-
expect(result).toBe('Goal "Blocked resume" resume blocked: API key: Set API_KEY locally.');
|
|
1269
|
-
expect(run?.status).toBe("blocked");
|
|
1270
|
-
expect(run?.blockers).toContain("API key: Set API_KEY locally.");
|
|
1271
|
-
expect(run?.evidence).toEqual(expect.arrayContaining([
|
|
1272
|
-
expect.objectContaining({
|
|
1273
|
-
label: "Goal resume blocked",
|
|
1274
|
-
content: "API key: Set API_KEY locally.",
|
|
1275
|
-
}),
|
|
1276
|
-
]));
|
|
1277
|
-
});
|
|
1278
|
-
it("keeps a Goal ready when final audit creates a follow-up worker task", async () => {
|
|
1279
|
-
await executeGoals({
|
|
1280
|
-
action: "create",
|
|
1281
|
-
run_id: "goal-audit-missing",
|
|
1282
|
-
title: "Audit missing report",
|
|
1283
|
-
goal: "Ensure report matches verifier result",
|
|
1284
|
-
success_criteria: ["Report reflects latest verifier pass"],
|
|
1285
|
-
prerequisites: [],
|
|
1286
|
-
verifier_command: "pnpm test",
|
|
1287
|
-
});
|
|
1288
|
-
await executeGoals({
|
|
1289
|
-
action: "task",
|
|
1290
|
-
run_id: "goal-audit-missing",
|
|
1291
|
-
task_id: "report-task",
|
|
1292
|
-
task_title: "Write report",
|
|
1293
|
-
task_prompt: "Write the report",
|
|
1294
|
-
task_status: "done",
|
|
1295
|
-
attempts: 1,
|
|
1296
|
-
});
|
|
1297
|
-
await executeGoals({
|
|
1298
|
-
action: "verify",
|
|
1299
|
-
run_id: "goal-audit-missing",
|
|
1300
|
-
verification_status: "pass",
|
|
1301
|
-
summary: "Verifier passed",
|
|
1302
|
-
exit_code: 0,
|
|
1303
|
-
output_path: "artifacts/verifier.log",
|
|
1304
|
-
});
|
|
1305
|
-
await executeGoals({
|
|
1306
|
-
action: "task",
|
|
1307
|
-
run_id: "goal-audit-missing",
|
|
1308
|
-
task_id: "fix-report",
|
|
1309
|
-
task_title: "Fix stale final report",
|
|
1310
|
-
task_prompt: "Update the report to reflect the latest verifier pass.",
|
|
1311
|
-
task_status: "pending",
|
|
1312
|
-
summary: "Final audit found stale report content.",
|
|
1313
|
-
});
|
|
1314
|
-
await executeGoals({
|
|
1315
|
-
action: "audit",
|
|
1316
|
-
run_id: "goal-audit-missing",
|
|
1317
|
-
verification_status: "fail",
|
|
1318
|
-
summary: "FINAL_AUDIT_FAIL report still describes an earlier verifier failure.",
|
|
1319
|
-
output_path: "artifacts/verifier.log",
|
|
1320
|
-
});
|
|
1321
|
-
const run = await getGoalRun(tmpProject, "goal-audit-missing");
|
|
1322
|
-
expect(run?.status).toBe("ready");
|
|
1323
|
-
expect(run?.completionAudit).toMatchObject({ status: "fail" });
|
|
1324
|
-
expect(run?.tasks).toEqual(expect.arrayContaining([expect.objectContaining({ id: "fix-report", status: "pending" })]));
|
|
1325
|
-
expect(run ? decideGoalNextAction(run) : null).toMatchObject({
|
|
1326
|
-
kind: "start_worker",
|
|
1327
|
-
task: expect.objectContaining({ id: "fix-report" }),
|
|
1328
|
-
});
|
|
1329
|
-
});
|
|
1330
|
-
it("allows completion after all tasks are done, verifier passes, and final audit passes", async () => {
|
|
1331
|
-
await executeGoals({
|
|
1332
|
-
action: "create",
|
|
1333
|
-
run_id: "goal-a",
|
|
1334
|
-
title: "Complete safely",
|
|
1335
|
-
goal: "Complete after proof",
|
|
1336
|
-
success_criteria: ["Task and verifier pass"],
|
|
1337
|
-
prerequisites: [],
|
|
1338
|
-
verifier_command: "pnpm test",
|
|
1339
|
-
evidence_plan: [
|
|
1340
|
-
{
|
|
1341
|
-
id: "verifier-proof",
|
|
1342
|
-
label: "Verifier proof",
|
|
1343
|
-
mechanism: "command",
|
|
1344
|
-
description: "Run verifier command",
|
|
1345
|
-
status: "ready",
|
|
1346
|
-
command: "pnpm test",
|
|
1347
|
-
evidence: "configured",
|
|
1348
|
-
},
|
|
1349
|
-
],
|
|
1350
|
-
});
|
|
1351
|
-
await executeGoals({
|
|
1352
|
-
action: "task",
|
|
1353
|
-
run_id: "goal-a",
|
|
1354
|
-
task_id: "task-a",
|
|
1355
|
-
task_title: "Done work",
|
|
1356
|
-
task_prompt: "Do the work",
|
|
1357
|
-
task_status: "done",
|
|
1358
|
-
});
|
|
1359
|
-
await executeGoals({
|
|
1360
|
-
action: "verify",
|
|
1361
|
-
run_id: "goal-a",
|
|
1362
|
-
verification_status: "pass",
|
|
1363
|
-
summary: "Verifier passed",
|
|
1364
|
-
exit_code: 0,
|
|
1365
|
-
output_path: "artifacts/verifier.log",
|
|
1366
|
-
});
|
|
1367
|
-
const beforeAudit = await executeGoals({ action: "complete", run_id: "goal-a" });
|
|
1368
|
-
expect(beforeAudit).toBe("Error: cannot complete goal: Final completion audit status is unknown.");
|
|
1369
|
-
await executeGoals({
|
|
1370
|
-
action: "task",
|
|
1371
|
-
run_id: "goal-a",
|
|
1372
|
-
task_id: "final-audit",
|
|
1373
|
-
task_title: "Audit Goal completion evidence",
|
|
1374
|
-
task_prompt: "Audit final durable artifacts.",
|
|
1375
|
-
task_status: "done",
|
|
1376
|
-
attempts: 1,
|
|
1377
|
-
});
|
|
1378
|
-
const auditResult = await executeGoals({
|
|
1379
|
-
action: "audit",
|
|
1380
|
-
run_id: "goal-a",
|
|
1381
|
-
verification_status: "pass",
|
|
1382
|
-
summary: `FINAL_AUDIT_PASS verifier_checked_at=${(await getGoalRun(tmpProject, "goal-a"))?.verifier?.lastResult?.checkedAt}; artifacts match verifier output.`,
|
|
1383
|
-
output_path: "artifacts/verifier.log",
|
|
1384
|
-
});
|
|
1385
|
-
const result = await executeGoals({ action: "complete", run_id: "goal-a" });
|
|
1386
|
-
const run = await getGoalRun(tmpProject, "goal-a");
|
|
1387
|
-
expect(auditResult).toBe('Completion audit recorded for "Complete safely": pass.');
|
|
1388
|
-
expect(result).toBe('Goal "Complete safely" is now passed.');
|
|
1389
|
-
expect(run?.status).toBe("passed");
|
|
1390
|
-
expect(run?.completionAudit).toMatchObject({ status: "pass" });
|
|
1391
|
-
});
|
|
1392
|
-
it("auto-stamps FINAL_AUDIT_PASS and verifier_checked_at so a plain prose pass audit succeeds", async () => {
|
|
1393
|
-
await executeGoals({
|
|
1394
|
-
action: "create",
|
|
1395
|
-
run_id: "autostamp-goal",
|
|
1396
|
-
title: "Auto stamp",
|
|
1397
|
-
goal: "Pass audits should not require transcribing structured tokens",
|
|
1398
|
-
success_criteria: ["audit passes from plain prose"],
|
|
1399
|
-
evidence_plan: [
|
|
1400
|
-
{
|
|
1401
|
-
id: "proof",
|
|
1402
|
-
label: "Proof",
|
|
1403
|
-
mechanism: "command",
|
|
1404
|
-
description: "Verifier log",
|
|
1405
|
-
status: "ready",
|
|
1406
|
-
path: "artifacts/verifier.log",
|
|
1407
|
-
evidence: "recorded",
|
|
1408
|
-
},
|
|
1409
|
-
],
|
|
1410
|
-
verifier_command: "true",
|
|
1411
|
-
});
|
|
1412
|
-
await executeGoals({
|
|
1413
|
-
action: "task",
|
|
1414
|
-
run_id: "autostamp-goal",
|
|
1415
|
-
task_id: "task-a",
|
|
1416
|
-
task_title: "Done",
|
|
1417
|
-
task_prompt: "Do work",
|
|
1418
|
-
task_status: "done",
|
|
1419
|
-
});
|
|
1420
|
-
await executeGoals({
|
|
1421
|
-
action: "verify",
|
|
1422
|
-
run_id: "autostamp-goal",
|
|
1423
|
-
verification_status: "pass",
|
|
1424
|
-
summary: "Verifier passed",
|
|
1425
|
-
exit_code: 0,
|
|
1426
|
-
output_path: "artifacts/verifier.log",
|
|
1427
|
-
});
|
|
1428
|
-
// Plain prose summary: no FINAL_AUDIT_PASS prefix, no transcribed timestamp.
|
|
1429
|
-
const auditResult = await executeGoals({
|
|
1430
|
-
action: "audit",
|
|
1431
|
-
run_id: "autostamp-goal",
|
|
1432
|
-
verification_status: "pass",
|
|
1433
|
-
summary: "Compared the verifier log against the success criteria; everything matches.",
|
|
1434
|
-
});
|
|
1435
|
-
expect(auditResult).toBe('Completion audit recorded for "Auto stamp": pass.');
|
|
1436
|
-
const run = await getGoalRun(tmpProject, "autostamp-goal");
|
|
1437
|
-
const checkedAt = run?.verifier?.lastResult?.checkedAt;
|
|
1438
|
-
expect(run?.completionAudit?.status).toBe("pass");
|
|
1439
|
-
expect(run?.completionAudit?.summary).toMatch(/^FINAL_AUDIT_PASS/);
|
|
1440
|
-
expect(run?.completionAudit?.summary).toContain(`verifier_checked_at=${checkedAt}`);
|
|
1441
|
-
expect(run?.completionAudit?.outputPath).toBe("artifacts/verifier.log");
|
|
1442
|
-
});
|
|
1443
|
-
});
|
|
1444
|
-
//# sourceMappingURL=goals.test.js.map
|