@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
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Product-surface dogfood for #2901 repository binding.
3
+ *
4
+ * Creates two sibling git repos, runs real `skc ultragoal` / `skc ralplan`
5
+ * CLI entrypoints from source, and prints fail-closed mismatch evidence.
6
+ *
7
+ * Usage (from monorepo root):
8
+ * bun packages/coding-agent/scripts/dogfood-repository-binding.ts
9
+ */
10
+ import * as fsp from "node:fs/promises";
11
+ import * as os from "node:os";
12
+ import * as path from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import {
15
+ assertCwdMatchesRepositoryBinding,
16
+ assertPathUnderRepositoryBinding,
17
+ parseRepositoryBinding,
18
+ resolveTaskRepositoryBinding,
19
+ } from "../src/skc-runtime/repository-binding";
20
+ import { readUltragoalPlan, startNextUltragoalGoal } from "../src/skc-runtime/ultragoal-runtime";
21
+
22
+ const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../..");
23
+ const cli = path.join(repoRoot, "packages/coding-agent/src/cli.ts");
24
+
25
+ async function runGit(cwd: string, args: string[]): Promise<void> {
26
+ const proc = Bun.spawn(["git", ...args], { cwd, stdout: "pipe", stderr: "pipe" });
27
+ const code = await proc.exited;
28
+ if (code !== 0) throw new Error(`git ${args.join(" ")} failed: ${await new Response(proc.stderr).text()}`);
29
+ }
30
+
31
+ async function initRepo(root: string): Promise<void> {
32
+ await fsp.mkdir(root, { recursive: true });
33
+ await runGit(root, ["init"]);
34
+ await runGit(root, ["config", "user.email", "dogfood@example.com"]);
35
+ await runGit(root, ["config", "user.name", "Dogfood"]);
36
+ await fsp.writeFile(path.join(root, "README.md"), `repo ${path.basename(root)}\n`);
37
+ await runGit(root, ["add", "README.md"]);
38
+ await runGit(root, ["commit", "-m", `init ${path.basename(root)}`]);
39
+ }
40
+
41
+ async function runCli(
42
+ cwd: string,
43
+ args: string[],
44
+ env: NodeJS.ProcessEnv,
45
+ ): Promise<{ code: number; stdout: string; stderr: string }> {
46
+ const proc = Bun.spawn(["bun", cli, ...args], { cwd, env, stdout: "pipe", stderr: "pipe" });
47
+ const [code, stdout, stderr] = await Promise.all([
48
+ proc.exited,
49
+ new Response(proc.stdout).text(),
50
+ new Response(proc.stderr).text(),
51
+ ]);
52
+ return { code, stdout, stderr };
53
+ }
54
+
55
+ async function main(): Promise<void> {
56
+ const dogfoodRoot = await fsp.mkdtemp(path.join(os.tmpdir(), "skc-dogfood-2901-"));
57
+ const left = path.join(dogfoodRoot, "sayknow-cli");
58
+ const right = path.join(dogfoodRoot, "oh-my-openagent-senpi");
59
+ await initRepo(left);
60
+ await initRepo(right);
61
+
62
+ const sessionId = `dogfood-2901-${process.pid}`;
63
+ const env = { ...process.env, SKC_SESSION_ID: sessionId };
64
+
65
+ console.log("# Dogfood: repository binding (#2901)");
66
+ console.log(`root=${dogfoodRoot}`);
67
+ console.log(`left=${left}`);
68
+ console.log(`right=${right}`);
69
+ console.log(`session=${sessionId}`);
70
+ console.log(`cli=${cli}`);
71
+ console.log(`bun=${Bun.version}`);
72
+ console.log(
73
+ `commit=${Bun.spawnSync(["git", "-C", repoRoot, "rev-parse", "--short", "HEAD"]).stdout.toString().trim()}`,
74
+ );
75
+ console.log();
76
+
77
+ // 1) Product CLI: create goals stamps binding
78
+ const create = await runCli(
79
+ left,
80
+ [
81
+ "ultragoal",
82
+ "create-goals",
83
+ "--brief",
84
+ "@goal dogfood binding\nProve repository binding stamps and fail-closed sibling mismatch.",
85
+ "--json",
86
+ ],
87
+ env,
88
+ );
89
+ console.log("## 1) skc ultragoal create-goals (LEFT)");
90
+ console.log(`exit=${create.code}`);
91
+ console.log(create.stdout.trim() || create.stderr.trim());
92
+ if (create.code !== 0) process.exit(1);
93
+
94
+ const plan = await readUltragoalPlan(left, sessionId);
95
+ if (!plan?.repositoryBinding) {
96
+ console.error("FAIL: plan missing repositoryBinding");
97
+ process.exit(1);
98
+ }
99
+ console.log();
100
+ console.log("## 2) goals.json repositoryBinding");
101
+ console.log(JSON.stringify(plan.repositoryBinding, null, 2));
102
+
103
+ // 2) Matching cwd starts goal
104
+ console.log();
105
+ console.log("## 3) startNextUltragoalGoal on LEFT (match)");
106
+ const started = await startNextUltragoalGoal({ cwd: left, sessionId });
107
+ console.log(`ok goal=${started.goal?.id} status=${started.goal?.status}`);
108
+
109
+ // 3) Sibling mismatch fails closed
110
+ console.log();
111
+ console.log("## 4) assertCwdMatchesRepositoryBinding on RIGHT (sibling)");
112
+ try {
113
+ await assertCwdMatchesRepositoryBinding(right, plan.repositoryBinding);
114
+ console.error("FAIL: expected identity_mismatch");
115
+ process.exit(1);
116
+ } catch (error) {
117
+ console.log(`fail_closed: ${error instanceof Error ? error.message : String(error)}`);
118
+ }
119
+
120
+ // 4) Path escape fails closed
121
+ console.log();
122
+ console.log("## 5) assertPathUnderRepositoryBinding sibling absolute path");
123
+ try {
124
+ assertPathUnderRepositoryBinding(plan.repositoryBinding, path.join(right, "README.md"));
125
+ console.error("FAIL: expected path_outside_root");
126
+ process.exit(1);
127
+ } catch (error) {
128
+ console.log(`fail_closed: ${error instanceof Error ? error.message : String(error)}`);
129
+ }
130
+
131
+ // 5) Task binding stamp + sibling fail-closed (pre-discovery authority)
132
+ console.log();
133
+ console.log("## 6) task binding stamp (omit declaration) + sibling reject");
134
+ const stamped = await resolveTaskRepositoryBinding(left, undefined);
135
+ console.log(`stamped_worktreeRoot=${stamped.worktreeRoot}`);
136
+ await assertCwdMatchesRepositoryBinding(left, stamped);
137
+ console.log("task_stamp_ok on LEFT");
138
+ const taskBinding = parseRepositoryBinding(plan.repositoryBinding);
139
+ try {
140
+ await resolveTaskRepositoryBinding(right, taskBinding);
141
+ console.error("FAIL: task binding should reject RIGHT");
142
+ process.exit(1);
143
+ } catch (error) {
144
+ console.log(`task_binding_fail_closed on RIGHT: ${error instanceof Error ? error.message : String(error)}`);
145
+ }
146
+
147
+ // 6) Ralplan seed stamps binding via product CLI
148
+ console.log();
149
+ console.log("## 7) skc ralplan seed (LEFT)");
150
+ const ralplan = await runCli(left, ["ralplan", "--json", "dogfood multi-repo binding"], env);
151
+ console.log(`exit=${ralplan.code}`);
152
+ console.log(ralplan.stdout.trim() || ralplan.stderr.trim());
153
+ if (ralplan.code !== 0) process.exit(1);
154
+ const statePath = path.join(left, ".skc", `_session-${sessionId}`, "state", "ralplan-state.json");
155
+ const state = JSON.parse(await fsp.readFile(statePath, "utf8")) as {
156
+ repository_binding?: unknown;
157
+ run_id?: string;
158
+ };
159
+ console.log();
160
+ console.log("## 8) ralplan-state.json repository_binding");
161
+ console.log(JSON.stringify({ run_id: state.run_id, repository_binding: state.repository_binding }, null, 2));
162
+ if (!state.repository_binding) {
163
+ console.error("FAIL: ralplan state missing repository_binding");
164
+ process.exit(1);
165
+ }
166
+
167
+ // 7) Ralplan stage write on LEFT succeeds and echoes repository_binding
168
+ console.log();
169
+ console.log("## 9) skc ralplan --write planner on LEFT (match)");
170
+ const notePath = path.join(left, "dogfood-planner.md");
171
+ await fsp.writeFile(notePath, "# dogfood planner\n");
172
+ const writeLeft = await runCli(
173
+ left,
174
+ ["ralplan", "--write", "--stage", "planner", "--stage_n", "1", "--artifact", notePath, "--json"],
175
+ env,
176
+ );
177
+ console.log(`exit=${writeLeft.code}`);
178
+ console.log(writeLeft.stdout.trim() || writeLeft.stderr.trim());
179
+ if (writeLeft.code !== 0) process.exit(1);
180
+ const writePayload = JSON.parse(writeLeft.stdout) as { repository_binding?: { worktreeRoot?: string } };
181
+ if (!writePayload.repository_binding?.worktreeRoot) {
182
+ console.error("FAIL: write receipt missing repository_binding");
183
+ process.exit(1);
184
+ }
185
+
186
+ // 8) Copy seed authority into RIGHT session layout → stage write fails closed
187
+ console.log();
188
+ console.log("## 10) ralplan --write on RIGHT with LEFT binding (fail-closed)");
189
+ const rightStateDir = path.join(right, ".skc", `_session-${sessionId}`, "state");
190
+ await fsp.mkdir(rightStateDir, { recursive: true });
191
+ await fsp.copyFile(statePath, path.join(rightStateDir, "ralplan-state.json"));
192
+ const writeRight = await runCli(
193
+ right,
194
+ ["ralplan", "--write", "--stage", "architect", "--stage_n", "1", "--artifact", "# arch\n", "--json"],
195
+ env,
196
+ );
197
+ console.log(`exit=${writeRight.code}`);
198
+ console.log((writeRight.stderr || writeRight.stdout).trim());
199
+ if (writeRight.code === 0) {
200
+ console.error("FAIL: expected sibling write to fail closed");
201
+ process.exit(1);
202
+ }
203
+ console.log("fail_closed: ralplan write on sibling rejected");
204
+
205
+ console.log();
206
+ console.log("DOGFOOD_OK");
207
+ }
208
+
209
+ await main();
@@ -3,6 +3,7 @@
3
3
  import * as fs from "node:fs/promises";
4
4
  import * as path from "node:path";
5
5
  import { Glob } from "bun";
6
+ import { isEmbeddableDoc } from "../../../scripts/docs-index-contract";
6
7
 
7
8
  async function pathExists(candidate: string): Promise<boolean> {
8
9
  try {
@@ -40,7 +41,9 @@ if (docsDir === undefined) {
40
41
  const glob = new Glob("**/*.md");
41
42
  const entries: string[] = [];
42
43
  for await (const relativePath of glob.scan(docsDir)) {
43
- entries.push(relativePath.split(path.sep).join("/"));
44
+ const rel = relativePath.split(path.sep).join("/");
45
+ if (!isEmbeddableDoc(rel)) continue;
46
+ entries.push(rel);
44
47
  }
45
48
  entries.sort();
46
49
 
@@ -39,6 +39,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
39
39
  "agent_session:setForcedToolChoice": "internal accessor/plumbing, not a user-facing control seam",
40
40
  "agent_session:getActiveSkillState": "internal accessor/plumbing, not a user-facing control seam",
41
41
  "agent_session:getActiveSkillPhase": "internal accessor/plumbing, not a user-facing control seam",
42
+ "agent_session:getDeepInterviewAskStage":
43
+ "internal AskTool schema-selection accessor, not a user-facing SDK control seam",
42
44
  "agent_session:peekQueueInvoker": "internal accessor/plumbing, not a user-facing control seam",
43
45
  "agent_session:peekStandingResolveHandler": "internal accessor/plumbing, not a user-facing control seam",
44
46
  "agent_session:setStandingResolveHandler": "internal accessor/plumbing, not a user-facing control seam",
@@ -68,6 +70,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
68
70
  "agent_session:getAsyncDeliveryStateForAcp":
69
71
  "internal ACP lifecycle quiescence plumbing, not a user-facing control seam",
70
72
  "agent_session:getToolByName": "internal accessor/plumbing, not a user-facing control seam",
73
+ "agent_session:getToolForExecution": "internal accessor/plumbing, not a user-facing control seam",
71
74
  "agent_session:registerForegroundBashBackgroundRequestHandler":
72
75
  "internal accessor/plumbing, not a user-facing control seam",
73
76
  "agent_session:hasForegroundBashBackgroundRequestHandler":
@@ -83,6 +86,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
83
86
  "agent_session:refreshMCPTools": "internal accessor/plumbing, not a user-facing control seam",
84
87
  "agent_session:refreshSkcSubskillTools": "internal accessor/plumbing, not a user-facing control seam",
85
88
  "agent_session:buildDisplaySessionContext": "internal accessor/plumbing, not a user-facing control seam",
89
+ "agent_session:buildPreparedDisplaySessionContext": "internal accessor/plumbing, not a user-facing control seam",
86
90
  "agent_session:convertMessagesToLlm": "internal accessor/plumbing, not a user-facing control seam",
87
91
  "agent_session:prepareSimpleStreamOptions": "internal accessor/plumbing, not a user-facing control seam",
88
92
  "agent_session:getPlanModeState": "internal accessor/plumbing, not a user-facing control seam",
@@ -115,6 +119,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
115
119
  "agent_session:continuePersistedHistory": "internal startup lifecycle plumbing, not a user-facing control seam",
116
120
  "agent_session:promoteRecoveryHydrationAfterOwnershipReadyFence":
117
121
  "internal owner-recovery authority transition after a durable writer fence, never a user-facing SDK operation",
122
+ "agent_session:restoreFromMemoryGuardCheckpoint":
123
+ "internal owner-recovery staged restore builder after durable claims/fencing, never a user-facing SDK operation",
118
124
  "agent_session:setActiveModelProfile": "internal accessor/plumbing, not a user-facing control seam",
119
125
  "agent_session:getActiveModelProfile": "internal accessor/plumbing, not a user-facing control seam",
120
126
  "agent_session:getSessionDefaultModelSelector": "internal accessor/plumbing, not a user-facing control seam",
@@ -147,6 +153,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
147
153
  "agent_session:prepareContributionPrep": "internal accessor/plumbing, not a user-facing control seam",
148
154
  "agent_session:setResourceSampler": "internal accessor/plumbing, not a user-facing control seam",
149
155
  "agent_session:setRetainedMemorySampler": "internal accessor/plumbing, not a user-facing control seam",
156
+ "agent_session:createBtwConversationScope":
157
+ "internal privacy-scoped side-chat snapshot factory, not a user-facing SDK control seam",
150
158
  "agent_session:recordBashResult": "internal accessor/plumbing, not a user-facing control seam",
151
159
  "agent_session:executePython": "internal accessor/plumbing, not a user-facing control seam",
152
160
  "agent_session:assertEvalExecutionAllowed": "internal accessor/plumbing, not a user-facing control seam",
@@ -193,6 +201,7 @@ const SEAM_TO_SDK: Readonly<Record<string, string>> = {
193
201
  "agent_session:setSessionName": "session.rename",
194
202
  "agent_session:setModel": "model.set",
195
203
  "agent_session:setDefaultModelSelection": "model.set",
204
+ "agent_session:activateModelProfileForControl": "model.profile.set",
196
205
  "agent_session:cycleModel": "model.cycle",
197
206
  "agent_session:setThinkingLevel": "thinking.set",
198
207
  "agent_session:cycleThinkingLevel": "thinking.cycle",
@@ -36,6 +36,8 @@ try {
36
36
  function validateRowReceipts(rows: ManifestAdapterRow[]): void {
37
37
  const ids = new Set<string>();
38
38
  const counts = new Map<string, number>();
39
+ // Each operation has one receipt, plus the dedicated config.patch secret-input receipt.
40
+ const expectedRowsPerAdapter = OPERATIONS.length + 1;
39
41
  for (const row of rows) {
40
42
  if (ids.has(row.adapterTestId)) throw new Error(`Duplicate adapter test ID: ${row.adapterTestId}`);
41
43
  ids.add(row.adapterTestId);
@@ -60,11 +62,11 @@ function validateRowReceipts(rows: ManifestAdapterRow[]): void {
60
62
  }
61
63
  counts.set(row.adapter, (counts.get(row.adapter) ?? 0) + 1);
62
64
  }
63
- if (rows.length !== ADAPTERS.length * 91)
64
- throw new Error(`Expected ${ADAPTERS.length * 91} adapter rows; received ${rows.length}.`);
65
+ if (rows.length !== ADAPTERS.length * expectedRowsPerAdapter)
66
+ throw new Error(`Expected ${ADAPTERS.length * expectedRowsPerAdapter} adapter rows; received ${rows.length}.`);
65
67
  for (const adapter of ADAPTERS) {
66
- if (counts.get(adapter) !== 91)
67
- throw new Error(`Expected 91 ${adapter} rows; received ${counts.get(adapter) ?? 0}.`);
68
+ if (counts.get(adapter) !== expectedRowsPerAdapter)
69
+ throw new Error(`Expected ${expectedRowsPerAdapter} ${adapter} rows; received ${counts.get(adapter) ?? 0}.`);
68
70
  }
69
71
  process.stdout.write(
70
72
  `manifest check: ${rows.length} row receipts (${[...counts].map(([adapter, count]) => `${adapter}=${count}`).join(", ")})\n`,
@@ -1421,13 +1421,107 @@ function braceBlockRange(contents: string, openingBrace: number): ShellRange | u
1421
1421
  return undefined;
1422
1422
  }
1423
1423
 
1424
- function exactTeamRuntimeSendKeysRanges(contents: string): ShellRange[] {
1425
- const guardMatches = [...contents.matchAll(/if\s*\(\s*useSendKeysFallback\s*\)\s*\{/g)];
1424
+ function scopeMatches<T extends RegExpMatchArray>(matches: T[], range: ShellRange): T[] {
1425
+ return matches.filter(match => {
1426
+ const index = match.index ?? -1;
1427
+ return index >= range.start && index < range.end;
1428
+ });
1429
+ }
1430
+
1431
+ function findFunctionRange(contents: string, headerPattern: RegExp): ShellRange | undefined {
1432
+ const header = headerPattern.exec(contents);
1433
+ if (!header) return undefined;
1434
+ const openingBrace = (header.index ?? 0) + header[0].lastIndexOf("{");
1435
+ return braceBlockRange(contents, openingBrace);
1436
+ }
1437
+
1438
+ /**
1439
+ * `relaunchWorkerPaneForMemoryGuard` intentionally re-runs the same sanctioned
1440
+ * tmux send-keys fallback shape as `startTmuxSession` (see
1441
+ * `exactTeamRuntimeSendKeysRanges` below) but through `input.config` /
1442
+ * `newPaneId` instead of `config` / `paneId`, since it dispatches a single
1443
+ * successor pane rather than looping over `config.workers`. Exact-match its
1444
+ * shape the same way so a second legitimate call site does not get treated as
1445
+ * an unsanctioned duplicate.
1446
+ */
1447
+ function exactMemoryGuardSendKeysRanges(contents: string): ShellRange[] {
1448
+ const fnRange = findFunctionRange(
1449
+ contents,
1450
+ /async\s+function\s+relaunchWorkerPaneForMemoryGuard\s*\([\s\S]{0,600}?\)\s*:\s*Promise<string>\s*\{/,
1451
+ );
1452
+ if (!fnRange) return [];
1453
+ const body = contents.slice(fnRange.start, fnRange.end);
1454
+ const guardMatches = [...body.matchAll(/if\s*\(\s*useSendKeysFallback\s*\)\s*\{/g)];
1426
1455
  const payloadMatches = [
1427
- ...contents.matchAll(
1428
- /Bun\.spawnSync\(\s*\[\s*config\.tmux_command\s*,\s*["']send-keys["']\s*,\s*["']-l["']\s*,\s*["']-t["']\s*,\s*paneId\s*,\s*workerCommand\s*\]\s*,\s*\{[\s\S]{0,200}?stdout\s*:\s*["']ignore["'][\s\S]{0,200}?stderr\s*:\s*["']ignore["'][\s\S]{0,100}?\}\s*\)\s*;/g,
1456
+ ...body.matchAll(
1457
+ /Bun\.spawnSync\(\s*\[\s*input\.config\.tmux_command\s*,\s*["']send-keys["']\s*,\s*["']-l["']\s*,\s*["']-t["']\s*,\s*newPaneId\s*,\s*workerCommand\s*\]\s*,\s*\{[\s\S]{0,200}?stdout\s*:\s*["']ignore["'][\s\S]{0,200}?stderr\s*:\s*["']ignore["'][\s\S]{0,100}?\}\s*\)\s*;/g,
1458
+ ),
1459
+ ];
1460
+ const enterMatches = [
1461
+ ...body.matchAll(
1462
+ /Bun\.spawnSync\(\s*\[\s*input\.config\.tmux_command\s*,\s*["']send-keys["']\s*,\s*["']-t["']\s*,\s*newPaneId\s*,\s*["']Enter["']\s*\]\s*,\s*\{[\s\S]{0,200}?stdout\s*:\s*["']ignore["'][\s\S]{0,200}?stderr\s*:\s*["']ignore["'][\s\S]{0,100}?\}\s*\)\s*;/g,
1429
1463
  ),
1430
1464
  ];
1465
+ const useFallbackMatches = [
1466
+ ...body.matchAll(
1467
+ /const\s+useSendKeysFallback\s*=\s*shouldDispatchWorkerWithSendKeys\(input\.config\.tmux_command\s*,\s*input\.platform\)\s*;/g,
1468
+ ),
1469
+ ];
1470
+ const splitWorkerCommandMatches = [
1471
+ ...body.matchAll(/\.\.\.\(useSendKeysFallback\s*\?\s*\[\]\s*:\s*\[workerCommand\]\)\s*,/g),
1472
+ ];
1473
+ if (
1474
+ guardMatches.length !== 1 ||
1475
+ payloadMatches.length !== 1 ||
1476
+ enterMatches.length !== 1 ||
1477
+ useFallbackMatches.length !== 1 ||
1478
+ splitWorkerCommandMatches.length !== 1
1479
+ )
1480
+ return [];
1481
+ const guardStart = guardMatches[0].index ?? 0;
1482
+ const payloadStart = payloadMatches[0].index ?? 0;
1483
+ const enterStart = enterMatches[0].index ?? 0;
1484
+ if (
1485
+ (useFallbackMatches[0].index ?? 0) >= (splitWorkerCommandMatches[0].index ?? 0) ||
1486
+ (splitWorkerCommandMatches[0].index ?? 0) >= guardStart ||
1487
+ payloadStart >= enterStart
1488
+ )
1489
+ return [];
1490
+ const guard = guardMatches[0];
1491
+ const openingBrace = (guard.index ?? 0) + guard[0].lastIndexOf("{");
1492
+ const range = braceBlockRange(body, openingBrace);
1493
+ if (
1494
+ !range ||
1495
+ payloadStart < range.start ||
1496
+ payloadStart >= range.end ||
1497
+ enterStart < range.start ||
1498
+ enterStart >= range.end
1499
+ )
1500
+ return [];
1501
+ return [
1502
+ { start: fnRange.start + payloadStart, end: fnRange.start + payloadStart + payloadMatches[0][0].length },
1503
+ { start: fnRange.start + enterStart, end: fnRange.start + enterStart + enterMatches[0][0].length },
1504
+ ];
1505
+ }
1506
+ function exactTeamRuntimeSendKeysRanges(contents: string): ShellRange[] {
1507
+ // Scope the loop-dispatch counts to `startTmuxSession` so the second
1508
+ // sanctioned call site (`relaunchWorkerPaneForMemoryGuard`, matched by
1509
+ // `exactMemoryGuardSendKeysRanges`) does not read as a duplicate. Fixtures
1510
+ // that carry the canonical shape without the enclosing function keep the
1511
+ // original whole-file scope, so exact-match strictness is unchanged.
1512
+ const mainFnRange = findFunctionRange(
1513
+ contents,
1514
+ /async\s+function\s+startTmuxSession\s*\([\s\S]{0,600}?\)\s*:\s*Promise<SkcTeamWorker\[\]>\s*\{/,
1515
+ ) ?? { start: 0, end: contents.length };
1516
+ const guardMatches = scopeMatches([...contents.matchAll(/if\s*\(\s*useSendKeysFallback\s*\)\s*\{/g)], mainFnRange);
1517
+ const payloadMatches = scopeMatches(
1518
+ [
1519
+ ...contents.matchAll(
1520
+ /Bun\.spawnSync\(\s*\[\s*config\.tmux_command\s*,\s*["']send-keys["']\s*,\s*["']-l["']\s*,\s*["']-t["']\s*,\s*paneId\s*,\s*workerCommand\s*\]\s*,\s*\{[\s\S]{0,200}?stdout\s*:\s*["']ignore["'][\s\S]{0,200}?stderr\s*:\s*["']ignore["'][\s\S]{0,100}?\}\s*\)\s*;/g,
1521
+ ),
1522
+ ],
1523
+ mainFnRange,
1524
+ );
1431
1525
  const continuationPromptMatches = [
1432
1526
  ...contents.matchAll(
1433
1527
  /(?:const\s+SKC_TEAM_CONTINUATION_PROMPT\s*=\s*["']Continue only your current claimed SKC team task\. Re-read current SKC team state; do not replay prior output; report status\.["']\s*;|import\s*\{[\s\S]{0,1000}?\bSKC_TEAM_CONTINUATION_PROMPT\b[\s\S]{0,1000}?\}\s*from\s*["']\.\/team-workers["']\s*;)/g,
@@ -1438,24 +1532,31 @@ function exactTeamRuntimeSendKeysRanges(contents: string): ShellRange[] {
1438
1532
  /const\s+args\s*=\s*Object\.freeze\(\s*\[\s*["']send-keys["']\s*,\s*["']-l["']\s*,\s*["']-t["']\s*,\s*worker\.pane_id\s*,\s*SKC_TEAM_CONTINUATION_PROMPT\s*,\s*["'];["']\s*,\s*["']send-keys["']\s*,\s*["']-t["']\s*,\s*worker\.pane_id\s*,\s*["']Enter["']\s*,?\s*\]\s*\)\s*;\s*const\s+dispatch\s*=\s*skcTeamRuntimeTestSeams\?\.continuationTmuxDispatch\s*\?\s*skcTeamRuntimeTestSeams\.continuationTmuxDispatch\(config\.tmux_command\s*,\s*args\)\s*:\s*Bun\.spawnSync\(\[config\.tmux_command\s*,\s*\.\.\.args\]\s*,\s*\{\s*stdout\s*:\s*["']ignore["']\s*,\s*stderr\s*:\s*["']ignore["']\s*,\s*timeout\s*:\s*SKC_TEAM_CONTINUATION_DISPATCH_TIMEOUT_MS\s*,?\s*\}\s*\)\s*;/g,
1439
1533
  ),
1440
1534
  ];
1441
- const enterMatches = [
1442
- ...contents.matchAll(
1443
- /const\s+sendKeys\s*=\s*Bun\.spawnSync\(\s*\[\s*config\.tmux_command\s*,\s*["']send-keys["']\s*,\s*["']-t["']\s*,\s*paneId\s*,\s*["']Enter["']\s*\]\s*,\s*\{[\s\S]{0,200}?stdout\s*:\s*["']ignore["'][\s\S]{0,200}?stderr\s*:\s*["']ignore["'][\s\S]{0,100}?\}\s*\)\s*;/g,
1444
- ),
1445
- ];
1535
+ const enterMatches = scopeMatches(
1536
+ [
1537
+ ...contents.matchAll(
1538
+ /const\s+sendKeys\s*=\s*Bun\.spawnSync\(\s*\[\s*config\.tmux_command\s*,\s*["']send-keys["']\s*,\s*["']-t["']\s*,\s*paneId\s*,\s*["']Enter["']\s*\]\s*,\s*\{[\s\S]{0,200}?stdout\s*:\s*["']ignore["'][\s\S]{0,200}?stderr\s*:\s*["']ignore["'][\s\S]{0,100}?\}\s*\)\s*;/g,
1539
+ ),
1540
+ ],
1541
+ mainFnRange,
1542
+ );
1446
1543
  const fallbackPredicateMatches = [
1447
1544
  ...contents.matchAll(
1448
1545
  /function\s+shouldDispatchWorkerWithSendKeys\([^)]*\)\s*:\s*boolean\s*\{\s*return\s+platform\s*===\s*["']win32["']\s*\|\|\s*path\.basename\(tmuxCommand\)\.toLowerCase\(\)\s*===\s*["']psmux["']\s*;\s*\}/g,
1449
1546
  ),
1450
1547
  ];
1451
- const useFallbackMatches = [
1452
- ...contents.matchAll(
1453
- /const\s+useSendKeysFallback\s*=\s*shouldDispatchWorkerWithSendKeys\(config\.tmux_command\)\s*;/g,
1454
- ),
1455
- ];
1456
- const splitWorkerCommandMatches = [
1457
- ...contents.matchAll(/\.\.\.\(useSendKeysFallback\s*\?\s*\[\]\s*:\s*\[workerCommand\]\)\s*,/g),
1458
- ];
1548
+ const useFallbackMatches = scopeMatches(
1549
+ [
1550
+ ...contents.matchAll(
1551
+ /const\s+useSendKeysFallback\s*=\s*shouldDispatchWorkerWithSendKeys\(config\.tmux_command\)\s*;/g,
1552
+ ),
1553
+ ],
1554
+ mainFnRange,
1555
+ );
1556
+ const splitWorkerCommandMatches = scopeMatches(
1557
+ [...contents.matchAll(/\.\.\.\(useSendKeysFallback\s*\?\s*\[\]\s*:\s*\[workerCommand\]\)\s*,/g)],
1558
+ mainFnRange,
1559
+ );
1459
1560
  if (
1460
1561
  guardMatches.length !== 1 ||
1461
1562
  payloadMatches.length !== 1 ||
@@ -1543,7 +1644,10 @@ function isTypeOnlyTmuxPrimitiveOccurrence(contents: string, occurrence: TmuxPri
1543
1644
 
1544
1645
  function tmuxMachineBusViolations(file: string, contents: string): string[] {
1545
1646
  if (isGeneratedDocumentationIndex(file)) return [];
1546
- const allowedTeamFallbackRanges = file === teamRuntimeTmuxPath ? exactTeamRuntimeSendKeysRanges(contents) : [];
1647
+ const allowedTeamFallbackRanges =
1648
+ file === teamRuntimeTmuxPath
1649
+ ? [...exactTeamRuntimeSendKeysRanges(contents), ...exactMemoryGuardSendKeysRanges(contents)]
1650
+ : [];
1547
1651
  const violations: string[] = [];
1548
1652
  for (const occurrence of tmuxPrimitiveOccurrences(contents)) {
1549
1653
  const isExactTeamFallback =