@kenkaiiii/ggcoder 4.3.211 → 4.3.213
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 +5 -8
- package/dist/cli.d.ts +3 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -61
- package/dist/cli.js.map +1 -1
- package/dist/core/continue-replay-inventory.test.d.ts +2 -0
- package/dist/core/continue-replay-inventory.test.d.ts.map +1 -0
- package/dist/core/continue-replay-inventory.test.js +42 -0
- package/dist/core/continue-replay-inventory.test.js.map +1 -0
- package/dist/core/goal-controller.d.ts +2 -0
- package/dist/core/goal-controller.d.ts.map +1 -1
- package/dist/core/goal-controller.js +283 -24
- package/dist/core/goal-controller.js.map +1 -1
- package/dist/core/goal-controller.test.js +413 -16
- package/dist/core/goal-controller.test.js.map +1 -1
- package/dist/core/goal-lifecycle-smoke.test.js +48 -6
- package/dist/core/goal-lifecycle-smoke.test.js.map +1 -1
- package/dist/core/goal-prerequisites.d.ts +23 -0
- package/dist/core/goal-prerequisites.d.ts.map +1 -0
- package/dist/core/goal-prerequisites.js +114 -0
- package/dist/core/goal-prerequisites.js.map +1 -0
- package/dist/core/goal-prerequisites.test.d.ts +2 -0
- package/dist/core/goal-prerequisites.test.d.ts.map +1 -0
- package/dist/core/goal-prerequisites.test.js +118 -0
- package/dist/core/goal-prerequisites.test.js.map +1 -0
- package/dist/core/goal-references.d.ts +14 -0
- package/dist/core/goal-references.d.ts.map +1 -0
- package/dist/core/goal-references.js +153 -0
- package/dist/core/goal-references.js.map +1 -0
- package/dist/core/goal-references.test.d.ts +2 -0
- package/dist/core/goal-references.test.d.ts.map +1 -0
- package/dist/core/goal-references.test.js +77 -0
- package/dist/core/goal-references.test.js.map +1 -0
- package/dist/core/goal-store.d.ts +25 -0
- package/dist/core/goal-store.d.ts.map +1 -1
- package/dist/core/goal-store.js +161 -38
- package/dist/core/goal-store.js.map +1 -1
- package/dist/core/goal-store.test.js +33 -8
- package/dist/core/goal-store.test.js.map +1 -1
- package/dist/core/goal-verifier.d.ts.map +1 -1
- package/dist/core/goal-verifier.js +4 -1
- package/dist/core/goal-verifier.js.map +1 -1
- package/dist/core/goal-verifier.test.js +43 -0
- package/dist/core/goal-verifier.test.js.map +1 -1
- package/dist/core/goal-worker.d.ts +2 -0
- package/dist/core/goal-worker.d.ts.map +1 -1
- package/dist/core/goal-worker.js +33 -9
- package/dist/core/goal-worker.js.map +1 -1
- package/dist/core/goal-worker.test.js +49 -1
- package/dist/core/goal-worker.test.js.map +1 -1
- package/dist/core/prompt-commands.d.ts.map +1 -1
- package/dist/core/prompt-commands.js +28 -845
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/prompt-commands.test.js +40 -74
- package/dist/core/prompt-commands.test.js.map +1 -1
- package/dist/core/runtime-mode.d.ts +14 -0
- package/dist/core/runtime-mode.d.ts.map +1 -0
- package/dist/core/runtime-mode.js +10 -0
- package/dist/core/runtime-mode.js.map +1 -0
- package/dist/core/session-restore-display.test.d.ts +2 -0
- package/dist/core/session-restore-display.test.d.ts.map +1 -0
- package/dist/core/session-restore-display.test.js +100 -0
- package/dist/core/session-restore-display.test.js.map +1 -0
- package/dist/core/verify-commands.js +4 -4
- package/dist/core/verify-commands.js.map +1 -1
- package/dist/system-prompt.d.ts +2 -1
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +51 -37
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +147 -40
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/bash.d.ts +3 -2
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +11 -4
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts +5 -3
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +14 -4
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/edit.test.js +0 -10
- package/dist/tools/edit.test.js.map +1 -1
- package/dist/tools/goal-mode.test.d.ts +2 -0
- package/dist/tools/goal-mode.test.d.ts.map +1 -0
- package/dist/tools/goal-mode.test.js +121 -0
- package/dist/tools/goal-mode.test.js.map +1 -0
- package/dist/tools/goals.d.ts +15 -3
- package/dist/tools/goals.d.ts.map +1 -1
- package/dist/tools/goals.js +385 -35
- package/dist/tools/goals.js.map +1 -1
- package/dist/tools/goals.test.js +389 -6
- package/dist/tools/goals.test.js.map +1 -1
- package/dist/tools/index.d.ts +7 -10
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -19
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan-mode.test.js +34 -224
- package/dist/tools/plan-mode.test.js.map +1 -1
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +2 -6
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/subagent.d.ts +3 -2
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +4 -9
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/write.d.ts +5 -3
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +14 -13
- package/dist/tools/write.js.map +1 -1
- package/dist/tools/write.test.js +0 -16
- package/dist/tools/write.test.js.map +1 -1
- package/dist/ui/App.d.ts +146 -30
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +1202 -910
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/activity-phrases.d.ts.map +1 -1
- package/dist/ui/activity-phrases.js +0 -2
- package/dist/ui/activity-phrases.js.map +1 -1
- package/dist/ui/app-state-persistence.test.js +181 -13
- package/dist/ui/app-state-persistence.test.js.map +1 -1
- package/dist/ui/chat-layout-pinning.test.d.ts +2 -0
- package/dist/ui/chat-layout-pinning.test.d.ts.map +1 -0
- package/dist/ui/chat-layout-pinning.test.js +407 -0
- package/dist/ui/chat-layout-pinning.test.js.map +1 -0
- package/dist/ui/components/ActivityIndicator.d.ts +1 -2
- package/dist/ui/components/ActivityIndicator.d.ts.map +1 -1
- package/dist/ui/components/ActivityIndicator.js +63 -94
- package/dist/ui/components/ActivityIndicator.js.map +1 -1
- package/dist/ui/components/AssistantMessage.d.ts +6 -2
- package/dist/ui/components/AssistantMessage.d.ts.map +1 -1
- package/dist/ui/components/AssistantMessage.js +9 -4
- package/dist/ui/components/AssistantMessage.js.map +1 -1
- package/dist/ui/components/AssistantMessage.test.d.ts +2 -0
- package/dist/ui/components/AssistantMessage.test.d.ts.map +1 -0
- package/dist/ui/components/AssistantMessage.test.js +369 -0
- package/dist/ui/components/AssistantMessage.test.js.map +1 -0
- package/dist/ui/components/BackgroundTasksBar.d.ts +1 -3
- package/dist/ui/components/BackgroundTasksBar.d.ts.map +1 -1
- package/dist/ui/components/BackgroundTasksBar.js +2 -4
- package/dist/ui/components/BackgroundTasksBar.js.map +1 -1
- package/dist/ui/components/Banner.d.ts +1 -3
- package/dist/ui/components/Banner.d.ts.map +1 -1
- package/dist/ui/components/Banner.js +7 -3
- package/dist/ui/components/Banner.js.map +1 -1
- package/dist/ui/components/Footer.d.ts +26 -4
- package/dist/ui/components/Footer.d.ts.map +1 -1
- package/dist/ui/components/Footer.js +73 -21
- package/dist/ui/components/Footer.js.map +1 -1
- package/dist/ui/components/GoalOverlay.d.ts +28 -20
- package/dist/ui/components/GoalOverlay.d.ts.map +1 -1
- package/dist/ui/components/GoalOverlay.js +283 -253
- package/dist/ui/components/GoalOverlay.js.map +1 -1
- package/dist/ui/components/InputArea.d.ts +2 -6
- package/dist/ui/components/InputArea.d.ts.map +1 -1
- package/dist/ui/components/InputArea.js +40 -32
- package/dist/ui/components/InputArea.js.map +1 -1
- package/dist/ui/components/InputArea.test.js +11 -1
- package/dist/ui/components/InputArea.test.js.map +1 -1
- package/dist/ui/components/Markdown.d.ts +11 -11
- package/dist/ui/components/Markdown.d.ts.map +1 -1
- package/dist/ui/components/Markdown.js +25 -198
- package/dist/ui/components/Markdown.js.map +1 -1
- package/dist/ui/components/PlanOverlay.d.ts.map +1 -1
- package/dist/ui/components/PlanOverlay.js +1 -1
- package/dist/ui/components/PlanOverlay.js.map +1 -1
- package/dist/ui/components/ServerToolExecution.d.ts.map +1 -1
- package/dist/ui/components/ServerToolExecution.js +3 -2
- package/dist/ui/components/ServerToolExecution.js.map +1 -1
- package/dist/ui/components/SlashCommandMenu.d.ts +4 -3
- package/dist/ui/components/SlashCommandMenu.d.ts.map +1 -1
- package/dist/ui/components/SlashCommandMenu.js +38 -26
- package/dist/ui/components/SlashCommandMenu.js.map +1 -1
- package/dist/ui/components/StreamingArea.d.ts +11 -2
- package/dist/ui/components/StreamingArea.d.ts.map +1 -1
- package/dist/ui/components/StreamingArea.js +20 -23
- package/dist/ui/components/StreamingArea.js.map +1 -1
- package/dist/ui/components/StreamingArea.test.d.ts +2 -0
- package/dist/ui/components/StreamingArea.test.d.ts.map +1 -0
- package/dist/ui/components/StreamingArea.test.js +18 -0
- package/dist/ui/components/StreamingArea.test.js.map +1 -0
- package/dist/ui/components/ToolExecution.d.ts.map +1 -1
- package/dist/ui/components/ToolExecution.js +11 -27
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/components/ToolGroupExecution.d.ts.map +1 -1
- package/dist/ui/components/ToolGroupExecution.js +9 -124
- package/dist/ui/components/ToolGroupExecution.js.map +1 -1
- package/dist/ui/components/UserMessage.d.ts.map +1 -1
- package/dist/ui/components/UserMessage.js +15 -10
- package/dist/ui/components/UserMessage.js.map +1 -1
- package/dist/ui/components/UserMessage.test.d.ts +2 -0
- package/dist/ui/components/UserMessage.test.d.ts.map +1 -0
- package/dist/ui/components/UserMessage.test.js +39 -0
- package/dist/ui/components/UserMessage.test.js.map +1 -0
- package/dist/ui/footer-status-layout.test.js +21 -7
- package/dist/ui/footer-status-layout.test.js.map +1 -1
- package/dist/ui/goal-events.d.ts +8 -0
- package/dist/ui/goal-events.d.ts.map +1 -1
- package/dist/ui/goal-events.js +28 -8
- package/dist/ui/goal-events.js.map +1 -1
- package/dist/ui/goal-events.test.js +40 -2
- package/dist/ui/goal-events.test.js.map +1 -1
- package/dist/ui/goal-lifecycle-orchestration.test.js +127 -34
- package/dist/ui/goal-lifecycle-orchestration.test.js.map +1 -1
- package/dist/ui/goal-overlay.test.js +122 -44
- package/dist/ui/goal-overlay.test.js.map +1 -1
- package/dist/ui/goal-summary.d.ts +14 -0
- package/dist/ui/goal-summary.d.ts.map +1 -0
- package/dist/ui/goal-summary.js +194 -0
- package/dist/ui/goal-summary.js.map +1 -0
- package/dist/ui/hooks/useAgentLoop.d.ts +8 -2
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +20 -9
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/dist/ui/hooks/useAgentLoop.test.d.ts +2 -0
- package/dist/ui/hooks/useAgentLoop.test.d.ts.map +1 -0
- package/dist/ui/hooks/useAgentLoop.test.js +8 -0
- package/dist/ui/hooks/useAgentLoop.test.js.map +1 -0
- package/dist/ui/hooks/useTerminalSize.d.ts +5 -9
- package/dist/ui/hooks/useTerminalSize.d.ts.map +1 -1
- package/dist/ui/hooks/useTerminalSize.js +9 -14
- package/dist/ui/hooks/useTerminalSize.js.map +1 -1
- package/dist/ui/live-item-flush.d.ts +2 -2
- package/dist/ui/live-item-flush.d.ts.map +1 -1
- package/dist/ui/live-item-flush.js +8 -4
- package/dist/ui/live-item-flush.js.map +1 -1
- package/dist/ui/long-prompt-regression-harness.test.d.ts +2 -0
- package/dist/ui/long-prompt-regression-harness.test.d.ts.map +1 -0
- package/dist/ui/long-prompt-regression-harness.test.js +195 -0
- package/dist/ui/long-prompt-regression-harness.test.js.map +1 -0
- package/dist/ui/plan-overlay.test.js +7 -29
- package/dist/ui/plan-overlay.test.js.map +1 -1
- package/dist/ui/queued-message.test.d.ts.map +1 -1
- package/dist/ui/queued-message.test.js +76 -14
- package/dist/ui/queued-message.test.js.map +1 -1
- package/dist/ui/render.d.ts +21 -24
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +46 -28
- package/dist/ui/render.js.map +1 -1
- package/dist/ui/render.test.d.ts +2 -0
- package/dist/ui/render.test.d.ts.map +1 -0
- package/dist/ui/render.test.js +16 -0
- package/dist/ui/render.test.js.map +1 -0
- package/dist/ui/scroll-stabilization.test.js +1 -1
- package/dist/ui/scroll-stabilization.test.js.map +1 -1
- package/dist/ui/slash-command-images.test.js +79 -4
- package/dist/ui/slash-command-images.test.js.map +1 -1
- package/dist/ui/terminal-history.d.ts +26 -0
- package/dist/ui/terminal-history.d.ts.map +1 -0
- package/dist/ui/terminal-history.js +910 -0
- package/dist/ui/terminal-history.js.map +1 -0
- package/dist/ui/terminal-history.test.d.ts +2 -0
- package/dist/ui/terminal-history.test.d.ts.map +1 -0
- package/dist/ui/terminal-history.test.js +314 -0
- package/dist/ui/terminal-history.test.js.map +1 -0
- package/dist/ui/tool-group-summary.d.ts +16 -0
- package/dist/ui/tool-group-summary.d.ts.map +1 -0
- package/dist/ui/tool-group-summary.js +123 -0
- package/dist/ui/tool-group-summary.js.map +1 -0
- package/dist/ui/tui-history-parity.test.d.ts +2 -0
- package/dist/ui/tui-history-parity.test.d.ts.map +1 -0
- package/dist/ui/tui-history-parity.test.js +243 -0
- package/dist/ui/tui-history-parity.test.js.map +1 -0
- package/dist/ui/utils/assistant-stream-split.d.ts +6 -0
- package/dist/ui/utils/assistant-stream-split.d.ts.map +1 -0
- package/dist/ui/utils/assistant-stream-split.js +37 -0
- package/dist/ui/utils/assistant-stream-split.js.map +1 -0
- package/dist/ui/utils/assistant-stream-split.test.d.ts +2 -0
- package/dist/ui/utils/assistant-stream-split.test.d.ts.map +1 -0
- package/dist/ui/utils/assistant-stream-split.test.js +58 -0
- package/dist/ui/utils/assistant-stream-split.test.js.map +1 -0
- package/dist/ui/utils/latex-to-unicode.d.ts +22 -0
- package/dist/ui/utils/latex-to-unicode.d.ts.map +1 -0
- package/dist/ui/utils/latex-to-unicode.js +538 -0
- package/dist/ui/utils/latex-to-unicode.js.map +1 -0
- package/dist/ui/utils/markdown-renderer.d.ts +20 -0
- package/dist/ui/utils/markdown-renderer.d.ts.map +1 -0
- package/dist/ui/utils/markdown-renderer.js +327 -0
- package/dist/ui/utils/markdown-renderer.js.map +1 -0
- package/dist/ui/utils/markdown-table.d.ts +9 -0
- package/dist/ui/utils/markdown-table.d.ts.map +1 -0
- package/dist/ui/utils/markdown-table.js +95 -0
- package/dist/ui/utils/markdown-table.js.map +1 -0
- package/dist/ui/utils/text-utils.d.ts +8 -0
- package/dist/ui/utils/text-utils.d.ts.map +1 -0
- package/dist/ui/utils/text-utils.js +16 -0
- package/dist/ui/utils/text-utils.js.map +1 -0
- package/dist/ui/utils/token-to-ansi.js +19 -9
- package/dist/ui/utils/token-to-ansi.js.map +1 -1
- package/dist/ui/utils/user-message-display.d.ts +7 -0
- package/dist/ui/utils/user-message-display.d.ts.map +1 -0
- package/dist/ui/utils/user-message-display.js +26 -0
- package/dist/ui/utils/user-message-display.js.map +1 -0
- package/dist/utils/format.js +0 -9
- package/dist/utils/format.js.map +1 -1
- package/package.json +9 -5
- package/dist/tools/enter-plan.d.ts +0 -8
- package/dist/tools/enter-plan.d.ts.map +0 -1
- package/dist/tools/enter-plan.js +0 -30
- package/dist/tools/enter-plan.js.map +0 -1
- package/dist/tools/exit-plan.d.ts +0 -8
- package/dist/tools/exit-plan.d.ts.map +0 -1
- package/dist/tools/exit-plan.js +0 -36
- package/dist/tools/exit-plan.js.map +0 -1
- package/dist/tools/tasks.d.ts +0 -16
- package/dist/tools/tasks.d.ts.map +0 -1
- package/dist/tools/tasks.js +0 -133
- package/dist/tools/tasks.js.map +0 -1
- package/dist/ui/components/EyesOverlay.d.ts +0 -10
- package/dist/ui/components/EyesOverlay.d.ts.map +0 -1
- package/dist/ui/components/EyesOverlay.js +0 -220
- package/dist/ui/components/EyesOverlay.js.map +0 -1
- package/dist/ui/components/TaskOverlay.d.ts +0 -10
- package/dist/ui/components/TaskOverlay.d.ts.map +0 -1
- package/dist/ui/components/TaskOverlay.js +0 -267
- package/dist/ui/components/TaskOverlay.js.map +0 -1
package/dist/tools/goals.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { log } from "../core/logger.js";
|
|
4
|
-
import { canCompleteGoalRun, decideGoalNextAction } from "../core/goal-controller.js";
|
|
5
|
-
import {
|
|
4
|
+
import { canCompleteGoalRun, decideGoalNextAction, hasFreshGoalCompletionAudit, } from "../core/goal-controller.js";
|
|
5
|
+
import { runGoalPrerequisiteCheckCommand } from "../core/goal-prerequisites.js";
|
|
6
|
+
import { appendGoalBlockers, appendGoalDecision, appendGoalEvidence, createGoalEvidence, formatGoalBlockingPrerequisiteList, formatGoalBlockingPrerequisites, getActiveGoalRun, getGoalRun, goalHasBlockingPrerequisites, loadGoalRuns, upsertGoalRun, updateGoalTask, } from "../core/goal-store.js";
|
|
7
|
+
import { referencesRequiringAcknowledgement } from "../core/goal-references.js";
|
|
8
|
+
import { getActiveGoalMode } from "../core/runtime-mode.js";
|
|
6
9
|
const PrerequisiteInput = z.object({
|
|
7
10
|
id: z.string().optional().describe("Stable prerequisite id"),
|
|
8
11
|
label: z.string().describe("Human-readable prerequisite label"),
|
|
@@ -51,7 +54,9 @@ const GoalsParams = z.object({
|
|
|
51
54
|
"prerequisite",
|
|
52
55
|
"task",
|
|
53
56
|
"evidence",
|
|
57
|
+
"evidence_plan",
|
|
54
58
|
"verify",
|
|
59
|
+
"audit",
|
|
55
60
|
"status",
|
|
56
61
|
"pause",
|
|
57
62
|
"resume",
|
|
@@ -81,6 +86,11 @@ const GoalsParams = z.object({
|
|
|
81
86
|
.array(EvidencePlanInput)
|
|
82
87
|
.optional()
|
|
83
88
|
.describe("Planned proof paths for end-to-end verification"),
|
|
89
|
+
evidence_plan_item_id: z.string().optional().describe("Evidence-plan item id to update"),
|
|
90
|
+
evidence_plan_status: z
|
|
91
|
+
.enum(["planned", "ready", "blocked"])
|
|
92
|
+
.optional()
|
|
93
|
+
.describe("Updated evidence-plan item status"),
|
|
84
94
|
verifier_command: z.string().optional().describe("Command that verifies the goal end-to-end"),
|
|
85
95
|
verifier_description: z.string().optional().describe("Natural-language verifier description"),
|
|
86
96
|
task_id: z.string().optional().describe("Goal task id to update"),
|
|
@@ -116,6 +126,40 @@ function asPrerequisiteStatus(value) {
|
|
|
116
126
|
return value;
|
|
117
127
|
return "unknown";
|
|
118
128
|
}
|
|
129
|
+
function requiresPrerequisiteCheck(status, evidence) {
|
|
130
|
+
return status === "unknown" || (status === "met" && !evidence?.trim());
|
|
131
|
+
}
|
|
132
|
+
function uncheckedPrerequisiteInstructions(label) {
|
|
133
|
+
return `Check ${label} locally and record non-secret evidence before workers can start.`;
|
|
134
|
+
}
|
|
135
|
+
async function normalizePrerequisiteInput(cwd, item) {
|
|
136
|
+
const requestedStatus = asPrerequisiteStatus(item.status);
|
|
137
|
+
const id = item.id ?? randomUUID();
|
|
138
|
+
if (item.check_command && requiresPrerequisiteCheck(requestedStatus, item.evidence)) {
|
|
139
|
+
const result = await runGoalPrerequisiteCheckCommand({ cwd, command: item.check_command });
|
|
140
|
+
return {
|
|
141
|
+
id,
|
|
142
|
+
label: item.label,
|
|
143
|
+
status: result.status,
|
|
144
|
+
checkCommand: item.check_command,
|
|
145
|
+
evidence: result.evidence,
|
|
146
|
+
...(result.status === "missing" || item.instructions
|
|
147
|
+
? { instructions: item.instructions ?? `Make \`${item.check_command}\` pass locally.` }
|
|
148
|
+
: {}),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
id,
|
|
153
|
+
label: item.label,
|
|
154
|
+
status: requestedStatus,
|
|
155
|
+
...(item.check_command ? { checkCommand: item.check_command } : {}),
|
|
156
|
+
...(item.instructions ? { instructions: item.instructions } : {}),
|
|
157
|
+
...(item.evidence ? { evidence: item.evidence } : {}),
|
|
158
|
+
...(requiresPrerequisiteCheck(requestedStatus, item.evidence) && !item.instructions
|
|
159
|
+
? { instructions: uncheckedPrerequisiteInstructions(item.label) }
|
|
160
|
+
: {}),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
119
163
|
function asTaskStatus(value) {
|
|
120
164
|
if (value === "pending" ||
|
|
121
165
|
value === "running" ||
|
|
@@ -137,6 +181,11 @@ function asEvidenceKind(value) {
|
|
|
137
181
|
}
|
|
138
182
|
return "summary";
|
|
139
183
|
}
|
|
184
|
+
function asEvidencePlanStatus(value) {
|
|
185
|
+
if (value === "ready" || value === "blocked" || value === "planned")
|
|
186
|
+
return value;
|
|
187
|
+
return "planned";
|
|
188
|
+
}
|
|
140
189
|
function asEvidenceMechanism(value) {
|
|
141
190
|
if (value === "command" ||
|
|
142
191
|
value === "test" ||
|
|
@@ -159,6 +208,12 @@ function asVerificationStatus(value) {
|
|
|
159
208
|
return value;
|
|
160
209
|
return "unknown";
|
|
161
210
|
}
|
|
211
|
+
function formatRunReferences(run) {
|
|
212
|
+
if (!run.references?.length)
|
|
213
|
+
return "";
|
|
214
|
+
const lines = run.references.map((reference) => `- ${reference.id}: ${reference.kind}; ${reference.label}${reference.value ? `; value=${reference.value}` : ""}${reference.path ? `; path=${reference.path}` : ""}`);
|
|
215
|
+
return `\nReferences:\n${lines.join("\n")}`;
|
|
216
|
+
}
|
|
162
217
|
function formatRun(run) {
|
|
163
218
|
const prereqs = run.prerequisites.length
|
|
164
219
|
? `${run.prerequisites.filter((item) => item.status === "met").length}/${run.prerequisites.length} prereqs met`
|
|
@@ -171,31 +226,144 @@ function formatRun(run) {
|
|
|
171
226
|
: run.verifier?.command
|
|
172
227
|
? "verifier configured"
|
|
173
228
|
: "no verifier";
|
|
229
|
+
const refs = run.references?.length ? `, ${run.references.length} reference(s)` : "";
|
|
230
|
+
const audit = run.completionAudit
|
|
231
|
+
? `, final audit ${run.completionAudit.status}`
|
|
232
|
+
: run.verifier?.lastResult?.status === "pass"
|
|
233
|
+
? ", final audit missing"
|
|
234
|
+
: "";
|
|
174
235
|
const blocker = goalHasBlockingPrerequisites(run)
|
|
175
236
|
? `\nUser prerequisites: ${formatGoalBlockingPrerequisites(run)}`
|
|
176
237
|
: "";
|
|
177
|
-
return `[${run.status}] ${run.title} (id: ${run.id.slice(0, 8)}) — ${prereqs}, ${tasks}, ${verifier}${blocker}`;
|
|
238
|
+
return `[${run.status}] ${run.title} (id: ${run.id.slice(0, 8)}) — ${prereqs}, ${tasks}, ${verifier}${refs}${audit}${blocker}${formatRunReferences(run)}`;
|
|
178
239
|
}
|
|
179
240
|
function recoverableTaskStatus(status) {
|
|
180
241
|
return status === "pending" || status === "failed";
|
|
181
242
|
}
|
|
182
243
|
function statusAfterTaskPatch(run, status) {
|
|
183
|
-
if (run.status !== "failed" || !recoverableTaskStatus(status))
|
|
244
|
+
if ((run.status !== "failed" && run.status !== "passed") || !recoverableTaskStatus(status)) {
|
|
184
245
|
return run.status;
|
|
246
|
+
}
|
|
185
247
|
return goalHasBlockingPrerequisites(run) ? "blocked" : "ready";
|
|
186
248
|
}
|
|
249
|
+
const SETUP_BLOCKER_PREFIX = "Goal setup incomplete:";
|
|
250
|
+
function referencesAcknowledged(references, fields) {
|
|
251
|
+
const required = referencesRequiringAcknowledgement(references ?? []);
|
|
252
|
+
if (required.length === 0)
|
|
253
|
+
return true;
|
|
254
|
+
const haystack = fields.join("\n").toLowerCase();
|
|
255
|
+
return required.every((reference) => {
|
|
256
|
+
const tokens = [reference.id, reference.label, reference.value, reference.path]
|
|
257
|
+
.filter((token) => !!token?.trim())
|
|
258
|
+
.map((token) => token.toLowerCase());
|
|
259
|
+
return tokens.some((token) => haystack.includes(token));
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
function hasOriginalGoalPromptReference(references) {
|
|
263
|
+
return (references ?? []).some((reference) => reference.id === "original-goal-prompt" &&
|
|
264
|
+
reference.kind === "prompt" &&
|
|
265
|
+
reference.content?.trim());
|
|
266
|
+
}
|
|
267
|
+
function setupBlockersForRun(run) {
|
|
268
|
+
const blockers = [];
|
|
269
|
+
const contractFields = [
|
|
270
|
+
run.goal ?? "",
|
|
271
|
+
...run.successCriteria,
|
|
272
|
+
...(run.references ?? []).map((reference) => `${reference.id} ${reference.label} ${reference.content ?? ""}`),
|
|
273
|
+
...(run.evidence ?? []).map((item) => `${item.label}\n${item.path ?? ""}\n${item.content ?? ""}`),
|
|
274
|
+
].join("\n");
|
|
275
|
+
const requiresReliabilityContract = /GOAL_PLAN/.test(contractFields);
|
|
276
|
+
if (requiresReliabilityContract && !hasOriginalGoalPromptReference(run.references)) {
|
|
277
|
+
blockers.push(`${SETUP_BLOCKER_PREFIX} durable [original-goal-prompt] reference is required.`);
|
|
278
|
+
}
|
|
279
|
+
const plannerFields = [
|
|
280
|
+
run.goal ?? "",
|
|
281
|
+
...(run.evidence ?? []).map((item) => `${item.label}\n${item.path ?? ""}\n${item.content ?? ""}`),
|
|
282
|
+
].join("\n");
|
|
283
|
+
if (requiresReliabilityContract &&
|
|
284
|
+
(!/GOAL_PLAN/.test(plannerFields) ||
|
|
285
|
+
!/research=/.test(plannerFields) ||
|
|
286
|
+
!/success=/.test(plannerFields))) {
|
|
287
|
+
blockers.push(`${SETUP_BLOCKER_PREFIX} durable planner GOAL_PLAN evidence/state is required.`);
|
|
288
|
+
}
|
|
289
|
+
if (run.successCriteria.length === 0)
|
|
290
|
+
blockers.push(`${SETUP_BLOCKER_PREFIX} success criteria are required.`);
|
|
291
|
+
if (run.evidencePlan.length === 0)
|
|
292
|
+
blockers.push(`${SETUP_BLOCKER_PREFIX} evidence_plan is required.`);
|
|
293
|
+
if (!run.verifier?.command)
|
|
294
|
+
blockers.push(`${SETUP_BLOCKER_PREFIX} verifier_command is required.`);
|
|
295
|
+
const referenceFields = [
|
|
296
|
+
...run.successCriteria,
|
|
297
|
+
...run.evidencePlan.map((item) => `${item.id} ${item.label} ${item.description} ${item.command ?? ""} ${item.path ?? ""} ${item.evidence ?? ""}`),
|
|
298
|
+
...run.tasks.map((task) => `${task.title} ${task.prompt}`),
|
|
299
|
+
run.verifier?.description ?? "",
|
|
300
|
+
run.verifier?.command ?? "",
|
|
301
|
+
];
|
|
302
|
+
if (!referencesAcknowledged(run.references, referenceFields)) {
|
|
303
|
+
blockers.push(`${SETUP_BLOCKER_PREFIX} every non-prompt Goal reference must be named in success criteria, task prompts, evidence_plan, or verifier metadata.`);
|
|
304
|
+
}
|
|
305
|
+
return blockers;
|
|
306
|
+
}
|
|
307
|
+
function blockersAfterSetupCheck(run, setupBlockers) {
|
|
308
|
+
if (run.status !== "draft")
|
|
309
|
+
return run.blockers;
|
|
310
|
+
return Array.from(new Set([
|
|
311
|
+
...run.blockers.filter((blocker) => !blocker.startsWith(SETUP_BLOCKER_PREFIX)),
|
|
312
|
+
...setupBlockers,
|
|
313
|
+
]));
|
|
314
|
+
}
|
|
315
|
+
function statusAfterSetupCheck(run, setupBlockers) {
|
|
316
|
+
if (run.status !== "draft")
|
|
317
|
+
return run.status;
|
|
318
|
+
if (setupBlockers.length > 0)
|
|
319
|
+
return "draft";
|
|
320
|
+
return goalHasBlockingPrerequisites(run) ? "blocked" : "ready";
|
|
321
|
+
}
|
|
322
|
+
function validatePassAuditContract(run, summary, outputPath) {
|
|
323
|
+
const verifier = run.verifier?.lastResult;
|
|
324
|
+
if (!verifier)
|
|
325
|
+
return "cannot audit completion before a verifier result exists.";
|
|
326
|
+
if (!summary.startsWith("FINAL_AUDIT_PASS"))
|
|
327
|
+
return "pass audit summary must start with FINAL_AUDIT_PASS.";
|
|
328
|
+
if (!summary.includes(`verifier_checked_at=${verifier.checkedAt}`)) {
|
|
329
|
+
return `pass audit summary must include verifier_checked_at=${verifier.checkedAt}.`;
|
|
330
|
+
}
|
|
331
|
+
if (!outputPath && !summary.match(/(?:output|artifact|log|path)=\S+/)) {
|
|
332
|
+
return "pass audit must include output_path or an output/artifact/log/path reference in the summary.";
|
|
333
|
+
}
|
|
334
|
+
const contractFields = [
|
|
335
|
+
run.goal,
|
|
336
|
+
...run.successCriteria,
|
|
337
|
+
...(run.references ?? []).map((reference) => `${reference.id} ${reference.label} ${reference.content ?? ""}`),
|
|
338
|
+
...run.evidence.map((item) => `${item.label}\n${item.path ?? ""}\n${item.content ?? ""}`),
|
|
339
|
+
].join("\n");
|
|
340
|
+
const requiresReliabilityContract = /GOAL_PLAN/.test(contractFields);
|
|
341
|
+
if (requiresReliabilityContract && !summary.includes("original-goal-prompt")) {
|
|
342
|
+
return "pass audit summary must explicitly reference original-goal-prompt.";
|
|
343
|
+
}
|
|
344
|
+
if (requiresReliabilityContract && !summary.includes("GOAL_PLAN")) {
|
|
345
|
+
return "pass audit summary must explicitly reference durable GOAL_PLAN evidence.";
|
|
346
|
+
}
|
|
347
|
+
if (!referencesAcknowledged(run.references, [summary, outputPath ?? ""])) {
|
|
348
|
+
return "pass audit summary or output_path must explicitly reference every non-prompt Goal reference id, label, URL, or path.";
|
|
349
|
+
}
|
|
350
|
+
return undefined;
|
|
351
|
+
}
|
|
187
352
|
async function resolveRun(cwd, id) {
|
|
188
353
|
if (id)
|
|
189
354
|
return getGoalRun(cwd, id);
|
|
190
355
|
return getActiveGoalRun(cwd);
|
|
191
356
|
}
|
|
192
|
-
export function createGoalsTool(cwd) {
|
|
357
|
+
export function createGoalsTool(cwd, goalModeRef, getGoalReferences) {
|
|
193
358
|
return {
|
|
194
359
|
name: "goals",
|
|
195
|
-
description: "Manage durable Goal runs for /goal and Ctrl+G workflows. Use this instead of tasks when the user wants a programmatic goal loop: define success criteria first, check prerequisites before launching workers, persist harness/diagnostics/evidence, add standalone worker tasks, and only mark the goal complete when verifier evidence proves the original objective. Do not require paid services or signups without recording a blocker and asking the user for the missing prerequisite.",
|
|
360
|
+
description: "Manage durable Goal runs for /goal and Ctrl+G workflows. Use this instead of tasks when the user wants a programmatic goal loop: define success criteria first, check prerequisites before launching workers, persist harness/diagnostics/evidence, add standalone worker tasks, record final completion audits, and only mark the goal complete when verifier plus final-audit evidence proves the original objective. Do not require paid services or signups without recording a blocker and asking the user for the missing prerequisite.",
|
|
196
361
|
parameters: GoalsParams,
|
|
197
362
|
executionMode: "sequential",
|
|
198
363
|
async execute(args) {
|
|
364
|
+
if (getActiveGoalMode(goalModeRef) === "planner") {
|
|
365
|
+
return "Error: goals is restricted in Goal planner mode. Emit a compact GOAL_PLAN block only; setup creates durable Goal state.";
|
|
366
|
+
}
|
|
199
367
|
switch (args.action) {
|
|
200
368
|
case "create": {
|
|
201
369
|
if (!args.title)
|
|
@@ -203,14 +371,9 @@ export function createGoalsTool(cwd) {
|
|
|
203
371
|
if (!args.goal)
|
|
204
372
|
return "Error: goal is required for create.";
|
|
205
373
|
const existing = args.run_id ? await getGoalRun(cwd, args.run_id) : null;
|
|
206
|
-
const prerequisites = args.prerequisites
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
status: asPrerequisiteStatus(item.status),
|
|
210
|
-
...(item.check_command ? { checkCommand: item.check_command } : {}),
|
|
211
|
-
...(item.instructions ? { instructions: item.instructions } : {}),
|
|
212
|
-
...(item.evidence ? { evidence: item.evidence } : {}),
|
|
213
|
-
}));
|
|
374
|
+
const prerequisites = args.prerequisites
|
|
375
|
+
? await Promise.all(args.prerequisites.map((item) => normalizePrerequisiteInput(cwd, item)))
|
|
376
|
+
: undefined;
|
|
214
377
|
const harness = args.harness?.map((item) => ({
|
|
215
378
|
id: item.id ?? randomUUID(),
|
|
216
379
|
label: item.label,
|
|
@@ -243,28 +406,58 @@ export function createGoalsTool(cwd) {
|
|
|
243
406
|
const nextPrerequisites = prerequisites ?? existing?.prerequisites ?? [];
|
|
244
407
|
const missingPrerequisites = formatGoalBlockingPrerequisiteList(nextPrerequisites);
|
|
245
408
|
const hasBlockingPrerequisites = missingPrerequisites !== "Goal has no missing user prerequisites.";
|
|
409
|
+
const references = [...(getGoalReferences?.() ?? existing?.references ?? [])];
|
|
410
|
+
const plannerEvidence = args.summary?.includes("GOAL_PLAN")
|
|
411
|
+
? [
|
|
412
|
+
createGoalEvidence({
|
|
413
|
+
kind: "summary",
|
|
414
|
+
label: "Planner GOAL_PLAN",
|
|
415
|
+
content: args.summary,
|
|
416
|
+
}),
|
|
417
|
+
]
|
|
418
|
+
: undefined;
|
|
419
|
+
const draftProbe = {
|
|
420
|
+
goal: args.goal,
|
|
421
|
+
successCriteria: args.success_criteria ?? existing?.successCriteria ?? [],
|
|
422
|
+
evidencePlan: evidencePlan ?? existing?.evidencePlan ?? [],
|
|
423
|
+
references,
|
|
424
|
+
tasks: existing?.tasks ?? [],
|
|
425
|
+
evidence: plannerEvidence ?? existing?.evidence ?? [],
|
|
426
|
+
verifier,
|
|
427
|
+
};
|
|
428
|
+
const setupBlockers = setupBlockersForRun(draftProbe);
|
|
429
|
+
const blockers = Array.from(new Set([
|
|
430
|
+
...(args.blockers ?? existing?.blockers ?? []),
|
|
431
|
+
...(hasBlockingPrerequisites ? [missingPrerequisites] : []),
|
|
432
|
+
...setupBlockers,
|
|
433
|
+
]));
|
|
246
434
|
const run = await upsertGoalRun(cwd, {
|
|
247
435
|
...(args.run_id ? { id: args.run_id } : {}),
|
|
248
436
|
title: args.title,
|
|
249
437
|
goal: args.goal,
|
|
250
|
-
status:
|
|
251
|
-
|
|
438
|
+
status: setupBlockers.length > 0
|
|
439
|
+
? "draft"
|
|
440
|
+
: hasBlockingPrerequisites
|
|
441
|
+
? "blocked"
|
|
442
|
+
: (existing?.status ?? "ready"),
|
|
443
|
+
successCriteria: draftProbe.successCriteria,
|
|
252
444
|
prerequisites: nextPrerequisites,
|
|
253
445
|
harness: harness ?? existing?.harness ?? [],
|
|
254
|
-
evidencePlan: evidencePlan
|
|
446
|
+
evidencePlan: draftProbe.evidencePlan,
|
|
447
|
+
references: draftProbe.references,
|
|
448
|
+
...(plannerEvidence ? { evidence: plannerEvidence } : {}),
|
|
255
449
|
...(verifier ? { verifier } : {}),
|
|
256
|
-
blockers
|
|
257
|
-
? Array.from(new Set([...(args.blockers ?? existing?.blockers ?? []), missingPrerequisites]))
|
|
258
|
-
: (args.blockers ?? []),
|
|
450
|
+
blockers,
|
|
259
451
|
});
|
|
260
452
|
await appendGoalDecision(cwd, run.id, {
|
|
261
453
|
kind: args.run_id ? "update" : "create",
|
|
262
|
-
reason: `criteria=${run.successCriteria.length}; prerequisites=${run.prerequisites.length}; harness=${run.harness.length}; evidence_plan=${run.evidencePlan.length}; verifier=${run.verifier?.command ? "configured" : "missing"}`,
|
|
454
|
+
reason: `criteria=${run.successCriteria.length}; prerequisites=${run.prerequisites.length}; harness=${run.harness.length}; evidence_plan=${run.evidencePlan.length}; references=${run.references?.length ?? 0}; verifier=${run.verifier?.command ? "configured" : "missing"}`,
|
|
263
455
|
});
|
|
264
456
|
log("INFO", "goals", `Goal created: ${run.title}`, { id: run.id, status: run.status });
|
|
457
|
+
const setupMessage = setupBlockers.length > 0 ? ` Setup blockers: ${setupBlockers.join(" ")}` : "";
|
|
265
458
|
return goalHasBlockingPrerequisites(run)
|
|
266
|
-
? `Goal ${args.run_id ? "updated" : "created"}: "${run.title}" (id: ${run.id.slice(0, 8)}, ${run.status}). User prerequisites: ${formatGoalBlockingPrerequisites(run)}`
|
|
267
|
-
: `Goal ${args.run_id ? "updated" : "created"}: "${run.title}" (id: ${run.id.slice(0, 8)}, ${run.status})`;
|
|
459
|
+
? `Goal ${args.run_id ? "updated" : "created"}: "${run.title}" (id: ${run.id.slice(0, 8)}, ${run.status}). User prerequisites: ${formatGoalBlockingPrerequisites(run)}${setupMessage}`
|
|
460
|
+
: `Goal ${args.run_id ? "updated" : "created"}: "${run.title}" (id: ${run.id.slice(0, 8)}, ${run.status}).${setupMessage}`;
|
|
268
461
|
}
|
|
269
462
|
case "status": {
|
|
270
463
|
if (args.run_id) {
|
|
@@ -288,12 +481,22 @@ export function createGoalsTool(cwd) {
|
|
|
288
481
|
const index = prereqId
|
|
289
482
|
? prerequisites.findIndex((item) => item.id === prereqId || item.id.startsWith(prereqId))
|
|
290
483
|
: -1;
|
|
484
|
+
const existingPrerequisite = index >= 0 ? prerequisites[index] : undefined;
|
|
291
485
|
const patch = {
|
|
292
486
|
id: prereqId ?? randomUUID(),
|
|
293
|
-
label: args.prerequisite_label ?? prereqId ?? "Prerequisite",
|
|
487
|
+
label: args.prerequisite_label ?? existingPrerequisite?.label ?? prereqId ?? "Prerequisite",
|
|
294
488
|
status: asPrerequisiteStatus(args.prerequisite_status),
|
|
295
489
|
...(args.instructions ? { instructions: args.instructions } : {}),
|
|
296
490
|
...(args.summary ? { evidence: args.summary } : {}),
|
|
491
|
+
...(asPrerequisiteStatus(args.prerequisite_status) === "met" && !args.summary
|
|
492
|
+
? {
|
|
493
|
+
instructions: args.instructions ??
|
|
494
|
+
uncheckedPrerequisiteInstructions(args.prerequisite_label ??
|
|
495
|
+
existingPrerequisite?.label ??
|
|
496
|
+
prereqId ??
|
|
497
|
+
"Prerequisite"),
|
|
498
|
+
}
|
|
499
|
+
: {}),
|
|
297
500
|
};
|
|
298
501
|
if (index >= 0) {
|
|
299
502
|
prerequisites[index] = {
|
|
@@ -305,12 +508,17 @@ export function createGoalsTool(cwd) {
|
|
|
305
508
|
else {
|
|
306
509
|
prerequisites.push(patch);
|
|
307
510
|
}
|
|
308
|
-
const
|
|
309
|
-
const updated = await upsertGoalRun(cwd, {
|
|
511
|
+
const prerequisiteRun = {
|
|
310
512
|
...run,
|
|
311
513
|
prerequisites,
|
|
312
|
-
status:
|
|
313
|
-
blockers:
|
|
514
|
+
status: goalHasBlockingPrerequisites({ ...run, prerequisites }) ? "blocked" : "ready",
|
|
515
|
+
blockers: goalHasBlockingPrerequisites({ ...run, prerequisites }) ? run.blockers : [],
|
|
516
|
+
};
|
|
517
|
+
const setupBlockers = setupBlockersForRun(prerequisiteRun);
|
|
518
|
+
const updated = await upsertGoalRun(cwd, {
|
|
519
|
+
...prerequisiteRun,
|
|
520
|
+
status: statusAfterSetupCheck(prerequisiteRun, setupBlockers),
|
|
521
|
+
blockers: blockersAfterSetupCheck(prerequisiteRun, setupBlockers),
|
|
314
522
|
});
|
|
315
523
|
await appendGoalDecision(cwd, updated.id, {
|
|
316
524
|
kind: "prerequisites",
|
|
@@ -333,6 +541,10 @@ export function createGoalsTool(cwd) {
|
|
|
333
541
|
if (!taskExisted && (!args.task_title || !args.task_prompt)) {
|
|
334
542
|
return "Error: task_title and task_prompt are required when adding a task.";
|
|
335
543
|
}
|
|
544
|
+
if (!taskExisted &&
|
|
545
|
+
!referencesAcknowledged(run.references, [args.task_title ?? "", args.task_prompt ?? ""])) {
|
|
546
|
+
return "Error: task_prompt must explicitly include each non-prompt Goal reference id, label, URL, or path so workers cannot silently ignore the user's references.";
|
|
547
|
+
}
|
|
336
548
|
const taskStatus = asTaskStatus(args.task_status);
|
|
337
549
|
const updated = await updateGoalTask(cwd, run.id, taskId, {
|
|
338
550
|
id: taskId,
|
|
@@ -344,10 +556,18 @@ export function createGoalsTool(cwd) {
|
|
|
344
556
|
...(args.summary ? { lastSummary: args.summary } : {}),
|
|
345
557
|
});
|
|
346
558
|
const recovered = updated
|
|
347
|
-
? await
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
559
|
+
? await (async () => {
|
|
560
|
+
const taskPatchedRun = {
|
|
561
|
+
...updated,
|
|
562
|
+
status: statusAfterTaskPatch(updated, taskStatus),
|
|
563
|
+
};
|
|
564
|
+
const setupBlockers = setupBlockersForRun(taskPatchedRun);
|
|
565
|
+
return upsertGoalRun(updated.projectPath, {
|
|
566
|
+
...taskPatchedRun,
|
|
567
|
+
status: statusAfterSetupCheck(taskPatchedRun, setupBlockers),
|
|
568
|
+
blockers: blockersAfterSetupCheck(taskPatchedRun, setupBlockers),
|
|
569
|
+
});
|
|
570
|
+
})()
|
|
351
571
|
: null;
|
|
352
572
|
if (!recovered)
|
|
353
573
|
return `Error: no task found matching id "${taskId}".`;
|
|
@@ -372,6 +592,48 @@ export function createGoalsTool(cwd) {
|
|
|
372
592
|
return "Error: failed to append evidence.";
|
|
373
593
|
return `Evidence added to "${updated.title}".`;
|
|
374
594
|
}
|
|
595
|
+
case "evidence_plan": {
|
|
596
|
+
const run = await resolveRun(cwd, args.run_id);
|
|
597
|
+
if (!run)
|
|
598
|
+
return "Error: no active goal run found.";
|
|
599
|
+
const evidencePlanItemId = args.evidence_plan_item_id;
|
|
600
|
+
if (!evidencePlanItemId)
|
|
601
|
+
return "Error: evidence_plan_item_id is required.";
|
|
602
|
+
const evidencePlan = [...run.evidencePlan];
|
|
603
|
+
const index = evidencePlan.findIndex((item) => item.id === evidencePlanItemId || item.id.startsWith(evidencePlanItemId));
|
|
604
|
+
if (index < 0) {
|
|
605
|
+
return `Error: no evidence-plan item found matching id "${args.evidence_plan_item_id}".`;
|
|
606
|
+
}
|
|
607
|
+
const existing = evidencePlan[index];
|
|
608
|
+
const status = asEvidencePlanStatus(args.evidence_plan_status);
|
|
609
|
+
evidencePlan[index] = {
|
|
610
|
+
...existing,
|
|
611
|
+
status,
|
|
612
|
+
...(args.instructions ? { instructions: args.instructions } : {}),
|
|
613
|
+
...(args.evidence_content || args.summary
|
|
614
|
+
? { evidence: args.evidence_content ?? args.summary }
|
|
615
|
+
: {}),
|
|
616
|
+
...(args.evidence_path ? { path: args.evidence_path } : {}),
|
|
617
|
+
};
|
|
618
|
+
const canRecoverBlockedRun = run.status === "blocked" && status === "ready" && !goalHasBlockingPrerequisites(run);
|
|
619
|
+
const evidencePlanRun = {
|
|
620
|
+
...run,
|
|
621
|
+
evidencePlan,
|
|
622
|
+
status: canRecoverBlockedRun ? "ready" : run.status,
|
|
623
|
+
blockers: canRecoverBlockedRun ? [] : run.blockers,
|
|
624
|
+
};
|
|
625
|
+
const setupBlockers = setupBlockersForRun(evidencePlanRun);
|
|
626
|
+
const updated = await upsertGoalRun(cwd, {
|
|
627
|
+
...evidencePlanRun,
|
|
628
|
+
status: statusAfterSetupCheck(evidencePlanRun, setupBlockers),
|
|
629
|
+
blockers: blockersAfterSetupCheck(evidencePlanRun, setupBlockers),
|
|
630
|
+
});
|
|
631
|
+
await appendGoalDecision(cwd, updated.id, {
|
|
632
|
+
kind: "evidence_plan",
|
|
633
|
+
reason: `Evidence-plan item ${existing.label} is ${status}.`,
|
|
634
|
+
});
|
|
635
|
+
return `Evidence-plan item updated for "${updated.title}": "${existing.label}" is ${status}.`;
|
|
636
|
+
}
|
|
375
637
|
case "verify": {
|
|
376
638
|
const run = await resolveRun(cwd, args.run_id);
|
|
377
639
|
if (!run)
|
|
@@ -395,6 +657,17 @@ export function createGoalsTool(cwd) {
|
|
|
395
657
|
: {}),
|
|
396
658
|
lastResult: result,
|
|
397
659
|
},
|
|
660
|
+
...(result.status === "pass"
|
|
661
|
+
? {
|
|
662
|
+
completionAudit: {
|
|
663
|
+
status: "unknown",
|
|
664
|
+
summary: "Final completion audit pending for latest verifier result.",
|
|
665
|
+
checkedAt: result.checkedAt,
|
|
666
|
+
verifierCheckedAt: result.checkedAt,
|
|
667
|
+
...(result.outputPath ? { outputPath: result.outputPath } : {}),
|
|
668
|
+
},
|
|
669
|
+
}
|
|
670
|
+
: {}),
|
|
398
671
|
evidence: [
|
|
399
672
|
...run.evidence,
|
|
400
673
|
createGoalEvidence({
|
|
@@ -424,6 +697,61 @@ export function createGoalsTool(cwd) {
|
|
|
424
697
|
});
|
|
425
698
|
return `Verifier recorded for "${updated.title}": ${result.status}.`;
|
|
426
699
|
}
|
|
700
|
+
case "audit": {
|
|
701
|
+
const run = await resolveRun(cwd, args.run_id);
|
|
702
|
+
if (!run)
|
|
703
|
+
return "Error: no active goal run found.";
|
|
704
|
+
const verifierResult = run.verifier?.lastResult;
|
|
705
|
+
if (!verifierResult || verifierResult.status !== "pass") {
|
|
706
|
+
return "Error: cannot audit completion before a passing verifier result exists.";
|
|
707
|
+
}
|
|
708
|
+
const auditStatus = asVerificationStatus(args.verification_status);
|
|
709
|
+
const auditSummary = args.summary ?? "Final completion audit recorded.";
|
|
710
|
+
const auditOutputPath = args.output_path ?? verifierResult.outputPath;
|
|
711
|
+
if (auditStatus === "pass") {
|
|
712
|
+
const contractError = validatePassAuditContract(run, auditSummary, auditOutputPath);
|
|
713
|
+
if (contractError)
|
|
714
|
+
return `Error: invalid final completion audit pass contract: ${contractError}`;
|
|
715
|
+
}
|
|
716
|
+
const completionAudit = {
|
|
717
|
+
status: auditStatus,
|
|
718
|
+
summary: auditSummary,
|
|
719
|
+
checkedAt: new Date().toISOString(),
|
|
720
|
+
verifierCheckedAt: verifierResult.checkedAt,
|
|
721
|
+
...(auditOutputPath ? { outputPath: auditOutputPath } : {}),
|
|
722
|
+
};
|
|
723
|
+
const runWithAudit = {
|
|
724
|
+
...run,
|
|
725
|
+
completionAudit,
|
|
726
|
+
evidence: [
|
|
727
|
+
...run.evidence,
|
|
728
|
+
createGoalEvidence({
|
|
729
|
+
kind: "summary",
|
|
730
|
+
label: `Final completion audit ${completionAudit.status}`,
|
|
731
|
+
content: completionAudit.summary,
|
|
732
|
+
...(completionAudit.outputPath ? { path: completionAudit.outputPath } : {}),
|
|
733
|
+
}),
|
|
734
|
+
],
|
|
735
|
+
};
|
|
736
|
+
const auditCheck = hasFreshGoalCompletionAudit(runWithAudit);
|
|
737
|
+
const completion = canCompleteGoalRun(runWithAudit);
|
|
738
|
+
const updated = await upsertGoalRun(cwd, {
|
|
739
|
+
...runWithAudit,
|
|
740
|
+
status: completionAudit.status === "pass" && auditCheck.ok && completion.ok
|
|
741
|
+
? "passed"
|
|
742
|
+
: goalHasBlockingPrerequisites(runWithAudit)
|
|
743
|
+
? "blocked"
|
|
744
|
+
: "ready",
|
|
745
|
+
blockers: completionAudit.status === "pass" && auditCheck.ok ? [] : run.blockers,
|
|
746
|
+
activeWorkerId: undefined,
|
|
747
|
+
});
|
|
748
|
+
await appendGoalDecision(cwd, updated.id, {
|
|
749
|
+
kind: "completion_audit",
|
|
750
|
+
reason: auditCheck.reason,
|
|
751
|
+
content: `status=${completionAudit.status}; verifierCheckedAt=${completionAudit.verifierCheckedAt ?? ""}; outputPath=${completionAudit.outputPath ?? ""}`,
|
|
752
|
+
});
|
|
753
|
+
return `Completion audit recorded for "${updated.title}": ${completionAudit.status}.`;
|
|
754
|
+
}
|
|
427
755
|
case "pause":
|
|
428
756
|
case "resume":
|
|
429
757
|
case "complete": {
|
|
@@ -431,8 +759,12 @@ export function createGoalsTool(cwd) {
|
|
|
431
759
|
if (!run)
|
|
432
760
|
return "Error: no active goal run found.";
|
|
433
761
|
let status;
|
|
434
|
-
if (args.action === "pause")
|
|
762
|
+
if (args.action === "pause") {
|
|
763
|
+
if (run.activeWorkerId || run.tasks.some((task) => task.status === "running")) {
|
|
764
|
+
return `Error: cannot pause goal while worker ${run.activeWorkerId ?? "task"} is active. Stop the worker first or wait for it to finish.`;
|
|
765
|
+
}
|
|
435
766
|
status = "paused";
|
|
767
|
+
}
|
|
436
768
|
else if (args.action === "resume") {
|
|
437
769
|
const missing = goalHasBlockingPrerequisites(run)
|
|
438
770
|
? formatGoalBlockingPrerequisites(run)
|
|
@@ -441,7 +773,7 @@ export function createGoalsTool(cwd) {
|
|
|
441
773
|
const updated = await upsertGoalRun(cwd, {
|
|
442
774
|
...run,
|
|
443
775
|
status: "blocked",
|
|
444
|
-
blockers:
|
|
776
|
+
blockers: appendGoalBlockers(run.blockers, missing),
|
|
445
777
|
evidence: [
|
|
446
778
|
...run.evidence,
|
|
447
779
|
createGoalEvidence({
|
|
@@ -469,7 +801,25 @@ export function createGoalsTool(cwd) {
|
|
|
469
801
|
],
|
|
470
802
|
};
|
|
471
803
|
const decision = decideGoalNextAction(resumed);
|
|
472
|
-
const
|
|
804
|
+
const blockedReason = decision.kind === "blocked" ? decision.reason : undefined;
|
|
805
|
+
const updated = await upsertGoalRun(cwd, {
|
|
806
|
+
...resumed,
|
|
807
|
+
...(blockedReason
|
|
808
|
+
? {
|
|
809
|
+
status: "blocked",
|
|
810
|
+
continueRequestedAt: undefined,
|
|
811
|
+
blockers: appendGoalBlockers(run.blockers, blockedReason),
|
|
812
|
+
evidence: [
|
|
813
|
+
...resumed.evidence,
|
|
814
|
+
createGoalEvidence({
|
|
815
|
+
kind: "summary",
|
|
816
|
+
label: "Goal resume blocked",
|
|
817
|
+
content: blockedReason,
|
|
818
|
+
}),
|
|
819
|
+
],
|
|
820
|
+
}
|
|
821
|
+
: {}),
|
|
822
|
+
});
|
|
473
823
|
await appendGoalDecision(cwd, updated.id, {
|
|
474
824
|
kind: "resume",
|
|
475
825
|
reason: decision.kind === "wait" ||
|