Phase 4 of the M8 consolidation plan — completes the ProcessManager edge contracts.
Spawn log consolidation
Added a private logSpawn(id:binary:arguments:captured:) helper that consolidates the duplicated spawn logging in runStreaming and runCaptured. The exact spawn / spawn(captured) prefixes and LogSanitizer.sanitizeArgs behaviour are preserved.
No changes to EOF, stdin, cancellation, or continuation machinery; termination handlers still install before Process.run(); waitUntilExit watchdogs still start only after a successful launch; exactly-one finalisation guards remain in the actor. runStreaming and runCaptured stay distinct APIs.
New deterministic edge-case tests (ProcessManagerTests)
explicitPartialFlushEmitsRowColorsJSON — child prints an unterminated ROW_COLORS_JSON: payload, signals readiness via a marker file, then parks; the test calls flushPartialLine and asserts exactly one .jsonRow with the prefix stripped and no .stdout leak.
unterminatedRowTailFinalizesAsJSONRow — child prints an unterminated row prefix and exits; finalisation emits .jsonRow (not .stdout) before exactly one .exit.
fastStreamingExitEmitsExactlyOneExit — immediate child exit produces exactly one .exit after a grace window that outlasts the 2 s finalise watchdog.
fastCapturedExitEmitsExactlyOneExit — immediate captured exit returns status 7 and produces exactly one .exit event after both the termination-handler and waitUntilExit watchdog paths have fired.
capturedRunSetsArgyllNotInteractive — captured child sees ARGYLL_NOT_INTERACTIVE=1.
killAllTerminatesStreamingAndCapturedChildren — one streaming + one captured child registered concurrently; killAll() returns 2, both calls finish, both ids unregister, and each emits exactly one exit.
All tests use bounded timeouts and readiness marker files; every test cleans up its children.
## Summary
Phase 4 of the M8 consolidation plan — completes the ProcessManager edge contracts.
### Spawn log consolidation
- Added a private `logSpawn(id:binary:arguments:captured:)` helper that consolidates the duplicated spawn logging in `runStreaming` and `runCaptured`. The exact `spawn` / `spawn(captured)` prefixes and `LogSanitizer.sanitizeArgs` behaviour are preserved.
- No changes to EOF, stdin, cancellation, or continuation machinery; termination handlers still install before `Process.run()`; `waitUntilExit` watchdogs still start only after a successful launch; exactly-one finalisation guards remain in the actor. `runStreaming` and `runCaptured` stay distinct APIs.
### New deterministic edge-case tests (`ProcessManagerTests`)
- `explicitPartialFlushEmitsRowColorsJSON` — child prints an unterminated `ROW_COLORS_JSON:` payload, signals readiness via a marker file, then parks; the test calls `flushPartialLine` and asserts exactly one `.jsonRow` with the prefix stripped and no `.stdout` leak.
- `unterminatedRowTailFinalizesAsJSONRow` — child prints an unterminated row prefix and exits; finalisation emits `.jsonRow` (not `.stdout`) before exactly one `.exit`.
- `fastStreamingExitEmitsExactlyOneExit` — immediate child exit produces exactly one `.exit` after a grace window that outlasts the 2 s finalise watchdog.
- `fastCapturedExitEmitsExactlyOneExit` — immediate captured exit returns status 7 and produces exactly one `.exit` event after both the termination-handler and `waitUntilExit` watchdog paths have fired.
- `capturedRunSetsArgyllNotInteractive` — captured child sees `ARGYLL_NOT_INTERACTIVE=1`.
- `killAllTerminatesStreamingAndCapturedChildren` — one streaming + one captured child registered concurrently; `killAll()` returns 2, both calls finish, both ids unregister, and each emits exactly one exit.
All tests use bounded timeouts and readiness marker files; every test cleans up its children.
### Gate
`xcodegen generate --spec project.yml && xcodebuild test -scheme ICCery -destination 'platform=macOS' -derivedDataPath build/DerivedData-feat-84-process-manager-edge-contracts ARCHS='arm64 x86_64' ONLY_ACTIVE_ARCH=NO CODE_SIGNING_ALLOWED=YES CODE_SIGN_IDENTITY='-' -only-testing:ICCeryCoreTests/ProcessManagerTests -only-testing:ICCeryCoreTests/ProcessLineDecoderTests -only-testing:ICCeryCoreTests/JSONAccumulatorTests -only-testing:ICCeryCoreTests/LogSanitizerTests`
**TEST SUCCEEDED** — 27 tests, 0 failures (ProcessManager 20, ProcessLineDecoder 3, JSONAccumulator 3, LogSanitizer 1).
Refs #84
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Phase 4 of the M8 consolidation plan — completes the ProcessManager edge contracts.
Spawn log consolidation
logSpawn(id:binary:arguments:captured:)helper that consolidates the duplicated spawn logging inrunStreamingandrunCaptured. The exactspawn/spawn(captured)prefixes andLogSanitizer.sanitizeArgsbehaviour are preserved.Process.run();waitUntilExitwatchdogs still start only after a successful launch; exactly-one finalisation guards remain in the actor.runStreamingandrunCapturedstay distinct APIs.New deterministic edge-case tests (
ProcessManagerTests)explicitPartialFlushEmitsRowColorsJSON— child prints an unterminatedROW_COLORS_JSON:payload, signals readiness via a marker file, then parks; the test callsflushPartialLineand asserts exactly one.jsonRowwith the prefix stripped and no.stdoutleak.unterminatedRowTailFinalizesAsJSONRow— child prints an unterminated row prefix and exits; finalisation emits.jsonRow(not.stdout) before exactly one.exit.fastStreamingExitEmitsExactlyOneExit— immediate child exit produces exactly one.exitafter a grace window that outlasts the 2 s finalise watchdog.fastCapturedExitEmitsExactlyOneExit— immediate captured exit returns status 7 and produces exactly one.exitevent after both the termination-handler andwaitUntilExitwatchdog paths have fired.capturedRunSetsArgyllNotInteractive— captured child seesARGYLL_NOT_INTERACTIVE=1.killAllTerminatesStreamingAndCapturedChildren— one streaming + one captured child registered concurrently;killAll()returns 2, both calls finish, both ids unregister, and each emits exactly one exit.All tests use bounded timeouts and readiness marker files; every test cleans up its children.
Gate
xcodegen generate --spec project.yml && xcodebuild test -scheme ICCery -destination 'platform=macOS' -derivedDataPath build/DerivedData-feat-84-process-manager-edge-contracts ARCHS='arm64 x86_64' ONLY_ACTIVE_ARCH=NO CODE_SIGNING_ALLOWED=YES CODE_SIGN_IDENTITY='-' -only-testing:ICCeryCoreTests/ProcessManagerTests -only-testing:ICCeryCoreTests/ProcessLineDecoderTests -only-testing:ICCeryCoreTests/JSONAccumulatorTests -only-testing:ICCeryCoreTests/LogSanitizerTestsTEST SUCCEEDED — 27 tests, 0 failures (ProcessManager 20, ProcessLineDecoder 3, JSONAccumulator 3, LogSanitizer 1).
Refs #84