opensquid 0.5.441 → 0.5.447

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 (380) hide show
  1. package/README.md +1 -0
  2. package/dist/functions/arm_scope.d.ts +27 -0
  3. package/dist/functions/arm_scope.d.ts.map +1 -0
  4. package/dist/functions/arm_scope.js +52 -0
  5. package/dist/functions/arm_scope.js.map +1 -0
  6. package/dist/functions/index.d.ts +1 -0
  7. package/dist/functions/index.d.ts.map +1 -1
  8. package/dist/functions/index.js +1 -0
  9. package/dist/functions/index.js.map +1 -1
  10. package/dist/runtime/bootstrap.d.ts.map +1 -1
  11. package/dist/runtime/bootstrap.js +2 -0
  12. package/dist/runtime/bootstrap.js.map +1 -1
  13. package/dist/runtime/handoff/render.d.ts +5 -4
  14. package/dist/runtime/handoff/render.d.ts.map +1 -1
  15. package/dist/runtime/handoff/render.js +7 -7
  16. package/dist/runtime/handoff/render.js.map +1 -1
  17. package/dist/runtime/hooks/active_task_mirror.js +0 -0
  18. package/dist/runtime/hooks/apply_patch.js +0 -0
  19. package/dist/runtime/hooks/dispatch.js +0 -0
  20. package/dist/runtime/hooks/hook_output.js +0 -0
  21. package/dist/runtime/hooks/memory_reconcile.js +0 -0
  22. package/dist/runtime/hooks/new_project_detect.js +0 -0
  23. package/dist/runtime/hooks/profession_resolver.js +0 -0
  24. package/dist/runtime/hooks/scope_intent.js +0 -0
  25. package/dist/runtime/hooks/session_id.js +0 -0
  26. package/dist/runtime/hooks/session_liveness.js +0 -0
  27. package/dist/runtime/hooks/stop_drive.js +0 -0
  28. package/dist/runtime/hooks/stop_stream.js +0 -0
  29. package/dist/runtime/hooks/subagent_guard.js +0 -0
  30. package/dist/runtime/hooks/transcript.js +0 -0
  31. package/dist/runtime/hooks/transcript_tasks.js +0 -0
  32. package/dist/runtime/ralph/orchestrator.d.ts.map +1 -1
  33. package/dist/runtime/ralph/orchestrator.js +2 -1
  34. package/dist/runtime/ralph/orchestrator.js.map +1 -1
  35. package/dist/setup/cli/limits_state.d.ts.map +1 -1
  36. package/dist/setup/cli/limits_state.js +6 -40
  37. package/dist/setup/cli/limits_state.js.map +1 -1
  38. package/dist/setup/cli/pack_walk.d.ts +32 -0
  39. package/dist/setup/cli/pack_walk.d.ts.map +1 -0
  40. package/dist/setup/cli/pack_walk.js +76 -0
  41. package/dist/setup/cli/pack_walk.js.map +1 -0
  42. package/dist/setup/cli/permissions_state.d.ts.map +1 -1
  43. package/dist/setup/cli/permissions_state.js +6 -37
  44. package/dist/setup/cli/permissions_state.js.map +1 -1
  45. package/dist/setup/cli/triggers_state.d.ts.map +1 -1
  46. package/dist/setup/cli/triggers_state.js +3 -29
  47. package/dist/setup/cli/triggers_state.js.map +1 -1
  48. package/dist/workgraph/events.d.ts.map +1 -1
  49. package/dist/workgraph/events.js +10 -0
  50. package/dist/workgraph/events.js.map +1 -1
  51. package/dist/workgraph/store.d.ts.map +1 -1
  52. package/dist/workgraph/store.js +5 -0
  53. package/dist/workgraph/store.js.map +1 -1
  54. package/dist/workgraph/types.d.ts +2 -1
  55. package/dist/workgraph/types.d.ts.map +1 -1
  56. package/docs/ARCHITECTURE.md +268 -0
  57. package/package.json +5 -3
  58. package/packs/builtin/coding-flow/skills/entry-and-handoffs/skill.yaml +13 -17
  59. package/dist/anti-drift/evaluator.d.ts +0 -88
  60. package/dist/anti-drift/evaluator.d.ts.map +0 -1
  61. package/dist/anti-drift/evaluator.js +0 -417
  62. package/dist/anti-drift/evaluator.js.map +0 -1
  63. package/dist/anti-drift/evaluator.test.js +0 -78
  64. package/dist/anti-drift/rules.d.ts +0 -80
  65. package/dist/anti-drift/rules.d.ts.map +0 -1
  66. package/dist/anti-drift/rules.js +0 -368
  67. package/dist/anti-drift/rules.js.map +0 -1
  68. package/dist/anti-drift/rules.test.js +0 -213
  69. package/dist/anti-drift/state.d.ts +0 -107
  70. package/dist/anti-drift/state.d.ts.map +0 -1
  71. package/dist/anti-drift/state.js +0 -177
  72. package/dist/anti-drift/state.js.map +0 -1
  73. package/dist/anti-drift/state.test.js +0 -120
  74. package/dist/chat/adapters/discord.d.ts +0 -41
  75. package/dist/chat/adapters/discord.d.ts.map +0 -1
  76. package/dist/chat/adapters/discord.js +0 -176
  77. package/dist/chat/adapters/discord.js.map +0 -1
  78. package/dist/chat/adapters/discord.test.js +0 -25
  79. package/dist/chat/adapters/slack.d.ts +0 -43
  80. package/dist/chat/adapters/slack.d.ts.map +0 -1
  81. package/dist/chat/adapters/slack.js +0 -172
  82. package/dist/chat/adapters/slack.js.map +0 -1
  83. package/dist/chat/adapters/slack.test.js +0 -30
  84. package/dist/chat/adapters/telegram.d.ts +0 -148
  85. package/dist/chat/adapters/telegram.d.ts.map +0 -1
  86. package/dist/chat/adapters/telegram.js +0 -498
  87. package/dist/chat/adapters/telegram.js.map +0 -1
  88. package/dist/chat/adapters/telegram.test.js +0 -94
  89. package/dist/chat/config.d.ts +0 -98
  90. package/dist/chat/config.d.ts.map +0 -1
  91. package/dist/chat/config.js +0 -185
  92. package/dist/chat/config.js.map +0 -1
  93. package/dist/chat/daemon/active-project.d.ts +0 -17
  94. package/dist/chat/daemon/active-project.d.ts.map +0 -1
  95. package/dist/chat/daemon/active-project.js +0 -23
  96. package/dist/chat/daemon/active-project.js.map +0 -1
  97. package/dist/chat/daemon/autospawn.d.ts +0 -40
  98. package/dist/chat/daemon/autospawn.d.ts.map +0 -1
  99. package/dist/chat/daemon/autospawn.js +0 -129
  100. package/dist/chat/daemon/autospawn.js.map +0 -1
  101. package/dist/chat/daemon/autospawn.test.js +0 -112
  102. package/dist/chat/daemon/cli.d.ts +0 -18
  103. package/dist/chat/daemon/cli.d.ts.map +0 -1
  104. package/dist/chat/daemon/cli.js +0 -71
  105. package/dist/chat/daemon/cli.js.map +0 -1
  106. package/dist/chat/daemon/collisions.js +0 -384
  107. package/dist/chat/daemon/health-check.d.ts +0 -69
  108. package/dist/chat/daemon/health-check.d.ts.map +0 -1
  109. package/dist/chat/daemon/health-check.js +0 -112
  110. package/dist/chat/daemon/health-check.js.map +0 -1
  111. package/dist/chat/daemon/inbox-read.d.ts +0 -35
  112. package/dist/chat/daemon/inbox-read.d.ts.map +0 -1
  113. package/dist/chat/daemon/inbox-read.js +0 -75
  114. package/dist/chat/daemon/inbox-read.js.map +0 -1
  115. package/dist/chat/daemon/inbox-read.test.js +0 -97
  116. package/dist/chat/daemon/inbox.d.ts +0 -63
  117. package/dist/chat/daemon/inbox.d.ts.map +0 -1
  118. package/dist/chat/daemon/inbox.js +0 -56
  119. package/dist/chat/daemon/inbox.js.map +0 -1
  120. package/dist/chat/daemon/inbox.test.js +0 -110
  121. package/dist/chat/daemon/lifecycle.d.ts +0 -71
  122. package/dist/chat/daemon/lifecycle.d.ts.map +0 -1
  123. package/dist/chat/daemon/lifecycle.js +0 -221
  124. package/dist/chat/daemon/lifecycle.js.map +0 -1
  125. package/dist/chat/daemon/lifecycle.test.js +0 -163
  126. package/dist/chat/daemon/protocol.d.ts +0 -107
  127. package/dist/chat/daemon/protocol.d.ts.map +0 -1
  128. package/dist/chat/daemon/protocol.js +0 -54
  129. package/dist/chat/daemon/protocol.js.map +0 -1
  130. package/dist/chat/daemon/routing.d.ts +0 -140
  131. package/dist/chat/daemon/routing.d.ts.map +0 -1
  132. package/dist/chat/daemon/routing.js +0 -198
  133. package/dist/chat/daemon/routing.js.map +0 -1
  134. package/dist/chat/daemon/routing.test.js +0 -259
  135. package/dist/chat/daemon/rpc-client.d.ts +0 -45
  136. package/dist/chat/daemon/rpc-client.d.ts.map +0 -1
  137. package/dist/chat/daemon/rpc-client.js +0 -133
  138. package/dist/chat/daemon/rpc-client.js.map +0 -1
  139. package/dist/chat/daemon/rpc-server.d.ts +0 -39
  140. package/dist/chat/daemon/rpc-server.d.ts.map +0 -1
  141. package/dist/chat/daemon/rpc-server.js +0 -385
  142. package/dist/chat/daemon/rpc-server.js.map +0 -1
  143. package/dist/chat/daemon/rpc.test.js +0 -177
  144. package/dist/chat/daemon/subscribers.js +0 -257
  145. package/dist/chat/daemon/worker.d.ts +0 -27
  146. package/dist/chat/daemon/worker.d.ts.map +0 -1
  147. package/dist/chat/daemon/worker.js +0 -313
  148. package/dist/chat/daemon/worker.js.map +0 -1
  149. package/dist/chat/daemon/workspace-topic.js +0 -324
  150. package/dist/chat/env-token.d.ts +0 -60
  151. package/dist/chat/env-token.d.ts.map +0 -1
  152. package/dist/chat/env-token.js +0 -137
  153. package/dist/chat/env-token.js.map +0 -1
  154. package/dist/chat/env-token.test.js +0 -160
  155. package/dist/chat/factory.d.ts +0 -30
  156. package/dist/chat/factory.d.ts.map +0 -1
  157. package/dist/chat/factory.js +0 -50
  158. package/dist/chat/factory.js.map +0 -1
  159. package/dist/chat/factory.test.js +0 -55
  160. package/dist/chat/gateway.d.ts +0 -176
  161. package/dist/chat/gateway.d.ts.map +0 -1
  162. package/dist/chat/gateway.js +0 -146
  163. package/dist/chat/gateway.js.map +0 -1
  164. package/dist/chat/gateway.test.js +0 -192
  165. package/dist/claude-md.d.ts +0 -39
  166. package/dist/claude-md.d.ts.map +0 -1
  167. package/dist/claude-md.js +0 -113
  168. package/dist/claude-md.js.map +0 -1
  169. package/dist/claude-md.test.js +0 -91
  170. package/dist/codex/activate.d.ts +0 -66
  171. package/dist/codex/activate.d.ts.map +0 -1
  172. package/dist/codex/activate.js +0 -329
  173. package/dist/codex/activate.js.map +0 -1
  174. package/dist/codex/activate.test.js +0 -229
  175. package/dist/codex/bundled-default/bundled-default.test.js +0 -161
  176. package/dist/codex/cli-publish.test.js +0 -133
  177. package/dist/codex/cli.d.ts +0 -35
  178. package/dist/codex/cli.d.ts.map +0 -1
  179. package/dist/codex/cli.js +0 -554
  180. package/dist/codex/cli.js.map +0 -1
  181. package/dist/codex/cli.test.js +0 -277
  182. package/dist/codex/import-skill-md.d.ts +0 -53
  183. package/dist/codex/import-skill-md.d.ts.map +0 -1
  184. package/dist/codex/import-skill-md.js +0 -236
  185. package/dist/codex/import-skill-md.js.map +0 -1
  186. package/dist/codex/import-skill-md.test.js +0 -225
  187. package/dist/codex/loader.d.ts +0 -27
  188. package/dist/codex/loader.d.ts.map +0 -1
  189. package/dist/codex/loader.js +0 -86
  190. package/dist/codex/loader.js.map +0 -1
  191. package/dist/codex/loader.test.js +0 -75
  192. package/dist/codex/parse.d.ts +0 -28
  193. package/dist/codex/parse.d.ts.map +0 -1
  194. package/dist/codex/parse.js +0 -309
  195. package/dist/codex/parse.js.map +0 -1
  196. package/dist/codex/parse.test.js +0 -241
  197. package/dist/codex/store.d.ts +0 -87
  198. package/dist/codex/store.d.ts.map +0 -1
  199. package/dist/codex/store.js +0 -205
  200. package/dist/codex/store.js.map +0 -1
  201. package/dist/codex/store.test.js +0 -242
  202. package/dist/codex/types.d.ts +0 -398
  203. package/dist/codex/types.d.ts.map +0 -1
  204. package/dist/codex/types.js +0 -21
  205. package/dist/codex/types.js.map +0 -1
  206. package/dist/config.d.ts +0 -53
  207. package/dist/config.d.ts.map +0 -1
  208. package/dist/config.js +0 -202
  209. package/dist/config.js.map +0 -1
  210. package/dist/config.test.js +0 -117
  211. package/dist/engine/cli.d.ts +0 -14
  212. package/dist/engine/cli.d.ts.map +0 -1
  213. package/dist/engine/cli.js +0 -171
  214. package/dist/engine/cli.js.map +0 -1
  215. package/dist/engine/client.d.ts +0 -219
  216. package/dist/engine/client.d.ts.map +0 -1
  217. package/dist/engine/client.js +0 -312
  218. package/dist/engine/client.js.map +0 -1
  219. package/dist/engine/config.d.ts +0 -62
  220. package/dist/engine/config.d.ts.map +0 -1
  221. package/dist/engine/config.js +0 -223
  222. package/dist/engine/config.js.map +0 -1
  223. package/dist/engine/index.d.ts +0 -17
  224. package/dist/engine/index.d.ts.map +0 -1
  225. package/dist/engine/index.js +0 -16
  226. package/dist/engine/index.js.map +0 -1
  227. package/dist/engine/resolver.d.ts +0 -62
  228. package/dist/engine/resolver.d.ts.map +0 -1
  229. package/dist/engine/resolver.js +0 -103
  230. package/dist/engine/resolver.js.map +0 -1
  231. package/dist/engine/singleton.d.ts +0 -95
  232. package/dist/engine/singleton.d.ts.map +0 -1
  233. package/dist/engine/singleton.js +0 -325
  234. package/dist/engine/singleton.js.map +0 -1
  235. package/dist/engine/types.d.ts +0 -402
  236. package/dist/engine/types.d.ts.map +0 -1
  237. package/dist/engine/types.js +0 -22
  238. package/dist/engine/types.js.map +0 -1
  239. package/dist/engine-binary-resolver.js +0 -110
  240. package/dist/engine-binary-resolver.test.js +0 -61
  241. package/dist/engine-cli.js +0 -60
  242. package/dist/engine-client.js +0 -301
  243. package/dist/engine-client.test.js +0 -118
  244. package/dist/functions/chain_state.d.ts +0 -51
  245. package/dist/functions/chain_state.d.ts.map +0 -1
  246. package/dist/functions/chain_state.js +0 -59
  247. package/dist/functions/chain_state.js.map +0 -1
  248. package/dist/hooks/drift-catalog.d.ts +0 -68
  249. package/dist/hooks/drift-catalog.d.ts.map +0 -1
  250. package/dist/hooks/drift-catalog.js +0 -184
  251. package/dist/hooks/drift-catalog.js.map +0 -1
  252. package/dist/hooks/drift-catalog.test.js +0 -154
  253. package/dist/hooks/drift-patterns.d.ts +0 -110
  254. package/dist/hooks/drift-patterns.d.ts.map +0 -1
  255. package/dist/hooks/drift-patterns.js +0 -289
  256. package/dist/hooks/drift-patterns.js.map +0 -1
  257. package/dist/hooks/drift-patterns.test.js +0 -325
  258. package/dist/hooks/engine-vocab-gate.d.ts +0 -108
  259. package/dist/hooks/engine-vocab-gate.d.ts.map +0 -1
  260. package/dist/hooks/engine-vocab-gate.js +0 -225
  261. package/dist/hooks/engine-vocab-gate.js.map +0 -1
  262. package/dist/hooks/engine-vocab-gate.test.js +0 -170
  263. package/dist/hooks/heartbeat.d.ts +0 -107
  264. package/dist/hooks/heartbeat.d.ts.map +0 -1
  265. package/dist/hooks/heartbeat.js +0 -316
  266. package/dist/hooks/heartbeat.js.map +0 -1
  267. package/dist/hooks/heartbeat.test.js +0 -393
  268. package/dist/hooks/honesty-ledger-session-scope.test.js +0 -100
  269. package/dist/hooks/honesty-ledger.d.ts +0 -123
  270. package/dist/hooks/honesty-ledger.d.ts.map +0 -1
  271. package/dist/hooks/honesty-ledger.js +0 -226
  272. package/dist/hooks/honesty-ledger.js.map +0 -1
  273. package/dist/hooks/honesty-ledger.test.js +0 -466
  274. package/dist/hooks/inline-report-check.d.ts +0 -63
  275. package/dist/hooks/inline-report-check.d.ts.map +0 -1
  276. package/dist/hooks/inline-report-check.js +0 -88
  277. package/dist/hooks/inline-report-check.js.map +0 -1
  278. package/dist/hooks/inline-report-check.test.js +0 -96
  279. package/dist/hooks/pre-tool-use.d.ts +0 -62
  280. package/dist/hooks/pre-tool-use.d.ts.map +0 -1
  281. package/dist/hooks/pre-tool-use.js +0 -342
  282. package/dist/hooks/pre-tool-use.js.map +0 -1
  283. package/dist/hooks/pre-tool-use.test.js +0 -134
  284. package/dist/hooks/session-end.d.ts +0 -15
  285. package/dist/hooks/session-end.d.ts.map +0 -1
  286. package/dist/hooks/session-end.js +0 -60
  287. package/dist/hooks/session-end.js.map +0 -1
  288. package/dist/hooks/session-end.test.js +0 -52
  289. package/dist/hooks/stop.d.ts +0 -35
  290. package/dist/hooks/stop.d.ts.map +0 -1
  291. package/dist/hooks/stop.js +0 -136
  292. package/dist/hooks/stop.js.map +0 -1
  293. package/dist/hooks/transcript-active-task.test.js +0 -342
  294. package/dist/hooks/transcript.d.ts +0 -26
  295. package/dist/hooks/transcript.d.ts.map +0 -1
  296. package/dist/hooks/transcript.js +0 -266
  297. package/dist/hooks/transcript.js.map +0 -1
  298. package/dist/hooks/transcript.test.js +0 -103
  299. package/dist/hooks/user-prompt-submit.d.ts +0 -74
  300. package/dist/hooks/user-prompt-submit.d.ts.map +0 -1
  301. package/dist/hooks/user-prompt-submit.js +0 -256
  302. package/dist/hooks/user-prompt-submit.js.map +0 -1
  303. package/dist/hooks/user-prompt-submit.test.js +0 -118
  304. package/dist/hooks/versioning-gate.d.ts +0 -101
  305. package/dist/hooks/versioning-gate.d.ts.map +0 -1
  306. package/dist/hooks/versioning-gate.js +0 -245
  307. package/dist/hooks/versioning-gate.js.map +0 -1
  308. package/dist/hooks/versioning-gate.test.js +0 -368
  309. package/dist/hooks/workflow-gate.d.ts +0 -64
  310. package/dist/hooks/workflow-gate.d.ts.map +0 -1
  311. package/dist/hooks/workflow-gate.js +0 -152
  312. package/dist/hooks/workflow-gate.js.map +0 -1
  313. package/dist/hooks/workflow-gate.test.js +0 -197
  314. package/dist/hooks-cli.d.ts +0 -25
  315. package/dist/hooks-cli.d.ts.map +0 -1
  316. package/dist/hooks-cli.js +0 -286
  317. package/dist/hooks-cli.js.map +0 -1
  318. package/dist/hooks-cli.test.js +0 -148
  319. package/dist/origin.d.ts +0 -16
  320. package/dist/origin.d.ts.map +0 -1
  321. package/dist/origin.js +0 -92
  322. package/dist/origin.js.map +0 -1
  323. package/dist/packs/seed_lessons_ingest.d.ts +0 -30
  324. package/dist/packs/seed_lessons_ingest.d.ts.map +0 -1
  325. package/dist/packs/seed_lessons_ingest.js +0 -107
  326. package/dist/packs/seed_lessons_ingest.js.map +0 -1
  327. package/dist/project-cli.d.ts +0 -7
  328. package/dist/project-cli.d.ts.map +0 -1
  329. package/dist/project-cli.js +0 -145
  330. package/dist/project-cli.js.map +0 -1
  331. package/dist/project.d.ts +0 -127
  332. package/dist/project.d.ts.map +0 -1
  333. package/dist/project.js +0 -281
  334. package/dist/project.js.map +0 -1
  335. package/dist/project.test.js +0 -287
  336. package/dist/rag/backends/loop_engine.d.ts +0 -61
  337. package/dist/rag/backends/loop_engine.d.ts.map +0 -1
  338. package/dist/rag/backends/loop_engine.js +0 -160
  339. package/dist/rag/backends/loop_engine.js.map +0 -1
  340. package/dist/recall.d.ts +0 -82
  341. package/dist/recall.d.ts.map +0 -1
  342. package/dist/recall.js +0 -81
  343. package/dist/recall.js.map +0 -1
  344. package/dist/runtime/agent_bridge/autospawn.d.ts +0 -131
  345. package/dist/runtime/agent_bridge/autospawn.d.ts.map +0 -1
  346. package/dist/runtime/agent_bridge/autospawn.js +0 -251
  347. package/dist/runtime/agent_bridge/autospawn.js.map +0 -1
  348. package/dist/runtime/chain_state.d.ts +0 -124
  349. package/dist/runtime/chain_state.d.ts.map +0 -1
  350. package/dist/runtime/chain_state.js +0 -189
  351. package/dist/runtime/chain_state.js.map +0 -1
  352. package/dist/runtime/hooks/permission_decision.d.ts +0 -34
  353. package/dist/runtime/hooks/permission_decision.d.ts.map +0 -1
  354. package/dist/runtime/hooks/permission_decision.js +0 -39
  355. package/dist/runtime/hooks/permission_decision.js.map +0 -1
  356. package/dist/runtime/workflow_fsm.d.ts +0 -21
  357. package/dist/runtime/workflow_fsm.d.ts.map +0 -1
  358. package/dist/runtime/workflow_fsm.js +0 -25
  359. package/dist/runtime/workflow_fsm.js.map +0 -1
  360. package/dist/runtime/workflow_map.d.ts +0 -26
  361. package/dist/runtime/workflow_map.d.ts.map +0 -1
  362. package/dist/runtime/workflow_map.js +0 -38
  363. package/dist/runtime/workflow_map.js.map +0 -1
  364. package/dist/scope.d.ts +0 -48
  365. package/dist/scope.d.ts.map +0 -1
  366. package/dist/scope.js +0 -111
  367. package/dist/scope.js.map +0 -1
  368. package/dist/setup/cli/topic_create_step.d.ts +0 -84
  369. package/dist/setup/cli/topic_create_step.d.ts.map +0 -1
  370. package/dist/setup/cli/topic_create_step.js +0 -213
  371. package/dist/setup/cli/topic_create_step.js.map +0 -1
  372. package/dist/system-export.d.ts +0 -65
  373. package/dist/system-export.d.ts.map +0 -1
  374. package/dist/system-export.js +0 -194
  375. package/dist/system-export.js.map +0 -1
  376. package/dist/utterance/classifier.d.ts +0 -53
  377. package/dist/utterance/classifier.d.ts.map +0 -1
  378. package/dist/utterance/classifier.js +0 -184
  379. package/dist/utterance/classifier.js.map +0 -1
  380. package/dist/utterance/classifier.test.js +0 -147
@@ -1,96 +0,0 @@
1
- /**
2
- * Tests for inline-report-check (0.7.30 / D3 inline variant).
3
- *
4
- * Covers checkInlineReportFormat + the count helpers. Stop-hook
5
- * integration left to integration tests (it composes the existing
6
- * BrokenPromise pipeline which already has its own coverage).
7
- */
8
- import { describe, expect, it } from "vitest";
9
- import { checkInlineReportFormat, countCommitHashes, countVersionRefs, hasPhasesBlock, } from "./inline-report-check.js";
10
- describe("countVersionRefs", () => {
11
- it("counts distinct 0.X.Y refs", () => {
12
- expect(countVersionRefs("shipped 0.7.20 then 0.7.21 and 0.7.22")).toBe(3);
13
- });
14
- it("dedupes repeated mentions", () => {
15
- expect(countVersionRefs("0.7.20 fixed in 0.7.20 again")).toBe(1);
16
- });
17
- it("returns 0 on plain prose with no version", () => {
18
- expect(countVersionRefs("hello world, no versions here")).toBe(0);
19
- });
20
- it("does NOT count partial versions like '0.7'", () => {
21
- expect(countVersionRefs("the 0.7 series")).toBe(0);
22
- });
23
- });
24
- describe("countCommitHashes", () => {
25
- it("counts distinct 7-char hashes", () => {
26
- expect(countCommitHashes("see 92fe415 and 0e59ba3 and 40342e3")).toBe(3);
27
- });
28
- it("requires at least one a-f letter (excludes pure decimal)", () => {
29
- // 7-digit decimals like timestamps shouldn't trigger.
30
- expect(countCommitHashes("count is 1234567 and 9876543")).toBe(0);
31
- });
32
- it("counts full 40-char shas", () => {
33
- expect(countCommitHashes("4eaf39d2d21f0540342e3e881d2c47cde6d4ab39 abc")).toBe(1);
34
- });
35
- it("dedupes repeated hashes", () => {
36
- expect(countCommitHashes("92fe415 ... revisit 92fe415")).toBe(1);
37
- });
38
- });
39
- describe("hasPhasesBlock", () => {
40
- it("true for 'PHASES:' uppercase block", () => {
41
- expect(hasPhasesBlock("\nPHASES:\n- pre_research: ...")).toBe(true);
42
- });
43
- it("true for 'phases:' lowercase", () => {
44
- expect(hasPhasesBlock("phases:\n- x")).toBe(true);
45
- });
46
- it("true when 'PHASES' is followed by a newline", () => {
47
- expect(hasPhasesBlock("PHASES\n- pre_research")).toBe(true);
48
- });
49
- it("false when 'phases' appears in unrelated prose", () => {
50
- expect(hasPhasesBlock("we have three phases of testing")).toBe(false);
51
- });
52
- });
53
- describe("checkInlineReportFormat", () => {
54
- it("flags multi-version status report without PHASES", () => {
55
- const text = `Shipped 0.7.20, 0.7.21, 0.7.22 today. All tests green.`;
56
- const v = checkInlineReportFormat(text);
57
- expect(v).not.toBeNull();
58
- expect(v.signals.version_refs).toBe(3);
59
- });
60
- it("flags multi-commit chain-ship without PHASES", () => {
61
- const text = `Commits: 92fe415, 0e59ba3, 40342e3, d6275a1 all pushed.`;
62
- const v = checkInlineReportFormat(text);
63
- expect(v).not.toBeNull();
64
- expect(v.signals.hash_refs).toBeGreaterThanOrEqual(2);
65
- });
66
- it("does NOT flag when PHASES block is present", () => {
67
- const text = `🦑 #7 shipped 0.7.20, 0.7.21, 0.7.22.\n\nPHASES:\n- pre_research: ...\n- learn: ...\n- code: ...\n- test: ...\n- audit: ...\n- post_research: ...\n- fix: ...`;
68
- expect(checkInlineReportFormat(text)).toBeNull();
69
- });
70
- it("does NOT flag a single-version prose mention (signal too weak)", () => {
71
- const text = `I bumped opensquid to 0.7.30 in package.json.`;
72
- expect(checkInlineReportFormat(text)).toBeNull();
73
- });
74
- it("does NOT flag a single-commit-hash prose mention", () => {
75
- const text = `The commit 92fe415 introduced the D9 guard.`;
76
- expect(checkInlineReportFormat(text)).toBeNull();
77
- });
78
- it("does NOT flag empty input", () => {
79
- expect(checkInlineReportFormat("")).toBeNull();
80
- });
81
- it("matched_text condenses to <=120 chars + trims whitespace", () => {
82
- const long = "Shipped 0.7.20 and 0.7.21 today.\n\n".repeat(10);
83
- const v = checkInlineReportFormat(long);
84
- expect(v).not.toBeNull();
85
- expect(v.matched_text.length).toBeLessThanOrEqual(120);
86
- });
87
- it("dogfood: catches the 'where are my 7 phases' incident shape", () => {
88
- // The user's complaint was the summary table I posted with 10
89
- // versions and 10 commit hashes but no PHASES heading.
90
- const text = `Final tally: 0.7.20 92fe415, 0.7.21 0e59ba3, 0.7.22 40342e3, 0.7.23 d6275a1, 0.7.24 e881d2c, 0.7.25 e47b65c, 0.7.26 2d21f05, 0.7.27 4ab3977, 0.7.28 47cde6d, 0.7.29 4eaf39d.`;
91
- const v = checkInlineReportFormat(text);
92
- expect(v).not.toBeNull();
93
- expect(v.signals.version_refs).toBe(10);
94
- expect(v.signals.hash_refs).toBe(10);
95
- });
96
- });
@@ -1,62 +0,0 @@
1
- /**
2
- * `opensquid hook pre-tool-use` — Claude Code PreToolUse hook handler.
3
- *
4
- * Wired in `~/.claude/settings.json`:
5
- *
6
- * {
7
- * "hooks": {
8
- * "PreToolUse": [
9
- * {
10
- * "matcher": "Bash",
11
- * "hooks": [
12
- * { "type": "command",
13
- * "command": "node /path/to/opensquid/dist/index.js hook pre-tool-use" }
14
- * ]
15
- * }
16
- * ]
17
- * }
18
- * }
19
- *
20
- * Stdin: JSON describing the planned tool call (Claude Code's hook
21
- * input schema). Stdout: empty on no-op. Stderr: drift findings.
22
- * Exit code: 0 to proceed, 2 to block the call.
23
- *
24
- * The catalog of intercepts lives in src/hooks/drift-patterns.ts and
25
- * grows lesson-by-lesson as drifts are observed and the user endorses
26
- * the rule.
27
- */
28
- import { type ToolCallInput } from "./drift-patterns.js";
29
- /**
30
- * #173 — return a warning string when an active-task-gated MCP tool is
31
- * about to be called without an in_progress TodoWrite task in the
32
- * transcript. Returns `null` when the tool isn't gated, no transcript
33
- * path is available, or an active task is detected.
34
- *
35
- * Transcript-read failures (missing file, malformed JSONL) swallow to
36
- * null — the hook must never block a legitimate call on its own bug.
37
- * The workflow-gate fail-opens silently in this case
38
- * (workflow-gate.ts:97-100); this surface makes that fail-open
39
- * observable from the call site.
40
- *
41
- * Exported for direct testing.
42
- */
43
- export declare function checkActiveTaskRequirement(call: ToolCallInput, transcriptPath: string | undefined): Promise<string | null>;
44
- /**
45
- * 0.7.25 / D3 — when `chat_send` is called with a body that looks like
46
- * a task-completion report (starts with the agent's `🦑 #<N>` marker),
47
- * verify the body includes a `PHASES` heading + at least 7 phase
48
- * lines per `[[feedback_telegram_reports]]`. Returns a non-blocking
49
- * warning string when the format is missing, null otherwise.
50
- *
51
- * Catches D3: paragraph summary sent instead of the locked 7-phase
52
- * format. Detection is heuristic (the agent could write a real
53
- * non-report message starting with `🦑 #N` — accepted noise).
54
- *
55
- * Exported for direct testing.
56
- */
57
- export declare function checkChatSendReportFormat(call: ToolCallInput): string | null;
58
- /**
59
- * Read JSON from stdin, evaluate drifts, exit with the appropriate code.
60
- */
61
- export declare function runPreToolUseHook(): Promise<void>;
62
- //# sourceMappingURL=pre-tool-use.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pre-tool-use.d.ts","sourceRoot":"","sources":["../../src.legacy/hooks/pre-tool-use.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAsB7E;;;;;;;;;;;;;GAaG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,aAAa,EACnB,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAkB5E;AAoBD;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2KvD"}
@@ -1,342 +0,0 @@
1
- /**
2
- * `opensquid hook pre-tool-use` — Claude Code PreToolUse hook handler.
3
- *
4
- * Wired in `~/.claude/settings.json`:
5
- *
6
- * {
7
- * "hooks": {
8
- * "PreToolUse": [
9
- * {
10
- * "matcher": "Bash",
11
- * "hooks": [
12
- * { "type": "command",
13
- * "command": "node /path/to/opensquid/dist/index.js hook pre-tool-use" }
14
- * ]
15
- * }
16
- * ]
17
- * }
18
- * }
19
- *
20
- * Stdin: JSON describing the planned tool call (Claude Code's hook
21
- * input schema). Stdout: empty on no-op. Stderr: drift findings.
22
- * Exit code: 0 to proceed, 2 to block the call.
23
- *
24
- * The catalog of intercepts lives in src/hooks/drift-patterns.ts and
25
- * grows lesson-by-lesson as drifts are observed and the user endorses
26
- * the rule.
27
- */
28
- import { decide, findDrifts } from "./drift-patterns.js";
29
- import { evaluateEngineVocabGate } from "./engine-vocab-gate.js";
30
- import { clearRecallRequired, isRecallRequired } from "./heartbeat.js";
31
- import { recordToolCall } from "./honesty-ledger.js";
32
- import { readActiveTaskId } from "./transcript.js";
33
- import { evaluateVersioningGate } from "./versioning-gate.js";
34
- import { evaluateWorkflowGate } from "./workflow-gate.js";
35
- /**
36
- * MCP tools that participate in the drift-protection track. When any
37
- * of these is called WITHOUT an in_progress TodoWrite task in the
38
- * transcript, the workflow-gate / chat-routing signals end up writing
39
- * to a ledger that no gate validates against. We can't BLOCK these
40
- * calls (legitimate ad-hoc usage exists), but emit a loud stderr
41
- * warning so the gap is visible. #173 / drift D1 structural fix
42
- * (locked 2026-05-17).
43
- */
44
- const ACTIVE_TASK_GATED_MCP_TOOLS = new Set([
45
- "mcp__opensquid__log_phase",
46
- "mcp__opensquid__chat_send",
47
- ]);
48
- /**
49
- * #173 — return a warning string when an active-task-gated MCP tool is
50
- * about to be called without an in_progress TodoWrite task in the
51
- * transcript. Returns `null` when the tool isn't gated, no transcript
52
- * path is available, or an active task is detected.
53
- *
54
- * Transcript-read failures (missing file, malformed JSONL) swallow to
55
- * null — the hook must never block a legitimate call on its own bug.
56
- * The workflow-gate fail-opens silently in this case
57
- * (workflow-gate.ts:97-100); this surface makes that fail-open
58
- * observable from the call site.
59
- *
60
- * Exported for direct testing.
61
- */
62
- export async function checkActiveTaskRequirement(call, transcriptPath) {
63
- if (!ACTIVE_TASK_GATED_MCP_TOOLS.has(call.tool))
64
- return null;
65
- if (!transcriptPath)
66
- return null;
67
- try {
68
- const activeTaskId = await readActiveTaskId(transcriptPath);
69
- if (activeTaskId)
70
- return null;
71
- }
72
- catch {
73
- return null;
74
- }
75
- return (`🦑 [opensquid] ${call.tool} called without an in_progress TodoWrite task — ` +
76
- `the entries it writes WON'T be validated by the workflow-gate. ` +
77
- `Call TaskCreate (and set in_progress) first so the gate has an active task to enforce against.\n`);
78
- }
79
- /**
80
- * 0.7.25 / D3 — when `chat_send` is called with a body that looks like
81
- * a task-completion report (starts with the agent's `🦑 #<N>` marker),
82
- * verify the body includes a `PHASES` heading + at least 7 phase
83
- * lines per `[[feedback_telegram_reports]]`. Returns a non-blocking
84
- * warning string when the format is missing, null otherwise.
85
- *
86
- * Catches D3: paragraph summary sent instead of the locked 7-phase
87
- * format. Detection is heuristic (the agent could write a real
88
- * non-report message starting with `🦑 #N` — accepted noise).
89
- *
90
- * Exported for direct testing.
91
- */
92
- export function checkChatSendReportFormat(call) {
93
- if (call.tool !== "mcp__opensquid__chat_send")
94
- return null;
95
- const text = call.input.text;
96
- if (typeof text !== "string")
97
- return null;
98
- // Trigger: message starts with the report marker `🦑 #N`.
99
- if (!/^\s*🦑\s+#\d/.test(text))
100
- return null;
101
- // Format requirement: must include a PHASES heading and the 7 phase
102
- // names. The phase names match the codex's default workflow.
103
- if (!/\bPHASES\b/.test(text)) {
104
- return (`🦑 [opensquid] chat_send body looks like a task-completion report ` +
105
- `(starts with \`🦑 #N\`) but is missing the \`PHASES\` block. ` +
106
- `Per [[feedback_telegram_reports]] reports must list each phase ` +
107
- `(pre_research, learn, code, test, audit, post_research, fix) ` +
108
- `with a concrete one-line finding — not just ✅. Catches drift D3.\n`);
109
- }
110
- return null;
111
- }
112
- /**
113
- * Read JSON from stdin, evaluate drifts, exit with the appropriate code.
114
- */
115
- export async function runPreToolUseHook() {
116
- let raw = "";
117
- for await (const chunk of process.stdin) {
118
- raw += chunk;
119
- }
120
- // Empty stdin → nothing to evaluate. Some hook configurations may
121
- // pipe nothing during tests; bail gracefully.
122
- if (!raw.trim()) {
123
- process.exit(0);
124
- }
125
- let payload;
126
- try {
127
- payload = JSON.parse(raw);
128
- }
129
- catch {
130
- // Malformed input — don't block on opensquid's own bug.
131
- process.stderr.write("[opensquid hook] malformed PreToolUse input — proceeding\n");
132
- process.exit(0);
133
- }
134
- if (!payload.tool_name || typeof payload.tool_name !== "string") {
135
- process.exit(0);
136
- }
137
- const call = {
138
- tool: payload.tool_name,
139
- input: payload.tool_input ?? {},
140
- };
141
- // #173 / 0.7.29 — D1 BLOCK upgrade. When an active-task-gated MCP
142
- // tool is called without an in_progress TodoWrite task in the
143
- // transcript, BLOCK (was: WARN). The design doc rule #1 says BLOCK
144
- // is the right semantic: log_phase / chat_send without an active
145
- // task is exactly the failure mode the workflow-gate exists to
146
- // prevent, and a soft warning was empirically ignored every time.
147
- // Bypass: OPENSQUID_SKIP_ACTIVE_TASK_GATE=1 for legitimate
148
- // non-task-scoped calls.
149
- const taskWarning = await checkActiveTaskRequirement(call, payload.transcript_path);
150
- if (taskWarning) {
151
- process.stderr.write(taskWarning);
152
- if (!checkActiveTaskBypassEnv()) {
153
- process.stderr.write(` This is a BLOCK (was WARN through 0.7.28). Call TaskCreate first.\n` +
154
- ` Override (genuine non-task-scoped call): set OPENSQUID_SKIP_ACTIVE_TASK_GATE=1.\n`);
155
- process.exit(2);
156
- }
157
- process.stderr.write(` 🦑 [opensquid active-task-gate] BYPASSED via OPENSQUID_SKIP_ACTIVE_TASK_GATE=1\n`);
158
- }
159
- // 0.7.25 / D3 — when chat_send body looks like a report but is missing
160
- // the 7-phase format, warn. Non-blocking.
161
- const formatWarning = checkChatSendReportFormat(call);
162
- if (formatWarning) {
163
- process.stderr.write(formatWarning);
164
- }
165
- // 0.7.26 / D7 — heartbeat-recall enforcement. When UPS surfaced a
166
- // heartbeat nudge this turn, the recall-required flag is set; block
167
- // any mcp__opensquid__* tool other than `recall` until the agent
168
- // actually calls recall. On a recall call, clear the flag.
169
- if (payload.session_id) {
170
- try {
171
- if (call.tool === "mcp__opensquid__recall" && (await isRecallRequired(payload.session_id))) {
172
- await clearRecallRequired(payload.session_id);
173
- }
174
- else if (call.tool.startsWith("mcp__opensquid__") &&
175
- !checkRecallBypassEnv() &&
176
- (await isRecallRequired(payload.session_id))) {
177
- process.stderr.write(buildRecallRequiredBlockMessage(call.tool));
178
- process.exit(2);
179
- }
180
- }
181
- catch (err) {
182
- process.stderr.write(`[opensquid hook] recall-required check failed (proceeding): ${err instanceof Error ? err.message : err}\n`);
183
- }
184
- }
185
- // v0.4: append to the honesty ledger so the Stop hook can reconcile
186
- // assistant claims against tool calls. Best-effort — never block the
187
- // call on a ledger write failure.
188
- if (payload.session_id) {
189
- try {
190
- const inputSummary = summarizeInput(call.tool, call.input);
191
- await recordToolCall(payload.session_id, call.tool, inputSummary);
192
- }
193
- catch (err) {
194
- process.stderr.write(`[opensquid hook] honesty-ledger write failed (non-fatal): ${err instanceof Error ? err.message : err}\n`);
195
- }
196
- }
197
- const hits = findDrifts(call);
198
- const { exit, stderr } = decide(hits, call);
199
- if (stderr)
200
- process.stderr.write(stderr);
201
- if (exit !== 0) {
202
- // Existing drift gate already blocking; don't spend RPC budget on
203
- // the workflow gate.
204
- process.exit(exit);
205
- }
206
- // v0.6.1 workflow gate — when the tool call is `git commit` (not
207
- // --amend, which has its own gate), check that the active task's
208
- // phase ledger has the required phases logged. Engine-RPC-backed,
209
- // so only fires when the engine binary is reachable. Fail-open on
210
- // any error (per [[honesty-ledger]] precedent — never block on
211
- // opensquid's own bug). Spawning the engine just for this check is
212
- // expensive (~hundreds of ms per hook), so it's scoped tightly to
213
- // commit commands.
214
- if (looksLikeGitCommit(call)) {
215
- try {
216
- const gateResult = await evaluateWorkflowGate({
217
- transcriptPath: payload.transcript_path,
218
- });
219
- if (gateResult.block) {
220
- process.stderr.write(gateResult.stderr);
221
- process.exit(2);
222
- }
223
- else if (gateResult.stderr) {
224
- // Warning only — proceed.
225
- process.stderr.write(gateResult.stderr);
226
- }
227
- }
228
- catch (err) {
229
- process.stderr.write(`[opensquid hook] workflow-gate failed (proceeding): ${err instanceof Error ? err.message : err}\n`);
230
- }
231
- // v0.6.3 versioning gate — enforce per-commit patch bumps. Local
232
- // git diff inspection only (no RPC), so cheap. Same fail-open
233
- // invariant as the workflow gate.
234
- try {
235
- const versionResult = await evaluateVersioningGate({ cwd: payload.cwd });
236
- if (versionResult.block) {
237
- process.stderr.write(versionResult.stderr);
238
- process.exit(2);
239
- }
240
- else if (versionResult.stderr) {
241
- process.stderr.write(versionResult.stderr);
242
- }
243
- }
244
- catch (err) {
245
- process.stderr.write(`[opensquid hook] versioning-gate failed (proceeding): ${err instanceof Error ? err.message : err}\n`);
246
- }
247
- // 0.7.21 / D6 — engine vocabulary gate. Blocks engine commits whose
248
- // -m message OR staged diff content references consumer-product
249
- // names (opensquid, claude code, etc.). Early-exits on non-engine
250
- // cwd; cheap when not applicable.
251
- try {
252
- const bashCmd = stringField(call.input, "command");
253
- const vocabResult = await evaluateEngineVocabGate({
254
- cwd: payload.cwd,
255
- bashCommand: bashCmd ?? undefined,
256
- });
257
- if (vocabResult.block) {
258
- process.stderr.write(vocabResult.stderr);
259
- process.exit(2);
260
- }
261
- else if (vocabResult.stderr) {
262
- process.stderr.write(vocabResult.stderr);
263
- }
264
- }
265
- catch (err) {
266
- process.stderr.write(`[opensquid hook] engine-vocab-gate failed (proceeding): ${err instanceof Error ? err.message : err}\n`);
267
- }
268
- }
269
- process.exit(0);
270
- }
271
- function stringField(input, field) {
272
- const v = input[field];
273
- return typeof v === "string" ? v : null;
274
- }
275
- /**
276
- * 0.7.26 / D7 — emergency bypass for the recall-required block. For
277
- * cases where the engine is unreachable and the agent can't call
278
- * recall through normal channels.
279
- */
280
- function checkRecallBypassEnv() {
281
- return process.env.OPENSQUID_SKIP_RECALL_GATE === "1";
282
- }
283
- /**
284
- * 0.7.29 / D1 BLOCK upgrade — emergency bypass for the active-task
285
- * requirement. For legitimate non-task-scoped log_phase / chat_send
286
- * calls (e.g. an ad-hoc one-shot ping to the user).
287
- */
288
- function checkActiveTaskBypassEnv() {
289
- return process.env.OPENSQUID_SKIP_ACTIVE_TASK_GATE === "1";
290
- }
291
- function buildRecallRequiredBlockMessage(tool) {
292
- return (`🦑 [opensquid recall-gate] ${tool} blocked — heartbeat was surfaced ` +
293
- `this turn but recall hasn't been called yet.\n` +
294
- `Call \`mcp__opensquid__recall\` first to re-anchor on the active task, ` +
295
- `then retry. Drift D7.\n` +
296
- `Override (genuine emergency, e.g. engine unreachable): set ` +
297
- `OPENSQUID_SKIP_RECALL_GATE=1 for this command.\n`);
298
- }
299
- function looksLikeGitCommit(call) {
300
- if (call.tool !== "Bash")
301
- return false;
302
- const cmd = call.input.command;
303
- if (typeof cmd !== "string")
304
- return false;
305
- // Match `git commit ...` but NOT `git commit --amend` (handled by
306
- // existing drift pattern). Also skip cases where the command is
307
- // clearly a comment or inside quotes (drift-patterns.ts uses the
308
- // same quote-stripping; we duplicate the minimal version here).
309
- const stripped = cmd.replace(/"[^"]*"/g, "").replace(/'[^']*'/g, "");
310
- if (!/\bgit\s+commit\b/.test(stripped))
311
- return false;
312
- if (/\bgit\s+commit\b[^|;&]*--amend/.test(stripped))
313
- return false;
314
- return true;
315
- }
316
- /**
317
- * Tight summary of tool input for the ledger. We keep just enough to
318
- * reconcile claims (e.g. "did the agent run npm test?") without writing
319
- * the whole tool_input blob.
320
- */
321
- function summarizeInput(tool, input) {
322
- if (tool === "Bash") {
323
- const cmd = input.command;
324
- return typeof cmd === "string" ? cmd.slice(0, 500) : "";
325
- }
326
- if (tool === "Edit" || tool === "Write" || tool === "Read") {
327
- const fp = input.file_path;
328
- return typeof fp === "string" ? fp : "";
329
- }
330
- if (tool === "Agent") {
331
- const desc = input.description ?? input.subagent_type ?? "";
332
- return typeof desc === "string" ? desc.slice(0, 200) : "";
333
- }
334
- // Default — short JSON peek for unknown tools.
335
- try {
336
- return JSON.stringify(input).slice(0, 200);
337
- }
338
- catch {
339
- return "";
340
- }
341
- }
342
- //# sourceMappingURL=pre-tool-use.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pre-tool-use.js","sourceRoot":"","sources":["../../src.legacy/hooks/pre-tool-use.ts"],"names":[],"mappings":"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"}
@@ -1,134 +0,0 @@
1
- /**
2
- * Pre-tool-use hook tests — focused on the #173 (drift D1) active-task
3
- * requirement check. Runs against a synthetic transcript file with
4
- * controllable TodoWrite shape.
5
- */
6
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
7
- import * as crypto from "node:crypto";
8
- import { promises as fs } from "node:fs";
9
- import * as os from "node:os";
10
- import * as path from "node:path";
11
- import { checkActiveTaskRequirement, checkChatSendReportFormat } from "./pre-tool-use.js";
12
- let tmpDir;
13
- let transcriptPath;
14
- beforeEach(async () => {
15
- tmpDir = path.join(os.tmpdir(), `opensquid-ptu-${crypto.randomUUID()}`);
16
- await fs.mkdir(tmpDir, { recursive: true });
17
- transcriptPath = path.join(tmpDir, "transcript.jsonl");
18
- });
19
- afterEach(async () => {
20
- await fs.rm(tmpDir, { recursive: true, force: true });
21
- });
22
- async function writeTranscriptWithActiveTask(taskId) {
23
- const event = {
24
- type: "assistant",
25
- message: {
26
- role: "assistant",
27
- content: [
28
- {
29
- type: "tool_use",
30
- name: "TodoWrite",
31
- input: {
32
- todos: [{ id: taskId, status: "in_progress", content: "active thing" }],
33
- },
34
- },
35
- ],
36
- },
37
- };
38
- await fs.writeFile(transcriptPath, JSON.stringify(event) + "\n", "utf8");
39
- }
40
- describe("checkActiveTaskRequirement — #173 / drift D1 fix", () => {
41
- it("returns null for tools that aren't active-task-gated", async () => {
42
- const result = await checkActiveTaskRequirement({ tool: "Bash", input: { command: "ls" } }, transcriptPath);
43
- expect(result).toBeNull();
44
- });
45
- it("returns null when no transcript path is provided", async () => {
46
- const result = await checkActiveTaskRequirement({ tool: "mcp__opensquid__log_phase", input: {} }, undefined);
47
- expect(result).toBeNull();
48
- });
49
- it("returns null when an in_progress task exists in the transcript", async () => {
50
- await writeTranscriptWithActiveTask("42");
51
- const result = await checkActiveTaskRequirement({ tool: "mcp__opensquid__log_phase", input: { task_id: "42", phase: "code" } }, transcriptPath);
52
- expect(result).toBeNull();
53
- });
54
- it("returns a warning when log_phase is called with no in_progress task", async () => {
55
- await fs.writeFile(transcriptPath, "", "utf8"); // empty transcript = no tasks
56
- const result = await checkActiveTaskRequirement({ tool: "mcp__opensquid__log_phase", input: { task_id: "42", phase: "code" } }, transcriptPath);
57
- expect(result).not.toBeNull();
58
- expect(result).toContain("mcp__opensquid__log_phase called without an in_progress");
59
- expect(result).toContain("TaskCreate");
60
- });
61
- it("returns a warning when chat_send is called with no in_progress task", async () => {
62
- await fs.writeFile(transcriptPath, "", "utf8");
63
- const result = await checkActiveTaskRequirement({ tool: "mcp__opensquid__chat_send", input: { channel: "telegram:1", text: "hi" } }, transcriptPath);
64
- expect(result).not.toBeNull();
65
- expect(result).toContain("mcp__opensquid__chat_send called without an in_progress");
66
- });
67
- it("emits the warning even when the transcript file is missing (readActiveTaskId returns null gracefully)", async () => {
68
- // readActiveTaskId handles missing files internally and returns
69
- // null. The D1 check treats null-active-task as "no in_progress
70
- // signal" regardless of cause, which is the right semantic — the
71
- // agent skipped TaskCreate is the failure mode either way.
72
- const result = await checkActiveTaskRequirement({ tool: "mcp__opensquid__log_phase", input: {} }, path.join(tmpDir, "nonexistent.jsonl"));
73
- expect(result).not.toBeNull();
74
- expect(result).toContain("called without an in_progress");
75
- });
76
- });
77
- describe("checkChatSendReportFormat — 0.7.25 / drift D3", () => {
78
- it("returns null for tools other than chat_send", () => {
79
- const result = checkChatSendReportFormat({
80
- tool: "Bash",
81
- input: { command: "🦑 #4 fake bash" },
82
- });
83
- expect(result).toBeNull();
84
- });
85
- it("returns null when text doesn't start with the 🦑 #N marker", () => {
86
- const result = checkChatSendReportFormat({
87
- tool: "mcp__opensquid__chat_send",
88
- input: { text: "just a regular ping" },
89
- });
90
- expect(result).toBeNull();
91
- });
92
- it("returns null when text starts with the marker AND has PHASES heading", () => {
93
- const result = checkChatSendReportFormat({
94
- tool: "mcp__opensquid__chat_send",
95
- input: {
96
- text: "🦑 #170 — engine-client startupAck fix\n\n" +
97
- "PHASES:\n" +
98
- "- pre_research: surveyed engine-client.ts and engine-client.test.ts\n" +
99
- "- learn: bug localized to startupAck memoization\n" +
100
- "- code: 3-LOC fix in src/engine-client.ts:103-110\n" +
101
- "- test: 2 new tests for respawn-after-exit\n" +
102
- "- audit: reviewed for regressions; none found\n" +
103
- "- post_research: docs note on resume behavior\n" +
104
- "- fix: applied + committed\n",
105
- },
106
- });
107
- expect(result).toBeNull();
108
- });
109
- it("WARNS when text starts with marker but PHASES heading missing", () => {
110
- const result = checkChatSendReportFormat({
111
- tool: "mcp__opensquid__chat_send",
112
- input: {
113
- text: "🦑 #170 — engine-client startupAck fix\n\nshipped, all green",
114
- },
115
- });
116
- expect(result).not.toBeNull();
117
- expect(result).toContain("missing the `PHASES` block");
118
- expect(result).toContain("drift D3");
119
- });
120
- it("respects leading whitespace before the marker", () => {
121
- const result = checkChatSendReportFormat({
122
- tool: "mcp__opensquid__chat_send",
123
- input: { text: " 🦑 #4 cleanup\n\nno phases here" },
124
- });
125
- expect(result).not.toBeNull();
126
- });
127
- it("returns null when text input is missing entirely", () => {
128
- const result = checkChatSendReportFormat({
129
- tool: "mcp__opensquid__chat_send",
130
- input: { channel: "telegram:1" },
131
- });
132
- expect(result).toBeNull();
133
- });
134
- });
@@ -1,15 +0,0 @@
1
- /**
2
- * `opensquid hook session-end` — Claude Code SessionEnd hook handler.
3
- *
4
- * Fires when a Claude Code session terminates. Wipes the session's
5
- * honesty-ledger state (turn-ledger.jsonl + broken-promises.jsonl) so
6
- * the ledger doesn't grow unbounded across all-time sessions.
7
- *
8
- * Without this hook, every Claude Code session creates a
9
- * <data-root>/sessions/<id>/ directory with two JSONL files that
10
- * never get cleaned up. Disk usage grows linearly with session count.
11
- *
12
- * Exit 0 always — SessionEnd is cleanup, not blocking.
13
- */
14
- export declare function runSessionEndHook(): Promise<void>;
15
- //# sourceMappingURL=session-end.d.ts.map