opensquid 0.5.441 → 0.5.449

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 (391) 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/functions/recall_pre_inject.d.ts.map +1 -1
  11. package/dist/functions/recall_pre_inject.js +12 -0
  12. package/dist/functions/recall_pre_inject.js.map +1 -1
  13. package/dist/rag/store_git.d.ts +23 -0
  14. package/dist/rag/store_git.d.ts.map +1 -0
  15. package/dist/rag/store_git.js +57 -0
  16. package/dist/rag/store_git.js.map +1 -0
  17. package/dist/runtime/bootstrap.d.ts.map +1 -1
  18. package/dist/runtime/bootstrap.js +2 -0
  19. package/dist/runtime/bootstrap.js.map +1 -1
  20. package/dist/runtime/handoff/render.d.ts +5 -4
  21. package/dist/runtime/handoff/render.d.ts.map +1 -1
  22. package/dist/runtime/handoff/render.js +7 -7
  23. package/dist/runtime/handoff/render.js.map +1 -1
  24. package/dist/runtime/hooks/active_task_mirror.js +0 -0
  25. package/dist/runtime/hooks/apply_patch.js +0 -0
  26. package/dist/runtime/hooks/dispatch.js +0 -0
  27. package/dist/runtime/hooks/hook_output.js +0 -0
  28. package/dist/runtime/hooks/memory_reconcile.js +0 -0
  29. package/dist/runtime/hooks/new_project_detect.js +0 -0
  30. package/dist/runtime/hooks/profession_resolver.js +0 -0
  31. package/dist/runtime/hooks/scope_intent.js +0 -0
  32. package/dist/runtime/hooks/session-end.js +11 -0
  33. package/dist/runtime/hooks/session-end.js.map +1 -1
  34. package/dist/runtime/hooks/session_id.js +0 -0
  35. package/dist/runtime/hooks/session_liveness.js +0 -0
  36. package/dist/runtime/hooks/stop_drive.js +0 -0
  37. package/dist/runtime/hooks/stop_stream.js +0 -0
  38. package/dist/runtime/hooks/subagent_guard.js +0 -0
  39. package/dist/runtime/hooks/transcript.js +0 -0
  40. package/dist/runtime/hooks/transcript_tasks.js +0 -0
  41. package/dist/runtime/ralph/orchestrator.d.ts.map +1 -1
  42. package/dist/runtime/ralph/orchestrator.js +2 -1
  43. package/dist/runtime/ralph/orchestrator.js.map +1 -1
  44. package/dist/setup/cli/limits_state.d.ts.map +1 -1
  45. package/dist/setup/cli/limits_state.js +6 -40
  46. package/dist/setup/cli/limits_state.js.map +1 -1
  47. package/dist/setup/cli/pack_walk.d.ts +32 -0
  48. package/dist/setup/cli/pack_walk.d.ts.map +1 -0
  49. package/dist/setup/cli/pack_walk.js +76 -0
  50. package/dist/setup/cli/pack_walk.js.map +1 -0
  51. package/dist/setup/cli/permissions_state.d.ts.map +1 -1
  52. package/dist/setup/cli/permissions_state.js +6 -37
  53. package/dist/setup/cli/permissions_state.js.map +1 -1
  54. package/dist/setup/cli/triggers_state.d.ts.map +1 -1
  55. package/dist/setup/cli/triggers_state.js +3 -29
  56. package/dist/setup/cli/triggers_state.js.map +1 -1
  57. package/dist/workgraph/events.d.ts.map +1 -1
  58. package/dist/workgraph/events.js +10 -0
  59. package/dist/workgraph/events.js.map +1 -1
  60. package/dist/workgraph/store.d.ts.map +1 -1
  61. package/dist/workgraph/store.js +5 -0
  62. package/dist/workgraph/store.js.map +1 -1
  63. package/dist/workgraph/types.d.ts +2 -1
  64. package/dist/workgraph/types.d.ts.map +1 -1
  65. package/docs/ARCHITECTURE.md +268 -0
  66. package/docs/pack-runtime.md +15 -12
  67. package/docs/skill-grammar-guide.md +4 -4
  68. package/package.json +5 -3
  69. package/packs/builtin/coding-flow/skills/entry-and-handoffs/skill.yaml +13 -17
  70. package/dist/anti-drift/evaluator.d.ts +0 -88
  71. package/dist/anti-drift/evaluator.d.ts.map +0 -1
  72. package/dist/anti-drift/evaluator.js +0 -417
  73. package/dist/anti-drift/evaluator.js.map +0 -1
  74. package/dist/anti-drift/evaluator.test.js +0 -78
  75. package/dist/anti-drift/rules.d.ts +0 -80
  76. package/dist/anti-drift/rules.d.ts.map +0 -1
  77. package/dist/anti-drift/rules.js +0 -368
  78. package/dist/anti-drift/rules.js.map +0 -1
  79. package/dist/anti-drift/rules.test.js +0 -213
  80. package/dist/anti-drift/state.d.ts +0 -107
  81. package/dist/anti-drift/state.d.ts.map +0 -1
  82. package/dist/anti-drift/state.js +0 -177
  83. package/dist/anti-drift/state.js.map +0 -1
  84. package/dist/anti-drift/state.test.js +0 -120
  85. package/dist/chat/adapters/discord.d.ts +0 -41
  86. package/dist/chat/adapters/discord.d.ts.map +0 -1
  87. package/dist/chat/adapters/discord.js +0 -176
  88. package/dist/chat/adapters/discord.js.map +0 -1
  89. package/dist/chat/adapters/discord.test.js +0 -25
  90. package/dist/chat/adapters/slack.d.ts +0 -43
  91. package/dist/chat/adapters/slack.d.ts.map +0 -1
  92. package/dist/chat/adapters/slack.js +0 -172
  93. package/dist/chat/adapters/slack.js.map +0 -1
  94. package/dist/chat/adapters/slack.test.js +0 -30
  95. package/dist/chat/adapters/telegram.d.ts +0 -148
  96. package/dist/chat/adapters/telegram.d.ts.map +0 -1
  97. package/dist/chat/adapters/telegram.js +0 -498
  98. package/dist/chat/adapters/telegram.js.map +0 -1
  99. package/dist/chat/adapters/telegram.test.js +0 -94
  100. package/dist/chat/config.d.ts +0 -98
  101. package/dist/chat/config.d.ts.map +0 -1
  102. package/dist/chat/config.js +0 -185
  103. package/dist/chat/config.js.map +0 -1
  104. package/dist/chat/daemon/active-project.d.ts +0 -17
  105. package/dist/chat/daemon/active-project.d.ts.map +0 -1
  106. package/dist/chat/daemon/active-project.js +0 -23
  107. package/dist/chat/daemon/active-project.js.map +0 -1
  108. package/dist/chat/daemon/autospawn.d.ts +0 -40
  109. package/dist/chat/daemon/autospawn.d.ts.map +0 -1
  110. package/dist/chat/daemon/autospawn.js +0 -129
  111. package/dist/chat/daemon/autospawn.js.map +0 -1
  112. package/dist/chat/daemon/autospawn.test.js +0 -112
  113. package/dist/chat/daemon/cli.d.ts +0 -18
  114. package/dist/chat/daemon/cli.d.ts.map +0 -1
  115. package/dist/chat/daemon/cli.js +0 -71
  116. package/dist/chat/daemon/cli.js.map +0 -1
  117. package/dist/chat/daemon/collisions.js +0 -384
  118. package/dist/chat/daemon/health-check.d.ts +0 -69
  119. package/dist/chat/daemon/health-check.d.ts.map +0 -1
  120. package/dist/chat/daemon/health-check.js +0 -112
  121. package/dist/chat/daemon/health-check.js.map +0 -1
  122. package/dist/chat/daemon/inbox-read.d.ts +0 -35
  123. package/dist/chat/daemon/inbox-read.d.ts.map +0 -1
  124. package/dist/chat/daemon/inbox-read.js +0 -75
  125. package/dist/chat/daemon/inbox-read.js.map +0 -1
  126. package/dist/chat/daemon/inbox-read.test.js +0 -97
  127. package/dist/chat/daemon/inbox.d.ts +0 -63
  128. package/dist/chat/daemon/inbox.d.ts.map +0 -1
  129. package/dist/chat/daemon/inbox.js +0 -56
  130. package/dist/chat/daemon/inbox.js.map +0 -1
  131. package/dist/chat/daemon/inbox.test.js +0 -110
  132. package/dist/chat/daemon/lifecycle.d.ts +0 -71
  133. package/dist/chat/daemon/lifecycle.d.ts.map +0 -1
  134. package/dist/chat/daemon/lifecycle.js +0 -221
  135. package/dist/chat/daemon/lifecycle.js.map +0 -1
  136. package/dist/chat/daemon/lifecycle.test.js +0 -163
  137. package/dist/chat/daemon/protocol.d.ts +0 -107
  138. package/dist/chat/daemon/protocol.d.ts.map +0 -1
  139. package/dist/chat/daemon/protocol.js +0 -54
  140. package/dist/chat/daemon/protocol.js.map +0 -1
  141. package/dist/chat/daemon/routing.d.ts +0 -140
  142. package/dist/chat/daemon/routing.d.ts.map +0 -1
  143. package/dist/chat/daemon/routing.js +0 -198
  144. package/dist/chat/daemon/routing.js.map +0 -1
  145. package/dist/chat/daemon/routing.test.js +0 -259
  146. package/dist/chat/daemon/rpc-client.d.ts +0 -45
  147. package/dist/chat/daemon/rpc-client.d.ts.map +0 -1
  148. package/dist/chat/daemon/rpc-client.js +0 -133
  149. package/dist/chat/daemon/rpc-client.js.map +0 -1
  150. package/dist/chat/daemon/rpc-server.d.ts +0 -39
  151. package/dist/chat/daemon/rpc-server.d.ts.map +0 -1
  152. package/dist/chat/daemon/rpc-server.js +0 -385
  153. package/dist/chat/daemon/rpc-server.js.map +0 -1
  154. package/dist/chat/daemon/rpc.test.js +0 -177
  155. package/dist/chat/daemon/subscribers.js +0 -257
  156. package/dist/chat/daemon/worker.d.ts +0 -27
  157. package/dist/chat/daemon/worker.d.ts.map +0 -1
  158. package/dist/chat/daemon/worker.js +0 -313
  159. package/dist/chat/daemon/worker.js.map +0 -1
  160. package/dist/chat/daemon/workspace-topic.js +0 -324
  161. package/dist/chat/env-token.d.ts +0 -60
  162. package/dist/chat/env-token.d.ts.map +0 -1
  163. package/dist/chat/env-token.js +0 -137
  164. package/dist/chat/env-token.js.map +0 -1
  165. package/dist/chat/env-token.test.js +0 -160
  166. package/dist/chat/factory.d.ts +0 -30
  167. package/dist/chat/factory.d.ts.map +0 -1
  168. package/dist/chat/factory.js +0 -50
  169. package/dist/chat/factory.js.map +0 -1
  170. package/dist/chat/factory.test.js +0 -55
  171. package/dist/chat/gateway.d.ts +0 -176
  172. package/dist/chat/gateway.d.ts.map +0 -1
  173. package/dist/chat/gateway.js +0 -146
  174. package/dist/chat/gateway.js.map +0 -1
  175. package/dist/chat/gateway.test.js +0 -192
  176. package/dist/claude-md.d.ts +0 -39
  177. package/dist/claude-md.d.ts.map +0 -1
  178. package/dist/claude-md.js +0 -113
  179. package/dist/claude-md.js.map +0 -1
  180. package/dist/claude-md.test.js +0 -91
  181. package/dist/codex/activate.d.ts +0 -66
  182. package/dist/codex/activate.d.ts.map +0 -1
  183. package/dist/codex/activate.js +0 -329
  184. package/dist/codex/activate.js.map +0 -1
  185. package/dist/codex/activate.test.js +0 -229
  186. package/dist/codex/bundled-default/bundled-default.test.js +0 -161
  187. package/dist/codex/cli-publish.test.js +0 -133
  188. package/dist/codex/cli.d.ts +0 -35
  189. package/dist/codex/cli.d.ts.map +0 -1
  190. package/dist/codex/cli.js +0 -554
  191. package/dist/codex/cli.js.map +0 -1
  192. package/dist/codex/cli.test.js +0 -277
  193. package/dist/codex/import-skill-md.d.ts +0 -53
  194. package/dist/codex/import-skill-md.d.ts.map +0 -1
  195. package/dist/codex/import-skill-md.js +0 -236
  196. package/dist/codex/import-skill-md.js.map +0 -1
  197. package/dist/codex/import-skill-md.test.js +0 -225
  198. package/dist/codex/loader.d.ts +0 -27
  199. package/dist/codex/loader.d.ts.map +0 -1
  200. package/dist/codex/loader.js +0 -86
  201. package/dist/codex/loader.js.map +0 -1
  202. package/dist/codex/loader.test.js +0 -75
  203. package/dist/codex/parse.d.ts +0 -28
  204. package/dist/codex/parse.d.ts.map +0 -1
  205. package/dist/codex/parse.js +0 -309
  206. package/dist/codex/parse.js.map +0 -1
  207. package/dist/codex/parse.test.js +0 -241
  208. package/dist/codex/store.d.ts +0 -87
  209. package/dist/codex/store.d.ts.map +0 -1
  210. package/dist/codex/store.js +0 -205
  211. package/dist/codex/store.js.map +0 -1
  212. package/dist/codex/store.test.js +0 -242
  213. package/dist/codex/types.d.ts +0 -398
  214. package/dist/codex/types.d.ts.map +0 -1
  215. package/dist/codex/types.js +0 -21
  216. package/dist/codex/types.js.map +0 -1
  217. package/dist/config.d.ts +0 -53
  218. package/dist/config.d.ts.map +0 -1
  219. package/dist/config.js +0 -202
  220. package/dist/config.js.map +0 -1
  221. package/dist/config.test.js +0 -117
  222. package/dist/engine/cli.d.ts +0 -14
  223. package/dist/engine/cli.d.ts.map +0 -1
  224. package/dist/engine/cli.js +0 -171
  225. package/dist/engine/cli.js.map +0 -1
  226. package/dist/engine/client.d.ts +0 -219
  227. package/dist/engine/client.d.ts.map +0 -1
  228. package/dist/engine/client.js +0 -312
  229. package/dist/engine/client.js.map +0 -1
  230. package/dist/engine/config.d.ts +0 -62
  231. package/dist/engine/config.d.ts.map +0 -1
  232. package/dist/engine/config.js +0 -223
  233. package/dist/engine/config.js.map +0 -1
  234. package/dist/engine/index.d.ts +0 -17
  235. package/dist/engine/index.d.ts.map +0 -1
  236. package/dist/engine/index.js +0 -16
  237. package/dist/engine/index.js.map +0 -1
  238. package/dist/engine/resolver.d.ts +0 -62
  239. package/dist/engine/resolver.d.ts.map +0 -1
  240. package/dist/engine/resolver.js +0 -103
  241. package/dist/engine/resolver.js.map +0 -1
  242. package/dist/engine/singleton.d.ts +0 -95
  243. package/dist/engine/singleton.d.ts.map +0 -1
  244. package/dist/engine/singleton.js +0 -325
  245. package/dist/engine/singleton.js.map +0 -1
  246. package/dist/engine/types.d.ts +0 -402
  247. package/dist/engine/types.d.ts.map +0 -1
  248. package/dist/engine/types.js +0 -22
  249. package/dist/engine/types.js.map +0 -1
  250. package/dist/engine-binary-resolver.js +0 -110
  251. package/dist/engine-binary-resolver.test.js +0 -61
  252. package/dist/engine-cli.js +0 -60
  253. package/dist/engine-client.js +0 -301
  254. package/dist/engine-client.test.js +0 -118
  255. package/dist/functions/chain_state.d.ts +0 -51
  256. package/dist/functions/chain_state.d.ts.map +0 -1
  257. package/dist/functions/chain_state.js +0 -59
  258. package/dist/functions/chain_state.js.map +0 -1
  259. package/dist/hooks/drift-catalog.d.ts +0 -68
  260. package/dist/hooks/drift-catalog.d.ts.map +0 -1
  261. package/dist/hooks/drift-catalog.js +0 -184
  262. package/dist/hooks/drift-catalog.js.map +0 -1
  263. package/dist/hooks/drift-catalog.test.js +0 -154
  264. package/dist/hooks/drift-patterns.d.ts +0 -110
  265. package/dist/hooks/drift-patterns.d.ts.map +0 -1
  266. package/dist/hooks/drift-patterns.js +0 -289
  267. package/dist/hooks/drift-patterns.js.map +0 -1
  268. package/dist/hooks/drift-patterns.test.js +0 -325
  269. package/dist/hooks/engine-vocab-gate.d.ts +0 -108
  270. package/dist/hooks/engine-vocab-gate.d.ts.map +0 -1
  271. package/dist/hooks/engine-vocab-gate.js +0 -225
  272. package/dist/hooks/engine-vocab-gate.js.map +0 -1
  273. package/dist/hooks/engine-vocab-gate.test.js +0 -170
  274. package/dist/hooks/heartbeat.d.ts +0 -107
  275. package/dist/hooks/heartbeat.d.ts.map +0 -1
  276. package/dist/hooks/heartbeat.js +0 -316
  277. package/dist/hooks/heartbeat.js.map +0 -1
  278. package/dist/hooks/heartbeat.test.js +0 -393
  279. package/dist/hooks/honesty-ledger-session-scope.test.js +0 -100
  280. package/dist/hooks/honesty-ledger.d.ts +0 -123
  281. package/dist/hooks/honesty-ledger.d.ts.map +0 -1
  282. package/dist/hooks/honesty-ledger.js +0 -226
  283. package/dist/hooks/honesty-ledger.js.map +0 -1
  284. package/dist/hooks/honesty-ledger.test.js +0 -466
  285. package/dist/hooks/inline-report-check.d.ts +0 -63
  286. package/dist/hooks/inline-report-check.d.ts.map +0 -1
  287. package/dist/hooks/inline-report-check.js +0 -88
  288. package/dist/hooks/inline-report-check.js.map +0 -1
  289. package/dist/hooks/inline-report-check.test.js +0 -96
  290. package/dist/hooks/pre-tool-use.d.ts +0 -62
  291. package/dist/hooks/pre-tool-use.d.ts.map +0 -1
  292. package/dist/hooks/pre-tool-use.js +0 -342
  293. package/dist/hooks/pre-tool-use.js.map +0 -1
  294. package/dist/hooks/pre-tool-use.test.js +0 -134
  295. package/dist/hooks/session-end.d.ts +0 -15
  296. package/dist/hooks/session-end.d.ts.map +0 -1
  297. package/dist/hooks/session-end.js +0 -60
  298. package/dist/hooks/session-end.js.map +0 -1
  299. package/dist/hooks/session-end.test.js +0 -52
  300. package/dist/hooks/stop.d.ts +0 -35
  301. package/dist/hooks/stop.d.ts.map +0 -1
  302. package/dist/hooks/stop.js +0 -136
  303. package/dist/hooks/stop.js.map +0 -1
  304. package/dist/hooks/transcript-active-task.test.js +0 -342
  305. package/dist/hooks/transcript.d.ts +0 -26
  306. package/dist/hooks/transcript.d.ts.map +0 -1
  307. package/dist/hooks/transcript.js +0 -266
  308. package/dist/hooks/transcript.js.map +0 -1
  309. package/dist/hooks/transcript.test.js +0 -103
  310. package/dist/hooks/user-prompt-submit.d.ts +0 -74
  311. package/dist/hooks/user-prompt-submit.d.ts.map +0 -1
  312. package/dist/hooks/user-prompt-submit.js +0 -256
  313. package/dist/hooks/user-prompt-submit.js.map +0 -1
  314. package/dist/hooks/user-prompt-submit.test.js +0 -118
  315. package/dist/hooks/versioning-gate.d.ts +0 -101
  316. package/dist/hooks/versioning-gate.d.ts.map +0 -1
  317. package/dist/hooks/versioning-gate.js +0 -245
  318. package/dist/hooks/versioning-gate.js.map +0 -1
  319. package/dist/hooks/versioning-gate.test.js +0 -368
  320. package/dist/hooks/workflow-gate.d.ts +0 -64
  321. package/dist/hooks/workflow-gate.d.ts.map +0 -1
  322. package/dist/hooks/workflow-gate.js +0 -152
  323. package/dist/hooks/workflow-gate.js.map +0 -1
  324. package/dist/hooks/workflow-gate.test.js +0 -197
  325. package/dist/hooks-cli.d.ts +0 -25
  326. package/dist/hooks-cli.d.ts.map +0 -1
  327. package/dist/hooks-cli.js +0 -286
  328. package/dist/hooks-cli.js.map +0 -1
  329. package/dist/hooks-cli.test.js +0 -148
  330. package/dist/origin.d.ts +0 -16
  331. package/dist/origin.d.ts.map +0 -1
  332. package/dist/origin.js +0 -92
  333. package/dist/origin.js.map +0 -1
  334. package/dist/packs/seed_lessons_ingest.d.ts +0 -30
  335. package/dist/packs/seed_lessons_ingest.d.ts.map +0 -1
  336. package/dist/packs/seed_lessons_ingest.js +0 -107
  337. package/dist/packs/seed_lessons_ingest.js.map +0 -1
  338. package/dist/project-cli.d.ts +0 -7
  339. package/dist/project-cli.d.ts.map +0 -1
  340. package/dist/project-cli.js +0 -145
  341. package/dist/project-cli.js.map +0 -1
  342. package/dist/project.d.ts +0 -127
  343. package/dist/project.d.ts.map +0 -1
  344. package/dist/project.js +0 -281
  345. package/dist/project.js.map +0 -1
  346. package/dist/project.test.js +0 -287
  347. package/dist/rag/backends/loop_engine.d.ts +0 -61
  348. package/dist/rag/backends/loop_engine.d.ts.map +0 -1
  349. package/dist/rag/backends/loop_engine.js +0 -160
  350. package/dist/rag/backends/loop_engine.js.map +0 -1
  351. package/dist/recall.d.ts +0 -82
  352. package/dist/recall.d.ts.map +0 -1
  353. package/dist/recall.js +0 -81
  354. package/dist/recall.js.map +0 -1
  355. package/dist/runtime/agent_bridge/autospawn.d.ts +0 -131
  356. package/dist/runtime/agent_bridge/autospawn.d.ts.map +0 -1
  357. package/dist/runtime/agent_bridge/autospawn.js +0 -251
  358. package/dist/runtime/agent_bridge/autospawn.js.map +0 -1
  359. package/dist/runtime/chain_state.d.ts +0 -124
  360. package/dist/runtime/chain_state.d.ts.map +0 -1
  361. package/dist/runtime/chain_state.js +0 -189
  362. package/dist/runtime/chain_state.js.map +0 -1
  363. package/dist/runtime/hooks/permission_decision.d.ts +0 -34
  364. package/dist/runtime/hooks/permission_decision.d.ts.map +0 -1
  365. package/dist/runtime/hooks/permission_decision.js +0 -39
  366. package/dist/runtime/hooks/permission_decision.js.map +0 -1
  367. package/dist/runtime/workflow_fsm.d.ts +0 -21
  368. package/dist/runtime/workflow_fsm.d.ts.map +0 -1
  369. package/dist/runtime/workflow_fsm.js +0 -25
  370. package/dist/runtime/workflow_fsm.js.map +0 -1
  371. package/dist/runtime/workflow_map.d.ts +0 -26
  372. package/dist/runtime/workflow_map.d.ts.map +0 -1
  373. package/dist/runtime/workflow_map.js +0 -38
  374. package/dist/runtime/workflow_map.js.map +0 -1
  375. package/dist/scope.d.ts +0 -48
  376. package/dist/scope.d.ts.map +0 -1
  377. package/dist/scope.js +0 -111
  378. package/dist/scope.js.map +0 -1
  379. package/dist/setup/cli/topic_create_step.d.ts +0 -84
  380. package/dist/setup/cli/topic_create_step.d.ts.map +0 -1
  381. package/dist/setup/cli/topic_create_step.js +0 -213
  382. package/dist/setup/cli/topic_create_step.js.map +0 -1
  383. package/dist/system-export.d.ts +0 -65
  384. package/dist/system-export.d.ts.map +0 -1
  385. package/dist/system-export.js +0 -194
  386. package/dist/system-export.js.map +0 -1
  387. package/dist/utterance/classifier.d.ts +0 -53
  388. package/dist/utterance/classifier.d.ts.map +0 -1
  389. package/dist/utterance/classifier.js +0 -184
  390. package/dist/utterance/classifier.js.map +0 -1
  391. package/dist/utterance/classifier.test.js +0 -147
@@ -1,245 +0,0 @@
1
- /**
2
- * Versioning gate — pre-commit check enforcing per-commit patch bumps
3
- * (v0.6.3). Wired into the PreToolUse hook for `git commit` commands.
4
- *
5
- * Problem this fixes: I keep batching multiple fixes into one commit
6
- * and bumping the minor (or no bump at all) instead of one patch per
7
- * fix. The discipline rule was memorized (`mem-d2cc0e78`) but rules
8
- * I can ignore aren't structural protection. This gate makes the
9
- * discipline mechanical — if your commit touches source code AND
10
- * doesn't include a manifest version bump in the same commit, it
11
- * gets rejected before `git commit` runs.
12
- *
13
- * Detection:
14
- * 1. `git diff --cached --name-only` → list of staged files
15
- * 2. If no `src/**` files staged → allow (docs/CI/config commits
16
- * don't need version bumps)
17
- * 3. If `src/**` files staged → require a manifest (Cargo.toml or
18
- * package.json) to also be staged with a `version` line diff
19
- * 4. Otherwise → block with actionable message
20
- *
21
- * Fail-open invariant: any error running git or parsing output →
22
- * allow with a stderr warning (per the honesty-ledger + workflow-gate
23
- * precedent — never block on opensquid's own bug).
24
- *
25
- * Emergency override: `OPENSQUID_SKIP_VERSION_GATE=1` bypasses with a
26
- * loud stderr warning. For genuine emergencies (revert commits,
27
- * generated-code-only diffs, etc.) where the discipline doesn't
28
- * apply.
29
- */
30
- import { exec as execCb } from "node:child_process";
31
- import { promisify } from "node:util";
32
- const exec = promisify(execCb);
33
- export async function evaluateVersioningGate(input = {}) {
34
- if (checkOverrideEnv()) {
35
- return {
36
- block: false,
37
- stderr: "🦑 [opensquid versioning-gate] BYPASSED via OPENSQUID_SKIP_VERSION_GATE=1\n",
38
- };
39
- }
40
- const cwd = input.cwd ?? process.cwd();
41
- // List staged files. `--no-renames` keeps the output simple (renames
42
- // appear as both old + new path rather than `R100\told\tnew`).
43
- let stagedFiles;
44
- try {
45
- const { stdout } = await exec("git diff --cached --name-only --no-renames", {
46
- cwd,
47
- maxBuffer: 1024 * 1024,
48
- });
49
- stagedFiles = stdout
50
- .split("\n")
51
- .map((l) => l.trim())
52
- .filter(Boolean);
53
- }
54
- catch (err) {
55
- return {
56
- block: false,
57
- stderr: `[opensquid versioning-gate] git diff failed (proceeding): ${err instanceof Error ? err.message : err}\n`,
58
- };
59
- }
60
- if (stagedFiles.length === 0) {
61
- // Nothing staged — git commit will fail on its own with no need
62
- // for this gate to intervene.
63
- return { block: false, stderr: "" };
64
- }
65
- const sourceFiles = stagedFiles.filter(isSourceFile);
66
- if (sourceFiles.length === 0) {
67
- // Docs / CI / config / fixtures / etc. — no source change, no bump needed.
68
- return { block: false, stderr: "" };
69
- }
70
- const manifests = stagedFiles.filter(isManifestFile);
71
- if (manifests.length === 0) {
72
- return {
73
- block: true,
74
- stderr: buildBlockMessage(sourceFiles, []),
75
- };
76
- }
77
- // At least one manifest is staged — check that at least one has a
78
- // version-line diff (just touching the manifest without bumping
79
- // version doesn't count).
80
- let bumpedManifest = null;
81
- for (const m of manifests) {
82
- const jump = await readManifestVersionBump(cwd, m);
83
- if (jump) {
84
- bumpedManifest = { path: m, jump };
85
- break;
86
- }
87
- }
88
- if (!bumpedManifest) {
89
- return {
90
- block: true,
91
- stderr: buildBlockMessage(sourceFiles, manifests),
92
- };
93
- }
94
- // 0.7.23 / D5 — catch-up bump detection. The PATCH-ONLY rule
95
- // ([[feedback_pre1_versioning]] v4) says every src commit = exactly
96
- // one patch bump. A jump like 0.7.10 → 0.7.14 in a single commit
97
- // means previous src commits skipped their bumps. Don't BLOCK
98
- // (legitimate explicit catch-ups exist), but surface a loud warning
99
- // so the skip is visible.
100
- const { jump } = bumpedManifest;
101
- if (jump && isMultiPatchJump(jump)) {
102
- return {
103
- block: false,
104
- stderr: `🦑 [opensquid versioning-gate] WARN: catch-up bump detected (${jump.from} → ${jump.to})\n` +
105
- ` PATCH-ONLY rule says one patch per commit. A multi-patch jump in one\n` +
106
- ` commit usually means earlier src commits shipped without bumps. Drift D5.\n`,
107
- };
108
- }
109
- return { block: false, stderr: "" };
110
- }
111
- /**
112
- * Is this a source file that should trigger version-bump enforcement?
113
- * Generous definition: anything under `src/` for any language we support.
114
- */
115
- export function isSourceFile(p) {
116
- // src/ at any depth (top-level or nested workspace member)
117
- return /(^|\/)src\//.test(p);
118
- }
119
- /** Is this the repo's version manifest? */
120
- export function isManifestFile(p) {
121
- const base = p.split("/").pop() ?? "";
122
- return base === "Cargo.toml" || base === "package.json";
123
- }
124
- /**
125
- * Look at the staged diff of a manifest and return the version jump
126
- * (from → to). Returns null when the diff doesn't touch a `version`
127
- * line at all.
128
- *
129
- * Exported for direct testing.
130
- */
131
- export async function readManifestVersionBump(cwd, manifestPath) {
132
- let diff;
133
- try {
134
- const { stdout } = await exec(`git diff --cached --no-color -U0 -- ${quoteShell(manifestPath)}`, { cwd, maxBuffer: 1024 * 1024 });
135
- diff = stdout;
136
- }
137
- catch {
138
- return null;
139
- }
140
- return parseVersionJumpFromDiff(diff);
141
- }
142
- /**
143
- * Parse `+`/`-` lines from a manifest diff and extract the version
144
- * jump. Cargo: `version = "..."`. package.json: `"version": "..."`.
145
- *
146
- * Anchor discipline:
147
- * - Cargo (TOML, line-oriented) → anchor `^version` so we don't
148
- * match a dep with `version = "..."` in `[dependencies.foo]`.
149
- * - package.json (JSON, can be MINIFIED single-line) → do NOT
150
- * anchor; `"version"` can appear mid-line in minified JSON.
151
- *
152
- * Exported for direct testing.
153
- */
154
- export function parseVersionJumpFromDiff(diff) {
155
- let oldVersion = null;
156
- let newVersion = null;
157
- for (const line of diff.split("\n")) {
158
- if (line.startsWith("+++") || line.startsWith("---"))
159
- continue;
160
- const sign = line[0];
161
- if (sign !== "+" && sign !== "-")
162
- continue;
163
- const body = line.slice(1).trim();
164
- let v = null;
165
- const cargoMatch = body.match(/^version\s*=\s*"([^"]+)"/);
166
- if (cargoMatch)
167
- v = cargoMatch[1];
168
- if (v === null) {
169
- const npmMatch = body.match(/"version"\s*:\s*"([^"]+)"/);
170
- if (npmMatch)
171
- v = npmMatch[1];
172
- }
173
- if (v === null)
174
- continue;
175
- if (sign === "+")
176
- newVersion = v;
177
- else
178
- oldVersion = v;
179
- }
180
- if (!newVersion)
181
- return null;
182
- // New-version only (e.g. brand-new manifest with no prior `version`
183
- // line) is still a valid "version bump" — treat oldVersion as empty.
184
- return { from: oldVersion ?? "", to: newVersion };
185
- }
186
- /**
187
- * Detect a multi-patch jump: same major.minor, but patch advances by
188
- * more than 1 (catch-up bump).
189
- *
190
- * Returns false for:
191
- * - First-time bumps (from === "")
192
- * - Same-patch (no actual jump, shouldn't happen with proper diff)
193
- * - Minor/major bumps (those are user-authorized; PATCH-ONLY rule
194
- * forbids the agent from naming them but doesn't make them "drift")
195
- * - Non-SemVer version strings (best-effort parse)
196
- *
197
- * Exported for direct testing.
198
- */
199
- export function isMultiPatchJump(jump) {
200
- const oldParts = parseSemver(jump.from);
201
- const newParts = parseSemver(jump.to);
202
- if (!oldParts || !newParts)
203
- return false;
204
- // Only flag same-major.minor with patch jump > 1.
205
- if (oldParts.major !== newParts.major)
206
- return false;
207
- if (oldParts.minor !== newParts.minor)
208
- return false;
209
- return newParts.patch > oldParts.patch + 1;
210
- }
211
- function parseSemver(v) {
212
- const m = v.match(/^(\d+)\.(\d+)\.(\d+)/);
213
- if (!m)
214
- return null;
215
- return { major: Number(m[1]), minor: Number(m[2]), patch: Number(m[3]) };
216
- }
217
- function quoteShell(s) {
218
- // Defensive single-quote shell escape. Manifest paths are usually
219
- // boring but we don't trust them blindly.
220
- return `'${s.replace(/'/g, "'\\''")}'`;
221
- }
222
- function buildBlockMessage(sourceFiles, manifests) {
223
- const srcSample = sourceFiles.slice(0, 5).join(", ") + (sourceFiles.length > 5 ? ", ..." : "");
224
- const lines = [
225
- `🦑 [opensquid versioning-gate] commit blocked — source changes without a version bump`,
226
- ` source files staged (${sourceFiles.length}): ${srcSample}`,
227
- ];
228
- if (manifests.length === 0) {
229
- lines.push(` No Cargo.toml or package.json staged.`, ` Bump the patch version (per mem-d2cc0e78 — fix per commit, not batched), \`git add\` the manifest, then re-commit.`);
230
- }
231
- else {
232
- lines.push(` Manifest(s) staged but no version-line diff: ${manifests.join(", ")}`, ` Bump the version field (Cargo.toml: \`version = "x.y.z"\`, package.json: \`"version": "x.y.z"\`), re-stage, then re-commit.`);
233
- }
234
- lines.push(` Override (genuine emergency): set OPENSQUID_SKIP_VERSION_GATE=1 for this command.`);
235
- return lines.join("\n") + "\n";
236
- }
237
- /**
238
- * Emergency-override env var. Loud stderr warning on bypass so it
239
- * always shows up in scrollback / CI logs. Exported for the test
240
- * suite.
241
- */
242
- export function checkOverrideEnv() {
243
- return process.env.OPENSQUID_SKIP_VERSION_GATE === "1";
244
- }
245
- //# sourceMappingURL=versioning-gate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"versioning-gate.js","sourceRoot":"","sources":["../../src.legacy/hooks/versioning-gate.ts"],"names":[],"mappings":"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"}
@@ -1,368 +0,0 @@
1
- /**
2
- * Versioning-gate tests — exercise against real git repos in tmpdirs.
3
- * The gate's logic depends on actual `git diff --cached` output shape,
4
- * so synthesized state wouldn't catch the same class of bug that
5
- * v0.6.1 transcript-walker missed against real Claude Code shapes
6
- * (per the v0.6.2 lesson). Each test inits a fresh tmp git repo,
7
- * sets up the staged state we want, runs the gate, asserts.
8
- */
9
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
10
- import { execSync } from "node:child_process";
11
- import * as crypto from "node:crypto";
12
- import { promises as fs } from "node:fs";
13
- import * as os from "node:os";
14
- import * as path from "node:path";
15
- import { checkOverrideEnv, evaluateVersioningGate, isManifestFile, isMultiPatchJump, isSourceFile, parseVersionJumpFromDiff, } from "./versioning-gate.js";
16
- // ---------------------------------------------------------------------
17
- // Helpers
18
- // ---------------------------------------------------------------------
19
- let repoDir;
20
- beforeEach(async () => {
21
- repoDir = path.join(os.tmpdir(), `opensquid-ver-${crypto.randomUUID()}`);
22
- await fs.mkdir(repoDir, { recursive: true });
23
- // Minimal git init that doesn't depend on the user's global config.
24
- execSync("git init -q", { cwd: repoDir });
25
- execSync("git config user.email test@example.com", { cwd: repoDir });
26
- execSync("git config user.name 'Test'", { cwd: repoDir });
27
- });
28
- afterEach(async () => {
29
- await fs.rm(repoDir, { recursive: true, force: true });
30
- delete process.env.OPENSQUID_SKIP_VERSION_GATE;
31
- });
32
- async function writeFile(rel, content) {
33
- const full = path.join(repoDir, rel);
34
- await fs.mkdir(path.dirname(full), { recursive: true });
35
- await fs.writeFile(full, content, "utf8");
36
- }
37
- function stage(rel) {
38
- execSync(`git add ${rel}`, { cwd: repoDir });
39
- }
40
- function commit(message) {
41
- execSync(`git commit -q -m '${message}'`, { cwd: repoDir });
42
- }
43
- /** Initial commit so subsequent `git diff --cached` against HEAD works. */
44
- async function seedInitial() {
45
- await writeFile("README.md", "# seed\n");
46
- stage("README.md");
47
- commit("initial");
48
- }
49
- // ---------------------------------------------------------------------
50
- // Pure helper tests (no git involvement)
51
- // ---------------------------------------------------------------------
52
- describe("isSourceFile", () => {
53
- it("matches src/ at repo root", () => {
54
- expect(isSourceFile("src/index.ts")).toBe(true);
55
- expect(isSourceFile("src/hooks/foo.ts")).toBe(true);
56
- });
57
- it("matches nested src/ in workspace member", () => {
58
- expect(isSourceFile("crates/engine/src/lib.rs")).toBe(true);
59
- expect(isSourceFile("packages/x/src/foo.js")).toBe(true);
60
- });
61
- it("does not match top-level files outside src/", () => {
62
- expect(isSourceFile("README.md")).toBe(false);
63
- expect(isSourceFile("Cargo.toml")).toBe(false);
64
- expect(isSourceFile("package.json")).toBe(false);
65
- expect(isSourceFile("CHANGELOG.md")).toBe(false);
66
- expect(isSourceFile(".github/workflows/ci.yml")).toBe(false);
67
- expect(isSourceFile("tests/foo.test.ts")).toBe(false);
68
- });
69
- it("does not match 'srcfoo/' (false-prefix)", () => {
70
- expect(isSourceFile("srcfoo/bar.ts")).toBe(false);
71
- });
72
- });
73
- describe("isManifestFile", () => {
74
- it("matches root-level manifests", () => {
75
- expect(isManifestFile("Cargo.toml")).toBe(true);
76
- expect(isManifestFile("package.json")).toBe(true);
77
- });
78
- it("matches nested manifests (workspace members)", () => {
79
- expect(isManifestFile("crates/engine/Cargo.toml")).toBe(true);
80
- expect(isManifestFile("packages/x/package.json")).toBe(true);
81
- });
82
- it("does not match other tomls / jsons", () => {
83
- expect(isManifestFile("tsconfig.json")).toBe(false);
84
- expect(isManifestFile("rustfmt.toml")).toBe(false);
85
- expect(isManifestFile("clippy.toml")).toBe(false);
86
- });
87
- });
88
- // ---------------------------------------------------------------------
89
- // Allow paths — gate should NOT block
90
- // ---------------------------------------------------------------------
91
- describe("evaluateVersioningGate — allow paths", () => {
92
- it("allows when nothing is staged", async () => {
93
- await seedInitial();
94
- const r = await evaluateVersioningGate({ cwd: repoDir });
95
- expect(r.block).toBe(false);
96
- expect(r.stderr).toBe("");
97
- });
98
- it("allows docs-only commit (no src/ staged)", async () => {
99
- await seedInitial();
100
- await writeFile("README.md", "# updated\n");
101
- await writeFile("CHANGELOG.md", "## changes\n");
102
- stage("README.md");
103
- stage("CHANGELOG.md");
104
- const r = await evaluateVersioningGate({ cwd: repoDir });
105
- expect(r.block).toBe(false);
106
- });
107
- it("allows CI-only commit", async () => {
108
- await seedInitial();
109
- await writeFile(".github/workflows/ci.yml", "name: CI\n");
110
- stage(".github/workflows/ci.yml");
111
- const r = await evaluateVersioningGate({ cwd: repoDir });
112
- expect(r.block).toBe(false);
113
- });
114
- it("allows src + Cargo.toml version bump in same commit", async () => {
115
- await seedInitial();
116
- await writeFile("Cargo.toml", 'version = "0.1.0"\n');
117
- await writeFile("src/lib.rs", "// initial\n");
118
- stage("Cargo.toml");
119
- stage("src/lib.rs");
120
- commit("initial src + manifest");
121
- // Now bump:
122
- await writeFile("Cargo.toml", 'version = "0.1.1"\n');
123
- await writeFile("src/lib.rs", "// patched\n");
124
- stage("Cargo.toml");
125
- stage("src/lib.rs");
126
- const r = await evaluateVersioningGate({ cwd: repoDir });
127
- expect(r.block).toBe(false);
128
- });
129
- // Audit HIGH fix (v0.6.3): minified package.json was originally a
130
- // false-positive block because the regex anchored `^"version"` and
131
- // minified JSON has `"version"` mid-line. Drop the anchor.
132
- it("allows src + MINIFIED package.json version bump (audit HIGH regression)", async () => {
133
- await seedInitial();
134
- await writeFile("package.json", '{"name":"x","version":"0.1.0"}\n');
135
- await writeFile("src/index.ts", "// initial\n");
136
- stage("package.json");
137
- stage("src/index.ts");
138
- commit("initial");
139
- await writeFile("package.json", '{"name":"x","version":"0.1.1"}\n');
140
- await writeFile("src/index.ts", "// patched\n");
141
- stage("package.json");
142
- stage("src/index.ts");
143
- const r = await evaluateVersioningGate({ cwd: repoDir });
144
- expect(r.block).toBe(false);
145
- });
146
- it("allows src + package.json version bump in same commit (realistic multi-line JSON)", async () => {
147
- await seedInitial();
148
- // Real package.json is pretty-printed multi-line so the diff
149
- // surfaces a `"version": "..."` change on its own line.
150
- const pkgV1 = JSON.stringify({ name: "x", version: "0.1.0" }, null, 2) + "\n";
151
- const pkgV2 = JSON.stringify({ name: "x", version: "0.1.1" }, null, 2) + "\n";
152
- await writeFile("package.json", pkgV1);
153
- await writeFile("src/index.ts", "// initial\n");
154
- stage("package.json");
155
- stage("src/index.ts");
156
- commit("initial");
157
- await writeFile("package.json", pkgV2);
158
- await writeFile("src/index.ts", "// patched\n");
159
- stage("package.json");
160
- stage("src/index.ts");
161
- const r = await evaluateVersioningGate({ cwd: repoDir });
162
- expect(r.block).toBe(false);
163
- });
164
- });
165
- // ---------------------------------------------------------------------
166
- // Block paths — gate SHOULD block
167
- // ---------------------------------------------------------------------
168
- describe("evaluateVersioningGate — block paths", () => {
169
- it("blocks src/ change with no manifest staged", async () => {
170
- await seedInitial();
171
- await writeFile("Cargo.toml", 'version = "0.1.0"\n');
172
- await writeFile("src/lib.rs", "// initial\n");
173
- stage("Cargo.toml");
174
- stage("src/lib.rs");
175
- commit("initial src + manifest");
176
- // Now ONLY src changes, no manifest bump:
177
- await writeFile("src/lib.rs", "// edited\n");
178
- stage("src/lib.rs");
179
- const r = await evaluateVersioningGate({ cwd: repoDir });
180
- expect(r.block).toBe(true);
181
- expect(r.stderr).toContain("commit blocked");
182
- expect(r.stderr).toContain("src/lib.rs");
183
- expect(r.stderr).toContain("No Cargo.toml or package.json staged");
184
- });
185
- it("blocks src/ change with manifest staged but no version-line diff", async () => {
186
- await seedInitial();
187
- await writeFile("Cargo.toml", 'version = "0.1.0"\n[dependencies]\nfoo = "1"\n');
188
- await writeFile("src/lib.rs", "// initial\n");
189
- stage("Cargo.toml");
190
- stage("src/lib.rs");
191
- commit("initial");
192
- // Touch manifest (add dep) but DON'T bump version, also touch src:
193
- await writeFile("Cargo.toml", 'version = "0.1.0"\n[dependencies]\nfoo = "1"\nbar = "2"\n');
194
- await writeFile("src/lib.rs", "// edited\n");
195
- stage("Cargo.toml");
196
- stage("src/lib.rs");
197
- const r = await evaluateVersioningGate({ cwd: repoDir });
198
- expect(r.block).toBe(true);
199
- expect(r.stderr).toContain("no version-line diff");
200
- expect(r.stderr).toContain("Cargo.toml");
201
- });
202
- });
203
- // ---------------------------------------------------------------------
204
- // Multi-manifest / workspace
205
- // ---------------------------------------------------------------------
206
- describe("evaluateVersioningGate — workspace / multi-manifest", () => {
207
- it("allows when ANY staged manifest has a version bump", async () => {
208
- await seedInitial();
209
- await writeFile("crates/a/Cargo.toml", 'version = "0.1.0"\n');
210
- await writeFile("crates/b/Cargo.toml", 'version = "0.1.0"\n');
211
- await writeFile("crates/a/src/lib.rs", "// a\n");
212
- await writeFile("crates/b/src/lib.rs", "// b\n");
213
- stage("crates/a/Cargo.toml");
214
- stage("crates/b/Cargo.toml");
215
- stage("crates/a/src/lib.rs");
216
- stage("crates/b/src/lib.rs");
217
- commit("initial");
218
- // Bump ONLY crate a; edit src in BOTH:
219
- await writeFile("crates/a/Cargo.toml", 'version = "0.1.1"\n');
220
- await writeFile("crates/a/src/lib.rs", "// a patched\n");
221
- await writeFile("crates/b/src/lib.rs", "// b edited\n");
222
- stage("crates/a/Cargo.toml");
223
- stage("crates/a/src/lib.rs");
224
- stage("crates/b/src/lib.rs");
225
- const r = await evaluateVersioningGate({ cwd: repoDir });
226
- // Liberal policy: ANY manifest bump is enough. Workspace-wide
227
- // discipline is a v0.6.4+ refinement if needed.
228
- expect(r.block).toBe(false);
229
- });
230
- });
231
- // ---------------------------------------------------------------------
232
- // Emergency override
233
- // ---------------------------------------------------------------------
234
- describe("evaluateVersioningGate — emergency override", () => {
235
- it("ALLOWS with bypass warning when OPENSQUID_SKIP_VERSION_GATE=1", async () => {
236
- process.env.OPENSQUID_SKIP_VERSION_GATE = "1";
237
- expect(checkOverrideEnv()).toBe(true);
238
- await seedInitial();
239
- await writeFile("Cargo.toml", 'version = "0.1.0"\n');
240
- await writeFile("src/lib.rs", "// initial\n");
241
- stage("Cargo.toml");
242
- stage("src/lib.rs");
243
- commit("initial");
244
- await writeFile("src/lib.rs", "// edited\n");
245
- stage("src/lib.rs");
246
- const r = await evaluateVersioningGate({ cwd: repoDir });
247
- expect(r.block).toBe(false);
248
- expect(r.stderr).toContain("BYPASSED");
249
- });
250
- it("respects the env var only when EXACTLY '1'", async () => {
251
- process.env.OPENSQUID_SKIP_VERSION_GATE = "true";
252
- expect(checkOverrideEnv()).toBe(false);
253
- process.env.OPENSQUID_SKIP_VERSION_GATE = "1";
254
- expect(checkOverrideEnv()).toBe(true);
255
- });
256
- });
257
- // ---------------------------------------------------------------------
258
- // 0.7.23 / D5 — multi-patch catch-up jump detection
259
- // ---------------------------------------------------------------------
260
- describe("parseVersionJumpFromDiff", () => {
261
- it("parses a Cargo.toml patch bump", () => {
262
- const diff = `--- a/Cargo.toml
263
- +++ b/Cargo.toml
264
- @@ -1 +1 @@
265
- -version = "0.7.10"
266
- +version = "0.7.11"
267
- `;
268
- expect(parseVersionJumpFromDiff(diff)).toEqual({ from: "0.7.10", to: "0.7.11" });
269
- });
270
- it("parses a package.json patch bump", () => {
271
- const diff = `--- a/package.json
272
- +++ b/package.json
273
- @@ -2 +2 @@
274
- - "version": "0.7.10",
275
- + "version": "0.7.11",
276
- `;
277
- expect(parseVersionJumpFromDiff(diff)).toEqual({ from: "0.7.10", to: "0.7.11" });
278
- });
279
- it("parses a multi-patch jump (D5 incident shape)", () => {
280
- const diff = `--- a/package.json
281
- +++ b/package.json
282
- - "version": "0.7.10",
283
- + "version": "0.7.14",
284
- `;
285
- expect(parseVersionJumpFromDiff(diff)).toEqual({ from: "0.7.10", to: "0.7.14" });
286
- });
287
- it("returns null when no version line is touched", () => {
288
- const diff = `--- a/package.json
289
- +++ b/package.json
290
- + "description": "updated text",
291
- - "description": "old text",
292
- `;
293
- expect(parseVersionJumpFromDiff(diff)).toBeNull();
294
- });
295
- });
296
- describe("isMultiPatchJump", () => {
297
- it("flags 0.7.10 → 0.7.14 (D5 catch-up)", () => {
298
- expect(isMultiPatchJump({ from: "0.7.10", to: "0.7.14" })).toBe(true);
299
- });
300
- it("flags 0.7.10 → 0.7.12 (2-step jump)", () => {
301
- expect(isMultiPatchJump({ from: "0.7.10", to: "0.7.12" })).toBe(true);
302
- });
303
- it("does NOT flag a normal 0.7.10 → 0.7.11 patch bump", () => {
304
- expect(isMultiPatchJump({ from: "0.7.10", to: "0.7.11" })).toBe(false);
305
- });
306
- it("does NOT flag a minor bump (0.7.x → 0.8.0)", () => {
307
- // Minor/major bumps are user-authorized; not the agent's drift to warn about.
308
- expect(isMultiPatchJump({ from: "0.7.20", to: "0.8.0" })).toBe(false);
309
- });
310
- it("does NOT flag a first-time version (from empty)", () => {
311
- expect(isMultiPatchJump({ from: "", to: "0.1.0" })).toBe(false);
312
- });
313
- it("does NOT flag non-SemVer strings", () => {
314
- expect(isMultiPatchJump({ from: "wip", to: "wip-2" })).toBe(false);
315
- });
316
- });
317
- describe("evaluateVersioningGate — multi-patch warning end-to-end (D5)", () => {
318
- it("ALLOWS but WARNS when commit bumps version by >1 patch", async () => {
319
- await seedInitial();
320
- await writeFile("Cargo.toml", 'version = "0.7.10"\n');
321
- await writeFile("src/lib.rs", "// initial\n");
322
- stage("Cargo.toml");
323
- stage("src/lib.rs");
324
- commit("initial");
325
- // Now jump 0.7.10 → 0.7.14 in one commit alongside a src change
326
- await writeFile("Cargo.toml", 'version = "0.7.14"\n');
327
- await writeFile("src/lib.rs", "// changed\n");
328
- stage("Cargo.toml");
329
- stage("src/lib.rs");
330
- const r = await evaluateVersioningGate({ cwd: repoDir });
331
- expect(r.block).toBe(false);
332
- expect(r.stderr).toContain("catch-up bump detected");
333
- expect(r.stderr).toContain("0.7.10 → 0.7.14");
334
- expect(r.stderr).toContain("Drift D5");
335
- });
336
- it("does NOT warn on a clean +1 patch bump", async () => {
337
- await seedInitial();
338
- await writeFile("Cargo.toml", 'version = "0.7.10"\n');
339
- await writeFile("src/lib.rs", "// initial\n");
340
- stage("Cargo.toml");
341
- stage("src/lib.rs");
342
- commit("initial");
343
- await writeFile("Cargo.toml", 'version = "0.7.11"\n');
344
- await writeFile("src/lib.rs", "// changed\n");
345
- stage("Cargo.toml");
346
- stage("src/lib.rs");
347
- const r = await evaluateVersioningGate({ cwd: repoDir });
348
- expect(r.block).toBe(false);
349
- expect(r.stderr).toBe("");
350
- });
351
- });
352
- // ---------------------------------------------------------------------
353
- // Fail-open invariant
354
- // ---------------------------------------------------------------------
355
- describe("evaluateVersioningGate — fail-open invariant", () => {
356
- it("ALLOWS with stderr warning when git is not available (non-repo cwd)", async () => {
357
- const notARepo = path.join(os.tmpdir(), `not-a-repo-${crypto.randomUUID()}`);
358
- await fs.mkdir(notARepo, { recursive: true });
359
- try {
360
- const r = await evaluateVersioningGate({ cwd: notARepo });
361
- expect(r.block).toBe(false);
362
- expect(r.stderr).toContain("git diff failed");
363
- }
364
- finally {
365
- await fs.rm(notARepo, { recursive: true, force: true });
366
- }
367
- });
368
- });