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/project.js DELETED
@@ -1,281 +0,0 @@
1
- /**
2
- * Project identity — decouple project scope from filesystem path.
3
- *
4
- * Two artifacts work together:
5
- *
6
- * 1. **Local ID card** at `<project-root>/.opensquid/project.json` —
7
- * stable identity that travels with the project across moves /
8
- * renames. Contains `id` (human-friendly), `uuid` (machine-stable),
9
- * `created_at`.
10
- *
11
- * 2. **Global registry** at `~/.opensquid/projects.json` — index of
12
- * all known projects by uuid. Tracks `last_seen_path`,
13
- * `last_seen_at`, `status` (active|deleted) so we can detect
14
- * moves and prune deletes.
15
- *
16
- * State machine on `resolveProject(cwd)`:
17
- *
18
- * - card present, registry agrees on path → **known**
19
- * - card present, registry has different path for this uuid → **moved**
20
- * (registry's old path may or may not still exist; we update both)
21
- * - card absent → **new** (caller decides whether to auto-create)
22
- *
23
- * `pruneDeleted()` sweeps the registry: for each active entry whose
24
- * `last_seen_path` no longer exists on disk, flip status to "deleted".
25
- */
26
- import * as crypto from "node:crypto";
27
- import { promises as fs } from "node:fs";
28
- import * as os from "node:os";
29
- import * as path from "node:path";
30
- import { resolveDataRoot } from "./codex/store.js";
31
- // ---------------------------------------------------------------------
32
- // Paths
33
- // ---------------------------------------------------------------------
34
- const CARD_DIR = ".opensquid";
35
- const CARD_FILE = "project.json";
36
- const REGISTRY_FILE = "projects.json";
37
- /** Path to the registry file. */
38
- export function registryPath(dataRoot) {
39
- return path.join(resolveDataRoot(dataRoot), REGISTRY_FILE);
40
- }
41
- /** Path the ID card WOULD live at for a given project root. */
42
- export function cardPathForRoot(projectRoot) {
43
- return path.join(projectRoot, CARD_DIR, CARD_FILE);
44
- }
45
- // ---------------------------------------------------------------------
46
- // Card load / save
47
- // ---------------------------------------------------------------------
48
- /**
49
- * Walk up from `cwd` looking for a `.opensquid/project.json` card.
50
- * Stops at the filesystem root. Returns the card + the path the
51
- * card was found at, or null if no card exists in any ancestor.
52
- */
53
- export async function findProjectCard(cwd) {
54
- let dir = path.resolve(cwd);
55
- while (true) {
56
- const candidate = path.join(dir, CARD_DIR, CARD_FILE);
57
- try {
58
- const raw = await fs.readFile(candidate, "utf8");
59
- const parsed = JSON.parse(raw);
60
- if (parsed && parsed.version === 1 && parsed.uuid && parsed.id) {
61
- return { card: parsed, cardPath: candidate };
62
- }
63
- }
64
- catch {
65
- // ignore — keep walking up
66
- }
67
- const parent = path.dirname(dir);
68
- if (parent === dir)
69
- return null;
70
- dir = parent;
71
- }
72
- }
73
- /**
74
- * Write a project card at `<projectRoot>/.opensquid/project.json`.
75
- * Refuses to overwrite an existing card unless `force` is set —
76
- * overwriting is a manual operation, not an accidental one.
77
- */
78
- export async function writeProjectCard(projectRoot, card, options = {}) {
79
- const cardPath = cardPathForRoot(projectRoot);
80
- try {
81
- await fs.access(cardPath);
82
- if (!options.force) {
83
- throw new Error(`project card already exists at ${cardPath} (use force to overwrite)`);
84
- }
85
- }
86
- catch (err) {
87
- // Re-throw real errors; ENOENT means we proceed.
88
- if (err.code !== "ENOENT" &&
89
- !(err instanceof Error && err.message.includes("already exists"))) {
90
- throw err;
91
- }
92
- if (err instanceof Error && err.message.includes("already exists"))
93
- throw err;
94
- }
95
- await fs.mkdir(path.dirname(cardPath), { recursive: true });
96
- await fs.writeFile(cardPath, JSON.stringify(card, null, 2) + "\n", "utf8");
97
- return { cardPath };
98
- }
99
- // ---------------------------------------------------------------------
100
- // Registry load / save
101
- // ---------------------------------------------------------------------
102
- export async function loadRegistry(dataRoot) {
103
- const p = registryPath(dataRoot);
104
- try {
105
- const raw = await fs.readFile(p, "utf8");
106
- const parsed = JSON.parse(raw);
107
- if (parsed && parsed.version === 1 && parsed.projects)
108
- return parsed;
109
- }
110
- catch {
111
- // missing or malformed — return a fresh registry
112
- }
113
- return { version: 1, projects: {} };
114
- }
115
- export async function saveRegistry(reg, dataRoot) {
116
- const p = registryPath(dataRoot);
117
- await fs.mkdir(path.dirname(p), { recursive: true });
118
- await fs.writeFile(p, JSON.stringify(reg, null, 2) + "\n", "utf8");
119
- }
120
- // ---------------------------------------------------------------------
121
- // Resolve project state
122
- // ---------------------------------------------------------------------
123
- /**
124
- * Determine the project state for a given cwd.
125
- *
126
- * - Walks up from cwd for a card.
127
- * - Cross-references with the registry.
128
- * - Returns the state without mutating either file.
129
- *
130
- * `applyResolution` is the side-effect step: it updates the registry
131
- * based on the resolved state (and creates a card for `new` IF the
132
- * caller asks it to).
133
- */
134
- export async function resolveProject(cwd, options = {}) {
135
- const found = await findProjectCard(cwd);
136
- if (!found) {
137
- const suggested = await suggestedIdForCwd(cwd);
138
- return { kind: "new", project_root: null, suggested_id: suggested };
139
- }
140
- const reg = await loadRegistry(options.dataRoot);
141
- const projectRoot = path.dirname(path.dirname(found.cardPath));
142
- const entry = reg.projects[found.card.uuid];
143
- if (!entry || entry.last_seen_path === projectRoot) {
144
- return { kind: "known", card: found.card, cardPath: found.cardPath };
145
- }
146
- return {
147
- kind: "moved",
148
- card: found.card,
149
- cardPath: found.cardPath,
150
- from_path: entry.last_seen_path,
151
- };
152
- }
153
- /**
154
- * Side-effecting companion to `resolveProject`. Updates the registry
155
- * (creating the card if asked for `new`). Idempotent.
156
- *
157
- * - `known`: bump `last_seen_at` only.
158
- * - `moved`: update `last_seen_path` + `last_seen_at`.
159
- * - `new`: if `autoCreate` is true, create a card at `cwd` + register
160
- * it. Otherwise return null.
161
- */
162
- export async function applyResolution(cwd, resolved, options = {}) {
163
- const dataRoot = options.dataRoot;
164
- const now = new Date().toISOString();
165
- const reg = await loadRegistry(dataRoot);
166
- if (resolved.kind === "known") {
167
- const entry = reg.projects[resolved.card.uuid];
168
- if (entry) {
169
- entry.last_seen_at = now;
170
- entry.status = "active";
171
- }
172
- else {
173
- const projectRoot = path.dirname(path.dirname(resolved.cardPath));
174
- reg.projects[resolved.card.uuid] = {
175
- id: resolved.card.id,
176
- last_seen_path: projectRoot,
177
- last_seen_at: now,
178
- created_at: resolved.card.created_at,
179
- status: "active",
180
- };
181
- }
182
- await saveRegistry(reg, dataRoot);
183
- return resolved.card;
184
- }
185
- if (resolved.kind === "moved") {
186
- const projectRoot = path.dirname(path.dirname(resolved.cardPath));
187
- reg.projects[resolved.card.uuid] = {
188
- id: resolved.card.id,
189
- last_seen_path: projectRoot,
190
- last_seen_at: now,
191
- created_at: reg.projects[resolved.card.uuid]?.created_at ?? resolved.card.created_at,
192
- status: "active",
193
- };
194
- await saveRegistry(reg, dataRoot);
195
- return resolved.card;
196
- }
197
- // kind === "new"
198
- if (!options.autoCreate)
199
- return null;
200
- const id = options.id ?? resolved.suggested_id;
201
- const uuid = crypto.randomUUID();
202
- const created_at = now;
203
- const card = { version: 1, id, uuid, created_at };
204
- await writeProjectCard(path.resolve(cwd), card);
205
- reg.projects[uuid] = {
206
- id,
207
- last_seen_path: path.resolve(cwd),
208
- last_seen_at: now,
209
- created_at,
210
- status: "active",
211
- };
212
- await saveRegistry(reg, dataRoot);
213
- return card;
214
- }
215
- // ---------------------------------------------------------------------
216
- // Registry maintenance
217
- // ---------------------------------------------------------------------
218
- /**
219
- * Mark registry entries as "deleted" when their `last_seen_path` no
220
- * longer exists on disk. Does NOT actually remove the entry — kept
221
- * for historical reference and so the user can see what they had.
222
- *
223
- * Returns the count of entries that flipped from active → deleted.
224
- */
225
- export async function pruneDeleted(dataRoot) {
226
- const reg = await loadRegistry(dataRoot);
227
- let swept = 0;
228
- const removed_ids = [];
229
- for (const [uuid, entry] of Object.entries(reg.projects)) {
230
- if (entry.status !== "active")
231
- continue;
232
- try {
233
- await fs.access(entry.last_seen_path);
234
- }
235
- catch {
236
- entry.status = "deleted";
237
- swept++;
238
- removed_ids.push(entry.id);
239
- void uuid;
240
- }
241
- }
242
- if (swept > 0)
243
- await saveRegistry(reg, dataRoot);
244
- return { swept, removed_ids };
245
- }
246
- // ---------------------------------------------------------------------
247
- // Helpers
248
- // ---------------------------------------------------------------------
249
- /**
250
- * Default-id heuristic: git toplevel basename if available, else cwd
251
- * basename, else "project".
252
- */
253
- async function suggestedIdForCwd(cwd) {
254
- const gitTop = await gitToplevel(cwd);
255
- if (gitTop)
256
- return path.basename(gitTop);
257
- const cwdName = path.basename(path.resolve(cwd));
258
- return cwdName || "project";
259
- }
260
- async function gitToplevel(cwd) {
261
- // Walk up looking for a `.git` directory.
262
- let dir = path.resolve(cwd);
263
- while (true) {
264
- try {
265
- const stat = await fs.stat(path.join(dir, ".git"));
266
- if (stat.isDirectory())
267
- return dir;
268
- }
269
- catch {
270
- // keep walking
271
- }
272
- const parent = path.dirname(dir);
273
- if (parent === dir) {
274
- // tilde-fallback only used for tests where HOME might point at /
275
- void os.homedir;
276
- return null;
277
- }
278
- dir = parent;
279
- }
280
- }
281
- //# sourceMappingURL=project.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../src.legacy/project.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AA+CnD,wEAAwE;AACxE,QAAQ;AACR,wEAAwE;AAExE,MAAM,QAAQ,GAAG,YAAY,CAAC;AAC9B,MAAM,SAAS,GAAG,cAAc,CAAC;AACjC,MAAM,aAAa,GAAG,eAAe,CAAC;AAEtC,iCAAiC;AACjC,MAAM,UAAU,YAAY,CAAC,QAAiB;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,CAAC;AAC7D,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;AACrD,CAAC;AAED,wEAAwE;AACxE,mBAAmB;AACnB,wEAAwE;AAExE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW;IAEX,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QACtD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;YAC9C,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;gBAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;YAC/C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAChC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAmB,EACnB,IAAiB,EACjB,UAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,2BAA2B,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,iDAAiD;QACjD,IACG,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAChD,CAAC,CAAC,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,EACjE,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAAE,MAAM,GAAG,CAAC;IAChF,CAAC;IACD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3E,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED,wEAAwE;AACxE,uBAAuB;AACvB,wEAAwE;AAExE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAiB;IAClD,MAAM,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAC;QAC3C,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ;YAAE,OAAO,MAAM,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAa,EAAE,QAAiB;IACjE,MAAM,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACjC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACrE,CAAC;AAED,wEAAwE;AACxE,wBAAwB;AACxB,wEAAwE;AAExE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAW,EACX,UAAiC,EAAE;IAEnC,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;IACtE,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,cAAc,KAAK,WAAW,EAAE,CAAC;QACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;IACvE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,cAAc;KAChC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,QAAyB,EACzB,UAAoE,EAAE;IAEtE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEzC,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC;YACzB,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBACjC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE;gBACpB,cAAc,EAAE,WAAW;gBAC3B,YAAY,EAAE,GAAG;gBACjB,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU;gBACpC,MAAM,EAAE,QAAQ;aACjB,CAAC;QACJ,CAAC;QACD,MAAM,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAClC,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAClE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YACjC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE;YACpB,cAAc,EAAE,WAAW;YAC3B,YAAY,EAAE,GAAG;YACjB,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU;YACpF,MAAM,EAAE,QAAQ;SACjB,CAAC;QACF,MAAM,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAClC,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,iBAAiB;IACjB,IAAI,CAAC,OAAO,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,QAAQ,CAAC,YAAY,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACjC,MAAM,UAAU,GAAG,GAAG,CAAC;IACvB,MAAM,IAAI,GAAgB,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAC/D,MAAM,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IAChD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG;QACnB,EAAE;QACF,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;QACjC,YAAY,EAAE,GAAG;QACjB,UAAU;QACV,MAAM,EAAE,QAAQ;KACjB,CAAC;IACF,MAAM,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wEAAwE;AACxE,uBAAuB;AACvB,wEAAwE;AAExE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAiB;IAIlD,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ;YAAE,SAAS;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;YACzB,KAAK,EAAE,CAAC;YACR,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3B,KAAK,IAAI,CAAC;QACZ,CAAC;IACH,CAAC;IACD,IAAI,KAAK,GAAG,CAAC;QAAE,MAAM,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACjD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,wEAAwE;AACxE,UAAU;AACV,wEAAwE;AAExE;;;GAGG;AACH,KAAK,UAAU,iBAAiB,CAAC,GAAW;IAC1C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,MAAM;QAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,OAAO,OAAO,IAAI,SAAS,CAAC;AAC9B,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAW;IACpC,0CAA0C;IAC1C,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;YACnD,IAAI,IAAI,CAAC,WAAW,EAAE;gBAAE,OAAO,GAAG,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,iEAAiE;YACjE,KAAK,EAAE,CAAC,OAAO,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -1,287 +0,0 @@
1
- import * as crypto from "node:crypto";
2
- import { promises as fs } from "node:fs";
3
- import * as os from "node:os";
4
- import * as path from "node:path";
5
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
6
- import { applyResolution, cardPathForRoot, findProjectCard, loadRegistry, pruneDeleted, resolveProject, saveRegistry, writeProjectCard, } from "./project.js";
7
- let tmpRoot;
8
- let tmpHome;
9
- beforeEach(async () => {
10
- const uniq = crypto.randomUUID();
11
- tmpRoot = path.join(os.tmpdir(), `oscli-project-cwd-${uniq}`);
12
- tmpHome = path.join(os.tmpdir(), `oscli-project-home-${uniq}`);
13
- await fs.mkdir(tmpRoot, { recursive: true });
14
- await fs.mkdir(tmpHome, { recursive: true });
15
- });
16
- afterEach(async () => {
17
- await fs.rm(tmpRoot, { recursive: true, force: true });
18
- await fs.rm(tmpHome, { recursive: true, force: true });
19
- });
20
- // ---------------------------------------------------------------------
21
- // findProjectCard
22
- // ---------------------------------------------------------------------
23
- describe("findProjectCard", () => {
24
- it("returns null when no card in any ancestor", async () => {
25
- expect(await findProjectCard(tmpRoot)).toBeNull();
26
- });
27
- it("finds a card at cwd", async () => {
28
- const card = {
29
- version: 1,
30
- id: "x",
31
- uuid: "u-1",
32
- created_at: "2026-05-15T00:00:00Z",
33
- };
34
- await writeProjectCard(tmpRoot, card);
35
- const found = await findProjectCard(tmpRoot);
36
- expect(found?.card.uuid).toBe("u-1");
37
- });
38
- it("walks up to find a card at an ancestor", async () => {
39
- const card = {
40
- version: 1,
41
- id: "x",
42
- uuid: "u-1",
43
- created_at: "2026-05-15T00:00:00Z",
44
- };
45
- await writeProjectCard(tmpRoot, card);
46
- const deep = path.join(tmpRoot, "src", "nested", "deep");
47
- await fs.mkdir(deep, { recursive: true });
48
- const found = await findProjectCard(deep);
49
- expect(found?.card.uuid).toBe("u-1");
50
- expect(found?.cardPath).toBe(cardPathForRoot(tmpRoot));
51
- });
52
- it("ignores malformed card files", async () => {
53
- await fs.mkdir(path.join(tmpRoot, ".opensquid"), { recursive: true });
54
- await fs.writeFile(cardPathForRoot(tmpRoot), "{not valid json", "utf8");
55
- expect(await findProjectCard(tmpRoot)).toBeNull();
56
- });
57
- });
58
- // ---------------------------------------------------------------------
59
- // writeProjectCard
60
- // ---------------------------------------------------------------------
61
- describe("writeProjectCard", () => {
62
- it("creates the .opensquid/project.json file", async () => {
63
- const card = {
64
- version: 1,
65
- id: "x",
66
- uuid: "u-1",
67
- created_at: "now",
68
- };
69
- const res = await writeProjectCard(tmpRoot, card);
70
- expect(res.cardPath).toBe(cardPathForRoot(tmpRoot));
71
- const read = await fs.readFile(res.cardPath, "utf8");
72
- expect(JSON.parse(read).uuid).toBe("u-1");
73
- });
74
- it("refuses to overwrite without force", async () => {
75
- const card = {
76
- version: 1,
77
- id: "x",
78
- uuid: "u-1",
79
- created_at: "now",
80
- };
81
- await writeProjectCard(tmpRoot, card);
82
- await expect(writeProjectCard(tmpRoot, card)).rejects.toThrow(/already exists/);
83
- });
84
- it("overwrites with force=true", async () => {
85
- const v1 = {
86
- version: 1,
87
- id: "x",
88
- uuid: "u-1",
89
- created_at: "now",
90
- };
91
- await writeProjectCard(tmpRoot, v1);
92
- const v2 = { ...v1, id: "y" };
93
- await writeProjectCard(tmpRoot, v2, { force: true });
94
- const found = await findProjectCard(tmpRoot);
95
- expect(found?.card.id).toBe("y");
96
- });
97
- });
98
- // ---------------------------------------------------------------------
99
- // resolveProject — state machine
100
- // ---------------------------------------------------------------------
101
- describe("resolveProject state machine", () => {
102
- it("returns 'new' when no card exists", async () => {
103
- const r = await resolveProject(tmpRoot, { dataRoot: tmpHome });
104
- expect(r.kind).toBe("new");
105
- if (r.kind === "new") {
106
- expect(r.suggested_id).toBe(path.basename(tmpRoot));
107
- }
108
- });
109
- it("returns 'known' when card exists at path that matches registry", async () => {
110
- const card = {
111
- version: 1,
112
- id: "x",
113
- uuid: "u-1",
114
- created_at: "now",
115
- };
116
- await writeProjectCard(tmpRoot, card);
117
- // Apply once so registry knows the path.
118
- await applyResolution(tmpRoot, await resolveProject(tmpRoot, { dataRoot: tmpHome }), {
119
- dataRoot: tmpHome,
120
- });
121
- const r = await resolveProject(tmpRoot, { dataRoot: tmpHome });
122
- expect(r.kind).toBe("known");
123
- });
124
- it("returns 'moved' when card exists at NEW path but registry has DIFFERENT path", async () => {
125
- // Create card at tmpRoot, register it there.
126
- const card = {
127
- version: 1,
128
- id: "x",
129
- uuid: "u-1",
130
- created_at: "now",
131
- };
132
- await writeProjectCard(tmpRoot, card);
133
- await applyResolution(tmpRoot, await resolveProject(tmpRoot, { dataRoot: tmpHome }), {
134
- dataRoot: tmpHome,
135
- });
136
- // Simulate move: write the same card at a new path, leave registry as-is.
137
- const newRoot = path.join(os.tmpdir(), `oscli-moved-${crypto.randomUUID()}`);
138
- await fs.mkdir(newRoot, { recursive: true });
139
- try {
140
- await writeProjectCard(newRoot, card);
141
- const r = await resolveProject(newRoot, { dataRoot: tmpHome });
142
- expect(r.kind).toBe("moved");
143
- if (r.kind === "moved") {
144
- expect(r.from_path).toBe(tmpRoot);
145
- }
146
- }
147
- finally {
148
- await fs.rm(newRoot, { recursive: true, force: true });
149
- }
150
- });
151
- });
152
- // ---------------------------------------------------------------------
153
- // applyResolution
154
- // ---------------------------------------------------------------------
155
- describe("applyResolution", () => {
156
- it("auto-creates card on 'new' when autoCreate=true", async () => {
157
- const r = await resolveProject(tmpRoot, { dataRoot: tmpHome });
158
- expect(r.kind).toBe("new");
159
- const card = await applyResolution(tmpRoot, r, {
160
- dataRoot: tmpHome,
161
- autoCreate: true,
162
- });
163
- expect(card).not.toBeNull();
164
- expect(card?.id).toBe(path.basename(tmpRoot));
165
- // Card persisted on disk.
166
- const found = await findProjectCard(tmpRoot);
167
- expect(found?.card.uuid).toBe(card?.uuid);
168
- // Registry has it.
169
- const reg = await loadRegistry(tmpHome);
170
- expect(reg.projects[card.uuid].last_seen_path).toBe(tmpRoot);
171
- });
172
- it("returns null on 'new' when autoCreate=false (default)", async () => {
173
- const r = await resolveProject(tmpRoot, { dataRoot: tmpHome });
174
- const card = await applyResolution(tmpRoot, r, { dataRoot: tmpHome });
175
- expect(card).toBeNull();
176
- expect(await findProjectCard(tmpRoot)).toBeNull();
177
- });
178
- it("custom --id overrides the suggested default on auto-create", async () => {
179
- const r = await resolveProject(tmpRoot, { dataRoot: tmpHome });
180
- const card = await applyResolution(tmpRoot, r, {
181
- dataRoot: tmpHome,
182
- autoCreate: true,
183
- id: "custom-name",
184
- });
185
- expect(card?.id).toBe("custom-name");
186
- });
187
- it("updates registry path on 'moved'", async () => {
188
- // Create card + register at tmpRoot.
189
- const card = {
190
- version: 1,
191
- id: "x",
192
- uuid: "u-mov",
193
- created_at: "now",
194
- };
195
- await writeProjectCard(tmpRoot, card);
196
- await applyResolution(tmpRoot, await resolveProject(tmpRoot, { dataRoot: tmpHome }), {
197
- dataRoot: tmpHome,
198
- });
199
- // Move: same card at a new path.
200
- const newRoot = path.join(os.tmpdir(), `oscli-moved-${crypto.randomUUID()}`);
201
- await fs.mkdir(newRoot, { recursive: true });
202
- try {
203
- await writeProjectCard(newRoot, card);
204
- const r = await resolveProject(newRoot, { dataRoot: tmpHome });
205
- expect(r.kind).toBe("moved");
206
- await applyResolution(newRoot, r, { dataRoot: tmpHome });
207
- const reg = await loadRegistry(tmpHome);
208
- expect(reg.projects["u-mov"].last_seen_path).toBe(newRoot);
209
- }
210
- finally {
211
- await fs.rm(newRoot, { recursive: true, force: true });
212
- }
213
- });
214
- it("preserves created_at across registry updates", async () => {
215
- const card = {
216
- version: 1,
217
- id: "x",
218
- uuid: "u-1",
219
- created_at: "2020-01-01T00:00:00Z",
220
- };
221
- await writeProjectCard(tmpRoot, card);
222
- await applyResolution(tmpRoot, await resolveProject(tmpRoot, { dataRoot: tmpHome }), {
223
- dataRoot: tmpHome,
224
- });
225
- const reg1 = await loadRegistry(tmpHome);
226
- const firstCreatedAt = reg1.projects["u-1"].created_at;
227
- // Second invocation shouldn't change created_at even when last_seen_at moves.
228
- await applyResolution(tmpRoot, await resolveProject(tmpRoot, { dataRoot: tmpHome }), {
229
- dataRoot: tmpHome,
230
- });
231
- const reg2 = await loadRegistry(tmpHome);
232
- expect(reg2.projects["u-1"].created_at).toBe(firstCreatedAt);
233
- });
234
- });
235
- // ---------------------------------------------------------------------
236
- // pruneDeleted
237
- // ---------------------------------------------------------------------
238
- describe("pruneDeleted", () => {
239
- it("flips entries whose last_seen_path no longer exists", async () => {
240
- // Set up two entries: one path exists, one doesn't.
241
- const goneRoot = path.join(os.tmpdir(), `oscli-gone-${crypto.randomUUID()}`);
242
- await fs.mkdir(goneRoot);
243
- await saveRegistry({
244
- version: 1,
245
- projects: {
246
- alive: {
247
- id: "alive",
248
- last_seen_path: tmpRoot,
249
- last_seen_at: "2026-05-15T00:00:00Z",
250
- created_at: "2026-05-15T00:00:00Z",
251
- status: "active",
252
- },
253
- gone: {
254
- id: "gone",
255
- last_seen_path: goneRoot,
256
- last_seen_at: "2026-05-15T00:00:00Z",
257
- created_at: "2026-05-15T00:00:00Z",
258
- status: "active",
259
- },
260
- },
261
- }, tmpHome);
262
- // Delete the path for "gone" so it'll be flagged.
263
- await fs.rm(goneRoot, { recursive: true, force: true });
264
- const res = await pruneDeleted(tmpHome);
265
- expect(res.swept).toBe(1);
266
- expect(res.removed_ids).toEqual(["gone"]);
267
- const reg = await loadRegistry(tmpHome);
268
- expect(reg.projects.alive.status).toBe("active");
269
- expect(reg.projects.gone.status).toBe("deleted");
270
- });
271
- it("does not touch already-deleted entries", async () => {
272
- await saveRegistry({
273
- version: 1,
274
- projects: {
275
- ghost: {
276
- id: "ghost",
277
- last_seen_path: "/nonexistent/path",
278
- last_seen_at: "2026-05-15T00:00:00Z",
279
- created_at: "2026-05-15T00:00:00Z",
280
- status: "deleted",
281
- },
282
- },
283
- }, tmpHome);
284
- const res = await pruneDeleted(tmpHome);
285
- expect(res.swept).toBe(0);
286
- });
287
- });
@@ -1,61 +0,0 @@
1
- /**
2
- * Loop-engine RAG backend — routes RagBackend through the engine daemon's
3
- * JSON-RPC API (memory.search + memory.create) via the T.4 UDS singleton.
4
- *
5
- * Quality: `mode: 'hybrid'` invokes engine-side RRF fusion (K=60, Cormack
6
- * et al. 2009) — drop-in equivalent to opensquid's `src/rag/rrf.ts:65`
7
- * per T.1.JJ. No TS-side fusion needed; engine does it server-side over a
8
- * larger native vector index than libsql's DiskANN.
9
- *
10
- * Critical design locks (T.1.B + T.1.#6):
11
- *
12
- * 1. **storeLesson → memory.create is INTENTIONAL, not a bug.** Routing
13
- * here through `lesson.create` would force every recall-pool write
14
- * through the wedge gate's 24h + applied_count=3 + external_signal
15
- * promotion requirements (per T.1.F — unsatisfiable in a single
16
- * write call, breaks unit tests). RagBackend.storeLesson semantically
17
- * stores a recallable memory, NOT a wedge-gated lesson; lesson
18
- * lifecycle is a separate surface added in T.6.
19
- *
20
- * 2. **Description synthesis is mandatory.** `memory.create` rejects
21
- * empty `description` (T.1.B INVALID_PARAMS -32602). Synthesized
22
- * from first sentence → first 80 chars → ultimate fallback. Lesson
23
- * shape doesn't carry a description field today, so we derive it.
24
- *
25
- * 3. **`include_body: true` on every recall.** memory.search's default
26
- * `body_preview` is truncated to 240 chars (engine serve.rs); without
27
- * this flag RecallHit.lesson.content gets cut mid-sentence.
28
- *
29
- * 4. **Source vocab mapping at the boundary.** Engine speaks
30
- * `'semantic' | 'text' | 'both'`; RagBackend's RecallHit speaks
31
- * `'semantic' | 'lexical' | 'fused'`. The adapter table is the
32
- * single point of translation — DO NOT leak engine vocab past it.
33
- *
34
- * 5. **Engine schema gap.** `memory.create` doesn't preserve tags /
35
- * source / author / createdAt today (T.8 follow-up filed). For v1
36
- * we send `description` + `content` only; lesson metadata round-trips
37
- * via the Lesson defaults applied by `src/functions/rag.ts:122-145`.
38
- *
39
- * 6. **No daemon lifecycle here.** `EngineClient` connects via the T.4
40
- * `acquireOrSpawnEngine()` singleton transparently — zero per-call
41
- * subprocess cost, cross-session shared engine.
42
- *
43
- * Imports from: ../../engine/client.js, ../ollama_client.js, ../types.js.
44
- * Imported by: src/rag/backend_factory.ts.
45
- */
46
- import { EngineClient } from '../../engine/client.js';
47
- import type { RagBackend } from '../types.js';
48
- export interface LoopEngineBackendOpts {
49
- /** Injected client for tests; production uses the singleton-backed default. */
50
- client?: EngineClient;
51
- /** Recall mode. 'hybrid' = engine semantic+text+RRF (default, matches
52
- * libsql-qwen3 quality per T.1.JJ). 'semantic' = vector only. 'text' =
53
- * pure text-match. */
54
- mode?: 'semantic' | 'text' | 'hybrid';
55
- /** Ollama URL for embed() — only used when a rule asks for a raw vector
56
- * via the `embed` primitive. Engine handles embedding internally for
57
- * memory.create + memory.search. */
58
- ollamaUrl?: string;
59
- }
60
- export declare function loopEngineBackend(opts?: LoopEngineBackendOpts): RagBackend;
61
- //# sourceMappingURL=loop_engine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loop_engine.d.ts","sourceRoot":"","sources":["../../../src/rag/backends/loop_engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,EAAgB,YAAY,EAAY,MAAM,wBAAwB,CAAC;AAK9E,OAAO,KAAK,EAAwB,UAAU,EAAa,MAAM,aAAa,CAAC;AAE/E,MAAM,WAAW,qBAAqB;IACpC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;2BAEuB;IACvB,IAAI,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACtC;;yCAEqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,qBAA0B,GAAG,UAAU,CAgF9E"}