From 4d545f2e0e21456a8720871fbb1c2798129aa7ec Mon Sep 17 00:00:00 2001 From: Jakob Heuser Date: Fri, 18 Sep 2026 11:10:03 -0700 Subject: [PATCH 1/4] feat(rules): flag the process global in files that do not import node:process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An ast-grep rule, prefer-node-process, reports a bare `process` identifier in packages/cli/src when the file has no `import … from "node:process"` and declares no binding named `process` (const/let/var, parameter, or catch clause). A file that shadows the name anywhere is treated as clean for the whole file, and `globalThis.process` is a property access and out of scope. Reference behaviour is ESLint n/prefer-global/process: ["error", "never"]. No fix is attempted: an import needs placement. --- .../prefer-node-process-20260918-test.yml | 45 ++++++++++++ .../prefer-node-process.yml | 69 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 .taskless/rules/sg/prefer-node-process/.tests/prefer-node-process-20260918-test.yml create mode 100644 .taskless/rules/sg/prefer-node-process/prefer-node-process.yml diff --git a/.taskless/rules/sg/prefer-node-process/.tests/prefer-node-process-20260918-test.yml b/.taskless/rules/sg/prefer-node-process/.tests/prefer-node-process-20260918-test.yml new file mode 100644 index 00000000..d907c4dd --- /dev/null +++ b/.taskless/rules/sg/prefer-node-process/.tests/prefer-node-process-20260918-test.yml @@ -0,0 +1,45 @@ +id: prefer-node-process +valid: + - | + import process from "node:process"; + const ci = process.env.CI === "true"; + - | + import process from "node:process"; + import { join } from "node:path"; + process.exitCode = 1; + console.log(join(process.cwd(), "dist")); + - | + import { env } from "node:process"; + const home = env.HOME; + - | + const process = spawn("node", ["dist/index.js"]); + process.stdout.on("data", () => {}); + - | + function kill(process: ChildProcess) { + process.kill(); + } + - | + const run = (process?: ChildProcess) => process?.pid; + - | + const settings = { process: "batch" }; + const mode = settings.process; + - | + import { execFile } from "node:child_process"; + execFile("git", ["status"]); + - | + const nodeProcess = globalThis.process; +invalid: + - | + const ci = process.env.CI === "true"; + - | + import { join } from "node:path"; + console.log(join(process.cwd(), "dist")); + - | + process.exitCode = 1; + - | + export function isTTY(): boolean { + return process.stdout.isTTY === true; + } + - | + import type { Process } from "./types"; + const { env } = process; diff --git a/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml b/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml new file mode 100644 index 00000000..50ee6c49 --- /dev/null +++ b/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml @@ -0,0 +1,69 @@ +id: prefer-node-process +language: TypeScript +severity: error +message: Import process from "node:process" instead of reaching for the global. +note: | + An explicit `import process from "node:process";` makes the Node + dependency visible in the module graph: a build-time check that reads + rollup's resolved imports can see an import, but not a reach for a + global. It is also the convention every other Node built-in here + already follows (`node:path`, `node:fs`, `node:child_process`). + + Reference behaviour: ESLint `n/prefer-global/process: ["error", "never"]`. + + There is no auto-fix. An import needs placement (Node built-ins first, + grouped, per .conventions/STYLEGUIDE-CODE.md), so the finding names the + file and you add the line by hand. + + What the rule matches: a bare `process` identifier in a file that has + no `import … from "node:process"` and declares no binding named + `process` anywhere (a `const`/`let`/`var`, a parameter, or a `catch` + clause). A file that shadows the name at any depth is treated as clean + for the whole file, which errs toward silence rather than a false + finding. `globalThis.process` is a property access, not an identifier + reference, and is out of scope. +files: + - "packages/cli/src/**/*.ts" +ignores: + - ".github/scripts/**" +rule: + kind: identifier + regex: '^process$' + not: + inside: + stopBy: end + kind: import_statement + inside: + stopBy: end + kind: program + not: + any: + - has: + kind: import_statement + has: + stopBy: end + kind: string_fragment + regex: '^node:process$' + - has: + stopBy: end + any: + - kind: variable_declarator + has: + field: name + kind: identifier + regex: '^process$' + - kind: required_parameter + has: + field: pattern + kind: identifier + regex: '^process$' + - kind: optional_parameter + has: + field: pattern + kind: identifier + regex: '^process$' + - kind: catch_clause + has: + field: parameter + kind: identifier + regex: '^process$' From 08551a2fa910efb7161a45571854c1ffb4575e0e Mon Sep 17 00:00:00 2001 From: Jakob Heuser Date: Fri, 18 Sep 2026 11:10:09 -0700 Subject: [PATCH 2/4] refactor(cli): import process from node:process Add `import process from "node:process";` to the 27 files under packages/cli/src that reached for the global, placed in the Node built-ins group per .conventions/STYLEGUIDE-CODE.md. Nothing else changes in these files; this is what makes the prefer-node-process rule land green. --- packages/cli/src/api/config.ts | 1 + packages/cli/src/auth/login-interactive.ts | 2 ++ packages/cli/src/auth/token.ts | 1 + packages/cli/src/commands/agent.ts | 1 + packages/cli/src/commands/auth.ts | 1 + packages/cli/src/commands/check.ts | 1 + packages/cli/src/commands/demo.ts | 1 + packages/cli/src/commands/detect.ts | 1 + packages/cli/src/commands/feedback.ts | 1 + packages/cli/src/commands/info.ts | 1 + packages/cli/src/commands/init.ts | 1 + packages/cli/src/commands/onboard.ts | 1 + packages/cli/src/commands/rules.ts | 1 + packages/cli/src/commands/verify.ts | 1 + packages/cli/src/filesystem/migrate.ts | 1 + packages/cli/src/index.ts | 2 ++ packages/cli/src/rules/platform-binary.ts | 1 + packages/cli/src/rules/runtime/invoke.ts | 1 + packages/cli/src/rules/runtime/narrow.ts | 1 + packages/cli/src/rules/scan.ts | 1 + packages/cli/src/rules/vale/run.ts | 1 + packages/cli/src/rules/verify.ts | 1 + packages/cli/src/telemetry-run.ts | 1 + packages/cli/src/telemetry.ts | 1 + packages/cli/src/util/adoption-dimensions.ts | 1 + packages/cli/src/util/color.ts | 2 ++ packages/cli/src/util/package-manager.ts | 2 ++ 27 files changed, 31 insertions(+) diff --git a/packages/cli/src/api/config.ts b/packages/cli/src/api/config.ts index 6c6ab607..a659226b 100644 --- a/packages/cli/src/api/config.ts +++ b/packages/cli/src/api/config.ts @@ -1,5 +1,6 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; +import process from "node:process"; import { getConfigDirectory } from "../auth/token"; diff --git a/packages/cli/src/auth/login-interactive.ts b/packages/cli/src/auth/login-interactive.ts index 8db04bf6..3e85744f 100644 --- a/packages/cli/src/auth/login-interactive.ts +++ b/packages/cli/src/auth/login-interactive.ts @@ -1,3 +1,5 @@ +import process from "node:process"; + import { deviceFlowProvider } from "./device-flow"; import { getToken, saveToken } from "./token"; import { resolveRepositoryUrl } from "../util/git-remote"; diff --git a/packages/cli/src/auth/token.ts b/packages/cli/src/auth/token.ts index 38fdabf2..150c6215 100644 --- a/packages/cli/src/auth/token.ts +++ b/packages/cli/src/auth/token.ts @@ -3,6 +3,7 @@ import { existsSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; import { mkdir, readFile, rm, writeFile } from "node:fs/promises"; +import process from "node:process"; import { addToGitignore } from "../filesystem/gitignore"; import { getCliPrefix } from "../util/package-manager"; diff --git a/packages/cli/src/commands/agent.ts b/packages/cli/src/commands/agent.ts index 65988867..54cedade 100644 --- a/packages/cli/src/commands/agent.ts +++ b/packages/cli/src/commands/agent.ts @@ -1,4 +1,5 @@ import { resolve } from "node:path"; +import process from "node:process"; import { defineCommand, diff --git a/packages/cli/src/commands/auth.ts b/packages/cli/src/commands/auth.ts index 0c45ee75..170c450b 100644 --- a/packages/cli/src/commands/auth.ts +++ b/packages/cli/src/commands/auth.ts @@ -1,4 +1,5 @@ import { resolve } from "node:path"; +import process from "node:process"; import { defineCommand } from "citty"; import { loginInteractive } from "../auth/login-interactive"; diff --git a/packages/cli/src/commands/check.ts b/packages/cli/src/commands/check.ts index 4f237aa7..d3a51402 100644 --- a/packages/cli/src/commands/check.ts +++ b/packages/cli/src/commands/check.ts @@ -1,5 +1,6 @@ import { resolve, isAbsolute, relative } from "node:path"; import { stat } from "node:fs/promises"; +import process from "node:process"; import { defineCommand } from "citty"; import { hasValeRules, runEngines } from "../rules/dispatch"; diff --git a/packages/cli/src/commands/demo.ts b/packages/cli/src/commands/demo.ts index c91bdc1c..843ee1ba 100644 --- a/packages/cli/src/commands/demo.ts +++ b/packages/cli/src/commands/demo.ts @@ -1,5 +1,6 @@ import { stat } from "node:fs/promises"; import { resolve } from "node:path"; +import process from "node:process"; import { defineCommand } from "citty"; diff --git a/packages/cli/src/commands/detect.ts b/packages/cli/src/commands/detect.ts index f0be6b32..79d6e608 100644 --- a/packages/cli/src/commands/detect.ts +++ b/packages/cli/src/commands/detect.ts @@ -1,4 +1,5 @@ import { resolve } from "node:path"; +import process from "node:process"; import { defineCommand } from "citty"; diff --git a/packages/cli/src/commands/feedback.ts b/packages/cli/src/commands/feedback.ts index abf92843..bbf6028e 100644 --- a/packages/cli/src/commands/feedback.ts +++ b/packages/cli/src/commands/feedback.ts @@ -1,5 +1,6 @@ import { readFile } from "node:fs/promises"; import { resolve } from "node:path"; +import process from "node:process"; import { defineCommand } from "citty"; import { ZodError } from "zod"; diff --git a/packages/cli/src/commands/info.ts b/packages/cli/src/commands/info.ts index 979b989b..86b94cf9 100644 --- a/packages/cli/src/commands/info.ts +++ b/packages/cli/src/commands/info.ts @@ -1,4 +1,5 @@ import { join, resolve } from "node:path"; +import process from "node:process"; import { defineCommand } from "citty"; import { checkStaleness } from "../install/install"; diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 748df729..9cc1ae23 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -1,4 +1,5 @@ import { join, resolve } from "node:path"; +import process from "node:process"; import { defineCommand } from "citty"; import { ensureTasklessDirectory } from "../filesystem/directory"; diff --git a/packages/cli/src/commands/onboard.ts b/packages/cli/src/commands/onboard.ts index b934d943..308de480 100644 --- a/packages/cli/src/commands/onboard.ts +++ b/packages/cli/src/commands/onboard.ts @@ -1,4 +1,5 @@ import { resolve } from "node:path"; +import process from "node:process"; import { defineCommand } from "citty"; diff --git a/packages/cli/src/commands/rules.ts b/packages/cli/src/commands/rules.ts index a4cb2df2..37b491b6 100644 --- a/packages/cli/src/commands/rules.ts +++ b/packages/cli/src/commands/rules.ts @@ -1,5 +1,6 @@ import { resolve } from "node:path"; import { readFile } from "node:fs/promises"; +import process from "node:process"; import { defineCommand } from "citty"; import { ZodError } from "zod"; diff --git a/packages/cli/src/commands/verify.ts b/packages/cli/src/commands/verify.ts index b19a30c6..bc072493 100644 --- a/packages/cli/src/commands/verify.ts +++ b/packages/cli/src/commands/verify.ts @@ -1,4 +1,5 @@ import { resolve } from "node:path"; +import process from "node:process"; import { defineCommand } from "citty"; diff --git a/packages/cli/src/filesystem/migrate.ts b/packages/cli/src/filesystem/migrate.ts index 57cd0097..43af2310 100644 --- a/packages/cli/src/filesystem/migrate.ts +++ b/packages/cli/src/filesystem/migrate.ts @@ -1,5 +1,6 @@ import { readFile, writeFile } from "node:fs/promises"; import { join } from "node:path"; +import process from "node:process"; import { CLIError } from "../util/cli-error"; import { buildInvocation } from "../util/invocation"; diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index d7658efa..4369a572 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,3 +1,5 @@ +import process from "node:process"; + import { defineCommand, runCommand, showUsage } from "citty"; import { createAgentCommand } from "./commands/agent"; diff --git a/packages/cli/src/rules/platform-binary.ts b/packages/cli/src/rules/platform-binary.ts index 9025dfb9..caaf8ca0 100644 --- a/packages/cli/src/rules/platform-binary.ts +++ b/packages/cli/src/rules/platform-binary.ts @@ -2,6 +2,7 @@ import { spawnSync } from "node:child_process"; import { existsSync } from "node:fs"; import { createRequire } from "node:module"; import { dirname, resolve } from "node:path"; +import process from "node:process"; import { fileURLToPath } from "node:url"; /** diff --git a/packages/cli/src/rules/runtime/invoke.ts b/packages/cli/src/rules/runtime/invoke.ts index 3a00ae91..39d62a88 100644 --- a/packages/cli/src/rules/runtime/invoke.ts +++ b/packages/cli/src/rules/runtime/invoke.ts @@ -4,6 +4,7 @@ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; import { readFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; +import process from "node:process"; import type { Finding, Match } from "../../types/runtime-rule"; diff --git a/packages/cli/src/rules/runtime/narrow.ts b/packages/cli/src/rules/runtime/narrow.ts index d3c5cefd..81210af1 100644 --- a/packages/cli/src/rules/runtime/narrow.ts +++ b/packages/cli/src/rules/runtime/narrow.ts @@ -1,6 +1,7 @@ import { spawn } from "node:child_process"; import { copyFile, mkdtemp, mkdir, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; +import process from "node:process"; import { createInterface } from "node:readline"; import { join } from "node:path"; import { StringDecoder } from "node:string_decoder"; diff --git a/packages/cli/src/rules/scan.ts b/packages/cli/src/rules/scan.ts index 3f5c5815..8e4ed5f5 100644 --- a/packages/cli/src/rules/scan.ts +++ b/packages/cli/src/rules/scan.ts @@ -1,5 +1,6 @@ import { spawn } from "node:child_process"; import { dirname, resolve } from "node:path"; +import process from "node:process"; import { createInterface } from "node:readline"; import { StringDecoder } from "node:string_decoder"; import { fileURLToPath } from "node:url"; diff --git a/packages/cli/src/rules/vale/run.ts b/packages/cli/src/rules/vale/run.ts index 6357ae0b..1707afcc 100644 --- a/packages/cli/src/rules/vale/run.ts +++ b/packages/cli/src/rules/vale/run.ts @@ -1,6 +1,7 @@ import { spawn } from "node:child_process"; import { stat } from "node:fs/promises"; import { isAbsolute, join, resolve as resolvePath } from "node:path"; +import process from "node:process"; import { StringDecoder } from "node:string_decoder"; import type { CheckResult } from "../../types/check"; diff --git a/packages/cli/src/rules/verify.ts b/packages/cli/src/rules/verify.ts index 702c9fa2..6522f81a 100644 --- a/packages/cli/src/rules/verify.ts +++ b/packages/cli/src/rules/verify.ts @@ -1,6 +1,7 @@ import { readFile, readdir } from "node:fs/promises"; import { join } from "node:path"; import { spawn } from "node:child_process"; +import process from "node:process"; import { StringDecoder } from "node:string_decoder"; import { stripVTControlCharacters } from "node:util"; diff --git a/packages/cli/src/telemetry-run.ts b/packages/cli/src/telemetry-run.ts index 4404040c..6d49c384 100644 --- a/packages/cli/src/telemetry-run.ts +++ b/packages/cli/src/telemetry-run.ts @@ -1,4 +1,5 @@ import { resolve } from "node:path"; +import process from "node:process"; import type { TelemetryClient } from "./telemetry"; import { splitRawArguments } from "./util/argv"; diff --git a/packages/cli/src/telemetry.ts b/packages/cli/src/telemetry.ts index 55af0a1f..1b04822a 100644 --- a/packages/cli/src/telemetry.ts +++ b/packages/cli/src/telemetry.ts @@ -1,6 +1,7 @@ import { randomUUID } from "node:crypto"; import { mkdir, readFile, writeFile } from "node:fs/promises"; import { join } from "node:path"; +import process from "node:process"; import { PostHog } from "posthog-node"; import { decodeJwt } from "jose"; diff --git a/packages/cli/src/util/adoption-dimensions.ts b/packages/cli/src/util/adoption-dimensions.ts index ea9c5989..a118c25e 100644 --- a/packages/cli/src/util/adoption-dimensions.ts +++ b/packages/cli/src/util/adoption-dimensions.ts @@ -2,6 +2,7 @@ import { execFile } from "node:child_process"; import { createHash } from "node:crypto"; import { existsSync } from "node:fs"; import { resolve } from "node:path"; +import process from "node:process"; import { LANGUAGE_MARKERS } from "../detect/scan"; import { resolveRepositoryPath } from "./git-remote"; diff --git a/packages/cli/src/util/color.ts b/packages/cli/src/util/color.ts index 86e5913a..311235be 100644 --- a/packages/cli/src/util/color.ts +++ b/packages/cli/src/util/color.ts @@ -1,3 +1,5 @@ +import process from "node:process"; + import chalk from "chalk"; /** diff --git a/packages/cli/src/util/package-manager.ts b/packages/cli/src/util/package-manager.ts index 024281d5..73279424 100644 --- a/packages/cli/src/util/package-manager.ts +++ b/packages/cli/src/util/package-manager.ts @@ -1,3 +1,5 @@ +import process from "node:process"; + import { buildInvocation } from "./invocation"; /** From 335fc8e21c396aebcfd79ee83a77e9e38ca574c5 Mon Sep 17 00:00:00 2001 From: Jakob Heuser Date: Fri, 18 Sep 2026 11:16:49 -0700 Subject: [PATCH 3/4] feat(rules): scope process shadowing to ancestors and always flag globalThis.process The shadow check now walks the reference's ancestors instead of the whole file: an enclosing function, arrow, or method binding a `process` parameter, an enclosing `catch (process)`, or an enclosing block (or the file) whose direct child declares `process`, including an exported one. A binding in a sibling scope no longer silences a global reach elsewhere in the file. `globalThis.process` is now an independent finding regardless of imports or shadowing: it is the same reach with the global spelled out. --- .../prefer-node-process-20260918-test.yml | 63 +++++++- .../prefer-node-process.yml | 134 ++++++++++++------ 2 files changed, 151 insertions(+), 46 deletions(-) diff --git a/.taskless/rules/sg/prefer-node-process/.tests/prefer-node-process-20260918-test.yml b/.taskless/rules/sg/prefer-node-process/.tests/prefer-node-process-20260918-test.yml index d907c4dd..696ccfa4 100644 --- a/.taskless/rules/sg/prefer-node-process/.tests/prefer-node-process-20260918-test.yml +++ b/.taskless/rules/sg/prefer-node-process/.tests/prefer-node-process-20260918-test.yml @@ -14,20 +14,48 @@ valid: - | const process = spawn("node", ["dist/index.js"]); process.stdout.on("data", () => {}); + - | + export const process = spawn("node", ["dist/index.js"]); + process.stdout.on("data", () => {}); - | function kill(process: ChildProcess) { process.kill(); } - | const run = (process?: ChildProcess) => process?.pid; + - | + const pid = (process) => process.pid; + - | + class Runner { + stop(process: ChildProcess) { + return process.kill(); + } + } + - | + try { + run(); + } catch (process) { + console.error(process); + } + - | + function main() { + const process = spawn("git", ["status"]); + if (process.pid) { + process.stdout.on("data", () => {}); + } + } + - | + function outer() { + const process = spawn("git", ["status"]); + const inner = () => process.pid; + return inner(); + } - | const settings = { process: "batch" }; const mode = settings.process; - | import { execFile } from "node:child_process"; execFile("git", ["status"]); - - | - const nodeProcess = globalThis.process; invalid: - | const ci = process.env.CI === "true"; @@ -43,3 +71,34 @@ invalid: - | import type { Process } from "./types"; const { env } = process; + - | + function kill(process: ChildProcess) { + process.kill(); + } + function cwd() { + return process.cwd(); + } + - | + function main() { + { + const process = spawn("git", ["status"]); + process.stdout.on("data", () => {}); + } + return process.cwd(); + } + - | + try { + run(); + } catch (process) { + console.error(process); + } + process.exitCode = 1; + - | + const nodeProcess = globalThis.process; + - | + import process from "node:process"; + const home = globalThis.process.env.HOME; + - | + function main(process: ChildProcess) { + return globalThis.process.cwd(); + } diff --git a/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml b/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml index 50ee6c49..7a18e7f3 100644 --- a/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml +++ b/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml @@ -15,55 +15,101 @@ note: | grouped, per .conventions/STYLEGUIDE-CODE.md), so the finding names the file and you add the line by hand. - What the rule matches: a bare `process` identifier in a file that has - no `import … from "node:process"` and declares no binding named - `process` anywhere (a `const`/`let`/`var`, a parameter, or a `catch` - clause). A file that shadows the name at any depth is treated as clean - for the whole file, which errs toward silence rather than a false - finding. `globalThis.process` is a property access, not an identifier - reference, and is out of scope. + Two forms are reported: + + - A bare `process` identifier in a file with no `import … from + "node:process"`, unless an ANCESTOR of the reference binds the name: + an enclosing function, arrow, or method with a parameter named + `process`, an enclosing `catch (process)`, or an enclosing block (or + the file itself) holding a `const`/`let`/`var` declarator named + `process`. A binding in a sibling scope does not count, so a shadow + in one function does not silence a global reach in another. + - `globalThis.process`, always. It is the same reach with the global + spelled out, and no import or shadow makes it the module-graph + dependency this rule asks for. Import and use `process` instead. files: - "packages/cli/src/**/*.ts" ignores: - ".github/scripts/**" rule: - kind: identifier - regex: '^process$' - not: - inside: - stopBy: end - kind: import_statement - inside: - stopBy: end - kind: program - not: - any: - - has: - kind: import_statement - has: + any: + - pattern: globalThis.process + - kind: identifier + regex: '^process$' + all: + - not: + inside: stopBy: end - kind: string_fragment - regex: '^node:process$' - - has: + kind: import_statement + - inside: stopBy: end - any: - - kind: variable_declarator - has: - field: name - kind: identifier - regex: '^process$' - - kind: required_parameter - has: - field: pattern - kind: identifier - regex: '^process$' - - kind: optional_parameter + kind: program + not: + has: + kind: import_statement has: - field: pattern - kind: identifier - regex: '^process$' - - kind: catch_clause - has: - field: parameter - kind: identifier - regex: '^process$' + stopBy: end + kind: string_fragment + regex: '^node:process$' + - not: + inside: + stopBy: end + any: + # an enclosing function whose parameter list binds `process` + - any: + - kind: function_declaration + - kind: function_expression + - kind: generator_function_declaration + - kind: generator_function + - kind: arrow_function + - kind: method_definition + has: + field: parameters + has: + any: + - kind: required_parameter + - kind: optional_parameter + has: + field: pattern + kind: identifier + regex: '^process$' + # `process => …`: a single unparenthesised arrow parameter + - kind: arrow_function + has: + field: parameter + kind: identifier + regex: '^process$' + # an enclosing `catch (process)` + - kind: catch_clause + has: + field: parameter + kind: identifier + regex: '^process$' + # an enclosing block, or the file, declaring `process` as a + # direct child: a `const`/`let`/`var`, or an `export` of one + - any: + - kind: statement_block + - kind: program + has: + any: + - any: + - kind: lexical_declaration + - kind: variable_declaration + has: + kind: variable_declarator + has: + field: name + kind: identifier + regex: '^process$' + - kind: export_statement + has: + field: declaration + any: + - kind: lexical_declaration + - kind: variable_declaration + has: + kind: variable_declarator + has: + field: name + kind: identifier + regex: '^process$' From 1bdf9f737f9ce5e70fd142667b106760a2ce3706 Mon Sep 17 00:00:00 2001 From: Jakob Heuser Date: Fri, 18 Sep 2026 12:58:28 -0700 Subject: [PATCH 4/4] chore(rules): drop the unreachable ignores entry from prefer-node-process --- .taskless/rules/sg/prefer-node-process/prefer-node-process.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml b/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml index 7a18e7f3..57ed91c3 100644 --- a/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml +++ b/.taskless/rules/sg/prefer-node-process/prefer-node-process.yml @@ -29,8 +29,6 @@ note: | dependency this rule asks for. Import and use `process` instead. files: - "packages/cli/src/**/*.ts" -ignores: - - ".github/scripts/**" rule: any: - pattern: globalThis.process