{"record":{"id":"0de22ffe77527a99","repo":"stablyai/orca","slug":"watcher-supervisor-did-not-replace-the-faulted-chi","errorCode":null,"errorMessage":"Watcher supervisor did not replace the faulted child","messagePattern":"Watcher supervisor did not replace the faulted child","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"config/scripts/runtime-file-watcher-fault-harness.mjs","lineNumber":139,"sourceCode":"      (listener) => {\n        eventListener = listener\n      },\n      (event) => event.path === join(rootPath, 'before.txt'),\n      'pre-crash watch event'\n    )\n    await writeFile(join(rootPath, 'before.txt'), 'before')\n    await Promise.race([beforeEvent, watcherError])\n\n    const firstChildPid = supervisor.child?.pid\n    if (!firstChildPid) {\n      throw new Error('Watcher supervisor did not expose a live child')\n    }\n    process.kill(firstChildPid, 'SIGSEGV')\n    await Promise.race([interrupted, watcherError])\n\n    const replacementChildPid = supervisor.child?.pid\n    if (!replacementChildPid || replacementChildPid === firstChildPid) {\n      throw new Error('Watcher supervisor did not replace the faulted child')\n    }\n    const afterEvent = nextMatchingEvent(\n      (listener) => {\n        eventListener = listener\n      },\n      (event) => event.path === join(rootPath, 'after.txt'),\n      'post-crash watch event'\n    )\n    await writeFile(join(rootPath, 'after.txt'), 'after')\n    await Promise.race([afterEvent, watcherError])\n\n    console.log(\n      JSON.stringify({\n        hostPid: process.pid,\n        killedWatcherPid: firstChildPid,\n        replacementWatcherPid: replacementChildPid,\n        hostSurvived: true,\n        automaticResubscribe: true,","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/runtime-file-watcher-fault-harness.mjs#L121-L157","documentation":"After sending SIGSEGV to firstChildPid and awaiting the interrupted/replacement event, the harness reads supervisor.child?.pid again. It expects a NEW pid (different from firstChildPid) — proving the supervisor auto-respawned the crashed watcher. If the pid is missing or unchanged, the supervisor's self-healing contract is broken and the test fails.","triggerScenarios":"The supervisor did not respawn the child after SIGSEGV (no recovery logic), respawned but reused the same pid (impossible normally), or the replacement race window closed before the read.","commonSituations":"A regression in WatcherProcessSupervisor that removed/bugged the respawn-on-crash path; the SIGSEGV killed the supervisor itself instead of just the child; respawn is async and the read happened before it completed; crash backoff disabled.","solutions":["Confirm the SIGSEGV was sent to the child pid, not the supervisor pid (the harness uses firstChildPid).","Await the supervisor's respawn promise/event (the harness races interrupted vs watcherError — extend the race to include the respawn signal).","Re-enable/fix the supervisor's auto-respawn logic; this assertion exists precisely to catch its removal.","If the supervisor intentionally does not respawn, this test is N/A — skip it on that code path."],"exampleFix":"// before\nprocess.kill(firstChildPid, 'SIGSEGV')\nawait Promise.race([interrupted, watcherError])\nconst replacementChildPid = supervisor.child?.pid\n// after\nprocess.kill(firstChildPid, 'SIGSEGV')\nawait supervisor.waitForRespawn()  // explicit respawn signal\nconst replacementChildPid = supervisor.child?.pid","handlingStrategy":"validation","validationCode":"const replacement = supervisor.child?.pid\nif (typeof replacement !== 'number' || replacement === firstChildPid) {\n  console.error('Supervisor did not respawn the faulted child'); process.exit(1)\n}","typeGuard":"function isRespawned(next: number | undefined, prev: number): next is number {\n  return typeof next === 'number' && next !== prev\n}","tryCatchPattern":"if (!isRespawned(supervisor.child?.pid, firstChildPid)) {\n  throw new Error('Watcher supervisor did not replace the faulted child')\n}","preventionTips":["Await the supervisor's explicit respawn event before reading the new pid.","Confirm SIGSEGV targeted the child pid, not the supervisor pid.","Keep this assertion in place — it guards the auto-respawn contract."],"tags":["file-watcher","parcel","fault-injection","process-respawn","child-process"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}