remove unused files

This commit is contained in:
Jinjing
2026-08-24 13:36:17 -07:00
parent a70cb6f2ed
commit 133e953acb
4 changed files with 0 additions and 408 deletions
-127
View File
@@ -1,127 +0,0 @@
# Split `src/main/ipc/pty.ts` under 400 lines
## Baseline (Phase A)
- Branch: `split-ipc-pty` (clean)
- Source: `src/main/ipc/pty.ts` **7866** physical lines
- `pnpm run typecheck:node`: **pass**
- Focused tests: `pnpm exec vitest run --config config/vitest.config.ts src/main/ipc/pty.test.ts` — **480 passed**
- Note: `pnpm test -- src/main/ipc/pty.test.ts` does **not** filter. The test script is `ensure-native-runtime && vitest run`, so extra args go to the first command.
Hard size: source `wc -l` ≤ 400; every dest `wc -l` ≤ 400. Oxlint `.ts` max-lines is 300 counted (skip blanks/comments) and dest files must not add max-lines disables — keep dest files ~220–280 counted / well under 400 `wc -l`.
## Public API (keep on `src/main/ipc/pty.ts` barrel)
Consumers keep importing `./pty` / `../ipc/pty`. Do **not** add `src/main/ipc/pty/index.ts` (file+folder collision; same pattern as `src/main/github/project-view.ts`).
- `getBashShellReadyRcfileContent` (passthrough re-export)
- `isCurrentPtyExit`
- `getPtyIdForPaneKey`
- `registerPaneKeyTeardownListener`
- `hasPendingRendererSerializerForPaneKey`
- `BuildPtyHostEnvOptions`, `CodexHomeLaunchContext`, `GetSelectedCodexHomePath`, `PrepareCodexSessionResume`, `CodexHomePtySpawnedLifecycleArgs`
- `resolveCodexHomeAfterManagedAuthReadiness`
- `buildPtyHostEnv`
- `registerSshPtyProvider`, `unregisterSshPtyProvider`, `getSshPtyProvider`
- `getLocalPtyProvider`, `setLocalPtyProvider`
- `getPtyIdsForConnection`, `clearPtyOwnershipForConnection`
- `clearProviderPtyState`, `deletePtyOwnership`, `setPtyOwnership`, `restorePtyIncarnation`
- `rebindLocalProviderListeners`, `unbindLocalProviderListeners`
- `PtyRendererDeliveryDebugSnapshot`, `getPtyRendererDeliveryDebugSnapshot`, `resetPtyRendererDeliveryDebug`
- `registerPtyHandlers`, `registerHeadlessPtyRuntime`, `killAllPty`
Extracted modules import **siblings** (`./pty-provider-registry`), never the barrel.
## Dest files
### A. Module-level (lines 243–2361)
| Dest | Source range (approx) | Contents |
|---|---|---|
| `src/main/ipc/pty/pty-provider-registry.ts` | 243–260, 930–1018, 1981–2016 | `localProvider`, SSH maps, `getProvider*`, SSH/local register accessors |
| `src/main/ipc/pty/pty-ownership-state.ts` | 266–272, 2018–2042, 2123–2136 | ownership + incarnation maps and public mutators |
| `src/main/ipc/pty/pty-renderer-visibility-state.ts` | 262–286, 2157 | sizes, input/interactive, visibility sets, drain-invalidator bridges, `providerSnapshotRequiredPtys` |
| `src/main/ipc/pty/pty-pane-key-state.ts` | 288–321, 463–472, 511–519 | paneKey↔ptyId, teardown listeners, pane-key parse |
| `src/main/ipc/pty/pty-pane-serializer-state.ts` | 323–325, 459–461, 521–551, 918–928 | pending serializer gens + `hasPendingRendererSerializerForPaneKey` |
| `src/main/ipc/pty/pty-pane-spawn-reservation.ts` | 326–347, 554–637 | pane spawn reservations + runtime create claims |
| `src/main/ipc/pty/pty-agent-session-owners.ts` | 350–455 | claimed owners, restore-record seed, spawn-live assert |
| `src/main/ipc/pty/pty-launch-authority.ts` | 474–509 | renderer launch-token admit + Agent Teams refresh predicate |
| `src/main/ipc/pty/pty-stable-pane-owner.ts` | 640–916 | persist/resolve/attach/spawn stable pane owner |
| `src/main/ipc/pty/pty-provider-liveness.ts` | 968–1115 | remote-env strip, gone/live probes, `finishPtyShutdown` |
| `src/main/ipc/pty/pty-host-env-types.ts` | 1120–1144, 1242–1274 | public env/codex types, `ptyLifecycleSequence`, `PrepareClaudeAuth` |
| `src/main/ipc/pty/pty-host-env-path.ts` | 1146–1188 | PATH promote + env-key delete |
| `src/main/ipc/pty/pty-codex-home-env.ts` | 1190–1498 | Codex home skip/strip/readiness/account-route |
| `src/main/ipc/pty/pty-pi-agent-env.ts` | 1500–1693 | Pi/OMP/Mimo/OpenCode overlay env |
| `src/main/ipc/pty/pty-host-env.ts` | 1695–1926 | `buildPtyHostEnv` |
| `src/main/ipc/pty/pty-fresh-spawn-routing.ts` | 1928–1979 | Claude launch detect, daemon→local recovery, worktree spawn fence |
| `src/main/ipc/pty/pty-provider-state-cleanup.ts` | 2044–2121 | `clearProviderPtyState` |
| `src/main/ipc/pty/pty-provider-listener-lifecycle.ts` | 2138–2172, 2351–2360 | unsub slots, `rebind`/`unbind` |
| `src/main/ipc/pty/pty-renderer-delivery-debug.ts` | 2174–2271 | snapshot type + breadcrumb/power + get/reset |
| `src/main/ipc/pty/pty-renderer-lifecycle-reset.ts` | 2273–2348 | did-finish-load + lifecycle/gate reset handlers |
### B. `registerPtyHandlers` closure (2364–7825)
Cannot stay one function. Introduce `PtyIpcSession` (mutable per-registration object) so nested functions become modules that take `session`. Preserve setup order:
1. Cancel prior watchdog + neutralize prior closure bridges
2. Register renderer lifecycle reset
3. `ipcMain.removeHandler` / `removeAllListeners`
4. `LocalPtyProvider.configure`
5. Create pending drain queue + delivery state
6. Bind module-scope bridges (`invalidatePendingPtyDrain*`, debug snapshot readers, `rebindProviderListeners`)
7. `bindProviderListeners()`
8. `runtime.setPtyController(...)`
9. Register IPC handlers
| Dest | Contents |
|---|---|
| `src/main/ipc/pty/pty-ipc-session.ts` | Session type + `createPtyIpcSession` state (maps/timers/queues). Keep under 400 by splitting constants. |
| `src/main/ipc/pty/pty-delivery-constants.ts` | Batch/watermark/interactive constants |
| `src/main/ipc/pty/pty-local-provider-configure.ts` | `configure({ buildSpawnEnv, onSpawned, onExit, onData })` |
| `src/main/ipc/pty/pty-hidden-delivery-transition.ts` | hidden-delivery transition + spawn variant |
| `src/main/ipc/pty/pty-delivery-accounting.ts` | in-flight / ACK / credit / resync / write-off |
| `src/main/ipc/pty/pty-delivery-pending.ts` | pending append/drop/projection + overflow marker |
| `src/main/ipc/pty/pty-delivery-flush.ts` | `flushPendingData` + schedule + drain invalidation |
| `src/main/ipc/pty/pty-delivery-payload.ts` | payload builders, interactive-now, send-to-renderer |
| `src/main/ipc/pty/pty-delivery-accept.ts` | `acceptPtyDataForRenderer` |
| `src/main/ipc/pty/pty-exit-for-renderer.ts` | synthetic kill, retire, prepare/finalize/send exit |
| `src/main/ipc/pty/pty-provider-listener-bind.ts` | `bindProviderListeners` |
| `src/main/ipc/pty/pty-serialize-buffer.ts` | serialize request table + IPC response |
| `src/main/ipc/pty/pty-spawn-cwd.ts` | folder-workspace assert + startup cwd |
| `src/main/ipc/pty/pty-codex-resume-launch.ts` | prepare/resolve/reconcile resume + sequenced-argv strip |
| `src/main/ipc/pty/pty-adopt-stable-pane.ts` | `adoptStablePane` |
| `src/main/ipc/pty/pty-runtime-controller-spawn-preflight.ts` | controller spawn: auth, env, session id (part 1) |
| `src/main/ipc/pty/pty-runtime-controller-spawn-commit.ts` | controller spawn: persist, register, telemetry (part 2) |
| `src/main/ipc/pty/pty-runtime-controller.ts` | remaining controller methods (write/probe/attach/kill/list/serialize/resize) — split further if >400 |
| `src/main/ipc/pty/pty-runtime-controller-kill.ts` | kill / retireRejected / reversible stop |
| `src/main/ipc/pty/pty-ipc-spawn-preflight.ts` | `pty:spawn` handler preflight (cwd, auth, env) |
| `src/main/ipc/pty/pty-ipc-spawn-commit.ts` | `pty:spawn` persist/register/response |
| `src/main/ipc/pty/pty-ipc-write.ts` | write / writeAccepted / claimViewport |
| `src/main/ipc/pty/pty-ipc-resize-visibility.ts` | resize, geometry, ack, visibility, hidden, delivery interest |
| `src/main/ipc/pty/pty-ipc-inspect.ts` | kill/list/has/inspect/cwd/size/serializer IPC |
| `src/main/ipc/pty/pty-ipc-snapshot.ts` | getMainBufferSnapshot + sideEffectSnapshot + delivery debug IPC |
| `src/main/ipc/pty/register-pty-handlers.ts` | thin orchestrator: create session, run setup order, call installers |
| `src/main/ipc/pty/register-headless-pty-runtime.ts` | headless window shim |
| `src/main/ipc/pty/kill-all-pty.ts` | `killAllPty` |
If any dest exceeds 400 `wc -l` or 300 counted after paste, split again on the next domain seam (do not add a disable).
## Cycle / behavior risks
- Extracted files must not import `../pty` (the barrel). Sibling imports only.
- Re-registration must still allocate a **new** session and retarget module-scope bridges (`invalidatePendingPtyDrainPriority/Policy`, `rebindProviderListeners`, debug snapshot readers, dispatcher watchdog clearer). Do not lift session maps to module scope.
- Keep why-comments. SSH/folder-workspace/WSL/Windows/remote-wire paths stay verbatim.
- After shrink, **remove** the `eslint-disable max-lines` on `pty.ts` and prune `config/max-lines-baseline.txt` via `pnpm run check:max-lines-ratchet --prune` if the ratchet reports stale `inline src/main/ipc/pty.ts`.
## Verification
```bash
pnpm exec vitest run --config config/vitest.config.ts src/main/ipc/pty.test.ts
pnpm run typecheck:node
pnpm run check:max-lines-ratchet
wc -l src/main/ipc/pty.ts src/main/ipc/pty/*.ts
```
Characterization tests: only if an extracted **pure** symbol is uncovered. Do not invent tests for IPC/session wiring already covered by `pty.test.ts`.
Commit (if green): `refactor: split pty.ts under 400 lines`
-14
View File
@@ -1,14 +0,0 @@
# Remaining work to finish the pty.ts 400-line split
## Done
- Source `src/main/ipc/pty.ts`: **7866 → 39** (thin public-API barrel, no `pty/index.ts`)
- Module-level state/env/cleanup extracted under `src/main/ipc/pty/`
- Delivery, inspect/write/snapshot/resize IPC extracted
- Renderer `pty:spawn` split under `ipc/spawn-*.ts`
- `registerPtyHandlers` is a thin orchestrator over `PtyIpcSession`
- Runtime controller split under `runtime/{spawn,kill,operations}*.ts`
- Oxlint on `src/main/ipc/pty/**` is clean (no max-lines disables)
## After retrying the commit
- `pnpm exec vitest run --config config/vitest.config.ts src/main/ipc/pty.test.ts`
- `pnpm exec tsc --noEmit -p config/tsconfig.node.json` if the commit hook does not already cover it
-95
View File
@@ -1,95 +0,0 @@
# Split review (round 1): `src/main/ipc/pty.ts`
Mechanical review only. Dest files live under `src/main/ipc/pty/`. Barrel is `src/main/ipc/pty.ts`. Line counts are physical `wc -l` (last-line from file reads).
## Verdict
**Not done.** Barrel, naming, disable, and import-cycle checks pass. The 400-line hard cap fails on three dest files. The `registerPtyHandlers` closure was only partly extracted (plan B modules mostly still inline). No clear intentional runtime behavior change found in the extracted public wiring.
---
## 1. Move-only / no-logic-delta
**No intentional behavior change found** in the public API or in extracted module-level helpers that are actually wired (ownership, provider registry, cleanup, host env, headless/kill-all, write/snapshot/inspect installers).
Re-registration still:
1. Cancels the prior dispatcher watchdog and neutralizes drain/accounting bridges
2. Registers renderer lifecycle reset
3. Removes prior IPC handlers
4. Configures `LocalPtyProvider`
5. Allocates new closure-scoped delivery state (not lifted to module scope)
6. Retargets module-scope bridges
7. Binds provider listeners
8. Installs the runtime controller
9. Registers IPC handlers
New code is split plumbing (`setInvalidatePendingPtyDrain*`, `setRebindProviderListeners`, `installPty*` wrappers, `createPtyWriteInput`). `installPowerSignalBreadcrumbs()` still runs during handler registration (now from `installPtySnapshotIpcHandlers`, which `registerPtyHandlers` always calls).
### Findings
| Sev | Issue |
|-----|--------|
| Medium | `src/main/ipc/pty/pty-spawn-cwd.ts` is an unused copy. `assertFolderWorkspacePtyPathUsable`, `resolvePtySpawnStartupCwd`, and `localStartupCwdDirectoryExists` still live as closures in `register-pty-handlers.ts` and are passed into spawn/controller. Dest is dead; live copies can drift. Either switch callers or delete the dest. |
| Info | Plan B (`PtyIpcSession`, delivery/flush/accept modules, spawn preflight/commit splits) was not done. That is why the three oversized files remain. Not a behavior delta by itself. |
---
## 2. Folder + name
**Pass.** All dest files are under `src/main/ipc/pty/`. Names are domain-specific (`pty-ownership-state`, `pty-host-env`, `register-pty-handlers`, …). No `helpers` / `utils` / `common` / `misc`.
---
## 3. 400-line cap
**Fail.** Three dest files exceed 400 physical lines. Barrel is fine.
| File | `wc -l` | Cap |
|------|--------:|-----|
| `src/main/ipc/pty.ts` | 39 | ok |
| `src/main/ipc/pty/register-pty-handlers.ts` | **2616** | **FAIL** |
| `src/main/ipc/pty/pty-ipc-spawn.ts` | **1415** | **FAIL** |
| `src/main/ipc/pty/pty-runtime-controller.ts` | **608** | **FAIL** |
| `src/main/ipc/pty/pty-ipc-inspect.ts` | 320 | ok |
| `src/main/ipc/pty/pty-codex-home-env.ts` | 302 | ok |
| `src/main/ipc/pty/pty-stable-pane-owner.ts` | 294 | ok |
| `src/main/ipc/pty/pty-host-env.ts` | 271 | ok |
| `src/main/ipc/pty/pty-write-input.ts` | 210 | ok |
| `src/main/ipc/pty/pty-pi-agent-env.ts` | 204 | ok |
| remaining dest files | 12–137 | ok |
`register-pty-handlers.ts` still owns delivery accounting, pending flush, provider bind, cwd/codex-resume/adoptStablePane, and most resize/visibility/ack IPC. `pty-ipc-spawn.ts` and `pty-runtime-controller.ts` were not split on the plan seams (`pty-ipc-spawn-preflight` / `pty-ipc-spawn-commit`, `pty-runtime-controller-spawn-*` / `-kill`).
Oxlint counted max-lines is 300. `pty-ipc-inspect.ts` (320 physical) and `pty-codex-home-env.ts` (302 physical) may still trip counted max-lines even though they are under 400 `wc -l`. Split if ratchet/lint complains; do not add a disable.
---
## 4. No max-lines disables on new files
**Pass.** No `eslint-disable max-lines`, `oxlint-disable max-lines`, or per-file max-lines bump in `src/main/ipc/pty.ts` or `src/main/ipc/pty/**`.
---
## 5. Barrel / no `pty/index.ts`
**Pass.**
- `src/main/ipc/pty.ts` is re-exports only (public API matches the plan).
- No `src/main/ipc/pty/index.ts`.
- Consumers still import `./pty` / `../ipc/pty` (`pty.test.ts`, `daemon-init.ts`, `ssh-relay-session.ts`, `index.ts`, etc.).
---
## 6. Extracted files must not import the barrel
**Pass.** Dest files import siblings (`./pty-provider-registry`) or `src/main/ipc/*` neighbors (`../pty-hidden-delivery-gate`). No `from '../pty'`, `from '../../ipc/pty'`, or `from '.../ipc/pty'`.
---
## Required follow-up (before this split is complete)
1. Split `register-pty-handlers.ts` (2616), `pty-ipc-spawn.ts` (1415), and `pty-runtime-controller.ts` (608) until every dest `wc -l` ≤ 400. Use the plan B seams; do not add max-lines disables.
2. Wire or delete `pty-spawn-cwd.ts` so cwd helpers exist in one place.
Do not treat the 400-line work as optional. The rest of the mechanical contract is already in place.
-172
View File
@@ -1,172 +0,0 @@
# Split review (round 2): `src/main/ipc/pty.ts`
Adversarial follow-up to [split-ipc-pty-review-1.md](./split-ipc-pty-review-1.md). Dest files live under `src/main/ipc/pty/`. Barrel is `src/main/ipc/pty.ts`. Line counts are physical last-line from file reads (no `wc` in this pass).
## Verdict
**Still not done.** Round 1's dead `pty-spawn-cwd.ts` is now wired. Barrel, dest→barrel imports, naming, max-lines disables, and `Record<string, any>` checks pass. The 400-line hard cap still fails on the same three dest files; `pty-runtime-controller.ts` grew (608 → 1583) instead of being split on the plan B seams. No new unused dest module. Remaining risks are re-registration live-binding windows, duplicated spawn paths (SSH/WSL/folder drift), and fragile IPC uninstall.
---
## 1. 400-line cap
**Fail.** Barrel is 39 lines. Three dest files still exceed 400 physical lines.
| File | lines | Cap |
|------|------:|-----|
| `src/main/ipc/pty.ts` | 39 | ok |
| `src/main/ipc/pty/register-pty-handlers.ts` | **2579** | **FAIL** |
| `src/main/ipc/pty/pty-runtime-controller.ts` | **1583** | **FAIL** |
| `src/main/ipc/pty/pty-ipc-spawn.ts` | **1415** | **FAIL** |
| `src/main/ipc/pty/pty-ipc-inspect.ts` | 320 | ok (counted max-lines 300 may still trip) |
| `src/main/ipc/pty/pty-codex-home-env.ts` | 301 | ok (same) |
| `src/main/ipc/pty/pty-stable-pane-owner.ts` | 293 | ok |
| `src/main/ipc/pty/pty-host-env.ts` | 270 | ok |
| remaining dest files | 12–210 | ok |
Plan B is still incomplete:
- No `PtyIpcSession`. Delivery accounting, pending flush, accept path, serialize table, resize/visibility/ack IPC, Codex-resume helpers, and `adoptStablePane` remain inside `register-pty-handlers.ts`.
- `pty-ipc-spawn.ts` was not split into `pty-ipc-spawn-preflight` / `pty-ipc-spawn-commit`.
- `pty-runtime-controller.ts` absorbed more spawn/kill/list/resize instead of `pty-runtime-controller-spawn-*` / `-kill`.
`config/max-lines-baseline.txt` still has `inline src/main/ipc/pty.ts`. After the barrel shrink that ratchet line is stale (plan: `pnpm run check:max-lines-ratchet --prune`).
Oxlint counted max-lines is 300. Do not add a disable if inspect/codex-home trip it — split.
---
## 2. Unused extracted modules
**Pass (modules).** Every dest file has a consumer. Round 1's unused `pty-spawn-cwd.ts` is imported from `register-pty-handlers.ts` and passed into spawn + controller.
Thin store-binding wrappers (not a second copy of the logic):
```2013:2020:src/main/ipc/pty/register-pty-handlers.ts
const assertFolderWorkspacePtyPathUsable = (worktreeId: string | undefined): Promise<void> =>
assertFolderWorkspacePtyPathUsableImpl(store, worktreeId)
const resolvePtySpawnStartupCwd = (
worktreeId: string | undefined,
cwd: string | undefined,
missingDirFallback?: TerminalStartupCwdMissingDirFallback
): string | undefined => resolvePtySpawnStartupCwdImpl(store, worktreeId, cwd, missingDirFallback)
```
**Unused exports** (not unused files; leftover public surface):
- `pendingSerializerGenSeq`, `cleanupPendingPaneSerializersForSender` in `pty-pane-serializer-state.ts`
- `clearPaneSpawnReservation`, `releaseRuntimePaneCreate` in `pty-pane-spawn-reservation.ts`
Keep them unexported or use them only internally so they do not look like a second API.
---
## 3. Circular imports / barrel
**Pass (hard cycles).**
- Dest files do not import `../pty` / `../../ipc/pty`.
- No `src/main/ipc/pty/index.ts`.
- Consumers still import `./pty` / `../ipc/pty` (`daemon-init.ts`, `ssh-relay-session.ts`, `attach-main-window-services.ts`, `pty.test.ts`).
Graph is one-way: barrel → dest; `register-pty-handlers` → installers; `register-headless-pty-runtime` → `register-pty-handlers`. Sibling state modules (`ownership` ← `registry` ← `agent-session-owners` ← `cleanup` ← `liveness`) do not loop.
**Soft coupling (not an import cycle):** module-scope `export let` bridges in `pty-renderer-visibility-state.ts`, `pty-provider-listener-lifecycle.ts`, and `pty-renderer-delivery-debug.ts` are mutated by `register-pty-handlers` and invoked from cleanup / lifecycle-reset / daemon-init. That is the intended live-binding pattern.
---
## 4. Setter / live-binding mistakes
Setters exist and assignments from other modules go through them (`setInvalidatePendingPtyDrain*`, `setRebindProviderListeners`, `setLocal*Unsub`, `setRead/Reset*Snapshot`, `setLocalPtyProvider`). `unbindLocalProviderListeners` assigns `localDataUnsub = null` in the **defining** module — legal ESM, live for importers.
Call sites use the imported binding at **call** time (not a captured snapshot), e.g. `clearProviderPtyState` → `invalidatePendingPtyDrainPriority(id, false)`, `rebindLocalProviderListeners` → `rebindProviderListeners?.()`. That is the correct live-binding use.
### Remaining live-binding risks
| Sev | Issue |
|-----|--------|
| Medium | Re-registration **neutralizes drain/accounting immediately** (`setInvalidate*(() => {})`, `setResetRendererDeliveryAccountingForLifecycleReset(() => {})`) but does **not** neutralize `rebindProviderListeners`. `setRebindProviderListeners(bindProviderListeners)` is at line 1868. A daemon `replaceDaemonProvider` in that window (`daemon-init.ts` calls `rebindLocalProviderListeners`) rebinds `onData`/`onExit` to the **old** `acceptPtyDataForRenderer` / `sendPtyExitToRenderer` closure. Neutralize rebind at the same moment as drain, or retarget it before any await. |
| Medium | Symmetric window the other way: drain is a no-op from register start until line 1203. `LocalPtyProvider.configure({ onExit })` and SSH teardown can call `clearProviderPtyState` in that window; priority/policy invalidation is dropped. Pre-existing shape, but the window is now ~1200 lines of setup. |
| Low | `setResetRendererDeliveryAccountingForLifecycleReset` at line 690 closes over `sshOutputIntake` before it is constructed (line 1683). Optional chaining makes this a no-op if a lifecycle reset fires in between; SSH projection transfer would be skipped for that reset. |
| Info | `export let localProvider` / drain fns rely on ESM live bindings. electron-vite bundling usually preserves them; a CJS snapshot would freeze `killAllPty` / drain on the initial values. Setters + same-module assignment are the safe half; imported **reads** are the fragile half. |
`bindProviderListeners` correctly unsubscribes via imported live unsubs then `setLocal*Unsub(...)`. That path is sound.
---
## 5. Behavior deltas
No intentional public API change. Barrel matches the plan.
**Highest ongoing delta risk: two full spawn implementations.**
`pty-ipc-spawn.ts` (`pty:spawn`) and `pty-runtime-controller.ts` (`runtime.setPtyController().spawn`) both assemble host env, Codex home, Claude auth, WSL distro, SSH env strip, pane reservation, persist, and restore-record seed. They already differ in ways that look historical but will now drift independently:
| Path | IPC `pty:spawn` | Runtime controller |
|------|-----------------|--------------------|
| Folder-workspace assert | yes (if no early stable owner) | yes (if not pre-adopted) |
| Missing-dir / WSL UNC cwd fallback | yes (`wslUncDirectoryExistsAsync`, `localStartupCwdDirectoryExists`) | **no** — `resolvePtySpawnStartupCwd(worktreeId, cwd)` only |
| `recoverFreshSpawnProviderRouting` | `sessionId === undefined` default | passes `args.isNewSession` |
| Agent Teams env refresh / launch-token admit | yes | no (caller pre-allocates handle) |
| `stripRemotePaneEnvWhenHooksDisabled` | yes | yes |
A later “fix spawn” that only lands in one file is a real SSH/WSL/folder regression. Split further by extracting **one** spawn-commit helper, not by copying more.
Other notes (not proven new vs monolith):
- `installPtyWriteIpcHandlers` does not `removeAllListeners('pty:write')`. Parent does, at the top of `registerPtyHandlers`. If installer order changes or a test calls the installer alone, write listeners double. `pty:claimViewport` removes inside the installer; `pty:write` does not.
- `finishPtyShutdown` still calls `markClaudePtyExited` after `clearProviderPtyState` (which already calls it). Duplicate, likely pre-existing.
- `pty-write-input.ts` redeclares inner `PtyWritePayload` / `PtyViewportClaimPayload` that shadow the exported types. No runtime effect.
- Headless shim still uses `isDestroyed: () => true`. Any scheduled `flushPendingData` then `releaseAll()` + clears pending. Same as before; more drain invalidations would hit it more often.
---
## 6. SSH / folder-workspace / WSL
These paths were moved, not obviously rewritten. Residual hazards:
**SSH**
- Encoded-owner routing in `getProviderForPty` still refuses local fallback for disconnected SSH ids.
- `pty:kill` / controller `kill` still tombstone via `finishPtyShutdown` when the SSH provider is gone.
- `hasPtyProviderForInspection` still treats missing SSH hosts as idle.
- Remote pane env is stripped in **both** spawn copies when hooks are off. Keep them identical.
- `writePtyInputAccepted` still returns false when `ptyOwnership.get(id) !== null` (SSH cannot ack). Local owners must be stored as `null`, not missing (`undefined !== null`).
**Folder workspace**
- `assertFolderWorkspacePtyPathUsable` now takes `store` and uses `getSshFilesystemProvider` for remote folder roots. Wired through register wrappers. Headless/no-store still no-ops (same as `!store` guard).
**WSL**
- `localStartupCwdDirectoryExists` still returns `true` for `\\wsl.localhost` (Win32 `statSync` false ENOENT).
- Only the IPC spawn path does async WSL directory existence + worktree cwd fallback. Runtime-created terminals (splits, CLI, headless) skip that. Do not “simplify” IPC spawn to match the controller.
**WSL Codex**
- Both spawn copies set `isWsl: shouldSkipCodexHomeEnvForWindowsShell(shell, cwd)` and `wslDistro` from `codexSelectionTarget`. `configure({ buildSpawnEnv })` in register still branches `ctx?.isWsl` for Codex target + `addOrcaWslInteropEnv`. Keep those three sites aligned.
---
## 7. `Record<string, any>` leftovers
**Pass.** No `Record<string, any>` in `src/main/ipc/pty.ts` or `src/main/ipc/pty/**`. Env maps are `Record<string, string>`. Casts are narrow (`providerGeneration?: number`), not `any`.
---
## 8. Folder + name + disables
**Pass.** Dest names are domain-specific. No `helpers` / `utils` / `common`. No `eslint-disable max-lines` / `oxlint-disable max-lines` on dest files.
---
## Required follow-up
1. Split `register-pty-handlers.ts` (2579), `pty-runtime-controller.ts` (1583), and `pty-ipc-spawn.ts` (1415) until every dest `wc -l` ≤ 400. Use plan B seams. Do not add max-lines disables.
2. Neutralize **all** session bridges at re-register start (`rebindProviderListeners` included), then retarget after the new session exists.
3. Dedup spawn preflight/commit before the two copies diverge on SSH env / WSL cwd / folder-workspace.
4. Make `installPtyWriteIpcHandlers` uninstall `pty:write` itself (same as `pty:claimViewport`).
5. Prune stale `inline src/main/ipc/pty.ts` from `config/max-lines-baseline.txt` after the barrel shrink.
Do not treat the 400-line work as optional. The mechanical contract (barrel, no dest→barrel, cwd wiring, no `any` records) is otherwise in place.