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
package/dist/hooks-cli.js DELETED
@@ -1,286 +0,0 @@
1
- /**
2
- * `opensquid hooks <subcommand>` — Claude Code settings.json hooks
3
- * installer.
4
- *
5
- * Subcommands:
6
- * install — append the opensquid PreToolUse hook to
7
- * ~/.claude/settings.json (idempotent — re-running
8
- * refreshes the hook command pointer without disturbing
9
- * other hooks)
10
- * uninstall — remove the opensquid PreToolUse hook
11
- * doctor — report what's currently installed
12
- *
13
- * The PreToolUse hook runs the local opensquid build's `hook
14
- * pre-tool-use` handler (see src/hooks/pre-tool-use.ts), which
15
- * intercepts known-anti-pattern actions (amend, push, substrate-impure
16
- * engine commits) before Claude Code executes them.
17
- */
18
- import { promises as fs } from "node:fs";
19
- import * as os from "node:os";
20
- import * as path from "node:path";
21
- import * as url from "node:url";
22
- export class HooksCliError extends Error {
23
- hint;
24
- constructor(message, hint) {
25
- super(message);
26
- this.hint = hint;
27
- this.name = "HooksCliError";
28
- }
29
- }
30
- /**
31
- * Per-event opensquid hook id. Was a single shared id pre-#118, which
32
- * meant uninstall could not selectively target one event AND legacy
33
- * entries written by older opensquid versions never got recognized
34
- * (since they had a different id, or none at all).
35
- */
36
- const HOOK_IDS = {
37
- PreToolUse: "opensquid-pre-tool-use",
38
- Stop: "opensquid-stop",
39
- StopFalseStopGuard: "opensquid-stop-false-stop-guard",
40
- UserPromptSubmit: "opensquid-user-prompt-submit",
41
- SessionEnd: "opensquid-session-end",
42
- };
43
- /** Legacy id used through 2026-05-15 — purgeOurHook still recognizes it. */
44
- const LEGACY_HOOK_ID = "opensquid-drift-pretooluse";
45
- /**
46
- * Path-substring fallback that identifies opensquid hook entries even
47
- * when no `_id` marker is present (older installs, manual edits, etc.).
48
- * Matches anything that runs `opensquid/dist/index.js`, regardless of
49
- * whether the subcommand is the legacy `hook <event>` (≤0.7.34) or the
50
- * new unified `anti-drift <event>` (0.7.35+).
51
- */
52
- const COMMAND_FINGERPRINT = "/opensquid/dist/index.js";
53
- /**
54
- * D9 false-stop guard prompt — fires as a `type: "prompt"` Stop hook
55
- * alongside the existing `type: "command"` Stop hook. Claude Code
56
- * evaluates this prompt against the assistant's just-completed turn
57
- * via the configured model and uses the YES/NO answer to allow or
58
- * block the stop. When blocked, the agent is re-prompted to continue.
59
- *
60
- * The prompt is intentionally framed so the default (YES, allow stop)
61
- * fires on the vast majority of turns; only trailing politeness
62
- * reflexes ("Run it?", "Want me to start B4?", "Should I continue?")
63
- * tip it to NO.
64
- *
65
- * Catches drift D9 per loop/docs/opensquid-anti-drift-unified-evaluator-design.md
66
- * rule #10b. Locked 2026-05-17 — user requirement: complete prevention.
67
- */
68
- const FALSE_STOP_GUARD_PROMPT = `The assistant just finished a turn with this message:
69
-
70
- $ARGUMENTS
71
-
72
- Did the assistant message above end with a REAL blocking question that requires user input before the agent can continue? Most messages end normally (no question, or with a question mark that's part of a real decision the user must make) and should answer YES (allow the stop).
73
-
74
- Only answer NO when the message ends with a politeness reflex or suggestion the agent should just execute past — patterns like "Run it?", "Want me to do X?", "Should I continue?", "Ready for the next step?", "Want me to start Y?". These are forbidden by the user's locked automation-mode rule.
75
-
76
- OUTPUT FORMAT (required): Begin your response with the literal prefix "🦑 [opensquid D9-guard] " so the user can visually identify this as an automated hook output (not agent text). After the prefix, respond YES or NO followed by a one-sentence justification.
77
-
78
- Examples of well-formed responses:
79
- - "🦑 [opensquid D9-guard] YES — message ends with a factual statement of completion, not a question."
80
- - "🦑 [opensquid D9-guard] NO — message ends with 'Want me to start B4?' which is a politeness reflex the agent should execute past."`;
81
- const FALSE_STOP_GUARD_MODEL = "claude-haiku-4-5";
82
- function settingsPath() {
83
- return path.join(os.homedir(), ".claude", "settings.json");
84
- }
85
- async function loadSettings() {
86
- try {
87
- const raw = await fs.readFile(settingsPath(), "utf8");
88
- const parsed = JSON.parse(raw);
89
- return parsed && typeof parsed === "object" ? parsed : {};
90
- }
91
- catch {
92
- return {};
93
- }
94
- }
95
- async function saveSettings(settings) {
96
- const p = settingsPath();
97
- await fs.mkdir(path.dirname(p), { recursive: true });
98
- await fs.writeFile(p, JSON.stringify(settings, null, 2) + "\n", "utf8");
99
- }
100
- /** Absolute path to the opensquid CLI binary that hosts this code. */
101
- function opensquidBinPath() {
102
- // import.meta.url points at dist/hooks-cli.js after build; the entry
103
- // point is dist/index.js in the same directory.
104
- const here = url.fileURLToPath(import.meta.url);
105
- return path.join(path.dirname(here), "index.js");
106
- }
107
- function buildHookCommand(hookName) {
108
- // 0.7.35 cutover: register hooks pointing at the unified anti-drift
109
- // evaluator (src/anti-drift/evaluator.ts) instead of the per-file
110
- // legacy handlers (src/hooks/<event>.ts). The legacy `hook <event>`
111
- // dispatch is preserved in index.ts for backward compat with
112
- // settings.json entries that haven't been re-installed yet.
113
- return `node ${opensquidBinPath()} anti-drift ${hookName}`;
114
- }
115
- /** True when a hook entry is recognizably opensquid's. */
116
- export function isOurHook(h) {
117
- if (h._id === LEGACY_HOOK_ID)
118
- return true;
119
- for (const id of Object.values(HOOK_IDS)) {
120
- if (h._id === id)
121
- return true;
122
- }
123
- // Fallback: command-path fingerprint catches un-marked legacy entries
124
- // that purgeOurHook used to silently skip (the bug from #118 dogfood).
125
- // Case-insensitive — macOS APFS default is case-preserving but case-
126
- // insensitive, so an install at /projects/OpenSquid/ should match too.
127
- // Prompt-typed hooks have no command field — they're recognized only
128
- // by their _id (handled above); manual / unmarked prompt entries are
129
- // not our concern (no installer wrote them).
130
- if (h.type === "command" &&
131
- typeof h.command === "string" &&
132
- h.command.toLowerCase().includes(COMMAND_FINGERPRINT.toLowerCase())) {
133
- return true;
134
- }
135
- return false;
136
- }
137
- /** Remove any existing opensquid hook from a matcher list. */
138
- function purgeOurHook(matchers) {
139
- return matchers
140
- .map((m) => ({
141
- ...m,
142
- hooks: m.hooks.filter((h) => !isOurHook(h)),
143
- }))
144
- .filter((m) => m.hooks.length > 0);
145
- }
146
- async function cmdInstall() {
147
- const settings = await loadSettings();
148
- const hooks = settings.hooks ?? {};
149
- // PreToolUse — single matcher ".*" is sufficient. It catches Bash
150
- // (drift checks live in pre-tool-use.ts handler keyed off tool_name)
151
- // AND every other tool (so the honesty ledger has full evidence for
152
- // Stop-hook reconciliation). Pre-#118 we registered TWO matchers
153
- // (Bash + .*) which double-fired on Bash and caused duplicate ledger
154
- // entries.
155
- const preToolUse = purgeOurHook(hooks.PreToolUse ?? []);
156
- preToolUse.push({
157
- matcher: ".*",
158
- hooks: [
159
- {
160
- type: "command",
161
- command: buildHookCommand("pre-tool-use"),
162
- _id: HOOK_IDS.PreToolUse,
163
- },
164
- ],
165
- });
166
- // Stop — claim-vs-action reconciliation + auto-classify spawn at turn end.
167
- const stop = purgeOurHook(hooks.Stop ?? []);
168
- stop.push({
169
- hooks: [{ type: "command", command: buildHookCommand("stop"), _id: HOOK_IDS.Stop }],
170
- });
171
- // D9 false-stop guard — fires as a native `type: "prompt"` hook so
172
- // Claude Code's framework handles the LLM evaluation (no subprocess
173
- // wrapper needed in opensquid). Catches trailing politeness reflexes
174
- // like "Run it?" / "Want me to start B4?" and blocks the stop,
175
- // re-prompting the agent to continue per the user's locked
176
- // automation-mode rule. Counts against the user's Claude Code
177
- // subscription model quota (haiku-class, cheap). 0.7.20 / drift D9.
178
- stop.push({
179
- hooks: [
180
- {
181
- type: "prompt",
182
- prompt: FALSE_STOP_GUARD_PROMPT,
183
- model: FALSE_STOP_GUARD_MODEL,
184
- _id: HOOK_IDS.StopFalseStopGuard,
185
- },
186
- ],
187
- });
188
- // UserPromptSubmit — surface previous turn's broken promises +
189
- // auto-classify candidates at the start of the next turn.
190
- const ups = purgeOurHook(hooks.UserPromptSubmit ?? []);
191
- ups.push({
192
- hooks: [
193
- {
194
- type: "command",
195
- command: buildHookCommand("user-prompt-submit"),
196
- _id: HOOK_IDS.UserPromptSubmit,
197
- },
198
- ],
199
- });
200
- // SessionEnd — clearSession to bound disk usage from per-session
201
- // ledger accumulation.
202
- const sessionEnd = purgeOurHook(hooks.SessionEnd ?? []);
203
- sessionEnd.push({
204
- hooks: [
205
- {
206
- type: "command",
207
- command: buildHookCommand("session-end"),
208
- _id: HOOK_IDS.SessionEnd,
209
- },
210
- ],
211
- });
212
- settings.hooks = {
213
- ...hooks,
214
- PreToolUse: preToolUse,
215
- Stop: stop,
216
- UserPromptSubmit: ups,
217
- SessionEnd: sessionEnd,
218
- };
219
- await saveSettings(settings);
220
- console.log(`[opensquid hooks install] wrote ${settingsPath()}`);
221
- console.log(` PreToolUse → ${buildHookCommand("pre-tool-use")}`);
222
- console.log(` Stop → ${buildHookCommand("stop")}`);
223
- console.log(` Stop (D9 guard) → type:prompt model:${FALSE_STOP_GUARD_MODEL}`);
224
- console.log(` UserPromptSubmit → ${buildHookCommand("user-prompt-submit")}`);
225
- console.log(` SessionEnd → ${buildHookCommand("session-end")}`);
226
- console.log(` next: restart Claude Code so the new settings load.`);
227
- }
228
- async function cmdUninstall() {
229
- const settings = await loadSettings();
230
- const hooks = settings.hooks;
231
- if (!hooks) {
232
- console.log(`[opensquid hooks uninstall] no hooks configured`);
233
- return;
234
- }
235
- let totalRemoved = 0;
236
- for (const event of ["PreToolUse", "Stop", "UserPromptSubmit", "SessionEnd"]) {
237
- const matchers = hooks[event];
238
- if (!matchers)
239
- continue;
240
- totalRemoved += countOurHooks(matchers);
241
- const purged = purgeOurHook(matchers);
242
- if (purged.length === 0) {
243
- delete hooks[event];
244
- }
245
- else {
246
- hooks[event] = purged;
247
- }
248
- }
249
- await saveSettings(settings);
250
- console.log(`[opensquid hooks uninstall] removed ${totalRemoved} opensquid hook(s)`);
251
- }
252
- async function cmdDoctor() {
253
- const settings = await loadSettings();
254
- const hooks = settings.hooks ?? {};
255
- console.log(`[opensquid hooks doctor]`);
256
- console.log(` settings.json: ${settingsPath()}`);
257
- for (const event of ["PreToolUse", "Stop", "UserPromptSubmit", "SessionEnd"]) {
258
- const matchers = hooks[event] ?? [];
259
- const ours = countOurHooks(matchers);
260
- console.log(` ${event.padEnd(18)} total=${matchers.length} opensquid=${ours}`);
261
- }
262
- }
263
- function countOurHooks(matchers) {
264
- let n = 0;
265
- for (const m of matchers) {
266
- for (const h of m.hooks) {
267
- if (isOurHook(h))
268
- n++;
269
- }
270
- }
271
- return n;
272
- }
273
- export async function runHooksCli(cmd, _argv) {
274
- switch (cmd) {
275
- case "install":
276
- await cmdInstall();
277
- return;
278
- case "uninstall":
279
- await cmdUninstall();
280
- return;
281
- case "doctor":
282
- await cmdDoctor();
283
- return;
284
- }
285
- }
286
- //# sourceMappingURL=hooks-cli.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hooks-cli.js","sourceRoot":"","sources":["../src.legacy/hooks-cli.ts"],"names":[],"mappings":"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"}
@@ -1,148 +0,0 @@
1
- /**
2
- * Tests for #118 — hooks-cli legacy entry detection + per-event HOOK_IDs.
3
- *
4
- * Covers `isOurHook` directly: recognition by per-event id, by legacy id,
5
- * by command-path fingerprint (un-marked entries from older installs),
6
- * and rejection of non-opensquid hooks.
7
- *
8
- * The install/uninstall integration tests are deferred — they touch the
9
- * user's real ~/.claude/settings.json and would need test-isolation
10
- * infrastructure that the hooks-cli module doesn't currently expose.
11
- */
12
- import { describe, expect, it } from "vitest";
13
- import { isOurHook } from "./hooks-cli.js";
14
- describe("isOurHook — per-event marker detection", () => {
15
- it("recognizes the PreToolUse marker", () => {
16
- expect(isOurHook({
17
- type: "command",
18
- command: "node /path/to/something/dist/index.js hook pre-tool-use",
19
- _id: "opensquid-pre-tool-use",
20
- })).toBe(true);
21
- });
22
- it("recognizes the Stop marker", () => {
23
- expect(isOurHook({
24
- type: "command",
25
- command: "node /path/to/something/dist/index.js hook stop",
26
- _id: "opensquid-stop",
27
- })).toBe(true);
28
- });
29
- it("recognizes the UserPromptSubmit marker", () => {
30
- expect(isOurHook({
31
- type: "command",
32
- command: "node /path/to/something/dist/index.js hook user-prompt-submit",
33
- _id: "opensquid-user-prompt-submit",
34
- })).toBe(true);
35
- });
36
- it("recognizes the SessionEnd marker", () => {
37
- expect(isOurHook({
38
- type: "command",
39
- command: "node /path/to/something/dist/index.js hook session-end",
40
- _id: "opensquid-session-end",
41
- })).toBe(true);
42
- });
43
- });
44
- describe("isOurHook — legacy marker detection (pre-#118)", () => {
45
- it("recognizes the legacy opensquid-drift-pretooluse id even on Stop entries", () => {
46
- expect(isOurHook({
47
- type: "command",
48
- command: "node /opt/foo/opensquid/dist/index.js hook stop",
49
- _id: "opensquid-drift-pretooluse",
50
- })).toBe(true);
51
- });
52
- });
53
- describe("isOurHook — command-path fallback (un-marked legacy entries)", () => {
54
- it("recognizes un-marked entries by command-path fingerprint", () => {
55
- expect(isOurHook({
56
- type: "command",
57
- command: "node /Users/alice/projects/opensquid/dist/index.js hook pre-tool-use",
58
- // No _id — the bug from #118 dogfood that left these undetected.
59
- })).toBe(true);
60
- });
61
- it("recognizes un-marked entries with absolute paths", () => {
62
- expect(isOurHook({
63
- type: "command",
64
- command: "/usr/local/bin/node /opt/opensquid/dist/index.js hook stop",
65
- })).toBe(true);
66
- });
67
- it("matches case-insensitively (macOS APFS case-preserving)", () => {
68
- expect(isOurHook({
69
- type: "command",
70
- command: "node /Users/alice/projects/OpenSquid/dist/index.js hook pre-tool-use",
71
- })).toBe(true);
72
- expect(isOurHook({
73
- type: "command",
74
- command: "node /OPENSQUID/dist/index.js hook stop",
75
- })).toBe(true);
76
- });
77
- it("does NOT match commands that incidentally contain 'opensquid' in unrelated context", () => {
78
- expect(isOurHook({
79
- type: "command",
80
- command: "echo 'I love opensquid'",
81
- })).toBe(false);
82
- });
83
- it("does NOT match similarly-named third-party tools", () => {
84
- expect(isOurHook({
85
- type: "command",
86
- command: "node /opt/some-other/dist/index.js hook stop",
87
- })).toBe(false);
88
- });
89
- });
90
- describe("FALSE_STOP_GUARD_PROMPT content (0.7.31 — squid emoji prefix)", () => {
91
- it("install writes a Stop prompt hook whose prompt instructs Haiku to prefix with 🦑 [opensquid D9-guard]", async () => {
92
- // Indirect: re-load the source file content via the install module
93
- // and verify the embedded prompt string contains the marker. Avoids
94
- // monkeypatching ~/.claude/settings.json in CI.
95
- const fs = await import("node:fs/promises");
96
- const path = await import("node:path");
97
- const url = await import("node:url");
98
- const here = url.fileURLToPath(import.meta.url);
99
- const sourcePath = path.join(path.dirname(here), "hooks-cli.ts");
100
- const src = await fs.readFile(sourcePath, "utf8");
101
- expect(src).toContain("🦑 [opensquid D9-guard]");
102
- });
103
- });
104
- describe("isOurHook — prompt-type Stop guard (0.7.20 / drift D9)", () => {
105
- it("recognizes the false-stop guard prompt hook by _id", () => {
106
- expect(isOurHook({
107
- type: "prompt",
108
- prompt: "any prompt text",
109
- model: "claude-haiku-4-5",
110
- _id: "opensquid-stop-false-stop-guard",
111
- })).toBe(true);
112
- });
113
- it("rejects a prompt-type entry with a foreign _id (no command fingerprint to fall back on)", () => {
114
- expect(isOurHook({
115
- type: "prompt",
116
- prompt: "some other prompt",
117
- model: "claude-haiku-4-5",
118
- _id: "other-tool-prompt-hook",
119
- })).toBe(false);
120
- });
121
- it("rejects an unmarked prompt-type entry (no _id, no command field)", () => {
122
- expect(isOurHook({
123
- type: "prompt",
124
- prompt: "unmarked prompt",
125
- })).toBe(false);
126
- });
127
- });
128
- describe("isOurHook — rejection of foreign hooks", () => {
129
- it("rejects entries with a different _id and a non-matching command", () => {
130
- expect(isOurHook({
131
- type: "command",
132
- command: "bun run /Users/slee/claude-memory/scripts/sync-to-supabase.ts",
133
- _id: "memory-sync",
134
- })).toBe(false);
135
- });
136
- it("rejects entries with no _id and a non-matching command", () => {
137
- expect(isOurHook({
138
- type: "command",
139
- command: "/usr/local/bin/some-other-hook --flag",
140
- })).toBe(false);
141
- });
142
- it("rejects empty command", () => {
143
- expect(isOurHook({
144
- type: "command",
145
- command: "",
146
- })).toBe(false);
147
- });
148
- });
package/dist/origin.d.ts DELETED
@@ -1,16 +0,0 @@
1
- import type { MemoryOrigin } from "./engine-client.js";
2
- /**
3
- * Build a `MemoryOrigin` block describing the current opensquid
4
- * process. Called once per `memorize`; cheap (env reads + base
5
- * conversions). Returns a typed object with all detected fields
6
- * populated; absent fields stay `undefined` so engine-side
7
- * `skip_serializing_if = "Option::is_none"` keeps the on-disk YAML
8
- * tight.
9
- */
10
- export declare function detectOrigin(): MemoryOrigin;
11
- /**
12
- * Test seam: re-export the stable fallback session id so suites can
13
- * assert determinism across calls within one process.
14
- */
15
- export declare function fallbackSessionId(): string;
16
- //# sourceMappingURL=origin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"origin.d.ts","sourceRoot":"","sources":["../src.legacy/origin.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA8CvD;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,YAAY,CAU3C;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
package/dist/origin.js DELETED
@@ -1,92 +0,0 @@
1
- /**
2
- * Origination metadata auto-detection — v0.4 Phase 1.
3
- *
4
- * Builds the `MemoryOrigin` block opensquid attaches to every
5
- * `memorize` call. The engine treats it as opaque-ish data (typed
6
- * struct with all-optional fields); the wedge gate consumes
7
- * `session_id` for v0.4+ multi-session reproducibility scoring.
8
- *
9
- * Detection priority per field:
10
- *
11
- * - `host` — `OPENSQUID_HOST` env (explicit override) ->
12
- * `claude-code` heuristic (CLAUDE_CODE_* / ANTHROPIC_*
13
- * env presence) -> `unknown`.
14
- * - `session_id` — `CLAUDE_SESSION_ID` env -> fallback opaque
15
- * `sha1(start_time + pid)[:8]` (stable per
16
- * process, not per conversation — documented).
17
- * - `model` — `OPENSQUID_MODEL` env -> `ANTHROPIC_MODEL` env ->
18
- * undefined (omitted).
19
- * - `cwd_basename` — `path.basename(process.cwd())` always.
20
- * - `written_at` — `new Date().toISOString()` always.
21
- *
22
- * Privacy invariant (mirrors engine-side docs): NEVER emit full file
23
- * paths, raw transcript content, or user identity. `session_id` is
24
- * opaque — the raw transcript path is hashed before truncation.
25
- */
26
- import { createHash } from "node:crypto";
27
- import * as path from "node:path";
28
- /**
29
- * Process-lifetime fallback session id. Computed once at module load
30
- * so all memorize calls from one opensquid subprocess share the same
31
- * id when no host-provided id is available.
32
- */
33
- const FALLBACK_SESSION_ID = computeFallbackSessionId();
34
- function computeFallbackSessionId() {
35
- const seed = `${Date.now()}.${process.pid}.${Math.random()}`;
36
- return createHash("sha1").update(seed).digest("hex").slice(0, 8);
37
- }
38
- function detectHost() {
39
- if (process.env.OPENSQUID_HOST)
40
- return process.env.OPENSQUID_HOST;
41
- // Claude Code exposes a handful of CLAUDE_* env vars when it spawns
42
- // an MCP child. Probe for any of them as a soft signal.
43
- if (process.env.CLAUDE_CODE_VERSION ||
44
- process.env.CLAUDE_PROJECT_DIR ||
45
- process.env.CLAUDE_SESSION_ID) {
46
- return "claude-code";
47
- }
48
- return "unknown";
49
- }
50
- function detectSessionId() {
51
- const raw = process.env.CLAUDE_SESSION_ID?.trim();
52
- if (raw) {
53
- // Hash + truncate so the on-disk id is opaque (not the raw UUID
54
- // visible elsewhere on the system). Privacy invariant.
55
- return createHash("sha1").update(raw).digest("hex").slice(0, 8);
56
- }
57
- return FALLBACK_SESSION_ID;
58
- }
59
- function detectModel() {
60
- return process.env.OPENSQUID_MODEL?.trim() || process.env.ANTHROPIC_MODEL?.trim() || undefined;
61
- }
62
- function detectCwdBasename() {
63
- return path.basename(process.cwd());
64
- }
65
- /**
66
- * Build a `MemoryOrigin` block describing the current opensquid
67
- * process. Called once per `memorize`; cheap (env reads + base
68
- * conversions). Returns a typed object with all detected fields
69
- * populated; absent fields stay `undefined` so engine-side
70
- * `skip_serializing_if = "Option::is_none"` keeps the on-disk YAML
71
- * tight.
72
- */
73
- export function detectOrigin() {
74
- const origin = {
75
- host: detectHost(),
76
- session_id: detectSessionId(),
77
- cwd_basename: detectCwdBasename(),
78
- written_at: new Date().toISOString(),
79
- };
80
- const model = detectModel();
81
- if (model)
82
- origin.model = model;
83
- return origin;
84
- }
85
- /**
86
- * Test seam: re-export the stable fallback session id so suites can
87
- * assert determinism across calls within one process.
88
- */
89
- export function fallbackSessionId() {
90
- return FALLBACK_SESSION_ID;
91
- }
92
- //# sourceMappingURL=origin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"origin.js","sourceRoot":"","sources":["../src.legacy/origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC;;;;GAIG;AACH,MAAM,mBAAmB,GAAG,wBAAwB,EAAE,CAAC;AAEvD,SAAS,wBAAwB;IAC/B,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;IAC7D,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,UAAU;IACjB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAClE,oEAAoE;IACpE,wDAAwD;IACxD,IACE,OAAO,CAAC,GAAG,CAAC,mBAAmB;QAC/B,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC9B,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAC7B,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IAClD,IAAI,GAAG,EAAE,CAAC;QACR,gEAAgE;QAChE,uDAAuD;QACvD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;AACjG,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAiB;QAC3B,IAAI,EAAE,UAAU,EAAE;QAClB,UAAU,EAAE,eAAe,EAAE;QAC7B,YAAY,EAAE,iBAAiB,EAAE;QACjC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACrC,CAAC;IACF,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,IAAI,KAAK;QAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;IAChC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,mBAAmB,CAAC;AAC7B,CAAC"}
@@ -1,30 +0,0 @@
1
- import type { EngineClient } from '../engine/client.js';
2
- import type { SeedLesson } from './schemas/manifest.js';
3
- export interface IngestResult {
4
- ingested: number;
5
- skipped: number;
6
- failed: readonly {
7
- title: string;
8
- error: string;
9
- }[];
10
- }
11
- /**
12
- * Ingest `seeds` into the engine. Returns `{ingested, skipped, failed}`:
13
- * - `ingested`: seeds that the engine accepted as NEW rows
14
- * (`result.updated === false`)
15
- * - `skipped`: seeds the engine UPSERTed onto an existing row
16
- * (`result.updated === true`) — idempotent re-ingest
17
- * - `failed`: per-seed RPC errors (engine down, validation error,
18
- * network blip). Never thrown — callers log.
19
- */
20
- export declare function ingestSeedLessons(packName: string, packVersion: string, seeds: readonly SeedLesson[], engine: EngineClient, packDir: string): Promise<IngestResult>;
21
- /**
22
- * sha256-derived external_id for engine UPSERT.
23
- *
24
- * Stable across opensquid processes for the same (pack@version + title),
25
- * collision-resistant under pack-author discipline (no two seeds in one
26
- * pack share a title). Different packs that happen to use the same title
27
- * produce distinct external_ids because pack name is part of the input.
28
- */
29
- export declare function makeExternalId(packName: string, packVersion: string, title: string): string;
30
- //# sourceMappingURL=seed_lessons_ingest.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"seed_lessons_ingest.d.ts","sourceRoot":"","sources":["../../src/packs/seed_lessons_ingest.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACrD;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CA2BvB;AAiCD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG3F"}