@ponythewhite/base-context 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/NOTICE +0 -5
- package/README.md +44 -27
- package/dist/NOTICE +0 -5
- package/dist/base-context-runtime/pyproject.toml +1 -1
- package/dist/base-context-runtime/src/rlm/__init__.py +7 -5
- package/dist/base-context-runtime/test/test_subagent_registry.py +28 -1
- package/dist/base-context-runtime/uv.lock +1 -1
- package/dist/build-info.json +1 -1
- package/dist/bundle/amazon-bedrock.js +21 -0
- package/dist/bundle/{anthropic-YY4S534V.js → anthropic-UV5GZDGU.js} +5 -5
- package/dist/bundle/{azure-openai-responses-JRP6MIM3.js → azure-openai-responses-WSNPXLYC.js} +6 -6
- package/dist/bundle/{bundled-modules-P5HARVZA.js → bundled-modules-PWOGKUQQ.js} +71 -16
- package/dist/bundle/chunk-27QCJ2AZ.js +2578 -0
- package/dist/bundle/{chunk-BYVP7LWV.js → chunk-44PEHPOG.js} +1916 -4689
- package/dist/bundle/{chunk-MZHTNNVA.js → chunk-4GXPNXOJ.js} +8 -0
- package/dist/bundle/{chunk-SC5KG5R4.js → chunk-DGNX7HQ3.js} +1 -7
- package/dist/bundle/{chunk-A53O363M.js → chunk-GRJFXLBM.js} +0 -1
- package/dist/bundle/chunk-HKINIBP4.js +29 -0
- package/dist/bundle/{chunk-73DCPU3D.js → chunk-IADCPVEI.js} +1019 -3427
- package/dist/bundle/{chunk-UDSW6FNG.js → chunk-KTNETTHI.js} +1 -1
- package/dist/bundle/{chunk-U7AUVG3B.js → chunk-VSIYFWYI.js} +24 -6
- package/dist/bundle/{chunk-IW77OXFS.js → chunk-W46VZFI6.js} +0 -2099
- package/dist/bundle/{cli-main-O4X7GFGY.js → cli-main-4DS7Y3PI.js} +8 -6
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/{google-AUTVGDGZ.js → google-T32FMD4G.js} +6 -6
- package/dist/bundle/{google-vertex-Q75D7RKS.js → google-vertex-56KP6I3B.js} +3 -3
- package/dist/bundle/{main-XKOW2BV6.js → main-SV7JLVEB.js} +7 -5
- package/dist/bundle/{mistral-7ESB7QUD.js → mistral-WGBMYIVU.js} +5 -5
- package/dist/bundle/{openai-codex-responses-LV3QRPN4.js → openai-codex-responses-PIV2RQ3G.js} +6 -6
- package/dist/bundle/{openai-completions-OJECLPXJ.js → openai-completions-64C3JPR4.js} +11 -22
- package/dist/bundle/{openai-responses-FN6HZMBC.js → openai-responses-UI7RSTDV.js} +6 -6
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +108 -59
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/daemon-ps.d.ts +4 -3
- package/dist/cli/daemon-ps.d.ts.map +1 -1
- package/dist/cli/daemon-ps.js +6 -1
- package/dist/cli/daemon-ps.js.map +1 -1
- package/dist/cli/product-doctor.d.ts +0 -1
- package/dist/cli/product-doctor.d.ts.map +1 -1
- package/dist/cli/product-doctor.js +6 -3
- package/dist/cli/product-doctor.js.map +1 -1
- package/dist/config.d.ts +0 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -8
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-config.d.ts +1 -2
- package/dist/core/agent-session-config.d.ts.map +1 -1
- package/dist/core/agent-session-config.js +0 -3
- package/dist/core/agent-session-config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +5 -4
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +5 -3
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -27
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +10 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +107 -107
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +8 -35
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +33 -243
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/cron-jobs.d.ts.map +1 -1
- package/dist/core/cron-jobs.js +7 -1
- package/dist/core/cron-jobs.js.map +1 -1
- package/dist/core/inference-coordinator.d.ts +6 -1
- package/dist/core/inference-coordinator.d.ts.map +1 -1
- package/dist/core/inference-coordinator.js +18 -2
- package/dist/core/inference-coordinator.js.map +1 -1
- package/dist/core/kernel/bootstrap.d.ts.map +1 -1
- package/dist/core/kernel/bootstrap.js +2 -2
- package/dist/core/kernel/bootstrap.js.map +1 -1
- package/dist/core/kernel/repl-manager.d.ts +2 -0
- package/dist/core/kernel/repl-manager.d.ts.map +1 -1
- package/dist/core/kernel/repl-manager.js +44 -1
- package/dist/core/kernel/repl-manager.js.map +1 -1
- package/dist/core/logging.d.ts +4 -3
- package/dist/core/logging.d.ts.map +1 -1
- package/dist/core/logging.js +6 -6
- package/dist/core/logging.js.map +1 -1
- package/dist/core/mcp/mcp-manager.d.ts.map +1 -1
- package/dist/core/mcp/mcp-manager.js +3 -3
- package/dist/core/mcp/mcp-manager.js.map +1 -1
- package/dist/core/model-registry.d.ts +1 -16
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +88 -196
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +2 -19
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +36 -266
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/provider-contracts.d.ts +5 -6
- package/dist/core/provider-contracts.d.ts.map +1 -1
- package/dist/core/provider-contracts.js +25 -36
- package/dist/core/provider-contracts.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +0 -2
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/rlm-max-subagents.d.ts +32 -0
- package/dist/core/rlm-max-subagents.d.ts.map +1 -0
- package/dist/core/rlm-max-subagents.js +50 -0
- package/dist/core/rlm-max-subagents.js.map +1 -0
- package/dist/core/rlm-runtime.d.ts +3 -3
- package/dist/core/rlm-runtime.d.ts.map +1 -1
- package/dist/core/rlm-runtime.js.map +1 -1
- package/dist/core/sdk.d.ts +4 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +27 -14
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +12 -44
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +6 -6
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/installer.mjs +2 -3
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +39 -34
- package/dist/main.js.map +1 -1
- package/dist/modes/acp/acp-mode.d.ts.map +1 -1
- package/dist/modes/acp/acp-mode.js +1 -1
- package/dist/modes/acp/acp-mode.js.map +1 -1
- package/dist/modes/agent-connection/daemon-agent-connection.d.ts +6 -2
- package/dist/modes/agent-connection/daemon-agent-connection.d.ts.map +1 -1
- package/dist/modes/agent-connection/daemon-agent-connection.js +13 -2
- package/dist/modes/agent-connection/daemon-agent-connection.js.map +1 -1
- package/dist/modes/agent-connection/in-process-agent-connection.d.ts +2 -0
- package/dist/modes/agent-connection/in-process-agent-connection.d.ts.map +1 -1
- package/dist/modes/agent-connection/in-process-agent-connection.js +6 -0
- package/dist/modes/agent-connection/in-process-agent-connection.js.map +1 -1
- package/dist/modes/agent-connection/types.d.ts +3 -0
- package/dist/modes/agent-connection/types.d.ts.map +1 -1
- package/dist/modes/agent-connection/types.js.map +1 -1
- package/dist/modes/agents-view/agents-view-mode.d.ts.map +1 -1
- package/dist/modes/agents-view/agents-view-mode.js +2 -19
- package/dist/modes/agents-view/agents-view-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-mode.d.ts +5 -0
- package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-mode.js +107 -12
- package/dist/modes/daemon/daemon-mode.js.map +1 -1
- package/dist/modes/daemon/daemon-protocol.d.ts +194 -165
- package/dist/modes/daemon/daemon-protocol.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-protocol.js +16 -11
- package/dist/modes/daemon/daemon-protocol.js.map +1 -1
- package/dist/modes/daemon/daemon-rlm-capacity-coordinator.d.ts +19 -0
- package/dist/modes/daemon/daemon-rlm-capacity-coordinator.d.ts.map +1 -0
- package/dist/modes/daemon/daemon-rlm-capacity-coordinator.js +74 -0
- package/dist/modes/daemon/daemon-rlm-capacity-coordinator.js.map +1 -0
- package/dist/modes/daemon/daemon-rlm-capacity.d.ts +19 -0
- package/dist/modes/daemon/daemon-rlm-capacity.d.ts.map +1 -0
- package/dist/modes/daemon/daemon-rlm-capacity.js +85 -0
- package/dist/modes/daemon/daemon-rlm-capacity.js.map +1 -0
- package/dist/modes/daemon/daemon-session-summarizer.d.ts +2 -3
- package/dist/modes/daemon/daemon-session-summarizer.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-session-summarizer.js +32 -23
- package/dist/modes/daemon/daemon-session-summarizer.js.map +1 -1
- package/dist/modes/daemon/daemon-state-root.d.ts +15 -0
- package/dist/modes/daemon/daemon-state-root.d.ts.map +1 -0
- package/dist/modes/daemon/daemon-state-root.js +40 -0
- package/dist/modes/daemon/daemon-state-root.js.map +1 -0
- package/dist/modes/daemon/daemon-supervisor-ownership.d.ts +2 -0
- package/dist/modes/daemon/daemon-supervisor-ownership.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor-ownership.js +27 -0
- package/dist/modes/daemon/daemon-supervisor-ownership.js.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.d.ts +10 -1
- package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor.js +213 -20
- package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.d.ts +28 -1
- package/dist/modes/daemon/daemon-worker-protocol.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-worker-protocol.js +16 -2
- package/dist/modes/daemon/daemon-worker-protocol.js.map +1 -1
- package/dist/modes/daemon/saved-session-catalog.d.ts.map +1 -1
- package/dist/modes/daemon/saved-session-catalog.js +2 -0
- package/dist/modes/daemon/saved-session-catalog.js.map +1 -1
- package/dist/modes/interactive/auth-flows.d.ts +0 -6
- package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
- package/dist/modes/interactive/auth-flows.js +6 -126
- package/dist/modes/interactive/auth-flows.js.map +1 -1
- package/dist/modes/interactive/components/configuration-menu.d.ts +3 -0
- package/dist/modes/interactive/components/configuration-menu.d.ts.map +1 -1
- package/dist/modes/interactive/components/configuration-menu.js +13 -2
- package/dist/modes/interactive/components/configuration-menu.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +2 -2
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +0 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +0 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +0 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +3 -40
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +2 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +13 -2
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +2 -11
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/feature-hints.d.ts.map +1 -1
- package/dist/modes/interactive/feature-hints.js +0 -4
- package/dist/modes/interactive/feature-hints.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +3 -12
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +81 -507
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/onboarding.d.ts +0 -3
- package/dist/modes/interactive/onboarding.d.ts.map +1 -1
- package/dist/modes/interactive/onboarding.js +0 -17
- package/dist/modes/interactive/onboarding.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +4 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +82 -42
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/node/amazon-bedrock.d.ts +2 -0
- package/dist/node/amazon-bedrock.d.ts.map +1 -0
- package/dist/node/amazon-bedrock.js +6 -0
- package/dist/node/amazon-bedrock.js.map +1 -0
- package/dist/product-identity.d.ts +0 -1
- package/dist/product-identity.d.ts.map +1 -1
- package/dist/product-identity.js +0 -1
- package/dist/product-identity.js.map +1 -1
- package/docs/development.md +1 -1
- package/docs/fork-philosophy.md +4 -8
- package/docs/installation.md +83 -62
- package/docs/providers.md +23 -25
- package/docs/quickstart.md +19 -10
- package/docs/rlm-runtime.md +13 -5
- package/docs/rpc.md +4 -4
- package/docs/sdk.md +20 -11
- package/docs/sessions.md +0 -1
- package/docs/settings.md +9 -42
- package/docs/skills.md +0 -1
- package/docs/upstream-0.9.5.md +171 -0
- package/docs/usage.md +14 -10
- package/package.json +4 -4
- package/dist/core/agent-traces.d.ts +0 -149
- package/dist/core/agent-traces.d.ts.map +0 -1
- package/dist/core/agent-traces.js +0 -904
- package/dist/core/agent-traces.js.map +0 -1
- package/dist/core/prime-inference-auth.d.ts +0 -70
- package/dist/core/prime-inference-auth.d.ts.map +0 -1
- package/dist/core/prime-inference-auth.js +0 -352
- package/dist/core/prime-inference-auth.js.map +0 -1
- package/dist/core/prime-inference-model-selection.d.ts +0 -16
- package/dist/core/prime-inference-model-selection.d.ts.map +0 -1
- package/dist/core/prime-inference-model-selection.js +0 -16
- package/dist/core/prime-inference-model-selection.js.map +0 -1
- package/dist/core/prime-inference-models.d.ts +0 -6
- package/dist/core/prime-inference-models.d.ts.map +0 -1
- package/dist/core/prime-inference-models.js +0 -62
- package/dist/core/prime-inference-models.js.map +0 -1
- package/dist/core/telemetry.d.ts +0 -95
- package/dist/core/telemetry.d.ts.map +0 -1
- package/dist/core/telemetry.js +0 -637
- package/dist/core/telemetry.js.map +0 -1
- package/dist/modes/interactive/components/prime-onboarding-splash.d.ts +0 -39
- package/dist/modes/interactive/components/prime-onboarding-splash.d.ts.map +0 -1
- package/dist/modes/interactive/components/prime-onboarding-splash.js +0 -286
- package/dist/modes/interactive/components/prime-onboarding-splash.js.map +0 -1
- package/dist/modes/interactive/components/prime-team-selector.d.ts +0 -30
- package/dist/modes/interactive/components/prime-team-selector.d.ts.map +0 -1
- package/dist/modes/interactive/components/prime-team-selector.js +0 -166
- package/dist/modes/interactive/components/prime-team-selector.js.map +0 -1
- package/dist/skills/prime-intellect/SKILL.md +0 -87
- package/dist/skills/prime-intellect/references/compute.md +0 -45
- package/dist/skills/prime-intellect/references/environments.md +0 -73
- package/dist/skills/prime-intellect/references/inference.md +0 -47
- package/dist/skills/prime-intellect/references/sandboxes.md +0 -75
- package/skills/prime-intellect/SKILL.md +0 -87
- package/skills/prime-intellect/references/compute.md +0 -45
- package/skills/prime-intellect/references/environments.md +0 -73
- package/skills/prime-intellect/references/inference.md +0 -47
- package/skills/prime-intellect/references/sandboxes.md +0 -75
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-supervisor.d.ts","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-supervisor.ts"],"names":[],"mappings":"AAiCA,OAAO,EACN,KAAK,yBAAyB,EAI9B,MAAM,oCAAoC,CAAC;AAiB5C,OAAO,EAEN,KAAK,mBAAmB,EAExB,MAAM,oCAAoC,CAAC;AA+U5C,UAAU,uBAAuB;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,yBAAyB,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAiQD,wBAAgB,2BAA2B,CAAC,mBAAmB,EAAE,mBAAmB,GAAG,MAAM,CAM5F;AA8BD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,KAAK,CAAC,CAK9F;AAED,qBAAa,gBAAgB;IAyD3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAxD5B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,cAAc,CAAC,CAAuB;IAC9C,OAAO,CAAC,WAAW,CAAC,CAAwB;IAC5C,OAAO,CAAC,qBAAqB,CAAC,CAAQ;IACtC,OAAO,CAAC,SAAS,CAAC,CAA+D;IACjF,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,kBAAkB,CAAC,CAAsC;IACjE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6C;IAC3E,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA6C;IACrF,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAkD;IAC9F,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6C;IAC/E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,gBAAgB,CAAC,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA8C;IAC7E,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyE;IAC1G,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAkD;IACrF,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAyB;IAC/D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA4B;IACjE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA6C;IACjF,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAqB;IAC9D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqB;IAC1D,gGAAgG;IAChG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,mBAAmB,CAAC,CAAiC;IAC7D,OAAO,CAAC,sBAAsB,CAAC,CAAiB;IAChD,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,eAAe,CAAC,CAAgB;IACxC,OAAO,CAAC,iBAAiB,CAAC,CAAgC;IAC1D,OAAO,CAAC,iBAAiB,CAAC,CAAgB;IAC1C,OAAO,CAAC,iBAAiB,CAAC,CAAgB;IAC1C,OAAO,CAAC,kBAAkB,CAAC,CAAgC;IAC3D,OAAO,CAAC,sBAAsB,CAAC,CAAgB;IAC/C,OAAO,CAAC,4BAA4B,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA6B;IAEnE,YACkB,UAAU,EAAE,MAAM,EACnC,OAAO,EAAE,uBAAuB,EAoBhC;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAiG3B;IAED,OAAO,CAAC,MAAM;IAgBd,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,qCAAqC;YAkB/B,2BAA2B;YAoE3B,6BAA6B;YA8B7B,wBAAwB;IA8BtC,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,sBAAsB;IAwB9B,4HAA4H;IAC5H,OAAO,CAAC,0BAA0B;YAWpB,oBAAoB;YAgFpB,wBAAwB;YAcxB,iBAAiB;YAUjB,8BAA8B;YAW9B,6BAA6B;IAiC3C,OAAO,CAAC,8BAA8B;YAmBxB,sBAAsB;YAmBtB,6BAA6B;YAM7B,qBAAqB;IAOnC,OAAO,CAAC,6BAA6B;IAkBrC,OAAO,CAAC,qBAAqB;IAmC7B,4IAA4I;IAC5I,OAAO,CAAC,6BAA6B;IAyBrC,OAAO,CAAC,6BAA6B;IAqBrC,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,6BAA6B;IAMrC,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,gBAAgB;IAgFxB,OAAO,CAAC,wBAAwB;IAUhC,OAAO,CAAC,gBAAgB;YAIV,+BAA+B;IAsD7C,OAAO,CAAC,kCAAkC;IAY1C,OAAO,CAAC,mCAAmC;IAW3C,OAAO,CAAC,0BAA0B;IA2BlC,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,sCAAsC;IAgC9C,0FAA0F;IAC1F,OAAO,CAAC,sCAAsC;IAoD9C,OAAO,CAAC,sBAAsB;YAShB,UAAU;YAwLV,aAAa;YA8yBb,UAAU;YAqGV,iBAAiB;YASjB,kBAAkB;IAShC,OAAO,CAAC,qBAAqB;YAsBf,sBAAsB;YAqBtB,mBAAmB;YA8EnB,oBAAoB;YAmCpB,iBAAiB;IAU/B,OAAO,CAAC,uBAAuB;IAU/B,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,mBAAmB;YAab,8BAA8B;YAmD9B,kBAAkB;IA4BhC,OAAO,CAAC,0BAA0B;YASpB,YAAY;YAyQZ,aAAa;IAuD3B,OAAO,CAAC,sBAAsB;YAiBhB,eAAe;YAoBf,oBAAoB;YAuFpB,sBAAsB;YAqCtB,iBAAiB;IAuD/B,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,yBAAyB;IAUjC,OAAO,CAAC,mBAAmB;YAsBb,4BAA4B;IA+B1C,OAAO,CAAC,uBAAuB;IA+C/B,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,yBAAyB;IA6BjC,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,sBAAsB;IAkB9B,OAAO,CAAC,iCAAiC;IAWzC,OAAO,CAAC,iCAAiC;YAa3B,aAAa;IAuI3B,OAAO,CAAC,yBAAyB;IASjC,OAAO,CAAC,wBAAwB;YAQlB,gCAAgC;YAoFhC,sBAAsB;YAyDtB,oBAAoB;YAiBpB,0BAA0B;YAgB1B,oCAAoC;IAalD,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,kBAAkB;IAiC1B,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,6BAA6B;IAKrC,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,+BAA+B;IAMvC,OAAO,CAAC,mBAAmB;YAIb,gBAAgB;IAsB9B,OAAO,CAAC,6BAA6B;IAuBrC,OAAO,CAAC,wBAAwB;IAsBhC,OAAO,CAAC,sBAAsB;IAsB9B,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,sBAAsB;YAahB,yBAAyB;IAsEvC,OAAO,CAAC,iCAAiC;IAoBzC,OAAO,CAAC,6BAA6B;IASrC,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,+BAA+B;IAkBvC,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,oBAAoB;IAa5B,sFAAsF;IACtF,OAAO,CAAC,cAAc;IAmBtB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;YAIX,gCAAgC;IAiB9C,OAAO,CAAC,2BAA2B;YAarB,yCAAyC;IAcvD,OAAO,CAAC,+BAA+B;IAyBvC,OAAO,CAAC,eAAe;IAIvB,gFAAgF;IAChF,OAAO,CAAC,gBAAgB;IAIxB,gEAAgE;IAChE,OAAO,CAAC,YAAY;IAIpB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,4BAA4B;YAWtB,kBAAkB;IAkEhC,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;YAUP,UAAU;IAsBxB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,8BAA8B;IAMtC,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,mBAAmB;IAyB3B,OAAO,CAAC,uBAAuB;YA0BjB,eAAe;YAiBf,YAAY;IAiM1B,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,mBAAmB;IA6D3B,OAAO,CAAC,0BAA0B;IAyClC,OAAO,CAAC,0BAA0B;YAgBpB,cAAc;IAiF5B,OAAO,CAAC,qBAAqB;IAkC7B,OAAO,CAAC,mBAAmB;YAIb,mBAAmB;IA2BjC,OAAO,CAAC,YAAY;YAgBN,qBAAqB;IAUnC,OAAO,CAAC,iBAAiB;IAmbzB,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,sBAAsB;IAiB9B,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,aAAa;YAgBP,uBAAuB;YAWvB,mBAAmB;YAsFnB,oBAAoB;YAmBpB,0BAA0B;IAsIxC,OAAO,CAAC,gCAAgC;IA0CxC;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IAiBvB;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;YAcpB,UAAU;YAiBV,mBAAmB;IAoKjC;;;;OAIG;IACH,OAAO,CAAC,8BAA8B;YASxB,0BAA0B;YAqF1B,0BAA0B;YAgB1B,iCAAiC;YAgDjC,kCAAkC;IAyBhD,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,4BAA4B;IAapC,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,sBAAsB;IAe9B,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,4BAA4B;IAkBpC,OAAO,CAAC,aAAa;YAUP,0BAA0B;YAQ1B,8BAA8B;YA4E9B,cAAc;IAQ5B,OAAO,CAAC,oBAAoB;YASd,QAAQ;CA4FtB","sourcesContent":["import { type ChildProcess, spawn } from \"node:child_process\";\nimport { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport {\n\tchmodSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\trmSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { createServer, type Server, type Socket } from \"node:net\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { Writable } from \"node:stream\";\nimport { getLogger } from \"@ponythewhite/base-context-ai\";\nimport { createCliSubprocessEnv, createCliSubprocessLaunchSpec } from \"../../cli/subprocess-launch.js\";\nimport {\n\tappendRotatingLog,\n\tgetCronJobsPath,\n\tgetDaemonLogPath,\n\tgetDaemonUpdateRestartManifestPath,\n\tgetSessionsDir,\n\tVERSION,\n} from \"../../config.js\";\nimport {\n\ttype AgentFamilyCatalogEntry,\n\ttype AgentSessionMessageAgentSummary,\n\tassertAgentFamilyReach,\n\tassertAgentSessionNameAvailable,\n\tformatAgentSessionNameUnavailable,\n\tsessionNameReservationKey,\n} from \"../../core/agent-messages.js\";\nimport {\n\ttype AgentSessionRuntimeConfig,\n\ttype DurableAgentSessionRuntimeConfig,\n\tdurableAgentSessionRuntimeConfig,\n\tmergeAgentSessionRuntimeConfig,\n} from \"../../core/agent-session-config.js\";\nimport {\n\ttype AgentCronJob,\n\tAgentCronJobStore,\n\tisHeartbeatCronJob,\n\tmigrateLegacyCronJobsToSessionArtifacts,\n\tSESSION_SCHEDULED_JOBS_FILENAME,\n} from \"../../core/cron-jobs.js\";\nimport {\n\tclearOrphanProcessJournal,\n\tkillOrphanProcess,\n\tORPHAN_PROCESS_JOURNAL_ENV,\n\treadActiveOrphanProcesses,\n\tshouldReapOrphanProcess,\n} from \"../../core/orphan-process-journal.js\";\nimport { PromptAdmissionCancelledError, waitForPromptAdmission } from \"../../core/prompt-admission.js\";\nimport { RlmJournalOwner } from \"../../core/rlm-journal-owner.js\";\nimport {\n\tcanEvictWorker,\n\ttype IdleEvictionMinutes,\n\ttype WorkerEvictionSnapshot,\n} from \"../../core/session-action-store.js\";\nimport { canonicalSessionPath, getProcessStartId, SessionAlreadyActiveError } from \"../../core/session-lease.js\";\nimport { getSessionArtifactPathForFile, readSessionInfo, type SessionInfo } from \"../../core/session-manager.js\";\nimport { looksLikeSessionPath } from \"../../core/session-resolver.js\";\nimport { SettingsManager } from \"../../core/settings-manager.js\";\nimport { PRODUCT } from \"../../product-identity.js\";\nimport { isProcessAlive, processIdExists, signalProcessGroupOrProcess } from \"../../utils/child-process.js\";\nimport type { AgentConnectionHeartbeat } from \"../agent-connection/types.js\";\nimport { attachJsonlLineReader, serializeJsonLine } from \"../rpc/jsonl.js\";\nimport type { PrivateFrame } from \"../session-worker/private-framing.js\";\nimport { createActiveSessionId, type DaemonSocketClient } from \"./active-session-state.js\";\nimport {\n\tAgentRoster,\n\ttype AgentRosterEntry,\n\ttype AgentRosterMutation,\n\tpassivatedWorkerRosterEntry,\n\trosterAgentIdForSummary,\n\tsessionSummaryFromRosterEntry,\n\ttype WorkerRosterEntry,\n\tworkerRosterEntryFromSummary,\n} from \"./agent-roster.js\";\nimport {\n\ttype CommandJournalBeginResult,\n\tCommandRecoveryJournal,\n\tcreateCommandIdempotencyKey,\n} from \"./command-recovery-journal.js\";\nimport { CompactAssistantStreamReconstructor, isCompactAssistantDelta } from \"./compact-session-stream.js\";\nimport { DAEMON_CATALOG_ROLE_ENV, DaemonCatalogClient } from \"./daemon-catalog-process.js\";\nimport { deserializeDaemonError, serializeDaemonError } from \"./daemon-errors.js\";\nimport {\n\tCANONICAL_SESSION_OWNERSHIP_COMPATIBILITY,\n\tcollectDaemonClientEnv,\n\tcreateDaemonEventMeta,\n\tDAEMON_COMMAND_COMPATIBILITY,\n\tDAEMON_COMMAND_ENVELOPE_MIN_PROTOCOL_VERSION,\n\tDAEMON_DEFAULT_CLIENT_CAPABILITIES,\n\tDAEMON_DEFAULT_SERVER_CAPABILITIES,\n\tDAEMON_PROTOCOL_INFO,\n\tDAEMON_SCHEMA_ID,\n\tDAEMON_SCHEMA_REVISION,\n\tDAEMON_UPDATE_RESTART_FORMAT_VERSION,\n\ttype DaemonAttachResult,\n\ttype DaemonClientCapability,\n\ttype DaemonClosingReason,\n\ttype DaemonCommand,\n\ttype DaemonOutbound,\n\ttype DaemonPeerTransportTicket,\n\ttype DaemonResponse,\n\ttype DaemonServerCapability,\n\ttype DaemonUpdateRestartManifest,\n\tfailure,\n\tisDaemonCommandEnvelope,\n\tisDaemonMutatingCommand,\n\tisLegacyDaemonInspection,\n\tsalvageDaemonCommandId,\n\tsuccess,\n\tUPDATE_RESTART_DRAIN_COMMANDS,\n} from \"./daemon-protocol.js\";\nimport { getDaemonRuntimeIdentity } from \"./daemon-runtime-identity.js\";\nimport { matchesSessionIdSuffix } from \"./daemon-session-id.js\";\nimport {\n\tclassifySessionRosterStatus,\n\tisEvictableEmptySessionSummary,\n\tisSessionSummaryBusy,\n\ttype SessionSummary,\n\tsummaryForInactiveSession,\n} from \"./daemon-session-list.js\";\nimport {\n\tacquireDaemonSocketPathLease,\n\tcleanupDaemonSocketPath,\n\ttype DaemonSocketIdentity,\n\ttype DaemonSocketPathLease,\n\tdefaultDaemonSocketDir,\n\tdefaultDaemonSocketPath,\n\tgetDaemonSocketIdentity,\n\tnormalizeSocketPath,\n\tprepareDaemonSocketPath,\n\trestrictDaemonSocketPath,\n} from \"./daemon-socket.js\";\nimport {\n\tacquireDaemonSupervisorOwnership,\n\tisDaemonShutdownAdmissionActive,\n\twaitForDaemonStartupFence,\n} from \"./daemon-supervisor-ownership.js\";\nimport {\n\tDaemonWorkerAuthenticationError,\n\tDaemonWorkerClient,\n\tDaemonWorkerCompatibilityError,\n\tDaemonWorkerProbeTimeoutError,\n} from \"./daemon-worker-client.js\";\nimport {\n\tDAEMON_WORKER_ACTIVE_SESSION_ID_ENV,\n\tDAEMON_WORKER_INSTANCE_ID_ENV,\n\tDAEMON_WORKER_PEER_TRANSPORT_CAPABILITY,\n\tDAEMON_WORKER_RECOVERY_JOURNAL_ENV,\n\tDAEMON_WORKER_ROLE_ENV,\n\tDAEMON_WORKER_ROSTER_CAPABILITY,\n\tDAEMON_WORKER_STARTUP_GATE_COMMIT,\n\tDAEMON_WORKER_STARTUP_GATE_FD_ENV,\n\tDAEMON_WORKER_SUPERVISOR_SOCKET_ENV,\n\tDAEMON_WORKER_TOKEN_ENV,\n\ttype DaemonCreateCommand,\n\ttype DaemonWorkerDescriptor,\n\ttype DaemonWorkerFrameHeader,\n\ttype DaemonWorkerLifecycle,\n\ttype DaemonWorkerRosterOutbound,\n\tdurableDaemonCreateCommand,\n\tdurableDaemonWorkerDescriptor,\n\tROSTER_HEARTBEAT_INTERVAL_MS,\n\tSESSION_LEASE_OWNER_ID_ENV,\n\tSESSION_LEASES_ENABLED_ENV,\n} from \"./daemon-worker-protocol.js\";\nimport { MutationDrainLatch } from \"./mutation-drain-latch.js\";\nimport {\n\tcreateRlmLedgerRegistrySeedSource,\n\ttype RlmLedgerEdge,\n\tRlmSpawnLedger,\n\trlmLedgerPath,\n\ttombstoneSavedSessionDelete,\n} from \"./rlm-ledger.js\";\nimport { captureSavedSessionPageQuery } from \"./saved-session-page.js\";\nimport { SNAPSHOT_TARGET_CHUNK_BYTES, SnapshotTranscriptCache } from \"./snapshot-transcript-cache.js\";\nimport { WorkerRecoveryJournal } from \"./worker-recovery-journal.js\";\n\ntype DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;\ntype DaemonCommandBody = DistributiveOmit<DaemonCommand, \"id\">;\n\nconst structuredLog = getLogger(\"coding-agent.daemon-supervisor\");\nconst WORKER_CONNECT_TIMEOUT_MS = 30_000;\nconst ROSTER_WATCHDOG_INTERVAL_MS = 15_000;\nconst ROSTER_STALE_AFTER_MS = 3 * ROSTER_HEARTBEAT_INTERVAL_MS;\nconst SUPERVISOR_SERVER_CAPABILITIES: readonly DaemonServerCapability[] = [\n\t...DAEMON_DEFAULT_SERVER_CAPABILITIES,\n\t\"agent_roster\",\n\t\"direct_peer_transport\",\n\t\"rlm_ledger_mutation\",\n];\nconst PEER_TRANSPORT_GRANT_TTL_MS = 10_000;\nconst WORKER_REQUEST_TIMEOUT_MS = 24 * 60 * 60 * 1000;\nconst INPUT_PAUSE_CLEANUP_TIMEOUT_MS = 5_000;\nconst UPDATE_RESTART_MUTATION_DRAIN_TIMEOUT_MS = 80_000;\nconst UPDATE_RESTART_WORKER_REQUEST_TIMEOUT_MS = 90_000;\n// The whole pre-commit prepare (drain + worker fencing) must finish inside the\n// caller's 120s prepare_update_restart request timeout, or roll back; otherwise\n// an abandoned prepare leaves the daemon permanently fenced with workers stopped.\nconst UPDATE_RESTART_PREPARE_DEADLINE_MS = 100_000;\nconst WORKER_RETRY_DELAYS_MS = [250, 1000, 5000] as const;\nconst DEFERRED_RECOVERY_RECHECK_MS = 5000;\n// ~2.5 minutes of probing: each round is one 5s defer recheck plus a ~11s three-delay probe pass.\nconst MAX_DEFERRED_RECOVERY_ROUNDS = 10;\nconst STOP_FINALIZATION_RECHECK_MS = 250;\nconst STOP_FINALIZATION_SIGKILL_GRACE_MS = 5000;\nconst STOP_FINALIZATION_RETRY_MS = 5000;\nconst STALE_RECLAIM_WAIT_MS = 10_000;\n// Polling loops probe existence cheaply via kill(0); the ps-backed zombie and\n// identity checks are throttled so a wedged worker cannot saturate the\n// supervisor event loop with synchronous subprocess spawns.\nconst LIVENESS_IDENTITY_RECHECK_MS = 500;\nconst OWNED_WORKER_DISCONNECT_GRACE_MS = 30_000;\nconst IDLE_EVICTION_MAX_SWEEP_INTERVAL_MS = 5 * 60_000;\nconst IDLE_EVICTION_MIN_SWEEP_INTERVAL_MS = 60_000;\nconst IDLE_EVICTION_DRAIN_TIMEOUT_MS = 5_000;\nconst CHILD_PASSIVATION_PER_WORKER_CAP = 2;\nconst SCHEDULED_WAKE_RETRY_MS = 60_000;\nconst SCHEDULED_WAKE_MAX_TIMEOUT_MS = 2_147_483_647;\nconst SCHEDULED_WAKE_CLIENT_ID = \"scheduled-wake\";\nconst SUPERVISOR_CONFIG_FILE_NAME = \"supervisor-config\";\nconst WORKER_STARTUP_GATE_FD = 3;\n\nconst DAEMON_COMMAND_TYPES: ReadonlySet<string> = new Set([\n\t\"ack_result\",\n\t\"list\",\n\t\"list_agent_peers\",\n\t\"rlm_ledger_mutate\",\n\t\"get_direct_worker_transport\",\n\t\"roster_subscribe\",\n\t\"roster_unsubscribe\",\n\t\"list_saved_sessions\",\n\t\"create\",\n\t\"attach\",\n\t\"reattach\",\n\t\"detach\",\n\t\"complete_owned_session\",\n\t\"promote_owned_session\",\n\t\"kill\",\n\t\"rename\",\n\t\"prompt\",\n\t\"cancel_prompt_admission\",\n\t\"prompt_and_wait\",\n\t\"steer\",\n\t\"follow_up\",\n\t\"restore_next_turn\",\n\t\"restore_actions\",\n\t\"append_custom_message\",\n\t\"resume_queue\",\n\t\"send_message\",\n\t\"send_result\",\n\t\"agent_messages_status\",\n\t\"agent_messages_pause\",\n\t\"agent_messages_resume\",\n\t\"agent_messages_clear\",\n\t\"abort\",\n\t\"start_side_question\",\n\t\"abort_side_question\",\n\t\"execute_bash\",\n\t\"execute_bash_and_wait\",\n\t\"abort_bash\",\n\t\"cancel_rlm_child\",\n\t\"delete_rlm_subagent\",\n\t\"wait_for_idle\",\n\t\"wait_for_headless_completion\",\n\t\"get_session_header\",\n\t\"get_state\",\n\t\"get_connection_state\",\n\t\"get_messages\",\n\t\"get_rlm_children\",\n\t\"get_session_stats\",\n\t\"get_context_tree\",\n\t\"get_commands\",\n\t\"get_resource_snapshot\",\n\t\"replace_acp_mcp_servers\",\n\t\"get_model_catalog\",\n\t\"get_available_models\",\n\t\"get_queue\",\n\t\"mutate_queued_message\",\n\t\"clear_queue\",\n\t\"abort_and_clear_queue\",\n\t\"acquire_session_input_pause\",\n\t\"release_session_input_pause\",\n\t\"cron_list\",\n\t\"heartbeats_list\",\n\t\"heartbeat_manage\",\n\t\"cron_add\",\n\t\"cron_cancel\",\n\t\"cron_resume\",\n\t\"heartbeat_get\",\n\t\"heartbeat_set\",\n\t\"heartbeat_update\",\n\t\"set_model\",\n\t\"cycle_model\",\n\t\"set_scoped_models\",\n\t\"set_thinking_level\",\n\t\"cycle_thinking_level\",\n\t\"set_service_tier\",\n\t\"set_transport\",\n\t\"set_steering_mode\",\n\t\"set_follow_up_mode\",\n\t\"set_auto_compaction\",\n\t\"set_auto_retry\",\n\t\"compact\",\n\t\"refine\",\n\t\"abort_compaction\",\n\t\"abort_branch_summary\",\n\t\"abort_retry\",\n\t\"reload\",\n\t\"new_session\",\n\t\"switch_session\",\n\t\"fork\",\n\t\"navigate_tree\",\n\t\"import_jsonl\",\n\t\"export_html\",\n\t\"export_jsonl\",\n\t\"set_session_name\",\n\t\"get_rlm_max_depth_status\",\n\t\"set_rlm_max_depth\",\n\t\"rename_saved_session\",\n\t\"delete_saved_session\",\n\t\"get_session_context\",\n\t\"get_session_tree\",\n\t\"get_user_messages_for_forking\",\n\t\"get_last_assistant_text\",\n\t\"get_system_prompt\",\n\t\"get_tool_definition\",\n\t\"set_session_entry_label\",\n\t\"extension_ui_response\",\n\t\"prepare_update_restart\",\n\t\"retry_worker\",\n\t\"restart\",\n\t\"shutdown\",\n]);\n\ninterface ResidentWorker {\n\tdescriptor: DaemonWorkerDescriptor;\n\tdescriptorPath: string;\n\tclient?: DaemonWorkerClient;\n\tcompatibilityError?: DaemonWorkerCompatibilityError;\n\theartbeatSnapshot?: AgentConnectionHeartbeat[];\n\theartbeatSnapshotStale?: boolean;\n\tsummaries: Map<string, SessionSummary>;\n\tsnapshotCache: Map<string, DaemonAttachResult>;\n\ttranscriptCaches: Map<string, SnapshotTranscriptCache>;\n\tsnapshotGenerations: Map<string, Map<string, SnapshotTranscriptGeneration>>;\n\tsnapshotLoads: Map<string, Promise<DaemonAttachResult>>;\n\trecovery?: Promise<void>;\n\tdeferredRecovery?: Promise<void>;\n\tintentionalStop: boolean;\n\tstopRevision: number;\n\tlaunchEnv?: Record<string, string>;\n\ttransientCreateCommand?: DaemonCreateCommand;\n\tstopFinalization?: Promise<void>;\n\townerCleanupTimer?: ReturnType<typeof setTimeout>;\n\tpromotedOwnerClientId?: string;\n\tupdateRestartPrepareClient?: DaemonWorkerClient;\n\tlastFrameAt?: number;\n\trosterStale?: boolean;\n\t/** worker_auth advertised peer-transport support; absent on workers from older builds. */\n\tpeerTransportCapable?: boolean;\n\t/** In-flight replacement connection during authentication; an allowed frame source alongside client. */\n\tpendingClient?: DaemonWorkerClient;\n\t/** Consecutive defer->probe rounds against a live-but-silent worker; bounded by MAX_DEFERRED_RECOVERY_ROUNDS. */\n\tdeferredRecoveryRounds?: number;\n\t/** Bumped per applied roster frame; a summaries pull that straddles a frame must not gap-fill. */\n\trosterEpoch?: number;\n\trosterApplyChain?: Promise<void>;\n\trosterRepairPull?: Promise<void>;\n}\n\ninterface SnapshotDuplicateValidation {\n\tpromise: Promise<void>;\n\tresolve: () => void;\n\treject: (error: Error) => void;\n}\n\ninterface SnapshotTranscriptGeneration {\n\ttranscript: SnapshotTranscriptCache;\n\tresult: DaemonAttachResult;\n\tbegin?: Buffer;\n\tend?: Buffer;\n\tincoming: boolean;\n\tretired: boolean;\n\tduplicateChunkIndex?: number;\n\tduplicateResult?: DaemonAttachResult;\n\tvalidation?: SnapshotDuplicateValidation;\n}\n\ninterface DaemonSupervisorOptions {\n\tsocketPath?: string;\n\tdefaultSessionConfig: AgentSessionRuntimeConfig;\n\tdescriptorDir?: string;\n}\n\ninterface PersistedSupervisorConfig {\n\tversion: 1;\n\tsocketPath: string;\n\tdefaultSessionConfig: DurableAgentSessionRuntimeConfig;\n}\n\ninterface WorkerMatch {\n\tworker: ResidentWorker;\n\tsummary: SessionSummary;\n}\n\ninterface WorkerAttachData {\n\tresult: DaemonAttachResult;\n\tworker: ResidentWorker;\n\ttranscript?: SnapshotTranscriptCache;\n\treleaseTranscript?: () => void;\n}\n\ninterface SupervisorPromptAdmission {\n\tclient: DaemonSocketClient;\n\tactiveSessionId: string;\n\tpublicAdmissionId: string;\n\tworkerAdmissionId: string;\n\tstatus: \"waiting\" | \"owned\" | \"cancelled\";\n\tcontroller: AbortController;\n\tworker?: ResidentWorker;\n\tworkerActiveSessionId?: string;\n}\n\ninterface SupervisorSessionInputPause {\n\towner: DaemonSocketClient;\n\tworker: ResidentWorker;\n\tactiveSessionId: string;\n\trequestedActiveSessionId: string;\n\tleaseKey: string;\n\tpauseId: string;\n\treleaseTask?: Promise<DaemonResponse>;\n}\n\nfunction throwIfAdmissionCancelled(admission: SupervisorPromptAdmission | undefined): void {\n\tif (admission?.status === \"cancelled\") throw new PromptAdmissionCancelledError();\n}\n\nclass SupervisorRecoveryCancelledError extends Error {\n\treadonly code = \"supervisor_recovery_cancelled\" as const;\n}\n\nclass SnapshotLoadInvalidatedError extends Error {}\n\nclass WorkerStopTimeoutError extends Error {}\n\nfunction isSupervisorGenerationStale(error: unknown): boolean {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error as { code?: unknown }).code === \"supervisor_generation_stale\"\n\t);\n}\n\nfunction isSupervisorRecoveryCancelled(error: unknown): boolean {\n\treturn isSupervisorShutdownAdmissionCancelled(error) || isSupervisorGenerationStale(error);\n}\n\n// Workers can be registered mid-tree (a resumed subagent transcript), so descent is membership at\n// any step of the parent walk, never a comparison against the ultimate root alone.\nfunction rosterFamilyDescendsFrom(\n\tedges: readonly RlmLedgerEdge[],\n): (path: string, roots: ReadonlySet<string>) => boolean {\n\tconst parentByChild = new Map(\n\t\tedges.map((edge) => [canonicalSessionPath(edge.child), canonicalSessionPath(edge.parent)]),\n\t);\n\treturn (path, roots) => {\n\t\tconst visited = new Set<string>();\n\t\tlet current = path;\n\t\twhile (!visited.has(current)) {\n\t\t\tif (roots.has(current)) return true;\n\t\t\tvisited.add(current);\n\t\t\tconst parent = parentByChild.get(current);\n\t\t\tif (parent === undefined) return false;\n\t\t\tcurrent = parent;\n\t\t}\n\t\treturn false;\n\t};\n}\n\nfunction isDaemonWorkerProbeTimeout(error: unknown): boolean {\n\treturn error instanceof DaemonWorkerProbeTimeoutError;\n}\n\nfunction isSupervisorShutdownAdmissionCancelled(error: unknown): boolean {\n\treturn (\n\t\terror instanceof SupervisorRecoveryCancelledError ||\n\t\t(typeof error === \"object\" &&\n\t\t\terror !== null &&\n\t\t\t\"code\" in error &&\n\t\t\t(error as { code?: unknown }).code === \"supervisor_recovery_cancelled\")\n\t);\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms));\n}\n\nfunction unrefDelay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms).unref());\n}\n\nfunction commitWorkerStartupGate(gate: Writable): Promise<void> {\n\treturn new Promise((resolveCommit, rejectCommit) => {\n\t\tlet settled = false;\n\t\tconst finish = (error?: Error | null) => {\n\t\t\tif (settled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tif (error) {\n\t\t\t\trejectCommit(error);\n\t\t\t} else {\n\t\t\t\tresolveCommit();\n\t\t\t}\n\t\t};\n\t\tconst onError = (error: Error) => finish(error);\n\t\tgate.on(\"error\", onError);\n\t\tgate.once(\"close\", () => gate.off(\"error\", onError));\n\t\tgate.end(DAEMON_WORKER_STARTUP_GATE_COMMIT, (error?: Error | null) => finish(error));\n\t});\n}\n\nfunction withoutCommandId(command: DaemonCommand): DaemonCommandBody {\n\tconst { id: _id, ...body } = command;\n\treturn body as DaemonCommandBody;\n}\n\nfunction withoutSupervisorCreateFields(command: DaemonCreateCommand): DaemonCreateCommand {\n\tconst { launchEnv: _launchEnv, lifecycle: _lifecycle, ...workerCommand } = command;\n\treturn workerCommand;\n}\n\nfunction responseWithId(response: DaemonResponse, id: string | undefined): DaemonResponse {\n\treturn { ...response, id };\n}\n\nfunction isSessionSummary(value: unknown): value is SessionSummary {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as { id?: unknown; sessionId?: unknown; cwd?: unknown };\n\treturn (\n\t\ttypeof candidate.id === \"string\" && typeof candidate.sessionId === \"string\" && typeof candidate.cwd === \"string\"\n\t);\n}\n\nfunction isDaemonWorkerDescriptor(value: unknown, socketPath: string): value is DaemonWorkerDescriptor {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst descriptor = value as Partial<DaemonWorkerDescriptor>;\n\treturn (\n\t\t(descriptor.version === 1 || descriptor.version === 2) &&\n\t\ttypeof descriptor.supervisorSocketPath === \"string\" &&\n\t\tnormalizeSocketPath(descriptor.supervisorSocketPath) === socketPath &&\n\t\ttypeof descriptor.workerId === \"string\" &&\n\t\tNumber.isInteger(descriptor.pid) &&\n\t\t(descriptor.pid ?? 0) > 0 &&\n\t\t(descriptor.processStartId === undefined || typeof descriptor.processStartId === \"string\") &&\n\t\t(descriptor.ownerClientId === undefined || typeof descriptor.ownerClientId === \"string\") &&\n\t\ttypeof descriptor.socketPath === \"string\" &&\n\t\ttypeof descriptor.authenticationToken === \"string\" &&\n\t\t(descriptor.workerInstanceId === undefined || typeof descriptor.workerInstanceId === \"string\") &&\n\t\ttypeof descriptor.rootActiveSessionId === \"string\" &&\n\t\ttypeof descriptor.createdAt === \"string\" &&\n\t\ttypeof descriptor.updatedAt === \"string\" &&\n\t\tNumber.isInteger(descriptor.consecutiveFailures) &&\n\t\tdescriptor.createCommand !== undefined &&\n\t\ttypeof descriptor.createCommand === \"object\" &&\n\t\tdescriptor.createCommand.type === \"create\"\n\t);\n}\n\nclass PreRosterWorkerError extends Error {}\n\nfunction workerAuthAdvertisesRoster(data: unknown): boolean {\n\tif (typeof data !== \"object\" || data === null) return false;\n\tconst capabilities = (data as { capabilities?: unknown }).capabilities;\n\treturn Array.isArray(capabilities) && capabilities.includes(DAEMON_WORKER_ROSTER_CAPABILITY);\n}\n\nfunction workerAuthAdvertisesPeerTransport(data: unknown): boolean {\n\tif (typeof data !== \"object\" || data === null) return false;\n\tconst capabilities = (data as { capabilities?: unknown }).capabilities;\n\treturn Array.isArray(capabilities) && capabilities.includes(DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY);\n}\n\nfunction sessionSummariesFromResponse(response: DaemonResponse): SessionSummary[] {\n\tif (!response.success || !response.data || typeof response.data !== \"object\" || !(\"sessions\" in response.data)) {\n\t\tthrow new Error(\"Session worker returned an invalid list response\");\n\t}\n\tconst sessions = (response.data as { sessions: unknown }).sessions;\n\tif (!Array.isArray(sessions) || !sessions.every(isSessionSummary)) {\n\t\tthrow new Error(\"Session worker returned an invalid list response\");\n\t}\n\treturn sessions;\n}\n\nfunction attachResultFromResponse(response: DaemonResponse): DaemonAttachResult {\n\tif (!response.success || !response.data || typeof response.data !== \"object\") {\n\t\tthrow new Error(response.success ? \"Session worker returned an invalid attach response\" : response.error);\n\t}\n\tconst candidate = response.data as Partial<DaemonAttachResult>;\n\tif (typeof candidate.activeSessionId !== \"string\" || !candidate.snapshot || !candidate.client) {\n\t\tthrow new Error(\"Session worker returned an invalid attach response\");\n\t}\n\treturn candidate as DaemonAttachResult;\n}\n\nfunction cronJobsFromResponse(response: DaemonResponse): AgentCronJob[] {\n\tif (!response.success || !response.data || typeof response.data !== \"object\") {\n\t\treturn [];\n\t}\n\tconst jobs = (response.data as { jobs?: unknown }).jobs;\n\treturn Array.isArray(jobs) ? (jobs as AgentCronJob[]) : [];\n}\n\nfunction heartbeatsFromResponse(response: DaemonResponse): AgentConnectionHeartbeat[] {\n\tif (!response.success || !response.data || typeof response.data !== \"object\") {\n\t\treturn [];\n\t}\n\tconst heartbeats = (response.data as { heartbeats?: unknown }).heartbeats;\n\treturn Array.isArray(heartbeats) ? (heartbeats as AgentConnectionHeartbeat[]) : [];\n}\n\nfunction sortCronJobs(jobs: AgentCronJob[]): AgentCronJob[] {\n\treturn jobs.sort((left, right) => {\n\t\tif (left.nextRunAt === right.nextRunAt) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (left.nextRunAt === undefined) {\n\t\t\treturn 1;\n\t\t}\n\t\tif (right.nextRunAt === undefined) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn Date.parse(left.nextRunAt) - Date.parse(right.nextRunAt);\n\t});\n}\n\nfunction descriptorKey(socketPath: string): string {\n\treturn createHash(\"sha256\").update(normalizeSocketPath(socketPath)).digest(\"hex\").slice(0, 12);\n}\n\nfunction defaultWorkerDescriptorDir(agentDir: string, socketPath: string): string {\n\treturn join(agentDir, \"daemon-workers\", descriptorKey(socketPath));\n}\n\nexport function idleEvictionSweepIntervalMs(idleEvictionMinutes: IdleEvictionMinutes): number {\n\tif (idleEvictionMinutes === \"off\") return IDLE_EVICTION_MAX_SWEEP_INTERVAL_MS;\n\treturn Math.max(\n\t\tIDLE_EVICTION_MIN_SWEEP_INTERVAL_MS,\n\t\tMath.min(IDLE_EVICTION_MAX_SWEEP_INTERVAL_MS, (idleEvictionMinutes * 60_000) / 3),\n\t);\n}\n\nfunction workerSocketPath(supervisorSocketPath: string, workerId: string): string {\n\tconst key = descriptorKey(supervisorSocketPath);\n\tif (process.platform === \"win32\") {\n\t\treturn `\\\\\\\\.\\\\pipe\\\\${PRODUCT.command}-worker-${key}-${workerId.slice(0, 12)}`;\n\t}\n\treturn join(defaultDaemonSocketDir(), `worker-${key}-${workerId.slice(0, 12)}.sock`);\n}\n\nfunction isFinalizedTranscriptEvent(eventType: string | undefined): boolean {\n\treturn (\n\t\teventType === \"message_end\" ||\n\t\teventType === \"turn_end\" ||\n\t\teventType === \"compaction_end\" ||\n\t\teventType === \"bash_end\"\n\t);\n}\n\nfunction normalizeCapabilities(\n\tcapabilities: readonly DaemonClientCapability[] | undefined,\n\tsupportsExtensionUi: boolean | undefined,\n): Set<DaemonClientCapability> {\n\tconst normalized = new Set(capabilities ?? DAEMON_DEFAULT_CLIENT_CAPABILITIES);\n\tif (supportsExtensionUi) {\n\t\tnormalized.add(\"extension_ui\");\n\t}\n\treturn normalized;\n}\n\nexport async function runDaemonSupervisorMode(options: DaemonSupervisorOptions): Promise<never> {\n\tconst socketPath = normalizeSocketPath(options.socketPath ?? defaultDaemonSocketPath());\n\tconst supervisor = new DaemonSupervisor(socketPath, options);\n\tawait supervisor.start();\n\treturn new Promise(() => {});\n}\n\nexport class DaemonSupervisor {\n\tprivate server?: Server;\n\tprivate readonly ready: Promise<void>;\n\tprivate markReady: () => void = () => {};\n\tprivate rejectReady: (error: Error) => void = () => {};\n\tprivate ownsSocketPath = false;\n\tprivate socketIdentity?: DaemonSocketIdentity;\n\tprivate socketLease?: DaemonSocketPathLease;\n\tprivate socketLeaseCompromise?: Error;\n\tprivate ownership?: Awaited<ReturnType<typeof acquireDaemonSupervisorOwnership>>;\n\tprivate cleanupPromise?: Promise<void>;\n\tprivate shuttingDown = false;\n\tprivate startupComplete = false;\n\tprivate updateRestartPhase?: \"draining\" | \"fencing\" | \"prepared\";\n\tprivate readonly mutationDrain = new MutationDrainLatch();\n\tprivate readonly clients = new Set<DaemonSocketClient>();\n\tprivate readonly connectionIds = new WeakMap<DaemonSocketClient, string>();\n\tprivate readonly sessionInputPauseEpochs = new WeakMap<DaemonSocketClient, number>();\n\tprivate readonly detachingInputPauseSessions = new WeakMap<DaemonSocketClient, Set<string>>();\n\tprivate readonly protocolClientIds = new WeakMap<DaemonSocketClient, string>();\n\tprivate readonly workers = new Map<string, ResidentWorker>();\n\tprivate workerStopCounts?: Map<ResidentWorker, number>;\n\tprivate readonly openingWorkers = new Map<string, Promise<ResidentWorker>>();\n\t/** Public admission ids are scoped to the socket that registered them. */\n\tprivate readonly promptAdmissions = new Map<DaemonSocketClient, Map<string, SupervisorPromptAdmission>>();\n\tprivate readonly sessionInputPauses = new Map<string, SupervisorSessionInputPause>();\n\tprivate readonly signalCleanupHandlers: Array<() => void> = [];\n\tprivate readonly descriptorDir: string;\n\tprivate readonly generation = randomUUID();\n\tprivate readonly supervisorConfigPath: string;\n\tprivate readonly defaultSessionConfig: AgentSessionRuntimeConfig;\n\tprivate readonly snapshotCacheRoot: string;\n\tprivate commandJournal!: CommandRecoveryJournal;\n\tprivate readonly streamReconstructor = new CompactAssistantStreamReconstructor();\n\tprivate readonly compactCatchupInProgress = new Set<string>();\n\tprivate readonly pendingSessionNames = new Set<string>();\n\tprivate readonly catalog: DaemonCatalogClient;\n\tprivate readonly settingsManager: SettingsManager;\n\tprivate rosterStore?: AgentRoster;\n\tprivate readonly pendingRosterChanged = new Set<string>();\n\tprivate readonly pendingRosterRemoved = new Set<string>();\n\t/** Ids declared to subscribers: gates removals to once and keeps owned-only row ids private. */\n\tprivate readonly publishedRosterIds = new Set<string>();\n\tprivate rosterPushScheduled = false;\n\tprivate rosterWatchdogTimer?: ReturnType<typeof setInterval>;\n\tprivate rlmSpawnLedgerInstance?: RlmSpawnLedger;\n\tprivate rlmJournalOwner?: RlmJournalOwner;\n\tprivate rlmJournalClose?: Promise<void>;\n\tprivate idleEvictionTimer?: ReturnType<typeof setTimeout>;\n\tprivate idleEvictionSweep?: Promise<void>;\n\tprivate idleEvictionFence?: Promise<void>;\n\tprivate scheduledWakeTimer?: ReturnType<typeof setTimeout>;\n\tprivate scheduledWakeRecompute?: Promise<void>;\n\tprivate scheduledWakeRecomputeQueued = false;\n\tprivate readonly scheduledWakeFailures = new Map<string, number>();\n\n\tconstructor(\n\t\tprivate readonly socketPath: string,\n\t\toptions: DaemonSupervisorOptions,\n\t) {\n\t\tthis.ready = new Promise<void>((resolveReady, rejectReady) => {\n\t\t\tthis.markReady = resolveReady;\n\t\t\tthis.rejectReady = rejectReady;\n\t\t});\n\t\tvoid this.ready.catch(() => undefined);\n\t\tconst agentDir = options.defaultSessionConfig.agentDir;\n\t\tif (!agentDir) {\n\t\t\tthrow new Error(\"Daemon supervisor config is missing agentDir\");\n\t\t}\n\t\tthis.descriptorDir = options.descriptorDir ?? defaultWorkerDescriptorDir(agentDir, socketPath);\n\t\tthis.supervisorConfigPath = join(this.descriptorDir, SUPERVISOR_CONFIG_FILE_NAME);\n\t\tthis.defaultSessionConfig = mergeAgentSessionRuntimeConfig(\n\t\t\toptions.defaultSessionConfig,\n\t\t\tthis.loadPersistedSupervisorConfig(),\n\t\t);\n\t\tthis.snapshotCacheRoot = join(this.descriptorDir, \"snapshot-cache\", this.generation);\n\t\tthis.catalog = new DaemonCatalogClient((message) => this.log(message));\n\t\tthis.settingsManager = SettingsManager.create(process.cwd(), this.defaultSessionConfig.agentDir ?? agentDir);\n\t}\n\n\tasync start(): Promise<void> {\n\t\ttry {\n\t\t\tconst agentDir = this.defaultSessionConfig.agentDir;\n\t\t\tif (!agentDir) {\n\t\t\t\tthrow new Error(\"Daemon supervisor config is missing agentDir\");\n\t\t\t}\n\t\t\tthis.socketLease = await acquireDaemonSocketPathLease(this.socketPath);\n\t\t\tthis.socketLease?.onCompromised((error) => this.handleSocketLeaseCompromised(error));\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tawait waitForDaemonStartupFence(this.socketPath);\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tconst journalScope = this.rlmJournalScope();\n\t\t\tthis.ownership = await acquireDaemonSupervisorOwnership({\n\t\t\t\tsocketPath: this.socketPath,\n\t\t\t\tdescriptorDir: this.descriptorDir,\n\t\t\t\tagentDir,\n\t\t\t\tjournalPath: journalScope.journalPath,\n\t\t\t\tgeneration: this.generation,\n\t\t\t\tappVersion: VERSION,\n\t\t\t});\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tthis.rlmJournalOwner = await RlmJournalOwner.open(journalScope);\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tawait prepareDaemonSocketPath(this.socketPath, this.socketLease);\n\n\t\t\tmkdirSync(this.descriptorDir, { recursive: true, mode: 0o700 });\n\t\t\tchmodSync(this.descriptorDir, 0o700);\n\t\t\tthis.persistSupervisorConfig();\n\t\t\trmSync(this.snapshotCacheRoot, { recursive: true, force: true });\n\t\t\tmkdirSync(this.snapshotCacheRoot, { recursive: true, mode: 0o700 });\n\t\t\tthis.commandJournal = new CommandRecoveryJournal(join(this.descriptorDir, \"command-journal.jsonl\"));\n\t\t\tthis.loadWorkerDescriptors();\n\t\t\tconst workersToAdopt = [...this.workers.values()];\n\n\t\t\tthis.server = createServer((socket) => this.handleConnection(socket));\n\t\t\tawait this.listen();\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tthis.socketIdentity = getDaemonSocketIdentity(this.socketPath);\n\t\t\tif (process.platform !== \"win32\" && !this.socketIdentity) {\n\t\t\t\tthrow new Error(`Could not capture daemon socket identity: ${this.socketPath}`);\n\t\t\t}\n\t\t\tthis.ownsSocketPath = true;\n\t\t\trestrictDaemonSocketPath(this.socketPath);\n\n\t\t\tthis.registerSignalHandlers();\n\t\t\tconst ownedSessionFiles = new Set(\n\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t.flatMap((worker) => [worker.descriptor.sessionFile, worker.descriptor.createCommand.sessionPath])\n\t\t\t\t\t.filter((path): path is string => typeof path === \"string\")\n\t\t\t\t\t.map((path) => resolve(path)),\n\t\t\t);\n\t\t\tconst migratedJobs = migrateLegacyCronJobsToSessionArtifacts(getCronJobsPath(agentDir), {\n\t\t\t\tisSessionOwned: (job) => ownedSessionFiles.has(resolve(job.sessionFile)),\n\t\t\t});\n\t\t\tif (migratedJobs > 0) {\n\t\t\t\tthis.log(`Migrated ${migratedJobs} scheduled jobs into session artifacts`);\n\t\t\t}\n\t\t\tawait this.catalog.start().catch((error) => this.log(`Could not start daemon catalog: ${String(error)}`));\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tawait this.seedRosterLedger();\n\t\t\tlet adoptionFailure: unknown;\n\t\t\tlet adoptionFailed = false;\n\t\t\tawait Promise.all(\n\t\t\t\tworkersToAdopt.map(async (worker) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.adoptOrRecoverWorker(worker);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (!adoptionFailed) {\n\t\t\t\t\t\t\tadoptionFailed = true;\n\t\t\t\t\t\t\tadoptionFailure = error;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (adoptionFailed) {\n\t\t\t\tthrow adoptionFailure;\n\t\t\t}\n\t\t\tfor (const worker of this.workers.values()) {\n\t\t\t\tthis.scheduleOwnedWorkerCleanup(worker);\n\t\t\t}\n\t\t\tthis.scheduleIdleEvictionSweep();\n\t\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\t\tthis.rosterWatchdogTimer = setInterval(() => this.sweepRosterStaleness(), ROSTER_WATCHDOG_INTERVAL_MS);\n\t\t\tthis.rosterWatchdogTimer.unref();\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tawait this.ownership.updatePhase(\"owner\");\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tthis.startupComplete = true;\n\t\t\tthis.log(`${PRODUCT.name} daemon supervisor ${this.generation} listening on ${this.socketPath}`);\n\t\t\tthis.markReady();\n\t\t} catch (error) {\n\t\t\tconst startupError = error instanceof Error ? error : new Error(String(error));\n\t\t\tthis.log(`Daemon supervisor startup failed: ${startupError.stack ?? startupError.message}`);\n\t\t\tawait this.cleanupSupervisorResources();\n\t\t\tthis.rejectReady(startupError);\n\t\t\tthrow startupError;\n\t\t}\n\t}\n\n\tprivate listen(): Promise<void> {\n\t\treturn new Promise<void>((resolveListen, rejectListen) => {\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\tthis.server?.off(\"listening\", onListening);\n\t\t\t\trejectListen(error);\n\t\t\t};\n\t\t\tconst onListening = () => {\n\t\t\t\tthis.server?.off(\"error\", onError);\n\t\t\t\tresolveListen();\n\t\t\t};\n\t\t\tthis.server?.once(\"error\", onError);\n\t\t\tthis.server?.once(\"listening\", onListening);\n\t\t\tthis.server?.listen(this.socketPath);\n\t\t});\n\t}\n\n\tprivate log(message: string): void {\n\t\tconsole.error(message);\n\t\tstructuredLog.warn(message, { socketPath: this.socketPath });\n\t\tappendRotatingLog(getDaemonLogPath(this.socketPath), `[${new Date().toISOString()}] supervisor: ${message}`);\n\t}\n\n\tprivate clearIdleEvictionTimer(): void {\n\t\tif (!this.idleEvictionTimer) return;\n\t\tclearTimeout(this.idleEvictionTimer);\n\t\tthis.idleEvictionTimer = undefined;\n\t}\n\n\tprivate clearRosterWatchdogTimer(): void {\n\t\tif (!this.rosterWatchdogTimer) return;\n\t\tclearInterval(this.rosterWatchdogTimer);\n\t\tthis.rosterWatchdogTimer = undefined;\n\t}\n\n\tprivate clearScheduledWakeTimer(): void {\n\t\tif (!this.scheduledWakeTimer) return;\n\t\tclearTimeout(this.scheduledWakeTimer);\n\t\tthis.scheduledWakeTimer = undefined;\n\t}\n\n\t// The supervisor only wakes non-resident trees; firing and delivery stay worker-owned.\n\tprivate scheduleScheduledSessionWakeRecompute(): void {\n\t\tif (this.shuttingDown) return;\n\t\tif (this.scheduledWakeRecompute) {\n\t\t\tthis.scheduledWakeRecomputeQueued = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.scheduledWakeRecompute = this.recomputeScheduledSessionWake()\n\t\t\t.catch((error) => this.log(`Scheduled-session wake recompute failed: ${String(error)}`))\n\t\t\t.finally(() => {\n\t\t\t\tthis.scheduledWakeRecompute = undefined;\n\t\t\t\tif (this.scheduledWakeRecomputeQueued) {\n\t\t\t\t\tthis.scheduledWakeRecomputeQueued = false;\n\t\t\t\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/** Durable truth: the ledger family (fork headers stripped) plus each session's scheduled-jobs artifact. */\n\tprivate async collectPassiveScheduledJobs(\n\t\tincludeInactive = false,\n\t): Promise<Array<{ rootSessionFile: string; job: AgentCronJob; info: SessionInfo }>> {\n\t\tconst pendingCancelRoots = new Set<string>();\n\t\tfor (const intent of this.collectEphemeralCancelIntents()) {\n\t\t\tconst context = this.workerSessionArtifactContext(intent);\n\t\t\tif (!context || !intent.descriptor.rootSessionId) continue;\n\t\t\ttry {\n\t\t\t\tawait this.cancelScheduledJobsForSessionTree(intent.descriptor.rootSessionId, context.sessionFile);\n\t\t\t\tthis.deleteWorkerDescriptor(intent);\n\t\t\t} catch {\n\t\t\t\t// Still owned until the cancel lands; the tree stays excluded below.\n\t\t\t\tpendingCancelRoots.add(canonicalSessionPath(context.sessionFile));\n\t\t\t}\n\t\t}\n\t\tconst infos = await this.rlmSpawnLedger().family();\n\t\tconst infoByPath = new Map(infos.map((info) => [canonicalSessionPath(info.path), info] as const));\n\t\tconst storeBySessionId = new Map<string, AgentCronJobStore>();\n\t\tconst infoBySessionId = new Map<string, SessionInfo>();\n\t\tfor (const info of infos) {\n\t\t\tif (info.state !== undefined && info.state.status !== \"active\") continue;\n\t\t\tconst artifactDir = getSessionArtifactPathForFile(resolve(info.path), info.id);\n\t\t\tif (!existsSync(join(artifactDir, SESSION_SCHEDULED_JOBS_FILENAME))) continue;\n\t\t\tconst store = AgentCronJobStore.forSessionArtifacts();\n\t\t\tstore.registerSessionArtifact(info.id, artifactDir);\n\t\t\tstoreBySessionId.set(info.id, store);\n\t\t\tinfoBySessionId.set(info.id, info);\n\t\t}\n\t\tif (infoBySessionId.size === 0) return [];\n\t\tconst uncoveredRootFor = (info: SessionInfo): string | undefined => {\n\t\t\tlet current = info;\n\t\t\tconst visited = new Set([canonicalSessionPath(current.path)]);\n\t\t\twhile (true) {\n\t\t\t\ttry {\n\t\t\t\t\tif (this.findWorkerBySessionFile(current.path)) return undefined;\n\t\t\t\t} catch {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tif (!current.parentSessionPath) break;\n\t\t\t\tconst parent = infoByPath.get(canonicalSessionPath(current.parentSessionPath));\n\t\t\t\tif (!parent || visited.has(canonicalSessionPath(parent.path))) break;\n\t\t\t\tvisited.add(canonicalSessionPath(parent.path));\n\t\t\t\tcurrent = parent;\n\t\t\t}\n\t\t\treturn current.path;\n\t\t};\n\t\tconst results: Array<{ rootSessionFile: string; job: AgentCronJob; info: SessionInfo }> = [];\n\t\tfor (const [artifactSessionId, store] of storeBySessionId) {\n\t\t\tlet jobs: AgentCronJob[];\n\t\t\ttry {\n\t\t\t\tjobs = store.list();\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Skipping unreadable scheduled jobs for session ${artifactSessionId}: ${String(error)}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const job of jobs) {\n\t\t\t\tif (!includeInactive && job.status !== \"active\" && job.status !== \"paused\") continue;\n\t\t\t\tconst info = infoBySessionId.get(job.sessionId);\n\t\t\t\tif (!info) continue;\n\t\t\t\tconst rootSessionFile = uncoveredRootFor(info);\n\t\t\t\tif (rootSessionFile === undefined) continue;\n\t\t\t\tif (pendingCancelRoots.has(canonicalSessionPath(rootSessionFile))) continue;\n\t\t\t\tresults.push({ rootSessionFile, job, info });\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async recomputeScheduledSessionWake(): Promise<void> {\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\tconst candidates = await this.collectPassiveScheduledJobs();\n\t\tthis.clearScheduledWakeTimer();\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\tconst now = Date.now();\n\t\tconst wakeTimes: number[] = [];\n\t\tconst candidateRoots = new Set(candidates.map(({ rootSessionFile }) => canonicalSessionPath(rootSessionFile)));\n\t\tfor (const root of [...this.scheduledWakeFailures.keys()]) {\n\t\t\tif (!candidateRoots.has(root)) this.scheduledWakeFailures.delete(root);\n\t\t}\n\t\tfor (const { rootSessionFile, job } of candidates) {\n\t\t\tif (job.status !== \"active\" || job.nextRunAt === undefined) continue;\n\t\t\tconst runAt = Date.parse(job.nextRunAt);\n\t\t\tif (!Number.isFinite(runAt)) continue;\n\t\t\t// The failure floor keeps an overdue job off a hot retry loop.\n\t\t\tconst failedAt = this.scheduledWakeFailures.get(canonicalSessionPath(rootSessionFile));\n\t\t\twakeTimes.push(failedAt !== undefined ? Math.max(runAt, failedAt + SCHEDULED_WAKE_RETRY_MS) : runAt);\n\t\t}\n\t\tif (wakeTimes.length === 0) return;\n\t\tconst delay = Math.min(Math.max(0, Math.min(...wakeTimes) - now), SCHEDULED_WAKE_MAX_TIMEOUT_MS);\n\t\tthis.scheduledWakeTimer = setTimeout(() => {\n\t\t\tthis.scheduledWakeTimer = undefined;\n\t\t\tvoid this.wakeDueScheduledSessions().catch((error) =>\n\t\t\t\tthis.log(`Scheduled-session wake failed: ${String(error)}`),\n\t\t\t);\n\t\t}, delay);\n\t\tthis.scheduledWakeTimer.unref();\n\t}\n\n\tprivate async wakeDueScheduledSessions(now = Date.now()): Promise<void> {\n\t\t// Disarmed during update-restart preparation; the phase transition or next boot re-arms once.\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) {\n\t\t\tthis.clearScheduledWakeTimer();\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst due = new Map<string, string>();\n\t\t\tfor (const { rootSessionFile, job } of await this.collectPassiveScheduledJobs()) {\n\t\t\t\tif (job.status !== \"active\" || job.nextRunAt === undefined) continue;\n\t\t\t\tconst runAt = Date.parse(job.nextRunAt);\n\t\t\t\tif (!Number.isFinite(runAt) || runAt > now) continue;\n\t\t\t\tdue.set(canonicalSessionPath(rootSessionFile), rootSessionFile);\n\t\t\t}\n\t\t\tfor (const [rootKey, sessionPath] of due) {\n\t\t\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.createOrReuseWorker(SCHEDULED_WAKE_CLIENT_ID, { type: \"create\", sessionPath });\n\t\t\t\t\tthis.scheduledWakeFailures.delete(rootKey);\n\t\t\t\t\tthis.log(`Woke session worker for a due scheduled job: ${sessionPath}`);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.scheduledWakeFailures.set(rootKey, Date.now());\n\t\t\t\t\tthis.log(`Scheduled wake failed for ${sessionPath}: ${String(error)}`);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\t}\n\t}\n\n\tprivate scheduleIdleEvictionSweep(): void {\n\t\tif (this.shuttingDown || this.idleEvictionTimer || this.idleEvictionSweep) return;\n\t\tconst delayMs = idleEvictionSweepIntervalMs(this.settingsManager.getIdleEvictionMinutes());\n\t\tthis.idleEvictionTimer = setTimeout(() => {\n\t\t\tthis.idleEvictionTimer = undefined;\n\t\t\tconst sweep = this.runIdleEvictionSweep()\n\t\t\t\t.catch((error) => this.log(`Idle eviction sweep failed: ${String(error)}`))\n\t\t\t\t.finally(() => {\n\t\t\t\t\tif (this.idleEvictionSweep === sweep) this.idleEvictionSweep = undefined;\n\t\t\t\t\tthis.scheduleIdleEvictionSweep();\n\t\t\t\t});\n\t\t\tthis.idleEvictionSweep = sweep;\n\t\t}, delayMs);\n\t\tthis.idleEvictionTimer.unref();\n\t}\n\n\tprivate workerEvictionSnapshot(worker: ResidentWorker): WorkerEvictionSnapshot {\n\t\treturn {\n\t\t\tlifecycle: worker.descriptor.lifecycle,\n\t\t\tisConnected: worker.client !== undefined,\n\t\t\tisStopping: this.isWorkerStopping(worker),\n\t\t\thasOwnerClient: worker.descriptor.ownerClientId !== undefined,\n\t\t\tisPreparingUpdateRestart:\n\t\t\t\tthis.updateRestartPhase !== undefined || worker.updateRestartPrepareClient !== undefined,\n\t\t\thasWakeBlindSchedule: this.isWakeBlindScheduledWorker(worker),\n\t\t\tsessions: this.workerRosterEntries(worker)\n\t\t\t\t.filter((entry) => !entry.queuedChild)\n\t\t\t\t.map(sessionSummaryFromRosterEntry)\n\t\t\t\t.map((summary) => {\n\t\t\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tisSessionActive: isSessionSummaryBusy(summary),\n\t\t\t\t\t\tattachedClients: this.attachedClientCount(summary, activeSessionId),\n\t\t\t\t\t\thasRegisteredCronJob: summary.hasRegisteredCronJob === true,\n\t\t\t\t\t\tlastActivityAt: Date.parse(summary.lastActivityAt ?? \"\"),\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t};\n\t}\n\n\t/** A schedule whose root file sits outside the enumerable sessions root is invisible to the wake scan; keep it resident. */\n\tprivate isWakeBlindScheduledWorker(worker: ResidentWorker): boolean {\n\t\tconst sessionFile = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\tconst agentDir = this.defaultSessionConfig.agentDir;\n\t\tif (!sessionFile || !agentDir) return false;\n\t\tconst sessionsRoot = canonicalSessionPath(this.defaultSessionConfig.sessionDir ?? getSessionsDir(agentDir));\n\t\tif (dirname(canonicalSessionPath(sessionFile)) === sessionsRoot) return false;\n\t\treturn this.workerRosterEntries(worker).some(\n\t\t\t(entry) => entry.summary.hasRegisteredHeartbeat === true || entry.summary.hasRegisteredCronJob === true,\n\t\t);\n\t}\n\n\tprivate async runIdleEvictionSweep(now = Date.now()): Promise<void> {\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined || this.idleEvictionFence) return;\n\t\tawait this.settingsManager.reload();\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\tconst idleEvictionMinutes = this.settingsManager.getIdleEvictionMinutes();\n\t\tif (idleEvictionMinutes === \"off\") return;\n\n\t\tconst refreshed = new Set<ResidentWorker>();\n\t\tawait Promise.all(\n\t\t\t[...this.workers.values()].map(async (worker) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.refreshWorkerSummaries(worker);\n\t\t\t\t\trefreshed.add(worker);\n\t\t\t\t} catch {\n\t\t\t\t\t// A disconnected or transitioning worker is never an eviction candidate.\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t\tconst candidates = [...refreshed].filter((worker) =>\n\t\t\tcanEvictWorker(this.workerEvictionSnapshot(worker), idleEvictionMinutes, now),\n\t\t);\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t// Whole-tree candidates skip child work because stopWorker releases everything.\n\t\tawait Promise.all(\n\t\t\t[...refreshed]\n\t\t\t\t.filter((worker) => !candidates.includes(worker))\n\t\t\t\t.map(async (worker) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await worker.client?.requestWorker(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"worker_passivate_idle_children\",\n\t\t\t\t\t\t\t\tidleEvictionMinutes,\n\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\tlimit: CHILD_PASSIVATION_PER_WORKER_CAP,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t30_000,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (response && !response.success) throw new Error(response.error);\n\t\t\t\t\t\tawait this.refreshWorkerSummaries(worker);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\trefreshed.delete(worker);\n\t\t\t\t\t\tthis.log(`Child passivation sweep failed for worker ${worker.descriptor.workerId}: ${String(error)}`);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t);\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\n\t\tawait this.withEvictionFence(\"Timed out draining daemon mutations for idle eviction\", async () => {\n\t\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t\tawait Promise.all(\n\t\t\t\tcandidates.map((worker) => this.refreshWorkerSummaries(worker).catch(() => refreshed.delete(worker))),\n\t\t\t);\n\t\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t\tconst evictable = candidates.filter(\n\t\t\t\t(worker) =>\n\t\t\t\t\trefreshed.has(worker) &&\n\t\t\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\t\t\tcanEvictWorker(this.workerEvictionSnapshot(worker), idleEvictionMinutes, now),\n\t\t\t);\n\t\t\t// Promise.all may reject and release the fence while sibling stops are still\n\t\t\t// finishing. That is safe: a racing mutation either reaches a live worker or\n\t\t\t// gets a clean disconnected/unknown-session error.\n\t\t\tawait Promise.all(\n\t\t\t\tevictable.map(async (worker) => {\n\t\t\t\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t\t\t\tconst snapshot = this.workerEvictionSnapshot(worker);\n\t\t\t\t\tconst idleMinutes = Math.floor(\n\t\t\t\t\t\tMath.min(...snapshot.sessions.map((session) => now - session.lastActivityAt)) / 60_000,\n\t\t\t\t\t);\n\t\t\t\t\tconst root = worker.summaries.get(worker.descriptor.rootActiveSessionId);\n\t\t\t\t\tawait this.stopWorker(worker, true);\n\t\t\t\t\tthis.log(\n\t\t\t\t\t\t`Evicted idle worker ${worker.descriptor.workerId} root=${root?.sessionId ?? worker.descriptor.rootSessionId ?? worker.descriptor.rootActiveSessionId} idleMinutes=${idleMinutes} sessions=${snapshot.sessions.length}`,\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\t}\n\n\t/** Waits for any held eviction fence, then takes the slot; release clears it only if still ours. */\n\tprivate async acquireIdleEvictionFence(): Promise<() => void> {\n\t\twhile (this.idleEvictionFence) await this.idleEvictionFence;\n\t\tlet releaseFence: () => void = () => {};\n\t\tconst fence = new Promise<void>((resolveFence) => {\n\t\t\treleaseFence = resolveFence;\n\t\t});\n\t\tthis.idleEvictionFence = fence;\n\t\treturn () => {\n\t\t\tif (this.idleEvictionFence === fence) this.idleEvictionFence = undefined;\n\t\t\treleaseFence();\n\t\t};\n\t}\n\n\t/** Runs a passivation decision under the eviction fence after draining admitted mutations. */\n\tprivate async withEvictionFence(drainMessage: string, action: () => Promise<void>): Promise<void> {\n\t\tconst releaseFence = await this.acquireIdleEvictionFence();\n\t\ttry {\n\t\t\tawait this.mutationDrain.waitForDrain(0, AbortSignal.timeout(IDLE_EVICTION_DRAIN_TIMEOUT_MS), drainMessage);\n\t\t\tawait action();\n\t\t} finally {\n\t\t\treleaseFence();\n\t\t}\n\t}\n\n\tprivate async passivateWorkerIfStillEligible(\n\t\tworker: ResidentWorker,\n\t\tisStillEligible: () => boolean,\n\t\tdescribeEvicted: () => string,\n\t): Promise<void> {\n\t\tawait this.refreshWorkerSummaries(worker, false, true);\n\t\tif (!isStillEligible()) return;\n\t\tawait this.stopWorker(worker, true);\n\t\tthis.log(describeEvicted());\n\t}\n\n\tprivate async evictEmptySessionOnLastDetach(activeSessionId: string): Promise<void> {\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\tconst worker = this.matchWorkers(activeSessionId)[0]?.worker;\n\t\tif (\n\t\t\t!worker ||\n\t\t\tworker.descriptor.lifecycle !== \"ready\" ||\n\t\t\t!worker.client ||\n\t\t\tworker.descriptor.ownerClientId !== undefined || // owned workers have their own cleanup path\n\t\t\tthis.isWorkerStopping(worker)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tawait this.refreshWorkerSummaries(worker, false, true);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (!this.isEmptyDetachEvictionCandidate(worker)) return;\n\t\ttry {\n\t\t\t// Idle-sweep coordination: fence new mutations, drain admitted ones, re-read before deciding.\n\t\t\tawait this.withEvictionFence(\"Timed out draining daemon mutations for empty-session eviction\", () =>\n\t\t\t\tthis.passivateWorkerIfStillEligible(\n\t\t\t\t\tworker,\n\t\t\t\t\t() => this.isEmptyDetachEvictionCandidate(worker),\n\t\t\t\t\t() =>\n\t\t\t\t\t\t`Evicted empty session worker ${worker.descriptor.workerId} root=${worker.descriptor.rootSessionId ?? worker.descriptor.rootActiveSessionId} on last client detach`,\n\t\t\t\t),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthis.log(`Empty-session eviction failed for worker ${worker.descriptor.workerId}: ${String(error)}`);\n\t\t}\n\t}\n\n\tprivate isEmptyDetachEvictionCandidate(worker: ResidentWorker): boolean {\n\t\tif (\n\t\t\tthis.shuttingDown ||\n\t\t\tthis.updateRestartPhase !== undefined ||\n\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker ||\n\t\t\tthis.isWorkerStopping(worker) ||\n\t\t\tthis.isWakeBlindScheduledWorker(worker)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\tconst summaries = this.workerRosterEntries(worker)\n\t\t\t.filter((entry) => !entry.queuedChild)\n\t\t\t.map(sessionSummaryFromRosterEntry);\n\t\tconst hasAttachedClient = summaries.some(\n\t\t\t(summary) => this.attachedClientCount(summary, summary.activeSessionId ?? summary.id) > 0,\n\t\t);\n\t\treturn summaries.length > 0 && !hasAttachedClient && summaries.every(isEvictableEmptySessionSummary);\n\t}\n\n\tprivate async assertCurrentOwnership(): Promise<void> {\n\t\tconst ownership = this.ownership;\n\t\tif (!ownership) {\n\t\t\tconst error = new Error(\n\t\t\t\t`Daemon supervisor generation ${this.generation} holds no registry ownership (never acquired or already released); ` +\n\t\t\t\t\t`socket: ${this.socketPath}; restart the daemon to recover — sessions are preserved`,\n\t\t\t);\n\t\t\tObject.assign(error, { code: \"supervisor_generation_stale\" as const });\n\t\t\tthis.fenceRlmJournalOwner();\n\t\t\tthrow error;\n\t\t}\n\t\ttry {\n\t\t\tawait ownership.assertCurrent();\n\t\t} catch (error) {\n\t\t\tthis.fenceRlmJournalOwner();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async assertServingCurrentOwnership(allowWorkerLedger = false): Promise<void> {\n\t\tthis.assertSupervisorServing(allowWorkerLedger);\n\t\tawait this.assertCurrentOwnership();\n\t\tthis.assertSupervisorServing(allowWorkerLedger);\n\t}\n\n\tprivate async assertRecoveryAllowed(): Promise<void> {\n\t\tawait this.assertServingCurrentOwnership();\n\t\tif (await isDaemonShutdownAdmissionActive()) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Daemon shutdown admission cancelled worker recovery\");\n\t\t}\n\t}\n\n\tprivate supervisorAuthenticationClaim(): {\n\t\tsupervisorGeneration: string;\n\t\tsupervisorPid: number;\n\t\tsupervisorProcessStartId?: string;\n\t\tsupervisorSocketPath: string;\n\t} {\n\t\tconst record = this.ownership?.record;\n\t\tif (!record) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Daemon supervisor ownership is unavailable\");\n\t\t}\n\t\treturn {\n\t\t\tsupervisorGeneration: this.generation,\n\t\t\tsupervisorPid: record.pid,\n\t\t\t...(record.processStartId ? { supervisorProcessStartId: record.processStartId } : {}),\n\t\t\tsupervisorSocketPath: record.socketPath,\n\t\t};\n\t}\n\n\tprivate loadWorkerDescriptors(): void {\n\t\tfor (const name of readdirSync(this.descriptorDir)) {\n\t\t\tif (name === SUPERVISOR_CONFIG_FILE_NAME || !name.endsWith(\".json\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst path = join(this.descriptorDir, name);\n\t\t\ttry {\n\t\t\t\tconst descriptor: unknown = JSON.parse(readFileSync(path, \"utf8\"));\n\t\t\t\tif (!isDaemonWorkerDescriptor(descriptor, this.socketPath)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tdescriptor.supervisorSocketPath = normalizeSocketPath(descriptor.supervisorSocketPath);\n\t\t\t\tdescriptor.lifecycle = \"recovering\";\n\t\t\t\tdescriptor.recoveryJournalPath ??= join(this.descriptorDir, `${descriptor.workerId}.recovery.jsonl`);\n\t\t\t\tdescriptor.orphanProcessJournalPath ??= join(this.descriptorDir, `${descriptor.workerId}.orphans.jsonl`);\n\t\t\t\tconst durableDescriptor = durableDaemonWorkerDescriptor(descriptor);\n\t\t\t\tconst worker: ResidentWorker = {\n\t\t\t\t\tdescriptor: durableDescriptor,\n\t\t\t\t\tdescriptorPath: path,\n\t\t\t\t\tsummaries: new Map(),\n\t\t\t\t\tsnapshotCache: new Map(),\n\t\t\t\t\ttranscriptCaches: new Map(),\n\t\t\t\t\tsnapshotGenerations: new Map(),\n\t\t\t\t\tsnapshotLoads: new Map(),\n\t\t\t\t\tintentionalStop: durableDescriptor.stopRequestedAt !== undefined,\n\t\t\t\t\tstopRevision: 0,\n\t\t\t\t};\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tthis.workers.set(durableDescriptor.workerId, worker);\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Ignoring invalid worker descriptor ${path}: ${String(error)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Trees whose ephemeral-stop cancel failed stay owned until a retry lands: tombstoned client-owned descriptors with no resident worker. */\n\tprivate collectEphemeralCancelIntents(): Array<{ descriptor: DaemonWorkerDescriptor; descriptorPath: string }> {\n\t\tconst intents: Array<{ descriptor: DaemonWorkerDescriptor; descriptorPath: string }> = [];\n\t\tlet names: string[];\n\t\ttry {\n\t\t\tnames = readdirSync(this.descriptorDir);\n\t\t} catch {\n\t\t\treturn intents;\n\t\t}\n\t\tfor (const name of names) {\n\t\t\tif (name === SUPERVISOR_CONFIG_FILE_NAME || !name.endsWith(\".json\")) continue;\n\t\t\tconst descriptorPath = join(this.descriptorDir, name);\n\t\t\tlet descriptor: unknown;\n\t\t\ttry {\n\t\t\t\tdescriptor = JSON.parse(readFileSync(descriptorPath, \"utf8\"));\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!isDaemonWorkerDescriptor(descriptor, this.socketPath)) continue;\n\t\t\tif (descriptor.stopRequestedAt === undefined || descriptor.ownerClientId === undefined) continue;\n\t\t\tif (this.workers.has(descriptor.workerId)) continue;\n\t\t\tintents.push({ descriptor, descriptorPath });\n\t\t}\n\t\treturn intents;\n\t}\n\n\tprivate loadPersistedSupervisorConfig(): AgentSessionRuntimeConfig | undefined {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(\n\t\t\t\treadFileSync(this.supervisorConfigPath, \"utf8\"),\n\t\t\t) as Partial<PersistedSupervisorConfig>;\n\t\t\tif (\n\t\t\t\tparsed.version !== 1 ||\n\t\t\t\ttypeof parsed.socketPath !== \"string\" ||\n\t\t\t\tnormalizeSocketPath(parsed.socketPath) !== this.socketPath ||\n\t\t\t\t!parsed.defaultSessionConfig ||\n\t\t\t\ttypeof parsed.defaultSessionConfig !== \"object\" ||\n\t\t\t\ttypeof parsed.defaultSessionConfig.agentDir !== \"string\"\n\t\t\t) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn durableAgentSessionRuntimeConfig(parsed.defaultSessionConfig);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate persistSupervisorConfig(): void {\n\t\tconst persisted: PersistedSupervisorConfig = {\n\t\t\tversion: 1,\n\t\t\tsocketPath: this.socketPath,\n\t\t\tdefaultSessionConfig: durableAgentSessionRuntimeConfig(this.defaultSessionConfig),\n\t\t};\n\t\tconst tempPath = `${this.supervisorConfigPath}.${process.pid}.tmp`;\n\t\twriteFileSync(tempPath, `${JSON.stringify(persisted, null, 2)}\\n`, { mode: 0o600 });\n\t\tchmodSync(tempPath, 0o600);\n\t\trenameSync(tempPath, this.supervisorConfigPath);\n\t}\n\n\tprivate hasPersistedWorkerDescriptors(): boolean {\n\t\treturn readdirSync(this.descriptorDir).some(\n\t\t\t(name) => name !== SUPERVISOR_CONFIG_FILE_NAME && name.endsWith(\".json\"),\n\t\t);\n\t}\n\n\tprivate persistWorker(worker: ResidentWorker): void {\n\t\tworker.descriptor.updatedAt = new Date().toISOString();\n\t\tconst persisted = durableDaemonWorkerDescriptor(worker.descriptor);\n\t\tconst tempPath = `${worker.descriptorPath}.${process.pid}.tmp`;\n\t\twriteFileSync(tempPath, `${JSON.stringify(persisted, null, 2)}\\n`, { mode: 0o600 });\n\t\tchmodSync(tempPath, 0o600);\n\t\trenameSync(tempPath, worker.descriptorPath);\n\t}\n\n\tprivate deleteWorkerDescriptor(worker: { descriptorPath: string; descriptor: DaemonWorkerDescriptor }): void {\n\t\ttry {\n\t\t\trmSync(worker.descriptorPath, { force: true });\n\t\t\trmSync(worker.descriptor.recoveryJournalPath, { force: true });\n\t\t\tif (worker.descriptor.orphanProcessJournalPath) {\n\t\t\t\trmSync(worker.descriptor.orphanProcessJournalPath, { force: true });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.log(`Failed to remove worker descriptor ${worker.descriptorPath}: ${String(error)}`);\n\t\t}\n\t}\n\n\tprivate handleConnection(socket: Socket): void {\n\t\tconst client: DaemonSocketClient = {\n\t\t\tid: createActiveSessionId(),\n\t\t\tsocket,\n\t\t\tattachedActiveSessionIds: new Set(),\n\t\t\tcatchupActiveSessionIds: new Set(),\n\t\t\tbackpressured: false,\n\t\t\tauthenticated: true,\n\t\t\tsnapshotActiveSessionIds: new Set(),\n\t\t\tdetachInput: () => {},\n\t\t\tsupportsExtensionUi: false,\n\t\t\tcapabilities: new Set(DAEMON_DEFAULT_CLIENT_CAPABILITIES),\n\t\t};\n\t\tthis.connectionIds.set(client, client.id);\n\t\tthis.sessionInputPauseEpochs.set(client, 0);\n\t\tthis.detachingInputPauseSessions.set(client, new Set());\n\t\tthis.clients.add(client);\n\t\tvoid this.ready.then(\n\t\t\t() => {\n\t\t\t\tif (!client.socket.destroyed && this.clients.has(client)) {\n\t\t\t\t\tthis.write(client, {\n\t\t\t\t\t\ttype: \"daemon_hello\",\n\t\t\t\t\t\tsocketPath: this.socketPath,\n\t\t\t\t\t\tprotocol: DAEMON_PROTOCOL_INFO,\n\t\t\t\t\t\tschemaId: DAEMON_SCHEMA_ID,\n\t\t\t\t\t\tschemaRevision: DAEMON_SCHEMA_REVISION,\n\t\t\t\t\t\tappVersion: VERSION,\n\t\t\t\t\t\truntime: getDaemonRuntimeIdentity(),\n\t\t\t\t\t\tsupervisorGeneration: this.generation,\n\t\t\t\t\t\tsupervisorOwnerToken: this.ownership?.record.token,\n\t\t\t\t\t\tsupervisorPid: process.pid,\n\t\t\t\t\t\tsupervisorProcessStartId: this.ownership?.record.processStartId,\n\t\t\t\t\t\tsupervisorSocketPath: this.ownership?.record.socketPath,\n\t\t\t\t\t\tclientId: client.id,\n\t\t\t\t\t\tserverCapabilities: SUPERVISOR_SERVER_CAPABILITIES,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => client.socket.destroy(),\n\t\t);\n\n\t\tclient.detachInput = attachJsonlLineReader(socket, (line) => void this.handleLine(client, line));\n\t\tlet cleaned = false;\n\t\tconst cleanup = () => {\n\t\t\tif (cleaned) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcleaned = true;\n\t\t\tclient.detachInput();\n\t\t\tthis.sessionInputPauseEpochs.set(client, (this.sessionInputPauseEpochs.get(client) ?? 0) + 1);\n\t\t\tconst ownerClientId = this.protocolClientId(client);\n\t\t\tvoid this.releaseClientSessionInputPauses(client, undefined, true).catch((error: unknown) =>\n\t\t\t\tthis.log(`Failed to release input pauses for disconnected client ${ownerClientId}: ${String(error)}`),\n\t\t\t);\n\t\t\tthis.clients.delete(client);\n\t\t\tthis.cancelWaitingPromptAdmissionsForClient(client);\n\t\t\tfor (const activeSessionId of [...client.attachedActiveSessionIds]) {\n\t\t\t\tclient.attachedActiveSessionIds.delete(activeSessionId);\n\t\t\t\tvoid this.syncWorkerExtensionUi(activeSessionId);\n\t\t\t\tvoid this.evictEmptySessionOnLastDetach(activeSessionId);\n\t\t\t}\n\t\t\tthis.scheduleOwnedWorkerCleanupForClient(this.protocolClientId(client));\n\t\t};\n\t\tsocket.on(\"close\", cleanup);\n\t\tsocket.on(\"error\", cleanup);\n\t\tsocket.on(\"drain\", () => {\n\t\t\tclient.backpressured = false;\n\t\t\tif (client.rosterResyncPending && client.rosterSubscribed === true) {\n\t\t\t\t// socket.write queues even when it reports backpressure: one resync per loss gap.\n\t\t\t\tclient.rosterResyncPending = false;\n\t\t\t\tthis.write(client, { type: \"roster_update\", changed: this.rosterEntriesForClient(), resync: true });\n\t\t\t}\n\t\t\tif (!client.snapshotStreaming) {\n\t\t\t\tvoid this.catchUpClient(client).catch((error) =>\n\t\t\t\t\tthis.log(`Failed to catch up client ${client.id}: ${String(error)}`),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate cancelOwnedWorkerCleanup(clientId: string): void {\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker.descriptor.ownerClientId !== clientId || !worker.ownerCleanupTimer) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t}\n\t}\n\n\tprivate protocolClientId(client: DaemonSocketClient): string {\n\t\treturn this.protocolClientIds.get(client) ?? client.id;\n\t}\n\n\tprivate async releaseClientSessionInputPauses(\n\t\towner: DaemonSocketClient,\n\t\tactiveSessionId?: string,\n\t\tforceCleanupOnFailure = false,\n\t): Promise<void> {\n\t\tconst entries = [...this.sessionInputPauses.values()].filter(\n\t\t\t(entry) =>\n\t\t\t\tentry.owner === owner &&\n\t\t\t\t(activeSessionId === undefined ||\n\t\t\t\t\tentry.activeSessionId === activeSessionId ||\n\t\t\t\t\tentry.requestedActiveSessionId === activeSessionId),\n\t\t);\n\t\tawait Promise.all(\n\t\t\tentries.map(async (entry) => {\n\t\t\t\tif (this.workers.get(entry.worker.descriptor.workerId) !== entry.worker || !entry.worker.client) {\n\t\t\t\t\tif (this.sessionInputPauses.get(entry.pauseId) === entry) this.sessionInputPauses.delete(entry.pauseId);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await this.forwardToWorker(\n\t\t\t\t\t\tentry.worker,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: randomUUID(),\n\t\t\t\t\t\t\ttype: \"release_session_input_pause\",\n\t\t\t\t\t\t\tactiveSessionId: entry.activeSessionId,\n\t\t\t\t\t\t\tpauseId: entry.pauseId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tINPUT_PAUSE_CLEANUP_TIMEOUT_MS,\n\t\t\t\t\t);\n\t\t\t\t\tif (!response.success) throw new Error(response.error);\n\t\t\t\t\tif (this.sessionInputPauses.get(entry.pauseId) === entry) this.sessionInputPauses.delete(entry.pauseId);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (forceCleanupOnFailure) {\n\t\t\t\t\t\tconst workerClient = entry.worker.client;\n\t\t\t\t\t\tif (workerClient) {\n\t\t\t\t\t\t\tworkerClient.close();\n\t\t\t\t\t\t\tawait this.handleWorkerClose(\n\t\t\t\t\t\t\t\tentry.worker,\n\t\t\t\t\t\t\t\tworkerClient,\n\t\t\t\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.invalidateWorkerSessionInputPauses(\n\t\t\t\t\t\t\t\tentry.worker,\n\t\t\t\t\t\t\t\t\"Session worker became unavailable while releasing an input pause\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate invalidateWorkerSessionInputPauses(worker: ResidentWorker, reason: string): void {\n\t\tconst owners = new Set<DaemonSocketClient>();\n\t\tfor (const [pauseId, entry] of this.sessionInputPauses) {\n\t\t\tif (entry.worker !== worker) continue;\n\t\t\tthis.sessionInputPauses.delete(pauseId);\n\t\t\towners.add(entry.owner);\n\t\t}\n\t\tfor (const owner of owners) {\n\t\t\towner.socket.destroy(new Error(reason));\n\t\t}\n\t}\n\n\tprivate scheduleOwnedWorkerCleanupForClient(clientId: string): void {\n\t\tif ([...this.clients].some((client) => this.protocolClientId(client) === clientId)) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker.descriptor.ownerClientId === clientId) {\n\t\t\t\tthis.scheduleOwnedWorkerCleanup(worker);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate scheduleOwnedWorkerCleanup(worker: ResidentWorker): void {\n\t\tconst ownerClientId = worker.descriptor.ownerClientId;\n\t\tif (\n\t\t\t!ownerClientId ||\n\t\t\tworker.compatibilityError !== undefined ||\n\t\t\tworker.ownerCleanupTimer ||\n\t\t\t[...this.clients].some((client) => this.protocolClientId(client) === ownerClientId)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tworker.ownerCleanupTimer = setTimeout(() => {\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t\tif (\n\t\t\t\tworker.compatibilityError !== undefined ||\n\t\t\t\tworker.descriptor.ownerClientId !== ownerClientId ||\n\t\t\t\t[...this.clients].some((client) => this.protocolClientId(client) === ownerClientId) ||\n\t\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvoid this.stopWorker(worker, true).catch((error) =>\n\t\t\t\tthis.log(`Could not clean up client-owned worker ${worker.descriptor.workerId}: ${String(error)}`),\n\t\t\t);\n\t\t}, OWNED_WORKER_DISCONNECT_GRACE_MS);\n\t\tworker.ownerCleanupTimer.unref();\n\t}\n\n\tprivate promptAdmissionKey(activeSessionId: string, publicAdmissionId: string): string {\n\t\treturn `${activeSessionId}\\0${publicAdmissionId}`;\n\t}\n\n\tprivate promptAdmissionsFor(client: DaemonSocketClient): Map<string, SupervisorPromptAdmission> {\n\t\tlet admissions = this.promptAdmissions.get(client);\n\t\tif (!admissions) {\n\t\t\tadmissions = new Map();\n\t\t\tthis.promptAdmissions.set(client, admissions);\n\t\t}\n\t\treturn admissions;\n\t}\n\n\tprivate getPromptAdmission(\n\t\tclient: DaemonSocketClient,\n\t\tactiveSessionId: string,\n\t\tpublicAdmissionId: string,\n\t): SupervisorPromptAdmission | undefined {\n\t\treturn this.promptAdmissions.get(client)?.get(this.promptAdmissionKey(activeSessionId, publicAdmissionId));\n\t}\n\n\tprivate deletePromptAdmission(admission: SupervisorPromptAdmission): void {\n\t\tconst admissions = this.promptAdmissions.get(admission.client);\n\t\tconst key = this.promptAdmissionKey(admission.activeSessionId, admission.publicAdmissionId);\n\t\tif (admissions?.get(key) !== admission) return;\n\t\tadmissions.delete(key);\n\t\tif (admissions.size === 0) this.promptAdmissions.delete(admission.client);\n\t}\n\n\tprivate cancelWaitingPromptAdmissionsForClient(client: DaemonSocketClient): void {\n\t\tfor (const admission of this.promptAdmissions.get(client)?.values() ?? []) {\n\t\t\tif (admission.status !== \"waiting\") continue;\n\t\t\tif (!admission.worker || !admission.workerActiveSessionId) {\n\t\t\t\tadmission.status = \"cancelled\";\n\t\t\t\tadmission.controller.abort();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst worker = admission.worker;\n\t\t\tconst workerActiveSessionId = admission.workerActiveSessionId;\n\t\t\tvoid this.forwardToWorker(worker, {\n\t\t\t\ttype: \"cancel_prompt_admission\",\n\t\t\t\tactiveSessionId: workerActiveSessionId,\n\t\t\t\tadmissionId: admission.workerAdmissionId,\n\t\t\t})\n\t\t\t\t.then((response) => {\n\t\t\t\t\tif (admission.status !== \"waiting\") return;\n\t\t\t\t\tconst status =\n\t\t\t\t\t\tresponse.success && response.data && typeof response.data === \"object\" && \"status\" in response.data\n\t\t\t\t\t\t\t? (response.data as { status?: unknown }).status\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (status === \"owned\") admission.status = \"owned\";\n\t\t\t\t\telse if (status === \"cancelled\") admission.status = \"cancelled\";\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tthis.log(\n\t\t\t\t\t\t`Could not cancel prompt admission ${admission.workerAdmissionId} on disconnected client: ${String(error)}`,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/** Non-async by design: prompt registration completes before handleLine's first await. */\n\tprivate parseCommandAndRegisterPromptAdmission(\n\t\tclient: DaemonSocketClient,\n\t\tline: string,\n\t): {\n\t\tcommand: DaemonCommand;\n\t\tenvelopeClientId?: string;\n\t\tprotocolVersion: number;\n\t\tadmission?: SupervisorPromptAdmission;\n\t} {\n\t\tconst parsed = JSON.parse(line) as unknown;\n\t\tconst envelope = isDaemonCommandEnvelope(parsed) ? parsed : undefined;\n\t\tif (!envelope) {\n\t\t\tthrow new Error(`Daemon commands require protocol ${DAEMON_COMMAND_ENVELOPE_MIN_PROTOCOL_VERSION} or newer`);\n\t\t}\n\t\tconst command = { ...envelope.command, id: envelope.id } as DaemonCommand;\n\t\tif (\n\t\t\tenvelope.protocol.version < CANONICAL_SESSION_OWNERSHIP_COMPATIBILITY.minProtocol &&\n\t\t\t!isLegacyDaemonInspection(command)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Native daemon commands require protocol ${CANONICAL_SESSION_OWNERSHIP_COMPATIBILITY.minProtocol} canonical session ownership and bounded invocation output; only passive inspection is available`,\n\t\t\t);\n\t\t}\n\t\tlet admission: SupervisorPromptAdmission | undefined;\n\t\tif ((command.type === \"prompt\" || command.type === \"prompt_and_wait\") && command.admissionId !== undefined) {\n\t\t\tif (typeof command.activeSessionId !== \"string\" || typeof command.admissionId !== \"string\") {\n\t\t\t\tthrow new Error(\"Prompt admission requires string activeSessionId and admissionId\");\n\t\t\t}\n\t\t\tif (command.admissionId === \"\") throw new Error(\"admissionId must not be empty\");\n\t\t\tconst admissions = this.promptAdmissionsFor(client);\n\t\t\tconst key = this.promptAdmissionKey(command.activeSessionId, command.admissionId);\n\t\t\tif (admissions.has(key)) {\n\t\t\t\tthrow new Error(`Prompt admission id is already in use: ${command.admissionId}`);\n\t\t\t}\n\t\t\tadmission = {\n\t\t\t\tclient,\n\t\t\t\tactiveSessionId: command.activeSessionId,\n\t\t\t\tpublicAdmissionId: command.admissionId,\n\t\t\t\tworkerAdmissionId: `supervisor-admission:${randomUUID()}`,\n\t\t\t\tstatus: \"waiting\",\n\t\t\t\tcontroller: new AbortController(),\n\t\t\t};\n\t\t\tadmissions.set(key, admission);\n\t\t}\n\t\treturn {\n\t\t\tcommand,\n\t\t\tenvelopeClientId: envelope.clientId ?? client.id,\n\t\t\tprotocolVersion: envelope.protocol.version,\n\t\t\tadmission,\n\t\t};\n\t}\n\n\tprivate isWorkerLedgerEnvelope(line: string): boolean {\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(line);\n\t\t\treturn isDaemonCommandEnvelope(parsed) && parsed.command.type === \"rlm_ledger_mutate\";\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate async handleLine(client: DaemonSocketClient, line: string): Promise<void> {\n\t\ttry {\n\t\t\tthis.assertSupervisorServing(this.shuttingDown && this.isWorkerLedgerEnvelope(line));\n\t\t} catch (error) {\n\t\t\tthis.write(client, failure(salvageDaemonCommandId(line), \"dispatch\", error, serializeDaemonError(error)));\n\t\t\treturn;\n\t\t}\n\t\tlet preParsed: ReturnType<DaemonSupervisor[\"parseCommandAndRegisterPromptAdmission\"]>;\n\t\ttry {\n\t\t\tpreParsed = this.parseCommandAndRegisterPromptAdmission(client, line);\n\t\t} catch (error) {\n\t\t\tthis.write(client, failure(salvageDaemonCommandId(line), \"parse\", error));\n\t\t\treturn;\n\t\t}\n\t\tconst command = preParsed.command;\n\t\tconst parsedAdmission = preParsed.admission;\n\t\tif (command.type === \"cancel_prompt_admission\" && this.updateRestartPhase !== undefined) {\n\t\t\tthis.write(client, failure(command.id, command.type, \"Daemon is preparing an update restart\"));\n\t\t\treturn;\n\t\t}\n\t\tconst cancellationAdmission =\n\t\t\tcommand.type === \"cancel_prompt_admission\"\n\t\t\t\t? this.getPromptAdmission(client, command.activeSessionId, command.admissionId)\n\t\t\t\t: undefined;\n\t\tif (cancellationAdmission?.status === \"waiting\" && !cancellationAdmission.worker) {\n\t\t\tcancellationAdmission.status = \"cancelled\";\n\t\t\tcancellationAdmission.controller.abort();\n\t\t}\n\t\ttry {\n\t\t\tawait waitForPromptAdmission(this.ready, parsedAdmission?.controller.signal);\n\t\t} catch (error) {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(client, failure(command.id, command.type, error));\n\t\t\treturn;\n\t\t}\n\t\tconst envelopeClientId = preParsed.envelopeClientId;\n\t\tif (envelopeClientId) {\n\t\t\tthis.protocolClientIds.set(client, envelopeClientId);\n\t\t\tclient.id = envelopeClientId;\n\t\t}\n\t\tthis.cancelOwnedWorkerCleanup(client.id);\n\t\tif (!DAEMON_COMMAND_TYPES.has(command.type)) {\n\t\t\tthis.write(client, failure(command.id, command.type, `Unknown daemon command: ${command.type}`));\n\t\t\treturn;\n\t\t}\n\t\tif (\n\t\t\tcommand.type === \"get_session_tree\" &&\n\t\t\tpreParsed.protocolVersion < DAEMON_COMMAND_COMPATIBILITY.get_session_tree.minProtocol\n\t\t) {\n\t\t\tthis.write(\n\t\t\t\tclient,\n\t\t\t\tfailure(\n\t\t\t\t\tcommand.id,\n\t\t\t\t\tcommand.type,\n\t\t\t\t\t`get_session_tree requires client protocol ${DAEMON_COMMAND_COMPATIBILITY.get_session_tree.minProtocol} or newer`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait waitForPromptAdmission(\n\t\t\t\tthis.assertServingCurrentOwnership(command.type === \"rlm_ledger_mutate\"),\n\t\t\t\tparsedAdmission?.controller.signal,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(client, failure(command.id, command.type, error));\n\t\t\treturn;\n\t\t}\n\n\t\tconst mutation = isDaemonMutatingCommand(command);\n\t\tconst journalIdentity =\n\t\t\tenvelopeClientId && command.id && mutation ? { clientId: envelopeClientId, commandId: command.id } : undefined;\n\t\tconst existing = journalIdentity\n\t\t\t? this.commandJournal.lookup(journalIdentity.clientId, journalIdentity.commandId)\n\t\t\t: undefined;\n\t\tif (existing?.status === \"complete\") {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(client, existing.response);\n\t\t\treturn;\n\t\t}\n\t\tif (existing?.status === \"pending\" && journalIdentity) {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(\n\t\t\t\tclient,\n\t\t\t\tfailure(command.id, command.type, \"The previous command result is uncertain and was not replayed\", {\n\t\t\t\t\tcode: \"command_result_uncertain\",\n\t\t\t\t\t...journalIdentity,\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst phase = this.updateRestartPhase;\n\t\tconst restartRejected =\n\t\t\tphase === \"draining\"\n\t\t\t\t? !UPDATE_RESTART_DRAIN_COMMANDS.has(command.type)\n\t\t\t\t: phase !== undefined && !(phase === \"prepared\" && command.type === \"shutdown\");\n\t\tif (restartRejected && mutation && command.type !== \"rlm_ledger_mutate\") {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(client, failure(command.id, command.type, \"Daemon is preparing an update restart\"));\n\t\t\treturn;\n\t\t}\n\t\tif (mutation && !UPDATE_RESTART_DRAIN_COMMANDS.has(command.type)) {\n\t\t\tconst idleEvictionFence = this.idleEvictionFence;\n\t\t\tif (idleEvictionFence) {\n\t\t\t\tawait idleEvictionFence;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.assertServingCurrentOwnership(command.type === \"rlm_ledger_mutate\");\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\t\t\tthis.write(client, failure(command.id, command.type, error, serializeDaemonError(error)));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (journalIdentity) {\n\t\t\tlet admitted: CommandJournalBeginResult;\n\t\t\ttry {\n\t\t\t\tadmitted = this.commandJournal.begin(journalIdentity.clientId, journalIdentity.commandId, command.type);\n\t\t\t} catch (error) {\n\t\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\t\tthis.write(client, failure(command.id, command.type, error, serializeDaemonError(error)));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (admitted.status === \"complete\") {\n\t\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\t\tthis.write(client, admitted.response);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (admitted.status === \"pending\") {\n\t\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\t\tthis.write(\n\t\t\t\t\tclient,\n\t\t\t\t\tfailure(command.id, command.type, \"The previous command result is uncertain and was not replayed\", {\n\t\t\t\t\t\tcode: \"command_result_uncertain\",\n\t\t\t\t\t\t...journalIdentity,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Attach is intentionally read-only and is not fence-gated. If eviction wins\n\t\t// the race, attach fails cleanly with \"Session worker is not connected\" and\n\t\t// the client retries through the saved-session path instead of mutating state.\n\t\tif (mutation) this.mutationDrain.begin();\n\t\tlet commandCompleted = false;\n\t\ttry {\n\t\t\tconst response = await this.handleCommand(client, command, cancellationAdmission);\n\t\t\tcommandCompleted = true;\n\t\t\tif (response) {\n\t\t\t\tif (journalIdentity) {\n\t\t\t\t\tawait this.assertCurrentOwnership();\n\t\t\t\t\tthis.commandJournal.recordResult(journalIdentity.clientId, journalIdentity.commandId, response);\n\t\t\t\t}\n\t\t\t\tthis.write(client, response);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.log(`Supervisor command ${command.type} failed: ${error instanceof Error ? error.stack : String(error)}`);\n\t\t\tlet response = failure(command.id, command.type, error, serializeDaemonError(error));\n\t\t\t// A completed command must not get a conflicting failure result after uncertain result persistence.\n\t\t\tif (journalIdentity && !commandCompleted && !isSupervisorGenerationStale(error)) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.assertCurrentOwnership();\n\t\t\t\t\tthis.commandJournal.recordResult(journalIdentity.clientId, journalIdentity.commandId, response);\n\t\t\t\t} catch (persistenceError) {\n\t\t\t\t\tconst failureError =\n\t\t\t\t\t\tpersistenceError === error\n\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t: new AggregateError(\n\t\t\t\t\t\t\t\t\t[error, persistenceError],\n\t\t\t\t\t\t\t\t\t\"Supervisor command and result persistence failed\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\tresponse = failure(command.id, command.type, failureError, serializeDaemonError(failureError));\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.write(client, response);\n\t\t} finally {\n\t\t\tif (mutation) this.mutationDrain.end();\n\t\t}\n\t}\n\n\tprivate async handleCommand(\n\t\tclient: DaemonSocketClient,\n\t\tcommand: DaemonCommand,\n\t\tcancellationAdmission?: SupervisorPromptAdmission,\n\t): Promise<DaemonResponse | undefined> {\n\t\tswitch (command.type) {\n\t\t\tcase \"cancel_prompt_admission\": {\n\t\t\t\tconst admission =\n\t\t\t\t\tcancellationAdmission ?? this.getPromptAdmission(client, command.activeSessionId, command.admissionId);\n\t\t\t\tif (!admission) return success(command.id, command.type, { status: \"unknown\" as const });\n\t\t\t\tif (admission.status === \"owned\") return success(command.id, command.type, { status: \"owned\" as const });\n\t\t\t\t// A definitive cancellation never downgrades to unknown/waiting.\n\t\t\t\tif (admission.status === \"cancelled\") {\n\t\t\t\t\treturn success(command.id, command.type, { status: \"cancelled\" as const });\n\t\t\t\t}\n\t\t\t\tif (!admission.worker || !admission.workerActiveSessionId) {\n\t\t\t\t\tadmission.status = \"cancelled\";\n\t\t\t\t\tadmission.controller.abort();\n\t\t\t\t\treturn success(command.id, command.type, { status: \"cancelled\" as const });\n\t\t\t\t}\n\t\t\t\tconst response = await this.forwardToWorker(admission.worker, {\n\t\t\t\t\t...command,\n\t\t\t\t\tactiveSessionId: admission.workerActiveSessionId,\n\t\t\t\t\tadmissionId: admission.workerAdmissionId,\n\t\t\t\t});\n\t\t\t\tconst status =\n\t\t\t\t\tresponse.success && response.data && typeof response.data === \"object\" && \"status\" in response.data\n\t\t\t\t\t\t? (response.data as { status: \"cancelled\" | \"owned\" | \"unknown\" }).status\n\t\t\t\t\t\t: \"unknown\";\n\t\t\t\t// Re-read: a socket close may have cancelled during the round-trip (cast widens TS's pre-await narrowing).\n\t\t\t\tconst current = (admission as SupervisorPromptAdmission).status;\n\t\t\t\tif (status === \"owned\") admission.status = \"owned\";\n\t\t\t\telse if (status === \"cancelled\") admission.status = \"cancelled\";\n\t\t\t\telse if (current !== \"cancelled\") admission.status = \"waiting\";\n\t\t\t\treturn { ...response, id: command.id };\n\t\t\t}\n\t\t\tcase \"ack_result\":\n\t\t\t\tthis.commandJournal.acknowledge(client.id, command.commandId);\n\t\t\t\treturn undefined;\n\t\t\tcase \"list\":\n\t\t\t\treturn this.handleList(client, command);\n\t\t\tcase \"roster_subscribe\":\n\t\t\t\tclient.rosterSubscribed = true;\n\t\t\t\treturn success(command.id, command.type, { roster: this.rosterEntriesForClient() });\n\t\t\tcase \"roster_unsubscribe\":\n\t\t\t\tclient.rosterSubscribed = false;\n\t\t\t\tclient.rosterResyncPending = false;\n\t\t\t\treturn success(command.id, command.type);\n\t\t\tcase \"list_agent_peers\": {\n\t\t\t\tconst requester = [...this.workers.values()].find(\n\t\t\t\t\t(worker) => worker.descriptor.authenticationToken === command.workerToken,\n\t\t\t\t);\n\t\t\t\tif (!requester) throw new Error(\"Worker authentication failed\");\n\t\t\t\tconst peers = [...this.workers.values()]\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(worker) =>\n\t\t\t\t\t\t\tworker !== requester &&\n\t\t\t\t\t\t\tthis.isLiveWorker(worker) &&\n\t\t\t\t\t\t\tworker.descriptor.lifecycle === \"ready\" &&\n\t\t\t\t\t\t\tworker.client !== undefined,\n\t\t\t\t\t)\n\t\t\t\t\t.flatMap((worker) => {\n\t\t\t\t\t\tconst root = this.roster().byActiveSessionId(worker.descriptor.rootActiveSessionId);\n\t\t\t\t\t\treturn root ? [this.agentPeerSummary(sessionSummaryFromRosterEntry(root))] : [];\n\t\t\t\t\t});\n\t\t\t\treturn success(command.id, command.type, { peers });\n\t\t\t}\n\t\t\tcase \"rlm_ledger_mutate\": {\n\t\t\t\tconst worker = [...this.workers.values()].find(\n\t\t\t\t\t(candidate) => candidate.descriptor.authenticationToken === command.workerToken,\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\t!worker ||\n\t\t\t\t\t!command.workerInstanceId ||\n\t\t\t\t\tworker.descriptor.workerInstanceId !== command.workerInstanceId ||\n\t\t\t\t\tworker.compatibilityError ||\n\t\t\t\t\tthis.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId) !== \"current\"\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Worker authentication failed for RLM ledger mutation\");\n\t\t\t\t}\n\t\t\t\tconst owner = this.assertRlmJournalAdmission();\n\t\t\t\tconst scope = this.rlmJournalScope(worker.descriptor.sessionDir ?? this.defaultSessionConfig.sessionDir);\n\t\t\t\tif (canonicalSessionPath(scope.journalPath) !== owner.ledgerPath) {\n\t\t\t\t\tthrow new Error(\"Worker RLM ledger family is not owned by this supervisor\");\n\t\t\t\t}\n\t\t\t\tawait this.rlmSpawnLedger().mutate(command.mutation);\n\t\t\t\treturn success(command.id, command.type);\n\t\t\t}\n\t\t\tcase \"get_direct_worker_transport\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tif (match.worker.descriptor.ownerClientId !== undefined) {\n\t\t\t\t\tthrow new Error(\"Direct transport is unavailable for client-owned workers\");\n\t\t\t\t}\n\t\t\t\tconst ticket = await this.issuePeerTransport(match.worker, match.summary);\n\t\t\t\treturn success(command.id, command.type, ticket);\n\t\t\t}\n\t\t\tcase \"list_saved_sessions\":\n\t\t\t\treturn this.handleSavedSessionList(client, command);\n\t\t\tcase \"create\": {\n\t\t\t\tconst worker = await this.createOrReuseWorker(this.protocolClientId(client), command);\n\t\t\t\tconst requestedSummary = command.sessionPath\n\t\t\t\t\t? this.findSummaryInWorker(worker, command.sessionPath)\n\t\t\t\t\t: undefined;\n\t\t\t\tif (\n\t\t\t\t\trequestedSummary &&\n\t\t\t\t\t(requestedSummary.activeSessionId ?? requestedSummary.id) !== worker.descriptor.rootActiveSessionId\n\t\t\t\t) {\n\t\t\t\t\t// A create forwarded to a recovering worker still surfaces an opaque lifecycle error.\n\t\t\t\t\tconst response = await this.forwardToWorker(worker, withoutSupervisorCreateFields(command));\n\t\t\t\t\tif (response.success && isSessionSummary(response.data)) {\n\t\t\t\t\t\tthis.writeRosterEntry(workerRosterEntryFromSummary(response.data), worker);\n\t\t\t\t\t\treturn { ...response, id: command.id, data: this.publicSummary(worker, response.data) };\n\t\t\t\t\t}\n\t\t\t\t\treturn responseWithId(response, command.id);\n\t\t\t\t}\n\t\t\t\tconst root = this.roster().byActiveSessionId(worker.descriptor.rootActiveSessionId);\n\t\t\t\tif (!root) {\n\t\t\t\t\tthrow new Error(\"Session worker started without a root session\");\n\t\t\t\t}\n\t\t\t\treturn success(command.id, \"create\", this.publicSummary(worker, sessionSummaryFromRosterEntry(root)));\n\t\t\t}\n\t\t\tcase \"attach\": {\n\t\t\t\tconst attached = await this.attachClient(client, command);\n\t\t\t\tif (client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\t\t\tconst transcript = attached.transcript;\n\t\t\t\t\tif (!transcript) {\n\t\t\t\t\t\tthrow new Error(\"Session worker did not provide a snapshot transcript\");\n\t\t\t\t\t}\n\t\t\t\t\tconst streamedResult = this.createStreamedAttachResult(attached.result, transcript);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.write(client, success(command.id, \"attach\", streamedResult));\n\t\t\t\t\t\tvoid this.streamSnapshot(\n\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\tattached.worker,\n\t\t\t\t\t\t\tstreamedResult,\n\t\t\t\t\t\t\ttranscript,\n\t\t\t\t\t\t\t\"attach\",\n\t\t\t\t\t\t\tattached.releaseTranscript,\n\t\t\t\t\t\t).catch((error) =>\n\t\t\t\t\t\t\tthis.log(\n\t\t\t\t\t\t\t\t`Failed to stream attach snapshot for ${streamedResult.activeSessionId}: ${String(error)}`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tattached.releaseTranscript?.();\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\treturn success(command.id, \"attach\", attached.result);\n\t\t\t}\n\t\t\tcase \"reattach\": {\n\t\t\t\tconst target = await this.findWorkerForClient(client, command.targetActiveSessionId);\n\t\t\t\tconst targetActiveSessionId = target.summary.activeSessionId ?? target.summary.id;\n\t\t\t\tif (targetActiveSessionId === command.activeSessionId) {\n\t\t\t\t\tconst detachingSessions = this.detachingInputPauseSessions?.get(client);\n\t\t\t\t\tdetachingSessions?.delete(command.activeSessionId);\n\t\t\t\t\tdetachingSessions?.delete(command.targetActiveSessionId);\n\t\t\t\t\tdetachingSessions?.delete(targetActiveSessionId);\n\t\t\t\t\treturn success(command.id, command.type, { cancelled: false });\n\t\t\t\t}\n\t\t\t\tconst targetWasAttached = client.attachedActiveSessionIds.has(targetActiveSessionId);\n\t\t\t\tconst releaseSnapshotReservation = this.reserveSnapshotStream(client, targetActiveSessionId);\n\t\t\t\tlet releaseTranscript: (() => void) | undefined;\n\t\t\t\tclient.attachedActiveSessionIds.add(targetActiveSessionId);\n\t\t\t\ttry {\n\t\t\t\t\tconst attached = await this.attachClient(client, {\n\t\t\t\t\t\t...command,\n\t\t\t\t\t\ttype: \"attach\",\n\t\t\t\t\t\tactiveSessionId: targetActiveSessionId,\n\t\t\t\t\t});\n\t\t\t\t\tconst detachingSessions = this.detachingInputPauseSessions?.get(client);\n\t\t\t\t\tdetachingSessions?.delete(command.activeSessionId);\n\t\t\t\t\tdetachingSessions?.delete(command.targetActiveSessionId);\n\t\t\t\t\tdetachingSessions?.delete(targetActiveSessionId);\n\t\t\t\t\tif (client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\t\t\t\tconst transcript =\n\t\t\t\t\t\t\tattached.transcript ?? this.getOrCreateTranscriptCache(attached.worker, attached.result);\n\t\t\t\t\t\treleaseTranscript = attached.releaseTranscript;\n\t\t\t\t\t\tconst streamedResult = this.createStreamedAttachResult(attached.result, transcript);\n\t\t\t\t\t\tthis.write(client, success(command.id, command.type, streamedResult));\n\t\t\t\t\t\tthis.detachClient(client, command.activeSessionId);\n\t\t\t\t\t\tconst streaming = this.streamSnapshot(\n\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\tattached.worker,\n\t\t\t\t\t\t\tstreamedResult,\n\t\t\t\t\t\t\ttranscript,\n\t\t\t\t\t\t\t\"replacement\",\n\t\t\t\t\t\t\treleaseTranscript,\n\t\t\t\t\t\t\treleaseSnapshotReservation,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treleaseTranscript = undefined;\n\t\t\t\t\t\tvoid streaming.catch((error) =>\n\t\t\t\t\t\t\tthis.log(`Failed to stream reattach snapshot for ${targetActiveSessionId}: ${String(error)}`),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t\tthis.write(client, success(command.id, command.type, attached.result));\n\t\t\t\t\tthis.detachClient(client, command.activeSessionId);\n\t\t\t\t\treleaseSnapshotReservation();\n\t\t\t\t\treturn undefined;\n\t\t\t\t} catch (error) {\n\t\t\t\t\treleaseTranscript?.();\n\t\t\t\t\tif (!targetWasAttached) {\n\t\t\t\t\t\tthis.detachClient(client, targetActiveSessionId);\n\t\t\t\t\t}\n\t\t\t\t\treleaseSnapshotReservation();\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"acquire_session_input_pause\": {\n\t\t\t\tconst detachingSessions = this.detachingInputPauseSessions.get(client);\n\t\t\t\tif (detachingSessions?.has(command.activeSessionId)) {\n\t\t\t\t\tthrow new Error(`Session is detaching: ${command.activeSessionId}`);\n\t\t\t\t}\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tconst activeSessionId = match.summary.activeSessionId ?? match.summary.id;\n\t\t\t\tif (detachingSessions?.has(command.activeSessionId) || detachingSessions?.has(activeSessionId)) {\n\t\t\t\t\tthrow new Error(`Session is detaching: ${command.activeSessionId}`);\n\t\t\t\t}\n\t\t\t\tconst ownerClientId = this.protocolClientId(client);\n\t\t\t\tconst connectionId = this.connectionIds.get(client);\n\t\t\t\tif (!connectionId) throw new Error(\"Daemon client connection identity is unavailable\");\n\t\t\t\tconst acquisitionEpoch = this.sessionInputPauseEpochs.get(client) ?? 0;\n\t\t\t\tconst existing = [...this.sessionInputPauses.values()].find(\n\t\t\t\t\t(entry) =>\n\t\t\t\t\t\tentry.owner === client &&\n\t\t\t\t\t\tentry.worker === match.worker &&\n\t\t\t\t\t\tentry.activeSessionId === activeSessionId &&\n\t\t\t\t\t\tentry.leaseKey === command.leaseKey &&\n\t\t\t\t\t\t!entry.releaseTask,\n\t\t\t\t);\n\t\t\t\tif (existing) {\n\t\t\t\t\treturn success(command.id, command.type, { pauseId: existing.pauseId });\n\t\t\t\t}\n\t\t\t\tconst response = await this.forwardToWorker(match.worker, {\n\t\t\t\t\t...command,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tleaseKey: JSON.stringify([connectionId, ownerClientId, command.leaseKey]),\n\t\t\t\t});\n\t\t\t\tif (!response.success) return response;\n\t\t\t\tconst pauseId = (response.data as { pauseId?: unknown } | undefined)?.pauseId;\n\t\t\t\tif (typeof pauseId !== \"string\") throw new Error(\"Worker returned an invalid session input pause id\");\n\t\t\t\tif (!this.clients.has(client) || (this.sessionInputPauseEpochs.get(client) ?? 0) !== acquisitionEpoch) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst release = await this.forwardToWorker(match.worker, {\n\t\t\t\t\t\t\tid: randomUUID(),\n\t\t\t\t\t\t\ttype: \"release_session_input_pause\",\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tpauseId,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (!release.success) throw new Error(release.error);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tmatch.worker.client?.close();\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tthrow new Error(\"Session input pause acquisition was invalidated before completion\");\n\t\t\t\t}\n\t\t\t\tthis.sessionInputPauses.set(pauseId, {\n\t\t\t\t\towner: client,\n\t\t\t\t\tworker: match.worker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\trequestedActiveSessionId: command.activeSessionId,\n\t\t\t\t\tleaseKey: command.leaseKey,\n\t\t\t\t\tpauseId,\n\t\t\t\t});\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\tcase \"release_session_input_pause\": {\n\t\t\t\tconst entry = this.sessionInputPauses.get(command.pauseId);\n\t\t\t\tif (!entry) return success(command.id, command.type);\n\t\t\t\tif (entry.owner !== client) {\n\t\t\t\t\tthrow new Error(`Session input pause is owned by another client: ${command.pauseId}`);\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tcommand.activeSessionId !== entry.activeSessionId &&\n\t\t\t\t\tcommand.activeSessionId !== entry.requestedActiveSessionId\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(`Session input pause belongs to another session: ${command.pauseId}`);\n\t\t\t\t}\n\t\t\t\tconst releaseTask =\n\t\t\t\t\tentry.releaseTask ??\n\t\t\t\t\tthis.forwardToWorker(entry.worker, {\n\t\t\t\t\t\t...command,\n\t\t\t\t\t\tactiveSessionId: entry.activeSessionId,\n\t\t\t\t\t});\n\t\t\t\tentry.releaseTask = releaseTask;\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await releaseTask;\n\t\t\t\t\tif (response.success && this.sessionInputPauses.get(command.pauseId) === entry) {\n\t\t\t\t\t\tthis.sessionInputPauses.delete(command.pauseId);\n\t\t\t\t\t}\n\t\t\t\t\treturn response;\n\t\t\t\t} finally {\n\t\t\t\t\tif (this.sessionInputPauses.get(command.pauseId) === entry && entry.releaseTask === releaseTask) {\n\t\t\t\t\t\tentry.releaseTask = undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"detach\": {\n\t\t\t\tconst detachingSessions = this.detachingInputPauseSessions.get(client) ?? new Set<string>();\n\t\t\t\tthis.detachingInputPauseSessions.set(client, detachingSessions);\n\t\t\t\tif (command.activeSessionId) detachingSessions.add(command.activeSessionId);\n\t\t\t\telse for (const activeSessionId of client.attachedActiveSessionIds) detachingSessions.add(activeSessionId);\n\t\t\t\tthis.sessionInputPauseEpochs.set(client, (this.sessionInputPauseEpochs.get(client) ?? 0) + 1);\n\t\t\t\tthis.detachClient(client, command.activeSessionId);\n\t\t\t\tawait this.releaseClientSessionInputPauses(client, command.activeSessionId, true);\n\t\t\t\treturn success(command.id, \"detach\");\n\t\t\t}\n\t\t\tcase \"complete_owned_session\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tif (match.worker.descriptor.ownerClientId !== this.protocolClientId(client)) {\n\t\t\t\t\tthrow new Error(\"Session is not owned by this client\");\n\t\t\t\t}\n\t\t\t\tif (match.worker.ownerCleanupTimer) {\n\t\t\t\t\tclearTimeout(match.worker.ownerCleanupTimer);\n\t\t\t\t\tmatch.worker.ownerCleanupTimer = undefined;\n\t\t\t\t}\n\t\t\t\tawait this.stopWorker(match.worker, true);\n\t\t\t\treturn success(command.id, command.type);\n\t\t\t}\n\t\t\tcase \"promote_owned_session\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tawait this.promoteOwnedWorker(client, match.worker);\n\t\t\t\treturn success(command.id, command.type, this.publicSummary(match.worker, match.summary));\n\t\t\t}\n\t\t\tcase \"retry_worker\": {\n\t\t\t\tconst direct = [...this.workers.values()].find(\n\t\t\t\t\t(worker) =>\n\t\t\t\t\t\tworker.descriptor.rootActiveSessionId === command.activeSessionId ||\n\t\t\t\t\t\tworker.descriptor.rootSessionId === command.activeSessionId,\n\t\t\t\t);\n\t\t\t\tconst worker = direct ?? (await this.findWorkerForClient(client, command.activeSessionId)).worker;\n\t\t\t\tthis.assertWorkerAccessibleToClient(client, worker, command.activeSessionId);\n\t\t\t\tif ((this.workerStopCounts?.get(worker) ?? 0) > 0) {\n\t\t\t\t\tthrow new Error(\"Session worker is stopping; retry after it finishes\");\n\t\t\t\t}\n\t\t\t\tworker.intentionalStop = false;\n\t\t\t\tworker.descriptor.stopRequestedAt = undefined;\n\t\t\t\tworker.descriptor.archiveOnStop = undefined;\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tworker.descriptor.consecutiveFailures = 0;\n\t\t\t\tworker.deferredRecoveryRounds = 0;\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tawait this.recoverWorker(worker);\n\t\t\t\tif (this.workers.get(worker.descriptor.workerId)?.descriptor.lifecycle !== \"ready\") {\n\t\t\t\t\tthrow new Error(worker.descriptor.lastError ?? \"Session worker recovery failed\");\n\t\t\t\t}\n\t\t\t\tconst summary = worker.summaries.get(worker.descriptor.rootActiveSessionId);\n\t\t\t\treturn success(command.id, command.type, summary ? this.publicSummary(worker, summary) : undefined);\n\t\t\t}\n\t\t\tcase \"restart\":\n\t\t\t\tsetImmediate(() => void this.shutdown(0, false, true, false, \"update\"));\n\t\t\t\treturn success(command.id, command.type);\n\t\t\tcase \"shutdown\":\n\t\t\t\tsetImmediate(() => void this.shutdown(0, true, false, command.force === true, \"shutdown\"));\n\t\t\t\treturn success(command.id, \"shutdown\");\n\t\t\tcase \"prepare_update_restart\": {\n\t\t\t\tconst manifest = await this.prepareUpdateRestart();\n\t\t\t\treturn success(command.id, \"prepare_update_restart\", manifest);\n\t\t\t}\n\t\t\tcase \"agent_messages_status\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst first = [...this.workers.values()].find((worker) => this.isLiveWorker(worker) && worker.client);\n\t\t\t\tif (!first) {\n\t\t\t\t\treturn success(command.id, command.type, { paused: false, limits: {} });\n\t\t\t\t}\n\t\t\t\treturn this.forwardToWorker(first, command);\n\t\t\t}\n\t\t\tcase \"agent_messages_pause\":\n\t\t\tcase \"agent_messages_resume\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst responses = await Promise.all(\n\t\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t\t.filter((worker) => this.isLiveWorker(worker) && worker.client)\n\t\t\t\t\t\t.map((worker) => this.forwardToWorker(worker, command)),\n\t\t\t\t);\n\t\t\t\tconst failed = responses.find((response) => !response.success);\n\t\t\t\treturn failed ?? success(command.id, command.type, responses.find((response) => response.success)?.data);\n\t\t\t}\n\t\t\tcase \"cron_list\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst jobs = new Map<string, AgentCronJob>();\n\t\t\t\tconst responses = await Promise.all(\n\t\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(worker) => this.isLiveWorker(worker) && worker.client && worker.descriptor.lifecycle === \"ready\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map((worker) =>\n\t\t\t\t\t\t\tthis.forwardToWorker(worker, command, 5000).catch((error: unknown) =>\n\t\t\t\t\t\t\t\tfailure(command.id, command.type, error, serializeDaemonError(error)),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tfor (const response of responses) {\n\t\t\t\t\tif (!response.success) {\n\t\t\t\t\t\tthis.log(`Could not list scheduled jobs from a worker: ${response.error}`);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tfor (const job of cronJobsFromResponse(response)) {\n\t\t\t\t\t\tjobs.set(job.id, job);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (const { job } of await this.collectPassiveScheduledJobs(command.includeInactive === true)) {\n\t\t\t\t\tif (!jobs.has(job.id)) jobs.set(job.id, job);\n\t\t\t\t}\n\t\t\t\treturn success(command.id, \"cron_list\", { jobs: sortCronJobs([...jobs.values()]) });\n\t\t\t}\n\t\t\tcase \"heartbeats_list\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst workers = [...this.workers.values()].filter(\n\t\t\t\t\t(worker) => this.isLiveWorker(worker) && worker.descriptor.lifecycle !== \"failed\",\n\t\t\t\t);\n\t\t\t\tconst heartbeats = new Map<string, AgentConnectionHeartbeat>();\n\t\t\t\tconst snapshots: Array<{ heartbeats?: AgentConnectionHeartbeat[]; response?: DaemonResponse }> =\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tworkers.map(async (worker) => {\n\t\t\t\t\t\t\tif (worker.client && worker.descriptor.lifecycle === \"ready\") {\n\t\t\t\t\t\t\t\tconst response = await this.forwardToWorker(worker, command, 5000).catch((error: unknown) =>\n\t\t\t\t\t\t\t\t\tfailure(command.id, command.type, error, serializeDaemonError(error)),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (response.success) {\n\t\t\t\t\t\t\t\t\tconst snapshot = heartbeatsFromResponse(response);\n\t\t\t\t\t\t\t\t\tworker.heartbeatSnapshot = snapshot;\n\t\t\t\t\t\t\t\t\tworker.heartbeatSnapshotStale = false;\n\t\t\t\t\t\t\t\t\treturn { heartbeats: snapshot };\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis.log(`Could not list heartbeats from a worker: ${response.error}`);\n\t\t\t\t\t\t\t\tif (worker.heartbeatSnapshot === undefined || worker.heartbeatSnapshotStale === true) {\n\t\t\t\t\t\t\t\t\treturn { response };\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (worker.heartbeatSnapshot !== undefined && worker.heartbeatSnapshotStale !== true) {\n\t\t\t\t\t\t\t\treturn { heartbeats: worker.heartbeatSnapshot };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst state =\n\t\t\t\t\t\t\t\tworker.descriptor.lifecycle === \"ready\" ? \"disconnected\" : worker.descriptor.lifecycle;\n\t\t\t\t\t\t\tconst error = new Error(`Cannot list heartbeats while session worker is ${state}`);\n\t\t\t\t\t\t\treturn { response: failure(command.id, command.type, error, serializeDaemonError(error)) };\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\tconst failed = snapshots.find((snapshot) => snapshot.response)?.response;\n\t\t\t\tif (failed) {\n\t\t\t\t\treturn failed;\n\t\t\t\t}\n\t\t\t\tfor (const snapshot of snapshots) {\n\t\t\t\t\tfor (const heartbeat of snapshot.heartbeats ?? []) {\n\t\t\t\t\t\theartbeats.set(heartbeat.job.id, heartbeat);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Passivated sessions keep their armed heartbeats; no worker can list them.\n\t\t\t\tfor (const { job, info } of await this.collectPassiveScheduledJobs()) {\n\t\t\t\t\tif (!isHeartbeatCronJob(job) || heartbeats.has(job.id)) continue;\n\t\t\t\t\theartbeats.set(job.id, {\n\t\t\t\t\t\tjob,\n\t\t\t\t\t\t...(info.name !== undefined ? { sessionName: info.name } : {}),\n\t\t\t\t\t\t...(info.firstMessage !== undefined ? { firstMessage: info.firstMessage } : {}),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn success(command.id, \"heartbeats_list\", { heartbeats: [...heartbeats.values()] });\n\t\t\t}\n\t\t\tcase \"heartbeat_manage\": {\n\t\t\t\tconst cachedWorker = [...this.workers.values()].find((worker) =>\n\t\t\t\t\tworker.heartbeatSnapshot?.some(\n\t\t\t\t\t\t(heartbeat) =>\n\t\t\t\t\t\t\theartbeat.job.id === command.jobId && heartbeat.job.activeSessionId === command.activeSessionId,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tif (!cachedWorker) {\n\t\t\t\t\t// Passive jobs are managed against their durable store; no wake just to flip a status.\n\t\t\t\t\tconst passive = (await this.collectPassiveScheduledJobs()).find(\n\t\t\t\t\t\t({ job }) => job.id === command.jobId && job.activeSessionId === command.activeSessionId,\n\t\t\t\t\t);\n\t\t\t\t\tif (passive) {\n\t\t\t\t\t\tconst store = AgentCronJobStore.forSessionArtifacts();\n\t\t\t\t\t\tstore.registerSessionArtifact(\n\t\t\t\t\t\t\tpassive.info.id,\n\t\t\t\t\t\t\tgetSessionArtifactPathForFile(resolve(passive.info.path), passive.info.id),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst heartbeat = store.manageHeartbeat(command.activeSessionId, command.jobId, command.action);\n\t\t\t\t\t\tif (heartbeat) {\n\t\t\t\t\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\t\t\t\t\treturn success(command.id, \"heartbeat_manage\", { heartbeat });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst worker = cachedWorker ?? (await this.findWorkerForClient(client, command.activeSessionId)).worker;\n\t\t\t\tthis.assertWorkerAccessibleToClient(client, worker, command.activeSessionId);\n\t\t\t\tconst response = await this.forwardToWorker(worker, command);\n\t\t\t\tif (\n\t\t\t\t\tresponse.success &&\n\t\t\t\t\tresponse.data &&\n\t\t\t\t\ttypeof response.data === \"object\" &&\n\t\t\t\t\t\"heartbeat\" in response.data\n\t\t\t\t) {\n\t\t\t\t\tconst job = (response.data as { heartbeat?: AgentCronJob }).heartbeat;\n\t\t\t\t\tif (job && worker.heartbeatSnapshot) {\n\t\t\t\t\t\tconst existing = worker.heartbeatSnapshot.find((heartbeat) => heartbeat.job.id === job.id);\n\t\t\t\t\t\tconst remaining = worker.heartbeatSnapshot.filter((heartbeat) => heartbeat.job.id !== job.id);\n\t\t\t\t\t\tworker.heartbeatSnapshot =\n\t\t\t\t\t\t\tjob.status === \"active\" || job.status === \"paused\"\n\t\t\t\t\t\t\t\t? [...remaining, existing ? { ...existing, job } : { job }]\n\t\t\t\t\t\t\t\t: remaining;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\tcase \"cron_add\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tconst response = await this.forwardToWorker(match.worker, command);\n\t\t\t\tif (response.success && command.promoteOwnedSession) {\n\t\t\t\t\tawait this.promoteOwnedWorker(client, match.worker);\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\tcase \"cron_cancel\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst listed = await Promise.all(\n\t\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(worker) => this.isLiveWorker(worker) && worker.client && worker.descriptor.lifecycle === \"ready\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map(async (worker) => ({\n\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\tresponse: await this.forwardToWorker(\n\t\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\t\t{ type: \"cron_list\", includeInactive: true },\n\t\t\t\t\t\t\t\t5000,\n\t\t\t\t\t\t\t).catch(() => undefined),\n\t\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\tfor (const candidate of listed) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcandidate.response?.success &&\n\t\t\t\t\t\tcronJobsFromResponse(candidate.response).some((job) => job.id === command.jobId)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn this.forwardToWorker(candidate.worker, command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst passive = (await this.collectPassiveScheduledJobs()).find(({ job }) => job.id === command.jobId);\n\t\t\t\tif (passive) {\n\t\t\t\t\tconst store = AgentCronJobStore.forSessionArtifacts();\n\t\t\t\t\tstore.registerSessionArtifact(\n\t\t\t\t\t\tpassive.info.id,\n\t\t\t\t\t\tgetSessionArtifactPathForFile(resolve(passive.info.path), passive.info.id),\n\t\t\t\t\t);\n\t\t\t\t\tconst job = store.cancel(command.jobId);\n\t\t\t\t\tif (job) {\n\t\t\t\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\t\t\t\treturn success(command.id, \"cron_cancel\", { job });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new Error(`No cron job found: ${command.jobId}`);\n\t\t\t}\n\t\t\tcase \"cron_resume\": {\n\t\t\t\tif (command.activeSessionId !== undefined) {\n\t\t\t\t\tconst entry = this.roster().byActiveSessionId(command.activeSessionId);\n\t\t\t\t\tconst worker = entry?.workerId !== undefined ? this.workers.get(entry.workerId) : undefined;\n\t\t\t\t\tif (!worker || entry?.queuedChild) {\n\t\t\t\t\t\tthrow new Error(\"Cron resume requires an already bound destination runtime\");\n\t\t\t\t\t}\n\t\t\t\t\tthis.assertWorkerAccessibleToClient(client, worker, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(worker, command);\n\t\t\t\t}\n\t\t\t\tconst listed = await Promise.all(\n\t\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(worker) => this.isLiveWorker(worker) && worker.client && worker.descriptor.lifecycle === \"ready\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map(async (worker) => ({\n\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\tresponse: await this.forwardToWorker(\n\t\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\t\t{ type: \"cron_list\", includeInactive: true },\n\t\t\t\t\t\t\t\t5000,\n\t\t\t\t\t\t\t).catch(() => undefined),\n\t\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\tfor (const candidate of listed) {\n\t\t\t\t\tconst job = candidate.response?.success\n\t\t\t\t\t\t? cronJobsFromResponse(candidate.response).find((job) => job.id === command.jobId)\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (job) {\n\t\t\t\t\t\tthis.assertWorkerAccessibleToClient(client, candidate.worker, job.activeSessionId);\n\t\t\t\t\t\treturn this.forwardToWorker(candidate.worker, command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Cron resume requires an already bound destination runtime for job: ${command.jobId}`);\n\t\t\t}\n\t\t\tcase \"heartbeat_get\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t}\n\t\t\tcase \"heartbeat_set\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tconst response = await this.forwardToWorker(match.worker, command);\n\t\t\t\tif (response.success && command.promoteOwnedSession) {\n\t\t\t\t\tawait this.promoteOwnedWorker(client, match.worker);\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\tcase \"heartbeat_update\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t}\n\t\t\tcase \"rename_saved_session\": {\n\t\t\t\tconst target = await this.savedSessionNameReservationInput(command.sessionPath, command.name.trim());\n\t\t\t\treturn await this.withSessionNameReservation(target, async () => {\n\t\t\t\t\tawait this.assertSupervisorSavedSessionNameAvailable(command.sessionPath, target.name);\n\t\t\t\t\tif (!command.activeSessionId) {\n\t\t\t\t\t\tthis.assertRlmJournalAdmission();\n\t\t\t\t\t\tawait this.catalog.rename(command.sessionPath, command.name);\n\t\t\t\t\t\t// Third rename write point: an offline saved-session rename\n\t\t\t\t\t\t// changes the name the ledger carries for that child.\n\t\t\t\t\t\tawait this.rlmSpawnLedger().appendRenameByChildPath(command.sessionPath, target.name);\n\t\t\t\t\t\tconst entry = this.roster().bySessionFile(canonicalSessionPath(command.sessionPath));\n\t\t\t\t\t\tif (entry) {\n\t\t\t\t\t\t\tthis.writeRosterEntry({ ...entry, summary: { ...entry.summary, sessionName: target.name } });\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn success(command.id, command.type);\n\t\t\t\t\t}\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn await this.forwardToWorker(match.worker, {\n\t\t\t\t\t\t...command,\n\t\t\t\t\t\tactiveSessionId: match.summary.activeSessionId ?? match.summary.id,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t\tcase \"delete_saved_session\":\n\t\t\t\tif (!command.activeSessionId) {\n\t\t\t\t\tconst deletedPath = canonicalSessionPath(command.sessionPath);\n\t\t\t\t\tconst entry = this.roster().bySessionFile(deletedPath);\n\t\t\t\t\tif (entry?.summary.activeSessionId !== undefined) {\n\t\t\t\t\t\tthrow new Error(\"Cannot delete the currently active session\");\n\t\t\t\t\t}\n\t\t\t\t\tconst owner = this.findWorkerBySessionFile(command.sessionPath);\n\t\t\t\t\tif (owner) {\n\t\t\t\t\t\t// A client-owned worker's files are invisible to other clients: a foreign delete is an unknown target.\n\t\t\t\t\t\tthis.assertWorkerAccessibleToClient(client, owner, command.sessionPath);\n\t\t\t\t\t\tif (owner.client && !this.isWorkerStopping(owner)) {\n\t\t\t\t\t\t\treturn this.forwardToWorker(owner, command);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!(await this.reclaimStaleWorkerRegistration(owner))) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Session worker is ${this.effectiveWorkerState(owner)}; retry the delete once it is reachable`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.assertRlmJournalAdmission();\n\t\t\t\t\tawait tombstoneSavedSessionDelete(this.rlmSpawnLedger(), command.sessionPath, entry?.summary);\n\t\t\t\t\tconst result = await this.catalog.delete(command.sessionPath);\n\t\t\t\t\tif (result.ok && entry && this.roster().get(entry.agentId) === entry) {\n\t\t\t\t\t\tthis.roster().delete(entry.agentId);\n\t\t\t\t\t}\n\t\t\t\t\treturn success(command.id, command.type, result);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (command.type === \"send_message\" || command.type === \"send_result\") {\n\t\t\t// agentOrigin without fromActiveSessionId is trusted only at the direct socket-client boundary.\n\t\t\tconst source = command.fromActiveSessionId\n\t\t\t\t? await this.findWorkerForClient(client, command.fromActiveSessionId)\n\t\t\t\t: undefined;\n\t\t\tlet target: WorkerMatch;\n\t\t\ttry {\n\t\t\t\ttarget = await this.findWorkerForClient(client, command.targetActiveSessionId);\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof Error) || !error.message.startsWith(\"Unknown active session:\")) throw error;\n\t\t\t\tconst cwd = source?.summary.cwd ?? this.defaultSessionConfig.cwd ?? process.cwd();\n\t\t\t\tlet sessionPath: string;\n\t\t\t\ttry {\n\t\t\t\t\tsessionPath = await this.catalog.resolve(\n\t\t\t\t\t\tcommand.targetActiveSessionId,\n\t\t\t\t\t\tcwd,\n\t\t\t\t\t\tsource?.worker.descriptor.sessionDir ?? this.defaultSessionConfig.sessionDir,\n\t\t\t\t\t);\n\t\t\t\t} catch (catalogError) {\n\t\t\t\t\t// Preserve selector ambiguity so a2a senders can distinguish it from\n\t\t\t\t\t// the original unknown-active-session lookup failure.\n\t\t\t\t\tif (catalogError instanceof Error && catalogError.message.startsWith(\"Ambiguous session selector\")) {\n\t\t\t\t\t\tthrow catalogError;\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (source && command.agentOrigin === true) {\n\t\t\t\t\tconst targetInfo = await readSessionInfo(sessionPath);\n\t\t\t\t\tif (!targetInfo) throw new Error(`Unknown active session: ${command.targetActiveSessionId}`);\n\t\t\t\t\tassertAgentFamilyReach(\n\t\t\t\t\t\tthis.familyCatalogEntry(source.summary),\n\t\t\t\t\t\tthis.familyCatalogEntry(summaryForInactiveSession(targetInfo)),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst worker = await this.createOrReuseWorker(this.protocolClientId(client), {\n\t\t\t\t\ttype: \"create\",\n\t\t\t\t\tsessionPath,\n\t\t\t\t\tcontinueRecent: false,\n\t\t\t\t});\n\t\t\t\tconst root = this.roster().byActiveSessionId(worker.descriptor.rootActiveSessionId);\n\t\t\t\tconst summary =\n\t\t\t\t\tthis.findSummaryInWorker(worker, sessionPath) ??\n\t\t\t\t\t(root ? sessionSummaryFromRosterEntry(root) : undefined);\n\t\t\t\tif (!summary) throw new Error(\"Woken session worker has no target session\");\n\t\t\t\ttarget = { worker, summary };\n\t\t\t}\n\t\t\tconst targetActiveSessionId = target.summary.activeSessionId ?? target.summary.id;\n\t\t\tif (source && command.agentOrigin === true) {\n\t\t\t\tassertAgentFamilyReach(this.familyCatalogEntry(source.summary), this.familyCatalogEntry(target.summary));\n\t\t\t}\n\t\t\tif (source) {\n\t\t\t\tif ((source.summary.activeSessionId ?? source.summary.id) === targetActiveSessionId) {\n\t\t\t\t\tthrow new Error(\"Agent messaging cannot target the sending session\");\n\t\t\t\t}\n\t\t\t\tconst targetClient = this.requireAvailableWorkerClient(target.worker);\n\t\t\t\tconst response = await targetClient.requestWorker(\n\t\t\t\t\t{\n\t\t\t\t\t\t...(command.type === \"send_result\"\n\t\t\t\t\t\t\t? { type: \"worker_deliver_result\" as const, summary: command.summary, findings: command.findings }\n\t\t\t\t\t\t\t: { type: \"worker_deliver_message\" as const, message: command.message }),\n\t\t\t\t\t\ttargetActiveSessionId,\n\t\t\t\t\t\tsender: {\n\t\t\t\t\t\t\tactiveSessionId: source.summary.activeSessionId ?? source.summary.id,\n\t\t\t\t\t\t\tsessionId: source.summary.sessionId,\n\t\t\t\t\t\t\t...(source.summary.sessionName ? { sessionName: source.summary.sessionName } : {}),\n\t\t\t\t\t\t\truntimeKind: source.summary.runtimeKind ?? \"top-level\",\n\t\t\t\t\t\t\tclientId: client.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tWORKER_REQUEST_TIMEOUT_MS,\n\t\t\t\t);\n\t\t\t\treturn { ...response, id: command.id, command: command.type };\n\t\t\t}\n\t\t\treturn this.forwardToWorker(target.worker, { ...command, targetActiveSessionId });\n\t\t}\n\n\t\tif (!(\"activeSessionId\" in command) || typeof command.activeSessionId !== \"string\") {\n\t\t\tthrow new Error(`Supervisor cannot route daemon command: ${command.type}`);\n\t\t}\n\t\tconst admission =\n\t\t\t(command.type === \"prompt\" || command.type === \"prompt_and_wait\") && command.admissionId\n\t\t\t\t? this.getPromptAdmission(client, command.activeSessionId, command.admissionId)\n\t\t\t\t: undefined;\n\t\ttry {\n\t\t\tthrowIfAdmissionCancelled(admission);\n\t\t\tconst match = await waitForPromptAdmission(\n\t\t\t\tcommand.type === \"set_session_name\" && command.workerToken !== undefined\n\t\t\t\t\t? this.findWorker(\n\t\t\t\t\t\t\tcommand.activeSessionId,\n\t\t\t\t\t\t\t(worker) => worker.descriptor.authenticationToken === command.workerToken,\n\t\t\t\t\t\t)\n\t\t\t\t\t: this.findWorkerForClient(client, command.activeSessionId),\n\t\t\t\tadmission?.controller.signal,\n\t\t\t);\n\t\t\tthrowIfAdmissionCancelled(admission);\n\t\t\tconst resolvedCommand = {\n\t\t\t\t...command,\n\t\t\t\tactiveSessionId: match.summary.activeSessionId ?? match.summary.id,\n\t\t\t\t...(admission ? { admissionId: admission.workerAdmissionId } : {}),\n\t\t\t} as DaemonCommand;\n\t\t\tif (admission) {\n\t\t\t\tadmission.worker = match.worker;\n\t\t\t\tadmission.workerActiveSessionId = match.summary.activeSessionId ?? match.summary.id;\n\t\t\t}\n\t\t\tconst isRootKill =\n\t\t\t\tcommand.type === \"kill\" &&\n\t\t\t\t(match.summary.activeSessionId ?? match.summary.id) === match.worker.descriptor.rootActiveSessionId;\n\t\t\tif (!isRootKill) {\n\t\t\t\tconst forward = async () => {\n\t\t\t\t\tconst response = await this.forwardToWorker(match.worker, resolvedCommand);\n\t\t\t\t\tif (admission && response.success) admission.status = \"owned\";\n\t\t\t\t\treturn response;\n\t\t\t\t};\n\t\t\t\tif (command.type === \"rename\" || command.type === \"set_session_name\") {\n\t\t\t\t\tconst reservation = this.summaryNameReservationInput(match.summary, command.name.trim());\n\t\t\t\t\treturn await this.withSessionNameReservation(reservation, async () => {\n\t\t\t\t\t\tawait this.assertSupervisorSessionNameAvailable(match.summary, reservation.name);\n\t\t\t\t\t\treturn forward();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn await forward();\n\t\t\t}\n\t\t\tthis.persistWorkerStopTombstone(match.worker, true);\n\t\t\tconst releaseStopOwnership = this.acquireWorkerStopOwnership(match.worker);\n\t\t\tlet response: DaemonResponse;\n\t\t\ttry {\n\t\t\t\tresponse = await this.forwardToWorker(match.worker, resolvedCommand);\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.stopWorker(match.worker, true, false, true);\n\t\t\t\t} finally {\n\t\t\t\t\treleaseStopOwnership();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn response;\n\t\t} finally {\n\t\t\tif (admission) this.deletePromptAdmission(admission);\n\t\t}\n\t}\n\n\tprivate async handleList(\n\t\tclient: DaemonSocketClient,\n\t\tcommand: Extract<DaemonCommand, { type: \"list\" }>,\n\t): Promise<DaemonResponse> {\n\t\tconst active: SessionSummary[] = [];\n\t\tconst activeByFile = new Map<string, SessionSummary>();\n\t\tlet busyClientOwnedSessionCount = 0;\n\t\tfor (const entry of this.roster().values()) {\n\t\t\tif (entry.queuedChild) continue;\n\t\t\tconst worker = entry.workerId !== undefined ? this.workers.get(entry.workerId) : undefined;\n\t\t\tif (worker === undefined) continue;\n\t\t\tconst summary = this.publicSummary(worker, sessionSummaryFromRosterEntry(entry));\n\t\t\tif (this.isVisibleWorker(worker)) {\n\t\t\t\tactive.push(summary);\n\t\t\t\tif (summary.sessionFile) activeByFile.set(canonicalSessionPath(summary.sessionFile), summary);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (summary.sessionFile) activeByFile.set(canonicalSessionPath(summary.sessionFile), summary);\n\t\t\tif (isSessionSummaryBusy(summary)) busyClientOwnedSessionCount += 1;\n\t\t\tif (command.includeClientOwned === true && this.isWorkerAccessibleToClient(client, worker)) {\n\t\t\t\tactive.push(summary);\n\t\t\t}\n\t\t}\n\t\tconst data = {\n\t\t\tsessions: active,\n\t\t\t...(command.includeClientOwned ? { busyClientOwnedSessionCount } : {}),\n\t\t};\n\t\tif (!command.all) {\n\t\t\treturn success(command.id, \"list\", data);\n\t\t}\n\t\tconst sessionDir = command.sessionDir ?? this.defaultSessionConfig.sessionDir;\n\t\tconst scanned = await this.catalog.list(command.cwd ? resolve(command.cwd) : undefined, sessionDir);\n\t\tconst cwd = command.cwd ? resolve(command.cwd) : undefined;\n\t\tconst merged: SessionSummary[] = [];\n\t\tconst servedRows = new Set(active);\n\t\tconst mergedActiveFiles = new Set<string>();\n\t\tconst scannedFiles = new Set<string>();\n\t\tfor (const info of scanned) {\n\t\t\tconst file = canonicalSessionPath(info.path);\n\t\t\tscannedFiles.add(file);\n\t\t\tconst workerRow = activeByFile.get(file);\n\t\t\tif (workerRow && servedRows.has(workerRow)) {\n\t\t\t\tmerged.push(workerRow);\n\t\t\t\tmergedActiveFiles.add(file);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// The on-disk scan is public: an unserved (client-owned) worker row hides its live metadata only.\n\t\t\tmerged.push(summaryForInactiveSession(info));\n\t\t}\n\t\t// The boot seed covers registered workers' families only, so dead families (pure on-disk\n\t\t// history, no registered worker anywhere in the tree) are not roster-resident. Their\n\t\t// subagent rows are read from the spawn ledger on demand instead.\n\t\tlet spawnEdges: RlmLedgerEdge[] = [];\n\t\ttry {\n\t\t\tspawnEdges = await this.rlmSpawnLedger().liveEdges();\n\t\t} catch (error) {\n\t\t\tthis.log(`Could not list spawn-ledger sessions: ${String(error)}`);\n\t\t}\n\t\tconst spawnParents = new Map(spawnEdges.map((edge) => [canonicalSessionPath(edge.child), edge.parent]));\n\t\tconst offlineRows: AgentRosterEntry[] = [];\n\t\tfor (const entry of this.roster().values()) {\n\t\t\tif (entry.queuedChild || entry.summary.activeSessionId !== undefined) continue;\n\t\t\tif (entry.workerId !== undefined && this.workers.has(entry.workerId)) continue;\n\t\t\tconst file = entry.summary.sessionFile ? canonicalSessionPath(entry.summary.sessionFile) : undefined;\n\t\t\tif (file === undefined || scannedFiles.has(file) || activeByFile.has(file)) continue;\n\t\t\tofflineRows.push(entry);\n\t\t}\n\t\tfor (const hydrated of await Promise.all(offlineRows.map((entry) => this.hydrateSeededEntry(entry)))) {\n\t\t\tconst summary = sessionSummaryFromRosterEntry(hydrated);\n\t\t\tif (cwd !== undefined && resolve(summary.cwd) !== cwd) continue;\n\t\t\tif (!this.matchesListSessionDir(summary, sessionDir, spawnParents)) continue;\n\t\t\tmerged.push(summary);\n\t\t}\n\t\tconst unseededFiles = new Set<string>();\n\t\tfor (const edge of spawnEdges) {\n\t\t\tconst childPath = canonicalSessionPath(edge.child);\n\t\t\tif (scannedFiles.has(childPath) || activeByFile.has(childPath) || unseededFiles.has(childPath)) continue;\n\t\t\tif (this.roster().hasSessionFile(childPath)) continue;\n\t\t\tconst entry = this.rosterEntryForSpawnLedgerEdge(edge);\n\t\t\tif (this.roster().has(entry.agentId)) continue;\n\t\t\tunseededFiles.add(childPath);\n\t\t\t// Hydrated one at a time, like the boot seed: a large dead-family ledger must not fan\n\t\t\t// out into one concurrent transcript read per child.\n\t\t\tconst hydrated = await this.hydratedSeedEntry(entry);\n\t\t\t// The same classification a roster write would have applied: these rows read \"inactive\".\n\t\t\tconst summary = sessionSummaryFromRosterEntry({\n\t\t\t\t...hydrated,\n\t\t\t\tstatus: classifySessionRosterStatus(hydrated.summary),\n\t\t\t});\n\t\t\tif (cwd !== undefined && resolve(summary.cwd) !== cwd) continue;\n\t\t\tif (!this.matchesListSessionDir(summary, sessionDir, spawnParents)) continue;\n\t\t\tmerged.push(summary);\n\t\t}\n\t\tfor (const summary of active) {\n\t\t\tconst file = summary.sessionFile ? canonicalSessionPath(summary.sessionFile) : undefined;\n\t\t\tif (file !== undefined && mergedActiveFiles.has(file)) continue;\n\t\t\tmerged.push(summary);\n\t\t}\n\t\treturn success(command.id, \"list\", { ...data, sessions: merged });\n\t}\n\n\tprivate async hydratedSeedEntry<T extends WorkerRosterEntry>(entry: T): Promise<T> {\n\t\tconst info = entry.summary.sessionFile\n\t\t\t? await readSessionInfo(entry.summary.sessionFile).catch(() => undefined)\n\t\t\t: undefined;\n\t\tif (!info) return { ...entry, seededCwd: true as const };\n\t\tconst { seededCwd, ...rest } = entry;\n\t\treturn { ...rest, summary: { ...entry.summary, cwd: info.cwd } } as T;\n\t}\n\n\tprivate async hydrateSeededEntry(entry: AgentRosterEntry): Promise<AgentRosterEntry> {\n\t\tif (entry.seededCwd !== true || !entry.summary.sessionFile) return entry;\n\t\tconst hydrated = await this.hydratedSeedEntry(entry);\n\t\tif (hydrated.seededCwd === true) return entry;\n\t\tconst current = this.roster().get(entry.agentId);\n\t\tif (current !== entry) return current ?? entry;\n\t\treturn this.roster().write(hydrated, entry.workerId, entry.statusLabel);\n\t}\n\n\tprivate matchesListSessionDir(\n\t\tsummary: SessionSummary,\n\t\tsessionDir: string | undefined,\n\t\tspawnParents?: ReadonlyMap<string, string>,\n\t): boolean {\n\t\tif (sessionDir === undefined) return true;\n\t\tif (!summary.sessionFile) return false;\n\t\tlet file = resolve(summary.sessionFile);\n\t\tlet parentSessionPath = summary.parentSessionPath;\n\t\tconst visited = new Set<string>();\n\t\twhile (parentSessionPath !== undefined) {\n\t\t\tconst canonical = canonicalSessionPath(parentSessionPath);\n\t\t\tif (visited.has(canonical)) break;\n\t\t\tvisited.add(canonical);\n\t\t\tfile = resolve(parentSessionPath);\n\t\t\t// Dead-family ancestors are not roster-resident; the spawn ledger continues the walk.\n\t\t\tparentSessionPath =\n\t\t\t\tthis.roster().bySessionFile(canonical)?.summary.parentSessionPath ?? spawnParents?.get(canonical);\n\t\t}\n\t\treturn dirname(file) === resolve(sessionDir);\n\t}\n\n\tprivate async handleSavedSessionList(\n\t\tclient: DaemonSocketClient,\n\t\tcommand: Extract<DaemonCommand, { type: \"list_saved_sessions\" }>,\n\t): Promise<DaemonResponse> {\n\t\tconst pageQuery = captureSavedSessionPageQuery(command.page ?? {});\n\t\tconst scope = command.scope;\n\t\tlet cwd: string;\n\t\tlet sessionDir: string | undefined;\n\t\tif (\"activeSessionId\" in command) {\n\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\tcwd = match.summary.cwd;\n\t\t\tsessionDir = this.defaultSessionConfig.sessionDir;\n\t\t} else {\n\t\t\tcwd = resolve(command.cwd);\n\t\t\tsessionDir = command.sessionDir;\n\t\t}\n\t\tconst { agentDir, sessionsDir: ledgerSessionDir } = this.rlmJournalScope(sessionDir);\n\t\tconst page = await this.catalog.list(cwd, sessionDir, { page: pageQuery, scope, agentDir, ledgerSessionDir });\n\t\treturn success(command.id, \"list_saved_sessions\", page);\n\t}\n\n\tprivate async createOrReuseWorker(clientId: string, command: DaemonCreateCommand): Promise<ResidentWorker> {\n\t\tlet createCommand = command;\n\t\tif (command.name !== undefined) {\n\t\t\tconst normalizedName = command.name.trim();\n\t\t\tif (!normalizedName) {\n\t\t\t\tthrow new Error(\"Session name cannot be empty\");\n\t\t\t}\n\t\t\tcreateCommand = { ...command, name: normalizedName };\n\t\t}\n\t\tconst ownerClientId = command.lifecycle === \"client_owned\" ? clientId : undefined;\n\t\tif (command.sessionPath) {\n\t\t\tconst activeMatches = this.matchWorkers(command.sessionPath);\n\t\t\tif (\n\t\t\t\tactiveMatches.length === 1 &&\n\t\t\t\t!(await this.reclaimStaleWorkerRegistration(activeMatches[0]!.worker, command.launchEnv !== undefined))\n\t\t\t) {\n\t\t\t\treturn this.reuseWorkerForCreate(activeMatches[0]!.worker, ownerClientId, command.sessionPath);\n\t\t\t}\n\t\t\tif (activeMatches.length > 1) {\n\t\t\t\tthrow new Error(`Ambiguous active session \"${command.sessionPath}\"`);\n\t\t\t}\n\t\t\tconst config = mergeAgentSessionRuntimeConfig(this.defaultSessionConfig, command.config);\n\t\t\tconst sessionPath = looksLikeSessionPath(command.sessionPath)\n\t\t\t\t? resolve(command.sessionPath)\n\t\t\t\t: await this.catalog.resolve(command.sessionPath, config.cwd ?? process.cwd(), config.sessionDir);\n\t\t\tcreateCommand = { ...createCommand, sessionPath };\n\t\t}\n\t\tconst key = createCommand.sessionPath\n\t\t\t? canonicalSessionPath(createCommand.sessionPath)\n\t\t\t: `new:${command.id ? createCommandIdempotencyKey(clientId, command.id) : createActiveSessionId()}`;\n\t\tconst pending = this.openingWorkers.get(key);\n\t\tif (pending) {\n\t\t\treturn this.joinOpeningWorker(pending, ownerClientId, createCommand.sessionPath ?? key);\n\t\t}\n\t\tif (createCommand.sessionPath) {\n\t\t\tconst existing = this.findWorkerBySessionFile(createCommand.sessionPath);\n\t\t\tif (existing && !(await this.reclaimStaleWorkerRegistration(existing, command.launchEnv !== undefined))) {\n\t\t\t\treturn this.reuseWorkerForCreate(existing, ownerClientId, createCommand.sessionPath);\n\t\t\t}\n\t\t\t// The reclaim await may have let a concurrent opener register; join it instead of double-launching.\n\t\t\tconst opened = this.openingWorkers.get(key);\n\t\t\tif (opened) {\n\t\t\t\treturn this.joinOpeningWorker(opened, ownerClientId, createCommand.sessionPath);\n\t\t\t}\n\t\t}\n\t\tif (createCommand.sessionPath) {\n\t\t\tconst existing = this.findWorkerBySessionFile(createCommand.sessionPath);\n\t\t\tif (existing && !(await this.reclaimStaleWorkerRegistration(existing, command.launchEnv !== undefined))) {\n\t\t\t\treturn this.reuseWorkerForCreate(existing, ownerClientId, createCommand.sessionPath);\n\t\t\t}\n\t\t}\n\t\tconst opening = (async () => {\n\t\t\tif (!createCommand.name) return this.launchWorker(createCommand, undefined, ownerClientId);\n\t\t\tconst savedSiblings = createCommand.sessionPath ? await this.rlmLedgerSiblings(createCommand.sessionPath) : [];\n\t\t\tconst target = savedSiblings.find(\n\t\t\t\t(session) => canonicalSessionPath(session.path) === canonicalSessionPath(createCommand.sessionPath!),\n\t\t\t);\n\t\t\tconst targetSummary = target ? summaryForInactiveSession(target) : { sessionId: \"new-root\", rlmDepth: 0 };\n\t\t\tconst reservation = this.summaryNameReservationInput(targetSummary, createCommand.name);\n\t\t\treturn this.withSessionNameReservation(reservation, async () => {\n\t\t\t\tif (target?.parentSessionPath && (target.rlmDepth ?? 0) > 0) {\n\t\t\t\t\tthis.assertSavedSiblingNameAvailable(savedSiblings, target, createCommand.name!);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.assertSupervisorSessionNameAvailable(targetSummary, createCommand.name!);\n\t\t\t\t}\n\t\t\t\treturn this.launchWorker(createCommand, undefined, ownerClientId);\n\t\t\t});\n\t\t})();\n\t\tthis.openingWorkers.set(key, opening);\n\t\ttry {\n\t\t\treturn await opening;\n\t\t} finally {\n\t\t\tif (this.openingWorkers.get(key) === opening) {\n\t\t\t\tthis.openingWorkers.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async reuseWorkerForCreate(\n\t\tworker: ResidentWorker,\n\t\townerClientId: string | undefined,\n\t\tsessionPath: string,\n\t): Promise<ResidentWorker> {\n\t\tif (worker.descriptor.lifecycle === \"failed\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Session \"${sessionPath}\" is registered to a failed worker that could not be safely reclaimed`,\n\t\t\t);\n\t\t}\n\t\tthis.assertWorkerCreateOwner(worker, ownerClientId, sessionPath);\n\t\tif (!this.isWorkerReadyForCreate(worker)) {\n\t\t\tif (worker.recovery) {\n\t\t\t\tawait worker.recovery;\n\t\t\t} else if (this.isWorkerRecoveryEligible(worker)) {\n\t\t\t\tawait this.recoverWorker(worker);\n\t\t\t}\n\t\t}\n\t\tconst current = this.workers.get(worker.descriptor.workerId);\n\t\tif (!current) {\n\t\t\tthrow new Error(`Session \"${sessionPath}\" worker recovery was interrupted; retry opening the session`);\n\t\t}\n\t\tthis.assertWorkerCreateOwner(current, ownerClientId, sessionPath);\n\t\tif (!this.isWorkerReadyForCreate(current)) {\n\t\t\tif (!this.workerHasRosterRoot(current)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Session \"${sessionPath}\" worker is unavailable for reuse: assigned root session is missing`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst detail = current.descriptor.lastError ? `: ${current.descriptor.lastError}` : \"\";\n\t\t\tthrow new Error(`Session \"${sessionPath}\" worker is ${this.effectiveWorkerState(current)}${detail}`);\n\t\t}\n\t\treturn current;\n\t}\n\n\tprivate async joinOpeningWorker(\n\t\tpending: Promise<ResidentWorker>,\n\t\townerClientId: string | undefined,\n\t\tsessionPath: string,\n\t): Promise<ResidentWorker> {\n\t\tconst worker = await pending;\n\t\tthis.assertWorkerCreateOwner(worker, ownerClientId, sessionPath);\n\t\treturn worker;\n\t}\n\n\tprivate assertWorkerCreateOwner(\n\t\tworker: ResidentWorker,\n\t\townerClientId: string | undefined,\n\t\tsessionPath: string,\n\t): void {\n\t\tif (worker.descriptor.ownerClientId !== ownerClientId) {\n\t\t\tthrow new SessionAlreadyActiveError(sessionPath, worker.descriptor.rootActiveSessionId);\n\t\t}\n\t}\n\n\tprivate isWorkerReadyForCreate(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tworker.descriptor.lifecycle === \"ready\" &&\n\t\t\tworker.client !== undefined &&\n\t\t\tthis.workerHasRosterRoot(worker) &&\n\t\t\t!this.isWorkerStopping(worker)\n\t\t);\n\t}\n\n\tprivate workerHasRosterRoot(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tthis.roster().byActiveSessionId(worker.descriptor.rootActiveSessionId)?.workerId === worker.descriptor.workerId\n\t\t);\n\t}\n\n\t/**\n\t * A stopping worker whose process already died can strand its registration\n\t * (for example when the stop timed out and its finalization was interrupted\n\t * by a supervisor restart). Such a registration would block reopening the\n\t * saved transcript forever, so complete the interrupted stop and let the\n\t * caller launch a fresh worker for the saved session.\n\t */\n\tprivate async reclaimStaleWorkerRegistration(worker: ResidentWorker, freshCreate = false): Promise<boolean> {\n\t\tif (worker.client !== undefined || worker.recovery !== undefined) {\n\t\t\treturn false;\n\t\t}\n\t\tif (worker.descriptor.stopRequestedAt === undefined) {\n\t\t\tif (worker.descriptor.lifecycle !== \"failed\" || worker.descriptor.ownerClientId) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst identity = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t\tif (identity === \"current\") {\n\t\t\t\tif (worker.compatibilityError || !freshCreate || !worker.descriptor.processStartId) return false;\n\t\t\t\tawait this.stopWorker(worker, true, true);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (identity !== \"gone\" && identity !== \"replaced\") {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tworker.intentionalStop = true;\n\t\t\tawait this.recoverUncertainWorkerOperations(worker);\n\t\t\tthis.invalidateWorkerSessionInputPauses(worker, \"Session worker stopped while input was paused\");\n\t\t\tthis.workers.delete(worker.descriptor.workerId);\n\t\t\tthis.flipWorkerRosterEntriesInactive(worker);\n\t\t\tthis.deleteWorkerDescriptor(worker);\n\t\t\treturn true;\n\t\t}\n\t\t// Fail fast before waiting on anything: only a confirmed-dead process is\n\t\t// reclaimable. A live, unknown, or still-stopping worker is left alone\n\t\t// and the caller reports the session as already active.\n\t\tconst identity = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\tif (identity !== \"gone\" && identity !== \"replaced\") {\n\t\t\treturn false;\n\t\t}\n\t\t// Single cleanup path: the background stop finalizer is identity-aware,\n\t\t// retrying, and single-flighted, so concurrent resumes share one stop.\n\t\t// The wait is bounded so a resume request always returns promptly.\n\t\tthis.scheduleWorkerStopFinalization(worker);\n\t\tconst finalization = worker.stopFinalization;\n\t\tif (finalization) {\n\t\t\tawait Promise.race([finalization.catch(() => undefined), unrefDelay(STALE_RECLAIM_WAIT_MS)]);\n\t\t}\n\t\tif (this.workers.get(worker.descriptor.workerId) === worker) {\n\t\t\t// The process is confirmed dead, so the registration must never be\n\t\t\t// reused; slow cleanup fails the resume honestly instead.\n\t\t\tthrow new Error(\n\t\t\t\t`Stopped session worker ${worker.descriptor.workerId} is still being cleaned up; retry shortly`,\n\t\t\t);\n\t\t}\n\t\tthis.log(`Reclaimed stale registration for stopped worker ${worker.descriptor.workerId}`);\n\t\treturn true;\n\t}\n\n\tprivate async promoteOwnedWorker(client: DaemonSocketClient, worker: ResidentWorker): Promise<void> {\n\t\tconst clientId = this.protocolClientId(client);\n\t\tif (worker.descriptor.ownerClientId === undefined && worker.promotedOwnerClientId === clientId) {\n\t\t\treturn;\n\t\t}\n\t\tif (worker.descriptor.ownerClientId !== clientId) {\n\t\t\tthrow new Error(\"Session is not owned by this client\");\n\t\t}\n\t\tconst previousDescriptor = worker.descriptor;\n\t\tworker.descriptor = { ...previousDescriptor, ownerClientId: undefined };\n\t\ttry {\n\t\t\tthis.persistWorker(worker);\n\t\t} catch (error) {\n\t\t\tworker.descriptor = previousDescriptor;\n\t\t\tthrow error;\n\t\t}\n\t\tworker.promotedOwnerClientId = clientId;\n\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\tthis.roster().amend(entry.agentId, {});\n\t\t}\n\t\tif (worker.ownerCleanupTimer) {\n\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t}\n\t\tworker.launchEnv = undefined;\n\t\tworker.transientCreateCommand = undefined;\n\t}\n\n\tprivate describeWorkerSpawnFailure(error: Error): Error {\n\t\tconst errno = (error as NodeJS.ErrnoException).code;\n\t\tconst hint =\n\t\t\terrno === \"EMFILE\" || errno === \"ENFILE\"\n\t\t\t\t? ` (${this.workers.size} resident session workers are holding file descriptors; stop unused sessions or raise the open-file limit (ulimit -n))`\n\t\t\t\t: \"\";\n\t\treturn new Error(`Failed to spawn session worker: ${error.message}${hint}`);\n\t}\n\n\tprivate async launchWorker(\n\t\tcommand: DaemonCreateCommand,\n\t\texisting?: ResidentWorker,\n\t\townerClientId?: string,\n\t): Promise<ResidentWorker> {\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (existing && this.isWorkerRecoveryCancelled(existing)) {\n\t\t\tthrow new Error(`Session worker ${existing.descriptor.workerId} recovery was cancelled`);\n\t\t}\n\t\tconst recoveryStopRevision = existing?.stopRevision;\n\t\tconst launchEnv = command.launchEnv ?? existing?.launchEnv;\n\t\tconst createCommand: DaemonCreateCommand = {\n\t\t\t...withoutSupervisorCreateFields(command),\n\t\t\tconfig: mergeAgentSessionRuntimeConfig(this.defaultSessionConfig, command.config),\n\t\t};\n\t\tconst workerId = existing?.descriptor.workerId ?? createActiveSessionId();\n\t\tconst rootActiveSessionId = existing?.descriptor.rootActiveSessionId ?? createActiveSessionId();\n\t\tconst socketPath = existing?.descriptor.socketPath ?? workerSocketPath(this.socketPath, workerId);\n\t\tconst token = existing?.descriptor.authenticationToken ?? randomBytes(32).toString(\"base64url\");\n\t\t// Fresh per incarnation: peer transport grants must never survive a worker restart.\n\t\tconst workerInstanceId = randomUUID();\n\t\tconst now = new Date().toISOString();\n\t\tconst descriptorPath = existing?.descriptorPath ?? join(this.descriptorDir, `${workerId}.json`);\n\t\tconst recoveryJournalPath =\n\t\t\texisting?.descriptor.recoveryJournalPath ?? join(this.descriptorDir, `${workerId}.recovery.jsonl`);\n\t\tconst orphanProcessJournalPath =\n\t\t\texisting?.descriptor.orphanProcessJournalPath ?? join(this.descriptorDir, `${workerId}.orphans.jsonl`);\n\t\tconst launch = createCliSubprocessLaunchSpec([\"--mode\", \"daemon\", \"--daemon-socket\", socketPath]);\n\t\tconst workerEnvironment = createCliSubprocessEnv({\n\t\t\t...process.env,\n\t\t\t...launchEnv,\n\t\t\t[DAEMON_WORKER_ROLE_ENV]: \"1\",\n\t\t\t[DAEMON_WORKER_TOKEN_ENV]: token,\n\t\t\t[DAEMON_WORKER_INSTANCE_ID_ENV]: workerInstanceId,\n\t\t\t[DAEMON_WORKER_ACTIVE_SESSION_ID_ENV]: rootActiveSessionId,\n\t\t\t[DAEMON_WORKER_SUPERVISOR_SOCKET_ENV]: this.socketPath,\n\t\t\t[DAEMON_WORKER_RECOVERY_JOURNAL_ENV]: recoveryJournalPath,\n\t\t\t[DAEMON_WORKER_STARTUP_GATE_FD_ENV]: String(WORKER_STARTUP_GATE_FD),\n\t\t\t[ORPHAN_PROCESS_JOURNAL_ENV]: orphanProcessJournalPath,\n\t\t\t[SESSION_LEASES_ENABLED_ENV]: \"1\",\n\t\t\t[SESSION_LEASE_OWNER_ID_ENV]: rootActiveSessionId,\n\t\t});\n\t\tdelete workerEnvironment.BASE_CONTEXT_RLM_DEPTH;\n\t\tawait this.assertRecoveryAllowed();\n\t\tconst child: ChildProcess = spawn(launch.command, launch.args, {\n\t\t\tcwd: createCommand.config?.cwd ?? process.cwd(),\n\t\t\tdetached: true,\n\t\t\tenv: workerEnvironment,\n\t\t\tstdio: [\"ignore\", \"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tconst detachWorkerStderr = child.stderr\n\t\t\t? attachJsonlLineReader(child.stderr, (line) => this.log(`Session worker ${workerId} stderr: ${line}`), {\n\t\t\t\t\tmaxLineLength: 64 * 1024,\n\t\t\t\t\tonLineOverflow: (prefix) => this.log(`Session worker ${workerId} stderr: ${prefix} [truncated]`),\n\t\t\t\t})\n\t\t\t: () => {};\n\t\tchild.once(\"close\", detachWorkerStderr);\n\t\tconst childClosed = new Promise<void>((resolveClose) => child.once(\"close\", () => resolveClose()));\n\t\tlet spawnFailure: Error | undefined;\n\t\tconst spawnSettled = new Promise<void>((resolveSpawn) => {\n\t\t\tchild.once(\"spawn\", () => resolveSpawn());\n\t\t\tchild.once(\"error\", (error) => {\n\t\t\t\tspawnFailure = error instanceof Error ? error : new Error(String(error));\n\t\t\t\tresolveSpawn();\n\t\t\t});\n\t\t});\n\t\tchild.on(\"error\", (error) => {\n\t\t\tthis.log(\n\t\t\t\t`Session worker ${workerId} process error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t});\n\t\t// A failed spawn (e.g. EMFILE) leaves child.stdio undefined.\n\t\tconst startupGate = child.stdio?.[WORKER_STARTUP_GATE_FD];\n\t\tconst previousDescriptor = existing?.descriptor;\n\t\tconst previousIntentionalStop = existing?.intentionalStop;\n\t\tlet descriptorAssigned = false;\n\t\tlet childPid: number;\n\t\tlet childProcessStartId: string | undefined;\n\t\tlet worker: ResidentWorker;\n\t\ttry {\n\t\t\tawait spawnSettled;\n\t\t\tif (spawnFailure) {\n\t\t\t\tthrow this.describeWorkerSpawnFailure(spawnFailure);\n\t\t\t}\n\t\t\tif (!child.pid) {\n\t\t\t\tthrow new Error(\"Failed to obtain daemon session worker pid\");\n\t\t\t}\n\t\t\tif (!(startupGate instanceof Writable)) {\n\t\t\t\tthrow new Error(\"Failed to create daemon session worker startup gate\");\n\t\t\t}\n\t\t\tchildPid = child.pid;\n\t\t\tchildProcessStartId = getProcessStartId(childPid);\n\t\t\tawait this.assertRecoveryAllowed();\n\n\t\t\tconst descriptor: DaemonWorkerDescriptor = {\n\t\t\t\tversion: 2,\n\t\t\t\tworkerId,\n\t\t\t\tpid: childPid,\n\t\t\t\t...(childProcessStartId ? { processStartId: childProcessStartId } : {}),\n\t\t\t\tsocketPath,\n\t\t\t\trecoveryJournalPath,\n\t\t\t\torphanProcessJournalPath,\n\t\t\t\tsupervisorSocketPath: this.socketPath,\n\t\t\t\tauthenticationToken: token,\n\t\t\t\tworkerInstanceId,\n\t\t\t\trootActiveSessionId,\n\t\t\t\townerClientId: existing?.descriptor.ownerClientId ?? ownerClientId,\n\t\t\t\tsessionDir: createCommand.config?.sessionDir,\n\t\t\t\ttelemetryDisabled: createCommand.config?.telemetryDisabled,\n\t\t\t\tcreatedAt: existing?.descriptor.createdAt ?? now,\n\t\t\t\tupdatedAt: now,\n\t\t\t\tlifecycle: \"starting\",\n\t\t\t\tcreateCommand: durableDaemonCreateCommand(createCommand),\n\t\t\t\tconsecutiveFailures: existing?.descriptor.consecutiveFailures ?? 0,\n\t\t\t};\n\t\t\tworker = existing ?? {\n\t\t\t\tdescriptor,\n\t\t\t\tdescriptorPath,\n\t\t\t\tsummaries: new Map(),\n\t\t\t\tsnapshotCache: new Map(),\n\t\t\t\ttranscriptCaches: new Map(),\n\t\t\t\tsnapshotGenerations: new Map(),\n\t\t\t\tsnapshotLoads: new Map(),\n\t\t\t\tintentionalStop: false,\n\t\t\t\tstopRevision: 0,\n\t\t\t\tlaunchEnv,\n\t\t\t\ttransientCreateCommand: ownerClientId ? createCommand : undefined,\n\t\t\t};\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tworker.descriptor = descriptor;\n\t\t\tworker.launchEnv = launchEnv;\n\t\t\tworker.transientCreateCommand = descriptor.ownerClientId ? createCommand : undefined;\n\t\t\tdescriptorAssigned = true;\n\t\t\tthis.persistWorker(worker);\n\t\t\tworker.intentionalStop = false;\n\t\t\tthis.workers.set(workerId, worker);\n\t\t} catch (error) {\n\t\t\tif (startupGate instanceof Writable) {\n\t\t\t\tstartupGate.destroy();\n\t\t\t}\n\t\t\tawait childClosed;\n\t\t\tchild.unref();\n\t\t\ttry {\n\t\t\t\trmSync(`${descriptorPath}.${process.pid}.tmp`, { force: true });\n\t\t\t} catch (cleanupError) {\n\t\t\t\tthis.reportCleanupFailure(`worker launch temp ${workerId}`, cleanupError);\n\t\t\t}\n\t\t\tif (existing && descriptorAssigned && previousDescriptor) {\n\t\t\t\ttry {\n\t\t\t\t\texisting.descriptor = previousDescriptor;\n\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\tthis.reportCleanupFailure(`worker launch descriptor ${workerId}`, cleanupError);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\ttry {\n\t\t\ttry {\n\t\t\t\tawait commitWorkerStartupGate(startupGate);\n\t\t\t} catch (error) {\n\t\t\t\tstartupGate.destroy();\n\t\t\t\tawait childClosed;\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tchild.unref();\n\t\t\t}\n\t\t\tconst client = await this.connectWorker(worker, WORKER_CONNECT_TIMEOUT_MS);\n\t\t\tconst response = await client.request(withoutCommandId(createCommand), WORKER_REQUEST_TIMEOUT_MS);\n\t\t\tif (!response.success) {\n\t\t\t\tthrow deserializeDaemonError(response);\n\t\t\t}\n\t\t\tif (!isSessionSummary(response.data)) {\n\t\t\t\tthrow new Error(\"Session worker returned an invalid create response\");\n\t\t\t}\n\t\t\tconst summary = response.data;\n\t\t\tif ((summary.activeSessionId ?? summary.id) !== rootActiveSessionId) {\n\t\t\t\tthrow new Error(\"Session worker did not preserve its assigned active session id\");\n\t\t\t}\n\t\t\tthis.writeRosterEntry(workerRosterEntryFromSummary(summary), worker);\n\t\t\tworker.descriptor.rootSessionId = summary.sessionId;\n\t\t\tworker.descriptor.sessionFile = summary.sessionFile;\n\t\t\tawait this.subscribeWorker(worker, rootActiveSessionId);\n\t\t\tawait this.refreshWorkerSummaries(worker, true);\n\t\t\tif (existing && (this.isWorkerRecoveryCancelled(worker) || worker.stopRevision !== recoveryStopRevision)) {\n\t\t\t\tthrow new Error(`Session worker ${workerId} recovery was cancelled`);\n\t\t\t}\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tworker.descriptor.lifecycle = \"ready\";\n\t\t\tworker.descriptor.consecutiveFailures = 0;\n\t\t\tworker.deferredRecoveryRounds = 0;\n\t\t\tworker.descriptor.lastError = undefined;\n\t\t\tthis.persistWorker(worker);\n\t\t\tif (!worker.descriptor.ownerClientId) {\n\t\t\t\tworker.launchEnv = undefined;\n\t\t\t\tworker.transientCreateCommand = undefined;\n\t\t\t}\n\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\treturn worker;\n\t\t} catch (error) {\n\t\t\tif (isSupervisorGenerationStale(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\tthis.parkIncompatibleWorker(worker, error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (isSupervisorShutdownAdmissionCancelled(error)) {\n\t\t\t\tlet rolledBack = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.stopWorker(worker, existing === undefined, true, false, existing !== undefined, {\n\t\t\t\t\t\tchild,\n\t\t\t\t\t\tclosed: childClosed,\n\t\t\t\t\t});\n\t\t\t\t\trolledBack = true;\n\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\tthis.reportCleanupFailure(`cancelled worker launch ${workerId}`, cleanupError);\n\t\t\t\t}\n\t\t\t\tconst mappedWorker = this.workers.get(workerId);\n\t\t\t\tif (\n\t\t\t\t\trolledBack &&\n\t\t\t\t\texisting &&\n\t\t\t\t\tpreviousDescriptor &&\n\t\t\t\t\t!this.shuttingDown &&\n\t\t\t\t\texisting.stopRevision === recoveryStopRevision &&\n\t\t\t\t\texisting.descriptor.stopRequestedAt === undefined &&\n\t\t\t\t\t(mappedWorker === undefined || mappedWorker === existing)\n\t\t\t\t) {\n\t\t\t\t\texisting.descriptor = previousDescriptor;\n\t\t\t\t\texisting.intentionalStop = previousIntentionalStop ?? false;\n\t\t\t\t\tthis.workers.set(workerId, existing);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.persistWorker(existing);\n\t\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\t\tthis.reportCleanupFailure(`cancelled worker recovery ${workerId}`, cleanupError);\n\t\t\t\t\t}\n\t\t\t\t\tthis.deferWorkerRecovery(existing, error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tconst shouldResumeRecovery =\n\t\t\t\texisting !== undefined &&\n\t\t\t\t!this.shuttingDown &&\n\t\t\t\tworker.descriptor.stopRequestedAt === undefined &&\n\t\t\t\tworker.stopRevision === recoveryStopRevision;\n\t\t\tawait this.stopWorker(worker, existing === undefined, true, false, existing !== undefined).catch((stopError) =>\n\t\t\t\tthis.log(`Could not stop failed worker ${workerId}: ${String(stopError)}`),\n\t\t\t);\n\t\t\tif (\n\t\t\t\tshouldResumeRecovery &&\n\t\t\t\t!this.shuttingDown &&\n\t\t\t\tworker.descriptor.stopRequestedAt === undefined &&\n\t\t\t\tworker.stopRevision === recoveryStopRevision\n\t\t\t) {\n\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\tworker.intentionalStop = false;\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tthis.workers.set(workerId, worker);\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async connectWorker(worker: ResidentWorker, timeoutMs: number): Promise<DaemonWorkerClient> {\n\t\tconst deadline = Date.now() + timeoutMs;\n\t\tlet lastError: unknown;\n\t\twhile (Date.now() < deadline) {\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tconst client = new DaemonWorkerClient(worker.descriptor.socketPath);\n\t\t\ttry {\n\t\t\t\tawait client.connect(Math.min(500, Math.max(50, deadline - Date.now())));\n\t\t\t\tawait client.waitForHello(1000);\n\t\t\t\t// Listen before authenticating: the worker flushes its roster snapshot right after auth succeeds.\n\t\t\t\tclient.onFrame((frame) => this.handleWorkerFrame(worker, frame, client));\n\t\t\t\tclient.onClose((error) => void this.handleWorkerClose(worker, client, error));\n\t\t\t\tworker.pendingClient = client;\n\t\t\t\ttry {\n\t\t\t\t\tconst authResponse = await client.authenticateWorker(\n\t\t\t\t\t\tworker.descriptor.authenticationToken,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...this.supervisorAuthenticationClaim(),\n\t\t\t\t\t\t\t...(worker.descriptor.workerInstanceId !== undefined\n\t\t\t\t\t\t\t\t? { workerInstanceId: worker.descriptor.workerInstanceId }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t1000,\n\t\t\t\t\t);\n\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\tif (!workerAuthAdvertisesRoster(authResponse.data)) {\n\t\t\t\t\t\tthrow new PreRosterWorkerError(\"Session worker predates the roster protocol and must be restarted\");\n\t\t\t\t\t}\n\t\t\t\t\tworker.peerTransportCapable = workerAuthAdvertisesPeerTransport(authResponse.data);\n\t\t\t\t\tworker.lastFrameAt = Date.now();\n\t\t\t\t\tworker.client?.close();\n\t\t\t\t\tworker.client = client;\n\t\t\t\t\tworker.compatibilityError = undefined;\n\t\t\t\t\tworker.descriptor.lastError = undefined;\n\t\t\t\t\treturn client;\n\t\t\t\t} finally {\n\t\t\t\t\tif (worker.pendingClient === client) worker.pendingClient = undefined;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error;\n\t\t\t\tclient.close();\n\t\t\t\tif (\n\t\t\t\t\tisSupervisorRecoveryCancelled(error) ||\n\t\t\t\t\terror instanceof PreRosterWorkerError ||\n\t\t\t\t\terror instanceof DaemonWorkerAuthenticationError ||\n\t\t\t\t\terror instanceof DaemonWorkerCompatibilityError\n\t\t\t\t) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tawait delay(25);\n\t\t\t}\n\t\t}\n\t\tthrow new DaemonWorkerProbeTimeoutError(`Timed out connecting to daemon session worker: ${String(lastError)}`);\n\t}\n\n\tprivate parkIncompatibleWorker(worker: ResidentWorker, error: DaemonWorkerCompatibilityError): void {\n\t\t// Compatibility refusal is not evidence that this process or its ownership is dead.\n\t\tworker.compatibilityError = error;\n\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\tworker.descriptor.lastError = error.message;\n\t\tconst client = worker.client;\n\t\tworker.client = undefined;\n\t\tclient?.close();\n\t\tif (worker.ownerCleanupTimer) {\n\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t}\n\t\tthis.persistWorker(worker);\n\t\tthis.markWorkerRosterEntries(worker, \"recovering\");\n\t\tthis.log(`Kept incompatible worker ${worker.descriptor.workerId}: ${error.message}`);\n\t}\n\n\tprivate async subscribeWorker(worker: ResidentWorker, activeSessionId: string): Promise<void> {\n\t\tif (!worker.client) {\n\t\t\tthrow new Error(\"Session worker is not connected\");\n\t\t}\n\t\tconst supportsExtensionUi = [...this.clients].some(\n\t\t\t(client) => client.attachedActiveSessionIds.has(activeSessionId) && client.supportsExtensionUi,\n\t\t);\n\t\tconst response = await worker.client.requestWorker({\n\t\t\ttype: \"worker_subscribe\",\n\t\t\tactiveSessionId,\n\t\t\tcapabilities: supportsExtensionUi\n\t\t\t\t? [\"attach_snapshot\", \"event_sequence\", \"extension_ui\", \"slim_attach\", \"chunked_snapshot\"]\n\t\t\t\t: [\"attach_snapshot\", \"event_sequence\", \"slim_attach\", \"chunked_snapshot\"],\n\t\t\tsupportsExtensionUi,\n\t\t});\n\t\tif (!response.success) {\n\t\t\tthrow new Error(response.error);\n\t\t}\n\t}\n\n\tprivate async adoptOrRecoverWorker(worker: ResidentWorker): Promise<void> {\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (worker.descriptor.stopRequestedAt) {\n\t\t\ttry {\n\t\t\t\t// A descriptor persisted before identity tracking has no\n\t\t\t\t// processStartId, so stopWorker could neither signal the live\n\t\t\t\t// process nor let the finalizer escalate. Authenticating on the\n\t\t\t\t// worker's socket proves the pid still belongs to our worker, so\n\t\t\t\t// the start id observed while it was alive can be persisted (and\n\t\t\t\t// the connected client gives stopWorker its graceful IPC path).\n\t\t\t\tif (worker.descriptor.processStartId === undefined && isProcessAlive(worker.descriptor.pid)) {\n\t\t\t\t\tconst observedProcessStartId = getProcessStartId(worker.descriptor.pid);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.connectWorker(worker, 2000);\n\t\t\t\t\t\tif (observedProcessStartId) {\n\t\t\t\t\t\t\tworker.descriptor.processStartId = observedProcessStartId;\n\t\t\t\t\t\t\tthis.persistWorker(worker);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Unverifiable identity stays untrusted; the stop below\n\t\t\t\t\t\t// still runs its graceful path and the finalizer keeps\n\t\t\t\t\t\t// waiting rather than signalling a possibly-recycled pid.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tawait this.stopWorker(worker, true, true, worker.descriptor.archiveOnStop === true);\n\t\t\t\tthis.log(`Completed intentional stop for worker ${worker.descriptor.workerId} during supervisor adoption`);\n\t\t\t} catch (error) {\n\t\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\t\tworker.descriptor.lastError = error instanceof Error ? error.message : String(error);\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tthis.log(`Could not complete intentional stop for worker ${worker.descriptor.workerId}: ${String(error)}`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet observedProcessStartId: string | undefined;\n\t\ttry {\n\t\t\tif (!isProcessAlive(worker.descriptor.pid)) {\n\t\t\t\tthrow new Error(\"Session worker process is no longer running\");\n\t\t\t}\n\t\t\tobservedProcessStartId = getProcessStartId(worker.descriptor.pid);\n\t\t\tawait this.connectWorker(worker, 2000);\n\t\t\tawait this.subscribeWorker(worker, worker.descriptor.rootActiveSessionId);\n\t\t\tawait this.refreshWorkerSummaries(worker, true);\n\t\t\tif (worker.descriptor.processStartId === undefined && observedProcessStartId) {\n\t\t\t\tworker.descriptor.processStartId = observedProcessStartId;\n\t\t\t}\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tworker.descriptor.lifecycle = \"ready\";\n\t\t\tworker.descriptor.consecutiveFailures = 0;\n\t\t\tworker.deferredRecoveryRounds = 0;\n\t\t\tthis.persistWorker(worker);\n\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t} catch (error) {\n\t\t\tif (isSupervisorRecoveryCancelled(error)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\tthis.parkIncompatibleWorker(worker, error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.log(`Could not adopt worker ${worker.descriptor.workerId}: ${String(error)}`);\n\t\t\t// A client-owned worker's launch env lives only with its owner; recoverWorker parks it instead.\n\t\t\tif (error instanceof PreRosterWorkerError && worker.descriptor.ownerClientId === undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.restartPreRosterWorker(worker, observedProcessStartId);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (restartError) {\n\t\t\t\t\tif (isSupervisorRecoveryCancelled(restartError)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.log(`Could not restart pre-roster worker ${worker.descriptor.workerId}: ${String(restartError)}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst identityNow = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t\tif (isDaemonWorkerProbeTimeout(error) && (identityNow === \"current\" || identityNow === \"unknown\")) {\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tworker.descriptor.lastError = error instanceof Error ? error.message : String(error);\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tvoid this.recoverWorker(worker).catch((recoveryError) =>\n\t\t\t\t\tthis.log(`Could not recover worker ${worker.descriptor.workerId}: ${String(recoveryError)}`),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait this.recoverWorker(worker);\n\t\t}\n\t}\n\n\tprivate async restartPreRosterWorker(\n\t\tworker: ResidentWorker,\n\t\tobservedProcessStartId: string | undefined,\n\t): Promise<void> {\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (worker.descriptor.processStartId === undefined && observedProcessStartId !== undefined) {\n\t\t\tworker.descriptor.processStartId = observedProcessStartId;\n\t\t}\n\t\tconst identity = () => this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t// The one deliberate kill of a live worker: it authenticated as ours and predates the roster\n\t\t// protocol, so this identity-verified upgrade replaces it. No await between recheck and signal.\n\t\tif (identity() === \"current\") {\n\t\t\tsignalProcessGroupOrProcess(worker.descriptor.pid, \"SIGKILL\");\n\t\t\t// SIGKILL is uninterceptable; this wait only covers kernel teardown of the old process and socket.\n\t\t\tconst killDeadline = Date.now() + 1000;\n\t\t\twhile (identity() === \"current\" && Date.now() < killDeadline) {\n\t\t\t\tawait delay(25);\n\t\t\t}\n\t\t}\n\t\tconst finalIdentity = identity();\n\t\tif (finalIdentity !== \"gone\" && finalIdentity !== \"replaced\") {\n\t\t\t// A live or unverifiable survivor parks failed with no destructive cleanup: interruption\n\t\t\t// marking and orphan reaping must never run against a possibly-active worker.\n\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\tworker.descriptor.lastError = `Pre-roster worker process ${worker.descriptor.pid} is still running and cannot be replaced safely`;\n\t\t\tthis.persistWorker(worker);\n\t\t\tthis.markWorkerRosterEntries(worker, \"failed\");\n\t\t\tthis.log(`Kept pre-roster worker ${worker.descriptor.workerId} failed: ${worker.descriptor.lastError}`);\n\t\t\treturn;\n\t\t}\n\t\tawait this.recoverUncertainWorkerOperations(worker);\n\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.launchWorker(worker.descriptor.createCommand, worker, worker.descriptor.ownerClientId);\n\t}\n\n\tprivate async handleWorkerClose(worker: ResidentWorker, client: DaemonWorkerClient, error: Error): Promise<void> {\n\t\tif (worker.client !== client) {\n\t\t\treturn;\n\t\t}\n\t\tworker.client = undefined;\n\t\tthis.invalidateWorkerSessionInputPauses(worker, \"Session worker disconnected while input was paused\");\n\t\tconst interrupted = new Map<string, Set<string>>();\n\t\tfor (const [activeSessionId, generations] of worker.snapshotGenerations ?? []) {\n\t\t\tfor (const generation of generations.values()) {\n\t\t\t\tif (generation.incoming || !generation.transcript.complete) {\n\t\t\t\t\tconst snapshotIds = interrupted.get(activeSessionId) ?? new Set<string>();\n\t\t\t\t\tsnapshotIds.add(generation.transcript.snapshotId);\n\t\t\t\t\tinterrupted.set(activeSessionId, snapshotIds);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const [activeSessionId, transcript] of worker.transcriptCaches) {\n\t\t\tif (!transcript.complete) {\n\t\t\t\tconst snapshotIds = interrupted.get(activeSessionId) ?? new Set<string>();\n\t\t\t\tsnapshotIds.add(transcript.snapshotId);\n\t\t\t\tinterrupted.set(activeSessionId, snapshotIds);\n\t\t\t}\n\t\t}\n\t\tfor (const [activeSessionId, snapshotIds] of interrupted) {\n\t\t\tfor (const snapshotId of snapshotIds) {\n\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\tworker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tnew Error(\"Session worker disconnected during snapshot transfer\"),\n\t\t\t\t\tfalse,\n\t\t\t\t\tsnapshotId,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (this.shuttingDown || worker.intentionalStop) {\n\t\t\treturn;\n\t\t}\n\t\tthis.markWorkerRosterEntries(worker, \"recovering\");\n\t\ttry {\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t} catch (recoveryError) {\n\t\t\tif (!isSupervisorGenerationStale(recoveryError)) {\n\t\t\t\tthis.deferWorkerRecovery(worker, error);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!this.isWorkerRecoveryEligible(worker)) {\n\t\t\treturn;\n\t\t}\n\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\tworker.descriptor.lastError = error.message;\n\t\tthis.persistWorker(worker);\n\t\tvoid this.recoverWorker(worker);\n\t}\n\n\tprivate isWorkerRecoveryEligible(worker: ResidentWorker): boolean {\n\t\treturn this.isWorkerRecoveryCandidate(worker) && worker.recovery === undefined;\n\t}\n\n\tprivate isWorkerRecoveryCandidate(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\t!this.shuttingDown &&\n\t\t\t!worker.intentionalStop &&\n\t\t\tworker.descriptor.stopRequestedAt === undefined &&\n\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\tworker.client === undefined\n\t\t);\n\t}\n\n\tprivate deferWorkerRecovery(worker: ResidentWorker, disconnectError: Error): void {\n\t\tif (worker.compatibilityError || worker.deferredRecovery) {\n\t\t\treturn;\n\t\t}\n\t\t// A live-but-silent worker must not probe forever: park it failed (user-visible through the\n\t\t// roster's failed status) and keep its process alive for a manual retry_worker.\n\t\tworker.deferredRecoveryRounds = (worker.deferredRecoveryRounds ?? 0) + 1;\n\t\tif (worker.deferredRecoveryRounds > MAX_DEFERRED_RECOVERY_ROUNDS) {\n\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\tworker.descriptor.lastError = `Live session worker did not answer recovery probes for ${MAX_DEFERRED_RECOVERY_ROUNDS} rounds: ${disconnectError.message}`;\n\t\t\tthis.persistWorker(worker);\n\t\t\tthis.markWorkerRosterEntries(worker, \"failed\");\n\t\t\tthis.log(\n\t\t\t\t`Worker ${worker.descriptor.workerId} is unresponsive; parked failed after ${MAX_DEFERRED_RECOVERY_ROUNDS} probe rounds`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tworker.deferredRecovery = this.resumeDeferredWorkerRecovery(worker, disconnectError).finally(() => {\n\t\t\tworker.deferredRecovery = undefined;\n\t\t});\n\t}\n\n\tprivate async resumeDeferredWorkerRecovery(worker: ResidentWorker, disconnectError: Error): Promise<void> {\n\t\twhile (true) {\n\t\t\tawait unrefDelay(DEFERRED_RECOVERY_RECHECK_MS);\n\t\t\tif (worker.compatibilityError || !this.isWorkerRecoveryCandidate(worker)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this.isWorkerRecoveryEligible(worker)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t} catch (error) {\n\t\t\t\tif (isSupervisorGenerationStale(error)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (worker.compatibilityError || !this.isWorkerRecoveryCandidate(worker)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this.isWorkerRecoveryEligible(worker)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\tworker.descriptor.lastError = disconnectError.message;\n\t\t\tthis.persistWorker(worker);\n\t\t\tvoid this.recoverWorker(worker);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate failWorkerSnapshotCache(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\terror: Error,\n\t\tcloseWorkerChannel = false,\n\t\texpectedSnapshotId?: string,\n\t): void {\n\t\tconst generations = worker.snapshotGenerations?.get(activeSessionId);\n\t\tif (expectedSnapshotId) {\n\t\t\tconst generation = generations?.get(expectedSnapshotId);\n\t\t\tif (generation) {\n\t\t\t\tthis.failSnapshotGeneration(worker, activeSessionId, generation, error);\n\t\t\t} else {\n\t\t\t\tconst transcript = worker.transcriptCaches.get(activeSessionId);\n\t\t\t\tif (transcript?.snapshotId !== expectedSnapshotId) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttranscript.markFailed(error);\n\t\t\t\ttranscript.dispose();\n\t\t\t\tworker.transcriptCaches.delete(activeSessionId);\n\t\t\t\tif (worker.snapshotCache.get(activeSessionId)?.snapshotStream?.id === expectedSnapshotId) {\n\t\t\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst failedTranscripts = new Set<SnapshotTranscriptCache>();\n\t\t\tfor (const generation of [...(generations?.values() ?? [])]) {\n\t\t\t\tfailedTranscripts.add(generation.transcript);\n\t\t\t\tthis.failSnapshotGeneration(worker, activeSessionId, generation, error);\n\t\t\t}\n\t\t\tconst transcript = worker.transcriptCaches.get(activeSessionId);\n\t\t\tif (transcript && !failedTranscripts.has(transcript)) {\n\t\t\t\ttranscript.markFailed(error);\n\t\t\t\ttranscript.dispose();\n\t\t\t}\n\t\t\tworker.transcriptCaches.delete(activeSessionId);\n\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t}\n\t\tif (closeWorkerChannel) {\n\t\t\tconst client = worker.client;\n\t\t\tif (client) {\n\t\t\t\tthis.handleWorkerClose(worker, client, error);\n\t\t\t\tclient.close();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate retireWorkerSnapshotCache(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\texpectedTranscript: SnapshotTranscriptCache,\n\t): void {\n\t\tif (worker.transcriptCaches.get(activeSessionId) === expectedTranscript) {\n\t\t\tworker.transcriptCaches.delete(activeSessionId);\n\t\t}\n\t\tif (worker.snapshotCache.get(activeSessionId)?.snapshotStream?.id === expectedTranscript.snapshotId) {\n\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t}\n\t\tconst generation = this.snapshotGeneration(worker, activeSessionId, expectedTranscript.snapshotId);\n\t\tif (!generation) {\n\t\t\texpectedTranscript.dispose();\n\t\t\treturn;\n\t\t}\n\t\tgeneration.retired = true;\n\t\tthis.settleSnapshotDuplicateValidation(generation);\n\t\tif (generation.incoming) {\n\t\t\treturn;\n\t\t}\n\t\tthis.deleteSnapshotGeneration(worker, activeSessionId, generation);\n\t\texpectedTranscript.dispose();\n\t}\n\n\tprivate snapshotGenerationsFor(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t): Map<string, SnapshotTranscriptGeneration> {\n\t\tworker.snapshotGenerations ??= new Map();\n\t\tlet generations = worker.snapshotGenerations.get(activeSessionId);\n\t\tif (!generations) {\n\t\t\tgenerations = new Map();\n\t\t\tworker.snapshotGenerations.set(activeSessionId, generations);\n\t\t}\n\t\treturn generations;\n\t}\n\n\tprivate snapshotGeneration(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\tsnapshotId: string,\n\t): SnapshotTranscriptGeneration | undefined {\n\t\treturn worker.snapshotGenerations?.get(activeSessionId)?.get(snapshotId);\n\t}\n\n\tprivate currentSnapshotGeneration(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t): SnapshotTranscriptGeneration | undefined {\n\t\tworker.transcriptCaches ??= new Map();\n\t\tworker.snapshotCache ??= new Map();\n\t\tconst transcript = worker.transcriptCaches.get(activeSessionId);\n\t\tif (!transcript) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst generations = this.snapshotGenerationsFor(worker, activeSessionId);\n\t\tlet generation = generations.get(transcript.snapshotId);\n\t\tif (generation) {\n\t\t\treturn generation;\n\t\t}\n\t\tconst result = worker.snapshotCache.get(activeSessionId);\n\t\tif (!result) {\n\t\t\treturn undefined;\n\t\t}\n\t\tgeneration = {\n\t\t\ttranscript,\n\t\t\tresult,\n\t\t\tincoming: false,\n\t\t\tretired: false,\n\t\t};\n\t\tgenerations.set(transcript.snapshotId, generation);\n\t\treturn generation;\n\t}\n\n\tprivate deleteSnapshotGeneration(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\tgeneration: SnapshotTranscriptGeneration,\n\t): void {\n\t\tconst generations = worker.snapshotGenerations?.get(activeSessionId);\n\t\tif (!generations) {\n\t\t\treturn;\n\t\t}\n\t\tif (generations.get(generation.transcript.snapshotId) === generation) {\n\t\t\tgenerations.delete(generation.transcript.snapshotId);\n\t\t}\n\t\tif (generations.size === 0) {\n\t\t\tworker.snapshotGenerations.delete(activeSessionId);\n\t\t}\n\t}\n\n\tprivate failSnapshotGeneration(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\tgeneration: SnapshotTranscriptGeneration,\n\t\terror: Error,\n\t): void {\n\t\tthis.settleSnapshotDuplicateValidation(generation, error);\n\t\tgeneration.transcript.markFailed(error);\n\t\tgeneration.transcript.dispose();\n\t\tthis.deleteSnapshotGeneration(worker, activeSessionId, generation);\n\t\tif (worker.transcriptCaches.get(activeSessionId) === generation.transcript) {\n\t\t\tworker.transcriptCaches.delete(activeSessionId);\n\t\t}\n\t\tif (worker.snapshotCache.get(activeSessionId)?.snapshotStream?.id === generation.transcript.snapshotId) {\n\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t}\n\t}\n\n\tprivate createSnapshotDuplicateValidation(): SnapshotDuplicateValidation {\n\t\tlet resolve!: () => void;\n\t\tlet reject!: (error: Error) => void;\n\t\tconst promise = new Promise<void>((resolvePromise, rejectPromise) => {\n\t\t\tresolve = resolvePromise;\n\t\t\treject = rejectPromise;\n\t\t});\n\t\tvoid promise.catch(() => undefined);\n\t\treturn { promise, resolve, reject };\n\t}\n\n\tprivate settleSnapshotDuplicateValidation(generation: SnapshotTranscriptGeneration, error?: Error): void {\n\t\tconst validation = generation.validation;\n\t\tif (!validation) {\n\t\t\treturn;\n\t\t}\n\t\tgeneration.validation = undefined;\n\t\tif (error) {\n\t\t\tvalidation.reject(error);\n\t\t} else {\n\t\t\tvalidation.resolve();\n\t\t}\n\t}\n\n\tprivate async recoverWorker(worker: ResidentWorker): Promise<void> {\n\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\treturn;\n\t\t}\n\t\tif (worker.descriptor.ownerClientId && !worker.launchEnv && !isProcessAlive(worker.descriptor.pid)) {\n\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\tworker.descriptor.lastError = \"Waiting for the owning client to reconnect\";\n\t\t\tthis.persistWorker(worker);\n\t\t\treturn;\n\t\t}\n\t\tif (worker.recovery) {\n\t\t\treturn worker.recovery;\n\t\t}\n\t\tworker.recovery = (async () => {\n\t\t\tlet keepProbingLiveWorker = false;\n\t\t\tfor (const retryDelay of WORKER_RETRY_DELAYS_MS) {\n\t\t\t\tawait delay(retryDelay);\n\t\t\t\tkeepProbingLiveWorker = false;\n\t\t\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\tconst identityNow = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t\t\t\tconst identityCompatible =\n\t\t\t\t\t\tidentityNow === \"current\" ||\n\t\t\t\t\t\t(identityNow === \"unknown\" && worker.descriptor.processStartId === undefined);\n\t\t\t\t\tif (identityCompatible) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait this.connectWorker(worker, 1500);\n\t\t\t\t\t\t\tawait this.subscribeWorker(worker, worker.descriptor.rootActiveSessionId);\n\t\t\t\t\t\t\tawait this.refreshWorkerSummaries(worker, true);\n\t\t\t\t\t\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (worker.descriptor.processStartId === undefined) {\n\t\t\t\t\t\t\t\tconst observedProcessStartId = getProcessStartId(worker.descriptor.pid);\n\t\t\t\t\t\t\t\tif (observedProcessStartId) {\n\t\t\t\t\t\t\t\t\tworker.descriptor.processStartId = observedProcessStartId;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\t\t\tworker.descriptor.lifecycle = \"ready\";\n\t\t\t\t\t\t\tworker.descriptor.consecutiveFailures = 0;\n\t\t\t\t\t\t\tworker.deferredRecoveryRounds = 0;\n\t\t\t\t\t\t\tthis.persistWorker(worker);\n\t\t\t\t\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tif (isSupervisorRecoveryCancelled(error) || error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\t\t\tworker.client?.close();\n\t\t\t\t\t\t\tworker.client = undefined;\n\t\t\t\t\t\t\t// A worker with the same durable process identity may be load-slow.\n\t\t\t\t\t\t\t// Keep probing it instead of replacing live work after a timeout.\n\t\t\t\t\t\t\tkeepProbingLiveWorker = isDaemonWorkerProbeTimeout(error) || identityNow !== \"current\";\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (identityNow === \"unknown\") {\n\t\t\t\t\t\tkeepProbingLiveWorker = true;\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Cannot safely replace live session worker ${worker.descriptor.workerId} without a verified process identity`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst recoveryCommand = worker.descriptor.ownerClientId ? worker.transientCreateCommand : undefined;\n\t\t\t\t\tif (!recoveryCommand || !worker.launchEnv) {\n\t\t\t\t\t\tawait this.recoverUncertainWorkerOperations(worker);\n\t\t\t\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\t\t\t\tworker.descriptor.lastError = \"Waiting for a client with fresh runtime context\";\n\t\t\t\t\t\tthis.persistWorker(worker);\n\t\t\t\t\t\tthis.markWorkerRosterEntries(worker, \"failed\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.recoverUncertainWorkerOperations(worker);\n\t\t\t\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.launchWorker(recoveryCommand, worker, worker.descriptor.ownerClientId);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isSupervisorRecoveryCancelled(error) || this.isWorkerRecoveryCancelled(worker)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\t\t\tthis.parkIncompatibleWorker(worker, error);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tworker.client?.close();\n\t\t\t\t\tworker.client = undefined;\n\t\t\t\t\tworker.descriptor.consecutiveFailures++;\n\t\t\t\t\tworker.descriptor.lastFailureAt = new Date().toISOString();\n\t\t\t\t\tworker.descriptor.lastError = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tthis.persistWorker(worker);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (keepProbingLiveWorker) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t} catch {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tthis.deferWorkerRecovery(\n\t\t\t\t\tworker,\n\t\t\t\t\tnew Error(worker.descriptor.lastError ?? \"Live session worker did not answer recovery probes\"),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t} catch {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Leak-over-kill: a live worker that keeps failing for non-timeout reasons parks failed with\n\t\t\t// its process intact. A verified-identity survivor is reclaimed by the next fresh create;\n\t\t\t// an unverifiable one waits for exit — killing a pid we cannot verify as ours is worse.\n\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\tthis.persistWorker(worker);\n\t\t\tthis.markWorkerRosterEntries(worker, \"failed\");\n\t\t\tthis.log(`Worker ${worker.descriptor.workerId} failed after three recovery attempts`);\n\t\t})().finally(() => {\n\t\t\tworker.recovery = undefined;\n\t\t});\n\t\treturn worker.recovery;\n\t}\n\n\tprivate isWorkerRecoveryCancelled(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tthis.shuttingDown ||\n\t\t\tworker.intentionalStop ||\n\t\t\tworker.descriptor.stopRequestedAt !== undefined ||\n\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker\n\t\t);\n\t}\n\n\tprivate isWorkerCleanupCancelled(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tthis.shuttingDown ||\n\t\t\tworker.descriptor.stopRequestedAt !== undefined ||\n\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker\n\t\t);\n\t}\n\n\tprivate async recoverUncertainWorkerOperations(worker: ResidentWorker): Promise<void> {\n\t\tawait this.assertRecoveryAllowed();\n\t\tconst journal = new WorkerRecoveryJournal(worker.descriptor.recoveryJournalPath);\n\t\tconst latest = journal.getLatest();\n\t\tconst uncertain = latest.filter((record) => record.busy);\n\t\tif (uncertain.length > 0) await this.catalog.start();\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (this.isWorkerCleanupCancelled(worker)) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Worker recovery was cancelled before destructive cleanup\");\n\t\t}\n\n\t\tconst interruptedSessions = new Map<\n\t\t\tstring,\n\t\t\t{ activeSessionId: string; sessionFile: string; operations: Set<string> }\n\t\t>();\n\t\tfor (const record of uncertain) {\n\t\t\tconst sessionFile =\n\t\t\t\trecord.sessionFile ??\n\t\t\t\t(record.activeSessionId === worker.descriptor.rootActiveSessionId\n\t\t\t\t\t? worker.descriptor.sessionFile\n\t\t\t\t\t: undefined);\n\t\t\tif (!sessionFile) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst key = `${record.activeSessionId}\\0${sessionFile}`;\n\t\t\tlet interrupted = interruptedSessions.get(key);\n\t\t\tif (!interrupted) {\n\t\t\t\tinterrupted = { activeSessionId: record.activeSessionId, sessionFile, operations: new Set() };\n\t\t\t\tinterruptedSessions.set(key, interrupted);\n\t\t\t}\n\t\t\tinterrupted.operations.add(record.operation);\n\t\t}\n\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (this.isWorkerCleanupCancelled(worker)) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Worker recovery was cancelled before interruption was recorded\");\n\t\t}\n\t\tawait Promise.all(\n\t\t\t[...interruptedSessions.values()].map((interrupted) =>\n\t\t\t\tthis.catalog.markInterrupted(interrupted.sessionFile, interrupted.activeSessionId, [\n\t\t\t\t\t...interrupted.operations,\n\t\t\t\t]),\n\t\t\t),\n\t\t);\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (this.isWorkerCleanupCancelled(worker)) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Worker recovery was cancelled before process cleanup\");\n\t\t}\n\t\tconst orphanProcessJournalPath = worker.descriptor.orphanProcessJournalPath;\n\t\tif (orphanProcessJournalPath) {\n\t\t\ttry {\n\t\t\t\tconst orphans = readActiveOrphanProcesses(orphanProcessJournalPath, worker.descriptor.pid);\n\t\t\t\tlet reapFailed = false;\n\t\t\t\tlet retryIsSafe = true;\n\t\t\t\tfor (const orphan of orphans) {\n\t\t\t\t\tif (orphan.processStartId === undefined) retryIsSafe = false;\n\t\t\t\t\tif (!shouldReapOrphanProcess(orphan)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!killOrphanProcess(orphan.pid)) reapFailed = true;\n\t\t\t\t}\n\t\t\t\tif (!reapFailed || !retryIsSafe) clearOrphanProcessJournal(orphanProcessJournalPath);\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Could not reap orphaned worker resources: ${String(error)}`);\n\t\t\t}\n\t\t}\n\t\tif (uncertain.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const record of latest) {\n\t\t\tjournal.record({\n\t\t\t\tactiveSessionId: record.activeSessionId,\n\t\t\t\tsessionId: record.sessionId,\n\t\t\t\t...(record.sessionFile ? { sessionFile: record.sessionFile } : {}),\n\t\t\t\tbusy: false,\n\t\t\t\toperation: \"recovery_hold\",\n\t\t\t});\n\t\t}\n\t\tthis.log(\n\t\t\t`Recovered worker ${worker.descriptor.workerId} without replaying uncertain operations: ${uncertain\n\t\t\t\t.map((record) => record.operation)\n\t\t\t\t.join(\", \")}`,\n\t\t);\n\t}\n\tprivate async refreshWorkerSummaries(\n\t\tworker: ResidentWorker,\n\t\trecovery = false,\n\t\tfillGaps = recovery,\n\t\tretried = false,\n\t): Promise<void> {\n\t\tif (this.isWorkerStopping(worker)) {\n\t\t\tthrow new Error(\"Session worker is stopping\");\n\t\t}\n\t\tif (!worker.client) {\n\t\t\tthrow new Error(\"Session worker is not connected\");\n\t\t}\n\t\tconst pullSource = worker.client;\n\t\tconst epochAtStart = worker.rosterEpoch ?? 0;\n\t\tconst response = await pullSource.request({ type: \"list\" }, 5000);\n\t\t// A frame received mid-pull can remove rows this stale pull would resurrect; re-pull once, then skip the fill.\n\t\tif (fillGaps && (worker.rosterEpoch ?? 0) !== epochAtStart && !retried) {\n\t\t\treturn this.refreshWorkerSummaries(worker, recovery, fillGaps, true);\n\t\t}\n\t\tconst summaries = sessionSummariesFromResponse(response);\n\t\tconst nextSummaries = new Map(summaries.map((summary) => [summary.activeSessionId ?? summary.id, summary]));\n\t\tconst root = nextSummaries.get(worker.descriptor.rootActiveSessionId);\n\t\tif (recovery && !root) {\n\t\t\tthrow new Error(`Session worker omitted its root session during recovery`);\n\t\t}\n\t\tworker.summaries = nextSummaries;\n\t\tif (fillGaps) {\n\t\t\tawait this.chainWorkerRosterApply(worker, pullSource, () => {\n\t\t\t\tif ((worker.rosterEpoch ?? 0) === epochAtStart) this.syncRosterFromWorkerSummaries(worker);\n\t\t\t});\n\t\t}\n\t\tfor (const summary of summaries) {\n\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\tif (summary.streamingMessage?.role === \"assistant\") {\n\t\t\t\tthis.streamReconstructor.seed(activeSessionId, summary.streamingMessage);\n\t\t\t} else if (!summary.isStreaming) {\n\t\t\t\tthis.streamReconstructor.clear(activeSessionId);\n\t\t\t}\n\t\t}\n\t\tif (root) {\n\t\t\tif (recovery) {\n\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t}\n\t\t\tawait this.chainWorkerRosterApply(worker, pullSource, () => {\n\t\t\t\tif ((worker.rosterEpoch ?? 0) !== epochAtStart) return;\n\t\t\t\tworker.descriptor.rootSessionId = root.sessionId;\n\t\t\t\tworker.descriptor.sessionFile = root.sessionFile;\n\t\t\t\tworker.descriptor.createCommand = durableDaemonCreateCommand({\n\t\t\t\t\ttype: \"create\",\n\t\t\t\t\tsessionPath: root.sessionFile,\n\t\t\t\t\tnoSession: worker.descriptor.createCommand.noSession,\n\t\t\t\t});\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async familyCatalogEntries(): Promise<AgentFamilyCatalogEntry[]> {\n\t\tconst rosterRows = [...this.roster().values()];\n\t\tconst entries = rosterRows.map((entry) => this.familyCatalogEntry(sessionSummaryFromRosterEntry(entry)));\n\t\tconst knownFiles = new Set(\n\t\t\trosterRows.flatMap((entry) =>\n\t\t\t\tentry.summary.sessionFile ? [canonicalSessionPath(entry.summary.sessionFile)] : [],\n\t\t\t),\n\t\t);\n\t\tconst scanned = await this.catalog.list(undefined, this.defaultSessionConfig.sessionDir);\n\t\tfor (const info of scanned) {\n\t\t\tif (knownFiles.has(canonicalSessionPath(info.path))) continue;\n\t\t\tif ((info.rlmDepth ?? (info.parentSessionPath ? -1 : 0)) !== 0) continue;\n\t\t\tentries.push(this.familyCatalogEntry(summaryForInactiveSession(info)));\n\t\t}\n\t\treturn entries;\n\t}\n\n\tprivate async withSessionNameReservation<T>(\n\t\tinput: { name: string; depth: number; parentSessionId?: string; parentSessionPath?: string },\n\t\taction: () => Promise<T>,\n\t): Promise<T> {\n\t\tconst key = sessionNameReservationKey(input);\n\t\tif (this.pendingSessionNames.has(key)) {\n\t\t\tthrow new Error(formatAgentSessionNameUnavailable(input.name, input.depth));\n\t\t}\n\t\tthis.pendingSessionNames.add(key);\n\t\ttry {\n\t\t\treturn await action();\n\t\t} finally {\n\t\t\tthis.pendingSessionNames.delete(key);\n\t\t}\n\t}\n\n\tprivate async assertSupervisorSessionNameAvailable(\n\t\ttarget: Pick<SessionSummary, \"sessionId\" | \"rlmDepth\" | \"parentSessionId\" | \"parentSessionPath\">,\n\t\tname: string,\n\t): Promise<void> {\n\t\tassertAgentSessionNameAvailable(await this.familyCatalogEntries(), {\n\t\t\tname,\n\t\t\tdepth: target.rlmDepth ?? 0,\n\t\t\tparentSessionId: target.parentSessionId,\n\t\t\tparentSessionPath: target.parentSessionPath ? canonicalSessionPath(target.parentSessionPath) : undefined,\n\t\t\tignoreSessionId: target.sessionId,\n\t\t});\n\t}\n\n\tprivate roster(): AgentRoster {\n\t\tthis.rosterStore ??= new AgentRoster(canonicalSessionPath, (mutation) => this.onRosterMutation(mutation));\n\t\treturn this.rosterStore;\n\t}\n\n\tprivate onRosterMutation(mutation: AgentRosterMutation): void {\n\t\tif (mutation.type === \"delete\") {\n\t\t\tthis.pendingRosterChanged.delete(mutation.agentId);\n\t\t\tthis.pendingRosterRemoved.add(mutation.agentId);\n\t\t} else {\n\t\t\tthis.pendingRosterRemoved.delete(mutation.agentId);\n\t\t\tthis.pendingRosterChanged.add(mutation.agentId);\n\t\t}\n\t\tthis.scheduleRosterPush();\n\t}\n\n\tprivate scheduleRosterPush(): void {\n\t\tif (this.rosterPushScheduled || this.shuttingDown) return;\n\t\tthis.rosterPushScheduled = true;\n\t\tsetImmediate(() => {\n\t\t\tthis.rosterPushScheduled = false;\n\t\t\tthis.flushRosterUpdates();\n\t\t});\n\t}\n\n\tprivate flushRosterUpdates(): void {\n\t\tconst changed: AgentRosterEntry[] = [];\n\t\tconst removed: string[] = [];\n\t\tfor (const agentId of this.pendingRosterRemoved) {\n\t\t\tif (this.publishedRosterIds.delete(agentId)) removed.push(agentId);\n\t\t}\n\t\tfor (const agentId of this.pendingRosterChanged) {\n\t\t\tconst entry = this.roster().get(agentId);\n\t\t\tif (!entry) continue;\n\t\t\tif (this.isRosterEntryVisibleToClients(entry)) {\n\t\t\t\tchanged.push(entry);\n\t\t\t\tthis.publishedRosterIds.add(agentId);\n\t\t\t} else if (this.publishedRosterIds.delete(agentId)) {\n\t\t\t\tremoved.push(agentId);\n\t\t\t}\n\t\t}\n\t\tthis.pendingRosterChanged.clear();\n\t\tthis.pendingRosterRemoved.clear();\n\t\tif (changed.length === 0 && removed.length === 0) return;\n\t\tfor (const client of this.clients) {\n\t\t\tif (client.rosterSubscribed !== true) continue;\n\t\t\tif (client.backpressured === true) {\n\t\t\t\tclient.rosterResyncPending = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.write(client, {\n\t\t\t\ttype: \"roster_update\",\n\t\t\t\tchanged,\n\t\t\t\t...(removed.length > 0 ? { removed } : {}),\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate rosterEntriesForClient(): AgentRosterEntry[] {\n\t\tconst entries = [...this.roster().values()].filter((entry) => this.isRosterEntryVisibleToClients(entry));\n\t\tfor (const entry of entries) this.publishedRosterIds.add(entry.agentId);\n\t\treturn entries;\n\t}\n\n\tprivate isRosterEntryVisibleToClients(entry: AgentRosterEntry): boolean {\n\t\tconst worker = entry.workerId !== undefined ? this.workers.get(entry.workerId) : undefined;\n\t\treturn worker === undefined || this.isVisibleWorker(worker);\n\t}\n\n\tprivate writeRosterEntry(\n\t\tentry: WorkerRosterEntry,\n\t\tworker?: ResidentWorker,\n\t\tstatusLabel?: AgentRosterEntry[\"statusLabel\"],\n\t): AgentRosterEntry {\n\t\tconst previousDirect = this.roster().get(entry.agentId)?.summary.directAttachedClients ?? 0;\n\t\tconst stored = this.roster().write(entry, worker?.descriptor.workerId, statusLabel);\n\t\t// Direct peers attach and detach on the worker socket, so their last detach arrives\n\t\t// here as roster truth instead of through a supervisor-socket close.\n\t\tif (worker !== undefined && previousDirect > 0 && (entry.summary.directAttachedClients ?? 0) === 0) {\n\t\t\tvoid this.evictEmptySessionOnLastDetach(entry.summary.activeSessionId ?? entry.summary.id);\n\t\t}\n\t\treturn stored;\n\t}\n\n\tprivate workerOwnedRosterSummaryForPath(canonicalPath: string): SessionSummary | undefined {\n\t\tconst entry = this.roster().bySessionFile(canonicalPath);\n\t\tif (!entry || entry.workerId === undefined || !this.workers.has(entry.workerId)) return undefined;\n\t\treturn sessionSummaryFromRosterEntry(entry);\n\t}\n\n\tprivate workerRosterEntries(worker: ResidentWorker): AgentRosterEntry[] {\n\t\treturn this.roster().entriesForWorker(worker.descriptor.workerId);\n\t}\n\n\tprivate async seedRosterLedger(): Promise<void> {\n\t\ttry {\n\t\t\tconst roots = new Set<string>();\n\t\t\tfor (const worker of this.workers.values()) {\n\t\t\t\tconst root = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\t\t\tif (root !== undefined) roots.add(canonicalSessionPath(root));\n\t\t\t}\n\t\t\tif (roots.size === 0) return;\n\t\t\tconst edges = await this.rlmSpawnLedger().liveEdges();\n\t\t\tconst descendsFrom = rosterFamilyDescendsFrom(edges);\n\t\t\tfor (const edge of edges) {\n\t\t\t\tif (!descendsFrom(canonicalSessionPath(edge.parent), roots)) continue;\n\t\t\t\tconst entry = this.rosterEntryForSpawnLedgerEdge(edge);\n\t\t\t\tif (this.roster().has(entry.agentId)) continue;\n\t\t\t\tif (this.roster().hasSessionFile(canonicalSessionPath(edge.child))) continue;\n\t\t\t\tthis.roster().write(await this.hydratedSeedEntry(entry));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.log(`Could not seed the agent roster from the spawn ledger: ${String(error)}`);\n\t\t}\n\t}\n\n\tprivate rosterEntryForSpawnLedgerEdge(edge: RlmLedgerEdge): WorkerRosterEntry {\n\t\tconst persistedSessionId = basename(edge.child, \".jsonl\");\n\t\tconst summary: WorkerRosterEntry[\"summary\"] = {\n\t\t\tid: persistedSessionId,\n\t\t\tlifecycle: \"live\",\n\t\t\tactivity: \"idle\",\n\t\t\tisSessionActive: false,\n\t\t\truntimeKind: \"subagent\",\n\t\t\trlmDepth: edge.depth,\n\t\t\tsessionId: persistedSessionId,\n\t\t\tsessionFile: edge.child,\n\t\t\tsessionName: edge.name,\n\t\t\tcwd: dirname(edge.child),\n\t\t\tisStreaming: false,\n\t\t\tisCompacting: false,\n\t\t\tattachedClients: 0,\n\t\t\tmessageCount: 0,\n\t\t\tparentSessionPath: edge.parent,\n\t\t\trlmChildId: edge.childId,\n\t\t};\n\t\treturn { agentId: rosterAgentIdForSummary(summary), summary };\n\t}\n\n\tprivate consumeWorkerRosterDelta(worker: ResidentWorker, payload: Buffer, source?: DaemonWorkerClient): void {\n\t\tlet delta: Extract<DaemonWorkerRosterOutbound, { type: \"roster_delta\" }>;\n\t\ttry {\n\t\t\tdelta = JSON.parse(payload.toString(\"utf8\")) as Extract<DaemonWorkerRosterOutbound, { type: \"roster_delta\" }>;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (delta.type !== \"roster_delta\" || !Array.isArray(delta.entries)) return;\n\t\tworker.rosterEpoch = (worker.rosterEpoch ?? 0) + 1;\n\t\tconst applySource = source ?? worker.client ?? worker.pendingClient;\n\t\tif (!this.isWorkerRosterApplyCurrent(worker, applySource)) return;\n\t\tif (delta.snapshot !== true && worker.rosterApplyChain === undefined) {\n\t\t\tthis.applyWorkerRosterDelta(worker, delta);\n\t\t\treturn;\n\t\t}\n\t\tthis.chainWorkerRosterApply(worker, applySource, () =>\n\t\t\tdelta.snapshot === true\n\t\t\t\t? this.applyWorkerRosterSnapshot(worker, delta, applySource)\n\t\t\t\t: this.applyWorkerRosterDelta(worker, delta),\n\t\t);\n\t}\n\n\tprivate chainWorkerRosterApply(\n\t\tworker: ResidentWorker,\n\t\tsource: DaemonWorkerClient | undefined,\n\t\tapply: () => void | Promise<void>,\n\t): Promise<void> {\n\t\tconst chained = (worker.rosterApplyChain ?? Promise.resolve())\n\t\t\t.then(() => {\n\t\t\t\tif (!this.isWorkerRosterApplyCurrent(worker, source)) return;\n\t\t\t\treturn apply();\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tthis.log(`could not apply a roster frame: ${String(error)}`);\n\t\t\t\tthis.scheduleRosterRepairPull(worker);\n\t\t\t});\n\t\tworker.rosterApplyChain = chained;\n\t\tvoid chained.finally(() => {\n\t\t\tif (worker.rosterApplyChain === chained) worker.rosterApplyChain = undefined;\n\t\t});\n\t\treturn chained;\n\t}\n\n\t// An apply is valid only while its own source connection is current: dead connections' parked applies abort.\n\tprivate isWorkerRosterApplyCurrent(worker: ResidentWorker, source: DaemonWorkerClient | undefined): boolean {\n\t\treturn (\n\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\tsource !== undefined &&\n\t\t\t(source === worker.client || source === worker.pendingClient)\n\t\t);\n\t}\n\n\tprivate scheduleRosterRepairPull(worker: ResidentWorker): void {\n\t\tif (worker.rosterRepairPull || !this.isWorkerRosterApplyCurrent(worker, worker.client)) return;\n\t\t// The marker stays set while the repair's own fill applies, so a failing repair never respawns itself.\n\t\tworker.rosterRepairPull = this.refreshWorkerSummaries(worker, false, true)\n\t\t\t.catch((error: unknown) =>\n\t\t\t\tthis.log(`Roster repair pull failed for worker ${worker.descriptor.workerId}: ${String(error)}`),\n\t\t\t)\n\t\t\t.finally(() => {\n\t\t\t\tworker.rosterRepairPull = undefined;\n\t\t\t});\n\t}\n\n\tprivate applyWorkerRosterDelta(\n\t\tworker: ResidentWorker,\n\t\tdelta: Extract<DaemonWorkerRosterOutbound, { type: \"roster_delta\" }>,\n\t): void {\n\t\tfor (const entry of delta.entries) {\n\t\t\tthis.writeRosterEntry(entry, worker);\n\t\t\tthis.syncRootDescriptorFromRosterEntry(worker, entry);\n\t\t}\n\t\tfor (const agentId of delta.removedAgentIds ?? []) {\n\t\t\tthis.roster().delete(agentId);\n\t\t}\n\t}\n\n\tprivate async applyWorkerRosterSnapshot(\n\t\tworker: ResidentWorker,\n\t\tdelta: Extract<DaemonWorkerRosterOutbound, { type: \"roster_delta\" }>,\n\t\tsource?: DaemonWorkerClient,\n\t): Promise<void> {\n\t\tlet edgesFailed = false;\n\t\tconst edges = await this.rlmSpawnLedger()\n\t\t\t.liveEdges()\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tthis.log(`Could not read the spawn ledger during a snapshot apply: ${String(error)}`);\n\t\t\t\tedgesFailed = true;\n\t\t\t\treturn [] as RlmLedgerEdge[];\n\t\t\t});\n\t\tconst applySource = source ?? worker.client ?? worker.pendingClient;\n\t\tif (!this.isWorkerRosterApplyCurrent(worker, applySource)) return;\n\t\tconst sent = new Set(delta.entries.map((entry) => entry.agentId));\n\t\tconst removed = new Set(delta.removedAgentIds ?? []);\n\t\tconst unclaimed = new Map<string, AgentRosterEntry>();\n\t\tif (!edgesFailed) {\n\t\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\t\tif (sent.has(entry.agentId)) continue;\n\t\t\t\tunclaimed.set(entry.agentId, entry);\n\t\t\t}\n\t\t}\n\t\t// Only this worker's family reseeds: anything wider can resurrect a client-owned worker's dropped children.\n\t\tconst workerRoot = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\tconst rootPaths = new Set(workerRoot !== undefined ? [canonicalSessionPath(workerRoot)] : []);\n\t\tconst descendsFrom = rosterFamilyDescendsFrom(edges);\n\t\tconst familyEdges = edges.filter((edge) => descendsFrom(canonicalSessionPath(edge.parent), rootPaths));\n\t\t// \"Unclaimed\" rows survive: the sweep deletes them but the restore branch rewrites them.\n\t\tconst rowSurvivesWithoutReseed = (entry: WorkerRosterEntry, childPath: string): boolean => {\n\t\t\tif (unclaimed.has(entry.agentId)) return true;\n\t\t\tif (sent.has(entry.agentId) && !removed.has(entry.agentId)) return true;\n\t\t\tconst survives = (row: AgentRosterEntry | undefined): boolean =>\n\t\t\t\trow !== undefined && !unclaimed.has(row.agentId) && !removed.has(row.agentId);\n\t\t\treturn survives(this.roster().get(entry.agentId)) || survives(this.roster().bySessionFile(childPath));\n\t\t};\n\t\tconst seededEntries = new Map<string, WorkerRosterEntry>();\n\t\tfor (const edge of familyEdges) {\n\t\t\tconst entry = this.rosterEntryForSpawnLedgerEdge(edge);\n\t\t\tif (rowSurvivesWithoutReseed(entry, canonicalSessionPath(edge.child))) continue;\n\t\t\tseededEntries.set(entry.agentId, await this.hydratedSeedEntry(entry));\n\t\t\tif (!this.isWorkerRosterApplyCurrent(worker, applySource)) return;\n\t\t}\n\n\t\t// Unreadable edges skip the absentee sweep: it cannot tell registry children from stale rows.\n\t\tfor (const entry of unclaimed.values()) this.roster().delete(entry.agentId);\n\t\tfor (const entry of delta.entries) {\n\t\t\tthis.writeRosterEntry(entry, worker);\n\t\t\tthis.syncRootDescriptorFromRosterEntry(worker, entry);\n\t\t}\n\t\tfor (const agentId of removed) this.roster().delete(agentId);\n\t\tif (edgesFailed) {\n\t\t\tthis.scheduleRosterRepairPull(worker);\n\t\t\treturn;\n\t\t}\n\t\tfor (const edge of familyEdges) {\n\t\t\tconst entry = this.rosterEntryForSpawnLedgerEdge(edge);\n\t\t\tif (this.roster().has(entry.agentId)) continue;\n\t\t\tif (this.roster().hasSessionFile(canonicalSessionPath(edge.child))) continue;\n\t\t\tconst previous = unclaimed.get(entry.agentId);\n\t\t\tif (previous) {\n\t\t\t\tconst { status, statusLabel, lastHeardFromAt, workerId, ...rest } = previous;\n\t\t\t\tthis.writeRosterEntry(rest, worker);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.roster().write(seededEntries.get(entry.agentId) ?? { ...entry, seededCwd: true });\n\t\t}\n\t}\n\n\tprivate syncRootDescriptorFromRosterEntry(worker: ResidentWorker, entry: WorkerRosterEntry): void {\n\t\tconst summary = entry.summary;\n\t\tif (summary.activeSessionId !== worker.descriptor.rootActiveSessionId) return;\n\t\tif (\n\t\t\tworker.descriptor.rootSessionId === summary.sessionId &&\n\t\t\tworker.descriptor.sessionFile === summary.sessionFile\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tworker.descriptor.rootSessionId = summary.sessionId;\n\t\tworker.descriptor.sessionFile = summary.sessionFile;\n\t\tworker.descriptor.createCommand = durableDaemonCreateCommand({\n\t\t\ttype: \"create\",\n\t\t\tsessionPath: summary.sessionFile,\n\t\t\tnoSession: worker.descriptor.createCommand.noSession,\n\t\t});\n\t\tthis.persistWorker(worker);\n\t}\n\n\t// Behind the pull-epoch guard the pull is never staler than the row it replaces; never steal another worker's claim.\n\tprivate syncRosterFromWorkerSummaries(worker: ResidentWorker): void {\n\t\tfor (const summary of worker.summaries.values()) {\n\t\t\tconst entry = workerRosterEntryFromSummary(summary);\n\t\t\tconst existing = this.roster().get(entry.agentId);\n\t\t\tif (existing?.workerId !== undefined && existing.workerId !== worker.descriptor.workerId) continue;\n\t\t\tthis.writeRosterEntry(entry, worker);\n\t\t}\n\t}\n\n\tprivate markWorkerRosterEntries(worker: ResidentWorker, statusLabel: \"recovering\" | \"failed\" | undefined): void {\n\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\tif (!entry.queuedChild && entry.summary.activeSessionId === undefined) continue;\n\t\t\tthis.roster().amend(entry.agentId, { statusLabel });\n\t\t}\n\t}\n\n\tprivate flipWorkerRosterEntriesInactive(worker: ResidentWorker): void {\n\t\t// Client-owned workers are ephemeral and private: their rows die with the registration.\n\t\tconst ephemeral = worker.descriptor.ownerClientId !== undefined;\n\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\tif (ephemeral || entry.queuedChild) {\n\t\t\t\tthis.roster().delete(entry.agentId);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Registration marks survive eviction: passive rows still have schedules behind them.\n\t\t\tthis.writeRosterEntry(\n\t\t\t\tpassivatedWorkerRosterEntry(entry, {\n\t\t\t\t\thasRegisteredHeartbeat: entry.summary.hasRegisteredHeartbeat === true,\n\t\t\t\t\thasRegisteredCronJob: entry.summary.hasRegisteredCronJob === true,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate sweepRosterStaleness(now = Date.now()): void {\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker.client === undefined || worker.lastFrameAt === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (now - worker.lastFrameAt > ROSTER_STALE_AFTER_MS) {\n\t\t\t\tconst lastHeardFromAt = new Date(worker.lastFrameAt).toISOString();\n\t\t\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\t\t\t// write() rebuilds rows without the mark; the sweep owns it and restamps only those.\n\t\t\t\t\tif (entry.lastHeardFromAt !== lastHeardFromAt) this.roster().amend(entry.agentId, { lastHeardFromAt });\n\t\t\t\t}\n\t\t\t\tworker.rosterStale = true;\n\t\t\t} else if (worker.rosterStale) {\n\t\t\t\tthis.clearRosterStaleness(worker);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate clearRosterStaleness(worker: ResidentWorker): void {\n\t\tif (!worker.rosterStale) return;\n\t\tworker.rosterStale = false;\n\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\tthis.roster().amend(entry.agentId, { lastHeardFromAt: undefined });\n\t\t}\n\t}\n\n\tprivate rlmJournalScope(sessionDir?: string): { agentDir: string; sessionsDir: string; journalPath: string } {\n\t\tconst agentDir = this.defaultSessionConfig.agentDir;\n\t\tif (!agentDir) throw new Error(\"Daemon supervisor config is missing agentDir\");\n\t\tconst sessionsDir = sessionDir ?? this.defaultSessionConfig.sessionDir ?? getSessionsDir(agentDir);\n\t\treturn { agentDir, sessionsDir, journalPath: rlmLedgerPath(agentDir, sessionsDir) };\n\t}\n\n\tprivate assertRlmJournalAdmission(): RlmJournalOwner {\n\t\tconst owner = this.rlmJournalOwner;\n\t\tif (!owner || this.rlmJournalClose) throw new Error(\"RLM journal mutation admission is closed\");\n\t\ttry {\n\t\t\tif (!this.ownership) throw new Error(\"RLM journal supervisor ownership is unavailable\");\n\t\t\tthis.ownership.assertJournalCurrent(owner.ledgerPath);\n\t\t} catch (error) {\n\t\t\tthis.fenceRlmJournalOwner();\n\t\t\tthrow error;\n\t\t}\n\t\treturn owner;\n\t}\n\n\tprivate fenceRlmJournalOwner(): void {\n\t\tvoid this.closeRlmJournalOwner().catch((error: unknown) => this.reportCleanupFailure(\"RLM journal owner\", error));\n\t}\n\n\tprivate closeRlmJournalOwner(): Promise<void> {\n\t\tthis.rlmSpawnLedgerInstance?.stopAdmission();\n\t\tif (this.rlmJournalClose) return this.rlmJournalClose;\n\t\tconst owner = this.rlmJournalOwner;\n\t\tif (!owner) return Promise.resolve();\n\t\tthis.rlmJournalClose = (async () => {\n\t\t\tawait this.rlmSpawnLedgerInstance?.flush();\n\t\t\tawait owner.close();\n\t\t\tthis.rlmJournalOwner = undefined;\n\t\t})();\n\t\treturn this.rlmJournalClose;\n\t}\n\n\t/** Reads are local; every mutation is acknowledged by the external lifetime owner. */\n\tprivate rlmSpawnLedger(): RlmSpawnLedger {\n\t\tconst { agentDir, sessionsDir } = this.rlmJournalScope();\n\t\tthis.rlmSpawnLedgerInstance ??= new RlmSpawnLedger(\n\t\t\tagentDir,\n\t\t\tsessionsDir,\n\t\t\tcreateRlmLedgerRegistrySeedSource(),\n\t\t\t(message) => this.log(message),\n\t\t\t{\n\t\t\t\tmode: \"remote\",\n\t\t\t\tmutate: (mutation) => {\n\t\t\t\t\tconst owner = this.rlmJournalOwner;\n\t\t\t\t\tif (!owner) throw new Error(\"RLM journal owner is unavailable\");\n\t\t\t\t\treturn owner.mutate(mutation);\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\treturn this.rlmSpawnLedgerInstance;\n\t}\n\n\t/**\n\t * Ledger-backed same-parent rows for name reservation and admission. Rows\n\t * carry ledger topology plus best-effort display fields; consumers here\n\t * only need id/path/name/depth/parent.\n\t */\n\tprivate rlmLedgerSiblings(sessionPath: string): Promise<SessionInfo[]> {\n\t\treturn this.rlmSpawnLedger().siblings(sessionPath);\n\t}\n\n\tprivate async savedSessionNameReservationInput(\n\t\tsessionPath: string,\n\t\tname: string,\n\t): Promise<{ name: string; depth: number; parentSessionId?: string; parentSessionPath?: string }> {\n\t\tconst targetPath = canonicalSessionPath(sessionPath);\n\t\tconst active = this.workerOwnedRosterSummaryForPath(targetPath);\n\t\tif (active) return this.summaryNameReservationInput(active, name);\n\t\tconst siblings = await this.rlmLedgerSiblings(sessionPath);\n\t\tconst saved = siblings.find((info) => canonicalSessionPath(info.path) === targetPath);\n\t\tif (!saved) throw new Error(`Session not found: ${sessionPath}`);\n\t\treturn {\n\t\t\tname,\n\t\t\tdepth: saved.rlmDepth ?? siblings.find((sibling) => sibling.rlmDepth !== undefined)?.rlmDepth ?? 0,\n\t\t\tparentSessionPath: saved.parentSessionPath,\n\t\t};\n\t}\n\n\tprivate summaryNameReservationInput(\n\t\ttarget: Pick<SessionSummary, \"rlmDepth\" | \"parentSessionId\" | \"parentSessionPath\">,\n\t\tname: string,\n\t): { name: string; depth: number; parentSessionId?: string; parentSessionPath?: string } {\n\t\tconst depth = target.rlmDepth ?? (target.parentSessionPath ? 1 : 0);\n\t\treturn {\n\t\t\tname,\n\t\t\tdepth,\n\t\t\t...(depth > 0 && target.parentSessionId ? { parentSessionId: target.parentSessionId } : {}),\n\t\t\t...(depth > 0 && target.parentSessionPath ? { parentSessionPath: target.parentSessionPath } : {}),\n\t\t};\n\t}\n\n\tprivate async assertSupervisorSavedSessionNameAvailable(sessionPath: string, name: string): Promise<void> {\n\t\tconst targetPath = canonicalSessionPath(sessionPath);\n\t\tconst active = this.workerOwnedRosterSummaryForPath(targetPath);\n\t\tif (active) return this.assertSupervisorSessionNameAvailable(active, name);\n\t\tconst siblings = await this.rlmLedgerSiblings(sessionPath);\n\t\tconst saved = siblings.find((info) => canonicalSessionPath(info.path) === targetPath);\n\t\tif (!saved) throw new Error(`Session not found: ${sessionPath}`);\n\t\tif (saved.parentSessionPath && (saved.rlmDepth ?? 0) > 0) {\n\t\t\tthis.assertSavedSiblingNameAvailable(siblings, saved, name);\n\t\t} else {\n\t\t\tawait this.assertSupervisorSessionNameAvailable(summaryForInactiveSession(saved), name);\n\t\t}\n\t}\n\n\tprivate assertSavedSiblingNameAvailable(siblings: SessionInfo[], target: SessionInfo, name: string): void {\n\t\tconst setDepth = target.rlmDepth ?? siblings.find((sibling) => sibling.rlmDepth !== undefined)?.rlmDepth ?? 0;\n\t\tassertAgentSessionNameAvailable(\n\t\t\tsiblings.map((info) => {\n\t\t\t\tconst summary = summaryForInactiveSession(info);\n\t\t\t\tconst ledgerRow = this.roster().bySessionFile(canonicalSessionPath(info.path));\n\t\t\t\treturn {\n\t\t\t\t\tid: summary.sessionId,\n\t\t\t\t\t...(summary.sessionName ? { name: summary.sessionName } : {}),\n\t\t\t\t\tdepth: setDepth,\n\t\t\t\t\tstatus: ledgerRow?.status ?? classifySessionRosterStatus(summary),\n\t\t\t\t\t...(summary.parentSessionPath\n\t\t\t\t\t\t? { parentSessionPath: canonicalSessionPath(summary.parentSessionPath) }\n\t\t\t\t\t\t: {}),\n\t\t\t\t};\n\t\t\t}),\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdepth: setDepth,\n\t\t\t\tparentSessionPath: target.parentSessionPath ? canonicalSessionPath(target.parentSessionPath) : undefined,\n\t\t\t\tignoreSessionId: target.id,\n\t\t\t},\n\t\t);\n\t}\n\n\tprivate isVisibleWorker(worker: ResidentWorker): boolean {\n\t\treturn worker.descriptor.ownerClientId === undefined;\n\t}\n\n\t/** A worker with a durable or in-memory stop intent is stopping, never live. */\n\tprivate isWorkerStopping(worker: ResidentWorker): boolean {\n\t\treturn worker.intentionalStop || worker.descriptor.stopRequestedAt !== undefined;\n\t}\n\n\t/** Live workers are visible to all clients and not stopping. */\n\tprivate isLiveWorker(worker: ResidentWorker): boolean {\n\t\treturn this.isVisibleWorker(worker) && !this.isWorkerStopping(worker);\n\t}\n\n\t/**\n\t * The lifecycle reported to clients. A stop intent always wins, and a worker\n\t * whose process connection is gone is never reported as \"ready\".\n\t */\n\tprivate effectiveWorkerState(worker: ResidentWorker): DaemonWorkerLifecycle {\n\t\tif (this.isWorkerStopping(worker)) {\n\t\t\treturn \"stopping\";\n\t\t}\n\t\tif (worker.descriptor.lifecycle === \"ready\" && worker.client === undefined) {\n\t\t\treturn \"recovering\";\n\t\t}\n\t\treturn worker.descriptor.lifecycle;\n\t}\n\n\tprivate requireAvailableWorkerClient(worker: ResidentWorker, allowStopping = false): DaemonWorkerClient {\n\t\tif (\n\t\t\t!worker.client ||\n\t\t\tworker.descriptor.lifecycle !== \"ready\" ||\n\t\t\t(!allowStopping && this.isWorkerStopping(worker))\n\t\t) {\n\t\t\tthrow new Error(`Session worker is ${this.effectiveWorkerState(worker)}`);\n\t\t}\n\t\treturn worker.client;\n\t}\n\n\tprivate async issuePeerTransport(\n\t\tworker: ResidentWorker,\n\t\tsummary: SessionSummary,\n\t): Promise<DaemonPeerTransportTicket> {\n\t\tawait this.assertCurrentOwnership();\n\t\tif (!worker.peerTransportCapable) {\n\t\t\tthrow new Error(\"Session worker does not support direct peer transport\");\n\t\t}\n\t\tawait this.refreshWorkerSummaries(worker);\n\t\tconst workerClient = this.requireAvailableWorkerClient(worker);\n\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\tconst currentSummary = this.findSummaryInWorker(worker, activeSessionId);\n\t\tif (!currentSummary) {\n\t\t\tthrow new Error(\"Direct transport target changed during admission\");\n\t\t}\n\t\tconst workerInstanceId = worker.descriptor.workerInstanceId;\n\t\tconst workerProcessStartId = worker.descriptor.processStartId;\n\t\tif (!workerInstanceId || !workerProcessStartId) {\n\t\t\tthrow new Error(\"Direct transport requires an exact worker process identity\");\n\t\t}\n\t\tif (this.processIdentity(worker.descriptor.pid, workerProcessStartId) !== \"current\") {\n\t\t\tthrow new Error(\"Direct transport worker process identity is not current\");\n\t\t}\n\t\tlet socketIdentity: DaemonSocketIdentity | undefined;\n\t\ttry {\n\t\t\tsocketIdentity = getDaemonSocketIdentity(worker.descriptor.socketPath);\n\t\t} catch {\n\t\t\tsocketIdentity = undefined;\n\t\t}\n\t\tif (!socketIdentity) {\n\t\t\tthrow new Error(\"Direct transport requires an exact worker socket identity\");\n\t\t}\n\t\tconst grantId = randomUUID();\n\t\tconst token = randomBytes(32).toString(\"base64url\");\n\t\tconst expiresAt = new Date(Date.now() + PEER_TRANSPORT_GRANT_TTL_MS).toISOString();\n\t\tconst resolvedActiveSessionId = currentSummary.activeSessionId ?? currentSummary.id;\n\t\tconst registration = await workerClient.requestWorker(\n\t\t\t{\n\t\t\t\ttype: \"worker_register_peer_transport\",\n\t\t\t\tgrant: {\n\t\t\t\t\tgrantId,\n\t\t\t\t\ttoken,\n\t\t\t\t\texpiresAt,\n\t\t\t\t\tpurpose: \"session_client\",\n\t\t\t\t\tworkerInstanceId,\n\t\t\t\t\tactiveSessionId: resolvedActiveSessionId,\n\t\t\t\t\tissuerGeneration: this.generation,\n\t\t\t\t},\n\t\t\t},\n\t\t\t3000,\n\t\t);\n\t\tif (!registration.success) {\n\t\t\tthrow deserializeDaemonError(registration);\n\t\t}\n\t\treturn {\n\t\t\tpurpose: \"session_client\",\n\t\t\tsocketPath: worker.descriptor.socketPath,\n\t\t\tsocketIdentity,\n\t\t\tworkerInstanceId,\n\t\t\tactiveSessionId: resolvedActiveSessionId,\n\t\t\tgrantId,\n\t\t\ttoken,\n\t\t\texpiresAt,\n\t\t};\n\t}\n\n\tprivate familyCatalogEntry(summary: SessionSummary): AgentFamilyCatalogEntry {\n\t\tconst depth = summary.rlmDepth ?? (summary.parentSessionPath ? 1 : 0);\n\t\treturn {\n\t\t\tid: summary.sessionId,\n\t\t\t...(summary.sessionName ? { name: summary.sessionName } : {}),\n\t\t\tdepth,\n\t\t\tstatus: summary.rosterStatus ?? classifySessionRosterStatus(summary),\n\t\t\t...(depth > 0 && summary.parentSessionId ? { parentSessionId: summary.parentSessionId } : {}),\n\t\t\t...(depth > 0 && summary.parentSessionPath\n\t\t\t\t? { parentSessionPath: canonicalSessionPath(summary.parentSessionPath) }\n\t\t\t\t: {}),\n\t\t\t...(summary.sessionFile ? { sessionPath: canonicalSessionPath(summary.sessionFile) } : {}),\n\t\t};\n\t}\n\n\tprivate agentPeerSummary(summary: SessionSummary): AgentSessionMessageAgentSummary {\n\t\treturn {\n\t\t\tactiveSessionId: summary.activeSessionId ?? summary.id,\n\t\t\tsessionId: summary.sessionId,\n\t\t\t...(summary.sessionName ? { sessionName: summary.sessionName } : {}),\n\t\t\truntimeKind: summary.runtimeKind ?? \"top-level\",\n\t\t\tcwd: summary.cwd,\n\t\t\tisStreaming: summary.isStreaming,\n\t\t\tunfinishedActionCount:\n\t\t\t\tsummary.unfinishedActionCount ??\n\t\t\t\t(summary.sessionActions.active\n\t\t\t\t\t? 1 + summary.sessionActions.queuedCount\n\t\t\t\t\t: summary.sessionActions.queuedCount),\n\t\t\t...(summary.parentActiveSessionId ? { parentActiveSessionId: summary.parentActiveSessionId } : {}),\n\t\t\t...(summary.parentSessionId ? { parentSessionId: summary.parentSessionId } : {}),\n\t\t\t...(summary.parentSessionPath ? { parentSessionPath: summary.parentSessionPath } : {}),\n\t\t\t...(summary.sessionFile ? { sessionPath: summary.sessionFile } : {}),\n\t\t\t...(summary.rlmDepth !== undefined ? { rlmDepth: summary.rlmDepth } : {}),\n\t\t\tstatus: summary.rosterStatus ?? classifySessionRosterStatus(summary),\n\t\t\t...(summary.rlmChildId ? { rlmChildId: summary.rlmChildId } : {}),\n\t\t};\n\t}\n\n\tprivate attachedClientCount(summary: SessionSummary, activeSessionId: string): number {\n\t\treturn (\n\t\t\t(summary.directAttachedClients ?? 0) +\n\t\t\t[...this.clients].filter((client) => client.attachedActiveSessionIds.has(activeSessionId)).length\n\t\t);\n\t}\n\n\tprivate publicSummary(worker: ResidentWorker, summary: SessionSummary): SessionSummary {\n\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\treturn {\n\t\t\t...summary,\n\t\t\tattachedClients: this.attachedClientCount(summary, activeSessionId),\n\t\t\tworkerState: this.effectiveWorkerState(worker),\n\t\t\tworkerPid: worker.descriptor.pid,\n\t\t};\n\t}\n\n\tprivate async findWorker(\n\t\tselector: string,\n\t\tincludeWorker?: (worker: ResidentWorker) => boolean,\n\t): Promise<WorkerMatch> {\n\t\tlet matches = this.matchWorkers(selector, includeWorker);\n\t\tif (matches.length === 0) {\n\t\t\tawait Promise.all(\n\t\t\t\t[...this.workers.values()].map((worker) =>\n\t\t\t\t\tthis.refreshWorkerSummaries(worker, false, true).catch(() => undefined),\n\t\t\t\t),\n\t\t\t);\n\t\t\tmatches = this.matchWorkers(selector, includeWorker);\n\t\t}\n\t\tif (matches.length === 1) {\n\t\t\treturn matches[0]!;\n\t\t}\n\t\tif (matches.length > 1) {\n\t\t\tthrow new Error(`Ambiguous active session \"${selector}\"`);\n\t\t}\n\t\tthrow new Error(`Unknown active session: ${selector}`);\n\t}\n\n\tprivate findWorkerForClient(client: DaemonSocketClient, selector: string): Promise<WorkerMatch> {\n\t\treturn this.findWorker(selector, (worker) => this.isWorkerAccessibleToClient(client, worker));\n\t}\n\n\tprivate isWorkerAccessibleToClient(client: DaemonSocketClient, worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tworker.descriptor.ownerClientId === undefined ||\n\t\t\tworker.descriptor.ownerClientId === this.protocolClientId(client)\n\t\t);\n\t}\n\n\tprivate assertWorkerAccessibleToClient(client: DaemonSocketClient, worker: ResidentWorker, selector: string): void {\n\t\tif (!this.isWorkerAccessibleToClient(client, worker)) {\n\t\t\tthrow new Error(`Unknown active session: ${selector}`);\n\t\t}\n\t}\n\n\tprivate matchWorkers(selector: string, includeWorker?: (worker: ResidentWorker) => boolean): WorkerMatch[] {\n\t\tconst exact: WorkerMatch[] = [];\n\t\tconst suffix: WorkerMatch[] = [];\n\t\tfor (const entry of this.roster().values()) {\n\t\t\tif (entry.queuedChild) continue;\n\t\t\tconst worker = entry.workerId !== undefined ? this.workers.get(entry.workerId) : undefined;\n\t\t\tif (!worker || (includeWorker && !includeWorker(worker))) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst summary = sessionSummaryFromRosterEntry(entry);\n\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\tconst match = { worker, summary };\n\t\t\tif (activeSessionId === selector || summary.sessionId === selector || summary.sessionName === selector) {\n\t\t\t\texact.push(match);\n\t\t\t} else if (\n\t\t\t\tmatchesSessionIdSuffix(activeSessionId, selector) ||\n\t\t\t\tmatchesSessionIdSuffix(summary.sessionId, selector)\n\t\t\t) {\n\t\t\t\tsuffix.push(match);\n\t\t\t}\n\t\t}\n\t\treturn exact.length > 0 ? exact : suffix;\n\t}\n\n\tprivate findSummaryInWorker(worker: ResidentWorker, selector: string): SessionSummary | undefined {\n\t\tconst pathSelector = looksLikeSessionPath(selector) ? canonicalSessionPath(selector) : undefined;\n\t\tconst summaries = this.workerRosterEntries(worker)\n\t\t\t.filter((entry) => !entry.queuedChild)\n\t\t\t.map(sessionSummaryFromRosterEntry);\n\t\tconst exact = summaries.find((summary) => {\n\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\treturn (\n\t\t\t\tactiveSessionId === selector ||\n\t\t\t\tsummary.sessionId === selector ||\n\t\t\t\tsummary.sessionName === selector ||\n\t\t\t\t(pathSelector !== undefined &&\n\t\t\t\t\tsummary.sessionFile !== undefined &&\n\t\t\t\t\tcanonicalSessionPath(summary.sessionFile) === pathSelector)\n\t\t\t);\n\t\t});\n\t\tif (exact) return exact;\n\t\treturn summaries.find((summary) => {\n\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\treturn (\n\t\t\t\tmatchesSessionIdSuffix(activeSessionId, selector) || matchesSessionIdSuffix(summary.sessionId, selector)\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate findWorkerBySessionFile(sessionFile: string, exclude?: ResidentWorker): ResidentWorker | undefined {\n\t\tconst target = canonicalSessionPath(sessionFile);\n\t\tconst targetEntry = this.roster().bySessionFile(target);\n\t\tconst matches = new Set<ResidentWorker>();\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker === exclude) continue;\n\t\t\t// The roster is the one live ownership source; the stale pull cache must not resurrect a match.\n\t\t\tconst summaryMatches = targetEntry?.workerId === worker.descriptor.workerId;\n\t\t\tconst descriptorPath = worker.descriptor.sessionFile\n\t\t\t\t? canonicalSessionPath(worker.descriptor.sessionFile)\n\t\t\t\t: undefined;\n\t\t\tconst configuredPath = worker.descriptor.createCommand.sessionPath\n\t\t\t\t? canonicalSessionPath(worker.descriptor.createCommand.sessionPath)\n\t\t\t\t: undefined;\n\t\t\tif (!summaryMatches && descriptorPath !== target && configuredPath !== target) continue;\n\t\t\tif (descriptorPath && configuredPath && descriptorPath !== configuredPath) {\n\t\t\t\tthrow new Error(`Conflicting resident session paths for worker ${worker.descriptor.workerId}`);\n\t\t\t}\n\t\t\tmatches.add(worker);\n\t\t}\n\t\tif (matches.size > 1) {\n\t\t\tthrow new Error(`Ambiguous resident session path \"${sessionFile}\"`);\n\t\t}\n\t\treturn matches.values().next().value;\n\t}\n\n\tprivate async forwardToWorker(\n\t\tworker: ResidentWorker,\n\t\tcommand: DaemonCommand,\n\t\ttimeoutMs = WORKER_REQUEST_TIMEOUT_MS,\n\t): Promise<DaemonResponse> {\n\t\tconst client = this.requireAvailableWorkerClient(worker, command.type === \"kill\");\n\t\tconst response = await client.request(withoutCommandId(command), timeoutMs);\n\t\tif (command.type === \"get_state\" && response.success && isSessionSummary(response.data)) {\n\t\t\treturn { ...response, id: command.id, data: this.publicSummary(worker, response.data) };\n\t\t}\n\t\tif (command.type === \"rename\" && response.success && isSessionSummary(response.data)) {\n\t\t\tthis.writeRosterEntry(workerRosterEntryFromSummary(response.data), worker);\n\t\t\treturn { ...response, id: command.id, data: this.publicSummary(worker, response.data) };\n\t\t}\n\t\treturn responseWithId(response, command.id);\n\t}\n\n\tprivate async attachClient(\n\t\tclient: DaemonSocketClient,\n\t\tcommand: Extract<DaemonCommand, { type: \"attach\" }>,\n\t): Promise<WorkerAttachData> {\n\t\tconst ownedWorker = [...this.workers.values()].find(\n\t\t\t(worker) =>\n\t\t\t\tworker.descriptor.ownerClientId !== undefined &&\n\t\t\t\t(worker.descriptor.rootActiveSessionId === command.activeSessionId ||\n\t\t\t\t\tworker.descriptor.rootSessionId === command.activeSessionId),\n\t\t);\n\t\tif (ownedWorker) {\n\t\t\tif (ownedWorker.descriptor.ownerClientId !== this.protocolClientId(client)) {\n\t\t\t\tthrow new Error(`Unknown active session: ${command.activeSessionId}`);\n\t\t\t}\n\t\t\tthis.assertTelemetryAttachAllowed(ownedWorker, command.telemetryDisabled);\n\t\t\townedWorker.launchEnv = command.launchEnv ?? ownedWorker.launchEnv;\n\t\t\tif (!ownedWorker.client || ownedWorker.descriptor.lifecycle !== \"ready\") {\n\t\t\t\tif (command.recoveryConfig) {\n\t\t\t\t\townedWorker.transientCreateCommand = {\n\t\t\t\t\t\t...ownedWorker.descriptor.createCommand,\n\t\t\t\t\t\tconfig: {\n\t\t\t\t\t\t\t...command.recoveryConfig,\n\t\t\t\t\t\t\t...(ownedWorker.descriptor.telemetryDisabled === true ? { telemetryDisabled: true } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tenv: command.env,\n\t\t\t\t\t\tlaunchEnv: command.launchEnv,\n\t\t\t\t\t\tlifecycle: \"client_owned\",\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (!ownedWorker.launchEnv) {\n\t\t\t\t\tthrow new Error(\"Client-owned session recovery requires the owning client environment\");\n\t\t\t\t}\n\t\t\t\townedWorker.intentionalStop = false;\n\t\t\t\townedWorker.descriptor.stopRequestedAt = undefined;\n\t\t\t\townedWorker.descriptor.archiveOnStop = undefined;\n\t\t\t\townedWorker.descriptor.lifecycle = \"recovering\";\n\t\t\t\townedWorker.descriptor.consecutiveFailures = 0;\n\t\t\t\townedWorker.deferredRecoveryRounds = 0;\n\t\t\t\tthis.persistWorker(ownedWorker);\n\t\t\t\tawait this.recoverWorker(ownedWorker);\n\t\t\t}\n\t\t}\n\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\tthis.assertTelemetryAttachAllowed(match.worker, command.telemetryDisabled);\n\t\tthis.requireAvailableWorkerClient(match.worker);\n\t\tconst activeSessionId = match.summary.activeSessionId ?? match.summary.id;\n\t\tconst duplicateValidation = this.currentSnapshotGeneration(match.worker, activeSessionId)?.validation;\n\t\tif (duplicateValidation) {\n\t\t\tawait duplicateValidation.promise;\n\t\t}\n\t\tif (command.clientId) {\n\t\t\tclient.id = command.clientId;\n\t\t}\n\t\tclient.capabilities = normalizeCapabilities(command.capabilities, command.supportsExtensionUi);\n\t\tclient.supportsExtensionUi = client.capabilities.has(\"extension_ui\");\n\n\t\tlet result = match.worker.snapshotCache.get(activeSessionId);\n\t\tif (\n\t\t\tresult &&\n\t\t\t!client.capabilities.has(\"chunked_snapshot\") &&\n\t\t\tresult.snapshot.messages.length < result.snapshot.summary.messageCount\n\t\t) {\n\t\t\tresult = undefined;\n\t\t}\n\t\tif (!result) {\n\t\t\tconst snapshotLoadKey = `${activeSessionId}:${client.capabilities.has(\"chunked_snapshot\") ? \"chunked\" : \"full\"}`;\n\t\t\tlet retryInvalidatedLoad = true;\n\t\t\twhile (!result) {\n\t\t\t\tlet loading = match.worker.snapshotLoads.get(snapshotLoadKey);\n\t\t\t\tif (!loading) {\n\t\t\t\t\tconst observedSnapshotId =\n\t\t\t\t\t\tmatch.worker.transcriptCaches.get(activeSessionId)?.snapshotId ??\n\t\t\t\t\t\tmatch.worker.snapshotCache.get(activeSessionId)?.snapshotStream?.id;\n\t\t\t\t\tloading = (async () => {\n\t\t\t\t\t\tconst workerClient = this.requireAvailableWorkerClient(match.worker);\n\t\t\t\t\t\tconst response = await workerClient.request({\n\t\t\t\t\t\t\ttype: \"attach\",\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tcapabilities: client.capabilities.has(\"chunked_snapshot\")\n\t\t\t\t\t\t\t\t? [\"attach_snapshot\", \"event_sequence\", \"slim_attach\", \"chunked_snapshot\"]\n\t\t\t\t\t\t\t\t: [\"attach_snapshot\", \"event_sequence\", \"slim_attach\"],\n\t\t\t\t\t\t\tsupportsExtensionUi: false,\n\t\t\t\t\t\t\tenv: command.env ?? collectDaemonClientEnv(),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst loaded = attachResultFromResponse(response);\n\t\t\t\t\t\tif (match.worker.snapshotLoads.get(snapshotLoadKey) !== loading) {\n\t\t\t\t\t\t\tthrow new SnapshotLoadInvalidatedError(\"Session snapshot changed during attach\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this.cacheLoadedSnapshot(match.worker, activeSessionId, loaded, observedSnapshotId);\n\t\t\t\t\t})();\n\t\t\t\t\tmatch.worker.snapshotLoads.set(snapshotLoadKey, loading);\n\t\t\t\t\tvoid loading.then(\n\t\t\t\t\t\tasync (loaded) => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst snapshotId = loaded.snapshotStream?.id;\n\t\t\t\t\t\t\t\tconst transcript = snapshotId\n\t\t\t\t\t\t\t\t\t? this.snapshotGeneration(match.worker, loaded.activeSessionId, snapshotId)?.transcript\n\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\t\tif (transcript && !transcript.complete) {\n\t\t\t\t\t\t\t\t\tlet chunkIndex = 0;\n\t\t\t\t\t\t\t\t\twhile (await transcript.waitForChunk(chunkIndex)) {\n\t\t\t\t\t\t\t\t\t\tchunkIndex++;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Failed transfers must allow a fresh snapshot request.\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tif (match.worker.snapshotLoads.get(snapshotLoadKey) === loading) {\n\t\t\t\t\t\t\t\t\tmatch.worker.snapshotLoads.delete(snapshotLoadKey);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\tif (match.worker.snapshotLoads.get(snapshotLoadKey) === loading) {\n\t\t\t\t\t\t\t\tmatch.worker.snapshotLoads.delete(snapshotLoadKey);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tresult = await loading;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!(error instanceof SnapshotLoadInvalidatedError)) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tif (!retryInvalidatedLoad) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tretryInvalidatedLoad = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.requireAvailableWorkerClient(match.worker);\n\t\tconst wasAttached = client.attachedActiveSessionIds.has(activeSessionId);\n\t\tlet transcript: SnapshotTranscriptCache | undefined;\n\t\tif (client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\twhile (true) {\n\t\t\t\tconst validation = this.currentSnapshotGeneration(match.worker, activeSessionId)?.validation;\n\t\t\t\tif (validation) {\n\t\t\t\t\tawait validation.promise;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tresult = match.worker.snapshotCache.get(activeSessionId) ?? result;\n\t\t\t\ttranscript = this.getOrCreateTranscriptCache(match.worker, result);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tconst releaseTranscript = transcript?.retain();\n\t\tclient.attachedActiveSessionIds.add(activeSessionId);\n\t\ttry {\n\t\t\tconst publicSummary = this.publicSummary(match.worker, result.snapshot.summary);\n\t\t\tif (publicSummary.streamingMessage?.role === \"assistant\") {\n\t\t\t\tthis.streamReconstructor.seed(activeSessionId, publicSummary.streamingMessage);\n\t\t\t} else {\n\t\t\t\tfor (let index = result.snapshot.messages.length - 1; index >= 0; index--) {\n\t\t\t\t\tconst latestMessage = result.snapshot.messages[index];\n\t\t\t\t\tif (latestMessage?.role === \"assistant\") {\n\t\t\t\t\t\tthis.streamReconstructor.seed(activeSessionId, latestMessage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst publicResult: DaemonAttachResult = {\n\t\t\t\t...result,\n\t\t\t\tstate: result.state ? publicSummary : undefined,\n\t\t\t\tsnapshot: { ...result.snapshot, summary: publicSummary },\n\t\t\t\tclient: { id: client.id, capabilities: [...client.capabilities] },\n\t\t\t};\n\t\t\tif (publicResult.state && publicResult.messages) {\n\t\t\t\tthis.write(client, {\n\t\t\t\t\ttype: \"session_attached\",\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tstate: publicResult.state,\n\t\t\t\t\tmessages: publicResult.messages,\n\t\t\t\t\tsnapshot: publicResult.snapshot,\n\t\t\t\t\treplay: publicResult.replay,\n\t\t\t\t\tlastEventSequence: publicResult.lastEventSequence,\n\t\t\t\t});\n\t\t\t}\n\t\t\tvoid this.syncWorkerExtensionUi(activeSessionId);\n\t\t\tconst detachingSessions = this.detachingInputPauseSessions?.get(client);\n\t\t\tdetachingSessions?.delete(command.activeSessionId);\n\t\t\tdetachingSessions?.delete(activeSessionId);\n\t\t\treturn { result: publicResult, worker: match.worker, transcript, releaseTranscript };\n\t\t} catch (error) {\n\t\t\treleaseTranscript?.();\n\t\t\tif (!wasAttached) {\n\t\t\t\tclient.attachedActiveSessionIds.delete(activeSessionId);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate assertTelemetryAttachAllowed(worker: ResidentWorker, telemetryDisabled: true | undefined): void {\n\t\tif (telemetryDisabled && worker.descriptor.telemetryDisabled !== true) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Cannot attach to this active agent while telemetry is disabled for the current invocation. Stop the agent and retry so it can restart without telemetry.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate cacheLoadedSnapshot(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\tloaded: DaemonAttachResult,\n\t\tobservedSnapshotId: string | undefined,\n\t): DaemonAttachResult {\n\t\tconst currentTranscript = worker.transcriptCaches.get(activeSessionId);\n\t\tconst currentGeneration = this.currentSnapshotGeneration(worker, activeSessionId);\n\t\tconst currentResult = currentGeneration?.result ?? worker.snapshotCache.get(activeSessionId);\n\t\tconst currentSnapshotId = currentTranscript?.snapshotId ?? currentResult?.snapshotStream?.id;\n\t\tconst loadedSnapshotId = loaded.snapshotStream?.id;\n\t\tif (!loaded.snapshotStream) {\n\t\t\tif (currentSnapshotId && currentSnapshotId !== observedSnapshotId) {\n\t\t\t\treturn loaded;\n\t\t\t}\n\t\t\tworker.snapshotCache.set(activeSessionId, loaded);\n\t\t\treturn loaded;\n\t\t}\n\t\tif (\n\t\t\tcurrentSnapshotId &&\n\t\t\tcurrentSnapshotId !== loadedSnapshotId &&\n\t\t\t(currentSnapshotId !== observedSnapshotId ||\n\t\t\t\t(currentResult?.lastEventSequence ?? -1) > loaded.lastEventSequence)\n\t\t) {\n\t\t\treturn currentResult ?? loaded;\n\t\t}\n\t\tlet transcript = currentTranscript;\n\t\tif (transcript && transcript.snapshotId !== loaded.snapshotStream.id) {\n\t\t\tthis.retireWorkerSnapshotCache(worker, activeSessionId, transcript);\n\t\t\ttranscript = undefined;\n\t\t}\n\t\tconst generations = this.snapshotGenerationsFor(worker, activeSessionId);\n\t\tlet generation = generations.get(loaded.snapshotStream.id);\n\t\tif (!transcript) {\n\t\t\ttranscript = generation?.transcript;\n\t\t}\n\t\tif (!transcript) {\n\t\t\ttranscript = new SnapshotTranscriptCache({\n\t\t\t\tactiveSessionId,\n\t\t\t\tsnapshotId: loaded.snapshotStream.id,\n\t\t\t\tcacheRoot: this.snapshotCacheRoot,\n\t\t\t\ttargetChunkBytes: loaded.snapshotStream.targetChunkBytes,\n\t\t\t});\n\t\t}\n\t\tif (!generation) {\n\t\t\tgeneration = {\n\t\t\t\ttranscript,\n\t\t\t\tresult: loaded,\n\t\t\t\tincoming: false,\n\t\t\t\tretired: false,\n\t\t\t};\n\t\t\tgenerations.set(loaded.snapshotStream.id, generation);\n\t\t} else {\n\t\t\tgeneration.result = loaded;\n\t\t\tgeneration.retired = false;\n\t\t}\n\t\tworker.transcriptCaches.set(activeSessionId, transcript);\n\t\tworker.snapshotCache.set(activeSessionId, loaded);\n\t\treturn loaded;\n\t}\n\n\tprivate getOrCreateTranscriptCache(worker: ResidentWorker, result: DaemonAttachResult): SnapshotTranscriptCache {\n\t\tconst activeSessionId = result.activeSessionId;\n\t\tconst existing = worker.transcriptCaches.get(activeSessionId);\n\t\tif (existing && (!result.snapshotStream || existing.snapshotId === result.snapshotStream.id)) {\n\t\t\treturn existing;\n\t\t}\n\t\tif (result.snapshot.messages.length < result.snapshot.summary.messageCount) {\n\t\t\tthrow new Error(\"Session snapshot generation changed before its transcript could be selected\");\n\t\t}\n\t\tif (existing) {\n\t\t\tthis.retireWorkerSnapshotCache(worker, activeSessionId, existing);\n\t\t}\n\t\tconst revision = createHash(\"sha256\")\n\t\t\t.update(\n\t\t\t\t`${activeSessionId}:${result.snapshot.summary.sessionId}:${result.lastEventSequence}:${result.snapshot.messages.length}`,\n\t\t\t)\n\t\t\t.digest(\"hex\")\n\t\t\t.slice(0, 16);\n\t\tconst transcript = new SnapshotTranscriptCache({\n\t\t\tactiveSessionId,\n\t\t\tsnapshotId: `${activeSessionId}-${revision}`,\n\t\t\tmessages: result.snapshot.messages,\n\t\t\tcacheRoot: this.snapshotCacheRoot,\n\t\t\ttargetChunkBytes: SNAPSHOT_TARGET_CHUNK_BYTES,\n\t\t});\n\t\tworker.transcriptCaches.set(activeSessionId, transcript);\n\t\tconst cachedResult = {\n\t\t\t...result,\n\t\t\tmessages: result.messages ? [] : undefined,\n\t\t\tsnapshot: { ...result.snapshot, messages: [] },\n\t\t};\n\t\tworker.snapshotCache.set(activeSessionId, cachedResult);\n\t\tthis.snapshotGenerationsFor(worker, activeSessionId).set(transcript.snapshotId, {\n\t\t\ttranscript,\n\t\t\tresult: cachedResult,\n\t\t\tincoming: false,\n\t\t\tretired: false,\n\t\t});\n\t\treturn transcript;\n\t}\n\n\tprivate createStreamedAttachResult(\n\t\tresult: DaemonAttachResult,\n\t\ttranscript: SnapshotTranscriptCache,\n\t): DaemonAttachResult {\n\t\treturn {\n\t\t\t...result,\n\t\t\tmessages: result.messages ? [] : undefined,\n\t\t\tsnapshot: { ...result.snapshot, messages: [] },\n\t\t\tsnapshotStream: {\n\t\t\t\tid: transcript.snapshotId,\n\t\t\t\tmessageCount: result.snapshot.summary.messageCount,\n\t\t\t\ttargetChunkBytes: transcript.targetChunkBytes,\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async streamSnapshot(\n\t\tclient: DaemonSocketClient,\n\t\tworker: ResidentWorker,\n\t\tresult: DaemonAttachResult,\n\t\ttranscript: SnapshotTranscriptCache,\n\t\tpurpose: \"attach\" | \"replacement\" | \"resync\" = \"attach\",\n\t\tretainedTranscriptRelease?: () => void,\n\t\treleaseSnapshotReservation = this.reserveSnapshotStream(client, result.activeSessionId),\n\t): Promise<void> {\n\t\tconst stream = result.snapshotStream;\n\t\tconst releaseTranscript = retainedTranscriptRelease ?? transcript.retain();\n\t\tif (!stream || client.socket.destroyed) {\n\t\t\treleaseSnapshotReservation();\n\t\t\treleaseTranscript();\n\t\t\treturn;\n\t\t}\n\t\tconst { messages: _messages, ...snapshotHeader } = result.snapshot;\n\t\ttry {\n\t\t\tif (\n\t\t\t\t!(await this.writeSnapshotRecord(client, {\n\t\t\t\t\ttype: \"session_snapshot_begin\",\n\t\t\t\t\tactiveSessionId: result.activeSessionId,\n\t\t\t\t\tsnapshotId: stream.id,\n\t\t\t\t\tsnapshot: snapshotHeader,\n\t\t\t\t\tmessageCount: stream.messageCount,\n\t\t\t\t\ttargetChunkBytes: stream.targetChunkBytes,\n\t\t\t\t\tpurpose,\n\t\t\t\t}))\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet chunkCount = 0;\n\t\t\twhile (true) {\n\t\t\t\tlet chunk: Buffer | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tchunk = await transcript.waitForChunk(chunkCount);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst streamError = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\tthis.failWorkerSnapshotCache(worker, result.activeSessionId, streamError, false, stream.id);\n\t\t\t\t\tthrow streamError;\n\t\t\t\t}\n\t\t\t\tif (!chunk) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!(await this.writeSnapshotBuffer(client, chunk))) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tchunkCount++;\n\t\t\t}\n\t\t\tawait this.writeSnapshotRecord(client, {\n\t\t\t\ttype: \"session_snapshot_end\",\n\t\t\t\tactiveSessionId: result.activeSessionId,\n\t\t\t\tsnapshotId: stream.id,\n\t\t\t\tchunkCount,\n\t\t\t\tlastEventSequence: result.lastEventSequence,\n\t\t\t\tlastEventCursor: result.lastEventCursor,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst streamError = error instanceof Error ? error : new Error(String(error));\n\t\t\tif (!client.socket.destroyed) {\n\t\t\t\ttry {\n\t\t\t\t\tconst delivered = await this.writeSnapshotRecord(client, {\n\t\t\t\t\t\ttype: \"session_snapshot_failed\",\n\t\t\t\t\t\tactiveSessionId: result.activeSessionId,\n\t\t\t\t\t\tsnapshotId: stream.id,\n\t\t\t\t\t\terror: streamError.message,\n\t\t\t\t\t});\n\t\t\t\t\tif (!delivered && !client.socket.destroyed) {\n\t\t\t\t\t\tclient.socket.destroy(streamError);\n\t\t\t\t\t}\n\t\t\t\t} catch (deliveryError) {\n\t\t\t\t\tclient.socket.destroy(deliveryError instanceof Error ? deliveryError : new Error(String(deliveryError)));\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow streamError;\n\t\t} finally {\n\t\t\treleaseSnapshotReservation();\n\t\t\treleaseTranscript();\n\t\t}\n\t}\n\n\tprivate reserveSnapshotStream(client: DaemonSocketClient, activeSessionId: string): () => void {\n\t\tclient.snapshotStreaming = true;\n\t\tclient.snapshotActiveSessionIds ??= new Set();\n\t\tclient.snapshotActiveSessionIds.add(activeSessionId);\n\t\tclient.snapshotActiveSessionCounts ??= new Map();\n\t\tclient.snapshotActiveSessionCounts.set(\n\t\t\tactiveSessionId,\n\t\t\t(client.snapshotActiveSessionCounts.get(activeSessionId) ?? 0) + 1,\n\t\t);\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treleased = true;\n\t\t\tconst streamCount = client.snapshotActiveSessionCounts?.get(activeSessionId) ?? 1;\n\t\t\tif (streamCount > 1) {\n\t\t\t\tclient.snapshotActiveSessionCounts?.set(activeSessionId, streamCount - 1);\n\t\t\t} else {\n\t\t\t\tclient.snapshotActiveSessionCounts?.delete(activeSessionId);\n\t\t\t\tclient.snapshotActiveSessionIds?.delete(activeSessionId);\n\t\t\t}\n\t\t\tclient.snapshotStreaming = (client.snapshotActiveSessionIds?.size ?? 0) > 0;\n\t\t\tif (!client.snapshotStreaming) {\n\t\t\t\tclient.backpressured = false;\n\t\t\t}\n\t\t\tif (!client.snapshotStreaming && client.catchupActiveSessionIds?.size) {\n\t\t\t\tvoid this.catchUpClient(client).catch((error) =>\n\t\t\t\t\tthis.log(`Failed to catch up client ${client.id}: ${String(error)}`),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate writeSnapshotRecord(client: DaemonSocketClient, message: DaemonOutbound): Promise<boolean> {\n\t\treturn this.writeSnapshotBuffer(client, Buffer.from(serializeJsonLine(message)));\n\t}\n\n\tprivate async writeSnapshotBuffer(client: DaemonSocketClient, buffer: Uint8Array): Promise<boolean> {\n\t\tif (client.socket.destroyed) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.writeSerialized(client, buffer)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn new Promise<boolean>((resolveDrain) => {\n\t\t\tlet settled = false;\n\t\t\tconst finish = (value: boolean) => {\n\t\t\t\tif (settled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsettled = true;\n\t\t\t\tclient.socket.off(\"drain\", onDrain);\n\t\t\t\tclient.socket.off(\"close\", onClose);\n\t\t\t\tclient.socket.off(\"error\", onClose);\n\t\t\t\tresolveDrain(value);\n\t\t\t};\n\t\t\tconst onDrain = () => finish(true);\n\t\t\tconst onClose = () => finish(false);\n\t\t\tclient.socket.once(\"drain\", onDrain);\n\t\t\tclient.socket.once(\"close\", onClose);\n\t\t\tclient.socket.once(\"error\", onClose);\n\t\t});\n\t}\n\n\tprivate detachClient(client: DaemonSocketClient, activeSessionId?: string): void {\n\t\tconst targets = activeSessionId ? [activeSessionId] : [...client.attachedActiveSessionIds];\n\t\tfor (const selector of targets) {\n\t\t\tconst match = this.matchWorkers(selector)[0];\n\t\t\tconst resolvedId = match ? (match.summary.activeSessionId ?? match.summary.id) : selector;\n\t\t\tif (!client.attachedActiveSessionIds.delete(resolvedId)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tclient.catchupActiveSessionIds?.delete(resolvedId);\n\t\t\tclient.catchupPurposes?.delete(resolvedId);\n\t\t\tthis.write(client, { type: \"session_detached\", activeSessionId: resolvedId });\n\t\t\tvoid this.syncWorkerExtensionUi(resolvedId);\n\t\t\tvoid this.evictEmptySessionOnLastDetach(resolvedId);\n\t\t}\n\t}\n\n\tprivate async syncWorkerExtensionUi(activeSessionId: string): Promise<void> {\n\t\tconst match = this.matchWorkers(activeSessionId)[0];\n\t\tif (!match?.worker.client) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.subscribeWorker(match.worker, match.summary.activeSessionId ?? match.summary.id).catch(\n\t\t\t() => undefined,\n\t\t);\n\t}\n\n\tprivate handleWorkerFrame(\n\t\tworker: ResidentWorker,\n\t\tframe: PrivateFrame<DaemonWorkerFrameHeader>,\n\t\tsource?: DaemonWorkerClient,\n\t): void {\n\t\tif (frame.header.kind !== \"outbound\") {\n\t\t\treturn;\n\t\t}\n\t\tif (source !== undefined && source !== worker.client && source !== worker.pendingClient) {\n\t\t\treturn;\n\t\t}\n\t\tworker.lastFrameAt = Date.now();\n\t\tthis.clearRosterStaleness(worker);\n\t\tconst {\n\t\t\toutboundType,\n\t\t\tactiveSessionId,\n\t\t\tsnapshotId: frameSnapshotId,\n\t\t\tsessionEventType,\n\t\t\tpayloadEncoding,\n\t\t\tsnapshotPurpose,\n\t\t} = frame.header;\n\t\tif (outboundType === \"roster_delta\") {\n\t\t\tthis.consumeWorkerRosterDelta(worker, frame.payload, source);\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"roster_heartbeat\") {\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"heartbeats_changed\") {\n\t\t\tworker.heartbeatSnapshotStale = true;\n\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"session_snapshot_begin\" && activeSessionId) {\n\t\t\ttry {\n\t\t\t\tconst begin = JSON.parse(frame.payload.toString(\"utf8\")) as Extract<\n\t\t\t\t\tDaemonOutbound,\n\t\t\t\t\t{ type: \"session_snapshot_begin\" }\n\t\t\t\t>;\n\t\t\t\tif (\n\t\t\t\t\tbegin.type !== \"session_snapshot_begin\" ||\n\t\t\t\t\tbegin.activeSessionId !== activeSessionId ||\n\t\t\t\t\ttypeof begin.snapshotId !== \"string\" ||\n\t\t\t\t\t(frameSnapshotId !== undefined && frameSnapshotId !== begin.snapshotId) ||\n\t\t\t\t\ttypeof begin.targetChunkBytes !== \"number\" ||\n\t\t\t\t\t!begin.snapshot ||\n\t\t\t\t\t!isSessionSummary(begin.snapshot.summary)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Worker returned an invalid snapshot begin frame\");\n\t\t\t\t}\n\t\t\t\tconst publicSummary = this.publicSummary(worker, begin.snapshot.summary);\n\t\t\t\tconst snapshot = {\n\t\t\t\t\t...begin.snapshot,\n\t\t\t\t\tsummary: publicSummary,\n\t\t\t\t\tmessages: [],\n\t\t\t\t};\n\t\t\t\tconst result: DaemonAttachResult = {\n\t\t\t\t\tprotocol: DAEMON_PROTOCOL_INFO,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tsnapshot,\n\t\t\t\t\treplay: {\n\t\t\t\t\t\tstatus: \"complete\",\n\t\t\t\t\t\ttoSequence: snapshot.lastEventSequence,\n\t\t\t\t\t\t...(snapshot.lastEventCursor ? { toCursor: snapshot.lastEventCursor } : {}),\n\t\t\t\t\t},\n\t\t\t\t\tlastEventSequence: snapshot.lastEventSequence,\n\t\t\t\t\t...(snapshot.lastEventCursor ? { lastEventCursor: snapshot.lastEventCursor } : {}),\n\t\t\t\t\tsnapshotStream: {\n\t\t\t\t\t\tid: begin.snapshotId,\n\t\t\t\t\t\tmessageCount: begin.messageCount,\n\t\t\t\t\t\ttargetChunkBytes: begin.targetChunkBytes,\n\t\t\t\t\t},\n\t\t\t\t\tclient: { id: \"supervisor\", capabilities: [\"chunked_snapshot\"] },\n\t\t\t\t};\n\t\t\t\tconst generations = this.snapshotGenerationsFor(worker, activeSessionId);\n\t\t\t\tlet generation = generations.get(begin.snapshotId);\n\t\t\t\tif (generation?.incoming) {\n\t\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\t\tworker,\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tnew Error(`Snapshot ${begin.snapshotId} restarted before completion`),\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tbegin.snapshotId,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Snapshot summaries/state include live fields (for example activity and attached client\n\t\t\t\t// counts) that can change without advancing the transcript sequence. Treat the stable\n\t\t\t\t// transfer envelope as identity; duplicate chunks and end metadata are still byte-checked.\n\t\t\t\tconst duplicate =\n\t\t\t\t\tgeneration?.transcript.complete === true &&\n\t\t\t\t\tgeneration.end !== undefined &&\n\t\t\t\t\tgeneration.result.snapshotStream?.messageCount === begin.messageCount &&\n\t\t\t\t\tgeneration.result.snapshotStream?.targetChunkBytes === begin.targetChunkBytes &&\n\t\t\t\t\tgeneration.result.lastEventSequence === result.lastEventSequence &&\n\t\t\t\t\tgeneration.result.snapshot.lastEventSequence === result.snapshot.lastEventSequence &&\n\t\t\t\t\tgeneration.result.snapshot.lastEventCursor?.generation === result.snapshot.lastEventCursor?.generation &&\n\t\t\t\t\tgeneration.result.snapshot.lastEventCursor?.sequence === result.snapshot.lastEventCursor?.sequence;\n\t\t\t\tif (generation?.transcript.complete && !duplicate) {\n\t\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\t\tworker,\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tnew Error(`Snapshot ${begin.snapshotId} did not match the cached transfer`),\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tbegin.snapshotId,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst currentGeneration = this.currentSnapshotGeneration(worker, activeSessionId);\n\t\t\t\tconst currentResult = currentGeneration?.result ?? worker.snapshotCache.get(activeSessionId);\n\t\t\t\tconst isOlderThanCurrent =\n\t\t\t\t\tcurrentGeneration !== undefined &&\n\t\t\t\t\tcurrentGeneration.transcript.snapshotId !== begin.snapshotId &&\n\t\t\t\t\tcurrentResult !== undefined &&\n\t\t\t\t\tresult.lastEventSequence < currentResult.lastEventSequence;\n\t\t\t\tif (isOlderThanCurrent && !generation) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (duplicate && generation) {\n\t\t\t\t\tgeneration.incoming = true;\n\t\t\t\t\tgeneration.duplicateChunkIndex = 0;\n\t\t\t\t\tgeneration.duplicateResult = result;\n\t\t\t\t\tgeneration.validation = this.createSnapshotDuplicateValidation();\n\t\t\t\t\tif (currentGeneration === generation) {\n\t\t\t\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tcurrentGeneration &&\n\t\t\t\t\tcurrentGeneration.transcript.snapshotId !== begin.snapshotId &&\n\t\t\t\t\t!isOlderThanCurrent\n\t\t\t\t) {\n\t\t\t\t\tif (!currentGeneration.transcript.complete && !currentGeneration.incoming) {\n\t\t\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tnew Error(`Snapshot ${currentGeneration.transcript.snapshotId} was superseded`),\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tcurrentGeneration.transcript.snapshotId,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.retireWorkerSnapshotCache(worker, activeSessionId, currentGeneration.transcript);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!generation) {\n\t\t\t\t\tconst transcript = new SnapshotTranscriptCache({\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tsnapshotId: begin.snapshotId,\n\t\t\t\t\t\tcacheRoot: this.snapshotCacheRoot,\n\t\t\t\t\t\ttargetChunkBytes: begin.targetChunkBytes,\n\t\t\t\t\t});\n\t\t\t\t\tgeneration = {\n\t\t\t\t\t\ttranscript,\n\t\t\t\t\t\tresult,\n\t\t\t\t\t\tincoming: false,\n\t\t\t\t\t\tretired: isOlderThanCurrent,\n\t\t\t\t\t};\n\t\t\t\t\tthis.snapshotGenerationsFor(worker, activeSessionId).set(begin.snapshotId, generation);\n\t\t\t\t}\n\t\t\t\tgeneration.result = result;\n\t\t\t\tgeneration.begin = Buffer.from(frame.payload);\n\t\t\t\tgeneration.end = undefined;\n\t\t\t\tgeneration.incoming = true;\n\t\t\t\tgeneration.duplicateChunkIndex = undefined;\n\t\t\t\tgeneration.duplicateResult = undefined;\n\t\t\t\tgeneration.validation = undefined;\n\t\t\t\tif (!isOlderThanCurrent) {\n\t\t\t\t\tgeneration.retired = false;\n\t\t\t\t\tworker.transcriptCaches.set(activeSessionId, generation.transcript);\n\t\t\t\t\tworker.snapshotCache.set(activeSessionId, result);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Invalid worker snapshot begin frame: ${String(error)}`);\n\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\tworker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"session_snapshot_chunk\" && activeSessionId) {\n\t\t\tconst snapshotId = frameSnapshotId ?? worker.transcriptCaches.get(activeSessionId)?.snapshotId;\n\t\t\tif (!snapshotId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst generation = this.snapshotGeneration(worker, activeSessionId, snapshotId);\n\t\t\tif (generation?.incoming) {\n\t\t\t\ttry {\n\t\t\t\t\tconst duplicateIndex = generation.duplicateChunkIndex;\n\t\t\t\t\tif (duplicateIndex === undefined) {\n\t\t\t\t\t\tgeneration.transcript.appendEncodedChunk(Buffer.from(frame.payload));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst chunk = JSON.parse(frame.payload.toString(\"utf8\")) as Extract<\n\t\t\t\t\t\t\tDaemonOutbound,\n\t\t\t\t\t\t\t{ type: \"session_snapshot_chunk\" }\n\t\t\t\t\t\t>;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tchunk.type !== \"session_snapshot_chunk\" ||\n\t\t\t\t\t\t\tchunk.activeSessionId !== activeSessionId ||\n\t\t\t\t\t\t\tchunk.snapshotId !== generation.transcript.snapshotId ||\n\t\t\t\t\t\t\tchunk.index !== duplicateIndex ||\n\t\t\t\t\t\t\t!generation.transcript.readChunk(duplicateIndex).equals(Buffer.from(frame.payload))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Duplicate snapshot ${generation.transcript.snapshotId} did not match cached bytes`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgeneration.duplicateChunkIndex = duplicateIndex + 1;\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\t\tworker,\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tgeneration.transcript.snapshotId,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"session_snapshot_end\" && activeSessionId) {\n\t\t\tconst snapshotId = frameSnapshotId ?? worker.transcriptCaches.get(activeSessionId)?.snapshotId;\n\t\t\tif (!snapshotId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst generation = this.snapshotGeneration(worker, activeSessionId, snapshotId);\n\t\t\tif (!generation?.incoming) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst transcript = generation.transcript;\n\t\t\ttry {\n\t\t\t\tconst duplicateChunkCount = generation.duplicateChunkIndex;\n\t\t\t\tif (duplicateChunkCount === undefined) {\n\t\t\t\t\ttranscript.markComplete();\n\t\t\t\t\tif (!generation.begin) {\n\t\t\t\t\t\tthrow new Error(`Snapshot ${transcript.snapshotId} has no begin frame`);\n\t\t\t\t\t}\n\t\t\t\t\tgeneration.end = Buffer.from(frame.payload);\n\t\t\t\t} else {\n\t\t\t\t\tconst end = JSON.parse(frame.payload.toString(\"utf8\")) as Extract<\n\t\t\t\t\t\tDaemonOutbound,\n\t\t\t\t\t\t{ type: \"session_snapshot_end\" }\n\t\t\t\t\t>;\n\t\t\t\t\tif (\n\t\t\t\t\t\tend.type !== \"session_snapshot_end\" ||\n\t\t\t\t\t\tend.activeSessionId !== activeSessionId ||\n\t\t\t\t\t\tend.snapshotId !== transcript.snapshotId ||\n\t\t\t\t\t\tend.chunkCount !== duplicateChunkCount ||\n\t\t\t\t\t\tend.chunkCount !== transcript.chunkCount ||\n\t\t\t\t\t\t!generation.end?.equals(frame.payload)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new Error(`Duplicate snapshot ${transcript.snapshotId} ended with different metadata`);\n\t\t\t\t\t}\n\t\t\t\t\tif (!generation.duplicateResult) {\n\t\t\t\t\t\tthrow new Error(`Duplicate snapshot ${transcript.snapshotId} has no result`);\n\t\t\t\t\t}\n\t\t\t\t\tgeneration.result = generation.duplicateResult;\n\t\t\t\t\tif (worker.transcriptCaches.get(activeSessionId) === transcript) {\n\t\t\t\t\t\tworker.snapshotCache.set(activeSessionId, generation.duplicateResult);\n\t\t\t\t\t}\n\t\t\t\t\tthis.settleSnapshotDuplicateValidation(generation);\n\t\t\t\t}\n\t\t\t\tgeneration.incoming = false;\n\t\t\t\tgeneration.duplicateChunkIndex = undefined;\n\t\t\t\tgeneration.duplicateResult = undefined;\n\t\t\t} catch (error) {\n\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\tworker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\ttrue,\n\t\t\t\t\ttranscript.snapshotId,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst published = worker.transcriptCaches.get(activeSessionId) === transcript;\n\t\t\tif (generation.retired) {\n\t\t\t\tthis.deleteSnapshotGeneration(worker, activeSessionId, generation);\n\t\t\t\ttranscript.dispose();\n\t\t\t}\n\t\t\tif (published && (snapshotPurpose === \"replacement\" || snapshotPurpose === \"catchup\")) {\n\t\t\t\tfor (const client of this.clients) {\n\t\t\t\t\tif (!client.attachedActiveSessionIds.has(activeSessionId)) continue;\n\t\t\t\t\tthis.queueCatchup(client, activeSessionId, snapshotPurpose === \"replacement\" ? \"replacement\" : \"resync\");\n\t\t\t\t\tvoid this.catchUpClient(client).catch((error) =>\n\t\t\t\t\t\tthis.log(`Failed to catch up client ${client.id}: ${String(error)}`),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"session_snapshot_failed\" && activeSessionId) {\n\t\t\ttry {\n\t\t\t\tconst failed = JSON.parse(frame.payload.toString(\"utf8\")) as Extract<\n\t\t\t\t\tDaemonOutbound,\n\t\t\t\t\t{ type: \"session_snapshot_failed\" }\n\t\t\t\t>;\n\t\t\t\tif (\n\t\t\t\t\tfailed.type !== \"session_snapshot_failed\" ||\n\t\t\t\t\tfailed.activeSessionId !== activeSessionId ||\n\t\t\t\t\ttypeof failed.snapshotId !== \"string\" ||\n\t\t\t\t\ttypeof failed.error !== \"string\" ||\n\t\t\t\t\t(frameSnapshotId !== undefined && frameSnapshotId !== failed.snapshotId)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Worker returned an invalid snapshot failure frame\");\n\t\t\t\t}\n\t\t\t\tconst currentGeneration = this.currentSnapshotGeneration(worker, activeSessionId);\n\t\t\t\tconst generation =\n\t\t\t\t\tthis.snapshotGeneration(worker, activeSessionId, failed.snapshotId) ??\n\t\t\t\t\t(currentGeneration?.transcript.snapshotId === failed.snapshotId ? currentGeneration : undefined);\n\t\t\t\tif (!generation) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst published = worker.transcriptCaches.get(activeSessionId) === generation.transcript;\n\t\t\t\tthis.failWorkerSnapshotCache(worker, activeSessionId, new Error(failed.error), false, failed.snapshotId);\n\t\t\t\tif (published && (snapshotPurpose === \"replacement\" || snapshotPurpose === \"catchup\")) {\n\t\t\t\t\tfor (const client of this.clients) {\n\t\t\t\t\t\tif (!client.attachedActiveSessionIds.has(activeSessionId)) continue;\n\t\t\t\t\t\tthis.queueCatchup(\n\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tsnapshotPurpose === \"replacement\" ? \"replacement\" : \"resync\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tvoid this.catchUpClient(client).catch((error) =>\n\t\t\t\t\t\t\tthis.log(`Failed to catch up client ${client.id}: ${String(error)}`),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\tworker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (\n\t\t\toutboundType === \"daemon_hello\" ||\n\t\t\toutboundType === \"response\" ||\n\t\t\toutboundType === \"session_list_progress\" ||\n\t\t\toutboundType === \"session_list_item\" ||\n\t\t\toutboundType === \"session_attached\" ||\n\t\t\toutboundType === \"session_detached\" ||\n\t\t\t!activeSessionId\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tlet publicPayload = frame.payload;\n\t\tlet decodedOutbound: DaemonOutbound | undefined;\n\t\tif (payloadEncoding === \"assistant-delta\") {\n\t\t\tlet compactValue: unknown;\n\t\t\ttry {\n\t\t\t\tcompactValue = JSON.parse(frame.payload.toString(\"utf8\"));\n\t\t\t} catch {\n\t\t\t\tthis.scheduleCompactCatchup(worker, activeSessionId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!isCompactAssistantDelta(compactValue)) {\n\t\t\t\tthis.scheduleCompactCatchup(worker, activeSessionId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst reconstructed = this.streamReconstructor.reconstruct(compactValue);\n\t\t\tif (!reconstructed) {\n\t\t\t\tthis.scheduleCompactCatchup(worker, activeSessionId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpublicPayload = Buffer.from(serializeJsonLine(reconstructed));\n\t\t} else if (\n\t\t\tsessionEventType === \"message_start\" ||\n\t\t\tsessionEventType === \"message_end\" ||\n\t\t\toutboundType === \"session_replaced\" ||\n\t\t\toutboundType === \"session_resynced\" ||\n\t\t\toutboundType === \"session_closed\"\n\t\t) {\n\t\t\ttry {\n\t\t\t\tdecodedOutbound = JSON.parse(frame.payload.toString(\"utf8\")) as DaemonOutbound;\n\t\t\t\tthis.streamReconstructor.observe(decodedOutbound);\n\t\t\t} catch {\n\t\t\t\t// A malformed worker event is still isolated to this worker connection.\n\t\t\t}\n\t\t}\n\t\tconst replacementSnapshotFollows =\n\t\t\tdecodedOutbound?.type === \"session_replaced\" && decodedOutbound.snapshotFollows === true;\n\t\tthis.invalidateWorkerSnapshot(\n\t\t\tworker,\n\t\t\tactiveSessionId,\n\t\t\toutboundType === \"session_replaced\" ||\n\t\t\t\toutboundType === \"session_closed\" ||\n\t\t\t\tisFinalizedTranscriptEvent(sessionEventType),\n\t\t);\n\t\tfor (const client of this.clients) {\n\t\t\tif (!client.attachedActiveSessionIds.has(activeSessionId)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (replacementSnapshotFollows && !client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (outboundType === \"extension_ui_request\" && !client.supportsExtensionUi) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (client.snapshotActiveSessionIds?.has(activeSessionId)) {\n\t\t\t\tthis.queueCatchup(client, activeSessionId, outboundType === \"session_replaced\" ? \"replacement\" : \"resync\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (client.backpressured === true) {\n\t\t\t\tthis.queueCatchup(client, activeSessionId, outboundType === \"session_replaced\" ? \"replacement\" : \"resync\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.writeSerialized(client, publicPayload);\n\t\t}\n\t\tif (\n\t\t\tdecodedOutbound?.type === \"session_closed\" &&\n\t\t\tdecodedOutbound.reason === \"shutdown\" &&\n\t\t\tactiveSessionId === worker.descriptor.rootActiveSessionId &&\n\t\t\t!this.shuttingDown\n\t\t) {\n\t\t\tworker.intentionalStop = true;\n\t\t\t// An exact stop owns its registration and descriptor cleanup until its\n\t\t\t// tuple assertions complete. A synchronous root shutdown event can arrive\n\t\t\t// before its request resolves, so leave both intact while it is active.\n\t\t\tif ((this.workerStopCounts?.get(worker) ?? 0) === 0) {\n\t\t\t\tthis.invalidateWorkerSessionInputPauses(worker, \"Session worker stopped while input was paused\");\n\t\t\t\tthis.workers.delete(worker.descriptor.workerId);\n\t\t\t\tthis.flipWorkerRosterEntriesInactive(worker);\n\t\t\t\tthis.deleteWorkerDescriptor(worker);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate invalidateWorkerSnapshot(worker: ResidentWorker, activeSessionId: string, transcriptChanged = true): void {\n\t\tworker.snapshotCache.delete(activeSessionId);\n\t\tif (!transcriptChanged) {\n\t\t\treturn;\n\t\t}\n\t\tworker.snapshotLoads.delete(`${activeSessionId}:chunked`);\n\t\tworker.snapshotLoads.delete(`${activeSessionId}:full`);\n\t\tconst transcript = worker.transcriptCaches.get(activeSessionId);\n\t\tif (transcript) {\n\t\t\tthis.retireWorkerSnapshotCache(worker, activeSessionId, transcript);\n\t\t}\n\t}\n\n\tprivate scheduleCompactCatchup(worker: ResidentWorker, activeSessionId: string): void {\n\t\tif (this.compactCatchupInProgress.has(activeSessionId)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.compactCatchupInProgress.add(activeSessionId);\n\t\tthis.invalidateWorkerSnapshot(worker, activeSessionId);\n\t\tconst clients = [...this.clients].filter((client) => client.attachedActiveSessionIds.has(activeSessionId));\n\t\tfor (const client of clients) {\n\t\t\tthis.queueCatchup(client, activeSessionId);\n\t\t}\n\t\tvoid Promise.all(clients.map((client) => this.catchUpClient(client)))\n\t\t\t.catch((error) => this.log(`Failed compact catch-up for ${activeSessionId}: ${String(error)}`))\n\t\t\t.finally(() => {\n\t\t\t\tthis.compactCatchupInProgress.delete(activeSessionId);\n\t\t\t});\n\t}\n\n\tprivate queueCatchup(\n\t\tclient: DaemonSocketClient,\n\t\tactiveSessionId: string,\n\t\tpurpose: \"replacement\" | \"resync\" = \"resync\",\n\t): void {\n\t\tif (!client.catchupActiveSessionIds) {\n\t\t\tclient.catchupActiveSessionIds = new Set();\n\t\t}\n\t\tclient.catchupActiveSessionIds.add(activeSessionId);\n\t\tclient.catchupPurposes ??= new Map();\n\t\tif (purpose === \"replacement\" || !client.catchupPurposes.has(activeSessionId)) {\n\t\t\tclient.catchupPurposes.set(activeSessionId, purpose);\n\t\t}\n\t}\n\n\tprivate catchUpClient(client: DaemonSocketClient): Promise<void> {\n\t\tif (client.catchupPromise) {\n\t\t\treturn client.catchupPromise;\n\t\t}\n\t\tif (client.snapshotStreaming || client.backpressured) {\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tconst catchup = this.drainClientCatchupQueue(client).finally(() => {\n\t\t\tif (client.catchupPromise === catchup) {\n\t\t\t\tclient.catchupPromise = undefined;\n\t\t\t}\n\t\t});\n\t\tclient.catchupPromise = catchup;\n\t\treturn catchup;\n\t}\n\n\tprivate async drainClientCatchupQueue(client: DaemonSocketClient): Promise<void> {\n\t\twhile (\n\t\t\t!client.socket.destroyed &&\n\t\t\t!client.snapshotStreaming &&\n\t\t\t!client.backpressured &&\n\t\t\tclient.catchupActiveSessionIds?.size\n\t\t) {\n\t\t\tawait this.drainClientCatchups(client);\n\t\t}\n\t}\n\n\tprivate async drainClientCatchups(client: DaemonSocketClient): Promise<void> {\n\t\tif (client.socket.destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst pending = [...(client.catchupActiveSessionIds ?? [])].map((activeSessionId) => ({\n\t\t\tactiveSessionId,\n\t\t\tpurpose: client.catchupPurposes?.get(activeSessionId) ?? (\"resync\" as const),\n\t\t}));\n\t\tclient.catchupActiveSessionIds?.clear();\n\t\tclient.catchupPurposes?.clear();\n\t\tfor (let index = 0; index < pending.length; index++) {\n\t\t\tconst { activeSessionId, purpose } = pending[index]!;\n\t\t\tlet releaseTranscript: (() => void) | undefined;\n\t\t\ttry {\n\t\t\t\tconst attached = await this.attachClient(client, {\n\t\t\t\t\ttype: \"attach\",\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tcapabilities: [...client.capabilities],\n\t\t\t\t\tsupportsExtensionUi: client.supportsExtensionUi,\n\t\t\t\t});\n\t\t\t\treleaseTranscript = attached.releaseTranscript;\n\t\t\t\tif (client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\t\t\tconst transcript = attached.transcript;\n\t\t\t\t\tif (!transcript) {\n\t\t\t\t\t\tthrow new Error(\"Session worker did not provide a snapshot transcript\");\n\t\t\t\t\t}\n\t\t\t\t\tif (purpose === \"replacement\") {\n\t\t\t\t\t\tthis.write(client, {\n\t\t\t\t\t\t\ttype: \"session_replaced\",\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tstate: attached.result.snapshot.state,\n\t\t\t\t\t\t\tmessages: [],\n\t\t\t\t\t\t\tsnapshotFollows: true,\n\t\t\t\t\t\t\tmeta: createDaemonEventMeta(\n\t\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\t\tattached.result.lastEventSequence,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tattached.result.lastEventCursor?.generation,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tawait this.streamSnapshot(\n\t\t\t\t\t\tclient,\n\t\t\t\t\t\tattached.worker,\n\t\t\t\t\t\tthis.createStreamedAttachResult(attached.result, transcript),\n\t\t\t\t\t\ttranscript,\n\t\t\t\t\t\tpurpose,\n\t\t\t\t\t\treleaseTranscript,\n\t\t\t\t\t);\n\t\t\t\t\treleaseTranscript = undefined;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst meta = createDaemonEventMeta(\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tattached.result.lastEventSequence,\n\t\t\t\t\tundefined,\n\t\t\t\t\tattached.result.lastEventCursor?.generation,\n\t\t\t\t);\n\t\t\t\tconst catchup: DaemonOutbound =\n\t\t\t\t\tpurpose === \"replacement\"\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttype: \"session_replaced\",\n\t\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\t\tstate: attached.result.snapshot.state,\n\t\t\t\t\t\t\t\tmessages: attached.result.snapshot.messages,\n\t\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\ttype: \"session_resynced\",\n\t\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\t\tsnapshot: attached.result.snapshot,\n\t\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\t};\n\t\t\t\tif (!this.write(client, catchup)) {\n\t\t\t\t\tfor (const remaining of pending.slice(index + 1)) {\n\t\t\t\t\t\tthis.queueCatchup(client, remaining.activeSessionId, remaining.purpose);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\treleaseTranscript?.();\n\t\t\t\tthis.log(`Failed to catch up client ${client.id} for ${activeSessionId}: ${String(error)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async prepareUpdateRestart(): Promise<DaemonUpdateRestartManifest> {\n\t\tif (this.updateRestartPhase !== undefined) throw new Error(\"Daemon is already preparing an update restart\");\n\t\tthis.updateRestartPhase = \"draining\";\n\t\ttry {\n\t\t\tconst deadline = Date.now() + UPDATE_RESTART_PREPARE_DEADLINE_MS;\n\t\t\tconst abort = AbortSignal.timeout(Math.min(UPDATE_RESTART_MUTATION_DRAIN_TIMEOUT_MS, deadline - Date.now()));\n\t\t\tawait this.mutationDrain.waitForDrain(1, abort, \"Timed out draining daemon mutations for update restart\");\n\t\t\tthis.updateRestartPhase = \"fencing\";\n\t\t\tawait this.mutationDrain.waitForDrain(1, abort, \"Timed out draining daemon mutations for update restart\");\n\t\t\tconst manifest = await this.prepareUpdateRestartFenced(deadline);\n\t\t\tthis.updateRestartPhase = \"prepared\";\n\t\t\treturn manifest;\n\t\t} catch (error) {\n\t\t\tthis.updateRestartPhase = undefined;\n\t\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async prepareUpdateRestartFenced(deadline: number): Promise<DaemonUpdateRestartManifest> {\n\t\tconst residents = [...this.workers.values()];\n\t\tconst unavailable = residents.find(\n\t\t\t(worker) =>\n\t\t\t\tthis.isWorkerStopping(worker) || worker.descriptor.lifecycle !== \"ready\" || worker.client === undefined,\n\t\t);\n\t\tif (unavailable) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot prepare update restart while resident worker ${unavailable.descriptor.workerId} is ${this.effectiveWorkerState(unavailable)}${unavailable.client ? \"\" : \" and disconnected\"}`,\n\t\t\t);\n\t\t}\n\t\tconst workers = residents as Array<ResidentWorker & { client: DaemonWorkerClient }>;\n\t\tconst acknowledged: ResidentWorker[] = [];\n\t\tconst preparationResults = await Promise.allSettled(\n\t\t\tworkers.map(async (worker) => {\n\t\t\t\tconst client = worker.client;\n\t\t\t\tconst response = await client.requestWorker(\n\t\t\t\t\t{ type: \"worker_prepare_update\" },\n\t\t\t\t\tMath.max(1, Math.min(UPDATE_RESTART_WORKER_REQUEST_TIMEOUT_MS, deadline - Date.now())),\n\t\t\t\t);\n\t\t\t\tif (!response.success) throw new Error(response.error);\n\t\t\t\tworker.updateRestartPrepareClient = client;\n\t\t\t\tacknowledged.push(worker);\n\t\t\t\tif (!response.data || typeof response.data !== \"object\") {\n\t\t\t\t\tthrow new Error(\"Worker returned an invalid update manifest\");\n\t\t\t\t}\n\t\t\t\tif (worker.client !== client || worker.descriptor.lifecycle !== \"ready\") {\n\t\t\t\t\tthrow new Error(`Worker ${worker.descriptor.workerId} disconnected during update preparation`);\n\t\t\t\t}\n\t\t\t\tconst manifest = response.data as DaemonUpdateRestartManifest;\n\t\t\t\tif (manifest.formatVersion !== DAEMON_UPDATE_RESTART_FORMAT_VERSION) {\n\t\t\t\t\tthrow new Error(`Worker returned unsupported update manifest version ${manifest.formatVersion}`);\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\t!manifest.sessions.some(\n\t\t\t\t\t\t(session) => session.activeSessionId === worker.descriptor.rootActiveSessionId,\n\t\t\t\t\t) &&\n\t\t\t\t\t!manifest.discardedActiveSessionIds?.includes(worker.descriptor.rootActiveSessionId)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Worker ${worker.descriptor.workerId} omitted its root disposition from the update manifest`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn { worker, manifest };\n\t\t\t}),\n\t\t);\n\t\tconst cancelAcknowledged = async () => {\n\t\t\tawait Promise.all(\n\t\t\t\tacknowledged.map(async (worker) => {\n\t\t\t\t\tconst prepareClient = worker.updateRestartPrepareClient;\n\t\t\t\t\tworker.updateRestartPrepareClient = undefined;\n\t\t\t\t\tif (!prepareClient) return;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await prepareClient.requestWorker({ type: \"worker_cancel_update\" }, 5000);\n\t\t\t\t\t\tif (!response.success) throw new Error(response.error);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.log(\n\t\t\t\t\t\t\t`Could not cancel prepared worker ${worker.descriptor.workerId}; reconnecting it: ${String(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprepareClient.close();\n\t\t\t\t\t\tif (worker.client && worker.client !== prepareClient) worker.client.close();\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t};\n\t\tconst preparationFailure = preparationResults.find(\n\t\t\t(result): result is PromiseRejectedResult => result.status === \"rejected\",\n\t\t);\n\t\tif (preparationFailure) {\n\t\t\tawait cancelAcknowledged();\n\t\t\tthrow preparationFailure.reason;\n\t\t}\n\t\tconst prepared = preparationResults.flatMap((result) =>\n\t\t\tresult.status === \"fulfilled\" ? [result.value.worker] : [],\n\t\t);\n\t\tconst responses = preparationResults.flatMap((result) =>\n\t\t\tresult.status === \"fulfilled\" ? [result.value.manifest] : [],\n\t\t);\n\t\tconst discardedActiveSessionIds = responses.flatMap((manifest) => manifest.discardedActiveSessionIds ?? []);\n\t\tconst manifest: DaemonUpdateRestartManifest = {\n\t\t\tformatVersion: DAEMON_UPDATE_RESTART_FORMAT_VERSION,\n\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\tsessions: responses.flatMap((manifest) => manifest.sessions),\n\t\t\t...(discardedActiveSessionIds.length > 0 ? { discardedActiveSessionIds } : {}),\n\t\t};\n\t\t// A worker that disconnected after preparing cancelled its checkpoint with\n\t\t// the old client; a recovered replacement may have admitted inputs past the\n\t\t// captured manifest. Abort before the manifest is persisted so the caller's\n\t\t// fallback cannot restore from the stale checkpoint.\n\t\tconst staleWorker = prepared.find((worker) => worker.client !== worker.updateRestartPrepareClient);\n\t\tif (staleWorker) {\n\t\t\tawait cancelAcknowledged();\n\t\t\tthrow new Error(\n\t\t\t\t`Worker ${staleWorker.descriptor.workerId} reconnected during update preparation; its checkpoint is stale`,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tthis.validateAndPersistUpdateManifest(manifest);\n\t\t} catch (error) {\n\t\t\tawait cancelAcknowledged();\n\t\t\tthrow error;\n\t\t}\n\t\t// Commit through the connection that owns the prepared transaction; a client\n\t\t// swapped in after the check above must fail the commit rather than reach a\n\t\t// worker that no longer holds the checkpoint.\n\t\tconst commitClients = new Map(prepared.map((worker) => [worker, worker.updateRestartPrepareClient]));\n\t\tfor (const worker of prepared) worker.updateRestartPrepareClient = undefined;\n\t\tconst commitResults = await Promise.allSettled(\n\t\t\tprepared.map(async (worker) => {\n\t\t\t\tconst client = commitClients.get(worker);\n\t\t\t\tif (!client) throw new Error(`Worker ${worker.descriptor.workerId} disconnected before update commit`);\n\t\t\t\tconst response = await client.requestWorker(\n\t\t\t\t\t{ type: \"worker_commit_update\" },\n\t\t\t\t\tUPDATE_RESTART_WORKER_REQUEST_TIMEOUT_MS,\n\t\t\t\t);\n\t\t\t\tif (!response.success) throw new Error(response.error);\n\t\t\t}),\n\t\t);\n\t\tconst commitFailure = commitResults.find(\n\t\t\t(result): result is PromiseRejectedResult => result.status === \"rejected\",\n\t\t);\n\t\tif (commitFailure) {\n\t\t\tthis.log(`Update restart commit response failed; forcing restart completion: ${String(commitFailure.reason)}`);\n\t\t\tawait Promise.allSettled(prepared.map((worker) => this.stopWorker(worker, false, true)));\n\t\t\treturn manifest;\n\t\t}\n\t\tconst stopResults = await Promise.allSettled(prepared.map((worker) => this.stopWorker(worker, false)));\n\t\tif (stopResults.some((result) => result.status === \"rejected\")) {\n\t\t\tthis.log(\"A committed update worker did not stop gracefully; forcing restart completion\");\n\t\t\tawait Promise.allSettled(prepared.map((worker) => this.stopWorker(worker, false, true)));\n\t\t}\n\t\treturn manifest;\n\t}\n\n\tprivate validateAndPersistUpdateManifest(manifest: DaemonUpdateRestartManifest): void {\n\t\tif (manifest.formatVersion !== DAEMON_UPDATE_RESTART_FORMAT_VERSION) {\n\t\t\tthrow new Error(`Unsupported update manifest version ${manifest.formatVersion}`);\n\t\t}\n\t\tconst activeSessionIds = new Set<string>();\n\t\tconst sessionFiles = new Set<string>();\n\t\tfor (const discardedActiveSessionId of manifest.discardedActiveSessionIds ?? []) {\n\t\t\tif (!discardedActiveSessionId || activeSessionIds.has(discardedActiveSessionId)) {\n\t\t\t\tthrow new Error(\"Update manifest contains an invalid discarded session disposition\");\n\t\t\t}\n\t\t\tactiveSessionIds.add(discardedActiveSessionId);\n\t\t}\n\t\tfor (const session of manifest.sessions) {\n\t\t\tif (!session.activeSessionId || !session.sessionFile) {\n\t\t\t\tthrow new Error(\"Update manifest contains an incomplete session checkpoint\");\n\t\t\t}\n\t\t\tif (activeSessionIds.has(session.activeSessionId)) {\n\t\t\t\tthrow new Error(`Update manifest contains duplicate active session ${session.activeSessionId}`);\n\t\t\t}\n\t\t\tconst sessionFile = canonicalSessionPath(session.sessionFile);\n\t\t\tif (sessionFiles.has(sessionFile)) {\n\t\t\t\tthrow new Error(`Update manifest contains duplicate session file ${sessionFile}`);\n\t\t\t}\n\t\t\tactiveSessionIds.add(session.activeSessionId);\n\t\t\tsessionFiles.add(sessionFile);\n\t\t}\n\t\tconst agentDir = this.defaultSessionConfig.agentDir;\n\t\tif (!agentDir) {\n\t\t\tthrow new Error(\"Daemon supervisor config is missing agentDir\");\n\t\t}\n\t\tconst path = getDaemonUpdateRestartManifestPath(this.socketPath, agentDir);\n\t\tmkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n\t\tconst tempPath = `${path}.${process.pid}.tmp`;\n\t\twriteFileSync(tempPath, `${JSON.stringify(manifest)}\\n`, { mode: 0o600 });\n\t\tchmodSync(tempPath, 0o600);\n\t\tconst validated = JSON.parse(readFileSync(tempPath, \"utf8\")) as DaemonUpdateRestartManifest;\n\t\tif (!Array.isArray(validated.sessions) || validated.sessions.length !== manifest.sessions.length) {\n\t\t\tthrow new Error(\"Could not validate aggregate update manifest\");\n\t\t}\n\t\trenameSync(tempPath, path);\n\t}\n\n\t/**\n\t * Verdict on whether a pid is still the process we launched. Callers must\n\t * be conservative in both directions: signal a pid only on \"current\"\n\t * (never SIGKILL a recycled pid), and clean up a registration only on\n\t * \"gone\"/\"replaced\" (never orphan a live worker because a transient\n\t * identity lookup failed).\n\t */\n\tprivate processIdentity(\n\t\tpid: number,\n\t\tprocessStartId: string | undefined,\n\t): \"current\" | \"replaced\" | \"gone\" | \"unknown\" {\n\t\tif (!isProcessAlive(pid)) {\n\t\t\treturn \"gone\";\n\t\t}\n\t\tif (processStartId === undefined) {\n\t\t\treturn \"unknown\";\n\t\t}\n\t\tconst observed = getProcessStartId(pid);\n\t\tif (observed === undefined) {\n\t\t\treturn \"unknown\";\n\t\t}\n\t\treturn observed === processStartId ? \"current\" : \"replaced\";\n\t}\n\n\t/**\n\t * Keep an exact stop's registration and descriptor authoritative while any\n\t * part of its cleanup is in flight. Root kills acquire this before forwarding\n\t * because a synchronous shutdown event may arrive before the worker replies.\n\t */\n\tprivate acquireWorkerStopOwnership(worker: ResidentWorker): () => void {\n\t\tif (!this.workerStopCounts) this.workerStopCounts = new Map();\n\t\tconst stopCounts = this.workerStopCounts;\n\t\tstopCounts.set(worker, (stopCounts.get(worker) ?? 0) + 1);\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\tconst remaining = (stopCounts.get(worker) ?? 1) - 1;\n\t\t\tif (remaining === 0) stopCounts.delete(worker);\n\t\t\telse stopCounts.set(worker, remaining);\n\t\t};\n\t}\n\n\tprivate async stopWorker(\n\t\tworker: ResidentWorker,\n\t\tremoveDescriptor: boolean,\n\t\tforce = false,\n\t\tarchiveSession = false,\n\t\trecoveryCleanup = false,\n\t\tdirectChild?: { child: ChildProcess; closed: Promise<void> },\n\t): Promise<void> {\n\t\tif (worker.compatibilityError) throw worker.compatibilityError;\n\t\tconst releaseStopOwnership = this.acquireWorkerStopOwnership(worker);\n\t\ttry {\n\t\t\tawait this.stopWorkerUntracked(worker, removeDescriptor, force, archiveSession, recoveryCleanup, directChild);\n\t\t} finally {\n\t\t\treleaseStopOwnership();\n\t\t}\n\t}\n\n\tprivate async stopWorkerUntracked(\n\t\tworker: ResidentWorker,\n\t\tremoveDescriptor: boolean,\n\t\tforce = false,\n\t\tarchiveSession = false,\n\t\trecoveryCleanup = false,\n\t\tdirectChild?: { child: ChildProcess; closed: Promise<void> },\n\t): Promise<void> {\n\t\tif (worker.ownerCleanupTimer) {\n\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t}\n\t\tif (!recoveryCleanup) {\n\t\t\tworker.stopRevision++;\n\t\t}\n\t\t// A retry can rescind this stop and relaunch the worker while we await\n\t\t// below. Bind every liveness check and signal to the process this stop\n\t\t// entered with, and abort cleanup once the stop no longer applies: the\n\t\t// pid changed (relaunched) or a removeDescriptor stop lost its tombstone\n\t\t// (rescinded, even before the successor pid lands).\n\t\tconst entryPid = worker.descriptor.pid;\n\t\tconst entryStartId = worker.descriptor.processStartId;\n\t\tconst assertStopStillApplies = () => {\n\t\t\tif (worker.compatibilityError) throw worker.compatibilityError;\n\t\t\tif (directChild) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tworker.descriptor.pid !== entryPid ||\n\t\t\t\t(removeDescriptor && worker.descriptor.stopRequestedAt === undefined)\n\t\t\t) {\n\t\t\t\tthrow new Error(`Session worker ${worker.descriptor.workerId} was relaunched during stop`);\n\t\t\t}\n\t\t};\n\t\ttry {\n\t\t\tif (removeDescriptor) {\n\t\t\t\tthis.persistWorkerStopTombstone(worker, archiveSession);\n\t\t\t} else {\n\t\t\t\tworker.intentionalStop = true;\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (!directChild) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tthis.reportCleanupFailure(`worker rollback state ${worker.descriptor.workerId}`, error);\n\t\t}\n\t\tconst transferError = new Error(\"Session worker stopped during snapshot transfer\");\n\t\tconst generationTranscripts = new Set<SnapshotTranscriptCache>();\n\t\tfor (const [activeSessionId, generations] of [...(worker.snapshotGenerations ?? new Map())]) {\n\t\t\tfor (const generation of [...generations.values()]) {\n\t\t\t\tgenerationTranscripts.add(generation.transcript);\n\t\t\t\tif (generation.incoming || !generation.transcript.complete || generation.validation) {\n\t\t\t\t\tthis.failSnapshotGeneration(worker, activeSessionId, generation, transferError);\n\t\t\t\t} else {\n\t\t\t\t\tgeneration.transcript.dispose();\n\t\t\t\t\tthis.deleteSnapshotGeneration(worker, activeSessionId, generation);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const transcript of worker.transcriptCaches.values()) {\n\t\t\tif (!generationTranscripts.has(transcript) && !transcript.complete) {\n\t\t\t\ttranscript.markFailed(transferError);\n\t\t\t}\n\t\t\ttranscript.dispose();\n\t\t}\n\t\tworker.transcriptCaches.clear();\n\t\tworker.snapshotCache.clear();\n\t\tworker.snapshotGenerations?.clear();\n\t\tif (worker.client) {\n\t\t\tif (archiveSession) {\n\t\t\t\tawait worker.client\n\t\t\t\t\t.requestWorker({ type: \"worker_archive_and_shutdown\" }, force ? 1000 : 5000)\n\t\t\t\t\t.catch(() => undefined);\n\t\t\t} else {\n\t\t\t\tawait worker.client.request({ type: \"shutdown\" }, force ? 1000 : 5000).catch(() => undefined);\n\t\t\t}\n\t\t\tassertStopStillApplies();\n\t\t\tworker.client.close();\n\t\t\tworker.client = undefined;\n\t\t} else if (directChild) {\n\t\t\tdirectChild.child.kill(\"SIGTERM\");\n\t\t} else if (this.processIdentity(entryPid, entryStartId) === \"current\") {\n\t\t\tsignalProcessGroupOrProcess(entryPid, \"SIGTERM\");\n\t\t}\n\t\t// Identity-aware in both directions: a replaced pid counts as gone (never\n\t\t// signal a recycled pid) while an unknown identity counts as alive (never\n\t\t// clean up a possibly-live worker on a transient lookup failure). kill(0)\n\t\t// runs on every poll; the expensive identity check is throttled.\n\t\tlet identityVerdict: \"current\" | \"replaced\" | \"gone\" | \"unknown\" = \"current\";\n\t\tlet identityCheckedAt = 0;\n\t\tconst isWorkerProcessAlive = () => {\n\t\t\tif (directChild) {\n\t\t\t\treturn directChild.child.exitCode === null && directChild.child.signalCode === null;\n\t\t\t}\n\t\t\tif (!processIdExists(entryPid)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst now = Date.now();\n\t\t\tif (now - identityCheckedAt >= LIVENESS_IDENTITY_RECHECK_MS) {\n\t\t\t\tidentityCheckedAt = now;\n\t\t\t\tidentityVerdict = this.processIdentity(entryPid, entryStartId);\n\t\t\t}\n\t\t\treturn identityVerdict !== \"replaced\" && identityVerdict !== \"gone\";\n\t\t};\n\t\tconst gracefulDeadline = Date.now() + (force ? 500 : 2000);\n\t\twhile (isWorkerProcessAlive() && Date.now() < gracefulDeadline) {\n\t\t\tawait delay(25);\n\t\t}\n\t\tlet sigkillSent = false;\n\t\tif (force && isWorkerProcessAlive()) {\n\t\t\tassertStopStillApplies();\n\t\t\tif (directChild) {\n\t\t\t\tsigkillSent = directChild.child.kill(\"SIGKILL\");\n\t\t\t} else if (this.processIdentity(entryPid, entryStartId) === \"current\") {\n\t\t\t\t// Fresh, unthrottled check: the cached verdict may be up to 500ms\n\t\t\t\t// old, long enough for the pid to be recycled.\n\t\t\t\tsignalProcessGroupOrProcess(entryPid, \"SIGKILL\");\n\t\t\t\tsigkillSent = true;\n\t\t\t}\n\t\t\tconst forceDeadline = Date.now() + 1000;\n\t\t\twhile (isWorkerProcessAlive() && Date.now() < forceDeadline) {\n\t\t\t\tawait delay(25);\n\t\t\t}\n\t\t}\n\t\tif (isWorkerProcessAlive()) {\n\t\t\tworker.intentionalStop = worker.descriptor.stopRequestedAt !== undefined;\n\t\t\tif (removeDescriptor) {\n\t\t\t\tthis.scheduleWorkerStopFinalization(worker);\n\t\t\t}\n\t\t\tthrow new WorkerStopTimeoutError(\n\t\t\t\t`Session worker ${worker.descriptor.workerId} did not stop${sigkillSent ? \" after SIGKILL\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t\tif (directChild) {\n\t\t\tawait directChild.closed;\n\t\t}\n\t\tassertStopStillApplies();\n\t\tif (removeDescriptor && worker.descriptor.archiveOnStop) {\n\t\t\tif (force) {\n\t\t\t\tthis.reclaimStoppedWorkerCronLock(worker);\n\t\t\t}\n\t\t\tawait this.finalizeArchivedWorkerStop(worker);\n\t\t\tassertStopStillApplies();\n\t\t}\n\t\tthis.invalidateWorkerSessionInputPauses(worker, \"Session worker stopped while input was paused\");\n\t\t// Client-owned schedules die with the registration, like their roster rows. Cancel\n\t\t// before the worker leaves the map, so no recompute sees the tree uncovered mid-stop.\n\t\tlet ephemeralCancelSettled = true;\n\t\tif (removeDescriptor && worker.descriptor.ownerClientId !== undefined) {\n\t\t\tephemeralCancelSettled = await this.cancelEphemeralWorkerScheduledJobs(worker);\n\t\t}\n\t\tthis.workers.delete(worker.descriptor.workerId);\n\t\tthis.flipWorkerRosterEntriesInactive(worker);\n\t\t// A failed cancel keeps the stop tombstone as the durable intent; the enumeration retry or the next boot finishes it.\n\t\tif (removeDescriptor && ephemeralCancelSettled) {\n\t\t\tthis.deleteWorkerDescriptor(worker);\n\t\t}\n\t\tif (!this.shuttingDown) {\n\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t}\n\t}\n\n\t/**\n\t * A stop that timed out leaves a tombstoned registration behind. Keep\n\t * escalating in the background until the process is gone, then finish the\n\t * interrupted cleanup instead of leaving a dead worker registered forever.\n\t */\n\tprivate scheduleWorkerStopFinalization(worker: ResidentWorker): void {\n\t\tif (worker.stopFinalization) {\n\t\t\treturn;\n\t\t}\n\t\tworker.stopFinalization = this.finalizeTimedOutWorkerStop(worker).finally(() => {\n\t\t\tworker.stopFinalization = undefined;\n\t\t});\n\t}\n\n\tprivate async finalizeTimedOutWorkerStop(worker: ResidentWorker): Promise<void> {\n\t\t// Bind to the exact process generation being stopped: a retry can rescind\n\t\t// the stop and relaunch with a new pid, and the OS can recycle the old\n\t\t// pid. The finalizer must never follow either successor.\n\t\tconst pid = worker.descriptor.pid;\n\t\tconst processStartId = worker.descriptor.processStartId;\n\t\tconst stopRevision = worker.stopRevision;\n\t\tconst isStopGenerationCurrent = () =>\n\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\tworker.stopRevision === stopRevision &&\n\t\t\tworker.descriptor.stopRequestedAt !== undefined &&\n\t\t\tworker.descriptor.pid === pid;\n\t\t// A replaced pid counts as gone (never SIGKILL a recycled pid); an\n\t\t// unobservable identity counts as alive (never clean up a possibly-live\n\t\t// worker). kill(0) probes every poll; ps-backed checks are throttled.\n\t\tlet stoppedVerdict = true;\n\t\tlet stoppedCanSignal = processStartId !== undefined;\n\t\tlet stoppedCheckedAt = 0;\n\t\tconst isStoppedProcessAlive = () => {\n\t\t\tif (!processIdExists(pid)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst now = Date.now();\n\t\t\tif (now - stoppedCheckedAt < LIVENESS_IDENTITY_RECHECK_MS) {\n\t\t\t\treturn stoppedVerdict;\n\t\t\t}\n\t\t\tstoppedCheckedAt = now;\n\t\t\tif (!isProcessAlive(pid)) {\n\t\t\t\tstoppedVerdict = false;\n\t\t\t} else if (processStartId === undefined) {\n\t\t\t\tstoppedVerdict = true;\n\t\t\t\t// Without an identity captured while the original worker was known\n\t\t\t\t// alive, this pid may now belong to an unrelated process. Keep\n\t\t\t\t// waiting for it to disappear, but never escalate by pid alone.\n\t\t\t\tstoppedCanSignal = false;\n\t\t\t} else {\n\t\t\t\tconst observed = getProcessStartId(pid);\n\t\t\t\tstoppedVerdict = observed !== processStartId ? observed === undefined : true;\n\t\t\t\tstoppedCanSignal = observed === processStartId;\n\t\t\t}\n\t\t\treturn stoppedVerdict;\n\t\t};\n\t\tconst sigkillDeadline = Date.now() + STOP_FINALIZATION_SIGKILL_GRACE_MS;\n\t\tlet killed = false;\n\t\twhile (!this.shuttingDown) {\n\t\t\tif (!isStopGenerationCurrent()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!isStoppedProcessAlive()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!killed && stoppedCanSignal && Date.now() >= sigkillDeadline) {\n\t\t\t\t// Fresh, unthrottled identity check right before signalling: the\n\t\t\t\t// cached verdict may be up to 500ms old, long enough for the pid\n\t\t\t\t// to be recycled by an unrelated process. A transiently\n\t\t\t\t// unobservable identity skips this attempt but keeps escalation\n\t\t\t\t// armed so a wedged worker is still killed on a later pass.\n\t\t\t\tconst observedNow = processStartId === undefined ? undefined : getProcessStartId(pid);\n\t\t\t\tif (processStartId === undefined || observedNow === processStartId) {\n\t\t\t\t\tsignalProcessGroupOrProcess(pid, \"SIGKILL\");\n\t\t\t\t\tkilled = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait unrefDelay(STOP_FINALIZATION_RECHECK_MS);\n\t\t}\n\t\t// Retry transient cleanup failures (for example catalog archival) so a\n\t\t// dead worker's registration is never stranded permanently. Each attempt\n\t\t// bumps the worker's stopRevision, so rescission is detected through the\n\t\t// registration and tombstone instead of the waiting-phase snapshot.\n\t\tconst isCleanupStillWanted = () =>\n\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\tworker.descriptor.stopRequestedAt !== undefined &&\n\t\t\tworker.descriptor.pid === pid;\n\t\twhile (!this.shuttingDown && isCleanupStillWanted()) {\n\t\t\ttry {\n\t\t\t\tawait this.stopWorker(worker, true, true, worker.descriptor.archiveOnStop === true);\n\t\t\t\tthis.log(`Finalized timed-out stop for worker ${worker.descriptor.workerId}`);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tthis.reportCleanupFailure(`timed-out worker stop ${worker.descriptor.workerId}`, error);\n\t\t\t\tawait unrefDelay(STOP_FINALIZATION_RETRY_MS);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async finalizeArchivedWorkerStop(worker: ResidentWorker): Promise<void> {\n\t\tconst context = this.workerSessionArtifactContext(worker);\n\t\tif (!context) {\n\t\t\treturn;\n\t\t}\n\t\tif (worker.descriptor.rootSessionId) {\n\t\t\tconst cronStore = AgentCronJobStore.forSessionArtifacts();\n\t\t\tcronStore.registerSessionArtifact(worker.descriptor.rootSessionId, context.artifactDir);\n\t\t\tcronStore.cancelJobsForSession({\n\t\t\t\tsessionId: worker.descriptor.rootSessionId,\n\t\t\t\tsessionFile: context.sessionFile,\n\t\t\t});\n\t\t\tawait this.catalog.archive(context.sessionFile, worker.descriptor.rootSessionId);\n\t\t}\n\t}\n\n\tprivate async cancelScheduledJobsForSessionTree(\n\t\trootSessionId: string,\n\t\trootSessionFile: string,\n\t\tstillWanted?: () => boolean,\n\t\texclude?: ResidentWorker,\n\t): Promise<void> {\n\t\tconst store = AgentCronJobStore.forSessionArtifacts();\n\t\tconst sessions = [{ sessionId: rootSessionId, sessionFile: rootSessionFile }];\n\t\tconst childrenByParent = new Map<string, SessionInfo[]>();\n\t\tfor (const info of await this.rlmSpawnLedger().family()) {\n\t\t\tif (!info.parentSessionPath) continue;\n\t\t\tconst key = canonicalSessionPath(info.parentSessionPath);\n\t\t\tchildrenByParent.set(key, [...(childrenByParent.get(key) ?? []), info]);\n\t\t}\n\t\tconst queue = [canonicalSessionPath(rootSessionFile)];\n\t\tconst visited = new Set(queue);\n\t\twhile (queue.length > 0) {\n\t\t\tfor (const info of childrenByParent.get(queue.shift()!) ?? []) {\n\t\t\t\tconst child = canonicalSessionPath(info.path);\n\t\t\t\tif (visited.has(child)) continue;\n\t\t\t\tvisited.add(child);\n\t\t\t\tsessions.push({ sessionId: info.id, sessionFile: info.path });\n\t\t\t\tqueue.push(child);\n\t\t\t}\n\t\t}\n\t\t// A worker covering any tree member owns its stores again; a stale intent must not kill new schedules.\n\t\tfor (const { sessionFile } of sessions) {\n\t\t\ttry {\n\t\t\t\tif (this.findWorkerBySessionFile(sessionFile, exclude)) return;\n\t\t\t} catch {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tlet registered = false;\n\t\tfor (const { sessionId, sessionFile } of sessions) {\n\t\t\tconst artifactDir = getSessionArtifactPathForFile(sessionFile, sessionId);\n\t\t\tif (!existsSync(join(artifactDir, SESSION_SCHEDULED_JOBS_FILENAME))) continue;\n\t\t\tstore.registerSessionArtifact(sessionId, artifactDir);\n\t\t\tregistered = true;\n\t\t}\n\t\tif (!registered) return;\n\t\t// Re-checked in the same synchronous turn as the walk: a promotion committed during the family read keeps its schedules.\n\t\tif (stillWanted && !stillWanted()) return;\n\t\tfor (const { sessionFile } of sessions) {\n\t\t\tstore.cancelJobsForSession({ sessionFile });\n\t\t}\n\t}\n\n\tprivate async cancelEphemeralWorkerScheduledJobs(worker: ResidentWorker): Promise<boolean> {\n\t\tconst context = this.workerSessionArtifactContext(worker);\n\t\tif (!context || !worker.descriptor.rootSessionId) {\n\t\t\treturn true;\n\t\t}\n\t\ttry {\n\t\t\tawait this.cancelScheduledJobsForSessionTree(\n\t\t\t\tworker.descriptor.rootSessionId,\n\t\t\t\tcontext.sessionFile,\n\t\t\t\t() => worker.descriptor.ownerClientId !== undefined,\n\t\t\t\tworker,\n\t\t\t);\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\t// A promotion that landed during the failed read means the cancel is no longer wanted.\n\t\t\tif (worker.descriptor.ownerClientId === undefined) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tthis.log(\n\t\t\t\t`Could not cancel scheduled jobs for client-owned worker ${worker.descriptor.workerId}: ${String(error)}`,\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate reclaimStoppedWorkerCronLock(worker: ResidentWorker): void {\n\t\tconst context = this.workerSessionArtifactContext(worker);\n\t\tif (!context) {\n\t\t\treturn;\n\t\t}\n\t\trmSync(join(context.artifactDir, `${SESSION_SCHEDULED_JOBS_FILENAME}.lock`), { recursive: true, force: true });\n\t}\n\n\tprivate workerSessionArtifactContext(worker: {\n\t\tdescriptor: DaemonWorkerDescriptor;\n\t}): { sessionFile: string; artifactDir: string } | undefined {\n\t\tconst sessionFile = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\tif (!sessionFile || !worker.descriptor.rootSessionId) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tsessionFile,\n\t\t\tartifactDir: getSessionArtifactPathForFile(sessionFile, worker.descriptor.rootSessionId),\n\t\t};\n\t}\n\n\tprivate persistWorkerStopTombstone(worker: ResidentWorker, archiveSession = false): void {\n\t\tif (worker.compatibilityError) throw worker.compatibilityError;\n\t\tworker.intentionalStop = true;\n\t\tworker.descriptor.stopRequestedAt ??= new Date().toISOString();\n\t\tworker.descriptor.archiveOnStop ||= archiveSession;\n\t\tthis.persistWorker(worker);\n\t}\n\n\tprivate write(client: DaemonSocketClient, message: DaemonOutbound): boolean {\n\t\treturn this.writeSerialized(client, serializeJsonLine(message));\n\t}\n\n\tprivate broadcastHeartbeatsChanged(): void {\n\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\tfor (const client of this.clients) {\n\t\t\tthis.write(client, { type: \"heartbeats_changed\" });\n\t\t}\n\t}\n\n\tprivate writeSerialized(client: DaemonSocketClient, line: string | Uint8Array): boolean {\n\t\tif (client.socket.destroyed) {\n\t\t\treturn false;\n\t\t}\n\t\tconst accepted = client.socket.write(line);\n\t\tif (!accepted) {\n\t\t\tclient.backpressured = true;\n\t\t}\n\t\treturn accepted;\n\t}\n\n\tprivate registerSignalHandlers(): void {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGINT\", \"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => void this.shutdown(signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143, false);\n\t\t\tprocess.on(signal, handler);\n\t\t\tthis.signalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t\tconst exitHandler = () => this.cleanupSocket();\n\t\tprocess.on(\"exit\", exitHandler);\n\t\tthis.signalCleanupHandlers.push(() => process.off(\"exit\", exitHandler));\n\t}\n\n\tprivate assertSocketLeaseHeld(): void {\n\t\tconst compromise = this.socketLeaseCompromise ?? this.socketLease?.compromise;\n\t\tif (compromise) throw new Error(`Daemon socket lease was compromised: ${compromise.message}`);\n\t}\n\n\tprivate assertSupervisorServing(allowWorkerLedger = false): void {\n\t\tthis.assertSocketLeaseHeld();\n\t\tif (this.shuttingDown && (!allowWorkerLedger || this.rlmJournalClose !== undefined)) {\n\t\t\tconst error = new Error(`Daemon supervisor generation ${this.generation} is shutting down; retry the command`);\n\t\t\tObject.assign(error, { code: \"supervisor_generation_stale\" as const });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate fenceSupervisorSocket(): void {\n\t\ttry {\n\t\t\tthis.server?.close();\n\t\t} catch {\n\t\t\t// The server may already be closed by a concurrent shutdown.\n\t\t}\n\t\tfor (const client of this.clients) {\n\t\t\tclient.detachInput();\n\t\t\tclient.socket.destroy();\n\t\t}\n\t}\n\n\tprivate handleSocketLeaseCompromised(error: Error): void {\n\t\tif (this.socketLeaseCompromise) return;\n\t\tthis.socketLeaseCompromise = error;\n\t\tthis.shuttingDown = true;\n\t\tthis.fenceRlmJournalOwner();\n\t\tthis.fenceSupervisorSocket();\n\t\tconst message = `Daemon socket lease was compromised; relinquishing supervisor ownership: ${error.message}`;\n\t\ttry {\n\t\t\tthis.log(message);\n\t\t} catch {\n\t\t\tconsole.error(message);\n\t\t}\n\t\tif (!this.startupComplete) return;\n\t\tvoid this.cleanupSupervisorResources().catch((cleanupError) =>\n\t\t\tthis.reportCleanupFailure(\"compromised daemon socket lease\", cleanupError),\n\t\t);\n\t}\n\n\tprivate cleanupSocket(): void {\n\t\tif (!this.ownsSocketPath) {\n\t\t\treturn;\n\t\t}\n\t\tthis.ownsSocketPath = false;\n\t\tconst identity = this.socketIdentity;\n\t\tthis.socketIdentity = undefined;\n\t\tcleanupDaemonSocketPath(this.socketPath, identity, this.socketLease);\n\t}\n\n\tprivate async cleanupSupervisorResources(): Promise<void> {\n\t\tif (this.cleanupPromise) {\n\t\t\treturn this.cleanupPromise;\n\t\t}\n\t\tthis.cleanupPromise = this.cleanupSupervisorResourcesOnce();\n\t\treturn this.cleanupPromise;\n\t}\n\n\tprivate async cleanupSupervisorResourcesOnce(): Promise<void> {\n\t\tthis.shuttingDown = true;\n\t\tthis.clearIdleEvictionTimer();\n\t\tthis.clearScheduledWakeTimer();\n\t\tthis.clearRosterWatchdogTimer();\n\t\tawait this.idleEvictionSweep?.catch(() => undefined);\n\t\tfor (const cleanup of this.signalCleanupHandlers.splice(0)) {\n\t\t\tawait this.runCleanupStep(\"signal handler\", cleanup);\n\t\t}\n\t\tconst server = this.server;\n\t\tthis.server = undefined;\n\t\tconst serverClosed = new Promise<void>((resolveClose) => {\n\t\t\tif (!server?.listening) {\n\t\t\t\tresolveClose();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tserver.close(() => resolveClose());\n\t\t\t} catch (error) {\n\t\t\t\tthis.reportCleanupFailure(\"daemon server\", error);\n\t\t\t\tresolveClose();\n\t\t\t}\n\t\t});\n\t\tfor (const client of this.clients) {\n\t\t\tclient.attachedActiveSessionIds.clear();\n\t\t\tawait this.runCleanupStep(`daemon client input ${client.id}`, () => client.detachInput());\n\t\t\tawait this.runCleanupStep(`daemon client socket ${client.id}`, () => {\n\t\t\t\tclient.socket.destroy();\n\t\t\t});\n\t\t}\n\t\tthis.clients.clear();\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker.ownerCleanupTimer) {\n\t\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t\t}\n\t\t\tawait this.runCleanupStep(`worker client ${worker.descriptor.workerId}`, () => worker.client?.close());\n\t\t\tworker.client = undefined;\n\t\t\tconst transcripts = new Set(worker.transcriptCaches.values());\n\t\t\tfor (const generations of worker.snapshotGenerations?.values() ?? []) {\n\t\t\t\tfor (const generation of generations.values()) {\n\t\t\t\t\ttranscripts.add(generation.transcript);\n\t\t\t\t\tthis.settleSnapshotDuplicateValidation(\n\t\t\t\t\t\tgeneration,\n\t\t\t\t\t\tnew Error(\"Daemon supervisor stopped during snapshot transfer\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (!generation.transcript.complete) {\n\t\t\t\t\t\tgeneration.transcript.markFailed(new Error(\"Daemon supervisor stopped during snapshot transfer\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const transcript of transcripts) {\n\t\t\t\tawait this.runCleanupStep(`worker transcript ${worker.descriptor.workerId}`, () => transcript.dispose());\n\t\t\t}\n\t\t\tworker.transcriptCaches.clear();\n\t\t\tworker.snapshotGenerations?.clear();\n\t\t\tworker.snapshotCache.clear();\n\t\t\tworker.snapshotLoads.clear();\n\t\t}\n\t\tthis.workers.clear();\n\t\tthis.openingWorkers.clear();\n\t\tawait this.runCleanupStep(\"daemon catalog\", () => this.catalog.stop());\n\t\tawait this.runCleanupStep(\"daemon server\", () => serverClosed);\n\t\tawait this.runCleanupStep(\"daemon socket\", () => this.cleanupSocket());\n\t\tawait this.runCleanupStep(\"supervisor cache\", () => {\n\t\t\trmSync(this.snapshotCacheRoot, { recursive: true, force: true });\n\t\t});\n\t\tawait this.closeRlmJournalOwner();\n\t\tconst lease = this.socketLease;\n\t\tthis.socketLease = undefined;\n\t\tawait this.runCleanupStep(\"daemon socket lock\", async () => lease?.release());\n\t\tconst ownership = this.ownership;\n\t\tthis.ownership = undefined;\n\t\tawait this.runCleanupStep(\"daemon ownership\", async () => ownership?.release());\n\t}\n\n\tprivate async runCleanupStep(label: string, action: () => void | Promise<void>): Promise<void> {\n\t\ttry {\n\t\t\tawait action();\n\t\t} catch (error) {\n\t\t\tthis.reportCleanupFailure(label, error);\n\t\t}\n\t}\n\n\tprivate reportCleanupFailure(label: string, error: unknown): void {\n\t\tconst message = `Failed to clean up ${label}: ${String(error)}`;\n\t\ttry {\n\t\t\tthis.log(message);\n\t\t} catch {\n\t\t\tconsole.error(message);\n\t\t}\n\t}\n\n\tprivate async shutdown(\n\t\texitCode: number,\n\t\tstopWorkers: boolean,\n\t\trelaunch = false,\n\t\tforceWorkers = false,\n\t\tclosingReason?: DaemonClosingReason,\n\t): Promise<never> {\n\t\tif (this.shuttingDown) {\n\t\t\tprocess.exit(exitCode);\n\t\t}\n\t\tthis.shuttingDown = true;\n\t\tthis.clearIdleEvictionTimer();\n\t\tthis.clearScheduledWakeTimer();\n\t\tthis.clearRosterWatchdogTimer();\n\t\tawait this.idleEvictionSweep?.catch(() => undefined);\n\t\tif (closingReason) {\n\t\t\tfor (const client of this.clients) {\n\t\t\t\tthis.write(client, { type: \"daemon_closing\", reason: closingReason });\n\t\t\t}\n\t\t}\n\t\tfor (const cleanup of this.signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tif (stopWorkers) {\n\t\t\tawait Promise.all(\n\t\t\t\t[...this.workers.values()].map(async (worker) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.stopWorker(worker, true, forceWorkers, true);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\t\t\t\tthis.log(`Keeping live incompatible worker ${worker.descriptor.workerId}: ${error.message}`);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!(error instanceof WorkerStopTimeoutError)) {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.log(\n\t\t\t\t\t\t\t`Worker ${worker.descriptor.workerId} remains tombstoned for recovery after shutdown: ${error.message}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (!this.hasPersistedWorkerDescriptors()) {\n\t\t\t\trmSync(this.supervisorConfigPath, { force: true });\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const worker of this.workers.values()) {\n\t\t\t\tif (worker.compatibilityError) continue;\n\t\t\t\tworker.intentionalStop = true;\n\t\t\t\tworker.client?.close();\n\t\t\t\tworker.client = undefined;\n\t\t\t}\n\t\t}\n\t\tawait this.catalog.stop();\n\t\tfor (const client of this.clients) {\n\t\t\tclient.detachInput();\n\t\t\tclient.socket.end();\n\t\t}\n\t\tawait new Promise<void>((resolveClose) => this.server?.close(() => resolveClose()) ?? resolveClose());\n\t\tawait this.runCleanupStep(\"daemon socket\", () => this.cleanupSocket());\n\t\tawait this.runCleanupStep(\"supervisor cache\", () => {\n\t\t\trmSync(this.snapshotCacheRoot, { recursive: true, force: true });\n\t\t});\n\t\tawait this.closeRlmJournalOwner();\n\t\tconst lease = this.socketLease;\n\t\tthis.socketLease = undefined;\n\t\tawait this.runCleanupStep(\"daemon socket lock\", async () => lease?.release());\n\t\tconst ownership = this.ownership;\n\t\tthis.ownership = undefined;\n\t\tawait this.runCleanupStep(\"daemon ownership\", async () => ownership?.release());\n\t\tif (relaunch) {\n\t\t\tconst launch = createCliSubprocessLaunchSpec([\"--mode\", \"daemon\", \"--daemon-socket\", this.socketPath]);\n\t\t\tconst environment = createCliSubprocessEnv();\n\t\t\tdelete environment[DAEMON_CATALOG_ROLE_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_ROLE_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_TOKEN_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_ACTIVE_SESSION_ID_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_SUPERVISOR_SOCKET_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_RECOVERY_JOURNAL_ENV];\n\t\t\tdelete environment[ORPHAN_PROCESS_JOURNAL_ENV];\n\t\t\tdelete environment[SESSION_LEASES_ENABLED_ENV];\n\t\t\tdelete environment[SESSION_LEASE_OWNER_ID_ENV];\n\t\t\tconst replacement = spawn(launch.command, launch.args, {\n\t\t\t\tcwd: this.defaultSessionConfig.cwd ?? process.cwd(),\n\t\t\t\tdetached: true,\n\t\t\t\tenv: environment,\n\t\t\t\tstdio: \"ignore\",\n\t\t\t});\n\t\t\treplacement.unref();\n\t\t}\n\t\tprocess.exit(exitCode);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"daemon-supervisor.d.ts","sourceRoot":"","sources":["../../../src/modes/daemon/daemon-supervisor.ts"],"names":[],"mappings":"AAiCA,OAAO,EACN,KAAK,yBAAyB,EAI9B,MAAM,oCAAoC,CAAC;AAiB5C,OAAO,EAEN,KAAK,mBAAmB,EAExB,MAAM,oCAAoC,CAAC;AAoV5C,UAAU,uBAAuB;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,yBAAyB,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAiQD,wBAAgB,2BAA2B,CAAC,mBAAmB,EAAE,mBAAmB,GAAG,MAAM,CAM5F;AA8BD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,KAAK,CAAC,CAK9F;AAED,qBAAa,gBAAgB;IA4D3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IA3D5B,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,cAAc,CAAC,CAAuB;IAC9C,OAAO,CAAC,WAAW,CAAC,CAAwB;IAC5C,OAAO,CAAC,qBAAqB,CAAC,CAAQ;IACtC,OAAO,CAAC,SAAS,CAAC,CAA+D;IACjF,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,kBAAkB,CAAC,CAAsC;IACjE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6C;IAC3E,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAA6C;IACrF,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAkD;IAC9F,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6C;IAC/E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,gBAAgB,CAAC,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA8C;IAC7E,0EAA0E;IAC1E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyE;IAC1G,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAkD;IACrF,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAyB;IAC/D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA4B;IACjE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA6C;IACjF,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAqB;IAC9D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAChE,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CAA0C;IACzF,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqB;IAC1D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqB;IAC1D,gGAAgG;IAChG,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,mBAAmB,CAAC,CAAiC;IAC7D,OAAO,CAAC,sBAAsB,CAAC,CAAiB;IAChD,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,eAAe,CAAC,CAAgB;IACxC,OAAO,CAAC,iBAAiB,CAAC,CAAgC;IAC1D,OAAO,CAAC,iBAAiB,CAAC,CAAgB;IAC1C,OAAO,CAAC,iBAAiB,CAAC,CAAgB;IAC1C,OAAO,CAAC,kBAAkB,CAAC,CAAgC;IAC3D,OAAO,CAAC,sBAAsB,CAAC,CAAgB;IAC/C,OAAO,CAAC,4BAA4B,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA6B;IAEnE,YACkB,UAAU,EAAE,MAAM,EACnC,OAAO,EAAE,uBAAuB,EAqBhC;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAkG3B;IAED,OAAO,CAAC,MAAM;IAgBd,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,qCAAqC;YAkB/B,2BAA2B;YAoE3B,6BAA6B;YA8B7B,wBAAwB;IA8BtC,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,sBAAsB;IAwB9B,4HAA4H;IAC5H,OAAO,CAAC,0BAA0B;YAWpB,oBAAoB;YAgFpB,wBAAwB;YAcxB,iBAAiB;YAUjB,8BAA8B;YAW9B,6BAA6B;IAiC3C,OAAO,CAAC,8BAA8B;YAmBxB,sBAAsB;YAmBtB,6BAA6B;YAM7B,qBAAqB;IAOnC,OAAO,CAAC,6BAA6B;IAkBrC,OAAO,CAAC,qBAAqB;IAmC7B,4IAA4I;IAC5I,OAAO,CAAC,6BAA6B;IAyBrC,OAAO,CAAC,6BAA6B;IAqBrC,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,6BAA6B;IAMrC,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,gBAAgB;IAgFxB,OAAO,CAAC,wBAAwB;IAUhC,OAAO,CAAC,gBAAgB;YAIV,+BAA+B;IAsD7C,OAAO,CAAC,kCAAkC;IAY1C,OAAO,CAAC,mCAAmC;IAW3C,OAAO,CAAC,0BAA0B;IA2BlC,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,sCAAsC;IAgC9C,0FAA0F;IAC1F,OAAO,CAAC,sCAAsC;IAoD9C,OAAO,CAAC,sBAAsB;YAYhB,UAAU;IA0LxB,OAAO,CAAC,gBAAgB;YAIV,iBAAiB;IAmB/B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,wBAAwB;YAMlB,sBAAsB;YAqBtB,wBAAwB;YAwBxB,iBAAiB;YAoFjB,aAAa;YAgzBb,UAAU;YAqGV,iBAAiB;YASjB,kBAAkB;IAShC,OAAO,CAAC,qBAAqB;YAsBf,sBAAsB;YAqBtB,mBAAmB;YA8EnB,oBAAoB;YAmCpB,iBAAiB;IAU/B,OAAO,CAAC,uBAAuB;IAU/B,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,mBAAmB;YAab,8BAA8B;YAmD9B,kBAAkB;IA4BhC,OAAO,CAAC,0BAA0B;YASpB,YAAY;YAwQZ,aAAa;IAwD3B,OAAO,CAAC,sBAAsB;YAiBhB,eAAe;YAoBf,oBAAoB;YAoGpB,sBAAsB;YA6CtB,iBAAiB;IAuD/B,OAAO,CAAC,wBAAwB;IAIhC,OAAO,CAAC,yBAAyB;IAUjC,OAAO,CAAC,mBAAmB;YAsBb,4BAA4B;IA+B1C,OAAO,CAAC,uBAAuB;IA+C/B,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,yBAAyB;IA6BjC,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,sBAAsB;IAkB9B,OAAO,CAAC,iCAAiC;IAWzC,OAAO,CAAC,iCAAiC;YAa3B,aAAa;IAkK3B,OAAO,CAAC,yBAAyB;IASjC,OAAO,CAAC,wBAAwB;YAQlB,gCAAgC;YAoFhC,sBAAsB;YAyDtB,oBAAoB;YAiBpB,0BAA0B;YAgB1B,oCAAoC;IAalD,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,kBAAkB;IAiC1B,OAAO,CAAC,sBAAsB;IAM9B,OAAO,CAAC,6BAA6B;IAKrC,OAAO,CAAC,gBAAgB;IA2BxB,OAAO,CAAC,+BAA+B;IAMvC,OAAO,CAAC,mBAAmB;YAIb,gBAAgB;IAsB9B,OAAO,CAAC,6BAA6B;IAuBrC,OAAO,CAAC,wBAAwB;IAsBhC,OAAO,CAAC,sBAAsB;IAsB9B,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,sBAAsB;YAahB,yBAAyB;IAsEvC,OAAO,CAAC,iCAAiC;IAoBzC,OAAO,CAAC,6BAA6B;IASrC,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,+BAA+B;IAkBvC,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,oBAAoB;IAa5B,sFAAsF;IACtF,OAAO,CAAC,cAAc;IAmBtB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;YAIX,gCAAgC;IAiB9C,OAAO,CAAC,2BAA2B;YAarB,yCAAyC;IAcvD,OAAO,CAAC,+BAA+B;IAyBvC,OAAO,CAAC,eAAe;IAIvB,gFAAgF;IAChF,OAAO,CAAC,gBAAgB;IAIxB,gEAAgE;IAChE,OAAO,CAAC,YAAY;IAIpB;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,4BAA4B;YAWtB,kBAAkB;IAkEhC,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,gBAAgB;IAuBxB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,aAAa;YAUP,UAAU;IAsBxB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,8BAA8B;IAMtC,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,mBAAmB;IAyB3B,OAAO,CAAC,uBAAuB;YA0BjB,eAAe;YAiBf,YAAY;IA4L1B,OAAO,CAAC,mBAAmB;IA6D3B,OAAO,CAAC,0BAA0B;IAyClC,OAAO,CAAC,0BAA0B;YAgBpB,cAAc;IAiF5B,OAAO,CAAC,qBAAqB;IAkC7B,OAAO,CAAC,mBAAmB;YAIb,mBAAmB;IA2BjC,OAAO,CAAC,YAAY;YAgBN,qBAAqB;IAUnC,OAAO,CAAC,iBAAiB;IAmbzB,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,sBAAsB;IAiB9B,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,aAAa;YAgBP,uBAAuB;YAWvB,mBAAmB;YAsFnB,oBAAoB;YAmBpB,0BAA0B;IAsIxC,OAAO,CAAC,gCAAgC;IA0CxC;;;;;;OAMG;IACH,OAAO,CAAC,eAAe;IAiBvB;;;;OAIG;IACH,OAAO,CAAC,0BAA0B;YAcpB,UAAU;YAiBV,mBAAmB;IAqKjC;;;;OAIG;IACH,OAAO,CAAC,8BAA8B;YASxB,0BAA0B;YAqF1B,0BAA0B;YAgB1B,iCAAiC;YAgDjC,kCAAkC;IAyBhD,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,4BAA4B;IAapC,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,sBAAsB;IAe9B,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,4BAA4B;IAkBpC,OAAO,CAAC,aAAa;YAUP,0BAA0B;YAQ1B,8BAA8B;YA4E9B,cAAc;IAQ5B,OAAO,CAAC,oBAAoB;YASd,QAAQ;CA4FtB","sourcesContent":["import { type ChildProcess, spawn } from \"node:child_process\";\nimport { createHash, randomBytes, randomUUID } from \"node:crypto\";\nimport {\n\tchmodSync,\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trenameSync,\n\trmSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { createServer, type Server, type Socket } from \"node:net\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { Writable } from \"node:stream\";\nimport { getLogger } from \"@ponythewhite/base-context-ai\";\nimport { createCliSubprocessEnv, createCliSubprocessLaunchSpec } from \"../../cli/subprocess-launch.js\";\nimport {\n\tappendRotatingLog,\n\tgetCronJobsPath,\n\tgetDaemonLogPath,\n\tgetDaemonUpdateRestartManifestPath,\n\tgetSessionsDir,\n\tVERSION,\n} from \"../../config.js\";\nimport {\n\ttype AgentFamilyCatalogEntry,\n\ttype AgentSessionMessageAgentSummary,\n\tassertAgentFamilyReach,\n\tassertAgentSessionNameAvailable,\n\tformatAgentSessionNameUnavailable,\n\tsessionNameReservationKey,\n} from \"../../core/agent-messages.js\";\nimport {\n\ttype AgentSessionRuntimeConfig,\n\ttype DurableAgentSessionRuntimeConfig,\n\tdurableAgentSessionRuntimeConfig,\n\tmergeAgentSessionRuntimeConfig,\n} from \"../../core/agent-session-config.js\";\nimport {\n\ttype AgentCronJob,\n\tAgentCronJobStore,\n\tisHeartbeatCronJob,\n\tmigrateLegacyCronJobsToSessionArtifacts,\n\tSESSION_SCHEDULED_JOBS_FILENAME,\n} from \"../../core/cron-jobs.js\";\nimport {\n\tclearOrphanProcessJournal,\n\tkillOrphanProcess,\n\tORPHAN_PROCESS_JOURNAL_ENV,\n\treadActiveOrphanProcesses,\n\tshouldReapOrphanProcess,\n} from \"../../core/orphan-process-journal.js\";\nimport { PromptAdmissionCancelledError, waitForPromptAdmission } from \"../../core/prompt-admission.js\";\nimport { RlmJournalOwner } from \"../../core/rlm-journal-owner.js\";\nimport {\n\tcanEvictWorker,\n\ttype IdleEvictionMinutes,\n\ttype WorkerEvictionSnapshot,\n} from \"../../core/session-action-store.js\";\nimport { canonicalSessionPath, getProcessStartId, SessionAlreadyActiveError } from \"../../core/session-lease.js\";\nimport { getSessionArtifactPathForFile, readSessionInfo, type SessionInfo } from \"../../core/session-manager.js\";\nimport { looksLikeSessionPath } from \"../../core/session-resolver.js\";\nimport { SettingsManager } from \"../../core/settings-manager.js\";\nimport { PRODUCT } from \"../../product-identity.js\";\nimport { isProcessAlive, processIdExists, signalProcessGroupOrProcess } from \"../../utils/child-process.js\";\nimport type { AgentConnectionHeartbeat } from \"../agent-connection/types.js\";\nimport { attachJsonlLineReader, serializeJsonLine } from \"../rpc/jsonl.js\";\nimport type { PrivateFrame } from \"../session-worker/private-framing.js\";\nimport { createActiveSessionId, type DaemonSocketClient } from \"./active-session-state.js\";\nimport {\n\tAgentRoster,\n\ttype AgentRosterEntry,\n\ttype AgentRosterMutation,\n\tpassivatedWorkerRosterEntry,\n\trosterAgentIdForSummary,\n\tsessionSummaryFromRosterEntry,\n\ttype WorkerRosterEntry,\n\tworkerRosterEntryFromSummary,\n} from \"./agent-roster.js\";\nimport {\n\ttype CommandJournalBeginResult,\n\tCommandRecoveryJournal,\n\tcreateCommandIdempotencyKey,\n} from \"./command-recovery-journal.js\";\nimport { CompactAssistantStreamReconstructor, isCompactAssistantDelta } from \"./compact-session-stream.js\";\nimport { DAEMON_CATALOG_ROLE_ENV, DaemonCatalogClient } from \"./daemon-catalog-process.js\";\nimport { deserializeDaemonError, serializeDaemonError } from \"./daemon-errors.js\";\nimport {\n\tCANONICAL_SESSION_OWNERSHIP_COMPATIBILITY,\n\tcollectDaemonClientEnv,\n\tcreateDaemonEventMeta,\n\tDAEMON_COMMAND_COMPATIBILITY,\n\tDAEMON_COMMAND_ENVELOPE_MIN_PROTOCOL_VERSION,\n\tDAEMON_DEFAULT_CLIENT_CAPABILITIES,\n\tDAEMON_DEFAULT_SERVER_CAPABILITIES,\n\tDAEMON_PROTOCOL_INFO,\n\tDAEMON_SCHEMA_ID,\n\tDAEMON_SCHEMA_REVISION,\n\tDAEMON_UPDATE_RESTART_FORMAT_VERSION,\n\ttype DaemonAttachResult,\n\ttype DaemonClientCapability,\n\ttype DaemonClosingReason,\n\ttype DaemonCommand,\n\ttype DaemonOutbound,\n\ttype DaemonPeerTransportTicket,\n\ttype DaemonResponse,\n\ttype DaemonServerCapability,\n\ttype DaemonUpdateRestartManifest,\n\tfailure,\n\tisDaemonCommandEnvelope,\n\tisDaemonMutatingCommand,\n\tisLegacyDaemonInspection,\n\tsalvageDaemonCommandId,\n\tsuccess,\n\tUPDATE_RESTART_DRAIN_COMMANDS,\n} from \"./daemon-protocol.js\";\nimport { DaemonRlmCapacityCoordinator } from \"./daemon-rlm-capacity-coordinator.js\";\nimport { getDaemonRuntimeIdentity } from \"./daemon-runtime-identity.js\";\nimport { matchesSessionIdSuffix } from \"./daemon-session-id.js\";\nimport {\n\tclassifySessionRosterStatus,\n\tisEvictableEmptySessionSummary,\n\tisSessionSummaryBusy,\n\ttype SessionSummary,\n\tsummaryForInactiveSession,\n} from \"./daemon-session-list.js\";\nimport {\n\tacquireDaemonSocketPathLease,\n\tcleanupDaemonSocketPath,\n\ttype DaemonSocketIdentity,\n\ttype DaemonSocketPathLease,\n\tdefaultDaemonSocketDir,\n\tdefaultDaemonSocketPath,\n\tgetDaemonSocketIdentity,\n\tnormalizeSocketPath,\n\tprepareDaemonSocketPath,\n\trestrictDaemonSocketPath,\n} from \"./daemon-socket.js\";\nimport {\n\tacquireDaemonSupervisorOwnership,\n\tisDaemonShutdownAdmissionActive,\n\twaitForDaemonStartupFence,\n} from \"./daemon-supervisor-ownership.js\";\nimport {\n\tDaemonWorkerAuthenticationError,\n\tDaemonWorkerClient,\n\tDaemonWorkerCompatibilityError,\n\tDaemonWorkerProbeTimeoutError,\n} from \"./daemon-worker-client.js\";\nimport {\n\tDAEMON_WORKER_ACTIVE_SESSION_ID_ENV,\n\tDAEMON_WORKER_INSTANCE_ID_ENV,\n\tDAEMON_WORKER_PEER_TRANSPORT_CAPABILITY,\n\tDAEMON_WORKER_RECOVERY_JOURNAL_ENV,\n\tDAEMON_WORKER_ROLE_ENV,\n\tDAEMON_WORKER_ROSTER_CAPABILITY,\n\tDAEMON_WORKER_STARTUP_GATE_COMMIT,\n\tDAEMON_WORKER_STARTUP_GATE_FD_ENV,\n\tDAEMON_WORKER_SUPERVISOR_SOCKET_ENV,\n\tDAEMON_WORKER_TOKEN_ENV,\n\ttype DaemonCreateCommand,\n\ttype DaemonWorkerDescriptor,\n\ttype DaemonWorkerFrameHeader,\n\ttype DaemonWorkerLifecycle,\n\ttype DaemonWorkerRosterOutbound,\n\tdurableDaemonCreateCommand,\n\tdurableDaemonWorkerDescriptor,\n\tisDaemonRlmCapacitySnapshot,\n\tROSTER_HEARTBEAT_INTERVAL_MS,\n\tSESSION_LEASE_OWNER_ID_ENV,\n\tSESSION_LEASES_ENABLED_ENV,\n} from \"./daemon-worker-protocol.js\";\nimport { MutationDrainLatch } from \"./mutation-drain-latch.js\";\nimport {\n\tcreateRlmLedgerRegistrySeedSource,\n\ttype RlmLedgerEdge,\n\tRlmSpawnLedger,\n\trlmLedgerPath,\n\ttombstoneSavedSessionDelete,\n} from \"./rlm-ledger.js\";\nimport { captureSavedSessionPageQuery } from \"./saved-session-page.js\";\nimport { SNAPSHOT_TARGET_CHUNK_BYTES, SnapshotTranscriptCache } from \"./snapshot-transcript-cache.js\";\nimport { WorkerRecoveryJournal } from \"./worker-recovery-journal.js\";\n\ntype DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;\ntype DaemonCommandBody = DistributiveOmit<DaemonCommand, \"id\">;\n\nconst structuredLog = getLogger(\"coding-agent.daemon-supervisor\");\nconst WORKER_CONNECT_TIMEOUT_MS = 30_000;\nconst ROSTER_WATCHDOG_INTERVAL_MS = 15_000;\nconst ROSTER_STALE_AFTER_MS = 3 * ROSTER_HEARTBEAT_INTERVAL_MS;\nconst SUPERVISOR_SERVER_CAPABILITIES: readonly DaemonServerCapability[] = [\n\t...DAEMON_DEFAULT_SERVER_CAPABILITIES,\n\t\"agent_roster\",\n\t\"direct_peer_transport\",\n\t\"rlm_ledger_mutation\",\n];\nconst PEER_TRANSPORT_GRANT_TTL_MS = 10_000;\nconst WORKER_REQUEST_TIMEOUT_MS = 24 * 60 * 60 * 1000;\nconst INPUT_PAUSE_CLEANUP_TIMEOUT_MS = 5_000;\nconst UPDATE_RESTART_MUTATION_DRAIN_TIMEOUT_MS = 80_000;\nconst UPDATE_RESTART_WORKER_REQUEST_TIMEOUT_MS = 90_000;\n// The whole pre-commit prepare (drain + worker fencing) must finish inside the\n// caller's 120s prepare_update_restart request timeout, or roll back; otherwise\n// an abandoned prepare leaves the daemon permanently fenced with workers stopped.\nconst UPDATE_RESTART_PREPARE_DEADLINE_MS = 100_000;\nconst WORKER_RETRY_DELAYS_MS = [250, 1000, 5000] as const;\nconst DEFERRED_RECOVERY_RECHECK_MS = 5000;\n// ~2.5 minutes of probing: each round is one 5s defer recheck plus a ~11s three-delay probe pass.\nconst MAX_DEFERRED_RECOVERY_ROUNDS = 10;\nconst STOP_FINALIZATION_RECHECK_MS = 250;\nconst STOP_FINALIZATION_SIGKILL_GRACE_MS = 5000;\nconst STOP_FINALIZATION_RETRY_MS = 5000;\nconst STALE_RECLAIM_WAIT_MS = 10_000;\n// Polling loops probe existence cheaply via kill(0); the ps-backed zombie and\n// identity checks are throttled so a wedged worker cannot saturate the\n// supervisor event loop with synchronous subprocess spawns.\nconst LIVENESS_IDENTITY_RECHECK_MS = 500;\nconst OWNED_WORKER_DISCONNECT_GRACE_MS = 30_000;\nconst IDLE_EVICTION_MAX_SWEEP_INTERVAL_MS = 5 * 60_000;\nconst IDLE_EVICTION_MIN_SWEEP_INTERVAL_MS = 60_000;\nconst IDLE_EVICTION_DRAIN_TIMEOUT_MS = 5_000;\nconst CHILD_PASSIVATION_PER_WORKER_CAP = 2;\nconst SCHEDULED_WAKE_RETRY_MS = 60_000;\nconst SCHEDULED_WAKE_MAX_TIMEOUT_MS = 2_147_483_647;\nconst SCHEDULED_WAKE_CLIENT_ID = \"scheduled-wake\";\nconst SUPERVISOR_CONFIG_FILE_NAME = \"supervisor-config\";\nconst WORKER_STARTUP_GATE_FD = 3;\n\nconst DAEMON_COMMAND_TYPES: ReadonlySet<string> = new Set([\n\t\"ack_result\",\n\t\"list\",\n\t\"list_agent_peers\",\n\t\"rlm_ledger_mutate\",\n\t\"rlm_capacity\",\n\t\"get_direct_worker_transport\",\n\t\"roster_subscribe\",\n\t\"roster_unsubscribe\",\n\t\"list_saved_sessions\",\n\t\"create\",\n\t\"attach\",\n\t\"reattach\",\n\t\"detach\",\n\t\"complete_owned_session\",\n\t\"promote_owned_session\",\n\t\"kill\",\n\t\"rename\",\n\t\"prompt\",\n\t\"cancel_prompt_admission\",\n\t\"prompt_and_wait\",\n\t\"steer\",\n\t\"follow_up\",\n\t\"restore_next_turn\",\n\t\"restore_actions\",\n\t\"append_custom_message\",\n\t\"resume_queue\",\n\t\"send_message\",\n\t\"send_result\",\n\t\"agent_messages_status\",\n\t\"agent_messages_pause\",\n\t\"agent_messages_resume\",\n\t\"agent_messages_clear\",\n\t\"abort\",\n\t\"start_side_question\",\n\t\"abort_side_question\",\n\t\"execute_bash\",\n\t\"execute_bash_and_wait\",\n\t\"abort_bash\",\n\t\"cancel_rlm_child\",\n\t\"delete_rlm_subagent\",\n\t\"wait_for_idle\",\n\t\"wait_for_headless_completion\",\n\t\"get_session_header\",\n\t\"get_state\",\n\t\"get_connection_state\",\n\t\"get_messages\",\n\t\"get_rlm_children\",\n\t\"get_session_stats\",\n\t\"get_context_tree\",\n\t\"get_commands\",\n\t\"get_resource_snapshot\",\n\t\"replace_acp_mcp_servers\",\n\t\"get_model_catalog\",\n\t\"get_available_models\",\n\t\"get_queue\",\n\t\"mutate_queued_message\",\n\t\"clear_queue\",\n\t\"abort_and_clear_queue\",\n\t\"acquire_session_input_pause\",\n\t\"release_session_input_pause\",\n\t\"cron_list\",\n\t\"heartbeats_list\",\n\t\"heartbeat_manage\",\n\t\"cron_add\",\n\t\"cron_cancel\",\n\t\"cron_resume\",\n\t\"heartbeat_get\",\n\t\"heartbeat_set\",\n\t\"heartbeat_update\",\n\t\"set_model\",\n\t\"cycle_model\",\n\t\"set_scoped_models\",\n\t\"set_thinking_level\",\n\t\"cycle_thinking_level\",\n\t\"set_service_tier\",\n\t\"set_transport\",\n\t\"set_steering_mode\",\n\t\"set_follow_up_mode\",\n\t\"set_auto_compaction\",\n\t\"set_auto_retry\",\n\t\"compact\",\n\t\"refine\",\n\t\"abort_compaction\",\n\t\"abort_branch_summary\",\n\t\"abort_retry\",\n\t\"reload\",\n\t\"new_session\",\n\t\"switch_session\",\n\t\"fork\",\n\t\"navigate_tree\",\n\t\"import_jsonl\",\n\t\"export_html\",\n\t\"export_jsonl\",\n\t\"set_session_name\",\n\t\"get_rlm_max_depth_status\",\n\t\"set_rlm_max_depth\",\n\t\"get_rlm_max_subagents_status\",\n\t\"set_rlm_max_subagents\",\n\t\"rename_saved_session\",\n\t\"delete_saved_session\",\n\t\"get_session_context\",\n\t\"get_session_tree\",\n\t\"get_user_messages_for_forking\",\n\t\"get_last_assistant_text\",\n\t\"get_system_prompt\",\n\t\"get_tool_definition\",\n\t\"set_session_entry_label\",\n\t\"extension_ui_response\",\n\t\"prepare_update_restart\",\n\t\"retry_worker\",\n\t\"restart\",\n\t\"shutdown\",\n]);\n\ninterface ResidentWorker {\n\tdescriptor: DaemonWorkerDescriptor;\n\tdescriptorPath: string;\n\tclient?: DaemonWorkerClient;\n\tcompatibilityError?: DaemonWorkerCompatibilityError;\n\theartbeatSnapshot?: AgentConnectionHeartbeat[];\n\theartbeatSnapshotStale?: boolean;\n\tsummaries: Map<string, SessionSummary>;\n\tsnapshotCache: Map<string, DaemonAttachResult>;\n\ttranscriptCaches: Map<string, SnapshotTranscriptCache>;\n\tsnapshotGenerations: Map<string, Map<string, SnapshotTranscriptGeneration>>;\n\tsnapshotLoads: Map<string, Promise<DaemonAttachResult>>;\n\trecovery?: Promise<void>;\n\tdeferredRecovery?: Promise<void>;\n\tintentionalStop: boolean;\n\tstopRevision: number;\n\tlaunchEnv?: Record<string, string>;\n\ttransientCreateCommand?: DaemonCreateCommand;\n\tstopFinalization?: Promise<void>;\n\townerCleanupTimer?: ReturnType<typeof setTimeout>;\n\tpromotedOwnerClientId?: string;\n\tupdateRestartPrepareClient?: DaemonWorkerClient;\n\tlastFrameAt?: number;\n\trosterStale?: boolean;\n\t/** worker_auth advertised peer-transport support; absent on workers from older builds. */\n\tpeerTransportCapable?: boolean;\n\t/** In-flight replacement connection during authentication; an allowed frame source alongside client. */\n\tpendingClient?: DaemonWorkerClient;\n\t/** Consecutive defer->probe rounds against a live-but-silent worker; bounded by MAX_DEFERRED_RECOVERY_ROUNDS. */\n\tdeferredRecoveryRounds?: number;\n\t/** Bumped per applied roster frame; a summaries pull that straddles a frame must not gap-fill. */\n\trosterEpoch?: number;\n\trosterApplyChain?: Promise<void>;\n\trosterRepairPull?: Promise<void>;\n}\n\ninterface SnapshotDuplicateValidation {\n\tpromise: Promise<void>;\n\tresolve: () => void;\n\treject: (error: Error) => void;\n}\n\ninterface SnapshotTranscriptGeneration {\n\ttranscript: SnapshotTranscriptCache;\n\tresult: DaemonAttachResult;\n\tbegin?: Buffer;\n\tend?: Buffer;\n\tincoming: boolean;\n\tretired: boolean;\n\tduplicateChunkIndex?: number;\n\tduplicateResult?: DaemonAttachResult;\n\tvalidation?: SnapshotDuplicateValidation;\n}\n\ninterface DaemonSupervisorOptions {\n\tsocketPath?: string;\n\tdefaultSessionConfig: AgentSessionRuntimeConfig;\n\tdescriptorDir?: string;\n}\n\ninterface PersistedSupervisorConfig {\n\tversion: 1;\n\tsocketPath: string;\n\tdefaultSessionConfig: DurableAgentSessionRuntimeConfig;\n}\n\ninterface WorkerMatch {\n\tworker: ResidentWorker;\n\tsummary: SessionSummary;\n}\n\ninterface WorkerAttachData {\n\tresult: DaemonAttachResult;\n\tworker: ResidentWorker;\n\ttranscript?: SnapshotTranscriptCache;\n\treleaseTranscript?: () => void;\n}\n\ninterface SupervisorPromptAdmission {\n\tclient: DaemonSocketClient;\n\tactiveSessionId: string;\n\tpublicAdmissionId: string;\n\tworkerAdmissionId: string;\n\tstatus: \"waiting\" | \"owned\" | \"cancelled\";\n\tcontroller: AbortController;\n\tworker?: ResidentWorker;\n\tworkerActiveSessionId?: string;\n}\n\ninterface SupervisorSessionInputPause {\n\towner: DaemonSocketClient;\n\tworker: ResidentWorker;\n\tactiveSessionId: string;\n\trequestedActiveSessionId: string;\n\tleaseKey: string;\n\tpauseId: string;\n\treleaseTask?: Promise<DaemonResponse>;\n}\n\nfunction throwIfAdmissionCancelled(admission: SupervisorPromptAdmission | undefined): void {\n\tif (admission?.status === \"cancelled\") throw new PromptAdmissionCancelledError();\n}\n\nclass SupervisorRecoveryCancelledError extends Error {\n\treadonly code = \"supervisor_recovery_cancelled\" as const;\n}\n\nclass SnapshotLoadInvalidatedError extends Error {}\n\nclass WorkerStopTimeoutError extends Error {}\n\nfunction isSupervisorGenerationStale(error: unknown): boolean {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"code\" in error &&\n\t\t(error as { code?: unknown }).code === \"supervisor_generation_stale\"\n\t);\n}\n\nfunction isSupervisorRecoveryCancelled(error: unknown): boolean {\n\treturn isSupervisorShutdownAdmissionCancelled(error) || isSupervisorGenerationStale(error);\n}\n\n// Workers can be registered mid-tree (a resumed subagent transcript), so descent is membership at\n// any step of the parent walk, never a comparison against the ultimate root alone.\nfunction rosterFamilyDescendsFrom(\n\tedges: readonly RlmLedgerEdge[],\n): (path: string, roots: ReadonlySet<string>) => boolean {\n\tconst parentByChild = new Map(\n\t\tedges.map((edge) => [canonicalSessionPath(edge.child), canonicalSessionPath(edge.parent)]),\n\t);\n\treturn (path, roots) => {\n\t\tconst visited = new Set<string>();\n\t\tlet current = path;\n\t\twhile (!visited.has(current)) {\n\t\t\tif (roots.has(current)) return true;\n\t\t\tvisited.add(current);\n\t\t\tconst parent = parentByChild.get(current);\n\t\t\tif (parent === undefined) return false;\n\t\t\tcurrent = parent;\n\t\t}\n\t\treturn false;\n\t};\n}\n\nfunction isDaemonWorkerProbeTimeout(error: unknown): boolean {\n\treturn error instanceof DaemonWorkerProbeTimeoutError;\n}\n\nfunction isSupervisorShutdownAdmissionCancelled(error: unknown): boolean {\n\treturn (\n\t\terror instanceof SupervisorRecoveryCancelledError ||\n\t\t(typeof error === \"object\" &&\n\t\t\terror !== null &&\n\t\t\t\"code\" in error &&\n\t\t\t(error as { code?: unknown }).code === \"supervisor_recovery_cancelled\")\n\t);\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms));\n}\n\nfunction unrefDelay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms).unref());\n}\n\nfunction commitWorkerStartupGate(gate: Writable): Promise<void> {\n\treturn new Promise((resolveCommit, rejectCommit) => {\n\t\tlet settled = false;\n\t\tconst finish = (error?: Error | null) => {\n\t\t\tif (settled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tif (error) {\n\t\t\t\trejectCommit(error);\n\t\t\t} else {\n\t\t\t\tresolveCommit();\n\t\t\t}\n\t\t};\n\t\tconst onError = (error: Error) => finish(error);\n\t\tgate.on(\"error\", onError);\n\t\tgate.once(\"close\", () => gate.off(\"error\", onError));\n\t\tgate.end(DAEMON_WORKER_STARTUP_GATE_COMMIT, (error?: Error | null) => finish(error));\n\t});\n}\n\nfunction withoutCommandId(command: DaemonCommand): DaemonCommandBody {\n\tconst { id: _id, ...body } = command;\n\treturn body as DaemonCommandBody;\n}\n\nfunction withoutSupervisorCreateFields(command: DaemonCreateCommand): DaemonCreateCommand {\n\tconst { launchEnv: _launchEnv, lifecycle: _lifecycle, ...workerCommand } = command;\n\treturn workerCommand;\n}\n\nfunction responseWithId(response: DaemonResponse, id: string | undefined): DaemonResponse {\n\treturn { ...response, id };\n}\n\nfunction isSessionSummary(value: unknown): value is SessionSummary {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst candidate = value as { id?: unknown; sessionId?: unknown; cwd?: unknown };\n\treturn (\n\t\ttypeof candidate.id === \"string\" && typeof candidate.sessionId === \"string\" && typeof candidate.cwd === \"string\"\n\t);\n}\n\nfunction isDaemonWorkerDescriptor(value: unknown, socketPath: string): value is DaemonWorkerDescriptor {\n\tif (!value || typeof value !== \"object\") {\n\t\treturn false;\n\t}\n\tconst descriptor = value as Partial<DaemonWorkerDescriptor>;\n\treturn (\n\t\t(descriptor.version === 1 || descriptor.version === 2) &&\n\t\ttypeof descriptor.supervisorSocketPath === \"string\" &&\n\t\tnormalizeSocketPath(descriptor.supervisorSocketPath) === socketPath &&\n\t\ttypeof descriptor.workerId === \"string\" &&\n\t\tNumber.isInteger(descriptor.pid) &&\n\t\t(descriptor.pid ?? 0) > 0 &&\n\t\t(descriptor.processStartId === undefined || typeof descriptor.processStartId === \"string\") &&\n\t\t(descriptor.ownerClientId === undefined || typeof descriptor.ownerClientId === \"string\") &&\n\t\ttypeof descriptor.socketPath === \"string\" &&\n\t\ttypeof descriptor.authenticationToken === \"string\" &&\n\t\t(descriptor.workerInstanceId === undefined || typeof descriptor.workerInstanceId === \"string\") &&\n\t\ttypeof descriptor.rootActiveSessionId === \"string\" &&\n\t\ttypeof descriptor.createdAt === \"string\" &&\n\t\ttypeof descriptor.updatedAt === \"string\" &&\n\t\tNumber.isInteger(descriptor.consecutiveFailures) &&\n\t\tdescriptor.createCommand !== undefined &&\n\t\ttypeof descriptor.createCommand === \"object\" &&\n\t\tdescriptor.createCommand.type === \"create\"\n\t);\n}\n\nclass PreRosterWorkerError extends Error {}\n\nfunction workerAuthAdvertisesRoster(data: unknown): boolean {\n\tif (typeof data !== \"object\" || data === null) return false;\n\tconst capabilities = (data as { capabilities?: unknown }).capabilities;\n\treturn Array.isArray(capabilities) && capabilities.includes(DAEMON_WORKER_ROSTER_CAPABILITY);\n}\n\nfunction workerAuthAdvertisesPeerTransport(data: unknown): boolean {\n\tif (typeof data !== \"object\" || data === null) return false;\n\tconst capabilities = (data as { capabilities?: unknown }).capabilities;\n\treturn Array.isArray(capabilities) && capabilities.includes(DAEMON_WORKER_PEER_TRANSPORT_CAPABILITY);\n}\n\nfunction sessionSummariesFromResponse(response: DaemonResponse): SessionSummary[] {\n\tif (!response.success || !response.data || typeof response.data !== \"object\" || !(\"sessions\" in response.data)) {\n\t\tthrow new Error(\"Session worker returned an invalid list response\");\n\t}\n\tconst sessions = (response.data as { sessions: unknown }).sessions;\n\tif (!Array.isArray(sessions) || !sessions.every(isSessionSummary)) {\n\t\tthrow new Error(\"Session worker returned an invalid list response\");\n\t}\n\treturn sessions;\n}\n\nfunction attachResultFromResponse(response: DaemonResponse): DaemonAttachResult {\n\tif (!response.success || !response.data || typeof response.data !== \"object\") {\n\t\tthrow new Error(response.success ? \"Session worker returned an invalid attach response\" : response.error);\n\t}\n\tconst candidate = response.data as Partial<DaemonAttachResult>;\n\tif (typeof candidate.activeSessionId !== \"string\" || !candidate.snapshot || !candidate.client) {\n\t\tthrow new Error(\"Session worker returned an invalid attach response\");\n\t}\n\treturn candidate as DaemonAttachResult;\n}\n\nfunction cronJobsFromResponse(response: DaemonResponse): AgentCronJob[] {\n\tif (!response.success || !response.data || typeof response.data !== \"object\") {\n\t\treturn [];\n\t}\n\tconst jobs = (response.data as { jobs?: unknown }).jobs;\n\treturn Array.isArray(jobs) ? (jobs as AgentCronJob[]) : [];\n}\n\nfunction heartbeatsFromResponse(response: DaemonResponse): AgentConnectionHeartbeat[] {\n\tif (!response.success || !response.data || typeof response.data !== \"object\") {\n\t\treturn [];\n\t}\n\tconst heartbeats = (response.data as { heartbeats?: unknown }).heartbeats;\n\treturn Array.isArray(heartbeats) ? (heartbeats as AgentConnectionHeartbeat[]) : [];\n}\n\nfunction sortCronJobs(jobs: AgentCronJob[]): AgentCronJob[] {\n\treturn jobs.sort((left, right) => {\n\t\tif (left.nextRunAt === right.nextRunAt) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (left.nextRunAt === undefined) {\n\t\t\treturn 1;\n\t\t}\n\t\tif (right.nextRunAt === undefined) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn Date.parse(left.nextRunAt) - Date.parse(right.nextRunAt);\n\t});\n}\n\nfunction descriptorKey(socketPath: string): string {\n\treturn createHash(\"sha256\").update(normalizeSocketPath(socketPath)).digest(\"hex\").slice(0, 12);\n}\n\nfunction defaultWorkerDescriptorDir(agentDir: string, socketPath: string): string {\n\treturn join(agentDir, \"daemon-workers\", descriptorKey(socketPath));\n}\n\nexport function idleEvictionSweepIntervalMs(idleEvictionMinutes: IdleEvictionMinutes): number {\n\tif (idleEvictionMinutes === \"off\") return IDLE_EVICTION_MAX_SWEEP_INTERVAL_MS;\n\treturn Math.max(\n\t\tIDLE_EVICTION_MIN_SWEEP_INTERVAL_MS,\n\t\tMath.min(IDLE_EVICTION_MAX_SWEEP_INTERVAL_MS, (idleEvictionMinutes * 60_000) / 3),\n\t);\n}\n\nfunction workerSocketPath(supervisorSocketPath: string, workerId: string): string {\n\tconst key = descriptorKey(supervisorSocketPath);\n\tif (process.platform === \"win32\") {\n\t\treturn `\\\\\\\\.\\\\pipe\\\\${PRODUCT.command}-worker-${key}-${workerId.slice(0, 12)}`;\n\t}\n\treturn join(defaultDaemonSocketDir(), `worker-${key}-${workerId.slice(0, 12)}.sock`);\n}\n\nfunction isFinalizedTranscriptEvent(eventType: string | undefined): boolean {\n\treturn (\n\t\teventType === \"message_end\" ||\n\t\teventType === \"turn_end\" ||\n\t\teventType === \"compaction_end\" ||\n\t\teventType === \"bash_end\"\n\t);\n}\n\nfunction normalizeCapabilities(\n\tcapabilities: readonly DaemonClientCapability[] | undefined,\n\tsupportsExtensionUi: boolean | undefined,\n): Set<DaemonClientCapability> {\n\tconst normalized = new Set(capabilities ?? DAEMON_DEFAULT_CLIENT_CAPABILITIES);\n\tif (supportsExtensionUi) {\n\t\tnormalized.add(\"extension_ui\");\n\t}\n\treturn normalized;\n}\n\nexport async function runDaemonSupervisorMode(options: DaemonSupervisorOptions): Promise<never> {\n\tconst socketPath = normalizeSocketPath(options.socketPath ?? defaultDaemonSocketPath());\n\tconst supervisor = new DaemonSupervisor(socketPath, options);\n\tawait supervisor.start();\n\treturn new Promise(() => {});\n}\n\nexport class DaemonSupervisor {\n\tprivate server?: Server;\n\tprivate readonly ready: Promise<void>;\n\tprivate markReady: () => void = () => {};\n\tprivate rejectReady: (error: Error) => void = () => {};\n\tprivate ownsSocketPath = false;\n\tprivate socketIdentity?: DaemonSocketIdentity;\n\tprivate socketLease?: DaemonSocketPathLease;\n\tprivate socketLeaseCompromise?: Error;\n\tprivate ownership?: Awaited<ReturnType<typeof acquireDaemonSupervisorOwnership>>;\n\tprivate cleanupPromise?: Promise<void>;\n\tprivate shuttingDown = false;\n\tprivate startupComplete = false;\n\tprivate updateRestartPhase?: \"draining\" | \"fencing\" | \"prepared\";\n\tprivate readonly mutationDrain = new MutationDrainLatch();\n\tprivate readonly clients = new Set<DaemonSocketClient>();\n\tprivate readonly connectionIds = new WeakMap<DaemonSocketClient, string>();\n\tprivate readonly sessionInputPauseEpochs = new WeakMap<DaemonSocketClient, number>();\n\tprivate readonly detachingInputPauseSessions = new WeakMap<DaemonSocketClient, Set<string>>();\n\tprivate readonly protocolClientIds = new WeakMap<DaemonSocketClient, string>();\n\tprivate readonly workers = new Map<string, ResidentWorker>();\n\tprivate workerStopCounts?: Map<ResidentWorker, number>;\n\tprivate readonly openingWorkers = new Map<string, Promise<ResidentWorker>>();\n\t/** Public admission ids are scoped to the socket that registered them. */\n\tprivate readonly promptAdmissions = new Map<DaemonSocketClient, Map<string, SupervisorPromptAdmission>>();\n\tprivate readonly sessionInputPauses = new Map<string, SupervisorSessionInputPause>();\n\tprivate readonly signalCleanupHandlers: Array<() => void> = [];\n\tprivate readonly descriptorDir: string;\n\tprivate readonly generation = randomUUID();\n\tprivate readonly supervisorConfigPath: string;\n\tprivate readonly defaultSessionConfig: AgentSessionRuntimeConfig;\n\tprivate readonly snapshotCacheRoot: string;\n\tprivate commandJournal!: CommandRecoveryJournal;\n\tprivate readonly streamReconstructor = new CompactAssistantStreamReconstructor();\n\tprivate readonly compactCatchupInProgress = new Set<string>();\n\tprivate readonly pendingSessionNames = new Set<string>();\n\tprivate readonly catalog: DaemonCatalogClient;\n\tprivate readonly settingsManager: SettingsManager;\n\tprivate readonly rlmCapacity: DaemonRlmCapacityCoordinator;\n\tprivate readonly pendingRlmCapacity = new Set<ResidentWorker>();\n\tprivate readonly releasedDuringCapacityRecovery = new Map<ResidentWorker, Set<string>>();\n\tprivate rosterStore?: AgentRoster;\n\tprivate readonly pendingRosterChanged = new Set<string>();\n\tprivate readonly pendingRosterRemoved = new Set<string>();\n\t/** Ids declared to subscribers: gates removals to once and keeps owned-only row ids private. */\n\tprivate readonly publishedRosterIds = new Set<string>();\n\tprivate rosterPushScheduled = false;\n\tprivate rosterWatchdogTimer?: ReturnType<typeof setInterval>;\n\tprivate rlmSpawnLedgerInstance?: RlmSpawnLedger;\n\tprivate rlmJournalOwner?: RlmJournalOwner;\n\tprivate rlmJournalClose?: Promise<void>;\n\tprivate idleEvictionTimer?: ReturnType<typeof setTimeout>;\n\tprivate idleEvictionSweep?: Promise<void>;\n\tprivate idleEvictionFence?: Promise<void>;\n\tprivate scheduledWakeTimer?: ReturnType<typeof setTimeout>;\n\tprivate scheduledWakeRecompute?: Promise<void>;\n\tprivate scheduledWakeRecomputeQueued = false;\n\tprivate readonly scheduledWakeFailures = new Map<string, number>();\n\n\tconstructor(\n\t\tprivate readonly socketPath: string,\n\t\toptions: DaemonSupervisorOptions,\n\t) {\n\t\tthis.ready = new Promise<void>((resolveReady, rejectReady) => {\n\t\t\tthis.markReady = resolveReady;\n\t\t\tthis.rejectReady = rejectReady;\n\t\t});\n\t\tvoid this.ready.catch(() => undefined);\n\t\tconst agentDir = options.defaultSessionConfig.agentDir;\n\t\tif (!agentDir) {\n\t\t\tthrow new Error(\"Daemon supervisor config is missing agentDir\");\n\t\t}\n\t\tthis.descriptorDir = options.descriptorDir ?? defaultWorkerDescriptorDir(agentDir, socketPath);\n\t\tthis.supervisorConfigPath = join(this.descriptorDir, SUPERVISOR_CONFIG_FILE_NAME);\n\t\tthis.defaultSessionConfig = mergeAgentSessionRuntimeConfig(\n\t\t\toptions.defaultSessionConfig,\n\t\t\tthis.loadPersistedSupervisorConfig(),\n\t\t);\n\t\tthis.snapshotCacheRoot = join(this.descriptorDir, \"snapshot-cache\", this.generation);\n\t\tthis.catalog = new DaemonCatalogClient((message) => this.log(message));\n\t\tthis.settingsManager = SettingsManager.create(process.cwd(), this.defaultSessionConfig.agentDir ?? agentDir);\n\t\tthis.rlmCapacity = new DaemonRlmCapacityCoordinator(this.settingsManager);\n\t}\n\n\tasync start(): Promise<void> {\n\t\ttry {\n\t\t\tconst agentDir = this.defaultSessionConfig.agentDir;\n\t\t\tif (!agentDir) {\n\t\t\t\tthrow new Error(\"Daemon supervisor config is missing agentDir\");\n\t\t\t}\n\t\t\tthis.socketLease = await acquireDaemonSocketPathLease(this.socketPath);\n\t\t\tthis.socketLease?.onCompromised((error) => this.handleSocketLeaseCompromised(error));\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tawait waitForDaemonStartupFence(this.socketPath);\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tconst journalScope = this.rlmJournalScope();\n\t\t\tthis.ownership = await acquireDaemonSupervisorOwnership({\n\t\t\t\tsocketPath: this.socketPath,\n\t\t\t\tdescriptorDir: this.descriptorDir,\n\t\t\t\tagentDir,\n\t\t\t\tjournalPath: journalScope.journalPath,\n\t\t\t\tgeneration: this.generation,\n\t\t\t\tappVersion: VERSION,\n\t\t\t});\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tthis.rlmJournalOwner = await RlmJournalOwner.open(journalScope);\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tawait prepareDaemonSocketPath(this.socketPath, this.socketLease);\n\n\t\t\tmkdirSync(this.descriptorDir, { recursive: true, mode: 0o700 });\n\t\t\tchmodSync(this.descriptorDir, 0o700);\n\t\t\tthis.persistSupervisorConfig();\n\t\t\trmSync(this.snapshotCacheRoot, { recursive: true, force: true });\n\t\t\tmkdirSync(this.snapshotCacheRoot, { recursive: true, mode: 0o700 });\n\t\t\tthis.commandJournal = new CommandRecoveryJournal(join(this.descriptorDir, \"command-journal.jsonl\"));\n\t\t\tthis.loadWorkerDescriptors();\n\t\t\tconst workersToAdopt = [...this.workers.values()];\n\t\t\tfor (const worker of workersToAdopt) this.pendingRlmCapacity.add(worker);\n\n\t\t\tthis.server = createServer((socket) => this.handleConnection(socket));\n\t\t\tawait this.listen();\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tthis.socketIdentity = getDaemonSocketIdentity(this.socketPath);\n\t\t\tif (process.platform !== \"win32\" && !this.socketIdentity) {\n\t\t\t\tthrow new Error(`Could not capture daemon socket identity: ${this.socketPath}`);\n\t\t\t}\n\t\t\tthis.ownsSocketPath = true;\n\t\t\trestrictDaemonSocketPath(this.socketPath);\n\n\t\t\tthis.registerSignalHandlers();\n\t\t\tconst ownedSessionFiles = new Set(\n\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t.flatMap((worker) => [worker.descriptor.sessionFile, worker.descriptor.createCommand.sessionPath])\n\t\t\t\t\t.filter((path): path is string => typeof path === \"string\")\n\t\t\t\t\t.map((path) => resolve(path)),\n\t\t\t);\n\t\t\tconst migratedJobs = migrateLegacyCronJobsToSessionArtifacts(getCronJobsPath(agentDir), {\n\t\t\t\tisSessionOwned: (job) => ownedSessionFiles.has(resolve(job.sessionFile)),\n\t\t\t});\n\t\t\tif (migratedJobs > 0) {\n\t\t\t\tthis.log(`Migrated ${migratedJobs} scheduled jobs into session artifacts`);\n\t\t\t}\n\t\t\tawait this.catalog.start().catch((error) => this.log(`Could not start daemon catalog: ${String(error)}`));\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tawait this.seedRosterLedger();\n\t\t\tlet adoptionFailure: unknown;\n\t\t\tlet adoptionFailed = false;\n\t\t\tawait Promise.all(\n\t\t\t\tworkersToAdopt.map(async (worker) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.adoptOrRecoverWorker(worker, this.ready);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (!adoptionFailed) {\n\t\t\t\t\t\t\tadoptionFailed = true;\n\t\t\t\t\t\t\tadoptionFailure = error;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (adoptionFailed) {\n\t\t\t\tthrow adoptionFailure;\n\t\t\t}\n\t\t\tfor (const worker of this.workers.values()) {\n\t\t\t\tthis.scheduleOwnedWorkerCleanup(worker);\n\t\t\t}\n\t\t\tthis.scheduleIdleEvictionSweep();\n\t\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\t\tthis.rosterWatchdogTimer = setInterval(() => this.sweepRosterStaleness(), ROSTER_WATCHDOG_INTERVAL_MS);\n\t\t\tthis.rosterWatchdogTimer.unref();\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tawait this.ownership.updatePhase(\"owner\");\n\t\t\tthis.assertSocketLeaseHeld();\n\t\t\tthis.startupComplete = true;\n\t\t\tthis.log(`${PRODUCT.name} daemon supervisor ${this.generation} listening on ${this.socketPath}`);\n\t\t\tthis.markReady();\n\t\t} catch (error) {\n\t\t\tconst startupError = error instanceof Error ? error : new Error(String(error));\n\t\t\tthis.log(`Daemon supervisor startup failed: ${startupError.stack ?? startupError.message}`);\n\t\t\tawait this.cleanupSupervisorResources();\n\t\t\tthis.rejectReady(startupError);\n\t\t\tthrow startupError;\n\t\t}\n\t}\n\n\tprivate listen(): Promise<void> {\n\t\treturn new Promise<void>((resolveListen, rejectListen) => {\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\tthis.server?.off(\"listening\", onListening);\n\t\t\t\trejectListen(error);\n\t\t\t};\n\t\t\tconst onListening = () => {\n\t\t\t\tthis.server?.off(\"error\", onError);\n\t\t\t\tresolveListen();\n\t\t\t};\n\t\t\tthis.server?.once(\"error\", onError);\n\t\t\tthis.server?.once(\"listening\", onListening);\n\t\t\tthis.server?.listen(this.socketPath);\n\t\t});\n\t}\n\n\tprivate log(message: string): void {\n\t\tconsole.error(message);\n\t\tstructuredLog.warn(message, { socketPath: this.socketPath });\n\t\tappendRotatingLog(getDaemonLogPath(this.socketPath), `[${new Date().toISOString()}] supervisor: ${message}`);\n\t}\n\n\tprivate clearIdleEvictionTimer(): void {\n\t\tif (!this.idleEvictionTimer) return;\n\t\tclearTimeout(this.idleEvictionTimer);\n\t\tthis.idleEvictionTimer = undefined;\n\t}\n\n\tprivate clearRosterWatchdogTimer(): void {\n\t\tif (!this.rosterWatchdogTimer) return;\n\t\tclearInterval(this.rosterWatchdogTimer);\n\t\tthis.rosterWatchdogTimer = undefined;\n\t}\n\n\tprivate clearScheduledWakeTimer(): void {\n\t\tif (!this.scheduledWakeTimer) return;\n\t\tclearTimeout(this.scheduledWakeTimer);\n\t\tthis.scheduledWakeTimer = undefined;\n\t}\n\n\t// The supervisor only wakes non-resident trees; firing and delivery stay worker-owned.\n\tprivate scheduleScheduledSessionWakeRecompute(): void {\n\t\tif (this.shuttingDown) return;\n\t\tif (this.scheduledWakeRecompute) {\n\t\t\tthis.scheduledWakeRecomputeQueued = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.scheduledWakeRecompute = this.recomputeScheduledSessionWake()\n\t\t\t.catch((error) => this.log(`Scheduled-session wake recompute failed: ${String(error)}`))\n\t\t\t.finally(() => {\n\t\t\t\tthis.scheduledWakeRecompute = undefined;\n\t\t\t\tif (this.scheduledWakeRecomputeQueued) {\n\t\t\t\t\tthis.scheduledWakeRecomputeQueued = false;\n\t\t\t\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\t/** Durable truth: the ledger family (fork headers stripped) plus each session's scheduled-jobs artifact. */\n\tprivate async collectPassiveScheduledJobs(\n\t\tincludeInactive = false,\n\t): Promise<Array<{ rootSessionFile: string; job: AgentCronJob; info: SessionInfo }>> {\n\t\tconst pendingCancelRoots = new Set<string>();\n\t\tfor (const intent of this.collectEphemeralCancelIntents()) {\n\t\t\tconst context = this.workerSessionArtifactContext(intent);\n\t\t\tif (!context || !intent.descriptor.rootSessionId) continue;\n\t\t\ttry {\n\t\t\t\tawait this.cancelScheduledJobsForSessionTree(intent.descriptor.rootSessionId, context.sessionFile);\n\t\t\t\tthis.deleteWorkerDescriptor(intent);\n\t\t\t} catch {\n\t\t\t\t// Still owned until the cancel lands; the tree stays excluded below.\n\t\t\t\tpendingCancelRoots.add(canonicalSessionPath(context.sessionFile));\n\t\t\t}\n\t\t}\n\t\tconst infos = await this.rlmSpawnLedger().family();\n\t\tconst infoByPath = new Map(infos.map((info) => [canonicalSessionPath(info.path), info] as const));\n\t\tconst storeBySessionId = new Map<string, AgentCronJobStore>();\n\t\tconst infoBySessionId = new Map<string, SessionInfo>();\n\t\tfor (const info of infos) {\n\t\t\tif (info.state !== undefined && info.state.status !== \"active\") continue;\n\t\t\tconst artifactDir = getSessionArtifactPathForFile(resolve(info.path), info.id);\n\t\t\tif (!existsSync(join(artifactDir, SESSION_SCHEDULED_JOBS_FILENAME))) continue;\n\t\t\tconst store = AgentCronJobStore.forSessionArtifacts();\n\t\t\tstore.registerSessionArtifact(info.id, artifactDir);\n\t\t\tstoreBySessionId.set(info.id, store);\n\t\t\tinfoBySessionId.set(info.id, info);\n\t\t}\n\t\tif (infoBySessionId.size === 0) return [];\n\t\tconst uncoveredRootFor = (info: SessionInfo): string | undefined => {\n\t\t\tlet current = info;\n\t\t\tconst visited = new Set([canonicalSessionPath(current.path)]);\n\t\t\twhile (true) {\n\t\t\t\ttry {\n\t\t\t\t\tif (this.findWorkerBySessionFile(current.path)) return undefined;\n\t\t\t\t} catch {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tif (!current.parentSessionPath) break;\n\t\t\t\tconst parent = infoByPath.get(canonicalSessionPath(current.parentSessionPath));\n\t\t\t\tif (!parent || visited.has(canonicalSessionPath(parent.path))) break;\n\t\t\t\tvisited.add(canonicalSessionPath(parent.path));\n\t\t\t\tcurrent = parent;\n\t\t\t}\n\t\t\treturn current.path;\n\t\t};\n\t\tconst results: Array<{ rootSessionFile: string; job: AgentCronJob; info: SessionInfo }> = [];\n\t\tfor (const [artifactSessionId, store] of storeBySessionId) {\n\t\t\tlet jobs: AgentCronJob[];\n\t\t\ttry {\n\t\t\t\tjobs = store.list();\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Skipping unreadable scheduled jobs for session ${artifactSessionId}: ${String(error)}`);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const job of jobs) {\n\t\t\t\tif (!includeInactive && job.status !== \"active\" && job.status !== \"paused\") continue;\n\t\t\t\tconst info = infoBySessionId.get(job.sessionId);\n\t\t\t\tif (!info) continue;\n\t\t\t\tconst rootSessionFile = uncoveredRootFor(info);\n\t\t\t\tif (rootSessionFile === undefined) continue;\n\t\t\t\tif (pendingCancelRoots.has(canonicalSessionPath(rootSessionFile))) continue;\n\t\t\t\tresults.push({ rootSessionFile, job, info });\n\t\t\t}\n\t\t}\n\t\treturn results;\n\t}\n\n\tprivate async recomputeScheduledSessionWake(): Promise<void> {\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\tconst candidates = await this.collectPassiveScheduledJobs();\n\t\tthis.clearScheduledWakeTimer();\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\tconst now = Date.now();\n\t\tconst wakeTimes: number[] = [];\n\t\tconst candidateRoots = new Set(candidates.map(({ rootSessionFile }) => canonicalSessionPath(rootSessionFile)));\n\t\tfor (const root of [...this.scheduledWakeFailures.keys()]) {\n\t\t\tif (!candidateRoots.has(root)) this.scheduledWakeFailures.delete(root);\n\t\t}\n\t\tfor (const { rootSessionFile, job } of candidates) {\n\t\t\tif (job.status !== \"active\" || job.nextRunAt === undefined) continue;\n\t\t\tconst runAt = Date.parse(job.nextRunAt);\n\t\t\tif (!Number.isFinite(runAt)) continue;\n\t\t\t// The failure floor keeps an overdue job off a hot retry loop.\n\t\t\tconst failedAt = this.scheduledWakeFailures.get(canonicalSessionPath(rootSessionFile));\n\t\t\twakeTimes.push(failedAt !== undefined ? Math.max(runAt, failedAt + SCHEDULED_WAKE_RETRY_MS) : runAt);\n\t\t}\n\t\tif (wakeTimes.length === 0) return;\n\t\tconst delay = Math.min(Math.max(0, Math.min(...wakeTimes) - now), SCHEDULED_WAKE_MAX_TIMEOUT_MS);\n\t\tthis.scheduledWakeTimer = setTimeout(() => {\n\t\t\tthis.scheduledWakeTimer = undefined;\n\t\t\tvoid this.wakeDueScheduledSessions().catch((error) =>\n\t\t\t\tthis.log(`Scheduled-session wake failed: ${String(error)}`),\n\t\t\t);\n\t\t}, delay);\n\t\tthis.scheduledWakeTimer.unref();\n\t}\n\n\tprivate async wakeDueScheduledSessions(now = Date.now()): Promise<void> {\n\t\t// Disarmed during update-restart preparation; the phase transition or next boot re-arms once.\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) {\n\t\t\tthis.clearScheduledWakeTimer();\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst due = new Map<string, string>();\n\t\t\tfor (const { rootSessionFile, job } of await this.collectPassiveScheduledJobs()) {\n\t\t\t\tif (job.status !== \"active\" || job.nextRunAt === undefined) continue;\n\t\t\t\tconst runAt = Date.parse(job.nextRunAt);\n\t\t\t\tif (!Number.isFinite(runAt) || runAt > now) continue;\n\t\t\t\tdue.set(canonicalSessionPath(rootSessionFile), rootSessionFile);\n\t\t\t}\n\t\t\tfor (const [rootKey, sessionPath] of due) {\n\t\t\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.createOrReuseWorker(SCHEDULED_WAKE_CLIENT_ID, { type: \"create\", sessionPath });\n\t\t\t\t\tthis.scheduledWakeFailures.delete(rootKey);\n\t\t\t\t\tthis.log(`Woke session worker for a due scheduled job: ${sessionPath}`);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.scheduledWakeFailures.set(rootKey, Date.now());\n\t\t\t\t\tthis.log(`Scheduled wake failed for ${sessionPath}: ${String(error)}`);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\t}\n\t}\n\n\tprivate scheduleIdleEvictionSweep(): void {\n\t\tif (this.shuttingDown || this.idleEvictionTimer || this.idleEvictionSweep) return;\n\t\tconst delayMs = idleEvictionSweepIntervalMs(this.settingsManager.getIdleEvictionMinutes());\n\t\tthis.idleEvictionTimer = setTimeout(() => {\n\t\t\tthis.idleEvictionTimer = undefined;\n\t\t\tconst sweep = this.runIdleEvictionSweep()\n\t\t\t\t.catch((error) => this.log(`Idle eviction sweep failed: ${String(error)}`))\n\t\t\t\t.finally(() => {\n\t\t\t\t\tif (this.idleEvictionSweep === sweep) this.idleEvictionSweep = undefined;\n\t\t\t\t\tthis.scheduleIdleEvictionSweep();\n\t\t\t\t});\n\t\t\tthis.idleEvictionSweep = sweep;\n\t\t}, delayMs);\n\t\tthis.idleEvictionTimer.unref();\n\t}\n\n\tprivate workerEvictionSnapshot(worker: ResidentWorker): WorkerEvictionSnapshot {\n\t\treturn {\n\t\t\tlifecycle: worker.descriptor.lifecycle,\n\t\t\tisConnected: worker.client !== undefined,\n\t\t\tisStopping: this.isWorkerStopping(worker),\n\t\t\thasOwnerClient: worker.descriptor.ownerClientId !== undefined,\n\t\t\tisPreparingUpdateRestart:\n\t\t\t\tthis.updateRestartPhase !== undefined || worker.updateRestartPrepareClient !== undefined,\n\t\t\thasWakeBlindSchedule: this.isWakeBlindScheduledWorker(worker),\n\t\t\tsessions: this.workerRosterEntries(worker)\n\t\t\t\t.filter((entry) => !entry.queuedChild)\n\t\t\t\t.map(sessionSummaryFromRosterEntry)\n\t\t\t\t.map((summary) => {\n\t\t\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tisSessionActive: isSessionSummaryBusy(summary),\n\t\t\t\t\t\tattachedClients: this.attachedClientCount(summary, activeSessionId),\n\t\t\t\t\t\thasRegisteredCronJob: summary.hasRegisteredCronJob === true,\n\t\t\t\t\t\tlastActivityAt: Date.parse(summary.lastActivityAt ?? \"\"),\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t};\n\t}\n\n\t/** A schedule whose root file sits outside the enumerable sessions root is invisible to the wake scan; keep it resident. */\n\tprivate isWakeBlindScheduledWorker(worker: ResidentWorker): boolean {\n\t\tconst sessionFile = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\tconst agentDir = this.defaultSessionConfig.agentDir;\n\t\tif (!sessionFile || !agentDir) return false;\n\t\tconst sessionsRoot = canonicalSessionPath(this.defaultSessionConfig.sessionDir ?? getSessionsDir(agentDir));\n\t\tif (dirname(canonicalSessionPath(sessionFile)) === sessionsRoot) return false;\n\t\treturn this.workerRosterEntries(worker).some(\n\t\t\t(entry) => entry.summary.hasRegisteredHeartbeat === true || entry.summary.hasRegisteredCronJob === true,\n\t\t);\n\t}\n\n\tprivate async runIdleEvictionSweep(now = Date.now()): Promise<void> {\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined || this.idleEvictionFence) return;\n\t\tawait this.settingsManager.reload();\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\tconst idleEvictionMinutes = this.settingsManager.getIdleEvictionMinutes();\n\t\tif (idleEvictionMinutes === \"off\") return;\n\n\t\tconst refreshed = new Set<ResidentWorker>();\n\t\tawait Promise.all(\n\t\t\t[...this.workers.values()].map(async (worker) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.refreshWorkerSummaries(worker);\n\t\t\t\t\trefreshed.add(worker);\n\t\t\t\t} catch {\n\t\t\t\t\t// A disconnected or transitioning worker is never an eviction candidate.\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t\tconst candidates = [...refreshed].filter((worker) =>\n\t\t\tcanEvictWorker(this.workerEvictionSnapshot(worker), idleEvictionMinutes, now),\n\t\t);\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t// Whole-tree candidates skip child work because stopWorker releases everything.\n\t\tawait Promise.all(\n\t\t\t[...refreshed]\n\t\t\t\t.filter((worker) => !candidates.includes(worker))\n\t\t\t\t.map(async (worker) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await worker.client?.requestWorker(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"worker_passivate_idle_children\",\n\t\t\t\t\t\t\t\tidleEvictionMinutes,\n\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\tlimit: CHILD_PASSIVATION_PER_WORKER_CAP,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t30_000,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (response && !response.success) throw new Error(response.error);\n\t\t\t\t\t\tawait this.refreshWorkerSummaries(worker);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\trefreshed.delete(worker);\n\t\t\t\t\t\tthis.log(`Child passivation sweep failed for worker ${worker.descriptor.workerId}: ${String(error)}`);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t);\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\n\t\tawait this.withEvictionFence(\"Timed out draining daemon mutations for idle eviction\", async () => {\n\t\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t\tawait Promise.all(\n\t\t\t\tcandidates.map((worker) => this.refreshWorkerSummaries(worker).catch(() => refreshed.delete(worker))),\n\t\t\t);\n\t\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t\tconst evictable = candidates.filter(\n\t\t\t\t(worker) =>\n\t\t\t\t\trefreshed.has(worker) &&\n\t\t\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\t\t\tcanEvictWorker(this.workerEvictionSnapshot(worker), idleEvictionMinutes, now),\n\t\t\t);\n\t\t\t// Promise.all may reject and release the fence while sibling stops are still\n\t\t\t// finishing. That is safe: a racing mutation either reaches a live worker or\n\t\t\t// gets a clean disconnected/unknown-session error.\n\t\t\tawait Promise.all(\n\t\t\t\tevictable.map(async (worker) => {\n\t\t\t\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\t\t\t\tconst snapshot = this.workerEvictionSnapshot(worker);\n\t\t\t\t\tconst idleMinutes = Math.floor(\n\t\t\t\t\t\tMath.min(...snapshot.sessions.map((session) => now - session.lastActivityAt)) / 60_000,\n\t\t\t\t\t);\n\t\t\t\t\tconst root = worker.summaries.get(worker.descriptor.rootActiveSessionId);\n\t\t\t\t\tawait this.stopWorker(worker, true);\n\t\t\t\t\tthis.log(\n\t\t\t\t\t\t`Evicted idle worker ${worker.descriptor.workerId} root=${root?.sessionId ?? worker.descriptor.rootSessionId ?? worker.descriptor.rootActiveSessionId} idleMinutes=${idleMinutes} sessions=${snapshot.sessions.length}`,\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\t}\n\n\t/** Waits for any held eviction fence, then takes the slot; release clears it only if still ours. */\n\tprivate async acquireIdleEvictionFence(): Promise<() => void> {\n\t\twhile (this.idleEvictionFence) await this.idleEvictionFence;\n\t\tlet releaseFence: () => void = () => {};\n\t\tconst fence = new Promise<void>((resolveFence) => {\n\t\t\treleaseFence = resolveFence;\n\t\t});\n\t\tthis.idleEvictionFence = fence;\n\t\treturn () => {\n\t\t\tif (this.idleEvictionFence === fence) this.idleEvictionFence = undefined;\n\t\t\treleaseFence();\n\t\t};\n\t}\n\n\t/** Runs a passivation decision under the eviction fence after draining admitted mutations. */\n\tprivate async withEvictionFence(drainMessage: string, action: () => Promise<void>): Promise<void> {\n\t\tconst releaseFence = await this.acquireIdleEvictionFence();\n\t\ttry {\n\t\t\tawait this.mutationDrain.waitForDrain(0, AbortSignal.timeout(IDLE_EVICTION_DRAIN_TIMEOUT_MS), drainMessage);\n\t\t\tawait action();\n\t\t} finally {\n\t\t\treleaseFence();\n\t\t}\n\t}\n\n\tprivate async passivateWorkerIfStillEligible(\n\t\tworker: ResidentWorker,\n\t\tisStillEligible: () => boolean,\n\t\tdescribeEvicted: () => string,\n\t): Promise<void> {\n\t\tawait this.refreshWorkerSummaries(worker, false, true);\n\t\tif (!isStillEligible()) return;\n\t\tawait this.stopWorker(worker, true);\n\t\tthis.log(describeEvicted());\n\t}\n\n\tprivate async evictEmptySessionOnLastDetach(activeSessionId: string): Promise<void> {\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined) return;\n\t\tconst worker = this.matchWorkers(activeSessionId)[0]?.worker;\n\t\tif (\n\t\t\t!worker ||\n\t\t\tworker.descriptor.lifecycle !== \"ready\" ||\n\t\t\t!worker.client ||\n\t\t\tworker.descriptor.ownerClientId !== undefined || // owned workers have their own cleanup path\n\t\t\tthis.isWorkerStopping(worker)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tawait this.refreshWorkerSummaries(worker, false, true);\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (!this.isEmptyDetachEvictionCandidate(worker)) return;\n\t\ttry {\n\t\t\t// Idle-sweep coordination: fence new mutations, drain admitted ones, re-read before deciding.\n\t\t\tawait this.withEvictionFence(\"Timed out draining daemon mutations for empty-session eviction\", () =>\n\t\t\t\tthis.passivateWorkerIfStillEligible(\n\t\t\t\t\tworker,\n\t\t\t\t\t() => this.isEmptyDetachEvictionCandidate(worker),\n\t\t\t\t\t() =>\n\t\t\t\t\t\t`Evicted empty session worker ${worker.descriptor.workerId} root=${worker.descriptor.rootSessionId ?? worker.descriptor.rootActiveSessionId} on last client detach`,\n\t\t\t\t),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthis.log(`Empty-session eviction failed for worker ${worker.descriptor.workerId}: ${String(error)}`);\n\t\t}\n\t}\n\n\tprivate isEmptyDetachEvictionCandidate(worker: ResidentWorker): boolean {\n\t\tif (\n\t\t\tthis.shuttingDown ||\n\t\t\tthis.updateRestartPhase !== undefined ||\n\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker ||\n\t\t\tthis.isWorkerStopping(worker) ||\n\t\t\tthis.isWakeBlindScheduledWorker(worker)\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\tconst summaries = this.workerRosterEntries(worker)\n\t\t\t.filter((entry) => !entry.queuedChild)\n\t\t\t.map(sessionSummaryFromRosterEntry);\n\t\tconst hasAttachedClient = summaries.some(\n\t\t\t(summary) => this.attachedClientCount(summary, summary.activeSessionId ?? summary.id) > 0,\n\t\t);\n\t\treturn summaries.length > 0 && !hasAttachedClient && summaries.every(isEvictableEmptySessionSummary);\n\t}\n\n\tprivate async assertCurrentOwnership(): Promise<void> {\n\t\tconst ownership = this.ownership;\n\t\tif (!ownership) {\n\t\t\tconst error = new Error(\n\t\t\t\t`Daemon supervisor generation ${this.generation} holds no registry ownership (never acquired or already released); ` +\n\t\t\t\t\t`socket: ${this.socketPath}; restart the daemon to recover — sessions are preserved`,\n\t\t\t);\n\t\t\tObject.assign(error, { code: \"supervisor_generation_stale\" as const });\n\t\t\tthis.fenceRlmJournalOwner();\n\t\t\tthrow error;\n\t\t}\n\t\ttry {\n\t\t\tawait ownership.assertCurrent();\n\t\t} catch (error) {\n\t\t\tthis.fenceRlmJournalOwner();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async assertServingCurrentOwnership(allowWorkerLedger = false): Promise<void> {\n\t\tthis.assertSupervisorServing(allowWorkerLedger);\n\t\tawait this.assertCurrentOwnership();\n\t\tthis.assertSupervisorServing(allowWorkerLedger);\n\t}\n\n\tprivate async assertRecoveryAllowed(): Promise<void> {\n\t\tawait this.assertServingCurrentOwnership();\n\t\tif (await isDaemonShutdownAdmissionActive()) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Daemon shutdown admission cancelled worker recovery\");\n\t\t}\n\t}\n\n\tprivate supervisorAuthenticationClaim(): {\n\t\tsupervisorGeneration: string;\n\t\tsupervisorPid: number;\n\t\tsupervisorProcessStartId?: string;\n\t\tsupervisorSocketPath: string;\n\t} {\n\t\tconst record = this.ownership?.record;\n\t\tif (!record) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Daemon supervisor ownership is unavailable\");\n\t\t}\n\t\treturn {\n\t\t\tsupervisorGeneration: this.generation,\n\t\t\tsupervisorPid: record.pid,\n\t\t\t...(record.processStartId ? { supervisorProcessStartId: record.processStartId } : {}),\n\t\t\tsupervisorSocketPath: record.socketPath,\n\t\t};\n\t}\n\n\tprivate loadWorkerDescriptors(): void {\n\t\tfor (const name of readdirSync(this.descriptorDir)) {\n\t\t\tif (name === SUPERVISOR_CONFIG_FILE_NAME || !name.endsWith(\".json\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst path = join(this.descriptorDir, name);\n\t\t\ttry {\n\t\t\t\tconst descriptor: unknown = JSON.parse(readFileSync(path, \"utf8\"));\n\t\t\t\tif (!isDaemonWorkerDescriptor(descriptor, this.socketPath)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tdescriptor.supervisorSocketPath = normalizeSocketPath(descriptor.supervisorSocketPath);\n\t\t\t\tdescriptor.lifecycle = \"recovering\";\n\t\t\t\tdescriptor.recoveryJournalPath ??= join(this.descriptorDir, `${descriptor.workerId}.recovery.jsonl`);\n\t\t\t\tdescriptor.orphanProcessJournalPath ??= join(this.descriptorDir, `${descriptor.workerId}.orphans.jsonl`);\n\t\t\t\tconst durableDescriptor = durableDaemonWorkerDescriptor(descriptor);\n\t\t\t\tconst worker: ResidentWorker = {\n\t\t\t\t\tdescriptor: durableDescriptor,\n\t\t\t\t\tdescriptorPath: path,\n\t\t\t\t\tsummaries: new Map(),\n\t\t\t\t\tsnapshotCache: new Map(),\n\t\t\t\t\ttranscriptCaches: new Map(),\n\t\t\t\t\tsnapshotGenerations: new Map(),\n\t\t\t\t\tsnapshotLoads: new Map(),\n\t\t\t\t\tintentionalStop: durableDescriptor.stopRequestedAt !== undefined,\n\t\t\t\t\tstopRevision: 0,\n\t\t\t\t};\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tthis.workers.set(durableDescriptor.workerId, worker);\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Ignoring invalid worker descriptor ${path}: ${String(error)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Trees whose ephemeral-stop cancel failed stay owned until a retry lands: tombstoned client-owned descriptors with no resident worker. */\n\tprivate collectEphemeralCancelIntents(): Array<{ descriptor: DaemonWorkerDescriptor; descriptorPath: string }> {\n\t\tconst intents: Array<{ descriptor: DaemonWorkerDescriptor; descriptorPath: string }> = [];\n\t\tlet names: string[];\n\t\ttry {\n\t\t\tnames = readdirSync(this.descriptorDir);\n\t\t} catch {\n\t\t\treturn intents;\n\t\t}\n\t\tfor (const name of names) {\n\t\t\tif (name === SUPERVISOR_CONFIG_FILE_NAME || !name.endsWith(\".json\")) continue;\n\t\t\tconst descriptorPath = join(this.descriptorDir, name);\n\t\t\tlet descriptor: unknown;\n\t\t\ttry {\n\t\t\t\tdescriptor = JSON.parse(readFileSync(descriptorPath, \"utf8\"));\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!isDaemonWorkerDescriptor(descriptor, this.socketPath)) continue;\n\t\t\tif (descriptor.stopRequestedAt === undefined || descriptor.ownerClientId === undefined) continue;\n\t\t\tif (this.workers.has(descriptor.workerId)) continue;\n\t\t\tintents.push({ descriptor, descriptorPath });\n\t\t}\n\t\treturn intents;\n\t}\n\n\tprivate loadPersistedSupervisorConfig(): AgentSessionRuntimeConfig | undefined {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(\n\t\t\t\treadFileSync(this.supervisorConfigPath, \"utf8\"),\n\t\t\t) as Partial<PersistedSupervisorConfig>;\n\t\t\tif (\n\t\t\t\tparsed.version !== 1 ||\n\t\t\t\ttypeof parsed.socketPath !== \"string\" ||\n\t\t\t\tnormalizeSocketPath(parsed.socketPath) !== this.socketPath ||\n\t\t\t\t!parsed.defaultSessionConfig ||\n\t\t\t\ttypeof parsed.defaultSessionConfig !== \"object\" ||\n\t\t\t\ttypeof parsed.defaultSessionConfig.agentDir !== \"string\"\n\t\t\t) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn durableAgentSessionRuntimeConfig(parsed.defaultSessionConfig);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate persistSupervisorConfig(): void {\n\t\tconst persisted: PersistedSupervisorConfig = {\n\t\t\tversion: 1,\n\t\t\tsocketPath: this.socketPath,\n\t\t\tdefaultSessionConfig: durableAgentSessionRuntimeConfig(this.defaultSessionConfig),\n\t\t};\n\t\tconst tempPath = `${this.supervisorConfigPath}.${process.pid}.tmp`;\n\t\twriteFileSync(tempPath, `${JSON.stringify(persisted, null, 2)}\\n`, { mode: 0o600 });\n\t\tchmodSync(tempPath, 0o600);\n\t\trenameSync(tempPath, this.supervisorConfigPath);\n\t}\n\n\tprivate hasPersistedWorkerDescriptors(): boolean {\n\t\treturn readdirSync(this.descriptorDir).some(\n\t\t\t(name) => name !== SUPERVISOR_CONFIG_FILE_NAME && name.endsWith(\".json\"),\n\t\t);\n\t}\n\n\tprivate persistWorker(worker: ResidentWorker): void {\n\t\tworker.descriptor.updatedAt = new Date().toISOString();\n\t\tconst persisted = durableDaemonWorkerDescriptor(worker.descriptor);\n\t\tconst tempPath = `${worker.descriptorPath}.${process.pid}.tmp`;\n\t\twriteFileSync(tempPath, `${JSON.stringify(persisted, null, 2)}\\n`, { mode: 0o600 });\n\t\tchmodSync(tempPath, 0o600);\n\t\trenameSync(tempPath, worker.descriptorPath);\n\t}\n\n\tprivate deleteWorkerDescriptor(worker: { descriptorPath: string; descriptor: DaemonWorkerDescriptor }): void {\n\t\ttry {\n\t\t\trmSync(worker.descriptorPath, { force: true });\n\t\t\trmSync(worker.descriptor.recoveryJournalPath, { force: true });\n\t\t\tif (worker.descriptor.orphanProcessJournalPath) {\n\t\t\t\trmSync(worker.descriptor.orphanProcessJournalPath, { force: true });\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.log(`Failed to remove worker descriptor ${worker.descriptorPath}: ${String(error)}`);\n\t\t}\n\t}\n\n\tprivate handleConnection(socket: Socket): void {\n\t\tconst client: DaemonSocketClient = {\n\t\t\tid: createActiveSessionId(),\n\t\t\tsocket,\n\t\t\tattachedActiveSessionIds: new Set(),\n\t\t\tcatchupActiveSessionIds: new Set(),\n\t\t\tbackpressured: false,\n\t\t\tauthenticated: true,\n\t\t\tsnapshotActiveSessionIds: new Set(),\n\t\t\tdetachInput: () => {},\n\t\t\tsupportsExtensionUi: false,\n\t\t\tcapabilities: new Set(DAEMON_DEFAULT_CLIENT_CAPABILITIES),\n\t\t};\n\t\tthis.connectionIds.set(client, client.id);\n\t\tthis.sessionInputPauseEpochs.set(client, 0);\n\t\tthis.detachingInputPauseSessions.set(client, new Set());\n\t\tthis.clients.add(client);\n\t\tvoid this.ready.then(\n\t\t\t() => {\n\t\t\t\tif (!client.socket.destroyed && this.clients.has(client)) {\n\t\t\t\t\tthis.write(client, {\n\t\t\t\t\t\ttype: \"daemon_hello\",\n\t\t\t\t\t\tsocketPath: this.socketPath,\n\t\t\t\t\t\tprotocol: DAEMON_PROTOCOL_INFO,\n\t\t\t\t\t\tschemaId: DAEMON_SCHEMA_ID,\n\t\t\t\t\t\tschemaRevision: DAEMON_SCHEMA_REVISION,\n\t\t\t\t\t\tappVersion: VERSION,\n\t\t\t\t\t\truntime: getDaemonRuntimeIdentity(),\n\t\t\t\t\t\tsupervisorGeneration: this.generation,\n\t\t\t\t\t\tsupervisorOwnerToken: this.ownership?.record.token,\n\t\t\t\t\t\tsupervisorPid: process.pid,\n\t\t\t\t\t\tsupervisorProcessStartId: this.ownership?.record.processStartId,\n\t\t\t\t\t\tsupervisorSocketPath: this.ownership?.record.socketPath,\n\t\t\t\t\t\tclientId: client.id,\n\t\t\t\t\t\tserverCapabilities: SUPERVISOR_SERVER_CAPABILITIES,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => client.socket.destroy(),\n\t\t);\n\n\t\tclient.detachInput = attachJsonlLineReader(socket, (line) => void this.handleLine(client, line));\n\t\tlet cleaned = false;\n\t\tconst cleanup = () => {\n\t\t\tif (cleaned) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcleaned = true;\n\t\t\tclient.detachInput();\n\t\t\tthis.sessionInputPauseEpochs.set(client, (this.sessionInputPauseEpochs.get(client) ?? 0) + 1);\n\t\t\tconst ownerClientId = this.protocolClientId(client);\n\t\t\tvoid this.releaseClientSessionInputPauses(client, undefined, true).catch((error: unknown) =>\n\t\t\t\tthis.log(`Failed to release input pauses for disconnected client ${ownerClientId}: ${String(error)}`),\n\t\t\t);\n\t\t\tthis.clients.delete(client);\n\t\t\tthis.cancelWaitingPromptAdmissionsForClient(client);\n\t\t\tfor (const activeSessionId of [...client.attachedActiveSessionIds]) {\n\t\t\t\tclient.attachedActiveSessionIds.delete(activeSessionId);\n\t\t\t\tvoid this.syncWorkerExtensionUi(activeSessionId);\n\t\t\t\tvoid this.evictEmptySessionOnLastDetach(activeSessionId);\n\t\t\t}\n\t\t\tthis.scheduleOwnedWorkerCleanupForClient(this.protocolClientId(client));\n\t\t};\n\t\tsocket.on(\"close\", cleanup);\n\t\tsocket.on(\"error\", cleanup);\n\t\tsocket.on(\"drain\", () => {\n\t\t\tclient.backpressured = false;\n\t\t\tif (client.rosterResyncPending && client.rosterSubscribed === true) {\n\t\t\t\t// socket.write queues even when it reports backpressure: one resync per loss gap.\n\t\t\t\tclient.rosterResyncPending = false;\n\t\t\t\tthis.write(client, { type: \"roster_update\", changed: this.rosterEntriesForClient(), resync: true });\n\t\t\t}\n\t\t\tif (!client.snapshotStreaming) {\n\t\t\t\tvoid this.catchUpClient(client).catch((error) =>\n\t\t\t\t\tthis.log(`Failed to catch up client ${client.id}: ${String(error)}`),\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate cancelOwnedWorkerCleanup(clientId: string): void {\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker.descriptor.ownerClientId !== clientId || !worker.ownerCleanupTimer) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t}\n\t}\n\n\tprivate protocolClientId(client: DaemonSocketClient): string {\n\t\treturn this.protocolClientIds.get(client) ?? client.id;\n\t}\n\n\tprivate async releaseClientSessionInputPauses(\n\t\towner: DaemonSocketClient,\n\t\tactiveSessionId?: string,\n\t\tforceCleanupOnFailure = false,\n\t): Promise<void> {\n\t\tconst entries = [...this.sessionInputPauses.values()].filter(\n\t\t\t(entry) =>\n\t\t\t\tentry.owner === owner &&\n\t\t\t\t(activeSessionId === undefined ||\n\t\t\t\t\tentry.activeSessionId === activeSessionId ||\n\t\t\t\t\tentry.requestedActiveSessionId === activeSessionId),\n\t\t);\n\t\tawait Promise.all(\n\t\t\tentries.map(async (entry) => {\n\t\t\t\tif (this.workers.get(entry.worker.descriptor.workerId) !== entry.worker || !entry.worker.client) {\n\t\t\t\t\tif (this.sessionInputPauses.get(entry.pauseId) === entry) this.sessionInputPauses.delete(entry.pauseId);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await this.forwardToWorker(\n\t\t\t\t\t\tentry.worker,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: randomUUID(),\n\t\t\t\t\t\t\ttype: \"release_session_input_pause\",\n\t\t\t\t\t\t\tactiveSessionId: entry.activeSessionId,\n\t\t\t\t\t\t\tpauseId: entry.pauseId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tINPUT_PAUSE_CLEANUP_TIMEOUT_MS,\n\t\t\t\t\t);\n\t\t\t\t\tif (!response.success) throw new Error(response.error);\n\t\t\t\t\tif (this.sessionInputPauses.get(entry.pauseId) === entry) this.sessionInputPauses.delete(entry.pauseId);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (forceCleanupOnFailure) {\n\t\t\t\t\t\tconst workerClient = entry.worker.client;\n\t\t\t\t\t\tif (workerClient) {\n\t\t\t\t\t\t\tworkerClient.close();\n\t\t\t\t\t\t\tawait this.handleWorkerClose(\n\t\t\t\t\t\t\t\tentry.worker,\n\t\t\t\t\t\t\t\tworkerClient,\n\t\t\t\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.invalidateWorkerSessionInputPauses(\n\t\t\t\t\t\t\t\tentry.worker,\n\t\t\t\t\t\t\t\t\"Session worker became unavailable while releasing an input pause\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate invalidateWorkerSessionInputPauses(worker: ResidentWorker, reason: string): void {\n\t\tconst owners = new Set<DaemonSocketClient>();\n\t\tfor (const [pauseId, entry] of this.sessionInputPauses) {\n\t\t\tif (entry.worker !== worker) continue;\n\t\t\tthis.sessionInputPauses.delete(pauseId);\n\t\t\towners.add(entry.owner);\n\t\t}\n\t\tfor (const owner of owners) {\n\t\t\towner.socket.destroy(new Error(reason));\n\t\t}\n\t}\n\n\tprivate scheduleOwnedWorkerCleanupForClient(clientId: string): void {\n\t\tif ([...this.clients].some((client) => this.protocolClientId(client) === clientId)) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker.descriptor.ownerClientId === clientId) {\n\t\t\t\tthis.scheduleOwnedWorkerCleanup(worker);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate scheduleOwnedWorkerCleanup(worker: ResidentWorker): void {\n\t\tconst ownerClientId = worker.descriptor.ownerClientId;\n\t\tif (\n\t\t\t!ownerClientId ||\n\t\t\tworker.compatibilityError !== undefined ||\n\t\t\tworker.ownerCleanupTimer ||\n\t\t\t[...this.clients].some((client) => this.protocolClientId(client) === ownerClientId)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tworker.ownerCleanupTimer = setTimeout(() => {\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t\tif (\n\t\t\t\tworker.compatibilityError !== undefined ||\n\t\t\t\tworker.descriptor.ownerClientId !== ownerClientId ||\n\t\t\t\t[...this.clients].some((client) => this.protocolClientId(client) === ownerClientId) ||\n\t\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvoid this.stopWorker(worker, true).catch((error) =>\n\t\t\t\tthis.log(`Could not clean up client-owned worker ${worker.descriptor.workerId}: ${String(error)}`),\n\t\t\t);\n\t\t}, OWNED_WORKER_DISCONNECT_GRACE_MS);\n\t\tworker.ownerCleanupTimer.unref();\n\t}\n\n\tprivate promptAdmissionKey(activeSessionId: string, publicAdmissionId: string): string {\n\t\treturn `${activeSessionId}\\0${publicAdmissionId}`;\n\t}\n\n\tprivate promptAdmissionsFor(client: DaemonSocketClient): Map<string, SupervisorPromptAdmission> {\n\t\tlet admissions = this.promptAdmissions.get(client);\n\t\tif (!admissions) {\n\t\t\tadmissions = new Map();\n\t\t\tthis.promptAdmissions.set(client, admissions);\n\t\t}\n\t\treturn admissions;\n\t}\n\n\tprivate getPromptAdmission(\n\t\tclient: DaemonSocketClient,\n\t\tactiveSessionId: string,\n\t\tpublicAdmissionId: string,\n\t): SupervisorPromptAdmission | undefined {\n\t\treturn this.promptAdmissions.get(client)?.get(this.promptAdmissionKey(activeSessionId, publicAdmissionId));\n\t}\n\n\tprivate deletePromptAdmission(admission: SupervisorPromptAdmission): void {\n\t\tconst admissions = this.promptAdmissions.get(admission.client);\n\t\tconst key = this.promptAdmissionKey(admission.activeSessionId, admission.publicAdmissionId);\n\t\tif (admissions?.get(key) !== admission) return;\n\t\tadmissions.delete(key);\n\t\tif (admissions.size === 0) this.promptAdmissions.delete(admission.client);\n\t}\n\n\tprivate cancelWaitingPromptAdmissionsForClient(client: DaemonSocketClient): void {\n\t\tfor (const admission of this.promptAdmissions.get(client)?.values() ?? []) {\n\t\t\tif (admission.status !== \"waiting\") continue;\n\t\t\tif (!admission.worker || !admission.workerActiveSessionId) {\n\t\t\t\tadmission.status = \"cancelled\";\n\t\t\t\tadmission.controller.abort();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst worker = admission.worker;\n\t\t\tconst workerActiveSessionId = admission.workerActiveSessionId;\n\t\t\tvoid this.forwardToWorker(worker, {\n\t\t\t\ttype: \"cancel_prompt_admission\",\n\t\t\t\tactiveSessionId: workerActiveSessionId,\n\t\t\t\tadmissionId: admission.workerAdmissionId,\n\t\t\t})\n\t\t\t\t.then((response) => {\n\t\t\t\t\tif (admission.status !== \"waiting\") return;\n\t\t\t\t\tconst status =\n\t\t\t\t\t\tresponse.success && response.data && typeof response.data === \"object\" && \"status\" in response.data\n\t\t\t\t\t\t\t? (response.data as { status?: unknown }).status\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (status === \"owned\") admission.status = \"owned\";\n\t\t\t\t\telse if (status === \"cancelled\") admission.status = \"cancelled\";\n\t\t\t\t})\n\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\tthis.log(\n\t\t\t\t\t\t`Could not cancel prompt admission ${admission.workerAdmissionId} on disconnected client: ${String(error)}`,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/** Non-async by design: prompt registration completes before handleLine's first await. */\n\tprivate parseCommandAndRegisterPromptAdmission(\n\t\tclient: DaemonSocketClient,\n\t\tline: string,\n\t): {\n\t\tcommand: DaemonCommand;\n\t\tenvelopeClientId?: string;\n\t\tprotocolVersion: number;\n\t\tadmission?: SupervisorPromptAdmission;\n\t} {\n\t\tconst parsed = JSON.parse(line) as unknown;\n\t\tconst envelope = isDaemonCommandEnvelope(parsed) ? parsed : undefined;\n\t\tif (!envelope) {\n\t\t\tthrow new Error(`Daemon commands require protocol ${DAEMON_COMMAND_ENVELOPE_MIN_PROTOCOL_VERSION} or newer`);\n\t\t}\n\t\tconst command = { ...envelope.command, id: envelope.id } as DaemonCommand;\n\t\tif (\n\t\t\tenvelope.protocol.version < CANONICAL_SESSION_OWNERSHIP_COMPATIBILITY.minProtocol &&\n\t\t\t!isLegacyDaemonInspection(command)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Native daemon commands require protocol ${CANONICAL_SESSION_OWNERSHIP_COMPATIBILITY.minProtocol} canonical session ownership and bounded invocation output; only passive inspection is available`,\n\t\t\t);\n\t\t}\n\t\tlet admission: SupervisorPromptAdmission | undefined;\n\t\tif ((command.type === \"prompt\" || command.type === \"prompt_and_wait\") && command.admissionId !== undefined) {\n\t\t\tif (typeof command.activeSessionId !== \"string\" || typeof command.admissionId !== \"string\") {\n\t\t\t\tthrow new Error(\"Prompt admission requires string activeSessionId and admissionId\");\n\t\t\t}\n\t\t\tif (command.admissionId === \"\") throw new Error(\"admissionId must not be empty\");\n\t\t\tconst admissions = this.promptAdmissionsFor(client);\n\t\t\tconst key = this.promptAdmissionKey(command.activeSessionId, command.admissionId);\n\t\t\tif (admissions.has(key)) {\n\t\t\t\tthrow new Error(`Prompt admission id is already in use: ${command.admissionId}`);\n\t\t\t}\n\t\t\tadmission = {\n\t\t\t\tclient,\n\t\t\t\tactiveSessionId: command.activeSessionId,\n\t\t\t\tpublicAdmissionId: command.admissionId,\n\t\t\t\tworkerAdmissionId: `supervisor-admission:${randomUUID()}`,\n\t\t\t\tstatus: \"waiting\",\n\t\t\t\tcontroller: new AbortController(),\n\t\t\t};\n\t\t\tadmissions.set(key, admission);\n\t\t}\n\t\treturn {\n\t\t\tcommand,\n\t\t\tenvelopeClientId: envelope.clientId ?? client.id,\n\t\t\tprotocolVersion: envelope.protocol.version,\n\t\t\tadmission,\n\t\t};\n\t}\n\n\tprivate isWorkerLedgerEnvelope(line: string): boolean {\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(line);\n\t\t\treturn (\n\t\t\t\tisDaemonCommandEnvelope(parsed) &&\n\t\t\t\t(parsed.command.type === \"rlm_ledger_mutate\" || parsed.command.type === \"rlm_capacity\")\n\t\t\t);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate async handleLine(client: DaemonSocketClient, line: string): Promise<void> {\n\t\ttry {\n\t\t\tthis.assertSupervisorServing(this.shuttingDown && this.isWorkerLedgerEnvelope(line));\n\t\t} catch (error) {\n\t\t\tthis.write(client, failure(salvageDaemonCommandId(line), \"dispatch\", error, serializeDaemonError(error)));\n\t\t\treturn;\n\t\t}\n\t\tlet preParsed: ReturnType<DaemonSupervisor[\"parseCommandAndRegisterPromptAdmission\"]>;\n\t\ttry {\n\t\t\tpreParsed = this.parseCommandAndRegisterPromptAdmission(client, line);\n\t\t} catch (error) {\n\t\t\tthis.write(client, failure(salvageDaemonCommandId(line), \"parse\", error));\n\t\t\treturn;\n\t\t}\n\t\tconst command = preParsed.command;\n\t\tconst parsedAdmission = preParsed.admission;\n\t\tif (command.type === \"cancel_prompt_admission\" && this.updateRestartPhase !== undefined) {\n\t\t\tthis.write(client, failure(command.id, command.type, \"Daemon is preparing an update restart\"));\n\t\t\treturn;\n\t\t}\n\t\tconst cancellationAdmission =\n\t\t\tcommand.type === \"cancel_prompt_admission\"\n\t\t\t\t? this.getPromptAdmission(client, command.activeSessionId, command.admissionId)\n\t\t\t\t: undefined;\n\t\tif (cancellationAdmission?.status === \"waiting\" && !cancellationAdmission.worker) {\n\t\t\tcancellationAdmission.status = \"cancelled\";\n\t\t\tcancellationAdmission.controller.abort();\n\t\t}\n\t\ttry {\n\t\t\tawait waitForPromptAdmission(this.ready, parsedAdmission?.controller.signal);\n\t\t} catch (error) {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(client, failure(command.id, command.type, error));\n\t\t\treturn;\n\t\t}\n\t\tconst envelopeClientId = preParsed.envelopeClientId;\n\t\tif (envelopeClientId) {\n\t\t\tthis.protocolClientIds.set(client, envelopeClientId);\n\t\t\tclient.id = envelopeClientId;\n\t\t}\n\t\tthis.cancelOwnedWorkerCleanup(client.id);\n\t\tif (!DAEMON_COMMAND_TYPES.has(command.type)) {\n\t\t\tthis.write(client, failure(command.id, command.type, `Unknown daemon command: ${command.type}`));\n\t\t\treturn;\n\t\t}\n\t\tif (\n\t\t\tcommand.type === \"get_session_tree\" &&\n\t\t\tpreParsed.protocolVersion < DAEMON_COMMAND_COMPATIBILITY.get_session_tree.minProtocol\n\t\t) {\n\t\t\tthis.write(\n\t\t\t\tclient,\n\t\t\t\tfailure(\n\t\t\t\t\tcommand.id,\n\t\t\t\t\tcommand.type,\n\t\t\t\t\t`get_session_tree requires client protocol ${DAEMON_COMMAND_COMPATIBILITY.get_session_tree.minProtocol} or newer`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait waitForPromptAdmission(\n\t\t\t\tthis.assertServingCurrentOwnership(command.type === \"rlm_ledger_mutate\" || command.type === \"rlm_capacity\"),\n\t\t\t\tparsedAdmission?.controller.signal,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(client, failure(command.id, command.type, error));\n\t\t\treturn;\n\t\t}\n\n\t\tconst mutation = isDaemonMutatingCommand(command);\n\t\tconst journalIdentity =\n\t\t\tenvelopeClientId && command.id && mutation ? { clientId: envelopeClientId, commandId: command.id } : undefined;\n\t\tconst existing = journalIdentity\n\t\t\t? this.commandJournal.lookup(journalIdentity.clientId, journalIdentity.commandId)\n\t\t\t: undefined;\n\t\tif (existing?.status === \"complete\") {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(client, existing.response);\n\t\t\treturn;\n\t\t}\n\t\tif (existing?.status === \"pending\" && journalIdentity) {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(\n\t\t\t\tclient,\n\t\t\t\tfailure(command.id, command.type, \"The previous command result is uncertain and was not replayed\", {\n\t\t\t\t\tcode: \"command_result_uncertain\",\n\t\t\t\t\t...journalIdentity,\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst phase = this.updateRestartPhase;\n\t\tconst restartRejected =\n\t\t\tphase === \"draining\"\n\t\t\t\t? !UPDATE_RESTART_DRAIN_COMMANDS.has(command.type)\n\t\t\t\t: phase !== undefined && !(phase === \"prepared\" && command.type === \"shutdown\");\n\t\tif (restartRejected && mutation && command.type !== \"rlm_ledger_mutate\" && command.type !== \"rlm_capacity\") {\n\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\tthis.write(client, failure(command.id, command.type, \"Daemon is preparing an update restart\"));\n\t\t\treturn;\n\t\t}\n\t\tif (mutation && !UPDATE_RESTART_DRAIN_COMMANDS.has(command.type)) {\n\t\t\tconst idleEvictionFence = this.idleEvictionFence;\n\t\t\tif (idleEvictionFence) {\n\t\t\t\tawait idleEvictionFence;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.assertServingCurrentOwnership(\n\t\t\t\t\t\tcommand.type === \"rlm_ledger_mutate\" || command.type === \"rlm_capacity\",\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\t\t\tthis.write(client, failure(command.id, command.type, error, serializeDaemonError(error)));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (journalIdentity) {\n\t\t\tlet admitted: CommandJournalBeginResult;\n\t\t\ttry {\n\t\t\t\tadmitted = this.commandJournal.begin(journalIdentity.clientId, journalIdentity.commandId, command.type);\n\t\t\t} catch (error) {\n\t\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\t\tthis.write(client, failure(command.id, command.type, error, serializeDaemonError(error)));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (admitted.status === \"complete\") {\n\t\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\t\tthis.write(client, admitted.response);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (admitted.status === \"pending\") {\n\t\t\t\tif (parsedAdmission) this.deletePromptAdmission(parsedAdmission);\n\t\t\t\tthis.write(\n\t\t\t\t\tclient,\n\t\t\t\t\tfailure(command.id, command.type, \"The previous command result is uncertain and was not replayed\", {\n\t\t\t\t\t\tcode: \"command_result_uncertain\",\n\t\t\t\t\t\t...journalIdentity,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Attach is intentionally read-only and is not fence-gated. If eviction wins\n\t\t// the race, attach fails cleanly with \"Session worker is not connected\" and\n\t\t// the client retries through the saved-session path instead of mutating state.\n\t\tif (mutation) this.mutationDrain.begin();\n\t\tlet commandCompleted = false;\n\t\ttry {\n\t\t\tconst response = await this.handleCommand(client, command, cancellationAdmission);\n\t\t\tcommandCompleted = true;\n\t\t\tif (response) {\n\t\t\t\tif (journalIdentity) {\n\t\t\t\t\tawait this.assertCurrentOwnership();\n\t\t\t\t\tthis.commandJournal.recordResult(journalIdentity.clientId, journalIdentity.commandId, response);\n\t\t\t\t}\n\t\t\t\tthis.write(client, response);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.log(`Supervisor command ${command.type} failed: ${error instanceof Error ? error.stack : String(error)}`);\n\t\t\tlet response = failure(command.id, command.type, error, serializeDaemonError(error));\n\t\t\t// A completed command must not get a conflicting failure result after uncertain result persistence.\n\t\t\tif (journalIdentity && !commandCompleted && !isSupervisorGenerationStale(error)) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.assertCurrentOwnership();\n\t\t\t\t\tthis.commandJournal.recordResult(journalIdentity.clientId, journalIdentity.commandId, response);\n\t\t\t\t} catch (persistenceError) {\n\t\t\t\t\tconst failureError =\n\t\t\t\t\t\tpersistenceError === error\n\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t: new AggregateError(\n\t\t\t\t\t\t\t\t\t[error, persistenceError],\n\t\t\t\t\t\t\t\t\t\"Supervisor command and result persistence failed\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\tresponse = failure(command.id, command.type, failureError, serializeDaemonError(failureError));\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.write(client, response);\n\t\t} finally {\n\t\t\tif (mutation) this.mutationDrain.end();\n\t\t}\n\t}\n\n\tprivate rlmCapacityOwner(worker: ResidentWorker): string {\n\t\treturn `${worker.descriptor.workerId}:${worker.descriptor.workerInstanceId ?? \"unavailable\"}`;\n\t}\n\n\tprivate async rlmCapacityFamily(sessionFile: string | undefined, owner: string, sessionId: string): Promise<string> {\n\t\tif (!sessionFile) return `memory:${owner}:${sessionId}`;\n\t\tconst parents = new Map(\n\t\t\t(await this.rlmSpawnLedger().liveEdges({ strict: true })).map(\n\t\t\t\t(edge) => [canonicalSessionPath(edge.child), canonicalSessionPath(edge.parent)] as const,\n\t\t\t),\n\t\t);\n\t\tlet root = canonicalSessionPath(sessionFile);\n\t\tconst visited = new Set<string>();\n\t\twhile (parents.has(root)) {\n\t\t\tif (visited.has(root)) throw new Error(\"RLM family ancestry contains a cycle\");\n\t\t\tvisited.add(root);\n\t\t\tconst parent = parents.get(root);\n\t\t\tif (parent === undefined) break;\n\t\t\troot = parent;\n\t\t}\n\t\treturn `file:${root}`;\n\t}\n\n\tprivate isRlmMainRoot(sessionFile: string | undefined, family: string): boolean {\n\t\treturn sessionFile === undefined || family === `file:${canonicalSessionPath(sessionFile)}`;\n\t}\n\n\tprivate releaseWorkerRlmCapacity(worker: ResidentWorker): void {\n\t\tthis.rlmCapacity.releaseOwner(this.rlmCapacityOwner(worker));\n\t\tthis.pendingRlmCapacity.delete(worker);\n\t\tthis.releasedDuringCapacityRecovery.delete(worker);\n\t}\n\n\tprivate async assertRlmCapacityKnown(family: string): Promise<void> {\n\t\tfor (const worker of [...this.pendingRlmCapacity]) {\n\t\t\tconst identity = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t\tif (identity === \"gone\" || identity === \"replaced\") {\n\t\t\t\tthis.releaseWorkerRlmCapacity(worker);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst path = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\t\tconst pendingFamily = path\n\t\t\t\t? await this.rlmCapacityFamily(\n\t\t\t\t\t\tpath,\n\t\t\t\t\t\tthis.rlmCapacityOwner(worker),\n\t\t\t\t\t\tworker.descriptor.rootSessionId ?? \"pending\",\n\t\t\t\t\t)\n\t\t\t\t: undefined;\n\t\t\tif (this.pendingRlmCapacity.has(worker) && (pendingFamily === undefined || pendingFamily === family)) {\n\t\t\t\tthrow new Error(\"RLM family capacity is waiting for a live worker to reconnect\");\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async restoreWorkerRlmCapacity(worker: ResidentWorker, client: DaemonWorkerClient): Promise<void> {\n\t\tif (!this.pendingRlmCapacity.has(worker)) return;\n\t\tconst owner = this.rlmCapacityOwner(worker);\n\t\tconst response = await client.requestWorker({ type: \"worker_get_rlm_capacity\" }, 2000);\n\t\tif (!response.success) throw deserializeDaemonError(response);\n\t\tif (!isDaemonRlmCapacitySnapshot(response.data))\n\t\t\tthrow new Error(\"Worker returned an invalid RLM capacity snapshot\");\n\t\tconst recovered = await Promise.all(\n\t\t\tresponse.data.reservations.map(async (reservation) => ({\n\t\t\t\treservation,\n\t\t\t\tfamily: await this.rlmCapacityFamily(reservation.sessionFile, owner, reservation.sessionId),\n\t\t\t})),\n\t\t);\n\t\tif (this.rlmCapacityOwner(worker) !== owner || !this.pendingRlmCapacity.has(worker)) return;\n\t\tconst released = this.releasedDuringCapacityRecovery.get(worker);\n\t\tfor (const { reservation, family } of recovered) {\n\t\t\tif (released?.has(reservation.reservationId)) continue;\n\t\t\tif (reservation.residentRoot && this.isRlmMainRoot(reservation.sessionFile, family)) continue;\n\t\t\tthis.rlmCapacity.restore(owner, reservation.reservationId, family);\n\t\t}\n\t\tthis.pendingRlmCapacity.delete(worker);\n\t\tthis.releasedDuringCapacityRecovery.delete(worker);\n\t}\n\n\tprivate async handleRlmCapacity(command: Extract<DaemonCommand, { type: \"rlm_capacity\" }>): Promise<DaemonResponse> {\n\t\tconst worker = [...this.workers.values()].find(\n\t\t\t(candidate) =>\n\t\t\t\tcandidate.descriptor.authenticationToken === command.workerToken &&\n\t\t\t\tcandidate.descriptor.workerInstanceId === command.workerInstanceId,\n\t\t);\n\t\tif (\n\t\t\t!worker ||\n\t\t\t!command.workerInstanceId ||\n\t\t\tworker.compatibilityError ||\n\t\t\tthis.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId) !== \"current\"\n\t\t) {\n\t\t\tthrow new Error(\"Worker authentication failed for RLM capacity\");\n\t\t}\n\t\tconst owner = this.rlmCapacityOwner(worker);\n\t\tconst journal = this.assertRlmJournalAdmission();\n\t\tconst scope = this.rlmJournalScope(worker.descriptor.sessionDir ?? this.defaultSessionConfig.sessionDir);\n\t\tif (canonicalSessionPath(scope.journalPath) !== journal.ledgerPath) {\n\t\t\tthrow new Error(\"Worker RLM family is not owned by this supervisor\");\n\t\t}\n\t\tconst operation = command.operation;\n\t\tif (!operation || typeof operation !== \"object\") throw new Error(\"Invalid RLM capacity operation\");\n\t\tif (operation.op === \"release\") {\n\t\t\tif (typeof operation.reservationId !== \"string\" || !operation.reservationId)\n\t\t\t\tthrow new Error(\"Invalid RLM reservation id\");\n\t\t\tthis.rlmCapacity.release(owner, operation.reservationId);\n\t\t\tif (this.pendingRlmCapacity.has(worker)) {\n\t\t\t\tlet released = this.releasedDuringCapacityRecovery.get(worker);\n\t\t\t\tif (!released) {\n\t\t\t\t\treleased = new Set();\n\t\t\t\t\tthis.releasedDuringCapacityRecovery.set(worker, released);\n\t\t\t\t}\n\t\t\t\treleased.add(operation.reservationId);\n\t\t\t}\n\t\t\treturn success(command.id, command.type);\n\t\t}\n\t\tif (operation.op !== \"status\" && operation.op !== \"set\" && operation.op !== \"reserve\")\n\t\t\tthrow new Error(\"Unknown RLM capacity operation\");\n\t\tif (\n\t\t\ttypeof operation.sessionId !== \"string\" ||\n\t\t\t!operation.sessionId ||\n\t\t\t(operation.sessionFile !== undefined && (typeof operation.sessionFile !== \"string\" || !operation.sessionFile))\n\t\t) {\n\t\t\tthrow new Error(\"Invalid RLM capacity origin\");\n\t\t}\n\t\tconst family = await this.rlmCapacityFamily(operation.sessionFile, owner, operation.sessionId);\n\t\tawait this.assertServingCurrentOwnership(true);\n\t\tif (this.rlmCapacityOwner(worker) !== owner || worker.descriptor.authenticationToken !== command.workerToken) {\n\t\t\tthrow new Error(\"RLM capacity worker incarnation changed\");\n\t\t}\n\t\tif (operation.op === \"status\") return success(command.id, command.type, this.rlmCapacity.getStatus(family));\n\t\tif (this.shuttingDown || this.updateRestartPhase !== undefined || worker.descriptor.stopRequestedAt) {\n\t\t\tthrow new Error(\"RLM capacity admission is closed while the worker or daemon is stopping\");\n\t\t}\n\t\tif (operation.op === \"set\") {\n\t\t\treturn success(\n\t\t\t\tcommand.id,\n\t\t\t\tcommand.type,\n\t\t\t\tawait this.rlmCapacity.setMaxSubagents(family, operation.maxSubagents),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\ttypeof operation.reservationId !== \"string\" ||\n\t\t\t!operation.reservationId ||\n\t\t\t(operation.residentRoot !== undefined && operation.residentRoot !== true)\n\t\t)\n\t\t\tthrow new Error(\"Invalid RLM reservation\");\n\t\tif (operation.residentRoot && this.isRlmMainRoot(operation.sessionFile, family)) {\n\t\t\treturn success(command.id, command.type, this.rlmCapacity.getStatus(family));\n\t\t}\n\t\tawait this.assertRlmCapacityKnown(family);\n\t\tawait this.assertServingCurrentOwnership();\n\t\tif (\n\t\t\tthis.updateRestartPhase !== undefined ||\n\t\t\tworker.descriptor.stopRequestedAt ||\n\t\t\tthis.rlmCapacityOwner(worker) !== owner ||\n\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker ||\n\t\t\tthis.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId) !== \"current\"\n\t\t) {\n\t\t\tthrow new Error(\"RLM capacity admission changed while resolving its family\");\n\t\t}\n\t\treturn success(command.id, command.type, this.rlmCapacity.reserve(owner, operation.reservationId, family));\n\t}\n\n\tprivate async handleCommand(\n\t\tclient: DaemonSocketClient,\n\t\tcommand: DaemonCommand,\n\t\tcancellationAdmission?: SupervisorPromptAdmission,\n\t): Promise<DaemonResponse | undefined> {\n\t\tswitch (command.type) {\n\t\t\tcase \"cancel_prompt_admission\": {\n\t\t\t\tconst admission =\n\t\t\t\t\tcancellationAdmission ?? this.getPromptAdmission(client, command.activeSessionId, command.admissionId);\n\t\t\t\tif (!admission) return success(command.id, command.type, { status: \"unknown\" as const });\n\t\t\t\tif (admission.status === \"owned\") return success(command.id, command.type, { status: \"owned\" as const });\n\t\t\t\t// A definitive cancellation never downgrades to unknown/waiting.\n\t\t\t\tif (admission.status === \"cancelled\") {\n\t\t\t\t\treturn success(command.id, command.type, { status: \"cancelled\" as const });\n\t\t\t\t}\n\t\t\t\tif (!admission.worker || !admission.workerActiveSessionId) {\n\t\t\t\t\tadmission.status = \"cancelled\";\n\t\t\t\t\tadmission.controller.abort();\n\t\t\t\t\treturn success(command.id, command.type, { status: \"cancelled\" as const });\n\t\t\t\t}\n\t\t\t\tconst response = await this.forwardToWorker(admission.worker, {\n\t\t\t\t\t...command,\n\t\t\t\t\tactiveSessionId: admission.workerActiveSessionId,\n\t\t\t\t\tadmissionId: admission.workerAdmissionId,\n\t\t\t\t});\n\t\t\t\tconst status =\n\t\t\t\t\tresponse.success && response.data && typeof response.data === \"object\" && \"status\" in response.data\n\t\t\t\t\t\t? (response.data as { status: \"cancelled\" | \"owned\" | \"unknown\" }).status\n\t\t\t\t\t\t: \"unknown\";\n\t\t\t\t// Re-read: a socket close may have cancelled during the round-trip (cast widens TS's pre-await narrowing).\n\t\t\t\tconst current = (admission as SupervisorPromptAdmission).status;\n\t\t\t\tif (status === \"owned\") admission.status = \"owned\";\n\t\t\t\telse if (status === \"cancelled\") admission.status = \"cancelled\";\n\t\t\t\telse if (current !== \"cancelled\") admission.status = \"waiting\";\n\t\t\t\treturn { ...response, id: command.id };\n\t\t\t}\n\t\t\tcase \"ack_result\":\n\t\t\t\tthis.commandJournal.acknowledge(client.id, command.commandId);\n\t\t\t\treturn undefined;\n\t\t\tcase \"list\":\n\t\t\t\treturn this.handleList(client, command);\n\t\t\tcase \"roster_subscribe\":\n\t\t\t\tclient.rosterSubscribed = true;\n\t\t\t\treturn success(command.id, command.type, { roster: this.rosterEntriesForClient() });\n\t\t\tcase \"roster_unsubscribe\":\n\t\t\t\tclient.rosterSubscribed = false;\n\t\t\t\tclient.rosterResyncPending = false;\n\t\t\t\treturn success(command.id, command.type);\n\t\t\tcase \"list_agent_peers\": {\n\t\t\t\tconst requester = [...this.workers.values()].find(\n\t\t\t\t\t(worker) => worker.descriptor.authenticationToken === command.workerToken,\n\t\t\t\t);\n\t\t\t\tif (!requester) throw new Error(\"Worker authentication failed\");\n\t\t\t\tconst peers = [...this.workers.values()]\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(worker) =>\n\t\t\t\t\t\t\tworker !== requester &&\n\t\t\t\t\t\t\tthis.isLiveWorker(worker) &&\n\t\t\t\t\t\t\tworker.descriptor.lifecycle === \"ready\" &&\n\t\t\t\t\t\t\tworker.client !== undefined,\n\t\t\t\t\t)\n\t\t\t\t\t.flatMap((worker) => {\n\t\t\t\t\t\tconst root = this.roster().byActiveSessionId(worker.descriptor.rootActiveSessionId);\n\t\t\t\t\t\treturn root ? [this.agentPeerSummary(sessionSummaryFromRosterEntry(root))] : [];\n\t\t\t\t\t});\n\t\t\t\treturn success(command.id, command.type, { peers });\n\t\t\t}\n\t\t\tcase \"rlm_capacity\":\n\t\t\t\treturn this.handleRlmCapacity(command);\n\t\t\tcase \"rlm_ledger_mutate\": {\n\t\t\t\tconst worker = [...this.workers.values()].find(\n\t\t\t\t\t(candidate) => candidate.descriptor.authenticationToken === command.workerToken,\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\t!worker ||\n\t\t\t\t\t!command.workerInstanceId ||\n\t\t\t\t\tworker.descriptor.workerInstanceId !== command.workerInstanceId ||\n\t\t\t\t\tworker.compatibilityError ||\n\t\t\t\t\tthis.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId) !== \"current\"\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Worker authentication failed for RLM ledger mutation\");\n\t\t\t\t}\n\t\t\t\tconst owner = this.assertRlmJournalAdmission();\n\t\t\t\tconst scope = this.rlmJournalScope(worker.descriptor.sessionDir ?? this.defaultSessionConfig.sessionDir);\n\t\t\t\tif (canonicalSessionPath(scope.journalPath) !== owner.ledgerPath) {\n\t\t\t\t\tthrow new Error(\"Worker RLM ledger family is not owned by this supervisor\");\n\t\t\t\t}\n\t\t\t\tawait this.rlmSpawnLedger().mutate(command.mutation);\n\t\t\t\treturn success(command.id, command.type);\n\t\t\t}\n\t\t\tcase \"get_direct_worker_transport\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tif (match.worker.descriptor.ownerClientId !== undefined) {\n\t\t\t\t\tthrow new Error(\"Direct transport is unavailable for client-owned workers\");\n\t\t\t\t}\n\t\t\t\tconst ticket = await this.issuePeerTransport(match.worker, match.summary);\n\t\t\t\treturn success(command.id, command.type, ticket);\n\t\t\t}\n\t\t\tcase \"list_saved_sessions\":\n\t\t\t\treturn this.handleSavedSessionList(client, command);\n\t\t\tcase \"create\": {\n\t\t\t\tconst worker = await this.createOrReuseWorker(this.protocolClientId(client), command);\n\t\t\t\tconst requestedSummary = command.sessionPath\n\t\t\t\t\t? this.findSummaryInWorker(worker, command.sessionPath)\n\t\t\t\t\t: undefined;\n\t\t\t\tif (\n\t\t\t\t\trequestedSummary &&\n\t\t\t\t\t(requestedSummary.activeSessionId ?? requestedSummary.id) !== worker.descriptor.rootActiveSessionId\n\t\t\t\t) {\n\t\t\t\t\t// A create forwarded to a recovering worker still surfaces an opaque lifecycle error.\n\t\t\t\t\tconst response = await this.forwardToWorker(worker, withoutSupervisorCreateFields(command));\n\t\t\t\t\tif (response.success && isSessionSummary(response.data)) {\n\t\t\t\t\t\tthis.writeRosterEntry(workerRosterEntryFromSummary(response.data), worker);\n\t\t\t\t\t\treturn { ...response, id: command.id, data: this.publicSummary(worker, response.data) };\n\t\t\t\t\t}\n\t\t\t\t\treturn responseWithId(response, command.id);\n\t\t\t\t}\n\t\t\t\tconst root = this.roster().byActiveSessionId(worker.descriptor.rootActiveSessionId);\n\t\t\t\tif (!root) {\n\t\t\t\t\tthrow new Error(\"Session worker started without a root session\");\n\t\t\t\t}\n\t\t\t\treturn success(command.id, \"create\", this.publicSummary(worker, sessionSummaryFromRosterEntry(root)));\n\t\t\t}\n\t\t\tcase \"attach\": {\n\t\t\t\tconst attached = await this.attachClient(client, command);\n\t\t\t\tif (client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\t\t\tconst transcript = attached.transcript;\n\t\t\t\t\tif (!transcript) {\n\t\t\t\t\t\tthrow new Error(\"Session worker did not provide a snapshot transcript\");\n\t\t\t\t\t}\n\t\t\t\t\tconst streamedResult = this.createStreamedAttachResult(attached.result, transcript);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.write(client, success(command.id, \"attach\", streamedResult));\n\t\t\t\t\t\tvoid this.streamSnapshot(\n\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\tattached.worker,\n\t\t\t\t\t\t\tstreamedResult,\n\t\t\t\t\t\t\ttranscript,\n\t\t\t\t\t\t\t\"attach\",\n\t\t\t\t\t\t\tattached.releaseTranscript,\n\t\t\t\t\t\t).catch((error) =>\n\t\t\t\t\t\t\tthis.log(\n\t\t\t\t\t\t\t\t`Failed to stream attach snapshot for ${streamedResult.activeSessionId}: ${String(error)}`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tattached.releaseTranscript?.();\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\treturn success(command.id, \"attach\", attached.result);\n\t\t\t}\n\t\t\tcase \"reattach\": {\n\t\t\t\tconst target = await this.findWorkerForClient(client, command.targetActiveSessionId);\n\t\t\t\tconst targetActiveSessionId = target.summary.activeSessionId ?? target.summary.id;\n\t\t\t\tif (targetActiveSessionId === command.activeSessionId) {\n\t\t\t\t\tconst detachingSessions = this.detachingInputPauseSessions?.get(client);\n\t\t\t\t\tdetachingSessions?.delete(command.activeSessionId);\n\t\t\t\t\tdetachingSessions?.delete(command.targetActiveSessionId);\n\t\t\t\t\tdetachingSessions?.delete(targetActiveSessionId);\n\t\t\t\t\treturn success(command.id, command.type, { cancelled: false });\n\t\t\t\t}\n\t\t\t\tconst targetWasAttached = client.attachedActiveSessionIds.has(targetActiveSessionId);\n\t\t\t\tconst releaseSnapshotReservation = this.reserveSnapshotStream(client, targetActiveSessionId);\n\t\t\t\tlet releaseTranscript: (() => void) | undefined;\n\t\t\t\tclient.attachedActiveSessionIds.add(targetActiveSessionId);\n\t\t\t\ttry {\n\t\t\t\t\tconst attached = await this.attachClient(client, {\n\t\t\t\t\t\t...command,\n\t\t\t\t\t\ttype: \"attach\",\n\t\t\t\t\t\tactiveSessionId: targetActiveSessionId,\n\t\t\t\t\t});\n\t\t\t\t\tconst detachingSessions = this.detachingInputPauseSessions?.get(client);\n\t\t\t\t\tdetachingSessions?.delete(command.activeSessionId);\n\t\t\t\t\tdetachingSessions?.delete(command.targetActiveSessionId);\n\t\t\t\t\tdetachingSessions?.delete(targetActiveSessionId);\n\t\t\t\t\tif (client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\t\t\t\tconst transcript =\n\t\t\t\t\t\t\tattached.transcript ?? this.getOrCreateTranscriptCache(attached.worker, attached.result);\n\t\t\t\t\t\treleaseTranscript = attached.releaseTranscript;\n\t\t\t\t\t\tconst streamedResult = this.createStreamedAttachResult(attached.result, transcript);\n\t\t\t\t\t\tthis.write(client, success(command.id, command.type, streamedResult));\n\t\t\t\t\t\tthis.detachClient(client, command.activeSessionId);\n\t\t\t\t\t\tconst streaming = this.streamSnapshot(\n\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\tattached.worker,\n\t\t\t\t\t\t\tstreamedResult,\n\t\t\t\t\t\t\ttranscript,\n\t\t\t\t\t\t\t\"replacement\",\n\t\t\t\t\t\t\treleaseTranscript,\n\t\t\t\t\t\t\treleaseSnapshotReservation,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treleaseTranscript = undefined;\n\t\t\t\t\t\tvoid streaming.catch((error) =>\n\t\t\t\t\t\t\tthis.log(`Failed to stream reattach snapshot for ${targetActiveSessionId}: ${String(error)}`),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\t\t\t\t\tthis.write(client, success(command.id, command.type, attached.result));\n\t\t\t\t\tthis.detachClient(client, command.activeSessionId);\n\t\t\t\t\treleaseSnapshotReservation();\n\t\t\t\t\treturn undefined;\n\t\t\t\t} catch (error) {\n\t\t\t\t\treleaseTranscript?.();\n\t\t\t\t\tif (!targetWasAttached) {\n\t\t\t\t\t\tthis.detachClient(client, targetActiveSessionId);\n\t\t\t\t\t}\n\t\t\t\t\treleaseSnapshotReservation();\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"acquire_session_input_pause\": {\n\t\t\t\tconst detachingSessions = this.detachingInputPauseSessions.get(client);\n\t\t\t\tif (detachingSessions?.has(command.activeSessionId)) {\n\t\t\t\t\tthrow new Error(`Session is detaching: ${command.activeSessionId}`);\n\t\t\t\t}\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tconst activeSessionId = match.summary.activeSessionId ?? match.summary.id;\n\t\t\t\tif (detachingSessions?.has(command.activeSessionId) || detachingSessions?.has(activeSessionId)) {\n\t\t\t\t\tthrow new Error(`Session is detaching: ${command.activeSessionId}`);\n\t\t\t\t}\n\t\t\t\tconst ownerClientId = this.protocolClientId(client);\n\t\t\t\tconst connectionId = this.connectionIds.get(client);\n\t\t\t\tif (!connectionId) throw new Error(\"Daemon client connection identity is unavailable\");\n\t\t\t\tconst acquisitionEpoch = this.sessionInputPauseEpochs.get(client) ?? 0;\n\t\t\t\tconst existing = [...this.sessionInputPauses.values()].find(\n\t\t\t\t\t(entry) =>\n\t\t\t\t\t\tentry.owner === client &&\n\t\t\t\t\t\tentry.worker === match.worker &&\n\t\t\t\t\t\tentry.activeSessionId === activeSessionId &&\n\t\t\t\t\t\tentry.leaseKey === command.leaseKey &&\n\t\t\t\t\t\t!entry.releaseTask,\n\t\t\t\t);\n\t\t\t\tif (existing) {\n\t\t\t\t\treturn success(command.id, command.type, { pauseId: existing.pauseId });\n\t\t\t\t}\n\t\t\t\tconst response = await this.forwardToWorker(match.worker, {\n\t\t\t\t\t...command,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tleaseKey: JSON.stringify([connectionId, ownerClientId, command.leaseKey]),\n\t\t\t\t});\n\t\t\t\tif (!response.success) return response;\n\t\t\t\tconst pauseId = (response.data as { pauseId?: unknown } | undefined)?.pauseId;\n\t\t\t\tif (typeof pauseId !== \"string\") throw new Error(\"Worker returned an invalid session input pause id\");\n\t\t\t\tif (!this.clients.has(client) || (this.sessionInputPauseEpochs.get(client) ?? 0) !== acquisitionEpoch) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst release = await this.forwardToWorker(match.worker, {\n\t\t\t\t\t\t\tid: randomUUID(),\n\t\t\t\t\t\t\ttype: \"release_session_input_pause\",\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tpauseId,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (!release.success) throw new Error(release.error);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tmatch.worker.client?.close();\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tthrow new Error(\"Session input pause acquisition was invalidated before completion\");\n\t\t\t\t}\n\t\t\t\tthis.sessionInputPauses.set(pauseId, {\n\t\t\t\t\towner: client,\n\t\t\t\t\tworker: match.worker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\trequestedActiveSessionId: command.activeSessionId,\n\t\t\t\t\tleaseKey: command.leaseKey,\n\t\t\t\t\tpauseId,\n\t\t\t\t});\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\tcase \"release_session_input_pause\": {\n\t\t\t\tconst entry = this.sessionInputPauses.get(command.pauseId);\n\t\t\t\tif (!entry) return success(command.id, command.type);\n\t\t\t\tif (entry.owner !== client) {\n\t\t\t\t\tthrow new Error(`Session input pause is owned by another client: ${command.pauseId}`);\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tcommand.activeSessionId !== entry.activeSessionId &&\n\t\t\t\t\tcommand.activeSessionId !== entry.requestedActiveSessionId\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(`Session input pause belongs to another session: ${command.pauseId}`);\n\t\t\t\t}\n\t\t\t\tconst releaseTask =\n\t\t\t\t\tentry.releaseTask ??\n\t\t\t\t\tthis.forwardToWorker(entry.worker, {\n\t\t\t\t\t\t...command,\n\t\t\t\t\t\tactiveSessionId: entry.activeSessionId,\n\t\t\t\t\t});\n\t\t\t\tentry.releaseTask = releaseTask;\n\t\t\t\ttry {\n\t\t\t\t\tconst response = await releaseTask;\n\t\t\t\t\tif (response.success && this.sessionInputPauses.get(command.pauseId) === entry) {\n\t\t\t\t\t\tthis.sessionInputPauses.delete(command.pauseId);\n\t\t\t\t\t}\n\t\t\t\t\treturn response;\n\t\t\t\t} finally {\n\t\t\t\t\tif (this.sessionInputPauses.get(command.pauseId) === entry && entry.releaseTask === releaseTask) {\n\t\t\t\t\t\tentry.releaseTask = undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase \"detach\": {\n\t\t\t\tconst detachingSessions = this.detachingInputPauseSessions.get(client) ?? new Set<string>();\n\t\t\t\tthis.detachingInputPauseSessions.set(client, detachingSessions);\n\t\t\t\tif (command.activeSessionId) detachingSessions.add(command.activeSessionId);\n\t\t\t\telse for (const activeSessionId of client.attachedActiveSessionIds) detachingSessions.add(activeSessionId);\n\t\t\t\tthis.sessionInputPauseEpochs.set(client, (this.sessionInputPauseEpochs.get(client) ?? 0) + 1);\n\t\t\t\tthis.detachClient(client, command.activeSessionId);\n\t\t\t\tawait this.releaseClientSessionInputPauses(client, command.activeSessionId, true);\n\t\t\t\treturn success(command.id, \"detach\");\n\t\t\t}\n\t\t\tcase \"complete_owned_session\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tif (match.worker.descriptor.ownerClientId !== this.protocolClientId(client)) {\n\t\t\t\t\tthrow new Error(\"Session is not owned by this client\");\n\t\t\t\t}\n\t\t\t\tif (match.worker.ownerCleanupTimer) {\n\t\t\t\t\tclearTimeout(match.worker.ownerCleanupTimer);\n\t\t\t\t\tmatch.worker.ownerCleanupTimer = undefined;\n\t\t\t\t}\n\t\t\t\tawait this.stopWorker(match.worker, true);\n\t\t\t\treturn success(command.id, command.type);\n\t\t\t}\n\t\t\tcase \"promote_owned_session\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tawait this.promoteOwnedWorker(client, match.worker);\n\t\t\t\treturn success(command.id, command.type, this.publicSummary(match.worker, match.summary));\n\t\t\t}\n\t\t\tcase \"retry_worker\": {\n\t\t\t\tconst direct = [...this.workers.values()].find(\n\t\t\t\t\t(worker) =>\n\t\t\t\t\t\tworker.descriptor.rootActiveSessionId === command.activeSessionId ||\n\t\t\t\t\t\tworker.descriptor.rootSessionId === command.activeSessionId,\n\t\t\t\t);\n\t\t\t\tconst worker = direct ?? (await this.findWorkerForClient(client, command.activeSessionId)).worker;\n\t\t\t\tthis.assertWorkerAccessibleToClient(client, worker, command.activeSessionId);\n\t\t\t\tif ((this.workerStopCounts?.get(worker) ?? 0) > 0) {\n\t\t\t\t\tthrow new Error(\"Session worker is stopping; retry after it finishes\");\n\t\t\t\t}\n\t\t\t\tworker.intentionalStop = false;\n\t\t\t\tworker.descriptor.stopRequestedAt = undefined;\n\t\t\t\tworker.descriptor.archiveOnStop = undefined;\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tworker.descriptor.consecutiveFailures = 0;\n\t\t\t\tworker.deferredRecoveryRounds = 0;\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tawait this.recoverWorker(worker);\n\t\t\t\tif (this.workers.get(worker.descriptor.workerId)?.descriptor.lifecycle !== \"ready\") {\n\t\t\t\t\tthrow new Error(worker.descriptor.lastError ?? \"Session worker recovery failed\");\n\t\t\t\t}\n\t\t\t\tconst summary = worker.summaries.get(worker.descriptor.rootActiveSessionId);\n\t\t\t\treturn success(command.id, command.type, summary ? this.publicSummary(worker, summary) : undefined);\n\t\t\t}\n\t\t\tcase \"restart\":\n\t\t\t\tsetImmediate(() => void this.shutdown(0, false, true, false, \"update\"));\n\t\t\t\treturn success(command.id, command.type);\n\t\t\tcase \"shutdown\":\n\t\t\t\tsetImmediate(() => void this.shutdown(0, true, false, command.force === true, \"shutdown\"));\n\t\t\t\treturn success(command.id, \"shutdown\");\n\t\t\tcase \"prepare_update_restart\": {\n\t\t\t\tconst manifest = await this.prepareUpdateRestart();\n\t\t\t\treturn success(command.id, \"prepare_update_restart\", manifest);\n\t\t\t}\n\t\t\tcase \"agent_messages_status\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst first = [...this.workers.values()].find((worker) => this.isLiveWorker(worker) && worker.client);\n\t\t\t\tif (!first) {\n\t\t\t\t\treturn success(command.id, command.type, { paused: false, limits: {} });\n\t\t\t\t}\n\t\t\t\treturn this.forwardToWorker(first, command);\n\t\t\t}\n\t\t\tcase \"agent_messages_pause\":\n\t\t\tcase \"agent_messages_resume\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst responses = await Promise.all(\n\t\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t\t.filter((worker) => this.isLiveWorker(worker) && worker.client)\n\t\t\t\t\t\t.map((worker) => this.forwardToWorker(worker, command)),\n\t\t\t\t);\n\t\t\t\tconst failed = responses.find((response) => !response.success);\n\t\t\t\treturn failed ?? success(command.id, command.type, responses.find((response) => response.success)?.data);\n\t\t\t}\n\t\t\tcase \"cron_list\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst jobs = new Map<string, AgentCronJob>();\n\t\t\t\tconst responses = await Promise.all(\n\t\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(worker) => this.isLiveWorker(worker) && worker.client && worker.descriptor.lifecycle === \"ready\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map((worker) =>\n\t\t\t\t\t\t\tthis.forwardToWorker(worker, command, 5000).catch((error: unknown) =>\n\t\t\t\t\t\t\t\tfailure(command.id, command.type, error, serializeDaemonError(error)),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tfor (const response of responses) {\n\t\t\t\t\tif (!response.success) {\n\t\t\t\t\t\tthis.log(`Could not list scheduled jobs from a worker: ${response.error}`);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tfor (const job of cronJobsFromResponse(response)) {\n\t\t\t\t\t\tjobs.set(job.id, job);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (const { job } of await this.collectPassiveScheduledJobs(command.includeInactive === true)) {\n\t\t\t\t\tif (!jobs.has(job.id)) jobs.set(job.id, job);\n\t\t\t\t}\n\t\t\t\treturn success(command.id, \"cron_list\", { jobs: sortCronJobs([...jobs.values()]) });\n\t\t\t}\n\t\t\tcase \"heartbeats_list\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst workers = [...this.workers.values()].filter(\n\t\t\t\t\t(worker) => this.isLiveWorker(worker) && worker.descriptor.lifecycle !== \"failed\",\n\t\t\t\t);\n\t\t\t\tconst heartbeats = new Map<string, AgentConnectionHeartbeat>();\n\t\t\t\tconst snapshots: Array<{ heartbeats?: AgentConnectionHeartbeat[]; response?: DaemonResponse }> =\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tworkers.map(async (worker) => {\n\t\t\t\t\t\t\tif (worker.client && worker.descriptor.lifecycle === \"ready\") {\n\t\t\t\t\t\t\t\tconst response = await this.forwardToWorker(worker, command, 5000).catch((error: unknown) =>\n\t\t\t\t\t\t\t\t\tfailure(command.id, command.type, error, serializeDaemonError(error)),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tif (response.success) {\n\t\t\t\t\t\t\t\t\tconst snapshot = heartbeatsFromResponse(response);\n\t\t\t\t\t\t\t\t\tworker.heartbeatSnapshot = snapshot;\n\t\t\t\t\t\t\t\t\tworker.heartbeatSnapshotStale = false;\n\t\t\t\t\t\t\t\t\treturn { heartbeats: snapshot };\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthis.log(`Could not list heartbeats from a worker: ${response.error}`);\n\t\t\t\t\t\t\t\tif (worker.heartbeatSnapshot === undefined || worker.heartbeatSnapshotStale === true) {\n\t\t\t\t\t\t\t\t\treturn { response };\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (worker.heartbeatSnapshot !== undefined && worker.heartbeatSnapshotStale !== true) {\n\t\t\t\t\t\t\t\treturn { heartbeats: worker.heartbeatSnapshot };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst state =\n\t\t\t\t\t\t\t\tworker.descriptor.lifecycle === \"ready\" ? \"disconnected\" : worker.descriptor.lifecycle;\n\t\t\t\t\t\t\tconst error = new Error(`Cannot list heartbeats while session worker is ${state}`);\n\t\t\t\t\t\t\treturn { response: failure(command.id, command.type, error, serializeDaemonError(error)) };\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\tconst failed = snapshots.find((snapshot) => snapshot.response)?.response;\n\t\t\t\tif (failed) {\n\t\t\t\t\treturn failed;\n\t\t\t\t}\n\t\t\t\tfor (const snapshot of snapshots) {\n\t\t\t\t\tfor (const heartbeat of snapshot.heartbeats ?? []) {\n\t\t\t\t\t\theartbeats.set(heartbeat.job.id, heartbeat);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Passivated sessions keep their armed heartbeats; no worker can list them.\n\t\t\t\tfor (const { job, info } of await this.collectPassiveScheduledJobs()) {\n\t\t\t\t\tif (!isHeartbeatCronJob(job) || heartbeats.has(job.id)) continue;\n\t\t\t\t\theartbeats.set(job.id, {\n\t\t\t\t\t\tjob,\n\t\t\t\t\t\t...(info.name !== undefined ? { sessionName: info.name } : {}),\n\t\t\t\t\t\t...(info.firstMessage !== undefined ? { firstMessage: info.firstMessage } : {}),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn success(command.id, \"heartbeats_list\", { heartbeats: [...heartbeats.values()] });\n\t\t\t}\n\t\t\tcase \"heartbeat_manage\": {\n\t\t\t\tconst cachedWorker = [...this.workers.values()].find((worker) =>\n\t\t\t\t\tworker.heartbeatSnapshot?.some(\n\t\t\t\t\t\t(heartbeat) =>\n\t\t\t\t\t\t\theartbeat.job.id === command.jobId && heartbeat.job.activeSessionId === command.activeSessionId,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tif (!cachedWorker) {\n\t\t\t\t\t// Passive jobs are managed against their durable store; no wake just to flip a status.\n\t\t\t\t\tconst passive = (await this.collectPassiveScheduledJobs()).find(\n\t\t\t\t\t\t({ job }) => job.id === command.jobId && job.activeSessionId === command.activeSessionId,\n\t\t\t\t\t);\n\t\t\t\t\tif (passive) {\n\t\t\t\t\t\tconst store = AgentCronJobStore.forSessionArtifacts();\n\t\t\t\t\t\tstore.registerSessionArtifact(\n\t\t\t\t\t\t\tpassive.info.id,\n\t\t\t\t\t\t\tgetSessionArtifactPathForFile(resolve(passive.info.path), passive.info.id),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst heartbeat = store.manageHeartbeat(command.activeSessionId, command.jobId, command.action);\n\t\t\t\t\t\tif (heartbeat) {\n\t\t\t\t\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\t\t\t\t\treturn success(command.id, \"heartbeat_manage\", { heartbeat });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst worker = cachedWorker ?? (await this.findWorkerForClient(client, command.activeSessionId)).worker;\n\t\t\t\tthis.assertWorkerAccessibleToClient(client, worker, command.activeSessionId);\n\t\t\t\tconst response = await this.forwardToWorker(worker, command);\n\t\t\t\tif (\n\t\t\t\t\tresponse.success &&\n\t\t\t\t\tresponse.data &&\n\t\t\t\t\ttypeof response.data === \"object\" &&\n\t\t\t\t\t\"heartbeat\" in response.data\n\t\t\t\t) {\n\t\t\t\t\tconst job = (response.data as { heartbeat?: AgentCronJob }).heartbeat;\n\t\t\t\t\tif (job && worker.heartbeatSnapshot) {\n\t\t\t\t\t\tconst existing = worker.heartbeatSnapshot.find((heartbeat) => heartbeat.job.id === job.id);\n\t\t\t\t\t\tconst remaining = worker.heartbeatSnapshot.filter((heartbeat) => heartbeat.job.id !== job.id);\n\t\t\t\t\t\tworker.heartbeatSnapshot =\n\t\t\t\t\t\t\tjob.status === \"active\" || job.status === \"paused\"\n\t\t\t\t\t\t\t\t? [...remaining, existing ? { ...existing, job } : { job }]\n\t\t\t\t\t\t\t\t: remaining;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\tcase \"cron_add\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tconst response = await this.forwardToWorker(match.worker, command);\n\t\t\t\tif (response.success && command.promoteOwnedSession) {\n\t\t\t\t\tawait this.promoteOwnedWorker(client, match.worker);\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\tcase \"cron_cancel\": {\n\t\t\t\tif (command.activeSessionId) {\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t\t}\n\t\t\t\tconst listed = await Promise.all(\n\t\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(worker) => this.isLiveWorker(worker) && worker.client && worker.descriptor.lifecycle === \"ready\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map(async (worker) => ({\n\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\tresponse: await this.forwardToWorker(\n\t\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\t\t{ type: \"cron_list\", includeInactive: true },\n\t\t\t\t\t\t\t\t5000,\n\t\t\t\t\t\t\t).catch(() => undefined),\n\t\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\tfor (const candidate of listed) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcandidate.response?.success &&\n\t\t\t\t\t\tcronJobsFromResponse(candidate.response).some((job) => job.id === command.jobId)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn this.forwardToWorker(candidate.worker, command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst passive = (await this.collectPassiveScheduledJobs()).find(({ job }) => job.id === command.jobId);\n\t\t\t\tif (passive) {\n\t\t\t\t\tconst store = AgentCronJobStore.forSessionArtifacts();\n\t\t\t\t\tstore.registerSessionArtifact(\n\t\t\t\t\t\tpassive.info.id,\n\t\t\t\t\t\tgetSessionArtifactPathForFile(resolve(passive.info.path), passive.info.id),\n\t\t\t\t\t);\n\t\t\t\t\tconst job = store.cancel(command.jobId);\n\t\t\t\t\tif (job) {\n\t\t\t\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\t\t\t\treturn success(command.id, \"cron_cancel\", { job });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new Error(`No cron job found: ${command.jobId}`);\n\t\t\t}\n\t\t\tcase \"cron_resume\": {\n\t\t\t\tif (command.activeSessionId !== undefined) {\n\t\t\t\t\tconst entry = this.roster().byActiveSessionId(command.activeSessionId);\n\t\t\t\t\tconst worker = entry?.workerId !== undefined ? this.workers.get(entry.workerId) : undefined;\n\t\t\t\t\tif (!worker || entry?.queuedChild) {\n\t\t\t\t\t\tthrow new Error(\"Cron resume requires an already bound destination runtime\");\n\t\t\t\t\t}\n\t\t\t\t\tthis.assertWorkerAccessibleToClient(client, worker, command.activeSessionId);\n\t\t\t\t\treturn this.forwardToWorker(worker, command);\n\t\t\t\t}\n\t\t\t\tconst listed = await Promise.all(\n\t\t\t\t\t[...this.workers.values()]\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t(worker) => this.isLiveWorker(worker) && worker.client && worker.descriptor.lifecycle === \"ready\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map(async (worker) => ({\n\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\tresponse: await this.forwardToWorker(\n\t\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\t\t{ type: \"cron_list\", includeInactive: true },\n\t\t\t\t\t\t\t\t5000,\n\t\t\t\t\t\t\t).catch(() => undefined),\n\t\t\t\t\t\t})),\n\t\t\t\t);\n\t\t\t\tfor (const candidate of listed) {\n\t\t\t\t\tconst job = candidate.response?.success\n\t\t\t\t\t\t? cronJobsFromResponse(candidate.response).find((job) => job.id === command.jobId)\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (job) {\n\t\t\t\t\t\tthis.assertWorkerAccessibleToClient(client, candidate.worker, job.activeSessionId);\n\t\t\t\t\t\treturn this.forwardToWorker(candidate.worker, command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Cron resume requires an already bound destination runtime for job: ${command.jobId}`);\n\t\t\t}\n\t\t\tcase \"heartbeat_get\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t}\n\t\t\tcase \"heartbeat_set\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\tconst response = await this.forwardToWorker(match.worker, command);\n\t\t\t\tif (response.success && command.promoteOwnedSession) {\n\t\t\t\t\tawait this.promoteOwnedWorker(client, match.worker);\n\t\t\t\t}\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\tcase \"heartbeat_update\": {\n\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\treturn this.forwardToWorker(match.worker, command);\n\t\t\t}\n\t\t\tcase \"rename_saved_session\": {\n\t\t\t\tconst target = await this.savedSessionNameReservationInput(command.sessionPath, command.name.trim());\n\t\t\t\treturn await this.withSessionNameReservation(target, async () => {\n\t\t\t\t\tawait this.assertSupervisorSavedSessionNameAvailable(command.sessionPath, target.name);\n\t\t\t\t\tif (!command.activeSessionId) {\n\t\t\t\t\t\tthis.assertRlmJournalAdmission();\n\t\t\t\t\t\tawait this.catalog.rename(command.sessionPath, command.name);\n\t\t\t\t\t\t// Third rename write point: an offline saved-session rename\n\t\t\t\t\t\t// changes the name the ledger carries for that child.\n\t\t\t\t\t\tawait this.rlmSpawnLedger().appendRenameByChildPath(command.sessionPath, target.name);\n\t\t\t\t\t\tconst entry = this.roster().bySessionFile(canonicalSessionPath(command.sessionPath));\n\t\t\t\t\t\tif (entry) {\n\t\t\t\t\t\t\tthis.writeRosterEntry({ ...entry, summary: { ...entry.summary, sessionName: target.name } });\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn success(command.id, command.type);\n\t\t\t\t\t}\n\t\t\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\t\t\treturn await this.forwardToWorker(match.worker, {\n\t\t\t\t\t\t...command,\n\t\t\t\t\t\tactiveSessionId: match.summary.activeSessionId ?? match.summary.id,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t\tcase \"delete_saved_session\":\n\t\t\t\tif (!command.activeSessionId) {\n\t\t\t\t\tconst deletedPath = canonicalSessionPath(command.sessionPath);\n\t\t\t\t\tconst entry = this.roster().bySessionFile(deletedPath);\n\t\t\t\t\tif (entry?.summary.activeSessionId !== undefined) {\n\t\t\t\t\t\tthrow new Error(\"Cannot delete the currently active session\");\n\t\t\t\t\t}\n\t\t\t\t\tconst owner = this.findWorkerBySessionFile(command.sessionPath);\n\t\t\t\t\tif (owner) {\n\t\t\t\t\t\t// A client-owned worker's files are invisible to other clients: a foreign delete is an unknown target.\n\t\t\t\t\t\tthis.assertWorkerAccessibleToClient(client, owner, command.sessionPath);\n\t\t\t\t\t\tif (owner.client && !this.isWorkerStopping(owner)) {\n\t\t\t\t\t\t\treturn this.forwardToWorker(owner, command);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!(await this.reclaimStaleWorkerRegistration(owner))) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Session worker is ${this.effectiveWorkerState(owner)}; retry the delete once it is reachable`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.assertRlmJournalAdmission();\n\t\t\t\t\tawait tombstoneSavedSessionDelete(this.rlmSpawnLedger(), command.sessionPath, entry?.summary);\n\t\t\t\t\tconst result = await this.catalog.delete(command.sessionPath);\n\t\t\t\t\tif (result.ok && entry && this.roster().get(entry.agentId) === entry) {\n\t\t\t\t\t\tthis.roster().delete(entry.agentId);\n\t\t\t\t\t}\n\t\t\t\t\treturn success(command.id, command.type, result);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif (command.type === \"send_message\" || command.type === \"send_result\") {\n\t\t\t// agentOrigin without fromActiveSessionId is trusted only at the direct socket-client boundary.\n\t\t\tconst source = command.fromActiveSessionId\n\t\t\t\t? await this.findWorkerForClient(client, command.fromActiveSessionId)\n\t\t\t\t: undefined;\n\t\t\tlet target: WorkerMatch;\n\t\t\ttry {\n\t\t\t\ttarget = await this.findWorkerForClient(client, command.targetActiveSessionId);\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof Error) || !error.message.startsWith(\"Unknown active session:\")) throw error;\n\t\t\t\tconst cwd = source?.summary.cwd ?? this.defaultSessionConfig.cwd ?? process.cwd();\n\t\t\t\tlet sessionPath: string;\n\t\t\t\ttry {\n\t\t\t\t\tsessionPath = await this.catalog.resolve(\n\t\t\t\t\t\tcommand.targetActiveSessionId,\n\t\t\t\t\t\tcwd,\n\t\t\t\t\t\tsource?.worker.descriptor.sessionDir ?? this.defaultSessionConfig.sessionDir,\n\t\t\t\t\t);\n\t\t\t\t} catch (catalogError) {\n\t\t\t\t\t// Preserve selector ambiguity so a2a senders can distinguish it from\n\t\t\t\t\t// the original unknown-active-session lookup failure.\n\t\t\t\t\tif (catalogError instanceof Error && catalogError.message.startsWith(\"Ambiguous session selector\")) {\n\t\t\t\t\t\tthrow catalogError;\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (source && command.agentOrigin === true) {\n\t\t\t\t\tconst targetInfo = await readSessionInfo(sessionPath);\n\t\t\t\t\tif (!targetInfo) throw new Error(`Unknown active session: ${command.targetActiveSessionId}`);\n\t\t\t\t\tassertAgentFamilyReach(\n\t\t\t\t\t\tthis.familyCatalogEntry(source.summary),\n\t\t\t\t\t\tthis.familyCatalogEntry(summaryForInactiveSession(targetInfo)),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst worker = await this.createOrReuseWorker(this.protocolClientId(client), {\n\t\t\t\t\ttype: \"create\",\n\t\t\t\t\tsessionPath,\n\t\t\t\t\tcontinueRecent: false,\n\t\t\t\t});\n\t\t\t\tconst root = this.roster().byActiveSessionId(worker.descriptor.rootActiveSessionId);\n\t\t\t\tconst summary =\n\t\t\t\t\tthis.findSummaryInWorker(worker, sessionPath) ??\n\t\t\t\t\t(root ? sessionSummaryFromRosterEntry(root) : undefined);\n\t\t\t\tif (!summary) throw new Error(\"Woken session worker has no target session\");\n\t\t\t\ttarget = { worker, summary };\n\t\t\t}\n\t\t\tconst targetActiveSessionId = target.summary.activeSessionId ?? target.summary.id;\n\t\t\tif (source && command.agentOrigin === true) {\n\t\t\t\tassertAgentFamilyReach(this.familyCatalogEntry(source.summary), this.familyCatalogEntry(target.summary));\n\t\t\t}\n\t\t\tif (source) {\n\t\t\t\tif ((source.summary.activeSessionId ?? source.summary.id) === targetActiveSessionId) {\n\t\t\t\t\tthrow new Error(\"Agent messaging cannot target the sending session\");\n\t\t\t\t}\n\t\t\t\tconst targetClient = this.requireAvailableWorkerClient(target.worker);\n\t\t\t\tconst response = await targetClient.requestWorker(\n\t\t\t\t\t{\n\t\t\t\t\t\t...(command.type === \"send_result\"\n\t\t\t\t\t\t\t? { type: \"worker_deliver_result\" as const, summary: command.summary, findings: command.findings }\n\t\t\t\t\t\t\t: { type: \"worker_deliver_message\" as const, message: command.message }),\n\t\t\t\t\t\ttargetActiveSessionId,\n\t\t\t\t\t\tsender: {\n\t\t\t\t\t\t\tactiveSessionId: source.summary.activeSessionId ?? source.summary.id,\n\t\t\t\t\t\t\tsessionId: source.summary.sessionId,\n\t\t\t\t\t\t\t...(source.summary.sessionName ? { sessionName: source.summary.sessionName } : {}),\n\t\t\t\t\t\t\truntimeKind: source.summary.runtimeKind ?? \"top-level\",\n\t\t\t\t\t\t\tclientId: client.id,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tWORKER_REQUEST_TIMEOUT_MS,\n\t\t\t\t);\n\t\t\t\treturn { ...response, id: command.id, command: command.type };\n\t\t\t}\n\t\t\treturn this.forwardToWorker(target.worker, { ...command, targetActiveSessionId });\n\t\t}\n\n\t\tif (!(\"activeSessionId\" in command) || typeof command.activeSessionId !== \"string\") {\n\t\t\tthrow new Error(`Supervisor cannot route daemon command: ${command.type}`);\n\t\t}\n\t\tconst admission =\n\t\t\t(command.type === \"prompt\" || command.type === \"prompt_and_wait\") && command.admissionId\n\t\t\t\t? this.getPromptAdmission(client, command.activeSessionId, command.admissionId)\n\t\t\t\t: undefined;\n\t\ttry {\n\t\t\tthrowIfAdmissionCancelled(admission);\n\t\t\tconst match = await waitForPromptAdmission(\n\t\t\t\tcommand.type === \"set_session_name\" && command.workerToken !== undefined\n\t\t\t\t\t? this.findWorker(\n\t\t\t\t\t\t\tcommand.activeSessionId,\n\t\t\t\t\t\t\t(worker) => worker.descriptor.authenticationToken === command.workerToken,\n\t\t\t\t\t\t)\n\t\t\t\t\t: this.findWorkerForClient(client, command.activeSessionId),\n\t\t\t\tadmission?.controller.signal,\n\t\t\t);\n\t\t\tthrowIfAdmissionCancelled(admission);\n\t\t\tconst resolvedCommand = {\n\t\t\t\t...command,\n\t\t\t\tactiveSessionId: match.summary.activeSessionId ?? match.summary.id,\n\t\t\t\t...(admission ? { admissionId: admission.workerAdmissionId } : {}),\n\t\t\t} as DaemonCommand;\n\t\t\tif (admission) {\n\t\t\t\tadmission.worker = match.worker;\n\t\t\t\tadmission.workerActiveSessionId = match.summary.activeSessionId ?? match.summary.id;\n\t\t\t}\n\t\t\tconst isRootKill =\n\t\t\t\tcommand.type === \"kill\" &&\n\t\t\t\t(match.summary.activeSessionId ?? match.summary.id) === match.worker.descriptor.rootActiveSessionId;\n\t\t\tif (!isRootKill) {\n\t\t\t\tconst forward = async () => {\n\t\t\t\t\tconst response = await this.forwardToWorker(match.worker, resolvedCommand);\n\t\t\t\t\tif (admission && response.success) admission.status = \"owned\";\n\t\t\t\t\treturn response;\n\t\t\t\t};\n\t\t\t\tif (command.type === \"rename\" || command.type === \"set_session_name\") {\n\t\t\t\t\tconst reservation = this.summaryNameReservationInput(match.summary, command.name.trim());\n\t\t\t\t\treturn await this.withSessionNameReservation(reservation, async () => {\n\t\t\t\t\t\tawait this.assertSupervisorSessionNameAvailable(match.summary, reservation.name);\n\t\t\t\t\t\treturn forward();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn await forward();\n\t\t\t}\n\t\t\tthis.persistWorkerStopTombstone(match.worker, true);\n\t\t\tconst releaseStopOwnership = this.acquireWorkerStopOwnership(match.worker);\n\t\t\tlet response: DaemonResponse;\n\t\t\ttry {\n\t\t\t\tresponse = await this.forwardToWorker(match.worker, resolvedCommand);\n\t\t\t} finally {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.stopWorker(match.worker, true, false, true);\n\t\t\t\t} finally {\n\t\t\t\t\treleaseStopOwnership();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn response;\n\t\t} finally {\n\t\t\tif (admission) this.deletePromptAdmission(admission);\n\t\t}\n\t}\n\n\tprivate async handleList(\n\t\tclient: DaemonSocketClient,\n\t\tcommand: Extract<DaemonCommand, { type: \"list\" }>,\n\t): Promise<DaemonResponse> {\n\t\tconst active: SessionSummary[] = [];\n\t\tconst activeByFile = new Map<string, SessionSummary>();\n\t\tlet busyClientOwnedSessionCount = 0;\n\t\tfor (const entry of this.roster().values()) {\n\t\t\tif (entry.queuedChild) continue;\n\t\t\tconst worker = entry.workerId !== undefined ? this.workers.get(entry.workerId) : undefined;\n\t\t\tif (worker === undefined) continue;\n\t\t\tconst summary = this.publicSummary(worker, sessionSummaryFromRosterEntry(entry));\n\t\t\tif (this.isVisibleWorker(worker)) {\n\t\t\t\tactive.push(summary);\n\t\t\t\tif (summary.sessionFile) activeByFile.set(canonicalSessionPath(summary.sessionFile), summary);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (summary.sessionFile) activeByFile.set(canonicalSessionPath(summary.sessionFile), summary);\n\t\t\tif (isSessionSummaryBusy(summary)) busyClientOwnedSessionCount += 1;\n\t\t\tif (command.includeClientOwned === true && this.isWorkerAccessibleToClient(client, worker)) {\n\t\t\t\tactive.push(summary);\n\t\t\t}\n\t\t}\n\t\tconst data = {\n\t\t\tsessions: active,\n\t\t\t...(command.includeClientOwned ? { busyClientOwnedSessionCount } : {}),\n\t\t};\n\t\tif (!command.all) {\n\t\t\treturn success(command.id, \"list\", data);\n\t\t}\n\t\tconst sessionDir = command.sessionDir ?? this.defaultSessionConfig.sessionDir;\n\t\tconst scanned = await this.catalog.list(command.cwd ? resolve(command.cwd) : undefined, sessionDir);\n\t\tconst cwd = command.cwd ? resolve(command.cwd) : undefined;\n\t\tconst merged: SessionSummary[] = [];\n\t\tconst servedRows = new Set(active);\n\t\tconst mergedActiveFiles = new Set<string>();\n\t\tconst scannedFiles = new Set<string>();\n\t\tfor (const info of scanned) {\n\t\t\tconst file = canonicalSessionPath(info.path);\n\t\t\tscannedFiles.add(file);\n\t\t\tconst workerRow = activeByFile.get(file);\n\t\t\tif (workerRow && servedRows.has(workerRow)) {\n\t\t\t\tmerged.push(workerRow);\n\t\t\t\tmergedActiveFiles.add(file);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// The on-disk scan is public: an unserved (client-owned) worker row hides its live metadata only.\n\t\t\tmerged.push(summaryForInactiveSession(info));\n\t\t}\n\t\t// The boot seed covers registered workers' families only, so dead families (pure on-disk\n\t\t// history, no registered worker anywhere in the tree) are not roster-resident. Their\n\t\t// subagent rows are read from the spawn ledger on demand instead.\n\t\tlet spawnEdges: RlmLedgerEdge[] = [];\n\t\ttry {\n\t\t\tspawnEdges = await this.rlmSpawnLedger().liveEdges();\n\t\t} catch (error) {\n\t\t\tthis.log(`Could not list spawn-ledger sessions: ${String(error)}`);\n\t\t}\n\t\tconst spawnParents = new Map(spawnEdges.map((edge) => [canonicalSessionPath(edge.child), edge.parent]));\n\t\tconst offlineRows: AgentRosterEntry[] = [];\n\t\tfor (const entry of this.roster().values()) {\n\t\t\tif (entry.queuedChild || entry.summary.activeSessionId !== undefined) continue;\n\t\t\tif (entry.workerId !== undefined && this.workers.has(entry.workerId)) continue;\n\t\t\tconst file = entry.summary.sessionFile ? canonicalSessionPath(entry.summary.sessionFile) : undefined;\n\t\t\tif (file === undefined || scannedFiles.has(file) || activeByFile.has(file)) continue;\n\t\t\tofflineRows.push(entry);\n\t\t}\n\t\tfor (const hydrated of await Promise.all(offlineRows.map((entry) => this.hydrateSeededEntry(entry)))) {\n\t\t\tconst summary = sessionSummaryFromRosterEntry(hydrated);\n\t\t\tif (cwd !== undefined && resolve(summary.cwd) !== cwd) continue;\n\t\t\tif (!this.matchesListSessionDir(summary, sessionDir, spawnParents)) continue;\n\t\t\tmerged.push(summary);\n\t\t}\n\t\tconst unseededFiles = new Set<string>();\n\t\tfor (const edge of spawnEdges) {\n\t\t\tconst childPath = canonicalSessionPath(edge.child);\n\t\t\tif (scannedFiles.has(childPath) || activeByFile.has(childPath) || unseededFiles.has(childPath)) continue;\n\t\t\tif (this.roster().hasSessionFile(childPath)) continue;\n\t\t\tconst entry = this.rosterEntryForSpawnLedgerEdge(edge);\n\t\t\tif (this.roster().has(entry.agentId)) continue;\n\t\t\tunseededFiles.add(childPath);\n\t\t\t// Hydrated one at a time, like the boot seed: a large dead-family ledger must not fan\n\t\t\t// out into one concurrent transcript read per child.\n\t\t\tconst hydrated = await this.hydratedSeedEntry(entry);\n\t\t\t// The same classification a roster write would have applied: these rows read \"inactive\".\n\t\t\tconst summary = sessionSummaryFromRosterEntry({\n\t\t\t\t...hydrated,\n\t\t\t\tstatus: classifySessionRosterStatus(hydrated.summary),\n\t\t\t});\n\t\t\tif (cwd !== undefined && resolve(summary.cwd) !== cwd) continue;\n\t\t\tif (!this.matchesListSessionDir(summary, sessionDir, spawnParents)) continue;\n\t\t\tmerged.push(summary);\n\t\t}\n\t\tfor (const summary of active) {\n\t\t\tconst file = summary.sessionFile ? canonicalSessionPath(summary.sessionFile) : undefined;\n\t\t\tif (file !== undefined && mergedActiveFiles.has(file)) continue;\n\t\t\tmerged.push(summary);\n\t\t}\n\t\treturn success(command.id, \"list\", { ...data, sessions: merged });\n\t}\n\n\tprivate async hydratedSeedEntry<T extends WorkerRosterEntry>(entry: T): Promise<T> {\n\t\tconst info = entry.summary.sessionFile\n\t\t\t? await readSessionInfo(entry.summary.sessionFile).catch(() => undefined)\n\t\t\t: undefined;\n\t\tif (!info) return { ...entry, seededCwd: true as const };\n\t\tconst { seededCwd, ...rest } = entry;\n\t\treturn { ...rest, summary: { ...entry.summary, cwd: info.cwd } } as T;\n\t}\n\n\tprivate async hydrateSeededEntry(entry: AgentRosterEntry): Promise<AgentRosterEntry> {\n\t\tif (entry.seededCwd !== true || !entry.summary.sessionFile) return entry;\n\t\tconst hydrated = await this.hydratedSeedEntry(entry);\n\t\tif (hydrated.seededCwd === true) return entry;\n\t\tconst current = this.roster().get(entry.agentId);\n\t\tif (current !== entry) return current ?? entry;\n\t\treturn this.roster().write(hydrated, entry.workerId, entry.statusLabel);\n\t}\n\n\tprivate matchesListSessionDir(\n\t\tsummary: SessionSummary,\n\t\tsessionDir: string | undefined,\n\t\tspawnParents?: ReadonlyMap<string, string>,\n\t): boolean {\n\t\tif (sessionDir === undefined) return true;\n\t\tif (!summary.sessionFile) return false;\n\t\tlet file = resolve(summary.sessionFile);\n\t\tlet parentSessionPath = summary.parentSessionPath;\n\t\tconst visited = new Set<string>();\n\t\twhile (parentSessionPath !== undefined) {\n\t\t\tconst canonical = canonicalSessionPath(parentSessionPath);\n\t\t\tif (visited.has(canonical)) break;\n\t\t\tvisited.add(canonical);\n\t\t\tfile = resolve(parentSessionPath);\n\t\t\t// Dead-family ancestors are not roster-resident; the spawn ledger continues the walk.\n\t\t\tparentSessionPath =\n\t\t\t\tthis.roster().bySessionFile(canonical)?.summary.parentSessionPath ?? spawnParents?.get(canonical);\n\t\t}\n\t\treturn dirname(file) === resolve(sessionDir);\n\t}\n\n\tprivate async handleSavedSessionList(\n\t\tclient: DaemonSocketClient,\n\t\tcommand: Extract<DaemonCommand, { type: \"list_saved_sessions\" }>,\n\t): Promise<DaemonResponse> {\n\t\tconst pageQuery = captureSavedSessionPageQuery(command.page ?? {});\n\t\tconst scope = command.scope;\n\t\tlet cwd: string;\n\t\tlet sessionDir: string | undefined;\n\t\tif (\"activeSessionId\" in command) {\n\t\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\t\tcwd = match.summary.cwd;\n\t\t\tsessionDir = this.defaultSessionConfig.sessionDir;\n\t\t} else {\n\t\t\tcwd = resolve(command.cwd);\n\t\t\tsessionDir = command.sessionDir;\n\t\t}\n\t\tconst { agentDir, sessionsDir: ledgerSessionDir } = this.rlmJournalScope(sessionDir);\n\t\tconst page = await this.catalog.list(cwd, sessionDir, { page: pageQuery, scope, agentDir, ledgerSessionDir });\n\t\treturn success(command.id, \"list_saved_sessions\", page);\n\t}\n\n\tprivate async createOrReuseWorker(clientId: string, command: DaemonCreateCommand): Promise<ResidentWorker> {\n\t\tlet createCommand = command;\n\t\tif (command.name !== undefined) {\n\t\t\tconst normalizedName = command.name.trim();\n\t\t\tif (!normalizedName) {\n\t\t\t\tthrow new Error(\"Session name cannot be empty\");\n\t\t\t}\n\t\t\tcreateCommand = { ...command, name: normalizedName };\n\t\t}\n\t\tconst ownerClientId = command.lifecycle === \"client_owned\" ? clientId : undefined;\n\t\tif (command.sessionPath) {\n\t\t\tconst activeMatches = this.matchWorkers(command.sessionPath);\n\t\t\tif (\n\t\t\t\tactiveMatches.length === 1 &&\n\t\t\t\t!(await this.reclaimStaleWorkerRegistration(activeMatches[0]!.worker, command.launchEnv !== undefined))\n\t\t\t) {\n\t\t\t\treturn this.reuseWorkerForCreate(activeMatches[0]!.worker, ownerClientId, command.sessionPath);\n\t\t\t}\n\t\t\tif (activeMatches.length > 1) {\n\t\t\t\tthrow new Error(`Ambiguous active session \"${command.sessionPath}\"`);\n\t\t\t}\n\t\t\tconst config = mergeAgentSessionRuntimeConfig(this.defaultSessionConfig, command.config);\n\t\t\tconst sessionPath = looksLikeSessionPath(command.sessionPath)\n\t\t\t\t? resolve(command.sessionPath)\n\t\t\t\t: await this.catalog.resolve(command.sessionPath, config.cwd ?? process.cwd(), config.sessionDir);\n\t\t\tcreateCommand = { ...createCommand, sessionPath };\n\t\t}\n\t\tconst key = createCommand.sessionPath\n\t\t\t? canonicalSessionPath(createCommand.sessionPath)\n\t\t\t: `new:${command.id ? createCommandIdempotencyKey(clientId, command.id) : createActiveSessionId()}`;\n\t\tconst pending = this.openingWorkers.get(key);\n\t\tif (pending) {\n\t\t\treturn this.joinOpeningWorker(pending, ownerClientId, createCommand.sessionPath ?? key);\n\t\t}\n\t\tif (createCommand.sessionPath) {\n\t\t\tconst existing = this.findWorkerBySessionFile(createCommand.sessionPath);\n\t\t\tif (existing && !(await this.reclaimStaleWorkerRegistration(existing, command.launchEnv !== undefined))) {\n\t\t\t\treturn this.reuseWorkerForCreate(existing, ownerClientId, createCommand.sessionPath);\n\t\t\t}\n\t\t\t// The reclaim await may have let a concurrent opener register; join it instead of double-launching.\n\t\t\tconst opened = this.openingWorkers.get(key);\n\t\t\tif (opened) {\n\t\t\t\treturn this.joinOpeningWorker(opened, ownerClientId, createCommand.sessionPath);\n\t\t\t}\n\t\t}\n\t\tif (createCommand.sessionPath) {\n\t\t\tconst existing = this.findWorkerBySessionFile(createCommand.sessionPath);\n\t\t\tif (existing && !(await this.reclaimStaleWorkerRegistration(existing, command.launchEnv !== undefined))) {\n\t\t\t\treturn this.reuseWorkerForCreate(existing, ownerClientId, createCommand.sessionPath);\n\t\t\t}\n\t\t}\n\t\tconst opening = (async () => {\n\t\t\tif (!createCommand.name) return this.launchWorker(createCommand, undefined, ownerClientId);\n\t\t\tconst savedSiblings = createCommand.sessionPath ? await this.rlmLedgerSiblings(createCommand.sessionPath) : [];\n\t\t\tconst target = savedSiblings.find(\n\t\t\t\t(session) => canonicalSessionPath(session.path) === canonicalSessionPath(createCommand.sessionPath!),\n\t\t\t);\n\t\t\tconst targetSummary = target ? summaryForInactiveSession(target) : { sessionId: \"new-root\", rlmDepth: 0 };\n\t\t\tconst reservation = this.summaryNameReservationInput(targetSummary, createCommand.name);\n\t\t\treturn this.withSessionNameReservation(reservation, async () => {\n\t\t\t\tif (target?.parentSessionPath && (target.rlmDepth ?? 0) > 0) {\n\t\t\t\t\tthis.assertSavedSiblingNameAvailable(savedSiblings, target, createCommand.name!);\n\t\t\t\t} else {\n\t\t\t\t\tawait this.assertSupervisorSessionNameAvailable(targetSummary, createCommand.name!);\n\t\t\t\t}\n\t\t\t\treturn this.launchWorker(createCommand, undefined, ownerClientId);\n\t\t\t});\n\t\t})();\n\t\tthis.openingWorkers.set(key, opening);\n\t\ttry {\n\t\t\treturn await opening;\n\t\t} finally {\n\t\t\tif (this.openingWorkers.get(key) === opening) {\n\t\t\t\tthis.openingWorkers.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async reuseWorkerForCreate(\n\t\tworker: ResidentWorker,\n\t\townerClientId: string | undefined,\n\t\tsessionPath: string,\n\t): Promise<ResidentWorker> {\n\t\tif (worker.descriptor.lifecycle === \"failed\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Session \"${sessionPath}\" is registered to a failed worker that could not be safely reclaimed`,\n\t\t\t);\n\t\t}\n\t\tthis.assertWorkerCreateOwner(worker, ownerClientId, sessionPath);\n\t\tif (!this.isWorkerReadyForCreate(worker)) {\n\t\t\tif (worker.recovery) {\n\t\t\t\tawait worker.recovery;\n\t\t\t} else if (this.isWorkerRecoveryEligible(worker)) {\n\t\t\t\tawait this.recoverWorker(worker);\n\t\t\t}\n\t\t}\n\t\tconst current = this.workers.get(worker.descriptor.workerId);\n\t\tif (!current) {\n\t\t\tthrow new Error(`Session \"${sessionPath}\" worker recovery was interrupted; retry opening the session`);\n\t\t}\n\t\tthis.assertWorkerCreateOwner(current, ownerClientId, sessionPath);\n\t\tif (!this.isWorkerReadyForCreate(current)) {\n\t\t\tif (!this.workerHasRosterRoot(current)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Session \"${sessionPath}\" worker is unavailable for reuse: assigned root session is missing`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst detail = current.descriptor.lastError ? `: ${current.descriptor.lastError}` : \"\";\n\t\t\tthrow new Error(`Session \"${sessionPath}\" worker is ${this.effectiveWorkerState(current)}${detail}`);\n\t\t}\n\t\treturn current;\n\t}\n\n\tprivate async joinOpeningWorker(\n\t\tpending: Promise<ResidentWorker>,\n\t\townerClientId: string | undefined,\n\t\tsessionPath: string,\n\t): Promise<ResidentWorker> {\n\t\tconst worker = await pending;\n\t\tthis.assertWorkerCreateOwner(worker, ownerClientId, sessionPath);\n\t\treturn worker;\n\t}\n\n\tprivate assertWorkerCreateOwner(\n\t\tworker: ResidentWorker,\n\t\townerClientId: string | undefined,\n\t\tsessionPath: string,\n\t): void {\n\t\tif (worker.descriptor.ownerClientId !== ownerClientId) {\n\t\t\tthrow new SessionAlreadyActiveError(sessionPath, worker.descriptor.rootActiveSessionId);\n\t\t}\n\t}\n\n\tprivate isWorkerReadyForCreate(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tworker.descriptor.lifecycle === \"ready\" &&\n\t\t\tworker.client !== undefined &&\n\t\t\tthis.workerHasRosterRoot(worker) &&\n\t\t\t!this.isWorkerStopping(worker)\n\t\t);\n\t}\n\n\tprivate workerHasRosterRoot(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tthis.roster().byActiveSessionId(worker.descriptor.rootActiveSessionId)?.workerId === worker.descriptor.workerId\n\t\t);\n\t}\n\n\t/**\n\t * A stopping worker whose process already died can strand its registration\n\t * (for example when the stop timed out and its finalization was interrupted\n\t * by a supervisor restart). Such a registration would block reopening the\n\t * saved transcript forever, so complete the interrupted stop and let the\n\t * caller launch a fresh worker for the saved session.\n\t */\n\tprivate async reclaimStaleWorkerRegistration(worker: ResidentWorker, freshCreate = false): Promise<boolean> {\n\t\tif (worker.client !== undefined || worker.recovery !== undefined) {\n\t\t\treturn false;\n\t\t}\n\t\tif (worker.descriptor.stopRequestedAt === undefined) {\n\t\t\tif (worker.descriptor.lifecycle !== \"failed\" || worker.descriptor.ownerClientId) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst identity = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t\tif (identity === \"current\") {\n\t\t\t\tif (worker.compatibilityError || !freshCreate || !worker.descriptor.processStartId) return false;\n\t\t\t\tawait this.stopWorker(worker, true, true);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (identity !== \"gone\" && identity !== \"replaced\") {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tworker.intentionalStop = true;\n\t\t\tawait this.recoverUncertainWorkerOperations(worker);\n\t\t\tthis.invalidateWorkerSessionInputPauses(worker, \"Session worker stopped while input was paused\");\n\t\t\tthis.workers.delete(worker.descriptor.workerId);\n\t\t\tthis.flipWorkerRosterEntriesInactive(worker);\n\t\t\tthis.deleteWorkerDescriptor(worker);\n\t\t\treturn true;\n\t\t}\n\t\t// Fail fast before waiting on anything: only a confirmed-dead process is\n\t\t// reclaimable. A live, unknown, or still-stopping worker is left alone\n\t\t// and the caller reports the session as already active.\n\t\tconst identity = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\tif (identity !== \"gone\" && identity !== \"replaced\") {\n\t\t\treturn false;\n\t\t}\n\t\t// Single cleanup path: the background stop finalizer is identity-aware,\n\t\t// retrying, and single-flighted, so concurrent resumes share one stop.\n\t\t// The wait is bounded so a resume request always returns promptly.\n\t\tthis.scheduleWorkerStopFinalization(worker);\n\t\tconst finalization = worker.stopFinalization;\n\t\tif (finalization) {\n\t\t\tawait Promise.race([finalization.catch(() => undefined), unrefDelay(STALE_RECLAIM_WAIT_MS)]);\n\t\t}\n\t\tif (this.workers.get(worker.descriptor.workerId) === worker) {\n\t\t\t// The process is confirmed dead, so the registration must never be\n\t\t\t// reused; slow cleanup fails the resume honestly instead.\n\t\t\tthrow new Error(\n\t\t\t\t`Stopped session worker ${worker.descriptor.workerId} is still being cleaned up; retry shortly`,\n\t\t\t);\n\t\t}\n\t\tthis.log(`Reclaimed stale registration for stopped worker ${worker.descriptor.workerId}`);\n\t\treturn true;\n\t}\n\n\tprivate async promoteOwnedWorker(client: DaemonSocketClient, worker: ResidentWorker): Promise<void> {\n\t\tconst clientId = this.protocolClientId(client);\n\t\tif (worker.descriptor.ownerClientId === undefined && worker.promotedOwnerClientId === clientId) {\n\t\t\treturn;\n\t\t}\n\t\tif (worker.descriptor.ownerClientId !== clientId) {\n\t\t\tthrow new Error(\"Session is not owned by this client\");\n\t\t}\n\t\tconst previousDescriptor = worker.descriptor;\n\t\tworker.descriptor = { ...previousDescriptor, ownerClientId: undefined };\n\t\ttry {\n\t\t\tthis.persistWorker(worker);\n\t\t} catch (error) {\n\t\t\tworker.descriptor = previousDescriptor;\n\t\t\tthrow error;\n\t\t}\n\t\tworker.promotedOwnerClientId = clientId;\n\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\tthis.roster().amend(entry.agentId, {});\n\t\t}\n\t\tif (worker.ownerCleanupTimer) {\n\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t}\n\t\tworker.launchEnv = undefined;\n\t\tworker.transientCreateCommand = undefined;\n\t}\n\n\tprivate describeWorkerSpawnFailure(error: Error): Error {\n\t\tconst errno = (error as NodeJS.ErrnoException).code;\n\t\tconst hint =\n\t\t\terrno === \"EMFILE\" || errno === \"ENFILE\"\n\t\t\t\t? ` (${this.workers.size} resident session workers are holding file descriptors; stop unused sessions or raise the open-file limit (ulimit -n))`\n\t\t\t\t: \"\";\n\t\treturn new Error(`Failed to spawn session worker: ${error.message}${hint}`);\n\t}\n\n\tprivate async launchWorker(\n\t\tcommand: DaemonCreateCommand,\n\t\texisting?: ResidentWorker,\n\t\townerClientId?: string,\n\t): Promise<ResidentWorker> {\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (existing && this.isWorkerRecoveryCancelled(existing)) {\n\t\t\tthrow new Error(`Session worker ${existing.descriptor.workerId} recovery was cancelled`);\n\t\t}\n\t\tconst recoveryStopRevision = existing?.stopRevision;\n\t\tconst launchEnv = command.launchEnv ?? existing?.launchEnv;\n\t\tconst createCommand: DaemonCreateCommand = {\n\t\t\t...withoutSupervisorCreateFields(command),\n\t\t\tconfig: mergeAgentSessionRuntimeConfig(this.defaultSessionConfig, command.config),\n\t\t};\n\t\tconst workerId = existing?.descriptor.workerId ?? createActiveSessionId();\n\t\tconst rootActiveSessionId = existing?.descriptor.rootActiveSessionId ?? createActiveSessionId();\n\t\tconst socketPath = existing?.descriptor.socketPath ?? workerSocketPath(this.socketPath, workerId);\n\t\tconst token = existing?.descriptor.authenticationToken ?? randomBytes(32).toString(\"base64url\");\n\t\t// Fresh per incarnation: peer transport grants must never survive a worker restart.\n\t\tconst workerInstanceId = randomUUID();\n\t\tconst now = new Date().toISOString();\n\t\tconst descriptorPath = existing?.descriptorPath ?? join(this.descriptorDir, `${workerId}.json`);\n\t\tconst recoveryJournalPath =\n\t\t\texisting?.descriptor.recoveryJournalPath ?? join(this.descriptorDir, `${workerId}.recovery.jsonl`);\n\t\tconst orphanProcessJournalPath =\n\t\t\texisting?.descriptor.orphanProcessJournalPath ?? join(this.descriptorDir, `${workerId}.orphans.jsonl`);\n\t\tconst launch = createCliSubprocessLaunchSpec([\"--mode\", \"daemon\", \"--daemon-socket\", socketPath]);\n\t\tconst workerEnvironment = createCliSubprocessEnv({\n\t\t\t...process.env,\n\t\t\t...launchEnv,\n\t\t\t[DAEMON_WORKER_ROLE_ENV]: \"1\",\n\t\t\t[DAEMON_WORKER_TOKEN_ENV]: token,\n\t\t\t[DAEMON_WORKER_INSTANCE_ID_ENV]: workerInstanceId,\n\t\t\t[DAEMON_WORKER_ACTIVE_SESSION_ID_ENV]: rootActiveSessionId,\n\t\t\t[DAEMON_WORKER_SUPERVISOR_SOCKET_ENV]: this.socketPath,\n\t\t\t[DAEMON_WORKER_RECOVERY_JOURNAL_ENV]: recoveryJournalPath,\n\t\t\t[DAEMON_WORKER_STARTUP_GATE_FD_ENV]: String(WORKER_STARTUP_GATE_FD),\n\t\t\t[ORPHAN_PROCESS_JOURNAL_ENV]: orphanProcessJournalPath,\n\t\t\t[SESSION_LEASES_ENABLED_ENV]: \"1\",\n\t\t\t[SESSION_LEASE_OWNER_ID_ENV]: rootActiveSessionId,\n\t\t});\n\t\tdelete workerEnvironment.BASE_CONTEXT_RLM_DEPTH;\n\t\tawait this.assertRecoveryAllowed();\n\t\tconst child: ChildProcess = spawn(launch.command, launch.args, {\n\t\t\tcwd: createCommand.config?.cwd ?? process.cwd(),\n\t\t\tdetached: true,\n\t\t\tenv: workerEnvironment,\n\t\t\tstdio: [\"ignore\", \"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tconst detachWorkerStderr = child.stderr\n\t\t\t? attachJsonlLineReader(child.stderr, (line) => this.log(`Session worker ${workerId} stderr: ${line}`), {\n\t\t\t\t\tmaxLineLength: 64 * 1024,\n\t\t\t\t\tonLineOverflow: (prefix) => this.log(`Session worker ${workerId} stderr: ${prefix} [truncated]`),\n\t\t\t\t})\n\t\t\t: () => {};\n\t\tchild.once(\"close\", detachWorkerStderr);\n\t\tconst childClosed = new Promise<void>((resolveClose) => child.once(\"close\", () => resolveClose()));\n\t\tlet spawnFailure: Error | undefined;\n\t\tconst spawnSettled = new Promise<void>((resolveSpawn) => {\n\t\t\tchild.once(\"spawn\", () => resolveSpawn());\n\t\t\tchild.once(\"error\", (error) => {\n\t\t\t\tspawnFailure = error instanceof Error ? error : new Error(String(error));\n\t\t\t\tresolveSpawn();\n\t\t\t});\n\t\t});\n\t\tchild.on(\"error\", (error) => {\n\t\t\tthis.log(\n\t\t\t\t`Session worker ${workerId} process error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t});\n\t\t// A failed spawn (e.g. EMFILE) leaves child.stdio undefined.\n\t\tconst startupGate = child.stdio?.[WORKER_STARTUP_GATE_FD];\n\t\tconst previousDescriptor = existing?.descriptor;\n\t\tconst previousIntentionalStop = existing?.intentionalStop;\n\t\tlet descriptorAssigned = false;\n\t\tlet childPid: number;\n\t\tlet childProcessStartId: string | undefined;\n\t\tlet worker: ResidentWorker;\n\t\ttry {\n\t\t\tawait spawnSettled;\n\t\t\tif (spawnFailure) {\n\t\t\t\tthrow this.describeWorkerSpawnFailure(spawnFailure);\n\t\t\t}\n\t\t\tif (!child.pid) {\n\t\t\t\tthrow new Error(\"Failed to obtain daemon session worker pid\");\n\t\t\t}\n\t\t\tif (!(startupGate instanceof Writable)) {\n\t\t\t\tthrow new Error(\"Failed to create daemon session worker startup gate\");\n\t\t\t}\n\t\t\tchildPid = child.pid;\n\t\t\tchildProcessStartId = getProcessStartId(childPid);\n\t\t\tawait this.assertRecoveryAllowed();\n\n\t\t\tconst descriptor: DaemonWorkerDescriptor = {\n\t\t\t\tversion: 2,\n\t\t\t\tworkerId,\n\t\t\t\tpid: childPid,\n\t\t\t\t...(childProcessStartId ? { processStartId: childProcessStartId } : {}),\n\t\t\t\tsocketPath,\n\t\t\t\trecoveryJournalPath,\n\t\t\t\torphanProcessJournalPath,\n\t\t\t\tsupervisorSocketPath: this.socketPath,\n\t\t\t\tauthenticationToken: token,\n\t\t\t\tworkerInstanceId,\n\t\t\t\trootActiveSessionId,\n\t\t\t\townerClientId: existing?.descriptor.ownerClientId ?? ownerClientId,\n\t\t\t\tsessionDir: createCommand.config?.sessionDir,\n\t\t\t\tcreatedAt: existing?.descriptor.createdAt ?? now,\n\t\t\t\tupdatedAt: now,\n\t\t\t\tlifecycle: \"starting\",\n\t\t\t\tcreateCommand: durableDaemonCreateCommand(createCommand),\n\t\t\t\tconsecutiveFailures: existing?.descriptor.consecutiveFailures ?? 0,\n\t\t\t};\n\t\t\tworker = existing ?? {\n\t\t\t\tdescriptor,\n\t\t\t\tdescriptorPath,\n\t\t\t\tsummaries: new Map(),\n\t\t\t\tsnapshotCache: new Map(),\n\t\t\t\ttranscriptCaches: new Map(),\n\t\t\t\tsnapshotGenerations: new Map(),\n\t\t\t\tsnapshotLoads: new Map(),\n\t\t\t\tintentionalStop: false,\n\t\t\t\tstopRevision: 0,\n\t\t\t\tlaunchEnv,\n\t\t\t\ttransientCreateCommand: ownerClientId ? createCommand : undefined,\n\t\t\t};\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tworker.descriptor = descriptor;\n\t\t\tworker.launchEnv = launchEnv;\n\t\t\tworker.transientCreateCommand = descriptor.ownerClientId ? createCommand : undefined;\n\t\t\tdescriptorAssigned = true;\n\t\t\tthis.persistWorker(worker);\n\t\t\tworker.intentionalStop = false;\n\t\t\tthis.workers.set(workerId, worker);\n\t\t} catch (error) {\n\t\t\tif (startupGate instanceof Writable) {\n\t\t\t\tstartupGate.destroy();\n\t\t\t}\n\t\t\tawait childClosed;\n\t\t\tchild.unref();\n\t\t\ttry {\n\t\t\t\trmSync(`${descriptorPath}.${process.pid}.tmp`, { force: true });\n\t\t\t} catch (cleanupError) {\n\t\t\t\tthis.reportCleanupFailure(`worker launch temp ${workerId}`, cleanupError);\n\t\t\t}\n\t\t\tif (existing && descriptorAssigned && previousDescriptor) {\n\t\t\t\ttry {\n\t\t\t\t\texisting.descriptor = previousDescriptor;\n\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\tthis.reportCleanupFailure(`worker launch descriptor ${workerId}`, cleanupError);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\ttry {\n\t\t\ttry {\n\t\t\t\tawait commitWorkerStartupGate(startupGate);\n\t\t\t} catch (error) {\n\t\t\t\tstartupGate.destroy();\n\t\t\t\tawait childClosed;\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tchild.unref();\n\t\t\t}\n\t\t\tconst client = await this.connectWorker(worker, WORKER_CONNECT_TIMEOUT_MS);\n\t\t\tconst response = await client.request(withoutCommandId(createCommand), WORKER_REQUEST_TIMEOUT_MS);\n\t\t\tif (!response.success) {\n\t\t\t\tthrow deserializeDaemonError(response);\n\t\t\t}\n\t\t\tif (!isSessionSummary(response.data)) {\n\t\t\t\tthrow new Error(\"Session worker returned an invalid create response\");\n\t\t\t}\n\t\t\tconst summary = response.data;\n\t\t\tif ((summary.activeSessionId ?? summary.id) !== rootActiveSessionId) {\n\t\t\t\tthrow new Error(\"Session worker did not preserve its assigned active session id\");\n\t\t\t}\n\t\t\tthis.writeRosterEntry(workerRosterEntryFromSummary(summary), worker);\n\t\t\tworker.descriptor.rootSessionId = summary.sessionId;\n\t\t\tworker.descriptor.sessionFile = summary.sessionFile;\n\t\t\tawait this.subscribeWorker(worker, rootActiveSessionId);\n\t\t\tawait this.refreshWorkerSummaries(worker, true);\n\t\t\tif (existing && (this.isWorkerRecoveryCancelled(worker) || worker.stopRevision !== recoveryStopRevision)) {\n\t\t\t\tthrow new Error(`Session worker ${workerId} recovery was cancelled`);\n\t\t\t}\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tworker.descriptor.lifecycle = \"ready\";\n\t\t\tworker.descriptor.consecutiveFailures = 0;\n\t\t\tworker.deferredRecoveryRounds = 0;\n\t\t\tworker.descriptor.lastError = undefined;\n\t\t\tthis.persistWorker(worker);\n\t\t\tif (!worker.descriptor.ownerClientId) {\n\t\t\t\tworker.launchEnv = undefined;\n\t\t\t\tworker.transientCreateCommand = undefined;\n\t\t\t}\n\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\treturn worker;\n\t\t} catch (error) {\n\t\t\tif (isSupervisorGenerationStale(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\tthis.parkIncompatibleWorker(worker, error);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (isSupervisorShutdownAdmissionCancelled(error)) {\n\t\t\t\tlet rolledBack = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait this.stopWorker(worker, existing === undefined, true, false, existing !== undefined, {\n\t\t\t\t\t\tchild,\n\t\t\t\t\t\tclosed: childClosed,\n\t\t\t\t\t});\n\t\t\t\t\trolledBack = true;\n\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\tthis.reportCleanupFailure(`cancelled worker launch ${workerId}`, cleanupError);\n\t\t\t\t}\n\t\t\t\tconst mappedWorker = this.workers.get(workerId);\n\t\t\t\tif (\n\t\t\t\t\trolledBack &&\n\t\t\t\t\texisting &&\n\t\t\t\t\tpreviousDescriptor &&\n\t\t\t\t\t!this.shuttingDown &&\n\t\t\t\t\texisting.stopRevision === recoveryStopRevision &&\n\t\t\t\t\texisting.descriptor.stopRequestedAt === undefined &&\n\t\t\t\t\t(mappedWorker === undefined || mappedWorker === existing)\n\t\t\t\t) {\n\t\t\t\t\texisting.descriptor = previousDescriptor;\n\t\t\t\t\texisting.intentionalStop = previousIntentionalStop ?? false;\n\t\t\t\t\tthis.workers.set(workerId, existing);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.persistWorker(existing);\n\t\t\t\t\t} catch (cleanupError) {\n\t\t\t\t\t\tthis.reportCleanupFailure(`cancelled worker recovery ${workerId}`, cleanupError);\n\t\t\t\t\t}\n\t\t\t\t\tthis.deferWorkerRecovery(existing, error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tconst shouldResumeRecovery =\n\t\t\t\texisting !== undefined &&\n\t\t\t\t!this.shuttingDown &&\n\t\t\t\tworker.descriptor.stopRequestedAt === undefined &&\n\t\t\t\tworker.stopRevision === recoveryStopRevision;\n\t\t\tawait this.stopWorker(worker, existing === undefined, true, false, existing !== undefined).catch((stopError) =>\n\t\t\t\tthis.log(`Could not stop failed worker ${workerId}: ${String(stopError)}`),\n\t\t\t);\n\t\t\tif (\n\t\t\t\tshouldResumeRecovery &&\n\t\t\t\t!this.shuttingDown &&\n\t\t\t\tworker.descriptor.stopRequestedAt === undefined &&\n\t\t\t\tworker.stopRevision === recoveryStopRevision\n\t\t\t) {\n\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\tworker.intentionalStop = false;\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tthis.workers.set(workerId, worker);\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async connectWorker(worker: ResidentWorker, timeoutMs: number): Promise<DaemonWorkerClient> {\n\t\tconst deadline = Date.now() + timeoutMs;\n\t\tlet lastError: unknown;\n\t\twhile (Date.now() < deadline) {\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tconst client = new DaemonWorkerClient(worker.descriptor.socketPath);\n\t\t\ttry {\n\t\t\t\tawait client.connect(Math.min(500, Math.max(50, deadline - Date.now())));\n\t\t\t\tawait client.waitForHello(1000);\n\t\t\t\t// Listen before authenticating: the worker flushes its roster snapshot right after auth succeeds.\n\t\t\t\tclient.onFrame((frame) => this.handleWorkerFrame(worker, frame, client));\n\t\t\t\tclient.onClose((error) => void this.handleWorkerClose(worker, client, error));\n\t\t\t\tworker.pendingClient = client;\n\t\t\t\ttry {\n\t\t\t\t\tconst authResponse = await client.authenticateWorker(\n\t\t\t\t\t\tworker.descriptor.authenticationToken,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...this.supervisorAuthenticationClaim(),\n\t\t\t\t\t\t\t...(worker.descriptor.workerInstanceId !== undefined\n\t\t\t\t\t\t\t\t? { workerInstanceId: worker.descriptor.workerInstanceId }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\t1000,\n\t\t\t\t\t);\n\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\tif (!workerAuthAdvertisesRoster(authResponse.data)) {\n\t\t\t\t\t\tthrow new PreRosterWorkerError(\"Session worker predates the roster protocol and must be restarted\");\n\t\t\t\t\t}\n\t\t\t\t\tawait this.restoreWorkerRlmCapacity(worker, client);\n\t\t\t\t\tworker.peerTransportCapable = workerAuthAdvertisesPeerTransport(authResponse.data);\n\t\t\t\t\tworker.lastFrameAt = Date.now();\n\t\t\t\t\tworker.client?.close();\n\t\t\t\t\tworker.client = client;\n\t\t\t\t\tworker.compatibilityError = undefined;\n\t\t\t\t\tworker.descriptor.lastError = undefined;\n\t\t\t\t\treturn client;\n\t\t\t\t} finally {\n\t\t\t\t\tif (worker.pendingClient === client) worker.pendingClient = undefined;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error;\n\t\t\t\tclient.close();\n\t\t\t\tif (\n\t\t\t\t\tisSupervisorRecoveryCancelled(error) ||\n\t\t\t\t\terror instanceof PreRosterWorkerError ||\n\t\t\t\t\terror instanceof DaemonWorkerAuthenticationError ||\n\t\t\t\t\terror instanceof DaemonWorkerCompatibilityError\n\t\t\t\t) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tawait delay(25);\n\t\t\t}\n\t\t}\n\t\tthrow new DaemonWorkerProbeTimeoutError(`Timed out connecting to daemon session worker: ${String(lastError)}`);\n\t}\n\n\tprivate parkIncompatibleWorker(worker: ResidentWorker, error: DaemonWorkerCompatibilityError): void {\n\t\t// Compatibility refusal is not evidence that this process or its ownership is dead.\n\t\tworker.compatibilityError = error;\n\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\tworker.descriptor.lastError = error.message;\n\t\tconst client = worker.client;\n\t\tworker.client = undefined;\n\t\tclient?.close();\n\t\tif (worker.ownerCleanupTimer) {\n\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t}\n\t\tthis.persistWorker(worker);\n\t\tthis.markWorkerRosterEntries(worker, \"recovering\");\n\t\tthis.log(`Kept incompatible worker ${worker.descriptor.workerId}: ${error.message}`);\n\t}\n\n\tprivate async subscribeWorker(worker: ResidentWorker, activeSessionId: string): Promise<void> {\n\t\tif (!worker.client) {\n\t\t\tthrow new Error(\"Session worker is not connected\");\n\t\t}\n\t\tconst supportsExtensionUi = [...this.clients].some(\n\t\t\t(client) => client.attachedActiveSessionIds.has(activeSessionId) && client.supportsExtensionUi,\n\t\t);\n\t\tconst response = await worker.client.requestWorker({\n\t\t\ttype: \"worker_subscribe\",\n\t\t\tactiveSessionId,\n\t\t\tcapabilities: supportsExtensionUi\n\t\t\t\t? [\"attach_snapshot\", \"event_sequence\", \"extension_ui\", \"slim_attach\", \"chunked_snapshot\"]\n\t\t\t\t: [\"attach_snapshot\", \"event_sequence\", \"slim_attach\", \"chunked_snapshot\"],\n\t\t\tsupportsExtensionUi,\n\t\t});\n\t\tif (!response.success) {\n\t\t\tthrow new Error(response.error);\n\t\t}\n\t}\n\n\tprivate async adoptOrRecoverWorker(worker: ResidentWorker, recoveryReady?: Promise<void>): Promise<void> {\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (worker.descriptor.stopRequestedAt) {\n\t\t\ttry {\n\t\t\t\t// A descriptor persisted before identity tracking has no\n\t\t\t\t// processStartId, so stopWorker could neither signal the live\n\t\t\t\t// process nor let the finalizer escalate. Authenticating on the\n\t\t\t\t// worker's socket proves the pid still belongs to our worker, so\n\t\t\t\t// the start id observed while it was alive can be persisted (and\n\t\t\t\t// the connected client gives stopWorker its graceful IPC path).\n\t\t\t\tif (worker.descriptor.processStartId === undefined && isProcessAlive(worker.descriptor.pid)) {\n\t\t\t\t\tconst observedProcessStartId = getProcessStartId(worker.descriptor.pid);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.connectWorker(worker, 2000);\n\t\t\t\t\t\tif (observedProcessStartId) {\n\t\t\t\t\t\t\tworker.descriptor.processStartId = observedProcessStartId;\n\t\t\t\t\t\t\tthis.persistWorker(worker);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Unverifiable identity stays untrusted; the stop below\n\t\t\t\t\t\t// still runs its graceful path and the finalizer keeps\n\t\t\t\t\t\t// waiting rather than signalling a possibly-recycled pid.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tawait this.stopWorker(worker, true, true, worker.descriptor.archiveOnStop === true);\n\t\t\t\tthis.log(`Completed intentional stop for worker ${worker.descriptor.workerId} during supervisor adoption`);\n\t\t\t} catch (error) {\n\t\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\t\tworker.descriptor.lastError = error instanceof Error ? error.message : String(error);\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tthis.log(`Could not complete intentional stop for worker ${worker.descriptor.workerId}: ${String(error)}`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tlet observedProcessStartId: string | undefined;\n\t\ttry {\n\t\t\tif (!isProcessAlive(worker.descriptor.pid)) {\n\t\t\t\tthrow new Error(\"Session worker process is no longer running\");\n\t\t\t}\n\t\t\tobservedProcessStartId = getProcessStartId(worker.descriptor.pid);\n\t\t\tawait this.connectWorker(worker, 2000);\n\t\t\tawait this.subscribeWorker(worker, worker.descriptor.rootActiveSessionId);\n\t\t\tawait this.refreshWorkerSummaries(worker, true);\n\t\t\tif (worker.descriptor.processStartId === undefined && observedProcessStartId) {\n\t\t\t\tworker.descriptor.processStartId = observedProcessStartId;\n\t\t\t}\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t\tworker.descriptor.lifecycle = \"ready\";\n\t\t\tworker.descriptor.consecutiveFailures = 0;\n\t\t\tworker.deferredRecoveryRounds = 0;\n\t\t\tthis.persistWorker(worker);\n\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t} catch (error) {\n\t\t\tif (isSupervisorRecoveryCancelled(error)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\tthis.parkIncompatibleWorker(worker, error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.log(`Could not adopt worker ${worker.descriptor.workerId}: ${String(error)}`);\n\t\t\tif (recoveryReady) {\n\t\t\t\t// Recovery can create workers that call back for capacity. Keep it single-flight,\n\t\t\t\t// but let adoption finish before those callbacks need the normal ready gate.\n\t\t\t\tvoid this.recoverWorker(worker, {\n\t\t\t\t\tready: recoveryReady,\n\t\t\t\t\t...(error instanceof PreRosterWorkerError && worker.descriptor.ownerClientId === undefined\n\t\t\t\t\t\t? { preRoster: { observedProcessStartId } }\n\t\t\t\t\t\t: {}),\n\t\t\t\t}).catch((recoveryError) =>\n\t\t\t\t\tthis.log(`Could not recover worker ${worker.descriptor.workerId}: ${String(recoveryError)}`),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// A client-owned worker's launch env lives only with its owner; recoverWorker parks it instead.\n\t\t\tif (error instanceof PreRosterWorkerError && worker.descriptor.ownerClientId === undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.restartPreRosterWorker(worker, observedProcessStartId);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (restartError) {\n\t\t\t\t\tif (isSupervisorRecoveryCancelled(restartError)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.log(`Could not restart pre-roster worker ${worker.descriptor.workerId}: ${String(restartError)}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst identityNow = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t\tif (isDaemonWorkerProbeTimeout(error) && (identityNow === \"current\" || identityNow === \"unknown\")) {\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tworker.descriptor.lastError = error instanceof Error ? error.message : String(error);\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tvoid this.recoverWorker(worker).catch((recoveryError) =>\n\t\t\t\t\tthis.log(`Could not recover worker ${worker.descriptor.workerId}: ${String(recoveryError)}`),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait this.recoverWorker(worker);\n\t\t}\n\t}\n\n\tprivate async restartPreRosterWorker(\n\t\tworker: ResidentWorker,\n\t\tobservedProcessStartId: string | undefined,\n\t): Promise<void> {\n\t\tconst stopRevision = worker.stopRevision;\n\t\tconst workerInstanceId = worker.descriptor.workerInstanceId;\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (\n\t\t\tthis.isWorkerRecoveryCancelled(worker) ||\n\t\t\tworker.stopRevision !== stopRevision ||\n\t\t\tworker.descriptor.workerInstanceId !== workerInstanceId\n\t\t)\n\t\t\treturn;\n\t\tif (worker.descriptor.processStartId === undefined && observedProcessStartId !== undefined) {\n\t\t\tworker.descriptor.processStartId = observedProcessStartId;\n\t\t}\n\t\tconst identity = () => this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t// The one deliberate kill of a live worker: it authenticated as ours and predates the roster\n\t\t// protocol, so this identity-verified upgrade replaces it. No await between recheck and signal.\n\t\tif (identity() === \"current\") {\n\t\t\tsignalProcessGroupOrProcess(worker.descriptor.pid, \"SIGKILL\");\n\t\t\t// SIGKILL is uninterceptable; this wait only covers kernel teardown of the old process and socket.\n\t\t\tconst killDeadline = Date.now() + 1000;\n\t\t\twhile (identity() === \"current\" && Date.now() < killDeadline) {\n\t\t\t\tawait delay(25);\n\t\t\t}\n\t\t}\n\t\tconst finalIdentity = identity();\n\t\tif (finalIdentity !== \"gone\" && finalIdentity !== \"replaced\") {\n\t\t\t// A live or unverifiable survivor parks failed with no destructive cleanup: interruption\n\t\t\t// marking and orphan reaping must never run against a possibly-active worker.\n\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\tworker.descriptor.lastError = `Pre-roster worker process ${worker.descriptor.pid} is still running and cannot be replaced safely`;\n\t\t\tthis.persistWorker(worker);\n\t\t\tthis.markWorkerRosterEntries(worker, \"failed\");\n\t\t\tthis.log(`Kept pre-roster worker ${worker.descriptor.workerId} failed: ${worker.descriptor.lastError}`);\n\t\t\treturn;\n\t\t}\n\t\tawait this.recoverUncertainWorkerOperations(worker);\n\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.launchWorker(worker.descriptor.createCommand, worker, worker.descriptor.ownerClientId);\n\t}\n\n\tprivate async handleWorkerClose(worker: ResidentWorker, client: DaemonWorkerClient, error: Error): Promise<void> {\n\t\tif (worker.client !== client) {\n\t\t\treturn;\n\t\t}\n\t\tworker.client = undefined;\n\t\tthis.invalidateWorkerSessionInputPauses(worker, \"Session worker disconnected while input was paused\");\n\t\tconst interrupted = new Map<string, Set<string>>();\n\t\tfor (const [activeSessionId, generations] of worker.snapshotGenerations ?? []) {\n\t\t\tfor (const generation of generations.values()) {\n\t\t\t\tif (generation.incoming || !generation.transcript.complete) {\n\t\t\t\t\tconst snapshotIds = interrupted.get(activeSessionId) ?? new Set<string>();\n\t\t\t\t\tsnapshotIds.add(generation.transcript.snapshotId);\n\t\t\t\t\tinterrupted.set(activeSessionId, snapshotIds);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const [activeSessionId, transcript] of worker.transcriptCaches) {\n\t\t\tif (!transcript.complete) {\n\t\t\t\tconst snapshotIds = interrupted.get(activeSessionId) ?? new Set<string>();\n\t\t\t\tsnapshotIds.add(transcript.snapshotId);\n\t\t\t\tinterrupted.set(activeSessionId, snapshotIds);\n\t\t\t}\n\t\t}\n\t\tfor (const [activeSessionId, snapshotIds] of interrupted) {\n\t\t\tfor (const snapshotId of snapshotIds) {\n\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\tworker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tnew Error(\"Session worker disconnected during snapshot transfer\"),\n\t\t\t\t\tfalse,\n\t\t\t\t\tsnapshotId,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (this.shuttingDown || worker.intentionalStop) {\n\t\t\treturn;\n\t\t}\n\t\tthis.markWorkerRosterEntries(worker, \"recovering\");\n\t\ttry {\n\t\t\tawait this.assertRecoveryAllowed();\n\t\t} catch (recoveryError) {\n\t\t\tif (!isSupervisorGenerationStale(recoveryError)) {\n\t\t\t\tthis.deferWorkerRecovery(worker, error);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!this.isWorkerRecoveryEligible(worker)) {\n\t\t\treturn;\n\t\t}\n\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\tworker.descriptor.lastError = error.message;\n\t\tthis.persistWorker(worker);\n\t\tvoid this.recoverWorker(worker);\n\t}\n\n\tprivate isWorkerRecoveryEligible(worker: ResidentWorker): boolean {\n\t\treturn this.isWorkerRecoveryCandidate(worker) && worker.recovery === undefined;\n\t}\n\n\tprivate isWorkerRecoveryCandidate(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\t!this.shuttingDown &&\n\t\t\t!worker.intentionalStop &&\n\t\t\tworker.descriptor.stopRequestedAt === undefined &&\n\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\tworker.client === undefined\n\t\t);\n\t}\n\n\tprivate deferWorkerRecovery(worker: ResidentWorker, disconnectError: Error): void {\n\t\tif (worker.compatibilityError || worker.deferredRecovery) {\n\t\t\treturn;\n\t\t}\n\t\t// A live-but-silent worker must not probe forever: park it failed (user-visible through the\n\t\t// roster's failed status) and keep its process alive for a manual retry_worker.\n\t\tworker.deferredRecoveryRounds = (worker.deferredRecoveryRounds ?? 0) + 1;\n\t\tif (worker.deferredRecoveryRounds > MAX_DEFERRED_RECOVERY_ROUNDS) {\n\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\tworker.descriptor.lastError = `Live session worker did not answer recovery probes for ${MAX_DEFERRED_RECOVERY_ROUNDS} rounds: ${disconnectError.message}`;\n\t\t\tthis.persistWorker(worker);\n\t\t\tthis.markWorkerRosterEntries(worker, \"failed\");\n\t\t\tthis.log(\n\t\t\t\t`Worker ${worker.descriptor.workerId} is unresponsive; parked failed after ${MAX_DEFERRED_RECOVERY_ROUNDS} probe rounds`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tworker.deferredRecovery = this.resumeDeferredWorkerRecovery(worker, disconnectError).finally(() => {\n\t\t\tworker.deferredRecovery = undefined;\n\t\t});\n\t}\n\n\tprivate async resumeDeferredWorkerRecovery(worker: ResidentWorker, disconnectError: Error): Promise<void> {\n\t\twhile (true) {\n\t\t\tawait unrefDelay(DEFERRED_RECOVERY_RECHECK_MS);\n\t\t\tif (worker.compatibilityError || !this.isWorkerRecoveryCandidate(worker)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this.isWorkerRecoveryEligible(worker)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t} catch (error) {\n\t\t\t\tif (isSupervisorGenerationStale(error)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (worker.compatibilityError || !this.isWorkerRecoveryCandidate(worker)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this.isWorkerRecoveryEligible(worker)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\tworker.descriptor.lastError = disconnectError.message;\n\t\t\tthis.persistWorker(worker);\n\t\t\tvoid this.recoverWorker(worker);\n\t\t\treturn;\n\t\t}\n\t}\n\n\tprivate failWorkerSnapshotCache(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\terror: Error,\n\t\tcloseWorkerChannel = false,\n\t\texpectedSnapshotId?: string,\n\t): void {\n\t\tconst generations = worker.snapshotGenerations?.get(activeSessionId);\n\t\tif (expectedSnapshotId) {\n\t\t\tconst generation = generations?.get(expectedSnapshotId);\n\t\t\tif (generation) {\n\t\t\t\tthis.failSnapshotGeneration(worker, activeSessionId, generation, error);\n\t\t\t} else {\n\t\t\t\tconst transcript = worker.transcriptCaches.get(activeSessionId);\n\t\t\t\tif (transcript?.snapshotId !== expectedSnapshotId) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttranscript.markFailed(error);\n\t\t\t\ttranscript.dispose();\n\t\t\t\tworker.transcriptCaches.delete(activeSessionId);\n\t\t\t\tif (worker.snapshotCache.get(activeSessionId)?.snapshotStream?.id === expectedSnapshotId) {\n\t\t\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst failedTranscripts = new Set<SnapshotTranscriptCache>();\n\t\t\tfor (const generation of [...(generations?.values() ?? [])]) {\n\t\t\t\tfailedTranscripts.add(generation.transcript);\n\t\t\t\tthis.failSnapshotGeneration(worker, activeSessionId, generation, error);\n\t\t\t}\n\t\t\tconst transcript = worker.transcriptCaches.get(activeSessionId);\n\t\t\tif (transcript && !failedTranscripts.has(transcript)) {\n\t\t\t\ttranscript.markFailed(error);\n\t\t\t\ttranscript.dispose();\n\t\t\t}\n\t\t\tworker.transcriptCaches.delete(activeSessionId);\n\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t}\n\t\tif (closeWorkerChannel) {\n\t\t\tconst client = worker.client;\n\t\t\tif (client) {\n\t\t\t\tthis.handleWorkerClose(worker, client, error);\n\t\t\t\tclient.close();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate retireWorkerSnapshotCache(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\texpectedTranscript: SnapshotTranscriptCache,\n\t): void {\n\t\tif (worker.transcriptCaches.get(activeSessionId) === expectedTranscript) {\n\t\t\tworker.transcriptCaches.delete(activeSessionId);\n\t\t}\n\t\tif (worker.snapshotCache.get(activeSessionId)?.snapshotStream?.id === expectedTranscript.snapshotId) {\n\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t}\n\t\tconst generation = this.snapshotGeneration(worker, activeSessionId, expectedTranscript.snapshotId);\n\t\tif (!generation) {\n\t\t\texpectedTranscript.dispose();\n\t\t\treturn;\n\t\t}\n\t\tgeneration.retired = true;\n\t\tthis.settleSnapshotDuplicateValidation(generation);\n\t\tif (generation.incoming) {\n\t\t\treturn;\n\t\t}\n\t\tthis.deleteSnapshotGeneration(worker, activeSessionId, generation);\n\t\texpectedTranscript.dispose();\n\t}\n\n\tprivate snapshotGenerationsFor(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t): Map<string, SnapshotTranscriptGeneration> {\n\t\tworker.snapshotGenerations ??= new Map();\n\t\tlet generations = worker.snapshotGenerations.get(activeSessionId);\n\t\tif (!generations) {\n\t\t\tgenerations = new Map();\n\t\t\tworker.snapshotGenerations.set(activeSessionId, generations);\n\t\t}\n\t\treturn generations;\n\t}\n\n\tprivate snapshotGeneration(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\tsnapshotId: string,\n\t): SnapshotTranscriptGeneration | undefined {\n\t\treturn worker.snapshotGenerations?.get(activeSessionId)?.get(snapshotId);\n\t}\n\n\tprivate currentSnapshotGeneration(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t): SnapshotTranscriptGeneration | undefined {\n\t\tworker.transcriptCaches ??= new Map();\n\t\tworker.snapshotCache ??= new Map();\n\t\tconst transcript = worker.transcriptCaches.get(activeSessionId);\n\t\tif (!transcript) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst generations = this.snapshotGenerationsFor(worker, activeSessionId);\n\t\tlet generation = generations.get(transcript.snapshotId);\n\t\tif (generation) {\n\t\t\treturn generation;\n\t\t}\n\t\tconst result = worker.snapshotCache.get(activeSessionId);\n\t\tif (!result) {\n\t\t\treturn undefined;\n\t\t}\n\t\tgeneration = {\n\t\t\ttranscript,\n\t\t\tresult,\n\t\t\tincoming: false,\n\t\t\tretired: false,\n\t\t};\n\t\tgenerations.set(transcript.snapshotId, generation);\n\t\treturn generation;\n\t}\n\n\tprivate deleteSnapshotGeneration(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\tgeneration: SnapshotTranscriptGeneration,\n\t): void {\n\t\tconst generations = worker.snapshotGenerations?.get(activeSessionId);\n\t\tif (!generations) {\n\t\t\treturn;\n\t\t}\n\t\tif (generations.get(generation.transcript.snapshotId) === generation) {\n\t\t\tgenerations.delete(generation.transcript.snapshotId);\n\t\t}\n\t\tif (generations.size === 0) {\n\t\t\tworker.snapshotGenerations.delete(activeSessionId);\n\t\t}\n\t}\n\n\tprivate failSnapshotGeneration(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\tgeneration: SnapshotTranscriptGeneration,\n\t\terror: Error,\n\t): void {\n\t\tthis.settleSnapshotDuplicateValidation(generation, error);\n\t\tgeneration.transcript.markFailed(error);\n\t\tgeneration.transcript.dispose();\n\t\tthis.deleteSnapshotGeneration(worker, activeSessionId, generation);\n\t\tif (worker.transcriptCaches.get(activeSessionId) === generation.transcript) {\n\t\t\tworker.transcriptCaches.delete(activeSessionId);\n\t\t}\n\t\tif (worker.snapshotCache.get(activeSessionId)?.snapshotStream?.id === generation.transcript.snapshotId) {\n\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t}\n\t}\n\n\tprivate createSnapshotDuplicateValidation(): SnapshotDuplicateValidation {\n\t\tlet resolve!: () => void;\n\t\tlet reject!: (error: Error) => void;\n\t\tconst promise = new Promise<void>((resolvePromise, rejectPromise) => {\n\t\t\tresolve = resolvePromise;\n\t\t\treject = rejectPromise;\n\t\t});\n\t\tvoid promise.catch(() => undefined);\n\t\treturn { promise, resolve, reject };\n\t}\n\n\tprivate settleSnapshotDuplicateValidation(generation: SnapshotTranscriptGeneration, error?: Error): void {\n\t\tconst validation = generation.validation;\n\t\tif (!validation) {\n\t\t\treturn;\n\t\t}\n\t\tgeneration.validation = undefined;\n\t\tif (error) {\n\t\t\tvalidation.reject(error);\n\t\t} else {\n\t\t\tvalidation.resolve();\n\t\t}\n\t}\n\n\tprivate async recoverWorker(\n\t\tworker: ResidentWorker,\n\t\tstartup?: { ready: Promise<void>; preRoster?: { observedProcessStartId?: string } },\n\t): Promise<void> {\n\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\treturn;\n\t\t}\n\t\tif (worker.descriptor.ownerClientId && !worker.launchEnv && !isProcessAlive(worker.descriptor.pid)) {\n\t\t\tthis.releaseWorkerRlmCapacity(worker);\n\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\tworker.descriptor.lastError = \"Waiting for the owning client to reconnect\";\n\t\t\tthis.persistWorker(worker);\n\t\t\treturn;\n\t\t}\n\t\tif (worker.recovery) {\n\t\t\treturn worker.recovery;\n\t\t}\n\t\tconst stopRevision = worker.stopRevision;\n\t\tconst workerInstanceId = worker.descriptor.workerInstanceId;\n\t\tworker.recovery = (async () => {\n\t\t\tif (startup) {\n\t\t\t\tawait startup.ready;\n\t\t\t\tif (\n\t\t\t\t\tthis.isWorkerRecoveryCancelled(worker) ||\n\t\t\t\t\tworker.stopRevision !== stopRevision ||\n\t\t\t\t\tworker.descriptor.workerInstanceId !== workerInstanceId\n\t\t\t\t)\n\t\t\t\t\treturn;\n\t\t\t\tif (startup.preRoster) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.restartPreRosterWorker(worker, startup.preRoster.observedProcessStartId);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} catch (restartError) {\n\t\t\t\t\t\tif (isSupervisorRecoveryCancelled(restartError)) return;\n\t\t\t\t\t\tthis.log(\n\t\t\t\t\t\t\t`Could not restart pre-roster worker ${worker.descriptor.workerId}: ${String(restartError)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet keepProbingLiveWorker = false;\n\t\t\tfor (const retryDelay of WORKER_RETRY_DELAYS_MS) {\n\t\t\t\tawait delay(retryDelay);\n\t\t\t\tkeepProbingLiveWorker = false;\n\t\t\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\tconst identityNow = this.processIdentity(worker.descriptor.pid, worker.descriptor.processStartId);\n\t\t\t\t\tconst identityCompatible =\n\t\t\t\t\t\tidentityNow === \"current\" ||\n\t\t\t\t\t\t(identityNow === \"unknown\" && worker.descriptor.processStartId === undefined);\n\t\t\t\t\tif (identityCompatible) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait this.connectWorker(worker, 1500);\n\t\t\t\t\t\t\tawait this.subscribeWorker(worker, worker.descriptor.rootActiveSessionId);\n\t\t\t\t\t\t\tawait this.refreshWorkerSummaries(worker, true);\n\t\t\t\t\t\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (worker.descriptor.processStartId === undefined) {\n\t\t\t\t\t\t\t\tconst observedProcessStartId = getProcessStartId(worker.descriptor.pid);\n\t\t\t\t\t\t\t\tif (observedProcessStartId) {\n\t\t\t\t\t\t\t\t\tworker.descriptor.processStartId = observedProcessStartId;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\t\t\tworker.descriptor.lifecycle = \"ready\";\n\t\t\t\t\t\t\tworker.descriptor.consecutiveFailures = 0;\n\t\t\t\t\t\t\tworker.deferredRecoveryRounds = 0;\n\t\t\t\t\t\t\tthis.persistWorker(worker);\n\t\t\t\t\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tif (isSupervisorRecoveryCancelled(error) || error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\t\t\tworker.client?.close();\n\t\t\t\t\t\t\tworker.client = undefined;\n\t\t\t\t\t\t\t// A worker with the same durable process identity may be load-slow.\n\t\t\t\t\t\t\t// Keep probing it instead of replacing live work after a timeout.\n\t\t\t\t\t\t\tkeepProbingLiveWorker = isDaemonWorkerProbeTimeout(error) || identityNow !== \"current\";\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (identityNow === \"unknown\") {\n\t\t\t\t\t\tkeepProbingLiveWorker = true;\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Cannot safely replace live session worker ${worker.descriptor.workerId} without a verified process identity`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tthis.releaseWorkerRlmCapacity(worker);\n\t\t\t\t\tconst recoveryCommand = worker.descriptor.ownerClientId ? worker.transientCreateCommand : undefined;\n\t\t\t\t\tif (!recoveryCommand || !worker.launchEnv) {\n\t\t\t\t\t\tawait this.recoverUncertainWorkerOperations(worker);\n\t\t\t\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\t\t\t\tworker.descriptor.lastError = \"Waiting for a client with fresh runtime context\";\n\t\t\t\t\t\tthis.persistWorker(worker);\n\t\t\t\t\t\tthis.markWorkerRosterEntries(worker, \"failed\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.recoverUncertainWorkerOperations(worker);\n\t\t\t\t\tif (this.isWorkerRecoveryCancelled(worker)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.launchWorker(recoveryCommand, worker, worker.descriptor.ownerClientId);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (isSupervisorRecoveryCancelled(error) || this.isWorkerRecoveryCancelled(worker)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\t\t\tthis.parkIncompatibleWorker(worker, error);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tworker.client?.close();\n\t\t\t\t\tworker.client = undefined;\n\t\t\t\t\tworker.descriptor.consecutiveFailures++;\n\t\t\t\t\tworker.descriptor.lastFailureAt = new Date().toISOString();\n\t\t\t\t\tworker.descriptor.lastError = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tthis.persistWorker(worker);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (keepProbingLiveWorker) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t\t} catch {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t\tthis.deferWorkerRecovery(\n\t\t\t\t\tworker,\n\t\t\t\t\tnew Error(worker.descriptor.lastError ?? \"Live session worker did not answer recovery probes\"),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t} catch {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Leak-over-kill: a live worker that keeps failing for non-timeout reasons parks failed with\n\t\t\t// its process intact. A verified-identity survivor is reclaimed by the next fresh create;\n\t\t\t// an unverifiable one waits for exit — killing a pid we cannot verify as ours is worse.\n\t\t\tworker.descriptor.lifecycle = \"failed\";\n\t\t\tthis.persistWorker(worker);\n\t\t\tthis.markWorkerRosterEntries(worker, \"failed\");\n\t\t\tthis.log(`Worker ${worker.descriptor.workerId} failed after three recovery attempts`);\n\t\t})().finally(() => {\n\t\t\tworker.recovery = undefined;\n\t\t});\n\t\treturn worker.recovery;\n\t}\n\n\tprivate isWorkerRecoveryCancelled(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tthis.shuttingDown ||\n\t\t\tworker.intentionalStop ||\n\t\t\tworker.descriptor.stopRequestedAt !== undefined ||\n\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker\n\t\t);\n\t}\n\n\tprivate isWorkerCleanupCancelled(worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tthis.shuttingDown ||\n\t\t\tworker.descriptor.stopRequestedAt !== undefined ||\n\t\t\tthis.workers.get(worker.descriptor.workerId) !== worker\n\t\t);\n\t}\n\n\tprivate async recoverUncertainWorkerOperations(worker: ResidentWorker): Promise<void> {\n\t\tawait this.assertRecoveryAllowed();\n\t\tconst journal = new WorkerRecoveryJournal(worker.descriptor.recoveryJournalPath);\n\t\tconst latest = journal.getLatest();\n\t\tconst uncertain = latest.filter((record) => record.busy);\n\t\tif (uncertain.length > 0) await this.catalog.start();\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (this.isWorkerCleanupCancelled(worker)) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Worker recovery was cancelled before destructive cleanup\");\n\t\t}\n\n\t\tconst interruptedSessions = new Map<\n\t\t\tstring,\n\t\t\t{ activeSessionId: string; sessionFile: string; operations: Set<string> }\n\t\t>();\n\t\tfor (const record of uncertain) {\n\t\t\tconst sessionFile =\n\t\t\t\trecord.sessionFile ??\n\t\t\t\t(record.activeSessionId === worker.descriptor.rootActiveSessionId\n\t\t\t\t\t? worker.descriptor.sessionFile\n\t\t\t\t\t: undefined);\n\t\t\tif (!sessionFile) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst key = `${record.activeSessionId}\\0${sessionFile}`;\n\t\t\tlet interrupted = interruptedSessions.get(key);\n\t\t\tif (!interrupted) {\n\t\t\t\tinterrupted = { activeSessionId: record.activeSessionId, sessionFile, operations: new Set() };\n\t\t\t\tinterruptedSessions.set(key, interrupted);\n\t\t\t}\n\t\t\tinterrupted.operations.add(record.operation);\n\t\t}\n\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (this.isWorkerCleanupCancelled(worker)) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Worker recovery was cancelled before interruption was recorded\");\n\t\t}\n\t\tawait Promise.all(\n\t\t\t[...interruptedSessions.values()].map((interrupted) =>\n\t\t\t\tthis.catalog.markInterrupted(interrupted.sessionFile, interrupted.activeSessionId, [\n\t\t\t\t\t...interrupted.operations,\n\t\t\t\t]),\n\t\t\t),\n\t\t);\n\t\tawait this.assertRecoveryAllowed();\n\t\tif (this.isWorkerCleanupCancelled(worker)) {\n\t\t\tthrow new SupervisorRecoveryCancelledError(\"Worker recovery was cancelled before process cleanup\");\n\t\t}\n\t\tconst orphanProcessJournalPath = worker.descriptor.orphanProcessJournalPath;\n\t\tif (orphanProcessJournalPath) {\n\t\t\ttry {\n\t\t\t\tconst orphans = readActiveOrphanProcesses(orphanProcessJournalPath, worker.descriptor.pid);\n\t\t\t\tlet reapFailed = false;\n\t\t\t\tlet retryIsSafe = true;\n\t\t\t\tfor (const orphan of orphans) {\n\t\t\t\t\tif (orphan.processStartId === undefined) retryIsSafe = false;\n\t\t\t\t\tif (!shouldReapOrphanProcess(orphan)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!killOrphanProcess(orphan.pid)) reapFailed = true;\n\t\t\t\t}\n\t\t\t\tif (!reapFailed || !retryIsSafe) clearOrphanProcessJournal(orphanProcessJournalPath);\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Could not reap orphaned worker resources: ${String(error)}`);\n\t\t\t}\n\t\t}\n\t\tif (uncertain.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const record of latest) {\n\t\t\tjournal.record({\n\t\t\t\tactiveSessionId: record.activeSessionId,\n\t\t\t\tsessionId: record.sessionId,\n\t\t\t\t...(record.sessionFile ? { sessionFile: record.sessionFile } : {}),\n\t\t\t\tbusy: false,\n\t\t\t\toperation: \"recovery_hold\",\n\t\t\t});\n\t\t}\n\t\tthis.log(\n\t\t\t`Recovered worker ${worker.descriptor.workerId} without replaying uncertain operations: ${uncertain\n\t\t\t\t.map((record) => record.operation)\n\t\t\t\t.join(\", \")}`,\n\t\t);\n\t}\n\tprivate async refreshWorkerSummaries(\n\t\tworker: ResidentWorker,\n\t\trecovery = false,\n\t\tfillGaps = recovery,\n\t\tretried = false,\n\t): Promise<void> {\n\t\tif (this.isWorkerStopping(worker)) {\n\t\t\tthrow new Error(\"Session worker is stopping\");\n\t\t}\n\t\tif (!worker.client) {\n\t\t\tthrow new Error(\"Session worker is not connected\");\n\t\t}\n\t\tconst pullSource = worker.client;\n\t\tconst epochAtStart = worker.rosterEpoch ?? 0;\n\t\tconst response = await pullSource.request({ type: \"list\" }, 5000);\n\t\t// A frame received mid-pull can remove rows this stale pull would resurrect; re-pull once, then skip the fill.\n\t\tif (fillGaps && (worker.rosterEpoch ?? 0) !== epochAtStart && !retried) {\n\t\t\treturn this.refreshWorkerSummaries(worker, recovery, fillGaps, true);\n\t\t}\n\t\tconst summaries = sessionSummariesFromResponse(response);\n\t\tconst nextSummaries = new Map(summaries.map((summary) => [summary.activeSessionId ?? summary.id, summary]));\n\t\tconst root = nextSummaries.get(worker.descriptor.rootActiveSessionId);\n\t\tif (recovery && !root) {\n\t\t\tthrow new Error(`Session worker omitted its root session during recovery`);\n\t\t}\n\t\tworker.summaries = nextSummaries;\n\t\tif (fillGaps) {\n\t\t\tawait this.chainWorkerRosterApply(worker, pullSource, () => {\n\t\t\t\tif ((worker.rosterEpoch ?? 0) === epochAtStart) this.syncRosterFromWorkerSummaries(worker);\n\t\t\t});\n\t\t}\n\t\tfor (const summary of summaries) {\n\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\tif (summary.streamingMessage?.role === \"assistant\") {\n\t\t\t\tthis.streamReconstructor.seed(activeSessionId, summary.streamingMessage);\n\t\t\t} else if (!summary.isStreaming) {\n\t\t\t\tthis.streamReconstructor.clear(activeSessionId);\n\t\t\t}\n\t\t}\n\t\tif (root) {\n\t\t\tif (recovery) {\n\t\t\t\tawait this.assertRecoveryAllowed();\n\t\t\t}\n\t\t\tawait this.chainWorkerRosterApply(worker, pullSource, () => {\n\t\t\t\tif ((worker.rosterEpoch ?? 0) !== epochAtStart) return;\n\t\t\t\tworker.descriptor.rootSessionId = root.sessionId;\n\t\t\t\tworker.descriptor.sessionFile = root.sessionFile;\n\t\t\t\tworker.descriptor.createCommand = durableDaemonCreateCommand({\n\t\t\t\t\ttype: \"create\",\n\t\t\t\t\tsessionPath: root.sessionFile,\n\t\t\t\t\tnoSession: worker.descriptor.createCommand.noSession,\n\t\t\t\t});\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async familyCatalogEntries(): Promise<AgentFamilyCatalogEntry[]> {\n\t\tconst rosterRows = [...this.roster().values()];\n\t\tconst entries = rosterRows.map((entry) => this.familyCatalogEntry(sessionSummaryFromRosterEntry(entry)));\n\t\tconst knownFiles = new Set(\n\t\t\trosterRows.flatMap((entry) =>\n\t\t\t\tentry.summary.sessionFile ? [canonicalSessionPath(entry.summary.sessionFile)] : [],\n\t\t\t),\n\t\t);\n\t\tconst scanned = await this.catalog.list(undefined, this.defaultSessionConfig.sessionDir);\n\t\tfor (const info of scanned) {\n\t\t\tif (knownFiles.has(canonicalSessionPath(info.path))) continue;\n\t\t\tif ((info.rlmDepth ?? (info.parentSessionPath ? -1 : 0)) !== 0) continue;\n\t\t\tentries.push(this.familyCatalogEntry(summaryForInactiveSession(info)));\n\t\t}\n\t\treturn entries;\n\t}\n\n\tprivate async withSessionNameReservation<T>(\n\t\tinput: { name: string; depth: number; parentSessionId?: string; parentSessionPath?: string },\n\t\taction: () => Promise<T>,\n\t): Promise<T> {\n\t\tconst key = sessionNameReservationKey(input);\n\t\tif (this.pendingSessionNames.has(key)) {\n\t\t\tthrow new Error(formatAgentSessionNameUnavailable(input.name, input.depth));\n\t\t}\n\t\tthis.pendingSessionNames.add(key);\n\t\ttry {\n\t\t\treturn await action();\n\t\t} finally {\n\t\t\tthis.pendingSessionNames.delete(key);\n\t\t}\n\t}\n\n\tprivate async assertSupervisorSessionNameAvailable(\n\t\ttarget: Pick<SessionSummary, \"sessionId\" | \"rlmDepth\" | \"parentSessionId\" | \"parentSessionPath\">,\n\t\tname: string,\n\t): Promise<void> {\n\t\tassertAgentSessionNameAvailable(await this.familyCatalogEntries(), {\n\t\t\tname,\n\t\t\tdepth: target.rlmDepth ?? 0,\n\t\t\tparentSessionId: target.parentSessionId,\n\t\t\tparentSessionPath: target.parentSessionPath ? canonicalSessionPath(target.parentSessionPath) : undefined,\n\t\t\tignoreSessionId: target.sessionId,\n\t\t});\n\t}\n\n\tprivate roster(): AgentRoster {\n\t\tthis.rosterStore ??= new AgentRoster(canonicalSessionPath, (mutation) => this.onRosterMutation(mutation));\n\t\treturn this.rosterStore;\n\t}\n\n\tprivate onRosterMutation(mutation: AgentRosterMutation): void {\n\t\tif (mutation.type === \"delete\") {\n\t\t\tthis.pendingRosterChanged.delete(mutation.agentId);\n\t\t\tthis.pendingRosterRemoved.add(mutation.agentId);\n\t\t} else {\n\t\t\tthis.pendingRosterRemoved.delete(mutation.agentId);\n\t\t\tthis.pendingRosterChanged.add(mutation.agentId);\n\t\t}\n\t\tthis.scheduleRosterPush();\n\t}\n\n\tprivate scheduleRosterPush(): void {\n\t\tif (this.rosterPushScheduled || this.shuttingDown) return;\n\t\tthis.rosterPushScheduled = true;\n\t\tsetImmediate(() => {\n\t\t\tthis.rosterPushScheduled = false;\n\t\t\tthis.flushRosterUpdates();\n\t\t});\n\t}\n\n\tprivate flushRosterUpdates(): void {\n\t\tconst changed: AgentRosterEntry[] = [];\n\t\tconst removed: string[] = [];\n\t\tfor (const agentId of this.pendingRosterRemoved) {\n\t\t\tif (this.publishedRosterIds.delete(agentId)) removed.push(agentId);\n\t\t}\n\t\tfor (const agentId of this.pendingRosterChanged) {\n\t\t\tconst entry = this.roster().get(agentId);\n\t\t\tif (!entry) continue;\n\t\t\tif (this.isRosterEntryVisibleToClients(entry)) {\n\t\t\t\tchanged.push(entry);\n\t\t\t\tthis.publishedRosterIds.add(agentId);\n\t\t\t} else if (this.publishedRosterIds.delete(agentId)) {\n\t\t\t\tremoved.push(agentId);\n\t\t\t}\n\t\t}\n\t\tthis.pendingRosterChanged.clear();\n\t\tthis.pendingRosterRemoved.clear();\n\t\tif (changed.length === 0 && removed.length === 0) return;\n\t\tfor (const client of this.clients) {\n\t\t\tif (client.rosterSubscribed !== true) continue;\n\t\t\tif (client.backpressured === true) {\n\t\t\t\tclient.rosterResyncPending = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.write(client, {\n\t\t\t\ttype: \"roster_update\",\n\t\t\t\tchanged,\n\t\t\t\t...(removed.length > 0 ? { removed } : {}),\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate rosterEntriesForClient(): AgentRosterEntry[] {\n\t\tconst entries = [...this.roster().values()].filter((entry) => this.isRosterEntryVisibleToClients(entry));\n\t\tfor (const entry of entries) this.publishedRosterIds.add(entry.agentId);\n\t\treturn entries;\n\t}\n\n\tprivate isRosterEntryVisibleToClients(entry: AgentRosterEntry): boolean {\n\t\tconst worker = entry.workerId !== undefined ? this.workers.get(entry.workerId) : undefined;\n\t\treturn worker === undefined || this.isVisibleWorker(worker);\n\t}\n\n\tprivate writeRosterEntry(\n\t\tentry: WorkerRosterEntry,\n\t\tworker?: ResidentWorker,\n\t\tstatusLabel?: AgentRosterEntry[\"statusLabel\"],\n\t): AgentRosterEntry {\n\t\tconst existing = entry.summary.sessionFile\n\t\t\t? this.roster().bySessionFile(entry.summary.sessionFile)\n\t\t\t: this.roster().get(entry.agentId);\n\t\t// A parent's saved-child row cannot replace that child's independent live worker.\n\t\tif (\n\t\t\tworker &&\n\t\t\t!entry.summary.activeSessionId &&\n\t\t\texisting?.summary.activeSessionId &&\n\t\t\texisting.workerId !== undefined &&\n\t\t\texisting.workerId !== worker.descriptor.workerId\n\t\t)\n\t\t\treturn existing;\n\t\tconst previousDirect = this.roster().get(entry.agentId)?.summary.directAttachedClients ?? 0;\n\t\tconst stored = this.roster().write(entry, worker?.descriptor.workerId, statusLabel);\n\t\t// Direct peers attach and detach on the worker socket, so their last detach arrives\n\t\t// here as roster truth instead of through a supervisor-socket close.\n\t\tif (worker !== undefined && previousDirect > 0 && (entry.summary.directAttachedClients ?? 0) === 0) {\n\t\t\tvoid this.evictEmptySessionOnLastDetach(entry.summary.activeSessionId ?? entry.summary.id);\n\t\t}\n\t\treturn stored;\n\t}\n\n\tprivate workerOwnedRosterSummaryForPath(canonicalPath: string): SessionSummary | undefined {\n\t\tconst entry = this.roster().bySessionFile(canonicalPath);\n\t\tif (!entry || entry.workerId === undefined || !this.workers.has(entry.workerId)) return undefined;\n\t\treturn sessionSummaryFromRosterEntry(entry);\n\t}\n\n\tprivate workerRosterEntries(worker: ResidentWorker): AgentRosterEntry[] {\n\t\treturn this.roster().entriesForWorker(worker.descriptor.workerId);\n\t}\n\n\tprivate async seedRosterLedger(): Promise<void> {\n\t\ttry {\n\t\t\tconst roots = new Set<string>();\n\t\t\tfor (const worker of this.workers.values()) {\n\t\t\t\tconst root = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\t\t\tif (root !== undefined) roots.add(canonicalSessionPath(root));\n\t\t\t}\n\t\t\tif (roots.size === 0) return;\n\t\t\tconst edges = await this.rlmSpawnLedger().liveEdges();\n\t\t\tconst descendsFrom = rosterFamilyDescendsFrom(edges);\n\t\t\tfor (const edge of edges) {\n\t\t\t\tif (!descendsFrom(canonicalSessionPath(edge.parent), roots)) continue;\n\t\t\t\tconst entry = this.rosterEntryForSpawnLedgerEdge(edge);\n\t\t\t\tif (this.roster().has(entry.agentId)) continue;\n\t\t\t\tif (this.roster().hasSessionFile(canonicalSessionPath(edge.child))) continue;\n\t\t\t\tthis.roster().write(await this.hydratedSeedEntry(entry));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.log(`Could not seed the agent roster from the spawn ledger: ${String(error)}`);\n\t\t}\n\t}\n\n\tprivate rosterEntryForSpawnLedgerEdge(edge: RlmLedgerEdge): WorkerRosterEntry {\n\t\tconst persistedSessionId = basename(edge.child, \".jsonl\");\n\t\tconst summary: WorkerRosterEntry[\"summary\"] = {\n\t\t\tid: persistedSessionId,\n\t\t\tlifecycle: \"live\",\n\t\t\tactivity: \"idle\",\n\t\t\tisSessionActive: false,\n\t\t\truntimeKind: \"subagent\",\n\t\t\trlmDepth: edge.depth,\n\t\t\tsessionId: persistedSessionId,\n\t\t\tsessionFile: edge.child,\n\t\t\tsessionName: edge.name,\n\t\t\tcwd: dirname(edge.child),\n\t\t\tisStreaming: false,\n\t\t\tisCompacting: false,\n\t\t\tattachedClients: 0,\n\t\t\tmessageCount: 0,\n\t\t\tparentSessionPath: edge.parent,\n\t\t\trlmChildId: edge.childId,\n\t\t};\n\t\treturn { agentId: rosterAgentIdForSummary(summary), summary };\n\t}\n\n\tprivate consumeWorkerRosterDelta(worker: ResidentWorker, payload: Buffer, source?: DaemonWorkerClient): void {\n\t\tlet delta: Extract<DaemonWorkerRosterOutbound, { type: \"roster_delta\" }>;\n\t\ttry {\n\t\t\tdelta = JSON.parse(payload.toString(\"utf8\")) as Extract<DaemonWorkerRosterOutbound, { type: \"roster_delta\" }>;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (delta.type !== \"roster_delta\" || !Array.isArray(delta.entries)) return;\n\t\tworker.rosterEpoch = (worker.rosterEpoch ?? 0) + 1;\n\t\tconst applySource = source ?? worker.client ?? worker.pendingClient;\n\t\tif (!this.isWorkerRosterApplyCurrent(worker, applySource)) return;\n\t\tif (delta.snapshot !== true && worker.rosterApplyChain === undefined) {\n\t\t\tthis.applyWorkerRosterDelta(worker, delta);\n\t\t\treturn;\n\t\t}\n\t\tthis.chainWorkerRosterApply(worker, applySource, () =>\n\t\t\tdelta.snapshot === true\n\t\t\t\t? this.applyWorkerRosterSnapshot(worker, delta, applySource)\n\t\t\t\t: this.applyWorkerRosterDelta(worker, delta),\n\t\t);\n\t}\n\n\tprivate chainWorkerRosterApply(\n\t\tworker: ResidentWorker,\n\t\tsource: DaemonWorkerClient | undefined,\n\t\tapply: () => void | Promise<void>,\n\t): Promise<void> {\n\t\tconst chained = (worker.rosterApplyChain ?? Promise.resolve())\n\t\t\t.then(() => {\n\t\t\t\tif (!this.isWorkerRosterApplyCurrent(worker, source)) return;\n\t\t\t\treturn apply();\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tthis.log(`could not apply a roster frame: ${String(error)}`);\n\t\t\t\tthis.scheduleRosterRepairPull(worker);\n\t\t\t});\n\t\tworker.rosterApplyChain = chained;\n\t\tvoid chained.finally(() => {\n\t\t\tif (worker.rosterApplyChain === chained) worker.rosterApplyChain = undefined;\n\t\t});\n\t\treturn chained;\n\t}\n\n\t// An apply is valid only while its own source connection is current: dead connections' parked applies abort.\n\tprivate isWorkerRosterApplyCurrent(worker: ResidentWorker, source: DaemonWorkerClient | undefined): boolean {\n\t\treturn (\n\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\tsource !== undefined &&\n\t\t\t(source === worker.client || source === worker.pendingClient)\n\t\t);\n\t}\n\n\tprivate scheduleRosterRepairPull(worker: ResidentWorker): void {\n\t\tif (worker.rosterRepairPull || !this.isWorkerRosterApplyCurrent(worker, worker.client)) return;\n\t\t// The marker stays set while the repair's own fill applies, so a failing repair never respawns itself.\n\t\tworker.rosterRepairPull = this.refreshWorkerSummaries(worker, false, true)\n\t\t\t.catch((error: unknown) =>\n\t\t\t\tthis.log(`Roster repair pull failed for worker ${worker.descriptor.workerId}: ${String(error)}`),\n\t\t\t)\n\t\t\t.finally(() => {\n\t\t\t\tworker.rosterRepairPull = undefined;\n\t\t\t});\n\t}\n\n\tprivate applyWorkerRosterDelta(\n\t\tworker: ResidentWorker,\n\t\tdelta: Extract<DaemonWorkerRosterOutbound, { type: \"roster_delta\" }>,\n\t): void {\n\t\tfor (const entry of delta.entries) {\n\t\t\tthis.writeRosterEntry(entry, worker);\n\t\t\tthis.syncRootDescriptorFromRosterEntry(worker, entry);\n\t\t}\n\t\tfor (const agentId of delta.removedAgentIds ?? []) {\n\t\t\tthis.roster().delete(agentId);\n\t\t}\n\t}\n\n\tprivate async applyWorkerRosterSnapshot(\n\t\tworker: ResidentWorker,\n\t\tdelta: Extract<DaemonWorkerRosterOutbound, { type: \"roster_delta\" }>,\n\t\tsource?: DaemonWorkerClient,\n\t): Promise<void> {\n\t\tlet edgesFailed = false;\n\t\tconst edges = await this.rlmSpawnLedger()\n\t\t\t.liveEdges()\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tthis.log(`Could not read the spawn ledger during a snapshot apply: ${String(error)}`);\n\t\t\t\tedgesFailed = true;\n\t\t\t\treturn [] as RlmLedgerEdge[];\n\t\t\t});\n\t\tconst applySource = source ?? worker.client ?? worker.pendingClient;\n\t\tif (!this.isWorkerRosterApplyCurrent(worker, applySource)) return;\n\t\tconst sent = new Set(delta.entries.map((entry) => entry.agentId));\n\t\tconst removed = new Set(delta.removedAgentIds ?? []);\n\t\tconst unclaimed = new Map<string, AgentRosterEntry>();\n\t\tif (!edgesFailed) {\n\t\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\t\tif (sent.has(entry.agentId)) continue;\n\t\t\t\tunclaimed.set(entry.agentId, entry);\n\t\t\t}\n\t\t}\n\t\t// Only this worker's family reseeds: anything wider can resurrect a client-owned worker's dropped children.\n\t\tconst workerRoot = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\tconst rootPaths = new Set(workerRoot !== undefined ? [canonicalSessionPath(workerRoot)] : []);\n\t\tconst descendsFrom = rosterFamilyDescendsFrom(edges);\n\t\tconst familyEdges = edges.filter((edge) => descendsFrom(canonicalSessionPath(edge.parent), rootPaths));\n\t\t// \"Unclaimed\" rows survive: the sweep deletes them but the restore branch rewrites them.\n\t\tconst rowSurvivesWithoutReseed = (entry: WorkerRosterEntry, childPath: string): boolean => {\n\t\t\tif (unclaimed.has(entry.agentId)) return true;\n\t\t\tif (sent.has(entry.agentId) && !removed.has(entry.agentId)) return true;\n\t\t\tconst survives = (row: AgentRosterEntry | undefined): boolean =>\n\t\t\t\trow !== undefined && !unclaimed.has(row.agentId) && !removed.has(row.agentId);\n\t\t\treturn survives(this.roster().get(entry.agentId)) || survives(this.roster().bySessionFile(childPath));\n\t\t};\n\t\tconst seededEntries = new Map<string, WorkerRosterEntry>();\n\t\tfor (const edge of familyEdges) {\n\t\t\tconst entry = this.rosterEntryForSpawnLedgerEdge(edge);\n\t\t\tif (rowSurvivesWithoutReseed(entry, canonicalSessionPath(edge.child))) continue;\n\t\t\tseededEntries.set(entry.agentId, await this.hydratedSeedEntry(entry));\n\t\t\tif (!this.isWorkerRosterApplyCurrent(worker, applySource)) return;\n\t\t}\n\n\t\t// Unreadable edges skip the absentee sweep: it cannot tell registry children from stale rows.\n\t\tfor (const entry of unclaimed.values()) this.roster().delete(entry.agentId);\n\t\tfor (const entry of delta.entries) {\n\t\t\tthis.writeRosterEntry(entry, worker);\n\t\t\tthis.syncRootDescriptorFromRosterEntry(worker, entry);\n\t\t}\n\t\tfor (const agentId of removed) this.roster().delete(agentId);\n\t\tif (edgesFailed) {\n\t\t\tthis.scheduleRosterRepairPull(worker);\n\t\t\treturn;\n\t\t}\n\t\tfor (const edge of familyEdges) {\n\t\t\tconst entry = this.rosterEntryForSpawnLedgerEdge(edge);\n\t\t\tif (this.roster().has(entry.agentId)) continue;\n\t\t\tif (this.roster().hasSessionFile(canonicalSessionPath(edge.child))) continue;\n\t\t\tconst previous = unclaimed.get(entry.agentId);\n\t\t\tif (previous) {\n\t\t\t\tconst { status, statusLabel, lastHeardFromAt, workerId, ...rest } = previous;\n\t\t\t\tthis.writeRosterEntry(rest, worker);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.roster().write(seededEntries.get(entry.agentId) ?? { ...entry, seededCwd: true });\n\t\t}\n\t}\n\n\tprivate syncRootDescriptorFromRosterEntry(worker: ResidentWorker, entry: WorkerRosterEntry): void {\n\t\tconst summary = entry.summary;\n\t\tif (summary.activeSessionId !== worker.descriptor.rootActiveSessionId) return;\n\t\tif (\n\t\t\tworker.descriptor.rootSessionId === summary.sessionId &&\n\t\t\tworker.descriptor.sessionFile === summary.sessionFile\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tworker.descriptor.rootSessionId = summary.sessionId;\n\t\tworker.descriptor.sessionFile = summary.sessionFile;\n\t\tworker.descriptor.createCommand = durableDaemonCreateCommand({\n\t\t\ttype: \"create\",\n\t\t\tsessionPath: summary.sessionFile,\n\t\t\tnoSession: worker.descriptor.createCommand.noSession,\n\t\t});\n\t\tthis.persistWorker(worker);\n\t}\n\n\t// Behind the pull-epoch guard the pull is never staler than the row it replaces; never steal another worker's claim.\n\tprivate syncRosterFromWorkerSummaries(worker: ResidentWorker): void {\n\t\tfor (const summary of worker.summaries.values()) {\n\t\t\tconst entry = workerRosterEntryFromSummary(summary);\n\t\t\tconst existing = this.roster().get(entry.agentId);\n\t\t\tif (existing?.workerId !== undefined && existing.workerId !== worker.descriptor.workerId) continue;\n\t\t\tthis.writeRosterEntry(entry, worker);\n\t\t}\n\t}\n\n\tprivate markWorkerRosterEntries(worker: ResidentWorker, statusLabel: \"recovering\" | \"failed\" | undefined): void {\n\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\tif (!entry.queuedChild && entry.summary.activeSessionId === undefined) continue;\n\t\t\tthis.roster().amend(entry.agentId, { statusLabel });\n\t\t}\n\t}\n\n\tprivate flipWorkerRosterEntriesInactive(worker: ResidentWorker): void {\n\t\t// Client-owned workers are ephemeral and private: their rows die with the registration.\n\t\tconst ephemeral = worker.descriptor.ownerClientId !== undefined;\n\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\tif (ephemeral || entry.queuedChild) {\n\t\t\t\tthis.roster().delete(entry.agentId);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Registration marks survive eviction: passive rows still have schedules behind them.\n\t\t\tthis.writeRosterEntry(\n\t\t\t\tpassivatedWorkerRosterEntry(entry, {\n\t\t\t\t\thasRegisteredHeartbeat: entry.summary.hasRegisteredHeartbeat === true,\n\t\t\t\t\thasRegisteredCronJob: entry.summary.hasRegisteredCronJob === true,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate sweepRosterStaleness(now = Date.now()): void {\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker.client === undefined || worker.lastFrameAt === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (now - worker.lastFrameAt > ROSTER_STALE_AFTER_MS) {\n\t\t\t\tconst lastHeardFromAt = new Date(worker.lastFrameAt).toISOString();\n\t\t\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\t\t\t// write() rebuilds rows without the mark; the sweep owns it and restamps only those.\n\t\t\t\t\tif (entry.lastHeardFromAt !== lastHeardFromAt) this.roster().amend(entry.agentId, { lastHeardFromAt });\n\t\t\t\t}\n\t\t\t\tworker.rosterStale = true;\n\t\t\t} else if (worker.rosterStale) {\n\t\t\t\tthis.clearRosterStaleness(worker);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate clearRosterStaleness(worker: ResidentWorker): void {\n\t\tif (!worker.rosterStale) return;\n\t\tworker.rosterStale = false;\n\t\tfor (const entry of this.workerRosterEntries(worker)) {\n\t\t\tthis.roster().amend(entry.agentId, { lastHeardFromAt: undefined });\n\t\t}\n\t}\n\n\tprivate rlmJournalScope(sessionDir?: string): { agentDir: string; sessionsDir: string; journalPath: string } {\n\t\tconst agentDir = this.defaultSessionConfig.agentDir;\n\t\tif (!agentDir) throw new Error(\"Daemon supervisor config is missing agentDir\");\n\t\tconst sessionsDir = sessionDir ?? this.defaultSessionConfig.sessionDir ?? getSessionsDir(agentDir);\n\t\treturn { agentDir, sessionsDir, journalPath: rlmLedgerPath(agentDir, sessionsDir) };\n\t}\n\n\tprivate assertRlmJournalAdmission(): RlmJournalOwner {\n\t\tconst owner = this.rlmJournalOwner;\n\t\tif (!owner || this.rlmJournalClose) throw new Error(\"RLM journal mutation admission is closed\");\n\t\ttry {\n\t\t\tif (!this.ownership) throw new Error(\"RLM journal supervisor ownership is unavailable\");\n\t\t\tthis.ownership.assertJournalCurrent(owner.ledgerPath);\n\t\t} catch (error) {\n\t\t\tthis.fenceRlmJournalOwner();\n\t\t\tthrow error;\n\t\t}\n\t\treturn owner;\n\t}\n\n\tprivate fenceRlmJournalOwner(): void {\n\t\tvoid this.closeRlmJournalOwner().catch((error: unknown) => this.reportCleanupFailure(\"RLM journal owner\", error));\n\t}\n\n\tprivate closeRlmJournalOwner(): Promise<void> {\n\t\tthis.rlmSpawnLedgerInstance?.stopAdmission();\n\t\tif (this.rlmJournalClose) return this.rlmJournalClose;\n\t\tconst owner = this.rlmJournalOwner;\n\t\tif (!owner) return Promise.resolve();\n\t\tthis.rlmJournalClose = (async () => {\n\t\t\tawait this.rlmSpawnLedgerInstance?.flush();\n\t\t\tawait owner.close();\n\t\t\tthis.rlmJournalOwner = undefined;\n\t\t})();\n\t\treturn this.rlmJournalClose;\n\t}\n\n\t/** Reads are local; every mutation is acknowledged by the external lifetime owner. */\n\tprivate rlmSpawnLedger(): RlmSpawnLedger {\n\t\tconst { agentDir, sessionsDir } = this.rlmJournalScope();\n\t\tthis.rlmSpawnLedgerInstance ??= new RlmSpawnLedger(\n\t\t\tagentDir,\n\t\t\tsessionsDir,\n\t\t\tcreateRlmLedgerRegistrySeedSource(),\n\t\t\t(message) => this.log(message),\n\t\t\t{\n\t\t\t\tmode: \"remote\",\n\t\t\t\tmutate: (mutation) => {\n\t\t\t\t\tconst owner = this.rlmJournalOwner;\n\t\t\t\t\tif (!owner) throw new Error(\"RLM journal owner is unavailable\");\n\t\t\t\t\treturn owner.mutate(mutation);\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\treturn this.rlmSpawnLedgerInstance;\n\t}\n\n\t/**\n\t * Ledger-backed same-parent rows for name reservation and admission. Rows\n\t * carry ledger topology plus best-effort display fields; consumers here\n\t * only need id/path/name/depth/parent.\n\t */\n\tprivate rlmLedgerSiblings(sessionPath: string): Promise<SessionInfo[]> {\n\t\treturn this.rlmSpawnLedger().siblings(sessionPath);\n\t}\n\n\tprivate async savedSessionNameReservationInput(\n\t\tsessionPath: string,\n\t\tname: string,\n\t): Promise<{ name: string; depth: number; parentSessionId?: string; parentSessionPath?: string }> {\n\t\tconst targetPath = canonicalSessionPath(sessionPath);\n\t\tconst active = this.workerOwnedRosterSummaryForPath(targetPath);\n\t\tif (active) return this.summaryNameReservationInput(active, name);\n\t\tconst siblings = await this.rlmLedgerSiblings(sessionPath);\n\t\tconst saved = siblings.find((info) => canonicalSessionPath(info.path) === targetPath);\n\t\tif (!saved) throw new Error(`Session not found: ${sessionPath}`);\n\t\treturn {\n\t\t\tname,\n\t\t\tdepth: saved.rlmDepth ?? siblings.find((sibling) => sibling.rlmDepth !== undefined)?.rlmDepth ?? 0,\n\t\t\tparentSessionPath: saved.parentSessionPath,\n\t\t};\n\t}\n\n\tprivate summaryNameReservationInput(\n\t\ttarget: Pick<SessionSummary, \"rlmDepth\" | \"parentSessionId\" | \"parentSessionPath\">,\n\t\tname: string,\n\t): { name: string; depth: number; parentSessionId?: string; parentSessionPath?: string } {\n\t\tconst depth = target.rlmDepth ?? (target.parentSessionPath ? 1 : 0);\n\t\treturn {\n\t\t\tname,\n\t\t\tdepth,\n\t\t\t...(depth > 0 && target.parentSessionId ? { parentSessionId: target.parentSessionId } : {}),\n\t\t\t...(depth > 0 && target.parentSessionPath ? { parentSessionPath: target.parentSessionPath } : {}),\n\t\t};\n\t}\n\n\tprivate async assertSupervisorSavedSessionNameAvailable(sessionPath: string, name: string): Promise<void> {\n\t\tconst targetPath = canonicalSessionPath(sessionPath);\n\t\tconst active = this.workerOwnedRosterSummaryForPath(targetPath);\n\t\tif (active) return this.assertSupervisorSessionNameAvailable(active, name);\n\t\tconst siblings = await this.rlmLedgerSiblings(sessionPath);\n\t\tconst saved = siblings.find((info) => canonicalSessionPath(info.path) === targetPath);\n\t\tif (!saved) throw new Error(`Session not found: ${sessionPath}`);\n\t\tif (saved.parentSessionPath && (saved.rlmDepth ?? 0) > 0) {\n\t\t\tthis.assertSavedSiblingNameAvailable(siblings, saved, name);\n\t\t} else {\n\t\t\tawait this.assertSupervisorSessionNameAvailable(summaryForInactiveSession(saved), name);\n\t\t}\n\t}\n\n\tprivate assertSavedSiblingNameAvailable(siblings: SessionInfo[], target: SessionInfo, name: string): void {\n\t\tconst setDepth = target.rlmDepth ?? siblings.find((sibling) => sibling.rlmDepth !== undefined)?.rlmDepth ?? 0;\n\t\tassertAgentSessionNameAvailable(\n\t\t\tsiblings.map((info) => {\n\t\t\t\tconst summary = summaryForInactiveSession(info);\n\t\t\t\tconst ledgerRow = this.roster().bySessionFile(canonicalSessionPath(info.path));\n\t\t\t\treturn {\n\t\t\t\t\tid: summary.sessionId,\n\t\t\t\t\t...(summary.sessionName ? { name: summary.sessionName } : {}),\n\t\t\t\t\tdepth: setDepth,\n\t\t\t\t\tstatus: ledgerRow?.status ?? classifySessionRosterStatus(summary),\n\t\t\t\t\t...(summary.parentSessionPath\n\t\t\t\t\t\t? { parentSessionPath: canonicalSessionPath(summary.parentSessionPath) }\n\t\t\t\t\t\t: {}),\n\t\t\t\t};\n\t\t\t}),\n\t\t\t{\n\t\t\t\tname,\n\t\t\t\tdepth: setDepth,\n\t\t\t\tparentSessionPath: target.parentSessionPath ? canonicalSessionPath(target.parentSessionPath) : undefined,\n\t\t\t\tignoreSessionId: target.id,\n\t\t\t},\n\t\t);\n\t}\n\n\tprivate isVisibleWorker(worker: ResidentWorker): boolean {\n\t\treturn worker.descriptor.ownerClientId === undefined;\n\t}\n\n\t/** A worker with a durable or in-memory stop intent is stopping, never live. */\n\tprivate isWorkerStopping(worker: ResidentWorker): boolean {\n\t\treturn worker.intentionalStop || worker.descriptor.stopRequestedAt !== undefined;\n\t}\n\n\t/** Live workers are visible to all clients and not stopping. */\n\tprivate isLiveWorker(worker: ResidentWorker): boolean {\n\t\treturn this.isVisibleWorker(worker) && !this.isWorkerStopping(worker);\n\t}\n\n\t/**\n\t * The lifecycle reported to clients. A stop intent always wins, and a worker\n\t * whose process connection is gone is never reported as \"ready\".\n\t */\n\tprivate effectiveWorkerState(worker: ResidentWorker): DaemonWorkerLifecycle {\n\t\tif (this.isWorkerStopping(worker)) {\n\t\t\treturn \"stopping\";\n\t\t}\n\t\tif (worker.descriptor.lifecycle === \"ready\" && worker.client === undefined) {\n\t\t\treturn \"recovering\";\n\t\t}\n\t\treturn worker.descriptor.lifecycle;\n\t}\n\n\tprivate requireAvailableWorkerClient(worker: ResidentWorker, allowStopping = false): DaemonWorkerClient {\n\t\tif (\n\t\t\t!worker.client ||\n\t\t\tworker.descriptor.lifecycle !== \"ready\" ||\n\t\t\t(!allowStopping && this.isWorkerStopping(worker))\n\t\t) {\n\t\t\tthrow new Error(`Session worker is ${this.effectiveWorkerState(worker)}`);\n\t\t}\n\t\treturn worker.client;\n\t}\n\n\tprivate async issuePeerTransport(\n\t\tworker: ResidentWorker,\n\t\tsummary: SessionSummary,\n\t): Promise<DaemonPeerTransportTicket> {\n\t\tawait this.assertCurrentOwnership();\n\t\tif (!worker.peerTransportCapable) {\n\t\t\tthrow new Error(\"Session worker does not support direct peer transport\");\n\t\t}\n\t\tawait this.refreshWorkerSummaries(worker);\n\t\tconst workerClient = this.requireAvailableWorkerClient(worker);\n\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\tconst currentSummary = this.findSummaryInWorker(worker, activeSessionId);\n\t\tif (!currentSummary) {\n\t\t\tthrow new Error(\"Direct transport target changed during admission\");\n\t\t}\n\t\tconst workerInstanceId = worker.descriptor.workerInstanceId;\n\t\tconst workerProcessStartId = worker.descriptor.processStartId;\n\t\tif (!workerInstanceId || !workerProcessStartId) {\n\t\t\tthrow new Error(\"Direct transport requires an exact worker process identity\");\n\t\t}\n\t\tif (this.processIdentity(worker.descriptor.pid, workerProcessStartId) !== \"current\") {\n\t\t\tthrow new Error(\"Direct transport worker process identity is not current\");\n\t\t}\n\t\tlet socketIdentity: DaemonSocketIdentity | undefined;\n\t\ttry {\n\t\t\tsocketIdentity = getDaemonSocketIdentity(worker.descriptor.socketPath);\n\t\t} catch {\n\t\t\tsocketIdentity = undefined;\n\t\t}\n\t\tif (!socketIdentity) {\n\t\t\tthrow new Error(\"Direct transport requires an exact worker socket identity\");\n\t\t}\n\t\tconst grantId = randomUUID();\n\t\tconst token = randomBytes(32).toString(\"base64url\");\n\t\tconst expiresAt = new Date(Date.now() + PEER_TRANSPORT_GRANT_TTL_MS).toISOString();\n\t\tconst resolvedActiveSessionId = currentSummary.activeSessionId ?? currentSummary.id;\n\t\tconst registration = await workerClient.requestWorker(\n\t\t\t{\n\t\t\t\ttype: \"worker_register_peer_transport\",\n\t\t\t\tgrant: {\n\t\t\t\t\tgrantId,\n\t\t\t\t\ttoken,\n\t\t\t\t\texpiresAt,\n\t\t\t\t\tpurpose: \"session_client\",\n\t\t\t\t\tworkerInstanceId,\n\t\t\t\t\tactiveSessionId: resolvedActiveSessionId,\n\t\t\t\t\tissuerGeneration: this.generation,\n\t\t\t\t},\n\t\t\t},\n\t\t\t3000,\n\t\t);\n\t\tif (!registration.success) {\n\t\t\tthrow deserializeDaemonError(registration);\n\t\t}\n\t\treturn {\n\t\t\tpurpose: \"session_client\",\n\t\t\tsocketPath: worker.descriptor.socketPath,\n\t\t\tsocketIdentity,\n\t\t\tworkerInstanceId,\n\t\t\tactiveSessionId: resolvedActiveSessionId,\n\t\t\tgrantId,\n\t\t\ttoken,\n\t\t\texpiresAt,\n\t\t};\n\t}\n\n\tprivate familyCatalogEntry(summary: SessionSummary): AgentFamilyCatalogEntry {\n\t\tconst depth = summary.rlmDepth ?? (summary.parentSessionPath ? 1 : 0);\n\t\treturn {\n\t\t\tid: summary.sessionId,\n\t\t\t...(summary.sessionName ? { name: summary.sessionName } : {}),\n\t\t\tdepth,\n\t\t\tstatus: summary.rosterStatus ?? classifySessionRosterStatus(summary),\n\t\t\t...(depth > 0 && summary.parentSessionId ? { parentSessionId: summary.parentSessionId } : {}),\n\t\t\t...(depth > 0 && summary.parentSessionPath\n\t\t\t\t? { parentSessionPath: canonicalSessionPath(summary.parentSessionPath) }\n\t\t\t\t: {}),\n\t\t\t...(summary.sessionFile ? { sessionPath: canonicalSessionPath(summary.sessionFile) } : {}),\n\t\t};\n\t}\n\n\tprivate agentPeerSummary(summary: SessionSummary): AgentSessionMessageAgentSummary {\n\t\treturn {\n\t\t\tactiveSessionId: summary.activeSessionId ?? summary.id,\n\t\t\tsessionId: summary.sessionId,\n\t\t\t...(summary.sessionName ? { sessionName: summary.sessionName } : {}),\n\t\t\truntimeKind: summary.runtimeKind ?? \"top-level\",\n\t\t\tcwd: summary.cwd,\n\t\t\tisStreaming: summary.isStreaming,\n\t\t\tunfinishedActionCount:\n\t\t\t\tsummary.unfinishedActionCount ??\n\t\t\t\t(summary.sessionActions.active\n\t\t\t\t\t? 1 + summary.sessionActions.queuedCount\n\t\t\t\t\t: summary.sessionActions.queuedCount),\n\t\t\t...(summary.parentActiveSessionId ? { parentActiveSessionId: summary.parentActiveSessionId } : {}),\n\t\t\t...(summary.parentSessionId ? { parentSessionId: summary.parentSessionId } : {}),\n\t\t\t...(summary.parentSessionPath ? { parentSessionPath: summary.parentSessionPath } : {}),\n\t\t\t...(summary.sessionFile ? { sessionPath: summary.sessionFile } : {}),\n\t\t\t...(summary.rlmDepth !== undefined ? { rlmDepth: summary.rlmDepth } : {}),\n\t\t\tstatus: summary.rosterStatus ?? classifySessionRosterStatus(summary),\n\t\t\t...(summary.rlmChildId ? { rlmChildId: summary.rlmChildId } : {}),\n\t\t};\n\t}\n\n\tprivate attachedClientCount(summary: SessionSummary, activeSessionId: string): number {\n\t\treturn (\n\t\t\t(summary.directAttachedClients ?? 0) +\n\t\t\t[...this.clients].filter((client) => client.attachedActiveSessionIds.has(activeSessionId)).length\n\t\t);\n\t}\n\n\tprivate publicSummary(worker: ResidentWorker, summary: SessionSummary): SessionSummary {\n\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\treturn {\n\t\t\t...summary,\n\t\t\tattachedClients: this.attachedClientCount(summary, activeSessionId),\n\t\t\tworkerState: this.effectiveWorkerState(worker),\n\t\t\tworkerPid: worker.descriptor.pid,\n\t\t};\n\t}\n\n\tprivate async findWorker(\n\t\tselector: string,\n\t\tincludeWorker?: (worker: ResidentWorker) => boolean,\n\t): Promise<WorkerMatch> {\n\t\tlet matches = this.matchWorkers(selector, includeWorker);\n\t\tif (matches.length === 0) {\n\t\t\tawait Promise.all(\n\t\t\t\t[...this.workers.values()].map((worker) =>\n\t\t\t\t\tthis.refreshWorkerSummaries(worker, false, true).catch(() => undefined),\n\t\t\t\t),\n\t\t\t);\n\t\t\tmatches = this.matchWorkers(selector, includeWorker);\n\t\t}\n\t\tif (matches.length === 1) {\n\t\t\treturn matches[0]!;\n\t\t}\n\t\tif (matches.length > 1) {\n\t\t\tthrow new Error(`Ambiguous active session \"${selector}\"`);\n\t\t}\n\t\tthrow new Error(`Unknown active session: ${selector}`);\n\t}\n\n\tprivate findWorkerForClient(client: DaemonSocketClient, selector: string): Promise<WorkerMatch> {\n\t\treturn this.findWorker(selector, (worker) => this.isWorkerAccessibleToClient(client, worker));\n\t}\n\n\tprivate isWorkerAccessibleToClient(client: DaemonSocketClient, worker: ResidentWorker): boolean {\n\t\treturn (\n\t\t\tworker.descriptor.ownerClientId === undefined ||\n\t\t\tworker.descriptor.ownerClientId === this.protocolClientId(client)\n\t\t);\n\t}\n\n\tprivate assertWorkerAccessibleToClient(client: DaemonSocketClient, worker: ResidentWorker, selector: string): void {\n\t\tif (!this.isWorkerAccessibleToClient(client, worker)) {\n\t\t\tthrow new Error(`Unknown active session: ${selector}`);\n\t\t}\n\t}\n\n\tprivate matchWorkers(selector: string, includeWorker?: (worker: ResidentWorker) => boolean): WorkerMatch[] {\n\t\tconst exact: WorkerMatch[] = [];\n\t\tconst suffix: WorkerMatch[] = [];\n\t\tfor (const entry of this.roster().values()) {\n\t\t\tif (entry.queuedChild) continue;\n\t\t\tconst worker = entry.workerId !== undefined ? this.workers.get(entry.workerId) : undefined;\n\t\t\tif (!worker || (includeWorker && !includeWorker(worker))) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst summary = sessionSummaryFromRosterEntry(entry);\n\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\tconst match = { worker, summary };\n\t\t\tif (activeSessionId === selector || summary.sessionId === selector || summary.sessionName === selector) {\n\t\t\t\texact.push(match);\n\t\t\t} else if (\n\t\t\t\tmatchesSessionIdSuffix(activeSessionId, selector) ||\n\t\t\t\tmatchesSessionIdSuffix(summary.sessionId, selector)\n\t\t\t) {\n\t\t\t\tsuffix.push(match);\n\t\t\t}\n\t\t}\n\t\treturn exact.length > 0 ? exact : suffix;\n\t}\n\n\tprivate findSummaryInWorker(worker: ResidentWorker, selector: string): SessionSummary | undefined {\n\t\tconst pathSelector = looksLikeSessionPath(selector) ? canonicalSessionPath(selector) : undefined;\n\t\tconst summaries = this.workerRosterEntries(worker)\n\t\t\t.filter((entry) => !entry.queuedChild)\n\t\t\t.map(sessionSummaryFromRosterEntry);\n\t\tconst exact = summaries.find((summary) => {\n\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\treturn (\n\t\t\t\tactiveSessionId === selector ||\n\t\t\t\tsummary.sessionId === selector ||\n\t\t\t\tsummary.sessionName === selector ||\n\t\t\t\t(pathSelector !== undefined &&\n\t\t\t\t\tsummary.sessionFile !== undefined &&\n\t\t\t\t\tcanonicalSessionPath(summary.sessionFile) === pathSelector)\n\t\t\t);\n\t\t});\n\t\tif (exact) return exact;\n\t\treturn summaries.find((summary) => {\n\t\t\tconst activeSessionId = summary.activeSessionId ?? summary.id;\n\t\t\treturn (\n\t\t\t\tmatchesSessionIdSuffix(activeSessionId, selector) || matchesSessionIdSuffix(summary.sessionId, selector)\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate findWorkerBySessionFile(sessionFile: string, exclude?: ResidentWorker): ResidentWorker | undefined {\n\t\tconst target = canonicalSessionPath(sessionFile);\n\t\tconst targetEntry = this.roster().bySessionFile(target);\n\t\tconst matches = new Set<ResidentWorker>();\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker === exclude) continue;\n\t\t\t// The roster is the one live ownership source; the stale pull cache must not resurrect a match.\n\t\t\tconst summaryMatches = targetEntry?.workerId === worker.descriptor.workerId;\n\t\t\tconst descriptorPath = worker.descriptor.sessionFile\n\t\t\t\t? canonicalSessionPath(worker.descriptor.sessionFile)\n\t\t\t\t: undefined;\n\t\t\tconst configuredPath = worker.descriptor.createCommand.sessionPath\n\t\t\t\t? canonicalSessionPath(worker.descriptor.createCommand.sessionPath)\n\t\t\t\t: undefined;\n\t\t\tif (!summaryMatches && descriptorPath !== target && configuredPath !== target) continue;\n\t\t\tif (descriptorPath && configuredPath && descriptorPath !== configuredPath) {\n\t\t\t\tthrow new Error(`Conflicting resident session paths for worker ${worker.descriptor.workerId}`);\n\t\t\t}\n\t\t\tmatches.add(worker);\n\t\t}\n\t\tif (matches.size > 1) {\n\t\t\tthrow new Error(`Ambiguous resident session path \"${sessionFile}\"`);\n\t\t}\n\t\treturn matches.values().next().value;\n\t}\n\n\tprivate async forwardToWorker(\n\t\tworker: ResidentWorker,\n\t\tcommand: DaemonCommand,\n\t\ttimeoutMs = WORKER_REQUEST_TIMEOUT_MS,\n\t): Promise<DaemonResponse> {\n\t\tconst client = this.requireAvailableWorkerClient(worker, command.type === \"kill\");\n\t\tconst response = await client.request(withoutCommandId(command), timeoutMs);\n\t\tif (command.type === \"get_state\" && response.success && isSessionSummary(response.data)) {\n\t\t\treturn { ...response, id: command.id, data: this.publicSummary(worker, response.data) };\n\t\t}\n\t\tif (command.type === \"rename\" && response.success && isSessionSummary(response.data)) {\n\t\t\tthis.writeRosterEntry(workerRosterEntryFromSummary(response.data), worker);\n\t\t\treturn { ...response, id: command.id, data: this.publicSummary(worker, response.data) };\n\t\t}\n\t\treturn responseWithId(response, command.id);\n\t}\n\n\tprivate async attachClient(\n\t\tclient: DaemonSocketClient,\n\t\tcommand: Extract<DaemonCommand, { type: \"attach\" }>,\n\t): Promise<WorkerAttachData> {\n\t\tconst ownedWorker = [...this.workers.values()].find(\n\t\t\t(worker) =>\n\t\t\t\tworker.descriptor.ownerClientId !== undefined &&\n\t\t\t\t(worker.descriptor.rootActiveSessionId === command.activeSessionId ||\n\t\t\t\t\tworker.descriptor.rootSessionId === command.activeSessionId),\n\t\t);\n\t\tif (ownedWorker) {\n\t\t\tif (ownedWorker.descriptor.ownerClientId !== this.protocolClientId(client)) {\n\t\t\t\tthrow new Error(`Unknown active session: ${command.activeSessionId}`);\n\t\t\t}\n\t\t\townedWorker.launchEnv = command.launchEnv ?? ownedWorker.launchEnv;\n\t\t\tif (!ownedWorker.client || ownedWorker.descriptor.lifecycle !== \"ready\") {\n\t\t\t\tif (command.recoveryConfig) {\n\t\t\t\t\townedWorker.transientCreateCommand = {\n\t\t\t\t\t\t...ownedWorker.descriptor.createCommand,\n\t\t\t\t\t\tconfig: command.recoveryConfig,\n\t\t\t\t\t\tenv: command.env,\n\t\t\t\t\t\tlaunchEnv: command.launchEnv,\n\t\t\t\t\t\tlifecycle: \"client_owned\",\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (!ownedWorker.launchEnv) {\n\t\t\t\t\tthrow new Error(\"Client-owned session recovery requires the owning client environment\");\n\t\t\t\t}\n\t\t\t\townedWorker.intentionalStop = false;\n\t\t\t\townedWorker.descriptor.stopRequestedAt = undefined;\n\t\t\t\townedWorker.descriptor.archiveOnStop = undefined;\n\t\t\t\townedWorker.descriptor.lifecycle = \"recovering\";\n\t\t\t\townedWorker.descriptor.consecutiveFailures = 0;\n\t\t\t\townedWorker.deferredRecoveryRounds = 0;\n\t\t\t\tthis.persistWorker(ownedWorker);\n\t\t\t\tawait this.recoverWorker(ownedWorker);\n\t\t\t}\n\t\t}\n\t\tconst match = await this.findWorkerForClient(client, command.activeSessionId);\n\t\tthis.requireAvailableWorkerClient(match.worker);\n\t\tconst activeSessionId = match.summary.activeSessionId ?? match.summary.id;\n\t\tconst duplicateValidation = this.currentSnapshotGeneration(match.worker, activeSessionId)?.validation;\n\t\tif (duplicateValidation) {\n\t\t\tawait duplicateValidation.promise;\n\t\t}\n\t\tif (command.clientId) {\n\t\t\tclient.id = command.clientId;\n\t\t}\n\t\tclient.capabilities = normalizeCapabilities(command.capabilities, command.supportsExtensionUi);\n\t\tclient.supportsExtensionUi = client.capabilities.has(\"extension_ui\");\n\n\t\tlet result = match.worker.snapshotCache.get(activeSessionId);\n\t\tif (\n\t\t\tresult &&\n\t\t\t!client.capabilities.has(\"chunked_snapshot\") &&\n\t\t\tresult.snapshot.messages.length < result.snapshot.summary.messageCount\n\t\t) {\n\t\t\tresult = undefined;\n\t\t}\n\t\tif (!result) {\n\t\t\tconst snapshotLoadKey = `${activeSessionId}:${client.capabilities.has(\"chunked_snapshot\") ? \"chunked\" : \"full\"}`;\n\t\t\tlet retryInvalidatedLoad = true;\n\t\t\twhile (!result) {\n\t\t\t\tlet loading = match.worker.snapshotLoads.get(snapshotLoadKey);\n\t\t\t\tif (!loading) {\n\t\t\t\t\tconst observedSnapshotId =\n\t\t\t\t\t\tmatch.worker.transcriptCaches.get(activeSessionId)?.snapshotId ??\n\t\t\t\t\t\tmatch.worker.snapshotCache.get(activeSessionId)?.snapshotStream?.id;\n\t\t\t\t\tloading = (async () => {\n\t\t\t\t\t\tconst workerClient = this.requireAvailableWorkerClient(match.worker);\n\t\t\t\t\t\tconst response = await workerClient.request({\n\t\t\t\t\t\t\ttype: \"attach\",\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tcapabilities: client.capabilities.has(\"chunked_snapshot\")\n\t\t\t\t\t\t\t\t? [\"attach_snapshot\", \"event_sequence\", \"slim_attach\", \"chunked_snapshot\"]\n\t\t\t\t\t\t\t\t: [\"attach_snapshot\", \"event_sequence\", \"slim_attach\"],\n\t\t\t\t\t\t\tsupportsExtensionUi: false,\n\t\t\t\t\t\t\tenv: command.env ?? collectDaemonClientEnv(),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst loaded = attachResultFromResponse(response);\n\t\t\t\t\t\tif (match.worker.snapshotLoads.get(snapshotLoadKey) !== loading) {\n\t\t\t\t\t\t\tthrow new SnapshotLoadInvalidatedError(\"Session snapshot changed during attach\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn this.cacheLoadedSnapshot(match.worker, activeSessionId, loaded, observedSnapshotId);\n\t\t\t\t\t})();\n\t\t\t\t\tmatch.worker.snapshotLoads.set(snapshotLoadKey, loading);\n\t\t\t\t\tvoid loading.then(\n\t\t\t\t\t\tasync (loaded) => {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst snapshotId = loaded.snapshotStream?.id;\n\t\t\t\t\t\t\t\tconst transcript = snapshotId\n\t\t\t\t\t\t\t\t\t? this.snapshotGeneration(match.worker, loaded.activeSessionId, snapshotId)?.transcript\n\t\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\t\tif (transcript && !transcript.complete) {\n\t\t\t\t\t\t\t\t\tlet chunkIndex = 0;\n\t\t\t\t\t\t\t\t\twhile (await transcript.waitForChunk(chunkIndex)) {\n\t\t\t\t\t\t\t\t\t\tchunkIndex++;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Failed transfers must allow a fresh snapshot request.\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tif (match.worker.snapshotLoads.get(snapshotLoadKey) === loading) {\n\t\t\t\t\t\t\t\t\tmatch.worker.snapshotLoads.delete(snapshotLoadKey);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\tif (match.worker.snapshotLoads.get(snapshotLoadKey) === loading) {\n\t\t\t\t\t\t\t\tmatch.worker.snapshotLoads.delete(snapshotLoadKey);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tresult = await loading;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!(error instanceof SnapshotLoadInvalidatedError)) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tif (!retryInvalidatedLoad) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tretryInvalidatedLoad = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.requireAvailableWorkerClient(match.worker);\n\t\tconst wasAttached = client.attachedActiveSessionIds.has(activeSessionId);\n\t\tlet transcript: SnapshotTranscriptCache | undefined;\n\t\tif (client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\twhile (true) {\n\t\t\t\tconst validation = this.currentSnapshotGeneration(match.worker, activeSessionId)?.validation;\n\t\t\t\tif (validation) {\n\t\t\t\t\tawait validation.promise;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tresult = match.worker.snapshotCache.get(activeSessionId) ?? result;\n\t\t\t\ttranscript = this.getOrCreateTranscriptCache(match.worker, result);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tconst releaseTranscript = transcript?.retain();\n\t\tclient.attachedActiveSessionIds.add(activeSessionId);\n\t\ttry {\n\t\t\tconst publicSummary = this.publicSummary(match.worker, result.snapshot.summary);\n\t\t\tif (publicSummary.streamingMessage?.role === \"assistant\") {\n\t\t\t\tthis.streamReconstructor.seed(activeSessionId, publicSummary.streamingMessage);\n\t\t\t} else {\n\t\t\t\tfor (let index = result.snapshot.messages.length - 1; index >= 0; index--) {\n\t\t\t\t\tconst latestMessage = result.snapshot.messages[index];\n\t\t\t\t\tif (latestMessage?.role === \"assistant\") {\n\t\t\t\t\t\tthis.streamReconstructor.seed(activeSessionId, latestMessage);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst publicResult: DaemonAttachResult = {\n\t\t\t\t...result,\n\t\t\t\tstate: result.state ? publicSummary : undefined,\n\t\t\t\tsnapshot: { ...result.snapshot, summary: publicSummary },\n\t\t\t\tclient: { id: client.id, capabilities: [...client.capabilities] },\n\t\t\t};\n\t\t\tif (publicResult.state && publicResult.messages) {\n\t\t\t\tthis.write(client, {\n\t\t\t\t\ttype: \"session_attached\",\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tstate: publicResult.state,\n\t\t\t\t\tmessages: publicResult.messages,\n\t\t\t\t\tsnapshot: publicResult.snapshot,\n\t\t\t\t\treplay: publicResult.replay,\n\t\t\t\t\tlastEventSequence: publicResult.lastEventSequence,\n\t\t\t\t});\n\t\t\t}\n\t\t\tvoid this.syncWorkerExtensionUi(activeSessionId);\n\t\t\tconst detachingSessions = this.detachingInputPauseSessions?.get(client);\n\t\t\tdetachingSessions?.delete(command.activeSessionId);\n\t\t\tdetachingSessions?.delete(activeSessionId);\n\t\t\treturn { result: publicResult, worker: match.worker, transcript, releaseTranscript };\n\t\t} catch (error) {\n\t\t\treleaseTranscript?.();\n\t\t\tif (!wasAttached) {\n\t\t\t\tclient.attachedActiveSessionIds.delete(activeSessionId);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate cacheLoadedSnapshot(\n\t\tworker: ResidentWorker,\n\t\tactiveSessionId: string,\n\t\tloaded: DaemonAttachResult,\n\t\tobservedSnapshotId: string | undefined,\n\t): DaemonAttachResult {\n\t\tconst currentTranscript = worker.transcriptCaches.get(activeSessionId);\n\t\tconst currentGeneration = this.currentSnapshotGeneration(worker, activeSessionId);\n\t\tconst currentResult = currentGeneration?.result ?? worker.snapshotCache.get(activeSessionId);\n\t\tconst currentSnapshotId = currentTranscript?.snapshotId ?? currentResult?.snapshotStream?.id;\n\t\tconst loadedSnapshotId = loaded.snapshotStream?.id;\n\t\tif (!loaded.snapshotStream) {\n\t\t\tif (currentSnapshotId && currentSnapshotId !== observedSnapshotId) {\n\t\t\t\treturn loaded;\n\t\t\t}\n\t\t\tworker.snapshotCache.set(activeSessionId, loaded);\n\t\t\treturn loaded;\n\t\t}\n\t\tif (\n\t\t\tcurrentSnapshotId &&\n\t\t\tcurrentSnapshotId !== loadedSnapshotId &&\n\t\t\t(currentSnapshotId !== observedSnapshotId ||\n\t\t\t\t(currentResult?.lastEventSequence ?? -1) > loaded.lastEventSequence)\n\t\t) {\n\t\t\treturn currentResult ?? loaded;\n\t\t}\n\t\tlet transcript = currentTranscript;\n\t\tif (transcript && transcript.snapshotId !== loaded.snapshotStream.id) {\n\t\t\tthis.retireWorkerSnapshotCache(worker, activeSessionId, transcript);\n\t\t\ttranscript = undefined;\n\t\t}\n\t\tconst generations = this.snapshotGenerationsFor(worker, activeSessionId);\n\t\tlet generation = generations.get(loaded.snapshotStream.id);\n\t\tif (!transcript) {\n\t\t\ttranscript = generation?.transcript;\n\t\t}\n\t\tif (!transcript) {\n\t\t\ttranscript = new SnapshotTranscriptCache({\n\t\t\t\tactiveSessionId,\n\t\t\t\tsnapshotId: loaded.snapshotStream.id,\n\t\t\t\tcacheRoot: this.snapshotCacheRoot,\n\t\t\t\ttargetChunkBytes: loaded.snapshotStream.targetChunkBytes,\n\t\t\t});\n\t\t}\n\t\tif (!generation) {\n\t\t\tgeneration = {\n\t\t\t\ttranscript,\n\t\t\t\tresult: loaded,\n\t\t\t\tincoming: false,\n\t\t\t\tretired: false,\n\t\t\t};\n\t\t\tgenerations.set(loaded.snapshotStream.id, generation);\n\t\t} else {\n\t\t\tgeneration.result = loaded;\n\t\t\tgeneration.retired = false;\n\t\t}\n\t\tworker.transcriptCaches.set(activeSessionId, transcript);\n\t\tworker.snapshotCache.set(activeSessionId, loaded);\n\t\treturn loaded;\n\t}\n\n\tprivate getOrCreateTranscriptCache(worker: ResidentWorker, result: DaemonAttachResult): SnapshotTranscriptCache {\n\t\tconst activeSessionId = result.activeSessionId;\n\t\tconst existing = worker.transcriptCaches.get(activeSessionId);\n\t\tif (existing && (!result.snapshotStream || existing.snapshotId === result.snapshotStream.id)) {\n\t\t\treturn existing;\n\t\t}\n\t\tif (result.snapshot.messages.length < result.snapshot.summary.messageCount) {\n\t\t\tthrow new Error(\"Session snapshot generation changed before its transcript could be selected\");\n\t\t}\n\t\tif (existing) {\n\t\t\tthis.retireWorkerSnapshotCache(worker, activeSessionId, existing);\n\t\t}\n\t\tconst revision = createHash(\"sha256\")\n\t\t\t.update(\n\t\t\t\t`${activeSessionId}:${result.snapshot.summary.sessionId}:${result.lastEventSequence}:${result.snapshot.messages.length}`,\n\t\t\t)\n\t\t\t.digest(\"hex\")\n\t\t\t.slice(0, 16);\n\t\tconst transcript = new SnapshotTranscriptCache({\n\t\t\tactiveSessionId,\n\t\t\tsnapshotId: `${activeSessionId}-${revision}`,\n\t\t\tmessages: result.snapshot.messages,\n\t\t\tcacheRoot: this.snapshotCacheRoot,\n\t\t\ttargetChunkBytes: SNAPSHOT_TARGET_CHUNK_BYTES,\n\t\t});\n\t\tworker.transcriptCaches.set(activeSessionId, transcript);\n\t\tconst cachedResult = {\n\t\t\t...result,\n\t\t\tmessages: result.messages ? [] : undefined,\n\t\t\tsnapshot: { ...result.snapshot, messages: [] },\n\t\t};\n\t\tworker.snapshotCache.set(activeSessionId, cachedResult);\n\t\tthis.snapshotGenerationsFor(worker, activeSessionId).set(transcript.snapshotId, {\n\t\t\ttranscript,\n\t\t\tresult: cachedResult,\n\t\t\tincoming: false,\n\t\t\tretired: false,\n\t\t});\n\t\treturn transcript;\n\t}\n\n\tprivate createStreamedAttachResult(\n\t\tresult: DaemonAttachResult,\n\t\ttranscript: SnapshotTranscriptCache,\n\t): DaemonAttachResult {\n\t\treturn {\n\t\t\t...result,\n\t\t\tmessages: result.messages ? [] : undefined,\n\t\t\tsnapshot: { ...result.snapshot, messages: [] },\n\t\t\tsnapshotStream: {\n\t\t\t\tid: transcript.snapshotId,\n\t\t\t\tmessageCount: result.snapshot.summary.messageCount,\n\t\t\t\ttargetChunkBytes: transcript.targetChunkBytes,\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async streamSnapshot(\n\t\tclient: DaemonSocketClient,\n\t\tworker: ResidentWorker,\n\t\tresult: DaemonAttachResult,\n\t\ttranscript: SnapshotTranscriptCache,\n\t\tpurpose: \"attach\" | \"replacement\" | \"resync\" = \"attach\",\n\t\tretainedTranscriptRelease?: () => void,\n\t\treleaseSnapshotReservation = this.reserveSnapshotStream(client, result.activeSessionId),\n\t): Promise<void> {\n\t\tconst stream = result.snapshotStream;\n\t\tconst releaseTranscript = retainedTranscriptRelease ?? transcript.retain();\n\t\tif (!stream || client.socket.destroyed) {\n\t\t\treleaseSnapshotReservation();\n\t\t\treleaseTranscript();\n\t\t\treturn;\n\t\t}\n\t\tconst { messages: _messages, ...snapshotHeader } = result.snapshot;\n\t\ttry {\n\t\t\tif (\n\t\t\t\t!(await this.writeSnapshotRecord(client, {\n\t\t\t\t\ttype: \"session_snapshot_begin\",\n\t\t\t\t\tactiveSessionId: result.activeSessionId,\n\t\t\t\t\tsnapshotId: stream.id,\n\t\t\t\t\tsnapshot: snapshotHeader,\n\t\t\t\t\tmessageCount: stream.messageCount,\n\t\t\t\t\ttargetChunkBytes: stream.targetChunkBytes,\n\t\t\t\t\tpurpose,\n\t\t\t\t}))\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet chunkCount = 0;\n\t\t\twhile (true) {\n\t\t\t\tlet chunk: Buffer | undefined;\n\t\t\t\ttry {\n\t\t\t\t\tchunk = await transcript.waitForChunk(chunkCount);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst streamError = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\tthis.failWorkerSnapshotCache(worker, result.activeSessionId, streamError, false, stream.id);\n\t\t\t\t\tthrow streamError;\n\t\t\t\t}\n\t\t\t\tif (!chunk) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!(await this.writeSnapshotBuffer(client, chunk))) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tchunkCount++;\n\t\t\t}\n\t\t\tawait this.writeSnapshotRecord(client, {\n\t\t\t\ttype: \"session_snapshot_end\",\n\t\t\t\tactiveSessionId: result.activeSessionId,\n\t\t\t\tsnapshotId: stream.id,\n\t\t\t\tchunkCount,\n\t\t\t\tlastEventSequence: result.lastEventSequence,\n\t\t\t\tlastEventCursor: result.lastEventCursor,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst streamError = error instanceof Error ? error : new Error(String(error));\n\t\t\tif (!client.socket.destroyed) {\n\t\t\t\ttry {\n\t\t\t\t\tconst delivered = await this.writeSnapshotRecord(client, {\n\t\t\t\t\t\ttype: \"session_snapshot_failed\",\n\t\t\t\t\t\tactiveSessionId: result.activeSessionId,\n\t\t\t\t\t\tsnapshotId: stream.id,\n\t\t\t\t\t\terror: streamError.message,\n\t\t\t\t\t});\n\t\t\t\t\tif (!delivered && !client.socket.destroyed) {\n\t\t\t\t\t\tclient.socket.destroy(streamError);\n\t\t\t\t\t}\n\t\t\t\t} catch (deliveryError) {\n\t\t\t\t\tclient.socket.destroy(deliveryError instanceof Error ? deliveryError : new Error(String(deliveryError)));\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow streamError;\n\t\t} finally {\n\t\t\treleaseSnapshotReservation();\n\t\t\treleaseTranscript();\n\t\t}\n\t}\n\n\tprivate reserveSnapshotStream(client: DaemonSocketClient, activeSessionId: string): () => void {\n\t\tclient.snapshotStreaming = true;\n\t\tclient.snapshotActiveSessionIds ??= new Set();\n\t\tclient.snapshotActiveSessionIds.add(activeSessionId);\n\t\tclient.snapshotActiveSessionCounts ??= new Map();\n\t\tclient.snapshotActiveSessionCounts.set(\n\t\t\tactiveSessionId,\n\t\t\t(client.snapshotActiveSessionCounts.get(activeSessionId) ?? 0) + 1,\n\t\t);\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treleased = true;\n\t\t\tconst streamCount = client.snapshotActiveSessionCounts?.get(activeSessionId) ?? 1;\n\t\t\tif (streamCount > 1) {\n\t\t\t\tclient.snapshotActiveSessionCounts?.set(activeSessionId, streamCount - 1);\n\t\t\t} else {\n\t\t\t\tclient.snapshotActiveSessionCounts?.delete(activeSessionId);\n\t\t\t\tclient.snapshotActiveSessionIds?.delete(activeSessionId);\n\t\t\t}\n\t\t\tclient.snapshotStreaming = (client.snapshotActiveSessionIds?.size ?? 0) > 0;\n\t\t\tif (!client.snapshotStreaming) {\n\t\t\t\tclient.backpressured = false;\n\t\t\t}\n\t\t\tif (!client.snapshotStreaming && client.catchupActiveSessionIds?.size) {\n\t\t\t\tvoid this.catchUpClient(client).catch((error) =>\n\t\t\t\t\tthis.log(`Failed to catch up client ${client.id}: ${String(error)}`),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate writeSnapshotRecord(client: DaemonSocketClient, message: DaemonOutbound): Promise<boolean> {\n\t\treturn this.writeSnapshotBuffer(client, Buffer.from(serializeJsonLine(message)));\n\t}\n\n\tprivate async writeSnapshotBuffer(client: DaemonSocketClient, buffer: Uint8Array): Promise<boolean> {\n\t\tif (client.socket.destroyed) {\n\t\t\treturn false;\n\t\t}\n\t\tif (this.writeSerialized(client, buffer)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn new Promise<boolean>((resolveDrain) => {\n\t\t\tlet settled = false;\n\t\t\tconst finish = (value: boolean) => {\n\t\t\t\tif (settled) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsettled = true;\n\t\t\t\tclient.socket.off(\"drain\", onDrain);\n\t\t\t\tclient.socket.off(\"close\", onClose);\n\t\t\t\tclient.socket.off(\"error\", onClose);\n\t\t\t\tresolveDrain(value);\n\t\t\t};\n\t\t\tconst onDrain = () => finish(true);\n\t\t\tconst onClose = () => finish(false);\n\t\t\tclient.socket.once(\"drain\", onDrain);\n\t\t\tclient.socket.once(\"close\", onClose);\n\t\t\tclient.socket.once(\"error\", onClose);\n\t\t});\n\t}\n\n\tprivate detachClient(client: DaemonSocketClient, activeSessionId?: string): void {\n\t\tconst targets = activeSessionId ? [activeSessionId] : [...client.attachedActiveSessionIds];\n\t\tfor (const selector of targets) {\n\t\t\tconst match = this.matchWorkers(selector)[0];\n\t\t\tconst resolvedId = match ? (match.summary.activeSessionId ?? match.summary.id) : selector;\n\t\t\tif (!client.attachedActiveSessionIds.delete(resolvedId)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tclient.catchupActiveSessionIds?.delete(resolvedId);\n\t\t\tclient.catchupPurposes?.delete(resolvedId);\n\t\t\tthis.write(client, { type: \"session_detached\", activeSessionId: resolvedId });\n\t\t\tvoid this.syncWorkerExtensionUi(resolvedId);\n\t\t\tvoid this.evictEmptySessionOnLastDetach(resolvedId);\n\t\t}\n\t}\n\n\tprivate async syncWorkerExtensionUi(activeSessionId: string): Promise<void> {\n\t\tconst match = this.matchWorkers(activeSessionId)[0];\n\t\tif (!match?.worker.client) {\n\t\t\treturn;\n\t\t}\n\t\tawait this.subscribeWorker(match.worker, match.summary.activeSessionId ?? match.summary.id).catch(\n\t\t\t() => undefined,\n\t\t);\n\t}\n\n\tprivate handleWorkerFrame(\n\t\tworker: ResidentWorker,\n\t\tframe: PrivateFrame<DaemonWorkerFrameHeader>,\n\t\tsource?: DaemonWorkerClient,\n\t): void {\n\t\tif (frame.header.kind !== \"outbound\") {\n\t\t\treturn;\n\t\t}\n\t\tif (source !== undefined && source !== worker.client && source !== worker.pendingClient) {\n\t\t\treturn;\n\t\t}\n\t\tworker.lastFrameAt = Date.now();\n\t\tthis.clearRosterStaleness(worker);\n\t\tconst {\n\t\t\toutboundType,\n\t\t\tactiveSessionId,\n\t\t\tsnapshotId: frameSnapshotId,\n\t\t\tsessionEventType,\n\t\t\tpayloadEncoding,\n\t\t\tsnapshotPurpose,\n\t\t} = frame.header;\n\t\tif (outboundType === \"roster_delta\") {\n\t\t\tthis.consumeWorkerRosterDelta(worker, frame.payload, source);\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"roster_heartbeat\") {\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"heartbeats_changed\") {\n\t\t\tworker.heartbeatSnapshotStale = true;\n\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"session_snapshot_begin\" && activeSessionId) {\n\t\t\ttry {\n\t\t\t\tconst begin = JSON.parse(frame.payload.toString(\"utf8\")) as Extract<\n\t\t\t\t\tDaemonOutbound,\n\t\t\t\t\t{ type: \"session_snapshot_begin\" }\n\t\t\t\t>;\n\t\t\t\tif (\n\t\t\t\t\tbegin.type !== \"session_snapshot_begin\" ||\n\t\t\t\t\tbegin.activeSessionId !== activeSessionId ||\n\t\t\t\t\ttypeof begin.snapshotId !== \"string\" ||\n\t\t\t\t\t(frameSnapshotId !== undefined && frameSnapshotId !== begin.snapshotId) ||\n\t\t\t\t\ttypeof begin.targetChunkBytes !== \"number\" ||\n\t\t\t\t\t!begin.snapshot ||\n\t\t\t\t\t!isSessionSummary(begin.snapshot.summary)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Worker returned an invalid snapshot begin frame\");\n\t\t\t\t}\n\t\t\t\tconst publicSummary = this.publicSummary(worker, begin.snapshot.summary);\n\t\t\t\tconst snapshot = {\n\t\t\t\t\t...begin.snapshot,\n\t\t\t\t\tsummary: publicSummary,\n\t\t\t\t\tmessages: [],\n\t\t\t\t};\n\t\t\t\tconst result: DaemonAttachResult = {\n\t\t\t\t\tprotocol: DAEMON_PROTOCOL_INFO,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tsnapshot,\n\t\t\t\t\treplay: {\n\t\t\t\t\t\tstatus: \"complete\",\n\t\t\t\t\t\ttoSequence: snapshot.lastEventSequence,\n\t\t\t\t\t\t...(snapshot.lastEventCursor ? { toCursor: snapshot.lastEventCursor } : {}),\n\t\t\t\t\t},\n\t\t\t\t\tlastEventSequence: snapshot.lastEventSequence,\n\t\t\t\t\t...(snapshot.lastEventCursor ? { lastEventCursor: snapshot.lastEventCursor } : {}),\n\t\t\t\t\tsnapshotStream: {\n\t\t\t\t\t\tid: begin.snapshotId,\n\t\t\t\t\t\tmessageCount: begin.messageCount,\n\t\t\t\t\t\ttargetChunkBytes: begin.targetChunkBytes,\n\t\t\t\t\t},\n\t\t\t\t\tclient: { id: \"supervisor\", capabilities: [\"chunked_snapshot\"] },\n\t\t\t\t};\n\t\t\t\tconst generations = this.snapshotGenerationsFor(worker, activeSessionId);\n\t\t\t\tlet generation = generations.get(begin.snapshotId);\n\t\t\t\tif (generation?.incoming) {\n\t\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\t\tworker,\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tnew Error(`Snapshot ${begin.snapshotId} restarted before completion`),\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tbegin.snapshotId,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// Snapshot summaries/state include live fields (for example activity and attached client\n\t\t\t\t// counts) that can change without advancing the transcript sequence. Treat the stable\n\t\t\t\t// transfer envelope as identity; duplicate chunks and end metadata are still byte-checked.\n\t\t\t\tconst duplicate =\n\t\t\t\t\tgeneration?.transcript.complete === true &&\n\t\t\t\t\tgeneration.end !== undefined &&\n\t\t\t\t\tgeneration.result.snapshotStream?.messageCount === begin.messageCount &&\n\t\t\t\t\tgeneration.result.snapshotStream?.targetChunkBytes === begin.targetChunkBytes &&\n\t\t\t\t\tgeneration.result.lastEventSequence === result.lastEventSequence &&\n\t\t\t\t\tgeneration.result.snapshot.lastEventSequence === result.snapshot.lastEventSequence &&\n\t\t\t\t\tgeneration.result.snapshot.lastEventCursor?.generation === result.snapshot.lastEventCursor?.generation &&\n\t\t\t\t\tgeneration.result.snapshot.lastEventCursor?.sequence === result.snapshot.lastEventCursor?.sequence;\n\t\t\t\tif (generation?.transcript.complete && !duplicate) {\n\t\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\t\tworker,\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tnew Error(`Snapshot ${begin.snapshotId} did not match the cached transfer`),\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tbegin.snapshotId,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst currentGeneration = this.currentSnapshotGeneration(worker, activeSessionId);\n\t\t\t\tconst currentResult = currentGeneration?.result ?? worker.snapshotCache.get(activeSessionId);\n\t\t\t\tconst isOlderThanCurrent =\n\t\t\t\t\tcurrentGeneration !== undefined &&\n\t\t\t\t\tcurrentGeneration.transcript.snapshotId !== begin.snapshotId &&\n\t\t\t\t\tcurrentResult !== undefined &&\n\t\t\t\t\tresult.lastEventSequence < currentResult.lastEventSequence;\n\t\t\t\tif (isOlderThanCurrent && !generation) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (duplicate && generation) {\n\t\t\t\t\tgeneration.incoming = true;\n\t\t\t\t\tgeneration.duplicateChunkIndex = 0;\n\t\t\t\t\tgeneration.duplicateResult = result;\n\t\t\t\t\tgeneration.validation = this.createSnapshotDuplicateValidation();\n\t\t\t\t\tif (currentGeneration === generation) {\n\t\t\t\t\t\tworker.snapshotCache.delete(activeSessionId);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tcurrentGeneration &&\n\t\t\t\t\tcurrentGeneration.transcript.snapshotId !== begin.snapshotId &&\n\t\t\t\t\t!isOlderThanCurrent\n\t\t\t\t) {\n\t\t\t\t\tif (!currentGeneration.transcript.complete && !currentGeneration.incoming) {\n\t\t\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tnew Error(`Snapshot ${currentGeneration.transcript.snapshotId} was superseded`),\n\t\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t\tcurrentGeneration.transcript.snapshotId,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.retireWorkerSnapshotCache(worker, activeSessionId, currentGeneration.transcript);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!generation) {\n\t\t\t\t\tconst transcript = new SnapshotTranscriptCache({\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tsnapshotId: begin.snapshotId,\n\t\t\t\t\t\tcacheRoot: this.snapshotCacheRoot,\n\t\t\t\t\t\ttargetChunkBytes: begin.targetChunkBytes,\n\t\t\t\t\t});\n\t\t\t\t\tgeneration = {\n\t\t\t\t\t\ttranscript,\n\t\t\t\t\t\tresult,\n\t\t\t\t\t\tincoming: false,\n\t\t\t\t\t\tretired: isOlderThanCurrent,\n\t\t\t\t\t};\n\t\t\t\t\tthis.snapshotGenerationsFor(worker, activeSessionId).set(begin.snapshotId, generation);\n\t\t\t\t}\n\t\t\t\tgeneration.result = result;\n\t\t\t\tgeneration.begin = Buffer.from(frame.payload);\n\t\t\t\tgeneration.end = undefined;\n\t\t\t\tgeneration.incoming = true;\n\t\t\t\tgeneration.duplicateChunkIndex = undefined;\n\t\t\t\tgeneration.duplicateResult = undefined;\n\t\t\t\tgeneration.validation = undefined;\n\t\t\t\tif (!isOlderThanCurrent) {\n\t\t\t\t\tgeneration.retired = false;\n\t\t\t\t\tworker.transcriptCaches.set(activeSessionId, generation.transcript);\n\t\t\t\t\tworker.snapshotCache.set(activeSessionId, result);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.log(`Invalid worker snapshot begin frame: ${String(error)}`);\n\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\tworker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"session_snapshot_chunk\" && activeSessionId) {\n\t\t\tconst snapshotId = frameSnapshotId ?? worker.transcriptCaches.get(activeSessionId)?.snapshotId;\n\t\t\tif (!snapshotId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst generation = this.snapshotGeneration(worker, activeSessionId, snapshotId);\n\t\t\tif (generation?.incoming) {\n\t\t\t\ttry {\n\t\t\t\t\tconst duplicateIndex = generation.duplicateChunkIndex;\n\t\t\t\t\tif (duplicateIndex === undefined) {\n\t\t\t\t\t\tgeneration.transcript.appendEncodedChunk(Buffer.from(frame.payload));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst chunk = JSON.parse(frame.payload.toString(\"utf8\")) as Extract<\n\t\t\t\t\t\t\tDaemonOutbound,\n\t\t\t\t\t\t\t{ type: \"session_snapshot_chunk\" }\n\t\t\t\t\t\t>;\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tchunk.type !== \"session_snapshot_chunk\" ||\n\t\t\t\t\t\t\tchunk.activeSessionId !== activeSessionId ||\n\t\t\t\t\t\t\tchunk.snapshotId !== generation.transcript.snapshotId ||\n\t\t\t\t\t\t\tchunk.index !== duplicateIndex ||\n\t\t\t\t\t\t\t!generation.transcript.readChunk(duplicateIndex).equals(Buffer.from(frame.payload))\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Duplicate snapshot ${generation.transcript.snapshotId} did not match cached bytes`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgeneration.duplicateChunkIndex = duplicateIndex + 1;\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\t\tworker,\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tgeneration.transcript.snapshotId,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"session_snapshot_end\" && activeSessionId) {\n\t\t\tconst snapshotId = frameSnapshotId ?? worker.transcriptCaches.get(activeSessionId)?.snapshotId;\n\t\t\tif (!snapshotId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst generation = this.snapshotGeneration(worker, activeSessionId, snapshotId);\n\t\t\tif (!generation?.incoming) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst transcript = generation.transcript;\n\t\t\ttry {\n\t\t\t\tconst duplicateChunkCount = generation.duplicateChunkIndex;\n\t\t\t\tif (duplicateChunkCount === undefined) {\n\t\t\t\t\ttranscript.markComplete();\n\t\t\t\t\tif (!generation.begin) {\n\t\t\t\t\t\tthrow new Error(`Snapshot ${transcript.snapshotId} has no begin frame`);\n\t\t\t\t\t}\n\t\t\t\t\tgeneration.end = Buffer.from(frame.payload);\n\t\t\t\t} else {\n\t\t\t\t\tconst end = JSON.parse(frame.payload.toString(\"utf8\")) as Extract<\n\t\t\t\t\t\tDaemonOutbound,\n\t\t\t\t\t\t{ type: \"session_snapshot_end\" }\n\t\t\t\t\t>;\n\t\t\t\t\tif (\n\t\t\t\t\t\tend.type !== \"session_snapshot_end\" ||\n\t\t\t\t\t\tend.activeSessionId !== activeSessionId ||\n\t\t\t\t\t\tend.snapshotId !== transcript.snapshotId ||\n\t\t\t\t\t\tend.chunkCount !== duplicateChunkCount ||\n\t\t\t\t\t\tend.chunkCount !== transcript.chunkCount ||\n\t\t\t\t\t\t!generation.end?.equals(frame.payload)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new Error(`Duplicate snapshot ${transcript.snapshotId} ended with different metadata`);\n\t\t\t\t\t}\n\t\t\t\t\tif (!generation.duplicateResult) {\n\t\t\t\t\t\tthrow new Error(`Duplicate snapshot ${transcript.snapshotId} has no result`);\n\t\t\t\t\t}\n\t\t\t\t\tgeneration.result = generation.duplicateResult;\n\t\t\t\t\tif (worker.transcriptCaches.get(activeSessionId) === transcript) {\n\t\t\t\t\t\tworker.snapshotCache.set(activeSessionId, generation.duplicateResult);\n\t\t\t\t\t}\n\t\t\t\t\tthis.settleSnapshotDuplicateValidation(generation);\n\t\t\t\t}\n\t\t\t\tgeneration.incoming = false;\n\t\t\t\tgeneration.duplicateChunkIndex = undefined;\n\t\t\t\tgeneration.duplicateResult = undefined;\n\t\t\t} catch (error) {\n\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\tworker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\ttrue,\n\t\t\t\t\ttranscript.snapshotId,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst published = worker.transcriptCaches.get(activeSessionId) === transcript;\n\t\t\tif (generation.retired) {\n\t\t\t\tthis.deleteSnapshotGeneration(worker, activeSessionId, generation);\n\t\t\t\ttranscript.dispose();\n\t\t\t}\n\t\t\tif (published && (snapshotPurpose === \"replacement\" || snapshotPurpose === \"catchup\")) {\n\t\t\t\tfor (const client of this.clients) {\n\t\t\t\t\tif (!client.attachedActiveSessionIds.has(activeSessionId)) continue;\n\t\t\t\t\tthis.queueCatchup(client, activeSessionId, snapshotPurpose === \"replacement\" ? \"replacement\" : \"resync\");\n\t\t\t\t\tvoid this.catchUpClient(client).catch((error) =>\n\t\t\t\t\t\tthis.log(`Failed to catch up client ${client.id}: ${String(error)}`),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (outboundType === \"session_snapshot_failed\" && activeSessionId) {\n\t\t\ttry {\n\t\t\t\tconst failed = JSON.parse(frame.payload.toString(\"utf8\")) as Extract<\n\t\t\t\t\tDaemonOutbound,\n\t\t\t\t\t{ type: \"session_snapshot_failed\" }\n\t\t\t\t>;\n\t\t\t\tif (\n\t\t\t\t\tfailed.type !== \"session_snapshot_failed\" ||\n\t\t\t\t\tfailed.activeSessionId !== activeSessionId ||\n\t\t\t\t\ttypeof failed.snapshotId !== \"string\" ||\n\t\t\t\t\ttypeof failed.error !== \"string\" ||\n\t\t\t\t\t(frameSnapshotId !== undefined && frameSnapshotId !== failed.snapshotId)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Worker returned an invalid snapshot failure frame\");\n\t\t\t\t}\n\t\t\t\tconst currentGeneration = this.currentSnapshotGeneration(worker, activeSessionId);\n\t\t\t\tconst generation =\n\t\t\t\t\tthis.snapshotGeneration(worker, activeSessionId, failed.snapshotId) ??\n\t\t\t\t\t(currentGeneration?.transcript.snapshotId === failed.snapshotId ? currentGeneration : undefined);\n\t\t\t\tif (!generation) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst published = worker.transcriptCaches.get(activeSessionId) === generation.transcript;\n\t\t\t\tthis.failWorkerSnapshotCache(worker, activeSessionId, new Error(failed.error), false, failed.snapshotId);\n\t\t\t\tif (published && (snapshotPurpose === \"replacement\" || snapshotPurpose === \"catchup\")) {\n\t\t\t\t\tfor (const client of this.clients) {\n\t\t\t\t\t\tif (!client.attachedActiveSessionIds.has(activeSessionId)) continue;\n\t\t\t\t\t\tthis.queueCatchup(\n\t\t\t\t\t\t\tclient,\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tsnapshotPurpose === \"replacement\" ? \"replacement\" : \"resync\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tvoid this.catchUpClient(client).catch((error) =>\n\t\t\t\t\t\t\tthis.log(`Failed to catch up client ${client.id}: ${String(error)}`),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.failWorkerSnapshotCache(\n\t\t\t\t\tworker,\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (\n\t\t\toutboundType === \"daemon_hello\" ||\n\t\t\toutboundType === \"response\" ||\n\t\t\toutboundType === \"session_list_progress\" ||\n\t\t\toutboundType === \"session_list_item\" ||\n\t\t\toutboundType === \"session_attached\" ||\n\t\t\toutboundType === \"session_detached\" ||\n\t\t\t!activeSessionId\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tlet publicPayload = frame.payload;\n\t\tlet decodedOutbound: DaemonOutbound | undefined;\n\t\tif (payloadEncoding === \"assistant-delta\") {\n\t\t\tlet compactValue: unknown;\n\t\t\ttry {\n\t\t\t\tcompactValue = JSON.parse(frame.payload.toString(\"utf8\"));\n\t\t\t} catch {\n\t\t\t\tthis.scheduleCompactCatchup(worker, activeSessionId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!isCompactAssistantDelta(compactValue)) {\n\t\t\t\tthis.scheduleCompactCatchup(worker, activeSessionId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst reconstructed = this.streamReconstructor.reconstruct(compactValue);\n\t\t\tif (!reconstructed) {\n\t\t\t\tthis.scheduleCompactCatchup(worker, activeSessionId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpublicPayload = Buffer.from(serializeJsonLine(reconstructed));\n\t\t} else if (\n\t\t\tsessionEventType === \"message_start\" ||\n\t\t\tsessionEventType === \"message_end\" ||\n\t\t\toutboundType === \"session_replaced\" ||\n\t\t\toutboundType === \"session_resynced\" ||\n\t\t\toutboundType === \"session_closed\"\n\t\t) {\n\t\t\ttry {\n\t\t\t\tdecodedOutbound = JSON.parse(frame.payload.toString(\"utf8\")) as DaemonOutbound;\n\t\t\t\tthis.streamReconstructor.observe(decodedOutbound);\n\t\t\t} catch {\n\t\t\t\t// A malformed worker event is still isolated to this worker connection.\n\t\t\t}\n\t\t}\n\t\tconst replacementSnapshotFollows =\n\t\t\tdecodedOutbound?.type === \"session_replaced\" && decodedOutbound.snapshotFollows === true;\n\t\tthis.invalidateWorkerSnapshot(\n\t\t\tworker,\n\t\t\tactiveSessionId,\n\t\t\toutboundType === \"session_replaced\" ||\n\t\t\t\toutboundType === \"session_closed\" ||\n\t\t\t\tisFinalizedTranscriptEvent(sessionEventType),\n\t\t);\n\t\tfor (const client of this.clients) {\n\t\t\tif (!client.attachedActiveSessionIds.has(activeSessionId)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (replacementSnapshotFollows && !client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (outboundType === \"extension_ui_request\" && !client.supportsExtensionUi) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (client.snapshotActiveSessionIds?.has(activeSessionId)) {\n\t\t\t\tthis.queueCatchup(client, activeSessionId, outboundType === \"session_replaced\" ? \"replacement\" : \"resync\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (client.backpressured === true) {\n\t\t\t\tthis.queueCatchup(client, activeSessionId, outboundType === \"session_replaced\" ? \"replacement\" : \"resync\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.writeSerialized(client, publicPayload);\n\t\t}\n\t\tif (\n\t\t\tdecodedOutbound?.type === \"session_closed\" &&\n\t\t\tdecodedOutbound.reason === \"shutdown\" &&\n\t\t\tactiveSessionId === worker.descriptor.rootActiveSessionId &&\n\t\t\t!this.shuttingDown\n\t\t) {\n\t\t\tworker.intentionalStop = true;\n\t\t\t// An exact stop owns its registration and descriptor cleanup until its\n\t\t\t// tuple assertions complete. A synchronous root shutdown event can arrive\n\t\t\t// before its request resolves, so leave both intact while it is active.\n\t\t\tif ((this.workerStopCounts?.get(worker) ?? 0) === 0) {\n\t\t\t\tthis.invalidateWorkerSessionInputPauses(worker, \"Session worker stopped while input was paused\");\n\t\t\t\tthis.workers.delete(worker.descriptor.workerId);\n\t\t\t\tthis.flipWorkerRosterEntriesInactive(worker);\n\t\t\t\tthis.deleteWorkerDescriptor(worker);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate invalidateWorkerSnapshot(worker: ResidentWorker, activeSessionId: string, transcriptChanged = true): void {\n\t\tworker.snapshotCache.delete(activeSessionId);\n\t\tif (!transcriptChanged) {\n\t\t\treturn;\n\t\t}\n\t\tworker.snapshotLoads.delete(`${activeSessionId}:chunked`);\n\t\tworker.snapshotLoads.delete(`${activeSessionId}:full`);\n\t\tconst transcript = worker.transcriptCaches.get(activeSessionId);\n\t\tif (transcript) {\n\t\t\tthis.retireWorkerSnapshotCache(worker, activeSessionId, transcript);\n\t\t}\n\t}\n\n\tprivate scheduleCompactCatchup(worker: ResidentWorker, activeSessionId: string): void {\n\t\tif (this.compactCatchupInProgress.has(activeSessionId)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.compactCatchupInProgress.add(activeSessionId);\n\t\tthis.invalidateWorkerSnapshot(worker, activeSessionId);\n\t\tconst clients = [...this.clients].filter((client) => client.attachedActiveSessionIds.has(activeSessionId));\n\t\tfor (const client of clients) {\n\t\t\tthis.queueCatchup(client, activeSessionId);\n\t\t}\n\t\tvoid Promise.all(clients.map((client) => this.catchUpClient(client)))\n\t\t\t.catch((error) => this.log(`Failed compact catch-up for ${activeSessionId}: ${String(error)}`))\n\t\t\t.finally(() => {\n\t\t\t\tthis.compactCatchupInProgress.delete(activeSessionId);\n\t\t\t});\n\t}\n\n\tprivate queueCatchup(\n\t\tclient: DaemonSocketClient,\n\t\tactiveSessionId: string,\n\t\tpurpose: \"replacement\" | \"resync\" = \"resync\",\n\t): void {\n\t\tif (!client.catchupActiveSessionIds) {\n\t\t\tclient.catchupActiveSessionIds = new Set();\n\t\t}\n\t\tclient.catchupActiveSessionIds.add(activeSessionId);\n\t\tclient.catchupPurposes ??= new Map();\n\t\tif (purpose === \"replacement\" || !client.catchupPurposes.has(activeSessionId)) {\n\t\t\tclient.catchupPurposes.set(activeSessionId, purpose);\n\t\t}\n\t}\n\n\tprivate catchUpClient(client: DaemonSocketClient): Promise<void> {\n\t\tif (client.catchupPromise) {\n\t\t\treturn client.catchupPromise;\n\t\t}\n\t\tif (client.snapshotStreaming || client.backpressured) {\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tconst catchup = this.drainClientCatchupQueue(client).finally(() => {\n\t\t\tif (client.catchupPromise === catchup) {\n\t\t\t\tclient.catchupPromise = undefined;\n\t\t\t}\n\t\t});\n\t\tclient.catchupPromise = catchup;\n\t\treturn catchup;\n\t}\n\n\tprivate async drainClientCatchupQueue(client: DaemonSocketClient): Promise<void> {\n\t\twhile (\n\t\t\t!client.socket.destroyed &&\n\t\t\t!client.snapshotStreaming &&\n\t\t\t!client.backpressured &&\n\t\t\tclient.catchupActiveSessionIds?.size\n\t\t) {\n\t\t\tawait this.drainClientCatchups(client);\n\t\t}\n\t}\n\n\tprivate async drainClientCatchups(client: DaemonSocketClient): Promise<void> {\n\t\tif (client.socket.destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst pending = [...(client.catchupActiveSessionIds ?? [])].map((activeSessionId) => ({\n\t\t\tactiveSessionId,\n\t\t\tpurpose: client.catchupPurposes?.get(activeSessionId) ?? (\"resync\" as const),\n\t\t}));\n\t\tclient.catchupActiveSessionIds?.clear();\n\t\tclient.catchupPurposes?.clear();\n\t\tfor (let index = 0; index < pending.length; index++) {\n\t\t\tconst { activeSessionId, purpose } = pending[index]!;\n\t\t\tlet releaseTranscript: (() => void) | undefined;\n\t\t\ttry {\n\t\t\t\tconst attached = await this.attachClient(client, {\n\t\t\t\t\ttype: \"attach\",\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tcapabilities: [...client.capabilities],\n\t\t\t\t\tsupportsExtensionUi: client.supportsExtensionUi,\n\t\t\t\t});\n\t\t\t\treleaseTranscript = attached.releaseTranscript;\n\t\t\t\tif (client.capabilities.has(\"chunked_snapshot\")) {\n\t\t\t\t\tconst transcript = attached.transcript;\n\t\t\t\t\tif (!transcript) {\n\t\t\t\t\t\tthrow new Error(\"Session worker did not provide a snapshot transcript\");\n\t\t\t\t\t}\n\t\t\t\t\tif (purpose === \"replacement\") {\n\t\t\t\t\t\tthis.write(client, {\n\t\t\t\t\t\t\ttype: \"session_replaced\",\n\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\tstate: attached.result.snapshot.state,\n\t\t\t\t\t\t\tmessages: [],\n\t\t\t\t\t\t\tsnapshotFollows: true,\n\t\t\t\t\t\t\tmeta: createDaemonEventMeta(\n\t\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\t\tattached.result.lastEventSequence,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\tattached.result.lastEventCursor?.generation,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tawait this.streamSnapshot(\n\t\t\t\t\t\tclient,\n\t\t\t\t\t\tattached.worker,\n\t\t\t\t\t\tthis.createStreamedAttachResult(attached.result, transcript),\n\t\t\t\t\t\ttranscript,\n\t\t\t\t\t\tpurpose,\n\t\t\t\t\t\treleaseTranscript,\n\t\t\t\t\t);\n\t\t\t\t\treleaseTranscript = undefined;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst meta = createDaemonEventMeta(\n\t\t\t\t\tactiveSessionId,\n\t\t\t\t\tattached.result.lastEventSequence,\n\t\t\t\t\tundefined,\n\t\t\t\t\tattached.result.lastEventCursor?.generation,\n\t\t\t\t);\n\t\t\t\tconst catchup: DaemonOutbound =\n\t\t\t\t\tpurpose === \"replacement\"\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\ttype: \"session_replaced\",\n\t\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\t\tstate: attached.result.snapshot.state,\n\t\t\t\t\t\t\t\tmessages: attached.result.snapshot.messages,\n\t\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\ttype: \"session_resynced\",\n\t\t\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\t\t\tsnapshot: attached.result.snapshot,\n\t\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\t};\n\t\t\t\tif (!this.write(client, catchup)) {\n\t\t\t\t\tfor (const remaining of pending.slice(index + 1)) {\n\t\t\t\t\t\tthis.queueCatchup(client, remaining.activeSessionId, remaining.purpose);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\treleaseTranscript?.();\n\t\t\t\tthis.log(`Failed to catch up client ${client.id} for ${activeSessionId}: ${String(error)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async prepareUpdateRestart(): Promise<DaemonUpdateRestartManifest> {\n\t\tif (this.updateRestartPhase !== undefined) throw new Error(\"Daemon is already preparing an update restart\");\n\t\tthis.updateRestartPhase = \"draining\";\n\t\ttry {\n\t\t\tconst deadline = Date.now() + UPDATE_RESTART_PREPARE_DEADLINE_MS;\n\t\t\tconst abort = AbortSignal.timeout(Math.min(UPDATE_RESTART_MUTATION_DRAIN_TIMEOUT_MS, deadline - Date.now()));\n\t\t\tawait this.mutationDrain.waitForDrain(1, abort, \"Timed out draining daemon mutations for update restart\");\n\t\t\tthis.updateRestartPhase = \"fencing\";\n\t\t\tawait this.mutationDrain.waitForDrain(1, abort, \"Timed out draining daemon mutations for update restart\");\n\t\t\tconst manifest = await this.prepareUpdateRestartFenced(deadline);\n\t\t\tthis.updateRestartPhase = \"prepared\";\n\t\t\treturn manifest;\n\t\t} catch (error) {\n\t\t\tthis.updateRestartPhase = undefined;\n\t\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async prepareUpdateRestartFenced(deadline: number): Promise<DaemonUpdateRestartManifest> {\n\t\tconst residents = [...this.workers.values()];\n\t\tconst unavailable = residents.find(\n\t\t\t(worker) =>\n\t\t\t\tthis.isWorkerStopping(worker) || worker.descriptor.lifecycle !== \"ready\" || worker.client === undefined,\n\t\t);\n\t\tif (unavailable) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot prepare update restart while resident worker ${unavailable.descriptor.workerId} is ${this.effectiveWorkerState(unavailable)}${unavailable.client ? \"\" : \" and disconnected\"}`,\n\t\t\t);\n\t\t}\n\t\tconst workers = residents as Array<ResidentWorker & { client: DaemonWorkerClient }>;\n\t\tconst acknowledged: ResidentWorker[] = [];\n\t\tconst preparationResults = await Promise.allSettled(\n\t\t\tworkers.map(async (worker) => {\n\t\t\t\tconst client = worker.client;\n\t\t\t\tconst response = await client.requestWorker(\n\t\t\t\t\t{ type: \"worker_prepare_update\" },\n\t\t\t\t\tMath.max(1, Math.min(UPDATE_RESTART_WORKER_REQUEST_TIMEOUT_MS, deadline - Date.now())),\n\t\t\t\t);\n\t\t\t\tif (!response.success) throw new Error(response.error);\n\t\t\t\tworker.updateRestartPrepareClient = client;\n\t\t\t\tacknowledged.push(worker);\n\t\t\t\tif (!response.data || typeof response.data !== \"object\") {\n\t\t\t\t\tthrow new Error(\"Worker returned an invalid update manifest\");\n\t\t\t\t}\n\t\t\t\tif (worker.client !== client || worker.descriptor.lifecycle !== \"ready\") {\n\t\t\t\t\tthrow new Error(`Worker ${worker.descriptor.workerId} disconnected during update preparation`);\n\t\t\t\t}\n\t\t\t\tconst manifest = response.data as DaemonUpdateRestartManifest;\n\t\t\t\tif (manifest.formatVersion !== DAEMON_UPDATE_RESTART_FORMAT_VERSION) {\n\t\t\t\t\tthrow new Error(`Worker returned unsupported update manifest version ${manifest.formatVersion}`);\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\t!manifest.sessions.some(\n\t\t\t\t\t\t(session) => session.activeSessionId === worker.descriptor.rootActiveSessionId,\n\t\t\t\t\t) &&\n\t\t\t\t\t!manifest.discardedActiveSessionIds?.includes(worker.descriptor.rootActiveSessionId)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Worker ${worker.descriptor.workerId} omitted its root disposition from the update manifest`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn { worker, manifest };\n\t\t\t}),\n\t\t);\n\t\tconst cancelAcknowledged = async () => {\n\t\t\tawait Promise.all(\n\t\t\t\tacknowledged.map(async (worker) => {\n\t\t\t\t\tconst prepareClient = worker.updateRestartPrepareClient;\n\t\t\t\t\tworker.updateRestartPrepareClient = undefined;\n\t\t\t\t\tif (!prepareClient) return;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await prepareClient.requestWorker({ type: \"worker_cancel_update\" }, 5000);\n\t\t\t\t\t\tif (!response.success) throw new Error(response.error);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.log(\n\t\t\t\t\t\t\t`Could not cancel prepared worker ${worker.descriptor.workerId}; reconnecting it: ${String(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tprepareClient.close();\n\t\t\t\t\t\tif (worker.client && worker.client !== prepareClient) worker.client.close();\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t};\n\t\tconst preparationFailure = preparationResults.find(\n\t\t\t(result): result is PromiseRejectedResult => result.status === \"rejected\",\n\t\t);\n\t\tif (preparationFailure) {\n\t\t\tawait cancelAcknowledged();\n\t\t\tthrow preparationFailure.reason;\n\t\t}\n\t\tconst prepared = preparationResults.flatMap((result) =>\n\t\t\tresult.status === \"fulfilled\" ? [result.value.worker] : [],\n\t\t);\n\t\tconst responses = preparationResults.flatMap((result) =>\n\t\t\tresult.status === \"fulfilled\" ? [result.value.manifest] : [],\n\t\t);\n\t\tconst discardedActiveSessionIds = responses.flatMap((manifest) => manifest.discardedActiveSessionIds ?? []);\n\t\tconst manifest: DaemonUpdateRestartManifest = {\n\t\t\tformatVersion: DAEMON_UPDATE_RESTART_FORMAT_VERSION,\n\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\tsessions: responses.flatMap((manifest) => manifest.sessions),\n\t\t\t...(discardedActiveSessionIds.length > 0 ? { discardedActiveSessionIds } : {}),\n\t\t};\n\t\t// A worker that disconnected after preparing cancelled its checkpoint with\n\t\t// the old client; a recovered replacement may have admitted inputs past the\n\t\t// captured manifest. Abort before the manifest is persisted so the caller's\n\t\t// fallback cannot restore from the stale checkpoint.\n\t\tconst staleWorker = prepared.find((worker) => worker.client !== worker.updateRestartPrepareClient);\n\t\tif (staleWorker) {\n\t\t\tawait cancelAcknowledged();\n\t\t\tthrow new Error(\n\t\t\t\t`Worker ${staleWorker.descriptor.workerId} reconnected during update preparation; its checkpoint is stale`,\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tthis.validateAndPersistUpdateManifest(manifest);\n\t\t} catch (error) {\n\t\t\tawait cancelAcknowledged();\n\t\t\tthrow error;\n\t\t}\n\t\t// Commit through the connection that owns the prepared transaction; a client\n\t\t// swapped in after the check above must fail the commit rather than reach a\n\t\t// worker that no longer holds the checkpoint.\n\t\tconst commitClients = new Map(prepared.map((worker) => [worker, worker.updateRestartPrepareClient]));\n\t\tfor (const worker of prepared) worker.updateRestartPrepareClient = undefined;\n\t\tconst commitResults = await Promise.allSettled(\n\t\t\tprepared.map(async (worker) => {\n\t\t\t\tconst client = commitClients.get(worker);\n\t\t\t\tif (!client) throw new Error(`Worker ${worker.descriptor.workerId} disconnected before update commit`);\n\t\t\t\tconst response = await client.requestWorker(\n\t\t\t\t\t{ type: \"worker_commit_update\" },\n\t\t\t\t\tUPDATE_RESTART_WORKER_REQUEST_TIMEOUT_MS,\n\t\t\t\t);\n\t\t\t\tif (!response.success) throw new Error(response.error);\n\t\t\t}),\n\t\t);\n\t\tconst commitFailure = commitResults.find(\n\t\t\t(result): result is PromiseRejectedResult => result.status === \"rejected\",\n\t\t);\n\t\tif (commitFailure) {\n\t\t\tthis.log(`Update restart commit response failed; forcing restart completion: ${String(commitFailure.reason)}`);\n\t\t\tawait Promise.allSettled(prepared.map((worker) => this.stopWorker(worker, false, true)));\n\t\t\treturn manifest;\n\t\t}\n\t\tconst stopResults = await Promise.allSettled(prepared.map((worker) => this.stopWorker(worker, false)));\n\t\tif (stopResults.some((result) => result.status === \"rejected\")) {\n\t\t\tthis.log(\"A committed update worker did not stop gracefully; forcing restart completion\");\n\t\t\tawait Promise.allSettled(prepared.map((worker) => this.stopWorker(worker, false, true)));\n\t\t}\n\t\treturn manifest;\n\t}\n\n\tprivate validateAndPersistUpdateManifest(manifest: DaemonUpdateRestartManifest): void {\n\t\tif (manifest.formatVersion !== DAEMON_UPDATE_RESTART_FORMAT_VERSION) {\n\t\t\tthrow new Error(`Unsupported update manifest version ${manifest.formatVersion}`);\n\t\t}\n\t\tconst activeSessionIds = new Set<string>();\n\t\tconst sessionFiles = new Set<string>();\n\t\tfor (const discardedActiveSessionId of manifest.discardedActiveSessionIds ?? []) {\n\t\t\tif (!discardedActiveSessionId || activeSessionIds.has(discardedActiveSessionId)) {\n\t\t\t\tthrow new Error(\"Update manifest contains an invalid discarded session disposition\");\n\t\t\t}\n\t\t\tactiveSessionIds.add(discardedActiveSessionId);\n\t\t}\n\t\tfor (const session of manifest.sessions) {\n\t\t\tif (!session.activeSessionId || !session.sessionFile) {\n\t\t\t\tthrow new Error(\"Update manifest contains an incomplete session checkpoint\");\n\t\t\t}\n\t\t\tif (activeSessionIds.has(session.activeSessionId)) {\n\t\t\t\tthrow new Error(`Update manifest contains duplicate active session ${session.activeSessionId}`);\n\t\t\t}\n\t\t\tconst sessionFile = canonicalSessionPath(session.sessionFile);\n\t\t\tif (sessionFiles.has(sessionFile)) {\n\t\t\t\tthrow new Error(`Update manifest contains duplicate session file ${sessionFile}`);\n\t\t\t}\n\t\t\tactiveSessionIds.add(session.activeSessionId);\n\t\t\tsessionFiles.add(sessionFile);\n\t\t}\n\t\tconst agentDir = this.defaultSessionConfig.agentDir;\n\t\tif (!agentDir) {\n\t\t\tthrow new Error(\"Daemon supervisor config is missing agentDir\");\n\t\t}\n\t\tconst path = getDaemonUpdateRestartManifestPath(this.socketPath, agentDir);\n\t\tmkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n\t\tconst tempPath = `${path}.${process.pid}.tmp`;\n\t\twriteFileSync(tempPath, `${JSON.stringify(manifest)}\\n`, { mode: 0o600 });\n\t\tchmodSync(tempPath, 0o600);\n\t\tconst validated = JSON.parse(readFileSync(tempPath, \"utf8\")) as DaemonUpdateRestartManifest;\n\t\tif (!Array.isArray(validated.sessions) || validated.sessions.length !== manifest.sessions.length) {\n\t\t\tthrow new Error(\"Could not validate aggregate update manifest\");\n\t\t}\n\t\trenameSync(tempPath, path);\n\t}\n\n\t/**\n\t * Verdict on whether a pid is still the process we launched. Callers must\n\t * be conservative in both directions: signal a pid only on \"current\"\n\t * (never SIGKILL a recycled pid), and clean up a registration only on\n\t * \"gone\"/\"replaced\" (never orphan a live worker because a transient\n\t * identity lookup failed).\n\t */\n\tprivate processIdentity(\n\t\tpid: number,\n\t\tprocessStartId: string | undefined,\n\t): \"current\" | \"replaced\" | \"gone\" | \"unknown\" {\n\t\tif (!isProcessAlive(pid)) {\n\t\t\treturn \"gone\";\n\t\t}\n\t\tif (processStartId === undefined) {\n\t\t\treturn \"unknown\";\n\t\t}\n\t\tconst observed = getProcessStartId(pid);\n\t\tif (observed === undefined) {\n\t\t\treturn \"unknown\";\n\t\t}\n\t\treturn observed === processStartId ? \"current\" : \"replaced\";\n\t}\n\n\t/**\n\t * Keep an exact stop's registration and descriptor authoritative while any\n\t * part of its cleanup is in flight. Root kills acquire this before forwarding\n\t * because a synchronous shutdown event may arrive before the worker replies.\n\t */\n\tprivate acquireWorkerStopOwnership(worker: ResidentWorker): () => void {\n\t\tif (!this.workerStopCounts) this.workerStopCounts = new Map();\n\t\tconst stopCounts = this.workerStopCounts;\n\t\tstopCounts.set(worker, (stopCounts.get(worker) ?? 0) + 1);\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\tconst remaining = (stopCounts.get(worker) ?? 1) - 1;\n\t\t\tif (remaining === 0) stopCounts.delete(worker);\n\t\t\telse stopCounts.set(worker, remaining);\n\t\t};\n\t}\n\n\tprivate async stopWorker(\n\t\tworker: ResidentWorker,\n\t\tremoveDescriptor: boolean,\n\t\tforce = false,\n\t\tarchiveSession = false,\n\t\trecoveryCleanup = false,\n\t\tdirectChild?: { child: ChildProcess; closed: Promise<void> },\n\t): Promise<void> {\n\t\tif (worker.compatibilityError) throw worker.compatibilityError;\n\t\tconst releaseStopOwnership = this.acquireWorkerStopOwnership(worker);\n\t\ttry {\n\t\t\tawait this.stopWorkerUntracked(worker, removeDescriptor, force, archiveSession, recoveryCleanup, directChild);\n\t\t} finally {\n\t\t\treleaseStopOwnership();\n\t\t}\n\t}\n\n\tprivate async stopWorkerUntracked(\n\t\tworker: ResidentWorker,\n\t\tremoveDescriptor: boolean,\n\t\tforce = false,\n\t\tarchiveSession = false,\n\t\trecoveryCleanup = false,\n\t\tdirectChild?: { child: ChildProcess; closed: Promise<void> },\n\t): Promise<void> {\n\t\tif (worker.ownerCleanupTimer) {\n\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t}\n\t\tif (!recoveryCleanup) {\n\t\t\tworker.stopRevision++;\n\t\t}\n\t\t// A retry can rescind this stop and relaunch the worker while we await\n\t\t// below. Bind every liveness check and signal to the process this stop\n\t\t// entered with, and abort cleanup once the stop no longer applies: the\n\t\t// pid changed (relaunched) or a removeDescriptor stop lost its tombstone\n\t\t// (rescinded, even before the successor pid lands).\n\t\tconst entryPid = worker.descriptor.pid;\n\t\tconst entryStartId = worker.descriptor.processStartId;\n\t\tconst assertStopStillApplies = () => {\n\t\t\tif (worker.compatibilityError) throw worker.compatibilityError;\n\t\t\tif (directChild) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tworker.descriptor.pid !== entryPid ||\n\t\t\t\t(removeDescriptor && worker.descriptor.stopRequestedAt === undefined)\n\t\t\t) {\n\t\t\t\tthrow new Error(`Session worker ${worker.descriptor.workerId} was relaunched during stop`);\n\t\t\t}\n\t\t};\n\t\ttry {\n\t\t\tif (removeDescriptor) {\n\t\t\t\tthis.persistWorkerStopTombstone(worker, archiveSession);\n\t\t\t} else {\n\t\t\t\tworker.intentionalStop = true;\n\t\t\t\tworker.descriptor.lifecycle = \"recovering\";\n\t\t\t\tthis.persistWorker(worker);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (!directChild) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tthis.reportCleanupFailure(`worker rollback state ${worker.descriptor.workerId}`, error);\n\t\t}\n\t\tconst transferError = new Error(\"Session worker stopped during snapshot transfer\");\n\t\tconst generationTranscripts = new Set<SnapshotTranscriptCache>();\n\t\tfor (const [activeSessionId, generations] of [...(worker.snapshotGenerations ?? new Map())]) {\n\t\t\tfor (const generation of [...generations.values()]) {\n\t\t\t\tgenerationTranscripts.add(generation.transcript);\n\t\t\t\tif (generation.incoming || !generation.transcript.complete || generation.validation) {\n\t\t\t\t\tthis.failSnapshotGeneration(worker, activeSessionId, generation, transferError);\n\t\t\t\t} else {\n\t\t\t\t\tgeneration.transcript.dispose();\n\t\t\t\t\tthis.deleteSnapshotGeneration(worker, activeSessionId, generation);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const transcript of worker.transcriptCaches.values()) {\n\t\t\tif (!generationTranscripts.has(transcript) && !transcript.complete) {\n\t\t\t\ttranscript.markFailed(transferError);\n\t\t\t}\n\t\t\ttranscript.dispose();\n\t\t}\n\t\tworker.transcriptCaches.clear();\n\t\tworker.snapshotCache.clear();\n\t\tworker.snapshotGenerations?.clear();\n\t\tif (worker.client) {\n\t\t\tif (archiveSession) {\n\t\t\t\tawait worker.client\n\t\t\t\t\t.requestWorker({ type: \"worker_archive_and_shutdown\" }, force ? 1000 : 5000)\n\t\t\t\t\t.catch(() => undefined);\n\t\t\t} else {\n\t\t\t\tawait worker.client.request({ type: \"shutdown\" }, force ? 1000 : 5000).catch(() => undefined);\n\t\t\t}\n\t\t\tassertStopStillApplies();\n\t\t\tworker.client.close();\n\t\t\tworker.client = undefined;\n\t\t} else if (directChild) {\n\t\t\tdirectChild.child.kill(\"SIGTERM\");\n\t\t} else if (this.processIdentity(entryPid, entryStartId) === \"current\") {\n\t\t\tsignalProcessGroupOrProcess(entryPid, \"SIGTERM\");\n\t\t}\n\t\t// Identity-aware in both directions: a replaced pid counts as gone (never\n\t\t// signal a recycled pid) while an unknown identity counts as alive (never\n\t\t// clean up a possibly-live worker on a transient lookup failure). kill(0)\n\t\t// runs on every poll; the expensive identity check is throttled.\n\t\tlet identityVerdict: \"current\" | \"replaced\" | \"gone\" | \"unknown\" = \"current\";\n\t\tlet identityCheckedAt = 0;\n\t\tconst isWorkerProcessAlive = () => {\n\t\t\tif (directChild) {\n\t\t\t\treturn directChild.child.exitCode === null && directChild.child.signalCode === null;\n\t\t\t}\n\t\t\tif (!processIdExists(entryPid)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst now = Date.now();\n\t\t\tif (now - identityCheckedAt >= LIVENESS_IDENTITY_RECHECK_MS) {\n\t\t\t\tidentityCheckedAt = now;\n\t\t\t\tidentityVerdict = this.processIdentity(entryPid, entryStartId);\n\t\t\t}\n\t\t\treturn identityVerdict !== \"replaced\" && identityVerdict !== \"gone\";\n\t\t};\n\t\tconst gracefulDeadline = Date.now() + (force ? 500 : 2000);\n\t\twhile (isWorkerProcessAlive() && Date.now() < gracefulDeadline) {\n\t\t\tawait delay(25);\n\t\t}\n\t\tlet sigkillSent = false;\n\t\tif (force && isWorkerProcessAlive()) {\n\t\t\tassertStopStillApplies();\n\t\t\tif (directChild) {\n\t\t\t\tsigkillSent = directChild.child.kill(\"SIGKILL\");\n\t\t\t} else if (this.processIdentity(entryPid, entryStartId) === \"current\") {\n\t\t\t\t// Fresh, unthrottled check: the cached verdict may be up to 500ms\n\t\t\t\t// old, long enough for the pid to be recycled.\n\t\t\t\tsignalProcessGroupOrProcess(entryPid, \"SIGKILL\");\n\t\t\t\tsigkillSent = true;\n\t\t\t}\n\t\t\tconst forceDeadline = Date.now() + 1000;\n\t\t\twhile (isWorkerProcessAlive() && Date.now() < forceDeadline) {\n\t\t\t\tawait delay(25);\n\t\t\t}\n\t\t}\n\t\tif (isWorkerProcessAlive()) {\n\t\t\tworker.intentionalStop = worker.descriptor.stopRequestedAt !== undefined;\n\t\t\tif (removeDescriptor) {\n\t\t\t\tthis.scheduleWorkerStopFinalization(worker);\n\t\t\t}\n\t\t\tthrow new WorkerStopTimeoutError(\n\t\t\t\t`Session worker ${worker.descriptor.workerId} did not stop${sigkillSent ? \" after SIGKILL\" : \"\"}`,\n\t\t\t);\n\t\t}\n\t\tif (directChild) {\n\t\t\tawait directChild.closed;\n\t\t}\n\t\tassertStopStillApplies();\n\t\tif (removeDescriptor && worker.descriptor.archiveOnStop) {\n\t\t\tif (force) {\n\t\t\t\tthis.reclaimStoppedWorkerCronLock(worker);\n\t\t\t}\n\t\t\tawait this.finalizeArchivedWorkerStop(worker);\n\t\t\tassertStopStillApplies();\n\t\t}\n\t\tthis.invalidateWorkerSessionInputPauses(worker, \"Session worker stopped while input was paused\");\n\t\t// Client-owned schedules die with the registration, like their roster rows. Cancel\n\t\t// before the worker leaves the map, so no recompute sees the tree uncovered mid-stop.\n\t\tlet ephemeralCancelSettled = true;\n\t\tif (removeDescriptor && worker.descriptor.ownerClientId !== undefined) {\n\t\t\tephemeralCancelSettled = await this.cancelEphemeralWorkerScheduledJobs(worker);\n\t\t}\n\t\tthis.releaseWorkerRlmCapacity(worker);\n\t\tthis.workers.delete(worker.descriptor.workerId);\n\t\tthis.flipWorkerRosterEntriesInactive(worker);\n\t\t// A failed cancel keeps the stop tombstone as the durable intent; the enumeration retry or the next boot finishes it.\n\t\tif (removeDescriptor && ephemeralCancelSettled) {\n\t\t\tthis.deleteWorkerDescriptor(worker);\n\t\t}\n\t\tif (!this.shuttingDown) {\n\t\t\tthis.broadcastHeartbeatsChanged();\n\t\t}\n\t}\n\n\t/**\n\t * A stop that timed out leaves a tombstoned registration behind. Keep\n\t * escalating in the background until the process is gone, then finish the\n\t * interrupted cleanup instead of leaving a dead worker registered forever.\n\t */\n\tprivate scheduleWorkerStopFinalization(worker: ResidentWorker): void {\n\t\tif (worker.stopFinalization) {\n\t\t\treturn;\n\t\t}\n\t\tworker.stopFinalization = this.finalizeTimedOutWorkerStop(worker).finally(() => {\n\t\t\tworker.stopFinalization = undefined;\n\t\t});\n\t}\n\n\tprivate async finalizeTimedOutWorkerStop(worker: ResidentWorker): Promise<void> {\n\t\t// Bind to the exact process generation being stopped: a retry can rescind\n\t\t// the stop and relaunch with a new pid, and the OS can recycle the old\n\t\t// pid. The finalizer must never follow either successor.\n\t\tconst pid = worker.descriptor.pid;\n\t\tconst processStartId = worker.descriptor.processStartId;\n\t\tconst stopRevision = worker.stopRevision;\n\t\tconst isStopGenerationCurrent = () =>\n\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\tworker.stopRevision === stopRevision &&\n\t\t\tworker.descriptor.stopRequestedAt !== undefined &&\n\t\t\tworker.descriptor.pid === pid;\n\t\t// A replaced pid counts as gone (never SIGKILL a recycled pid); an\n\t\t// unobservable identity counts as alive (never clean up a possibly-live\n\t\t// worker). kill(0) probes every poll; ps-backed checks are throttled.\n\t\tlet stoppedVerdict = true;\n\t\tlet stoppedCanSignal = processStartId !== undefined;\n\t\tlet stoppedCheckedAt = 0;\n\t\tconst isStoppedProcessAlive = () => {\n\t\t\tif (!processIdExists(pid)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tconst now = Date.now();\n\t\t\tif (now - stoppedCheckedAt < LIVENESS_IDENTITY_RECHECK_MS) {\n\t\t\t\treturn stoppedVerdict;\n\t\t\t}\n\t\t\tstoppedCheckedAt = now;\n\t\t\tif (!isProcessAlive(pid)) {\n\t\t\t\tstoppedVerdict = false;\n\t\t\t} else if (processStartId === undefined) {\n\t\t\t\tstoppedVerdict = true;\n\t\t\t\t// Without an identity captured while the original worker was known\n\t\t\t\t// alive, this pid may now belong to an unrelated process. Keep\n\t\t\t\t// waiting for it to disappear, but never escalate by pid alone.\n\t\t\t\tstoppedCanSignal = false;\n\t\t\t} else {\n\t\t\t\tconst observed = getProcessStartId(pid);\n\t\t\t\tstoppedVerdict = observed !== processStartId ? observed === undefined : true;\n\t\t\t\tstoppedCanSignal = observed === processStartId;\n\t\t\t}\n\t\t\treturn stoppedVerdict;\n\t\t};\n\t\tconst sigkillDeadline = Date.now() + STOP_FINALIZATION_SIGKILL_GRACE_MS;\n\t\tlet killed = false;\n\t\twhile (!this.shuttingDown) {\n\t\t\tif (!isStopGenerationCurrent()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!isStoppedProcessAlive()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!killed && stoppedCanSignal && Date.now() >= sigkillDeadline) {\n\t\t\t\t// Fresh, unthrottled identity check right before signalling: the\n\t\t\t\t// cached verdict may be up to 500ms old, long enough for the pid\n\t\t\t\t// to be recycled by an unrelated process. A transiently\n\t\t\t\t// unobservable identity skips this attempt but keeps escalation\n\t\t\t\t// armed so a wedged worker is still killed on a later pass.\n\t\t\t\tconst observedNow = processStartId === undefined ? undefined : getProcessStartId(pid);\n\t\t\t\tif (processStartId === undefined || observedNow === processStartId) {\n\t\t\t\t\tsignalProcessGroupOrProcess(pid, \"SIGKILL\");\n\t\t\t\t\tkilled = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tawait unrefDelay(STOP_FINALIZATION_RECHECK_MS);\n\t\t}\n\t\t// Retry transient cleanup failures (for example catalog archival) so a\n\t\t// dead worker's registration is never stranded permanently. Each attempt\n\t\t// bumps the worker's stopRevision, so rescission is detected through the\n\t\t// registration and tombstone instead of the waiting-phase snapshot.\n\t\tconst isCleanupStillWanted = () =>\n\t\t\tthis.workers.get(worker.descriptor.workerId) === worker &&\n\t\t\tworker.descriptor.stopRequestedAt !== undefined &&\n\t\t\tworker.descriptor.pid === pid;\n\t\twhile (!this.shuttingDown && isCleanupStillWanted()) {\n\t\t\ttry {\n\t\t\t\tawait this.stopWorker(worker, true, true, worker.descriptor.archiveOnStop === true);\n\t\t\t\tthis.log(`Finalized timed-out stop for worker ${worker.descriptor.workerId}`);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tthis.reportCleanupFailure(`timed-out worker stop ${worker.descriptor.workerId}`, error);\n\t\t\t\tawait unrefDelay(STOP_FINALIZATION_RETRY_MS);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async finalizeArchivedWorkerStop(worker: ResidentWorker): Promise<void> {\n\t\tconst context = this.workerSessionArtifactContext(worker);\n\t\tif (!context) {\n\t\t\treturn;\n\t\t}\n\t\tif (worker.descriptor.rootSessionId) {\n\t\t\tconst cronStore = AgentCronJobStore.forSessionArtifacts();\n\t\t\tcronStore.registerSessionArtifact(worker.descriptor.rootSessionId, context.artifactDir);\n\t\t\tcronStore.cancelJobsForSession({\n\t\t\t\tsessionId: worker.descriptor.rootSessionId,\n\t\t\t\tsessionFile: context.sessionFile,\n\t\t\t});\n\t\t\tawait this.catalog.archive(context.sessionFile, worker.descriptor.rootSessionId);\n\t\t}\n\t}\n\n\tprivate async cancelScheduledJobsForSessionTree(\n\t\trootSessionId: string,\n\t\trootSessionFile: string,\n\t\tstillWanted?: () => boolean,\n\t\texclude?: ResidentWorker,\n\t): Promise<void> {\n\t\tconst store = AgentCronJobStore.forSessionArtifacts();\n\t\tconst sessions = [{ sessionId: rootSessionId, sessionFile: rootSessionFile }];\n\t\tconst childrenByParent = new Map<string, SessionInfo[]>();\n\t\tfor (const info of await this.rlmSpawnLedger().family()) {\n\t\t\tif (!info.parentSessionPath) continue;\n\t\t\tconst key = canonicalSessionPath(info.parentSessionPath);\n\t\t\tchildrenByParent.set(key, [...(childrenByParent.get(key) ?? []), info]);\n\t\t}\n\t\tconst queue = [canonicalSessionPath(rootSessionFile)];\n\t\tconst visited = new Set(queue);\n\t\twhile (queue.length > 0) {\n\t\t\tfor (const info of childrenByParent.get(queue.shift()!) ?? []) {\n\t\t\t\tconst child = canonicalSessionPath(info.path);\n\t\t\t\tif (visited.has(child)) continue;\n\t\t\t\tvisited.add(child);\n\t\t\t\tsessions.push({ sessionId: info.id, sessionFile: info.path });\n\t\t\t\tqueue.push(child);\n\t\t\t}\n\t\t}\n\t\t// A worker covering any tree member owns its stores again; a stale intent must not kill new schedules.\n\t\tfor (const { sessionFile } of sessions) {\n\t\t\ttry {\n\t\t\t\tif (this.findWorkerBySessionFile(sessionFile, exclude)) return;\n\t\t\t} catch {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tlet registered = false;\n\t\tfor (const { sessionId, sessionFile } of sessions) {\n\t\t\tconst artifactDir = getSessionArtifactPathForFile(sessionFile, sessionId);\n\t\t\tif (!existsSync(join(artifactDir, SESSION_SCHEDULED_JOBS_FILENAME))) continue;\n\t\t\tstore.registerSessionArtifact(sessionId, artifactDir);\n\t\t\tregistered = true;\n\t\t}\n\t\tif (!registered) return;\n\t\t// Re-checked in the same synchronous turn as the walk: a promotion committed during the family read keeps its schedules.\n\t\tif (stillWanted && !stillWanted()) return;\n\t\tfor (const { sessionFile } of sessions) {\n\t\t\tstore.cancelJobsForSession({ sessionFile });\n\t\t}\n\t}\n\n\tprivate async cancelEphemeralWorkerScheduledJobs(worker: ResidentWorker): Promise<boolean> {\n\t\tconst context = this.workerSessionArtifactContext(worker);\n\t\tif (!context || !worker.descriptor.rootSessionId) {\n\t\t\treturn true;\n\t\t}\n\t\ttry {\n\t\t\tawait this.cancelScheduledJobsForSessionTree(\n\t\t\t\tworker.descriptor.rootSessionId,\n\t\t\t\tcontext.sessionFile,\n\t\t\t\t() => worker.descriptor.ownerClientId !== undefined,\n\t\t\t\tworker,\n\t\t\t);\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\t// A promotion that landed during the failed read means the cancel is no longer wanted.\n\t\t\tif (worker.descriptor.ownerClientId === undefined) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tthis.log(\n\t\t\t\t`Could not cancel scheduled jobs for client-owned worker ${worker.descriptor.workerId}: ${String(error)}`,\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate reclaimStoppedWorkerCronLock(worker: ResidentWorker): void {\n\t\tconst context = this.workerSessionArtifactContext(worker);\n\t\tif (!context) {\n\t\t\treturn;\n\t\t}\n\t\trmSync(join(context.artifactDir, `${SESSION_SCHEDULED_JOBS_FILENAME}.lock`), { recursive: true, force: true });\n\t}\n\n\tprivate workerSessionArtifactContext(worker: {\n\t\tdescriptor: DaemonWorkerDescriptor;\n\t}): { sessionFile: string; artifactDir: string } | undefined {\n\t\tconst sessionFile = worker.descriptor.sessionFile ?? worker.descriptor.createCommand.sessionPath;\n\t\tif (!sessionFile || !worker.descriptor.rootSessionId) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tsessionFile,\n\t\t\tartifactDir: getSessionArtifactPathForFile(sessionFile, worker.descriptor.rootSessionId),\n\t\t};\n\t}\n\n\tprivate persistWorkerStopTombstone(worker: ResidentWorker, archiveSession = false): void {\n\t\tif (worker.compatibilityError) throw worker.compatibilityError;\n\t\tworker.intentionalStop = true;\n\t\tworker.descriptor.stopRequestedAt ??= new Date().toISOString();\n\t\tworker.descriptor.archiveOnStop ||= archiveSession;\n\t\tthis.persistWorker(worker);\n\t}\n\n\tprivate write(client: DaemonSocketClient, message: DaemonOutbound): boolean {\n\t\treturn this.writeSerialized(client, serializeJsonLine(message));\n\t}\n\n\tprivate broadcastHeartbeatsChanged(): void {\n\t\tthis.scheduleScheduledSessionWakeRecompute();\n\t\tfor (const client of this.clients) {\n\t\t\tthis.write(client, { type: \"heartbeats_changed\" });\n\t\t}\n\t}\n\n\tprivate writeSerialized(client: DaemonSocketClient, line: string | Uint8Array): boolean {\n\t\tif (client.socket.destroyed) {\n\t\t\treturn false;\n\t\t}\n\t\tconst accepted = client.socket.write(line);\n\t\tif (!accepted) {\n\t\t\tclient.backpressured = true;\n\t\t}\n\t\treturn accepted;\n\t}\n\n\tprivate registerSignalHandlers(): void {\n\t\tconst signals: NodeJS.Signals[] = [\"SIGINT\", \"SIGTERM\"];\n\t\tif (process.platform !== \"win32\") {\n\t\t\tsignals.push(\"SIGHUP\");\n\t\t}\n\t\tfor (const signal of signals) {\n\t\t\tconst handler = () => void this.shutdown(signal === \"SIGINT\" ? 130 : signal === \"SIGHUP\" ? 129 : 143, false);\n\t\t\tprocess.on(signal, handler);\n\t\t\tthis.signalCleanupHandlers.push(() => process.off(signal, handler));\n\t\t}\n\t\tconst exitHandler = () => this.cleanupSocket();\n\t\tprocess.on(\"exit\", exitHandler);\n\t\tthis.signalCleanupHandlers.push(() => process.off(\"exit\", exitHandler));\n\t}\n\n\tprivate assertSocketLeaseHeld(): void {\n\t\tconst compromise = this.socketLeaseCompromise ?? this.socketLease?.compromise;\n\t\tif (compromise) throw new Error(`Daemon socket lease was compromised: ${compromise.message}`);\n\t}\n\n\tprivate assertSupervisorServing(allowWorkerLedger = false): void {\n\t\tthis.assertSocketLeaseHeld();\n\t\tif (this.shuttingDown && (!allowWorkerLedger || this.rlmJournalClose !== undefined)) {\n\t\t\tconst error = new Error(`Daemon supervisor generation ${this.generation} is shutting down; retry the command`);\n\t\t\tObject.assign(error, { code: \"supervisor_generation_stale\" as const });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate fenceSupervisorSocket(): void {\n\t\ttry {\n\t\t\tthis.server?.close();\n\t\t} catch {\n\t\t\t// The server may already be closed by a concurrent shutdown.\n\t\t}\n\t\tfor (const client of this.clients) {\n\t\t\tclient.detachInput();\n\t\t\tclient.socket.destroy();\n\t\t}\n\t}\n\n\tprivate handleSocketLeaseCompromised(error: Error): void {\n\t\tif (this.socketLeaseCompromise) return;\n\t\tthis.socketLeaseCompromise = error;\n\t\tthis.shuttingDown = true;\n\t\tthis.fenceRlmJournalOwner();\n\t\tthis.fenceSupervisorSocket();\n\t\tconst message = `Daemon socket lease was compromised; relinquishing supervisor ownership: ${error.message}`;\n\t\ttry {\n\t\t\tthis.log(message);\n\t\t} catch {\n\t\t\tconsole.error(message);\n\t\t}\n\t\tif (!this.startupComplete) return;\n\t\tvoid this.cleanupSupervisorResources().catch((cleanupError) =>\n\t\t\tthis.reportCleanupFailure(\"compromised daemon socket lease\", cleanupError),\n\t\t);\n\t}\n\n\tprivate cleanupSocket(): void {\n\t\tif (!this.ownsSocketPath) {\n\t\t\treturn;\n\t\t}\n\t\tthis.ownsSocketPath = false;\n\t\tconst identity = this.socketIdentity;\n\t\tthis.socketIdentity = undefined;\n\t\tcleanupDaemonSocketPath(this.socketPath, identity, this.socketLease);\n\t}\n\n\tprivate async cleanupSupervisorResources(): Promise<void> {\n\t\tif (this.cleanupPromise) {\n\t\t\treturn this.cleanupPromise;\n\t\t}\n\t\tthis.cleanupPromise = this.cleanupSupervisorResourcesOnce();\n\t\treturn this.cleanupPromise;\n\t}\n\n\tprivate async cleanupSupervisorResourcesOnce(): Promise<void> {\n\t\tthis.shuttingDown = true;\n\t\tthis.clearIdleEvictionTimer();\n\t\tthis.clearScheduledWakeTimer();\n\t\tthis.clearRosterWatchdogTimer();\n\t\tawait this.idleEvictionSweep?.catch(() => undefined);\n\t\tfor (const cleanup of this.signalCleanupHandlers.splice(0)) {\n\t\t\tawait this.runCleanupStep(\"signal handler\", cleanup);\n\t\t}\n\t\tconst server = this.server;\n\t\tthis.server = undefined;\n\t\tconst serverClosed = new Promise<void>((resolveClose) => {\n\t\t\tif (!server?.listening) {\n\t\t\t\tresolveClose();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tserver.close(() => resolveClose());\n\t\t\t} catch (error) {\n\t\t\t\tthis.reportCleanupFailure(\"daemon server\", error);\n\t\t\t\tresolveClose();\n\t\t\t}\n\t\t});\n\t\tfor (const client of this.clients) {\n\t\t\tclient.attachedActiveSessionIds.clear();\n\t\t\tawait this.runCleanupStep(`daemon client input ${client.id}`, () => client.detachInput());\n\t\t\tawait this.runCleanupStep(`daemon client socket ${client.id}`, () => {\n\t\t\t\tclient.socket.destroy();\n\t\t\t});\n\t\t}\n\t\tthis.clients.clear();\n\t\tfor (const worker of this.workers.values()) {\n\t\t\tif (worker.ownerCleanupTimer) {\n\t\t\t\tclearTimeout(worker.ownerCleanupTimer);\n\t\t\t\tworker.ownerCleanupTimer = undefined;\n\t\t\t}\n\t\t\tawait this.runCleanupStep(`worker client ${worker.descriptor.workerId}`, () => worker.client?.close());\n\t\t\tworker.client = undefined;\n\t\t\tconst transcripts = new Set(worker.transcriptCaches.values());\n\t\t\tfor (const generations of worker.snapshotGenerations?.values() ?? []) {\n\t\t\t\tfor (const generation of generations.values()) {\n\t\t\t\t\ttranscripts.add(generation.transcript);\n\t\t\t\t\tthis.settleSnapshotDuplicateValidation(\n\t\t\t\t\t\tgeneration,\n\t\t\t\t\t\tnew Error(\"Daemon supervisor stopped during snapshot transfer\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (!generation.transcript.complete) {\n\t\t\t\t\t\tgeneration.transcript.markFailed(new Error(\"Daemon supervisor stopped during snapshot transfer\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const transcript of transcripts) {\n\t\t\t\tawait this.runCleanupStep(`worker transcript ${worker.descriptor.workerId}`, () => transcript.dispose());\n\t\t\t}\n\t\t\tworker.transcriptCaches.clear();\n\t\t\tworker.snapshotGenerations?.clear();\n\t\t\tworker.snapshotCache.clear();\n\t\t\tworker.snapshotLoads.clear();\n\t\t}\n\t\tthis.workers.clear();\n\t\tthis.openingWorkers.clear();\n\t\tawait this.runCleanupStep(\"daemon catalog\", () => this.catalog.stop());\n\t\tawait this.runCleanupStep(\"daemon server\", () => serverClosed);\n\t\tawait this.runCleanupStep(\"daemon socket\", () => this.cleanupSocket());\n\t\tawait this.runCleanupStep(\"supervisor cache\", () => {\n\t\t\trmSync(this.snapshotCacheRoot, { recursive: true, force: true });\n\t\t});\n\t\tawait this.closeRlmJournalOwner();\n\t\tconst lease = this.socketLease;\n\t\tthis.socketLease = undefined;\n\t\tawait this.runCleanupStep(\"daemon socket lock\", async () => lease?.release());\n\t\tconst ownership = this.ownership;\n\t\tthis.ownership = undefined;\n\t\tawait this.runCleanupStep(\"daemon ownership\", async () => ownership?.release());\n\t}\n\n\tprivate async runCleanupStep(label: string, action: () => void | Promise<void>): Promise<void> {\n\t\ttry {\n\t\t\tawait action();\n\t\t} catch (error) {\n\t\t\tthis.reportCleanupFailure(label, error);\n\t\t}\n\t}\n\n\tprivate reportCleanupFailure(label: string, error: unknown): void {\n\t\tconst message = `Failed to clean up ${label}: ${String(error)}`;\n\t\ttry {\n\t\t\tthis.log(message);\n\t\t} catch {\n\t\t\tconsole.error(message);\n\t\t}\n\t}\n\n\tprivate async shutdown(\n\t\texitCode: number,\n\t\tstopWorkers: boolean,\n\t\trelaunch = false,\n\t\tforceWorkers = false,\n\t\tclosingReason?: DaemonClosingReason,\n\t): Promise<never> {\n\t\tif (this.shuttingDown) {\n\t\t\tprocess.exit(exitCode);\n\t\t}\n\t\tthis.shuttingDown = true;\n\t\tthis.clearIdleEvictionTimer();\n\t\tthis.clearScheduledWakeTimer();\n\t\tthis.clearRosterWatchdogTimer();\n\t\tawait this.idleEvictionSweep?.catch(() => undefined);\n\t\tif (closingReason) {\n\t\t\tfor (const client of this.clients) {\n\t\t\t\tthis.write(client, { type: \"daemon_closing\", reason: closingReason });\n\t\t\t}\n\t\t}\n\t\tfor (const cleanup of this.signalCleanupHandlers) {\n\t\t\tcleanup();\n\t\t}\n\t\tif (stopWorkers) {\n\t\t\tawait Promise.all(\n\t\t\t\t[...this.workers.values()].map(async (worker) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.stopWorker(worker, true, forceWorkers, true);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (error instanceof DaemonWorkerCompatibilityError) {\n\t\t\t\t\t\t\tthis.log(`Keeping live incompatible worker ${worker.descriptor.workerId}: ${error.message}`);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!(error instanceof WorkerStopTimeoutError)) {\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.log(\n\t\t\t\t\t\t\t`Worker ${worker.descriptor.workerId} remains tombstoned for recovery after shutdown: ${error.message}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (!this.hasPersistedWorkerDescriptors()) {\n\t\t\t\trmSync(this.supervisorConfigPath, { force: true });\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const worker of this.workers.values()) {\n\t\t\t\tif (worker.compatibilityError) continue;\n\t\t\t\tworker.intentionalStop = true;\n\t\t\t\tworker.client?.close();\n\t\t\t\tworker.client = undefined;\n\t\t\t}\n\t\t}\n\t\tawait this.catalog.stop();\n\t\tfor (const client of this.clients) {\n\t\t\tclient.detachInput();\n\t\t\tclient.socket.end();\n\t\t}\n\t\tawait new Promise<void>((resolveClose) => this.server?.close(() => resolveClose()) ?? resolveClose());\n\t\tawait this.runCleanupStep(\"daemon socket\", () => this.cleanupSocket());\n\t\tawait this.runCleanupStep(\"supervisor cache\", () => {\n\t\t\trmSync(this.snapshotCacheRoot, { recursive: true, force: true });\n\t\t});\n\t\tawait this.closeRlmJournalOwner();\n\t\tconst lease = this.socketLease;\n\t\tthis.socketLease = undefined;\n\t\tawait this.runCleanupStep(\"daemon socket lock\", async () => lease?.release());\n\t\tconst ownership = this.ownership;\n\t\tthis.ownership = undefined;\n\t\tawait this.runCleanupStep(\"daemon ownership\", async () => ownership?.release());\n\t\tif (relaunch) {\n\t\t\tconst launch = createCliSubprocessLaunchSpec([\"--mode\", \"daemon\", \"--daemon-socket\", this.socketPath]);\n\t\t\tconst environment = createCliSubprocessEnv();\n\t\t\tdelete environment[DAEMON_CATALOG_ROLE_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_ROLE_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_TOKEN_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_ACTIVE_SESSION_ID_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_SUPERVISOR_SOCKET_ENV];\n\t\t\tdelete environment[DAEMON_WORKER_RECOVERY_JOURNAL_ENV];\n\t\t\tdelete environment[ORPHAN_PROCESS_JOURNAL_ENV];\n\t\t\tdelete environment[SESSION_LEASES_ENABLED_ENV];\n\t\t\tdelete environment[SESSION_LEASE_OWNER_ID_ENV];\n\t\t\tconst replacement = spawn(launch.command, launch.args, {\n\t\t\t\tcwd: this.defaultSessionConfig.cwd ?? process.cwd(),\n\t\t\t\tdetached: true,\n\t\t\t\tenv: environment,\n\t\t\t\tstdio: \"ignore\",\n\t\t\t});\n\t\t\treplacement.unref();\n\t\t}\n\t\tprocess.exit(exitCode);\n\t}\n}\n"]}
|