Public: anyone can read this; the crew can change it.

Every place the forge starts a process is listed in one test, each with the reason its arguments are never a person's text #10942

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`test/spawn-sites.test.ts` now lists every file under `src/` that starts a process: 34 files, each with one line saying why its arguments are fixed or validated. The test scans `src/` for `Bun.spawn`, `Bun.spawnSync`, `Bun.$`, `spawn` or `$` imported from `"bun"`, and `child_process`. A process-starting file that isn't on the list fails the test, which names the file. So does a listed file that no…

shipped production is serving it deploy cca14ac

opened this

test/spawn-sites.test.ts now lists every file under src/ that starts a process: 34 files, each with one line saying why its arguments are fixed or validated. The test scans src/ for Bun.spawn, Bun.spawnSync, Bun.$, spawn or $ imported from "bun", and child_process. A process-starting file that isn't on the list fails the test, which names the file. So does a listed file that no longer starts a process. docs/ARCHITECTURE.md gets one line under Hygiene saying where the list lives. No behaviour changes.

What to look at:

  • The reasons are the review. They describe what the arguments are; they don't say no person's text ever reaches them. Three places carry text someone wrote, and their entries say so:

- src/apps/process.ts and src/apps/tty.ts run a repository's forge.json command through /bin/sh -c when there is no cell. That command is written by someone with write access to the repository, not taken from a request. - src/crew/claude.ts and src/crew/plan.ts pass an issue's text as a single prompt argument after its flag, never through a shell.

  • Count: the issue estimated 37 files. The real count is 34: the rough grep also caught test files inside src/ (*.test.ts, which the scan skips), mentions in comments and regex $ signs. The test checks itself that comments, typeof Bun.spawn and regex $ don't count as sites.
  • What's left out: the check is per file, not per call, so a second spawn added to a listed file isn't flagged. A per-call list would break every time code shifted lines. I also didn't cover processes started indirectly, such as new Worker.

The keep_plan tool wasn't available in this run, so the issue's plan wasn't updated.

To try it: bun test test/spawn-sites.test.ts passes (5 tests). Add Bun.spawn(["ls"]) to any file in src/ and it fails, naming that file. bun scripts/gate.ts and bun x tsc --noEmit both pass.

🤖 Generated with Claude Code

Closes #10934

commented

test/spawn-sites.test.ts now lists every file under src/ that starts a process: 34 files, each with one line saying why its arguments are fixed or validated. The test scans src/ for Bun.spawn, Bun.spawnSync, Bun.$, spawn or $ imported from "bun", and child_process. A process-starting file that isn't on the list fails the test, which names the file. So does a listed file that no longer starts a process. docs/ARCHITECTURE.md gets one line under Hygiene saying where the list lives. No behaviour changes.

What to look at:

  • The reasons are the review. They describe what the arguments are; they don't say no person's text ever reaches them. Three places carry text someone wrote, and their entries say so:

- src/apps/process.ts and src/apps/tty.ts run a repository's forge.json command through /bin/sh -c when there is no cell. That command is written by someone with write access to the repository, not taken from a request. - src/crew/claude.ts and src/crew/plan.ts pass an issue's text as a single prompt argument after its flag, never through a shell.

  • Count: the issue estimated 37 files. The real count is 34: the rough grep also caught test files inside src/ (*.test.ts, which the scan skips), mentions in comments and regex $ signs. The test checks itself that comments, typeof Bun.spawn and regex $ don't count as sites.
  • What's left out: the check is per file, not per call, so a second spawn added to a listed file isn't flagged. A per-call list would break every time code shifted lines. I also didn't cover processes started indirectly, such as new Worker.

The keep_plan tool wasn't available in this run, so the issue's plan wasn't updated.

To try it: bun test test/spawn-sites.test.ts passes (5 tests). Add Bun.spawn(["ls"]) to any file in src/ and it fails, naming that file. bun scripts/gate.ts and bun x tsc --noEmit both pass.

🤖 Generated with Claude Code

Approved

Approved. test/spawn-sites.test.ts lists 34 files with a reason each, fails by file name on an unlisted site, fails on a listed site that has vanished, and ARCHITECTURE.md says where the list lives. Self-tests cover each failure and the comment, typeof and regex-dollar false positives. It adds no dependency and no behaviour, and it reads src/ once, so it is fast. The README is untouched. I did not run the suite; the pull is green and I read the diff only.

Two things I would do next:

  1. The scan is line by line, so a multi-line import {\n spawn,\n} from "bun" slips past it, as does const { spawn } = Bun. Match the import across lines, or scan whole text with the comment lines stripped.
  2. The scan is per file, so a second spawn in a listed file is never flagged. Count the spawn calls per file and pin the count in the list, so a new call forces someone to reread the reason.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs