@kenkaiiii/ggcoder 5.44.2 → 5.45.0
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/core/agent-session-compaction.test.js +60 -0
- package/dist/core/agent-session-compaction.test.js.map +1 -1
- package/dist/core/agent-session-verification-gate.test.d.ts +2 -0
- package/dist/core/agent-session-verification-gate.test.d.ts.map +1 -0
- package/dist/core/agent-session-verification-gate.test.js +135 -0
- package/dist/core/agent-session-verification-gate.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +2 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +41 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/process-manager-wake.test.d.ts +2 -0
- package/dist/core/process-manager-wake.test.d.ts.map +1 -0
- package/dist/core/process-manager-wake.test.js +96 -0
- package/dist/core/process-manager-wake.test.js.map +1 -0
- package/dist/core/process-manager.d.ts +39 -1
- package/dist/core/process-manager.d.ts.map +1 -1
- package/dist/core/process-manager.js +146 -2
- package/dist/core/process-manager.js.map +1 -1
- package/dist/core/provider-cache.e2e.test.d.ts +2 -0
- package/dist/core/provider-cache.e2e.test.d.ts.map +1 -0
- package/dist/core/provider-cache.e2e.test.js +125 -0
- package/dist/core/provider-cache.e2e.test.js.map +1 -0
- package/dist/core/session-injections.test.d.ts +2 -0
- package/dist/core/session-injections.test.d.ts.map +1 -0
- package/dist/core/session-injections.test.js +117 -0
- package/dist/core/session-injections.test.js.map +1 -0
- package/dist/core/session-reconstructability.test.d.ts +2 -0
- package/dist/core/session-reconstructability.test.d.ts.map +1 -0
- package/dist/core/session-reconstructability.test.js +105 -0
- package/dist/core/session-reconstructability.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 +5 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/verification-gate.d.ts +55 -0
- package/dist/core/verification-gate.d.ts.map +1 -0
- package/dist/core/verification-gate.js +188 -0
- package/dist/core/verification-gate.js.map +1 -0
- package/dist/core/verification-gate.test.d.ts +2 -0
- package/dist/core/verification-gate.test.d.ts.map +1 -0
- package/dist/core/verification-gate.test.js +102 -0
- package/dist/core/verification-gate.test.js.map +1 -0
- package/dist/system-prompt.test.js +33 -0
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/bash.d.ts +4 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +57 -3
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/bash.test.js +37 -0
- package/dist/tools/bash.test.js.map +1 -1
- package/dist/tools/read-only-bash.d.ts +6 -0
- package/dist/tools/read-only-bash.d.ts.map +1 -1
- package/dist/tools/read-only-bash.js +168 -9
- package/dist/tools/read-only-bash.js.map +1 -1
- package/dist/tools/read-only-bash.test.js +49 -0
- package/dist/tools/read-only-bash.test.js.map +1 -1
- package/dist/tools/tool-catalog.test.d.ts +2 -0
- package/dist/tools/tool-catalog.test.d.ts.map +1 -0
- package/dist/tools/tool-catalog.test.js +124 -0
- package/dist/tools/tool-catalog.test.js.map +1 -0
- package/dist/ui/App.d.ts +3 -0
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +35 -1
- package/dist/ui/App.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replay invariant: history re-derived from the persisted session log equals
|
|
3
|
+
* the message array the provider actually received (deepseek-harness takeaway
|
|
4
|
+
* #1 — "model-visible means logged", the reconstruction half).
|
|
5
|
+
*
|
|
6
|
+
* A scripted palsu factory CAPTURES the request messages on every call (the
|
|
7
|
+
* sent side). The same session file is then re-loaded through the resume path
|
|
8
|
+
* (`SessionManager.load` + `getMessages`) and the derived history is compared
|
|
9
|
+
* against the final captured request. Divergence means something reached the
|
|
10
|
+
* model without being persisted (or persisted differently) — a resumed or
|
|
11
|
+
* replayed session would show the model a history that never happened.
|
|
12
|
+
*
|
|
13
|
+
* Documented, deliberate divergences between log and request:
|
|
14
|
+
* - `MAX_PERSISTED_TOOL_TEXT_CHARS` (40k) truncation of oversized tool text
|
|
15
|
+
* at persist time (session-storage.ts). Kept out of this test's happy path
|
|
16
|
+
* by keeping tool results small; the exemption is named here so a future
|
|
17
|
+
* failure can be checked against it.
|
|
18
|
+
* - Externalized media / display-only rows — not exercised here.
|
|
19
|
+
*/
|
|
20
|
+
import fs from "node:fs/promises";
|
|
21
|
+
import os from "node:os";
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
24
|
+
import { registerPalsuProvider } from "@kenkaiiii/gg-ai";
|
|
25
|
+
import { useFakeHome } from "../test-support/fake-home.js";
|
|
26
|
+
const shouldCompactMock = vi.hoisted(() => vi.fn());
|
|
27
|
+
const compactMock = vi.hoisted(() => vi.fn());
|
|
28
|
+
vi.mock("./compaction/compactor.js", async () => {
|
|
29
|
+
const actual = await vi.importActual("./compaction/compactor.js");
|
|
30
|
+
return { ...actual, shouldCompact: shouldCompactMock, compact: compactMock };
|
|
31
|
+
});
|
|
32
|
+
let restoreHome;
|
|
33
|
+
let tmpHome;
|
|
34
|
+
let tmpProject;
|
|
35
|
+
let palsu;
|
|
36
|
+
beforeEach(async () => {
|
|
37
|
+
tmpHome = await fs.mkdtemp(path.join(os.tmpdir(), "gg-replay-home-"));
|
|
38
|
+
tmpProject = await fs.mkdtemp(path.join(os.tmpdir(), "gg-replay-project-"));
|
|
39
|
+
restoreHome = useFakeHome(tmpHome);
|
|
40
|
+
palsu = registerPalsuProvider();
|
|
41
|
+
shouldCompactMock.mockReset().mockReturnValue(false);
|
|
42
|
+
compactMock.mockReset();
|
|
43
|
+
await fs.mkdir(path.join(tmpHome, ".gg"), { recursive: true });
|
|
44
|
+
await fs.writeFile(path.join(tmpHome, ".gg", "auth.json"), JSON.stringify({
|
|
45
|
+
palsu: { accessToken: "t", refreshToken: "r", expiresAt: Date.now() + 3_600_000 },
|
|
46
|
+
}), "utf-8");
|
|
47
|
+
});
|
|
48
|
+
afterEach(async () => {
|
|
49
|
+
palsu.unregister();
|
|
50
|
+
restoreHome?.();
|
|
51
|
+
await fs.rm(tmpHome, { recursive: true, force: true });
|
|
52
|
+
await fs.rm(tmpProject, { recursive: true, force: true });
|
|
53
|
+
vi.clearAllMocks();
|
|
54
|
+
});
|
|
55
|
+
describe("session log reconstructs exactly what the model received", () => {
|
|
56
|
+
it("derived history equals the final captured request", async () => {
|
|
57
|
+
const { AgentSession } = await import("./agent-session.js");
|
|
58
|
+
const { SessionManager } = await import("./session-manager.js");
|
|
59
|
+
// Every request the provider saw, deep-cloned at call time (the loop
|
|
60
|
+
// mutates its message array in place, so references alone would all show
|
|
61
|
+
// the final state). Each scripted reply is a factory that captures the
|
|
62
|
+
// request and returns the next scripted assistant message.
|
|
63
|
+
const capturedRequests = [];
|
|
64
|
+
const replies = [
|
|
65
|
+
{ content: [{ type: "tool_call", id: "call_1", name: "boom", args: {} }] },
|
|
66
|
+
{ content: [{ type: "text", text: "Recovered after the failed call." }] },
|
|
67
|
+
];
|
|
68
|
+
palsu.setResponses(replies.map((reply) => (messages) => {
|
|
69
|
+
capturedRequests.push(structuredClone(messages));
|
|
70
|
+
return { role: "assistant", ...reply };
|
|
71
|
+
}));
|
|
72
|
+
const session = new AgentSession({
|
|
73
|
+
provider: "palsu",
|
|
74
|
+
model: "claude-sonnet-5",
|
|
75
|
+
cwd: tmpProject,
|
|
76
|
+
systemPrompt: "test system prompt",
|
|
77
|
+
});
|
|
78
|
+
await session.initialize();
|
|
79
|
+
session.queueMessage("Steering: keep going."); // drained at the loop's initial poll
|
|
80
|
+
await session.prompt("Do the task.");
|
|
81
|
+
const sessionPath = session.getState().sessionPath; // before dispose() clears it
|
|
82
|
+
await session.dispose();
|
|
83
|
+
// The run must have made multiple requests (user→tool-call, then result).
|
|
84
|
+
expect(capturedRequests.length).toBeGreaterThanOrEqual(2);
|
|
85
|
+
const finalRequest = capturedRequests[capturedRequests.length - 1];
|
|
86
|
+
// Re-derive history exactly as resume does.
|
|
87
|
+
const manager = new SessionManager(path.join(tmpHome, ".gg", "sessions"));
|
|
88
|
+
const { entries } = await manager.load(sessionPath);
|
|
89
|
+
const derived = manager.getMessages(entries);
|
|
90
|
+
// The final request = [system, ...history]; getMessages drops the system
|
|
91
|
+
// row (resume re-attaches a freshly built system prompt).
|
|
92
|
+
// `provenance` is the ONE documented exemption: log-side bookkeeping
|
|
93
|
+
// (source/kind/visibility) that persistence adds and the wire strips —
|
|
94
|
+
// it never reaches the model, so the model-visible comparison drops it.
|
|
95
|
+
const stripProvenance = (messages) => messages.filter((m) => m.role !== "system").map(({ provenance: _p, ...rest }) => rest);
|
|
96
|
+
const derivedRows = stripProvenance(derived);
|
|
97
|
+
const sentRows = stripProvenance(finalRequest);
|
|
98
|
+
// The final assistant reply is persisted AFTER the last request (it IS the
|
|
99
|
+
// response to it), so the derived history = sent history + that reply.
|
|
100
|
+
expect(derivedRows.slice(0, sentRows.length)).toEqual(sentRows);
|
|
101
|
+
expect(derivedRows.length).toBe(sentRows.length + 1); // exactly one trailing reply
|
|
102
|
+
expect(derivedRows[derivedRows.length - 1].role).toBe("assistant");
|
|
103
|
+
}, 60_000);
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=session-reconstructability.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-reconstructability.test.js","sourceRoot":"","sources":["../../src/core/session-reconstructability.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,6 +37,7 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
37
37
|
}>>;
|
|
38
38
|
showTokenUsage: z.ZodDefault<z.ZodBoolean>;
|
|
39
39
|
idealReviewEnabled: z.ZodDefault<z.ZodBoolean>;
|
|
40
|
+
verificationGateEnabled: z.ZodDefault<z.ZodBoolean>;
|
|
40
41
|
lspDiagnostics: z.ZodDefault<z.ZodBoolean>;
|
|
41
42
|
allowOutsideWorkspaceWrites: z.ZodDefault<z.ZodBoolean>;
|
|
42
43
|
networkMode: z.ZodDefault<z.ZodEnum<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,QAAA,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0GlB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,gBAAgB,EAAE,QAuB9B,CAAC;AAIF,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,QAAQ,CAAC,EAAE,MAAM;IAIvB,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC;IAazB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,GAAG,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;IAI5C,GAAG,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9E,MAAM,IAAI,QAAQ;IAIlB;;4CAEwC;IACxC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAMtC;qCACiC;IAC3B,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAO/C"}
|
|
@@ -38,6 +38,10 @@ const SettingsSchema = z.object({
|
|
|
38
38
|
.default("auto"),
|
|
39
39
|
showTokenUsage: z.boolean().default(true),
|
|
40
40
|
idealReviewEnabled: z.boolean().default(true),
|
|
41
|
+
/** Pre-stop gate: when code was edited but no test/typecheck/lint/build
|
|
42
|
+
* command completed since the last edit, the turn is continued once with a
|
|
43
|
+
* demand to verify (then one escalation demanding an honest statement). */
|
|
44
|
+
verificationGateEnabled: z.boolean().default(true),
|
|
41
45
|
/** Append LSP diagnostics to edit/write tool results. */
|
|
42
46
|
lspDiagnostics: z.boolean().default(true),
|
|
43
47
|
/** Allow write/edit outside the workspace (cwd, tmpdir, ~/.gg). Off by
|
|
@@ -115,6 +119,7 @@ export const DEFAULT_SETTINGS = {
|
|
|
115
119
|
theme: "auto",
|
|
116
120
|
showTokenUsage: true,
|
|
117
121
|
idealReviewEnabled: true,
|
|
122
|
+
verificationGateEnabled: true,
|
|
118
123
|
lspDiagnostics: true,
|
|
119
124
|
allowOutsideWorkspaceWrites: false,
|
|
120
125
|
networkMode: "off",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-manager.js","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"settings-manager.js","sourceRoot":"","sources":["../../src/core/settings-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verification gate — the turn cannot claim "done" while a promised check is
|
|
3
|
+
* still owed.
|
|
4
|
+
*
|
|
5
|
+
* When a run mutated code files and no test / typecheck / lint / build command
|
|
6
|
+
* completed after the last mutation, the pre-stop hook injects a follow-up
|
|
7
|
+
* demanding the project's verification be run, and blocks completion until it
|
|
8
|
+
* is (or the budget escalates to an honest "this went unverified" statement).
|
|
9
|
+
* Prompt-only "verify before finishing" instructions can be ignored; this gate
|
|
10
|
+
* is harness-owned bookkeeping on what actually executed.
|
|
11
|
+
*
|
|
12
|
+
* Simplification: verification is recognised by a conservative runner-shape
|
|
13
|
+
* classifier (package-manager/runner + test/lint/check keyword). Both error
|
|
14
|
+
* directions are safe — a missed recognition leaves the gate silent (today's
|
|
15
|
+
* behavior), a false positive merely skips one continuation.
|
|
16
|
+
*/
|
|
17
|
+
import type { Message } from "@kenkaiiii/gg-ai";
|
|
18
|
+
/** Follow-ups per run before the gate escalates to "state what went unverified". */
|
|
19
|
+
export declare const MAX_VERIFICATION_INJECTIONS = 1;
|
|
20
|
+
/**
|
|
21
|
+
* True when the command looks like a test/typecheck/lint/build invocation:
|
|
22
|
+
* wrappers stripped, a known runner leading, and a verification keyword among
|
|
23
|
+
* its operands. Deliberately strict — `grep test x`, `git commit -m test` and
|
|
24
|
+
* `./run_tests.sh` all read as NOT verification.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isVerificationCommand(command: string): boolean;
|
|
27
|
+
/** True for paths that look like source code (not docs, config or assets). */
|
|
28
|
+
export declare function isCodeFilePath(filePath: string): boolean;
|
|
29
|
+
export declare function buildVerificationFollowUpMessage(files: readonly string[]): Message;
|
|
30
|
+
export declare function buildVerificationEscalationMessage(files: readonly string[]): Message;
|
|
31
|
+
/**
|
|
32
|
+
* Bookkeeping for "code was edited, nothing proved it since". Callers record
|
|
33
|
+
* successful edit/write mutations on code files and completed foreground
|
|
34
|
+
* verification commands, in occurrence order; the gate is owed whenever the
|
|
35
|
+
* newest recorded event is a mutation.
|
|
36
|
+
*/
|
|
37
|
+
export declare class VerificationGate {
|
|
38
|
+
private seq;
|
|
39
|
+
private lastMutationSeq;
|
|
40
|
+
private lastVerificationSeq;
|
|
41
|
+
private injections;
|
|
42
|
+
/** Code files mutated since the last verification — the gate's file list. */
|
|
43
|
+
private mutatedFiles;
|
|
44
|
+
recordMutation(filePath: string): void;
|
|
45
|
+
recordVerification(): void;
|
|
46
|
+
isOwed(): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The blocking message for the pre-stop hook, or null when nothing is owed
|
|
49
|
+
* or the injection budget is spent. First the demand (budget 1), then one
|
|
50
|
+
* terminal escalation requiring an honest unverified statement, then silent.
|
|
51
|
+
*/
|
|
52
|
+
followUp(): Message[] | null;
|
|
53
|
+
reset(): void;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=verification-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-gate.d.ts","sourceRoot":"","sources":["../../src/core/verification-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,oFAAoF;AACpF,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAkF7C;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAuB9D;AAMD,8EAA8E;AAC9E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAWlF;AAED,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAUpF;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,UAAU,CAAK;IACvB,6EAA6E;IAC7E,OAAO,CAAC,YAAY,CAAqB;IAEzC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKtC,kBAAkB,IAAI,IAAI;IAK1B,MAAM,IAAI,OAAO;IAIjB;;;;OAIG;IACH,QAAQ,IAAI,OAAO,EAAE,GAAG,IAAI;IAY5B,KAAK,IAAI,IAAI;CAOd"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/** Follow-ups per run before the gate escalates to "state what went unverified". */
|
|
2
|
+
export const MAX_VERIFICATION_INJECTIONS = 1;
|
|
3
|
+
/** Words that may precede the real command without changing its shape. */
|
|
4
|
+
const SHELL_WRAPPERS = new Set([
|
|
5
|
+
"env",
|
|
6
|
+
"nohup",
|
|
7
|
+
"nice",
|
|
8
|
+
"time",
|
|
9
|
+
"sudo",
|
|
10
|
+
"stdbuf",
|
|
11
|
+
"command",
|
|
12
|
+
"exec",
|
|
13
|
+
]);
|
|
14
|
+
/** Leading words that mark a command as a build/test-tool invocation. Anything
|
|
15
|
+
* else (git, grep, ./script.sh, bash …) is conservatively not verification. */
|
|
16
|
+
const RUNNERS = new Set([
|
|
17
|
+
"npm",
|
|
18
|
+
"pnpm",
|
|
19
|
+
"yarn",
|
|
20
|
+
"bun",
|
|
21
|
+
"npx",
|
|
22
|
+
"nr",
|
|
23
|
+
"deno",
|
|
24
|
+
"python",
|
|
25
|
+
"python3",
|
|
26
|
+
"py",
|
|
27
|
+
"uv",
|
|
28
|
+
"go",
|
|
29
|
+
"cargo",
|
|
30
|
+
"rustc",
|
|
31
|
+
"make",
|
|
32
|
+
"cmake",
|
|
33
|
+
"gradle",
|
|
34
|
+
"mvn",
|
|
35
|
+
"dotnet",
|
|
36
|
+
"sbt",
|
|
37
|
+
"swift",
|
|
38
|
+
"tsc",
|
|
39
|
+
"vitest",
|
|
40
|
+
"jest",
|
|
41
|
+
"mocha",
|
|
42
|
+
"pytest",
|
|
43
|
+
"unittest",
|
|
44
|
+
"eslint",
|
|
45
|
+
"biome",
|
|
46
|
+
"ruff",
|
|
47
|
+
"mypy",
|
|
48
|
+
"pylint",
|
|
49
|
+
]);
|
|
50
|
+
/** A non-flag word after the runner that makes the command a verification. */
|
|
51
|
+
const VERIFY_KEYWORDS = [
|
|
52
|
+
"test",
|
|
53
|
+
"tests",
|
|
54
|
+
"vitest",
|
|
55
|
+
"jest",
|
|
56
|
+
"mocha",
|
|
57
|
+
"pytest",
|
|
58
|
+
"unittest",
|
|
59
|
+
"tsc",
|
|
60
|
+
"typecheck",
|
|
61
|
+
"type-check",
|
|
62
|
+
"eslint",
|
|
63
|
+
"biome",
|
|
64
|
+
"ruff",
|
|
65
|
+
"mypy",
|
|
66
|
+
"pylint",
|
|
67
|
+
"lint",
|
|
68
|
+
"clippy",
|
|
69
|
+
"vet",
|
|
70
|
+
"check",
|
|
71
|
+
"build",
|
|
72
|
+
"compile",
|
|
73
|
+
"verify",
|
|
74
|
+
];
|
|
75
|
+
function isVerifyWord(word) {
|
|
76
|
+
// Exact keyword, or a script name built on one (npm run test:unit).
|
|
77
|
+
return VERIFY_KEYWORDS.some((keyword) => word === keyword || word.startsWith(`${keyword}:`));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* True when the command looks like a test/typecheck/lint/build invocation:
|
|
81
|
+
* wrappers stripped, a known runner leading, and a verification keyword among
|
|
82
|
+
* its operands. Deliberately strict — `grep test x`, `git commit -m test` and
|
|
83
|
+
* `./run_tests.sh` all read as NOT verification.
|
|
84
|
+
*/
|
|
85
|
+
export function isVerificationCommand(command) {
|
|
86
|
+
const words = command.trim().split(/\s+/);
|
|
87
|
+
let i = 0;
|
|
88
|
+
while (i < words.length) {
|
|
89
|
+
const word = words[i];
|
|
90
|
+
if (SHELL_WRAPPERS.has(word) || /^[A-Za-z_][A-Za-z0-9_]*=/.test(word)) {
|
|
91
|
+
i += 1;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
// `timeout <duration> runner …` — skip the duration argument too.
|
|
95
|
+
if (word === "timeout") {
|
|
96
|
+
i += 2;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
const runner = words[i] ?? "";
|
|
102
|
+
if (!RUNNERS.has(runner))
|
|
103
|
+
return false;
|
|
104
|
+
if (isVerifyWord(runner))
|
|
105
|
+
return true; // bare vitest / jest / tsc / eslint …
|
|
106
|
+
return words
|
|
107
|
+
.slice(i + 1)
|
|
108
|
+
.filter((word) => !word.startsWith("-"))
|
|
109
|
+
.some(isVerifyWord);
|
|
110
|
+
}
|
|
111
|
+
/** Source-file extensions whose edits count as code mutations. */
|
|
112
|
+
const CODE_EXT_RE = /\.(?:[cm]?[jt]sx?|py|rb|go|rs|java|kt|kts|swift|c|h|cpp|cc|hpp|cs|php|vue|svelte|scala|sh|sql|m|mm|zig|ex|exs|erl|dart|lua|pl|r|jl|hs|clj)$/;
|
|
113
|
+
/** True for paths that look like source code (not docs, config or assets). */
|
|
114
|
+
export function isCodeFilePath(filePath) {
|
|
115
|
+
return CODE_EXT_RE.test(filePath);
|
|
116
|
+
}
|
|
117
|
+
export function buildVerificationFollowUpMessage(files) {
|
|
118
|
+
return {
|
|
119
|
+
role: "user",
|
|
120
|
+
provenance: { source: "runtime", kind: "completion_gate", visibility: "hidden" },
|
|
121
|
+
content: "Verification gate: you changed code in this run, but no test, typecheck, lint or build " +
|
|
122
|
+
"command has completed since the last edit:\n" +
|
|
123
|
+
files.map((filePath) => `- ${filePath}`).join("\n") +
|
|
124
|
+
"\nRun the project's verification now (its test command, or the closest equivalent) and " +
|
|
125
|
+
"address any failures. Do not describe the change as tested or working without having run it.",
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
export function buildVerificationEscalationMessage(files) {
|
|
129
|
+
return {
|
|
130
|
+
role: "user",
|
|
131
|
+
provenance: { source: "runtime", kind: "completion_gate", visibility: "hidden" },
|
|
132
|
+
content: `Verification is still outstanding after ${MAX_VERIFICATION_INJECTIONS} attempt(s); ` +
|
|
133
|
+
"the gate will not prompt again. Give your final response now and state plainly which of " +
|
|
134
|
+
"these changes went unverified and why, so the user can check them:\n" +
|
|
135
|
+
files.map((filePath) => `- ${filePath}`).join("\n"),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Bookkeeping for "code was edited, nothing proved it since". Callers record
|
|
140
|
+
* successful edit/write mutations on code files and completed foreground
|
|
141
|
+
* verification commands, in occurrence order; the gate is owed whenever the
|
|
142
|
+
* newest recorded event is a mutation.
|
|
143
|
+
*/
|
|
144
|
+
export class VerificationGate {
|
|
145
|
+
seq = 0;
|
|
146
|
+
lastMutationSeq = 0;
|
|
147
|
+
lastVerificationSeq = 0;
|
|
148
|
+
injections = 0;
|
|
149
|
+
/** Code files mutated since the last verification — the gate's file list. */
|
|
150
|
+
mutatedFiles = new Set();
|
|
151
|
+
recordMutation(filePath) {
|
|
152
|
+
this.lastMutationSeq = ++this.seq;
|
|
153
|
+
this.mutatedFiles.add(filePath);
|
|
154
|
+
}
|
|
155
|
+
recordVerification() {
|
|
156
|
+
this.lastVerificationSeq = ++this.seq;
|
|
157
|
+
this.mutatedFiles.clear();
|
|
158
|
+
}
|
|
159
|
+
isOwed() {
|
|
160
|
+
return this.lastMutationSeq > this.lastVerificationSeq;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The blocking message for the pre-stop hook, or null when nothing is owed
|
|
164
|
+
* or the injection budget is spent. First the demand (budget 1), then one
|
|
165
|
+
* terminal escalation requiring an honest unverified statement, then silent.
|
|
166
|
+
*/
|
|
167
|
+
followUp() {
|
|
168
|
+
if (!this.isOwed())
|
|
169
|
+
return null;
|
|
170
|
+
if (this.injections >= MAX_VERIFICATION_INJECTIONS + 1)
|
|
171
|
+
return null;
|
|
172
|
+
this.injections += 1;
|
|
173
|
+
const files = [...this.mutatedFiles].sort();
|
|
174
|
+
return [
|
|
175
|
+
this.injections > MAX_VERIFICATION_INJECTIONS
|
|
176
|
+
? buildVerificationEscalationMessage(files)
|
|
177
|
+
: buildVerificationFollowUpMessage(files),
|
|
178
|
+
];
|
|
179
|
+
}
|
|
180
|
+
reset() {
|
|
181
|
+
this.seq = 0;
|
|
182
|
+
this.lastMutationSeq = 0;
|
|
183
|
+
this.lastVerificationSeq = 0;
|
|
184
|
+
this.injections = 0;
|
|
185
|
+
this.mutatedFiles.clear();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=verification-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-gate.js","sourceRoot":"","sources":["../../src/core/verification-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-gate.test.d.ts","sourceRoot":"","sources":["../../src/core/verification-gate.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { VerificationGate, isCodeFilePath, isVerificationCommand, MAX_VERIFICATION_INJECTIONS, } from "./verification-gate.js";
|
|
3
|
+
describe("isVerificationCommand", () => {
|
|
4
|
+
const yes = [
|
|
5
|
+
["npm test", "npm test"],
|
|
6
|
+
["pnpm test:unit", "script name with test: prefix"],
|
|
7
|
+
["yarn run build", "yarn run build"],
|
|
8
|
+
["npx vitest run src", "npx vitest"],
|
|
9
|
+
["vitest run", "bare vitest"],
|
|
10
|
+
["jest --coverage", "bare jest"],
|
|
11
|
+
["tsc --noEmit", "bare tsc"],
|
|
12
|
+
["eslint src/", "bare eslint"],
|
|
13
|
+
["go test ./...", "go test"],
|
|
14
|
+
["cargo test", "cargo test"],
|
|
15
|
+
["cargo clippy", "cargo clippy"],
|
|
16
|
+
["make check", "make check"],
|
|
17
|
+
["python -m pytest -x", "python -m pytest"],
|
|
18
|
+
["pytest tests/", "bare pytest"],
|
|
19
|
+
["uv run pytest", "uv run pytest"],
|
|
20
|
+
["timeout 30s npm test", "timeout wrapper with duration"],
|
|
21
|
+
["CI=1 npm test", "env-var wrapper"],
|
|
22
|
+
["ruff check src", "ruff check"],
|
|
23
|
+
["biome check .", "biome check"],
|
|
24
|
+
["gradle test", "gradle test"],
|
|
25
|
+
["dotnet test", "dotnet test"],
|
|
26
|
+
["deno task test", "deno task test"],
|
|
27
|
+
];
|
|
28
|
+
const no = [
|
|
29
|
+
["git commit -m fix test", "commit message mentioning test"],
|
|
30
|
+
["grep test file.ts", "grep for the word test"],
|
|
31
|
+
["cat test-output.log", "cat a log"],
|
|
32
|
+
["./run_tests.sh", "direct script"],
|
|
33
|
+
["bash scripts/test.sh", "bash-invoked script"],
|
|
34
|
+
["npm install", "package install"],
|
|
35
|
+
["npm run dev", "dev server"],
|
|
36
|
+
["go run main.go", "go run"],
|
|
37
|
+
["python train.py", "python script"],
|
|
38
|
+
["echo running tests soon", "echo mentioning tests"],
|
|
39
|
+
];
|
|
40
|
+
it.each(yes)("classifies %s as verification (%s)", (command) => {
|
|
41
|
+
expect(isVerificationCommand(command)).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
it.each(no)("classifies %s as NOT verification (%s)", (command) => {
|
|
44
|
+
expect(isVerificationCommand(command)).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe("isCodeFilePath", () => {
|
|
48
|
+
it("accepts source files", () => {
|
|
49
|
+
expect(isCodeFilePath("src/a.ts")).toBe(true);
|
|
50
|
+
expect(isCodeFilePath("src/a.test.tsx")).toBe(true);
|
|
51
|
+
expect(isCodeFilePath("lib/x.py")).toBe(true);
|
|
52
|
+
expect(isCodeFilePath("src/main.rs")).toBe(true);
|
|
53
|
+
expect(isCodeFilePath("cmd/tool.go")).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
it("rejects non-code files", () => {
|
|
56
|
+
expect(isCodeFilePath("README.md")).toBe(false);
|
|
57
|
+
expect(isCodeFilePath("package.json")).toBe(false);
|
|
58
|
+
expect(isCodeFilePath("logo.svg")).toBe(false);
|
|
59
|
+
expect(isCodeFilePath("notes.txt")).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe("VerificationGate", () => {
|
|
63
|
+
it("is silent with no mutations", () => {
|
|
64
|
+
const gate = new VerificationGate();
|
|
65
|
+
gate.recordVerification();
|
|
66
|
+
expect(gate.isOwed()).toBe(false);
|
|
67
|
+
expect(gate.followUp()).toBeNull();
|
|
68
|
+
});
|
|
69
|
+
it("is owed after a mutation until a verification follows", () => {
|
|
70
|
+
const gate = new VerificationGate();
|
|
71
|
+
gate.recordVerification();
|
|
72
|
+
gate.recordMutation("a.ts");
|
|
73
|
+
expect(gate.isOwed()).toBe(true);
|
|
74
|
+
const followUp = gate.followUp();
|
|
75
|
+
expect(followUp).toHaveLength(1);
|
|
76
|
+
expect(String(followUp[0].content)).toContain("a.ts");
|
|
77
|
+
gate.recordVerification();
|
|
78
|
+
expect(gate.isOwed()).toBe(false);
|
|
79
|
+
expect(gate.followUp()).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
it("demands once, escalates once, then goes silent", () => {
|
|
82
|
+
const gate = new VerificationGate();
|
|
83
|
+
gate.recordMutation("a.ts");
|
|
84
|
+
const demand = gate.followUp();
|
|
85
|
+
expect(String(demand[0].content)).toContain("Run the project's verification");
|
|
86
|
+
// Model stopped again without verifying.
|
|
87
|
+
const escalation = gate.followUp();
|
|
88
|
+
expect(String(escalation[0].content)).toContain("unverified");
|
|
89
|
+
expect(gate.followUp()).toBeNull();
|
|
90
|
+
expect(MAX_VERIFICATION_INJECTIONS).toBe(1);
|
|
91
|
+
});
|
|
92
|
+
it("a later mutation re-arms an already-satisfied gate after a fresh budget reset", () => {
|
|
93
|
+
const gate = new VerificationGate();
|
|
94
|
+
gate.recordMutation("a.ts");
|
|
95
|
+
gate.followUp();
|
|
96
|
+
gate.recordVerification();
|
|
97
|
+
expect(gate.followUp()).toBeNull();
|
|
98
|
+
gate.reset();
|
|
99
|
+
expect(gate.isOwed()).toBe(false);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=verification-gate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-gate.test.js","sourceRoot":"","sources":["../../src/core/verification-gate.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import os from "node:os";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { afterEach, describe, expect, it } from "vitest";
|
|
5
5
|
import { buildSubAgentSystemPrompt, buildSystemPrompt, collectProjectContext, PROJECT_CONTEXT_MAX_BYTES, } from "./system-prompt.js";
|
|
6
|
+
import { buildKenSystemPrompt } from "./core/ken-prompt.js";
|
|
6
7
|
const tempDirs = [];
|
|
7
8
|
async function makeProject(files = {}) {
|
|
8
9
|
const cwd = await fs.mkdtemp(path.join(os.tmpdir(), "ggcoder-system-prompt-"));
|
|
@@ -453,6 +454,38 @@ describe("buildSystemPrompt", () => {
|
|
|
453
454
|
expect(openai.startsWith("You are GG Coder by Ken Kai")).toBe(true);
|
|
454
455
|
expect(openai).not.toContain("You are Claude Code");
|
|
455
456
|
});
|
|
457
|
+
it("is byte-stable across builds in one process (prefix-cache safety)", async () => {
|
|
458
|
+
// Deterministic arm of bench/baseline/04-prefix-stability.mjs, promoted to
|
|
459
|
+
// a unit test so a volatile section landing in the cached prefix fails
|
|
460
|
+
// `pnpm test`, not a manual bench run. The live cache-hit e2e
|
|
461
|
+
// (core/provider-cache.e2e.test.ts) guards the same property end-to-end.
|
|
462
|
+
const cwd = await makeProject({
|
|
463
|
+
"CLAUDE.md": "Project rules win.",
|
|
464
|
+
"package.json": JSON.stringify({ scripts: { check: "tsc --noEmit" } }),
|
|
465
|
+
});
|
|
466
|
+
const args = {
|
|
467
|
+
skills: [],
|
|
468
|
+
planMode: false,
|
|
469
|
+
approvedPlanPath: undefined,
|
|
470
|
+
toolNames: ["read", "edit", "bash"],
|
|
471
|
+
activeLanguages: new Set(["typescript"]),
|
|
472
|
+
};
|
|
473
|
+
const a = await buildSystemPrompt(cwd, args.skills, args.planMode, args.approvedPlanPath, args.toolNames, args.activeLanguages);
|
|
474
|
+
const b = await buildSystemPrompt(cwd, args.skills, args.planMode, args.approvedPlanPath, args.toolNames, args.activeLanguages);
|
|
475
|
+
expect(a).toBe(b);
|
|
476
|
+
// Same for the Ken advisor prompt — its marker must also partition
|
|
477
|
+
// volatile bytes out of the cached prefix (ken-prompt.ts pins the marker
|
|
478
|
+
// as byte-identical to the build prompt's).
|
|
479
|
+
const kenA = await buildKenSystemPrompt(cwd);
|
|
480
|
+
const kenB = await buildKenSystemPrompt(cwd);
|
|
481
|
+
expect(kenA).toBe(kenB);
|
|
482
|
+
for (const prompt of [a, kenA]) {
|
|
483
|
+
expect(prompt).toContain("<!-- uncached -->");
|
|
484
|
+
// All volatile content (currently only the date) sits AFTER the marker.
|
|
485
|
+
const markerAt = prompt.indexOf("<!-- uncached -->");
|
|
486
|
+
expect(prompt.slice(markerAt)).toMatch(/Today's date: \d{1,2} \w+ \d{4}/);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
456
489
|
});
|
|
457
490
|
describe("collectProjectContext", () => {
|
|
458
491
|
it("picks one file per directory — AGENTS.md shadows CLAUDE.md and the rest", async () => {
|