harnery 0.36.0 → 0.37.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 (311) hide show
  1. package/dist/commander.js +4 -0
  2. package/dist/commands/agents.d.ts.map +1 -1
  3. package/dist/commands/agents.js +87 -46
  4. package/dist/commands/artifacts.d.ts.map +1 -1
  5. package/dist/commands/artifacts.js +26 -1
  6. package/dist/commands/browse.d.ts.map +1 -1
  7. package/dist/commands/browse.js +11 -0
  8. package/dist/commands/diagnostics.d.ts +4 -0
  9. package/dist/commands/diagnostics.d.ts.map +1 -0
  10. package/dist/commands/diagnostics.js +229 -0
  11. package/dist/commands/files.d.ts +12 -0
  12. package/dist/commands/files.d.ts.map +1 -1
  13. package/dist/commands/files.js +54 -1
  14. package/dist/commands/governor.d.ts.map +1 -1
  15. package/dist/commands/governor.js +4 -0
  16. package/dist/commands/ledger-v3.d.ts.map +1 -1
  17. package/dist/commands/ledger-v3.js +71 -2
  18. package/dist/commands/qa-run.d.ts +4 -0
  19. package/dist/commands/qa-run.d.ts.map +1 -0
  20. package/dist/commands/qa-run.js +141 -0
  21. package/dist/commands/resources.d.ts +4 -0
  22. package/dist/commands/resources.d.ts.map +1 -0
  23. package/dist/commands/resources.js +29 -0
  24. package/dist/commands/supervisor.d.ts +4 -0
  25. package/dist/commands/supervisor.d.ts.map +1 -0
  26. package/dist/commands/supervisor.js +101 -0
  27. package/dist/commands/web.d.ts.map +1 -1
  28. package/dist/commands/web.js +17 -0
  29. package/dist/commands/workflow.d.ts.map +1 -1
  30. package/dist/commands/workflow.js +4 -0
  31. package/dist/core/agents/cli.js +7 -3
  32. package/dist/core/agents/health.d.ts +17 -0
  33. package/dist/core/agents/health.d.ts.map +1 -0
  34. package/dist/core/agents/health.js +109 -0
  35. package/dist/core/agents/mailbox.d.ts +92 -0
  36. package/dist/core/agents/mailbox.d.ts.map +1 -0
  37. package/dist/core/agents/mailbox.js +325 -0
  38. package/dist/core/agents/reconcile-coordination-v3.d.ts +44 -0
  39. package/dist/core/agents/reconcile-coordination-v3.d.ts.map +1 -0
  40. package/dist/core/agents/reconcile-coordination-v3.js +58 -0
  41. package/dist/core/agents/render/prompt-context.d.ts +5 -0
  42. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  43. package/dist/core/agents/render/prompt-context.js +34 -13
  44. package/dist/core/agents/render/session-context.d.ts +8 -0
  45. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  46. package/dist/core/agents/render/session-context.js +34 -3
  47. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
  48. package/dist/core/agents/rules/commit-conflict.js +50 -1
  49. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  50. package/dist/core/agents/rules/stop-hook.js +6 -10
  51. package/dist/core/agents/session-finalizer-v3.js +4 -1
  52. package/dist/core/artifacts/index.d.ts +26 -1
  53. package/dist/core/artifacts/index.d.ts.map +1 -1
  54. package/dist/core/artifacts/index.js +146 -6
  55. package/dist/core/config.d.ts +12 -0
  56. package/dist/core/config.d.ts.map +1 -1
  57. package/dist/core/config.js +43 -0
  58. package/dist/core/diagnostics/advice.d.ts +9 -0
  59. package/dist/core/diagnostics/advice.d.ts.map +1 -0
  60. package/dist/core/diagnostics/advice.js +112 -0
  61. package/dist/core/diagnostics/bundle.d.ts +35 -0
  62. package/dist/core/diagnostics/bundle.d.ts.map +1 -0
  63. package/dist/core/diagnostics/bundle.js +874 -0
  64. package/dist/core/diagnostics/comparison.d.ts +5 -0
  65. package/dist/core/diagnostics/comparison.d.ts.map +1 -0
  66. package/dist/core/diagnostics/comparison.js +444 -0
  67. package/dist/core/diagnostics/contract.d.ts +245 -0
  68. package/dist/core/diagnostics/contract.d.ts.map +1 -0
  69. package/dist/core/diagnostics/contract.js +18 -0
  70. package/dist/core/diagnostics/identity.d.ts +3 -0
  71. package/dist/core/diagnostics/identity.d.ts.map +1 -0
  72. package/dist/core/diagnostics/identity.js +10 -0
  73. package/dist/core/diagnostics/index.d.ts +8 -0
  74. package/dist/core/diagnostics/index.d.ts.map +1 -0
  75. package/dist/core/diagnostics/index.js +7 -0
  76. package/dist/core/diagnostics/replay.d.ts +8 -0
  77. package/dist/core/diagnostics/replay.d.ts.map +1 -0
  78. package/dist/core/diagnostics/replay.js +213 -0
  79. package/dist/core/diagnostics/sanitize.d.ts +9 -0
  80. package/dist/core/diagnostics/sanitize.d.ts.map +1 -0
  81. package/dist/core/diagnostics/sanitize.js +84 -0
  82. package/dist/core/events/legacy-storage/compression.d.ts +13 -0
  83. package/dist/core/events/legacy-storage/compression.d.ts.map +1 -0
  84. package/dist/core/events/legacy-storage/compression.js +107 -0
  85. package/dist/core/events/legacy-storage/index.d.ts +1 -0
  86. package/dist/core/events/legacy-storage/index.d.ts.map +1 -1
  87. package/dist/core/events/legacy-storage/index.js +1 -0
  88. package/dist/core/events/v3/archive-retention.d.ts +33 -0
  89. package/dist/core/events/v3/archive-retention.d.ts.map +1 -0
  90. package/dist/core/events/v3/archive-retention.js +195 -0
  91. package/dist/core/events/v3/capabilities.d.ts +1 -1
  92. package/dist/core/events/v3/capabilities.d.ts.map +1 -1
  93. package/dist/core/events/v3/capabilities.js +1 -0
  94. package/dist/core/events/v3/index.d.ts +1 -0
  95. package/dist/core/events/v3/index.d.ts.map +1 -1
  96. package/dist/core/events/v3/index.js +1 -0
  97. package/dist/core/events/v3/live-routing.d.ts.map +1 -1
  98. package/dist/core/events/v3/live-routing.js +1 -0
  99. package/dist/core/events/v3/producers/hook-base.d.ts +1 -1
  100. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
  101. package/dist/core/events/v3/producers/hook-base.js +13 -2
  102. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  103. package/dist/core/events/v3/producers/intake.js +1 -0
  104. package/dist/core/events/v3/producers/recorder.d.ts +16 -0
  105. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  106. package/dist/core/events/v3/producers/recorder.js +88 -1
  107. package/dist/core/hooks/adapter/output.d.ts +8 -0
  108. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  109. package/dist/core/hooks/adapter/output.js +11 -1
  110. package/dist/core/hooks/cli.js +183 -192
  111. package/dist/core/hooks/health.d.ts +59 -0
  112. package/dist/core/hooks/health.d.ts.map +1 -0
  113. package/dist/core/hooks/health.js +84 -0
  114. package/dist/core/resources/contract.d.ts +90 -0
  115. package/dist/core/resources/contract.d.ts.map +1 -0
  116. package/dist/core/resources/contract.js +2 -0
  117. package/dist/core/resources/index.d.ts +6 -0
  118. package/dist/core/resources/index.d.ts.map +1 -0
  119. package/dist/core/resources/index.js +5 -0
  120. package/dist/core/resources/sampler.d.ts +27 -0
  121. package/dist/core/resources/sampler.d.ts.map +1 -0
  122. package/dist/core/resources/sampler.js +357 -0
  123. package/dist/core/resources/service-status.d.ts +3 -0
  124. package/dist/core/resources/service-status.d.ts.map +1 -0
  125. package/dist/core/resources/service-status.js +48 -0
  126. package/dist/core/resources/service.d.ts +26 -0
  127. package/dist/core/resources/service.d.ts.map +1 -0
  128. package/dist/core/resources/service.js +292 -0
  129. package/dist/core/resources/storage.d.ts +13 -0
  130. package/dist/core/resources/storage.d.ts.map +1 -0
  131. package/dist/core/resources/storage.js +30 -0
  132. package/dist/core/storage/atomic-json.d.ts +3 -0
  133. package/dist/core/storage/atomic-json.d.ts.map +1 -0
  134. package/dist/core/storage/atomic-json.js +15 -0
  135. package/dist/core/storage/builtins.d.ts.map +1 -1
  136. package/dist/core/storage/builtins.js +45 -6
  137. package/dist/core/storage/logger.d.ts +2 -0
  138. package/dist/core/storage/logger.d.ts.map +1 -1
  139. package/dist/core/storage/logger.js +2 -0
  140. package/dist/core/storage/query.d.ts +14 -0
  141. package/dist/core/storage/query.d.ts.map +1 -1
  142. package/dist/core/storage/query.js +51 -0
  143. package/dist/core/supervisor/activity.d.ts +4 -0
  144. package/dist/core/supervisor/activity.d.ts.map +1 -0
  145. package/dist/core/supervisor/activity.js +141 -0
  146. package/dist/core/supervisor/contract.d.ts +268 -0
  147. package/dist/core/supervisor/contract.d.ts.map +1 -0
  148. package/dist/core/supervisor/contract.js +35 -0
  149. package/dist/core/supervisor/explanations.d.ts +4 -0
  150. package/dist/core/supervisor/explanations.d.ts.map +1 -0
  151. package/dist/core/supervisor/explanations.js +71 -0
  152. package/dist/core/supervisor/findings.d.ts +20 -0
  153. package/dist/core/supervisor/findings.d.ts.map +1 -0
  154. package/dist/core/supervisor/findings.js +399 -0
  155. package/dist/core/supervisor/history.d.ts +9 -0
  156. package/dist/core/supervisor/history.d.ts.map +1 -0
  157. package/dist/core/supervisor/history.js +46 -0
  158. package/dist/core/supervisor/hook-health-alerts.d.ts +14 -0
  159. package/dist/core/supervisor/hook-health-alerts.d.ts.map +1 -0
  160. package/dist/core/supervisor/hook-health-alerts.js +70 -0
  161. package/dist/core/supervisor/hook-health-storage.d.ts +5 -0
  162. package/dist/core/supervisor/hook-health-storage.d.ts.map +1 -0
  163. package/dist/core/supervisor/hook-health-storage.js +24 -0
  164. package/dist/core/supervisor/hook-health.d.ts +72 -0
  165. package/dist/core/supervisor/hook-health.d.ts.map +1 -0
  166. package/dist/core/supervisor/hook-health.js +203 -0
  167. package/dist/core/supervisor/hooks.d.ts +10 -0
  168. package/dist/core/supervisor/hooks.d.ts.map +1 -0
  169. package/dist/core/supervisor/hooks.js +28 -0
  170. package/dist/core/supervisor/index.d.ts +15 -0
  171. package/dist/core/supervisor/index.d.ts.map +1 -0
  172. package/dist/core/supervisor/index.js +14 -0
  173. package/dist/core/supervisor/log-feed.d.ts +9 -0
  174. package/dist/core/supervisor/log-feed.d.ts.map +1 -0
  175. package/dist/core/supervisor/log-feed.js +103 -0
  176. package/dist/core/supervisor/service.d.ts +29 -0
  177. package/dist/core/supervisor/service.d.ts.map +1 -0
  178. package/dist/core/supervisor/service.js +450 -0
  179. package/dist/core/supervisor/services.d.ts +11 -0
  180. package/dist/core/supervisor/services.d.ts.map +1 -0
  181. package/dist/core/supervisor/services.js +155 -0
  182. package/dist/core/supervisor/status.d.ts +3 -0
  183. package/dist/core/supervisor/status.d.ts.map +1 -0
  184. package/dist/core/supervisor/status.js +48 -0
  185. package/dist/core/supervisor/storage.d.ts +30 -0
  186. package/dist/core/supervisor/storage.d.ts.map +1 -0
  187. package/dist/core/supervisor/storage.js +73 -0
  188. package/dist/core/supervisor/timeline.d.ts +3 -0
  189. package/dist/core/supervisor/timeline.d.ts.map +1 -0
  190. package/dist/core/supervisor/timeline.js +87 -0
  191. package/dist/core/workflow/admission.d.ts +23 -0
  192. package/dist/core/workflow/admission.d.ts.map +1 -0
  193. package/dist/core/workflow/admission.js +136 -0
  194. package/dist/core/workflow/engine.d.ts.map +1 -1
  195. package/dist/core/workflow/engine.js +77 -2
  196. package/dist/core/workflow/index.d.ts +3 -2
  197. package/dist/core/workflow/index.d.ts.map +1 -1
  198. package/dist/core/workflow/index.js +2 -1
  199. package/dist/core/workflow/proof.d.ts +2 -1
  200. package/dist/core/workflow/proof.d.ts.map +1 -1
  201. package/dist/core/workflow/proof.js +39 -1
  202. package/dist/core/workflow/run-state.d.ts +3 -2
  203. package/dist/core/workflow/run-state.d.ts.map +1 -1
  204. package/dist/core/workflow/run-state.js +8 -1
  205. package/dist/core/workflow/types.d.ts +33 -1
  206. package/dist/core/workflow/types.d.ts.map +1 -1
  207. package/dist/core/workflow/types.js +2 -1
  208. package/dist/lib/browser/client.d.ts +5 -0
  209. package/dist/lib/browser/client.d.ts.map +1 -1
  210. package/dist/lib/browser/client.js +1 -0
  211. package/dist/lib/browser/index.d.ts +2 -0
  212. package/dist/lib/browser/index.d.ts.map +1 -1
  213. package/dist/lib/browser/index.js +2 -0
  214. package/dist/lib/browser/qa-run-contracts.d.ts +173 -0
  215. package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -0
  216. package/dist/lib/browser/qa-run-contracts.js +226 -0
  217. package/dist/lib/browser/qa-run.d.ts +51 -0
  218. package/dist/lib/browser/qa-run.d.ts.map +1 -0
  219. package/dist/lib/browser/qa-run.js +684 -0
  220. package/dist/lib/coord-root-id.d.ts +9 -0
  221. package/dist/lib/coord-root-id.d.ts.map +1 -0
  222. package/dist/lib/coord-root-id.js +17 -0
  223. package/dist/lib/instructions/apply.d.ts +3 -1
  224. package/dist/lib/instructions/apply.d.ts.map +1 -1
  225. package/dist/lib/instructions/apply.js +74 -3
  226. package/dist/lib/instructions/templates.d.ts.map +1 -1
  227. package/dist/lib/instructions/templates.js +6 -0
  228. package/package.json +12 -1
  229. package/src/commander.ts +26 -0
  230. package/src/commands/agents.ts +102 -49
  231. package/src/commands/artifacts.ts +40 -2
  232. package/src/commands/browse.ts +15 -0
  233. package/src/commands/diagnostics.ts +271 -0
  234. package/src/commands/files.ts +102 -2
  235. package/src/commands/governor.ts +8 -0
  236. package/src/commands/ledger-v3.ts +82 -0
  237. package/src/commands/qa-run.ts +184 -0
  238. package/src/commands/resources.ts +38 -0
  239. package/src/commands/supervisor.ts +141 -0
  240. package/src/commands/web.ts +19 -0
  241. package/src/commands/workflow.ts +8 -0
  242. package/src/core/agents/cli.ts +7 -3
  243. package/src/core/agents/health.ts +142 -0
  244. package/src/core/agents/mailbox.ts +373 -0
  245. package/src/core/agents/reconcile-coordination-v3.ts +77 -0
  246. package/src/core/agents/render/prompt-context.ts +42 -12
  247. package/src/core/agents/render/session-context.ts +37 -3
  248. package/src/core/agents/rules/commit-conflict.ts +58 -1
  249. package/src/core/agents/rules/stop-hook.ts +6 -12
  250. package/src/core/agents/session-finalizer-v3.ts +4 -1
  251. package/src/core/artifacts/index.ts +196 -10
  252. package/src/core/config.ts +111 -2
  253. package/src/core/diagnostics/advice.ts +147 -0
  254. package/src/core/diagnostics/bundle.ts +1142 -0
  255. package/src/core/diagnostics/comparison.ts +565 -0
  256. package/src/core/diagnostics/contract.ts +311 -0
  257. package/src/core/diagnostics/identity.ts +11 -0
  258. package/src/core/diagnostics/index.ts +7 -0
  259. package/src/core/diagnostics/replay.ts +314 -0
  260. package/src/core/diagnostics/sanitize.ts +97 -0
  261. package/src/core/events/legacy-storage/compression.ts +130 -0
  262. package/src/core/events/legacy-storage/index.ts +1 -0
  263. package/src/core/events/v3/archive-retention.ts +251 -0
  264. package/src/core/events/v3/capabilities.ts +2 -0
  265. package/src/core/events/v3/index.ts +9 -0
  266. package/src/core/events/v3/live-routing.ts +1 -0
  267. package/src/core/events/v3/producers/hook-base.ts +14 -2
  268. package/src/core/events/v3/producers/intake.ts +1 -0
  269. package/src/core/events/v3/producers/recorder.ts +110 -1
  270. package/src/core/hooks/adapter/output.ts +12 -1
  271. package/src/core/hooks/cli.ts +192 -215
  272. package/src/core/hooks/health.ts +146 -0
  273. package/src/core/resources/contract.ts +98 -0
  274. package/src/core/resources/index.ts +5 -0
  275. package/src/core/resources/sampler.ts +458 -0
  276. package/src/core/resources/service-status.ts +62 -0
  277. package/src/core/resources/service.ts +337 -0
  278. package/src/core/resources/storage.ts +44 -0
  279. package/src/core/storage/atomic-json.ts +15 -0
  280. package/src/core/storage/builtins.ts +62 -6
  281. package/src/core/storage/logger.ts +2 -0
  282. package/src/core/storage/query.ts +58 -0
  283. package/src/core/supervisor/activity.ts +193 -0
  284. package/src/core/supervisor/contract.ts +312 -0
  285. package/src/core/supervisor/explanations.ts +104 -0
  286. package/src/core/supervisor/findings.ts +788 -0
  287. package/src/core/supervisor/history.ts +61 -0
  288. package/src/core/supervisor/hook-health-alerts.ts +108 -0
  289. package/src/core/supervisor/hook-health-storage.ts +25 -0
  290. package/src/core/supervisor/hook-health.ts +301 -0
  291. package/src/core/supervisor/hooks.ts +35 -0
  292. package/src/core/supervisor/index.ts +14 -0
  293. package/src/core/supervisor/log-feed.ts +131 -0
  294. package/src/core/supervisor/service.ts +511 -0
  295. package/src/core/supervisor/services.ts +203 -0
  296. package/src/core/supervisor/status.ts +59 -0
  297. package/src/core/supervisor/storage.ts +126 -0
  298. package/src/core/supervisor/timeline.ts +133 -0
  299. package/src/core/workflow/admission.ts +215 -0
  300. package/src/core/workflow/engine.ts +93 -1
  301. package/src/core/workflow/index.ts +10 -0
  302. package/src/core/workflow/proof.ts +54 -1
  303. package/src/core/workflow/run-state.ts +13 -1
  304. package/src/core/workflow/types.ts +39 -1
  305. package/src/lib/browser/client.ts +6 -0
  306. package/src/lib/browser/index.ts +29 -0
  307. package/src/lib/browser/qa-run-contracts.ts +380 -0
  308. package/src/lib/browser/qa-run.ts +784 -0
  309. package/src/lib/coord-root-id.ts +23 -0
  310. package/src/lib/instructions/apply.ts +81 -2
  311. package/src/lib/instructions/templates.ts +6 -0
@@ -141,6 +141,14 @@ interface TurnHarnessTimingV3 {
141
141
  slowest_hook_ms: number;
142
142
  }
143
143
 
144
+ interface CursorResponseRitualV3 {
145
+ turn_id: `tid_${string}`;
146
+ native_turn_id?: string;
147
+ observed_at: string;
148
+ status_box_present: boolean;
149
+ status_box_present_strict: boolean;
150
+ }
151
+
144
152
  interface PendingEventV3 {
145
153
  source_id?: `hid_${string}`;
146
154
  event: EventV3;
@@ -201,6 +209,10 @@ export interface HookProducerStateV3 {
201
209
  current_turn_id?: `tid_${string}`;
202
210
  /** Native turn identity retained owner-only for transcript attribution. */
203
211
  current_native_turn_id?: string;
212
+ /** Latest completed assistant response for Cursor's open turn. The response
213
+ * body is discarded by agent-hook; only these booleans survive until Stop
214
+ * copies them into the authoritative turn.completed ritual observation. */
215
+ cursor_response_ritual?: CursorResponseRitualV3;
204
216
  tool_call_count: number;
205
217
  tool_call_count_turn_id?: `tid_${string}`;
206
218
  last_event_id?: `evt_${string}`;
@@ -288,6 +300,12 @@ export type RecordHookSignalV3Result =
288
300
  /** A late signal for a span already closed in memory; preserved in diagnostics, never re-opened. */
289
301
  | { state: "suppressed"; reason: "closed_span" }
290
302
  | { state: "ignored" }
303
+ | {
304
+ state: "observed";
305
+ generation_id: `gen_${string}`;
306
+ turn_id: `tid_${string}`;
307
+ observed_at: string;
308
+ }
291
309
  /** Durably queued in the intake spool; a lease holder or drain hook records it. */
292
310
  | { state: "spooled" }
293
311
  | { state: "recorded"; event: EventV3; durability: WriteEventV3Result; recovered: boolean };
@@ -871,6 +889,51 @@ function processHookSignalLocked(
871
889
  // Sample once for the native event and every span it opens or closes so
872
890
  // their self-contained timing cannot drift by a millisecond.
873
891
  const eventClock = signalClock(input);
892
+ if (input.signal === "after-agent-response") {
893
+ if (
894
+ input.adapter !== "cursor" ||
895
+ !state.current_turn_id ||
896
+ !state.current_turn_span ||
897
+ !input.turn_ritual
898
+ ) {
899
+ writeProducerDiagnosticV3(input.coordRoot, "cursor_response_ritual_unbound", {
900
+ adapter: input.adapter,
901
+ instance_id: input.instance_id,
902
+ generation_id: state.generation_id,
903
+ signal: input.signal,
904
+ reason: !state.current_turn_id
905
+ ? "no_open_turn"
906
+ : !state.current_turn_span
907
+ ? "no_open_turn_span"
908
+ : "ritual_observation_missing",
909
+ });
910
+ publishProducerState(path, state);
911
+ return { state: "ignored" };
912
+ }
913
+ const observation: CursorResponseRitualV3 = {
914
+ turn_id: state.current_turn_id,
915
+ ...(input.payload.turn_id ? { native_turn_id: input.payload.turn_id } : {}),
916
+ observed_at: eventClock.observed_at,
917
+ status_box_present: input.turn_ritual.status_box_present,
918
+ status_box_present_strict: input.turn_ritual.status_box_present_strict,
919
+ };
920
+ state.cursor_response_ritual = observation;
921
+ publishProducerState(path, state);
922
+ writeProducerDiagnosticV3(input.coordRoot, "cursor_response_ritual_observed", {
923
+ instance_id: state.instance_id,
924
+ generation_id: state.generation_id,
925
+ turn_id: observation.turn_id,
926
+ ...(observation.native_turn_id ? { native_turn_id: observation.native_turn_id } : {}),
927
+ response_observed_at: observation.observed_at,
928
+ status_box_present_strict: observation.status_box_present_strict,
929
+ });
930
+ return {
931
+ state: "observed",
932
+ generation_id: state.generation_id,
933
+ turn_id: observation.turn_id,
934
+ observed_at: observation.observed_at,
935
+ };
936
+ }
874
937
  if (input.signal === "user-prompt-submit" && !state.current_turn_span) {
875
938
  state.current_turn_span = openSpanStateV3({
876
939
  span_id: spanIdV3(),
@@ -1096,6 +1159,38 @@ function processHookSignalLocked(
1096
1159
  // Before the signal's own event: the tool call or turn that carries the
1097
1160
  // new effort already ran under it, so it must ride the new attestation.
1098
1161
  maybeAttestTuningChange(input, state, path, rootId);
1162
+ const cursorResponseRitual =
1163
+ input.adapter === "cursor" &&
1164
+ (input.signal === "stop" || input.signal === "stop-failure") &&
1165
+ state.current_turn_id &&
1166
+ state.cursor_response_ritual?.turn_id === state.current_turn_id
1167
+ ? state.cursor_response_ritual
1168
+ : undefined;
1169
+ const terminalTurnRitual =
1170
+ input.adapter === "cursor" && (input.signal === "stop" || input.signal === "stop-failure")
1171
+ ? cursorResponseRitual
1172
+ ? {
1173
+ status_box_present: cursorResponseRitual.status_box_present,
1174
+ status_box_present_strict: cursorResponseRitual.status_box_present_strict,
1175
+ session_name_required: false,
1176
+ session_name_present: false,
1177
+ }
1178
+ : undefined
1179
+ : input.turn_ritual;
1180
+ if (cursorResponseRitual) {
1181
+ writeProducerDiagnosticV3(input.coordRoot, "cursor_response_ritual_consumed", {
1182
+ instance_id: state.instance_id,
1183
+ generation_id: state.generation_id,
1184
+ turn_id: cursorResponseRitual.turn_id,
1185
+ ...(cursorResponseRitual.native_turn_id
1186
+ ? { response_native_turn_id: cursorResponseRitual.native_turn_id }
1187
+ : {}),
1188
+ ...(input.payload.turn_id ? { stop_native_turn_id: input.payload.turn_id } : {}),
1189
+ response_observed_at: cursorResponseRitual.observed_at,
1190
+ stop_observed_at: eventClock.observed_at,
1191
+ status_box_present_strict: cursorResponseRitual.status_box_present_strict,
1192
+ });
1193
+ }
1099
1194
  const event = normalizeHookEventV3(input.signal, eventInput.payload, {
1100
1195
  coordRoot: input.coordRoot,
1101
1196
  adapter: input.adapter,
@@ -1154,7 +1249,7 @@ function processHookSignalLocked(
1154
1249
  child_generation_id: delegation?.child_generation_id,
1155
1250
  agent_role: delegation?.role,
1156
1251
  stop_remediation: input.stop_remediation,
1157
- turn_ritual: input.turn_ritual,
1252
+ turn_ritual: terminalTurnRitual,
1158
1253
  });
1159
1254
  if (!event) return { state: "ignored" };
1160
1255
  if (
@@ -3258,6 +3353,8 @@ function hookSignalCapability(signal: HookSignalV3): AdapterSignalV3 {
3258
3353
  return "session_end";
3259
3354
  case "user-prompt-submit":
3260
3355
  return "prompt";
3356
+ case "after-agent-response":
3357
+ return "assistant_reply_text";
3261
3358
  case "stop":
3262
3359
  case "stop-failure":
3263
3360
  return "turn_completion";
@@ -3515,6 +3612,7 @@ function applyCommittedEvent(state: HookProducerStateV3, event: EventV3): void {
3515
3612
  if (event.event_type === "turn.started") {
3516
3613
  const nextTurnId = (event.scope as { turn_id: `tid_${string}` }).turn_id;
3517
3614
  state.current_turn_id = nextTurnId;
3615
+ state.cursor_response_ritual = undefined;
3518
3616
  state.session_start_derivation = undefined;
3519
3617
  if (state.tool_call_count_turn_id !== nextTurnId) {
3520
3618
  state.tool_call_count = 0;
@@ -3600,6 +3698,7 @@ function applyCommittedEvent(state: HookProducerStateV3, event: EventV3): void {
3600
3698
  }
3601
3699
  state.current_turn_id = undefined;
3602
3700
  state.current_native_turn_id = undefined;
3701
+ state.cursor_response_ritual = undefined;
3603
3702
  state.current_turn_span = undefined;
3604
3703
  state.tool_call_count = 0;
3605
3704
  state.tool_call_count_turn_id = undefined;
@@ -3904,6 +4003,7 @@ function readProducerState(path: string): HookProducerStateV3 {
3904
4003
  "current_native_turn_id",
3905
4004
  "current_turn_span",
3906
4005
  "cursor_mode",
4006
+ "cursor_response_ritual",
3907
4007
  "delegations",
3908
4008
  "epoch_genesis_id",
3909
4009
  "format",
@@ -4021,6 +4121,15 @@ function readProducerState(path: string): HookProducerStateV3 {
4021
4121
  (typeof state.current_native_turn_id !== "string" ||
4022
4122
  state.current_native_turn_id.length === 0 ||
4023
4123
  state.current_native_turn_id.length > 512)) ||
4124
+ (state.cursor_response_ritual !== undefined &&
4125
+ (!/^tid_[a-f0-9]{64}$/.test(state.cursor_response_ritual.turn_id) ||
4126
+ (state.cursor_response_ritual.native_turn_id !== undefined &&
4127
+ (typeof state.cursor_response_ritual.native_turn_id !== "string" ||
4128
+ state.cursor_response_ritual.native_turn_id.length === 0 ||
4129
+ state.cursor_response_ritual.native_turn_id.length > 512)) ||
4130
+ !Number.isFinite(Date.parse(state.cursor_response_ritual.observed_at)) ||
4131
+ typeof state.cursor_response_ritual.status_box_present !== "boolean" ||
4132
+ typeof state.cursor_response_ritual.status_box_present_strict !== "boolean")) ||
4024
4133
  (state.last_event_id !== undefined && !/^evt_[0-9a-f-]{36}$/.test(state.last_event_id)) ||
4025
4134
  (state.last_monotonic_ns !== undefined && !/^\d+$/.test(state.last_monotonic_ns)) ||
4026
4135
  (state.last_observed_at !== undefined &&
@@ -31,10 +31,21 @@ export type SystemEvent =
31
31
  | "PreToolUse"
32
32
  | "PostToolUse";
33
33
 
34
+ /**
35
+ * Whether this adapter can actually receive injected context for an event.
36
+ * Cursor's beforeSubmitPrompt hook can allow or block a turn but cannot inject
37
+ * model context, so anything rendered for that event is discarded. A caller
38
+ * that consumes state to build the text (draining a mailbox, for instance)
39
+ * must check this first, or the state is spent on output nobody reads.
40
+ */
41
+ export function canReceiveContext(adapter: Adapter, event: SystemEvent): boolean {
42
+ return !(adapter === "cursor" && event === "UserPromptSubmit");
43
+ }
44
+
34
45
  /** Emit a context-injection (peer table, wiring check, council pending, …). */
35
46
  export function emitContext(adapter: Adapter, event: SystemEvent, text: string): void {
36
47
  if (!text || text.length === 0) return;
37
- if (adapter === "cursor" && event === "UserPromptSubmit") return;
48
+ if (!canReceiveContext(adapter, event)) return;
38
49
  const json = buildContextJson(adapter, event, text);
39
50
  process.stdout.write(`${JSON.stringify(json)}\n`);
40
51
  }