---
id: 11775
title: Extract reusable Windows batch spawn helper
state: CLOSED
labels:
  - enhancement
  - windows
  - ai
  - refactoring
  - build
assignees:
  - neo-gpt
createdAt: '2026-05-22T17:57:44Z'
updatedAt: '2026-05-22T18:42:17Z'
githubUrl: 'https://github.com/neomjs/neo/issues/11775'
author: neo-gpt
commentsCount: 0
parentIssue: null
subIssues: []
subIssuesCompleted: 0
subIssuesTotal: 0
blockedBy: []
blocking: []
closedAt: '2026-05-22T18:42:17Z'
---
# Extract reusable Windows batch spawn helper

## Context

PR #11769 repaired #11767 / #10684 by removing the direct `cross-spawn` dependency and owning the Windows `.cmd` dispatch path inside `ai/scripts/resumeHarness.mjs`. The operator explicitly called out that this should not grow #11769: the active PR should remain the Antigravity dependency-removal fix, while reusable helper work belongs in a separate ticket.

Pre-creation duplicate sweep:
- Knowledge Base ticket search for `Windows batch spawn helper cross-spawn cmd.exe quoting reusable subprocess helper ticket` found related historical Windows/subprocess issues (#7795, #10795), but no equivalent ticket for a reusable batch-spawn helper.
- Exact repo sweep over `resources/content/issues` and `resources/content/discussions` for `cross-spawn`, `cmd.exe`, `spawn helper`, `windows batch`, `batch spawn`, and `.cmd` found related mentions but no equivalent ticket.

## The Problem

The repo-owned Windows batch quoting logic now exists in one script because #11769 needed a contained fix. That is correct for the PR scope, but it leaves follow-up risk:

- `ai/scripts/resumeHarness.mjs` owns `isWindowsBatchCommand()`, `quoteWindowsBatchArgument()`, `buildWindowsBatchCommandLine()`, and `createSpawnRequest()` locally.
- Other agent/build subprocess surfaces still have their own platform handling or raw child-process calls.
- Future Windows `.cmd` fixes could reintroduce ad hoc quoting, `shell: true`, or another direct dependency if there is no reusable local primitive.

## The Architectural Reality

Current evidence from the code sweep:

- `ai/scripts/resumeHarness.mjs` now contains the repo-owned helper functions used by #11769.
- `test/playwright/unit/ai/scripts/resumeHarness.spec.mjs` contains adversarial coverage for the current helper behavior.
- `buildScripts/build/all.mjs` selects `npm.cmd` on Windows and uses `spawnSync(..., {shell: true})` across several build steps.
- `buildScripts/webpack/buildThreads.mjs` uses `spawnSync(..., {shell: true})` for webpack command dispatch.
- `buildScripts/webpack/development/webpack.config.appworker.mjs` and `buildScripts/webpack/production/webpack.config.appworker.mjs` pass a composed `copyFolder.mjs -s ... -t ...` string through a shell path.
- `ai/scripts/heartbeatLock.mjs`, `ai/scripts/bridge-daemon.mjs`, `ai/daemons/SwarmHeartbeatService.mjs`, and `ai/services/neural-link/ConnectionService.mjs` have generic subprocess call sites that may need consistent Windows batch-wrapper behavior later.
- `ai/daemons/services/PrimaryRepoSyncService.mjs` already has explicit `npm.cmd` handling through injected `execFileSyncFn` test seams.

This is not a request to rewrite every subprocess caller in one PR. The immediate substrate is the helper primitive and its first consumer migration.

## The Fix

Create a small repo-owned Windows batch spawn helper and migrate the current `resumeHarness` implementation to consume it.

Expected shape:

- Extract the Windows batch detection, quoting, command-line construction, and spawn-request construction from `ai/scripts/resumeHarness.mjs` into a shared `.mjs` helper selected through structural pre-flight at implementation time.
- Preserve the existing direct-spawn path for POSIX hosts and native Windows executables.
- Keep `.cmd` / `.bat` dispatch scoped to `cmd.exe /d /s /v:off /c` with repo-owned quoting.
- Move or duplicate the existing adversarial unit coverage to the helper boundary.
- Migrate `resumeHarness` as the first consumer.
- Optionally migrate one additional low-risk agent subprocess consumer if the helper API proves clean and the diff remains small.

## Contract Ledger Matrix

| Target Surface | Source of Authority | Proposed Behavior | Fallback | Docs | Evidence |
|---|---|---|---|---|---|
| Repo-owned Windows batch spawn helper | `ai/scripts/resumeHarness.mjs` behavior introduced by PR #11769 | Build spawn requests that execute `.cmd` / `.bat` through `cmd.exe /d /s /v:off /c` with escaped payload data | POSIX and native executables keep direct `spawn(cmd, args)` behavior | JSDoc `@summary` on exported helper functions | Unit coverage with adversarial metacharacter and newline payloads |
| `resumeHarness` subprocess dispatch | #11767 / PR #11769 | Consume the shared helper without changing harness behavior | Existing #11769 logic remains the behavior baseline | Existing `resumeHarness` JSDoc references updated if needed | Existing `resumeHarness.spec.mjs` assertions still pass |
| Future subprocess callers | Codebase sweep listed above | Provide a small local primitive so future migrations do not add `cross-spawn` or ad hoc shell quoting | Callers can remain unchanged until separately migrated | Ticket/PR notes identify candidates without forcing broad churn | Follow-up PR shows at least one migrated consumer or a clear non-migration rationale |

## Acceptance Criteria

- [ ] Shared helper exists in a structurally justified location, with JSDoc `@summary` and clear exported API.
- [ ] `resumeHarness` imports and uses the shared helper instead of owning the helper functions locally.
- [ ] Unit coverage verifies Windows `.cmd` dispatch through `cmd.exe /d /s /v:off /c` and adversarial argument escaping.
- [ ] Unit coverage verifies POSIX/native executable paths remain direct-spawn requests.
- [ ] PR body lists audited subprocess candidates and explicitly states which were migrated versus deferred.
- [ ] No direct `cross-spawn` dependency is added.

## Out of Scope

- Broad conversion of all `shell: true` build-script call sites.
- Rewriting build orchestration or webpack command topology.
- Changing PR #11769 behavior or widening its scope.
- Solving unrelated Windows shell compatibility issues without a concrete caller and test.
- Adding a third-party subprocess abstraction dependency.

## Avoided Traps

- Do not treat `cross-spawn` as the standard answer here. The operator rejected the dependency path for #11769 because this behavior is small enough to own locally.
- Do not turn this into a sweeping build-system cleanup. The value is a reusable primitive plus one proven consumer, not a giant shell migration.
- Do not rely on negated close-keyword phrasing in PR bodies when referencing related tickets; GitHub can still parse close targets incorrectly.

## Related

- #11767
- #10684
- PR #11769
- Historical related-but-not-duplicate tickets surfaced by duplicate sweep: #7795, #10795

Origin Session ID: 2741c4bd-92b2-428b-92d3-ab718d9a7c41

Retrieval Hint: `Windows batch spawn helper cross-spawn cmd.exe quoting resumeHarness PR #11769`
Retrieval Hint: `quoteWindowsBatchArgument buildWindowsBatchCommandLine createSpawnRequest`

## Timeline

- 2026-05-22T17:57:45Z @neo-gpt added the `enhancement` label
- 2026-05-22T17:57:46Z @neo-gpt added the `windows` label
- 2026-05-22T17:57:46Z @neo-gpt added the `ai` label
- 2026-05-22T17:57:46Z @neo-gpt added the `refactoring` label
- 2026-05-22T17:57:46Z @neo-gpt added the `build` label
- 2026-05-22T18:00:14Z @neo-gpt assigned to @neo-gpt
- 2026-05-22T18:05:09Z @neo-gpt cross-referenced by PR #11776
- 2026-05-22T18:42:17Z @tobiu referenced in commit `ebf5b87` - "refactor(ai): extract Windows batch spawn helper (#11775) (#11776)

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-05-22T18:42:18Z @tobiu closed this issue

