@scotthuang/agent-knock-knock 0.13.18 → 0.14.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 (270) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/CONTRIBUTING.md +212 -0
  3. package/README.md +105 -166
  4. package/connectors/deepseek-harness/LICENSE +21 -0
  5. package/connectors/deepseek-harness/README.md +406 -0
  6. package/connectors/pi/LICENSE +21 -0
  7. package/connectors/pi/README.md +446 -0
  8. package/dist/src/backend-recovery-semantic.d.ts +16 -0
  9. package/dist/src/backend-recovery-semantic.js +113 -0
  10. package/dist/src/backend-recovery-semantic.js.map +1 -0
  11. package/dist/src/backend-task-recovery.d.ts +103 -0
  12. package/dist/src/backend-task-recovery.js +142 -0
  13. package/dist/src/backend-task-recovery.js.map +1 -0
  14. package/dist/src/callback-transport.d.ts +8 -0
  15. package/dist/src/callback-transport.js +14 -0
  16. package/dist/src/callback-transport.js.map +1 -1
  17. package/dist/src/cli-core.js +18 -8
  18. package/dist/src/cli-core.js.map +1 -1
  19. package/dist/src/cli-runtime-context.d.ts +5 -0
  20. package/dist/src/cli-runtime-context.js.map +1 -1
  21. package/dist/src/codex-native-cli-adapter.d.ts +6 -0
  22. package/dist/src/codex-native-cli-adapter.js +273 -0
  23. package/dist/src/codex-native-cli-adapter.js.map +1 -0
  24. package/dist/src/codex-native-client-interactions.d.ts +6 -0
  25. package/dist/src/codex-native-client-interactions.js +124 -0
  26. package/dist/src/codex-native-client-interactions.js.map +1 -0
  27. package/dist/src/codex-native-client-rpc.d.ts +21 -0
  28. package/dist/src/codex-native-client-rpc.js +137 -0
  29. package/dist/src/codex-native-client-rpc.js.map +1 -0
  30. package/dist/src/codex-native-client.d.ts +42 -0
  31. package/dist/src/codex-native-client.js +326 -0
  32. package/dist/src/codex-native-client.js.map +1 -0
  33. package/dist/src/codex-native-identity.d.ts +6 -0
  34. package/dist/src/codex-native-identity.js +42 -0
  35. package/dist/src/codex-native-identity.js.map +1 -0
  36. package/dist/src/codex-native-monitor.d.ts +4 -0
  37. package/dist/src/codex-native-monitor.js +92 -0
  38. package/dist/src/codex-native-monitor.js.map +1 -0
  39. package/dist/src/codex-native-outbox.d.ts +16 -0
  40. package/dist/src/codex-native-outbox.js +120 -0
  41. package/dist/src/codex-native-outbox.js.map +1 -0
  42. package/dist/src/codex-native-public-projection.d.ts +545 -0
  43. package/dist/src/codex-native-public-projection.js +182 -0
  44. package/dist/src/codex-native-public-projection.js.map +1 -0
  45. package/dist/src/codex-native-record-store.d.ts +27 -0
  46. package/dist/src/codex-native-record-store.js +111 -0
  47. package/dist/src/codex-native-record-store.js.map +1 -0
  48. package/dist/src/codex-native-response-service.d.ts +69 -0
  49. package/dist/src/codex-native-response-service.js +244 -0
  50. package/dist/src/codex-native-response-service.js.map +1 -0
  51. package/dist/src/codex-native-runtime.d.ts +46 -0
  52. package/dist/src/codex-native-runtime.js +112 -0
  53. package/dist/src/codex-native-runtime.js.map +1 -0
  54. package/dist/src/codex-native-semantic.d.ts +17 -0
  55. package/dist/src/codex-native-semantic.js +175 -0
  56. package/dist/src/codex-native-semantic.js.map +1 -0
  57. package/dist/src/codex-native-snapshot.d.ts +19 -0
  58. package/dist/src/codex-native-snapshot.js +160 -0
  59. package/dist/src/codex-native-snapshot.js.map +1 -0
  60. package/dist/src/codex-native-state-store.d.ts +61 -0
  61. package/dist/src/codex-native-state-store.js +132 -0
  62. package/dist/src/codex-native-state-store.js.map +1 -0
  63. package/dist/src/codex-native-task-service.d.ts +71 -0
  64. package/dist/src/codex-native-task-service.js +502 -0
  65. package/dist/src/codex-native-task-service.js.map +1 -0
  66. package/dist/src/codex-native-types.d.ts +92 -0
  67. package/dist/src/codex-native-types.js +15 -0
  68. package/dist/src/codex-native-types.js.map +1 -0
  69. package/dist/src/conversation-list.d.ts +12 -0
  70. package/dist/src/conversation-list.js +30 -0
  71. package/dist/src/conversation-list.js.map +1 -0
  72. package/dist/src/conversation-route-dispatch.d.ts +13 -0
  73. package/dist/src/conversation-route-dispatch.js +66 -0
  74. package/dist/src/conversation-route-dispatch.js.map +1 -0
  75. package/dist/src/conversation-route-legacy.d.ts +18 -0
  76. package/dist/src/conversation-route-legacy.js +54 -0
  77. package/dist/src/conversation-route-legacy.js.map +1 -0
  78. package/dist/src/conversation-route-store.d.ts +51 -0
  79. package/dist/src/conversation-route-store.js +126 -0
  80. package/dist/src/conversation-route-store.js.map +1 -0
  81. package/dist/src/conversation-routing-cli-adapter.d.ts +12 -0
  82. package/dist/src/conversation-routing-cli-adapter.js +211 -0
  83. package/dist/src/conversation-routing-cli-adapter.js.map +1 -0
  84. package/dist/src/conversation-routing-commands.d.ts +11 -0
  85. package/dist/src/conversation-routing-commands.js +85 -0
  86. package/dist/src/conversation-routing-commands.js.map +1 -0
  87. package/dist/src/conversation-routing-home.d.ts +26 -0
  88. package/dist/src/conversation-routing-home.js +105 -0
  89. package/dist/src/conversation-routing-home.js.map +1 -0
  90. package/dist/src/conversation-routing-identity.d.ts +40 -0
  91. package/dist/src/conversation-routing-identity.js +174 -0
  92. package/dist/src/conversation-routing-identity.js.map +1 -0
  93. package/dist/src/conversation-runtime-route-store.d.ts +11 -0
  94. package/dist/src/conversation-runtime-route-store.js +118 -0
  95. package/dist/src/conversation-runtime-route-store.js.map +1 -0
  96. package/dist/src/desktop-async-interactions.d.ts +15 -0
  97. package/dist/src/desktop-async-interactions.js +88 -0
  98. package/dist/src/desktop-async-interactions.js.map +1 -0
  99. package/dist/src/desktop-async-state.d.ts +5 -0
  100. package/dist/src/desktop-async-state.js +53 -0
  101. package/dist/src/desktop-async-state.js.map +1 -0
  102. package/dist/src/desktop-cli-adapter.d.ts +7 -0
  103. package/dist/src/desktop-cli-adapter.js +322 -0
  104. package/dist/src/desktop-cli-adapter.js.map +1 -0
  105. package/dist/src/desktop-cli-controls.d.ts +9 -0
  106. package/dist/src/desktop-cli-controls.js +45 -0
  107. package/dist/src/desktop-cli-controls.js.map +1 -0
  108. package/dist/src/desktop-command-presentation.d.ts +2 -0
  109. package/dist/src/desktop-command-presentation.js +31 -0
  110. package/dist/src/desktop-command-presentation.js.map +1 -0
  111. package/dist/src/desktop-control-semantic.d.ts +8 -0
  112. package/dist/src/desktop-control-semantic.js +68 -0
  113. package/dist/src/desktop-control-semantic.js.map +1 -0
  114. package/dist/src/desktop-identity.d.ts +5 -0
  115. package/dist/src/desktop-identity.js +40 -0
  116. package/dist/src/desktop-identity.js.map +1 -0
  117. package/dist/src/desktop-interaction-projection.d.ts +57 -0
  118. package/dist/src/desktop-interaction-projection.js +196 -0
  119. package/dist/src/desktop-interaction-projection.js.map +1 -0
  120. package/dist/src/desktop-interaction-state.d.ts +3 -0
  121. package/dist/src/desktop-interaction-state.js +48 -0
  122. package/dist/src/desktop-interaction-state.js.map +1 -0
  123. package/dist/src/desktop-ipc-async-answer.d.ts +9 -0
  124. package/dist/src/desktop-ipc-async-answer.js +71 -0
  125. package/dist/src/desktop-ipc-async-answer.js.map +1 -0
  126. package/dist/src/desktop-ipc-client.d.ts +47 -0
  127. package/dist/src/desktop-ipc-client.js +400 -0
  128. package/dist/src/desktop-ipc-client.js.map +1 -0
  129. package/dist/src/desktop-ipc-native-operations.d.ts +11 -0
  130. package/dist/src/desktop-ipc-native-operations.js +126 -0
  131. package/dist/src/desktop-ipc-native-operations.js.map +1 -0
  132. package/dist/src/desktop-ipc-transport.d.ts +13 -0
  133. package/dist/src/desktop-ipc-transport.js +123 -0
  134. package/dist/src/desktop-ipc-transport.js.map +1 -0
  135. package/dist/src/desktop-list.d.ts +25 -0
  136. package/dist/src/desktop-list.js +55 -0
  137. package/dist/src/desktop-list.js.map +1 -0
  138. package/dist/src/desktop-metadata-reader.d.ts +30 -0
  139. package/dist/src/desktop-metadata-reader.js +182 -0
  140. package/dist/src/desktop-metadata-reader.js.map +1 -0
  141. package/dist/src/desktop-monitor.d.ts +4 -0
  142. package/dist/src/desktop-monitor.js +101 -0
  143. package/dist/src/desktop-monitor.js.map +1 -0
  144. package/dist/src/desktop-public-projection.d.ts +6 -0
  145. package/dist/src/desktop-public-projection.js +134 -0
  146. package/dist/src/desktop-public-projection.js.map +1 -0
  147. package/dist/src/desktop-request-interactions.d.ts +14 -0
  148. package/dist/src/desktop-request-interactions.js +144 -0
  149. package/dist/src/desktop-request-interactions.js.map +1 -0
  150. package/dist/src/desktop-response-dispatch.d.ts +14 -0
  151. package/dist/src/desktop-response-dispatch.js +19 -0
  152. package/dist/src/desktop-response-dispatch.js.map +1 -0
  153. package/dist/src/desktop-response-evidence.d.ts +4 -0
  154. package/dist/src/desktop-response-evidence.js +19 -0
  155. package/dist/src/desktop-response-evidence.js.map +1 -0
  156. package/dist/src/desktop-response-service.d.ts +11 -0
  157. package/dist/src/desktop-response-service.js +188 -0
  158. package/dist/src/desktop-response-service.js.map +1 -0
  159. package/dist/src/desktop-response-store.d.ts +35 -0
  160. package/dist/src/desktop-response-store.js +58 -0
  161. package/dist/src/desktop-response-store.js.map +1 -0
  162. package/dist/src/desktop-response-types.d.ts +20 -0
  163. package/dist/src/desktop-response-types.js +2 -0
  164. package/dist/src/desktop-response-types.js.map +1 -0
  165. package/dist/src/desktop-response-value.d.ts +6 -0
  166. package/dist/src/desktop-response-value.js +31 -0
  167. package/dist/src/desktop-response-value.js.map +1 -0
  168. package/dist/src/desktop-runtime.d.ts +153 -0
  169. package/dist/src/desktop-runtime.js +88 -0
  170. package/dist/src/desktop-runtime.js.map +1 -0
  171. package/dist/src/desktop-semantic.d.ts +21 -0
  172. package/dist/src/desktop-semantic.js +140 -0
  173. package/dist/src/desktop-semantic.js.map +1 -0
  174. package/dist/src/desktop-session-catalog.d.ts +68 -0
  175. package/dist/src/desktop-session-catalog.js +225 -0
  176. package/dist/src/desktop-session-catalog.js.map +1 -0
  177. package/dist/src/desktop-session-controls.d.ts +145 -0
  178. package/dist/src/desktop-session-controls.js +176 -0
  179. package/dist/src/desktop-session-controls.js.map +1 -0
  180. package/dist/src/desktop-sidebar-metadata.d.ts +27 -0
  181. package/dist/src/desktop-sidebar-metadata.js +83 -0
  182. package/dist/src/desktop-sidebar-metadata.js.map +1 -0
  183. package/dist/src/desktop-sidebar-projects.d.ts +10 -0
  184. package/dist/src/desktop-sidebar-projects.js +31 -0
  185. package/dist/src/desktop-sidebar-projects.js.map +1 -0
  186. package/dist/src/desktop-sidebar-selection.d.ts +28 -0
  187. package/dist/src/desktop-sidebar-selection.js +85 -0
  188. package/dist/src/desktop-sidebar-selection.js.map +1 -0
  189. package/dist/src/desktop-snapshot-details.d.ts +4 -0
  190. package/dist/src/desktop-snapshot-details.js +116 -0
  191. package/dist/src/desktop-snapshot-details.js.map +1 -0
  192. package/dist/src/desktop-snapshot.d.ts +11 -0
  193. package/dist/src/desktop-snapshot.js +276 -0
  194. package/dist/src/desktop-snapshot.js.map +1 -0
  195. package/dist/src/desktop-state-store.d.ts +72 -0
  196. package/dist/src/desktop-state-store.js +269 -0
  197. package/dist/src/desktop-state-store.js.map +1 -0
  198. package/dist/src/desktop-task-interactions.d.ts +10 -0
  199. package/dist/src/desktop-task-interactions.js +93 -0
  200. package/dist/src/desktop-task-interactions.js.map +1 -0
  201. package/dist/src/desktop-task-recovery.d.ts +38 -0
  202. package/dist/src/desktop-task-recovery.js +171 -0
  203. package/dist/src/desktop-task-recovery.js.map +1 -0
  204. package/dist/src/desktop-task-service.d.ts +54 -0
  205. package/dist/src/desktop-task-service.js +441 -0
  206. package/dist/src/desktop-task-service.js.map +1 -0
  207. package/dist/src/desktop-types.d.ts +281 -0
  208. package/dist/src/desktop-types.js +13 -0
  209. package/dist/src/desktop-types.js.map +1 -0
  210. package/dist/src/host-monitor-reconciliation.js +36 -4
  211. package/dist/src/host-monitor-reconciliation.js.map +1 -1
  212. package/dist/src/host-profile-runtime.js +7 -3
  213. package/dist/src/host-profile-runtime.js.map +1 -1
  214. package/dist/src/local-codex-cli-adapter.d.ts +7 -0
  215. package/dist/src/local-codex-cli-adapter.js +13 -0
  216. package/dist/src/local-codex-cli-adapter.js.map +1 -0
  217. package/dist/src/openclaw-callback-transport.js +2 -1
  218. package/dist/src/openclaw-callback-transport.js.map +1 -1
  219. package/dist/src/semantic-conversation-target.d.ts +4 -0
  220. package/dist/src/semantic-conversation-target.js +20 -0
  221. package/dist/src/semantic-conversation-target.js.map +1 -0
  222. package/dist/src/semantic-permission-control.js +47 -9
  223. package/dist/src/semantic-permission-control.js.map +1 -1
  224. package/dist/src/semantic-private-authority-offers.d.ts +1 -1
  225. package/dist/src/semantic-private-authority-offers.js +3 -1
  226. package/dist/src/semantic-private-authority-offers.js.map +1 -1
  227. package/dist/src/semantic-tool-command-helpers.d.ts +6 -0
  228. package/dist/src/semantic-tool-command-helpers.js +199 -78
  229. package/dist/src/semantic-tool-command-helpers.js.map +1 -1
  230. package/dist/src/semantic-tool-descriptions.d.ts +2 -1
  231. package/dist/src/semantic-tool-descriptions.js +81 -35
  232. package/dist/src/semantic-tool-descriptions.js.map +1 -1
  233. package/dist/src/semantic-tool-list-projection.js +66 -2
  234. package/dist/src/semantic-tool-list-projection.js.map +1 -1
  235. package/dist/src/semantic-tool-presentation.js +76 -7
  236. package/dist/src/semantic-tool-presentation.js.map +1 -1
  237. package/dist/src/semantic-tool-runtime.js +129 -29
  238. package/dist/src/semantic-tool-runtime.js.map +1 -1
  239. package/dist/src/semantic-tool-schemas.d.ts +410 -27
  240. package/dist/src/semantic-tool-schemas.js +176 -88
  241. package/dist/src/semantic-tool-schemas.js.map +1 -1
  242. package/dist/src/terminal-action-contracts.js +10 -6
  243. package/dist/src/terminal-action-contracts.js.map +1 -1
  244. package/dist/src/terminal-list-cli-adapter.d.ts +1 -0
  245. package/dist/src/terminal-list-cli-adapter.js +6 -3
  246. package/dist/src/terminal-list-cli-adapter.js.map +1 -1
  247. package/dist/src/terminal-monitor-decision-policy.d.ts +1 -1
  248. package/dist/src/terminal-permission-control-list-projection.d.ts +1 -1
  249. package/dist/src/terminal-user-send-intent.d.ts +2 -0
  250. package/dist/src/terminal-user-send-intent.js +11 -3
  251. package/dist/src/terminal-user-send-intent.js.map +1 -1
  252. package/docs/architecture/current-architecture.md +313 -0
  253. package/docs/architecture/interactive-terminal-response.md +276 -0
  254. package/docs/architecture/issue-126-final-report.md +248 -0
  255. package/docs/architecture/orchestration-refactor-history.md +2987 -0
  256. package/docs/architecture/orchestration-refactor.md +21 -0
  257. package/docs/backend-task-recovery.md +89 -0
  258. package/docs/bidirectional-agent-protocol.md +260 -0
  259. package/docs/codex-cli-native-compatibility.md +246 -0
  260. package/docs/codex-desktop-compatibility.md +414 -0
  261. package/docs/openclaw-operations.md +281 -0
  262. package/docs/openclaw-session-turn-delivery-requirement.md +45 -0
  263. package/docs/operator-guide.md +543 -0
  264. package/docs/storage-and-logging.md +91 -0
  265. package/docs/test-performance-issue-108.md +80 -0
  266. package/docs/test-performance-issue-120.md +226 -0
  267. package/docs/testing.md +628 -0
  268. package/openclaw.plugin.json +7 -3
  269. package/package.json +6 -13
  270. package/templates/openclaw-skills/agent-knock-knock/SKILL.md +66 -15
@@ -0,0 +1,2987 @@
1
+ # Historical Issue #126 orchestration refactor ledger
2
+
3
+ > Immutable historical record: this document records the v0.12.11 / Issue #126
4
+ > plan, its chronological phase reports, and later dated addenda. Tool counts,
5
+ > action-contract versions, Watch schemas, writer protocols, module sizes, and
6
+ > pending-work statements are true only for the snapshot named by their
7
+ > section. See [current-architecture.md](./current-architecture.md) for the
8
+ > authoritative current architecture, budgets, and refactor workflow.
9
+
10
+ Status: architecture implementation and enforceable static gates are complete
11
+ at the current closeout;
12
+ [issue #126](https://github.com/scotthuang/agent-knock-knock/issues/126)
13
+ remains open for longitudinal acceptance. The final timed
14
+ fast/integration/full profile, dynamic subprocess runtime attestation, and one
15
+ local OpenClaw install are separate pending final-evidence steps; this status
16
+ does not claim they have run.
17
+
18
+ The four remaining criteria require observations after the refactor:
19
+
20
+ - at least 70% of normal product changes no longer modify `cli-core.ts`;
21
+ - at least 80% of normal affected-test loops complete in 60 seconds or less;
22
+ - five post-refactor product changes reduce median ready-to-release lead time
23
+ by at least 40%; and
24
+ - repeated full-suite flaky failures remain below 1%.
25
+
26
+ The frozen ten-change selector replay proves selector behavior, and a
27
+ point-in-time suite profile proves only that measured revision. Neither can
28
+ substitute for these four longitudinal samples.
29
+
30
+ Snapshot: `main@ea592a88d7af4a709e7a7a1b989dd29e61932935` / `v0.12.11`, measured 2026-08-14
31
+
32
+ Machine-readable measurements: [orchestration-baseline.json](./orchestration-baseline.json)
33
+
34
+ ## Purpose
35
+
36
+ This document defines the boundaries, dependency direction, transaction rules,
37
+ and compatibility contract for the incremental orchestration refactor. It is a
38
+ design constraint for the PR sequence, not a claim that the current source tree
39
+ already satisfies the target architecture.
40
+
41
+ The objective is to make ordinary product changes local and reviewable while
42
+ preserving AKK's safety model. `src/cli-core.ts` must become a stable command
43
+ facade over typed services instead of remaining the owner of terminal authority,
44
+ dispatch, lifecycle, monitor, callback, persistence, and recovery state machines.
45
+
46
+ This work is a strangler refactor. Each PR extracts and characterizes existing
47
+ behavior behind a typed boundary before callers switch to that boundary. A
48
+ ground-up rewrite, protocol redesign, or safety simplification is out of scope.
49
+
50
+ ## Current baseline and concentration
51
+
52
+ The production scope is the 38 checked-in `src/**/*.ts` files. Tests, generated
53
+ `dist`, scripts, templates, and vendored dependencies are excluded.
54
+
55
+ | Metric | Current baseline |
56
+ | --- | ---: |
57
+ | Production physical LOC | 73,792 |
58
+ | Functions/methods with bodies | 2,449 |
59
+ | Files over 1,000 LOC | 16 |
60
+ | Functions over 100 LOC | 167 |
61
+ | Functions over 200 LOC | 57 |
62
+ | Functions over 500 LOC | 9 |
63
+ | Approximate complexity over 20 | 150 |
64
+ | Production import cycles | 0 |
65
+
66
+ `src/cli-core.ts` is the dominant risk concentration:
67
+
68
+ | Metric | `src/cli-core.ts` |
69
+ | --- | ---: |
70
+ | Physical LOC | 38,005 (51.5% of production source) |
71
+ | Functions/methods with bodies | 913 |
72
+ | Functions over 100 / 200 / 500 LOC | 116 / 43 / 8 |
73
+ | Approximate complexity over 20 | 98 |
74
+ | Import declarations | 37 |
75
+ | Distinct internal modules imported | 30 |
76
+ | `Record<string, any>` type references | 246 |
77
+ | Functions receiving an `options` bag | 152 |
78
+ | Distinct `options.<property>` names | 117 |
79
+ | Durable mutation calls | 204 |
80
+ | Lock or writer-lease acquisition calls | 91 |
81
+
82
+ The largest current paths are:
83
+
84
+ - `runTerminalControlSend` at `src/cli-core.ts:19838`: 1,886 lines,
85
+ approximate complexity 242.
86
+ - `runTerminalBridgeMonitorWithLock` at `src/cli-core.ts:27647`: 1,444
87
+ lines, approximate complexity 203.
88
+ - `terminalFirstListProjection` at `src/cli-core.ts:4931`: 1,283 lines;
89
+ its terminal projection callback is 1,162 lines with approximate complexity
90
+ 302.
91
+ - `runNativeThreadTransition` at `src/cli-core.ts:16516`: 812 lines; its
92
+ transaction callback is 790 lines.
93
+ - `runSend` at `src/cli-core.ts:18077`: 721 lines.
94
+ - `runApprove` at `src/cli-core.ts:19041`: 635 lines.
95
+
96
+ The problem is concentrated orchestration, not uniform source quality. The
97
+ import graph is currently acyclic and the public imported surface of
98
+ `cli-core.ts` is small, so behavior can be replaced behind that facade without
99
+ forcing consumers to migrate in one step.
100
+
101
+ The test cost is similarly concentrated. At the `v0.12.11` baseline, 71
102
+ TypeScript test files contain 71,902 physical lines. Three clean fast-tier runs
103
+ at concurrency four completed in 8.68, 8.70, and 8.85 seconds (median 8.70
104
+ seconds). Two clean integration-tier runs took 922.01 and 985.75 seconds; one
105
+ was green and one exposed the pre-existing monitor-singleton supersession
106
+ timeout. In both runs, `test/codex-no-rollout-binding-cli.test.ts` alone took
107
+ 921.81–985.56 seconds. Refactoring success therefore requires narrower affected
108
+ selection and lighter deterministic fixtures, not fewer safety invariants.
109
+
110
+ ## Architectural vocabulary
111
+
112
+ - **Facade**: stable CLI-facing API that parses a command, selects a handler,
113
+ formats output, and maps failures to the existing process contract.
114
+ - **Observation**: immutable facts sampled from Store, terminal, process, agent,
115
+ and transcript sources. An observation is evidence, not durable authority by
116
+ itself.
117
+ - **Authority decision**: a pure, typed allow/deny/recovery result derived from
118
+ an observation and a specific operation. It carries exact reasons and the
119
+ snapshot-bound tokens required for later revalidation.
120
+ - **Use case**: one command-level orchestration operation such as send, approve,
121
+ new thread, callback delivery, or one monitor step.
122
+ - **Transaction shell**: the only layer allowed to acquire mutation locks,
123
+ perform CAS writes, and execute ordered durable effects.
124
+ - **Port**: a typed interface used by a use case for time, Store, terminal,
125
+ process, transcript, or callback transport access.
126
+ - **Adapter**: an implementation of a port. Codex-, Claude-, tmux-, Herdr-,
127
+ filesystem-, and OpenClaw-specific behavior belongs here.
128
+
129
+ ## Target module ownership
130
+
131
+ The path names below describe ownership. A PR may choose nearby names, but it
132
+ must preserve the responsibility and dependency rules.
133
+
134
+ | Boundary | Owns | Must not own |
135
+ | --- | --- | --- |
136
+ | `cli.ts` | Process argv, stdout/stderr forwarding, process exit | Business decisions, Store or terminal access |
137
+ | CLI runtime and command registry | Per-execution context, typed parsing, command registration, output envelope | Terminal authority, lifecycle or callback state machines |
138
+ | `cli-core.ts` | Compatibility exports `parseCliCommand` and `executeCliCommand`; temporary routing shims | New state machines, new persistence codecs, new direct lock code |
139
+ | Terminal observation | Typed terminal/process/agent snapshots and normalization | Permission decisions or mutations |
140
+ | Authority and action projection | Binding match/conflict, ownership, selectors, tokens, `available_actions`, handoff decisions | I/O, clocks, filesystem paths, terminal input |
141
+ | Persistence repositories/codecs | Backward-compatible decoding, validation, atomic write primitives, revisions and CAS | Product policy or terminal input |
142
+ | Transaction/lock kernel | Canonical lock acquisition/release and per-transaction capabilities consumed by gated mutation ports | Business decisions, durable effect ordering, command parsing, or agent-specific screen logic |
143
+ | Dispatch service | Send/respond/approve/cancel preparation, exact input stages, acceptance receipt decisions | CLI formatting, callback transport, native-thread lifecycle policy |
144
+ | Lifecycle service | New/resume/adopt/reconcile classifications and transition reducer | Ordinary task submission or callback delivery |
145
+ | Callback/outbox service | Immutable callback message, attempt lease, retry and delivery settlement | Monitor polling or terminal authority projection |
146
+ | Monitor service | Poll scheduling, pure completion/question/approval/stall decisions, reconciliation effects | Gateway transport details or duplicated dispatch policy |
147
+ | Agent adapters | Codex/Claude process classification, composer/status/transcript profiles, native identity evidence | Store transactions or CLI response schemas |
148
+ | Terminal-control adapters | tmux/Herdr discovery, screen capture, exact terminal mutation | Session/Turn policy or Store writes |
149
+ | OpenClaw plugin | Tool schemas, argument mapping, command registration, Gateway integration | A second copy of CLI authority or action projection |
150
+
151
+ Existing cohesive modules such as `store.ts`, `session-store.ts`,
152
+ `terminal-control-provider.ts`, `terminal-agent-adapter.ts`, and agent-specific
153
+ adapters are retained behind ports. Extraction may split their codecs from
154
+ repositories, but it must not funnel their responsibilities back through the
155
+ CLI facade.
156
+
157
+ ## Dependency direction
158
+
159
+ The allowed direction is:
160
+
161
+ ```text
162
+ CLI / OpenClaw entrypoints
163
+ |
164
+ v
165
+ typed command facade and composition root
166
+ |
167
+ v
168
+ dispatch | lifecycle | callback | monitor use cases
169
+ |
170
+ v
171
+ pure authority, action, and state-transition policies
172
+ |
173
+ v
174
+ typed domain values and port interfaces
175
+ ^
176
+ |
177
+ filesystem, tmux, Herdr, Codex, Claude, and Gateway adapters
178
+ ```
179
+
180
+ The arrows represent compile-time dependencies. Infrastructure implements ports
181
+ defined inward; domain and use-case modules never import infrastructure or the
182
+ CLI facade.
183
+
184
+ Required rules:
185
+
186
+ 1. No new service may import `cli-core.ts`.
187
+ 2. Pure policy/reducer modules may not import `node:fs`, `node:child_process`,
188
+ environment access, wall clocks, or sleep functions.
189
+ 3. `cli-core.ts` and the OpenClaw plugin consume the same action and authority
190
+ result; neither reconstructs permission rules from output fields.
191
+ 4. Agent-specific composer, native-status, and transcript behavior stays behind
192
+ the agent-adapter boundary.
193
+ 5. Store codecs accept retained legacy formats at the boundary. Use cases
194
+ consume validated current domain values.
195
+ 6. The production import graph must remain acyclic. A cycle is a release
196
+ blocker, not an acceptable transitional state.
197
+ 7. Both `cli-core.ts` physical LOC and total `src/**/*.ts` physical LOC are
198
+ exact ratchets in the ownership manifest. An extraction may lower either
199
+ value, but cannot silently grow it back; any intentional increase requires
200
+ an explicit architecture review and manifest diff.
201
+
202
+ ## Canonical lock order
203
+
204
+ All newly extracted mutation code uses this acquisition order, skipping a scope
205
+ only when that resource is not involved:
206
+
207
+ ```text
208
+ terminal dispatch lock -> Store writer lease -> conversation state lock
209
+ ```
210
+
211
+ Locks are released in reverse order. An operation must never acquire a lock to
212
+ the left while it already holds a lock to the right.
213
+
214
+ - The terminal dispatch lock serializes all input and lifecycle effects for one
215
+ canonical terminal endpoint/incarnation.
216
+ - The Store writer lease fences incompatible writers and serializes mutations
217
+ across authoritative Session, Turn, transition, and transfer records.
218
+ - The conversation state lock protects one Turn state/event transaction and its
219
+ compare-before-write checks.
220
+
221
+ The transaction shell creates fresh opaque terminal, Store-writer, and optional
222
+ conversation-state scopes for every invocation. Capability-gated repositories
223
+ validate that every required scope is authentic, active, and belongs to the
224
+ same transaction and exact canonical terminal, Store, or state resource.
225
+ Repositories take their raw target from the verified frozen resource handle,
226
+ so a caller cannot pair a valid scope with a different path or terminal.
227
+ Scopes expire before lock release begins, so a leaked scope cannot authorize a
228
+ later write. Boolean parameters such as
229
+ `terminalSendLockHeld`, `terminalStateLockHeld`, and `storeWriterLeaseHeld` must
230
+ not be reproduced in new services.
231
+
232
+ Read-only observation must not take mutation locks merely for convenience.
233
+ Before a side effect, the transaction shell re-observes and revalidates exact
234
+ endpoint, process incarnation, binding generation, owner, composer, approval,
235
+ and snapshot/token authority under the required locks.
236
+
237
+ ### Current lock-order exceptions
238
+
239
+ The canonical order above is a target constraint, not a statement that every
240
+ `v0.12.11` path already conforms. Known structural exceptions at the baseline
241
+ include:
242
+
243
+ - `runTerminalControlSend` (`src/cli-core.ts:19838`) can express
244
+ terminal -> state -> writer through recursive `*LockHeld` flags.
245
+ - `runTerminalControlCancel` (`src/cli-core.ts:26274`) acquires terminal, then
246
+ state, then enters the writer lease.
247
+
248
+ Behavior-preserving extraction must inventory every reachable exception. It may
249
+ wrap an existing order temporarily, with a named compatibility note and focused
250
+ deadlock/crash tests, but it must not add another instance. Reordering an
251
+ existing transaction is a separate focused change with proof at every durable
252
+ write boundary; it must not be hidden inside a file move.
253
+
254
+ ## Transaction phases
255
+
256
+ ### Ordinary terminal dispatch
257
+
258
+ The target dispatch transaction is explicit and monotonic:
259
+
260
+ 1. **Resolve**: select the exact Session/Turn/terminal and capture observations.
261
+ 2. **Authorize**: derive one typed authority decision and required token set.
262
+ 3. **Lock and revalidate**: acquire terminal -> writer -> state and prove the
263
+ same endpoint, owner, process incarnation, binding generation, request, and
264
+ composer boundary.
265
+ 4. **Prepare**: persist the immutable request identity and `prepared` dispatch
266
+ ledger before terminal input.
267
+ 5. **Inject text**: record `text_injected` only after exact text injection is
268
+ acknowledged.
269
+ 6. **Dispatch Enter**: send exactly one Enter and durably record
270
+ `enter_dispatched`. Legacy `submitted` is compatibility evidence for this
271
+ stage, not proof of native acceptance.
272
+ 7. **Observe acceptance**: record `agent_accepted` only with exact supported
273
+ native evidence. Record `not_accepted` or `uncertain` when that is what the
274
+ evidence proves.
275
+ 8. **Commit and monitor**: commit Session/Turn/binding effects and start or
276
+ reconcile the monitor from durable state.
277
+
278
+ Before input, a proven rollback may end as `aborted` with `safe_to_retry=true`.
279
+ After input may have begun, ambiguous outcomes are `uncertain` with
280
+ `do_not_retry=true`. No extraction may collapse these two cases.
281
+
282
+ ### Native-thread lifecycle
283
+
284
+ New, resume, and adopted external handoff use a separate transition state
285
+ machine:
286
+
287
+ ```text
288
+ prepared -> dispatching -> submitted -> verified -> committed
289
+ | | |
290
+ +----------> uncertain <---+
291
+ |
292
+ +----------> aborted (only with zero-input proof)
293
+ ```
294
+
295
+ `prepared` transition and lifecycle ledger records precede terminal input.
296
+ `verified` requires exact postcondition identity. Session binding changes commit
297
+ with revision/CAS evidence before the lifecycle ledger becomes `resolved`.
298
+ Human-observed adoption is evidence and must never replay terminal input.
299
+
300
+ ### Deferred foreground transfer
301
+
302
+ The Codex follow-current path retains its own durable transfer receipt:
303
+
304
+ ```text
305
+ prepared -> source_reserved -> target_prepared -> dispatch_started
306
+ -> committed -> resolved
307
+ ```
308
+
309
+ Its input substage is monotonic:
310
+
311
+ ```text
312
+ none -> dispatch_started -> text_injected -> enter_dispatched -> agent_accepted
313
+ ```
314
+
315
+ Only zero-input proof may reach `aborted`/`abort_resolved`. Possible input with
316
+ an unproved outcome reaches `uncertain`; recovery may later prove and commit the
317
+ same dispatch but may not send it again.
318
+
319
+ ### Callback/outbox
320
+
321
+ 1. Resolve one trusted, versioned, secretless callback route; a present invalid
322
+ route fails closed and never falls back to legacy host fields.
323
+ 2. Prepare one immutable callback envelope and deterministic delivery/idempotency
324
+ identity.
325
+ 3. Persist the envelope, route snapshot, pending outbox state, and attempt lease
326
+ before transport.
327
+ 4. Resolve the route to a concrete adapter at the composition root. The current
328
+ adapter preserves the OpenClaw Gateway behavior; core services do not select
329
+ or construct it.
330
+ 5. Persist an explicit accepted, retryable-failure, permanent-failure, or
331
+ uncertain attempt outcome. Only retryable failure schedules another attempt;
332
+ accepted checkpoints survive a later wake/observation failure.
333
+ 6. Reconciliation resumes only the same persisted route, envelope,
334
+ message, and attempt authority. Current CLI options or Conversation fields
335
+ cannot redirect an existing outbox.
336
+
337
+ Callback transport state does not own or rewrite the semantic Turn phase.
338
+ Cross-Session callback delivery remains strictly isolated.
339
+
340
+ The first host-neutral slice retains the existing OpenClaw fields and Turn
341
+ status names as a read/write compatibility projection. OpenClaw's trusted
342
+ plugin still supplies the controller session identity; model-facing tools never
343
+ accept a callback destination or profile. A standalone supervisor and new host
344
+ adapters remain separate follow-on work.
345
+
346
+ ### Monitor step
347
+
348
+ A monitor iteration becomes `observe -> decide -> execute effects -> persist`.
349
+ The decision is pure and may yield wait, diagnostic, approval notification,
350
+ question, completion claim, verified-dead stall/close recovery, timeout stall,
351
+ or dispatch-ledger reconciliation. The I/O shell is responsible for locks and
352
+ idempotent effect execution. Polling never becomes authority to replay input.
353
+
354
+ ## Durable write points
355
+
356
+ The following records are externally observable recovery authorities. Their
357
+ ordering and compatibility are behavior, not implementation detail.
358
+
359
+ | Durable record | Current location | Authority retained during extraction |
360
+ | --- | --- | --- |
361
+ | Store manifest | `<store>/manifest.json` | Format/writer compatibility and writer fencing |
362
+ | Managed Session | `<store>/sessions/<session>/state.json` | Binding, native identity, revision/CAS, lineage |
363
+ | Turn/conversation state | `<store>/conversations/<turn>/state.json` | Semantic Turn phase, submission receipt, callback outbox |
364
+ | Turn event log | `<store>/conversations/<turn>/events.ndjson` | Append-only audit and recovery evidence |
365
+ | Native transition | `<store>/transitions/<transition>/state.json` | Lifecycle generation, input outcome, verification and commit |
366
+ | Deferred foreground transfer | `<store>/deferred-foreground-transfers/<transfer>/state.json` | Follow-current reservation, input stage, commit/abort authority |
367
+ | Terminal dispatch ledger | `<runtime-v2>/terminal-dispatch/terminal-dispatch-<key>.json` | Terminal-wide input owner and strongest transport receipt |
368
+ | Terminal/monitor lock files | `<runtime-v2>/terminal-locks` and monitor lock paths | Live serialization only; never semantic authority by themselves |
369
+
370
+ For every extracted transaction, the PR must include a durable write map that
371
+ states:
372
+
373
+ - the precondition and held lock scopes (and, once enforced by a gated port,
374
+ capabilities);
375
+ - the record and expected revision/generation;
376
+ - whether terminal input is definitely zero, possible, or accepted;
377
+ - the crash point immediately before and after the write;
378
+ - the single allowed reconciliation direction;
379
+ - whether retry is safe, forbidden, or requires explicit recovery authority.
380
+
381
+ The strongest durable proof is never overwritten by weaker observation. Event
382
+ write failure after a stronger state/ledger commit is reconciled as lagging
383
+ audit, not by downgrading the committed fact.
384
+
385
+ ### Transaction capability write map
386
+
387
+ PR3 applies the kernel only to operations that already use the target lock
388
+ order. Their business callbacks remain in `cli-core.ts`; the kernel owns scope
389
+ authenticity and lifetime, not these records or effects.
390
+
391
+ | Repository boundary | Required capabilities | Composition adapter retained |
392
+ | --- | --- | --- |
393
+ | Conversation state load / save / event append | state / writer + state / writer + state | existing Store filesystem and JSON functions |
394
+ | Terminal dispatch-ledger load / save / resolve / reconcile | terminal / terminal + writer | existing runtime-ledger filesystem and lifecycle reconciliation functions |
395
+ | Managed Session load / CAS save | writer | existing Session repository functions |
396
+
397
+ Lifecycle recovery and reconciliation receive both the exact locked terminal
398
+ and canonical Store path from a paired repository capability. A recorded
399
+ `store_dir` is comparison evidence only: a mismatch fails closed before any
400
+ transition read, quarantine, Session write, or lifecycle-ledger resolution.
401
+
402
+ | Operation | Held lock scopes | Durable writes and existing order | Terminal input | Crash/retry direction |
403
+ | --- | --- | --- | --- | --- |
404
+ | `runReconcileBinding` | terminal -> writer | one managed Session CAS detach at the listed revision | definitely zero | before CAS, refresh and reauthorize; after CAS, detached is final and a stale token cannot retry |
405
+ | `runTerminalConversationCancel` | terminal -> writer | none; runtime audit and JSON output remain after the adapter call | possible ordered cancel keys | before input, a fresh cancel may retry; after an unacknowledged transport attempt, adapter semantics remain authoritative |
406
+ | `runObservedHandoffClose` | terminal -> writer -> state | Turn state `closed` -> exact dispatch-ledger resolution -> close event | definitely zero | advance only toward ledger/event reconciliation; stale handoff authority cannot start a second close |
407
+ | `runTerminalDispatchClose` | terminal -> writer | lifecycle reconciliation keeps its existing writes; orphan recovery writes one exact dispatch-ledger generation as `resolved` | definitely zero | advance only toward resolved; refresh is required after the recorded generation changes |
408
+
409
+ Each callback continues to perform the same observations, compare-before-write
410
+ checks, output, and error text under the same lock scopes. Handoff close routes
411
+ its fresh Turn/Session/ledger loads, state save, ledger resolution, and event
412
+ append through the gated repositories. Dispatch close routes its
413
+ pane-incarnation load/resolution and later reconciliation writes through them;
414
+ binding reconciliation uses
415
+ the managed-Session adapter for its fresh reads and CAS detach. The transaction
416
+ module supplies no effect DSL and cannot construct Store or protocol state.
417
+ Native-transition and raw/managed-send entry points use the same paired
418
+ capability for lifecycle-fence recovery; unrelated dispatch and lifecycle
419
+ writes remain in their existing shells for their later service milestones.
420
+
421
+ ### Initial native-thread transition policy slice
422
+
423
+ PR5a introduces `native-thread-transition-policy.ts` as a 297-line pure typed
424
+ decision module. It owns lifecycle capability eligibility, exact resume
425
+ candidate and target-Session decisions, explicit binding-reconciliation
426
+ eligibility, prepared transition construction, the six in-memory transition
427
+ phase projections, and the durable failure-phase priority. `cli-core.ts`
428
+ remains at its 37,873-line ratchet: this first slice moves one authority source
429
+ without using formatting changes to claim a size reduction.
430
+
431
+ The module has only type dependencies on managed Session/transition state and
432
+ terminal identity. It imports no filesystem, process, terminal-control, Store,
433
+ clock, or lock implementation. The shell still owns every public error string,
434
+ terminal/process observation, token comparison input, clock read, and effect.
435
+ The existing `terminal -> Store writer` lock scope is unchanged. Durable order
436
+ also remains transition `prepared` before lifecycle ledger `prepared`, each
437
+ transition phase CAS before its matching ledger phase, target ownership proof
438
+ before commit, and verified Session commit before transition/ledger resolution.
439
+
440
+ The focused fast table covers new/resume construction (including null versus
441
+ existing target revision), all six phase events, failure priority, candidate
442
+ and target eligibility, and reconciliation. Affected-test selection binds this
443
+ module to `codex-no-rollout-binding-cli`, `human-handoff-adoption-cli`,
444
+ `native-thread-lifecycle-cli`, and `native-thread-lifecycle-recovery-cli`.
445
+
446
+ ### Initial dispatch-ledger codec slice
447
+
448
+ PR4b introduces `terminal-dispatch-ledger-codec.ts` as a pure document codec
449
+ and append-only receipt reducer. It owns v1/v2 in-memory document validation,
450
+ lifecycle-document classification, receipt history validation/candidate
451
+ projection/strength-preserving merge, and construction of the next JSON
452
+ document. This lowers `cli-core.ts` from 37,809 to 37,481 physical lines.
453
+
454
+ The shell still chooses canonical and legacy runtime keys and paths and owns
455
+ every filesystem observation and effect: dual-path conflict checks, symlink and
456
+ regular-file fences, reads, promotion rename, directory fsync, exclusive temp
457
+ creation, chmod, write/fsync, atomic rename, and cleanup. The codec receives
458
+ already-read bytes and precomputed document identity. Native `JSON.parse`
459
+ failures, invalid-ledger text, v1/v2 field presence and insertion order,
460
+ historical terminal-incarnation evidence, immutable receipt fields, strongest
461
+ receipt proof, and the one proven-safe abort retry generation remain unchanged.
462
+
463
+ Focused tables characterize malformed and duplicate histories, every lifecycle
464
+ discriminator and receipt status, immutable-field and terminal-incarnation
465
+ conflicts, proof downgrade prevention, safe-abort chronology, and v1/v2 JSON
466
+ ordering. The affected integration map covers dispatch authority, recovery,
467
+ receipt fences, terminal send gates, control locks, Codex no-rollout binding,
468
+ handoff adoption, and native lifecycle recovery.
469
+
470
+ ### PR4B1 dispatch receipt and application seam
471
+
472
+ PR4B1 introduces `terminal-dispatch-receipt.ts` for pure terminal bridge state
473
+ and append-only receipt construction and `terminal-dispatch-application.ts` as
474
+ a typed application seam for already-authorized ordinary dispatch writes. It
475
+ composes the existing ordinary-ledger codec and zero-input abort reducer behind
476
+ five local responsibility groups: irreversible-stage synchronization, state,
477
+ ledger, domain audit, and pre-input rollback. It imports no CLI option type,
478
+ raw JSON or filesystem adapter, lock implementation, terminal transport,
479
+ acceptance poller, native binding authority, or public presenter.
480
+
481
+ Measured against exact head `22a379e60329d19ed884264b532106149116726d`,
482
+ this seam lowers `cli-core.ts` from 32,146 to 31,321 physical lines. The
483
+ 492-line receipt module and 731-line application module bring total production
484
+ from 76,076 to 76,474 lines, a reviewed 398-line typed-boundary overhead. The
485
+ largest new function is the 164-line receipt reducer; the largest application
486
+ method is the 118-line zero-input abort method. All new functions remain below
487
+ the hard 500-line and approximate-complexity-50 gates.
488
+
489
+ PR4B1 deliberately preserves the legacy fallback lock acquisition order:
490
+ terminal send lock, Turn-state lock, then Store-writer lease. The composition
491
+ root continues to own those locks and supplies raw state, ledger, event,
492
+ rollback, clock, and crash-hook adapters. Application ports are invoked only
493
+ inside that existing scope and do not expose lock handles or repositories. The
494
+ stage synchronization port only copies the staged conversation and irreversible
495
+ stage timestamp into local core catch variables before state, ledger, or
496
+ deferred/handoff effects; it performs no I/O and cannot escape the invocation.
497
+
498
+ The composition root also retains terminal input and Enter, acceptance
499
+ observation and polling, deferred-transfer and native-binding authority,
500
+ collateral stalling, and every CLI/OpenClaw JSON result. Only durable object
501
+ construction and ordered application moved:
502
+
503
+ - prepared remains ledger then state; either failure restores the prior ledger,
504
+ rolls back the provisional raw attach, and rethrows before terminal input;
505
+ - each transport stage remains state then ledger, followed by the core-owned
506
+ deferred/handoff boundary, then a best-effort domain event; its irreversible
507
+ progress is synchronized to the core immediately before those effects;
508
+ - native identity failure remains core quarantine/deferred marking, ledger,
509
+ state, event, log; generic uncertainty remains ledger, state, event before
510
+ core collateral stalling and presentation;
511
+ - final acceptance remains state, best-effort final ledger, then best-effort
512
+ event, so a lagging ledger cannot downgrade the strongest state receipt; and
513
+ - zero input remains deferred abort or ledger restore, raw rollback, best-effort
514
+ aborted state, the shared abort reducer, best-effort event, then domain log.
515
+
516
+ Direct fast proofs compare `Object.keys` and newline-terminated pretty JSON
517
+ bytes for the bridge state, prepared receipt, and final ledger. They also lock
518
+ the write sequences above, text-stage state/ledger/boundary failures carrying a
519
+ `TerminalInputNotStartedError` without being reclassified as zero input,
520
+ final-ledger failure behavior, immutable receipt history, and the intentional
521
+ authority difference where setup presentation uses the initially constructed
522
+ aborted receipt while transport presentation uses the reducer-reported receipt.
523
+ The owner map selects exactly recovery, receipt-fence, session-acceptance,
524
+ terminal-send, and Codex virgin-binding integration suites. Dispatch-authority
525
+ remains a core lock/authority boundary rather than an application owner.
526
+
527
+ ### PR4C canonical dispatch transaction and execution seam
528
+
529
+ PR4C reuses the PR4B1 application seam as the only implementation of durable
530
+ dispatch ordering. Measured against exact head
531
+ `7a7987f038ac2d96f6c8dca22dcc07db4d8f1e6c`, it lowers `cli-core.ts` from
532
+ 30,640 to 29,281 physical lines (-1,359). Total production grows from 76,649
533
+ to 77,792 lines (+1,143, 84.11 percent of the core reduction). The reviewed
534
+ increase beyond the iteration budget is the exact-resource repair: authentic
535
+ cross-Store state scopes, canonical terminal/writer key-value pairs, malformed
536
+ resources, raw-attach rollback, and
537
+ post-input Session/deferred writes now fail closed before their repository I/O.
538
+ The largest remaining dispatch entry stage is 477 lines with approximate
539
+ complexity 34;
540
+ all new and split functions remain below 500 lines and complexity 50.
541
+
542
+ Ordinary terminal dispatch now acquires the canonical terminal resource, then
543
+ the exact Store writer, and derives any Turn-state scope from that same live
544
+ transaction. The state callback is awaited and the capability expires when it
545
+ returns. Both the dynamic send path and the static writer/state helper reject a
546
+ wrong Store, wrong event log, mixed transaction, released scope, or forged
547
+ resource before lock acquisition or filesystem I/O. Application repositories
548
+ consume those exact active capabilities for every state, ledger, event, and
549
+ rollback operation; they accept no free Store, path, terminal, or lock handle.
550
+
551
+ `terminal-dispatch-execution.ts` owns preflight, transport lifecycle, native
552
+ identity, acceptance, and authority orchestration behind five typed port
553
+ groups: clock, native observation, acceptance, terminal proof, and Turn
554
+ authority. Codex anchor capture/detection and Claude transcript detection are
555
+ implemented by the core-owned adapter; the service has no filesystem, Store,
556
+ raw-lock, public-JSON presenter, or concrete terminal-bridge dependency. Its
557
+ direct fake-port tables lock short-circuit order, exactly one Enter stage,
558
+ before/after-text failure classification, late acceptance and bounded pending
559
+ results, native identity outcomes, and Turn revalidation.
560
+
561
+ Raw terminal input, public CLI/OpenClaw JSON, acceptance adapter construction,
562
+ and authority composition remain in `cli-core.ts`. At the PR4C slice, the
563
+ 82-line `terminal-dispatch-composition.ts` file was explicitly recorded as a
564
+ temporary CLI-infrastructure type bridge owned by `terminal-dispatch-core`,
565
+ not an application service: it still named a concrete resolved terminal type
566
+ and the legacy `Record<string, any>` options bag, with PR7 assigned to remove
567
+ that leakage while moving the remaining facade.
568
+
569
+ The final PR7 decision keeps `TerminalDispatchTerminal` as a structural
570
+ CLI-infrastructure carrier only and eliminates the untyped options bag through
571
+ the six-field, unknown-valued `TerminalControlSendOptions` boundary. Business
572
+ services still receive explicit terminal fact projections, authenticated
573
+ routes, repositories, and typed ports; neither the structural carrier nor the
574
+ CLI options object crosses an execution, application, capability, or deferred
575
+ foreground service boundary.
576
+
577
+ The `terminal-dispatch-application` owner retains exactly five affected
578
+ integration witnesses: Codex no-rollout binding, dispatch recovery, receipt
579
+ fences, session acceptance, and terminal send gates. Focused direct tables also
580
+ prove the canonical resource identities and the preserved PR4B1 durable write
581
+ and error-priority sequences without introducing a second state machine.
582
+
583
+ ## Immutable public and safety contracts
584
+
585
+ The refactor must preserve all of the following unless a separate product issue
586
+ explicitly approves a change.
587
+
588
+ ### Public surfaces
589
+
590
+ - npm package `@scotthuang/agent-knock-knock` and executable
591
+ `agent-knock-knock`.
592
+ - Imported facade functions `parseCliCommand` and `executeCliCommand`, including
593
+ per-execution dependency isolation.
594
+ - Existing CLI command names, aliases, arguments, JSON field meanings, stdout,
595
+ and exit behavior. This includes `delegate`, `list`, `status`, `send`,
596
+ `new-thread`/`clear-thread`, `list-resumable-threads`/`threads`,
597
+ `native-inspect`/`native-status`, `resume-thread`, `reconcile-binding`,
598
+ `respond`, `approve`, `cancel`, `renew`, `reconcile-monitors`, `close`,
599
+ `transcript`, `install-openclaw`, `doctor`, `callback`, `retry-callback`, and
600
+ the internal `monitor` entrypoint.
601
+ - OpenClaw plugin id `agent-knock-knock`, `/akk`, and these 14 tool names:
602
+ `agent_knock_knock_list`, `agent_knock_knock_list_resumable_threads`,
603
+ `agent_knock_knock_native_inspect`, `agent_knock_knock_new_thread`,
604
+ `agent_knock_knock_reconcile_binding`, `agent_knock_knock_resume_thread`,
605
+ `agent_knock_knock_status`, `agent_knock_knock_send`,
606
+ `agent_knock_knock_respond`, `agent_knock_knock_renew`,
607
+ `agent_knock_knock_retry_callback`, `agent_knock_knock_cancel`,
608
+ `agent_knock_knock_close`, and `agent_knock_knock_approve`.
609
+ - The machine-readable `list` action contract, prefilled arguments, selectors,
610
+ and token semantics used by both CLI and OpenClaw.
611
+ - tmux and exact-version Herdr support, plus current Codex and Claude adapter
612
+ compatibility behavior.
613
+
614
+ ### Persistence and recovery
615
+
616
+ - Current and retained legacy Store readability/migration, including Store
617
+ format 1, writer protocol 5, and Session-authority protocol 3 behavior.
618
+ - Existing Session, Turn, native-transition, deferred-transfer, dispatch-ledger,
619
+ callback-outbox, and event schemas and their on-disk identities.
620
+ - Monotonic Session/transition/transfer revisions, binding-generation CAS, and
621
+ crash recovery.
622
+ - Idempotent message, dispatch, completion, and callback identities.
623
+ - Strict Store, Session, Turn, terminal-incarnation, and OpenClaw-session
624
+ isolation.
625
+
626
+ ### Terminal safety
627
+
628
+ - Full native UUID and process-incarnation authority; complete Codex rollout
629
+ identity where required.
630
+ - Fresh snapshot, candidate, binding, handoff, approval, and terminal tokens.
631
+ - Endpoint, route, pane/resource, PID/process-birth, cwd/workspace, owner,
632
+ approval, idle, and composer fences.
633
+ - `prepared -> text_injected -> enter_dispatched -> agent_accepted` evidence;
634
+ exactly one Enter after exact composer proof.
635
+ - No blind retry after possible input, uncertain submission, uncertain approval,
636
+ or uncertain lifecycle transition.
637
+ - Human input and explicit handoff remain higher priority than stale automation.
638
+ - `list` remains read-only unless reconciliation was explicitly requested.
639
+ - AKK never starts a coding-agent process.
640
+
641
+ ## Milestones and PR gates
642
+
643
+ Each milestone is independently reviewable and behavior-preserving. Later work
644
+ does not need to wait for every cleanup within an earlier module, but it may not
645
+ bypass an unfinished safety boundary.
646
+
647
+ 1. **PR0 — baseline and architecture**: this document, machine-readable
648
+ measurements, current ownership and contract inventory.
649
+ 2. **PR1 — terminal observation and binding authority**: extract the shared pure
650
+ exact-binding decision first while list and mutation each retain fresh,
651
+ purpose-built observations and mutation revalidation.
652
+ 3. **PR2 — verified-dead agent and orphan-turn policy**: one pure decision source
653
+ shared by managed close, startup reconciliation, and the direct monitor; keep
654
+ process, transcript, Store, terminal, and callback I/O in their existing shell.
655
+ 4. **PR3 — repositories and transaction kernel**: typed codecs/ports, lock
656
+ capabilities, durable write maps; initially preserve legacy ordering where a
657
+ documented exception requires it.
658
+ 5. **PR4 — dispatch service**: send/respond/approve/cancel transaction phases and
659
+ acceptance evidence behind the stable facade.
660
+ 6. **PR5 — lifecycle service**: new/resume/adopt/reconcile reducer and bounded I/O
661
+ shell, including deferred foreground transfer recovery.
662
+ 7. **PR6 — callback/outbox and monitor/reconciliation services**: extract these
663
+ as separate reviewable commits behind their existing durable boundaries;
664
+ callback preparation/settlement and monitor polling remain distinct services.
665
+ 8. **PR7 — typed facade and secondary cleanup**: finish the command registry,
666
+ keep only stable facade exports in `cli-core.ts`, split remaining OpenClaw
667
+ adapter glue, and remove only compatibility shims proven dead by tests.
668
+
669
+ Every PR records before/after metrics, responsibility movement, dependency
670
+ edges, lock order, durable write points, and the focused tests that protect the
671
+ moved boundary. Every production function must stay strictly below 500
672
+ physical lines and approximate complexity 50; reaching either boundary fails
673
+ the zero-allowlist hard gate. The normal target is under 100 lines and
674
+ complexity under 20.
675
+
676
+ The completion target remains:
677
+
678
+ - `cli-core.ts` at or below 8,000 physical lines and acting only as facade/router;
679
+ - no `Record<string, any>` or implicit `any` in new service APIs;
680
+ - no direct lock acquisition or JSON persistence in orchestration services;
681
+ - one authority/action decision source;
682
+ - zero production import cycles;
683
+ - unchanged black-box public contracts and full release gate.
684
+
685
+ ## Phase 1 review snapshot
686
+
687
+ This branch is the first bounded delivery for issue #126, not the completion of
688
+ the issue. It establishes enforceable architecture constraints and moves a set
689
+ of behavior-preserving decisions behind typed seams. The dispatch-service
690
+ experiment was explicitly retracted when review found that it owned CLI and
691
+ OpenClaw presentation. PR4 through PR7 therefore remain open work, and this
692
+ phase must not close issue #126.
693
+
694
+ Measured against `main@ea592a8` on 2026-08-14:
695
+
696
+ | Metric | Baseline | Phase 1 | Delta |
697
+ | --- | ---: | ---: | ---: |
698
+ | Production physical LOC | 73,792 | 75,848 | +2,056 (+2.79%) |
699
+ | `src/cli-core.ts` physical LOC | 38,005 | 35,608 | -2,397 (-6.31%) |
700
+ | `cli-core.ts` production share | 51.5% | 46.95% | -4.55 pp |
701
+ | Production modules | 38 | 52 | +14 |
702
+ | Production import edges / cycles | 95 / 0 | 130 / 0 | +35 / 0 |
703
+ | Functions over 100 / 200 / 500 LOC | 167 / 57 / 9 | 164 / 58 / 9 | -3 / +1 / 0 |
704
+ | Approximate complexity over 20 | 150 | 143 | -7 |
705
+ | Test TypeScript physical LOC | 71,902 | 76,108 | +4,206 (+5.85%) |
706
+ | Test TypeScript files | 71 | 86 | +15 |
707
+
708
+ The result is a reduction in orchestration risk concentration, not a reduction
709
+ in total code size. The exact `cli-core.ts` and production totals are ratcheted
710
+ in `config/production-module-ownership.json`; later phases must reduce them
711
+ rather than conceal extraction overhead. The focused test loop remains about
712
+ ten seconds, while the real-process integration tier remains the dominant
713
+ delivery cost.
714
+
715
+ ### Responsibility and dependency movement
716
+
717
+ | Seam | Responsibility moved inward | I/O, locks, and durable effects deliberately retained outside | Focused proof |
718
+ | --- | --- | --- | --- |
719
+ | Terminal binding authority | Exact binding-match decisions and typed list/mutation observations | Fresh terminal/process sampling and mutation revalidation remain in `cli-core.ts` | authority table tests plus list, lifecycle, handoff, and send integration |
720
+ | Verified-dead agent policy | Process-death proof validation, event replay, stall eligibility, completion tri-state | Process/transcript probes and terminal -> writer -> state orchestration remain in the shell | Codex/Claude completion-wins, fail-closed, deferred-transfer, and crash-replay tests |
721
+ | Canonical mutation kernel | Canonical acquisition/release plus fresh resource-bound terminal, writer, and optional state capabilities for four migrated paths | Business write ordering and raw filesystem/JSON adapters remain in composition | authenticity, lifetime, wrong-resource, cross-transaction, lock-order, error-precedence, and control-lock tests |
722
+ | Dispatch policy, zero-input abort reducer, and ledger codec | Pure preflight/abort precedence plus v1/v2 decode, construction, receipt merge, and validation | Ledger path selection, no-follow reads, atomic rename/fsync, Store locks, terminal input, and CLI formatting remain in the shell | reducer tables, codec byte/order tests, replay, receipt-fence, send-gate, and recovery tests; codec changes select the full tier |
723
+ | Lifecycle transition policy | Candidate/target classification and transition phase reduction | Terminal observation, transition CAS, deferred transfer, input, and recovery writes remain in the shell | transition tables and lifecycle/recovery integration |
724
+ | Callback policy, transport, and settlement | Retry decisions; Gateway process adapter; delivery progress/success/failure settlement | CLI composition owns the clock, state transaction, retry launcher, output, and callback preparation | retry matrix, exact transport call ordering, settlement write-order tests, and callback integration |
725
+ | Monitor seams | Approval clearing/suppression/notification, activity/completion/death/timeout decisions, fingerprint facts, and launch/ownership plans | Poll I/O, supervision process management, state/event writes, callback preparation, and terminal locks remain in the shell | decision/poll/launch tables and monitor recovery/lifecycle/approval integration |
726
+ | Terminal list renderer | Pure managed-Turn and action-contract projection from sampled facts | Store, process, ledger, Session, approval, and token observations remain in `cli-core.ts`; mutation never consumes list authority | exact v16 action order plus list/session/handoff integration |
727
+ | Conversation trace | Bounded executor-log parsing, secret redaction, and monitor-event projection | Status routing and conversation/event loading remain in `cli-core.ts`; the module performs only the existing optional read of the selected output log | exact parser/redaction/fallback unit tests plus management CLI integration |
728
+ | CLI runtime context | Per-execution dependency, output, clock, sleep, exit, and logging context | No business policy or persistent state moved into the runtime | nested and concurrent async-context isolation tests |
729
+ | Install and doctor adapters | OpenClaw plugin install/configure/restart/verify ordering plus typed doctor report composition | The shared CLI command runtime retains PATH/HOME lookup, package-root resolution, output redaction, and async-local exit/output authority; terminal, lifecycle, and dispatch logic are not imported | direct argv/effect-order, exact JSON bytes/key-order, exit-code, PATH/HOME isolation, and retained CLI boundary tests |
730
+
731
+ The new compile-time direction is
732
+ `cli-core composition -> callback settlement -> callback policy`, while the
733
+ OpenClaw child-process transport independently depends on the callback policy's
734
+ delivery outcome type. Settlement does not import the transport adapter or CLI
735
+ runtime.
736
+
737
+ ### Lock and durable-write parity
738
+
739
+ No Store, Session, transition, dispatch-ledger, callback-outbox, or public
740
+ protocol version changes in Phase 1. The extraction keeps the existing lock
741
+ scope and durable ordering at each migrated call site. In particular:
742
+
743
+ - verified-dead reconciliation continues to acquire terminal dispatch lock,
744
+ Store writer lease, then conversation state lock; callback execution stays
745
+ outside those locks;
746
+ - callback settlement still executes progress as load -> save -> event,
747
+ success as load -> save -> event, and failure as load -> retry-monitor launch
748
+ -> save -> failure event -> monitor event;
749
+ - terminal dispatch still records prepared state/ledger/evidence before input,
750
+ preserves `text_injected -> enter_dispatched -> agent_accepted`, and never
751
+ retries an uncertain input;
752
+ - lifecycle transition and deferred-transfer CAS/write/crash boundaries remain
753
+ in their original shell; and
754
+ - dispatch-ledger filesystem open/no-follow, temporary write, fsync, rename,
755
+ directory fsync, and cleanup behavior was not moved into a generic repository.
756
+
757
+ The Phase 1 review gate is architecture validation, typecheck/build, focused
758
+ policy and adapter tests, and one exact-head full test run. Packaging,
759
+ publishing, installation, protocol upgrades, and issue closure are not part of
760
+ this phase.
761
+
762
+ ### Reproducible refactor evidence guard
763
+
764
+ Run the local, non-integration evidence gate with:
765
+
766
+ ```sh
767
+ npm run validate:refactor-evidence
768
+ ```
769
+
770
+ `config/refactor-test-evidence.json` freezes two review inputs. First, it counts
771
+ static subprocess-startup call sites in `test/**/*.ts` for the immutable
772
+ `v0.12.11` baseline and the current tree. The included metric is CLI-process
773
+ plus fake-Node-process startup sites; other adapter/process calls are reported
774
+ separately. This is a deterministic source metric, not a claim about dynamic
775
+ process executions in one test run. The initial eight callback cases, the CLI
776
+ UX, native-ownership, management, selector, Session-binding, deterministic
777
+ dispatch-admission, and 20 normal callback invocations now use the imported
778
+ command service. The multilingual composer not-accepted witness now uses the
779
+ same imported command service while retaining the real tmux adapter and its
780
+ exactly-one-Enter assertion. The final slice also imports redundant callback,
781
+ installer, verifier/guard, Claude recovery, and nested approval wrappers. The
782
+ product-test value is now 19 of 48 baseline sites, a 60.42% reduction, and its
783
+ `final_threshold.required` flag is `true`. Measurement self-tests are reported
784
+ separately (baseline zero; current ten included fake-Node probes) under one
785
+ fixed diagnostic path applied to both revisions; they cannot dilute the
786
+ product migration ratio.
787
+
788
+ Second, the manifest freezes the exact changed paths and subjects of ten
789
+ pre-`v0.12.11` product/test commits and replays them through the current
790
+ affected-test selector. Eight changes now select owned integration witnesses;
791
+ the two commits that changed exact `src/store.ts` authority remain full. The
792
+ measured fallback is therefore 2 of 10 (20%), meeting the completion target.
793
+ Every normal production domain is capped at five integration witnesses, while
794
+ unknown paths, `src/store.ts`, `src/protocol.ts`, and shared kernels remain
795
+ full. Known test helpers resolve through an explicit transitive consumer map.
796
+ Tier-manifest additions and synchronized package-version bumps narrow only from
797
+ Git parent/current blob proof; deletion, movement, reordering, dependency
798
+ changes, or an unproved caller object fail closed. The validator fails if Git
799
+ history, a frozen path list, the measured count, or a replay result drifts, and
800
+ `affected_selector_replay.final_threshold.required` is now `true`.
801
+
802
+ `config/public-contract-witnesses.json` is the machine-readable compatibility
803
+ inventory. It pins the package executable and facade, CLI commands/JSON
804
+ witnesses, list action contract v16, all 14 OpenClaw tools, Store format 1 and
805
+ writer protocols 1 through 5, and eleven mappings from old executable tests to
806
+ focused service invariants and retained boundary witnesses. Every authority and
807
+ witness path must exist, each witness must remain in its declared test tier and
808
+ contain its named assertion, and unknown or missing manifest fields fail
809
+ closed.
810
+
811
+ `npm run validate:architecture` invokes the same evidence guard after the
812
+ ownership/import/LOC checks. Intentional contract or evidence changes therefore
813
+ require a reviewed manifest diff; changing only a number to conceal a failed
814
+ measurement does not pass because the validator reproduces it from source and
815
+ Git history.
816
+
817
+ ### Codex no-rollout process-contract consolidation
818
+
819
+ The canonical integration witness
820
+ `test/codex-no-rollout-binding-cli.test.ts` declares 102 named
821
+ tests with their original assertions. `config/test-file-shards.json` assigns
822
+ every declaration to exactly one of eight worker entrypoints. Test-tier
823
+ selection, production ownership, affected-test selection, public-contract
824
+ evidence, and dynamic subprocess evidence continue to name the canonical path;
825
+ the tier runner expands that one path to every compiled shard and fails closed
826
+ for a missing, duplicate, unused, out-of-range, or uncompiled shard. A targeted
827
+ canonical selection also rejects a shard query that does not match its actual
828
+ worker entry, so it can never execute only a subset while claiming the whole
829
+ witness.
830
+
831
+ Repeated executable invocations now use the same imported parser/command
832
+ boundary and fixture-scoped virtual clock as the surrounding invariant tests.
833
+ For injected exit checkpoints, the fixture freezes the exact durable filesystem
834
+ image at `cliExit`, rewrites active lock ownership to the simulated dead CLI
835
+ PID, and restores files without changing surviving rollout inodes before the
836
+ next recovery command. Ordinary exception compensation after the injected exit
837
+ therefore cannot forge the crash state, while recovery still proves lock
838
+ reclamation, descriptor identity, exact CAS state, and zero replay.
839
+
840
+ | Former repeated executable role | Same retained invariant | Authoritative real-process witness |
841
+ | --- | --- | --- |
842
+ | Virgin attach, terminal send, and status variants | Exact parser/command routing, terminal text plus one Enter, acceptance binding, and no Store mutation | `doctor exits non-zero when required package files are missing` in `cli-ux.test.ts` retains argv/exit; `raw background send durably prepares its terminal submission before tmux accepts it` in the composer-replay shard retains real terminal-adapter input |
843
+ | Deferred preparation, commit, acceptance-backfill, and recovery crash variants | Exact durable image at every named `cliExit(86)` checkpoint; subsequent recovery retains Session/Turn/ledger/transfer state and never replays input | `zero-input deferred source Session reservation before its transfer receipt recovery aborts safely before one refreshed retry` retains the real Store crash and exit-86 boundary used by dynamic evidence |
844
+ | Startup candidate-monitor reconciliation | Exact pending Turn is accepted and completed once, its transfer and dispatch ledger resolve, and no callback state appears | `startup reconciliation relaunches one pending candidate monitor without replay` retains detached monitor PID launch, liveness, and process exit |
845
+
846
+ The no-rollout suite retains two explicit `runCliSubprocess` call sites for its
847
+ unique Store-crash and detached-monitor process boundaries. Consolidation does not
848
+ shorten a production timeout, raise test concurrency, remove a test or
849
+ assertion, or replace the separate OpenClaw callback process boundaries.
850
+
851
+ ## Callback/outbox application service
852
+
853
+ The callback milestone now has one typed application boundary for generic
854
+ callback preparation and execution, retry classification and monitoring,
855
+ startup reconciliation, terminal-completion outbox preparation, and approval
856
+ notification outbox preparation. The service composes the existing pure retry
857
+ policy, OpenClaw delivery contract, and settlement service; it does not import
858
+ `cli-core.ts`, filesystem or process adapters, CLI presentation, or raw locks.
859
+ The OpenClaw child-process transport implements the policy-owned delivery
860
+ contract rather than exporting an infrastructure type back into the service.
861
+
862
+ Measured against its exact pre-extraction head, this vertical moves 1,133
863
+ physical lines out of `cli-core.ts` while adding 387 physical production lines
864
+ overall. The reviewed overhead is the explicit typed port/result surface and
865
+ the direct service boundary; it is not hidden by unrelated cleanup or compact
866
+ formatting. The hard maxima are 396 physical lines and approximate complexity
867
+ 32, below the 500/50 gates. The preparation span (277/32, including its nested
868
+ persistence phase), persistence phase (145/30), reconciliation callback
869
+ (129/20), and terminal-completion preparation (131/8) remain reviewed
870
+ exceptions to the default 100/20 target so their durable short-circuit and write
871
+ order stays visible. The production import graph remains acyclic.
872
+
873
+ The composition root still owns terminal and Store-writer locks, state-lock
874
+ implementation, Store/path resolution, JSON/event persistence adapters, retry
875
+ process launch, clock/process observation, Gateway transport construction, and
876
+ all public JSON. Terminal completion preserves state-lock scope across claim,
877
+ detected/message/outbox writes, and the record-only crash checkpoint, releases
878
+ that lock before settling the terminal dispatch ledger, and never replays
879
+ terminal input. Approval persistence still records the stable message id and
880
+ timestamp before invoking the service; the service either prepares that exact
881
+ message id or returns the same message without an outbox when no Gateway route
882
+ exists. Delivery settlement retains progress `load -> save -> event`, success
883
+ `load -> save -> event`, and failure `load -> retry-monitor -> save -> events`
884
+ ordering through the existing settlement service.
885
+
886
+ Direct fast proofs cover fresh/duplicate/non-retryable outbox preparation,
887
+ completion claim success/conflict and lock release, stable approval identity,
888
+ and the no-Gateway branch. Existing policy, settlement, transport, callback,
889
+ Claude, approval, monitor lifecycle, monitor recovery, and OpenClaw contract
890
+ witnesses remain the black-box boundary set.
891
+
892
+ ## Terminal monitor decision policy
893
+
894
+ The monitor decision milestone moves one pure policy boundary out of the CLI
895
+ composition root. It owns completion-first poll reduction, approval prompt
896
+ clearing, question/error classification, every consumed-prompt suppression,
897
+ verified-dead completion classification, post-effect timeout classification,
898
+ activity cadence, and stable approval/activity/screen identity facts. It
899
+ directly composes the existing poll and verified-dead policies and performs no
900
+ I/O, locking, process access, callback delivery, or CLI presentation.
901
+
902
+ Measured against exact head `e62a79cc94428ddb9a5c264600f259ca4d05ee0c`,
903
+ the extraction reduces `src/cli-core.ts` from 32,398 to 32,146 physical lines
904
+ (-252) and changes total production TypeScript from 75,934 to 76,076 (+142).
905
+ The 42-line excess over the preferred +100 budget is the reviewed, explicit
906
+ typed decision surface and direct proofability; no formatting compression or
907
+ unrelated responsibility movement is used. The 394-line module remains below
908
+ the 500-line hard boundary, every new function remains below 100 physical
909
+ lines, and the hard approximate-complexity maximum is 27. The approval reducer
910
+ (67/27) and consumed-approval classifier (58/23) are transparent exceptions to
911
+ the default complexity-20 target: their branch tables stay cohesive and direct
912
+ tests lock every precedence path.
913
+
914
+ The composition root still owns terminal singleton, Store-writer and state
915
+ locks; terminal observation and input adapters; process launch and death
916
+ probing; state/event/outbox writes; callback continuation; clocks and sleeping;
917
+ and public JSON/log presentation. Approval effects retain their asymmetric
918
+ durable order: question follows `fingerprint -> event -> record`, while an
919
+ unapprovable or evidence error follows `event -> fingerprint -> record`.
920
+ Polling retains `activity -> completion -> verified-dead -> fresh clock ->
921
+ timeout`, so work performed by persistence or the death probe can cross a
922
+ deadline without deferring the timeout by one poll. Application orchestration
923
+ and those effect ports remain the follow-on monitor service milestone.
924
+
925
+ ## Terminal monitor application service
926
+
927
+ The monitor application milestone moves the singleton-owned retry loop and the
928
+ complete locked monitor state machine behind five typed port groups: state,
929
+ authority, callbacks, runtime, and presentation. The service owns initialization,
930
+ submission reconciliation, binding deferral, observation application, approval
931
+ continuation, activity persistence, stable completion, verified-dead fallback,
932
+ and timeout routing. It composes the canonical monitor decision and poll policies;
933
+ it does not import `cli-core.ts`, filesystem or process modules, raw lock or JSON
934
+ persistence implementations, a callback transport, or a public JSON presenter.
935
+
936
+ Measured against exact head
937
+ `b637c012cfa87315380c150405a3384d653ac847`, the extraction reduces
938
+ `src/cli-core.ts` from 28,336 to 27,319 physical lines (-1,017). Total
939
+ production TypeScript changes from 79,308 to 80,554 lines (+1,246, 122.52
940
+ percent of the core reduction). The transparent overhead is the 1,583-line
941
+ typed application boundary, the 680-line CLI adapter and presenter boundary,
942
+ and their direct trace types; no unrelated deletion or compressed formatting is
943
+ used to hide that cost. Every new function remains within the preferred
944
+ 100-line/complexity-20 target. The largest is the 98-line/c20 public-result
945
+ presenter; the largest service function is the 89-line/c11 approval application,
946
+ and the service complexity maximum is c13. The production import graph remains
947
+ acyclic.
948
+
949
+ `cli-core.ts` still resolves the exact state and event paths, acquires the
950
+ singleton owner, and supplies the concrete terminal, Store-writer and Turn-state
951
+ lock functions. It also supplies state/event/ledger repositories, live process
952
+ and death probes, terminal observation, callback transport construction, clock
953
+ and crash hooks, and the public JSON/log writer. The CLI adapter accepts only
954
+ those invocation-local capabilities, applies them in the legacy lock order, and
955
+ cannot manufacture a path, Store, terminal route, or lock.
956
+
957
+ The application order remains `initialize -> submission reconciliation -> poll
958
+ -> detector/approval -> activity -> stable completion -> independent verified
959
+ death -> fresh clock -> timeout`. A completion persisted immediately before
960
+ process exit therefore still wins over orphan cleanup, and work performed by a
961
+ death probe can cross a deadline without postponing timeout classification by
962
+ one poll. Approval effects keep their intentional asymmetry: question is
963
+ `fingerprint -> event -> record`, while an unapprovable/evidence error is
964
+ `event -> fingerprint -> record`. Stale notifications sleep and retry without
965
+ callback execution; duplicates present without delivery; a consumed question
966
+ callback resumes the same generation; callback and completion claims remain
967
+ outside the Turn-state lock exactly as before.
968
+
969
+ Direct fast traces prove live-dispatcher PID gating before terminal I/O, two-poll
970
+ completion stability, exactly one status/screen snapshot per poll with the legacy
971
+ completion-metadata read order, death-before-fresh-clock ordering, both approval
972
+ effect orders, executor-to-callback actor mapping, prepared-recovery release
973
+ order (`state -> writer -> terminal`), and zero terminal I/O on a fresh-state
974
+ retry. Acceptance errors and not-accepted/fenced presentations remain inside
975
+ the terminal send lock; pending acceptance releases that lock before backoff.
976
+ The retained lifecycle, approval and
977
+ recovery shards provide 21 executable boundary cases for singleton ownership,
978
+ Store-lock deferral, callback concurrency, detector diagnostics, durable
979
+ completion, verified death, timeout, duplicate settlement, handoff and monitor
980
+ relaunch behavior.
981
+
982
+ ## Native-thread lifecycle query slice
983
+
984
+ The first native-thread lifecycle application slice moves only read-side
985
+ candidate discovery, active-owner observation, exact candidate-token
986
+ revalidation, restorable-origin eligibility, and previous-thread projection
987
+ behind `NativeThreadLifecycleQueryPorts`. New-thread and resume-thread mutation,
988
+ handoff, verified-empty recovery, reconciliation, dispatch recovery, selection
989
+ snapshot persistence, and public JSON presentation remain in `cli-core.ts`.
990
+ The query service has no transaction, lock, capability, Store-save, snapshot-save,
991
+ terminal-input, recovery, or presenter port.
992
+
993
+ Measured against exact head `ceb1e2fbb9ffa65af139182b36ea0bd527f4fe1e`,
994
+ the slice reduces `src/cli-core.ts` from 31,321 to 30,775 physical lines (-546)
995
+ and changes total production TypeScript from 76,474 to 76,569 (+95). The query
996
+ service is 495 physical lines. No function reaches 500 lines; architecture
997
+ validation retains the hard approximate-complexity ceiling of 50. The
998
+ production import graph remains acyclic and the module has one targeted
999
+ ownership domain, `native-thread-lifecycle-query`, with five retained lifecycle
1000
+ integration witnesses.
1001
+
1002
+ The default approximate-complexity target remains 20. The reviewed cohesive
1003
+ exceptions are `activeNativeThreadOwners` (93 LOC/c28),
1004
+ `verifiedPreviousResumeCandidate` (68 LOC/c24), and
1005
+ `decodeThreadCandidateToken` (38 LOC/c21); all remain below 100 LOC and c50.
1006
+
1007
+ The composition root implements the read port with frozen method-only adapters.
1008
+ It continues to own filesystem/process observation, terminal and agent adapters,
1009
+ Store path selection, selection snapshot writes, clock sampling, and public JSON.
1010
+ Store path selection is lazy and memoized at the first Store observation; token
1011
+ revalidation that fails before a Store read cannot resolve or inspect that path.
1012
+ Candidate observation preserves `active process ownership -> managed Session
1013
+ observation -> exact running version -> provider discovery`. Invalid UUID and
1014
+ Store-authority errors precede terminal scanning; an active external owner
1015
+ precedes managed-Session conflict observation. Version failure never calls the
1016
+ candidate provider. Candidate tokens retain baseline `JSON.stringify` byte and
1017
+ key-order semantics; no canonicalization was introduced. Their codec, candidate
1018
+ sorting, committed-previous policy, and pure snapshot assertions live in the
1019
+ adapter-neutral `native-thread-resume-snapshot-policy.ts`, so importing the
1020
+ query service cannot load snapshot filesystem persistence.
1021
+
1022
+ The direct fast table locks version short-circuit, observation order,
1023
+ deduplication and sorting, exact token mismatch precedence and bytes, Store then
1024
+ terminal ownership error priority, and one exact committed-transition read for
1025
+ the previous resume candidate. Snapshot assertion traces additionally lock lazy
1026
+ cwd and clock callbacks, terminal-evidence order, fingerprint-before-row
1027
+ short-circuiting, ordered-row equality, and rollout `JSON.stringify` field-order
1028
+ sensitivity. Since this slice writes nothing, it adds no durable-write or crash
1029
+ window; the existing core snapshot write and lifecycle mutation/recovery
1030
+ witnesses remain authoritative until the separate mutation application slice.
1031
+
1032
+ ## Terminal monitor startup eligibility policy
1033
+
1034
+ Startup, handoff, and locked launch preparation now share one pure staged
1035
+ eligibility policy. The policy owns candidate priority and exact reason text for
1036
+ terminal-bridge identity, dispatch authority, blocking submission, runtime
1037
+ identity, deferred-transfer acceptance, and deadline metadata. Its generator
1038
+ yields only the next typed observation, so the CLI composition root does not
1039
+ touch terminal control, the dispatch ledger, Store path authority, runtime
1040
+ identity, or a deferred transfer until every earlier candidate has passed.
1041
+ The policy has no ports, filesystem or process access, locks, mutation, or CLI
1042
+ presentation.
1043
+
1044
+ Measured against exact head `8e5c636604845d42f4f0e0af28b36621974e75b6`,
1045
+ the extraction reduces `src/cli-core.ts` from 30,775 to 30,640 physical lines
1046
+ (-135) and changes total production TypeScript from 76,569 to 76,649 (+80).
1047
+ The new policy is 195 physical lines. Its 135-line staged reducer has approximate
1048
+ complexity 48: this is a reviewed transparent exception to the preferred 100/20 target,
1049
+ while remaining below the hard 500/50 gate. Keeping the precedence in one
1050
+ reducer makes every short circuit directly table-testable without concealing
1051
+ branches in I/O adapters. The shared, I/O-free `terminal-submission-facts.ts`
1052
+ owns the submission projection and typed Codex anchor codec; its 99-line
1053
+ validator has approximate complexity 49, a reviewed transparent exception to
1054
+ the preferred complexity-20 target and still below the hard gate. All other
1055
+ new functions are below 15 lines and complexity 5.
1056
+
1057
+ The composition root remains the sole owner of terminal-control decoding,
1058
+ dispatch-ledger and deferred-transfer reads, Store path derivation and symlink
1059
+ validation, runtime identity observation, locks, mutation, monitor launch, and
1060
+ public JSON/log presentation. Observation order remains `bridge/status ->
1061
+ message -> terminal control -> dispatch ledger -> conversation state path ->
1062
+ Store derivation -> submission -> runtime -> Store derivation -> deferred
1063
+ transfer -> deadline`. In particular, non-terminal and inactive candidates
1064
+ never derive a Store, while a malformed Store path still fails before an
1065
+ already-invalid dispatch ledger is classified, preserving the prior error
1066
+ precedence. Dispatch `state_path` is not observed until the earlier ledger,
1067
+ message, control, conversation, Session, and Turn predicates have passed.
1068
+
1069
+ ## Native-thread transition verification and settlement
1070
+
1071
+ The second native-thread lifecycle slice moves the mutation's typed
1072
+ verification and settlement seam out of the CLI composition root. Before any
1073
+ durable transition is prepared, the verification adapter preserves lifecycle
1074
+ eligibility, plan selection, initial idle status, the exact Claude agents-row
1075
+ proof, and the single Codex `/status` probe. After core has durably recorded
1076
+ `command_submitted`, the settlement service owns stable identity verification,
1077
+ verified-transition persistence, the verified crash checkpoint, exclusive
1078
+ target ownership, Session commit, committed-transition persistence, resolved
1079
+ ledger persistence, and final presentation. Dispatch preparation, composer
1080
+ revalidation, terminal input, raw lock acquisition, recovery, handoff, and
1081
+ verified-empty reconciliation remain in `cli-core.ts`.
1082
+
1083
+ Measured against exact head `a96bfbb2c6d011e4bdbe53f883e01250ad1e4023`,
1084
+ the slice reduces `src/cli-core.ts` from 29,281 to 28,610 physical lines
1085
+ (-671) and changes total production TypeScript from 77,792 to 78,388 (+596).
1086
+ The transparent typed-capability overhead is 88.8% of the core movement. Issue
1087
+ #126 has no production-zero-growth requirement; the added lines are the five
1088
+ explicit port groups, exact verification adapter, capability-scoped repository
1089
+ surface, post-lock terminal/Store resource adapter, and reusable direct evidence
1090
+ rather than formatting compression or an unrelated responsibility move.
1091
+
1092
+ `runNativeThreadTransition` is 421 LOC/c1, with its transaction callback at
1093
+ 412 LOC/c44. The settlement service is 331 physical lines; its largest function
1094
+ is `settleFailedNativeThreadTransition` at 124 LOC/c9. The verification adapter
1095
+ is 707 physical lines; its largest function is
1096
+ `verifyNativeThreadTransition` at 201 LOC/c45. Every function remains below the
1097
+ hard 500 LOC/c50 gates. Reviewed exceptions to the default 100 LOC/c20 target
1098
+ are the cohesive transaction wrapper/callback (421/c1 and 412/c44), core port
1099
+ wiring (173/c1), failure settlement (124/c9), verification polling state
1100
+ machine (201/c45), and shared known-root reducer (94/c24). Keeping these order
1101
+ tables intact makes their fail-closed precedence visible and directly testable.
1102
+ The 100-line resource adapter's exported operation is 77 LOC/c1 and its inner
1103
+ capability gate is 55 LOC/c14, so it requires no default-threshold exception.
1104
+
1105
+ The service imports no filesystem or path API, raw lock, Store directory,
1106
+ public JSON, terminal bridge, `any`, or `Record<string, any>`. Core still owns
1107
+ argv and public JSON, constructs concrete terminal and Store adapters, acquires
1108
+ terminal then writer locks, and invokes the presenter before leaving the
1109
+ transaction callback. Every service repository operation receives the same
1110
+ authentic `CanonicalMutationScopes` and `CanonicalMutationResources`; the
1111
+ capability-gated repositories bind every verification, ownership, transition,
1112
+ Session, and ledger operation to both locked resources. Before observation or
1113
+ I/O, the adapter verifies active scopes, the post-lock terminal's exact resource
1114
+ key and process incarnation, and the captured Store resolving to the active
1115
+ canonical writer. Lifecycle ledger
1116
+ construction and save form one scoped port; its `store_dir` must strictly equal
1117
+ the active writer Store, and persistence uses the post-lock fresh terminal route.
1118
+ The lifecycle resource adapter reuses the common mutation pair gate and
1119
+ `terminalRuntimeResourceKey`; it imports no terminal-dispatch domain module.
1120
+ Agent kind and PID come only from that resolved terminal and are absent from the
1121
+ service verification request.
1122
+ Lifecycle and dispatch compatibility exports share one adapter-neutral native
1123
+ identity fence, matcher, and strict complete-rollout predicate in
1124
+ `terminal-binding-authority.ts`. Blank or malformed runtime rollout fields fail
1125
+ closed before path comparison and cannot escape as a `TypeError`.
1126
+
1127
+ Verified success retains `verify -> verified transition -> crash hook ->
1128
+ ownership -> Session commit -> committed transition -> resolved ledger ->
1129
+ present`. Failure retains committed-bookkeeping error precedence, verified
1130
+ recovery without roll-forward, proven-zero-input abort plus source restoration,
1131
+ and possible-input uncertainty plus source quarantine. A five-case recording
1132
+ port table asserts those orders, exact scope/resource forwarding, and
1133
+ presentation before writer and terminal lock release. The no-rollout identity
1134
+ case separately proves that a legitimate status-card or pre-materialization
1135
+ observation returns false without reading a missing rollout or throwing. One
1136
+ targeted ownership domain retains five native lifecycle integration witnesses.
1137
+ Direct resource-adapter cases additionally prove moved-route fresh bytes and
1138
+ zero verification/ownership/ledger I/O for wrong incarnation, malformed or
1139
+ key-mismatched terminal/writer resources, captured-Store mismatch, and released
1140
+ scopes. Adapter cases pin Codex probe/companion ordering, Claude rows-before-status
1141
+ ordering, and the no-revalidation callback's original synchronous invocation.
1142
+
1143
+ ## Terminal list and action authority projection
1144
+
1145
+ The terminal-list milestone gives list projection and fresh mutation
1146
+ preparation one canonical send-authority reducer. `terminal-action-projection.ts`
1147
+ owns Session-claim conflict precedence, dispatch/Session conflict composition,
1148
+ send authority, safe action selection, management facts, and handoff/recovery
1149
+ projection. `terminal-authority-policy.ts` owns provider-neutral terminal and
1150
+ process-incarnation facts, managed-binding conflict classification, Codex
1151
+ companion fences, exact deferred-source authority, stored Turn identity, and
1152
+ the byte-sensitive verified-empty, deferred-foreground, observed-handoff, and
1153
+ active-Turn token codecs. Both modules are typed and have no filesystem,
1154
+ process, lock, CLI-option, concrete-adapter, or public-JSON input boundary.
1155
+ The adapter-neutral complete-rollout predicate, identity fence and matcher from
1156
+ the lifecycle slice remain canonical in `terminal-binding-authority.ts`;
1157
+ authority policy directly imports and re-exports them. That module also owns
1158
+ the single status-card predicate and neutral binding-conflict/candidate helpers.
1159
+ PR4C's dispatch execution service imports those identity decisions from binding
1160
+ authority and its process-incarnation and companion decisions from authority
1161
+ policy, so production has one implementation for each decision and no cycle.
1162
+
1163
+ Measured against exact lifecycle head
1164
+ `10b2b9c60a8f5635961156bf9951472ea5542a48`, this slice reduces
1165
+ `src/cli-core.ts` from 28,610 to 28,336 physical lines (-274) and changes total
1166
+ production TypeScript from 78,388 to 79,308 (+920).
1167
+ The overhead is reported rather than hidden by compact formatting: it is the
1168
+ explicit typed observation handoff needed to keep Store and terminal reads in
1169
+ the composition root while making each authority stage independently bounded
1170
+ and testable. The production graph has 78 modules, 307 static import edges, and
1171
+ zero cycles. Targeted ownership is split honestly across
1172
+ `terminal-action-projection` and `terminal-authority-policy` with five retained
1173
+ integration witnesses each; the pre-existing binding-authority and
1174
+ dispatch-policy owners are also reduced to five witnesses each.
1175
+
1176
+ The old 1,162-line terminal projection callback is now a sequence of bounded
1177
+ stages. The final TypeScript AST spans are binding observation 298 lines,
1178
+ verified-empty authority 97, deferred-source authority 77, deferred action
1179
+ authority 106, handoff authority 139, terminal-scoped approval authority 96,
1180
+ authority composition 23, public rendering 256, and the outer list projection
1181
+ 144.
1182
+ No touched or extracted function reaches the hard 500-line boundary. The
1183
+ TypeScript AST approximate-complexity maximum across the touched and extracted
1184
+ production functions is 48, below the hard approximate-complexity-50 gate.
1185
+ Binding observation, deferred action authority, handoff authority, and
1186
+ public rendering are reviewed exceptions to the preferred 100-line and/or
1187
+ complexity-20 targets: further splitting them would duplicate the staged facts
1188
+ or move Store reads across a safety short circuit.
1189
+
1190
+ The composition root continues to own deferred-transfer, managed-Session,
1191
+ managed-Turn, transition, and dispatch-ledger reads; terminal/process
1192
+ collection; Codex inventory and identity observation; terminal-scoped approval
1193
+ boundary I/O; runtime logging; and the final public JSON shell. The staged calls
1194
+ preserve the old left-to-right read order. In particular, a Session-authority
1195
+ conflict never reads the dispatch owner's Session id, a genuine mismatch keeps
1196
+ the old two `sessionIdForConversation` calls, and every unresolved-transition
1197
+ read remains behind the same verified-empty, reconcile, external-handoff, or
1198
+ active-Turn preconditions. Listed tokens remain stale snapshots; mutation paths
1199
+ repeat fresh observation and invoke the same canonical send reducer before a
1200
+ side effect. Blocking Turn statuses do not inspect callback delivery, current
1201
+ approval actions are retargeted before reading the live terminal approval
1202
+ state, and stored native rollout fields remain unread until all earlier Turn
1203
+ identity exits have passed.
1204
+
1205
+ Direct fast proofs compare the old and new `JSON.stringify` action bytes and
1206
+ key order, verified-empty and deferred v2/v5 token hashes, active-Turn handoff
1207
+ hashes, conflict precedence with lazy managed-Turn facts, selector alias and
1208
+ process-incarnation behavior, and list-snapshot versus fresh-mutation send
1209
+ decisions. Getter-backed fixtures make the three lazy-read fences executable,
1210
+ and ordinary fixtures compare canonical results with the previous decisions.
1211
+ Existing binding-authority, dispatch-policy, list-renderer, and
1212
+ terminal-send boundary witnesses remain in place; this slice changes no action
1213
+ name, action order, error string, token field order, Store format, or public
1214
+ contract version.
1215
+ ## Native-thread lifecycle crash recovery and reconciliation
1216
+
1217
+ The third native-thread lifecycle slice moves one crash-recovery state machine
1218
+ from `recoverLifecycleFenceBeforeMutation` through fail-closed lifecycle-ledger
1219
+ reconciliation into `native-thread-lifecycle-recovery-service.ts`. It includes
1220
+ human-observed ledger rebuild, prepared rollback, verified roll-forward,
1221
+ committed/aborted replay, possible-input quarantine, and operator-authorized
1222
+ Claude/Codex identity reconciliation. Ordinary deferred foreground-dispatch
1223
+ recovery remains a core-owned state machine behind one scoped call. Verified
1224
+ empty recovery, observed external-handoff send/adoption, lifecycle mutation,
1225
+ monitor/callback orchestration, and public presentation remain outside this
1226
+ service.
1227
+
1228
+ Measured against exact head `29446b0649555c4bfca8ee23a4f2f0d9523c9fcf`,
1229
+ the slice reduces `src/cli-core.ts` from 27,319 to 26,095 physical lines
1230
+ (-1,224, -4.48%) and changes total production TypeScript from 80,554 to
1231
+ 81,427 (+873, +1.08%). The transparent typed-boundary overhead is 71.3% of
1232
+ the core movement. It consists of the four port groups, direct recording
1233
+ surface, fresh-route composition, normalized probe facts, and the core-side
1234
+ raw terminal adapter; issue #126 does not impose a zero-production-growth
1235
+ target. The production graph has 82 modules, 339 static import edges, and zero
1236
+ cycles.
1237
+
1238
+ The recovery service is 1,834 physical lines and its infrastructure adapter is
1239
+ 263 lines. The largest function remains the 211-line/c32 reconciliation reducer
1240
+ and the highest conservative approximate complexity is c37 in the 186-line
1241
+ manual Codex probe reducer. Every function is below the hard 500 LOC/c50 gates.
1242
+ The reviewed exceptions to the default 100 LOC/c20 target are:
1243
+
1244
+ - reconciliation (211/c32), whose ordered status and catch precedence is one
1245
+ directly recorded state machine;
1246
+ - prepared human-observed handoff recovery (116/c21), which keeps its source
1247
+ CAS, identity observation, rollback, and verified checkpoint together;
1248
+ - stored ledger/transition comparison (66/c36) and live-terminal/adapter
1249
+ comparison (68/c25), split only at the side-effect boundary so boolean
1250
+ short-circuit order is unchanged;
1251
+ - verified after-binding revalidation (143/c36), uncertain manual settlement
1252
+ (140/c15), Claude stable identity probing (115/c27), and Codex stable identity
1253
+ probing (186/c37), whose polling and exact-incarnation precedence remain
1254
+ visible as cohesive reducers;
1255
+ - the core-side probe adapter factory (110/c1), which keeps its closed raw
1256
+ capability, bridge preparation, normalization, and ordered observations in
1257
+ one infrastructure boundary while each returned method remains short.
1258
+
1259
+ The service imports no CLI core, filesystem/path API, raw lock, raw repository,
1260
+ raw JSON persistence, public presenter, `TerminalAgentAdapter`, terminal-agent
1261
+ bridge type or value, `any`, or `Record<..., any>`. It contains no raw screen
1262
+ excerpt or composer grammar. Its public request contains only fresh terminal
1263
+ facts; Store directory and path authority are absent. The four typed port
1264
+ groups are scoped authority, persistence, terminal/process evidence, and
1265
+ clock/sleep. Core retains terminal then writer lock acquisition, the ordinary
1266
+ deferred-recovery implementation, raw transition/Session/ledger repositories,
1267
+ terminal bridge and process probes, Store/path canonicalization, CLI logging,
1268
+ and JSON output. The core-side recovery adapter exposes only normalized
1269
+ status/probe facts and closed plan steps through separately scoped
1270
+ `probeThreadLifecycle`, `planThreadLifecycle`, and `observeThreadLifecycle`
1271
+ ports; the full terminal adapter is never returned to business code. Before
1272
+ either service entry, core projects the fresh resolved terminal into a new
1273
+ runtime object with exactly `conversationId`, `agent`, `pid`, and
1274
+ `terminalControl`; the broad resolved terminal remains captured only by the
1275
+ core ports closure.
1276
+
1277
+ Every authority, repository, process, and terminal port call receives the same
1278
+ active `CanonicalMutationScopes` and `CanonicalMutationResources`. Before the
1279
+ service is entered, core authenticates both scopes, resolves the terminal again
1280
+ after lock acquisition, proves the captured and fresh terminal/process
1281
+ incarnations match, and captures the canonical writer Store. The shared native
1282
+ thread resource adapter repeats those checks for every port call, including
1283
+ reads and probes as well as transition, Session, and ledger writes. Thus a
1284
+ request cannot retain free terminal-control, Store, cwd, or path authority, and
1285
+ released, cross-transaction, wrong-route, or wrong-Store capabilities fail
1286
+ before business I/O. Lifecycle ledger construction remains in the core adapter;
1287
+ rebuild phases replace their control with the post-lock fresh route and every
1288
+ persisted ledger Store must equal the canonical writer resource.
1289
+
1290
+ ### Recovery order and durable checkpoints
1291
+
1292
+ The extraction preserves these existing sequences inside the terminal ->
1293
+ writer lock scope:
1294
+
1295
+ | Recovery path | Exact effect order retained |
1296
+ | --- | --- |
1297
+ | Fence entry | authenticate/fresh terminal -> ordinary deferred recovery -> ledger load -> optional rebuild -> lifecycle classification -> reconcile |
1298
+ | Missing/resolved human-handoff ledger | transition list -> typed ledger build -> complete transition/terminal/adapter validation -> compare-and-save rebuild ledger -> reload |
1299
+ | Live automatic dispatcher | dispatcher process probe -> unchanged ledger; no Store transition read, probe bridge, or write |
1300
+ | Wrong Store / unavailable transition | Store comparison or transition load -> fail-closed uncertain-ledger CAS -> reload; a failed fail-closed CAS returns the original ledger |
1301
+ | Prepared, zero possible input | ledger/terminal/adapter validation -> exact before-owner proof -> target/source reads and source restoration -> aborted transition CAS -> resolved-ledger CAS -> reload |
1302
+ | Verified | after-binding/live identity verification -> exact target-owner proof -> Session commit -> committed transition CAS -> resolved-with-binding ledger CAS -> reload |
1303
+ | Committed / aborted replay | live verification and owner/target assertion or before-owner/source restoration -> resolved-ledger CAS -> reload |
1304
+ | Dispatching/submitted automatic recovery | uncertain transition CAS -> source quarantine Session CAS -> uncertain-ledger CAS -> reload |
1305
+ | Operator-authorized uncertain recovery | exact stable manual probe -> process/rollout assertion -> before rollback, or target verification -> target-owner proof -> Session commit -> committed transition CAS -> resolved-ledger CAS -> reload |
1306
+ | Inner recovery failure | source quarantine attempt -> fail-closed uncertain-ledger CAS -> reload/original ledger |
1307
+
1308
+ Bridge construction remains at the old probe checkpoints: after the verified
1309
+ human-handoff early return, after Claude prepare-time process validation, and
1310
+ after the Codex-agent guard but before root/runtime observation. Raw terminal
1311
+ status, clear-line, `/status` input, agents rows, resolver, and process-birth
1312
+ operations stay in core or its recovery adapter. A Claude sample performs
1313
+ agents-row load then lifecycle observation inside one scoped call, and business
1314
+ recovery performs terminal status only afterward. A Codex post-`/status` sample
1315
+ performs one raw status call and only then raw-screen lifecycle observation
1316
+ inside the same scoped adapter call; it returns normalized status plus the
1317
+ optional observation. No raw screen or composer decision crosses into the
1318
+ service. No new durable checkpoint or retry permission is introduced. Manual
1319
+ terminal-close JSON is still emitted by core before the writer and terminal
1320
+ scopes are released.
1321
+
1322
+ The direct fast recording table fixes five precedence witnesses: live
1323
+ dispatcher short-circuit; wrong-Store fail closed before transition load;
1324
+ prepared rollback; dispatching possible-input quarantine; and verified
1325
+ roll-forward. It asserts the exact transition/Session/ledger phase order, CAS
1326
+ expectations, probe-before-plan order, probe preparation point, and
1327
+ reference-equal forwarding of the same active scopes/resources on every port
1328
+ call. Direct adapter witnesses fix Claude rows -> observe and Codex status ->
1329
+ observe order, while the static boundary witness rejects bridge imports, full
1330
+ terminal-adapter capability, raw screen excerpts, or composer helpers in the
1331
+ service. A runtime-shape witness also fixes the four projected request keys and
1332
+ proves that neither `adapter` nor `legacy` survives projection. Existing
1333
+ lifecycle recovery, human handoff, no-rollout, lifecycle, and ownership
1334
+ integration witnesses remain the retained black-box boundary set.
1335
+
1336
+ ## Deferred Codex foreground application and recovery
1337
+
1338
+ This slice moves the complete deferred Codex foreground application vertical
1339
+ out of `cli-core.ts`: preparation and fresh-authority publication; source
1340
+ reservation and target preparation; dispatch begin/stage advancement;
1341
+ zero-input abort and rollback; accepted commit and resolution; uncertain
1342
+ settlement; and prepared, accepted, and committed crash recovery. The typed
1343
+ implementation is split across the application, preparation, and recovery
1344
+ services plus their CLI adapters, a data-only boundary module, and the
1345
+ invocation-scoped repository capability. Observed handoff, native-thread
1346
+ lifecycle recovery, ordinary dispatch, monitor/callback behavior, public
1347
+ presentation, and raw terminal I/O remain outside this vertical.
1348
+
1349
+ Measured against exact head
1350
+ `257950022ea40e343808ef68c903c6f874497a09`, the slice reduces
1351
+ `src/cli-core.ts` from 26,095 to 23,124 physical lines (-2,971, -11.39%) and
1352
+ changes total production TypeScript from 81,427 to 84,241 (+2,814, +3.46%).
1353
+ Typed production overhead is 94.7% of core movement, leaving 157 lines of
1354
+ positive movement margin. The production graph has 90 modules, 417 static
1355
+ import edges, and zero cycles.
1356
+
1357
+ Across the eight new production modules, the TypeScript AST inventory contains
1358
+ 219 functions. No function reaches the default 100 LOC/c20 review threshold;
1359
+ the maxima are 92 LOC and c19. Consequently there is no 500 LOC/c50 hard-gate
1360
+ exception. Application and preparation each expose three typed port groups;
1361
+ recovery exposes four. No service imports CLI core, Node filesystem/process
1362
+ APIs, raw JSON/lock helpers, a presenter, `ResolvedTerminalConversation`,
1363
+ `TerminalAgentAdapter`, or the concrete capability adapter. The service-side
1364
+ repository scope is a narrow interface in `deferred-foreground-boundary.ts`;
1365
+ its implementation is module-private and can only be obtained through the
1366
+ production terminal/writer or terminal/writer/state binders.
1367
+
1368
+ The preparation request receives a projected terminal object with exactly
1369
+ `conversationId`, `agent`, `pid`, optional `workspace`, `target`, `resourceKey`,
1370
+ optional endpoint evidence, and `canonicalEndpoint`. The returned application
1371
+ boundary contains only those terminal facts and immutable transfer/session,
1372
+ process-incarnation, dispatch-snapshot, rollout-authority, and CAS facts. The
1373
+ resolved terminal, concrete control, adapter, legacy marker, Store directory,
1374
+ Turn paths, and terminal transport methods remain captured in CLI adapter
1375
+ closures. Runtime `Object.keys` witnesses fix the request, terminal-facts, and
1376
+ boundary shapes and reject `adapter` or `terminalControl` leakage. A stable
1377
+ data-only projection carries the source-reserved and target-prepared revisions
1378
+ and binding tokens through verification, dispatch, commit, and resolution;
1379
+ the associated broad terminal remains only in the CLI adapter.
1380
+
1381
+ The capability binder authenticates one active terminal -> Store writer ->
1382
+ optional Turn state transaction before repository use. Terminal incarnation
1383
+ and resource key, absolute canonical Store key/value, `state.json` membership
1384
+ under that Store, matching `events.ndjson`, and state resource key/value are
1385
+ checked before I/O. Null, object, relative, cross-Store, wrong-key,
1386
+ wrong-process, wrong-log, and released-scope cases fail with ordinary errors
1387
+ before repository access. The concrete scope is not exported, and every scope
1388
+ method repeats the active-scope gate; retained scopes therefore expire when the
1389
+ transaction callback returns. Recovery asserts the transfer, projected
1390
+ terminal, and Turn route immediately after candidate selection and carries the
1391
+ same scope through every transfer/Session/state/ledger adapter operation. The
1392
+ PR172 lifecycle-recovery service retains ownership of its state machine and
1393
+ invokes this deferred service through its existing `recoverDeferred` port with
1394
+ the same active terminal and writer scopes/resources.
1395
+
1396
+ ### Application, CAS, and recovery order
1397
+
1398
+ The extraction preserves these Store, Turn, ledger, and terminal-evidence
1399
+ orders:
1400
+
1401
+ | Path | Exact effect and CAS order retained |
1402
+ | --- | --- |
1403
+ | Fresh preparation | process incarnation -> fresh rollout/dispatch observation -> fresh binding token -> target/transfer IDs -> canonical boundary revalidation -> exclusive ownership -> unresolved-transfer list (source identity or terminal id + endpoint; PID is not collision authority) -> request hash -> dispatcher pid -> clock -> transfer create with expected revision `null` |
1404
+ | Stale list token | process incarnation -> fresh observation -> freshly derived token -> reject; no ID generation, ownership check, list, hash, clock, or write |
1405
+ | Reservation | transfer load/authority -> fresh source verification -> source Session `bound -> transitioning` CAS -> crash point -> transfer `prepared -> source_reserved` CAS -> crash point -> transfer `source_reserved -> target_prepared` CAS with canonical Turn path -> crash point -> target Session create with expected revision `null` |
1406
+ | Dispatch evidence | target/source receipt checks -> transfer `target_prepared -> dispatch_started` CAS -> transfer `dispatch_started -> text_injected` CAS -> transfer `text_injected -> enter_dispatched` CAS; each write consumes the immediately loaded transfer revision |
1407
+ | Zero-input abort | possible-input guard first -> aborted transfer CAS -> target detach Session CAS -> source restore Session CAS -> `abort_resolved` transfer CAS. Before current-terminal recovery, every Store-authoritative aborted intent is finalized under the existing writer scope without pane/PID/cwd checks or a Turn-state lock, then transfers are listed again and filtered to the current terminal. Recovery with a prepared Turn first persists the aborted Turn receipt, then the resolved safe-to-retry ledger receipt, then performs those transfer/Session CAS writes |
1408
+ | Accepted commit | transfer/source/target reads and exact authority -> ownership -> optional same-thread source scrub Session CAS -> target accepted Session CAS -> committed transfer CAS -> source detach Session CAS -> target bind Session CAS -> exclusive-owner revalidation -> resolved transfer CAS |
1409
+ | Uncertain | authority and dispatch-start fence -> clock(s) -> one transfer CAS carrying `do_not_retry: true`; no Session rollback and no terminal retry |
1410
+ | Committed recovery | transfer/Turn/target/ledger authority -> exact acceptance observation -> accepted Turn state write -> accepted ledger write -> crash point -> source/target/transfer resolution CAS -> accepted Turn identity assertion |
1411
+ | Possible-input recovery | exact Turn/ledger authority -> one acceptance observation. Durable zero-input proof may enter the abort path; otherwise no abort or rollback is callable. A v3 pending candidate returns without replay, while older pending or observation failure reloads durable transfer authority, records uncertainty at most once, and fails closed |
1412
+
1413
+ Turn acceptance remains stronger than later Session and ledger bookkeeping. In
1414
+ accepted recovery the accepted Turn state is written before Session/transfer
1415
+ commit and the accepted ledger is written only after the resolved Session
1416
+ authority and Turn identity checks. If later bookkeeping fails, the accepted
1417
+ Turn is retained and the failure path records stalled/uncertain durable
1418
+ evidence; terminal input is never replayed. All transfer writes use explicit
1419
+ revision CAS, Session writes use the immediately observed managed-Session
1420
+ revision, target creation uses `null`, and no list token is reused as mutation
1421
+ authority: mutation always re-observes the canonical post-lock terminal and
1422
+ binding authority.
1423
+
1424
+ Four fast direct files provide the fake-port order, route, capability, and
1425
+ transition tables. They cover stale-token revalidation, request/boundary
1426
+ runtime shape, revision/clock order, possible-input never-abort behavior,
1427
+ single-observation recovery, durable reload before uncertainty, status routing,
1428
+ multiple-candidate rejection before state scope, cross-terminal abort cleanup
1429
+ before fresh matching, stable reservation-boundary CAS facts, canonical resource failures,
1430
+ non-public scope construction, and every-method released-scope failure. The
1431
+ five retained targeted integration witnesses are Codex no-rollout binding,
1432
+ dispatch authority, dispatch recovery, Session acceptance, and terminal send
1433
+ gates.
1434
+
1435
+ ## Terminal list and selector CLI facade
1436
+
1437
+ The terminal-list slice moves raw Store, managed-Session, managed-Turn,
1438
+ terminal/process, dispatch-ledger, and approval observations out of
1439
+ `cli-core.ts` into `terminal-list-cli-adapter.ts`. The adapter owns only CLI
1440
+ composition and infrastructure projection. Existing terminal action,
1441
+ authority, binding, dispatch, approval, and list-renderer modules remain the
1442
+ unique decision owners; the facade does not copy their reducers, tokens,
1443
+ identity classifiers, conflict precedence, or approval rules.
1444
+
1445
+ The exported facade has five cohesive, explicitly typed dependency groups:
1446
+ reconciliation, terminal discovery, Store observation, authority observation,
1447
+ and policy configuration. `cli-core.ts` constructs one local facade and routes
1448
+ list and selector work through it. Each facade call installs its own immutable
1449
+ dependency set in an async-local execution context. There is no mutable module
1450
+ configuration or catch-all `(...args: any[]) => any` runtime port, and the only
1451
+ runtime export from the adapter is `createTerminalListCliFacade`.
1452
+
1453
+ The direct concurrency witness runs facade A's reconciled `runList` and facade
1454
+ B's selector discovery concurrently, pauses both across independent awaits,
1455
+ then releases B before A. The observed post-await callbacks remain B's process
1456
+ source and A's idle reconciler respectively. After both Promises settle, a
1457
+ second selector call through each facade still observes its own marker. This
1458
+ locks the per-execution dependency isolation and factory-only entry boundary.
1459
+
1460
+ Selector candidate projection is the I/O-free
1461
+ `terminal-selector-projection-service.ts`; it accepts typed entry facts and one
1462
+ typed active-status policy. Process elapsed parsing has one I/O-free canonical
1463
+ owner in `terminal-process-facts.ts`; the process-source adapter compatibility
1464
+ re-exports it, while the selector service never imports the process-source
1465
+ module or its `node:child_process` edge. Managed-Session revision is read
1466
+ directly from `managed-session.ts`. Native Turn identity matching has one
1467
+ neutral implementation in `terminal-authority-policy.ts`, shared by list and
1468
+ dispatch; the dispatch module keeps only a compatibility re-export.
1469
+
1470
+ Measured against exact head `29219e4f98a6057924feb37ed05a9982e7310695`,
1471
+ the slice reduces `src/cli-core.ts` from 23,124 to 20,051 physical lines
1472
+ (-3,073) and changes production TypeScript from 84,241 to 84,907 (+666). The
1473
+ transparent typed-facade overhead is 21.67% of the core movement. The graph
1474
+ changes from 90 modules and 417 static import edges to 93 modules and 446
1475
+ edges, with zero cycles before and after. The terminal-list owner has two
1476
+ modules and four targeted integration witnesses. The preceding deferred
1477
+ foreground slice retains its eight-module ownership mapping unchanged.
1478
+
1479
+ The stacked composition preserves the deferred foreground authority,
1480
+ preparation, application, and recovery services as the only owners of their
1481
+ state machines. Its existing authority-adapter ports now call the terminal-list
1482
+ facade for managed-Turn attention, transition state, and terminal-incarnation
1483
+ blocking facts; no old inline deferred reducer was restored during the rebase.
1484
+
1485
+ The infrastructure adapter is a reviewed exception to the preferred
1486
+ 100-line/complexity-20 function target because its staged observation
1487
+ functions preserve existing Store/terminal/error priority and getter
1488
+ short-circuits. Its maximum function span is the 298-line/c43 binding
1489
+ observation, and its highest conservative approximate complexity is c44 in the
1490
+ 139-line handoff observation. Public rendering is 256/c42, terminal discovery
1491
+ entry composition is 227/c39, and scoped approval resolution is 221/c36. All
1492
+ remain below the hard 500-line/c50 boundary. The pure selector service peaks at
1493
+ 42/c11 and the process fact parser at 24/c9.
1494
+
1495
+ Direct fast proofs preserve exact selector JSON bytes and key insertion order,
1496
+ mutation-disabled lazy `available_actions` reads, approval fallback getter
1497
+ order and action target, canonical native-identity getter order, and concurrent
1498
+ facade isolation. Focused list, delegate, Session-selector, action projection,
1499
+ and process-source witnesses retain Store/terminal/error priority, the second
1500
+ Session lookup on mismatch, stale-list versus fresh-mutation separation, and
1501
+ public token bytes.
1502
+ ## Generic CLI file-lock infrastructure
1503
+
1504
+ The synchronous generic file-lock protocol now lives in
1505
+ `file-lock-cli-adapter.ts`. The adapter owns only exclusive private-file
1506
+ creation, stale-owner probing, reclaim-guard cleanup, token-matched release,
1507
+ and legacy owner decoding. Store leases, terminal routing, lifecycle ledgers,
1508
+ monitor ownership, callback policy, and deferred-transfer decisions remain in
1509
+ their existing owners.
1510
+
1511
+ The factory receives typed clock, PID, sleep, nonce, process-signal, and
1512
+ filesystem ports and retains no mutable global configuration. `cli-core.ts`
1513
+ binds its existing async-local clock/PID/sleep functions once; those functions
1514
+ still resolve the active command context at each lock call. All 28 acquisition
1515
+ call sites keep the same lock path, timeout/retry options, returned release
1516
+ closure, and surrounding `try`/`finally` order. The one stale probe and one
1517
+ owner read also retain their previous query inputs and results.
1518
+
1519
+ Against exact parent `59983e63c8e5569d27e6396dc0961433e3a6ec34`, the move
1520
+ reduces `cli-core.ts` from 20,051 to 19,901 physical lines (-150). The new
1521
+ infrastructure module is 192 lines, so production grows from 84,907 to 84,949
1522
+ (+42, below both the 50-line target and the 150-line core movement). Direct
1523
+ recording tests lock acquisition/write/close/release order, live-owner timeout
1524
+ cleanup, dead-owner reclaim-before-retry, and descriptor close-before-error
1525
+ propagation. No file-lock behavior or error precedence changes.
1526
+
1527
+ ## Ordinary terminal command CLI facade
1528
+
1529
+ The ordinary-command slice moves send, respond, approve, exclusive replay,
1530
+ and dispatch composition out of `cli-core.ts` into
1531
+ `terminal-command-cli-adapter.ts`. Cancel, renew, close, monitor, lifecycle,
1532
+ callback, and deferred-foreground state machines remain with their existing
1533
+ owners. The adapter composes the existing terminal-dispatch execution,
1534
+ application, capability, receipt, deferred-foreground, terminal-list, and
1535
+ file-lock factories; it does not introduce a second reducer or authority
1536
+ decision.
1537
+
1538
+ The only runtime export is `createTerminalCommandCliFacade`. Each invocation
1539
+ runs with an immutable dependency set in async-local context, so concurrently
1540
+ awaiting facades cannot observe one another's ports. The emitted command-facade
1541
+ declaration contains neither `any`, `Record<..., any>`, nor
1542
+ `ResolvedTerminalConversation`. Every callback has explicit parameters and
1543
+ results. `TerminalDispatchTerminal` is only a structural, CLI-infrastructure
1544
+ carrier for `conversationId`, `agent`, `pid`, and `terminalControl`; it does
1545
+ not claim to remove extra properties from the runtime object.
1546
+ `TerminalControlSendRequest` now uses a six-field
1547
+ `TerminalControlSendOptions extends Record<string, unknown>` boundary covering
1548
+ only the timeout, polling, scrollback, and Claude-home values read by dispatch.
1549
+ The structural terminal carrier and concrete deferred adapters remain
1550
+ CLI-infrastructure values, not business-service requests.
1551
+
1552
+ Every actual deferred business-service request still crosses the explicit
1553
+ `projectDeferredForegroundTerminalFacts()` literal projection. The direct
1554
+ preparation-service witness fixes the request and boundary `Object.keys`, and
1555
+ proves that neither `adapter` nor `terminalControl` crosses that boundary.
1556
+ Terminal-dispatch execution receives typed facts and ports, while dispatch
1557
+ application and capability receive authenticated routes/repositories; none of
1558
+ the three receives the concrete terminal carrier.
1559
+
1560
+ Measured against exact parent
1561
+ `921636a4a86da8d565c659bdcbb64021ac112366`, the slice reduces
1562
+ `src/cli-core.ts` from 19,901 to 16,350 physical lines (-3,551) and changes
1563
+ production TypeScript from 84,949 to 86,473 lines (+1,524). Typed production
1564
+ overhead is 42.92 percent of core movement, leaving 2,027 lines of movement
1565
+ margin. The production graph has 46 domains, 95 modules, 482 static import
1566
+ edges, and zero cycles. `cli-core.ts` retains one production importer. The
1567
+ ordinary-command owner has one module and exactly five focused integration
1568
+ witnesses.
1569
+
1570
+ The extraction preserves three critical transaction shapes. Replay validates
1571
+ ledger receipt history before active-ledger authority, validates every stored
1572
+ match (including getters and conflicting safe-abort receipts) before filtering
1573
+ retryable zero-input receipts, validates the durable log body, and presents
1574
+ inside the canonical mutation callback. Transport failure may call the
1575
+ zero-input reducer only when no text timestamp exists and the error is
1576
+ `TerminalInputNotStartedError`; every possible-input failure instead records
1577
+ uncertainty, emits `do_not_retry`, and presents the uncertain receipt. Managed
1578
+ approval holds the terminal lock across observation, reservation, key
1579
+ dispatch, durable resolution, monitor handoff, and JSON presentation. Its
1580
+ state lock is released before monitor launch as before, while a failed
1581
+ `beforeKeyDispatch` leaves the reserved uncertain marker and sends no key.
1582
+
1583
+ The following infrastructure functions are reviewed exceptions to the
1584
+ preferred 100-line/c20 target. Counts use the same conservative physical-span
1585
+ and nested-function-excluding complexity method as this document; every entry
1586
+ remains below the hard 500-line/c50 gate.
1587
+
1588
+ | Function or nested stage | LOC / approximate complexity |
1589
+ | --- | ---: |
1590
+ | `runManagedApprovalDispatch` | 486 / c2 |
1591
+ | `runRawTerminalSend` | 443 / c2 |
1592
+ | raw-send canonical mutation callback | 419 / c45 |
1593
+ | `runApprovalWithStateLock` | 393 / c30 |
1594
+ | `replayExactActiveTerminalSubmission` | 276 / c41 |
1595
+ | `runManagedSessionSend` | 265 / c21 |
1596
+ | `resolveTerminalDispatchSubmissionOwner` | 261 / c43 |
1597
+ | `prepareTerminalControlSend` | 255 / c42 |
1598
+ | `runTurnResponse` | 223 / c11 |
1599
+ | `replayExactStoredTerminalSubmission` | 188 / c22 |
1600
+ | managed-send mutation callback | 186 / c21 |
1601
+ | `runApprove` | 177 / c32 |
1602
+ | respond outer mutation callback | 164 / c1 |
1603
+ | `runTerminalConversationApprove` | 162 / c10 |
1604
+ | respond state callback | 153 / c22 |
1605
+ | `validateStoredTerminalSubmissionMatch` | 150 / c28 |
1606
+ | `createTerminalDispatchRuntime` | 148 / c4 |
1607
+ | approval `beforeKeyDispatch` callback | 132 / c31 |
1608
+ | `runTerminalControlSend` | 105 / c9 |
1609
+ | `runTerminalDispatchTransport` | 106 / c7 |
1610
+ | raw-send state callback | 103 / c4 |
1611
+
1612
+ The evidence map deliberately reuses the direct tests of the unique dispatch
1613
+ owners instead of copying their state machines into facade tests:
1614
+
1615
+ | Contract | Direct proof | Focused real-CLI proof |
1616
+ | --- | --- | --- |
1617
+ | Factory-only typed ports and await isolation | `terminal-command-cli-adapter.test.ts` fake-port trace | all five owner files exercise the bound production factory |
1618
+ | Replay receipt/log bytes, getter validation, error priority, and locked presentation | facade compiled-wiring proof; `terminal-dispatch-receipt.test.ts` exact bytes | `agent-cli-composer-replay.test.ts` exact output/log body and no second Enter |
1619
+ | Possible input never becomes zero-input retry | facade failure-wiring proof; `terminal-dispatch-application.test.ts` text-progress table; `terminal-dispatch-execution.test.ts` one-Enter table | `agent-cli-dispatch-authority.test.ts` retryable pre-input versus uncertain post-input receipts |
1620
+ | Approval uncertain reservation and terminal-lock lifetime | facade lock-wiring proof; `terminal-agent-bridge.test.ts` reservation/callback/no-key order | `agent-cli-claude-callback.test.ts` and `agent-cli-control-locks.test.ts` |
1621
+ | Native acceptance and dispatch-owner authority | execution/application fake-port tables | `agent-cli-session-acceptance.test.ts` |
1622
+ | Runtime stripping at the service boundary | `deferred-foreground-preparation-service.test.ts` exact request/boundary keys | the Session-acceptance witness traverses the same production projection |
1623
+
1624
+ The five selected focused files are composer replay, dispatch authority,
1625
+ control locks, Claude callback, and Session acceptance. They cover replay,
1626
+ send/possible-input, approval, lock order, and native acceptance without adding
1627
+ lifecycle, close, monitor, or callback ownership to this facade.
1628
+
1629
+ ## Terminal dispatch repository and recovery
1630
+
1631
+ The terminal dispatch recovery slice moves the raw ordinary-ledger repository,
1632
+ prepared and lagging crash reconciliation, verified-dead reconciliation, and
1633
+ callbackless local-completion settlement out of `cli-core.ts`. Ordinary
1634
+ send/respond/approve dispatch, deferred foreground transfer state machines,
1635
+ native lifecycle policy, monitor polling and callback transport remain in their
1636
+ existing owners. The composition root keeps the narrow callback-outbox
1637
+ preparation closure and routes the old helper names through one invocation-safe
1638
+ facade.
1639
+
1640
+ Measured against exact parent `9156a7d45c28b8d9a428fbd048c46cf2226d56aa`,
1641
+ the slice reduces `src/cli-core.ts` from 16,350 to 14,390 physical lines
1642
+ (-1,960) and changes total production TypeScript from 86,473 to 87,562 lines
1643
+ (+1,089, 55.56% of the core movement). The three-module ownership domain has five
1644
+ targeted integration witnesses. Architecture validation reports 98 production
1645
+ modules, 515 static import edges, and zero cycles.
1646
+
1647
+ The 410-line repository adapter is the sole owner of dispatch-ledger filesystem
1648
+ paths, raw bytes, legacy/canonical filenames, the dual lock set, file modes,
1649
+ directory fsync, and atomic replace. Its 321-line/c1 factory is a reviewed
1650
+ exception to the preferred 100-line function target; its largest inner
1651
+ operation is the 73-line/c18 save. The 791-line recovery service exposes exactly
1652
+ five typed port groups (`transaction`, `authority`, `evidence`, `state`, and
1653
+ `completion`), has a 47-line maximum function and c12 maximum complexity, and
1654
+ imports no Node filesystem/path API, CLI core, Store/session persistence, raw
1655
+ lock or JSON helper, `Record<..., any>`, full resolved terminal, or terminal
1656
+ adapter capability. The 1,848-line CLI transaction adapter owns path projection,
1657
+ Session/event reads, Store-writer and state locking, callback preparation, and
1658
+ legacy record validation. Its largest function is 77/c17. The reviewed
1659
+ complexity exception is the 37-line/c30 exact ledger-receipt predicate; every
1660
+ function remains below the hard 500 LOC/c50 gates, and the facade factory is
1661
+ 24/c1.
1662
+
1663
+ Repository compatibility remains fail closed. A canonical terminal acquires
1664
+ the canonical and legacy send locks in lexical order and releases them in
1665
+ reverse order through an idempotent closure. Reads reject symlinks and non-files
1666
+ without following the final path and reject simultaneous canonical/legacy
1667
+ owners. A validated legacy ledger is renamed to its canonical owner and the
1668
+ directory is synced before the next version-2 replace. Every replace creates a
1669
+ 0600 exclusive temporary file, writes the exact pretty-JSON-plus-newline bytes,
1670
+ fsyncs the file, renames, reapplies 0600, fsyncs the directory, and removes any
1671
+ temporary artifact. Receipt history remains append-preserving across migration
1672
+ and settlement; a failed conversation/message CAS leaves the original bytes
1673
+ unchanged. Restoring a prior durable generation replaces the top-level document
1674
+ while retaining its append-only receipt history, so the abandoned generation
1675
+ cannot leak a self-referential `previous_generation_id`.
1676
+
1677
+ Recovery retains `terminal dispatch lock -> Store writer lease -> Turn state
1678
+ lock`. Prepared keep decisions do not sample the clock, and owner mismatch
1679
+ returns before Store/binding projection. Prepared recovery resolves only when
1680
+ durable evidence proves zero input was possible; text-injected,
1681
+ Enter-dispatched, submitted, accepted, and uncertain proof is reconciled
1682
+ without terminal replay. Fresh verified-dead recovery applies the basic ledger
1683
+ fence first, then short-circuits state, Store, full ledger, receipt, and
1684
+ acceptance observations in order. It reuses or observes one process-death proof
1685
+ and lets a newly observed durable completion win before writing stall evidence.
1686
+ Stall persistence remains `death event -> stalled event -> crash fence -> state
1687
+ -> runtime log`. Completion preparation releases the state lock while retaining
1688
+ terminal and writer ownership; a failed release is retried by the enclosing
1689
+ transaction cleanup before writer and terminal release. Local completion
1690
+ verifies the exact claim, detected event,
1691
+ message event, accepted submission, and ledger before `resolve ledger -> settled
1692
+ event`. Reload, projection, and callback errors still unwind state, writer, then
1693
+ terminal ownership.
1694
+
1695
+ Direct fast evidence fixes legacy promotion, canonical bytes and 0600 mode,
1696
+ receipt preservation, canonical/legacy conflict rejection, dangling-symlink
1697
+ rejection, dual-lock cleanup, failed-CAS byte identity, verified-dead completion
1698
+ and stall write order, callbackless settlement idempotence, zero-input-only
1699
+ prepared resolution, no replay surface, five-port boundary hygiene, and all-lock
1700
+ cleanup after a locked reload failure. It also fixes replacement-document
1701
+ Object keys and bytes, lazy-observation call counts and reason strings, and a
1702
+ release-error retry. Existing dispatch recovery, receipt
1703
+ fence, control-lock, monitor recovery, and human-handoff suites remain the
1704
+ black-box boundary set.
1705
+
1706
+ ## Terminal runtime and provider CLI composition
1707
+
1708
+ The runtime/provider slice moves command-scoped terminal-control provider
1709
+ selection, process-source selection, Codex/Claude adapter registry composition,
1710
+ bridge construction, Claude `agents --json --all` observation, running-agent
1711
+ version observation, and provider-owned takeover decoding into
1712
+ `terminal-runtime-cli-adapter.ts`. Exact-bound Codex completion policy, native
1713
+ identity resolution and assertion, Store-backed runtime identity, durable
1714
+ request construction, endpoint refinement, legacy migration, acceptance,
1715
+ dispatch, monitor, lifecycle, callback, and deferred foreground work remain in
1716
+ their existing owners and enter this adapter only through typed callbacks.
1717
+
1718
+ The factory receives five invocation-local groups: options, async-local command
1719
+ dependencies, completion callbacks, opaque identity callbacks, and workspace
1720
+ validation. It retains no mutable global provider or dependency state. Bridge
1721
+ defaults are still evaluated lazily in provider -> agent registry -> process
1722
+ source order. Injected providers and sources still win before static fixtures;
1723
+ the original option truthiness rules are unchanged. Concrete raw JSON parsing
1724
+ and `spawnSync` calls stay in this CLI infrastructure adapter rather than
1725
+ crossing a service boundary. Claude keeps the exact
1726
+ `agents --json --all` argv, status/error handling, invalid-JSON diagnostics,
1727
+ required-observation refusal, and row normalization order. Running-version
1728
+ observation keeps injected -> per-PID fixture -> per-agent fixture -> exact
1729
+ `lsof` executable-path evidence priority.
1730
+
1731
+ Against exact parent `779e2e5d15ff18c5b8d0c5bbb7493e601f06cfb3`, the
1732
+ required top runtime movement plus the independent agent-version adapter reduce
1733
+ `src/cli-core.ts` from 14,390 to 13,935 physical lines (-455). Production
1734
+ TypeScript changes from 87,562 to 87,718 lines (+156, 34.29 percent of the core
1735
+ reduction), meeting the preferred overhead target and remaining below the 518
1736
+ lines of gross responsibility movement. The graph has 48 domains, 99 modules,
1737
+ 526 edges, and zero cycles. The generated adapter declaration has no `any`,
1738
+ `Record<..., any>`, or `ResolvedTerminalConversation`; the module imports no
1739
+ Store, identity-authority, acceptance, dispatch, monitor, lifecycle, callback,
1740
+ or deferred module. Every adapter function is below 100 physical lines and
1741
+ approximate complexity 20; the maxima are 47 lines and c15.
1742
+
1743
+ Direct fast proofs lock factory laziness and instance isolation, exact provider
1744
+ -> registry -> process-source getter order, injection/static truthiness,
1745
+ exact-bound completion short-circuiting, Claude subprocess argv and fail-closed
1746
+ errors, agent-version precedence, and tmux/Herdr takeover decoding. Its targeted
1747
+ owner selects five retained CLI witnesses spanning Claude native inspection,
1748
+ facade import laziness, lifecycle versioning, send gating, and native Session
1749
+ acceptance. The 8,997-line Codex no-rollout fixture is deliberately excluded:
1750
+ these narrower witnesses cover this composition boundary without selecting the
1751
+ integration tier's dominant runtime for every adapter edit.
1752
+
1753
+ ## Native acceptance and managed Turn application
1754
+
1755
+ The acceptance slice moves native acceptance composition, virgin Codex
1756
+ post-submission binding recovery, monitor acceptance reconciliation, uncertain
1757
+ settlement, managed Session identity refinement, managed Turn queries, and
1758
+ managed Turn construction out of `cli-core.ts`. The new CLI adapter composes the
1759
+ existing `TerminalDispatchExecutionService`, terminal-submission detectors,
1760
+ receipt merger, deferred-foreground recovery owner, and terminal-dispatch
1761
+ repository/recovery facades. Ordinary ledger locking, reads, and writes are
1762
+ projected directly from `terminalDispatchRepository`; prepared reconciliation
1763
+ and binding proof are projected directly from `terminalDispatchRecovery`. It
1764
+ obtains the command-local terminal runtime lazily and uses its existing Claude
1765
+ row and bridge ports instead of rebuilding provider composition. It does not
1766
+ copy acceptance scanning, receipt ranking,
1767
+ ledger repair, authority tokens, or deferred-transfer reducers.
1768
+
1769
+ `TerminalAcceptanceApplicationService` owns the ordered
1770
+ recover -> detect -> optional second recovery -> second detect -> exact draft
1771
+ proof -> commit decision. `ManagedTurnRecoveryService` owns the monotonic virgin
1772
+ binding sequence: validate literal facts, resolve the exact identity, require
1773
+ the canonical acceptance detector when neither side was committed, prove
1774
+ exclusive ownership, commit Session identity, commit Turn identity, then
1775
+ revalidate the Turn. Both services receive at most five typed port groups and
1776
+ import no filesystem, path, Store/session repository, raw lock, raw JSON,
1777
+ `Record<..., any>`, `ResolvedTerminalConversation`, or terminal adapter
1778
+ instances.
1779
+
1780
+ The CLI adapter retains the concrete resource discipline. Virgin recovery is
1781
+ terminal lock -> Store writer -> Turn state lock; monitor acceptance already
1782
+ holds the same terminal lock and therefore enters only writer -> state. Final
1783
+ acceptance writes Turn state before best-effort ledger and event bookkeeping,
1784
+ while uncertainty retains the legacy ledger -> Turn state -> event durable
1785
+ order. An `enter_dispatched` Turn with possible input never enters a replay or
1786
+ zero-input abort path: absent acceptance stays pending unless the exact draft
1787
+ is still present, in which case it becomes durable `not_accepted` with
1788
+ `do_not_retry` authority.
1789
+
1790
+ Managed Turn construction retains the original insertion order and exact
1791
+ storage-path suffix, binding id/generation, native identity, endpoint evidence,
1792
+ message metadata, and optional deferred transfer id. The public adapter
1793
+ declaration contains neither `any`, `Record<..., any>`, nor
1794
+ `ResolvedTerminalConversation`; deferred operations cross only the structural
1795
+ `TerminalDispatchTerminal` carrier.
1796
+
1797
+ Measured against exact parent
1798
+ `6318a3bbff2ec0aa10baa3ada8313d1eed038bd2`, this slice reduces
1799
+ `src/cli-core.ts` from 13,935 to 12,721 physical lines (-1,214) and changes
1800
+ production TypeScript from 87,718 to 88,732 lines (+1,014). The typed overhead
1801
+ is 83.53 percent of core movement and remains 200 lines below the hard
1802
+ movement ceiling; it does not meet the preferred 450-line overhead target, so
1803
+ that tradeoff is explicit. The production graph has 49 domains, 102 modules,
1804
+ 559 static import edges, and zero cycles. `cli-core.ts` retains one production
1805
+ importer, and the acceptance owner retains exactly five integration witnesses.
1806
+
1807
+ All extracted functions remain below the hard 500-line/c50 gates. The two
1808
+ reviewed preferred-target exceptions use the documented nested-function-
1809
+ excluding complexity method: `#recoverVirginLocked` is 104 physical lines/c2,
1810
+ and `attachManagedTurn` is 75 lines/c23. Every business-service function stays
1811
+ below 100 lines and c20.
1812
+
1813
+ The direct evidence fixes the critical boundaries:
1814
+
1815
+ | Contract | Direct proof | Focused real-CLI proof |
1816
+ | --- | --- | --- |
1817
+ | Virgin acceptance order and split CAS recovery | recording ports prove detector -> ownership -> Session -> Turn -> revalidation and both one-sided crash continuations | no-rollout binding and Session-acceptance shards |
1818
+ | Possible input never replays | application table proves pending without exact draft and `not_accepted` only with exact draft | Session acceptance and terminal-send gates |
1819
+ | Terminal -> writer -> state and durable write order | compiled facade wiring checks both lock stacks plus accepted and uncertain writes | monitor-recovery and no-rollout binding |
1820
+ | Managed Turn JSON shape | direct exact key/order/binding/message projection | handoff and Session-acceptance shards |
1821
+ | Data-only service boundary | declaration/source prohibition test and at-most-five-group typed ports | all five owner witnesses traverse the production facade |
1822
+
1823
+ The five focused witnesses are Codex no-rollout binding, human handoff,
1824
+ monitor recovery, Session acceptance, and terminal send gates. Together they
1825
+ cover virgin and deferred acceptance, process drift/quarantine, crash recovery,
1826
+ uncertainty, Turn construction, and no-replay behavior without assigning
1827
+ lifecycle, callback, or generic ledger-recovery ownership to this slice.
1828
+
1829
+ ## Terminal identity authority CLI composition
1830
+
1831
+ The identity-authority slice moves the exact 37-function inventory for terminal
1832
+ routing, process-incarnation and verified-dead observation, managed Session
1833
+ logical/native identity, Codex companion and pre-materialization fences,
1834
+ binding selection/conflict/materialization/reattach, and verified-empty deferred
1835
+ authority observation out of `cli-core.ts`. It deliberately leaves submission
1836
+ acceptance refinement/persistence/quarantine, current-native-identity polling,
1837
+ managed Turn creation, deferred detach/adoption state machines, repository,
1838
+ monitor, callback, and lifecycle mutation in their existing owners.
1839
+
1840
+ Against exact parent `918812c5b541d5586595c4ea793df370f538d3e4`,
1841
+ `src/cli-core.ts` falls from 12,721 to 11,468 physical lines (-1,253). Total
1842
+ production TypeScript changes from 88,732 to 89,156 (+424, 33.84 percent of the
1843
+ core movement), below the preferred 450-line overhead target. Architecture
1844
+ validation reports 50 domains, 104 production modules, 589 static import edges,
1845
+ and zero cycles. The factory has four explicit invocation-scoped groups
1846
+ (`runtime`, `store`, `authority`, and `environment`) and exports no singleton or
1847
+ mutable process-global runtime. The composition root projects provider ports
1848
+ directly from `terminalRuntime(options)` and acceptance-owned identity/Session
1849
+ ports directly from `terminalAcceptanceCliFacade`; it adds no interim owner.
1850
+
1851
+ The 78-line data-only service receives only projected native identity, process
1852
+ incarnation, companion, revision, status, and binding-token facts. It imports no
1853
+ filesystem/path/process-source, Store, managed Session, resolved terminal, raw
1854
+ JSON, lock, or `Record<..., any>` API. It owns only the moved exact-lifecycle
1855
+ fallback, deterministic companion uniqueness, and verified-empty snapshot
1856
+ comparison. The 1,599-line CLI adapter retains provider/process observation,
1857
+ Store reads, one managed-Session CAS reattach write, and explicit terminal
1858
+ projection. It reuses `terminal-binding-authority`,
1859
+ `terminal-authority-policy`, `terminal-dispatch-execution`, action projection,
1860
+ lifecycle verification, submission acceptance, verified-dead policy, and the
1861
+ runtime provider rather than copying rollout, fence, token, companion,
1862
+ status-card, or transition reducers.
1863
+
1864
+ Observation and mutation order remain fail closed. Exact bound-process proof
1865
+ short-circuits envelope, binding, then accepted-submission evidence before
1866
+ consulting the complete process inventory. Stored status-card identity remains
1867
+ preferred only under the committed companion/predecessor fence. Codex process
1868
+ birth lookup stays lazy, and Claude still rejects a missing process UUID before
1869
+ any fallback. Raw reattach performs exclusive-ownership observation, reloads
1870
+ the exact Session, revalidates revision plus binding token, then writes one
1871
+ generation-incremented Session CAS. Verified-empty handoff checks the initial
1872
+ snapshot, process incarnation, absent native identity, terminal status and
1873
+ dispatch readiness, then reloads and revalidates the Session before transition
1874
+ and composer gates. No new lock or durable-file order is introduced.
1875
+
1876
+ Every new function meets the preferred limits: the maximum adapter span is 95
1877
+ lines and the conservative maximum approximate complexity is c17; the service
1878
+ is smaller. Direct fast proofs cover malformed/fail-closed facts, deterministic
1879
+ companion selection, lazy process-birth lookup, parallel async-execution
1880
+ isolation, the four-group factory boundary, and service infrastructure hygiene.
1881
+ Five retained focused witnesses cover no-rollout/status-card binding, observed
1882
+ handoff/verified-empty authority, native lifecycle identity, Session acceptance,
1883
+ and terminal-send gates. The remaining exact-bound completion detector and
1884
+ requirement predicate stay with completion/recovery composition; endpoint
1885
+ refinement, Store-backed runtime identity, durable request construction, and
1886
+ legacy identity migration remain a later minimal identity-facade prerequisite
1887
+ rather than being duplicated here.
1888
+
1889
+ ## Terminal runtime prerequisites and exact completion authority
1890
+
1891
+ The follow-up prerequisite slice closes that deliberately deferred inventory.
1892
+ The single exact-bound Codex completion detector and requirement predicate now
1893
+ live in `terminal-dispatch-completion-cli-adapter.ts`; neither the raw dispatch
1894
+ repository nor recovery adapter imports it. The detector retains
1895
+ accepted-submission -> exact-required -> Codex-source -> exact-anchor -> bound
1896
+ rollout detection order, while its synthetic-acceptance switch is read lazily
1897
+ from the invocation-local CLI environment. Exact completion still uses the one
1898
+ `detectCodexBoundRolloutCompletion` implementation and preserves request-hash
1899
+ fallback, byte identity, diagnostics, pending behavior, and completion metadata.
1900
+
1901
+ Endpoint refinement, Store-backed runtime identity, durable request projection,
1902
+ and legacy terminal-agent identity migration are now methods of the existing
1903
+ identity facade. The earlier temporary `runtimeIdentity` and `durableRequest`
1904
+ callback ports are gone. A fifth typed completion group supplies only the exact
1905
+ requirement predicate. Runtime identity still checks binding id, generation,
1906
+ native thread, PID, terminal incarnation, and committed Codex companion fences
1907
+ before expanding its authority. Durable requests continue to prefer takeover
1908
+ request text and metadata. Endpoint refinement associates and saves only
1909
+ canonical evidence for the same terminal incarnation.
1910
+
1911
+ Legacy migration is split into observation, locked persistence, and reporting
1912
+ functions. Only provider/process observation is downgraded to a warning. The
1913
+ state lock still encloses reload, revalidation, and save; every path releases it
1914
+ in `finally`. A successful save is followed, outside that lock, by durable event
1915
+ append and then runtime logging. Save and event failures propagate. The runtime
1916
+ facade also owns Codex Session-provider selection and active-Session terminal
1917
+ attachment, preserving injected-provider and injected-adapter precedence,
1918
+ fixture truthiness and JSON parsing, production Store fallback, and the original
1919
+ provider/process-source/bridge construction counts.
1920
+
1921
+ Against exact parent `6c83f9efe5b3201c584db3ad2b50cd9e120310ad`,
1922
+ `src/cli-core.ts` falls from 11,468 to 11,066 physical lines (-402). Production
1923
+ TypeScript changes from 89,156 to 89,264 lines (+108, 26.87 percent of the core
1924
+ reduction), below the preferred 160-line overhead target and the 240-line hard
1925
+ cap. Architecture validation reports 51 domains, 105 production modules, 596
1926
+ static import edges, and zero cycles. The three changed facade declarations
1927
+ contain no `any`, `Record<..., any>`, or `ResolvedTerminalConversation`. New
1928
+ functions are below 55 physical lines and approximate c20; the expanded identity
1929
+ facade retains its pre-existing 95-line/c17 maxima, below both hard limits.
1930
+
1931
+ Direct fast proofs cover dynamic synthetic environment lookup; accepted, source,
1932
+ anchor, and real byte-detector order; exact binding/generation/thread/PID/
1933
+ incarnation and companion fences; takeover-first durable requests; canonical
1934
+ endpoint save; observation-only warning behavior; lock/reload/save/unlock/event/
1935
+ log order; save and event error propagation; provider injection, fixture
1936
+ truthiness, JSON validation, and active provider/source/bridge call counts. Four
1937
+ targeted integration witnesses retain exact monitor recovery, Session acceptance,
1938
+ terminal send gates, and import-time facade wiring.
1939
+
1940
+ ## Native lifecycle context, listing, and inspection CLI composition
1941
+
1942
+ The native-lifecycle Vertical A slice moves the exact 21-function inventory for
1943
+ binding tokens, lifecycle terminal resolution, query-port composition,
1944
+ workspace and exclusive-ownership observation, current lifecycle snapshots,
1945
+ resumable-thread listing, and the closed native status inspection out of
1946
+ `cli-core.ts`. It also moves terminal Store-authority and orphan projections
1947
+ behind the typed dispatch-recovery facade and keeps Codex latent-clear parsing,
1948
+ composer checks, and candidate-provider precedence in one command-scoped CLI
1949
+ adapter. Native new/resume/reconcile transition, recovery, verification,
1950
+ settlement, deferred handoff, acceptance, callback, and monitor state machines
1951
+ remain in their existing owners.
1952
+
1953
+ Against exact parent `81feac294d5a62ea8309c6e96a66c042ebf239b8`,
1954
+ `src/cli-core.ts` falls from 11,066 to 9,868 physical lines (-1,198). Total
1955
+ production TypeScript changes from 89,264 to 89,498 (+234, 19.53 percent of the
1956
+ core movement), below the preferred 350-line and hard 550-line overhead limits.
1957
+ Architecture validation reports 51 domains, 106 production modules, 615 static
1958
+ import edges, and zero cycles. The factory has exactly five explicit,
1959
+ invocation-scoped groups (`runtime`, `identity`, `state`, `terminalList`, and
1960
+ `output`) and exports no mutable singleton. Codex lifecycle-candidate selection
1961
+ delegates directly to the runtime facade's dedicated provider factory, retaining
1962
+ the invocation-local override before production Store fallback.
1963
+
1964
+ `currentSnapshot` is the only lifecycle snapshot sequencer. It resolves the
1965
+ claimed Codex companion context through `terminalIdentityAuthority`, observes
1966
+ the current native identity through `terminalAcceptanceCliFacade`, selects or
1967
+ materializes the managed Session, refines it through the acceptance owner when
1968
+ requested, derives the logical identity and companion set through the identity
1969
+ facade, performs exclusive ownership before returning a frozen data-only
1970
+ snapshot, and never returns a terminal adapter. Vertical B requests adapter
1971
+ behavior separately through the facade, so no full terminal or executable
1972
+ capability leaks into snapshot facts.
1973
+
1974
+ Native inspection retains the exact safety boundary: the terminal lock remains
1975
+ held through output presentation; `/status` is the only accepted plan; Enter is
1976
+ dispatched exactly once; a fresh terminal, binding token, agent version,
1977
+ identity, ownership, readiness, and composer are revalidated immediately before
1978
+ Enter; two consecutive fresh observations with the same evidence fingerprint
1979
+ are required; modal dismissal revalidates the same facts immediately before its
1980
+ single key sequence; and final status plus empty-composer proof precedes output.
1981
+ Only a pre-input `NativeInspectionSubmissionError` remains safely retryable;
1982
+ possible input and every post-Enter uncertainty retain the do-not-retry result.
1983
+
1984
+ The TypeScript compiler AST inventory contains 68 functions in the new adapter;
1985
+ every one stays below the preferred limits (maximum 64 physical lines and
1986
+ approximate complexity c14). Direct evidence
1987
+ fixes canonical and legacy binding-token bytes plus double getter order,
1988
+ snapshot sequencing and exact data-only keys, one-Enter/two-observation/final-
1989
+ revalidation ordering with lock-held presentation, parallel async provider
1990
+ isolation, the five-group factory boundary, and declaration/core forbidden
1991
+ patterns. The four focused witnesses are Claude native inspection,
1992
+ native-thread lifecycle, native ownership, and the Codex no-rollout native-
1993
+ inspection cases.
1994
+
1995
+ ## Deferred foreground and observed handoff CLI facade
1996
+
1997
+ This slice moves the exact 23-function deferred/verified-empty/observed-handoff
1998
+ inventory (1,733 physical function-span lines) out of `cli-core.ts`. It owns
1999
+ safe-aborted deferred retry validation, verified-empty detach and transport
2000
+ boundaries, deferred preparation/application/recovery composition, observed
2001
+ handoff token/selector/target/adoption/transport boundaries, and nonterminal
2002
+ transfer guards. Ordinary replay, deferred reducers and repositories,
2003
+ submission acceptance, identity authority, lifecycle commands, callbacks,
2004
+ monitoring, and `runObservedHandoffClose` remain with their existing owners.
2005
+
2006
+ Against exact parent `d4cb4f108ce240a006c7eebb56e2ce5cc9d70c3f`,
2007
+ `src/cli-core.ts` falls from 9,868 to 8,119 physical lines (-1,749). Total
2008
+ production TypeScript changes from 89,498 to 89,873 (+375), meeting the
2009
+ preferred 450-line overhead target and the 1,650–1,850 core-reduction target.
2010
+ Architecture validation reports 52 domains, 109 production modules, 643 static
2011
+ import edges, zero cycles, and one retained `cli-core.ts` importer. The new
2012
+ owner has three modules and exactly five focused integration witnesses.
2013
+
2014
+ `terminal-handoff-facts.ts` and `TerminalHandoffApplicationService` own only
2015
+ neutral zero-input chronology and ordered authority-thunk evaluation. They
2016
+ import no filesystem/path API, Store or Session repository, locks, raw JSON,
2017
+ full terminal object, or `Record<..., any>`. The CLI adapter retains concrete
2018
+ terminal, Session, ledger, and path translation. Its invocation-local factory
2019
+ has exactly five groups (`runtime`, `identity`, `acceptance`, `authority`, and
2020
+ `repository`); repository includes the already-authenticated transaction-shell
2021
+ operations. `identity` is the actual `terminalIdentityAuthority` facade type,
2022
+ not a copied identity port list. Acceptance observation and Turn checks remain
2023
+ direct projections of `terminalAcceptanceCliFacade`.
2024
+
2025
+ The recovery seam is explicit for downstream lifecycle composition.
2026
+ `recoverDeferredCodexForegroundTransferBeforeMutation` is entered while the
2027
+ caller owns the exact terminal lock; it creates the canonical transaction scope
2028
+ with a no-op terminal acquisition, then acquires the Store writer lease.
2029
+ `recoverDeferredCodexForegroundTransferWhileWriterLease` accepts the resulting
2030
+ typed canonical scopes/resources, and only `withDeferredForegroundRecoveryScope`
2031
+ may add the conversation state capability. Transfers without a state path use
2032
+ the writer capability directly. Thus the retained order is terminal -> writer
2033
+ -> state, and no service reconstructs a raw lock or held-lock flag. Fresh
2034
+ handoff identity/status observation is exposed as the invocation-scoped
2035
+ `observedExternalHandoffIdentity`; known roots and companions remain the
2036
+ invocation-scoped `terminalIdentityAuthority` operation rather than being
2037
+ reconstructed here.
2038
+
2039
+ Safe retry remains fail closed. Only an exact `aborted` receipt with
2040
+ `safe_to_retry=true`, zero-input chronology, canonical state/log paths, exact
2041
+ terminal route and process incarnation, one byte-identical canonical receipt,
2042
+ matching request hash, resolved zero-input ledger, and exact restored Session
2043
+ CAS authority may retry. A possible-input stage never takes this route.
2044
+ Verified-empty detach revalidates the source snapshot and identity boundary
2045
+ before its Session CAS. Observed adoption retains the durable order `prepared
2046
+ transition -> prepared ledger -> source transitioning -> fresh observation ->
2047
+ verified transition -> verified ledger -> Session commit -> committed
2048
+ transition -> resolved ledger`. Once the durable transition is verified or
2049
+ committed, catch handling rethrows and never downgrades it to uncertain.
2050
+
2051
+ The two previously over-complex boundaries are now below the hard gate:
2052
+ safe-aborted retry is 148 lines/c9 and observed-handoff transport is 166/c28.
2053
+ The reviewed preferred-target exceptions are:
2054
+
2055
+ | Function | LOC / approximate complexity |
2056
+ | --- | ---: |
2057
+ | `maybeAdoptObservedExternalThread` | 322 / c35 |
2058
+ | `assertObservedHandoffTransportBoundary` | 166 / c28 |
2059
+ | `prepareDeferredCodexForegroundBinding` | 152 / c2 |
2060
+ | `safeAbortedDeferredRetrySourceSession` | 148 / c9 |
2061
+ | `recoverDeferredCodexForegroundTransferWhileWriterLease` | 123 / c1 |
2062
+ | `maybeDetachVerifiedEmptyCodexSource` | 104 / c9 |
2063
+
2064
+ Direct fast evidence records parallel factory/capability isolation, selector
2065
+ WeakMap isolation, getter and original-error priority, zero-input chronology,
2066
+ canonical receipt/hash/route byte ordering, monotonic handoff writes,
2067
+ verified-state non-downgrade, terminal/writer/state capability order, neutral
2068
+ service imports, and direct identity-facade composition. The five retained
2069
+ focused witnesses are Codex no-rollout binding, human handoff adoption,
2070
+ dispatch recovery, Session acceptance, and terminal-send gates. They cover the
2071
+ real verified-empty, deferred crash/retry, observed adoption, acceptance, and
2072
+ pre-input transport paths without assigning lifecycle, callback, monitor, or
2073
+ ordinary replay ownership to this facade.
2074
+
2075
+ ## Callback CLI and outbox composition facade
2076
+
2077
+ The callback CLI slice moves the exact nine-function command, transaction,
2078
+ outbox-composition, prepared-result presentation, process-delivery recording,
2079
+ and OpenClaw transport inventory out of `cli-core.ts`. The new
2080
+ `callback-cli-adapter.ts` remains raw CLI infrastructure: it delegates every
2081
+ callback transition to the existing callback outbox service, settlement,
2082
+ policy, and OpenClaw transport owners and introduces no callback state machine.
2083
+ The outbox service boundary changes only mechanically from six port groups to
2084
+ five by placing `resolveCompletionDispatch` beside the other authority ports.
2085
+
2086
+ Against exact parent `0c2d4258094f47302bc8265eb98d4a05f5b44305`,
2087
+ `src/cli-core.ts` falls from 8,119 to 7,941 physical lines (-178). Total
2088
+ production TypeScript changes from 89,873 to 89,933 lines (+60, 33.71 percent
2089
+ of the core movement), meeting the preferred 60-line overhead target and the
2090
+ 120-line hard cap. Architecture validation reports 52 domains, 110 production
2091
+ modules, 651 static import edges, and zero cycles. The 240-line adapter has four
2092
+ invocation-scoped groups (`state`, `authority`, `retry`, and `runtime`), exports
2093
+ only its factory at runtime, and uses async-local binding rather than mutable
2094
+ process-global configuration. Its declaration contains no `any`,
2095
+ `Record<..., any>`, or resolved-terminal capability.
2096
+
2097
+ The transaction chronology is unchanged. A normal callback holds writer then
2098
+ state authority through required-message validation and outbox preparation,
2099
+ releases state then writer, and only then performs delivery and presentation.
2100
+ A manual retry loads its selected Turn, takes writer authority, reloads the
2101
+ fresh Turn, applies the canonical handoff facade's nonterminal-transfer fence,
2102
+ releases the writer, and only then enters accepted recovery or retry delivery.
2103
+ Settlement keeps its existing state transaction. Delivery never holds either
2104
+ outer lock. Fresh preparation retains message-before-path/Store validation and
2105
+ the existing message/event/monitor/state/runtime-log sequence; progress,
2106
+ accepted transport, success, failure, and bounded retry remain owned by the
2107
+ unchanged outbox service and settlement. Accepted transport followed by an
2108
+ observation error still settles as delivered. Process delivery still appends
2109
+ the redacted durable event before its redacted runtime log.
2110
+
2111
+ All adapter functions stay within the preferred limits (maximum 34 physical
2112
+ lines and approximate c2, excluding nested function bodies). Direct recording
2113
+ tests prove writer/state release before presentation, fresh deferred fencing
2114
+ before retry, accepted-transport recovery, nested facade isolation, compiled
2115
+ lock and redaction order, the four-group boundary, factory-only exports, and
2116
+ declaration prohibitions. The focused real-CLI witnesses remain callback CLI,
2117
+ Claude callback, monitor approval context, and monitor recovery; they exercise
2118
+ ordinary and recovered single emission, retry, completion/approval preparation,
2119
+ transport acceptance, and monitor consumption without duplicating callback
2120
+ authority.
2121
+
2122
+ ## Native lifecycle transition application
2123
+
2124
+ This slice moves the exact 13-function native lifecycle transition inventory
2125
+ (1,344 physical function-span lines) out of `cli-core.ts`. The new
2126
+ `native-thread-transition-application.ts` owns new-thread, exact resume,
2127
+ binding reconciliation, pre-mutation lifecycle recovery, transition
2128
+ settlement composition, and terminal-ready verification. The separate
2129
+ `native-thread-lifecycle-ledger-cli-adapter.ts` owns exact lifecycle ledger CAS
2130
+ against the existing terminal-dispatch repository. Candidate query,
2131
+ verification, settlement, recovery, ledger codec, identity, acceptance, and
2132
+ Session repositories remain with their existing owners; no reducer or
2133
+ repository is copied.
2134
+
2135
+ Against exact parent `98e3566f0e15e4a6ff0ffff6efa85cdde532ee77`,
2136
+ `src/cli-core.ts` falls from 7,941 to 6,483 physical lines (-1,458). Total
2137
+ production TypeScript changes from 89,933 to 90,578 (+645), inside the hard
2138
+ 650-line overhead gate. Architecture validation reports 52 domains, 112
2139
+ production modules, 669 static import edges, zero cycles, and one retained
2140
+ `cli-core.ts` importer.
2141
+
2142
+ The invocation-local CLI bounded I/O shell composes exactly five port groups
2143
+ (`runtime`, `lifecycle`, `state`, `authority`, and `mutation`). It extends the
2144
+ existing lifecycle query facade at the CLI composition root. Observed handoff
2145
+ identity and writer-scope deferred recovery call the merged terminal-handoff
2146
+ facade directly; verified-empty detach and transport continue through that
2147
+ same facade. Recovery services receive only projected terminal facts plus scoped
2148
+ capabilities. Binding reconciliation likewise receives data-only terminal and
2149
+ status facts, while the CLI adapter retains the exact runtime terminal needed
2150
+ for subsequent infrastructure calls.
2151
+
2152
+ The mutation sequence remains terminal lock -> Store writer lease. A fresh
2153
+ terminal route is re-resolved after both capabilities are authenticated.
2154
+ Resume snapshot expiry, action fingerprint, and the complete candidate set are
2155
+ revalidated before persistence and again at their mutation-adjacent fences.
2156
+ The durable order remains prepared transition -> prepared ledger -> source
2157
+ transitioning -> dispatching transition/ledger -> input -> submitted
2158
+ transition/ledger -> verification -> verified transition -> target ownership
2159
+ -> Session commit -> committed transition -> resolved ledger -> presentation.
2160
+ Presentation therefore remains inside both locks. Only a
2161
+ `TerminalInputNotStartedError` with no text-injection observation can take the
2162
+ zero-input abort path; possible input remains uncertain, quarantined, and
2163
+ do-not-retry.
2164
+
2165
+ Compiler-AST evidence covers every function-like declaration in the new
2166
+ application. The maximum span is 445 physical lines and maximum approximate
2167
+ complexity is c44, below the hard 500/c50 gates. Direct tests record exact
2168
+ ledger load/authority/save precedence, scoped recovery resources, verified
2169
+ commit and uncertain failure order, resolved-ledger-before-presentation, and
2170
+ presentation before writer/terminal lock release. Fast and focused lifecycle,
2171
+ recovery, ownership, Codex sticky-rollout, and stale-resume witnesses retain
2172
+ the real CLI behavior.
2173
+
2174
+ ## Terminal monitor state and collateral CLI facade
2175
+
2176
+ This slice moves the exact 14-function monitor state inventory plus its
2177
+ adjacent durable state/fact preparation out of `cli-core.ts`: uncertain-dispatch
2178
+ collateral fencing and repair evidence, approval notification persistence and
2179
+ clear, activity and detector diagnostics, stalled-state notification,
2180
+ callback/local-completion recovery, startup eligibility, and monitor service
2181
+ port composition. The state facade deliberately does not absorb process-owner
2182
+ inspection, legacy-owner decisions, watchdog supervision, monitor launch, or
2183
+ launch-event presentation. Those responsibilities now belong to the subsequent
2184
+ terminal monitor supervision facade documented below, rather than
2185
+ `cli-core.ts`.
2186
+
2187
+ Against exact parent `240732e4d0a654abb4f88a01020bd93734f0d020`,
2188
+ `src/cli-core.ts` falls from 6,212 to 4,547 physical lines (-1,665). Total
2189
+ production TypeScript changes from 90,711 to 91,535 lines (+824, 49.49 percent
2190
+ of the core movement), so production overhead remains below the moved core.
2191
+ Architecture validation reports 54 domains, 115 production modules, 712 static
2192
+ import edges, zero cycles, and one retained `cli-core.ts` importer.
2193
+
2194
+ `terminal-monitor-state-reconciliation-service.ts` is data-only and has four
2195
+ port groups (`state`, `completion`, `callbacks`, and `authority`). It imports no
2196
+ filesystem/path API, raw lock, Store, Session, resolved terminal, raw JSON, or
2197
+ `Record<..., any>`. Its reconciliation order remains local completion ->
2198
+ callback recovery -> terminal-bridge filter -> legacy identity migration ->
2199
+ verified-dead settlement -> deferred recovery -> virgin acceptance recovery ->
2200
+ binding assertion -> eligibility. Handled local, callback, dead-process, and
2201
+ ineligible results stop every later observation.
2202
+
2203
+ The CLI adapter has exactly five dependency groups (`dispatch`, `acceptance`,
2204
+ `authority`, `callbacks`, and `runtime`). It calls the merged
2205
+ `callbackCliFacade`, terminal-dispatch repository/recovery,
2206
+ `terminalAcceptanceCliFacade`, `terminalHandoffCliFacade`, and identity
2207
+ authority directly; it contains no copied callback, deferred, acceptance, or
2208
+ dispatch reducer. Command-selected Store authority is retained for terminal
2209
+ send locks, while state-path-derived Store authority is retained for writer
2210
+ leases, collateral repair, and verified-dead settlement.
2211
+
2212
+ The existing monitor application still samples one poll snapshot for status
2213
+ and screen facts. Prepared recovery preserves terminal -> writer -> state lock
2214
+ order; presentation stays inside the required lock scope. Approval state is
2215
+ saved before its event and outbox preparation, duplicate/recovery reads retain
2216
+ their original order, and approval/stalled callback delivery begins only after
2217
+ the state and writer locks release. Verified-dead completion calls the canonical
2218
+ prepared callback exactly once. Superseded binding remains a non-error skip,
2219
+ the subsequent supervision facade directly classifies raw `LOCK_TIMEOUT` for
2220
+ only its handoff and singleton process locks, and state/application deferral
2221
+ retains typed `StoreLockTimeoutError` plus the existing raw
2222
+ terminal/conversation timeout path.
2223
+
2224
+ All new functions remain below the hard 500-line/c50 gates. The transparent
2225
+ preferred-limit exceptions are the 209-line/c1 service-port composition table,
2226
+ the 122-line/c47 fail-closed collateral evidence predicate, and its
2227
+ 64-line/c22 exact owner predicate; splitting either evidence predicate would
2228
+ obscure its ordered short-circuit proof. The data-only service maximum is
2229
+ 63 lines/c8. Direct fast tests record resource identity and post-scope data,
2230
+ exact port/getter/error order, optional zero/null fields, prepared completion
2231
+ byte facts, canonical facade wiring, four/five-group declarations, and
2232
+ forbidden imports. The five focused CLI witnesses are Claude callback, monitor
2233
+ approval context, monitor lifecycle, monitor recovery, and Session acceptance.
2234
+
2235
+ ## Maintenance command facade
2236
+
2237
+ The renew, raw/managed cancel, observed-handoff close, generic managed close,
2238
+ and orphan/lifecycle dispatch-close slice now lives in
2239
+ `terminal-maintenance-cli-adapter.ts`. The adapter is a bounded CLI I/O shell;
2240
+ it composes the existing terminal identity, acceptance, handoff, list, native
2241
+ lifecycle, dispatch repository, and verified-dead recovery authorities rather
2242
+ than copying a reducer, receipt, repository, or CAS transition. The subsequent
2243
+ terminal monitor supervision facade owns monitor process supervision, monitor
2244
+ reconciliation, and startup reconciliation. Maintenance routes its monitor
2245
+ start and lock-version facts through that typed facade; ordinary delegate/send
2246
+ presentation remains with its existing owner.
2247
+
2248
+ Against exact parent `8683b42c248b2310c59165ba712ecc943da3d775`,
2249
+ `src/cli-core.ts` falls from 4,547 to 3,419 physical lines (-1,128). Total
2250
+ production TypeScript changes from 91,535 to 91,961 lines (+426, 37.77 percent
2251
+ of the core movement), meeting the preferred 450-line and hard 650-line
2252
+ overhead gates. Architecture validation reports 54 domains, 116 production
2253
+ modules, 742 static import edges, zero cycles, and one retained `cli-core.ts`
2254
+ importer. The now 1,555-line adapter exposes only its factory at runtime and binds
2255
+ four invocation-scoped port groups (`runtime`, `identity`, `authority`, and
2256
+ `repository`) through async-local context. Its public option surface is
2257
+ `Readonly<Record<string, unknown>>`; its source and declaration contain no
2258
+ `any`, raw JSON codec, or resolved-terminal capability API.
2259
+
2260
+ Renew preserves selector/migration, status, verified-dead and uncertain-submit
2261
+ fences before terminal availability, then reloads under its state lock,
2262
+ revalidates binding and hard lifetime, persists state before the renewal event,
2263
+ and launches/presents only after releasing state. Raw cancel takes terminal
2264
+ then writer authority. Managed cancel preserves its distinct authorities:
2265
+ the command-selected Store keys only the terminal lock, the state-file lock is
2266
+ second, and the state-path-derived Store keys the writer lease third. It
2267
+ releases writer -> state -> terminal. Its fresh Turn, terminal incarnation,
2268
+ exact dispatch owner, bridge cancellation, event, state, and presentation order
2269
+ is unchanged, and presentation stays inside the authenticated transaction.
2270
+
2271
+ Observed-handoff close retains terminal -> writer -> state, fresh Turn and
2272
+ Session loads, native identity observation, exclusive target ownership, exact
2273
+ handoff token and dispatch-generation validation, then Turn save -> ledger
2274
+ resolve -> close event -> presentation. Generic close keeps its observed
2275
+ handoff fence and verified-dead completion-first recovery, persists the closed
2276
+ Turn before dispatch resolution and the append-only close event, and presents
2277
+ only after those effects. Orphan/lifecycle dispatch close continues to
2278
+ reconcile incarnation and deferred-transfer authority before lifecycle
2279
+ recovery or exact message-id resolution. Possible terminal input is never
2280
+ retried or downgraded.
2281
+
2282
+ Every extracted function remains below the hard 500/c50 gates. The cohesive
2283
+ CLI-shell exceptions to the preferred 100/c20 target are:
2284
+
2285
+ | Function or nested transaction | LOC / approximate complexity |
2286
+ | --- | ---: |
2287
+ | `runClose` | 264 / c8 |
2288
+ | generic close fresh-state transaction | 205 / c24 |
2289
+ | `runRenew` | 192 / c32 |
2290
+ | dispatch-close transaction | 184 / c22 |
2291
+ | observed-handoff close transaction | 176 / c29 |
2292
+ | `assertGenericCloseDoesNotBypassObservedHandoff` | 138 / c19 |
2293
+
2294
+ Direct recording tests prove concurrent factory isolation, factory-only
2295
+ exports, typed declarations, raw-cancel reverse release, managed-cancel
2296
+ terminal/state/writer order with distinct command/state Store keys, every
2297
+ acquire/release error priority, and the getter/error/persistence tables for all
2298
+ three commands. The five focused files are the maintenance facade, control
2299
+ locks, monitor lifecycle, human-handoff adoption, and native lifecycle
2300
+ recovery witnesses; together they retain real CLI cancel/close races, renew,
2301
+ verified-dead completion, observed handoff, and exact lifecycle ledger
2302
+ recovery.
2303
+
2304
+ ## Terminal monitor supervision CLI facade
2305
+
2306
+ This slice moves 16 named monitor process-supervision functions spanning 706
2307
+ physical function-span lines, plus the
2308
+ `DEFAULT_MONITOR_POLL_INTERVAL_MS` constant, out of `cli-core.ts` into
2309
+ `terminal-monitor-supervision-cli-adapter.ts`:
2310
+ `spawnDetachedTerminalMonitor`,
2311
+ `startTerminalBridgeMonitorForConversation`,
2312
+ `ensureTerminalBridgeMonitorAfterApproval`, `runReconcileMonitors`,
2313
+ `reconcileMonitors`, `latestTerminalBridgeMonitorLaunchPid`,
2314
+ `prepareTerminalBridgeMonitorReconciliation`, `runMonitor`,
2315
+ `startCallbackRetryMonitor`, `runCallbackRetryMonitor`,
2316
+ `runTerminalBridgeMonitorHandoff`, `runTerminalBridgeMonitor`,
2317
+ `runTerminalBridgeMonitorWithLock`, `activeTerminalBridgeMonitorOwner`,
2318
+ `terminalBridgeMonitorLockOwner`, and
2319
+ `tryAcquireTerminalBridgeMonitorLock`. The adapter owns only the detached
2320
+ process shell, current/legacy process-owner supervision, watchdog retries,
2321
+ singleton monitor locks, launch presentation, and CLI command routing. Monitor
2322
+ state, acceptance, callback, deferred handoff, terminal-dispatch repository,
2323
+ and terminal runtime behavior continue through their canonical facades and
2324
+ services; no reducer or persistence protocol is copied.
2325
+
2326
+ Against exact parent `cc69f520207e276a4f3a55b0a32dfeb179ea8095`,
2327
+ `src/cli-core.ts` falls from 3,419 to 2,735 physical lines (-684). Total
2328
+ production TypeScript changes from 91,961 to 92,432 lines (+471), below the
2329
+ hard 500-line overhead gate and below the moved core. Architecture validation
2330
+ reports 54 domains, 117 production modules, 750 static import edges, zero
2331
+ cycles, and one retained `cli-core.ts` importer. The adapter exposes only its
2332
+ factory at runtime. Every function remains within the preferred limits; the
2333
+ compiler-AST maximum is 59 physical lines and approximate c8.
2334
+
2335
+ The invocation-local boundary has exactly five port groups: `state`,
2336
+ `callbacks`, `authority`, `io`, and `runtime`. `state` directly reuses
2337
+ `terminalMonitorStateCliFacade` for service execution, deferral, collateral
2338
+ repair, startup reconciliation, eligibility, and fresh launch preparation.
2339
+ The callback-retry command branch delegates directly to `callbackCliFacade`
2340
+ without acquiring a supervision lock. A normal callback reached through an
2341
+ owned monitor retains its message-generation singleton owner, but the existing
2342
+ callback/state adapters release state and writer locks before actual delivery.
2343
+ `authority` performs legacy identity migration and constructs the terminal
2344
+ bridge lazily.
2345
+ `io` binds detached spawn, the existing file-lock adapter, Store reads/events,
2346
+ and transcript reads. `runtime` supplies only invocation-scoped clock,
2347
+ environment, workspace, process-liveness, logging, and presentation facts.
2348
+ `loadTerminalDispatchLedgerOwner` and `assertManagedTerminalDispatchOwner`
2349
+ remain with dispatch/maintenance composition and were not moved into monitor
2350
+ supervision.
2351
+
2352
+ Startup reconciliation retains the durable observation order: collateral and
2353
+ state-facade reconciliation first (local completion -> callback recovery ->
2354
+ migration -> verified-dead -> deferred -> virgin -> binding -> eligibility),
2355
+ then current owner before legacy owner, fresh launch preparation, detached
2356
+ spawn, and only after successful spawn the exit/launch events, runtime log, and
2357
+ counters. A failed or disabled spawn records no launch event. The approval path
2358
+ also observes the exact generation owner, prepares the process plan, spawns,
2359
+ and only then records reuse, watchdog, or launch presentation.
2360
+
2361
+ The watchdog acquires its generation-specific handoff lock and performs a
2362
+ fresh Turn load on every retry; it never caches status, generation, owner, or
2363
+ launch preparation across sleeps. The owned monitor acquires its
2364
+ message-generation singleton lock before invoking
2365
+ `runTerminalMonitorWithStoreDeferral` and releases it in `finally`. Supervision
2366
+ directly classifies raw `LOCK_TIMEOUT` only while acquiring the handoff and
2367
+ message-generation singleton process locks. State/application deferral
2368
+ continues to classify typed Store timeouts and retains the existing raw
2369
+ terminal/conversation timeout path. The monitor configuration and terminal
2370
+ bridge remain lazy, so a replaced generation exits before timeout validation
2371
+ or effect initialization. Live owners stop duplicate launch, and dead owners
2372
+ are reclaimed by the canonical file-lock adapter. The monitor application
2373
+ service is the sole emitter of the `terminal_bridge_monitor_started` event and
2374
+ runtime log; command, receipt, and maintenance owners may still persist the
2375
+ separate `terminal_bridge_monitor_started_at` state field.
2376
+
2377
+ Maintenance remains the owner of renew/cancel/close durable transitions. Renew
2378
+ persists state and its renewal event under the state lock, releases that lock,
2379
+ then calls the supervision facade's typed `startMonitor`; its persisted
2380
+ `terminal_bridge_monitor_lock_version` now comes from the same facade. This
2381
+ keeps the cross-module durable order state -> renewal event -> state-lock
2382
+ release -> spawn -> launch event. Cancel and close lock stacks and their
2383
+ dispatch authority are unchanged.
2384
+
2385
+ The old black-box paths now have direct invariant witnesses:
2386
+
2387
+ | Old behavior path | New direct invariant | Direct witness |
2388
+ | --- | --- | --- |
2389
+ | monitor plan, approval launch, and process isolation | entry/environment/cwd/spawn/unref order, secret stripping, current-owner reuse, spawn failure without an event, and parallel factory isolation | `terminal-monitor-supervision-cli-adapter.test.ts` |
2390
+ | renew starts monitoring after its durable state transition | maintenance uses typed `startMonitor` and the supervision-owned lock version without changing renewal/cancel lock order | `terminal-maintenance-cli-adapter.test.ts` |
2391
+ | startup state and collateral recovery precede process ownership | the existing state facade returns a data-only handled/candidate result before owner or launch observations | `terminal-monitor-state-reconciliation-service.test.ts` |
2392
+ | monitor generation and Store contention | generation replacement precedes lazy configuration/bridge construction, while Store timeout deferral does not duplicate monitor start | `terminal-monitor-application-service.test.ts` |
2393
+ | live/dead singleton ownership and startup restart | current and legacy owners stop duplicate launch, while the canonical lock shell reclaims an exact dead owner | `terminal-monitor-supervision-cli-adapter.test.ts` and `file-lock-cli-adapter.test.ts` |
2394
+
2395
+ The configured focused integration witnesses remain exactly five shards:
2396
+ `test/shards/agent-cli-claude-callback.test.ts`,
2397
+ `test/shards/agent-cli-monitor-approval-context.test.ts`,
2398
+ `test/shards/agent-cli-monitor-lifecycle.test.ts`,
2399
+ `test/shards/agent-cli-monitor-recovery.test.ts`, and
2400
+ `test/shards/agent-cli-session-acceptance.test.ts`. They retain callback
2401
+ delivery, approval, monitor lifecycle, singleton/restart recovery, and
2402
+ Session-acceptance behavior through the real CLI boundary.
2403
+
2404
+ ## Status CLI facade and data-only facts
2405
+
2406
+ The standalone status read, explicit status reconciliation, terminal context,
2407
+ Codex history projection, managed Turn summary, discoverability fact, and idle
2408
+ timeout reconciliation now live in `terminal-status-cli-adapter.ts` and
2409
+ `terminal-status-facts.ts`. The CLI adapter is the bounded Store/runtime I/O
2410
+ shell. The facts module is data-only and imports no filesystem/path API, Store,
2411
+ Session repository, lock, raw JSON codec, or `Record<..., any>`. List,
2412
+ terminal-command, identity, and runtime-completion composition use the same
2413
+ exported fact or typed facade operation; no selector, terminal action, monitor,
2414
+ or callback authority is copied.
2415
+
2416
+ Against exact parent `afa09955b0c5bd528aaaa69cf4d4f92ed1f44079`,
2417
+ `src/cli-core.ts` falls from 2,735 to 2,122 physical lines (-613). This is the
2418
+ bounded fallback slice: the remaining shared state/path selection and runtime
2419
+ completion context stay at the composition root rather than absorbing
2420
+ maintenance, transcript, or monitor supervision merely to increase movement.
2421
+ Total production TypeScript changes from 92,432 to 92,904 lines (+472, 77.00
2422
+ percent of the core movement), below the hard 500-line overhead cap though not
2423
+ the preferred 300-line target. Architecture validation reports 55 domains, 119
2424
+ production modules, 772 static import edges, zero cycles, and one retained
2425
+ `cli-core.ts` importer.
2426
+
2427
+ The adapter exposes only its factory at runtime and has four invocation-scoped
2428
+ port groups (`selection`, `observation`, `reconciliation`, and `projection`).
2429
+ It directly reuses the invocation-local CLI clock/output/log and the existing
2430
+ Store and trace infrastructure appropriate to a bounded CLI adapter. Default
2431
+ `status` performs no writable-Store assertion, state lock, save, event append,
2432
+ idle close, or monitor reconciliation. Only exact `--reconcile` first asserts
2433
+ the Store writable, then calls the narrow monitor-reconciliation port, then
2434
+ runs idle reconciliation and aggregates the two results.
2435
+
2436
+ Terminal-control status retains selector-token fencing before bridge status,
2437
+ then historical context, JSON presentation, and the redacted runtime log.
2438
+ Managed status retains events -> summary/about/recent evidence -> optional
2439
+ trace -> terminal status ordering and its exact insertion order. Codex history
2440
+ prefers the active process session id, otherwise sorts matching-cwd sessions by
2441
+ descending update time, and finally reports screen-only evidence. Claude keeps
2442
+ the adapter display name and explicit historical-context limitation. Public
2443
+ options remain unknown-valued and the emitted declaration contains no `any` or
2444
+ resolved capability object.
2445
+
2446
+ Idle reconciliation still observes the listed snapshot before acquiring the
2447
+ state lock, skips nonterminal candidate-rollout source Turns, treats raw
2448
+ `LOCK_TIMEOUT` as a skip, reloads the fresh Turn under lock, and rechecks fresh
2449
+ idle age. A close remains save -> append-only event -> runtime log, with the
2450
+ state lock released in `finally`. All 51 extracted function-like declarations
2451
+ meet the preferred 100/c20 target: adapter maxima are 60 lines and c12; facts
2452
+ maxima are 48 lines and c8. Direct tests cover concurrent factory isolation,
2453
+ factory-only exports and declarations, zero-write default status, parent-exact
2454
+ managed continuation and screen getter timing, non-Codex getter/error priority,
2455
+ terminal and managed JSON order, newest-cwd Codex fallback and default bounds,
2456
+ exact monitor aggregation, fresh idle locking/log getter order, and lock-timeout
2457
+ skip. The five
2458
+ focused CLI witnesses are CLI UX, management, control locks, monitor recovery,
2459
+ and terminal-send gates.
2460
+
2461
+ ## OpenClaw plugin boundary split
2462
+
2463
+ Against exact parent `96b5dbdf775ed55ef0efb9391ab2618167a08966`, the
2464
+ 2,830-line `openclaw-plugin.ts` monolith becomes a 67-line composition entry
2465
+ (-2,763). The complete plugin family, including the unchanged 1,068-line
2466
+ helper, moves from 3,898 to 3,974 lines (+76). Total production TypeScript
2467
+ moves from 92,904 to 92,980 lines, so adapter overhead is 2.75 percent of the
2468
+ entry movement and remains below both the preferred 250-line and hard 500-line
2469
+ budgets. The graph moves from 119 to 123 production modules and from 772 to 783
2470
+ static import edges, with zero cycles and the same sole `cli-core.ts` importer.
2471
+ The affected ownership groups contain four OpenClaw plugin modules, two
2472
+ callback-transport modules, and four monitor-supervision modules.
2473
+
2474
+ The split assigns one explicit role to every authority path:
2475
+
2476
+ - `openclaw-plugin-schemas.ts` owns the 14 tool JSON schemas and their exact
2477
+ property, `required`, `not`, `anyOf`, and `allOf` insertion order.
2478
+ - `openclaw-plugin-command-adapter.ts` owns `/akk` parsing/formatting,
2479
+ registration and tool mapping, argv construction, synchronous/asynchronous
2480
+ CLI result/error priority, message identity, and the per-API relay-path
2481
+ `WeakMap`.
2482
+ - `openclaw-plugin-callback-adapter.ts` owns callback identity and target
2483
+ agreement, automatic approval, injection, delivery planning, and shortcut
2484
+ text.
2485
+ - `openclaw-plugin-supervisor.ts` owns startup reconciliation and the
2486
+ non-overlapping immediate/timer/start/stop monitor-supervision loop.
2487
+ - `openclaw-plugin.ts` owns only `definePluginEntry` composition, stable plugin
2488
+ metadata, ordered registration wiring, the default export, and
2489
+ `createOpenClawPluginForTest`.
2490
+ - `openclaw-plugin-helpers.ts` remains the canonical parser/formatter/store-dir
2491
+ helper owner; no helper was copied into a new module.
2492
+
2493
+ The static dependency graph is deliberately one-way:
2494
+
2495
+ ```text
2496
+ openclaw-plugin entry
2497
+ |-> callback adapter -> command adapter -> schemas -> executors
2498
+ | \-> helpers -> value guards
2499
+ |-> supervisor -------> command adapter
2500
+ | \-> helpers
2501
+ \-> command adapter ---> helpers
2502
+ ```
2503
+
2504
+ Neither callback nor supervisor is imported by command, schemas, or helpers,
2505
+ and no split module imports the entry. The entry still binds the relay path
2506
+ before registering the callback, then registers callback -> supervisor ->
2507
+ slash command/tools in the original observable order. The merged status and
2508
+ terminal-monitor-supervision facades remain unchanged and retain their newer
2509
+ configuration, process ownership, and documentation authorities.
2510
+
2511
+ | Old monolith boundary | Preserved invariant | New authority and proof boundary |
2512
+ | --- | --- | --- |
2513
+ | 14 inline schema objects | byte-identical JSON, tool order, descriptions, required/exclusion semantics | schemas module; 12,657-byte schema SHA-256 contract and exact 14-tool registration witness |
2514
+ | `/akk` plus tool registration/CLI execution | argv/env/cwd/stdout/stderr/exit/JSON/error and getter priority | command adapter; OpenClaw contract argv/result/error and Resume snapshot witnesses |
2515
+ | callback gateway block | modern/legacy Session/Turn identity agreement, auto-approval, injection/delivery/shortcut order | callback adapter; callback injection, mismatch, approval, and per-API isolation witnesses |
2516
+ | monitor reconciliation service | immediate startup, non-overlap, timer reschedule, stop/drain, catch-and-warn routing | supervisor module; recording supervisor timer witness |
2517
+ | plugin factory and metadata | id/name/description, Gateway scope/error code, registration order, instance-local snapshots | 67-line entry; runtime and declaration expose only `default` and `createOpenClawPluginForTest` |
2518
+
2519
+ This is a source-ownership change only. It adds or removes no lock, Store or
2520
+ durable JSON/event write, subprocess boundary, timer, Gateway method, or
2521
+ Gateway restart. The existing `spawnSync`/`spawn` calls and their exact argv,
2522
+ environment, working-directory, output, timeout, and error rules only moved to
2523
+ the command adapter. At this exact plugin-split slice, static subprocess
2524
+ startup evidence remained 38 included sites; that is a historical slice metric,
2525
+ not the final result. The later static closeout establishes 19 of 48 baseline
2526
+ sites. The single supervisor `setTimeout` loop only moved files, and no install
2527
+ or restart path is called by plugin registration. Multiple plugin definitions
2528
+ retain separate resume caches, while the existing per-API `WeakMap` keeps
2529
+ relay path and plugin config isolated.
2530
+
2531
+ All newly extracted or moved slice functions remain below the hard
2532
+ 500-line/c50 gates. The unchanged canonical `openclaw-plugin-helpers.ts` is not
2533
+ counted in this slice gate: its existing `parseAkkCommand` remains 188 lines/c58
2534
+ and is retained for the final global complexity closure. The cohesive preferred
2535
+ 100-line/c20 exceptions in this slice are transparent and recorded below;
2536
+ splitting the registration table or the ordered decision/format paths further
2537
+ would obscure schema/action order or fail-closed precedence without reducing
2538
+ authority.
2539
+
2540
+ | Function or table | LOC / approximate complexity |
2541
+ | --- | ---: |
2542
+ | `registerOpenClawCommands` | 398 / c1 |
2543
+ | `runDelegate` | 178 / c45 |
2544
+ | `handleAkkLifecycleCommand` | 165 / c30 |
2545
+ | `runCliAsync` | 100 / c1 |
2546
+ | callback `handleCallback` | 105 / c15 |
2547
+ | `handleAkkCommand` | 90 / c22 |
2548
+ | `formatSendCommandResult` | 84 / c28 |
2549
+ | `formatStatusCommandResult` | 59 / c27 |
2550
+ | `runSendRequest` | 93 / c21 |
2551
+
2552
+ The entry maximum is 37 lines/c3 and the supervisor maximum is 97 lines/c12.
2553
+ Machine-readable public-contract evidence freezes the exact manifest plus six
2554
+ source authority paths, checks a role-specific responsibility signature and
2555
+ each required direct import, and rejects missing command/schema roles or an
2556
+ existing but incorrect substitute path.
2557
+
2558
+ ## #195 production function hard-gate closeout
2559
+
2560
+ PR #195 compares exact parent
2561
+ `68e0e399152f5569ef0572b914da308acea36423` with exact candidate
2562
+ `256614ede43188c7cf29594b5afe14331ff9b909`. The compiler-AST measurement
2563
+ counts every production function, method, accessor, constructor, function
2564
+ expression, and arrow function with a body, excluding nested function bodies
2565
+ from the enclosing function's complexity.
2566
+
2567
+ | Metric | Parent | Candidate | Delta |
2568
+ | --- | ---: | ---: | ---: |
2569
+ | Production physical LOC | 92,980 | 93,303 | +323 |
2570
+ | Production functions | 4,019 | 4,044 | +25 |
2571
+ | Largest function / maximum complexity | 834 / c190 | 484 / c49 | strictly below 500 / c50 |
2572
+ | Hard-limit violations under the final rule | 6 | 0 | -6 |
2573
+ | Production modules / import edges / cycles | 123 / 783 / 0 | 123 / 783 / 0 | unchanged |
2574
+ | Static subprocess sites / affected full fallback | 19 of 48 / 2 of 10 | 19 of 48 / 2 of 10 | unchanged |
2575
+
2576
+ The six mechanical splits preserve evaluation, short-circuit, getter, and
2577
+ first-error order:
2578
+
2579
+ | Parent hard violation | Parent LOC / complexity | Candidate private stages | Candidate stage maxima |
2580
+ | --- | ---: | --- | ---: |
2581
+ | `pendingApprovalFromRecords` | 237 / c50 | turn selection, tool-use agreement, evidence projection | 91 / c22 |
2582
+ | `assertDeferredForegroundTransfer` | 834 / c190 | header, source history/binding, target, preparation, dispatch, commit, resolution, abort, failure | 142 / c37 |
2583
+ | `deriveRelationshipAssertions` | 121 / c60 | Session relationships and stable relationships | 90 / c36 |
2584
+ | `selectTerminalSnapshot` | 279 / c64 | row, process, management, and action selection | 128 / c28 |
2585
+ | `assertNativeThreadTransition` | 327 / c71 | header, identity, receipt, and binding consistency | 146 / c29 |
2586
+ | `parseAkkCommand` | 188 / c58 | lifecycle, Turn, and close parsing | 80 / c24 |
2587
+
2588
+ The gate is strict `<500` LOC and `<50` approximate complexity: a function
2589
+ that reaches 500 or c50 fails. There is no exception field or allowlist. The
2590
+ default `<100`/`<20` inventory remains visible for review but is not silently
2591
+ treated as a hard failure. This closeout changes no module ownership or import
2592
+ direction, lock scope or order, durable write or recovery phase, subprocess
2593
+ boundary, public command/tool/schema/JSON contract, Store protocol, or runtime
2594
+ export.
2595
+
2596
+ Exact-candidate validation covered typecheck, build, architecture, refactor
2597
+ evidence, and diff checks; 186 relevant direct tests, 1,001 fast tests, and
2598
+ five targeted integration files passed. Two independent exact-head reviews
2599
+ returned GO. No full suite, install, package, publish, or GitHub Actions run was
2600
+ part of PR #195.
2601
+
2602
+ ## Final CLI-core facade and ownership closeout
2603
+
2604
+ The final closeout moves the remaining reusable authority and I/O helpers out
2605
+ of `cli-core.ts` without moving another command state machine. CLI option
2606
+ coercion and canonical workspace checks now live in `cli-command-runtime.ts`;
2607
+ conversation activity/waiting policy lives in `protocol.ts`; callback process
2608
+ failure classification lives in `callback-outbox-policy.ts`; and terminal
2609
+ process liveness lives at the existing `ps` boundary in
2610
+ `terminal-process-source.ts`. Terminal send safety is owned by
2611
+ `terminal-authority-policy.ts`, OpenClaw yield presentation by
2612
+ `terminal-dispatch-presenter.ts`, and Codex completion-context reads by the
2613
+ status facade. List and monitor consumers reuse those canonical policies rather
2614
+ than retaining private copies.
2615
+
2616
+ The Store-backed current-Turn fence is exposed through
2617
+ `terminal-turn-binding-authority-cli-adapter.ts` under the existing terminal
2618
+ identity-authority domain. It preserves Store selection, terminal-control
2619
+ validation, writable-Store upgrade, protocol check, authoritative Session read,
2620
+ and exact-or-migrated binding comparison order. Dispatch recovery now exposes
2621
+ its existing ledger-owner read and managed-owner fence directly. Managed
2622
+ approval/cancellation still checks deferred transfer, current binding, and the
2623
+ ledger generation in that order; no lock, Store, error, or asynchronous
2624
+ boundary is reordered.
2625
+
2626
+ Against exact parent `1274306e8e2f1e294910c8719b23de0d74878a31`,
2627
+ `src/cli-core.ts` falls from 2,122 to 1,556 physical lines (-566). Total
2628
+ production TypeScript changes from 93,303 to 93,313 lines (+10), the typed
2629
+ owner/facade overhead for the final extraction. Architecture validation reports
2630
+ 57 domains, 125 production modules, 809 static import edges, zero cycles, and
2631
+ one retained `cli-core.ts` importer. Its public surface remains the stable
2632
+ `parseCliCommand` / `executeCliCommand` facade, and `CliCommandOptions` is now
2633
+ `Record<string, unknown>` in both source and emitted declarations.
2634
+
2635
+ The final typed-boundary cleanup adds nine interface-only production lines to
2636
+ remove the last `TerminalControlSendRequest` `Record<string, any>` bridge. The
2637
+ closeout production ratchet is therefore 93,322 physical lines;
2638
+ `cli-core.ts` remains 1,556 lines and the graph remains 125 modules, 809 edges,
2639
+ and zero cycles. Direct source and emitted-declaration guards freeze the six
2640
+ option properties and reject any reintroduction of raw `any` in the composition
2641
+ boundary.
2642
+
2643
+ The ownership validator also fixes an independent Issue-level ceiling of 8,000
2644
+ physical `cli-core.ts` lines. Manifest validation rejects a configured value
2645
+ above 8,000, while architecture validation rejects an actual source above
2646
+ 8,000 even when a coordinated manifest edit makes the two values equal. The
2647
+ exact ratchet remains 1,556; a direct tamper witness raises both source and
2648
+ ratchet to 8,001, synchronizes the production total, and still fails on the
2649
+ hard ceiling. The combined compiler-AST architecture gate reports zero
2650
+ production function hard-limit violations. It also fixes one owner for each of
2651
+ the six shared status predicates: conversation release, session-send blocking,
2652
+ and callback supersede belong to `protocol.ts`; deferred-transfer finality
2653
+ belongs to `deferred-foreground-transfer-policy.ts`; ordinary dispatch activity
2654
+ and recovery belong to `terminal-dispatch-policy.ts`. The same compiler-AST
2655
+ gate rejects duplicate predicate definitions, duplicate exact inline tables,
2656
+ and full active/recoverable tables that bypass their derived policy.
2657
+
2658
+ An exact compiler-AST inventory ratchets the 27 remaining top-level functions
2659
+ and rejects top-level classes or function-valued variables. A forbidden-owner
2660
+ guard prevents terminal-send policy, Turn-binding authority, Codex context
2661
+ loading, callback failure classification, process liveness, and status policy
2662
+ definitions from returning to the composition root. Direct tests record the
2663
+ Turn-generation and migrated compatibility boundary, superseded-error
2664
+ projection, delegated/malformed short-circuits, deferred -> binding -> ledger
2665
+ ordering and early failure, Codex provider/process/history read order, callback
2666
+ classification priority, terminal-send getter/error priority, canonical
2667
+ workspace behavior, and process/status policy reuse. Therefore `cli-core.ts`
2668
+ contains no send, lifecycle, monitor, or callback state-machine definition; it
2669
+ retains only stable parsing/execution, command routing, composition wiring,
2670
+ shared lock scopes, and CLI parser/presentation compatibility.
2671
+
2672
+ ## Integration virtual-clock profile remediation
2673
+
2674
+ The final profile remediation changes test timing only. Production timeout,
2675
+ polling, retry, lock, and composer windows are unchanged. The ordinary
2676
+ `runAgentCliInProcess` fixture also remains real-time by default. Selected
2677
+ sequential scenarios opt in to `runAgentCliInProcessVirtual`, whose wall and
2678
+ monotonic clocks are scoped by an explicit Store, state path, or
2679
+ `AKK_RUNTIME_DIR`. Async sleeps advance that clock and yield one `setImmediate`
2680
+ turn; sync sleeps only advance it. The fixture records both kinds of request,
2681
+ reuses one monotonic clock across calls in the same fixture, and fails fast if
2682
+ two commands try to share that clock concurrently.
2683
+
2684
+ The highest-volume sequential Codex cases may opt in one step further through
2685
+ `runAgentCliInProcessDirect`. That helper still runs the production CLI parser,
2686
+ composition, terminal adapters, identity fences, dispatch ledger, and receipt
2687
+ state machines. It replaces only the executable fake `tmux`/`ps`/`lsof` ports
2688
+ with the existing `MutableRecordingTerminalProvider` and
2689
+ `StaticTerminalProcessSource`. `writeFakeTmux` and `writeFakeProcessTools`
2690
+ register fixture-scoped panes, screens, and process snapshots; screen capture
2691
+ remains live across calls, and direct text/key operations are projected into
2692
+ the existing exact input ledger with a `direct_terminal_provider` marker.
2693
+ Explicit JSON terminal fixtures retain their own static adapters. The direct
2694
+ helper fails before command execution when it sees a capture/send/list gate,
2695
+ delay, transport failure, uncertain SIGKILL outcome, or overlapping command.
2696
+ It is additionally restricted to a non-empty Codex process fixture. Monitor,
2697
+ Claude, empty-process, process-death, and executable-observation scenarios may
2698
+ use virtual time where listed below, but never the direct provider seam.
2699
+
2700
+ The timing boundary is intentionally narrower than the test boundary:
2701
+
2702
+ | Virtual-time scenarios | Real-time boundary retained |
2703
+ | --- | --- |
2704
+ | Session follow-current/response generations and synthetic acceptance outcomes | v0.8.1 compatibility, Claude observation failure, the real native-binding window, and late-ACK child processes |
2705
+ | Sequential dispatch recovery and receipt-fence state machines, using direct terminal/process ports where the executable shim is not the contract | the public active-managed dispatch witness, uncertain transport/SIGKILL recovery, and both concurrent-send witnesses |
2706
+ | Wrapped-composer, prepared/orphan receipt, stable replay, and delegate replay semantics | the multilingual composer adapter witness and both gated raw-send process witnesses |
2707
+ | Same-cwd/low-confidence monitor decisions, working hard-timeout policy, and sequential renew semantics | one complete Gateway callback path and the gated renew-versus-close race |
2708
+ | Fake-process Claude death/transcript reconciliation | monitor singleton, live/dead PID and SIGKILL recovery, supervised/crash recovery, and transcript-monitor restart processes |
2709
+ | Idle-gate matrix except injected capture failure, and managed background-conversation projection | capture failure, stale-PID, partial-`lsof`, raw approval, and direct cancel adapter witnesses |
2710
+
2711
+ No test name or pre-existing assertion is removed. Receipt bytes, whitespace,
2712
+ error priority, no-second-Enter, no-terminal-input, and Store-authority
2713
+ assertions remain in their original integration tests. The existing
2714
+ `terminal-dispatch-ledger` public-contract mapping continues to pair those
2715
+ retained receipt/recovery boundaries with the direct dispatch application,
2716
+ ledger codec, receipt, and terminal-acceptance witnesses; no manifest path or
2717
+ tier changes merely to claim a timing improvement.
2718
+
2719
+ Measure the focused worker cost from a clean exact commit with the repository
2720
+ profile reporter. Run the identical command for the parent and candidate, on
2721
+ the same host, Node version, compile-cache state, and concurrency:
2722
+
2723
+ ```sh
2724
+ test -z "$(git status --porcelain)"
2725
+ npm run build
2726
+ test -z "$(git status --porcelain)"
2727
+ AKK_PROFILE_CACHE="$(mktemp -d /tmp/akk-126-integration-cache.XXXXXX)"
2728
+ AKK_PROFILE_OUTPUT="/tmp/akk-126-integration-$(git rev-parse HEAD).json"
2729
+ AKK_TEST_CONCURRENCY=4 \
2730
+ NODE_COMPILE_CACHE="$AKK_PROFILE_CACHE" \
2731
+ AKK_TEST_REPORTER="$PWD/scripts/test-profile-reporter.js" \
2732
+ AKK_TEST_PROFILE_TIER=integration \
2733
+ AKK_TEST_PROFILE_COMMIT="$(git rev-parse HEAD)" \
2734
+ AKK_TEST_PROFILE_DIRTY=0 \
2735
+ AKK_TEST_PROFILE_OUTPUT="$AKK_PROFILE_OUTPUT" \
2736
+ node scripts/run-test-tier.js integration \
2737
+ test/shards/agent-cli-session-acceptance.test.ts \
2738
+ test/shards/agent-cli-dispatch-recovery.test.ts \
2739
+ test/shards/agent-cli-dispatch-authority.test.ts \
2740
+ test/shards/agent-cli-composer-replay.test.ts \
2741
+ test/shards/agent-cli-monitor-recovery.test.ts \
2742
+ test/shards/agent-cli-monitor-lifecycle.test.ts \
2743
+ test/shards/agent-cli-terminal-send-gates.test.ts \
2744
+ test/shards/agent-cli-receipt-fences.test.ts
2745
+ ```
2746
+
2747
+ Compare the sum of `files[].duration_ms`, not nested test durations, and reject
2748
+ dirty, failed, wrong-SHA, wrong-Node, or wrong-concurrency reports. This section
2749
+ does not claim the final performance gate: exact merged-head before/after
2750
+ worker time and the repeated fast/full reports belong in the separate final
2751
+ evidence update after all remediation branches are stacked.
2752
+
2753
+ ## Soft freeze while #126 is active
2754
+
2755
+ Until the orchestration milestones finish:
2756
+
2757
+ 1. Do not add product features directly to a hotspot in `cli-core.ts`. Route new
2758
+ work through the next typed seam when reasonably possible.
2759
+ 2. Security, data-loss, liveness, and release-blocking regressions may patch the
2760
+ current path, but the PR must identify the temporary ownership and update the
2761
+ extraction inventory.
2762
+ 3. Do not introduce new `Record<string, any>` service inputs, new `*LockHeld`
2763
+ booleans, new direct persistence calls in `cli-core.ts`, or a new lock-order
2764
+ exception.
2765
+ 4. Keep refactor PRs free of unrelated user-facing behavior changes. A behavior
2766
+ change needs its own issue, acceptance tests, and explicit review.
2767
+ 5. Retain real-process contract tests for argv/exit, terminal input, Store crash
2768
+ recovery, and OpenClaw callback boundaries. First add deterministic reducer
2769
+ tests; consolidate duplicate black-box cases only after equivalent contract
2770
+ coverage is demonstrated.
2771
+ 6. Do not weaken identity, token, composer, approval, ownership, CAS, uncertain
2772
+ outcome, or callback isolation fences to make extraction easier.
2773
+
2774
+ ## Measurement method
2775
+
2776
+ Physical LOC is `wc -l` over checked-in `src/*.ts`. Function and approximate
2777
+ complexity measurements use the TypeScript compiler AST and count functions,
2778
+ methods, accessors, constructors, function expressions, and arrow functions with
2779
+ bodies. Approximate complexity is `1 + if/loop/case/catch/?:/&&/||/??`, excluding
2780
+ nested function bodies from the enclosing function. It is a prioritization
2781
+ signal, not a semantic correctness score.
2782
+
2783
+ The JSON baseline is immutable for this snapshot. Future PRs append their own
2784
+ before/after measurements or replace the documented current baseline while
2785
+ retaining this commit as the historical comparison point.
2786
+
2787
+ ## Issue #206 addendum — durable observation of human-started work
2788
+
2789
+ Issue #206 adds Terminal Watch as a new aggregate beside, not inside, the
2790
+ managed Session/Turn architecture. The v16 action-contract and 14-tool sections
2791
+ above remain immutable historical snapshots; at the time of the #206 delta,
2792
+ the public surface was list action-contract v23 with 16 registered OpenClaw
2793
+ tools. v23 keeps every structured
2794
+ Send semantic-ID-only while making Codex `terminal_user_explicit` independent
2795
+ of Composer visibility, stability, and exactness. Its physical fallback clears
2796
+ the current Composer once, injects the new request, waits through the paste
2797
+ window, and dispatches Enter exactly once without a post-text Composer veto.
2798
+ Claude Code user-explicit Send, native inspection, and lifecycle input remain
2799
+ exact-empty-only; the managed path may require exact empty before input, but a
2800
+ user-explicit Codex request cannot be vetoed by Composer observation after text
2801
+ injection. When managed delivery fails before input, the physical fallback
2802
+ captures a pre-Send provider boundary and best-effort attaches an exact
2803
+ request-bound Terminal Watch after Enter. The Watch supplies completion callback
2804
+ behavior without claiming a managed Turn, and its failure never revokes Send.
2805
+ No draft text or Composer digest crosses the model boundary.
2806
+
2807
+ The later interactive-response release advances the current public surface to
2808
+ action-contract v24 and 17 OpenClaw tools. It adds a status-bound semantic
2809
+ questionnaire response action while keeping prompt fingerprints, terminal-key
2810
+ plans, and one-shot mutation authority private.
2811
+
2812
+ Issue #298 P2 subsequently advances the current core surface to action-contract
2813
+ v25 and 19 OpenClaw tools. It adds explicit Codex `identify_foreground` and
2814
+ atomic `identify_and_send` operations plus independent screen, native-identity,
2815
+ and durable-activity status axes. The standalone 30-second `/status` proof is
2816
+ diagnostic only and is not persisted as reusable identity authority; normal
2817
+ Send, List, and Status do not run the probe.
2818
+
2819
+ ### Aggregate and persistence boundary
2820
+
2821
+ `TerminalWatch` schema v2 represents either one task that a human started
2822
+ directly in a Codex or Claude Code TUI or one request AKK delivered through the
2823
+ user-explicit unmanaged fallback. It is not a Conversation, Session, Turn, dispatch
2824
+ receipt, monitor owner, or terminal-input authority. Creating or reconciling it
2825
+ does not send input, adopt or claim the work, reserve the terminal, block later
2826
+ human activity, or create callback authority for a managed Turn.
2827
+
2828
+ Each strict record contains `watch_id`, revision, agent, exact terminal endpoint,
2829
+ workspace and internally resolved binding token; one privacy-safe provider anchor
2830
+ owns the process incarnation, native thread/task and exact captured agent-version
2831
+ evidence. Regression-tested versions are diagnostics rather than a Watch
2832
+ allowlist; structurally compatible future versions remain observable with a
2833
+ warning. The record also retains the originating OpenClaw session/binary,
2834
+ creation/update/deadline timestamps, status, last activity, optional terminal
2835
+ settlement, and an append-only notification outbox whose approval entries carry
2836
+ their own evidence fingerprints.
2837
+ Status is one of `active`, `completed`,
2838
+ `failed`, `timed_out`, `invalidated`, or `cancelled`. The files live at
2839
+ `<store>/terminal-watches/<watch_id>.json`, with a `0700` directory, `0600`
2840
+ owner-private atomic JSON, strict path/symlink/shape validation, and revision
2841
+ CAS. The independent namespace is admitted by the Store root allowlist while
2842
+ retaining Store format 1 and advancing the writer fence to protocol 6.
2843
+
2844
+ Codex anchors retain the exact process identity, rollout device/inode/path, native
2845
+ task, request hash, version, task-start/user-message/observed-end byte offsets,
2846
+ capture time, and evidence fingerprint. Claude anchors retain the exact
2847
+ process/session identity, workspace, transcript relative path/device/inode/file
2848
+ identity, root prompt, request hash, version, current-turn/observed-end byte
2849
+ offsets, capture time, and fingerprint. The compact terminal record separately
2850
+ binds endpoint/incarnation, workspace, and the internal creation-time binding
2851
+ token. The Store validates the provider-owned anchor directly, without a mirrored
2852
+ Watch-specific shape or any raw prompt or command text. Legacy schema-v1 Watch
2853
+ records normalize to v2 on read; protocol 6 prevents an older writer from
2854
+ treating those v2 records as compatible.
2855
+
2856
+ ### State, locking, and callback recovery
2857
+
2858
+ The user flow is human TUI start → fresh `/akk list` → copy only the advertised
2859
+ `terminals[].available_actions.watch` action's exact `terminal_id` → create Watch
2860
+ → address it only by `watch_id` for status or unwatch. The creation path resolves
2861
+ the current binding token internally, acquires the terminal lock, rescans and
2862
+ revalidates the exact terminal incarnation and token, captures one unique
2863
+ active-task anchor, then creates with expected revision `null`. All mutations acquire the canonical
2864
+ Store writer lease before the per-Watch file lock. Observation occurs outside
2865
+ that write scope; settlement reloads under `writer -> watch`, checks the exact
2866
+ terminal and anchor fingerprints plus deadline, and commits one CAS transition.
2867
+ Concurrent cancellation, timeout, settlement, or another observer therefore
2868
+ cannot overwrite a newer revision.
2869
+
2870
+ The observation reducer yields `pending`, `approval`, `completed`, `failed`, or
2871
+ `invalidated`. Any endpoint, process, native-thread/task, provider file,
2872
+ offset/boundary, version/profile, request, or fingerprint drift—and any missing,
2873
+ truncated, replaced, successor, unsupported, or ambiguous evidence—fails closed
2874
+ as invalidated rather than following current terminal work. `unwatch` settles
2875
+ only the aggregate as cancelled and never touches the TUI.
2876
+
2877
+ Approval appends one notification per exact fingerprint while leaving the Watch
2878
+ active. It carries metadata only, never raw prompt/command text; Terminal Watch
2879
+ has no approval execution port and cannot participate in automatic approval.
2880
+ Completed/failed observations may retain only provider-redacted bounded
2881
+ completion text (maximum 4,000 characters) plus optional completion identity and
2882
+ timestamp. Every terminal outcome appends exactly one outcome notification.
2883
+
2884
+ Notification IDs derive deterministically from Watch, kind, and evidence
2885
+ fingerprint; the transport idempotency key derives from Watch plus notification.
2886
+ Delivery first persists a leased claim, performs transport outside the lock,
2887
+ then CAS-settles success or retry metadata. A process crash leaves an expiring
2888
+ claim that startup/periodic reconciliation can reclaim. This is crash-safe
2889
+ at-least-once transport with effective at-most-once logical delivery when the
2890
+ OpenClaw transport honors the idempotency key. One Watch's observation or
2891
+ delivery failure is recorded in its reconciliation item and does not stop the
2892
+ remaining Watches.
2893
+
2894
+ ### Public wiring and supervision
2895
+
2896
+ The 16-tool OpenClaw surface adds `agent_knock_knock_watch` and
2897
+ `agent_knock_knock_unwatch`; the existing status tool accepts exactly one of a
2898
+ managed Turn target, semantic terminal target, or `watch_id`. List projects
2899
+ active Watches in `terminal_watches[]` and advertises `watch` only for an exact,
2900
+ supported terminal currently classified as working or awaiting approval. Slash
2901
+ routing is `/akk watch <exact-terminal-id>`, `/akk status <watch-id>`, and
2902
+ `/akk unwatch <watch-id>`. The internal CLI boundary has exactly four entries:
2903
+
2904
+ ```text
2905
+ watch-terminal --terminal <exact-terminal-id> ...
2906
+ watch-status --watch <watch-id> ...
2907
+ unwatch-terminal --watch <watch-id> ...
2908
+ reconcile-watches ...
2909
+ ```
2910
+
2911
+ Action-contract v18 establishes a zero-token model boundary. Structured actions
2912
+ carry semantic identities and user intent only:
2913
+
2914
+ - ordinary send is `{session_id, request}` for strict continuation or
2915
+ `{terminal_id, request}` for follow-current; the target fields are mutually
2916
+ exclusive and may both be absent only when AKK must prove one unique target;
2917
+ - Terminal Watch is `{terminal_id}` only;
2918
+ - native inspection is `{terminal_id, inspection}`, new is `{terminal_id}`, and
2919
+ resume is `{terminal_id, native_thread_id}`;
2920
+ - managed approval is `{turn_id}`, terminal-scoped approval is `{terminal_id}`,
2921
+ reconcile is `{terminal_id, conflicting_session_id}`, and handoff takeover is
2922
+ `{turn_id, reason:"superseded_by_human_context_switch"}`.
2923
+
2924
+ Approval, reconcile, and handoff still require explicit user confirmation. The
2925
+ trusted plugin/CLI retains that confirmation offer, derives fresh terminal,
2926
+ binding, candidate, approval, handoff, revision, and compare-and-swap fences,
2927
+ and revalidates them under the canonical locks immediately before mutation.
2928
+ None of those opaque values—including live native UUIDs used only as a handoff
2929
+ fence—crosses the model-facing boundary. Human slash selectors remain a CLI
2930
+ discovery layer. Orphan close keeps `expected_message_id` and
2931
+ `expected_transition_id` because they are durable entity identities rather than
2932
+ authority tokens. This projection change retains Store format 1 and the private
2933
+ persisted authority evidence while advancing the writer fence to protocol 6.
2934
+
2935
+ The existing non-overlapping OpenClaw supervisor now coordinates two independent
2936
+ steps at startup and every five seconds: managed-Turn monitor reconciliation and
2937
+ Terminal Watch reconciliation. Each has its own error boundary, so a failure in
2938
+ one cannot starve the other. Watch reconciliation observes active aggregates,
2939
+ settles deadlines/outcomes, and drains eligible durable notifications; it does
2940
+ not mutate Session/Turn state or replay terminal input.
2941
+
2942
+ The deterministic fast witnesses cover provider-anchor drift, Store privacy and
2943
+ CAS, service restart/dedupe/timeout/claim-crash/retry behavior, callback
2944
+ projection, list/action v18, slash/tool routing, and documentation. Per the
2945
+ repository test policy, integration/full/release tests remain reserved for the
2946
+ immediate pre-publication gate of an actual npm or ClawHub release.
2947
+
2948
+ ## Issue #212 addendum — Host-owned lifecycle adapter
2949
+
2950
+ AKK does not run a standalone supervisor. Exactly one external Host owns the
2951
+ in-process AKK lifecycle and calls `start()` and `stop()` with its own plugin or
2952
+ adapter lifetime. The Host injects an ordered list of reconciliation phases;
2953
+ the host-neutral lifecycle service owns only startup execution, periodic
2954
+ single-flight scheduling, per-phase error isolation, and stop/drain behavior.
2955
+ It owns no Store, callback transport, process identity, Host configuration,
2956
+ daemon entrypoint, or cross-Host lease.
2957
+
2958
+ OpenClaw is the first adapter. Its compatibility module continues to own the
2959
+ existing reconciliation argv, Store-dir lookup, log messages, unref timer
2960
+ policy, registration service id, and managed-monitor-before-Watch ordering. The
2961
+ legacy module and service names remain unchanged to avoid an unnecessary
2962
+ OpenClaw compatibility change; they do not represent an independently running
2963
+ Supervisor product. Callback route and delivery ports were already
2964
+ host-neutral, so this extraction does not change the Store or callback protocol.
2965
+
2966
+ Future Hosts such as Hermes compose their own adapter around the same lifecycle
2967
+ and callback ports. AKK deliberately does not add multi-Host ownership,
2968
+ Host-switch recovery, PID/heartbeat fencing, or no-Host continuity because
2969
+ those are outside the supported product behavior.
2970
+
2971
+ ## Issue #320 P2 addendum — Host connector capability handshake
2972
+
2973
+ The Host-neutral catalog now derives one immutable capability handshake for Pi
2974
+ and DeepSeek Harness. Version 1 contains only public catalog identity: the
2975
+ ordered tool names and derived count, a canonical metadata/schema SHA-256, and
2976
+ the canonical Skill name/SHA-256. It contains no controller route, environment,
2977
+ token, filesystem path, or other authority. Each connector validates the
2978
+ handshake before starting its Host lifecycle and validates the exact names it
2979
+ registered before reporting ready. Unknown versions, missing metadata, catalog
2980
+ drift, generated-Skill drift, and partial registration fail closed.
2981
+
2982
+ This replaces connector-local `EXPECTED_TOOL_COUNT` literals and removes the
2983
+ architecture dashboard's regex extraction of those constants. The checked-in
2984
+ public-contract witness still records the current 22-tool OpenClaw/Host Bridge
2985
+ surface; adding or removing a catalog entry intentionally changes that public
2986
+ witness, while connector counts and registration expectations derive from the
2987
+ same handshake without another manual edit.