@sayknow-cli/coding-agent 0.4.6 → 0.5.0

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.
Files changed (428) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/dist/types/capability/index.d.ts +10 -20
  3. package/dist/types/capability/types.d.ts +3 -0
  4. package/dist/types/cli/args.d.ts +0 -2
  5. package/dist/types/cli/read-cli.d.ts +1 -0
  6. package/dist/types/cli.d.ts +9 -1
  7. package/dist/types/commands/daemon.d.ts +2 -2
  8. package/dist/types/commands/deep-interview.d.ts +9 -0
  9. package/dist/types/commands/harness.d.ts +22 -0
  10. package/dist/types/commands/read.d.ts +6 -0
  11. package/dist/types/commands/sdk.d.ts +20 -2
  12. package/dist/types/config/keybindings.d.ts +34 -4
  13. package/dist/types/config/model-profile-contract.d.ts +40 -0
  14. package/dist/types/config/model-profiles.d.ts +2 -3
  15. package/dist/types/config/model-registry.d.ts +5 -0
  16. package/dist/types/config/provider-auth-health.d.ts +14 -0
  17. package/dist/types/config/provider-ranking.d.ts +59 -0
  18. package/dist/types/config/settings-schema.d.ts +156 -10
  19. package/dist/types/config/settings.d.ts +3 -0
  20. package/dist/types/edit/modes/patch.d.ts +13 -0
  21. package/dist/types/edit/path-mutation-lock.d.ts +15 -0
  22. package/dist/types/eval/py/executor.d.ts +1 -1
  23. package/dist/types/eval/py/runner-artifact.d.ts +8 -0
  24. package/dist/types/eval/py/tool-bridge.d.ts +1 -2
  25. package/dist/types/extensibility/extensions/types.d.ts +43 -2
  26. package/dist/types/extensibility/shared-events.d.ts +6 -0
  27. package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
  28. package/dist/types/main.d.ts +33 -2
  29. package/dist/types/memories/index.d.ts +2 -0
  30. package/dist/types/modes/acp/acp-agent.d.ts +22 -9
  31. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  32. package/dist/types/modes/components/btw-panel.d.ts +1 -0
  33. package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
  34. package/dist/types/modes/components/queue-pane.d.ts +8 -0
  35. package/dist/types/modes/components/queued-message-selector.d.ts +6 -0
  36. package/dist/types/modes/components/read-tool-group.d.ts +4 -4
  37. package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +2 -1
  38. package/dist/types/modes/components/session-observer-overlay.d.ts +4 -0
  39. package/dist/types/modes/components/settings-selector.d.ts +2 -0
  40. package/dist/types/modes/components/tool-execution.d.ts +8 -0
  41. package/dist/types/modes/components/tool-status-header.d.ts +4 -2
  42. package/dist/types/modes/components/welcome.d.ts +5 -0
  43. package/dist/types/modes/controllers/btw-controller.d.ts +5 -0
  44. package/dist/types/modes/controllers/command-controller.d.ts +2 -0
  45. package/dist/types/modes/controllers/event-controller.d.ts +3 -0
  46. package/dist/types/modes/interactive-mode.d.ts +13 -2
  47. package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
  48. package/dist/types/modes/prompt-action-autocomplete.d.ts +6 -1
  49. package/dist/types/modes/prompt-suggestion-controller.d.ts +35 -0
  50. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +2 -2
  51. package/dist/types/modes/types.d.ts +6 -0
  52. package/dist/types/modes/utils/hotkeys-markdown.d.ts +2 -1
  53. package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
  54. package/dist/types/runtime/memory-domain.d.ts +9 -0
  55. package/dist/types/runtime/memory-guard-contract.d.ts +71 -0
  56. package/dist/types/runtime/memory-guard.d.ts +39 -0
  57. package/dist/types/runtime/memory-limit.d.ts +11 -0
  58. package/dist/types/runtime-mcp/content-limits.d.ts +7 -0
  59. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +1 -1
  60. package/dist/types/runtime-mcp/manager.d.ts +9 -1
  61. package/dist/types/runtime-mcp/oauth-flow.d.ts +0 -5
  62. package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +14 -0
  63. package/dist/types/runtime-mcp/redaction.d.ts +2 -0
  64. package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
  65. package/dist/types/sdk/acp/final-text.d.ts +19 -0
  66. package/dist/types/sdk/acp/mcp.d.ts +23 -0
  67. package/dist/types/sdk/broker/broker.d.ts +2 -0
  68. package/dist/types/sdk/broker/lifecycle.d.ts +13 -0
  69. package/dist/types/sdk/bus/chat-daemon-control.d.ts +9 -1
  70. package/dist/types/sdk/bus/config-commands.d.ts +2 -2
  71. package/dist/types/sdk/bus/config.d.ts +2 -0
  72. package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
  73. package/dist/types/sdk/bus/conversation-store.d.ts +1 -0
  74. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  75. package/dist/types/sdk/bus/index.d.ts +52 -4
  76. package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +37 -0
  77. package/dist/types/sdk/bus/lifecycle-commands.d.ts +5 -4
  78. package/dist/types/sdk/bus/notification-orchestration.d.ts +1 -0
  79. package/dist/types/sdk/bus/notification-service.d.ts +34 -0
  80. package/dist/types/sdk/bus/operator-runtime.d.ts +1 -0
  81. package/dist/types/sdk/bus/prompt-reconciliation.d.ts +106 -0
  82. package/dist/types/sdk/bus/rate-limit-pool.d.ts +2 -0
  83. package/dist/types/sdk/bus/reconciliation-store.d.ts +65 -0
  84. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +33 -9
  85. package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -1
  86. package/dist/types/sdk/bus/telegram-daemon.d.ts +286 -12
  87. package/dist/types/sdk/bus/telegram-reference.d.ts +2 -0
  88. package/dist/types/sdk/bus/topic-registry.d.ts +88 -2
  89. package/dist/types/sdk/client/discovery.d.ts +2 -0
  90. package/dist/types/sdk/client/liveness.d.ts +7 -0
  91. package/dist/types/sdk/host/control/operations.d.ts +3 -2
  92. package/dist/types/sdk/host/host.d.ts +3 -1
  93. package/dist/types/sdk/host/query/handlers.d.ts +14 -0
  94. package/dist/types/sdk/index.d.ts +2 -0
  95. package/dist/types/sdk/lifecycle-session.d.ts +10 -1
  96. package/dist/types/sdk/prompt-status.d.ts +88 -0
  97. package/dist/types/sdk/session-directory.d.ts +1 -1
  98. package/dist/types/sdk/session.d.ts +7 -0
  99. package/dist/types/sdk/startup-capability.d.ts +9 -0
  100. package/dist/types/sdk/transport/auth-preface.d.ts +9 -0
  101. package/dist/types/sdk/transport/index.d.ts +12 -0
  102. package/dist/types/sdk/transport/relay.d.ts +43 -0
  103. package/dist/types/sdk/transport/serve-cli.d.ts +4 -0
  104. package/dist/types/sdk/transport/socket.d.ts +7 -0
  105. package/dist/types/sdk/transport/stdio.d.ts +3 -0
  106. package/dist/types/session/agent-session.d.ts +83 -24
  107. package/dist/types/session/btw-contract.d.ts +16 -0
  108. package/dist/types/session/fallback-chain-controller.d.ts +18 -2
  109. package/dist/types/session/internal/managed-session-scope.d.ts +70 -10
  110. package/dist/types/session/internal/managed-session-storage.d.ts +34 -12
  111. package/dist/types/session/internal/native-publish-outcome.d.ts +48 -0
  112. package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
  113. package/dist/types/session/session-manager.d.ts +89 -18
  114. package/dist/types/session/session-storage.d.ts +31 -0
  115. package/dist/types/session/streaming-output.d.ts +60 -5
  116. package/dist/types/setup/credential-import.d.ts +5 -1
  117. package/dist/types/setup/provider-onboarding.d.ts +2 -0
  118. package/dist/types/skc-runtime/deep-interview-runtime.d.ts +1 -1
  119. package/dist/types/skc-runtime/deep-interview-stage.d.ts +37 -0
  120. package/dist/types/skc-runtime/gc-runtime.d.ts +1 -1
  121. package/dist/types/skc-runtime/linux-proc.d.ts +22 -14
  122. package/dist/types/skc-runtime/memory-guard-owner-claims.d.ts +47 -0
  123. package/dist/types/skc-runtime/ralplan-runtime.d.ts +112 -1
  124. package/dist/types/skc-runtime/repository-binding.d.ts +63 -0
  125. package/dist/types/skc-runtime/state-runtime.d.ts +3 -1
  126. package/dist/types/skc-runtime/state-writer.d.ts +5 -1
  127. package/dist/types/skc-runtime/team-launch.d.ts +1 -1
  128. package/dist/types/skc-runtime/team-runtime.d.ts +9 -2
  129. package/dist/types/skc-runtime/team-store.d.ts +12 -0
  130. package/dist/types/skc-runtime/team-worker-memory-guard.d.ts +92 -0
  131. package/dist/types/skc-runtime/tmux-owner-isolation.d.ts +7 -0
  132. package/dist/types/skc-runtime/ultragoal-guard.d.ts +6 -5
  133. package/dist/types/skc-runtime/ultragoal-receipt-freshness.d.ts +28 -0
  134. package/dist/types/skc-runtime/ultragoal-runtime.d.ts +43 -5
  135. package/dist/types/skill-state/workflow-hud.d.ts +3 -0
  136. package/dist/types/ssh/utils.d.ts +1 -0
  137. package/dist/types/task/discovery.d.ts +3 -1
  138. package/dist/types/task/executor.d.ts +6 -0
  139. package/dist/types/task/index.d.ts +3 -1
  140. package/dist/types/task/provider-retry-status.d.ts +13 -0
  141. package/dist/types/task/receipt.d.ts +2 -0
  142. package/dist/types/task/types.d.ts +133 -0
  143. package/dist/types/task/ultragoal-redteam-activation.d.ts +33 -0
  144. package/dist/types/tools/browser/launch.d.ts +7 -0
  145. package/dist/types/tools/fetch.d.ts +22 -9
  146. package/dist/types/tools/image-gen.d.ts +63 -1
  147. package/dist/types/tools/index.d.ts +7 -1
  148. package/dist/types/tools/output-meta.d.ts +21 -1
  149. package/dist/types/tools/read-internals.d.ts +12 -0
  150. package/dist/types/tools/read.d.ts +45 -1
  151. package/dist/types/tools/resource-gc.d.ts +23 -0
  152. package/dist/types/tools/skill-discovery.d.ts +7 -0
  153. package/dist/types/tools/sqlite-reader.d.ts +7 -0
  154. package/dist/types/tools/tool-result.d.ts +7 -1
  155. package/dist/types/utils/prompt-suggestion.d.ts +33 -0
  156. package/dist/types/utils/shell-snapshot.d.ts +12 -0
  157. package/dist/types/web/insane/bridge.d.ts +1 -0
  158. package/dist/types/web/insane/url-guard.d.ts +17 -0
  159. package/package.json +8 -12
  160. package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
  161. package/scripts/capture-platform-shortcut-labels-showcase.ts +342 -0
  162. package/scripts/capture-sticky-viewport-showcase.ts +292 -0
  163. package/scripts/compile-args.ts +0 -1
  164. package/scripts/dogfood-repository-binding.ts +209 -0
  165. package/scripts/generate-docs-index.ts +4 -1
  166. package/scripts/generate-sdk-operation-inventory.ts +9 -0
  167. package/scripts/run-test-manifest.ts +6 -4
  168. package/scripts/verify-skc-sdk-canonicalization.ts +122 -18
  169. package/scripts/verify-sticky-viewport-showcase.ts +611 -0
  170. package/src/capability/index.ts +58 -42
  171. package/src/capability/types.ts +3 -0
  172. package/src/cli/args.ts +16 -100
  173. package/src/cli/fast-help.ts +1 -1
  174. package/src/cli/mcp-cli.ts +4 -21
  175. package/src/cli/notify-cli.ts +6 -38
  176. package/src/cli/read-cli.ts +2 -1
  177. package/src/cli/setup-cli.ts +10 -4
  178. package/src/cli.ts +133 -11
  179. package/src/commands/daemon.ts +22 -5
  180. package/src/commands/deep-interview.ts +26 -1
  181. package/src/commands/harness.ts +35 -12
  182. package/src/commands/read.ts +11 -2
  183. package/src/commands/sdk.ts +134 -17
  184. package/src/commands/team.ts +1 -1
  185. package/src/commit/agentic/index.ts +3 -3
  186. package/src/commit/map-reduce/index.ts +2 -2
  187. package/src/config/keybindings.ts +158 -25
  188. package/src/config/model-profile-contract.ts +174 -0
  189. package/src/config/model-profiles.ts +51 -10
  190. package/src/config/model-registry.ts +24 -4
  191. package/src/config/model-resolver.ts +2 -2
  192. package/src/config/provider-auth-health.ts +42 -0
  193. package/src/config/provider-ranking.ts +119 -0
  194. package/src/config/settings-schema.ts +157 -10
  195. package/src/config/settings.ts +254 -108
  196. package/src/coordinator-mcp/model-preset.ts +21 -74
  197. package/src/defaults/skc/skills/deep-interview/SKILL.md +147 -24
  198. package/src/defaults/skc/skills/ralplan/SKILL.md +91 -34
  199. package/src/defaults/skc/skills/team/SKILL.md +1 -1
  200. package/src/defaults/skc/skills/ultragoal/SKILL.md +68 -17
  201. package/src/discovery/ssh.ts +12 -1
  202. package/src/edit/index.ts +3 -6
  203. package/src/edit/modes/patch.ts +38 -1
  204. package/src/edit/modes/replace.ts +42 -0
  205. package/src/edit/path-mutation-lock.ts +112 -0
  206. package/src/eval/js/tool-bridge.ts +1 -1
  207. package/src/eval/py/executor.ts +37 -13
  208. package/src/eval/py/kernel.ts +1 -21
  209. package/src/eval/py/prelude.py +2 -2
  210. package/src/eval/py/runner-artifact.ts +84 -0
  211. package/src/eval/py/tool-bridge.ts +34 -18
  212. package/src/extensibility/extensions/runner.ts +4 -0
  213. package/src/extensibility/extensions/types.ts +42 -4
  214. package/src/extensibility/plugins/marketplace/fetcher.ts +191 -7
  215. package/src/extensibility/shared-events.ts +5 -0
  216. package/src/extensibility/skc-plugins/runtime-adapters.ts +2 -1
  217. package/src/hooks/native-skill-hook.ts +17 -4
  218. package/src/internal-urls/docs-index.generated.ts +17 -16
  219. package/src/internal-urls/local-protocol.ts +87 -25
  220. package/src/internal-urls/local-root-gc.ts +127 -0
  221. package/src/internal-urls/mcp-protocol.ts +73 -11
  222. package/src/main.ts +120 -42
  223. package/src/memories/index.ts +10 -0
  224. package/src/modes/DESIGN.md +52 -0
  225. package/src/modes/acp/acp-agent.ts +647 -83
  226. package/src/modes/acp/acp-event-mapper.ts +106 -12
  227. package/src/modes/acp/acp-mode.ts +39 -3
  228. package/src/modes/action-registry.ts +1 -1
  229. package/src/modes/components/assistant-message.ts +123 -22
  230. package/src/modes/components/btw-panel.ts +82 -16
  231. package/src/modes/components/irc-sidebar.ts +176 -62
  232. package/src/modes/components/model-selector.ts +61 -4
  233. package/src/modes/components/notifications-settings-editor.ts +1 -1
  234. package/src/modes/components/oauth-selector.ts +42 -12
  235. package/src/modes/components/plan-preview-overlay.ts +1 -1
  236. package/src/modes/components/queue-pane.ts +55 -9
  237. package/src/modes/components/queued-message-selector.ts +53 -10
  238. package/src/modes/components/read-tool-group.ts +82 -14
  239. package/src/modes/components/runtime-mcp-add-wizard.ts +5 -0
  240. package/src/modes/components/sayknow-pet-widget.ts +27 -8
  241. package/src/modes/components/session-observer-overlay.ts +187 -32
  242. package/src/modes/components/settings-selector.ts +60 -18
  243. package/src/modes/components/tool-execution.ts +138 -27
  244. package/src/modes/components/tool-status-header.ts +26 -8
  245. package/src/modes/components/welcome.ts +50 -23
  246. package/src/modes/controllers/btw-controller.ts +119 -36
  247. package/src/modes/controllers/command-controller.ts +101 -54
  248. package/src/modes/controllers/event-controller.ts +119 -27
  249. package/src/modes/controllers/extension-ui-controller.ts +23 -12
  250. package/src/modes/controllers/input-controller.ts +100 -8
  251. package/src/modes/controllers/runtime-mcp-command-controller.ts +29 -6
  252. package/src/modes/controllers/selector-controller.ts +4 -1
  253. package/src/modes/interactive-mode.ts +201 -60
  254. package/src/modes/irc-observation-ledger.ts +71 -15
  255. package/src/modes/prompt-action-autocomplete.ts +32 -13
  256. package/src/modes/prompt-suggestion-controller.ts +96 -0
  257. package/src/modes/runtime-init.ts +20 -2
  258. package/src/modes/shared/agent-wire/command-dispatch.ts +3 -3
  259. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +2 -2
  260. package/src/modes/types.ts +6 -0
  261. package/src/modes/utils/hotkeys-markdown.ts +64 -36
  262. package/src/modes/utils/ui-helpers.ts +99 -4
  263. package/src/prompts/agent-fragments/restricted-bash.md +1 -1
  264. package/src/prompts/agents/architect.md +17 -3
  265. package/src/prompts/agents/critic.md +17 -2
  266. package/src/prompts/agents/executor.md +1 -1
  267. package/src/prompts/agents/planner.md +8 -1
  268. package/src/prompts/system/btw-user.md +3 -8
  269. package/src/prompts/system/prompt-suggestion-system.md +32 -0
  270. package/src/prompts/system/system-prompt.md +6 -3
  271. package/src/prompts/tools/cron.md +3 -1
  272. package/src/prompts/tools/read.md +4 -2
  273. package/src/prompts/tools/skill-discovery.md +1 -0
  274. package/src/runtime/memory-domain.ts +66 -0
  275. package/src/runtime/memory-guard-contract.ts +73 -0
  276. package/src/runtime/memory-guard.ts +292 -0
  277. package/src/runtime/memory-limit.ts +50 -0
  278. package/src/runtime-mcp/client.ts +41 -55
  279. package/src/runtime-mcp/content-limits.ts +71 -0
  280. package/src/runtime-mcp/discoverable-tool-metadata.ts +1 -1
  281. package/src/runtime-mcp/json-rpc.ts +28 -11
  282. package/src/runtime-mcp/manager.ts +77 -59
  283. package/src/runtime-mcp/oauth-flow.ts +0 -72
  284. package/src/runtime-mcp/plugin-network-boundary.ts +101 -0
  285. package/src/runtime-mcp/redaction.ts +30 -0
  286. package/src/runtime-mcp/smithery-auth.ts +17 -2
  287. package/src/runtime-mcp/smithery-connect.ts +11 -1
  288. package/src/runtime-mcp/transports/http.ts +63 -22
  289. package/src/sdk/acp/adapter.ts +8 -1
  290. package/src/sdk/acp/final-text.ts +40 -0
  291. package/src/sdk/acp/mcp.ts +26 -0
  292. package/src/sdk/broker/broker.ts +34 -20
  293. package/src/sdk/broker/identity.ts +22 -12
  294. package/src/sdk/broker/lifecycle.ts +293 -43
  295. package/src/sdk/broker/session-index.ts +11 -1
  296. package/src/sdk/bus/chat-daemon-cli.ts +2 -2
  297. package/src/sdk/bus/chat-daemon-control.ts +22 -5
  298. package/src/sdk/bus/config-commands.ts +2 -2
  299. package/src/sdk/bus/config.ts +10 -2
  300. package/src/sdk/bus/control-drain-lease.ts +104 -0
  301. package/src/sdk/bus/conversation-store.ts +40 -6
  302. package/src/sdk/bus/daemon-paths.ts +2 -0
  303. package/src/sdk/bus/index.ts +793 -121
  304. package/src/sdk/bus/kind-aware-reconciliation.ts +242 -0
  305. package/src/sdk/bus/lifecycle-commands.ts +63 -10
  306. package/src/sdk/bus/lifecycle-control-runtime.ts +11 -2
  307. package/src/sdk/bus/lifecycle-orchestrator.ts +32 -1
  308. package/src/sdk/bus/notification-orchestration.ts +12 -0
  309. package/src/sdk/bus/notification-service.ts +87 -25
  310. package/src/sdk/bus/operator-runtime.ts +31 -5
  311. package/src/sdk/bus/prompt-reconciliation.ts +240 -0
  312. package/src/sdk/bus/rate-limit-pool.ts +8 -0
  313. package/src/sdk/bus/recent-activity.ts +90 -26
  314. package/src/sdk/bus/reconciliation-store.ts +224 -0
  315. package/src/sdk/bus/telegram-cli.ts +6 -13
  316. package/src/sdk/bus/telegram-daemon-cli.ts +8 -3
  317. package/src/sdk/bus/telegram-daemon-contract.ts +34 -9
  318. package/src/sdk/bus/telegram-daemon-control.ts +161 -40
  319. package/src/sdk/bus/telegram-daemon.ts +3649 -593
  320. package/src/sdk/bus/telegram-reference.ts +20 -2
  321. package/src/sdk/bus/topic-registry.ts +451 -12
  322. package/src/sdk/cli/session-cli.ts +15 -2
  323. package/src/sdk/client/discovery.ts +19 -3
  324. package/src/sdk/client/liveness.ts +49 -0
  325. package/src/sdk/host/control/dispatch.ts +8 -2
  326. package/src/sdk/host/control/operations.ts +3 -2
  327. package/src/sdk/host/host.ts +27 -9
  328. package/src/sdk/host/query/handlers.ts +125 -5
  329. package/src/sdk/index.ts +12 -0
  330. package/src/sdk/lifecycle-session.ts +19 -3
  331. package/src/sdk/mcp/server.ts +46 -18
  332. package/src/sdk/prompt-status.ts +97 -0
  333. package/src/sdk/protocol/operation-inventory.generated.json +145 -0
  334. package/src/sdk/protocol/operation-registry.ts +24 -4
  335. package/src/sdk/session-directory.ts +5 -1
  336. package/src/sdk/session.ts +69 -8
  337. package/src/sdk/startup-capability.ts +15 -1
  338. package/src/sdk/transport/auth-preface.ts +82 -0
  339. package/src/sdk/transport/index.ts +18 -0
  340. package/src/sdk/transport/relay.ts +252 -0
  341. package/src/sdk/transport/serve-cli.ts +105 -0
  342. package/src/sdk/transport/socket.ts +197 -0
  343. package/src/sdk/transport/stdio.ts +17 -0
  344. package/src/session/agent-session.ts +1112 -314
  345. package/src/session/blob-store.ts +25 -7
  346. package/src/session/btw-contract.ts +59 -0
  347. package/src/session/fallback-chain-controller.ts +47 -8
  348. package/src/session/internal/managed-session-scope.ts +1426 -259
  349. package/src/session/internal/managed-session-storage.ts +414 -238
  350. package/src/session/internal/native-publish-outcome.ts +271 -0
  351. package/src/session/memory-guard-checkpoint-participant.ts +131 -0
  352. package/src/session/session-manager.ts +2079 -469
  353. package/src/session/session-storage.ts +151 -11
  354. package/src/session/streaming-output.ts +262 -43
  355. package/src/setup/credential-import.ts +28 -3
  356. package/src/setup/provider-onboarding.ts +49 -5
  357. package/src/setup/provider-presets.json +2 -1
  358. package/src/skc-runtime/deep-interview-runtime.ts +303 -36
  359. package/src/skc-runtime/deep-interview-stage.ts +1016 -0
  360. package/src/skc-runtime/deep-interview-state.ts +8 -5
  361. package/src/skc-runtime/gc-render.ts +1 -0
  362. package/src/skc-runtime/gc-runtime.ts +11 -1
  363. package/src/skc-runtime/linux-proc.ts +70 -36
  364. package/src/skc-runtime/managed-owner-supervisor.ts +83 -4
  365. package/src/skc-runtime/memory-guard-owner-claims.ts +389 -0
  366. package/src/skc-runtime/ralplan-runtime.ts +1057 -75
  367. package/src/skc-runtime/repository-binding.ts +267 -0
  368. package/src/skc-runtime/session-state-sidecar.ts +25 -9
  369. package/src/skc-runtime/state-runtime.ts +50 -12
  370. package/src/skc-runtime/state-writer.ts +68 -56
  371. package/src/skc-runtime/team-launch.ts +34 -5
  372. package/src/skc-runtime/team-runtime.ts +41 -1
  373. package/src/skc-runtime/team-store.ts +32 -0
  374. package/src/skc-runtime/team-worker-memory-guard.ts +363 -0
  375. package/src/skc-runtime/team-workers.ts +1 -0
  376. package/src/skc-runtime/tmux-common.ts +13 -2
  377. package/src/skc-runtime/tmux-owner-isolation.ts +20 -1
  378. package/src/skc-runtime/tmux-sessions.ts +45 -6
  379. package/src/skc-runtime/ultragoal-guard.ts +93 -15
  380. package/src/skc-runtime/ultragoal-receipt-freshness.ts +123 -0
  381. package/src/skc-runtime/ultragoal-runtime.ts +469 -38
  382. package/src/skc-runtime/workflow-manifest.generated.json +195 -5
  383. package/src/skc-runtime/workflow-manifest.ts +67 -3
  384. package/src/skill-state/workflow-hud.ts +25 -2
  385. package/src/skill-state/workflow-mutation-guard.ts +104 -12
  386. package/src/slash-commands/builtin-registry.ts +1 -1
  387. package/src/ssh/utils.ts +14 -0
  388. package/src/task/discovery.ts +8 -2
  389. package/src/task/executor.ts +165 -47
  390. package/src/task/index.ts +123 -15
  391. package/src/task/provider-retry-status.ts +88 -0
  392. package/src/task/receipt.ts +3 -0
  393. package/src/task/render.ts +45 -26
  394. package/src/task/skc-command.ts +2 -2
  395. package/src/task/types.ts +55 -10
  396. package/src/task/ultragoal-redteam-activation.ts +75 -0
  397. package/src/tools/ask.ts +1 -1
  398. package/src/tools/ast-edit.ts +2 -2
  399. package/src/tools/bash-allowed-prefixes.ts +45 -1
  400. package/src/tools/bash-pty-selection.ts +2 -2
  401. package/src/tools/browser/launch.ts +41 -6
  402. package/src/tools/browser/screenshot-format.ts +6 -1
  403. package/src/tools/cron.ts +1 -1
  404. package/src/tools/fetch.ts +127 -154
  405. package/src/tools/image-gen.ts +476 -23
  406. package/src/tools/index.ts +7 -1
  407. package/src/tools/output-meta.ts +176 -9
  408. package/src/tools/path-utils.ts +5 -1
  409. package/src/tools/read-internals.ts +44 -0
  410. package/src/tools/read.ts +1544 -310
  411. package/src/tools/resource-gc.ts +665 -125
  412. package/src/tools/skill-discovery.ts +39 -3
  413. package/src/tools/sqlite-reader.ts +63 -5
  414. package/src/tools/subagent-render.ts +74 -16
  415. package/src/tools/subagent.ts +2 -0
  416. package/src/tools/tool-result.ts +14 -1
  417. package/src/utils/edit-mode.ts +2 -2
  418. package/src/utils/pasted-image-path.ts +15 -6
  419. package/src/utils/prompt-suggestion.ts +265 -0
  420. package/src/utils/shell-snapshot.ts +173 -63
  421. package/src/utils/sixel.ts +3 -3
  422. package/src/web/insane/bridge.ts +5 -1
  423. package/src/web/insane/url-guard.ts +140 -27
  424. package/src/web/scrapers/docs-rs.ts +30 -5
  425. package/src/web/scrapers/types.ts +19 -49
  426. package/src/web/scrapers/utils.ts +12 -26
  427. package/src/web/search/providers/codex.ts +1 -1
  428. package/src/workflow/workflow-intent-diff.ts +4 -1
@@ -25,9 +25,11 @@ import type {
25
25
  import { OWNERSHIP_MISMATCH_MESSAGE, ownershipMismatchRecovery } from "../../daemon/operator-contract";
26
26
  import { resolveSkcRuntimeSpawnInfo } from "../../daemon/runtime";
27
27
  import { isProcessIncarnation } from "../broker/process-incarnation";
28
+
28
29
  import { getNotificationConfig, isTelegramConfigured, tokenFingerprint } from "./config";
29
30
  import { exactUnlinkNotificationFile, readNotificationEndpointFile } from "./notification-service";
30
31
  import {
32
+ type AttestedLegacyDaemonOwner,
31
33
  confirmTelegramDaemonSpawn,
32
34
  type DaemonState,
33
35
  daemonPaths,
@@ -35,8 +37,10 @@ import {
35
37
  isCurrentCompatibleOwner,
36
38
  isFreshLiveOwner,
37
39
  isSignalableMatchingOwner,
40
+ readAttestedLegacyDaemonOwner,
38
41
  readDaemonRoots,
39
42
  readDaemonState,
43
+ readOwnerFreshnessSnapshot,
40
44
  spawnTelegramDaemonOwner,
41
45
  type TelegramDaemonDeps,
42
46
  type TelegramDaemonFs,
@@ -109,16 +113,19 @@ export async function clearTelegramControlRequest(
109
113
 
110
114
  export interface DaemonProcessReference {
111
115
  incarnation: string;
116
+ /** Whether the platform delivers the requested signal cooperatively or as a hard termination. */
117
+ termination: "cooperative" | "hard";
112
118
  signalRoot(signal: NodeJS.Signals): void;
113
119
  }
114
120
 
115
- function defaultProcessReference(pid: number, platform = os.platform()): DaemonProcessReference | undefined {
121
+ export function defaultProcessReference(pid: number, platform = os.platform()): DaemonProcessReference | undefined {
116
122
  try {
117
123
  const processRef = Process.fromPid(pid);
118
124
  if (!processRef || !isProcessIncarnation(processRef.incarnation)) return undefined;
119
125
  const incarnation = processRef.incarnation;
120
126
  return {
121
127
  incarnation,
128
+ termination: platform === "win32" ? "hard" : "cooperative",
122
129
  signalRoot: signal => {
123
130
  const nativeSignal = os.constants.signals[signal];
124
131
  if (nativeSignal === undefined) throw new Error(`Unsupported signal: ${signal}`);
@@ -178,8 +185,8 @@ function defaultPidAlive(pid: number): boolean {
178
185
  try {
179
186
  process.kill(pid, 0);
180
187
  return true;
181
- } catch {
182
- return false;
188
+ } catch (error) {
189
+ return (error as NodeJS.ErrnoException).code !== "ESRCH";
183
190
  }
184
191
  }
185
192
 
@@ -190,7 +197,6 @@ export class TelegramDaemonController implements BuiltInDaemonController {
190
197
  private readonly now: () => number;
191
198
  private readonly processReference: (pid: number) => DaemonProcessReference | undefined;
192
199
  private readonly waitStepMs: number;
193
-
194
200
  constructor(
195
201
  private readonly settings: Settings,
196
202
  private readonly deps: TelegramDaemonControlDeps = {},
@@ -219,7 +225,8 @@ export class TelegramDaemonController implements BuiltInDaemonController {
219
225
  if (!configured) {
220
226
  return { kind: this.kind, configured: false, health: "not_configured", runtime };
221
227
  }
222
- const state = await readDaemonState(this.settings, this.fsImpl);
228
+ const snapshot = await readOwnerFreshnessSnapshot({ settings: this.settings, fs: this.fsImpl });
229
+ const state = snapshot.state;
223
230
  const roots = await readDaemonRoots(this.settings, this.fsImpl);
224
231
  const health: DaemonHealth =
225
232
  !state || state.stoppedAt !== undefined || !this.pidAlive(state.pid)
@@ -231,6 +238,7 @@ export class TelegramDaemonController implements BuiltInDaemonController {
231
238
  chatId: cfg.chatId as string,
232
239
  pidAlive: this.pidAlive,
233
240
  pidIncarnation: this.deps.pidIncarnation,
241
+ effectiveHeartbeatAt: snapshot.effectiveHeartbeatAt,
234
242
  })
235
243
  ? "running"
236
244
  : "stale";
@@ -241,7 +249,7 @@ export class TelegramDaemonController implements BuiltInDaemonController {
241
249
  pid: state?.pid,
242
250
  ownerId: state?.ownerId,
243
251
  startedAt: state?.startedAt,
244
- heartbeatAt: state?.heartbeatAt,
252
+ heartbeatAt: snapshot.effectiveHeartbeatAt,
245
253
  roots,
246
254
  rootCount: roots.length,
247
255
  runtime,
@@ -315,31 +323,28 @@ export class TelegramDaemonController implements BuiltInDaemonController {
315
323
  tokenFingerprint: string,
316
324
  chatId: string,
317
325
  signal: NodeJS.Signals,
318
- ): Promise<"signaled" | "already_gone" | "ownership_changed"> {
326
+ ): Promise<"signaled" | "already_gone" | "ownership_changed" | "hard_termination"> {
319
327
  const current = await readDaemonState(this.settings, this.fsImpl);
320
- // The signal is a privileged action: immediately before sending it, prove the
321
- // complete state record is still the exact captured owner. A malformed record,
322
- // configuration mutation, or successor using a reused PID is never signalable.
323
- if (
324
- !hasSafeDaemonStateShape(current) ||
325
- current.ownerId !== captured.ownerId ||
326
- current.acquisitionId !== captured.acquisitionId ||
327
- current.pid !== captured.pid ||
328
- current.generation !== captured.generation ||
329
- current.incarnation !== captured.incarnation ||
330
- current.tokenFingerprint !== captured.tokenFingerprint ||
331
- current.chatId !== captured.chatId ||
332
- current.tokenFingerprint !== tokenFingerprint ||
333
- current.chatId !== chatId
334
- )
335
- return "ownership_changed";
336
- // A matching captured owner that exited between the request and recheck has
337
- // completed the handoff. A live owner with changed or unavailable provenance
338
- // remains ambiguous and must not be treated as stopped.
328
+
329
+ const modernCurrentMatches =
330
+ hasSafeDaemonStateShape(current) &&
331
+ current.ownerId === captured.ownerId &&
332
+ current.acquisitionId === captured.acquisitionId &&
333
+ current.pid === captured.pid &&
334
+ current.generation === captured.generation &&
335
+ current.incarnation === captured.incarnation &&
336
+ current.tokenFingerprint === captured.tokenFingerprint &&
337
+ current.chatId === captured.chatId &&
338
+ current.tokenFingerprint === tokenFingerprint &&
339
+ current.chatId === chatId;
340
+ // The signal is privileged: the persisted record must still be the exact
341
+ // modern owner. Legacy generation-3 records remain migration evidence only;
342
+ // this controller never upgrades or signals them.
343
+ if (!modernCurrentMatches) return "ownership_changed";
339
344
  if (!this.pidAlive(captured.pid)) return "already_gone";
340
345
  if (
341
346
  !isSignalableMatchingOwner({
342
- state: current,
347
+ state: modernCurrentMatches ? current : captured,
343
348
  tokenFingerprint,
344
349
  chatId,
345
350
  pidAlive: this.pidAlive,
@@ -352,6 +357,69 @@ export class TelegramDaemonController implements BuiltInDaemonController {
352
357
  // the exit-and-reuse window between ordinary provenance checks and signaling.
353
358
  // Its identity must still be the exact persisted incarnation before use.
354
359
  if (!processRef || processRef.incarnation !== captured.incarnation) return "ownership_changed";
360
+ if (signal === "SIGTERM" && processRef.termination === "hard") return "hard_termination";
361
+ try {
362
+ processRef.signalRoot(signal);
363
+ } catch {
364
+ return "already_gone";
365
+ }
366
+ return "signaled";
367
+ }
368
+
369
+ #currentConfigurationMatches(tokenFingerprintValue: string, chatId: string): boolean {
370
+ const current = getNotificationConfig(this.settings);
371
+ return (
372
+ isTelegramConfigured(current) &&
373
+ tokenFingerprint(current.botToken) === tokenFingerprintValue &&
374
+ current.chatId === chatId
375
+ );
376
+ }
377
+
378
+ async #signalAttestedLegacyOwner(
379
+ captured: AttestedLegacyDaemonOwner,
380
+ tokenFingerprint: string,
381
+ chatId: string,
382
+ signal: NodeJS.Signals,
383
+ ): Promise<"signaled" | "already_gone" | "ownership_changed" | "hard_termination"> {
384
+ if (!this.#currentConfigurationMatches(tokenFingerprint, chatId)) return "ownership_changed";
385
+ const current = await readAttestedLegacyDaemonOwner({
386
+ settings: this.settings,
387
+ fs: this.fsImpl,
388
+ now: this.now,
389
+ pidIncarnation: this.deps.pidIncarnation,
390
+ tokenFingerprint,
391
+ chatId,
392
+ });
393
+ if (
394
+ !current ||
395
+ current.state.pid !== captured.state.pid ||
396
+ current.state.ownerId !== captured.state.ownerId ||
397
+ current.state.startedAt !== captured.state.startedAt ||
398
+ current.incarnation !== captured.incarnation
399
+ )
400
+ return "ownership_changed";
401
+ if (!this.pidAlive(captured.state.pid)) return "already_gone";
402
+ const processRef = this.processReference(captured.state.pid);
403
+ if (!processRef || processRef.incarnation !== captured.incarnation) return "ownership_changed";
404
+ const rechecked = await readAttestedLegacyDaemonOwner({
405
+ settings: this.settings,
406
+ fs: this.fsImpl,
407
+ now: this.now,
408
+ pidIncarnation: this.deps.pidIncarnation,
409
+ tokenFingerprint,
410
+ chatId,
411
+ });
412
+ if (
413
+ !rechecked ||
414
+ rechecked.state.pid !== current.state.pid ||
415
+ rechecked.state.ownerId !== current.state.ownerId ||
416
+ rechecked.state.startedAt !== current.state.startedAt ||
417
+ rechecked.incarnation !== current.incarnation ||
418
+ !this.#currentConfigurationMatches(tokenFingerprint, chatId) ||
419
+ !this.pidAlive(captured.state.pid)
420
+ )
421
+ return "ownership_changed";
422
+ if (signal === "SIGTERM" && processRef.termination === "hard") return "hard_termination";
355
423
  try {
356
424
  processRef.signalRoot(signal);
357
425
  } catch {
@@ -376,7 +444,10 @@ export class TelegramDaemonController implements BuiltInDaemonController {
376
444
  return this.stopOrReload("reload", opts);
377
445
  }
378
446
 
379
- async reloadForGenerationUpgrade(opts: DaemonOperationOptions = {}): Promise<TelegramGenerationReloadResult> {
447
+ async reloadForGenerationUpgrade(
448
+ opts: DaemonOperationOptions = {},
449
+ attestedLegacyUpgrade = false,
450
+ ): Promise<TelegramGenerationReloadResult> {
380
451
  // A generation upgrade MUST replace an incompatible older-generation owner to
381
452
  // avoid a permanent single-poller deadlock. Unlike a manual `skc daemon
382
453
  // reload`, this automatic path force-escalates to SIGKILL when the old owner
@@ -384,7 +455,7 @@ export class TelegramDaemonController implements BuiltInDaemonController {
384
455
  // self-recovers instead of failing closed and asking the operator to rerun
385
456
  // with --force. The SIGKILL remains fenced to the still-live, still-matching
386
457
  // captured owner (same ownerId + pid), so a fresh replacement is never killed.
387
- const operation = await this.stopOrReload("reload", { ...opts, force: true });
458
+ const operation = await this.stopOrReload("reload", { ...opts, force: true }, attestedLegacyUpgrade);
388
459
  if (!operation.ok) return { outcome: "failed", operation };
389
460
  const after = await this.status();
390
461
  return after.health === "running" ? { outcome: "ready", operation } : { outcome: "failed", operation };
@@ -394,7 +465,11 @@ export class TelegramDaemonController implements BuiltInDaemonController {
394
465
  return this.stopOrReload("stop", opts);
395
466
  }
396
467
 
397
- private async stopOrReload(action: "stop" | "reload", opts: DaemonOperationOptions): Promise<DaemonOperationResult> {
468
+ private async stopOrReload(
469
+ action: "stop" | "reload",
470
+ opts: DaemonOperationOptions,
471
+ attestedLegacyUpgrade = false,
472
+ ): Promise<DaemonOperationResult> {
398
473
  const before = await this.status();
399
474
  const warnings: string[] = [];
400
475
  if (before.runtime.warning) warnings.push(before.runtime.warning);
@@ -408,7 +483,18 @@ export class TelegramDaemonController implements BuiltInDaemonController {
408
483
  const gracefulTimeoutMs = opts.gracefulTimeoutMs ?? DEFAULT_GRACEFUL_TIMEOUT_MS;
409
484
  const killTimeoutMs = opts.killTimeoutMs ?? DEFAULT_KILL_TIMEOUT_MS;
410
485
 
411
- const state = await readDaemonState(this.settings, this.fsImpl);
486
+ const ownerSnapshot = await readOwnerFreshnessSnapshot({ settings: this.settings, fs: this.fsImpl });
487
+ const state = ownerSnapshot.state;
488
+ const attestedLegacyOwner = attestedLegacyUpgrade
489
+ ? await readAttestedLegacyDaemonOwner({
490
+ settings: this.settings,
491
+ fs: this.fsImpl,
492
+ now: this.now,
493
+ pidIncarnation: this.deps.pidIncarnation,
494
+ tokenFingerprint: fp,
495
+ chatId,
496
+ })
497
+ : undefined;
412
498
  const replaceableLiveOwner =
413
499
  (action === "reload" &&
414
500
  state !== undefined &&
@@ -419,6 +505,7 @@ export class TelegramDaemonController implements BuiltInDaemonController {
419
505
  chatId,
420
506
  pidAlive: this.pidAlive,
421
507
  pidIncarnation: this.deps.pidIncarnation,
508
+ effectiveHeartbeatAt: ownerSnapshot.effectiveHeartbeatAt,
422
509
  }) &&
423
510
  isSignalableMatchingOwner({
424
511
  state,
@@ -427,6 +514,7 @@ export class TelegramDaemonController implements BuiltInDaemonController {
427
514
  pidAlive: this.pidAlive,
428
515
  pidIncarnation: this.deps.pidIncarnation,
429
516
  })) ||
517
+ (action === "reload" && attestedLegacyOwner !== undefined && this.pidAlive(attestedLegacyOwner.state.pid)) ||
430
518
  // A physically-live matching owner whose heartbeat is stale (hung) may be
431
519
  // past-TTL yet still holding the poller. Autostart/generation-upgrade reloads
432
520
  // stay conservative and refuse it, but an explicit `reload --force` must be
@@ -483,16 +571,18 @@ export class TelegramDaemonController implements BuiltInDaemonController {
483
571
  }
484
572
 
485
573
  // Running owner: capture identity, request cooperative stop, signal, wait.
486
- if (
487
- !hasSafeDaemonStateShape(state) ||
488
- !isSignalableMatchingOwner({
574
+ const modernCapturedOwner =
575
+ hasSafeDaemonStateShape(state) &&
576
+ isSignalableMatchingOwner({
489
577
  state,
490
578
  tokenFingerprint: fp,
491
579
  chatId,
492
580
  pidAlive: this.pidAlive,
493
581
  pidIncarnation: this.deps.pidIncarnation,
494
582
  })
495
- ) {
583
+ ? state
584
+ : undefined;
585
+ if (!modernCapturedOwner && !attestedLegacyOwner) {
496
586
  return this.result(
497
587
  action,
498
588
  false,
@@ -502,7 +592,7 @@ export class TelegramDaemonController implements BuiltInDaemonController {
502
592
  warnings,
503
593
  );
504
594
  }
505
- const capturedOwner = state;
595
+ const capturedOwner = modernCapturedOwner ?? attestedLegacyOwner!.state;
506
596
  const oldOwnerId = capturedOwner.ownerId;
507
597
  const oldPid = capturedOwner.pid;
508
598
  const requestId = this.deps.randomId?.() ?? `${this.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
@@ -511,7 +601,21 @@ export class TelegramDaemonController implements BuiltInDaemonController {
511
601
  { version: 1, requestId, action, ownerId: oldOwnerId, pid: oldPid, createdAt: this.now() },
512
602
  this.fsImpl,
513
603
  );
514
- if ((await this.signalCapturedOwner(capturedOwner, fp, chatId, "SIGTERM")) === "ownership_changed") {
604
+ const signalResult = attestedLegacyOwner
605
+ ? await this.#signalAttestedLegacyOwner(attestedLegacyOwner, fp, chatId, "SIGTERM")
606
+ : await this.signalCapturedOwner(modernCapturedOwner!, fp, chatId, "SIGTERM");
607
+ if (signalResult === "hard_termination") {
608
+ await this.clearOwnRequest(requestId);
609
+ return this.result(
610
+ action,
611
+ false,
612
+ "telegram daemon has hard process authority; refusing cooperative SIGTERM",
613
+ before,
614
+ await this.status(),
615
+ warnings,
616
+ );
617
+ }
618
+ if (signalResult === "ownership_changed") {
515
619
  await this.clearOwnRequest(requestId);
516
620
  return this.result(
517
621
  action,
@@ -529,7 +633,8 @@ export class TelegramDaemonController implements BuiltInDaemonController {
529
633
  let dead = await this.waitForPidDeath(oldPid, gracefulTimeoutMs);
530
634
  if (!dead) {
531
635
  // Old pid still alive after the cooperative SIGTERM. Inspect current ownership.
532
- const current = await readDaemonState(this.settings, this.fsImpl);
636
+ const currentSnapshot = await readOwnerFreshnessSnapshot({ settings: this.settings, fs: this.fsImpl });
637
+ const current = currentSnapshot.state;
533
638
  const changedToLiveOwner =
534
639
  current !== undefined &&
535
640
  current.ownerId !== oldOwnerId &&
@@ -540,6 +645,7 @@ export class TelegramDaemonController implements BuiltInDaemonController {
540
645
  chatId,
541
646
  pidAlive: this.pidAlive,
542
647
  pidIncarnation: this.deps.pidIncarnation,
648
+ effectiveHeartbeatAt: currentSnapshot.effectiveHeartbeatAt,
543
649
  });
544
650
  if (changedToLiveOwner) {
545
651
  await this.clearOwnRequest(requestId);
@@ -559,7 +665,9 @@ export class TelegramDaemonController implements BuiltInDaemonController {
559
665
  // the captured owner/pid still matches, so we never kill a different owner.
560
666
  const stillSameOwner = current !== undefined && current.ownerId === oldOwnerId && current.pid === oldPid;
561
667
  if (opts.force && stillSameOwner) {
562
- const killResult = await this.signalCapturedOwner(capturedOwner, fp, chatId, "SIGKILL");
668
+ const killResult = attestedLegacyOwner
669
+ ? await this.#signalAttestedLegacyOwner(attestedLegacyOwner, fp, chatId, "SIGKILL")
670
+ : await this.signalCapturedOwner(modernCapturedOwner!, fp, chatId, "SIGKILL");
563
671
  // Kill only a still-live matching owner; an owner that exited between the
564
672
  // graceful timeout and this recheck ("already_gone") is confirmed dead by
565
673
  // waitForPidDeath, while a real ownership change stays fenced.
@@ -585,11 +693,23 @@ export class TelegramDaemonController implements BuiltInDaemonController {
585
693
  return this.result(action, true, "stopped telegram daemon", before, after, warnings);
586
694
  }
587
695
 
696
+ if (!this.#currentConfigurationMatches(fp, chatId)) {
697
+ const after = await this.status();
698
+ return this.result(
699
+ action,
700
+ false,
701
+ "telegram notification configuration changed during reload; refusing to spawn",
702
+ before,
703
+ after,
704
+ warnings,
705
+ );
706
+ }
588
707
  const { spawned, ready } = await this.spawnAndWait(roots, fp, chatId);
589
708
  warnings.push(...spawned.warnings);
590
709
  const after = await this.status();
591
710
  if (spawned.result === "attached") {
592
- const attachedState = await readDaemonState(this.settings, this.fsImpl);
711
+ const attachedSnapshot = await readOwnerFreshnessSnapshot({ settings: this.settings, fs: this.fsImpl });
712
+ const attachedState = attachedSnapshot.state;
593
713
  if (
594
714
  !isCurrentCompatibleOwner({
595
715
  state: attachedState,
@@ -598,6 +718,7 @@ export class TelegramDaemonController implements BuiltInDaemonController {
598
718
  chatId,
599
719
  pidAlive: this.pidAlive,
600
720
  pidIncarnation: this.deps.pidIncarnation,
721
+ effectiveHeartbeatAt: attachedSnapshot.effectiveHeartbeatAt,
601
722
  })
602
723
  ) {
603
724
  return this.result(