@kenkaiiii/ggcoder 4.3.230 → 4.3.232
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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -0
- 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/goal-controller.d.ts +27 -6
- package/dist/core/goal-controller.d.ts.map +1 -1
- package/dist/core/goal-controller.js +246 -141
- package/dist/core/goal-controller.js.map +1 -1
- package/dist/core/goal-controller.test.js +210 -79
- package/dist/core/goal-controller.test.js.map +1 -1
- package/dist/core/goal-engine.d.ts +61 -0
- package/dist/core/goal-engine.d.ts.map +1 -0
- package/dist/core/goal-engine.js +123 -0
- package/dist/core/goal-engine.js.map +1 -0
- package/dist/core/goal-engine.test.d.ts +2 -0
- package/dist/core/goal-engine.test.d.ts.map +1 -0
- package/dist/core/goal-engine.test.js +295 -0
- package/dist/core/goal-engine.test.js.map +1 -0
- package/dist/core/goal-integration.d.ts +80 -0
- package/dist/core/goal-integration.d.ts.map +1 -0
- package/dist/core/goal-integration.js +296 -0
- package/dist/core/goal-integration.js.map +1 -0
- package/dist/core/goal-integration.test.d.ts +2 -0
- package/dist/core/goal-integration.test.d.ts.map +1 -0
- package/dist/core/goal-integration.test.js +369 -0
- package/dist/core/goal-integration.test.js.map +1 -0
- package/dist/core/goal-prerequisites.test.js +37 -1
- package/dist/core/goal-prerequisites.test.js.map +1 -1
- package/dist/core/goal-store.d.ts +80 -1
- package/dist/core/goal-store.d.ts.map +1 -1
- package/dist/core/goal-store.js +232 -65
- package/dist/core/goal-store.js.map +1 -1
- package/dist/core/goal-store.test.js +111 -2
- package/dist/core/goal-store.test.js.map +1 -1
- package/dist/core/goal-worker.d.ts.map +1 -1
- package/dist/core/goal-worker.js +55 -4
- package/dist/core/goal-worker.js.map +1 -1
- package/dist/core/goal-worker.test.js +75 -6
- package/dist/core/goal-worker.test.js.map +1 -1
- package/dist/core/goal-worktree.d.ts +55 -1
- package/dist/core/goal-worktree.d.ts.map +1 -1
- package/dist/core/goal-worktree.js +164 -1
- package/dist/core/goal-worktree.js.map +1 -1
- package/dist/core/goal-worktree.test.js +226 -4
- package/dist/core/goal-worktree.test.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/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/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +9 -6
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +1 -1
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/edit-diff.d.ts +17 -4
- package/dist/tools/edit-diff.d.ts.map +1 -1
- package/dist/tools/edit-diff.js +78 -16
- package/dist/tools/edit-diff.js.map +1 -1
- package/dist/tools/edit-diff.test.js +31 -1
- package/dist/tools/edit-diff.test.js.map +1 -1
- package/dist/tools/edit-robustness.test.d.ts +2 -0
- package/dist/tools/edit-robustness.test.d.ts.map +1 -0
- package/dist/tools/edit-robustness.test.js +415 -0
- package/dist/tools/edit-robustness.test.js.map +1 -0
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +15 -16
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/edit.test.js +23 -12
- package/dist/tools/edit.test.js.map +1 -1
- package/dist/tools/goals.d.ts +9 -1
- package/dist/tools/goals.d.ts.map +1 -1
- package/dist/tools/goals.js +78 -25
- package/dist/tools/goals.js.map +1 -1
- package/dist/tools/goals.test.js +142 -11
- package/dist/tools/goals.test.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/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 -1
- package/dist/tools/prompt-hints.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/ui/App.d.ts +11 -1
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +132 -17
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/app-items.d.ts +14 -1
- package/dist/ui/app-items.d.ts.map +1 -1
- package/dist/ui/app-items.js +2 -0
- package/dist/ui/app-items.js.map +1 -1
- package/dist/ui/components/ChatLayout.d.ts +8 -1
- package/dist/ui/components/ChatLayout.d.ts.map +1 -1
- package/dist/ui/components/ChatLayout.js +4 -1
- package/dist/ui/components/ChatLayout.js.map +1 -1
- package/dist/ui/components/ChatScreen.d.ts +14 -1
- package/dist/ui/components/ChatScreen.d.ts.map +1 -1
- package/dist/ui/components/ChatScreen.js +3 -2
- package/dist/ui/components/ChatScreen.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 +13 -1
- package/dist/ui/components/InputArea.d.ts.map +1 -1
- package/dist/ui/components/InputArea.js +96 -12
- package/dist/ui/components/InputArea.js.map +1 -1
- package/dist/ui/components/TranscriptViewport.d.ts +34 -0
- package/dist/ui/components/TranscriptViewport.d.ts.map +1 -0
- package/dist/ui/components/TranscriptViewport.js +45 -0
- package/dist/ui/components/TranscriptViewport.js.map +1 -0
- package/dist/ui/footer-jump-regression.test.d.ts +2 -0
- package/dist/ui/footer-jump-regression.test.d.ts.map +1 -0
- package/dist/ui/footer-jump-regression.test.js +167 -0
- package/dist/ui/footer-jump-regression.test.js.map +1 -0
- package/dist/ui/goal-events.d.ts +1 -1
- package/dist/ui/goal-events.d.ts.map +1 -1
- package/dist/ui/goal-events.js +2 -2
- package/dist/ui/goal-events.js.map +1 -1
- package/dist/ui/goal-events.test.js +2 -2
- package/dist/ui/goal-events.test.js.map +1 -1
- package/dist/ui/goal-lifecycle-orchestration.test.js +13 -97
- package/dist/ui/goal-lifecycle-orchestration.test.js.map +1 -1
- package/dist/ui/goal-progress.d.ts.map +1 -1
- package/dist/ui/goal-progress.js +0 -1
- package/dist/ui/goal-progress.js.map +1 -1
- package/dist/ui/goal-run-helpers.d.ts +0 -4
- package/dist/ui/goal-run-helpers.d.ts.map +1 -1
- package/dist/ui/goal-run-helpers.js +2 -21
- package/dist/ui/goal-run-helpers.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 +8 -0
- package/dist/ui/hooks/useChatLayoutMeasurements.d.ts.map +1 -1
- package/dist/ui/hooks/useChatLayoutMeasurements.js +2 -0
- package/dist/ui/hooks/useChatLayoutMeasurements.js.map +1 -1
- package/dist/ui/hooks/useGoalOrchestration.d.ts +2 -1
- package/dist/ui/hooks/useGoalOrchestration.d.ts.map +1 -1
- package/dist/ui/hooks/useGoalOrchestration.js +198 -80
- package/dist/ui/hooks/useGoalOrchestration.js.map +1 -1
- package/dist/ui/hooks/useTerminalSize.d.ts +8 -1
- package/dist/ui/hooks/useTerminalSize.d.ts.map +1 -1
- package/dist/ui/hooks/useTerminalSize.js +12 -2
- package/dist/ui/hooks/useTerminalSize.js.map +1 -1
- package/dist/ui/hooks/useTranscriptHistory.d.ts +1 -1
- package/dist/ui/hooks/useTranscriptHistory.d.ts.map +1 -1
- package/dist/ui/hooks/useTranscriptHistory.js +23 -9
- package/dist/ui/hooks/useTranscriptHistory.js.map +1 -1
- package/dist/ui/hooks/useTranscriptHistory.test.d.ts +2 -0
- package/dist/ui/hooks/useTranscriptHistory.test.d.ts.map +1 -0
- package/dist/ui/hooks/useTranscriptHistory.test.js +61 -0
- package/dist/ui/hooks/useTranscriptHistory.test.js.map +1 -0
- package/dist/ui/hooks/useTranscriptScroll.d.ts +30 -0
- package/dist/ui/hooks/useTranscriptScroll.d.ts.map +1 -0
- package/dist/ui/hooks/useTranscriptScroll.js +44 -0
- package/dist/ui/hooks/useTranscriptScroll.js.map +1 -0
- package/dist/ui/hooks/useTranscriptScroll.test.d.ts +2 -0
- package/dist/ui/hooks/useTranscriptScroll.test.d.ts.map +1 -0
- package/dist/ui/hooks/useTranscriptScroll.test.js +119 -0
- package/dist/ui/hooks/useTranscriptScroll.test.js.map +1 -0
- package/dist/ui/live-area-clamp.test.js +11 -2
- package/dist/ui/live-area-clamp.test.js.map +1 -1
- package/dist/ui/render.d.ts +11 -0
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +71 -7
- package/dist/ui/render.js.map +1 -1
- package/dist/ui/stores/transcript-scroll-store.d.ts +27 -0
- package/dist/ui/stores/transcript-scroll-store.d.ts.map +1 -0
- package/dist/ui/stores/transcript-scroll-store.js +73 -0
- package/dist/ui/stores/transcript-scroll-store.js.map +1 -0
- package/dist/ui/stores/transcript-scroll-store.test.d.ts +2 -0
- package/dist/ui/stores/transcript-scroll-store.test.d.ts.map +1 -0
- package/dist/ui/stores/transcript-scroll-store.test.js +73 -0
- package/dist/ui/stores/transcript-scroll-store.test.js.map +1 -0
- package/dist/ui/terminal-history.d.ts.map +1 -1
- package/dist/ui/terminal-history.js +8 -0
- package/dist/ui/terminal-history.js.map +1 -1
- package/dist/ui/testing/screen-recorder.d.ts +29 -0
- package/dist/ui/testing/screen-recorder.d.ts.map +1 -0
- package/dist/ui/testing/screen-recorder.js +179 -0
- package/dist/ui/testing/screen-recorder.js.map +1 -0
- package/dist/ui/transcript/TranscriptRenderer.d.ts.map +1 -1
- package/dist/ui/transcript/TranscriptRenderer.js +4 -1
- package/dist/ui/transcript/TranscriptRenderer.js.map +1 -1
- package/dist/ui/transcript/spacing.d.ts +3 -2
- package/dist/ui/transcript/spacing.d.ts.map +1 -1
- package/dist/ui/transcript/spacing.js +8 -0
- package/dist/ui/transcript/spacing.js.map +1 -1
- package/dist/ui/transcript/spacing.test.js +31 -0
- package/dist/ui/transcript/spacing.test.js.map +1 -1
- package/dist/ui/transcript/transcript-lines.d.ts +32 -0
- package/dist/ui/transcript/transcript-lines.d.ts.map +1 -0
- package/dist/ui/transcript/transcript-lines.js +82 -0
- package/dist/ui/transcript/transcript-lines.js.map +1 -0
- package/dist/ui/transcript/transcript-lines.test.d.ts +2 -0
- package/dist/ui/transcript/transcript-lines.test.d.ts.map +1 -0
- package/dist/ui/transcript/transcript-lines.test.js +76 -0
- package/dist/ui/transcript/transcript-lines.test.js.map +1 -0
- package/dist/ui/transcript-viewport-pinning.test.d.ts +2 -0
- package/dist/ui/transcript-viewport-pinning.test.d.ts.map +1 -0
- package/dist/ui/transcript-viewport-pinning.test.js +148 -0
- package/dist/ui/transcript-viewport-pinning.test.js.map +1 -0
- package/dist/ui/tui-history-parity.test.js +8 -0
- package/dist/ui/tui-history-parity.test.js.map +1 -1
- package/dist/ui/tui-simulation.test.d.ts +2 -0
- package/dist/ui/tui-simulation.test.d.ts.map +1 -0
- package/dist/ui/tui-simulation.test.js +138 -0
- package/dist/ui/tui-simulation.test.js.map +1 -0
- package/dist/ui/tui-terminal-recorder.test.d.ts +2 -0
- package/dist/ui/tui-terminal-recorder.test.d.ts.map +1 -0
- package/dist/ui/tui-terminal-recorder.test.js +134 -0
- package/dist/ui/tui-terminal-recorder.test.js.map +1 -0
- package/dist/utils/format.js +7 -0
- package/dist/utils/format.js.map +1 -1
- package/package.json +12 -6
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
import { formatGoalBlockingPrerequisites, goalHasBlockingPrerequisites, } from "./goal-store.js";
|
|
1
|
+
import { formatGoalBlockingPrerequisites, goalHasBlockingPrerequisites, goalHasUnmetLocalPrerequisites, unmetLocalGoalPrerequisites, } from "./goal-store.js";
|
|
2
2
|
import { formatGoalReferencesForPrompt, referencesRequiringAcknowledgement, } from "./goal-references.js";
|
|
3
3
|
export const DEFAULT_GOAL_TASK_ATTEMPT_LIMIT = 5;
|
|
4
4
|
export const DEFAULT_GOAL_VERIFIER_FIX_LIMIT = 5;
|
|
5
|
+
export const DEFAULT_GOAL_STRATEGY_LIMIT = 2;
|
|
6
|
+
/**
|
|
7
|
+
* Hard ceiling on total controller decisions per run. A safety net that
|
|
8
|
+
* guarantees termination even if some unforeseen state oscillates without
|
|
9
|
+
* tripping the per-dimension attempt/strategy/verifier/audit limits. Set high
|
|
10
|
+
* enough that legitimate large goals never hit it.
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_GOAL_DECISION_LIMIT = 300;
|
|
5
13
|
export const APPLY_INTEGRATION_TO_MAIN_TASK_TITLE = "Apply integrated worktree to main";
|
|
6
|
-
export const
|
|
7
|
-
const
|
|
14
|
+
export const RESOLVE_LOCAL_PREREQUISITES_TASK_TITLE = "Resolve local Goal prerequisites";
|
|
15
|
+
export const RE_STRATEGIZE_GOAL_TASK_TITLE = "Re-strategize Goal approach";
|
|
16
|
+
export const FINAL_COMPLETION_AUDIT_TASK_TITLE = "Audit Goal completion evidence";
|
|
8
17
|
const BUILD_GOAL_EVIDENCE_PATH_TASK_TITLE = "Build Goal evidence path";
|
|
9
18
|
const BUILD_GOAL_VERIFICATION_HARNESS_TASK_TITLE = "Build Goal verification harness";
|
|
10
19
|
const DEFINE_GOAL_VERIFIER_TASK_TITLE = "Define Goal verifier";
|
|
11
20
|
const FIX_VERIFIER_FAILURE_TASK_TITLE = "Fix verifier failure";
|
|
12
21
|
const DEFAULT_GOAL_COMPLETION_AUDIT_LIMIT = 3;
|
|
22
|
+
/** Count of controller decisions already recorded as durable evidence. */
|
|
23
|
+
export function goalDecisionCount(run) {
|
|
24
|
+
return run.evidence.filter((item) => item.label.startsWith("Goal decision:")).length;
|
|
25
|
+
}
|
|
13
26
|
function needsHarnessInstrumentation(run) {
|
|
14
27
|
return run.harness.some((item) => !item.command && !item.path);
|
|
15
28
|
}
|
|
@@ -168,85 +181,57 @@ function finalAuditTaskCount(run) {
|
|
|
168
181
|
function hasApplyIntegrationTask(run) {
|
|
169
182
|
return run.tasks.some((task) => task.title === APPLY_INTEGRATION_TO_MAIN_TASK_TITLE);
|
|
170
183
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
function
|
|
178
|
-
return run.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
184
|
+
/**
|
|
185
|
+
* Done worktree tasks whose committed candidate changes must reach the main
|
|
186
|
+
* checkout. Ordering is expressed by dependsOn; this gate only excludes tasks
|
|
187
|
+
* explicitly marked integration="manual". Read-only tasks (audit, etc.)
|
|
188
|
+
* produce no candidate changes and are excluded.
|
|
189
|
+
*/
|
|
190
|
+
function pendingWorktreeIntegrationTasks(run) {
|
|
191
|
+
return run.tasks.filter((task) => task.status === "done" &&
|
|
192
|
+
!!task.worktree &&
|
|
193
|
+
task.integration !== "manual" &&
|
|
194
|
+
(task.candidate?.changedFiles?.length ?? 0) > 0);
|
|
195
|
+
}
|
|
196
|
+
/** Typed integration gate: candidates reached main (applied or committed). */
|
|
197
|
+
function integrationApplied(run) {
|
|
198
|
+
return run.integration?.status === "applied" || run.integration?.status === "committed";
|
|
199
|
+
}
|
|
200
|
+
/** Typed integration gate: integrated changes are committed in main. */
|
|
201
|
+
function integrationCommitted(run) {
|
|
202
|
+
return run.integration?.status === "committed";
|
|
183
203
|
}
|
|
184
204
|
function hasIntegratedWorktreeChanges(run) {
|
|
185
|
-
return (
|
|
205
|
+
return (pendingWorktreeIntegrationTasks(run).length > 0 ||
|
|
206
|
+
(run.integration != null && run.integration.status !== "none"));
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* True when the latest verifier result predates the most recent substantive
|
|
210
|
+
* (non-audit, non-integration) worker completion, so the verifier evidence is
|
|
211
|
+
* stale and must be re-run before the audit/completion gates can trust it.
|
|
212
|
+
*/
|
|
213
|
+
function verifierStaleAfterWorker(run) {
|
|
214
|
+
return (!!run.verifier?.lastResult?.checkedAt &&
|
|
215
|
+
!!run.lastSubstantiveWorkerAt &&
|
|
216
|
+
run.lastSubstantiveWorkerAt > run.verifier.lastResult.checkedAt);
|
|
186
217
|
}
|
|
187
218
|
function needsMainIntegrationApplyTask(run) {
|
|
188
|
-
return (
|
|
219
|
+
return (pendingWorktreeIntegrationTasks(run).length > 0 &&
|
|
189
220
|
!hasApplyIntegrationTask(run) &&
|
|
190
|
-
!
|
|
191
|
-
}
|
|
192
|
-
function needsIntegratedGoalChangesCommitTask(run) {
|
|
193
|
-
return (hasIntegratedWorktreeChanges(run) &&
|
|
194
|
-
appliedIntegrationEvidence(run) &&
|
|
195
|
-
run.verifier?.lastResult?.status === "pass" &&
|
|
196
|
-
!latestNonAuditWorkerEvidenceAfterVerifier(run) &&
|
|
197
|
-
!hasCommitIntegratedChangesTask(run) &&
|
|
198
|
-
!committedIntegrationEvidence(run));
|
|
221
|
+
!integrationApplied(run));
|
|
199
222
|
}
|
|
200
223
|
function shouldCreateFinalAuditTask(run, limit = DEFAULT_GOAL_COMPLETION_AUDIT_LIMIT) {
|
|
201
224
|
return finalAuditTaskCount(run) < limit;
|
|
202
225
|
}
|
|
203
|
-
function isFinalAuditWorkerEvidence(run, label) {
|
|
204
|
-
const match = /^Worker\s+(\S+)\s+/.exec(label);
|
|
205
|
-
const workerId = match?.[1];
|
|
206
|
-
if (!workerId)
|
|
207
|
-
return false;
|
|
208
|
-
return run.tasks.some((task) => task.title === FINAL_COMPLETION_AUDIT_TASK_TITLE && task.workerId === workerId);
|
|
209
|
-
}
|
|
210
|
-
function isCompletionAuditDecision(label) {
|
|
211
|
-
return label === "Goal decision: completion_audit";
|
|
212
|
-
}
|
|
213
|
-
function latestMatchingEvidence(evidence, predicate) {
|
|
214
|
-
return evidence.filter(predicate).sort((a, b) => b.createdAt.localeCompare(a.createdAt))[0];
|
|
215
|
-
}
|
|
216
|
-
function latestNonAuditWorkerEvidenceAfterVerifier(run) {
|
|
217
|
-
const verifierCheckedAt = run.verifier?.lastResult?.checkedAt;
|
|
218
|
-
if (!verifierCheckedAt)
|
|
219
|
-
return undefined;
|
|
220
|
-
return latestMatchingEvidence(run.evidence, (item) => item.createdAt > verifierCheckedAt &&
|
|
221
|
-
item.label.startsWith("Worker ") &&
|
|
222
|
-
!isFinalAuditWorkerEvidence(run, item.label));
|
|
223
|
-
}
|
|
224
|
-
function latestCompletionRelevantEvidenceAfterVerifier(run) {
|
|
225
|
-
const verifierCheckedAt = run.verifier?.lastResult?.checkedAt;
|
|
226
|
-
if (!verifierCheckedAt)
|
|
227
|
-
return undefined;
|
|
228
|
-
return latestMatchingEvidence(run.evidence, (item) => {
|
|
229
|
-
if (item.createdAt <= verifierCheckedAt)
|
|
230
|
-
return false;
|
|
231
|
-
if (isFinalAuditWorkerEvidence(run, item.label))
|
|
232
|
-
return false;
|
|
233
|
-
if (isCompletionAuditDecision(item.label))
|
|
234
|
-
return false;
|
|
235
|
-
if (item.label === "Verifier result" || item.label.startsWith("Verifier "))
|
|
236
|
-
return false;
|
|
237
|
-
return item.label.startsWith("Worker ") || item.label.startsWith("Goal decision:");
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
226
|
export function hasFreshGoalCompletionAudit(run) {
|
|
241
227
|
const verifierResult = run.verifier?.lastResult;
|
|
242
228
|
if (!verifierResult || verifierResult.status !== "pass") {
|
|
243
229
|
return { ok: false, reason: "Goal has no passing verifier result to audit." };
|
|
244
230
|
}
|
|
245
|
-
|
|
246
|
-
if (postVerifierWorkerEvidence) {
|
|
231
|
+
if (verifierStaleAfterWorker(run)) {
|
|
247
232
|
return {
|
|
248
233
|
ok: false,
|
|
249
|
-
reason:
|
|
234
|
+
reason: "Latest verifier result is stale after a later substantive Goal worker completion.",
|
|
250
235
|
};
|
|
251
236
|
}
|
|
252
237
|
const audit = run.completionAudit;
|
|
@@ -256,19 +241,7 @@ export function hasFreshGoalCompletionAudit(run) {
|
|
|
256
241
|
if (audit.status !== "pass") {
|
|
257
242
|
return { ok: false, reason: `Final completion audit status is ${audit.status}.` };
|
|
258
243
|
}
|
|
259
|
-
if (!audit.
|
|
260
|
-
return {
|
|
261
|
-
ok: false,
|
|
262
|
-
reason: "Final completion audit pass summary must start with FINAL_AUDIT_PASS.",
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
if (!audit.summary.includes(`verifier_checked_at=${verifierResult.checkedAt}`)) {
|
|
266
|
-
return {
|
|
267
|
-
ok: false,
|
|
268
|
-
reason: "Final completion audit pass summary must include latest verifier_checked_at.",
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
if (!audit.outputPath && !audit.summary.match(/(?:output|artifact|log|path)=\S+/)) {
|
|
244
|
+
if (!audit.outputPath) {
|
|
272
245
|
return {
|
|
273
246
|
ok: false,
|
|
274
247
|
reason: "Final completion audit pass must reference verifier output or artifacts.",
|
|
@@ -286,13 +259,6 @@ export function hasFreshGoalCompletionAudit(run) {
|
|
|
286
259
|
reason: "Final completion audit is older than the latest verifier result.",
|
|
287
260
|
};
|
|
288
261
|
}
|
|
289
|
-
const newerEvidence = latestCompletionRelevantEvidenceAfterVerifier(run);
|
|
290
|
-
if (newerEvidence && newerEvidence.createdAt > audit.checkedAt) {
|
|
291
|
-
return {
|
|
292
|
-
ok: false,
|
|
293
|
-
reason: `Final completion audit is stale after later Goal evidence: ${newerEvidence.label}.`,
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
262
|
return { ok: true, reason: "Final completion audit passed after latest verifier evidence." };
|
|
297
263
|
}
|
|
298
264
|
function buildEvidencePlanTaskPrompt(run) {
|
|
@@ -311,21 +277,14 @@ function buildVerifierTaskPrompt(run) {
|
|
|
311
277
|
`Define and build a real end-to-end verifier for this Goal. Begin from the intended experience and required senses/signals already implied by the success criteria and evidence plan, including mandatory Goal references. Choose a proportional local/free verifier that observes those signals and catches the important goal-specific failures; do not add generic simulations, screenshots, benchmarks, or scripts unless they directly support that proof. Update the Goal with a verifier_command, verifier_description, and verifier_cwd when the command must run from an isolated worker worktree. The verifier must be runnable locally/free and produce durable command or file evidence, not narrative or human visual inspection. If an external prerequisite is missing, mark it missing with exact user instructions.`);
|
|
312
278
|
}
|
|
313
279
|
function buildApplyIntegrationToMainTaskPrompt(run) {
|
|
314
|
-
const integrationTasks =
|
|
280
|
+
const integrationTasks = pendingWorktreeIntegrationTasks(run)
|
|
315
281
|
.map((task) => `- ${task.id} / ${task.title}: worktree=${task.worktree?.path ?? "unknown"}; branch=${task.worktree?.branchName ?? "unknown"}; base=${task.worktree?.baseRef ?? "unknown"}; summary=${task.lastSummary?.slice(0, 600) ?? "none"}`)
|
|
316
282
|
.join("\n");
|
|
317
283
|
return (`Goal: ${run.goal}\n\n` +
|
|
318
284
|
referencePromptSection(run.references) +
|
|
319
|
-
`Apply accepted integration worktree changes into the user's main checkout before any release, verifier, final audit,
|
|
320
|
-
`Integrated
|
|
321
|
-
`For each integrated worktree, inspect its candidate packet, patch, diffstat, changed files, base SHA, verification logs, and risk notes. Apply or port only accepted changes to the main checkout; reject stale/risky/unrelated artifacts with durable evidence. Preserve user work. Run targeted checks in the main checkout after applying. Record durable evidence with label "Integrated worktree applied to main" containing the source worktree(s), accepted/rejected artifacts, changed files, diffstat, commands/results, and restart-needed note.
|
|
322
|
-
}
|
|
323
|
-
function buildCommitIntegratedGoalChangesTaskPrompt(run) {
|
|
324
|
-
return (`Goal: ${run.goal}\n\n` +
|
|
325
|
-
referencePromptSection(run.references) +
|
|
326
|
-
`Commit verified integrated Goal changes in the user's main checkout before final audit or completion. This task intentionally runs in the main checkout, not a new isolated worktree.\n\n` +
|
|
327
|
-
`Before committing, inspect git status and recent durable evidence to confirm accepted worktree changes were applied to main and main-checkout verification passed. Preserve user work: commit only files that belong to this Goal's accepted integrated changes, and do not stage unrelated user edits. If unrelated dirty files exist, block with exact paths and instructions instead of committing them.\n\n` +
|
|
328
|
-
`Run a targeted pre-commit check appropriate to the changed files if no fresh main-checkout verification evidence exists. Create one git commit with a concise message describing the Goal changes. Record durable evidence with label "Integrated Goal changes committed" containing the commit hash, staged/committed files, verification command/result used for confidence, and any restart-needed note. Do not mark the whole Goal complete.`);
|
|
285
|
+
`Apply accepted integration worktree changes into the user's main checkout before any release, verifier, final audit, or completion. This task intentionally runs in the main checkout, not a new isolated worktree.\n\n` +
|
|
286
|
+
`Integrated candidate worker outputs to apply:\n${integrationTasks || "- none recorded"}\n\n` +
|
|
287
|
+
`For each integrated worktree, inspect its candidate packet, patch, diffstat, changed files, base SHA, verification logs, and risk notes. Apply or port only accepted changes to the main checkout; reject stale/risky/unrelated artifacts with durable evidence. Preserve user work. Run targeted checks in the main checkout after applying. Record durable evidence with label "Integrated worktree applied to main" containing the source worktree(s), accepted/rejected artifacts, changed files, diffstat, commands/results, and restart-needed note. The orchestrator will deterministically commit/confirm accepted changes after this worker exits. Do not mark the whole Goal complete.`);
|
|
329
288
|
}
|
|
330
289
|
function incompleteTasks(run) {
|
|
331
290
|
return run.tasks.filter((task) => task.status !== "done");
|
|
@@ -425,7 +384,7 @@ export function canCompleteGoalRun(run) {
|
|
|
425
384
|
const requiredEvidence = hasRequiredGoalEvidence(run);
|
|
426
385
|
if (!requiredEvidence.ok)
|
|
427
386
|
return requiredEvidence;
|
|
428
|
-
if (hasIntegratedWorktreeChanges(run) && !
|
|
387
|
+
if (hasIntegratedWorktreeChanges(run) && !integrationCommitted(run)) {
|
|
429
388
|
return {
|
|
430
389
|
ok: false,
|
|
431
390
|
reason: "Integrated Goal changes have not been committed in the main checkout.",
|
|
@@ -481,7 +440,7 @@ function buildFinalCompletionAuditTaskPrompt(run) {
|
|
|
481
440
|
`Latest verifier: status=${verifier?.status ?? "unknown"}; checkedAt=${verifier?.checkedAt ?? "unknown"}; command=${verifier?.command ?? run.verifier?.command ?? "not recorded"}; output=${verifier?.outputPath ?? "not recorded"}; summary=${verifier?.summary ?? "not recorded"}\n\n` +
|
|
482
441
|
`Evidence plan:\n${evidencePlanItems || "- none"}\n\n` +
|
|
483
442
|
`Recent durable evidence:\n${recentEvidence || "- none"}\n\n` +
|
|
484
|
-
`Read the referenced report/log/source artifacts and compare them with the latest verifier result. The coordinator schedules and records decisions/state; the verifier path/UI/controller executes the configured verifier command as the final pre-audit gate and records goals verify evidence; this final audit records goals audit only after comparing the latest verifier output and references, including [original-goal-prompt] and durable GOAL_PLAN evidence. If an evidence-plan item is still planned but already matched by durable verifier/source/file evidence, update that evidence_plan item to status=ready with a concise evidence summary before recording the audit; if proof is missing, create a new pending Goal task with exact fix instructions and do not pass the audit. If everything matches, record a passing completion audit with the goals tool
|
|
443
|
+
`Read the referenced report/log/source artifacts and compare them with the latest verifier result. The coordinator schedules and records decisions/state; the verifier path/UI/controller executes the configured verifier command as the final pre-audit gate and records goals verify evidence; this final audit records goals audit only after comparing the latest verifier output and references, including [original-goal-prompt] and durable GOAL_PLAN evidence. If an evidence-plan item is still planned but already matched by durable verifier/source/file evidence, update that evidence_plan item to status=ready with a concise evidence summary before recording the audit; if proof is missing, create a new pending Goal task with exact fix instructions and do not pass the audit. If everything matches, record a passing completion audit with the goals tool using action=audit and verification_status=pass: write a plain-prose summary of which durable artifacts you compared and reference any mandatory non-prompt Goal references (and, when this Goal uses GOAL_PLAN planning, mention original-goal-prompt and GOAL_PLAN). The system auto-stamps FINAL_AUDIT_PASS and verifier_checked_at and fills output_path from the recorded verifier run, so do not transcribe the timestamp; any remaining contract gaps are returned all at once. If anything is missing, stale, contradictory, or unverified, create a new pending Goal task with exact instructions to fix it, record evidence describing the mismatch, and leave the audit failing or absent so the coordinator resumes a worker until fixed.`);
|
|
485
444
|
}
|
|
486
445
|
function buildVerifierFailureTaskPrompt(run) {
|
|
487
446
|
const result = run.verifier?.lastResult;
|
|
@@ -501,11 +460,137 @@ function buildVerifierFailureTaskPrompt(run) {
|
|
|
501
460
|
`Prior verifier summaries:\n${priorSummaries}\n\n` +
|
|
502
461
|
`Run targeted diagnostics, fix the root cause, update durable Goal evidence with the goals tool, and rerun the exact verifier command. Do not mark the Goal complete.`);
|
|
503
462
|
}
|
|
463
|
+
function buildResolveLocalPrerequisitesTaskPrompt(run) {
|
|
464
|
+
const items = unmetLocalGoalPrerequisites(run)
|
|
465
|
+
.map((item) => `- ${item.label} (${item.status})${item.checkCommand ? `; check: ${item.checkCommand}` : ""}${item.instructions ? `; instructions: ${item.instructions}` : ""}`)
|
|
466
|
+
.join("\n");
|
|
467
|
+
return (`Goal: ${run.goal}\n\n` +
|
|
468
|
+
referencePromptSection(run.references) +
|
|
469
|
+
`Resolve the following local Goal prerequisites so the Goal can proceed unattended. These are not user-supplied external inputs; satisfy each one locally with free tools.\n\n` +
|
|
470
|
+
`${items || "- none recorded"}\n\n` +
|
|
471
|
+
`For each prerequisite, make its check pass locally (install/configure/build as needed using local/free tooling), then record durable evidence and update the prerequisite to status=met with the goals tool (action="prerequisite"). If a prerequisite turns out to genuinely require user-supplied external input, mark it kind=external with exact user instructions instead of guessing.`);
|
|
472
|
+
}
|
|
473
|
+
function isReStrategizeTask(task) {
|
|
474
|
+
return task.title.startsWith(RE_STRATEGIZE_GOAL_TASK_TITLE);
|
|
475
|
+
}
|
|
476
|
+
export function goalStrategyTaskCount(run) {
|
|
477
|
+
return run.tasks.filter(isReStrategizeTask).length;
|
|
478
|
+
}
|
|
479
|
+
function workerEvidenceContentsForTask(run, task) {
|
|
480
|
+
if (!task.workerId)
|
|
481
|
+
return [];
|
|
482
|
+
return run.evidence
|
|
483
|
+
.filter((item) => {
|
|
484
|
+
const match = /^Worker\s+(\S+)\s+/.exec(item.label);
|
|
485
|
+
return match?.[1] === task.workerId;
|
|
486
|
+
})
|
|
487
|
+
.map((item) => (item.content ?? "").trim())
|
|
488
|
+
.filter(Boolean);
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* No-progress signal for an implementation task: the latest two worker evidence
|
|
492
|
+
* contents for the task's worker are identical, so re-running the same approach
|
|
493
|
+
* is unlikely to make progress.
|
|
494
|
+
*/
|
|
495
|
+
export function taskFailureRepeatedWithoutProgress(run, task) {
|
|
496
|
+
const contents = workerEvidenceContentsForTask(run, task);
|
|
497
|
+
if (contents.length < 2)
|
|
498
|
+
return false;
|
|
499
|
+
return contents[contents.length - 1] === contents[contents.length - 2];
|
|
500
|
+
}
|
|
501
|
+
function buildReStrategizeTaskPrompt(run, focus) {
|
|
502
|
+
const priorContents = focus
|
|
503
|
+
? workerEvidenceContentsForTask(run, focus)
|
|
504
|
+
: run.evidence
|
|
505
|
+
.filter((item) => item.label.startsWith("Verifier"))
|
|
506
|
+
.map((item) => (item.content ?? "").trim())
|
|
507
|
+
.filter(Boolean);
|
|
508
|
+
const priorSummaries = priorContents
|
|
509
|
+
.slice(-3)
|
|
510
|
+
.map((content) => `- ${content.slice(0, 500)}`)
|
|
511
|
+
.join("\n");
|
|
512
|
+
const what = focus ? `task "${focus.title}" (${focus.id})` : "the configured verifier";
|
|
513
|
+
return (`Original objective: ${run.goal}\n\n` +
|
|
514
|
+
referencePromptSection(run.references) +
|
|
515
|
+
`Prior attempts at ${what} repeatedly failed without progress.\n\n` +
|
|
516
|
+
`Prior attempt summaries:\n${priorSummaries || "- none recorded"}\n\n` +
|
|
517
|
+
`Analyze why the prior attempts failed, then take a fundamentally different approach to accomplish the original objective. Do not repeat the same strategy. Use local/free tools, record durable evidence with the goals tool, and update task status.${focus ? ` When you accomplish the objective, also mark the original failing task ${focus.id} done with the goals tool so the Goal can proceed.` : ""} If the objective genuinely requires user-supplied external input, record it as an external prerequisite with exact instructions.`);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Bounded re-strategy escalation: run an existing recoverable re-strategy task,
|
|
521
|
+
* else create one (up to the strategy limit), else terminate the run in
|
|
522
|
+
* `failed` with a structured diagnosis brief. Replaces the former pause/block
|
|
523
|
+
* dead-ends so the loop always either changes state or resolves.
|
|
524
|
+
*/
|
|
525
|
+
function reStrategizeOrFailDecision(run, options, context) {
|
|
526
|
+
const attemptLimit = options.taskAttemptLimit ?? DEFAULT_GOAL_TASK_ATTEMPT_LIMIT;
|
|
527
|
+
// Run an existing recoverable re-strategy task, but only while it still has
|
|
528
|
+
// attempt budget left, so a perpetually-failing strategy task cannot loop.
|
|
529
|
+
const recoverableStrategy = run.tasks.find((item) => isReStrategizeTask(item) && recoverableTask(item) && item.attempts < attemptLimit);
|
|
530
|
+
if (recoverableStrategy) {
|
|
531
|
+
return {
|
|
532
|
+
kind: "start_worker",
|
|
533
|
+
task: recoverableStrategy,
|
|
534
|
+
attempts: recoverableStrategy.attempts + 1,
|
|
535
|
+
reason: context.startReason,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
const strategyLimit = options.strategyLimit ?? DEFAULT_GOAL_STRATEGY_LIMIT;
|
|
539
|
+
const strategyCount = goalStrategyTaskCount(run);
|
|
540
|
+
if (strategyCount < strategyLimit) {
|
|
541
|
+
// Distinct titles per attempt so the orchestrator creates a fresh task
|
|
542
|
+
// instead of reusing an exhausted same-title one.
|
|
543
|
+
const title = strategyCount === 0
|
|
544
|
+
? RE_STRATEGIZE_GOAL_TASK_TITLE
|
|
545
|
+
: `${RE_STRATEGIZE_GOAL_TASK_TITLE} (${strategyCount + 1})`;
|
|
546
|
+
return {
|
|
547
|
+
kind: "create_task",
|
|
548
|
+
title,
|
|
549
|
+
prompt: buildReStrategizeTaskPrompt(run, context.focus),
|
|
550
|
+
reason: `${context.startReason} (${strategyCount + 1}/${strategyLimit})`,
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
return {
|
|
554
|
+
kind: "terminal",
|
|
555
|
+
status: "failed",
|
|
556
|
+
reason: buildGoalFailureDiagnosis(run, context.failReason),
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Structured diagnosis brief recorded when a Goal terminates in `failed` so the
|
|
561
|
+
* run ends resolved (not spinning, not silently paused) with an honest verdict.
|
|
562
|
+
*/
|
|
563
|
+
export function buildGoalFailureDiagnosis(run, reason) {
|
|
564
|
+
const attempts = run.tasks
|
|
565
|
+
.map((task) => `- ${task.title} (${task.id}): status=${task.status}; attempts=${task.attempts}${task.lastSummary ? `; last=${task.lastSummary.slice(0, 240)}` : ""}`)
|
|
566
|
+
.join("\n");
|
|
567
|
+
const failureSignatures = Array.from(new Set(run.evidence
|
|
568
|
+
.filter((item) => item.label === "Verifier fail" || item.label === "Verifier result")
|
|
569
|
+
.map((item) => (item.content ?? "").trim())
|
|
570
|
+
.filter(Boolean)))
|
|
571
|
+
.slice(-5)
|
|
572
|
+
.map((signature) => `- ${signature.slice(0, 240)}`)
|
|
573
|
+
.join("\n");
|
|
574
|
+
const verifier = run.verifier?.lastResult;
|
|
575
|
+
const externalNeeds = run.prerequisites
|
|
576
|
+
.filter((item) => (item.status !== "met" || !item.evidence?.trim()) && item.kind === "external")
|
|
577
|
+
.map((item) => `- ${item.label}: ${item.instructions ?? "user-supplied input required"}`)
|
|
578
|
+
.join("\n");
|
|
579
|
+
return [
|
|
580
|
+
"GOAL_FAILURE_DIAGNOSIS",
|
|
581
|
+
`objective=${run.goal}`,
|
|
582
|
+
`reason=${reason}`,
|
|
583
|
+
`tasks:\n${attempts || "- none"}`,
|
|
584
|
+
`distinct_failure_signatures:\n${failureSignatures || "- none"}`,
|
|
585
|
+
`latest_verifier=${verifier ? `${verifier.status} (exit ${verifier.exitCode ?? "unknown"}): ${verifier.summary?.slice(0, 240) ?? ""}` : "none"}`,
|
|
586
|
+
`human_decision_needed:\n${externalNeeds || "- none"}`,
|
|
587
|
+
].join("\n");
|
|
588
|
+
}
|
|
504
589
|
export function formatGoalControllerDecision(decision) {
|
|
505
590
|
const parts = [`kind=${decision.kind}`];
|
|
506
591
|
if ("reason" in decision)
|
|
507
592
|
parts.push(`reason=${decision.reason}`);
|
|
508
|
-
if (decision.kind === "start_worker"
|
|
593
|
+
if (decision.kind === "start_worker") {
|
|
509
594
|
parts.push(`task=${decision.task.id}`, `title=${decision.task.title}`, `attempts=${decision.attempts}`);
|
|
510
595
|
if (decision.task.workerId)
|
|
511
596
|
parts.push(`worker=${decision.task.workerId}`);
|
|
@@ -516,8 +601,8 @@ export function formatGoalControllerDecision(decision) {
|
|
|
516
601
|
if (decision.task.expectedChangedScope?.length) {
|
|
517
602
|
parts.push(`expected_changed_scope=${decision.task.expectedChangedScope.join(",")}`);
|
|
518
603
|
}
|
|
519
|
-
if (decision.task.
|
|
520
|
-
parts.push(`
|
|
604
|
+
if (decision.task.integration)
|
|
605
|
+
parts.push(`integration=${decision.task.integration}`);
|
|
521
606
|
}
|
|
522
607
|
if (decision.kind === "wait" && decision.workerId)
|
|
523
608
|
parts.push(`worker=${decision.workerId}`);
|
|
@@ -541,6 +626,17 @@ export function decideGoalNextAction(run, options = {}) {
|
|
|
541
626
|
}
|
|
542
627
|
return { kind: "complete", reason: completion.reason };
|
|
543
628
|
}
|
|
629
|
+
// Hard termination guarantee: if a run somehow keeps making decisions without
|
|
630
|
+
// completing or hitting a narrower limit, fail with a diagnosis rather than
|
|
631
|
+
// loop forever.
|
|
632
|
+
const decisionLimit = options.decisionLimit ?? DEFAULT_GOAL_DECISION_LIMIT;
|
|
633
|
+
if (goalDecisionCount(run) > decisionLimit) {
|
|
634
|
+
return {
|
|
635
|
+
kind: "terminal",
|
|
636
|
+
status: "failed",
|
|
637
|
+
reason: buildGoalFailureDiagnosis(run, `Goal exceeded the maximum of ${decisionLimit} controller decisions without completing; stopping to avoid an unbounded loop.`),
|
|
638
|
+
};
|
|
639
|
+
}
|
|
544
640
|
if (goalHasBlockingPrerequisites(run)) {
|
|
545
641
|
return { kind: "blocked", reason: formatGoalBlockingPrerequisites(run) };
|
|
546
642
|
}
|
|
@@ -565,17 +661,38 @@ export function decideGoalNextAction(run, options = {}) {
|
|
|
565
661
|
...(runningTask.workerId ? { workerId: runningTask.workerId } : {}),
|
|
566
662
|
};
|
|
567
663
|
}
|
|
664
|
+
if (goalHasUnmetLocalPrerequisites(run)) {
|
|
665
|
+
const duplicateDecision = duplicateAutoTaskDecision(run, RESOLVE_LOCAL_PREREQUISITES_TASK_TITLE, "Local Goal prerequisites must be satisfied locally before implementation.");
|
|
666
|
+
if (duplicateDecision)
|
|
667
|
+
return duplicateDecision;
|
|
668
|
+
return {
|
|
669
|
+
kind: "create_task",
|
|
670
|
+
title: RESOLVE_LOCAL_PREREQUISITES_TASK_TITLE,
|
|
671
|
+
prompt: buildResolveLocalPrerequisitesTaskPrompt(run),
|
|
672
|
+
reason: `Resolving ${unmetLocalGoalPrerequisites(run).length} local Goal prerequisite(s) locally instead of blocking.`,
|
|
673
|
+
};
|
|
674
|
+
}
|
|
568
675
|
const task = nextRunnableTask(run);
|
|
569
676
|
if (task) {
|
|
570
677
|
const attempts = task.attempts + 1;
|
|
571
678
|
const limit = options.taskAttemptLimit ?? DEFAULT_GOAL_TASK_ATTEMPT_LIMIT;
|
|
572
679
|
if (attempts > limit) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
680
|
+
// Past the soft attempt limit: keep retrying while the failure signature
|
|
681
|
+
// keeps changing (still making progress); on a no-progress repeat,
|
|
682
|
+
// re-strategize a bounded number of times, then fail with a diagnosis.
|
|
683
|
+
if (!isReStrategizeTask(task) && !taskFailureRepeatedWithoutProgress(run, task)) {
|
|
684
|
+
return {
|
|
685
|
+
kind: "start_worker",
|
|
686
|
+
task,
|
|
687
|
+
attempts,
|
|
688
|
+
reason: `Goal task "${task.title}" passed the soft attempt limit but is still making progress; continuing attempt ${attempts}.`,
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
return reStrategizeOrFailDecision(run, options, {
|
|
692
|
+
focus: task,
|
|
693
|
+
startReason: `Re-strategizing "${task.title}" with a fundamentally different approach.`,
|
|
694
|
+
failReason: `Task "${task.title}" could not be completed after ${task.attempts} attempt(s) and the bounded re-strategy limit.`,
|
|
695
|
+
});
|
|
579
696
|
}
|
|
580
697
|
return {
|
|
581
698
|
kind: "start_worker",
|
|
@@ -589,8 +706,9 @@ export function decideGoalNextAction(run, options = {}) {
|
|
|
589
706
|
const missingDependencies = dependencyBlockedTask.dependencies.filter((dependencyId) => !run.tasks.some((item) => taskMatchesDependency(item, dependencyId)));
|
|
590
707
|
if (missingDependencies.length > 0) {
|
|
591
708
|
return {
|
|
592
|
-
kind: "
|
|
593
|
-
|
|
709
|
+
kind: "terminal",
|
|
710
|
+
status: "failed",
|
|
711
|
+
reason: buildGoalFailureDiagnosis(run, `Goal task "${dependencyBlockedTask.task.title}" depends on missing task(s) that cannot be synthesized: ${missingDependencies.join(", ")}.`),
|
|
594
712
|
};
|
|
595
713
|
}
|
|
596
714
|
return {
|
|
@@ -610,16 +728,8 @@ export function decideGoalNextAction(run, options = {}) {
|
|
|
610
728
|
reason: "Accepted integration worktree changes must be applied to the user's main checkout before verifier, final audit, release, commit, or completion.",
|
|
611
729
|
};
|
|
612
730
|
}
|
|
613
|
-
if (needsIntegratedGoalChangesCommitTask(run)) {
|
|
614
|
-
return {
|
|
615
|
-
kind: "create_task",
|
|
616
|
-
title: COMMIT_INTEGRATED_GOAL_CHANGES_TASK_TITLE,
|
|
617
|
-
prompt: buildCommitIntegratedGoalChangesTaskPrompt(run),
|
|
618
|
-
reason: "Verified integrated Goal changes must be committed in the user's main checkout before final audit or completion.",
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
731
|
if (run.verifier?.lastResult?.status === "pass" &&
|
|
622
|
-
|
|
732
|
+
verifierStaleAfterWorker(run) &&
|
|
623
733
|
run.verifier?.command) {
|
|
624
734
|
return {
|
|
625
735
|
kind: "run_verifier",
|
|
@@ -638,8 +748,9 @@ export function decideGoalNextAction(run, options = {}) {
|
|
|
638
748
|
};
|
|
639
749
|
}
|
|
640
750
|
return {
|
|
641
|
-
kind: "
|
|
642
|
-
|
|
751
|
+
kind: "terminal",
|
|
752
|
+
status: "failed",
|
|
753
|
+
reason: buildGoalFailureDiagnosis(run, "Verifier passed, but the final completion audit could not reconcile the Goal evidence plan after bounded attempts."),
|
|
643
754
|
};
|
|
644
755
|
}
|
|
645
756
|
const duplicateDecision = duplicateAutoTaskDecision(run, BUILD_GOAL_EVIDENCE_PATH_TASK_TITLE, "Goal evidence plan still requires local instrumentation or exact prerequisite handling before verification.");
|
|
@@ -665,18 +776,18 @@ export function decideGoalNextAction(run, options = {}) {
|
|
|
665
776
|
}
|
|
666
777
|
if (run.verifier?.lastResult?.status === "fail") {
|
|
667
778
|
if (hasRepeatedVerifierFailure(run)) {
|
|
668
|
-
return {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
};
|
|
779
|
+
return reStrategizeOrFailDecision(run, options, {
|
|
780
|
+
startReason: "Verifier produced the same failure repeatedly; re-strategizing with a fundamentally different approach.",
|
|
781
|
+
failReason: "Verifier produced the same failure repeatedly and bounded re-strategy attempts were exhausted.",
|
|
782
|
+
});
|
|
672
783
|
}
|
|
673
784
|
const limit = options.verifierFixLimit ?? DEFAULT_GOAL_VERIFIER_FIX_LIMIT;
|
|
674
785
|
const blockedFixTask = existingBlockedTaskWithTitle(run, FIX_VERIFIER_FAILURE_TASK_TITLE);
|
|
675
786
|
if (blockedFixTask) {
|
|
676
|
-
return {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
};
|
|
787
|
+
return reStrategizeOrFailDecision(run, options, {
|
|
788
|
+
startReason: "A blocked verifier-fix task exists; re-strategizing the verifier fix with a different approach.",
|
|
789
|
+
failReason: "A verifier-fix task was blocked and bounded re-strategy attempts were exhausted.",
|
|
790
|
+
});
|
|
680
791
|
}
|
|
681
792
|
if (shouldCreateVerifierFixTask(run, limit)) {
|
|
682
793
|
return {
|
|
@@ -687,16 +798,9 @@ export function decideGoalNextAction(run, options = {}) {
|
|
|
687
798
|
};
|
|
688
799
|
}
|
|
689
800
|
return {
|
|
690
|
-
kind: "
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
title: FIX_VERIFIER_FAILURE_TASK_TITLE,
|
|
694
|
-
prompt: "Verifier fix attempt limit reached.",
|
|
695
|
-
status: "blocked",
|
|
696
|
-
attempts: limit,
|
|
697
|
-
},
|
|
698
|
-
attempts: limit,
|
|
699
|
-
reason: `Verifier fix task limit reached (${limit}).`,
|
|
801
|
+
kind: "terminal",
|
|
802
|
+
status: "failed",
|
|
803
|
+
reason: buildGoalFailureDiagnosis(run, `Verifier failed and the bounded verifier-fix limit (${limit}) was reached without a pass.`),
|
|
700
804
|
};
|
|
701
805
|
}
|
|
702
806
|
if (run.verifier?.lastResult?.status === "pass") {
|
|
@@ -709,8 +813,9 @@ export function decideGoalNextAction(run, options = {}) {
|
|
|
709
813
|
};
|
|
710
814
|
}
|
|
711
815
|
return {
|
|
712
|
-
kind: "
|
|
713
|
-
|
|
816
|
+
kind: "terminal",
|
|
817
|
+
status: "failed",
|
|
818
|
+
reason: buildGoalFailureDiagnosis(run, "Verifier passed, but the final completion audit did not pass after bounded attempts."),
|
|
714
819
|
};
|
|
715
820
|
}
|
|
716
821
|
if (run.verifier?.command) {
|