@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,342 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import {
4
+ PLATFORM_SHORTCUT_LABELS_SHOWCASE_ENTRIES,
5
+ PLATFORM_SHORTCUT_LABELS_SHOWCASE_EXPECTED_ENTRY_COUNT,
6
+ type PlatformShortcutLabelsShowcaseEntry,
7
+ renderPlatformShortcutLabelsShowcase,
8
+ } from "../test/fixtures/tui/platform-shortcut-labels-showcase";
9
+
10
+ const CANONICAL_COMMAND =
11
+ "bun packages/coding-agent/scripts/capture-platform-shortcut-labels-showcase.ts --output .skc/qa/platform-shortcut-labels";
12
+ const CAPTURE_TOOL_VERSION = "platform-shortcut-labels-fixture-injected-platform-v1";
13
+ const EXPECTED_KEYS = [
14
+ "darwin/composer-idle/80x24/unicode-color",
15
+ "darwin/composer-idle/120x36/unicode-color",
16
+ "darwin/composer-idle/160x48/unicode-color",
17
+ "darwin/composer-busy-effective-queue-remap/80x24/unicode-color",
18
+ "darwin/composer-busy-effective-queue-remap/120x36/unicode-color",
19
+ "darwin/composer-busy-effective-queue-remap/160x48/unicode-color",
20
+ "darwin/status-effective-remap-unbound/80x24/unicode-color",
21
+ "darwin/status-effective-remap-unbound/120x36/unicode-color",
22
+ "darwin/status-effective-remap-unbound/160x48/unicode-color",
23
+ "darwin/welcome-flow/80x24/unicode-color",
24
+ "darwin/welcome-flow/120x36/unicode-color",
25
+ "darwin/welcome-flow/160x48/unicode-color",
26
+ "win32/composer-idle/80x24/unicode-color",
27
+ "win32/composer-idle/120x36/unicode-color",
28
+ "win32/composer-busy-effective-queue-remap/80x24/unicode-color",
29
+ "win32/composer-busy-effective-queue-remap/120x36/unicode-color",
30
+ "win32/status-effective-remap-unbound/80x24/unicode-color",
31
+ "win32/status-effective-remap-unbound/120x36/unicode-color",
32
+ "win32/welcome-flow/80x24/unicode-color",
33
+ "win32/welcome-flow/120x36/unicode-color",
34
+ "linux/composer-idle/80x24/unicode-color",
35
+ "linux/composer-idle/120x36/unicode-color",
36
+ "linux/composer-busy-effective-queue-remap/80x24/unicode-color",
37
+ "linux/composer-busy-effective-queue-remap/120x36/unicode-color",
38
+ "linux/status-effective-remap-unbound/80x24/unicode-color",
39
+ "linux/status-effective-remap-unbound/120x36/unicode-color",
40
+ "linux/welcome-flow/80x24/unicode-color",
41
+ "linux/welcome-flow/120x36/unicode-color",
42
+ "darwin/composer-idle/80x24/ascii-no-color",
43
+ "darwin/composer-busy-effective-queue-remap/80x24/ascii-no-color",
44
+ "darwin/status-effective-remap-unbound/80x24/ascii-no-color",
45
+ "darwin/welcome-flow/80x24/ascii-no-color",
46
+ "darwin/status-effective-remap-unbound/48x36/unicode-color",
47
+ "darwin/welcome-flow/48x36/unicode-color",
48
+ ] as const;
49
+
50
+ type ArtifactFile = { path: string; sha256: string; byte_length: number };
51
+ type ManifestEntry = {
52
+ key: string;
53
+ platform: string;
54
+ surface: string;
55
+ viewport: { id: string; columns: number; rows: number };
56
+ render_mode: string;
57
+ capture_mode: "fixture-injected-platform";
58
+ files: ArtifactFile[];
59
+ };
60
+
61
+ function usage(): never {
62
+ throw new Error(`Usage: ${CANONICAL_COMMAND}`);
63
+ }
64
+ function outputPath(args: string[]): string {
65
+ if (args.length !== 2 || args[0] !== "--output" || !args[1]) usage();
66
+ return args[1];
67
+ }
68
+ function json(value: unknown): string {
69
+ return `${JSON.stringify(value, null, 2)}\n`;
70
+ }
71
+ function sha256(value: string): string {
72
+ return new Bun.CryptoHasher("sha256").update(value).digest("hex");
73
+ }
74
+ function escapeHtml(value: string): string {
75
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
76
+ }
77
+
78
+ type AnsiStyle = {
79
+ foreground?: string;
80
+ background?: string;
81
+ bold?: boolean;
82
+ dim?: boolean;
83
+ italic?: boolean;
84
+ underline?: boolean;
85
+ inverse?: boolean;
86
+ };
87
+
88
+ const ANSI_COLORS: Record<number, string> = {
89
+ 30: "#000000",
90
+ 31: "#cc0000",
91
+ 32: "#4e9a06",
92
+ 33: "#c4a000",
93
+ 34: "#3465a4",
94
+ 35: "#75507b",
95
+ 36: "#06989a",
96
+ 37: "#d3d7cf",
97
+ 90: "#555753",
98
+ 91: "#ef2929",
99
+ 92: "#8ae234",
100
+ 93: "#fce94f",
101
+ 94: "#729fcf",
102
+ 95: "#ad7fa8",
103
+ 96: "#34e2e2",
104
+ 97: "#eeeeec",
105
+ };
106
+
107
+ function ansi256Color(index: number): string {
108
+ if (index < 16) return ANSI_COLORS[index < 8 ? index + 30 : index + 82] ?? "#ffffff";
109
+ if (index >= 232) {
110
+ const value = (index - 232) * 10 + 8;
111
+ return `rgb(${value},${value},${value})`;
112
+ }
113
+ const value = index - 16;
114
+ const red = Math.floor(value / 36);
115
+ const green = Math.floor((value % 36) / 6);
116
+ const blue = value % 6;
117
+ const channel = (component: number) => (component === 0 ? 0 : component * 40 + 55);
118
+ return `rgb(${channel(red)},${channel(green)},${channel(blue)})`;
119
+ }
120
+
121
+ function styleAttribute(style: AnsiStyle): string {
122
+ const declarations: string[] = [];
123
+ if (style.foreground) declarations.push(`color:${style.foreground}`);
124
+ if (style.background) declarations.push(`background-color:${style.background}`);
125
+ if (style.bold) declarations.push("font-weight:700");
126
+ if (style.dim) declarations.push("opacity:.65");
127
+ if (style.italic) declarations.push("font-style:italic");
128
+ if (style.underline) declarations.push("text-decoration:underline");
129
+ if (style.inverse) declarations.push("filter:invert(1)");
130
+ return declarations.join(";");
131
+ }
132
+
133
+ const NON_VISUAL_TERMINAL_CONTROL = /\x1b_[^\x1b\x07]*(?:\x07|\x1b\\)/g;
134
+
135
+ /** Render emitted SGR styles as safe inline CSS without retaining terminal control codes. */
136
+ function ansiToHtml(value: string): string {
137
+ const visibleText = value.replace(NON_VISUAL_TERMINAL_CONTROL, "");
138
+ const sgr = /\x1b\[([0-9;]*)m/g;
139
+ let body = "";
140
+ let offset = 0;
141
+ let spanOpen = false;
142
+ let style: AnsiStyle = {};
143
+ const close = () => {
144
+ if (!spanOpen) return;
145
+ body += "</span>";
146
+ spanOpen = false;
147
+ };
148
+ const open = () => {
149
+ const attribute = styleAttribute(style);
150
+ if (!attribute) return;
151
+ body += `<span style="${attribute}">`;
152
+ spanOpen = true;
153
+ };
154
+
155
+ for (const match of visibleText.matchAll(sgr)) {
156
+ body += escapeHtml(visibleText.slice(offset, match.index));
157
+ offset = (match.index ?? 0) + match[0].length;
158
+ close();
159
+ const codes = (match[1] || "0").split(";").map(Number);
160
+ for (let index = 0; index < codes.length; index += 1) {
161
+ const code = codes[index];
162
+ if (code === 0) style = {};
163
+ else if (code === 1) style.bold = true;
164
+ else if (code === 2) style.dim = true;
165
+ else if (code === 3) style.italic = true;
166
+ else if (code === 4) style.underline = true;
167
+ else if (code === 7) style.inverse = true;
168
+ else if (code === 22) {
169
+ style.bold = false;
170
+ style.dim = false;
171
+ } else if (code === 23) style.italic = false;
172
+ else if (code === 24) style.underline = false;
173
+ else if (code === 27) style.inverse = false;
174
+ else if (code === 39) style.foreground = undefined;
175
+ else if (code === 49) style.background = undefined;
176
+ else if (code in ANSI_COLORS) style.foreground = ANSI_COLORS[code];
177
+ else if (code >= 40 && code <= 47) style.background = ANSI_COLORS[code - 10];
178
+ else if (code >= 100 && code <= 107) style.background = ANSI_COLORS[code - 10];
179
+ else if (code === 38 || code === 48) {
180
+ const colorMode = codes[index + 1];
181
+ if (colorMode === 2) {
182
+ const red = codes[index + 2];
183
+ const green = codes[index + 3];
184
+ const blue = codes[index + 4];
185
+ if ([red, green, blue].every(Number.isInteger)) {
186
+ if (code === 38) style.foreground = `rgb(${red},${green},${blue})`;
187
+ else style.background = `rgb(${red},${green},${blue})`;
188
+ }
189
+ index += 4;
190
+ } else if (colorMode === 5 && Number.isInteger(codes[index + 2])) {
191
+ if (code === 38) style.foreground = ansi256Color(codes[index + 2]!);
192
+ else style.background = ansi256Color(codes[index + 2]!);
193
+ index += 2;
194
+ }
195
+ }
196
+ }
197
+ open();
198
+ }
199
+ body += escapeHtml(visibleText.slice(offset));
200
+ close();
201
+ return `<!doctype html>\n<html lang="en"><head><meta charset="utf-8"><meta name="color-scheme" content="dark"><title>Platform shortcut labels showcase</title><style>body{margin:0;background:#110b0b;color:#ffe7dc;overflow:auto}pre{margin:0;padding:1em;white-space:pre;font-family:ui-monospace,monospace;line-height:1.2}</style></head><body><pre>${body}</pre></body></html>\n`;
202
+ }
203
+ function validateMatrix(entries: readonly PlatformShortcutLabelsShowcaseEntry[]): void {
204
+ if (PLATFORM_SHORTCUT_LABELS_SHOWCASE_EXPECTED_ENTRY_COUNT !== 34)
205
+ throw new Error("Expected showcase entry count must remain 34");
206
+ if (entries.length !== PLATFORM_SHORTCUT_LABELS_SHOWCASE_EXPECTED_ENTRY_COUNT)
207
+ throw new Error(`Showcase matrix changed: expected 34 entries, received ${entries.length}`);
208
+ const actual = entries.map(entry => entry.key);
209
+ if (new Set(actual).size !== actual.length) throw new Error("Showcase matrix contains duplicate entry keys");
210
+ const expected = new Set<string>(EXPECTED_KEYS);
211
+ const missing = EXPECTED_KEYS.filter(key => !actual.includes(key));
212
+ const surplus = actual.filter(key => !expected.has(key));
213
+ if (missing.length || surplus.length || actual.some((key, index) => key !== EXPECTED_KEYS[index]))
214
+ throw new Error(
215
+ `Showcase matrix keys differ; missing=${missing.join(",") || "none"}; surplus=${surplus.join(",") || "none"}`,
216
+ );
217
+ }
218
+ async function writeArtifact(filePath: string, content: string, outputRoot: string): Promise<ArtifactFile> {
219
+ await Bun.write(filePath, content);
220
+ return {
221
+ path: path.relative(outputRoot, filePath).split(path.sep).join("/"),
222
+ sha256: sha256(content),
223
+ byte_length: Buffer.byteLength(content, "utf8"),
224
+ };
225
+ }
226
+ async function captureEntry(
227
+ entry: PlatformShortcutLabelsShowcaseEntry,
228
+ outputRoot: string,
229
+ capturedAt: string,
230
+ ): Promise<ManifestEntry> {
231
+ const rendered = await renderPlatformShortcutLabelsShowcase(entry);
232
+ const directory = path.join(outputRoot, entry.platform, entry.surface, entry.viewport.id, entry.renderMode);
233
+ await fs.mkdir(directory, { recursive: true });
234
+ const html = ansiToHtml(rendered.terminalAnsiText);
235
+ const metadata = json({
236
+ schema_version: 1,
237
+ entry_key: entry.key,
238
+ platform: entry.platform,
239
+ viewport: entry.viewport,
240
+ render_mode: entry.renderMode,
241
+ capture_mode: rendered.captureMode,
242
+ platform_provenance: rendered.platformProvenance,
243
+ key_display_context: rendered.keyDisplayContext,
244
+ components: rendered.components,
245
+ capture_timestamp: capturedAt,
246
+ command_or_replay_source: CANONICAL_COMMAND,
247
+ fixture_source: "packages/coding-agent/test/fixtures/tui/platform-shortcut-labels-showcase.ts",
248
+ tool_version: CAPTURE_TOOL_VERSION,
249
+ terminal: {
250
+ columns: entry.viewport.columns,
251
+ rows: entry.viewport.rows,
252
+ font_rendering_assumptions:
253
+ "Embedded red-octopus truecolor theme; HTML uses a monospace terminal fallback stack.",
254
+ wrapping_policy:
255
+ "Real components render at the recorded terminal-cell width; CJK content is retained for width review.",
256
+ ansi_control_semantics:
257
+ "terminal-ansi.txt preserves emitted SGR sequences; terminal.txt strips them; ascii-no-color strips styling only.",
258
+ },
259
+ provenance: {
260
+ platform: "fixture-injected-platform",
261
+ live_capture: false,
262
+ native_platform_claim: entry.platform === "darwin" ? "none (fixture only)" : "none",
263
+ },
264
+ fixed_clock_timestamp: rendered.fixedClockTimestamp,
265
+ });
266
+ const files = await Promise.all([
267
+ writeArtifact(path.join(directory, "terminal.txt"), rendered.terminalText, outputRoot),
268
+ writeArtifact(path.join(directory, "terminal-ansi.txt"), rendered.terminalAnsiText, outputRoot),
269
+ writeArtifact(path.join(directory, "terminal.html"), html, outputRoot),
270
+ writeArtifact(path.join(directory, "metadata.json"), metadata, outputRoot),
271
+ ]);
272
+ return {
273
+ key: entry.key,
274
+ platform: entry.platform,
275
+ surface: entry.surface,
276
+ viewport: entry.viewport,
277
+ render_mode: entry.renderMode,
278
+ capture_mode: rendered.captureMode,
279
+ files,
280
+ };
281
+ }
282
+ async function main(): Promise<void> {
283
+ const root = path.resolve(outputPath(process.argv.slice(2)));
284
+ const capturedAt = new Date().toISOString();
285
+ validateMatrix(PLATFORM_SHORTCUT_LABELS_SHOWCASE_ENTRIES);
286
+ await fs.mkdir(root, { recursive: true });
287
+ const entries: ManifestEntry[] = [];
288
+ for (const entry of PLATFORM_SHORTCUT_LABELS_SHOWCASE_ENTRIES)
289
+ entries.push(await captureEntry(entry, root, capturedAt));
290
+ const manifest = json({
291
+ schema_version: 1,
292
+ capture_tool: CAPTURE_TOOL_VERSION,
293
+ capture_mode: "fixture-injected-platform",
294
+ command: CANONICAL_COMMAND,
295
+ capture_timestamp: capturedAt,
296
+ expected_entry_count: 34,
297
+ entry_count: entries.length,
298
+ ordered_keys: EXPECTED_KEYS,
299
+ provenance: "fixture-injected-platform",
300
+ review_input_file: "visual-review-input.json",
301
+ entries,
302
+ });
303
+ const manifestSha256 = sha256(manifest);
304
+ await Bun.write(path.join(root, "manifest.json"), manifest);
305
+ await Bun.write(
306
+ path.join(root, "visual-review-input.json"),
307
+ json({
308
+ schema_version: 1,
309
+ manifest_sha256: manifestSha256,
310
+ expected_manifest_entries: 34,
311
+ ordered_keys: EXPECTED_KEYS,
312
+ evidence_scope: {
313
+ component_surface: "Real CustomEditor, StatusLineComponent, and WelcomeComponent rendering.",
314
+ operations_boundary: "Fixed clock, in-memory settings, and explicit injected KeyDisplayContext platform.",
315
+ external_effects: "No network, filesystem settings, daemon, or live native platform capture is invoked.",
316
+ },
317
+ review_requirements: [
318
+ "Inspect every recorded key.",
319
+ "Confirm Darwin glyphs and ASCII/no-color variants retain the same labels.",
320
+ "Confirm CJK and terminal-cell width evidence in both 48x36 entries.",
321
+ "Confirm all platform provenance is fixture-injected-platform.",
322
+ ],
323
+ required_feature_cases: [
324
+ {
325
+ id: "darwin-composer",
326
+ entry_key: "darwin/composer-idle/80x24/unicode-color",
327
+ focus: "Darwin modifier and Enter glyph labels.",
328
+ },
329
+ {
330
+ id: "effective-remap",
331
+ entry_key: "darwin/status-effective-remap-unbound/80x24/unicode-color",
332
+ focus: "Effective remap and unbound action labels.",
333
+ },
334
+ { id: "cjk-width", entry_key: "darwin/welcome-flow/48x36/unicode-color", focus: "CJK width and wrapping." },
335
+ ],
336
+ }),
337
+ );
338
+ process.stdout.write(
339
+ `Captured ${entries.length} deterministic platform shortcut showcase entries to ${root}\nmanifest.json sha256: ${manifestSha256}\n`,
340
+ );
341
+ }
342
+ await main();
@@ -0,0 +1,292 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ import {
4
+ renderStickyViewportShowcase,
5
+ STICKY_VIEWPORT_SHOWCASE_ENTRIES,
6
+ STICKY_VIEWPORT_SHOWCASE_KEYS,
7
+ type StickyViewportShowcaseEntry,
8
+ } from "../test/fixtures/tui/sticky-viewport-showcase";
9
+
10
+ const COMMAND =
11
+ "bun packages/coding-agent/scripts/capture-sticky-viewport-showcase.ts --out .skc/qa/sticky-viewport-<run>";
12
+ const REVISION = "sticky-viewport-showcase-v2";
13
+ const TIMESTAMP = "1970-01-01T00:00:00.000Z";
14
+ const PAYLOADS = ["terminal.txt", "terminal-ansi.txt", "terminal.html", "metadata.json"] as const;
15
+ const FONT_RENDERING_ASSUMPTIONS =
16
+ "Embedded red-octopus theme at deterministic truecolor; HTML uses a monospace terminal fallback stack.";
17
+ const WRAPPING_TRUNCATION_POLICY =
18
+ "ANSI-aware terminal-cell wrapping preserves semantic CJK phrase boundaries; constrained height drops the notice, decorative pet, then low-priority hooks without truncating pinned status or the focused composer.";
19
+ const ACCEPTANCE_VERSION = "sticky-viewport-stage-03";
20
+ const DESIGN_VERSION = "modes-design-sticky-viewport-v3";
21
+ const CJK_PHRASE_BOUNDARIES = ["의미 있는 문장 경계", "意味のある文の境界", "保留语义短语边界"] as const;
22
+ const HOST_MATRIX = {
23
+ capture_host: "VirtualTerminal",
24
+ live_pty: false,
25
+ network: false,
26
+ } as const;
27
+ const escapeHtml = (value: string) =>
28
+ value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
29
+ type AnsiStyle = {
30
+ foreground?: string;
31
+ background?: string;
32
+ bold?: boolean;
33
+ dim?: boolean;
34
+ italic?: boolean;
35
+ underline?: boolean;
36
+ blink?: boolean;
37
+ inverse?: boolean;
38
+ invisible?: boolean;
39
+ strikethrough?: boolean;
40
+ overline?: boolean;
41
+ };
42
+ const TERMINAL_DEFAULT_FOREGROUND = "#ffe7dc";
43
+ const TERMINAL_DEFAULT_BACKGROUND = "#110b0b";
44
+ const ANSI_COLORS: Record<number, string> = {
45
+ 30: "#000000",
46
+ 31: "#cc0000",
47
+ 32: "#4e9a06",
48
+ 33: "#c4a000",
49
+ 34: "#3465a4",
50
+ 35: "#75507b",
51
+ 36: "#06989a",
52
+ 37: "#d3d7cf",
53
+ 90: "#555753",
54
+ 91: "#ef2929",
55
+ 92: "#8ae234",
56
+ 93: "#fce94f",
57
+ 94: "#729fcf",
58
+ 95: "#ad7fa8",
59
+ 96: "#34e2e2",
60
+ 97: "#eeeeec",
61
+ };
62
+ /** Converts an xterm 256-color palette index into its canonical CSS color. */
63
+ export const xterm256Color = (index: number): string => {
64
+ if (!Number.isInteger(index) || index < 0 || index > 255) throw new RangeError(`invalid xterm color index ${index}`);
65
+ if (index < 16) return ANSI_COLORS[index < 8 ? index + 30 : index + 82]!;
66
+ if (index >= 232) {
67
+ const value = (index - 232) * 10 + 8;
68
+ return `rgb(${value},${value},${value})`;
69
+ }
70
+ const value = index - 16,
71
+ channel = (component: number) => (component === 0 ? 0 : component * 40 + 55);
72
+ return `rgb(${channel(Math.floor(value / 36))},${channel(Math.floor((value % 36) / 6))},${channel(value % 6)})`;
73
+ };
74
+ const styleAttribute = (style: AnsiStyle): string => {
75
+ const foreground = style.inverse ? (style.background ?? TERMINAL_DEFAULT_BACKGROUND) : style.foreground;
76
+ const background = style.inverse ? (style.foreground ?? TERMINAL_DEFAULT_FOREGROUND) : style.background;
77
+ const decorations = [
78
+ style.underline && "underline",
79
+ style.strikethrough && "line-through",
80
+ style.overline && "overline",
81
+ ]
82
+ .filter(Boolean)
83
+ .join(" ");
84
+ return [
85
+ foreground && `color:${foreground}`,
86
+ background && `background-color:${background}`,
87
+ style.bold && "font-weight:700",
88
+ style.dim && "opacity:.65",
89
+ style.italic && "font-style:italic",
90
+ style.blink && "animation:blink 1s step-end infinite",
91
+ style.invisible && "visibility:hidden",
92
+ decorations && `text-decoration:${decorations}`,
93
+ ]
94
+ .filter(Boolean)
95
+ .join(";");
96
+ };
97
+ const NON_VISUAL_TERMINAL_CONTROL = /\x1b_[^\x1b\x07]*(?:\x07|\x1b\\)/g;
98
+ /** Stateful SGR conversion with closing/reopening spans and partial/full resets. */
99
+ export function ansiToHtml(value: string): string {
100
+ const visibleText = value.replace(NON_VISUAL_TERMINAL_CONTROL, "");
101
+ let body = "",
102
+ offset = 0,
103
+ spanOpen = false,
104
+ style: AnsiStyle = {};
105
+ const close = () => {
106
+ if (spanOpen) {
107
+ body += "</span>";
108
+ spanOpen = false;
109
+ }
110
+ };
111
+ const open = () => {
112
+ const attribute = styleAttribute(style);
113
+ if (attribute) {
114
+ body += `<span style="${attribute}">`;
115
+ spanOpen = true;
116
+ }
117
+ };
118
+ for (const match of visibleText.matchAll(/\x1b\[([0-9;]*)m/g)) {
119
+ body += escapeHtml(visibleText.slice(offset, match.index));
120
+ offset = (match.index ?? 0) + match[0].length;
121
+ close();
122
+ const codes = (match[1] || "0").split(";").map(Number);
123
+ for (let index = 0; index < codes.length; index += 1) {
124
+ const code = codes[index];
125
+ if (code === 0) style = {};
126
+ else if (code === 1) style.bold = true;
127
+ else if (code === 2) style.dim = true;
128
+ else if (code === 3) style.italic = true;
129
+ else if (code === 4) style.underline = true;
130
+ else if (code === 5) style.blink = true;
131
+ else if (code === 7) style.inverse = true;
132
+ else if (code === 8) style.invisible = true;
133
+ else if (code === 9) style.strikethrough = true;
134
+ else if (code === 22) {
135
+ style.bold = false;
136
+ style.dim = false;
137
+ } else if (code === 23) style.italic = false;
138
+ else if (code === 24) style.underline = false;
139
+ else if (code === 25) style.blink = false;
140
+ else if (code === 27) style.inverse = false;
141
+ else if (code === 28) style.invisible = false;
142
+ else if (code === 29) style.strikethrough = false;
143
+ else if (code === 53) style.overline = true;
144
+ else if (code === 55) style.overline = false;
145
+ else if (code === 39) style.foreground = undefined;
146
+ else if (code === 49) style.background = undefined;
147
+ else if (code in ANSI_COLORS) style.foreground = ANSI_COLORS[code];
148
+ else if (code >= 40 && code <= 47) style.background = ANSI_COLORS[code - 10];
149
+ else if (code >= 100 && code <= 107) style.background = ANSI_COLORS[code - 10];
150
+ else if (code === 38 || code === 48) {
151
+ const mode = codes[index + 1];
152
+ if (mode === 2 && [codes[index + 2], codes[index + 3], codes[index + 4]].every(Number.isInteger)) {
153
+ const color = `rgb(${codes[index + 2]},${codes[index + 3]},${codes[index + 4]})`;
154
+ if (code === 38) style.foreground = color;
155
+ else style.background = color;
156
+ index += 4;
157
+ } else if (mode === 5 && Number.isInteger(codes[index + 2])) {
158
+ if (code === 38) style.foreground = xterm256Color(codes[index + 2]!);
159
+ else style.background = xterm256Color(codes[index + 2]!);
160
+ index += 2;
161
+ }
162
+ }
163
+ }
164
+ open();
165
+ }
166
+ body += escapeHtml(visibleText.slice(offset));
167
+ close();
168
+ return `<!doctype html><html lang="en"><meta charset="utf-8"><title>Sticky viewport showcase</title><style>body{margin:0;background:#110b0b;color:#ffe7dc}pre{white-space:pre;font-family:ui-monospace,monospace}@keyframes blink{50%{visibility:hidden}}</style><pre>${body}</pre></html>\n`;
169
+ }
170
+ const json = (value: unknown) => `${JSON.stringify(value, null, 2)}\n`;
171
+ const hash = (value: string) => new Bun.CryptoHasher("sha256").update(value).digest("hex");
172
+ function out(args: string[]): string {
173
+ if (args.length !== 2 || args[0] !== "--out" || !args[1]) throw new Error(`Usage: ${COMMAND}`);
174
+ return args[1];
175
+ }
176
+ async function capture(entry: StickyViewportShowcaseEntry, root: string) {
177
+ const rendered = await renderStickyViewportShowcase(entry);
178
+ if (!rendered.state.composer_visible)
179
+ throw new Error(`${entry.key}: focused composer was not visible in production frame`);
180
+ if (entry.stateId === "manual-new-output" && rendered.state.notice !== true)
181
+ throw new Error(`${entry.key}: manual output notice precondition failed`);
182
+ if (
183
+ JSON.stringify(rendered.cjkPhraseBoundaries) !==
184
+ JSON.stringify(entry.stateId === "narrow-cjk" ? CJK_PHRASE_BOUNDARIES : [])
185
+ )
186
+ throw new Error(`${entry.key}: CJK phrase boundary metadata precondition failed`);
187
+ const directory = path.join(root, ...entry.key.split("/"));
188
+ await fs.mkdir(directory, { recursive: true });
189
+ const metadata = json({
190
+ schema_version: 2,
191
+ entry_key: entry.key,
192
+ fixture_revision: REVISION,
193
+ capture_timestamp: TIMESTAMP,
194
+ command_or_replay_source: COMMAND,
195
+ fixture_source: "packages/coding-agent/test/fixtures/tui/sticky-viewport-showcase.ts",
196
+ terminal: {
197
+ ...entry.viewport,
198
+ font_rendering_assumptions: FONT_RENDERING_ASSUMPTIONS,
199
+ wrapping_truncation_policy: WRAPPING_TRUNCATION_POLICY,
200
+ },
201
+ render_mode: entry.renderMode,
202
+ ansi_mode: entry.renderMode === "unicode-color",
203
+ source_revision: rendered.sourceRevision,
204
+ output_revision: rendered.outputRevision,
205
+ state: rendered.state,
206
+ provenance: {
207
+ capture_mode: "production-tui-virtual-terminal",
208
+ live_pty: false,
209
+ network: false,
210
+ fixed_clock: true,
211
+ author_identity: "capture-sticky-viewport-showcase",
212
+ executor_identity: "capture-sticky-viewport-showcase",
213
+ },
214
+ cjk_phrase_boundaries: rendered.cjkPhraseBoundaries,
215
+ });
216
+ const contents = {
217
+ "terminal.txt": rendered.terminalText,
218
+ "terminal-ansi.txt": rendered.terminalAnsiText,
219
+ "terminal.html": ansiToHtml(rendered.terminalAnsiText),
220
+ "metadata.json": metadata,
221
+ };
222
+ const files = await Promise.all(
223
+ PAYLOADS.map(async name => {
224
+ const content = contents[name];
225
+ await Bun.write(path.join(directory, name), content);
226
+ return {
227
+ path: `${entry.key}/${name}`,
228
+ sha256: hash(content),
229
+ byte_length: Buffer.byteLength(content),
230
+ };
231
+ }),
232
+ );
233
+ return {
234
+ key: entry.key,
235
+ state_id: entry.stateId,
236
+ viewport: entry.viewport,
237
+ render_mode: entry.renderMode,
238
+ files,
239
+ };
240
+ }
241
+ async function main() {
242
+ const root = path.resolve(out(process.argv.slice(2)));
243
+ await fs.mkdir(root, { recursive: true });
244
+ const entries = [];
245
+ for (const entry of STICKY_VIEWPORT_SHOWCASE_ENTRIES) entries.push(await capture(entry, root));
246
+ const manifest = json({
247
+ schema_version: 2,
248
+ fixture_revision: REVISION,
249
+ command: COMMAND,
250
+ capture_timestamp: TIMESTAMP,
251
+ expected_entry_count: 20,
252
+ entry_count: 20,
253
+ ordered_keys: STICKY_VIEWPORT_SHOWCASE_KEYS,
254
+ provenance: {
255
+ capture_mode: "production-tui-virtual-terminal",
256
+ live_pty: false,
257
+ network: false,
258
+ fixed_clock: true,
259
+ author_identity: "capture-sticky-viewport-showcase",
260
+ executor_identity: "capture-sticky-viewport-showcase",
261
+ },
262
+ review_input_file: "review-input.json",
263
+ entries,
264
+ });
265
+ await Bun.write(path.join(root, "manifest.json"), manifest);
266
+ await Bun.write(
267
+ path.join(root, "review-input.json"),
268
+ json({
269
+ schema_version: 2,
270
+ manifest_sha256: hash(manifest),
271
+ command_or_replay_source: COMMAND,
272
+ capture_timestamp: TIMESTAMP,
273
+ fixture_source: "packages/coding-agent/test/fixtures/tui/sticky-viewport-showcase.ts",
274
+ fixed_clock: true,
275
+ live_pty: false,
276
+ network: false,
277
+ expected_keys: STICKY_VIEWPORT_SHOWCASE_KEYS,
278
+ author_identity: "capture-sticky-viewport-showcase",
279
+ executor_identity: "capture-sticky-viewport-showcase",
280
+ required_artifacts: PAYLOADS,
281
+ acceptance_version: ACCEPTANCE_VERSION,
282
+ design_version: DESIGN_VERSION,
283
+ host_matrix: HOST_MATRIX,
284
+ narrow_cjk: {
285
+ entry_key: "narrow-cjk/48x10/unicode-color",
286
+ phrase_boundaries: ["의미 있는 문장 경계", "意味のある文の境界", "保留语义短语边界"],
287
+ },
288
+ }),
289
+ );
290
+ process.stdout.write(`Captured 20 production TUI sticky viewport entries to ${root}\n`);
291
+ }
292
+ if (import.meta.main) await main();
@@ -7,7 +7,6 @@ export interface CompileArgOptions {
7
7
  externals?: string[];
8
8
  }
9
9
 
10
-
11
10
  export const compileAutoloadDisableFlags = [
12
11
  "--no-compile-autoload-bunfig",
13
12
  "--no-compile-autoload-dotenv",