@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
@@ -1,44 +1,10 @@
1
1
  import * as path from "node:path";
2
2
  import { getAgentDir } from "@sayknow-cli/utils";
3
3
  import { YAML } from "bun";
4
+ import { UnknownModelProfileError, validateModelProfileName } from "../config/model-profile-contract";
5
+ import { mergeModelProfiles } from "../config/model-profiles";
4
6
  import { ModelsConfigSchema } from "../config/models-config-schema";
5
7
 
6
- /**
7
- * The coordinator runs in the shipped MCP process and must stay outside the
8
- * session host import graph. Keep this identity catalog in the coordinator
9
- * boundary; profile activation and model registry code belong to that host.
10
- */
11
- const BUILTIN_MODEL_PROFILE_NAMES = [
12
- "codex-eco",
13
- "codex-medium",
14
- "codex-pro",
15
- "opencodego",
16
- "claude-opus",
17
- "claude-fable",
18
- "glm-eco",
19
- "glm-medium",
20
- "glm-pro",
21
- "kimi-coding-plan-eco",
22
- "kimi-coding-plan-medium",
23
- "kimi-coding-plan-pro",
24
- "mimo-eco",
25
- "mimo-medium",
26
- "mimo-pro",
27
- "grok-eco",
28
- "grok-medium",
29
- "grok-pro",
30
- "grok-build-pro",
31
- "cursor-eco",
32
- "cursor-medium",
33
- "cursor-pro",
34
- "minimax-eco",
35
- "minimax-medium",
36
- "minimax-pro",
37
- "opus-codex",
38
- "codex-opencodego",
39
- "fable-opus-codex",
40
- ] as const;
41
-
42
8
  export interface CoordinatorModelProfile {
43
9
  name: string;
44
10
  }
@@ -53,8 +19,6 @@ export type CoordinatorModelProfileLoader = () =>
53
19
  | Promise<Map<string, CoordinatorModelProfile>>;
54
20
 
55
21
  const MAX_ECHOED_MPRESET_LENGTH = 128;
56
- const LEGACY_MODEL_PROFILE_ALIASES: ReadonlyMap<string, string> = new Map([["codex-standard", "codex-medium"]]);
57
-
58
22
  /**
59
23
  * Thrown by the default loader when `models.yml` exists but is invalid or
60
24
  * unreadable. This lets the resolver fail closed with a distinct, stable reason
@@ -69,35 +33,25 @@ export class CoordinatorModelProfileRegistryError extends Error {
69
33
  }
70
34
  }
71
35
 
72
- function builtInCoordinatorModelProfiles(): Map<string, CoordinatorModelProfile> {
73
- return new Map(BUILTIN_MODEL_PROFILE_NAMES.map(name => [name, { name }]));
36
+ function coordinatorModelProfiles(
37
+ profiles?: Parameters<typeof mergeModelProfiles>[0],
38
+ ): Map<string, CoordinatorModelProfile> {
39
+ return new Map([...mergeModelProfiles(profiles).keys()].map(name => [name, { name }]));
74
40
  }
75
41
 
76
42
  export const loadCoordinatorModelProfiles: CoordinatorModelProfileLoader = async () => {
77
43
  const modelsFile = Bun.file(path.join(getAgentDir(), "models.yml"));
78
- if (!(await modelsFile.exists())) return builtInCoordinatorModelProfiles();
44
+ if (!(await modelsFile.exists())) return coordinatorModelProfiles();
79
45
  try {
80
46
  const parsed = YAML.parse(await modelsFile.text());
81
47
  const config = ModelsConfigSchema.safeParse(parsed);
82
48
  if (!config.success) throw config.error;
83
- const profiles = builtInCoordinatorModelProfiles();
84
- for (const name of Object.keys(config.data.profiles ?? {})) profiles.set(name, { name });
85
- return profiles;
49
+ return coordinatorModelProfiles(config.data.profiles);
86
50
  } catch (error) {
87
51
  throw new CoordinatorModelProfileRegistryError(error);
88
52
  }
89
53
  };
90
54
 
91
- function sortedProfileNames(profiles: ReadonlyMap<string, CoordinatorModelProfile>): string[] {
92
- return [...profiles.keys()].sort((left, right) => left.localeCompare(right));
93
- }
94
-
95
- function resolveCoordinatorModelProfileName(profileName: string, profiles: ReadonlyMap<string, unknown>): string {
96
- if (profiles.has(profileName)) return profileName;
97
- const replacement = LEGACY_MODEL_PROFILE_ALIASES.get(profileName);
98
- return replacement && profiles.has(replacement) ? replacement : profileName;
99
- }
100
-
101
55
  export type CoordinatorMpresetResolution =
102
56
  | { ok: true; mpreset: string | null }
103
57
  | { ok: false; reason: "unknown_model_profile"; mpreset: string; available_profiles: string[] }
@@ -120,7 +74,7 @@ export async function resolveCoordinatorMpreset(
120
74
  loadProfiles: CoordinatorModelProfileLoader,
121
75
  ): Promise<CoordinatorMpresetResolution> {
122
76
  if (raw === undefined || raw === null) return { ok: true, mpreset: null };
123
- const requested = typeof raw === "string" ? raw.trim() : "";
77
+ const requested = typeof raw === "string" ? raw : "";
124
78
  const echoed = requested.slice(0, MAX_ECHOED_MPRESET_LENGTH);
125
79
  let profiles: Map<string, CoordinatorModelProfile>;
126
80
  try {
@@ -131,24 +85,17 @@ export async function resolveCoordinatorMpreset(
131
85
  }
132
86
  throw error;
133
87
  }
134
- // Non-string input and explicit blank/whitespace strings can never name a
135
- // profile; only absent/null (handled above) means "no selection".
136
- if (typeof raw !== "string" || requested.length === 0) {
137
- return {
138
- ok: false,
139
- reason: "unknown_model_profile",
140
- mpreset: echoed,
141
- available_profiles: sortedProfileNames(profiles),
142
- };
143
- }
144
- const canonical = resolveCoordinatorModelProfileName(requested, profiles);
145
- if (!profiles.has(canonical)) {
146
- return {
147
- ok: false,
148
- reason: "unknown_model_profile",
149
- mpreset: echoed,
150
- available_profiles: sortedProfileNames(profiles),
151
- };
88
+ try {
89
+ const canonical = validateModelProfileName(requested, profiles);
90
+ return { ok: true, mpreset: canonical };
91
+ } catch (error) {
92
+ if (error instanceof UnknownModelProfileError)
93
+ return {
94
+ ok: false,
95
+ reason: "unknown_model_profile",
96
+ mpreset: error.details.requestedProfile.slice(0, MAX_ECHOED_MPRESET_LENGTH),
97
+ available_profiles: error.details.availableProfiles,
98
+ };
99
+ throw error;
152
100
  }
153
- return { ok: true, mpreset: canonical };
154
101
  }
@@ -78,31 +78,66 @@ If this raw bundled skill is loaded by SKC's native skill loader through `/skill
78
78
 
79
79
  ## Corrupt current-session state recovery
80
80
 
81
- When deep-interview detects its own current-session state is corrupt, tampered, unreadable, or stale on resume, run `skc state clear --force --mode deep-interview` before reseeding or restarting. Scope the clear to the current session via `--session-id`, the command payload, or `SKC_SESSION_ID`; it clears only deep-interview state for that session and never clears other skills or sessions.
81
+ When deep-interview detects its own current-session state is corrupt, tampered, unreadable, or stale on resume, run `skc deep-interview clear --force` before reseeding or restarting. Scope the clear to the current session via `--session-id` or `SKC_SESSION_ID`; it clears only deep-interview state for that session and never clears other skills or sessions.
82
82
 
83
83
  ## Phase 0: Resolve Ambiguity Threshold (blocking prerequisite)
84
84
 
85
85
  Complete this phase before Phase 1, before brownfield exploration, before SKC state persistence, before Round 0, and before any ambiguity scoring. Do not continue if the resolved threshold and source are unknown.
86
86
 
87
- 1. **Read threshold settings in precedence order**:
88
- - User settings: `[$SKC_CONFIG_DIR|~/.skc]/settings.json`
89
- - Project settings: `./.skc/settings.json` (overrides user settings)
90
- 2. **Resolve threshold and source**:
91
- - Read `skc.deepInterview.ambiguityThreshold` from both files when present.
92
- - Use the project value when valid; otherwise use the user value when valid; otherwise use the default `0.05`.
93
- - Set these run variables exactly: `<resolvedThreshold>`, `<resolvedThresholdPercent>`, and `<resolvedThresholdSource>` (for example `./.skc/settings.json`, `[$SKC_CONFIG_DIR|~/.skc]/settings.json`, or `default`).
94
- 3. **Emit the required first line to the user before any other interview announcement**:
87
+ 1. **Prefer pre-resolved native state**:
88
+ - First inspect active deep-interview state with `skc deep-interview read --json`.
89
+ - If state contains a finite numeric `threshold` and a non-empty `threshold_source`, use those values, set `<resolvedThreshold>`, `<resolvedThresholdPercent>`, and `<resolvedThresholdSource>`, and skip optional settings-file reads. This is the normal `/skill:deep-interview` path because the native hook already resolved settings quietly before loading the skill.
90
+ 2. **Only if native state lacks a resolved threshold, read threshold settings in runtime precedence order**:
91
+ - YAML config first: read the **single** modern config path the environment selects — `$SKC_CODING_AGENT_DIR/config.yml` when `SKC_CODING_AGENT_DIR` is set, else `$SKC_CONFIG_DIR/agent/config.yml` when `SKC_CONFIG_DIR` is set, else `~/.skc/agent/config.yml`. Do not cascade through the other YAML locations when the selected one is absent or invalid.
92
+ - Then JSON settings: project settings `./.skc/settings.json`, then user settings `[$SKC_CONFIG_DIR|~/.skc]/settings.json`.
93
+ - Read `skc.deepInterview.ambiguityThreshold` only from files that are known to exist; optional config/settings-file absence is expected and must not be surfaced as failed `Read` calls.
94
+ - Do not probe arbitrary ancestor candidates such as `../../.skc/settings.json`; use the current project `.skc/settings.json` and user settings only.
95
+ 3. **Resolve threshold and source**:
96
+ - Use the first valid configured value in the precedence order above; otherwise use the mode default when a resolution flag was passed: `--quick` = `0.6`, `--standard` = `0.5`, `--deep` = `0.35`; with no resolution flag, use the base default `0.05`.
97
+ - Set these run variables exactly: `<resolvedThreshold>`, `<resolvedThresholdPercent>`, and `<resolvedThresholdSource>` (for example `SKC_CODING_AGENT_DIR/config.yml`, `$SKC_CONFIG_DIR/agent/config.yml`, `~/.skc/agent/config.yml`, `./.skc/settings.json`, `[$SKC_CONFIG_DIR|~/.skc]/settings.json`, or the selected mode default).
98
+ 4. **Emit the required first line to the user before any other interview announcement**:
95
99
 
96
100
  ```
97
101
  Deep Interview threshold: <resolvedThresholdPercent> (source: <resolvedThresholdSource>)
98
102
  ```
99
103
 
100
- 4. **Carry threshold source forward mechanically**:
104
+ 5. **Carry threshold source forward mechanically**:
101
105
  - Substitute `<resolvedThreshold>`, `<resolvedThresholdPercent>`, and `<resolvedThresholdSource>` throughout the remaining instructions before continuing.
102
- - Include `threshold_source` in the first `skc state write` payload and preserve it on later state updates; do not edit `.skc/_session-{sessionid}/state` files directly unless an explicit force override is active.
106
+ - Include `threshold_source` in the first `skc deep-interview write` payload and preserve it on later state updates; do not edit `.skc/_session-{sessionid}/state` files directly unless an explicit force override is active.
103
107
  - Include both threshold and source in the final spec metadata.
104
108
  - Read any `language` object from active deep-interview state and carry `language.instruction` forward mechanically. If absent, default to English unless `{{ARGUMENTS}}` makes another user/session language obvious or the user explicitly requests another language. Do not add language-specific special cases.
105
109
 
110
+ ## Phase 0.5: Suitability Gate
111
+
112
+ Run this gate after the Phase 0 threshold marker and before Phase 1, brownfield exploration, `skc deep-interview write`, Round 0, ambiguity scoring, or spec writing.
113
+
114
+ If the user request appended after this skill as the final `User:` line is already clear, bounded, low-risk, and asks for a quick fix, single change, known file/symbol edit, explicit command, or direct answer:
115
+
116
+ 1. **Stop deep-interview immediately**:
117
+ - First inspect current-session state with `skc deep-interview read --json` (include `--session-id <current-session-id>` when available).
118
+ - Clear through `skc deep-interview clear --force --json` only when the state is a newly seeded empty interview: no recorded `rounds`, no `spec_path`, no `handoff_from`, no final/pending spec, and no user-confirmed topology.
119
+ - If state already contains rounds, a spec path, handoff metadata, pending approval, or confirmed topology, do not clear it. Preserve the active interview and ask the user whether to continue, cancel, or explicitly clear the workflow.
120
+ - Do not initialize deep-interview state.
121
+ - Do not run Round 0.
122
+ - Do not write a pending-approval spec.
123
+ - Do not hand off to `ralplan`, `ultragoal`, `team`, or a role agent.
124
+ 2. **Return the request to direct implementation**:
125
+ - Say briefly that deep-interview is unnecessary because the request is already clear and small.
126
+ - State the direct implementation path the normal coding agent should take.
127
+ - If the user explicitly insists on deep-interview anyway, continue to Phase 1.
128
+
129
+ This gate exists to prevent deep-interview from making easy problems harder. A small verification need does not make a request interview-worthy.
130
+
131
+ ## Phase 0.75: Optional Trace Pre-Step
132
+
133
+ Run this phase only when the active deep-interview state or invocation indicates `--trace` / `state.trace.enabled === true`. It is a pre-interview research step, not an implementation phase.
134
+
135
+ 1. Read the native trace summary from active deep-interview state (`trace`, `state.trace`, or `state.trace_summary`). The native seed must have produced this summary before any interview question.
136
+ 2. Treat the summary as compact evidence: project hints, relevant paths, and path-level findings only. Do not expand it by dumping raw files, raw logs, or unbounded command output.
137
+ 3. Store or preserve it under `state.trace_summary` and fold it into `codebase_context` with citations to the summarized paths.
138
+ 4. Use trace findings to influence Round 0 topology, Phase 2 question targeting, requirement wording, acceptance criteria, and final Technical Context. Normal no-trace interviews must behave exactly as before.
139
+ 5. If `--trace` was requested but no valid bounded summary exists, increment `architect_failures` or record an internal audit note, then continue with the normal no-trace path without surfacing tool noise.
140
+
106
141
  ## Phase 1: Initialize
107
142
 
108
143
  1. **Parse the user's idea** from `{{ARGUMENTS}}`
@@ -130,7 +165,7 @@ Deep Interview threshold: <resolvedThresholdPercent> (source: <resolvedThreshold
130
165
  - Preferred: pass the spec markdown **inline** to the native deep-interview write command (`--write … --spec "<markdown>"`) — no scratch file is needed. The CLI is the only sanctioned writer for `.skc/_session-{sessionid}/specs`.
131
166
  - Only if a spec is too large to pass inline, stage it with the `write` tool to a system temp directory (`os.tmpdir()`/`$TMPDIR`, `/tmp`, `/var/tmp`) outside the project tree, then pass that path to `--spec`. The planning phase-boundary block tolerates these neutral temp writes; never stage interview artifacts inside the repo or under `.skc/`, and do not improvise repo-relative scratch files.
132
167
 
133
- 4. **Initialize state** via `skc state write`:
168
+ 4. **Initialize state** via `skc deep-interview write --input '<json>'`:
134
169
 
135
170
  ```json
136
171
  {
@@ -147,6 +182,7 @@ Deep Interview threshold: <resolvedThresholdPercent> (source: <resolvedThreshold
147
182
  "threshold": <resolvedThreshold>,
148
183
  "threshold_source": "<resolvedThresholdSource>",
149
184
  "language": "<existing language object from active state, if present>",
185
+ "trace_summary": "<bounded trace summary when --trace is active, else null>",
150
186
  "codebase_context": null,
151
187
  "topology": {
152
188
  "status": "pending|confirmed|legacy_missing",
@@ -206,6 +242,8 @@ Is that topology right? Should any component be added, removed, merged, split, o
206
242
 
207
243
  Options should include contextually relevant choices such as **Looks right**, **Add/remove/merge components**, **Defer one or more components**, plus free-text, translated/localized according to `language.instruction` when present. This is the only pre-scoring question and preserves the one-question-per-round rule.
208
244
 
245
+ The Round 0 `ask` call MUST include `deepInterview.round = 0`, `deepInterview.component = "review-topology"`, `deepInterview.dimension = "topology"`, `deepInterview.intent_contract.items` containing the exact displayed locked-intent items, and `deepInterview.intent_contract.confirmation_options` listing only the displayed affirmative labels that lock the proposal (normally **Looks right**). The runtime recorder canonicalizes and locks this contract only when the user selects one of those labels; correction, deferral, free-text, and clarification answers never lock the pre-question proposal. Do not manually copy raw free text into intent evidence, and do not continue if this required recorder write fails.
246
+
209
247
  3. **Lock topology into state** after the answer. Store a normalized component list and confirmation timestamp:
210
248
 
211
249
  ```json
@@ -241,6 +279,10 @@ Options should include contextually relevant choices such as **Looks right**, **
241
279
  }
242
280
  ```
243
281
 
282
+ In the same Round 0 answer, the runtime recorder persists `state.intent_contract` version 1 from `deepInterview.intent_contract.items`. It contains the four exact categories `artifact`, `surface`, `integration`, and `constraint`; every item has a unique category-prefixed ID (for example `surface:review`) and a bounded non-empty statement. The recorder canonically sorts items, persists the full SHA-256 manifest digest, and binds confirmation to a redacted answer-hash reference. The confirmation answer locks this manifest before Round 1; later prose, inferred implementation detail, raw answer content, or a regenerated digest cannot replace it.
283
+
284
+ Before spec persistence, include every preserved locked ID literally in the final spec. Additions and clarifications need no extra question; the runtime derives and persists a `not_required` review when every locked ID remains. For any proposed missing locked ID, ask one intent-review question through `ask` and include `deepInterview.intent_review` with the proposed `observed_items`, every `supporting_substitution`, and the exact `approval_options` labels that count as approval. The runtime recorder writes `pending` when the user does not approve and writes `approved` only when an approval option is selected, binding the review to the recorder-generated answer hash without storing raw answer text. Approved reductions require every removed ID to map to an observed replacement ID. Spec persistence and handoff fail closed for missing, pending, malformed, stale, or unrecorded reduction review evidence. Intent review approves only that output reduction and never authorizes execution or ralplan handoff.
285
+
244
286
  4. **Legacy state migration:** When resuming an existing `deep-interview` state file that lacks `topology`, treat it as `"status": "legacy_missing"`. If no final `spec_path` exists yet, run Round 0 before the next ambiguity scoring pass and then continue with the existing transcript. If a final spec already exists, do not rewrite history; note in any handoff that topology was not captured for that legacy interview.
245
287
 
246
288
  5. **Single-component pass-through:** If the user confirms one active component, Phase 2 proceeds with the existing flow while still carrying `topology.components[0]` into scoring and spec output.
@@ -306,6 +348,8 @@ After applying `language.instruction` to the visible question, options, and gene
306
348
 
307
349
  When calling `ask`, SHOULD include optional structured metadata so the runtime can record the round without manual state writes: `deepInterview.round_id?`, `deepInterview.round`, `deepInterview.component`, `deepInterview.dimension`, and `deepInterview.ambiguity`. Keep this metadata aligned with the visible Round/Component/Targeting/Ambiguity line; if metadata cannot be supplied, the legacy formatted question text remains the fallback.
308
350
 
351
+ If the `ask` tool returns `clarificationQuestion`, treat it as a non-answer about the displayed choices. Answer the clarification briefly from the current interview context, then call `ask` again with the exact original question, options, and `deepInterview.*` metadata. A clarification bypasses Step 2b′ auto-answer, Step 2b″ free-text refine, Step 2c ambiguity scoring, Step 2d progress reporting, and Step 2e state updates; it must not be recorded as a round answer. This does not violate the one-question-per-round rule because the round remains unresolved until the user submits a real listed option or `Other` answer.
352
+
309
353
  ### Step 2b′: Auto-Answer Opted-Out Questions
310
354
 
311
355
  After the `ask` tool resolves and before ambiguity scoring, if the user opts out of answering the current question or explicitly asks the agent to decide, load `auto-answer-uncertain.md` as an internal `kind: "skill-fragment"` prompt for a fork-context architect. Pass the opted-out question, prompt-safe transcript summary, locked topology, current scores/gaps, and any auto-research candidates used for the round. The architect must return exactly one decisive answer with rationale, confidence, and explicit uncertainty. Validate the response shape before using it; if valid, record it as the tentative answer for scoring, append the round number to `auto_answered_rounds`, and mark the transcript answer as architect-assisted.
@@ -314,7 +358,7 @@ Auto-answer has a clarity cap: unless the architect confidence is `high` and unc
314
358
 
315
359
  ### Step 2b″: Refine Free-Text Answers
316
360
 
317
- When the user's answer is free-text that carries reasoning, constraints, or scope decisions, do not forward it to scoring as a lossy one-line label. First structure it into a compact interpretation using the canonical sections — **Decision**, **Reasoning**, **Constraints (user-stated)**, **Out of scope (user-stated)**, and **Codebase context (verified)** (omit empty sections) — then confirm with exactly one `ask` that nothing is lost or misrepresented. Apply `language.instruction` when present.
361
+ When the user's answer is free-text that carries reasoning, constraints, or scope decisions, do not forward it to scoring as a lossy one-line label. First structure it into a compact interpretation using the canonical sections — **Decision**, **Reasoning**, **Constraints (user-stated)**, **Out of scope (user-stated)**, and **Codebase context (verified)** (omit empty sections). Then confirm with exactly one `ask` that nothing is lost or misrepresented: the `ask` question body MUST render the full structured interpretation — every non-empty canonical section, verbatim — before the confirmation prompt. The user is approving that specific interpretation, so it must be visible inside the question body; never ask "does this capture it?" / "이 해석이 맞아?" without first displaying the interpretation itself. A confirmation `ask` whose body omits the interpretation it is asking about is a hard error: re-issue it with the interpretation shown. Apply `language.instruction` when present.
318
362
 
319
363
  Offer options such as **Send as-is**, **Add a constraint**, **Mark something out of scope**, **Add context**, and **Rewrite**, plus free-text. If the user picks anything other than "Send as-is", collect the exact missing text with one follow-up `ask` (never infer it from the option label), fold it into the structured interpretation, and re-confirm. Do not advance to scoring while the user is still saying something is missing.
320
364
 
@@ -338,6 +382,17 @@ Ambiguity-raising triggers:
338
382
 
339
383
  Use **mechanism A** for every ambiguity rise: a trigger LOWERS the affected component/dimension clarity score, and the existing weighted formula raises ambiguity. There is **no separate penalty term**; ambiguity remains bounded by the same greenfield/brownfield formula.
340
384
 
385
+ **Deterministic ambiguity floor (runtime-enforced).** The runtime independently computes a code-level floor from persisted state and clamps every reported ambiguity to `max(reported, floor)` at write time — the scorer cannot under-report below what code can objectively measure:
386
+
387
+ - `+0.10` per established fact marked `disputed` that has no `superseded_by` resolution (contradiction pressure)
388
+ - `+0.05` per active topology component whose goal/constraints/criteria clarity is still unscored (gap pressure — persist `topology.components[].clarity_scores` every round or the floor blocks convergence)
389
+ - `+0.05 × (auto-answered rounds / scored rounds)` (assumption dilution)
390
+
391
+ Cooperate with the floor rather than fight it:
392
+ - Replacing an already-scored answer for the same round (a retraction/pivot) automatically marks that round's established facts as disputed; ambiguity rises mechanically even when no trigger is reported. Treat a floor-driven rise as trigger evidence and score the affected dimensions accordingly.
393
+ - A disputed fact keeps the floor at or above `0.10` — above the default threshold — so convergence is blocked until the dispute is resolved: either the user re-confirms the original fact (set `disputed: false`) or the superseding decision is recorded as a new established fact and the old fact gets `superseded_by: <new fact id>`. Never delete the contradicted fact.
394
+ - When the effective score was clamped upward, the persisted round carries `reported_ambiguity` (your raw score) and `ambiguity_floor`; report the floor and its dominant cause in the Step 2d table instead of pretending the raw score held.
395
+
341
396
  The rise is SILENT: no modal, no forced-resolution step, and no dedicated conflict UI. Surface it through the normal per-round report and by targeting the next question at the affected component/dimension.
342
397
 
343
398
  Structured scorer output is required. Include `triggers`, `trigger_status`, `affected_component`, `affected_dimension`, `prior_dimension_score`, `new_dimension_score`, `prior_ambiguity`, `new_ambiguity`, `evidence`, `contradicted_established_fact` when relevant, and `disputed_unresolved_rationale` when applicable.
@@ -401,6 +456,7 @@ Respond as JSON. Include an additional "ontology" key containing the entities ar
401
456
 
402
457
  Greenfield: `ambiguity = 1 - (goal × 0.40 + constraints × 0.30 + criteria × 0.30)`
403
458
  Brownfield: `ambiguity = 1 - (goal × 0.35 + constraints × 0.25 + criteria × 0.25 + context × 0.15)`
459
+ Brownfield adds the 15% Context Clarity dimension (Goal/Constraint/Criteria become 35/25/25) because safely modifying existing code requires understanding the system being changed.
404
460
 
405
461
  **Calculate ontology stability:**
406
462
 
@@ -433,6 +489,7 @@ Round {n} complete.
433
489
  | Success Criteria | {s} | {w} | {s*w} | {gap or "Clear"} |
434
490
  | Context (brownfield) | {s} | {w} | {s*w} | {gap or "Clear"} |
435
491
  | **Ambiguity** | | | **{prior_score}% -> {score}% {up|down|flat}** | {if up: trigger name such as "A direct contradiction"} |
492
+ | **Floor** (only when clamped) | | | **{floor}%** | {dominant cause: disputed fact / unscored component / auto-answer dilution} |
436
493
 
437
494
  **Topology:** Targeted {target_component_name} | Active: {active_component_count} | Deferred: {deferred_component_count} | Next rotation after: {last_targeted_component_id}
438
495
 
@@ -447,18 +504,84 @@ Round {n} complete.
447
504
 
448
505
  Apply `language.instruction` when present before showing this progress report so status text, gaps, and next-target phrasing stay in the preserved session language.
449
506
 
450
- Then apply the self-proofread once to narrative status text, generated prose cells, gaps, and next-target phrasing; preserve only table structure, fixed status labels, scores, weights, component ids, and trigger tokens.
507
+ Then apply the self-proofread once (DIPP-5) to narrative status text, generated prose cells, gaps, and next-target phrasing; preserve only table structure, fixed status labels, scores, weights, component ids, and trigger tokens.
451
508
 
452
509
  ### Step 2e: Update State
453
510
 
454
- Update state in two phases. The `ask` answer is first recorded by the runtime as an `answered` shell. Scoring then enriches the same round record to `scored` with global scores, per-component `topology.components[].clarity_scores`, `topology.components[].weakest_dimension`, trigger metadata, established-facts changes, ontology snapshot, `topology.last_targeted_component_id`, `auto_researched_rounds`, `auto_answered_rounds`, and `architect_failures`. When `deepInterview` ask metadata is present, no manual per-round `skc state write` is required for the answer shell; only scoring enrichment/state maintenance remains. When metadata is absent, use the legacy `skc state write` path to persist the new round and never patch `.skc/_session-{sessionid}/state` directly unless an explicit force override is active.
511
+ Update state in two phases. The `ask` answer is first recorded by the runtime as an `answered` shell. Scoring then enriches the same round record to `scored` with global scores, per-component `topology.components[].clarity_scores`, `topology.components[].weakest_dimension`, trigger metadata, established-facts changes, ontology snapshot, `topology.last_targeted_component_id`, `auto_researched_rounds`, `auto_answered_rounds`, and `architect_failures`. When `deepInterview` ask metadata is present, no manual per-round write is required for the answer shell; only scoring enrichment/state maintenance remains. For scoring enrichment and state maintenance, use the native `skc deep-interview` surface and keep every payload **incremental**: stage only the delta for the current round (`stage --for record-round` with just the one round record carrying its `round_key`; the runtime merges it into the existing transcript by durable key), only the changed facts (`--for update-facts`; facts merge losslessly by `id` — a one-fact patch never erases prior facts), or only the changed maintenance fields (`--for merge-state`). Never resend the whole `rounds` array or the full state envelope — earlier rounds are already persisted, resending them is wasteful and racy, and the merge preserves them without your copy. Optionally dry-run with `check`, then commit with `apply`; for a simple immediate update, `skc deep-interview write --input '<json>'` is the one-shot equivalent (incremental merge; add `--reset` only when deliberately replacing state — the locked intent contract survives a reset). Ambiguity is **runtime-owned**: `apply`/`write` derive `current_ambiguity` from the latest scored round and clamp it to the deterministic floor; report the round's scores and your raw `ambiguity` on the round record, then read the effective value back from the command output (`current_ambiguity`/`result_ambiguity`) instead of hand-setting `state.current_ambiguity`. The session resolves from `SKC_SESSION_ID` automatically; exactly one draft is pending at a time, and a revision conflict at `apply` invalidates the draft with typed recovery — re-stage the same small delta against current state, never do revision arithmetic. Never patch `.skc/_session-{sessionid}/state` directly unless an explicit force override is active.
455
512
  Also recompute and persist `ambiguity_milestone` each round (detect band transitions for the Phase 3 panel), and persist `auto_answer_streak`, `refined_rounds`, `lateral_reviews`, and `lateral_panel_failures` alongside the existing fields.
456
513
 
457
- ### Step 2f: Check Soft Limits
514
+ #### Delta payload schemas
515
+
516
+ Every staged/write payload is one JSON object `{"state": { …delta only… }}`. Envelope lifecycle keys (`current_phase`, `active`, `skill`, `version`, `state_revision`, `receipt`, `updated_at`, `last_applied_draft_id`) are runtime-owned — if included they are stripped and reported back as `ignored_runtime_owned_keys`, never persisted. `state.intent_contract` and `state.intent_review` are recorder-owned: only the Round 0 / intent-review `ask` recorder can write them (they carry canonical digests and answer-hash bindings you cannot fabricate); a payload carrying them is stripped the same way — never hand-construct an intent contract.
517
+
518
+ **`stage --for record-round`** — exactly one round record, merged into the transcript by `round_key`:
519
+
520
+ ```json
521
+ {
522
+ "state": {
523
+ "rounds": [
524
+ {
525
+ "round": <n>,
526
+ "round_key": "<durable key from the answered shell>",
527
+ "lifecycle": "scored",
528
+ "ambiguity": <raw 0..1 score>,
529
+ "scores": { "goal": 0.9, "constraints": 0.8, "criteria": 0.9, "context": 0.85 },
530
+ "weakest_component_id": "<component id>",
531
+ "weakest_dimension": "goal|constraints|criteria|context",
532
+ "component_scores": { "<component-id>": { "goal": 0.9, "constraints": 0.8, "criteria": 0.9, "context": 0.85, "gaps": { } } },
533
+ "structured_scorer_output": { },
534
+ "ontology": { },
535
+ "ontology_stability": { }
536
+ }
537
+ ]
538
+ }
539
+ }
540
+ ```
541
+
542
+ Include only the one round being enriched; identity fields (`question_text`, `answer_hash`) already persisted on the shell never need resending — the merge preserves them and never downgrades `scored` back to `answered`.
543
+
544
+ **`stage --for update-facts`** — only the changed fact records, merged field-wise by `id`:
545
+
546
+ ```json
547
+ {
548
+ "state": {
549
+ "established_facts": [
550
+ { "id": "<fact-id>", "statement": "<fact>", "round": <n>, "disputed": false }
551
+ ]
552
+ }
553
+ }
554
+ ```
555
+
556
+ To dispute: send `{ "id": "<fact-id>", "disputed": true }`. To supersede: send `{ "id": "<old-id>", "disputed": false, "superseded_by": "<new-id>" }` plus the new fact record. A delta can never hard-delete a fact — unaddressed facts survive verbatim, so never resend the full facts array.
557
+
558
+ **`stage --for merge-state`** — only the changed maintenance fields (shallow-merged into `state`; `null` deletes a key):
559
+
560
+ ```json
561
+ {
562
+ "state": {
563
+ "ambiguity_milestone": "<band>",
564
+ "auto_answer_streak": <n>,
565
+ "refined_rounds": [<n>],
566
+ "lateral_reviews": [ { "round": <n>, "personas": [], "findings": "<summary>" } ],
567
+ "topology": { "components": [ … ], "last_targeted_component_id": "<id>" }
568
+ }
569
+ }
570
+ ```
571
+
572
+ `topology` and other object fields replace whole — include the full object when changing any part of it; `rounds` and `established_facts` are the only keyed-merge collections.
573
+
574
+ **`write --input`** — same `{"state":{…}}` shape and same merge semantics as a staged `merge-state` apply, committed in one step. `write --reset --input` replaces the whole `state` with the payload (the locked `intent_contract` is re-attached automatically); use it only for deliberate re-initialization.
575
+
576
+ ### Step 2f: Check Tiered Confirmation Cadence
577
+
578
+ Confirmation cadence is tiered by round, adopted from ouroboros's ooo interview, while the hard safety cap is retained:
458
579
 
459
- - **Round 3+**: Allow early exit if user says "enough", "let's go", "build it"
460
- - **Round 10**: Show soft warning: "We're at 10 rounds. Current ambiguity: {score}%. Continue or proceed with current clarity?"
461
- - **Round 100**: Hard cap: "Maximum interview rounds reached. Proceeding with current clarity level ({score}%)."
580
+ - **Rounds 1-3 (auto-continue)**: minimum context gathering — proceed to the next question without a "continue?" prompt.
581
+ - **Rounds 4-15 (ask to continue)**: after each round, ask "Continue, or proceed with current clarity ({score}%)?" so the user controls depth.
582
+ - **Rounds 16+ (diminishing-returns warning)**: keep asking "Continue?" but prefix a diminishing-returns warning: "We're at {n} rounds (ambiguity: {score}%); each further round yields less. Continue or proceed?"
583
+ - **Round 3+ early exit**: still allow immediate exit if the user says "enough", "let's go", "build it".
584
+ - **Round 100 (hard cap)**: "Maximum interview rounds reached. Proceeding with current clarity level ({score}%)." The tiered cadence never removes this hard safety cap.
462
585
 
463
586
  ## Phase 3: Lateral Review Panel (milestone-triggered)
464
587
 
@@ -495,7 +618,7 @@ When ambiguity ≤ threshold (or hard cap / early exit):
495
618
 
496
619
  **4a. Closure / Acceptance Guard.** Even when ambiguity ≤ threshold, do not treat the math as completion. Run an independent readiness audit from the full main-session perspective (including explore findings, established facts, and triggers the scorer may not have fully weighed). Confirm every active topology component has goal/constraint/criteria coverage, no unresolved or disputed trigger remains on a path that matters, and no low-confidence auto-answer is standing in for user-confirmed truth above the clarity cap. If a material gap exists, explicitly override the gate to the user — "The math says ready, but I am not accepting it yet because {gap}" — and ask the single highest-impact follow-up, returning to Phase 2. Record any override in `state.closure_overrides`.
497
620
 
498
- **4b. Restate gate.** Once closure passes, collapse the agreed answers into ONE sentence goal that covers every active component, and confirm it with a single `ask`: "If someone read only this line, would they reach the same outcome you have in mind?" Offer **Yes, crystallize**, **Adjust wording**, and **Missing scope**, plus free-text, applying `language.instruction` when present. Because this gate has options, it MUST go through `ask`: do not print the Restate question and options as assistant prose with `Question:`/`Options:` labels. If the Restate gate was already printed that way, immediately call `ask` with the same question/options before accepting or waiting for any answer. On "Adjust wording" / "Missing scope", collect the exact correction with one follow-up `ask`, route it back through Step 2c scoring and established-facts maintenance (a correction can change ambiguity), then re-run closure and ask the Restate gate again. Cap at two loops; if alignment is not reached, return to Phase 2 with a targeted question instead of forcing a goal line. Persist the confirmed line as `state.restated_goal`.
621
+ **4b. Restate gate.** Once closure passes, collapse the agreed answers into ONE sentence goal that covers every active component, and confirm it with a single `ask` whose body MUST begin by stating that one-sentence goal verbatim, followed by: "If someone read only this line, would they reach the same outcome you have in mind?" The goal line must be visible inside the `ask` body; never ask the confirmation without first displaying the collapsed goal it refers to. Offer **Yes, crystallize**, **Adjust wording**, and **Missing scope**, plus free-text, applying `language.instruction` when present. Because this gate has options, it MUST go through `ask`: do not print the Restate question and options as assistant prose with `Question:`/`Options:` labels. If the Restate gate was already printed that way, immediately call `ask` with the same question/options before accepting or waiting for any answer. On "Adjust wording" / "Missing scope", collect the exact correction with one follow-up `ask`, route it back through Step 2c scoring and established-facts maintenance (a correction can change ambiguity), then re-run closure and ask the Restate gate again. Cap at two loops; if alignment is not reached, return to Phase 2 with a targeted question instead of forcing a goal line. Persist the confirmed line as `state.restated_goal`.
499
622
 
500
623
  1. **Generate the specification** using opus model with the prompt-safe transcript. If the full interview transcript or initial context is too large, include the summary plus all concrete decisions, acceptance criteria, unresolved gaps, and ontology snapshots; never overflow the prompt with raw oversized context.
501
624
  - Apply `language.instruction` when present so user-facing prose in the spec preserves the session language; keep code identifiers, file paths, commands, JSON/settings keys, and quoted source text unchanged.
@@ -647,10 +770,10 @@ After the spec is written, mark it `pending approval` and present execution opti
647
770
 
648
771
  ### Phase 5b: Handoff before chain
649
772
 
650
- Before invoking `/skill:ralplan`, `/skill:team`, or `/skill:ultragoal`, the final spec must already be persisted through the native deep-interview write command. For ordinary user-selected handoff, mark deep-interview ready for the skill tool's chain guard:
773
+ Before invoking `/skill:ralplan`, `/skill:team`, or `/skill:ultragoal`, the final spec must already be persisted through the native deep-interview write command (`skc deep-interview --write --stage final …`). That command itself moves the workflow to the `handoff` phase, so no separate state write is needed for the skill tool's chain guard. Verify readiness with:
651
774
 
652
775
  ```
653
- skc state deep-interview write --input '{"current_phase":"handoff"}' --json
776
+ skc deep-interview read --json
654
777
  ```
655
778
 
656
779
  For a preselected deliberate ralplan path, prefer the single sanctioned bridge command instead:
@@ -695,7 +818,7 @@ Skipping any stage is possible but reduces quality assurance:
695
818
  - Use `read/search/find exploration or a bounded read-only planner/architect subagent` for brownfield codebase exploration (run BEFORE asking user about codebase)
696
819
  - Use opus model (temperature 0.1) for ambiguity scoring — consistency is critical
697
820
  - Round 0 topology confirmation happens before ambiguity scoring; Phase 2 scoring must honor locked topology and rotate targeting across active components when more than one is present
698
- - Use `skc state write` / `skc state read` for interview state persistence; the initial and subsequent deep-interview state payloads must include `threshold_source` alongside `threshold`; do not edit `.skc/_session-{sessionid}/state` directly without force override.
821
+ - Use `skc deep-interview write` / `skc deep-interview read` for interview state persistence; the initial and subsequent deep-interview state payloads must include `threshold_source` alongside `threshold`; do not edit `.skc/_session-{sessionid}/state` directly without force override. For incremental scoring/maintenance updates, prefer the staged-transition verbs (`stage --for <transition> --input '<json>'`, `check`, `apply`, `discard`) — stage only the current delta (one round record by `round_key`, changed facts, or changed fields), never the whole transcript; `write` is incremental by default and replaces only with an explicit `--reset`; the session is inherited from `SKC_SESSION_ID`, revision CAS is runtime-owned, and the effective `current_ambiguity` is derived and clamped by the CLI at `apply`/`write` — read it from the command output rather than setting it yourself.
699
822
  - Use the SKC workflow CLI to save the final spec at `.skc/_session-{sessionid}/specs/deep-interview-{slug}.md` exactly; do not use `write`, `edit`, or `ast_edit` directly on `.skc/` paths without force override.
700
823
  - Use public SKC workflow entrypoints to bridge to ralplan, ultragoal, or team only after explicit execution approval — never implement directly. Implementation handoff defaults to ultragoal; reserve team for when tmux-based interactive worker parallelization is genuinely required.
701
824
  - The lateral-review panel spawns read-only persona subagents (Task tool) in parallel with independent context; it is an assist layer, never an executor and never the completion authority
@@ -837,7 +960,7 @@ Optional settings in `.skc/settings.json`:
837
960
 
838
961
  ## Resume
839
962
 
840
- If interrupted, run `/skill:deep-interview` again. The skill resumes from SKC workflow state via `skc state read`; do not read or edit `.skc/_session-{sessionid}/state` files directly unless an explicit force override is active.
963
+ If interrupted, run `/skill:deep-interview` again. The skill resumes from SKC workflow state via `skc deep-interview read`; do not read or edit `.skc/_session-{sessionid}/state` files directly unless an explicit force override is active.
841
964
 
842
965
  ## Integration with staged team routing
843
966