@kenkaiiii/ggcoder 4.3.205 → 4.3.207
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.js +38 -26
- package/dist/cli.js.map +1 -1
- package/dist/config.js +2 -2
- package/dist/core/compaction/compactor.d.ts.map +1 -1
- package/dist/core/compaction/compactor.js +6 -0
- package/dist/core/compaction/compactor.js.map +1 -1
- package/dist/core/compaction/compactor.test.js +16 -0
- package/dist/core/compaction/compactor.test.js.map +1 -1
- package/dist/core/goal-controller.d.ts +57 -0
- package/dist/core/goal-controller.d.ts.map +1 -0
- package/dist/core/goal-controller.js +285 -0
- package/dist/core/goal-controller.js.map +1 -0
- package/dist/core/goal-controller.test.d.ts +2 -0
- package/dist/core/goal-controller.test.d.ts.map +1 -0
- package/dist/core/goal-controller.test.js +419 -0
- package/dist/core/goal-controller.test.js.map +1 -0
- package/dist/core/goal-lifecycle-smoke.test.d.ts +2 -0
- package/dist/core/goal-lifecycle-smoke.test.d.ts.map +1 -0
- package/dist/core/goal-lifecycle-smoke.test.js +207 -0
- package/dist/core/goal-lifecycle-smoke.test.js.map +1 -0
- package/dist/core/goal-store.d.ts +164 -0
- package/dist/core/goal-store.d.ts.map +1 -0
- package/dist/core/goal-store.js +721 -0
- package/dist/core/goal-store.js.map +1 -0
- package/dist/core/goal-store.test.d.ts +2 -0
- package/dist/core/goal-store.test.d.ts.map +1 -0
- package/dist/core/goal-store.test.js +341 -0
- package/dist/core/goal-store.test.js.map +1 -0
- package/dist/core/goal-verifier.d.ts +17 -0
- package/dist/core/goal-verifier.d.ts.map +1 -0
- package/dist/core/goal-verifier.js +84 -0
- package/dist/core/goal-verifier.js.map +1 -0
- package/dist/core/goal-verifier.test.d.ts +2 -0
- package/dist/core/goal-verifier.test.d.ts.map +1 -0
- package/dist/core/goal-verifier.test.js +88 -0
- package/dist/core/goal-verifier.test.js.map +1 -0
- package/dist/core/goal-worker-dev-server-lifecycle.test.d.ts +2 -0
- package/dist/core/goal-worker-dev-server-lifecycle.test.d.ts.map +1 -0
- package/dist/core/goal-worker-dev-server-lifecycle.test.js +68 -0
- package/dist/core/goal-worker-dev-server-lifecycle.test.js.map +1 -0
- package/dist/core/goal-worker.d.ts +51 -0
- package/dist/core/goal-worker.d.ts.map +1 -0
- package/dist/core/goal-worker.js +339 -0
- package/dist/core/goal-worker.js.map +1 -0
- package/dist/core/goal-worker.test.d.ts +2 -0
- package/dist/core/goal-worker.test.d.ts.map +1 -0
- package/dist/core/goal-worker.test.js +224 -0
- package/dist/core/goal-worker.test.js.map +1 -0
- package/dist/core/model-registry.test.js +51 -1
- package/dist/core/model-registry.test.js.map +1 -1
- package/dist/core/oauth/gemini.d.ts.map +1 -1
- package/dist/core/oauth/gemini.js +138 -30
- package/dist/core/oauth/gemini.js.map +1 -1
- package/dist/core/oauth/gemini.test.d.ts +2 -0
- package/dist/core/oauth/gemini.test.d.ts.map +1 -0
- package/dist/core/oauth/gemini.test.js +154 -0
- package/dist/core/oauth/gemini.test.js.map +1 -0
- package/dist/core/process-manager-dev-server-repro.test.d.ts +2 -0
- package/dist/core/process-manager-dev-server-repro.test.d.ts.map +1 -0
- package/dist/core/process-manager-dev-server-repro.test.js +100 -0
- package/dist/core/process-manager-dev-server-repro.test.js.map +1 -0
- package/dist/core/process-manager.js +2 -2
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/prompt-commands.d.ts.map +1 -1
- package/dist/core/prompt-commands.js +125 -0
- package/dist/core/prompt-commands.js.map +1 -1
- package/dist/core/prompt-commands.test.js +38 -0
- package/dist/core/prompt-commands.test.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interactive.d.ts.map +1 -1
- package/dist/interactive.js +20 -11
- package/dist/interactive.js.map +1 -1
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +19 -50
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +124 -1
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/edit-diff.d.ts.map +1 -1
- package/dist/tools/edit-diff.js +71 -32
- package/dist/tools/edit-diff.js.map +1 -1
- package/dist/tools/edit-diff.test.js +14 -0
- package/dist/tools/edit-diff.test.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +38 -18
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/edit.test.js +56 -6
- package/dist/tools/edit.test.js.map +1 -1
- package/dist/tools/enter-plan.d.ts.map +1 -1
- package/dist/tools/enter-plan.js +1 -0
- package/dist/tools/enter-plan.js.map +1 -1
- package/dist/tools/goals.d.ts +110 -0
- package/dist/tools/goals.d.ts.map +1 -0
- package/dist/tools/goals.js +500 -0
- package/dist/tools/goals.js.map +1 -0
- package/dist/tools/goals.test.d.ts +2 -0
- package/dist/tools/goals.test.d.ts.map +1 -0
- package/dist/tools/goals.test.js +431 -0
- package/dist/tools/goals.test.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +2 -0
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/source-path.d.ts +9 -0
- package/dist/tools/source-path.d.ts.map +1 -0
- package/dist/tools/source-path.js +119 -0
- package/dist/tools/source-path.js.map +1 -0
- package/dist/tools/source-path.test.d.ts +2 -0
- package/dist/tools/source-path.test.d.ts.map +1 -0
- package/dist/tools/source-path.test.js +80 -0
- package/dist/tools/source-path.test.js.map +1 -0
- package/dist/tools/subagent.js +16 -0
- package/dist/tools/subagent.js.map +1 -1
- package/dist/ui/App.d.ts +73 -4
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +1068 -140
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/activity-phrases.d.ts.map +1 -1
- package/dist/ui/activity-phrases.js +7 -3
- package/dist/ui/activity-phrases.js.map +1 -1
- package/dist/ui/app-state-persistence.test.d.ts +2 -0
- package/dist/ui/app-state-persistence.test.d.ts.map +1 -0
- package/dist/ui/app-state-persistence.test.js +130 -0
- package/dist/ui/app-state-persistence.test.js.map +1 -0
- package/dist/ui/components/BackgroundTasksBar.d.ts +16 -1
- package/dist/ui/components/BackgroundTasksBar.d.ts.map +1 -1
- package/dist/ui/components/BackgroundTasksBar.js +15 -2
- package/dist/ui/components/BackgroundTasksBar.js.map +1 -1
- package/dist/ui/components/Banner.d.ts +2 -1
- package/dist/ui/components/Banner.d.ts.map +1 -1
- package/dist/ui/components/Banner.js +3 -3
- package/dist/ui/components/Banner.js.map +1 -1
- package/dist/ui/components/GoalOverlay.d.ts +74 -0
- package/dist/ui/components/GoalOverlay.d.ts.map +1 -0
- package/dist/ui/components/GoalOverlay.js +675 -0
- package/dist/ui/components/GoalOverlay.js.map +1 -0
- package/dist/ui/components/GoalStatusBar.d.ts +24 -0
- package/dist/ui/components/GoalStatusBar.d.ts.map +1 -0
- package/dist/ui/components/GoalStatusBar.js +113 -0
- package/dist/ui/components/GoalStatusBar.js.map +1 -0
- package/dist/ui/components/InputArea.d.ts +2 -1
- package/dist/ui/components/InputArea.d.ts.map +1 -1
- package/dist/ui/components/InputArea.js +44 -2
- package/dist/ui/components/InputArea.js.map +1 -1
- package/dist/ui/components/InputArea.test.d.ts +2 -0
- package/dist/ui/components/InputArea.test.d.ts.map +1 -0
- package/dist/ui/components/InputArea.test.js +79 -0
- package/dist/ui/components/InputArea.test.js.map +1 -0
- package/dist/ui/components/ToolExecution.d.ts.map +1 -1
- package/dist/ui/components/ToolExecution.js +96 -3
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/footer-status-layout.test.d.ts +2 -0
- package/dist/ui/footer-status-layout.test.d.ts.map +1 -0
- package/dist/ui/footer-status-layout.test.js +56 -0
- package/dist/ui/footer-status-layout.test.js.map +1 -0
- package/dist/ui/goal-events.d.ts +107 -0
- package/dist/ui/goal-events.d.ts.map +1 -0
- package/dist/ui/goal-events.js +323 -0
- package/dist/ui/goal-events.js.map +1 -0
- package/dist/ui/goal-events.test.d.ts +2 -0
- package/dist/ui/goal-events.test.d.ts.map +1 -0
- package/dist/ui/goal-events.test.js +293 -0
- package/dist/ui/goal-events.test.js.map +1 -0
- package/dist/ui/goal-overlay.test.d.ts +2 -0
- package/dist/ui/goal-overlay.test.d.ts.map +1 -0
- package/dist/ui/goal-overlay.test.js +276 -0
- package/dist/ui/goal-overlay.test.js.map +1 -0
- package/dist/ui/goal-status-bar.test.d.ts +2 -0
- package/dist/ui/goal-status-bar.test.d.ts.map +1 -0
- package/dist/ui/goal-status-bar.test.js +143 -0
- package/dist/ui/goal-status-bar.test.js.map +1 -0
- package/dist/ui/live-item-flush.test.js +48 -0
- package/dist/ui/live-item-flush.test.js.map +1 -1
- package/dist/ui/render.d.ts +11 -4
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +12 -3
- package/dist/ui/render.js.map +1 -1
- package/dist/ui/scroll-stabilization.test.d.ts +2 -0
- package/dist/ui/scroll-stabilization.test.d.ts.map +1 -0
- package/dist/ui/scroll-stabilization.test.js +70 -0
- package/dist/ui/scroll-stabilization.test.js.map +1 -0
- package/dist/ui/slash-command-images.test.d.ts +2 -0
- package/dist/ui/slash-command-images.test.d.ts.map +1 -0
- package/dist/ui/slash-command-images.test.js +47 -0
- package/dist/ui/slash-command-images.test.js.map +1 -0
- package/dist/utils/format.js +44 -0
- package/dist/utils/format.js.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { canCompleteGoalRun, decideGoalNextAction, formatGoalControllerDecision, shouldClearGoalContinuation, } from "./goal-controller.js";
|
|
3
|
+
function goalRun(overrides = {}) {
|
|
4
|
+
return {
|
|
5
|
+
id: "goal-a",
|
|
6
|
+
title: "Programmatic loop",
|
|
7
|
+
goal: "Make the loop deterministic",
|
|
8
|
+
status: "ready",
|
|
9
|
+
createdAt: "2024-01-01T00:00:00.000Z",
|
|
10
|
+
updatedAt: "2024-01-01T00:00:00.000Z",
|
|
11
|
+
projectPath: "/tmp/project",
|
|
12
|
+
successCriteria: ["Verifier passes"],
|
|
13
|
+
prerequisites: [],
|
|
14
|
+
harness: [],
|
|
15
|
+
evidencePlan: [],
|
|
16
|
+
tasks: [],
|
|
17
|
+
evidence: [],
|
|
18
|
+
blockers: [],
|
|
19
|
+
...overrides,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
describe("goal controller", () => {
|
|
23
|
+
it("starts the next pending worker task deterministically", () => {
|
|
24
|
+
const task = {
|
|
25
|
+
id: "task-a",
|
|
26
|
+
title: "Implement loop",
|
|
27
|
+
prompt: "Do work",
|
|
28
|
+
status: "pending",
|
|
29
|
+
attempts: 1,
|
|
30
|
+
};
|
|
31
|
+
expect(decideGoalNextAction(goalRun({ tasks: [task] }))).toEqual({
|
|
32
|
+
kind: "start_worker",
|
|
33
|
+
task,
|
|
34
|
+
attempts: 2,
|
|
35
|
+
reason: 'Goal task "Implement loop" is ready for worker attempt 2.',
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it("waits instead of starting duplicate work when a worker or task is active", () => {
|
|
39
|
+
expect(decideGoalNextAction(goalRun({ activeWorkerId: "worker-a" }))).toEqual({
|
|
40
|
+
kind: "wait",
|
|
41
|
+
reason: "Goal already has an active worker.",
|
|
42
|
+
workerId: "worker-a",
|
|
43
|
+
});
|
|
44
|
+
expect(decideGoalNextAction(goalRun({
|
|
45
|
+
tasks: [
|
|
46
|
+
{
|
|
47
|
+
id: "task-a",
|
|
48
|
+
title: "Running task",
|
|
49
|
+
prompt: "Do work",
|
|
50
|
+
status: "running",
|
|
51
|
+
workerId: "worker-a",
|
|
52
|
+
attempts: 1,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
}))).toMatchObject({ kind: "wait", workerId: "worker-a" });
|
|
56
|
+
});
|
|
57
|
+
it("treats closure evidence and ready evidence-plan items as satisfied after verifier pass", () => {
|
|
58
|
+
const run = goalRun({
|
|
59
|
+
evidencePlan: [
|
|
60
|
+
{
|
|
61
|
+
id: "ready-proof",
|
|
62
|
+
label: "Ready proof",
|
|
63
|
+
mechanism: "test",
|
|
64
|
+
description: "Ready proof was produced by the harness.",
|
|
65
|
+
status: "ready",
|
|
66
|
+
evidence: "Regression harness artifact was recorded.",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "closure-proof",
|
|
70
|
+
label: "Closure proof",
|
|
71
|
+
mechanism: "browser",
|
|
72
|
+
description: "Browser closure evidence proves the flow works.",
|
|
73
|
+
status: "planned",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "verifier-output-proof",
|
|
77
|
+
label: "Verifier output proof",
|
|
78
|
+
mechanism: "screenshot",
|
|
79
|
+
description: "Capture final verifier artifact.",
|
|
80
|
+
status: "planned",
|
|
81
|
+
path: "artifacts/final-verifier.log",
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
evidence: [
|
|
85
|
+
{
|
|
86
|
+
id: "evidence-closure-proof",
|
|
87
|
+
createdAt: "2024-01-01T00:00:00.000Z",
|
|
88
|
+
kind: "summary",
|
|
89
|
+
label: "Closure proof",
|
|
90
|
+
content: "Closure evidence recorded after the worker finished.",
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
verifier: {
|
|
94
|
+
description: "Full check",
|
|
95
|
+
command: "pnpm test",
|
|
96
|
+
lastResult: {
|
|
97
|
+
status: "pass",
|
|
98
|
+
summary: "Verifier passed and wrote final artifact.",
|
|
99
|
+
command: "pnpm test",
|
|
100
|
+
outputPath: "artifacts/final-verifier.log",
|
|
101
|
+
checkedAt: "2024-01-01T00:00:00.000Z",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
expect(canCompleteGoalRun(run)).toEqual({
|
|
106
|
+
ok: true,
|
|
107
|
+
reason: "All tasks are done and verifier evidence passed.",
|
|
108
|
+
});
|
|
109
|
+
expect(decideGoalNextAction(run)).toEqual({
|
|
110
|
+
kind: "complete",
|
|
111
|
+
reason: "All tasks are done and verifier evidence passed.",
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
it("blocks instead of spawning repeated evidence-path workers after verifier success", () => {
|
|
115
|
+
const decision = decideGoalNextAction(goalRun({
|
|
116
|
+
evidencePlan: [
|
|
117
|
+
{
|
|
118
|
+
id: "proof",
|
|
119
|
+
label: "Unmatched proof",
|
|
120
|
+
mechanism: "browser",
|
|
121
|
+
description: "Needs screenshot",
|
|
122
|
+
status: "planned",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
verifier: {
|
|
126
|
+
description: "Full check",
|
|
127
|
+
command: "pnpm test",
|
|
128
|
+
lastResult: {
|
|
129
|
+
status: "pass",
|
|
130
|
+
summary: "tests passed",
|
|
131
|
+
command: "pnpm test",
|
|
132
|
+
checkedAt: "2024-01-01T00:00:00.000Z",
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
}));
|
|
136
|
+
expect(decision).toEqual({
|
|
137
|
+
kind: "blocked",
|
|
138
|
+
reason: "Verifier passed, but the Goal evidence plan is still not satisfied; blocking instead of creating repeated evidence-path workers.",
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
it("runs the verifier only after all tasks are done", () => {
|
|
142
|
+
expect(decideGoalNextAction(goalRun({
|
|
143
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
144
|
+
verifier: { description: "Full check", command: "pnpm test" },
|
|
145
|
+
}))).toEqual({
|
|
146
|
+
kind: "run_verifier",
|
|
147
|
+
command: "pnpm test",
|
|
148
|
+
reason: "All Goal tasks are done; running configured verifier for real completion evidence.",
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
it("creates a verifier-building task when done tasks have no verifier command", () => {
|
|
152
|
+
expect(decideGoalNextAction(goalRun({
|
|
153
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
154
|
+
}))).toMatchObject({
|
|
155
|
+
kind: "create_task",
|
|
156
|
+
title: "Define Goal verifier",
|
|
157
|
+
reason: "No pending Goal task or verifier command is configured.",
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
it("creates a mobile/UI evidence-path task before verifier execution when proof is only planned", () => {
|
|
161
|
+
const decision = decideGoalNextAction(goalRun({
|
|
162
|
+
goal: "Make the mobile checkout screen render correctly on small viewports",
|
|
163
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
164
|
+
evidencePlan: [
|
|
165
|
+
{
|
|
166
|
+
id: "mobile-ui-proof",
|
|
167
|
+
label: "iOS simulator screenshot comparison",
|
|
168
|
+
mechanism: "screenshot",
|
|
169
|
+
description: "Capture the mobile checkout screen in a local simulator or browser viewport and compare the image/frame output.",
|
|
170
|
+
status: "planned",
|
|
171
|
+
path: "artifacts/mobile-checkout-diff.png",
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
verifier: { description: "Full check", command: "pnpm test:e2e" },
|
|
175
|
+
}));
|
|
176
|
+
expect(decision).toMatchObject({
|
|
177
|
+
kind: "create_task",
|
|
178
|
+
title: "Build Goal evidence path",
|
|
179
|
+
reason: "Goal evidence plan requires local instrumentation or exact prerequisite handling before verification.",
|
|
180
|
+
});
|
|
181
|
+
const prompt = decision.kind === "create_task" ? decision.prompt : "";
|
|
182
|
+
expect(prompt).toContain("iOS simulator screenshot comparison (screenshot)");
|
|
183
|
+
expect(prompt).toContain("what would prove this goal actually worked end-to-end");
|
|
184
|
+
expect(prompt).toContain("observable proof paths");
|
|
185
|
+
expect(prompt).toContain("not narrative-only verification or human visual inspection");
|
|
186
|
+
expect(prompt).toContain("dev servers");
|
|
187
|
+
expect(prompt).toContain("browser automation");
|
|
188
|
+
expect(prompt).toContain("logs");
|
|
189
|
+
expect(prompt).toContain("generated fixtures");
|
|
190
|
+
expect(prompt).toContain("source/docs/code-search comparison");
|
|
191
|
+
expect(prompt).toContain("iOS Simulator screenshots when available");
|
|
192
|
+
expect(prompt).toContain("image/frame checks");
|
|
193
|
+
});
|
|
194
|
+
it("blocks when an evidence plan item requires a true external prerequisite", () => {
|
|
195
|
+
expect(decideGoalNextAction(goalRun({
|
|
196
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
197
|
+
evidencePlan: [
|
|
198
|
+
{
|
|
199
|
+
id: "device-proof",
|
|
200
|
+
label: "Physical iPhone capture",
|
|
201
|
+
mechanism: "device",
|
|
202
|
+
description: "Run on a real phone.",
|
|
203
|
+
status: "blocked",
|
|
204
|
+
instructions: "Connect an unlocked iPhone with Developer Mode enabled.",
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
verifier: { description: "Full check", command: "pnpm test:e2e" },
|
|
208
|
+
}))).toEqual({
|
|
209
|
+
kind: "blocked",
|
|
210
|
+
reason: "Physical iPhone capture: Connect an unlocked iPhone with Developer Mode enabled.",
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
it("creates a harness-building task before verifier execution when instrumentation is missing", () => {
|
|
214
|
+
expect(decideGoalNextAction(goalRun({
|
|
215
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
216
|
+
harness: [{ id: "harness-a", label: "Browser fixture", description: "Create fixture" }],
|
|
217
|
+
verifier: { description: "Full check", command: "pnpm test:e2e" },
|
|
218
|
+
}))).toMatchObject({
|
|
219
|
+
kind: "create_task",
|
|
220
|
+
title: "Build Goal verification harness",
|
|
221
|
+
reason: "Goal harness requires local instrumentation before verification.",
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
it("blocks missing prerequisites with exact user instructions", () => {
|
|
225
|
+
expect(decideGoalNextAction(goalRun({
|
|
226
|
+
prerequisites: [
|
|
227
|
+
{
|
|
228
|
+
id: "api-key",
|
|
229
|
+
label: "Demo API key",
|
|
230
|
+
status: "missing",
|
|
231
|
+
instructions: "Provide DEMO_API_KEY in the local environment.",
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
}))).toEqual({
|
|
235
|
+
kind: "blocked",
|
|
236
|
+
reason: "Demo API key: Provide DEMO_API_KEY in the local environment.",
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
it("creates a bounded fix task for verifier failure when resumed", () => {
|
|
240
|
+
const run = goalRun({
|
|
241
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
242
|
+
verifier: {
|
|
243
|
+
description: "Full check",
|
|
244
|
+
command: "pnpm test",
|
|
245
|
+
lastResult: {
|
|
246
|
+
status: "fail",
|
|
247
|
+
summary: "tests failed",
|
|
248
|
+
checkedAt: "2024-01-01T00:00:00.000Z",
|
|
249
|
+
exitCode: 1,
|
|
250
|
+
outputPath: ".gg/log.log",
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
evidence: [
|
|
254
|
+
{
|
|
255
|
+
id: "evidence-a",
|
|
256
|
+
kind: "command",
|
|
257
|
+
label: "Verifier fail",
|
|
258
|
+
content: "tests failed",
|
|
259
|
+
path: ".gg/log.log",
|
|
260
|
+
createdAt: "2024-01-01T00:00:00.000Z",
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
});
|
|
264
|
+
const decision = decideGoalNextAction(run);
|
|
265
|
+
expect(decision).toMatchObject({
|
|
266
|
+
kind: "create_task",
|
|
267
|
+
title: "Fix verifier failure",
|
|
268
|
+
reason: "Verifier failed; creating bounded fix task 1/5.",
|
|
269
|
+
});
|
|
270
|
+
expect(decision.kind === "create_task" ? decision.prompt : "").toContain("Output path: .gg/log.log");
|
|
271
|
+
});
|
|
272
|
+
it("blocks repeated identical verifier failures instead of looping forever", () => {
|
|
273
|
+
const run = goalRun({
|
|
274
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
275
|
+
verifier: {
|
|
276
|
+
description: "Full check",
|
|
277
|
+
command: "pnpm test",
|
|
278
|
+
lastResult: {
|
|
279
|
+
status: "fail",
|
|
280
|
+
summary: "same",
|
|
281
|
+
checkedAt: "2024-01-01T00:00:00.000Z",
|
|
282
|
+
exitCode: 1,
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
evidence: [
|
|
286
|
+
{
|
|
287
|
+
id: "e1",
|
|
288
|
+
kind: "command",
|
|
289
|
+
label: "Verifier fail",
|
|
290
|
+
content: "same",
|
|
291
|
+
createdAt: "2024-01-01T00:00:00.000Z",
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
id: "e2",
|
|
295
|
+
kind: "command",
|
|
296
|
+
label: "Verifier fail",
|
|
297
|
+
content: "same",
|
|
298
|
+
createdAt: "2024-01-01T00:00:01.000Z",
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
});
|
|
302
|
+
expect(decideGoalNextAction(run)).toEqual({
|
|
303
|
+
kind: "blocked",
|
|
304
|
+
reason: "Verifier produced the same failure repeatedly; pause for diagnosis before creating more fix tasks.",
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
it("treats failed status as terminal unless a later tool action revives it to ready", () => {
|
|
308
|
+
const run = goalRun({
|
|
309
|
+
status: "failed",
|
|
310
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
311
|
+
verifier: {
|
|
312
|
+
description: "Full check",
|
|
313
|
+
command: "pnpm test",
|
|
314
|
+
lastResult: {
|
|
315
|
+
status: "fail",
|
|
316
|
+
summary: "tests failed",
|
|
317
|
+
checkedAt: "2024-01-01T00:00:00.000Z",
|
|
318
|
+
exitCode: 1,
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
evidence: [
|
|
322
|
+
{
|
|
323
|
+
id: "evidence-a",
|
|
324
|
+
kind: "command",
|
|
325
|
+
label: "Verifier result",
|
|
326
|
+
content: "tests failed",
|
|
327
|
+
createdAt: "2024-01-01T00:00:00.000Z",
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
});
|
|
331
|
+
expect(canCompleteGoalRun(run)).toEqual({ ok: false, reason: "Verifier status is fail." });
|
|
332
|
+
expect(decideGoalNextAction(run)).toEqual({
|
|
333
|
+
kind: "terminal",
|
|
334
|
+
status: "failed",
|
|
335
|
+
reason: "Goal is failed.",
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
it("completes only with all tasks done and pass verifier evidence", () => {
|
|
339
|
+
const run = goalRun({
|
|
340
|
+
tasks: [{ id: "task-a", title: "Done", prompt: "Done", status: "done", attempts: 1 }],
|
|
341
|
+
verifier: {
|
|
342
|
+
description: "Full check",
|
|
343
|
+
command: "pnpm test",
|
|
344
|
+
lastResult: {
|
|
345
|
+
status: "pass",
|
|
346
|
+
summary: "passed",
|
|
347
|
+
checkedAt: "2024-01-01T00:00:00.000Z",
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
expect(canCompleteGoalRun(run)).toEqual({
|
|
352
|
+
ok: true,
|
|
353
|
+
reason: "All tasks are done and verifier evidence passed.",
|
|
354
|
+
});
|
|
355
|
+
expect(decideGoalNextAction(run)).toEqual({
|
|
356
|
+
kind: "complete",
|
|
357
|
+
reason: "All tasks are done and verifier evidence passed.",
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
it("does not complete when verifier passed but tasks remain", () => {
|
|
361
|
+
const run = goalRun({
|
|
362
|
+
tasks: [
|
|
363
|
+
{ id: "done", title: "Done", prompt: "Done", status: "done", attempts: 1 },
|
|
364
|
+
{ id: "pending", title: "Pending", prompt: "Pending", status: "pending", attempts: 0 },
|
|
365
|
+
],
|
|
366
|
+
verifier: {
|
|
367
|
+
description: "Full check",
|
|
368
|
+
command: "pnpm test",
|
|
369
|
+
lastResult: {
|
|
370
|
+
status: "pass",
|
|
371
|
+
summary: "passed",
|
|
372
|
+
checkedAt: "2024-01-01T00:00:00.000Z",
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
expect(canCompleteGoalRun(run)).toEqual({ ok: false, reason: "1 Goal task is not done." });
|
|
377
|
+
expect(decideGoalNextAction(run)).toMatchObject({ kind: "start_worker" });
|
|
378
|
+
});
|
|
379
|
+
it("retries a failed task below the attempt limit for corrective work", () => {
|
|
380
|
+
const task = {
|
|
381
|
+
id: "task-a",
|
|
382
|
+
title: "Repair verifier failure",
|
|
383
|
+
prompt: "Fix the verifier failure using persisted evidence",
|
|
384
|
+
status: "failed",
|
|
385
|
+
attempts: 1,
|
|
386
|
+
lastSummary: "Verifier failed: assertion mismatch",
|
|
387
|
+
};
|
|
388
|
+
expect(decideGoalNextAction(goalRun({ tasks: [task] }))).toEqual({
|
|
389
|
+
kind: "start_worker",
|
|
390
|
+
task,
|
|
391
|
+
attempts: 2,
|
|
392
|
+
reason: 'Goal task "Repair verifier failure" is ready for worker attempt 2.',
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
it("formats durable-readable controller decisions", () => {
|
|
396
|
+
const decision = decideGoalNextAction(goalRun({ tasks: [] }));
|
|
397
|
+
const formatted = formatGoalControllerDecision(decision);
|
|
398
|
+
expect(formatted.label).toBe(`Goal decision: ${decision.kind}`);
|
|
399
|
+
expect(formatted.content).toContain(`kind=${decision.kind}`);
|
|
400
|
+
expect(shouldClearGoalContinuation({ kind: "wait", reason: "active" })).toBe(false);
|
|
401
|
+
expect(shouldClearGoalContinuation(decision)).toBe(true);
|
|
402
|
+
});
|
|
403
|
+
it("pauses after repeated non-progress rather than looping forever", () => {
|
|
404
|
+
const task = {
|
|
405
|
+
id: "task-a",
|
|
406
|
+
title: "Flaky repair",
|
|
407
|
+
prompt: "Do work",
|
|
408
|
+
status: "failed",
|
|
409
|
+
attempts: 5,
|
|
410
|
+
};
|
|
411
|
+
expect(decideGoalNextAction(goalRun({ tasks: [task] }))).toEqual({
|
|
412
|
+
kind: "pause",
|
|
413
|
+
task,
|
|
414
|
+
attempts: 6,
|
|
415
|
+
reason: "Attempt limit reached for task Flaky repair.",
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
//# sourceMappingURL=goal-controller.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goal-controller.test.js","sourceRoot":"","sources":["../../src/core/goal-controller.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goal-lifecycle-smoke.test.d.ts","sourceRoot":"","sources":["../../src/core/goal-lifecycle-smoke.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { decideGoalNextAction, canCompleteGoalRun } from "./goal-controller.js";
|
|
6
|
+
import { getGoalRun, loadGoalRuns } from "./goal-store.js";
|
|
7
|
+
import { createGoalsTool } from "../tools/goals.js";
|
|
8
|
+
let tmpBase;
|
|
9
|
+
let tmpProject;
|
|
10
|
+
async function goals(args) {
|
|
11
|
+
return createGoalsTool(tmpProject).execute(args, {
|
|
12
|
+
signal: new AbortController().signal,
|
|
13
|
+
toolCallId: "goal-lifecycle-smoke",
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
async function run() {
|
|
17
|
+
const current = await getGoalRun(tmpProject, "smoke-goal");
|
|
18
|
+
expect(current, "smoke goal should be persisted before inspection").toBeTruthy();
|
|
19
|
+
return current;
|
|
20
|
+
}
|
|
21
|
+
beforeEach(async () => {
|
|
22
|
+
tmpBase = await fs.mkdtemp(path.join(os.tmpdir(), "goal-lifecycle-smoke-base-"));
|
|
23
|
+
tmpProject = await fs.mkdtemp(path.join(os.tmpdir(), "goal-lifecycle-smoke-project-"));
|
|
24
|
+
process.env.GG_GOALS_BASE = tmpBase;
|
|
25
|
+
});
|
|
26
|
+
afterEach(async () => {
|
|
27
|
+
delete process.env.GG_GOALS_BASE;
|
|
28
|
+
await fs.rm(tmpBase, { recursive: true, force: true });
|
|
29
|
+
await fs.rm(tmpProject, { recursive: true, force: true });
|
|
30
|
+
});
|
|
31
|
+
describe("goal lifecycle smoke", () => {
|
|
32
|
+
it("persists and drives a mini Goal lifecycle from planned proof through corrective verification to completion", async () => {
|
|
33
|
+
await goals({
|
|
34
|
+
action: "create",
|
|
35
|
+
run_id: "smoke-goal",
|
|
36
|
+
title: "Lifecycle smoke",
|
|
37
|
+
goal: "Prove deterministic Goal lifecycle behavior in local temp storage",
|
|
38
|
+
success_criteria: [
|
|
39
|
+
"pending task completes",
|
|
40
|
+
"verifier failure produces repair",
|
|
41
|
+
"verifier pass gates completion",
|
|
42
|
+
],
|
|
43
|
+
prerequisites: [
|
|
44
|
+
{ id: "local", label: "Local temp project", status: "met", evidence: tmpProject },
|
|
45
|
+
],
|
|
46
|
+
harness: [
|
|
47
|
+
{
|
|
48
|
+
id: "local-harness",
|
|
49
|
+
label: "Local smoke harness",
|
|
50
|
+
command: "node ./scripts/goal-smoke.js",
|
|
51
|
+
path: "scripts/goal-smoke.js",
|
|
52
|
+
description: "Temp-only deterministic smoke harness metadata",
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
evidence_plan: [
|
|
56
|
+
{
|
|
57
|
+
id: "state-proof",
|
|
58
|
+
label: "Persisted state proof",
|
|
59
|
+
mechanism: "test",
|
|
60
|
+
description: "Vitest asserts transitions and JSON persistence",
|
|
61
|
+
status: "ready",
|
|
62
|
+
command: "pnpm --filter @kenkaiiii/ggcoder test -- goal-lifecycle-smoke",
|
|
63
|
+
path: "packages/ggcoder/src/core/goal-lifecycle-smoke.test.ts",
|
|
64
|
+
evidence: "This test inspects persisted Goal state after each tool call.",
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
verifier_command: "pnpm --filter @kenkaiiii/ggcoder test -- goal-lifecycle-smoke",
|
|
68
|
+
verifier_description: "Focused local Vitest lifecycle smoke",
|
|
69
|
+
});
|
|
70
|
+
await goals({
|
|
71
|
+
action: "task",
|
|
72
|
+
run_id: "smoke-goal",
|
|
73
|
+
task_id: "implement-smoke",
|
|
74
|
+
task_title: "Implement smoke target",
|
|
75
|
+
task_prompt: "Create the local smoke target and persist evidence.",
|
|
76
|
+
task_status: "pending",
|
|
77
|
+
});
|
|
78
|
+
let persisted = await run();
|
|
79
|
+
expect(decideGoalNextAction(persisted)).toMatchObject({ kind: "start_worker", attempts: 1 });
|
|
80
|
+
expect(persisted.harness).toEqual([
|
|
81
|
+
expect.objectContaining({ id: "local-harness", command: expect.any(String) }),
|
|
82
|
+
]);
|
|
83
|
+
expect(persisted.evidencePlan).toEqual([
|
|
84
|
+
expect.objectContaining({ id: "state-proof", status: "ready" }),
|
|
85
|
+
]);
|
|
86
|
+
expect((await loadGoalRuns(tmpProject)).map((item) => item.id)).toContain("smoke-goal");
|
|
87
|
+
await goals({
|
|
88
|
+
action: "task",
|
|
89
|
+
run_id: "smoke-goal",
|
|
90
|
+
task_id: "implement-smoke",
|
|
91
|
+
task_title: "Implement smoke target",
|
|
92
|
+
task_prompt: "Create the local smoke target and persist evidence.",
|
|
93
|
+
task_status: "done",
|
|
94
|
+
attempts: 1,
|
|
95
|
+
summary: "Initial task done with local fixture evidence.",
|
|
96
|
+
});
|
|
97
|
+
await goals({
|
|
98
|
+
action: "evidence",
|
|
99
|
+
run_id: "smoke-goal",
|
|
100
|
+
evidence_kind: "file",
|
|
101
|
+
evidence_label: "Local fixture artifact",
|
|
102
|
+
evidence_path: "tmp/goal-smoke-fixture.json",
|
|
103
|
+
evidence_content: "fixture persisted in temp-only smoke flow",
|
|
104
|
+
});
|
|
105
|
+
persisted = await run();
|
|
106
|
+
expect(decideGoalNextAction(persisted)).toEqual({
|
|
107
|
+
kind: "run_verifier",
|
|
108
|
+
command: "pnpm --filter @kenkaiiii/ggcoder test -- goal-lifecycle-smoke",
|
|
109
|
+
reason: "All Goal tasks are done; running configured verifier for real completion evidence.",
|
|
110
|
+
});
|
|
111
|
+
expect(persisted.tasks).toEqual([
|
|
112
|
+
expect.objectContaining({
|
|
113
|
+
id: "implement-smoke",
|
|
114
|
+
status: "done",
|
|
115
|
+
lastSummary: "Initial task done with local fixture evidence.",
|
|
116
|
+
}),
|
|
117
|
+
]);
|
|
118
|
+
expect(persisted.evidence).toEqual(expect.arrayContaining([
|
|
119
|
+
expect.objectContaining({
|
|
120
|
+
label: "Local fixture artifact",
|
|
121
|
+
path: "tmp/goal-smoke-fixture.json",
|
|
122
|
+
}),
|
|
123
|
+
]));
|
|
124
|
+
await goals({
|
|
125
|
+
action: "verify",
|
|
126
|
+
run_id: "smoke-goal",
|
|
127
|
+
verification_status: "fail",
|
|
128
|
+
summary: "intentional first verifier failure",
|
|
129
|
+
exit_code: 1,
|
|
130
|
+
output_path: "artifacts/goal-lifecycle-smoke-fail.log",
|
|
131
|
+
});
|
|
132
|
+
await goals({
|
|
133
|
+
action: "task",
|
|
134
|
+
run_id: "smoke-goal",
|
|
135
|
+
task_id: "repair-verifier",
|
|
136
|
+
task_title: "Fix verifier failure",
|
|
137
|
+
task_prompt: "Use persisted verifier evidence to repair the smoke flow.",
|
|
138
|
+
task_status: "pending",
|
|
139
|
+
});
|
|
140
|
+
persisted = await run();
|
|
141
|
+
expect(persisted.status).toBe("ready");
|
|
142
|
+
expect(persisted.verifier?.lastResult).toMatchObject({
|
|
143
|
+
status: "fail",
|
|
144
|
+
exitCode: 1,
|
|
145
|
+
outputPath: "artifacts/goal-lifecycle-smoke-fail.log",
|
|
146
|
+
});
|
|
147
|
+
expect(persisted.evidence).toEqual(expect.arrayContaining([
|
|
148
|
+
expect.objectContaining({
|
|
149
|
+
kind: "command",
|
|
150
|
+
label: "Verifier result",
|
|
151
|
+
content: "intentional first verifier failure",
|
|
152
|
+
}),
|
|
153
|
+
]));
|
|
154
|
+
expect(decideGoalNextAction(persisted)).toMatchObject({
|
|
155
|
+
kind: "start_worker",
|
|
156
|
+
task: expect.objectContaining({ id: "repair-verifier" }),
|
|
157
|
+
attempts: 1,
|
|
158
|
+
});
|
|
159
|
+
await goals({
|
|
160
|
+
action: "task",
|
|
161
|
+
run_id: "smoke-goal",
|
|
162
|
+
task_id: "repair-verifier",
|
|
163
|
+
task_title: "Fix verifier failure",
|
|
164
|
+
task_prompt: "Use persisted verifier evidence to repair the smoke flow.",
|
|
165
|
+
task_status: "done",
|
|
166
|
+
attempts: 1,
|
|
167
|
+
summary: "Corrective task completed.",
|
|
168
|
+
});
|
|
169
|
+
await goals({
|
|
170
|
+
action: "verify",
|
|
171
|
+
run_id: "smoke-goal",
|
|
172
|
+
verification_status: "pass",
|
|
173
|
+
summary: "focused lifecycle smoke passed",
|
|
174
|
+
exit_code: 0,
|
|
175
|
+
output_path: "artifacts/goal-lifecycle-smoke-pass.log",
|
|
176
|
+
});
|
|
177
|
+
persisted = await run();
|
|
178
|
+
expect(canCompleteGoalRun(persisted)).toEqual({
|
|
179
|
+
ok: true,
|
|
180
|
+
reason: "All tasks are done and verifier evidence passed.",
|
|
181
|
+
});
|
|
182
|
+
expect(decideGoalNextAction({ ...persisted, status: "ready" })).toEqual({
|
|
183
|
+
kind: "complete",
|
|
184
|
+
reason: "All tasks are done and verifier evidence passed.",
|
|
185
|
+
});
|
|
186
|
+
expect(await goals({ action: "complete", run_id: "smoke-goal" })).toBe('Goal "Lifecycle smoke" is now passed.');
|
|
187
|
+
persisted = await run();
|
|
188
|
+
expect(persisted.status).toBe("passed");
|
|
189
|
+
expect(decideGoalNextAction(persisted)).toEqual({
|
|
190
|
+
kind: "terminal",
|
|
191
|
+
status: "passed",
|
|
192
|
+
reason: "Goal is passed.",
|
|
193
|
+
});
|
|
194
|
+
expect(persisted.evidence).toEqual(expect.arrayContaining([
|
|
195
|
+
expect.objectContaining({ label: "Local fixture artifact" }),
|
|
196
|
+
expect.objectContaining({
|
|
197
|
+
label: "Verifier result",
|
|
198
|
+
content: "intentional first verifier failure",
|
|
199
|
+
}),
|
|
200
|
+
expect.objectContaining({
|
|
201
|
+
label: "Verifier result",
|
|
202
|
+
content: "focused lifecycle smoke passed",
|
|
203
|
+
}),
|
|
204
|
+
]));
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
//# sourceMappingURL=goal-lifecycle-smoke.test.js.map
|