@scotthuang/agent-knock-knock 0.13.17 → 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 (291) hide show
  1. package/CHANGELOG.md +38 -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-async-question-adapter.js +14 -4
  22. package/dist/src/codex-async-question-adapter.js.map +1 -1
  23. package/dist/src/codex-lifecycle-compatibility.d.ts +1 -1
  24. package/dist/src/codex-lifecycle-compatibility.js +9 -3
  25. package/dist/src/codex-lifecycle-compatibility.js.map +1 -1
  26. package/dist/src/codex-native-cli-adapter.d.ts +6 -0
  27. package/dist/src/codex-native-cli-adapter.js +273 -0
  28. package/dist/src/codex-native-cli-adapter.js.map +1 -0
  29. package/dist/src/codex-native-client-interactions.d.ts +6 -0
  30. package/dist/src/codex-native-client-interactions.js +124 -0
  31. package/dist/src/codex-native-client-interactions.js.map +1 -0
  32. package/dist/src/codex-native-client-rpc.d.ts +21 -0
  33. package/dist/src/codex-native-client-rpc.js +137 -0
  34. package/dist/src/codex-native-client-rpc.js.map +1 -0
  35. package/dist/src/codex-native-client.d.ts +42 -0
  36. package/dist/src/codex-native-client.js +326 -0
  37. package/dist/src/codex-native-client.js.map +1 -0
  38. package/dist/src/codex-native-identity.d.ts +6 -0
  39. package/dist/src/codex-native-identity.js +42 -0
  40. package/dist/src/codex-native-identity.js.map +1 -0
  41. package/dist/src/codex-native-monitor.d.ts +4 -0
  42. package/dist/src/codex-native-monitor.js +92 -0
  43. package/dist/src/codex-native-monitor.js.map +1 -0
  44. package/dist/src/codex-native-outbox.d.ts +16 -0
  45. package/dist/src/codex-native-outbox.js +120 -0
  46. package/dist/src/codex-native-outbox.js.map +1 -0
  47. package/dist/src/codex-native-public-projection.d.ts +545 -0
  48. package/dist/src/codex-native-public-projection.js +182 -0
  49. package/dist/src/codex-native-public-projection.js.map +1 -0
  50. package/dist/src/codex-native-record-store.d.ts +27 -0
  51. package/dist/src/codex-native-record-store.js +111 -0
  52. package/dist/src/codex-native-record-store.js.map +1 -0
  53. package/dist/src/codex-native-response-service.d.ts +69 -0
  54. package/dist/src/codex-native-response-service.js +244 -0
  55. package/dist/src/codex-native-response-service.js.map +1 -0
  56. package/dist/src/codex-native-runtime.d.ts +46 -0
  57. package/dist/src/codex-native-runtime.js +112 -0
  58. package/dist/src/codex-native-runtime.js.map +1 -0
  59. package/dist/src/codex-native-semantic.d.ts +17 -0
  60. package/dist/src/codex-native-semantic.js +175 -0
  61. package/dist/src/codex-native-semantic.js.map +1 -0
  62. package/dist/src/codex-native-snapshot.d.ts +19 -0
  63. package/dist/src/codex-native-snapshot.js +160 -0
  64. package/dist/src/codex-native-snapshot.js.map +1 -0
  65. package/dist/src/codex-native-state-store.d.ts +61 -0
  66. package/dist/src/codex-native-state-store.js +132 -0
  67. package/dist/src/codex-native-state-store.js.map +1 -0
  68. package/dist/src/codex-native-task-service.d.ts +71 -0
  69. package/dist/src/codex-native-task-service.js +502 -0
  70. package/dist/src/codex-native-task-service.js.map +1 -0
  71. package/dist/src/codex-native-types.d.ts +92 -0
  72. package/dist/src/codex-native-types.js +15 -0
  73. package/dist/src/codex-native-types.js.map +1 -0
  74. package/dist/src/codex-permission-surface.d.ts +1 -1
  75. package/dist/src/codex-permission-surface.js +1 -1
  76. package/dist/src/codex-permission-surface.js.map +1 -1
  77. package/dist/src/codex-terminal-agent-adapter.js +3 -1
  78. package/dist/src/codex-terminal-agent-adapter.js.map +1 -1
  79. package/dist/src/conversation-list.d.ts +12 -0
  80. package/dist/src/conversation-list.js +30 -0
  81. package/dist/src/conversation-list.js.map +1 -0
  82. package/dist/src/conversation-route-dispatch.d.ts +13 -0
  83. package/dist/src/conversation-route-dispatch.js +66 -0
  84. package/dist/src/conversation-route-dispatch.js.map +1 -0
  85. package/dist/src/conversation-route-legacy.d.ts +18 -0
  86. package/dist/src/conversation-route-legacy.js +54 -0
  87. package/dist/src/conversation-route-legacy.js.map +1 -0
  88. package/dist/src/conversation-route-store.d.ts +51 -0
  89. package/dist/src/conversation-route-store.js +126 -0
  90. package/dist/src/conversation-route-store.js.map +1 -0
  91. package/dist/src/conversation-routing-cli-adapter.d.ts +12 -0
  92. package/dist/src/conversation-routing-cli-adapter.js +211 -0
  93. package/dist/src/conversation-routing-cli-adapter.js.map +1 -0
  94. package/dist/src/conversation-routing-commands.d.ts +11 -0
  95. package/dist/src/conversation-routing-commands.js +85 -0
  96. package/dist/src/conversation-routing-commands.js.map +1 -0
  97. package/dist/src/conversation-routing-home.d.ts +26 -0
  98. package/dist/src/conversation-routing-home.js +105 -0
  99. package/dist/src/conversation-routing-home.js.map +1 -0
  100. package/dist/src/conversation-routing-identity.d.ts +40 -0
  101. package/dist/src/conversation-routing-identity.js +174 -0
  102. package/dist/src/conversation-routing-identity.js.map +1 -0
  103. package/dist/src/conversation-runtime-route-store.d.ts +11 -0
  104. package/dist/src/conversation-runtime-route-store.js +118 -0
  105. package/dist/src/conversation-runtime-route-store.js.map +1 -0
  106. package/dist/src/desktop-async-interactions.d.ts +15 -0
  107. package/dist/src/desktop-async-interactions.js +88 -0
  108. package/dist/src/desktop-async-interactions.js.map +1 -0
  109. package/dist/src/desktop-async-state.d.ts +5 -0
  110. package/dist/src/desktop-async-state.js +53 -0
  111. package/dist/src/desktop-async-state.js.map +1 -0
  112. package/dist/src/desktop-cli-adapter.d.ts +7 -0
  113. package/dist/src/desktop-cli-adapter.js +322 -0
  114. package/dist/src/desktop-cli-adapter.js.map +1 -0
  115. package/dist/src/desktop-cli-controls.d.ts +9 -0
  116. package/dist/src/desktop-cli-controls.js +45 -0
  117. package/dist/src/desktop-cli-controls.js.map +1 -0
  118. package/dist/src/desktop-command-presentation.d.ts +2 -0
  119. package/dist/src/desktop-command-presentation.js +31 -0
  120. package/dist/src/desktop-command-presentation.js.map +1 -0
  121. package/dist/src/desktop-control-semantic.d.ts +8 -0
  122. package/dist/src/desktop-control-semantic.js +68 -0
  123. package/dist/src/desktop-control-semantic.js.map +1 -0
  124. package/dist/src/desktop-identity.d.ts +5 -0
  125. package/dist/src/desktop-identity.js +40 -0
  126. package/dist/src/desktop-identity.js.map +1 -0
  127. package/dist/src/desktop-interaction-projection.d.ts +57 -0
  128. package/dist/src/desktop-interaction-projection.js +196 -0
  129. package/dist/src/desktop-interaction-projection.js.map +1 -0
  130. package/dist/src/desktop-interaction-state.d.ts +3 -0
  131. package/dist/src/desktop-interaction-state.js +48 -0
  132. package/dist/src/desktop-interaction-state.js.map +1 -0
  133. package/dist/src/desktop-ipc-async-answer.d.ts +9 -0
  134. package/dist/src/desktop-ipc-async-answer.js +71 -0
  135. package/dist/src/desktop-ipc-async-answer.js.map +1 -0
  136. package/dist/src/desktop-ipc-client.d.ts +47 -0
  137. package/dist/src/desktop-ipc-client.js +400 -0
  138. package/dist/src/desktop-ipc-client.js.map +1 -0
  139. package/dist/src/desktop-ipc-native-operations.d.ts +11 -0
  140. package/dist/src/desktop-ipc-native-operations.js +126 -0
  141. package/dist/src/desktop-ipc-native-operations.js.map +1 -0
  142. package/dist/src/desktop-ipc-transport.d.ts +13 -0
  143. package/dist/src/desktop-ipc-transport.js +123 -0
  144. package/dist/src/desktop-ipc-transport.js.map +1 -0
  145. package/dist/src/desktop-list.d.ts +25 -0
  146. package/dist/src/desktop-list.js +55 -0
  147. package/dist/src/desktop-list.js.map +1 -0
  148. package/dist/src/desktop-metadata-reader.d.ts +30 -0
  149. package/dist/src/desktop-metadata-reader.js +182 -0
  150. package/dist/src/desktop-metadata-reader.js.map +1 -0
  151. package/dist/src/desktop-monitor.d.ts +4 -0
  152. package/dist/src/desktop-monitor.js +101 -0
  153. package/dist/src/desktop-monitor.js.map +1 -0
  154. package/dist/src/desktop-public-projection.d.ts +6 -0
  155. package/dist/src/desktop-public-projection.js +134 -0
  156. package/dist/src/desktop-public-projection.js.map +1 -0
  157. package/dist/src/desktop-request-interactions.d.ts +14 -0
  158. package/dist/src/desktop-request-interactions.js +144 -0
  159. package/dist/src/desktop-request-interactions.js.map +1 -0
  160. package/dist/src/desktop-response-dispatch.d.ts +14 -0
  161. package/dist/src/desktop-response-dispatch.js +19 -0
  162. package/dist/src/desktop-response-dispatch.js.map +1 -0
  163. package/dist/src/desktop-response-evidence.d.ts +4 -0
  164. package/dist/src/desktop-response-evidence.js +19 -0
  165. package/dist/src/desktop-response-evidence.js.map +1 -0
  166. package/dist/src/desktop-response-service.d.ts +11 -0
  167. package/dist/src/desktop-response-service.js +188 -0
  168. package/dist/src/desktop-response-service.js.map +1 -0
  169. package/dist/src/desktop-response-store.d.ts +35 -0
  170. package/dist/src/desktop-response-store.js +58 -0
  171. package/dist/src/desktop-response-store.js.map +1 -0
  172. package/dist/src/desktop-response-types.d.ts +20 -0
  173. package/dist/src/desktop-response-types.js +2 -0
  174. package/dist/src/desktop-response-types.js.map +1 -0
  175. package/dist/src/desktop-response-value.d.ts +6 -0
  176. package/dist/src/desktop-response-value.js +31 -0
  177. package/dist/src/desktop-response-value.js.map +1 -0
  178. package/dist/src/desktop-runtime.d.ts +153 -0
  179. package/dist/src/desktop-runtime.js +88 -0
  180. package/dist/src/desktop-runtime.js.map +1 -0
  181. package/dist/src/desktop-semantic.d.ts +21 -0
  182. package/dist/src/desktop-semantic.js +140 -0
  183. package/dist/src/desktop-semantic.js.map +1 -0
  184. package/dist/src/desktop-session-catalog.d.ts +68 -0
  185. package/dist/src/desktop-session-catalog.js +225 -0
  186. package/dist/src/desktop-session-catalog.js.map +1 -0
  187. package/dist/src/desktop-session-controls.d.ts +145 -0
  188. package/dist/src/desktop-session-controls.js +176 -0
  189. package/dist/src/desktop-session-controls.js.map +1 -0
  190. package/dist/src/desktop-sidebar-metadata.d.ts +27 -0
  191. package/dist/src/desktop-sidebar-metadata.js +83 -0
  192. package/dist/src/desktop-sidebar-metadata.js.map +1 -0
  193. package/dist/src/desktop-sidebar-projects.d.ts +10 -0
  194. package/dist/src/desktop-sidebar-projects.js +31 -0
  195. package/dist/src/desktop-sidebar-projects.js.map +1 -0
  196. package/dist/src/desktop-sidebar-selection.d.ts +28 -0
  197. package/dist/src/desktop-sidebar-selection.js +85 -0
  198. package/dist/src/desktop-sidebar-selection.js.map +1 -0
  199. package/dist/src/desktop-snapshot-details.d.ts +4 -0
  200. package/dist/src/desktop-snapshot-details.js +116 -0
  201. package/dist/src/desktop-snapshot-details.js.map +1 -0
  202. package/dist/src/desktop-snapshot.d.ts +11 -0
  203. package/dist/src/desktop-snapshot.js +276 -0
  204. package/dist/src/desktop-snapshot.js.map +1 -0
  205. package/dist/src/desktop-state-store.d.ts +72 -0
  206. package/dist/src/desktop-state-store.js +269 -0
  207. package/dist/src/desktop-state-store.js.map +1 -0
  208. package/dist/src/desktop-task-interactions.d.ts +10 -0
  209. package/dist/src/desktop-task-interactions.js +93 -0
  210. package/dist/src/desktop-task-interactions.js.map +1 -0
  211. package/dist/src/desktop-task-recovery.d.ts +38 -0
  212. package/dist/src/desktop-task-recovery.js +171 -0
  213. package/dist/src/desktop-task-recovery.js.map +1 -0
  214. package/dist/src/desktop-task-service.d.ts +54 -0
  215. package/dist/src/desktop-task-service.js +441 -0
  216. package/dist/src/desktop-task-service.js.map +1 -0
  217. package/dist/src/desktop-types.d.ts +281 -0
  218. package/dist/src/desktop-types.js +13 -0
  219. package/dist/src/desktop-types.js.map +1 -0
  220. package/dist/src/host-monitor-reconciliation.js +36 -4
  221. package/dist/src/host-monitor-reconciliation.js.map +1 -1
  222. package/dist/src/host-profile-runtime.js +7 -3
  223. package/dist/src/host-profile-runtime.js.map +1 -1
  224. package/dist/src/local-codex-cli-adapter.d.ts +7 -0
  225. package/dist/src/local-codex-cli-adapter.js +13 -0
  226. package/dist/src/local-codex-cli-adapter.js.map +1 -0
  227. package/dist/src/openclaw-callback-transport.js +2 -1
  228. package/dist/src/openclaw-callback-transport.js.map +1 -1
  229. package/dist/src/semantic-conversation-target.d.ts +4 -0
  230. package/dist/src/semantic-conversation-target.js +20 -0
  231. package/dist/src/semantic-conversation-target.js.map +1 -0
  232. package/dist/src/semantic-permission-control.js +47 -9
  233. package/dist/src/semantic-permission-control.js.map +1 -1
  234. package/dist/src/semantic-private-authority-offers.d.ts +1 -1
  235. package/dist/src/semantic-private-authority-offers.js +3 -1
  236. package/dist/src/semantic-private-authority-offers.js.map +1 -1
  237. package/dist/src/semantic-tool-command-helpers.d.ts +6 -0
  238. package/dist/src/semantic-tool-command-helpers.js +199 -78
  239. package/dist/src/semantic-tool-command-helpers.js.map +1 -1
  240. package/dist/src/semantic-tool-descriptions.d.ts +2 -1
  241. package/dist/src/semantic-tool-descriptions.js +81 -35
  242. package/dist/src/semantic-tool-descriptions.js.map +1 -1
  243. package/dist/src/semantic-tool-list-projection.js +66 -2
  244. package/dist/src/semantic-tool-list-projection.js.map +1 -1
  245. package/dist/src/semantic-tool-presentation.js +76 -7
  246. package/dist/src/semantic-tool-presentation.js.map +1 -1
  247. package/dist/src/semantic-tool-runtime.js +129 -29
  248. package/dist/src/semantic-tool-runtime.js.map +1 -1
  249. package/dist/src/semantic-tool-schemas.d.ts +410 -27
  250. package/dist/src/semantic-tool-schemas.js +176 -88
  251. package/dist/src/semantic-tool-schemas.js.map +1 -1
  252. package/dist/src/terminal-action-contracts.js +10 -6
  253. package/dist/src/terminal-action-contracts.js.map +1 -1
  254. package/dist/src/terminal-list-cli-adapter.d.ts +1 -0
  255. package/dist/src/terminal-list-cli-adapter.js +6 -3
  256. package/dist/src/terminal-list-cli-adapter.js.map +1 -1
  257. package/dist/src/terminal-model-control-profile.d.ts +3 -1
  258. package/dist/src/terminal-model-control-profile.js +15 -7
  259. package/dist/src/terminal-model-control-profile.js.map +1 -1
  260. package/dist/src/terminal-monitor-decision-policy.d.ts +1 -1
  261. package/dist/src/terminal-native-inspection-profile.js +4 -0
  262. package/dist/src/terminal-native-inspection-profile.js.map +1 -1
  263. package/dist/src/terminal-permission-control-list-projection.d.ts +1 -1
  264. package/dist/src/terminal-permission-control.js +5 -1
  265. package/dist/src/terminal-permission-control.js.map +1 -1
  266. package/dist/src/terminal-questionnaire-adapter.js +5 -2
  267. package/dist/src/terminal-questionnaire-adapter.js.map +1 -1
  268. package/dist/src/terminal-user-send-intent.d.ts +2 -0
  269. package/dist/src/terminal-user-send-intent.js +11 -3
  270. package/dist/src/terminal-user-send-intent.js.map +1 -1
  271. package/docs/architecture/current-architecture.md +313 -0
  272. package/docs/architecture/interactive-terminal-response.md +276 -0
  273. package/docs/architecture/issue-126-final-report.md +248 -0
  274. package/docs/architecture/orchestration-refactor-history.md +2987 -0
  275. package/docs/architecture/orchestration-refactor.md +21 -0
  276. package/docs/backend-task-recovery.md +89 -0
  277. package/docs/bidirectional-agent-protocol.md +260 -0
  278. package/docs/codex-0.160.0-compatibility.md +126 -0
  279. package/docs/codex-cli-native-compatibility.md +246 -0
  280. package/docs/codex-desktop-compatibility.md +414 -0
  281. package/docs/codex-permissions.md +12 -1
  282. package/docs/openclaw-operations.md +281 -0
  283. package/docs/openclaw-session-turn-delivery-requirement.md +45 -0
  284. package/docs/operator-guide.md +543 -0
  285. package/docs/storage-and-logging.md +91 -0
  286. package/docs/test-performance-issue-108.md +80 -0
  287. package/docs/test-performance-issue-120.md +226 -0
  288. package/docs/testing.md +628 -0
  289. package/openclaw.plugin.json +7 -3
  290. package/package.json +6 -12
  291. package/templates/openclaw-skills/agent-knock-knock/SKILL.md +69 -18
@@ -0,0 +1,628 @@
1
+ # Testing
2
+
3
+ Agent Knock Knock keeps every deterministic, integration, compatibility, and
4
+ regression test, but it does not charge the full process-heavy suite to every
5
+ edit. The canonical classification is `test/test-tiers.json`. A manifest test
6
+ and every tier runner fail before execution if a test file is missing,
7
+ duplicated, or unclassified.
8
+
9
+ For periodic reviews of existing test value, use the repository's
10
+ [test-audit skill](../.agents/skills/test-audit/SKILL.md). It records the
11
+ contract each case protects before consolidating or deleting coverage, and
12
+ follows the fast-only development policy below.
13
+
14
+ `npm run architecture:dashboard` runs the same fail-closed architecture gate
15
+ as `validate:architecture` and prints the current health snapshot. It reports
16
+ total production LOC without gating it, while cycles, hard/default function
17
+ violations, large-file concentration, semantic tool counts, and bundled Skill
18
+ synchronization have explicit non-regression budgets. See
19
+ [`docs/architecture/current-architecture.md`](./architecture/current-architecture.md).
20
+
21
+ ## Test tiers
22
+
23
+ | Command | Purpose | When to run |
24
+ | --- | --- | --- |
25
+ | `npm run test:fast` | Deterministic unit/component tests without test-level child processes | Every development, debugging, refactoring, review, and local-install loop |
26
+ | `npm run test:integration` | CLI subprocess, monitor, SQLite, Store locking, lifecycle, installer, and compatibility fixtures | Release-gate component; do not run during ordinary development or local verification |
27
+ | `npm run test:affected` | Complete fast tier plus mapped integration tests; unknown or shared-core changes run the full tier | Maintainer/release diagnostics only; not an ordinary development command |
28
+ | `npm run test:full` | The exact union of fast and integration tests | Immediate pre-publication gate for an actual npm or ClawHub release |
29
+ | `npm test` | Compatibility alias for `test:full` | Same release-only boundary as `test:full` |
30
+ | `npm run test:release` | Full suite, isolated current-build OpenClaw compatibility check, ClawHub runtime validation, and ClawHub publish dry-run | Immediate pre-publication gate for an actual npm or ClawHub release |
31
+ | `npm run test:release:live` | The release tier plus credentialed native Codex and Claude lifecycle smoke/attestation | Optional release-time diagnostic with dedicated prepared tmux panes |
32
+ | `npm run compat:openclaw` | Full minimum/current/API-boundary OpenClaw compatibility matrix | Periodic maintainer check and any change to declared compatibility floors; not required for every package release |
33
+
34
+ During normal development, debugging, refactoring, review, local installation,
35
+ and local verification, run only `npm run test:fast`. Type checking, builds,
36
+ architecture/evidence validators, installation, and non-test health checks may be
37
+ run when relevant, but they do not authorize a broader test tier. Run the
38
+ full/release suite only immediately before an actual npm or ClawHub
39
+ publication. A local OpenClaw install is not a package release.
40
+
41
+ The live release tier can make authenticated coding-agent turns. It is never
42
+ selected by `npm test` or `test:release`; opting in is an explicit operational
43
+ decision. The ordinary release tier builds in temporary state and does not
44
+ control a real coding-agent pane.
45
+
46
+ Routine releases exercise the OpenClaw version pinned by
47
+ `openclaw.build.openclawVersion`. The slower minimum Host, minimum Plugin API,
48
+ and adjacent unsupported boundary checks remain available through
49
+ `npm run compat:openclaw` for periodic compatibility review. Run the full
50
+ matrix whenever a declared OpenClaw compatibility floor changes.
51
+
52
+ The live gate requires both complete panes, a new private evidence path outside
53
+ the repository, the environment opt-in, and the command-line confirmation. It
54
+ forwards the exact arguments to the single-attempt lifecycle runner and then
55
+ verifies the resulting Codex+Claude matrix evidence:
56
+
57
+ ```bash
58
+ AKK_RUN_LIVE_LIFECYCLE_SMOKE=1 npm run test:release:live -- \
59
+ --confirm-live \
60
+ --codex-target <session:window.pane> \
61
+ --codex-expected-pane-pid <pid> \
62
+ --codex-expected-version <version> \
63
+ --claude-target <session:window.pane> \
64
+ --claude-expected-pane-pid <pid> \
65
+ --claude-expected-version <version> \
66
+ --evidence </absolute/private/new-evidence.json>
67
+ ```
68
+
69
+ The runner builds once per tier and passes an explicit cross-platform file list
70
+ to Node instead of relying on shell glob behavior. Its default file concurrency
71
+ is capped at four because each integration worker recursively starts CLI and fake
72
+ terminal processes; higher values made both wall time and bounded test-fixture
73
+ timeouts worse on the maintainer machine. Override it with
74
+ `AKK_TEST_CONCURRENCY` for a controlled benchmark. The runner also gives Node
75
+ child processes a shared bytecode cache under the operating-system temporary
76
+ directory. Override `NODE_COMPILE_CACHE` when profiling a particular cache, or
77
+ point it at a new `mktemp -d` directory for a cold-cache comparison.
78
+
79
+ ## Affected tests
80
+
81
+ `test:affected` builds once, reads changed and untracked paths without shell
82
+ globs, and always runs the complete fast tier. By default it compares `HEAD`
83
+ with the current index and worktree. Supply an explicit base to include branch
84
+ commits as well as staged, unstaged, and untracked changes:
85
+
86
+ ```bash
87
+ npm run test:affected
88
+ npm run test:affected -- --base origin/main
89
+ ```
90
+
91
+ Known production domains map to no more than five exact integration-tier
92
+ witnesses. A changed integration test selects itself, a known test helper
93
+ selects its transitive integration consumers, and a changed fast test or
94
+ documentation file needs no additional integration worker. An additive
95
+ `test/test-tiers.json` edit narrows only when every new entry is also a changed
96
+ test and the prior tier order is preserved. `package.json` plus
97
+ `package-lock.json` narrow only when their parsed content proves one synchronized
98
+ version-only change. Deletion, tier movement, reordering, dependency or script
99
+ changes, and missing content proof select `test:full`.
100
+
101
+ Selection remains fail-closed for an unreadable Git diff, a stale ownership
102
+ mapping, an unknown path, exact Store/protocol modules, shared production
103
+ kernels, or selector/architecture authority files. `src/store.ts` and
104
+ `src/protocol.ts` cannot be narrowed by accompanying tests or manifest proof.
105
+
106
+ This selector remains documented for release-maintainer diagnostics. Under the
107
+ normal-development policy above, use `npm run test:fast` instead; an actual
108
+ publication uses the complete full/release gate rather than treating affected
109
+ selection as sufficient evidence.
110
+
111
+ ## Targeted integration map
112
+
113
+ The map below records which integration witnesses own each subsystem. It is for
114
+ release-gate triage and failure diagnosis, not permission to run integration
115
+ tests during ordinary development or local installation. In those workflows,
116
+ run only `npm run test:fast`. Paths are source paths under `test/`, and the tier
117
+ runner handles their compiled `dist` paths.
118
+
119
+ Pass one or more exact manifest paths after `--` to run only those integration
120
+ files. The runner rejects duplicates, unknown paths, and files from the fast
121
+ tier, so a typo cannot silently weaken the intended check:
122
+
123
+ ```bash
124
+ npm run test:integration -- \
125
+ test/codex-store-adapter.test.ts \
126
+ test/stale-bound-resume-cli.test.ts
127
+ ```
128
+
129
+ | Changed subsystem | Targeted integration files |
130
+ | --- | --- |
131
+ | CLI parser, help, version, doctor, redaction | `test/cli-ux.test.ts` |
132
+ | Raw/managed send, composer/Enter, acceptance and receipt fences | `test/shards/agent-cli-terminal-send-gates.test.ts`, `test/shards/agent-cli-composer-replay.test.ts`, `test/shards/agent-cli-session-acceptance.test.ts`, `test/shards/agent-cli-receipt-fences.test.ts`; add `test/codex-no-rollout-binding-cli.test.ts` for virgin attachment |
133
+ | Dispatch authorization, locks, retry and recovery | `test/shards/agent-cli-dispatch-authority.test.ts`, `test/shards/agent-cli-control-locks.test.ts`, `test/shards/agent-cli-dispatch-recovery.test.ts`, `test/shards/agent-cli-receipt-fences.test.ts` |
134
+ | Callback outbox, responder, retry, Gateway wake and close races | `test/callback-cli.test.ts`, `test/openclaw-plugin-contract.test.ts`, `test/shards/agent-cli-claude-callback.test.ts`, `test/shards/agent-cli-monitor-lifecycle.test.ts`, `test/shards/agent-cli-monitor-recovery.test.ts` |
135
+ | Monitor completion, approval context, cancellation and renewal | `test/shards/agent-cli-monitor-lifecycle.test.ts`, `test/shards/agent-cli-monitor-recovery.test.ts`, `test/shards/agent-cli-monitor-approval-context.test.ts`, `test/shards/agent-cli-control-locks.test.ts` |
136
+ | Delegate, workspace and terminal selection | `test/delegate-cli.test.ts`, `test/session-selector-cli.test.ts`, `test/management-cli.test.ts` |
137
+ | List, status, available actions and terminal discovery | `test/management-cli.test.ts`, `test/session-selector-cli.test.ts`; add `test/codex-no-rollout-binding-cli.test.ts` for binding conflicts |
138
+ | Codex SQLite/state DB, rollout fd, WAL, candidate discovery and version filtering | `test/codex-store-adapter.test.ts`, `test/codex-no-rollout-binding-cli.test.ts`, `test/stale-bound-resume-cli.test.ts` |
139
+ | Virgin attach, reconcile-binding, PID incarnation/reuse and orphan recovery | `test/codex-no-rollout-binding-cli.test.ts`, `test/native-thread-ownership-cli.test.ts`, `test/stale-bound-resume-cli.test.ts`, `test/turn-session-binding-cli.test.ts`, `test/shards/agent-cli-dispatch-recovery.test.ts` |
140
+ | Native New/Clear/Resume transitions and guards | `test/native-thread-lifecycle-cli.test.ts`, `test/native-thread-lifecycle-recovery-cli.test.ts`, `test/native-thread-ownership-cli.test.ts`, `test/native-lifecycle-command-guard-cli.test.ts`, `test/codex-sticky-rollout-lifecycle-cli.test.ts`, `test/stale-bound-resume-cli.test.ts`, `test/codex-no-rollout-binding-cli.test.ts` |
141
+ | Store, Session, Turn, writer protocol, migration and locks | `test/store.test.ts`, `test/store-protocol-cli.test.ts`, `test/turn-session-binding-cli.test.ts`; add `test/session-selector-cli.test.ts` for projections |
142
+ | OpenClaw tool schemas, slash routing, supervisor and manifest | `test/openclaw-plugin-contract.test.ts`, `test/management-cli.test.ts`; add `test/install-openclaw-cli.test.ts` for installation/skill sync |
143
+ | Installer trust, force, update and restart readiness | `test/install-openclaw-cli.test.ts` |
144
+ | Runtime logs, redaction and permissions | `test/runtime-log.test.ts` |
145
+ | Lifecycle evidence, verifier and release guards | `test/live-lifecycle-verifier.test.ts`, `test/live-smoke-guards.test.ts` |
146
+ | Compatibility or legacy identifiers/protocols | The exact domain file plus `test/store.test.ts`, `test/store-protocol-cli.test.ts`, `test/turn-session-binding-cli.test.ts`, or `test/session-selector-cli.test.ts` as applicable |
147
+
148
+ The 11 former `agent-cli.test.ts` domains map one-to-one to exact integration
149
+ manifest entries; use these names directly rather than a shell wildcard:
150
+
151
+ | Agent CLI domain | Exact manifest path |
152
+ | --- | --- |
153
+ | Claude callback and response delivery | `test/shards/agent-cli-claude-callback.test.ts` |
154
+ | Composer replay and paste-window submission | `test/shards/agent-cli-composer-replay.test.ts` |
155
+ | Terminal mutation and dispatch locks | `test/shards/agent-cli-control-locks.test.ts` |
156
+ | Dispatch ownership and authorization | `test/shards/agent-cli-dispatch-authority.test.ts` |
157
+ | Interrupted dispatch recovery | `test/shards/agent-cli-dispatch-recovery.test.ts` |
158
+ | Monitor approval context | `test/shards/agent-cli-monitor-approval-context.test.ts` |
159
+ | Monitor completion lifecycle | `test/shards/agent-cli-monitor-lifecycle.test.ts` |
160
+ | Monitor/callback recovery | `test/shards/agent-cli-monitor-recovery.test.ts` |
161
+ | Acceptance and delivery receipt fences | `test/shards/agent-cli-receipt-fences.test.ts` |
162
+ | Session/Turn acceptance and bookkeeping | `test/shards/agent-cli-session-acceptance.test.ts` |
163
+ | Raw and managed terminal send gates | `test/shards/agent-cli-terminal-send-gates.test.ts` |
164
+
165
+ The mapping diagnoses a release gate; it never replaces the complete
166
+ pre-publication full/release suite.
167
+ Safety fences from #87, native lifecycle smoke tooling from #88, Store upgrade
168
+ paths, Codex 0.146.0/0.146.1/0.147.0/0.148.0/0.149.1/0.150.1/0.151.0/0.153.0/0.153.4/0.154.0/0.155.1, OpenClaw boundaries, and verified
169
+ Claude Code 2.1.218/2.1.226/2.1.237/2.1.251/2.1.259/2.1.263/2.1.266/2.1.267/2.1.285 schemas
170
+ remain covered.
171
+
172
+ The [Codex 0.157.1 compatibility review](./codex-0.157.1-compatibility.md)
173
+ records partial fullscreen/status support and the known paginated-history
174
+ boundary. Managed completion and native thread transitions remain unavailable
175
+ on 0.157.0/0.157.1; passing the test suite does not promote those versions to
176
+ verified native-action profiles.
177
+
178
+ The [Claude Code 2.1.285 compatibility review](./claude-2.1.285-compatibility.md)
179
+ records native observations, the attachment ordering repair, and explicit
180
+ coverage limits for this local-only update.
181
+
182
+ ## #206 Terminal Watch fast contract
183
+
184
+ The fast tier owns the deterministic Terminal Watch contract:
185
+
186
+ | Fast witness | Contract proved |
187
+ | --- | --- |
188
+ | `test/terminal-watch-store.test.ts` | Owner-private atomic schema-v3 records under `terminal-watches/`, legacy-v1/v2 notify-only normalization, strict interaction aggregate validation, revision CAS, exact provider anchors plus terminal-activity anchors/checkpoints and immutable warnings, and `writer -> per-watch` lock order |
189
+ | `test/terminal-watch-service.test.ts` | Restart/list recovery, timeout and terminal settlement, actionable/manual questionnaire projection and redraw dedupe, exact observation fences, terminal-activity checkpoint persistence, callback claim-crash recovery, retry, and deterministic idempotency |
190
+ | `test/durable-notification-kernel.test.ts` | Store-neutral callback/Watch lease, retry timing, exhaustion, and settlement authorization policy |
191
+ | `test/terminal-submission-acceptance.test.ts`, `test/claude-local-transcript-provider.test.ts` | Preferred exact Codex rollout and Claude current-turn transcript anchors; source-less Codex candidate-set acceptance over anchored plus current roots, including closed-FD frozen-file scans and fail-closed replacement/deletion/multiple-acceptor evidence; drift invalidates an already exact-anchored Watch, while absence or structural incompatibility at manual-Watch creation can be downgraded to a warning and terminal-activity fallback |
192
+ | `test/terminal-watch-cli-adapter.test.ts`, `test/terminal-watch-callback-cli-adapter.test.ts` | Exact-task capture when available; best-effort `terminal_activity` fallback after observed activity and consecutive stable-idle sweeps; `watch_mode`/`confidence`/warning projection; no Session/Turn ownership; exact-Watch same-controller Status and one-shot `respond_interaction({watch_id})`; managed-first responder arbitration; zero-input release versus uncertain dispatch; activity/manual notification-only behavior; hard failure only for an absent/unobservable exact terminal or unwritable Store; privacy-safe callbacks that never present stable idle as exact task completion; and restart-safe exact fallback anchors |
193
+ | `test/terminal-agent-bridge.test.ts`, `test/terminal-list-action-policy.test.ts`, `test/terminal-action-projection.test.ts`, `test/terminal-list-renderer.test.ts`, `test/openclaw-plugin-helpers.test.ts`, `test/quickstart-docs.test.ts` | Broad read-only Watch discovery, direct user-explicit Watch by exact `terminal_id` even without advertisement, Watch status/unwatch routing and formatting, action-contract v30 semantic-ID-only projection including same-controller status-bound native-interaction response, exact Codex model-control residue repair, and explicit foreground identification, three-axis terminal status, Codex and Claude Code user-priority replace-current-Composer delivery without visibility/exactness or post-text Composer vetoes, automatic fallback Watch callback semantics, and the documented terminal selection → exact-task-or-activity Watch workflow |
194
+
195
+ The current public surface has 22 OpenClaw tools. Terminal Watch adds the
196
+ `watch-terminal`, `watch-status`, `unwatch-terminal`, and `reconcile-watches`
197
+ CLI entries. OpenClaw's supervisor coordinates managed-monitor and Watch
198
+ reconciliation in the same non-overlapping lifecycle but with independent error
199
+ boundaries, so either side can make progress when the other fails. The
200
+ process-level plugin contract remains in the integration tier and is exercised
201
+ only as part of an authorized pre-publication full/release gate.
202
+
203
+ The fallback completion-shaped event is deliberately a weaker contract. Tests
204
+ must assert that it is emitted only after the selected terminal/process has
205
+ shown activity and then stable idle across consecutive observations, carries
206
+ `watch_mode="terminal_activity"` and `confidence="best_effort"`, and tells the
207
+ controller that the signal is not exact task-completion proof. An initially
208
+ idle or unknown terminal cannot settle until activity has first been observed.
209
+
210
+ The v30 fast contract also proves that structured model actions expose semantic
211
+ IDs only: Watch uses `terminal_id`; send uses mutually exclusive `session_id` or
212
+ `terminal_id`; native inspection, new, resume, and reconcile use their documented
213
+ terminal/session/thread IDs; and approve or handoff retains explicit-confirmation
214
+ behavior without projecting opaque tokens, fingerprints, revisions, binding
215
+ IDs/generations, composer digests, draft text, or handoff-only live-native-UUID
216
+ fences. Questionnaire response uses a fresh same-controller Status projection,
217
+ one opaque interaction ID, semantic answer IDs or bounded text, and a durable
218
+ one-shot reservation; changed, manual-required, secret, or uncertain state stays
219
+ fail-closed. Codex and Claude Code `terminal_user_explicit` each prove one
220
+ clear/inject/paste-wait/Enter sequence even when the Composer is invisible,
221
+ truncated, unstable, or nonempty, with no post-text Composer veto. Codex uses
222
+ `C-u`; Claude Code uses a sentinel-backed native `C-s` stash-clear transaction that is independent of the cursor position and does not interrupt an active turn, then proves the main Composer empty. Native inspection and
223
+ lifecycle input remain exact-empty-only; managed delivery may require exact
224
+ empty before input, but either agent's user-explicit Enter is not post-text
225
+ gated. Once clear or request input may have occurred, uncertainty forbids an
226
+ automatic retry.
227
+ The Send result contract independently proves physical dispatch, native
228
+ acceptance, management mode, observation mode, and callback/interaction
229
+ capabilities. Durable close audit facts come from dispatch receipts rather than
230
+ human-readable close prose. Candidate-set recovery may leave a provisional Turn
231
+ pending until exactly one rollout accepts its immutable request hash; it never
232
+ replays terminal input while resolving that identity.
233
+ The semantic
234
+ `native_thread_id` remains public for resume. The plugin/CLI still derives and
235
+ revalidates those private fences under lock. Store format remains 1 and the
236
+ Terminal Watch schema is 3; writer protocol 9 fences capability-checked paginated task
237
+ bindings and private native-question checkpoints from older writers. It retains
238
+ the manual-interaction notification state and bounded callback metadata introduced
239
+ in writer protocol 7. The Watch schema version fences the response aggregate.
240
+
241
+ ## Profiling
242
+
243
+ Run the same tier, Node version, concurrency, machine, and compile-cache mode
244
+ before and after a performance change:
245
+
246
+ ```bash
247
+ npm run test:profile -- --output /tmp/akk-test-profile.json
248
+ npm run test:profile -- integration --output /tmp/akk-integration-profile.json
249
+ ```
250
+
251
+ The reporter records the commit and dirty state, Node/platform/CPU metadata,
252
+ concurrency and cache path, total wall duration, counts, per-file worker
253
+ duration, and every test duration. It prints the 20 slowest files and tests and
254
+ writes the complete JSON report when `--output` is supplied. Set an explicit
255
+ concurrency for a controlled comparison:
256
+
257
+ ```bash
258
+ AKK_TEST_CONCURRENCY=8 npm run test:profile -- --output /tmp/akk-profile-c8.json
259
+ ```
260
+
261
+ Do not reduce production polling/settle windows, disable process isolation, or
262
+ force-exit the runner to improve a benchmark. Split independent file workers,
263
+ inject clocks/providers where semantics permit it, and retain thin real-process
264
+ coverage for process, WAL/checkpoint, fs-lock, and lifecycle boundaries.
265
+
266
+ ## #126 callback in-process migration
267
+
268
+ Eight once-per-file executable starts in `test/callback-cli.test.ts` now use the
269
+ same `parseCliCommand` to `executeCliCommand` path imported by the executable.
270
+ Their original assertions remain in place. The migration maps each former
271
+ black-box case to the service invariant it exercises and the process boundary
272
+ that remains black-box:
273
+
274
+ | Former executable case | Imported service invariant | Retained real boundary |
275
+ | --- | --- | --- |
276
+ | Late callback after Turn release | Reject before state or event mutation | Emitted callback argv/stdout/exit goldens |
277
+ | Corrupted event log | Fail closed on Store validation | Emitted callback error projection |
278
+ | Failed question notification | Preserve `waiting_for_openclaw` and failed outbox state | Fake OpenClaw Gateway child failure |
279
+ | Close after failed delivery | Keep the failed outbox retryable and immutable | Gateway child plus separate executable concurrency witnesses |
280
+ | Reused message ID with changed payload | Reject payload mutation under an existing claim | Retained callback executable helper |
281
+ | Explicit Gateway URL/token retry | Persist authentication while redacting public state | Fake OpenClaw environment and argv |
282
+ | Automatic transient retry | Preserve retry state and monitor scheduling | Real retry-monitor and Gateway children |
283
+ | Manual retry during automatic attempt | Report the exact live lease without mutation | Concurrent winner/loser CLI processes |
284
+
285
+ The dynamic callback test path therefore starts eight fewer CLI processes. The
286
+ reproducible static evidence moves from 48 to 40 included startup sites
287
+ (`cli_process` 38 to 30), while all 10 fake-Node startup sites remain. The
288
+ machine-readable `callback-outbox` migration in
289
+ `config/public-contract-witnesses.json` ties the old executable witnesses to
290
+ the callback policy, settlement, and transport service invariants and to the
291
+ retained CLI, Claude, and OpenClaw boundaries.
292
+
293
+ ## #126 CLI UX and native-ownership in-process migration
294
+
295
+ The second migration slice routes 21 normal invocations through
296
+ `parseCliCommand` and `executeCliCommand`: eight help, version, doctor, and
297
+ redaction invocations plus thirteen native-ownership sends. The test and
298
+ assertion inventories are unchanged.
299
+
300
+ | Former executable cases | Imported service invariant | Retained real boundary |
301
+ | --- | --- | --- |
302
+ | Help and version aliases | Exact parser aliases, stdout bytes, and success status | CLI import isolation and copied-distribution doctor executable |
303
+ | Runnable-doctor failure and public redaction | Probe result projection and secret-free JSON | Copied-distribution doctor argv/stdout/OS-exit plus real-CLI runtime-log redaction |
304
+ | Codex and Claude native ownership sends | Exact PID/UUID, Store, binding-generation, and stale-ledger authority | Codex attach, handoff, lifecycle recovery, and terminal-send executable suites |
305
+
306
+ The static metric removes the two direct native-ownership startup sites and the
307
+ shared normal CLI UX startup site, moving the current evidence from 40 to 37
308
+ included sites (`cli_process` 30 to 27). All fake-Node sites remain. Claude
309
+ native inspection was also audited, but remains executable-backed because its
310
+ PATH-scoped `ps` and `tmux` discovery is not equivalent through the current
311
+ in-process dependency seam. Crash injection, OS exit, process competition,
312
+ file-lock, monitor-PID, nested Gateway approval, updater, and terminal-process
313
+ witnesses in `agent-cli-fixtures.ts` remain process-backed.
314
+
315
+ The machine-readable `cli-runtime` and `terminal-binding-authority` mappings in
316
+ `config/public-contract-witnesses.json` connect the migrated cases to focused
317
+ service invariants and retained executable witnesses.
318
+
319
+ ### Doctor capability boundary tier
320
+
321
+ Doctor capability evaluation and invalid-timeout policy remain in the fast
322
+ tier. The four tests that intentionally execute fake Node and shell programs
323
+ live in `test/doctor-capabilities-process.test.ts` in the integration tier.
324
+ They still prove exact argv, version parsing, executable permissions, timeout,
325
+ non-zero exit, missing executable, and malformed-output behavior; only their
326
+ tier classification changed.
327
+
328
+ ## #126 management, selector, and Session-binding in-process migration
329
+
330
+ The third migration slice removes the outer CLI process from 50 normal command
331
+ invocation expressions across 24 tests while preserving all 298 assertion call
332
+ sites. `management-cli` and `session-selector-cli` now exercise the executable's
333
+ same `parseCliCommand` to `executeCliCommand` path for list, status, selector,
334
+ static-terminal, and synthetic-acceptance behavior. The six record-only
335
+ `turn-session-binding-cli` callbacks use that path for Session authority checks.
336
+
337
+ | Former executable cases | Imported service invariant | Retained real boundary |
338
+ | --- | --- | --- |
339
+ | Ten management list/status invocations | Exact JSON projection, trace redaction, static terminal observation, and action-contract v24 | Standalone executable list/status in `store-protocol-cli`, copied-distribution CLI output/exit |
340
+ | Thirty-four selector, status, send, respond, and approve invocations | Deterministic ambiguity failures, canonical ownership, cross-Store fencing, semantic-ID routing, and private fence derivation | Codex binding and terminal-send executable suites with real terminal observation/input |
341
+ | Six record-only callback binding invocations | Protocol-3 Session presence, generation, process evidence, route-rename, and protocol-2 compatibility | Callback executable argv/exit, Gateway, retry, and concurrency suites |
342
+
343
+ The static metric removes one CLI startup site from each migrated file, moving
344
+ the evidence from 37 to 34 included sites (`cli_process` 27 to 24). All 10
345
+ fake-Node sites remain. Writer-protocol mismatch and fake-tmux observation in
346
+ `store-protocol-cli`, callback Gateway/concurrency, Store crash and migration,
347
+ terminal input, lock competition, monitor PID, and OS-exit witnesses remain
348
+ process-backed.
349
+
350
+ The machine-readable `callback-outbox`, `terminal-binding-authority`, and
351
+ `terminal-list-renderer` mappings tie each former executable family to its fast
352
+ service invariant and to a separate retained real-process witness.
353
+
354
+ ## #126 deterministic dispatch-admission in-process migration
355
+
356
+ The fourth migration slice removes 27 outer CLI process starts across 23 tests
357
+ while preserving all 63 assertion call sites in those cases. The commands still
358
+ enter through `parseCliCommand` and `executeCliCommand`; only the redundant Node
359
+ executable boundary is removed.
360
+
361
+ | Former executable cases | Imported service invariant | Retained real boundary |
362
+ | --- | --- | --- |
363
+ | Ten delegate routing tests (14 invocations) | Deterministic agent, workspace, pane-incarnation, and exact-selector routing over the production static terminal/process adapters | Dispatch-authority, recovery, and terminal-send executable suites |
364
+ | Twelve native slash-command guard cases | Every ordinary send/respond alias rejects before Store creation or terminal input | Native lifecycle and lifecycle-recovery crash/terminal executables |
365
+ | One static-fixture acceptance case | Synthetic transport cannot become native acceptance without the explicit opt-in | Session-acceptance, receipt-fence, and terminal-send executable suites |
366
+
367
+ The delegate fixture continues to use the production
368
+ `StaticTerminalProcessSource` selected by `--processes-json`. Its former fake
369
+ `ps` executable supplied only a deterministic Codex process-birth string and
370
+ was not a PATH-discovery assertion, so the imported command now injects that
371
+ same typed observation directly. PATH-scoped process discovery remains covered
372
+ by its dedicated executable tests. Environment, cwd, clock, output, and exit
373
+ state are scoped through the CLI async-local runtime; no test mutates process
374
+ globals.
375
+
376
+ The static metric removes one CLI startup site from each migrated file, moving
377
+ the evidence from 34 to 31 included sites (`cli_process` 24 to 21). All 10
378
+ fake-Node sites remain. Test tiers are unchanged: these filesystem and terminal
379
+ component cases remain in the integration tier even though their redundant
380
+ outer executable was removed.
381
+
382
+ The machine-readable `terminal-dispatch-policy` and
383
+ `terminal-dispatch-ledger` mappings connect the imported cases to focused
384
+ policy/acceptance invariants and to retained real-process witnesses for argv,
385
+ OS exit, terminal input, crash recovery, locks, concurrency, monitor PID,
386
+ Gateway transport, and Store writer fencing.
387
+
388
+ ## #126 callback normal-command in-process migration
389
+
390
+ The fifth migration slice routes all 20 successful invocations that formerly
391
+ shared the generic synchronous callback CLI helper through `runInProcessCli`,
392
+ and therefore through the production `parseCliCommand` to `executeCliCommand`
393
+ path. The 13 affected tests and all 160 assertion call sites remain. Nine tests
394
+ become async; four were already async.
395
+
396
+ | Former normal callback cases | Invocations | Imported service invariant | Retained real boundary |
397
+ | --- | ---: | --- | --- |
398
+ | Record-only creation and duplicate suppression | 3 | Message identity, Turn identity, event persistence, and idempotency | Concurrent duplicate CLI processes |
399
+ | Direct Gateway delivery and legacy identity derivation | 2 | Gateway payload projection, token redaction, and legacy Session/Turn fallback | Production fake-OpenClaw child processes |
400
+ | Close, retry, rebinding, and persisted authentication | 7 | Immutable outbox, close-state preservation, binding generation, and URL/token routing | Gateway success/failure helpers and the close-during-delivery child |
401
+ | Startup reconciliation and accepted-wake settlement | 4 | Retry-monitor launch/reconciliation and no-redelivery settlement | Real detached retry-monitor and Gateway children |
402
+ | `chat.send`, `agent.wait`, legacy plan, and `sessions.send` delivery | 4 | Accepted delivery plans, run observation, exact argv, and event recording | Production Gateway child-process transport |
403
+
404
+ Environment overlays remain scoped by the CLI async-local runtime. `PATH` and
405
+ Gateway-token overrides reach the production OpenClaw transport through
406
+ `cliEnv()`, while the transport continues to start the fake Gateway executable
407
+ itself. The tests do not mutate `process.env`, change cwd, observe the outer CLI
408
+ PID, or assert OS exit. The close-during-delivery and callback-retry competition
409
+ tests still use separate real CLI processes where process identity and file
410
+ competition are the behavior under test.
411
+
412
+ The in-process `callback` and `retry-callback` commands in this slice complete
413
+ their delivered or accepted settlement before returning. Reconciliation only
414
+ persists the PID of the real retry-monitor child it launches; it does not claim
415
+ an attempt for the in-process caller. No migrated case waits for an outer CLI
416
+ `attempt_pid` to die, while the manual in-flight and winner/loser lease cases
417
+ remain on their existing imported-failure and real-process paths.
418
+
419
+ Four explicit callback CLI startup sites remain: Gateway failure and success
420
+ helpers, the asynchronous concurrency helper, and the direct retry loser. They
421
+ perform 9, 6, 4, and 1 dynamic CLI starts respectively in this file. The
422
+ generic helper removes exactly 20 outer CLI starts without removing any
423
+ Gateway or retry-monitor start. `test/runtime-log.test.ts` also remains
424
+ process-backed because it proves the executable wrapper's `cli_start` and
425
+ `cli_finish` records, default `AKK_LOG_DIR` environment routing, and redaction.
426
+
427
+ The static metric moves from 31 to 30 included startup sites (`cli_process` 21
428
+ to 20); all 10 fake-Node sites remain. The machine-readable
429
+ `callback-cli-in-process` witness records the moved normal-command cases, while
430
+ `callback-cli-boundary` now names the retained winner/loser executable race.
431
+
432
+ ## #126 composer not-accepted in-process migration
433
+
434
+ The sixth migration slice routes the multilingual Codex composer
435
+ not-accepted command through `runInProcessCli`, and therefore through the same
436
+ production `parseCliCommand` to `executeCliCommand` path. The test still uses
437
+ the real tmux adapter executable, preserves the exact multiline composer after
438
+ paste and after Enter, disables synthetic acceptance, and asserts that AKK
439
+ dispatches exactly one `C-m`. Its durable not-accepted receipt, close recovery,
440
+ and public JSON assertions are unchanged; only the outer Node CLI wrapper is
441
+ removed. The explicitly injected process runner remains a visible
442
+ `other_process_or_adapter` site and still starts the fake tmux, `ps`, and
443
+ `lsof` executables with the command-scoped environment.
444
+
445
+ This removes one real CLI startup site without moving or hiding a spawn. The
446
+ static evidence becomes 29 included sites (`cli_process` 19 plus the unchanged
447
+ 10 fake-Node sites), a 39.58% reduction from the frozen 48-site baseline. The
448
+ machine-readable `terminal-composer-in-process` witness records the imported
449
+ command invariant, while raw/managed send, receipt-fence, crash, lock,
450
+ acceptance, and terminal-input executable witnesses remain process-backed.
451
+
452
+ ## #126 shared agent CLI in-process migration
453
+
454
+ The seventh migration slice removes the synchronous outer-Node
455
+ `runAgentCli` wrapper from `test/agent-cli-fixtures.ts`. All 197 former call
456
+ sites are classified by behavior. Normal deterministic commands now await the
457
+ shared `runAgentCliInProcess` path, which still executes the production
458
+ `parseCliCommand` to `executeCliCommand` boundary. Across parameterized tests
459
+ and shared fixture calls, 214 of the former 233 dynamic outer CLI starts move
460
+ in process. The remaining 19 dynamic starts use `runAgentCliAsync` because the
461
+ asserted behavior requires an independently dying PID, exit 86, a live monitor
462
+ or handoff singleton, cross-process lock competition, or a detached
463
+ monitor/retry child whose PID is observed.
464
+
465
+ The shared runner scopes environment, cwd, caller PID, wall and monotonic
466
+ clocks, and sleeps to one imported command. CLI JSON fixtures continue to
467
+ select the production static terminal, process, Codex-session, Claude-agent,
468
+ and version adapters. A command that instead supplies a fake `PATH` receives
469
+ the production `TmuxTerminalControlProvider`, `SystemTerminalProcessSource`,
470
+ and `CodexStoreAdapter` with one command-scoped runner. Fake `tmux`, `ps`,
471
+ `lsof`, and `claude` executables therefore remain real adapter subprocesses;
472
+ their single visible `spawnSync` call site is classified as
473
+ `other_process_or_adapter`, not hidden or counted as an imported CLI.
474
+
475
+ The 70 affected shard test declarations, the one parameterized native-
476
+ inspection declaration, and all 1,223 assertion call sites remain.
477
+ The static metric becomes 28 included sites (`cli_process` 18 plus the
478
+ unchanged 10 fake-Node sites), a 41.67% reduction from the frozen 48-site
479
+ baseline. The adapter runner raises the diagnostic-only
480
+ `other_process_or_adapter` count from 11 to 12 while deleting the synchronous
481
+ CLI startup site. No production source changes are part of this slice.
482
+
483
+ ## #126 final static subprocess gate
484
+
485
+ The final static slice removes nine more real product-test startup call sites.
486
+ It does not merge start helpers, move a start to an uncounted file, change the
487
+ lookahead, drop a test, or alter concurrency. Each migrated case still enters
488
+ the same production parser/command or domain authority:
489
+
490
+ | Former executable case | Imported invariant | Retained real boundary |
491
+ | --- | --- | --- |
492
+ | Callback success/failure helpers and the retry loser | Callback policy, immutable attempt claim, transport acceptance, and settlement | Async retry winner, callback CLI/Gateway concurrency, and fake OpenClaw children |
493
+ | `install-openclaw` outer CLI | Parser, installer filesystem effects, trust fallback, verification, readiness, and JSON projection | Real fake-OpenClaw, tmux, and Claude executables plus the doctor argv/OS-exit witness |
494
+ | Lifecycle evidence verifier wrapper | Exact argument policy, bounded reads, private output, redaction, validation codes, and tag round-trip through an injected IO port | Release-script wiring and the retained executable argv/OS-exit witness |
495
+ | Live tmux opt-in refusal | The same exported two-factor guard called by the executable entry | Live script keeps the guard before discovery/input; doctor retains executable exit projection |
496
+ | CLI-core import probe | An isolated Worker proves no argv inspection, output, exit, or import side effect | Doctor and runtime-log tests retain real CLI argv, stdout/stderr, OS exit, and environment routing |
497
+ | Duplicate Claude recovery wrapper | Exact lifecycle identity, CAS, and no-replay settlement through injected terminal/process seams | Codex black-box recovery remains executable and crash/lifecycle suites retain status 86 |
498
+ | Single auto-approval nested CLI | The real fake-Gateway child imports `parseCliCommand`/`executeCliCommand` for the nested approval | Sequential nested approval remains process-backed; Gateway, monitor, and callback children remain real |
499
+
500
+ `config/public-contract-witnesses.json` records this table as the
501
+ `static-subprocess-final` old-case → service-invariant → retained-boundary
502
+ mapping. The product-test count is now 19 of the immutable 48-site baseline
503
+ (`cli_process` 12, `fake_node_process` 7), or 39.58%, so the static
504
+ `final_threshold.required` gate is enabled. Store/file-lock competition,
505
+ crash-86, live monitor PID recovery, callback Gateway, tmux/ps/lsof/Claude
506
+ adapter, and real Herdr capability probes remain process-backed.
507
+
508
+ The measurement implementation's own CJS/ESM and process-tree probes are
509
+ reported separately: the baseline has zero diagnostic starts and the current
510
+ tree has 10 included fake-Node diagnostic starts plus one
511
+ `other_process_or_adapter` fork. The one canonical diagnostic path is applied
512
+ to both revisions and is fixed by validation; it cannot be widened to hide a
513
+ product-test start.
514
+
515
+ ## #126 dynamic subprocess reduction attestation
516
+
517
+ The static call-site count above remains a cheap architecture diagnostic. It
518
+ is not the final proof for the requirement to remove at least 60% of redundant
519
+ outer CLI starts: one helper can execute a call site many times, and moving a
520
+ `spawn` into another helper must not improve the result.
521
+
522
+ Run the final same-machine process-tree attestation from a clean worktree:
523
+
524
+ ```sh
525
+ node scripts/measure-subprocess-dynamic-evidence.js \
526
+ --output /tmp/akk-subprocess-evidence.json
527
+ ```
528
+
529
+ This command performs no install and uses no network service. It verifies that
530
+ `package-lock.json` is byte-identical at current HEAD and the immutable
531
+ `ea592a88d7af4a709e7a7a1b989dd29e61932935` baseline, creates a detached
532
+ temporary baseline worktree, links the already-present `node_modules`, builds
533
+ both revisions, and runs the full tier at concurrency four once per revision.
534
+ Both full runs must pass; a partial or failed run is not accepted as evidence.
535
+
536
+ `scripts/subprocess-dynamic-hook.cjs` is preloaded before the test workers. It
537
+ patches every standard `node:child_process` start entry point, synchronizes the
538
+ patched CommonJS exports into ESM named imports, and propagates the preload and
539
+ run identity even when a caller supplies an explicit stripped `env`. Every
540
+ launch also propagates one random, non-secret call ID into the child boot, so
541
+ synchronous launches are associated directly without scanning PIDs created by
542
+ other concurrent workers. Nested
543
+ implementations such as `exec` calling `execFile` emit one record for the real
544
+ child rather than two wrapper records, and `util.promisify.custom` remains
545
+ usable.
546
+
547
+ The attestation runs each full tier in one new POSIX process group. The hook
548
+ records every explicitly detached child as another process-group root. After
549
+ the direct runner exits, measurement waits on the kernel until the runner group
550
+ and every recorded detached group are empty; a shell that exits after forking a
551
+ background descendant therefore cannot create an unobserved quiet gap. Trace
552
+ files are read twice only after all groups are empty, and any live group fails
553
+ closed at the configured 30-second timeout. This local attestation consequently
554
+ supports macOS and Linux and fails closed on Windows. The baseline completion
555
+ finishes before current measurement starts, and the current completion finishes
556
+ before either trace is summarized. The final
557
+ count comes from observed CLI process boots and their process ancestry, not
558
+ from source locations. Moving a start behind a shared Node helper, shell, or
559
+ another call expression therefore does not make that start disappear. A
560
+ targeted CLI start without its corresponding boot, or a CLI boot without an
561
+ originating test, makes the attestation fail closed.
562
+
563
+ The denominator is the observed full-tree count at the immutable baseline;
564
+ the 233-call shared `runAgentCli` migration inventory is only one family and is
565
+ not misreported as the global baseline. Current HEAD must be at most 40% of the
566
+ same observed baseline (at least a 60% reduction). The report
567
+ contains only command basenames, CLI actions, option names, counts, status or
568
+ signal outcomes, and test paths; message bodies, tokens, environment values,
569
+ and raw argv are never recorded.
570
+
571
+ The reduction gate is paired with retained real-process checks so deleting or
572
+ reclassifying necessary coverage cannot satisfy it. The current full trace
573
+ must still demonstrate:
574
+
575
+ - real doctor argv and non-zero OS exit;
576
+ - a crash-injected CLI exit with status 86;
577
+ - overlapping CLI processes for Store/terminal lock competition;
578
+ - a live child PID and a `SIGKILL` monitor-recovery boundary;
579
+ - real fake-Gateway (`openclaw`) execution; and
580
+ - real `tmux`, `ps`, `lsof`, and `claude` adapter subprocesses.
581
+
582
+ Each retained observation is tied at runtime to its explicitly scoped,
583
+ allowlisted `TestContext.name`. The canonical path and exact test name in
584
+ `config/subprocess-dynamic-evidence.json` are immutable validation inputs, not
585
+ replaceable substring hints. Multiple argv,
586
+ exit, signal, or live-PID requirements on one boundary must be satisfied by the
587
+ same observed CLI process; unrelated children in the same file cannot be
588
+ combined into a passing witness. Multi-command adapter boundaries likewise
589
+ require every command beneath one outer CLI process, so separate tests in the
590
+ same source file cannot be combined into a passing case. Boundaries sharing one
591
+ canonical test name also share one command group. The retained Claude and
592
+ terminal-adapter witness is the raw background send case, where one outer CLI
593
+ process owns every observed `claude`, `tmux`, `ps`, and `lsof` child. The normal
594
+ fast evidence test validates that immutable configuration and executes a real
595
+ process-group probe in which an exited shell leaves a delayed 1.5-second
596
+ background CLI with an explicit stripped environment. A second CJS/ESM matrix
597
+ covers every sync and async launch API plus promisified `execFile`, exact
598
+ call-ID deduplication, and stripped-environment propagation; an overlapping
599
+ sync/concurrent-writer probe prevents shared-trace PID inference from returning.
600
+ Those probes transparently add ten fake-Node source sites to the separately
601
+ reported diagnostic scope; one fork probe is classified as
602
+ `other_process_or_adapter`. They do not increase either revision's product
603
+ migration numerator, and the same canonical partition is applied to baseline
604
+ and current. The dynamic full-tree ratio remains the final runtime 60% gate.
605
+ It validates the already-active preload without recursively starting its probe
606
+ while the outer dynamic attestation runs, avoiding a measurement of the
607
+ measurement itself. The expensive two-revision full attestation remains an
608
+ explicit final/local gate rather than running inside ordinary fast tests.
609
+
610
+ ## #108 performance record
611
+
612
+ The pre-refactor maintainer baseline was 48 files / 683 tests / about 573
613
+ seconds. By v0.11.3 it had grown to 48 files / 696 tests; with the two manifest
614
+ guards added by this work, the comparable before profile was 49 files / 698
615
+ tests / 513.96 seconds. The final stable profile is 59 files / 698 tests /
616
+ 301.05 seconds, a 41.4% reduction with no removed tests. A higher-concurrency
617
+ passing run reached 240.13 seconds but was not adopted because repeated stress
618
+ caused resource-starvation false failures.
619
+
620
+ See [the complete #108 performance report](test-performance-issue-108.md) for
621
+ the before/after critical paths and why the remaining real-process gates make a
622
+ stable 180-second full suite unattainable without the next handler/provider
623
+ injection refactor.
624
+
625
+ Issue #120 completed that next handler/provider-injection phase for the three
626
+ largest lifecycle families. See
627
+ [the #120 performance report](test-performance-issue-120.md) for the in-process
628
+ semantic inventory, retained black-box contracts, and final three-run profile.