@adhdev/daemon-core 0.9.82-rc.31 → 0.9.82-rc.311

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 (294) 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 +23 -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 +106 -63
  11. package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
  12. package/dist/cli-adapters/provider-cli-shared.d.ts +38 -0
  13. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  14. package/dist/cli-adapters/resolve-executable.d.ts +14 -0
  15. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
  16. package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
  17. package/dist/cli-adapters/terminal-screen.d.ts +4 -11
  18. package/dist/commands/cli-manager.d.ts +2 -1
  19. package/dist/commands/handler.d.ts +110 -0
  20. package/dist/commands/mesh-coordinator.d.ts +85 -1
  21. package/dist/commands/router.d.ts +214 -1
  22. package/dist/config/chat-history.d.ts +9 -0
  23. package/dist/config/config.d.ts +5 -0
  24. package/dist/config/mesh-config.d.ts +72 -1
  25. package/dist/git/git-commands.d.ts +9 -1
  26. package/dist/git/git-diff.d.ts +6 -0
  27. package/dist/git/git-executor.d.ts +11 -0
  28. package/dist/git/git-status.d.ts +9 -0
  29. package/dist/git/git-types.d.ts +2 -50
  30. package/dist/index.d.ts +51 -12
  31. package/dist/index.js +34705 -11938
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +38412 -15757
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/installer.d.ts +1 -4
  36. package/dist/ipc/local-ipc-server.d.ts +91 -0
  37. package/dist/launch.d.ts +1 -1
  38. package/dist/logging/async-batch-writer.d.ts +10 -0
  39. package/dist/mesh/contracts.d.ts +164 -0
  40. package/dist/mesh/coordinator-prompt.d.ts +36 -0
  41. package/dist/mesh/coordinator-registry.d.ts +59 -0
  42. package/dist/mesh/mesh-active-work.d.ts +108 -0
  43. package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
  44. package/dist/mesh/mesh-events-coordinator.d.ts +169 -0
  45. package/dist/mesh/mesh-events-pending.d.ts +45 -0
  46. package/dist/mesh/mesh-events-stale.d.ts +40 -0
  47. package/dist/mesh/mesh-events-utils.d.ts +47 -0
  48. package/dist/mesh/mesh-events.d.ts +6 -49
  49. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  50. package/dist/mesh/mesh-host-ownership.d.ts +9 -0
  51. package/dist/mesh/mesh-init.d.ts +86 -0
  52. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
  53. package/dist/mesh/mesh-ledger.d.ts +77 -1
  54. package/dist/mesh/mesh-missions.d.ts +116 -0
  55. package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
  56. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  57. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  58. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  59. package/dist/mesh/mesh-routing.d.ts +70 -0
  60. package/dist/mesh/mesh-runtime-store.d.ts +395 -0
  61. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  62. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +30 -0
  63. package/dist/mesh/mesh-work-queue.d.ts +204 -5
  64. package/dist/mesh/preview-freshness.d.ts +18 -0
  65. package/dist/mesh/refine-config.d.ts +215 -0
  66. package/dist/mesh/worktree-bootstrap-config.d.ts +135 -0
  67. package/dist/providers/acp-provider-instance.d.ts +2 -0
  68. package/dist/providers/approval-utils.d.ts +13 -0
  69. package/dist/providers/cli-provider-instance.d.ts +61 -3
  70. package/dist/providers/contracts.d.ts +130 -6
  71. package/dist/providers/external-sources.d.ts +71 -0
  72. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
  73. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  74. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  75. package/dist/providers/native-history/dispatcher.d.ts +27 -0
  76. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  77. package/dist/providers/native-history/index.d.ts +13 -0
  78. package/dist/providers/provider-instance-manager.d.ts +13 -0
  79. package/dist/providers/provider-instance.d.ts +13 -1
  80. package/dist/providers/provider-loader.d.ts +26 -4
  81. package/dist/providers/provider-trust.d.ts +31 -0
  82. package/dist/providers/read-chat-contract.d.ts +29 -0
  83. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  84. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +85 -0
  85. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  86. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  87. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  88. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  89. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  90. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  91. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  92. package/dist/providers/sdk/v1/index.d.ts +30 -0
  93. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  94. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  95. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  96. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  97. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  98. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  99. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  100. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  101. package/dist/providers/spec/adapter.d.ts +59 -0
  102. package/dist/providers/spec/cli-adapter.d.ts +217 -0
  103. package/dist/providers/spec/evaluator.d.ts +23 -0
  104. package/dist/providers/spec/fsm-driver.d.ts +278 -0
  105. package/dist/providers/spec/fsm-evaluator.d.ts +72 -0
  106. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  107. package/dist/providers/spec/fsm-types.d.ts +128 -0
  108. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  109. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  110. package/dist/providers/spec/route.d.ts +4 -0
  111. package/dist/providers/spec/types.d.ts +180 -0
  112. package/dist/providers/transcript-v2.d.ts +176 -0
  113. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  114. package/dist/repo-mesh-types.d.ts +291 -13
  115. package/dist/sessions/registry.d.ts +6 -0
  116. package/dist/shared-types-extra.d.ts +2 -4
  117. package/dist/shared-types.d.ts +42 -1
  118. package/dist/status/normalize.d.ts +1 -1
  119. package/dist/status/normalize.js +1 -0
  120. package/dist/status/normalize.js.map +1 -1
  121. package/dist/status/normalize.mjs +1 -0
  122. package/dist/status/normalize.mjs.map +1 -1
  123. package/dist/status/reporter.d.ts +2 -0
  124. package/dist/status/snapshot.d.ts +1 -0
  125. package/dist/types.d.ts +5 -0
  126. package/package.json +7 -3
  127. package/src/agent-stream/poller.ts +2 -3
  128. package/src/boot/daemon-lifecycle.ts +55 -12
  129. package/src/boot/process-hardening.ts +89 -0
  130. package/src/build-info.ts +73 -0
  131. package/src/chat/source-machine.ts +534 -0
  132. package/src/chat/source-resolver.ts +0 -0
  133. package/src/chat/subscription-updates.ts +20 -1
  134. package/src/cli-adapter-types.d.ts +1 -0
  135. package/src/cli-adapter-types.ts +22 -2
  136. package/src/cli-adapters/cli-script-runner.ts +421 -0
  137. package/src/cli-adapters/cli-state-engine.ts +1215 -0
  138. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  139. package/src/cli-adapters/provider-cli-adapter.ts +674 -1139
  140. package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
  141. package/src/cli-adapters/provider-cli-parse.ts +13 -0
  142. package/src/cli-adapters/provider-cli-runtime.ts +3 -1
  143. package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
  144. package/src/cli-adapters/provider-cli-shared.ts +68 -11
  145. package/src/cli-adapters/pty-transport.ts +2 -1
  146. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  147. package/src/cli-adapters/resolve-executable.ts +45 -0
  148. package/src/cli-adapters/session-host-transport.ts +2 -1
  149. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -29
  150. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  151. package/src/cli-adapters/terminal-screen.ts +16 -81
  152. package/src/commands/chat-commands.ts +1822 -61
  153. package/src/commands/cli-manager.ts +286 -14
  154. package/src/commands/handler.ts +809 -2
  155. package/src/commands/mesh-coordinator.ts +332 -122
  156. package/src/commands/router.ts +6041 -589
  157. package/src/commands/stream-commands.ts +8 -0
  158. package/src/commands/upgrade-helper.ts +29 -0
  159. package/src/config/chat-history.ts +483 -24
  160. package/src/config/config.ts +12 -0
  161. package/src/config/mesh-config.ts +320 -4
  162. package/src/config/recent-activity.ts +8 -2
  163. package/src/daemon/dev-auto-implement.ts +3 -2
  164. package/src/daemon/dev-cli-debug.ts +10 -1
  165. package/src/detection/ide-detector.ts +26 -16
  166. package/src/git/git-commands.ts +42 -12
  167. package/src/git/git-diff.ts +53 -0
  168. package/src/git/git-executor.ts +12 -0
  169. package/src/git/git-status.ts +302 -18
  170. package/src/git/git-types.ts +14 -62
  171. package/src/git/git-worktree.ts +8 -1
  172. package/src/index.ts +142 -11
  173. package/src/installer.d.ts +1 -1
  174. package/src/installer.ts +8 -6
  175. package/src/ipc/local-ipc-server.ts +278 -0
  176. package/src/launch.d.ts +1 -1
  177. package/src/launch.ts +37 -28
  178. package/src/logging/async-batch-writer.ts +55 -0
  179. package/src/logging/logger.ts +2 -1
  180. package/src/mesh/contracts.ts +329 -0
  181. package/src/mesh/coordinator-prompt.ts +234 -31
  182. package/src/mesh/coordinator-registry.ts +121 -0
  183. package/src/mesh/mesh-active-work.ts +469 -0
  184. package/src/mesh/mesh-delivery-policy.ts +315 -0
  185. package/src/mesh/mesh-events-coordinator.ts +1942 -0
  186. package/src/mesh/mesh-events-pending.ts +508 -0
  187. package/src/mesh/mesh-events-stale.ts +290 -0
  188. package/src/mesh/mesh-events-utils.ts +254 -0
  189. package/src/mesh/mesh-events.ts +30 -1035
  190. package/src/mesh/mesh-fast-forward.ts +839 -0
  191. package/src/mesh/mesh-host-ownership.ts +73 -0
  192. package/src/mesh/mesh-init.ts +260 -0
  193. package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
  194. package/src/mesh/mesh-ledger.ts +589 -102
  195. package/src/mesh/mesh-missions.ts +248 -0
  196. package/src/mesh/mesh-reconcile-loop.ts +466 -0
  197. package/src/mesh/mesh-refine-batch.ts +197 -0
  198. package/src/mesh/mesh-refine-status.ts +231 -0
  199. package/src/mesh/mesh-review-inbox.ts +307 -0
  200. package/src/mesh/mesh-routing.ts +291 -0
  201. package/src/mesh/mesh-runtime-store.ts +1565 -0
  202. package/src/mesh/mesh-task-stats.ts +154 -0
  203. package/src/mesh/mesh-unresolved-forward-outbox.ts +185 -0
  204. package/src/mesh/mesh-work-queue.ts +703 -140
  205. package/src/mesh/preview-freshness.ts +118 -0
  206. package/src/mesh/refine-config.ts +403 -0
  207. package/src/mesh/worktree-bootstrap-config.ts +326 -0
  208. package/src/providers/acp-provider-instance.ts +15 -1
  209. package/src/providers/approval-utils.d.ts +4 -0
  210. package/src/providers/approval-utils.ts +47 -5
  211. package/src/providers/chat-message-normalization.ts +4 -11
  212. package/src/providers/cli-provider-instance.ts +953 -87
  213. package/src/providers/contracts.d.ts +55 -0
  214. package/src/providers/contracts.ts +141 -6
  215. package/src/providers/extension-provider-instance.ts +5 -1
  216. package/src/providers/external-sources.ts +218 -0
  217. package/src/providers/ide-provider-instance.ts +25 -6
  218. package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
  219. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  220. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  221. package/src/providers/native-history/dispatcher.ts +340 -0
  222. package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
  223. package/src/providers/native-history/index.ts +30 -0
  224. package/src/providers/provider-instance-manager.ts +30 -0
  225. package/src/providers/provider-instance.ts +10 -1
  226. package/src/providers/provider-loader.ts +584 -50
  227. package/src/providers/provider-schema.ts +87 -14
  228. package/src/providers/provider-trust.ts +114 -0
  229. package/src/providers/read-chat-contract.ts +76 -16
  230. package/src/providers/sdk/README.md +49 -0
  231. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  232. package/src/providers/sdk/v1/builders/cli/detect-status.ts +262 -0
  233. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  234. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
  235. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  236. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  237. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  238. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  239. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  240. package/src/providers/sdk/v1/index.ts +152 -0
  241. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  242. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  243. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  244. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +504 -0
  245. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  246. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  247. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  248. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  249. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  250. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  251. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  252. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  253. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  254. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  255. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  256. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  257. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  258. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  259. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  260. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  261. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  262. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  263. package/src/providers/sdk/v1/validators/index.ts +19 -0
  264. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  265. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  266. package/src/providers/spec/adapter.ts +155 -0
  267. package/src/providers/spec/cli-adapter.ts +980 -0
  268. package/src/providers/spec/evaluator.ts +345 -0
  269. package/src/providers/spec/fsm-driver.ts +888 -0
  270. package/src/providers/spec/fsm-evaluator.ts +255 -0
  271. package/src/providers/spec/fsm-loader.ts +112 -0
  272. package/src/providers/spec/fsm-types.ts +222 -0
  273. package/src/providers/spec/native-history-executor.ts +1035 -0
  274. package/src/providers/spec/pre-launch-trust.ts +104 -0
  275. package/src/providers/spec/route.ts +51 -0
  276. package/src/providers/spec/types.ts +226 -0
  277. package/src/providers/transcript-v2.ts +567 -0
  278. package/src/providers/types/interactive-prompt.ts +536 -0
  279. package/src/providers/version-archive.ts +38 -20
  280. package/src/repo-mesh-types.ts +376 -13
  281. package/src/sessions/registry.ts +6 -0
  282. package/src/shared-types-extra.ts +2 -4
  283. package/src/shared-types.ts +45 -1
  284. package/src/status/builders.ts +26 -6
  285. package/src/status/normalize.ts +2 -0
  286. package/src/status/reporter.ts +15 -0
  287. package/src/status/snapshot.ts +84 -25
  288. package/src/system/host-memory.ts +29 -12
  289. package/src/types.ts +5 -0
  290. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  291. package/dist/mesh/mesh-sync.d.ts +0 -53
  292. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  293. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  294. package/src/mesh/mesh-sync.ts +0 -111
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Section + condition evaluator — pure functions shared by the v4 FSM engine.
3
+ *
4
+ * Provides: section resolution, condition evaluation (regex/changed/all/any),
5
+ * title/button extraction. The v4 FSM driver and evaluator import these
6
+ * directly; there is no v3 SpecDriver anymore.
7
+ */
8
+ 'use strict';
9
+
10
+ import type {
11
+ SectionDef, AnchorContext, Condition, RegexCondition,
12
+ ChangedCondition, AllCondition, AnyCondition,
13
+ ExtractTitle, ExtractButtons,
14
+ } from './types.js';
15
+
16
+ export interface ResolvedSection {
17
+ id: string;
18
+ fromLine: number; // inclusive
19
+ toLine: number; // exclusive
20
+ text: string;
21
+ }
22
+
23
+ export interface TraceEntry {
24
+ kind: 'section' | 'state_match' | 'state_skip' | 'modal' | 'control' | 'notification' | 'delegate';
25
+ text: string;
26
+ }
27
+
28
+ // ────────────────────────────────────────────────────────────────────────────
29
+ // Layout — sections{} object
30
+ // ────────────────────────────────────────────────────────────────────────────
31
+
32
+ function resolveSize(size: number | string | undefined, total: number): number {
33
+ if (size === undefined) return 0;
34
+ if (typeof size === 'number') return Math.max(0, Math.min(total, size));
35
+ const m = /^(\d+(?:\.\d+)?)%$/.exec(size);
36
+ if (!m) return 0;
37
+ const pct = Number(m[1]);
38
+ return Math.max(0, Math.min(total, Math.round((total * pct) / 100)));
39
+ }
40
+
41
+ export function resolveSections(
42
+ sectionsObj: Record<string, SectionDef>,
43
+ lines: string[],
44
+ ): ResolvedSection[] {
45
+ const total = lines.length;
46
+ const anchored = new Map<string, { fromLine: number; toLine: number }>();
47
+ const sectionEntries = Object.entries(sectionsObj);
48
+
49
+ for (const [id, sec] of sectionEntries) {
50
+ let from = 0;
51
+ let to = total;
52
+
53
+ if (sec.anchor !== undefined) {
54
+ try {
55
+ // Normalize anchor + context into parallel candidate lists. A
56
+ // scalar anchor becomes a single-entry array; a single context
57
+ // object applies to every entry; an array context is positional.
58
+ // Candidates are tried IN ORDER as independent passes: the first
59
+ // pattern that finds any line wins. This keeps a scalar anchor's
60
+ // behavior identical, and lets an array express a preferred shape
61
+ // (e.g. a box divider) with later entries as fallbacks (e.g. a
62
+ // divider-less modal anchored on its question line) — the
63
+ // fallback only takes over when the preferred pattern is absent.
64
+ const anchorPatterns = Array.isArray(sec.anchor) ? sec.anchor : [sec.anchor];
65
+ const sharedCtx: AnchorContext | null = Array.isArray(sec.anchor_context)
66
+ ? null
67
+ : (sec.anchor_context ?? null);
68
+ const ctxList: (AnchorContext | null)[] = Array.isArray(sec.anchor_context)
69
+ ? sec.anchor_context
70
+ : anchorPatterns.map(() => sharedCtx);
71
+ const candidates = anchorPatterns.map((pattern, k) => {
72
+ const ctx = ctxList[k] ?? null;
73
+ return {
74
+ re: new RegExp(pattern, sec.anchor_flags ?? ''),
75
+ prevRe: ctx?.prev !== undefined
76
+ ? new RegExp(ctx.prev, ctx.prev_flags ?? '') : null,
77
+ nextRe: ctx?.next !== undefined
78
+ ? new RegExp(ctx.next, ctx.next_flags ?? '') : null,
79
+ };
80
+ });
81
+ const matchesCandidate = (c: typeof candidates[number], i: number) =>
82
+ c.re.test(lines[i])
83
+ && (c.prevRe === null || (i > 0 && c.prevRe.test(lines[i - 1])))
84
+ && (c.nextRe === null || (i < total - 1 && c.nextRe.test(lines[i + 1])));
85
+ let idx = -1;
86
+ for (const c of candidates) {
87
+ if (sec.anchor_last) {
88
+ for (let i = total - 1; i >= 0; i--) { if (matchesCandidate(c, i)) { idx = i; break; } }
89
+ } else {
90
+ for (let i = 0; i < total; i++) { if (matchesCandidate(c, i)) { idx = i; break; } }
91
+ }
92
+ if (idx !== -1) break;
93
+ }
94
+ if (idx !== -1) {
95
+ from = idx;
96
+ to = total;
97
+ if (sec.until_regex !== undefined) {
98
+ try {
99
+ const ure = new RegExp(sec.until_regex, sec.until_regex_flags ?? '');
100
+ const end = lines.findIndex((l, i) => i > idx && ure.test(l));
101
+ if (end !== -1) to = end;
102
+ } catch { /* bad until_regex */ }
103
+ } else if (sec.lines !== undefined) {
104
+ to = Math.min(total, from + sec.lines);
105
+ }
106
+ }
107
+ } catch { /* bad anchor regex */ }
108
+ } else if (sec.from_top !== undefined) {
109
+ from = resolveSize(sec.from_top, total);
110
+ to = total;
111
+ } else if (sec.from_bottom !== undefined) {
112
+ const sz = resolveSize(sec.from_bottom, total);
113
+ from = total - sz;
114
+ to = total;
115
+ }
116
+
117
+ anchored.set(id, { fromLine: from, toLine: to });
118
+ }
119
+
120
+ // Second pass: apply `until` references or `until` regex strings.
121
+ const resolved: ResolvedSection[] = [];
122
+ for (const [id, sec] of sectionEntries) {
123
+ let { fromLine, toLine } = anchored.get(id)!;
124
+
125
+ if (sec.until !== undefined) {
126
+ if (sec.until.startsWith('^')) {
127
+ try {
128
+ const ure = new RegExp(sec.until);
129
+ const end = lines.findIndex((l, i) => i > fromLine && ure.test(l));
130
+ if (end !== -1) toLine = end;
131
+ } catch { /* bad until regex */ }
132
+ } else {
133
+ const target = anchored.get(sec.until);
134
+ if (target) toLine = target.fromLine;
135
+ }
136
+ }
137
+
138
+ if (toLine < fromLine) toLine = fromLine;
139
+ const text = lines.slice(fromLine, toLine).join('\n');
140
+ resolved.push({ id, fromLine, toLine, text });
141
+ }
142
+
143
+ return resolved;
144
+ }
145
+
146
+ export function sectionText(sections: ResolvedSection[], sectionId: string | undefined, fullScreen: string): string {
147
+ if (!sectionId) return fullScreen;
148
+ const found = sections.find(s => s.id === sectionId);
149
+ return found ? found.text : '';
150
+ }
151
+
152
+ // ────────────────────────────────────────────────────────────────────────────
153
+ // Condition evaluation
154
+ // ────────────────────────────────────────────────────────────────────────────
155
+
156
+ function isRegexCondition(c: Condition): c is RegexCondition {
157
+ return 'matches' in c;
158
+ }
159
+
160
+ function isChangedCondition(c: Condition): c is ChangedCondition {
161
+ return 'cursor_above' in c && 'changed' in c;
162
+ }
163
+
164
+ function isAllCondition(c: Condition): c is AllCondition {
165
+ return 'all' in c;
166
+ }
167
+
168
+ function isAnyCondition(c: Condition): c is AnyCondition {
169
+ return 'any' in c;
170
+ }
171
+
172
+ export function evaluateCondition(
173
+ cond: Condition,
174
+ sections: ResolvedSection[],
175
+ fullScreen: string,
176
+ cursor: { row: number; col: number } | undefined,
177
+ prevLines: string[] | undefined,
178
+ trace: TraceEntry[],
179
+ stateId: string,
180
+ ): boolean {
181
+ if (isAllCondition(cond)) {
182
+ for (const child of cond.all) {
183
+ if (!evaluateCondition(child, sections, fullScreen, cursor, prevLines, trace, stateId)) {
184
+ return false;
185
+ }
186
+ }
187
+ return true;
188
+ }
189
+
190
+ if (isAnyCondition(cond)) {
191
+ for (const child of cond.any) {
192
+ if (evaluateCondition(child, sections, fullScreen, cursor, prevLines, trace, stateId)) {
193
+ return true;
194
+ }
195
+ }
196
+ return false;
197
+ }
198
+
199
+ if (isChangedCondition(cond)) {
200
+ if (!cursor || !prevLines || prevLines.length === 0) return false;
201
+ const curLines = fullScreen.split('\n');
202
+ const startRow = Math.max(0, cursor.row - cond.cursor_above);
203
+ const endRow = cursor.row;
204
+ const currentSlice = curLines.slice(startRow, endRow).join('\n');
205
+ const prevSlice = prevLines.slice(startRow, endRow).join('\n');
206
+ const didChange = currentSlice !== prevSlice;
207
+ const result = cond.changed ? didChange : !didChange;
208
+ const stableSuffix = cond.stable_ms != null ? ` stable_ms=${cond.stable_ms}` : '';
209
+ trace.push({
210
+ kind: result ? 'state_match' : 'state_skip',
211
+ text: `state[${stateId}] changed cond cursor_above=${cond.cursor_above} rows[${startRow},${endRow}) changed=${didChange} expected=${cond.changed}${stableSuffix} result=${result}`,
212
+ });
213
+ return result;
214
+ }
215
+
216
+ if (isRegexCondition(cond)) {
217
+ const haystack = sectionText(sections, cond.section, fullScreen);
218
+ let matched = false;
219
+ try {
220
+ const re = new RegExp(cond.matches, cond.flags ?? 'i');
221
+ matched = re.test(haystack);
222
+ } catch { matched = false; }
223
+
224
+ if (!matched) {
225
+ trace.push({ kind: 'state_skip', text: `state[${stateId}] regex cond ${cond.section ?? '*'}~/${cond.matches}/ no match` });
226
+ return false;
227
+ }
228
+
229
+ if (cursor !== undefined) {
230
+ if (cond.cursor_row_min !== undefined && cursor.row < cond.cursor_row_min) {
231
+ trace.push({ kind: 'state_skip', text: `state[${stateId}] cursor row ${cursor.row} < cursor_row_min ${cond.cursor_row_min}` });
232
+ return false;
233
+ }
234
+ if (cond.cursor_row_max !== undefined && cursor.row > cond.cursor_row_max) {
235
+ trace.push({ kind: 'state_skip', text: `state[${stateId}] cursor row ${cursor.row} > cursor_row_max ${cond.cursor_row_max}` });
236
+ return false;
237
+ }
238
+ if (cond.cursor_col_min !== undefined && cursor.col < cond.cursor_col_min) {
239
+ trace.push({ kind: 'state_skip', text: `state[${stateId}] cursor col ${cursor.col} < cursor_col_min ${cond.cursor_col_min}` });
240
+ return false;
241
+ }
242
+ if (cond.cursor_col_max !== undefined && cursor.col > cond.cursor_col_max) {
243
+ trace.push({ kind: 'state_skip', text: `state[${stateId}] cursor col ${cursor.col} > cursor_col_max ${cond.cursor_col_max}` });
244
+ return false;
245
+ }
246
+ }
247
+
248
+ trace.push({ kind: 'state_match', text: `state[${stateId}] regex cond ${cond.section ?? '*'}~/${cond.matches}/ matched${cursor !== undefined ? ` cursor=(${cursor.row},${cursor.col})` : ''}` });
249
+ return true;
250
+ }
251
+
252
+ return false;
253
+ }
254
+
255
+ // ────────────────────────────────────────────────────────────────────────────
256
+ // Extraction helpers (used by FsmDriver for modal/title)
257
+ // ────────────────────────────────────────────────────────────────────────────
258
+
259
+ export function extractTitle(
260
+ rule: ExtractTitle,
261
+ sections: ResolvedSection[],
262
+ fullScreen: string,
263
+ ): string | null {
264
+ const hay = sectionText(sections, rule.section, fullScreen);
265
+ if (!hay) return null;
266
+
267
+ if (rule.first_line) {
268
+ const lines = hay.split('\n');
269
+ for (const line of lines) {
270
+ const stripped = line.trim();
271
+ if (stripped && !/^[─╌═─\s]+$/.test(stripped)) {
272
+ return stripped;
273
+ }
274
+ }
275
+ return null;
276
+ }
277
+
278
+ if (rule.regex) {
279
+ try {
280
+ const re = new RegExp(rule.regex, rule.flags ?? 'i');
281
+ const m = re.exec(hay);
282
+ if (m) return (m[1] ?? m[0]).trim();
283
+ } catch { /* bad regex */ }
284
+ }
285
+
286
+ return null;
287
+ }
288
+
289
+ function compilePattern(ref: { pattern: string; flags?: string }): RegExp {
290
+ const flags = ref.flags ?? 'gm';
291
+ return new RegExp(ref.pattern, flags.includes('g') ? flags : flags + 'g');
292
+ }
293
+
294
+ function compileLinePattern(ref: { pattern: string; flags?: string }): RegExp {
295
+ const flags = (ref.flags ?? 'm').replace(/g/g, '');
296
+ return new RegExp(ref.pattern, flags);
297
+ }
298
+
299
+ export function extractButtonsFromRule(
300
+ rule: ExtractButtons,
301
+ hay: string,
302
+ ): { index: number; label: string; key: string }[] {
303
+ const keyTemplate = rule.key_for_index;
304
+ const continuationLines = rule.continuation_lines ?? false;
305
+ const buttons: { index: number; label: string; key: string }[] = [];
306
+
307
+ if (continuationLines) {
308
+ const re = compileLinePattern(rule);
309
+ const lines = hay.split('\n');
310
+ for (let i = 0; i < lines.length; i += 1) {
311
+ const m = re.exec(lines[i]);
312
+ if (!m) continue;
313
+ const idx = Number(m[1]);
314
+ let label = String(m[2] ?? '').trim();
315
+ if (!Number.isFinite(idx) || idx <= 0 || !label) continue;
316
+ let j = i + 1;
317
+ while (j < lines.length) {
318
+ const next = lines[j];
319
+ if (!next.trim()) break;
320
+ if (re.test(next)) break;
321
+ if (!/^\s+/.test(next)) break;
322
+ label += ' ' + next.trim();
323
+ j += 1;
324
+ }
325
+ if (buttons.some(b => b.index === idx)) continue;
326
+ const key = keyTemplate.replace(/\{index\}/g, String(idx));
327
+ buttons.push({ index: idx, label, key });
328
+ i = j - 1;
329
+ }
330
+ } else {
331
+ const re = compilePattern(rule);
332
+ let m: RegExpExecArray | null;
333
+ while ((m = re.exec(hay)) !== null) {
334
+ const idx = Number(m[1]);
335
+ const label = String(m[2] ?? '').trim();
336
+ if (!Number.isFinite(idx) || idx <= 0 || !label) continue;
337
+ if (buttons.some(b => b.index === idx)) continue;
338
+ const key = keyTemplate.replace(/\{index\}/g, String(idx));
339
+ buttons.push({ index: idx, label, key });
340
+ }
341
+ }
342
+
343
+ buttons.sort((a, b) => a.index - b.index);
344
+ return buttons;
345
+ }