@adhdev/daemon-core 0.9.82-rc.34 → 0.9.82-rc.341

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 (318) hide show
  1. package/dist/boot/daemon-lifecycle.d.ts +8 -0
  2. package/dist/boot/process-hardening.d.ts +50 -0
  3. package/dist/build-info.d.ts +37 -0
  4. package/dist/chat/source-machine.d.ts +166 -0
  5. package/dist/chat/source-resolver.d.ts +104 -0
  6. package/dist/chat/subscription-updates.d.ts +1 -0
  7. package/dist/cli-adapter-types.d.ts +46 -2
  8. package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
  9. package/dist/cli-adapters/cli-state-engine.d.ts +198 -0
  10. package/dist/cli-adapters/provider-cli-adapter.d.ts +116 -64
  11. package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
  12. package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
  13. package/dist/cli-adapters/provider-cli-shared.d.ts +53 -0
  14. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  15. package/dist/cli-adapters/resolve-executable.d.ts +14 -0
  16. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
  17. package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
  18. package/dist/cli-adapters/terminal-screen.d.ts +4 -11
  19. package/dist/commands/cli-manager.d.ts +2 -1
  20. package/dist/commands/handler.d.ts +110 -0
  21. package/dist/commands/mesh-coordinator.d.ts +85 -1
  22. package/dist/commands/router.d.ts +308 -1
  23. package/dist/commands/upgrade-helper.d.ts +12 -0
  24. package/dist/config/chat-history.d.ts +9 -0
  25. package/dist/config/config.d.ts +5 -0
  26. package/dist/config/mesh-config.d.ts +77 -1
  27. package/dist/detection/ide-detector.d.ts +13 -0
  28. package/dist/detection/win32-ide-version.d.ts +37 -0
  29. package/dist/git/change-impact-config.d.ts +159 -0
  30. package/dist/git/git-commands.d.ts +11 -1
  31. package/dist/git/git-diff.d.ts +6 -0
  32. package/dist/git/git-executor.d.ts +11 -0
  33. package/dist/git/git-status.d.ts +23 -0
  34. package/dist/git/git-types.d.ts +2 -50
  35. package/dist/git/index.d.ts +2 -0
  36. package/dist/index.d.ts +52 -13
  37. package/dist/index.js +42012 -17098
  38. package/dist/index.js.map +1 -1
  39. package/dist/index.mjs +41683 -16890
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/installer.d.ts +1 -4
  42. package/dist/ipc/local-ipc-server.d.ts +91 -0
  43. package/dist/launch.d.ts +1 -1
  44. package/dist/logging/async-batch-writer.d.ts +10 -0
  45. package/dist/logging/log-redactor.d.ts +24 -0
  46. package/dist/logging/log-tail-reader.d.ts +46 -0
  47. package/dist/mesh/contracts.d.ts +164 -0
  48. package/dist/mesh/coordinator-prompt.d.ts +36 -0
  49. package/dist/mesh/coordinator-registry.d.ts +59 -0
  50. package/dist/mesh/mesh-active-work.d.ts +174 -0
  51. package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
  52. package/dist/mesh/mesh-events-coordinator.d.ts +169 -0
  53. package/dist/mesh/mesh-events-pending.d.ts +45 -0
  54. package/dist/mesh/mesh-events-stale.d.ts +40 -0
  55. package/dist/mesh/mesh-events-utils.d.ts +66 -0
  56. package/dist/mesh/mesh-events.d.ts +6 -49
  57. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  58. package/dist/mesh/mesh-host-ownership.d.ts +9 -0
  59. package/dist/mesh/mesh-init.d.ts +86 -0
  60. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
  61. package/dist/mesh/mesh-ledger.d.ts +77 -1
  62. package/dist/mesh/mesh-missions.d.ts +116 -0
  63. package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
  64. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  65. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  66. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  67. package/dist/mesh/mesh-routing.d.ts +70 -0
  68. package/dist/mesh/mesh-runtime-store.d.ts +418 -0
  69. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  70. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
  71. package/dist/mesh/mesh-work-queue.d.ts +208 -5
  72. package/dist/mesh/preview-freshness.d.ts +18 -0
  73. package/dist/mesh/refine-config.d.ts +216 -0
  74. package/dist/mesh/worktree-bootstrap-config.d.ts +135 -0
  75. package/dist/providers/acp-provider-instance.d.ts +2 -0
  76. package/dist/providers/approval-utils.d.ts +13 -0
  77. package/dist/providers/chat-message-normalization.d.ts +12 -0
  78. package/dist/providers/cli-provider-instance.d.ts +76 -3
  79. package/dist/providers/contracts.d.ts +139 -6
  80. package/dist/providers/external-sources.d.ts +71 -0
  81. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
  82. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  83. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  84. package/dist/providers/native-history/dispatcher.d.ts +27 -0
  85. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  86. package/dist/providers/native-history/index.d.ts +13 -0
  87. package/dist/providers/provider-instance-manager.d.ts +13 -0
  88. package/dist/providers/provider-instance.d.ts +13 -1
  89. package/dist/providers/provider-loader.d.ts +26 -4
  90. package/dist/providers/provider-trust.d.ts +31 -0
  91. package/dist/providers/read-chat-contract.d.ts +29 -0
  92. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  93. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +85 -0
  94. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  95. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  96. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  97. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  98. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  99. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  100. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  101. package/dist/providers/sdk/v1/index.d.ts +30 -0
  102. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  103. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  104. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  105. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  106. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  107. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  108. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  109. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  110. package/dist/providers/spec/adapter.d.ts +69 -0
  111. package/dist/providers/spec/cli-adapter.d.ts +217 -0
  112. package/dist/providers/spec/evaluator.d.ts +23 -0
  113. package/dist/providers/spec/fsm-driver.d.ts +306 -0
  114. package/dist/providers/spec/fsm-evaluator.d.ts +72 -0
  115. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  116. package/dist/providers/spec/fsm-types.d.ts +144 -0
  117. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  118. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  119. package/dist/providers/spec/route.d.ts +4 -0
  120. package/dist/providers/spec/types.d.ts +180 -0
  121. package/dist/providers/status-monitor.d.ts +7 -7
  122. package/dist/providers/transcript-v2.d.ts +176 -0
  123. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  124. package/dist/providers/working-dir.d.ts +17 -0
  125. package/dist/repo-mesh-types.d.ts +295 -13
  126. package/dist/sessions/registry.d.ts +6 -0
  127. package/dist/shared-types-extra.d.ts +2 -4
  128. package/dist/shared-types.d.ts +59 -2
  129. package/dist/status/normalize.d.ts +1 -1
  130. package/dist/status/normalize.js +1 -0
  131. package/dist/status/normalize.js.map +1 -1
  132. package/dist/status/normalize.mjs +1 -0
  133. package/dist/status/normalize.mjs.map +1 -1
  134. package/dist/status/reporter.d.ts +2 -0
  135. package/dist/status/snapshot.d.ts +26 -0
  136. package/dist/system/load-better-sqlite3.d.ts +21 -0
  137. package/dist/types.d.ts +5 -0
  138. package/package.json +7 -3
  139. package/src/agent-stream/poller.ts +2 -3
  140. package/src/agent-stream/provider-adapter.ts +1 -1
  141. package/src/boot/daemon-lifecycle.ts +55 -12
  142. package/src/boot/process-hardening.ts +89 -0
  143. package/src/build-info.ts +73 -0
  144. package/src/chat/source-machine.ts +534 -0
  145. package/src/chat/source-resolver.ts +0 -0
  146. package/src/chat/subscription-updates.ts +20 -1
  147. package/src/cli-adapter-types.d.ts +1 -0
  148. package/src/cli-adapter-types.ts +47 -2
  149. package/src/cli-adapters/cli-script-runner.ts +421 -0
  150. package/src/cli-adapters/cli-state-engine.ts +1215 -0
  151. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  152. package/src/cli-adapters/provider-cli-adapter.ts +774 -1141
  153. package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
  154. package/src/cli-adapters/provider-cli-parse.ts +13 -0
  155. package/src/cli-adapters/provider-cli-runtime.ts +56 -7
  156. package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
  157. package/src/cli-adapters/provider-cli-shared.ts +100 -11
  158. package/src/cli-adapters/pty-transport.ts +2 -1
  159. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  160. package/src/cli-adapters/resolve-executable.ts +90 -0
  161. package/src/cli-adapters/session-host-transport.ts +2 -1
  162. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -29
  163. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  164. package/src/cli-adapters/terminal-screen.ts +16 -81
  165. package/src/commands/chat-commands.ts +1823 -62
  166. package/src/commands/cli-manager.ts +286 -14
  167. package/src/commands/handler.ts +809 -2
  168. package/src/commands/mesh-coordinator.ts +332 -122
  169. package/src/commands/router.ts +7433 -1317
  170. package/src/commands/stream-commands.ts +8 -0
  171. package/src/commands/upgrade-helper.ts +81 -30
  172. package/src/config/chat-history.ts +483 -24
  173. package/src/config/config.ts +12 -0
  174. package/src/config/mesh-config.ts +388 -6
  175. package/src/config/recent-activity.ts +8 -2
  176. package/src/daemon/dev-auto-implement.ts +3 -2
  177. package/src/daemon/dev-cli-debug.ts +10 -1
  178. package/src/detection/cli-detector.ts +28 -9
  179. package/src/detection/ide-detector.ts +55 -16
  180. package/src/detection/win32-ide-version.ts +106 -0
  181. package/src/git/change-impact-config.ts +354 -0
  182. package/src/git/git-commands.ts +55 -14
  183. package/src/git/git-diff.ts +53 -0
  184. package/src/git/git-executor.ts +12 -0
  185. package/src/git/git-status.ts +574 -43
  186. package/src/git/git-types.ts +14 -62
  187. package/src/git/git-worktree.ts +8 -1
  188. package/src/git/index.ts +16 -0
  189. package/src/index.ts +146 -12
  190. package/src/installer.d.ts +1 -1
  191. package/src/installer.ts +8 -6
  192. package/src/ipc/local-ipc-server.ts +278 -0
  193. package/src/launch.d.ts +1 -1
  194. package/src/launch.ts +37 -28
  195. package/src/logging/async-batch-writer.ts +55 -0
  196. package/src/logging/log-redactor.ts +100 -0
  197. package/src/logging/log-tail-reader.ts +220 -0
  198. package/src/logging/logger.ts +2 -1
  199. package/src/mesh/contracts.ts +329 -0
  200. package/src/mesh/coordinator-prompt.ts +234 -31
  201. package/src/mesh/coordinator-registry.ts +121 -0
  202. package/src/mesh/mesh-active-work.ts +623 -0
  203. package/src/mesh/mesh-delivery-policy.ts +315 -0
  204. package/src/mesh/mesh-events-coordinator.ts +2144 -0
  205. package/src/mesh/mesh-events-pending.ts +508 -0
  206. package/src/mesh/mesh-events-stale.ts +290 -0
  207. package/src/mesh/mesh-events-utils.ts +300 -0
  208. package/src/mesh/mesh-events.ts +30 -1035
  209. package/src/mesh/mesh-fast-forward.ts +839 -0
  210. package/src/mesh/mesh-host-ownership.ts +73 -0
  211. package/src/mesh/mesh-init.ts +260 -0
  212. package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
  213. package/src/mesh/mesh-ledger.ts +589 -102
  214. package/src/mesh/mesh-missions.ts +248 -0
  215. package/src/mesh/mesh-reconcile-loop.ts +822 -0
  216. package/src/mesh/mesh-refine-batch.ts +197 -0
  217. package/src/mesh/mesh-refine-status.ts +231 -0
  218. package/src/mesh/mesh-review-inbox.ts +307 -0
  219. package/src/mesh/mesh-routing.ts +291 -0
  220. package/src/mesh/mesh-runtime-store.ts +1626 -0
  221. package/src/mesh/mesh-task-stats.ts +154 -0
  222. package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
  223. package/src/mesh/mesh-work-queue.ts +888 -141
  224. package/src/mesh/preview-freshness.ts +118 -0
  225. package/src/mesh/refine-config.ts +423 -0
  226. package/src/mesh/worktree-bootstrap-config.ts +331 -0
  227. package/src/providers/acp-provider-instance.ts +25 -9
  228. package/src/providers/approval-utils.d.ts +4 -0
  229. package/src/providers/approval-utils.ts +47 -5
  230. package/src/providers/chat-message-normalization.ts +45 -5
  231. package/src/providers/cli-provider-instance.ts +1038 -99
  232. package/src/providers/contracts.d.ts +55 -0
  233. package/src/providers/contracts.ts +150 -6
  234. package/src/providers/extension-provider-instance.ts +12 -7
  235. package/src/providers/external-sources.ts +218 -0
  236. package/src/providers/ide-provider-instance.ts +35 -12
  237. package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
  238. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  239. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  240. package/src/providers/native-history/dispatcher.ts +340 -0
  241. package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
  242. package/src/providers/native-history/index.ts +30 -0
  243. package/src/providers/provider-instance-manager.ts +30 -0
  244. package/src/providers/provider-instance.ts +10 -1
  245. package/src/providers/provider-loader.ts +670 -50
  246. package/src/providers/provider-schema.ts +87 -14
  247. package/src/providers/provider-trust.ts +114 -0
  248. package/src/providers/read-chat-contract.ts +76 -16
  249. package/src/providers/sdk/README.md +49 -0
  250. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  251. package/src/providers/sdk/v1/builders/cli/detect-status.ts +262 -0
  252. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  253. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
  254. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  255. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  256. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  257. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  258. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  259. package/src/providers/sdk/v1/index.ts +152 -0
  260. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  261. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  262. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  263. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +504 -0
  264. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  265. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  266. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  267. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  268. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  269. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  270. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  271. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  272. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  273. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  274. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  275. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  276. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  277. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  278. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  279. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  280. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  281. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  282. package/src/providers/sdk/v1/validators/index.ts +19 -0
  283. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  284. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  285. package/src/providers/spec/adapter.ts +168 -0
  286. package/src/providers/spec/cli-adapter.ts +986 -0
  287. package/src/providers/spec/evaluator.ts +345 -0
  288. package/src/providers/spec/fsm-driver.ts +1015 -0
  289. package/src/providers/spec/fsm-evaluator.ts +255 -0
  290. package/src/providers/spec/fsm-loader.ts +120 -0
  291. package/src/providers/spec/fsm-types.ts +238 -0
  292. package/src/providers/spec/native-history-executor.ts +1136 -0
  293. package/src/providers/spec/pre-launch-trust.ts +104 -0
  294. package/src/providers/spec/route.ts +51 -0
  295. package/src/providers/spec/types.ts +226 -0
  296. package/src/providers/status-monitor.d.ts +7 -7
  297. package/src/providers/status-monitor.ts +37 -22
  298. package/src/providers/transcript-v2.ts +567 -0
  299. package/src/providers/types/interactive-prompt.ts +536 -0
  300. package/src/providers/version-archive.ts +64 -24
  301. package/src/providers/working-dir.ts +23 -0
  302. package/src/repo-mesh-types.ts +378 -14
  303. package/src/sessions/registry.ts +6 -0
  304. package/src/shared-types-extra.ts +2 -4
  305. package/src/shared-types.d.ts +8 -0
  306. package/src/shared-types.ts +64 -1
  307. package/src/status/builders.ts +26 -6
  308. package/src/status/normalize.ts +2 -0
  309. package/src/status/reporter.ts +19 -1
  310. package/src/status/snapshot.ts +95 -26
  311. package/src/system/host-memory.ts +29 -12
  312. package/src/system/load-better-sqlite3.ts +68 -0
  313. package/src/types.ts +5 -0
  314. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  315. package/dist/mesh/mesh-sync.d.ts +0 -53
  316. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  317. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  318. package/src/mesh/mesh-sync.ts +0 -111
@@ -0,0 +1,69 @@
1
+ import type { PtyTransportFactory } from '../../cli-adapters/pty-transport.js';
2
+ export type { PtyTransportFactory };
3
+ export interface TerminalAdapterOpts {
4
+ binary: string;
5
+ args?: string[];
6
+ cwd?: string;
7
+ env?: Record<string, string>;
8
+ /**
9
+ * When true, `env` is already a COMPLETE, sanitized environment (the spawn
10
+ * planner merged + stripped process.env already) and must be passed to the
11
+ * PTY verbatim — NOT overlaid on top of process.env. Overlaying would
12
+ * re-introduce the npm_/PNPM_/parent-session keys the planner explicitly
13
+ * stripped, so the spec path's spawn env would diverge from the legacy
14
+ * path's. Defaults to false (legacy overlay behaviour) for any caller that
15
+ * still passes a partial env.
16
+ */
17
+ envIsComplete?: boolean;
18
+ cols?: number;
19
+ rows?: number;
20
+ /** Coalesce screen snapshots: emit on_screen_changed at most this often. */
21
+ screenChangeDebounceMs?: number;
22
+ tickIntervalMs?: number;
23
+ transportFactory?: PtyTransportFactory;
24
+ }
25
+ export interface TerminalAdapterHandlers {
26
+ init?(info: {
27
+ pid: number;
28
+ }): void;
29
+ on_pty_data?(chunk: string): void;
30
+ on_screen_changed?(snapshot: string): void;
31
+ on_exit?(info: {
32
+ exitCode: number;
33
+ }): void;
34
+ tick?(): void;
35
+ }
36
+ export declare class TerminalAdapter {
37
+ private readonly opts;
38
+ private readonly handlers;
39
+ private rows;
40
+ private cols;
41
+ private readonly screenDebounceMs;
42
+ private readonly tickIntervalMs;
43
+ private readonly factory;
44
+ private screen;
45
+ private pty;
46
+ private screenTimer;
47
+ private tickTimer;
48
+ private lastScreen;
49
+ constructor(opts: TerminalAdapterOpts, handlers: TerminalAdapterHandlers);
50
+ start(): void;
51
+ resize(cols: number, rows: number): void;
52
+ snapshot(): string;
53
+ /**
54
+ * Full-buffer snapshot including scrollback history. Unlike snapshot()
55
+ * (visible viewport only), this survives a tall prompt whose top has
56
+ * scrolled off-screen — used for content-pattern extraction (modal
57
+ * buttons / approval anchors), NOT for cursor-relative conditions.
58
+ */
59
+ snapshotWithScrollback(): string;
60
+ getCursorPosition(): {
61
+ row: number;
62
+ col: number;
63
+ };
64
+ send_keys(text: string): void;
65
+ kill(): void;
66
+ private onChunk;
67
+ private computeScreen;
68
+ private stopTimers;
69
+ }
@@ -0,0 +1,217 @@
1
+ import type { CliAdapter, CliAdapterStatus } from '../../cli-adapter-types.js';
2
+ import type { PtyTransportFactory } from '../../cli-adapters/pty-transport.js';
3
+ import { type InteractivePromptResponse } from '../types/interactive-prompt.js';
4
+ export declare class SpecCliAdapter implements CliAdapter {
5
+ readonly cliType: string;
6
+ readonly cliName: string;
7
+ readonly workingDir: string;
8
+ /**
9
+ * Marker the daemon's finalization gate checks: `getStatus()` returns
10
+ * `messages: []` by design here (chat history lives in the daemon's
11
+ * native-history pipeline, not the adapter). Without this flag,
12
+ * cli-provider-instance's `missing_final_assistant` gate would stall
13
+ * every turn until the 30s safety timeout because it expects the
14
+ * adapter to surface the final assistant message.
15
+ */
16
+ readonly chatMessagesOwnedExternally: true;
17
+ private driver;
18
+ /** Common spec fields the adapter reads, present in both v3 and v4. */
19
+ private spec;
20
+ private lastEvent;
21
+ private latestState;
22
+ private latestModal;
23
+ private statusCallback;
24
+ private ptyDataCallback;
25
+ private partialResponse;
26
+ private activeInteractivePrompt;
27
+ private interactivePromptTransport;
28
+ private claudeTuiPromptCaptureInFlight;
29
+ /**
30
+ * Wall clock of the first frame on which a held interactive prompt was
31
+ * observed to have left the screen. Mirrors the approval FSM's
32
+ * `modalLostAt` hysteresis (see cli-state-engine.ts): claude-cli's TUI
33
+ * repaints the choice picker as several PTY chunks, so a single frame
34
+ * with no "Enter to select" footer is not proof the prompt is gone — it
35
+ * may just be mid-repaint. We only clear the held prompt once it has
36
+ * been absent across a short grace window. Reset to null the moment the
37
+ * prompt footer reappears.
38
+ *
39
+ * Without this, a choice prompt resolved *directly in the terminal* (the
40
+ * user picked an option without going through ADHDev's
41
+ * setInteractivePromptResponse) was never cleared from
42
+ * `activeInteractivePrompt`, so getStatus() re-emitted the same prompt
43
+ * forever — the choice-resolve-stuck bug.
44
+ */
45
+ private interactivePromptLostAt;
46
+ private jsonLineTail;
47
+ private exited;
48
+ private spawned;
49
+ private providerSessionId;
50
+ /** Wall clock at the moment spawn() ran. Used as the cutoff for
51
+ * native-history file selection so a prior session's transcript
52
+ * can't leak into this session before the agent has written its
53
+ * own records. */
54
+ private spawnedAtMs;
55
+ /** Env vars the daemon set on the spawned child. Mesh coordinator
56
+ * points hermes at a per-coordinator HERMES_HOME so the dashboard's
57
+ * native-history reader needs that override to find the right
58
+ * state.db; without it the reader sees ~/.hermes/state.db which
59
+ * the coordinator-launched hermes never writes to. The choice to
60
+ * redirect HERMES_HOME is a workaround for an unresolved hermes
61
+ * upstream feature gap (see hermes-agent#23130 — runtime-supplied
62
+ * MCP config), so this routing keeps the dashboard honest until
63
+ * hermes ships a runtime MCP override. */
64
+ private spawnedEnv;
65
+ constructor(specPath: string, workingDir: string, cliArgs: string[], extraEnv: Record<string, string>, transportFactory?: PtyTransportFactory);
66
+ spawn(): Promise<void>;
67
+ sendMessage(text: string): Promise<void>;
68
+ getStatus(): CliAdapterStatus;
69
+ private maybeRefreshNativeHistory;
70
+ getScriptParsedStatus(): unknown;
71
+ getPartialResponse(): string;
72
+ shutdown(): void;
73
+ cancel(): void;
74
+ isProcessing(): boolean;
75
+ isReady(): boolean;
76
+ setOnStatusChange(cb: () => void): void;
77
+ setOnPtyData(cb: (data: string) => void): void;
78
+ writeRaw(data: string): void;
79
+ resize(cols: number, rows: number): void;
80
+ resolveModal(buttonIndex: number): void;
81
+ resolveAction(data: unknown): Promise<void>;
82
+ setInteractivePromptResponse(response: InteractivePromptResponse): Promise<void>;
83
+ isApprovalRecentlyResolved(): boolean;
84
+ clearHistory(): void;
85
+ updateRuntimeSettings(): void;
86
+ setServerConn(): void;
87
+ /**
88
+ * Map an invokeScript(name, args) call onto a control_bar entry.
89
+ *
90
+ * scriptName is matched against control.id. The control's action.type
91
+ * drives the dispatch:
92
+ *
93
+ * send_keys → click_control (e.g. stop)
94
+ * open_picker → two roles, driven by the screen, not a hardcoded list:
95
+ * - LIST (no choice arg): open the picker, wait for it
96
+ * to render, parse the on-screen options via
97
+ * `extract_choices`, and return them as
98
+ * `controlResult.options` (+ `currentValue`). This is
99
+ * how the dashboard's Model/Mode controls learn what is
100
+ * actually selectable in this CLI right now.
101
+ * - SELECT (args.choiceIndex / args.choiceLabel): drive
102
+ * the picker to that option using `submit_key`.
103
+ * attach_image → attach_image dispatch; expects args.blob (data url
104
+ * or base64) and args.mime
105
+ *
106
+ * Callers that pass an unknown control id get a { not_found } response.
107
+ * No control matched, no driver call — keeps the surface honest.
108
+ */
109
+ invokeScript(scriptName: string, args?: Record<string, unknown>): Promise<unknown>;
110
+ /**
111
+ * Open an `open_picker` control and return the options the CLI is showing,
112
+ * parsed live from the screen via `extract_choices`. Nothing is selected —
113
+ * the picker is left open so a follow-up SELECT invoke can commit a choice.
114
+ */
115
+ private openPickerAndListChoices;
116
+ /**
117
+ * Drive an already-listable picker to a specific option. The option can be
118
+ * named (choiceLabel — matched against the parsed on-screen labels) or
119
+ * positional (choiceIndex — the on-screen number). The actual keystrokes
120
+ * come from the spec's `submit_key` with `{index}` substituted, so the spec
121
+ * — not this code — decides how a selection is keyed for each CLI.
122
+ */
123
+ private selectPickerChoice;
124
+ /** Poll the live screen until the picker's `wait_for` condition matches,
125
+ * up to a short budget. Returns true if it rendered, false on timeout. */
126
+ private waitForPickerRendered;
127
+ /** Parse the picker's `extract_choices` pattern against the live screen.
128
+ * Each match yields { index, label, current }. `current` is true for the
129
+ * line the CLI marks with its cursor glyph (❯ ›). Purely screen-driven —
130
+ * no model/mode names are baked in. */
131
+ private extractPickerChoices;
132
+ /** Live text of a named screen section (or the whole screen when no
133
+ * section is named), resolved from the driver's current sections. */
134
+ private readScreenSectionText;
135
+ getDebugSnapshot(): unknown;
136
+ getRuntimeMetadata(): unknown;
137
+ updateRuntimeMeta(meta?: Record<string, unknown>): void;
138
+ refreshProviderDefinition(): void;
139
+ private handleEvent;
140
+ private detectInteractivePromptFromPtyChunk;
141
+ private readCurrentScreenSections;
142
+ private extractProviderSessionIdFromScreen;
143
+ private readClaudeScreenAssistantMessages;
144
+ /**
145
+ * Grace window a held interactive prompt must be absent from the screen
146
+ * before we treat it as resolved-in-terminal and clear it. claude-cli
147
+ * repaints the picker across multiple PTY chunks, so a single
148
+ * footer-less frame is not proof the prompt is gone. Sized in the same
149
+ * spirit as the approval FSM's `approvalCooldown` modal-lost hysteresis.
150
+ */
151
+ private static readonly INTERACTIVE_PROMPT_LOST_GRACE_MS;
152
+ /**
153
+ * Multi-question TUI capture: after Tabbing to a page, re-snapshot at this
154
+ * interval until its checkbox glyph column has settled, up to the timeout.
155
+ * The interval matches the legacy single fixed wait (120ms); the timeout
156
+ * bounds total capture time so a single-select page (which never shows
157
+ * glyphs) doesn't stall the capture indefinitely.
158
+ */
159
+ private static readonly CLAUDE_TUI_PAGE_POLL_INTERVAL_MS;
160
+ private static readonly CLAUDE_TUI_PAGE_SETTLE_TIMEOUT_MS;
161
+ /**
162
+ * Clear a held interactive prompt once the user has resolved it directly
163
+ * in the terminal (the choice picker leaves the screen without going
164
+ * through setInteractivePromptResponse). The approval path already does
165
+ * this via the FSM's modal-lost hysteresis; the interactive-prompt path
166
+ * had no equivalent, so a terminal-side answer left activeInteractivePrompt
167
+ * set and getStatus() re-emitted the same choice modal forever.
168
+ *
169
+ * Detection mirrors capture: the claude TUI picker is on-screen exactly
170
+ * while its "Enter to select" footer is rendered. When the footer is gone
171
+ * for INTERACTIVE_PROMPT_LOST_GRACE_MS the prompt is genuinely resolved.
172
+ */
173
+ private maybeClearResolvedClaudeTuiPrompt;
174
+ private maybeCaptureClaudeTuiPrompt;
175
+ /**
176
+ * The TUI prompt is captured on the FIRST frame that renders the
177
+ * "Enter to select" footer. At that instant the option rows' checkbox
178
+ * column may not have drawn yet, so `detectClaudeTuiMultiSelect` returns
179
+ * false and the prompt is frozen as single-select — the dashboard then
180
+ * renders radio buttons even though the picker is multi-select.
181
+ *
182
+ * While the same TUI prompt is still on screen, re-check the live snapshot:
183
+ * if checkbox glyphs have since appeared, promote any single-select
184
+ * question to multi-select and re-emit status. Promotion is one-way
185
+ * (false→true only) — once a question is known multi-select we never demote
186
+ * it, since the glyph column can scroll out of view on later frames.
187
+ *
188
+ * For MULTI-question prompts the per-page Tab capture is the actual source
189
+ * of the bug: pages 2..N are snapshotted ~120ms after the Tab keypress,
190
+ * before their option-row glyph column has redrawn, so those questions
191
+ * freeze as single-select while page 1 (already settled) is correct. We
192
+ * cannot upgrade blindly — the live snapshot shows only ONE focused page —
193
+ * but we CAN read that page's question text/header and upgrade the matching
194
+ * question. As the user navigates the picker (or it settles), each page is
195
+ * eventually re-read and repaired.
196
+ */
197
+ private maybeUpgradeClaudeTuiMultiSelect;
198
+ private readClaudeTuiHeaders;
199
+ /**
200
+ * Snapshot the currently-focused claude TUI page, polling until its
201
+ * option-row checkbox glyph column has settled (or a bounded timeout).
202
+ *
203
+ * Why poll: right after a Tab keypress the newly-focused page's glyph
204
+ * column has not redrawn yet, so an immediate snapshot shows the question +
205
+ * option labels but NO per-option checkbox markers — freezing that page as
206
+ * single-select. A fixed delay either races (too short) or is wasteful (too
207
+ * long). Instead we re-snapshot at a fixed interval and stop as soon as the
208
+ * frame shows multi-select glyphs, falling back to the last frame at the
209
+ * timeout. Single-select pages never show glyphs, so they always poll to the
210
+ * timeout — bounded small to keep capture snappy.
211
+ */
212
+ private snapshotSettledClaudeTuiPage;
213
+ private captureClaudeTuiPrompt;
214
+ getDebugState(): Record<string, any>;
215
+ getTraceState(limit?: number): Record<string, any>;
216
+ getProviderResolutionMeta(): Record<string, any>;
217
+ }
@@ -0,0 +1,23 @@
1
+ import type { SectionDef, Condition, ExtractTitle, ExtractButtons } from './types.js';
2
+ export interface ResolvedSection {
3
+ id: string;
4
+ fromLine: number;
5
+ toLine: number;
6
+ text: string;
7
+ }
8
+ export interface TraceEntry {
9
+ kind: 'section' | 'state_match' | 'state_skip' | 'modal' | 'control' | 'notification' | 'delegate';
10
+ text: string;
11
+ }
12
+ export declare function resolveSections(sectionsObj: Record<string, SectionDef>, lines: string[]): ResolvedSection[];
13
+ export declare function sectionText(sections: ResolvedSection[], sectionId: string | undefined, fullScreen: string): string;
14
+ export declare function evaluateCondition(cond: Condition, sections: ResolvedSection[], fullScreen: string, cursor: {
15
+ row: number;
16
+ col: number;
17
+ } | undefined, prevLines: string[] | undefined, trace: TraceEntry[], stateId: string): boolean;
18
+ export declare function extractTitle(rule: ExtractTitle, sections: ResolvedSection[], fullScreen: string): string | null;
19
+ export declare function extractButtonsFromRule(rule: ExtractButtons, hay: string): {
20
+ index: number;
21
+ label: string;
22
+ key: string;
23
+ }[];
@@ -0,0 +1,306 @@
1
+ import type { PtyTransportFactory } from '../../cli-adapters/pty-transport.js';
2
+ import { type TraceEntry } from './evaluator.js';
3
+ import { type TransitionEval } from './fsm-evaluator.js';
4
+ export type DashboardEvent = {
5
+ kind: 'pty_data';
6
+ chunk: string;
7
+ } | {
8
+ kind: 'state_changed';
9
+ state: {
10
+ id: string;
11
+ label: string;
12
+ title: string | null;
13
+ status: 'idle' | 'generating' | 'approval';
14
+ };
15
+ modal: {
16
+ title: string | null;
17
+ buttons: {
18
+ index: number;
19
+ label: string;
20
+ }[];
21
+ } | null;
22
+ controls: {
23
+ id: string;
24
+ label: string;
25
+ action_type: string;
26
+ }[];
27
+ } | {
28
+ kind: 'notification';
29
+ id: string;
30
+ title: string;
31
+ body: string;
32
+ } | {
33
+ kind: 'delegate';
34
+ id: string;
35
+ task: string;
36
+ } | {
37
+ kind: 'spec_trace';
38
+ entries: TraceEntry[];
39
+ } | {
40
+ kind: 'exit';
41
+ exit_code: number;
42
+ } | {
43
+ kind: 'spec_error';
44
+ errors: string[];
45
+ };
46
+ export type DashboardCommand = {
47
+ kind: 'send_message';
48
+ text: string;
49
+ } | {
50
+ kind: 'pty_write';
51
+ data: string;
52
+ } | {
53
+ kind: 'click_control';
54
+ control_id: string;
55
+ payload?: unknown;
56
+ } | {
57
+ kind: 'click_modal_button';
58
+ index: number;
59
+ } | {
60
+ kind: 'attach_image';
61
+ blob: string;
62
+ mime: string;
63
+ } | {
64
+ kind: 'resize';
65
+ cols: number;
66
+ rows: number;
67
+ } | {
68
+ kind: 'cancel';
69
+ } | {
70
+ kind: 'shutdown';
71
+ };
72
+ export interface DriverHistoryEntry {
73
+ stateId: string;
74
+ label: string;
75
+ at: number;
76
+ durationMs: number;
77
+ reason: string;
78
+ matchedStateId?: string;
79
+ matchedRules?: string[];
80
+ debounceKind?: string;
81
+ idleHoldMs?: number;
82
+ busyHoldMs?: number;
83
+ via?: string;
84
+ }
85
+ /**
86
+ * A frozen snapshot of the FULL FSM evaluation captured at the instant a
87
+ * transition fired — the rich `transitions[]` table (per-transition eligible /
88
+ * hold countdown / per-condition CondResult + remainingMs) that `getFsmDebug()`
89
+ * otherwise only computes live for the current instant. Kept in a separate ring
90
+ * buffer from `stateHistory` (which stays intentionally lightweight) so the
91
+ * "why did this rule fire just before the transition" question is answerable
92
+ * after the fact. before-only: this is the evaluation that PRODUCED the
93
+ * transition, not the post-transition state.
94
+ */
95
+ export interface FsmSnapshotEntry {
96
+ /** State we transitioned out of. */
97
+ stateFrom: string;
98
+ /** State we transitioned into (the fired transition's destination). */
99
+ stateTo: string;
100
+ /** Wall-clock time the transition committed (ms). */
101
+ at: number;
102
+ /** The fired transition's destination state id (== stateTo; kept explicit
103
+ * to mirror the rule that fired). */
104
+ firedTo: string;
105
+ /** Human label of the fired transition (e.g. "approval→busy"). */
106
+ firedLabel: string;
107
+ /** Why-it-fired summary, same shape produced for stateHistory.matchedRules. */
108
+ reason: string[];
109
+ /** Every outgoing transition from `stateFrom` as evaluated at `at`, each
110
+ * with its eligible / hold / per-condition CondResult + remainingMs. This
111
+ * is the full pre-transition evaluation table — the whole point of the
112
+ * snapshot. */
113
+ transitions: TransitionEval[];
114
+ }
115
+ export interface ISpecDriver {
116
+ subscribe(listener: (ev: DashboardEvent) => void): () => void;
117
+ start(): void;
118
+ dispatch(cmd: DashboardCommand): void;
119
+ snapshot(): string;
120
+ getCursorPosition(): {
121
+ row: number;
122
+ col: number;
123
+ };
124
+ getScreen(): string;
125
+ getSpecPath(): string;
126
+ shutdown(): void;
127
+ getStateHistory(): ReadonlyArray<DriverHistoryEntry>;
128
+ getSections(): Array<{
129
+ id: string;
130
+ text: string;
131
+ }> | null;
132
+ getLastBusyAt(): number;
133
+ hasIdleHoldPending(): boolean;
134
+ getCompletionIdleDebounceState(): {
135
+ active: boolean;
136
+ ageMs: number;
137
+ holdMs: number;
138
+ forceAfterMs: number;
139
+ } | null;
140
+ getFsmDebug?(): unknown;
141
+ getFsmSnapshotHistory?(): ReadonlyArray<FsmSnapshotEntry>;
142
+ }
143
+ export interface SpecDriverOpts {
144
+ specPath: string;
145
+ workingDir: string;
146
+ extraEnv?: Record<string, string>;
147
+ cols?: number;
148
+ rows?: number;
149
+ hotReload?: boolean;
150
+ emitTrace?: boolean;
151
+ transportFactory?: PtyTransportFactory;
152
+ extraCliArgs?: string[];
153
+ }
154
+ export declare function resolveSubmitDelayMs(specBeforeSubmit: number | undefined, text: string): number;
155
+ export declare function guessExt(mime: string): string;
156
+ type HistoryEntry = DriverHistoryEntry;
157
+ export declare class FsmDriver implements ISpecDriver {
158
+ private readonly opts;
159
+ private spec;
160
+ private adapter;
161
+ private listeners;
162
+ private currentStateId;
163
+ private stateEnteredAt;
164
+ private startedAtMs;
165
+ private prevScreenLines;
166
+ /** Per cursor_above region (key: cursor_above, -1 = whole screen) → last
167
+ * time that region's content changed. Drives stable_ms conditions. */
168
+ private regionLastChangedAt;
169
+ /** Timer that re-runs evaluate() when a time-condition would flip true
170
+ * with no PTY frame to trigger it. */
171
+ private wakeTimer;
172
+ /** Timer driving the focus-gated stall watchdog (refocus_when_stalled_ms).
173
+ * Re-arms itself while the machine is generating so a re-prime can fire
174
+ * even when the PTY has gone completely quiet. */
175
+ private stallTimer;
176
+ /** Wall-clock time the last stall re-prime was injected. The cooldown gate:
177
+ * after a re-prime we don't re-inject until the screen changes (which
178
+ * resets the stall reference) or another full stall window lapses. */
179
+ private lastRefocusAt;
180
+ private currentEval;
181
+ private stateHistory;
182
+ private prevStateAt;
183
+ private readySeenOnce;
184
+ private pendingSends;
185
+ private pickerInProgress;
186
+ private delegateTimers;
187
+ private specWatcher;
188
+ /** Last full FSM evaluation, kept for the debugger. */
189
+ private lastFsmEval;
190
+ /** Ring buffer (max 20) of the full FSM evaluation captured at each
191
+ * transition — the rich pre-transition table that lastFsmEval only keeps
192
+ * for the single most recent evaluation. Separate from stateHistory. */
193
+ private fsmSnapshotHistory;
194
+ constructor(opts: SpecDriverOpts);
195
+ subscribe(listener: (ev: DashboardEvent) => void): () => void;
196
+ start(): void;
197
+ private scheduleSpawnPrime;
198
+ /** Write the declared `send_on_spawn` sequences to the PTY once. Used both
199
+ * at spawn (scheduleSpawnPrime) and, for focus-gated TUIs, by the stall
200
+ * watchdog to re-inject the focus-in wake mid-turn. No-op when the spec
201
+ * declares no prime, so non-focus-gated CLIs are never poked. */
202
+ private sendSpawnPrime;
203
+ dispatch(cmd: DashboardCommand): void;
204
+ snapshot(): string;
205
+ getCursorPosition(): {
206
+ row: number;
207
+ col: number;
208
+ };
209
+ getScreen(): string;
210
+ /** Scrollback-inclusive screen as line array — used only for modal/button
211
+ * content extraction so a tall prompt's off-screen anchors stay matchable.
212
+ * Falls back to the viewport snapshot if scrollback read is unavailable. */
213
+ private scrollbackLines;
214
+ getSpecPath(): string;
215
+ shutdown(): void;
216
+ getFsmDebug(): {
217
+ currentState: string;
218
+ label: string;
219
+ stateAgeMs: number;
220
+ status: string;
221
+ cursor: {
222
+ row: number;
223
+ col: number;
224
+ };
225
+ transitions: TransitionEval[];
226
+ };
227
+ getStateHistory(): ReadonlyArray<HistoryEntry>;
228
+ getFsmSnapshotHistory(): ReadonlyArray<FsmSnapshotEntry>;
229
+ getSections(): Array<{
230
+ id: string;
231
+ text: string;
232
+ }> | null;
233
+ /** v3-compat shims so the cli-adapter's existing debug snapshot keeps
234
+ * working without branching on driver type. */
235
+ getLastBusyAt(): number;
236
+ hasIdleHoldPending(): boolean;
237
+ getCompletionIdleDebounceState(): {
238
+ active: boolean;
239
+ ageMs: number;
240
+ holdMs: number;
241
+ forceAfterMs: number;
242
+ } | null;
243
+ private loadSpecOrThrow;
244
+ private buildAdapterOpts;
245
+ private armSpecWatcher;
246
+ private emitInitialState;
247
+ private buildClock;
248
+ private evalFsmNow;
249
+ private reevaluate;
250
+ private commitTransition;
251
+ /** Snapshot the full FSM evaluation that produced a transition into the
252
+ * separate fsmSnapshotHistory ring buffer (max 20). The transitions[]
253
+ * table is captured by reference — it is freshly built per evaluation in
254
+ * evaluateFsm and never mutated after, so no clone is needed. */
255
+ private pushFsmSnapshot;
256
+ /** Re-derive the visible modal + controls for the current state and emit a
257
+ * state_changed if anything differs from the last emit. */
258
+ private emitStateChanged;
259
+ private deriveModal;
260
+ private deriveTitle;
261
+ private deriveControls;
262
+ /** Track which cursor_above regions changed since the previous frame so
263
+ * stable_ms conditions can measure quiet time. We record every region
264
+ * size referenced by a stable_ms condition in the spec, plus the whole
265
+ * screen (-1). */
266
+ private trackRegionChanges;
267
+ /** All cursor_above region sizes referenced by stable_ms conditions in the
268
+ * current state's outgoing transitions, plus whole-screen. Cached lazily
269
+ * per spec load would be nicer but the set is tiny. */
270
+ private stableRegionSizes;
271
+ /** Schedule a re-evaluation for the soonest pending time-condition on any
272
+ * outgoing transition (elapsed_ms / stable_ms / min_hold_ms). Without
273
+ * this, a state whose only exit is time-based would never leave once the
274
+ * PTY goes quiet. */
275
+ private scheduleWakeForState;
276
+ /** True when this spec opts into stall recovery (declares a positive
277
+ * refocus window AND a wake sequence to re-inject). */
278
+ private stallRecoveryEnabled;
279
+ /** Wall-clock time the screen last changed in the current state, falling
280
+ * back to state entry when it has not changed since (i.e. fully stalled
281
+ * from the start of the state). */
282
+ private lastScreenChangeAt;
283
+ /** Arm a timer to re-inject the focus-in prime if the screen stays frozen
284
+ * through a `generating` state. Only active for opted-in focus-gated specs;
285
+ * a no-op (and cleared) for every other CLI and every non-generating state.
286
+ * Re-arms itself so it keeps watching while the PTY is quiet. */
287
+ private scheduleStallWatchdog;
288
+ /** Fire when the stall window elapses: if the screen is still frozen and we
289
+ * are still generating, re-inject the focus-in wake once, then re-arm. */
290
+ private onStallTick;
291
+ private maybeMarkReady;
292
+ private fireNotifications;
293
+ private armOrCancelDelegateTimers;
294
+ private fireDelegate;
295
+ private handleSendMessage;
296
+ private actuallySendMessage;
297
+ private handleClickControl;
298
+ private handleClickModalButton;
299
+ private handleAttachImage;
300
+ private tryAdvancePicker;
301
+ private handleExit;
302
+ private pushHistory;
303
+ private specTag;
304
+ private emit;
305
+ }
306
+ export {};
@@ -0,0 +1,72 @@
1
+ import type { SectionDef } from './types.js';
2
+ import { type ResolvedSection, type TraceEntry } from './evaluator.js';
3
+ import { type CliSpecV4, type FsmCondition } from './fsm-types.js';
4
+ export interface FsmClock {
5
+ /** Wall-clock now (ms). Passed in so the evaluator stays pure. */
6
+ now: number;
7
+ /** When the current state was entered (ms). */
8
+ stateEnteredAt: number;
9
+ /** Last-changed timestamp per cursor_above region. Key = cursor_above
10
+ * value (0 / undefined → whole-screen, keyed as -1). Missing key means
11
+ * "never observed changing" → treated as stable since stateEnteredAt. */
12
+ regionLastChangedAt: Map<number, number>;
13
+ }
14
+ /** Per-condition evaluation detail — the debugging payload. */
15
+ export interface CondResult {
16
+ kind: 'regex' | 'changed' | 'elapsed' | 'stable' | 'all' | 'any' | 'not';
17
+ result: boolean;
18
+ detail: string;
19
+ /** Remaining ms until a time-based condition would flip to true. 0 if
20
+ * already true or not applicable. Lets the UI show a countdown. */
21
+ remainingMs?: number;
22
+ children?: CondResult[];
23
+ }
24
+ /** One evaluated transition with its full reasoning. */
25
+ export interface TransitionEval {
26
+ to: string;
27
+ label: string;
28
+ /** Did the `from` clause include the current state? (Always true for the
29
+ * transitions we return — kept for completeness.) */
30
+ eligible: boolean;
31
+ /** min_hold_ms guard satisfied? */
32
+ holdSatisfied: boolean;
33
+ holdRemainingMs: number;
34
+ /** Guard condition result (true if no `when`). */
35
+ condResult: boolean;
36
+ cond?: CondResult;
37
+ /** Overall: would this transition fire? */
38
+ fires: boolean;
39
+ priority: number;
40
+ }
41
+ export interface FsmEvaluation {
42
+ /** Sections resolved from the screen (shared with v3 shape). */
43
+ sections: ResolvedSection[];
44
+ /** Every outgoing transition from the current state, priority-ordered,
45
+ * each annotated with why it fired or didn't. */
46
+ transitions: TransitionEval[];
47
+ /** The transition that fires (first in priority order with fires===true),
48
+ * or null to stay in the current state. */
49
+ fired: TransitionEval | null;
50
+ /** v3-compatible trace lines for the legacy inspector. */
51
+ trace: TraceEntry[];
52
+ }
53
+ /**
54
+ * Evaluate the FSM: given the current state id and screen, return every
55
+ * outgoing transition annotated with why it fires/doesn't, plus the one that
56
+ * fires (if any).
57
+ */
58
+ export declare function evaluateFsm(spec: CliSpecV4, currentStateId: string, screenText: string, cursor: {
59
+ row: number;
60
+ col: number;
61
+ } | undefined, prevLines: string[] | undefined, clock: FsmClock): FsmEvaluation;
62
+ /**
63
+ * Evaluate a single condition against a screen + section map — for the spec
64
+ * editor's live preview ("does this regex match the current screen right
65
+ * now?"). Time leaves (elapsed_ms/stable_ms) are evaluated against a synthetic
66
+ * clock where the state was just entered, so they report their countdown
67
+ * rather than firing; the preview is about screen-content match, not timing.
68
+ */
69
+ export declare function evaluateConditionPreview(cond: FsmCondition, sections: Record<string, SectionDef> | undefined, screenText: string, cursor?: {
70
+ row: number;
71
+ col: number;
72
+ }): CondResult;