authorgravatar for saphid@gmail.comAlex Southwell <saphid@gmail.com> 2026-09-18 09:48:18+10:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-17 16:48:18-07:00
log1455cb5c35e50211145073be6ca155d56684f0f4
tree9d4bd56dbfeb81936239e61d74b5f99cbd584cf2
parentfcfd9f911a27ee3b813d64582c53d82dfa2e892b
signature Signed by PGP key B5690EEEBB952194

fix(server): checkpoint workspaces with empty nested repositories (#12181)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com>

2 files changed, 371 insertions(+), 20 deletions(-)

apps/server/src/vcs/GitVcsDriver.test.ts+292-1
...@@ -1,5 +1,10 @@...@@ -1,5 +1,10 @@
1import * as NodeServices from "@effect/platform-node/NodeServices";1import * as NodeServices from "@effect/platform-node/NodeServices";
2import * as Cause from "effect/Cause";
3import * as Exit from "effect/Exit";
4import * as Deferred from "effect/Deferred";
2import * as Effect from "effect/Effect";5import * as Effect from "effect/Effect";
6import * as Fiber from "effect/Fiber";
7import * as TestClock from "effect/testing/TestClock";
3import * as FileSystem from "effect/FileSystem";8import * as FileSystem from "effect/FileSystem";
4import * as Layer from "effect/Layer";9import * as Layer from "effect/Layer";
5import * as Path from "effect/Path";10import * as Path from "effect/Path";
...@@ -7,7 +12,7 @@ import * as PlatformError from "effect/PlatformError";...@@ -7,7 +12,7 @@ import * as PlatformError from "effect/PlatformError";
7import { ChildProcessSpawner } from "effect/unstable/process";12import { ChildProcessSpawner } from "effect/unstable/process";
8import { assert, it } from "@effect/vitest";13import { assert, it } from "@effect/vitest";
914
10import { CheckpointRef, GitCommandError } from "@t3tools/contracts";15import { CheckpointRef, GitCommandError, VcsProcessExitError } from "@t3tools/contracts";
11import * as ServerConfig from "../config.ts";16import * as ServerConfig from "../config.ts";
12import * as GitVcsDriver from "./GitVcsDriver.ts";17import * as GitVcsDriver from "./GitVcsDriver.ts";
13import * as VcsProcess from "./VcsProcess.ts";18import * as VcsProcess from "./VcsProcess.ts";
...@@ -86,6 +91,292 @@ const makeCheckpointFixture = Effect.fn("makeCheckpointFixture")(function* (...@@ -86,6 +91,292 @@ const makeCheckpointFixture = Effect.fn("makeCheckpointFixture")(function* (
86 return { git, checkpointRef };91 return { git, checkpointRef };
87});92});
8893
94it.effect("checkpoint capture skips untracked nested repositories without a commit", () =>
95 Effect.gen(function* () {
96 const fileSystem = yield* FileSystem.FileSystem;
97 const path = yield* Path.Path;
98 const driver = yield* GitVcsDriver.makeVcsDriverShape();
99 const cwd = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-checkpoint-unborn-" });
100 const { git, checkpointRef } = yield* makeCheckpointFixture(driver, cwd);
101 const nested = "scratch/empty [repo]";
102 yield* git(["init", nested]);
103 yield* git(["init", "another empty"]);
104 yield* fileSystem.writeFileString(path.join(cwd, nested, "private.txt"), "nested\n");
105 yield* git(["init", "committed"]);
106 yield* git([
107 "-C",
108 "committed",
109 "-c",
110 "user.name=Test",
111 "-c",
112 "user.email=test@test.com",
113 "commit",
114 "--allow-empty",
115 "-m",
116 "initial",
117 ]);
118 const nestedHead = (yield* git(["-C", "committed", "rev-parse", "HEAD"])).stdout.trim();
119 yield* fileSystem.writeFileString(path.join(cwd, "untracked.txt"), "new\n");
120 const originalIndex = yield* fileSystem.readFile(path.join(cwd, ".git", "index"));
121
122 yield* driver.checkpoints.captureCheckpoint({ cwd, checkpointRef });
123
124 assert.strictEqual((yield* git(["show", `${checkpointRef}:file.txt`])).stdout, "unstaged\n");
125 assert.strictEqual((yield* git(["show", `${checkpointRef}:untracked.txt`])).stdout, "new\n");
126 assert.strictEqual((yield* git(["ls-tree", "-r", checkpointRef, "--", nested])).stdout, "");
127 assert.strictEqual((yield* git(["ls-tree", checkpointRef, "--", "another empty"])).stdout, "");
128 assert.strictEqual(
129 (yield* git(["ls-tree", checkpointRef, "--", "committed"])).stdout,
130 `160000 commit ${nestedHead}\tcommitted\n`,
131 );
132 assert.deepEqual(yield* fileSystem.readFile(path.join(cwd, ".git", "index")), originalIndex);
133 assert.strictEqual(
134 yield* fileSystem.readFileString(path.join(cwd, nested, "private.txt")),
135 "nested\n",
136 );
137 }).pipe(Effect.scoped, Effect.provide(GitContractLayer)),
138);
139
140it.effect("checkpoint recovery discovers nested HEAD independently of inherited GIT_DIR", () =>
141 Effect.gen(function* () {
142 const fs = yield* FileSystem.FileSystem;
143 const path = yield* Path.Path;
144 const driver = yield* GitVcsDriver.makeVcsDriverShape();
145 const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-checkpoint-git-dir-" });
146 const { git, checkpointRef } = yield* makeCheckpointFixture(driver, cwd);
147 yield* git(["init", "empty"]);
148 const originalIndex = yield* fs.readFile(path.join(cwd, ".git", "index"));
149 yield* Effect.acquireUseRelease(
150 Effect.sync(() => {
151 const previous = process.env.GIT_DIR;
152 process.env.GIT_DIR = path.join(cwd, ".git");
153 return previous;
154 }),
155 () => driver.checkpoints.captureCheckpoint({ cwd, checkpointRef }),
156 (previous) =>
157 Effect.sync(() => {
158 if (previous === undefined) delete process.env.GIT_DIR;
159 else process.env.GIT_DIR = previous;
160 }),
161 );
162 assert.strictEqual((yield* git(["show", `${checkpointRef}:file.txt`])).stdout, "unstaged\n");
163 assert.strictEqual((yield* git(["ls-tree", "-r", checkpointRef, "--", "empty"])).stdout, "");
164 assert.deepEqual(yield* fs.readFile(path.join(cwd, ".git", "index")), originalIndex);
165 }).pipe(Effect.scoped, Effect.provide(GitContractLayer)),
166);
167
168it.effect("checkpoint capture still fails when a clean filter rejects a file", () =>
169 Effect.gen(function* () {
170 const fileSystem = yield* FileSystem.FileSystem;
171 const path = yield* Path.Path;
172 const driver = yield* GitVcsDriver.makeVcsDriverShape();
173 const cwd = yield* fileSystem.makeTempDirectoryScoped({
174 prefix: "t3-checkpoint-filter-failure-",
175 });
176 const { git, checkpointRef } = yield* makeCheckpointFixture(driver, cwd);
177 yield* fileSystem.writeFileString(path.join(cwd, ".gitattributes"), "file.txt filter=reject\n");
178 yield* git(["config", "filter.reject.clean", "false"]);
179 yield* git(["config", "filter.reject.required", "true"]);
180 const originalIndex = yield* fileSystem.readFile(path.join(cwd, ".git", "index"));
181
182 const result = yield* Effect.result(
183 driver.checkpoints.captureCheckpoint({ cwd, checkpointRef }),
184 );
185
186 assert.strictEqual(result._tag, "Failure");
187 assert.deepEqual(yield* fileSystem.readFile(path.join(cwd, ".git", "index")), originalIndex);
188 assert.isFalse(yield* driver.checkpoints.hasCheckpointRef({ cwd, checkpointRef }));
189 }).pipe(Effect.scoped, Effect.provide(GitContractLayer)),
190);
191
192it.effect("checkpoint capture refuses a truncated nested repository listing", () =>
193 Effect.gen(function* () {
194 const fs = yield* FileSystem.FileSystem;
195 const liveProcess = yield* VcsProcess.VcsProcess;
196 const driver = yield* GitVcsDriver.makeVcsDriverShape();
197 const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-checkpoint-truncated-" });
198 const { git, checkpointRef } = yield* makeCheckpointFixture(driver, cwd);
199 yield* git(["init", "empty"]);
200 const captureDriver = yield* GitVcsDriver.makeVcsDriverShape().pipe(
201 Effect.provideService(VcsProcess.VcsProcess, {
202 run: (input) =>
203 liveProcess
204 .run(input)
205 .pipe(
206 Effect.map((result) =>
207 input.args.includes("--others") ? { ...result, stdoutTruncated: true } : result,
208 ),
209 ),
210 }),
211 );
212
213 const result = yield* Effect.result(
214 captureDriver.checkpoints.captureCheckpoint({ cwd, checkpointRef }),
215 );
216
217 assert.strictEqual(result._tag, "Failure");
218 assert.isFalse(yield* driver.checkpoints.hasCheckpointRef({ cwd, checkpointRef }));
219 }).pipe(Effect.scoped, Effect.provide(GitContractLayer)),
220);
221
222it.effect("checkpoint recovery refuses excessive candidates before probing", () =>
223 Effect.gen(function* () {
224 const fs = yield* FileSystem.FileSystem;
225 const path = yield* Path.Path;
226 const liveProcess = yield* VcsProcess.VcsProcess;
227 const driver = yield* GitVcsDriver.makeVcsDriverShape();
228 const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-checkpoint-recovery-cap-" });
229 const { git, checkpointRef } = yield* makeCheckpointFixture(driver, cwd);
230 yield* git(["init", "empty0"]);
231 for (let i = 1; i < 65; i++)
232 yield* fs.copy(path.join(cwd, "empty0"), path.join(cwd, `empty${i}`));
233 const originalIndex = yield* fs.readFile(path.join(cwd, ".git", "index"));
234 let stageError: VcsProcessExitError | undefined;
235 let nestedProbes = 0;
236 let stageAttempts = 0;
237 const captureDriver = yield* GitVcsDriver.makeVcsDriverShape().pipe(
238 Effect.provideService(VcsProcess.VcsProcess, {
239 run: (input) => {
240 if (input.cwd !== cwd && input.args.includes("rev-parse")) nestedProbes++;
241 if (input.args.includes("add") && input.args.includes("-A")) stageAttempts++;
242 return liveProcess.run(input).pipe(
243 Effect.tapError((error) => {
244 if (error._tag === "VcsProcessExitError") stageError = error;
245 return Effect.void;
246 }),
247 );
248 },
249 }),
250 );
251 const result = yield* Effect.result(
252 captureDriver.checkpoints.captureCheckpoint({ cwd, checkpointRef }),
253 );
254 assert.strictEqual(nestedProbes, 0);
255 assert.strictEqual(stageAttempts, 1);
256 assert.strictEqual(result._tag, "Failure");
257 if (result._tag === "Failure") assert.strictEqual(result.failure, stageError);
258 assert.isFalse(yield* driver.checkpoints.hasCheckpointRef({ cwd, checkpointRef }));
259 assert.deepEqual(yield* fs.readFile(path.join(cwd, ".git", "index")), originalIndex);
260 }).pipe(Effect.scoped, Effect.provide(GitContractLayer)),
261);
262
263for (const blockedPhase of ["discovery", "probe", "retry"] as const) {
264 it.effect(`checkpoint recovery has one deadline including ${blockedPhase}`, () =>
265 Effect.gen(function* () {
266 const fs = yield* FileSystem.FileSystem;
267 const path = yield* Path.Path;
268 const liveProcess = yield* VcsProcess.VcsProcess;
269 const driver = yield* GitVcsDriver.makeVcsDriverShape();
270 const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-checkpoint-recovery-timeout-" });
271 const { git, checkpointRef } = yield* makeCheckpointFixture(driver, cwd);
272 yield* git(["init", "empty"]);
273 const originalIndex = yield* fs.readFile(path.join(cwd, ".git", "index"));
274 const entered = yield* Deferred.make<void>();
275 const discovered = yield* Deferred.make<void>();
276 let stageError: VcsProcessExitError | undefined;
277 let privateIndex: string | undefined;
278 let interrupted = false;
279 const captureDriver = yield* GitVcsDriver.makeVcsDriverShape().pipe(
280 Effect.provideService(VcsProcess.VcsProcess, {
281 run: (input) => {
282 const staging = input.args.includes("add") && input.args.includes("-A");
283 if (staging) privateIndex = input.env?.GIT_INDEX_FILE;
284 const block =
285 (blockedPhase === "discovery" && input.args.includes("--others")) ||
286 (blockedPhase === "probe" && input.cwd !== cwd && input.args.includes("rev-parse")) ||
287 (blockedPhase === "retry" &&
288 staging &&
289 input.args.some((arg) => arg.startsWith(":(exclude,literal)")));
290 if (block)
291 return (
292 blockedPhase === "retry"
293 ? fs
294 .writeFileString(
295 `${input.env!.GIT_INDEX_FILE!}.lock`,
296 "interrupted index write",
297 )
298 .pipe(Effect.orDie)
299 : Effect.void
300 ).pipe(
301 Effect.andThen(Deferred.succeed(entered, undefined)),
302 Effect.andThen(Effect.never),
303 Effect.onInterrupt(() =>
304 Effect.sync(() => {
305 interrupted = true;
306 }),
307 ),
308 );
309 return liveProcess.run(input).pipe(
310 Effect.tap(() =>
311 blockedPhase === "probe" && input.args.includes("--others")
312 ? Deferred.succeed(discovered, undefined).pipe(
313 Effect.andThen(Effect.sleep("3 seconds")),
314 )
315 : Effect.void,
316 ),
317 Effect.tapError((error) => {
318 if (staging && error._tag === "VcsProcessExitError") stageError = error;
319 return Effect.void;
320 }),
321 );
322 },
323 }),
324 );
325 const fiber = yield* captureDriver.checkpoints
326 .captureCheckpoint({ cwd, checkpointRef })
327 .pipe(Effect.flip, Effect.forkScoped);
328 if (blockedPhase === "probe") {
329 yield* Deferred.await(discovered);
330 yield* TestClock.adjust("3 seconds");
331 }
332 yield* Deferred.await(entered);
333 yield* TestClock.adjust(blockedPhase === "probe" ? "2 seconds" : "5 seconds");
334 const error = yield* Fiber.join(fiber);
335 assert.strictEqual(error, stageError);
336 assert.isTrue(interrupted);
337 assert.isDefined(privateIndex);
338 assert.isFalse(yield* fs.exists(privateIndex!));
339 assert.isFalse(yield* fs.exists(`${privateIndex!}.lock`));
340 assert.isFalse(yield* driver.checkpoints.hasCheckpointRef({ cwd, checkpointRef }));
341 assert.deepEqual(yield* fs.readFile(path.join(cwd, ".git", "index")), originalIndex);
342 }).pipe(Effect.scoped, Effect.provide(GitContractLayer)),
343 );
344}
345
346it.effect("checkpoint recovery preserves interruption and removes the private index", () =>
347 Effect.gen(function* () {
348 const fs = yield* FileSystem.FileSystem;
349 const liveProcess = yield* VcsProcess.VcsProcess;
350 const driver = yield* GitVcsDriver.makeVcsDriverShape();
351 const cwd = yield* fs.makeTempDirectoryScoped({ prefix: "t3-checkpoint-recovery-interrupt-" });
352 const { git, checkpointRef } = yield* makeCheckpointFixture(driver, cwd);
353 yield* git(["init", "empty"]);
354 const entered = yield* Deferred.make<void>();
355 let privateIndex: string | undefined;
356 const captureDriver = yield* GitVcsDriver.makeVcsDriverShape().pipe(
357 Effect.provideService(VcsProcess.VcsProcess, {
358 run: (input) => {
359 if (input.args.includes("add") && input.args.includes("-A"))
360 privateIndex = input.env?.GIT_INDEX_FILE;
361 return input.args.includes("--others")
362 ? Deferred.succeed(entered, undefined).pipe(Effect.andThen(Effect.never))
363 : liveProcess.run(input);
364 },
365 }),
366 );
367 const fiber = yield* captureDriver.checkpoints
368 .captureCheckpoint({ cwd, checkpointRef })
369 .pipe(Effect.forkScoped);
370 yield* Deferred.await(entered);
371 yield* Fiber.interrupt(fiber);
372 const exit = yield* Fiber.await(fiber);
373 assert.isTrue(Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause));
374 assert.isDefined(privateIndex);
375 assert.isFalse(yield* fs.exists(privateIndex!));
376 assert.isFalse(yield* driver.checkpoints.hasCheckpointRef({ cwd, checkpointRef }));
377 }).pipe(Effect.scoped, Effect.provide(GitContractLayer)),
378);
379
89it.effect("checkpoint capture does not rerun clean filters for unchanged indexed files", () =>380it.effect("checkpoint capture does not rerun clean filters for unchanged indexed files", () =>
90 Effect.gen(function* () {381 Effect.gen(function* () {
91 const fileSystem = yield* FileSystem.FileSystem;382 const fileSystem = yield* FileSystem.FileSystem;
apps/server/src/vcs/GitVcsDriver.ts+79-19
...@@ -379,6 +379,8 @@ export class GitVcsDriver extends Context.Service<...@@ -379,6 +379,8 @@ export class GitVcsDriver extends Context.Service<
379>()("t3/vcs/GitVcsDriver") {}379>()("t3/vcs/GitVcsDriver") {}
380380
381const WORKSPACE_FILES_MAX_OUTPUT_BYTES = 16 * 1024 * 1024;381const WORKSPACE_FILES_MAX_OUTPUT_BYTES = 16 * 1024 * 1024;
382const CHECKPOINT_RECOVERY_MAX_CANDIDATES = 64;
383const CHECKPOINT_RECOVERY_TIMEOUT = "5 seconds";
382const GIT_CHECK_IGNORE_MAX_STDIN_BYTES = 256 * 1024;384const GIT_CHECK_IGNORE_MAX_STDIN_BYTES = 256 * 1024;
383const CHECKPOINT_DIFF_MAX_OUTPUT_BYTES = 10_000_000;385const CHECKPOINT_DIFF_MAX_OUTPUT_BYTES = 10_000_000;
384const WORKSPACE_GIT_HARDENED_CONFIG_ARGS = [386const WORKSPACE_GIT_HARDENED_CONFIG_ARGS = [
...@@ -715,12 +717,13 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* (...@@ -715,12 +717,13 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* (
715 }),717 }),
716 );718 );
717719
718 const hasHeadCommit = (cwd: string) =>720 const hasHeadCommit = (cwd: string, env?: NodeJS.ProcessEnv) =>
719 execute({721 execute({
720 operation: "GitVcsDriver.checkpoints.hasHeadCommit",722 operation: "GitVcsDriver.checkpoints.hasHeadCommit",
721 cwd,723 cwd,
722 args: ["rev-parse", "--verify", "HEAD"],724 args: ["rev-parse", "--verify", "HEAD"],
723 allowNonZeroExit: true,725 allowNonZeroExit: true,
726 ...(env !== undefined ? { env } : {}),
724 }).pipe(Effect.map((result) => result.exitCode === 0));727 }).pipe(Effect.map((result) => result.exitCode === 0));
725728
726 const resolveCheckpointCommit = (cwd: string, checkpointRef: string) =>729 const resolveCheckpointCommit = (cwd: string, checkpointRef: string) =>
...@@ -784,9 +787,12 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* (...@@ -784,9 +787,12 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* (
784 GIT_COMMITTER_EMAIL: "t3code@users.noreply.github.com",787 GIT_COMMITTER_EMAIL: "t3code@users.noreply.github.com",
785 };788 };
786789
787 const cleanupTempIndex = fileSystem790 // Forced process termination can leave Git's private index lock behind.
788 .remove(tempIndexPath, { force: true })791 const cleanupTempIndex = Effect.forEach(
789 .pipe(Effect.ignore);792 [tempIndexPath, `${tempIndexPath}.lock`],
793 (indexFile) => fileSystem.remove(indexFile, { force: true }).pipe(Effect.ignore),
794 { discard: true },
795 );
790796
791 yield* Effect.gen(function* () {797 yield* Effect.gen(function* () {
792 const headExists = yield* hasHeadCommit(input.cwd);798 const headExists = yield* hasHeadCommit(input.cwd);
...@@ -914,21 +920,75 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* (...@@ -914,21 +920,75 @@ export const makeVcsDriverShape = Effect.fn("makeGitVcsDriverShape")(function* (
914 }920 }
915 }921 }
916922
917 yield* execute({923 const stageFiles = (exclusions: ReadonlyArray<string>) =>
918 operation,924 execute({
919 cwd: input.cwd,925 operation,
920 // Preserve absent skipped entries, but capture present nonignored files outside the cone.926 cwd: input.cwd,
921 args: [927 // Preserve absent skipped entries, but capture present nonignored files outside the cone.
922 ...indexConfig,928 args: [
923 ...durableWrite,929 ...indexConfig,
924 "add",930 ...durableWrite,
925 ...(sparseCheckout ? ["--sparse"] : []),931 "add",
926 "-A",932 ...(sparseCheckout ? ["--sparse"] : []),
927 "--",933 "-A",
928 ".",934 "--",
929 ],935 ".",
930 env: commitEnv,936 ...exclusions,
931 });937 ],
938 env: commitEnv,
939 });
940 yield* stageFiles([]).pipe(
941 Effect.catchTags({
942 VcsProcessExitError: (error) =>
943 Effect.gen(function* () {
944 // Git cannot stage an embedded repository until it has a commit. Discover these
945 // only after staging fails so ordinary checkpoints do not need another file scan.
946 const untracked = yield* execute({
947 operation,
948 cwd: input.cwd,
949 args: ["ls-files", "--others", "--exclude-standard", "-z", "--", "."],
950 env: commitEnv,
951 maxOutputBytes: WORKSPACE_FILES_MAX_OUTPUT_BYTES,
952 });
953 if (untracked.stdoutTruncated) return yield* error;
954 const candidates = splitNullSeparatedGitStdoutPaths(untracked).filter((entry) =>
955 entry.endsWith("/"),
956 );
957 // Refuse excessive recovery work before probing any nested repositories.
958 if (candidates.length > CHECKPOINT_RECOVERY_MAX_CANDIDATES) return yield* error;
959 // Discover each child's repository instead of inheriting the server's Git bindings.
960 const nestedRepoEnv: NodeJS.ProcessEnv = {
961 ...process.env,
962 GIT_DIR: undefined,
963 GIT_WORK_TREE: undefined,
964 GIT_COMMON_DIR: undefined,
965 GIT_INDEX_FILE: undefined,
966 GIT_OBJECT_DIRECTORY: undefined,
967 GIT_ALTERNATE_OBJECT_DIRECTORIES: undefined,
968 };
969 const exclusions: Array<string> = [];
970 for (const entry of candidates) {
971 const nestedCwd = path.join(input.cwd, entry);
972 if (
973 (yield* fileSystem
974 .exists(path.join(nestedCwd, ".git"))
975 .pipe(Effect.mapError(() => error))) &&
976 !(yield* hasHeadCommit(nestedCwd, nestedRepoEnv))
977 ) {
978 exclusions.push(`:(exclude,literal)${entry}`);
979 }
980 }
981 if (exclusions.length === 0) return yield* error;
982 return yield* stageFiles(exclusions);
983 }).pipe(
984 // One budget covers discovery, queued Git admission, probes, and the staging retry.
985 Effect.timeoutOrElse({
986 duration: CHECKPOINT_RECOVERY_TIMEOUT,
987 orElse: () => Effect.fail(error),
988 }),
989 ),
990 }),
991 );
932992
933 const writeTreeResult = yield* execute({993 const writeTreeResult = yield* execute({
934 operation,994 operation,