@aas-dev/stack 0.0.0-stage → 0.1.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/bin/aas.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import "../dist/bin.js"
package/dist/bin.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {}
package/dist/bin.js ADDED
@@ -0,0 +1,15 @@
1
+ import { main } from "./program.js";
2
+ import { NodeRuntime, NodeServices } from "@effect/platform-node";
3
+ import { Effect, Exit } from "effect";
4
+ // src/bin.ts
5
+ const teardown = (exit, onExit) => {
6
+ onExit(Exit.match(exit, {
7
+ onFailure: () => 1,
8
+ onSuccess: (code) => typeof code === "number" ? code : 1
9
+ }));
10
+ };
11
+ NodeRuntime.runMain(main(process.cwd()).pipe(Effect.provide(NodeServices.layer)), {
12
+ disableErrorReporting: true,
13
+ teardown
14
+ });
15
+ export {};
@@ -0,0 +1,5 @@
1
+ import { UserConfig } from "vite-plus";
2
+ export type AasConfig = UserConfig;
3
+ export declare const defineConfig: (options?: {
4
+ readonly ignorePatterns?: ReadonlyArray<string>;
5
+ }) => AasConfig;
package/dist/config.js ADDED
@@ -0,0 +1,75 @@
1
+ import { defineConfig as defineConfig$1 } from "vite-plus";
2
+ // src/config.ts
3
+ const pluginPath = `${import.meta.dirname}/../plugin/aas.mjs`;
4
+ const errors = (rules) => rules;
5
+ const rules = errors({
6
+ "aas/no-throw": "error",
7
+ "aas/no-try": "error",
8
+ "aas/no-error-class": "error",
9
+ "aas/no-process-env": "error",
10
+ "aas/no-type-assertion": "error",
11
+ "aas/no-explicit-any": "error",
12
+ "aas/no-non-null-assertion": "error",
13
+ "aas/no-bypass-comment": "error",
14
+ "aas/no-comments": "error",
15
+ "aas/effect-tests": "error",
16
+ "aas/no-raw-io": "error",
17
+ "aas/no-effect-run": "error",
18
+ "aas/no-module-let": "error",
19
+ "aas/no-plain-class": "error"
20
+ });
21
+ const defaultIgnore = [
22
+ "dist",
23
+ "vendor",
24
+ "node_modules",
25
+ "coverage",
26
+ ".vite-hooks/_",
27
+ "packages/fence/fixtures"
28
+ ];
29
+ const defineConfig = (options) => defineConfig$1({
30
+ lint: {
31
+ jsPlugins: [pluginPath],
32
+ options: {
33
+ denyWarnings: true,
34
+ respectEslintDisableDirectives: false
35
+ },
36
+ ignorePatterns: [...options?.ignorePatterns ?? defaultIgnore],
37
+ rules
38
+ },
39
+ fmt: {
40
+ printWidth: 100,
41
+ semi: false,
42
+ ignorePatterns: [
43
+ "node_modules",
44
+ "dist",
45
+ "vendor",
46
+ "coverage",
47
+ ".vitest",
48
+ ".vite-hooks/_"
49
+ ]
50
+ },
51
+ test: {
52
+ include: ["**/*.test.ts"],
53
+ exclude: [
54
+ "**/node_modules/**",
55
+ "**/dist/**",
56
+ "**/fixtures/**",
57
+ "**/vendor/**"
58
+ ],
59
+ passWithNoTests: false,
60
+ server: { deps: { inline: ["@effect/vitest"] } }
61
+ },
62
+ pack: {
63
+ entry: ["src/**/*.ts", "!src/**/*.test.ts"],
64
+ dts: true,
65
+ unbundle: true,
66
+ fixedExtension: false,
67
+ hash: false,
68
+ clean: true,
69
+ logLevel: "error",
70
+ failOnWarn: false,
71
+ report: false,
72
+ deps: { neverBundle: true }
73
+ }
74
+ });
75
+ export { defineConfig };
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,28 @@
1
+ import { BadHookInput } from "./errors.js";
2
+ import { writeStdout } from "./run.js";
3
+ import { commandBypassesVerify } from "./policy.js";
4
+ import { NodeRuntime, NodeServices } from "@effect/platform-node";
5
+ import { Effect, Result, Schema, Stream } from "effect";
6
+ import { Stdio } from "effect/Stdio";
7
+ // src/cursor-hook.ts
8
+ const HookInput = Schema.Struct({ command: Schema.optionalKey(Schema.String) });
9
+ const deny = JSON.stringify({
10
+ permission: "deny",
11
+ user_message: "pnpm verify cannot be skipped.",
12
+ agent_message: "Run pnpm verify. Do not pass --no-verify, a short -n on commit, LEFTHOOK=0, HUSKY=0, VP_GIT_HOOKS=0, VITE_GIT_HOOKS=0, or vp hooks disable."
13
+ });
14
+ const allow = JSON.stringify({ permission: "allow" });
15
+ const hook = Effect.gen(function* () {
16
+ const stdio = yield* Stdio;
17
+ const input = yield* Stream.mkString(Stream.decodeText(stdio.stdin));
18
+ const decoded = Schema.decodeResult(Schema.fromJsonString(HookInput))(input);
19
+ if (Result.isFailure(decoded)) return yield* new BadHookInput({});
20
+ const command = decoded.success.command ?? "";
21
+ if (command === "" || commandBypassesVerify(command)) {
22
+ yield* writeStdout(deny);
23
+ return;
24
+ }
25
+ yield* writeStdout(allow);
26
+ });
27
+ NodeRuntime.runMain(hook.pipe(Effect.provide(NodeServices.layer)), { disableErrorReporting: true });
28
+ export {};
@@ -0,0 +1,12 @@
1
+ import { Schema } from "effect";
2
+ declare const CommandFailed_base: Schema.Class<CommandFailed, Schema.TaggedStruct<"CommandFailed", {
3
+ readonly lines: Schema.$Array<Schema.String>;
4
+ }>, import("effect/Cause").YieldableError & {
5
+ readonly brand: unique symbol;
6
+ }>;
7
+ export declare class CommandFailed extends CommandFailed_base {}
8
+ declare const BadHookInput_base: Schema.Class<BadHookInput, Schema.TaggedStruct<"BadHookInput", {}>, import("effect/Cause").YieldableError & {
9
+ readonly brand: unique symbol;
10
+ }>;
11
+ export declare class BadHookInput extends BadHookInput_base {}
12
+ export {};
package/dist/errors.js ADDED
@@ -0,0 +1,5 @@
1
+ import { Schema } from "effect";
2
+ // src/errors.ts
3
+ var CommandFailed = class extends Schema.TaggedError()("CommandFailed", { lines: Schema.Array(Schema.String) }) {};
4
+ var BadHookInput = class extends Schema.TaggedError()("BadHookInput", {}) {};
5
+ export { BadHookInput, CommandFailed };
@@ -0,0 +1,3 @@
1
+ import { defineConfig } from "./config.js";
2
+ import { commandBypassesVerify } from "./policy.js";
3
+ export { commandBypassesVerify, defineConfig };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { defineConfig } from "./config.js";
2
+ import { commandBypassesVerify } from "./policy.js";
3
+ export { commandBypassesVerify, defineConfig };
@@ -0,0 +1 @@
1
+ export declare const commandBypassesVerify: (command: string) => boolean;
package/dist/policy.js ADDED
@@ -0,0 +1,124 @@
1
+ // src/policy.ts
2
+ const noVerifySubcommands = /* @__PURE__ */ new Set([
3
+ "am",
4
+ "cherry-pick",
5
+ "commit",
6
+ "merge",
7
+ "pull",
8
+ "rebase"
9
+ ]);
10
+ const globalOptionsWithValue = /* @__PURE__ */ new Set([
11
+ "-C",
12
+ "-c",
13
+ "--config-env",
14
+ "--exec-path",
15
+ "--git-dir",
16
+ "--list-cmds",
17
+ "--namespace",
18
+ "--super-prefix",
19
+ "--work-tree"
20
+ ]);
21
+ const isGitToken = (token) => token === "git" || token.endsWith("/git");
22
+ const tokenAt = (tokens, index) => {
23
+ if (index < 0 || index >= tokens.length) return "";
24
+ const token = tokens[index];
25
+ if (token === void 0 || token === "") return "";
26
+ return token;
27
+ };
28
+ const tokenize = (command) => {
29
+ const tokens = [];
30
+ let current = "";
31
+ let quote = "";
32
+ let index = 0;
33
+ while (index < command.length) {
34
+ const char = command.charAt(index);
35
+ if (quote === "" && (char === " " || char === " " || char === "\n")) {
36
+ if (current !== "") {
37
+ tokens.push(current);
38
+ current = "";
39
+ }
40
+ index += 1;
41
+ continue;
42
+ }
43
+ if (quote === "" && (char === "'" || char === "\"")) {
44
+ quote = char;
45
+ index += 1;
46
+ continue;
47
+ }
48
+ if (quote !== "" && char === quote) {
49
+ quote = "";
50
+ index += 1;
51
+ continue;
52
+ }
53
+ current += char;
54
+ index += 1;
55
+ }
56
+ if (current !== "") tokens.push(current);
57
+ return tokens;
58
+ };
59
+ const subcommandOf = (tokens) => {
60
+ let gitAt = -1;
61
+ let index = 0;
62
+ while (index < tokens.length) {
63
+ if (isGitToken(tokenAt(tokens, index))) {
64
+ gitAt = index;
65
+ break;
66
+ }
67
+ index += 1;
68
+ }
69
+ if (gitAt < 0) return {
70
+ name: "",
71
+ at: -1
72
+ };
73
+ index = gitAt + 1;
74
+ while (index < tokens.length) {
75
+ const token = tokenAt(tokens, index);
76
+ if (token === "--") return {
77
+ name: "",
78
+ at: -1
79
+ };
80
+ if (token.startsWith("-")) {
81
+ const option = token.includes("=") ? token.slice(0, token.indexOf("=")) : token;
82
+ if (globalOptionsWithValue.has(option) && !token.includes("=")) {
83
+ index += 2;
84
+ continue;
85
+ }
86
+ index += 1;
87
+ continue;
88
+ }
89
+ return {
90
+ name: token,
91
+ at: index
92
+ };
93
+ }
94
+ return {
95
+ name: "",
96
+ at: -1
97
+ };
98
+ };
99
+ const shortClusterHasN = (tokens, from) => {
100
+ let index = from;
101
+ while (index < tokens.length) {
102
+ const token = tokenAt(tokens, index);
103
+ if (token.startsWith("-") && !token.startsWith("--") && token.includes("n")) return true;
104
+ index += 1;
105
+ }
106
+ return false;
107
+ };
108
+ const tokensBypass = (tokens) => {
109
+ const sub = subcommandOf(tokens);
110
+ if (noVerifySubcommands.has(sub.name) && shortClusterHasN(tokens, sub.at + 1)) return true;
111
+ let index = 0;
112
+ while (index < tokens.length) {
113
+ const token = tokenAt(tokens, index);
114
+ if ((token.includes(" ") || token.includes("\n")) && commandBypassesVerify(token)) return true;
115
+ index += 1;
116
+ }
117
+ return false;
118
+ };
119
+ const skipsHook = (command) => command.includes("--no-verify") || command.includes("LEFTHOOK=0") || command.includes("HUSKY=0") || command.includes("VP_GIT_HOOKS=0") || command.includes("VITE_GIT_HOOKS=0") || command.includes("vp hooks disable") || command.includes("vp.hooks.disabled");
120
+ const commandBypassesVerify = (command) => {
121
+ if (skipsHook(command)) return true;
122
+ return tokensBypass(tokenize(command));
123
+ };
124
+ export { commandBypassesVerify };
@@ -0,0 +1,3 @@
1
+ import { Effect } from "effect";
2
+ import { Stdio } from "effect/Stdio";
3
+ export declare const main: (cwd: string) => Effect.Effect<number, import("effect/PlatformError").PlatformError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem | Stdio>;
@@ -0,0 +1,35 @@
1
+ import { CommandFailed } from "./errors.js";
2
+ import { writeStdout } from "./run.js";
3
+ import { init, sync } from "./scaffold.js";
4
+ import { verify } from "./verify.js";
5
+ import { Cause, Effect } from "effect";
6
+ import { Stdio } from "effect/Stdio";
7
+ // src/program.ts
8
+ const usage = "usage: aas verify | aas init | aas sync";
9
+ const main = (cwd) => Effect.gen(function* () {
10
+ const command = (yield* (yield* Stdio).args)[0];
11
+ return yield* dispatch(command, cwd).pipe(Effect.catchTag("CommandFailed", (error) => Effect.gen(function* () {
12
+ yield* writeStdout(error.lines.join("\n"));
13
+ return 1;
14
+ })), Effect.catchCause((cause) => Effect.gen(function* () {
15
+ yield* writeStdout(Cause.pretty(cause));
16
+ return 1;
17
+ })));
18
+ });
19
+ const dispatch = (command, cwd) => Effect.gen(function* () {
20
+ if (command === "verify") {
21
+ yield* verify(cwd);
22
+ return 0;
23
+ }
24
+ if (command === "init") {
25
+ yield* init(cwd);
26
+ return 0;
27
+ }
28
+ if (command === "sync") {
29
+ yield* sync(cwd);
30
+ return 0;
31
+ }
32
+ yield* writeStdout(usage);
33
+ return yield* new CommandFailed({ lines: [] });
34
+ });
35
+ export { main };
package/dist/run.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { CommandFailed } from "./errors.js";
2
+ import { Effect, FileSystem } from "effect";
3
+ import { Stdio } from "effect/Stdio";
4
+ import { ChildProcessSpawner } from "effect/process";
5
+ export declare const succeeded: (code: ChildProcessSpawner.ExitCode) => boolean;
6
+ export declare const findBin: (name: string) => Effect.Effect<string, CommandFailed | import("effect/PlatformError").PlatformError, FileSystem.FileSystem>;
7
+ export declare const runTool: (input: {
8
+ readonly bin: string;
9
+ readonly args: ReadonlyArray<string>;
10
+ readonly cwd: string;
11
+ }) => Effect.Effect<{
12
+ stdout: string;
13
+ stderr: string;
14
+ exitCode: ChildProcessSpawner.ExitCode;
15
+ }, import("effect/PlatformError").PlatformError, ChildProcessSpawner.ChildProcessSpawner>;
16
+ export declare const writeStdout: (text: string) => Effect.Effect<void, import("effect/PlatformError").PlatformError, Stdio>;
17
+ export declare const diagnosticsFrom: (text: string) => string[];
18
+ export declare const failLines: (name: string, text: string) => string[];
package/dist/run.js ADDED
@@ -0,0 +1,99 @@
1
+ import { CommandFailed } from "./errors.js";
2
+ import { Effect, FileSystem, Stream } from "effect";
3
+ import { Stdio } from "effect/Stdio";
4
+ import { ChildProcess, ChildProcessSpawner } from "effect/process";
5
+ // src/run.ts
6
+ const succeeded = (code) => code === ChildProcessSpawner.ExitCode(0);
7
+ const findBin = (name) => Effect.gen(function* () {
8
+ const fs = yield* FileSystem.FileSystem;
9
+ const segments = import.meta.dirname.split("/");
10
+ let index = segments.length;
11
+ while (index > 1) {
12
+ index -= 1;
13
+ const candidate = `${segments.slice(0, index).join("/")}/node_modules/.bin/${name}`;
14
+ if (yield* fs.exists(candidate)) return candidate;
15
+ }
16
+ return yield* new CommandFailed({ lines: [`${name}:1: missing executable ${name}`] });
17
+ });
18
+ const runTool = (input) => Effect.gen(function* () {
19
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
20
+ return yield* Effect.scoped(Effect.gen(function* () {
21
+ const handle = yield* spawner.spawn(ChildProcess.make(input.bin, Array.from(input.args), {
22
+ cwd: input.cwd,
23
+ env: {
24
+ CI: "1",
25
+ NO_COLOR: "1"
26
+ },
27
+ extendEnv: true
28
+ }));
29
+ const [stdout, stderr] = yield* Effect.all([Stream.mkString(Stream.decodeText(handle.stdout)), Stream.mkString(Stream.decodeText(handle.stderr))], { concurrency: 2 });
30
+ return {
31
+ stdout,
32
+ stderr,
33
+ exitCode: yield* handle.exitCode
34
+ };
35
+ }));
36
+ });
37
+ const writeStdout = (text) => Effect.gen(function* () {
38
+ if (text.length === 0) return;
39
+ const stdio = yield* Stdio;
40
+ const body = text.endsWith("\n") ? text : `${text}\n`;
41
+ yield* Stream.run(Stream.make(body), stdio.stdout());
42
+ });
43
+ const lintLine = /^(.*?):(\d+):\d+:\s*(.*)$/u;
44
+ const tscLine = /^(.*?)\((\d+),\d+\):\s*(.*)$/u;
45
+ const formatLine = /^(\S+\.[A-Za-z0-9]+)(?:\s+\(\d+ms\))?$/u;
46
+ const escape = String.fromCharCode(27);
47
+ const stripAnsi = (text) => {
48
+ let result = "";
49
+ let index = 0;
50
+ while (index < text.length) {
51
+ if (text.charAt(index) === escape && text.charAt(index + 1) === "[") {
52
+ index += 2;
53
+ while (index < text.length) {
54
+ const code = text.charCodeAt(index);
55
+ index += 1;
56
+ if (code >= 64 && code <= 126) break;
57
+ }
58
+ continue;
59
+ }
60
+ result += text.charAt(index);
61
+ index += 1;
62
+ }
63
+ return result;
64
+ };
65
+ const pushUnique = (lines, line) => {
66
+ if (!lines.includes(line)) lines.push(line);
67
+ };
68
+ const diagnosticsFrom = (text) => {
69
+ const lines = [];
70
+ for (const raw of stripAnsi(text).split("\n")) {
71
+ const trimmed = raw.trim();
72
+ if (trimmed === "") continue;
73
+ const lint = lintLine.exec(trimmed);
74
+ const lintFile = lint?.[1];
75
+ const lintNo = lint?.[2];
76
+ const lintMessage = lint?.[3];
77
+ if (lintFile !== void 0 && lintNo !== void 0 && lintMessage !== void 0) {
78
+ pushUnique(lines, `${lintFile}:${lintNo}: ${lintMessage}`);
79
+ continue;
80
+ }
81
+ const tsc = tscLine.exec(trimmed);
82
+ const tscFile = tsc?.[1];
83
+ const tscNo = tsc?.[2];
84
+ const tscMessage = tsc?.[3];
85
+ if (tscFile !== void 0 && tscNo !== void 0 && tscMessage !== void 0) {
86
+ pushUnique(lines, `${tscFile}:${tscNo}: ${tscMessage}`);
87
+ continue;
88
+ }
89
+ const formattedFile = formatLine.exec(trimmed)?.[1];
90
+ if (formattedFile !== void 0 && !formattedFile.includes("://")) pushUnique(lines, `${formattedFile}:1: format`);
91
+ }
92
+ return lines;
93
+ };
94
+ const failLines = (name, text) => {
95
+ const lines = diagnosticsFrom(text);
96
+ if (lines.length > 0) return lines;
97
+ return [`${name}:1: ${text.split("\n").map((line) => line.trim()).find((line) => line !== "") ?? "failed"}`];
98
+ };
99
+ export { diagnosticsFrom, failLines, findBin, runTool, succeeded, writeStdout };
@@ -0,0 +1,5 @@
1
+ import { CommandFailed } from "./errors.js";
2
+ import { Effect, FileSystem } from "effect";
3
+ export declare const writeTemplates: (cwd: string) => Effect.Effect<void, import("effect/PlatformError").PlatformError, FileSystem.FileSystem>;
4
+ export declare const init: (cwd: string) => Effect.Effect<void, CommandFailed | import("effect/PlatformError").PlatformError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem>;
5
+ export declare const sync: typeof writeTemplates;
@@ -0,0 +1,55 @@
1
+ import { CommandFailed } from "./errors.js";
2
+ import { findBin, runTool, succeeded } from "./run.js";
3
+ import { managedFiles, readTemplate } from "./templates.js";
4
+ import { Effect, FileSystem } from "effect";
5
+ // src/scaffold.ts
6
+ const parentOf = (path) => {
7
+ const slash = path.lastIndexOf("/");
8
+ if (slash <= 0) return "";
9
+ return path.slice(0, slash);
10
+ };
11
+ const writeTemplates = (cwd) => Effect.gen(function* () {
12
+ const fs = yield* FileSystem.FileSystem;
13
+ for (const file of managedFiles) {
14
+ const text = yield* readTemplate(file.template);
15
+ const target = `${cwd}/${file.path}`;
16
+ const parent = parentOf(target);
17
+ if (parent !== "") yield* fs.makeDirectory(parent, { recursive: true });
18
+ yield* fs.writeFileString(target, text);
19
+ }
20
+ });
21
+ const installHooks = (cwd) => Effect.gen(function* () {
22
+ const git = yield* runTool({
23
+ bin: "git",
24
+ args: ["rev-parse", "--git-dir"],
25
+ cwd
26
+ });
27
+ if (!succeeded(git.exitCode)) return;
28
+ const hooksPath = yield* runTool({
29
+ bin: "git",
30
+ args: [
31
+ "config",
32
+ "--get",
33
+ "core.hooksPath"
34
+ ],
35
+ cwd
36
+ });
37
+ if (succeeded(hooksPath.exitCode)) return;
38
+ const vp = yield* findBin("vp");
39
+ const installed = yield* runTool({
40
+ bin: vp,
41
+ args: ["hooks", "enable"],
42
+ cwd
43
+ });
44
+ if (!succeeded(installed.exitCode)) return yield* new CommandFailed({ lines: failOr(installed.stdout, installed.stderr) });
45
+ });
46
+ const failOr = (stdout, stderr) => {
47
+ const text = `${stdout}\n${stderr}`.trim();
48
+ return [`vp:1: ${text === "" ? "vp hooks enable failed" : text.split("\n")[0] ?? "failed"}`];
49
+ };
50
+ const init = (cwd) => Effect.gen(function* () {
51
+ yield* writeTemplates(cwd);
52
+ yield* installHooks(cwd);
53
+ });
54
+ const sync = writeTemplates;
55
+ export { init, sync, writeTemplates };
@@ -0,0 +1,6 @@
1
+ import { Effect, FileSystem } from "effect";
2
+ export declare const managedFiles: ReadonlyArray<{
3
+ readonly template: string;
4
+ readonly path: string;
5
+ }>;
6
+ export declare const readTemplate: (name: string) => Effect.Effect<string, import("effect/PlatformError").PlatformError, FileSystem.FileSystem>;
@@ -0,0 +1,37 @@
1
+ import { Effect, FileSystem } from "effect";
2
+ // src/templates.ts
3
+ const managedFiles = [
4
+ {
5
+ template: "hooks.json",
6
+ path: ".cursor/hooks.json"
7
+ },
8
+ {
9
+ template: "pre-commit",
10
+ path: ".vite-hooks/pre-commit"
11
+ },
12
+ {
13
+ template: "pnpm-workspace.yaml",
14
+ path: "pnpm-workspace.yaml"
15
+ },
16
+ {
17
+ template: "AGENTS.md",
18
+ path: "AGENTS.md"
19
+ },
20
+ {
21
+ template: "verify.yml",
22
+ path: ".github/workflows/verify.yml"
23
+ },
24
+ {
25
+ template: "vite.config.ts",
26
+ path: "vite.config.ts"
27
+ },
28
+ {
29
+ template: "tsconfig.json",
30
+ path: "tsconfig.json"
31
+ }
32
+ ];
33
+ const templateRoot = `${import.meta.dirname}/../templates`;
34
+ const readTemplate = (name) => Effect.gen(function* () {
35
+ return yield* (yield* FileSystem.FileSystem).readFileString(`${templateRoot}/${name}`);
36
+ });
37
+ export { managedFiles, readTemplate };
@@ -0,0 +1,3 @@
1
+ import { CommandFailed } from "./errors.js";
2
+ import { Effect, FileSystem } from "effect";
3
+ export declare const verify: (cwd: string) => Effect.Effect<undefined, CommandFailed | import("effect/PlatformError").PlatformError, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem>;