v0.7.0 — fix: _spawnFn mock should override TMB_DISABLE_REMOTE_SYNC env in sync backend
## Problem
`mcp/trajectory-server/src/sync/backend.ts:45-46` early-returns null when `TMB_DISABLE_REMOTE_SYNC=1` is set in the environment, *regardless* of whether a test-supplied `_spawnFn` mock is passed. `tests/run-all.sh:18` exports that env for every test invocation.
This creates a contradiction: per user-memory doctrine `feedback_issue_sync_posture` ("tests of the sync feature itself MUST mock spawn, NOT env-disable"), the canonical test pattern is to pass `_spawnFn`. But the implementation respects the env over the explicit mock, so any test that *wants* to test the success path of remote sync gets short-circuited.
**Symptom**: `mcp/trajectory-server/src/test/issues.test.ts:340` `issue_create with successful sync bumps updated_at (regression: Bug 2)` fails 1/436 when run via `bash tests/run-all.sh` (env set), but passes 436/436 when run via `node --experimental-sqlite --test dist/test/*.test.js` directly (env unset). Confirmed identical failure on `dev` and `refactor/slim-tmb-skills-bodies` branches — pre-existing, not Phase B regression.
## Evidence (verified 2026-05-17)
- `tests/run-all.sh:18` — `export TMB_DISABLE_REMOTE_SYNC=1`
- `mcp/trajectory-server/src/sync/backend.ts:45-46`:
```ts
process.env.TMB_DISABLE_REMOTE_SYNC === '1' ||
process.env.TMB_DISABLE_REMOTE_SYNC?.toLowerCase() === 'true'
```
- `mcp/trajectory-server/src/test/issues.test.ts:340-370` — test passes `_spawnFn: makeSpawnFn([{ status: 0, stdout: 'https://github.com/owner/repo/issues/42\n', ...}])` and asserts `remote_iid === 42`. Currently gets `null`.
- Reproduction: `cd plugin && bash tests/run-all.sh` → L2 reports `1 fail`. Same fail on dev.
## Plan
The implementation must let mocks be authoritative. Two complementary fixes:
1. **Primary** — in `src/sync/backend.ts`, when `_spawnFn` is explicitly provided (passed via `args['_spawnFn']` and reaching the sync path), skip the TMB_DISABLE_REMOTE_SYNC early-return. The env stays a production safety net for real-world TMB invocations (which never pass `_spawnFn`); tests with explicit mocks are authoritative.
2. **Belt-and-suspenders** — in the affected test file(s), add a `before`/`after` block that saves+unsets+restores `process.env.TMB_DISABLE_REMOTE_SYNC` like `src/test/pr-comments.test.ts:322-330` and `src/test/sync-backend.test.ts:9-17` already do. This makes the tests env-immune even if someone re-runs them with the env set.
## Acceptance criteria
- `bash tests/run-all.sh` → L2 reports 436 pass / 0 fail.
- Direct `node --experimental-sqlite --test dist/test/*.test.js` → unchanged 436/436 pass.
- New L2 micro-test: passing `_spawnFn` with `TMB_DISABLE_REMOTE_SYNC=1` set → mock is invoked (assert via spy/call-count); env is ignored.
- The TMB_DISABLE_REMOTE_SYNC env still works in production (e.g. for users who want to disable remote sync without changing config): add L2 test that calls `issue_create` *without* `_spawnFn` and verifies the env short-circuits.
## Out of scope
- Removing `TMB_DISABLE_REMOTE_SYNC` env entirely (it's a useful production safety net).
- Migrating other tests to the env-save pattern (do as opportunistic follow-up; this issue covers only the documented-broken test).
- Changing `tests/run-all.sh` to not set the env.
## Coordination
- Affects #2904 (slim-skills) only as a noise signal — Phase B confirmed the fail is pre-existing.
- Doctrine: `feedback_issue_sync_posture` user memory.
## Note on source
Discovered while running L2 against `refactor/slim-tmb-skills-bodies` (#2904 Phase B). Bisected to dev — same fail. Root cause traced to env-vs-mock precedence in `src/sync/backend.ts`.
issue