@moreih29/nexus-core 0.17.0 → 0.18.2

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 (415) hide show
  1. package/README.md +101 -67
  2. package/dist/cli/sync.d.ts +3 -0
  3. package/dist/cli/sync.d.ts.map +1 -0
  4. package/dist/cli/sync.js +59 -0
  5. package/dist/cli/sync.js.map +1 -0
  6. package/dist/generate/index.d.ts +3 -0
  7. package/dist/generate/index.d.ts.map +1 -0
  8. package/dist/generate/index.js +2 -0
  9. package/dist/generate/index.js.map +1 -0
  10. package/dist/generate/load-data.d.ts +8 -0
  11. package/dist/generate/load-data.d.ts.map +1 -0
  12. package/dist/generate/load-data.js +45 -0
  13. package/dist/generate/load-data.js.map +1 -0
  14. package/dist/generate/load-spec.d.ts +3 -0
  15. package/dist/generate/load-spec.d.ts.map +1 -0
  16. package/dist/generate/load-spec.js +48 -0
  17. package/dist/generate/load-spec.js.map +1 -0
  18. package/dist/generate/macros/expand.d.ts +3 -0
  19. package/dist/generate/macros/expand.d.ts.map +1 -0
  20. package/dist/generate/macros/expand.js +48 -0
  21. package/dist/generate/macros/expand.js.map +1 -0
  22. package/dist/generate/macros/parse.d.ts +4 -0
  23. package/dist/generate/macros/parse.d.ts.map +1 -0
  24. package/dist/generate/macros/parse.js +142 -0
  25. package/dist/generate/macros/parse.js.map +1 -0
  26. package/dist/generate/macros/validate.d.ts +3 -0
  27. package/dist/generate/macros/validate.d.ts.map +1 -0
  28. package/dist/generate/macros/validate.js +23 -0
  29. package/dist/generate/macros/validate.js.map +1 -0
  30. package/dist/generate/renderers/claude.d.ts +3 -0
  31. package/dist/generate/renderers/claude.d.ts.map +1 -0
  32. package/dist/generate/renderers/claude.js +48 -0
  33. package/dist/generate/renderers/claude.js.map +1 -0
  34. package/dist/generate/renderers/codex.d.ts +3 -0
  35. package/dist/generate/renderers/codex.d.ts.map +1 -0
  36. package/dist/generate/renderers/codex.js +79 -0
  37. package/dist/generate/renderers/codex.js.map +1 -0
  38. package/dist/generate/renderers/markdown.d.ts +2 -0
  39. package/dist/generate/renderers/markdown.d.ts.map +1 -0
  40. package/dist/generate/renderers/markdown.js +6 -0
  41. package/dist/generate/renderers/markdown.js.map +1 -0
  42. package/dist/generate/renderers/opencode.d.ts +3 -0
  43. package/dist/generate/renderers/opencode.d.ts.map +1 -0
  44. package/dist/generate/renderers/opencode.js +69 -0
  45. package/dist/generate/renderers/opencode.js.map +1 -0
  46. package/dist/generate/sync.d.ts +4 -0
  47. package/dist/generate/sync.d.ts.map +1 -0
  48. package/dist/generate/sync.js +60 -0
  49. package/dist/generate/sync.js.map +1 -0
  50. package/dist/generate/types.d.ts +74 -0
  51. package/dist/generate/types.d.ts.map +1 -0
  52. package/dist/generate/types.js +2 -0
  53. package/dist/generate/types.js.map +1 -0
  54. package/dist/index.d.ts +4 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +2 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/mcp/definitions/artifact.d.ts +20 -0
  59. package/dist/mcp/definitions/artifact.d.ts.map +1 -0
  60. package/dist/mcp/definitions/artifact.js +14 -0
  61. package/dist/mcp/definitions/artifact.js.map +1 -0
  62. package/dist/mcp/definitions/history.d.ts +20 -0
  63. package/dist/mcp/definitions/history.d.ts.map +1 -0
  64. package/dist/mcp/definitions/history.js +18 -0
  65. package/dist/mcp/definitions/history.js.map +1 -0
  66. package/dist/mcp/definitions/index.d.ts +276 -0
  67. package/dist/mcp/definitions/index.d.ts.map +1 -0
  68. package/dist/mcp/definitions/index.js +16 -0
  69. package/dist/mcp/definitions/index.js.map +1 -0
  70. package/dist/mcp/definitions/plan.d.ts +111 -0
  71. package/dist/mcp/definitions/plan.d.ts.map +1 -0
  72. package/dist/mcp/definitions/plan.js +89 -0
  73. package/dist/mcp/definitions/plan.js.map +1 -0
  74. package/dist/mcp/definitions/task.d.ts +138 -0
  75. package/dist/mcp/definitions/task.d.ts.map +1 -0
  76. package/dist/mcp/definitions/task.js +78 -0
  77. package/dist/mcp/definitions/task.js.map +1 -0
  78. package/dist/mcp/handlers/artifact.d.ts.map +1 -0
  79. package/dist/mcp/handlers/artifact.js +42 -0
  80. package/dist/mcp/handlers/artifact.js.map +1 -0
  81. package/dist/mcp/handlers/history.d.ts.map +1 -0
  82. package/dist/mcp/handlers/history.js +35 -0
  83. package/dist/mcp/handlers/history.js.map +1 -0
  84. package/dist/mcp/handlers/plan.d.ts.map +1 -0
  85. package/dist/mcp/handlers/plan.js +324 -0
  86. package/dist/mcp/handlers/plan.js.map +1 -0
  87. package/dist/mcp/handlers/task.d.ts.map +1 -0
  88. package/dist/mcp/handlers/task.js +216 -0
  89. package/dist/mcp/handlers/task.js.map +1 -0
  90. package/dist/{src/mcp → mcp}/server.d.ts +1 -1
  91. package/dist/mcp/server.d.ts.map +1 -0
  92. package/dist/mcp/server.js +58 -0
  93. package/dist/mcp/server.js.map +1 -0
  94. package/dist/shared/json-store.d.ts.map +1 -0
  95. package/dist/{src/shared → shared}/json-store.js +5 -4
  96. package/dist/shared/json-store.js.map +1 -0
  97. package/dist/shared/mcp-utils.d.ts.map +1 -0
  98. package/dist/shared/mcp-utils.js.map +1 -0
  99. package/dist/{src/shared → shared}/paths.d.ts +0 -6
  100. package/dist/shared/paths.d.ts.map +1 -0
  101. package/dist/shared/paths.js +62 -0
  102. package/dist/shared/paths.js.map +1 -0
  103. package/dist/shared/register-tool.d.ts +20 -0
  104. package/dist/shared/register-tool.d.ts.map +1 -0
  105. package/dist/shared/register-tool.js +15 -0
  106. package/dist/shared/register-tool.js.map +1 -0
  107. package/dist/{src/types → types}/state.d.ts +65 -65
  108. package/dist/types/state.d.ts.map +1 -0
  109. package/dist/{src/types → types}/state.js +1 -1
  110. package/dist/types/state.js.map +1 -0
  111. package/harness/claude/agent-rules.yml +21 -0
  112. package/harness/claude/invocations.yml +11 -0
  113. package/harness/claude/layout.yml +3 -0
  114. package/harness/codex/agent-rules.yml +28 -0
  115. package/harness/codex/invocations.yml +13 -0
  116. package/harness/codex/layout.yml +3 -0
  117. package/harness/opencode/agent-rules.yml +18 -0
  118. package/harness/opencode/invocations.yml +12 -0
  119. package/harness/opencode/layout.yml +3 -0
  120. package/package.json +38 -43
  121. package/{assets → spec}/agents/architect/body.ko.md +92 -84
  122. package/spec/agents/architect/body.md +185 -0
  123. package/spec/agents/designer/body.ko.md +330 -0
  124. package/spec/agents/designer/body.md +330 -0
  125. package/spec/agents/engineer/body.ko.md +166 -0
  126. package/spec/agents/engineer/body.md +166 -0
  127. package/spec/agents/lead/body.ko.md +276 -0
  128. package/spec/agents/lead/body.md +276 -0
  129. package/{assets → spec}/agents/postdoc/body.ko.md +116 -46
  130. package/spec/agents/postdoc/body.md +192 -0
  131. package/{assets → spec}/agents/researcher/body.ko.md +131 -45
  132. package/spec/agents/researcher/body.md +223 -0
  133. package/spec/agents/reviewer/body.ko.md +219 -0
  134. package/spec/agents/reviewer/body.md +219 -0
  135. package/{assets → spec}/agents/strategist/body.ko.md +108 -35
  136. package/spec/agents/strategist/body.md +187 -0
  137. package/spec/agents/tester/body.ko.md +272 -0
  138. package/spec/agents/tester/body.md +272 -0
  139. package/{assets → spec}/agents/writer/body.ko.md +109 -33
  140. package/spec/agents/writer/body.md +198 -0
  141. package/spec/skills/nx-auto-plan/body.ko.md +150 -0
  142. package/spec/skills/nx-auto-plan/body.md +150 -0
  143. package/spec/skills/nx-plan/body.ko.md +159 -0
  144. package/spec/skills/nx-plan/body.md +159 -0
  145. package/spec/skills/nx-run/body.ko.md +132 -0
  146. package/spec/skills/nx-run/body.md +132 -0
  147. package/vocabulary/enums/task-register-state.yml +4 -0
  148. package/vocabulary/invocations.yml +43 -0
  149. package/assets/agents/architect/body.md +0 -177
  150. package/assets/agents/designer/body.ko.md +0 -125
  151. package/assets/agents/designer/body.md +0 -125
  152. package/assets/agents/engineer/body.ko.md +0 -106
  153. package/assets/agents/engineer/body.md +0 -106
  154. package/assets/agents/lead/body.ko.md +0 -70
  155. package/assets/agents/lead/body.md +0 -70
  156. package/assets/agents/postdoc/body.md +0 -122
  157. package/assets/agents/researcher/body.md +0 -137
  158. package/assets/agents/reviewer/body.ko.md +0 -138
  159. package/assets/agents/reviewer/body.md +0 -138
  160. package/assets/agents/strategist/body.md +0 -116
  161. package/assets/agents/tester/body.ko.md +0 -195
  162. package/assets/agents/tester/body.md +0 -195
  163. package/assets/agents/writer/body.md +0 -122
  164. package/assets/capability-matrix.yml +0 -200
  165. package/assets/hooks/agent-bootstrap/handler.test.ts +0 -369
  166. package/assets/hooks/agent-bootstrap/handler.ts +0 -132
  167. package/assets/hooks/agent-bootstrap/meta.yml +0 -10
  168. package/assets/hooks/agent-finalize/handler.test.ts +0 -368
  169. package/assets/hooks/agent-finalize/handler.ts +0 -76
  170. package/assets/hooks/agent-finalize/meta.yml +0 -10
  171. package/assets/hooks/capability-matrix.yml +0 -313
  172. package/assets/hooks/post-tool-telemetry/handler.test.ts +0 -302
  173. package/assets/hooks/post-tool-telemetry/handler.ts +0 -49
  174. package/assets/hooks/post-tool-telemetry/meta.yml +0 -10
  175. package/assets/hooks/prompt-router/handler.test.ts +0 -801
  176. package/assets/hooks/prompt-router/handler.ts +0 -272
  177. package/assets/hooks/prompt-router/meta.yml +0 -11
  178. package/assets/hooks/session-init/handler.test.ts +0 -274
  179. package/assets/hooks/session-init/handler.ts +0 -31
  180. package/assets/hooks/session-init/meta.yml +0 -9
  181. package/assets/lsp-servers.json +0 -55
  182. package/assets/schema/lsp-servers.schema.json +0 -67
  183. package/assets/skills/nx-init/body.ko.md +0 -197
  184. package/assets/skills/nx-init/body.md +0 -197
  185. package/assets/skills/nx-plan/body.ko.md +0 -361
  186. package/assets/skills/nx-plan/body.md +0 -361
  187. package/assets/skills/nx-run/body.ko.md +0 -161
  188. package/assets/skills/nx-run/body.md +0 -160
  189. package/assets/skills/nx-sync/body.ko.md +0 -92
  190. package/assets/skills/nx-sync/body.md +0 -92
  191. package/assets/tools/tool-name-map.yml +0 -353
  192. package/dist/assets/hooks/agent-bootstrap/handler.d.ts +0 -4
  193. package/dist/assets/hooks/agent-bootstrap/handler.d.ts.map +0 -1
  194. package/dist/assets/hooks/agent-bootstrap/handler.js +0 -114
  195. package/dist/assets/hooks/agent-bootstrap/handler.js.map +0 -1
  196. package/dist/assets/hooks/agent-finalize/handler.d.ts +0 -4
  197. package/dist/assets/hooks/agent-finalize/handler.d.ts.map +0 -1
  198. package/dist/assets/hooks/agent-finalize/handler.js +0 -63
  199. package/dist/assets/hooks/agent-finalize/handler.js.map +0 -1
  200. package/dist/assets/hooks/post-tool-telemetry/handler.d.ts +0 -4
  201. package/dist/assets/hooks/post-tool-telemetry/handler.d.ts.map +0 -1
  202. package/dist/assets/hooks/post-tool-telemetry/handler.js +0 -40
  203. package/dist/assets/hooks/post-tool-telemetry/handler.js.map +0 -1
  204. package/dist/assets/hooks/prompt-router/handler.d.ts +0 -4
  205. package/dist/assets/hooks/prompt-router/handler.d.ts.map +0 -1
  206. package/dist/assets/hooks/prompt-router/handler.js +0 -214
  207. package/dist/assets/hooks/prompt-router/handler.js.map +0 -1
  208. package/dist/assets/hooks/session-init/handler.d.ts +0 -4
  209. package/dist/assets/hooks/session-init/handler.d.ts.map +0 -1
  210. package/dist/assets/hooks/session-init/handler.js +0 -22
  211. package/dist/assets/hooks/session-init/handler.js.map +0 -1
  212. package/dist/claude/.claude-plugin/marketplace.json +0 -75
  213. package/dist/claude/.claude-plugin/plugin.json +0 -67
  214. package/dist/claude/agents/architect.md +0 -172
  215. package/dist/claude/agents/designer.md +0 -120
  216. package/dist/claude/agents/engineer.md +0 -98
  217. package/dist/claude/agents/lead.md +0 -59
  218. package/dist/claude/agents/postdoc.md +0 -117
  219. package/dist/claude/agents/researcher.md +0 -132
  220. package/dist/claude/agents/reviewer.md +0 -133
  221. package/dist/claude/agents/strategist.md +0 -111
  222. package/dist/claude/agents/tester.md +0 -190
  223. package/dist/claude/agents/writer.md +0 -114
  224. package/dist/claude/dist/hooks/agent-bootstrap.js +0 -238
  225. package/dist/claude/dist/hooks/agent-finalize.js +0 -180
  226. package/dist/claude/dist/hooks/post-tool-telemetry.js +0 -71
  227. package/dist/claude/dist/hooks/prompt-router.js +0 -7336
  228. package/dist/claude/dist/hooks/session-init.js +0 -50
  229. package/dist/claude/hooks/hooks.json +0 -64
  230. package/dist/claude/settings.json +0 -3
  231. package/dist/claude/skills/nx-init/SKILL.md +0 -189
  232. package/dist/claude/skills/nx-plan/SKILL.md +0 -353
  233. package/dist/claude/skills/nx-run/SKILL.md +0 -154
  234. package/dist/claude/skills/nx-sync/SKILL.md +0 -87
  235. package/dist/codex/agents/architect.toml +0 -175
  236. package/dist/codex/agents/designer.toml +0 -123
  237. package/dist/codex/agents/engineer.toml +0 -105
  238. package/dist/codex/agents/lead.toml +0 -64
  239. package/dist/codex/agents/postdoc.toml +0 -120
  240. package/dist/codex/agents/researcher.toml +0 -136
  241. package/dist/codex/agents/reviewer.toml +0 -137
  242. package/dist/codex/agents/strategist.toml +0 -114
  243. package/dist/codex/agents/tester.toml +0 -194
  244. package/dist/codex/agents/writer.toml +0 -121
  245. package/dist/codex/dist/hooks/agent-bootstrap.js +0 -238
  246. package/dist/codex/dist/hooks/agent-finalize.js +0 -180
  247. package/dist/codex/dist/hooks/prompt-router.js +0 -7336
  248. package/dist/codex/dist/hooks/session-init.js +0 -50
  249. package/dist/codex/hooks/hooks.json +0 -28
  250. package/dist/codex/install/AGENTS.fragment.md +0 -60
  251. package/dist/codex/install/config.fragment.toml +0 -5
  252. package/dist/codex/install/install.sh +0 -60
  253. package/dist/codex/package.json +0 -20
  254. package/dist/codex/plugin/.codex-plugin/plugin.json +0 -57
  255. package/dist/codex/plugin/skills/nx-init/SKILL.md +0 -189
  256. package/dist/codex/plugin/skills/nx-plan/SKILL.md +0 -353
  257. package/dist/codex/plugin/skills/nx-run/SKILL.md +0 -154
  258. package/dist/codex/plugin/skills/nx-sync/SKILL.md +0 -87
  259. package/dist/codex/prompts/architect.md +0 -166
  260. package/dist/codex/prompts/designer.md +0 -114
  261. package/dist/codex/prompts/engineer.md +0 -97
  262. package/dist/codex/prompts/lead.md +0 -60
  263. package/dist/codex/prompts/postdoc.md +0 -111
  264. package/dist/codex/prompts/researcher.md +0 -127
  265. package/dist/codex/prompts/reviewer.md +0 -128
  266. package/dist/codex/prompts/strategist.md +0 -105
  267. package/dist/codex/prompts/tester.md +0 -185
  268. package/dist/codex/prompts/writer.md +0 -113
  269. package/dist/hooks/agent-bootstrap.js +0 -238
  270. package/dist/hooks/agent-finalize.js +0 -180
  271. package/dist/hooks/post-tool-telemetry.js +0 -71
  272. package/dist/hooks/prompt-router.js +0 -7336
  273. package/dist/hooks/session-init.js +0 -50
  274. package/dist/manifests/claude-hooks.json +0 -64
  275. package/dist/manifests/codex-hooks.json +0 -28
  276. package/dist/manifests/opencode-manifest.json +0 -54
  277. package/dist/manifests/portability-report.json +0 -75
  278. package/dist/opencode/.opencode/skills/nx-init/SKILL.md +0 -189
  279. package/dist/opencode/.opencode/skills/nx-plan/SKILL.md +0 -353
  280. package/dist/opencode/.opencode/skills/nx-run/SKILL.md +0 -154
  281. package/dist/opencode/.opencode/skills/nx-sync/SKILL.md +0 -87
  282. package/dist/opencode/package.json +0 -23
  283. package/dist/opencode/src/agents/architect.ts +0 -176
  284. package/dist/opencode/src/agents/designer.ts +0 -124
  285. package/dist/opencode/src/agents/engineer.ts +0 -105
  286. package/dist/opencode/src/agents/lead.ts +0 -66
  287. package/dist/opencode/src/agents/postdoc.ts +0 -121
  288. package/dist/opencode/src/agents/researcher.ts +0 -136
  289. package/dist/opencode/src/agents/reviewer.ts +0 -137
  290. package/dist/opencode/src/agents/strategist.ts +0 -115
  291. package/dist/opencode/src/agents/tester.ts +0 -194
  292. package/dist/opencode/src/agents/writer.ts +0 -121
  293. package/dist/opencode/src/index.ts +0 -25
  294. package/dist/opencode/src/plugin.ts +0 -6
  295. package/dist/scripts/build-agents.d.ts +0 -170
  296. package/dist/scripts/build-agents.d.ts.map +0 -1
  297. package/dist/scripts/build-agents.js +0 -907
  298. package/dist/scripts/build-agents.js.map +0 -1
  299. package/dist/scripts/build-hooks.d.ts +0 -57
  300. package/dist/scripts/build-hooks.d.ts.map +0 -1
  301. package/dist/scripts/build-hooks.js +0 -562
  302. package/dist/scripts/build-hooks.js.map +0 -1
  303. package/dist/scripts/cli.d.ts +0 -54
  304. package/dist/scripts/cli.d.ts.map +0 -1
  305. package/dist/scripts/cli.js +0 -504
  306. package/dist/scripts/cli.js.map +0 -1
  307. package/dist/scripts/smoke/smoke-claude.d.ts +0 -2
  308. package/dist/scripts/smoke/smoke-claude.d.ts.map +0 -1
  309. package/dist/scripts/smoke/smoke-claude.js +0 -58
  310. package/dist/scripts/smoke/smoke-claude.js.map +0 -1
  311. package/dist/scripts/smoke/smoke-codex.d.ts +0 -2
  312. package/dist/scripts/smoke/smoke-codex.d.ts.map +0 -1
  313. package/dist/scripts/smoke/smoke-codex.js +0 -50
  314. package/dist/scripts/smoke/smoke-codex.js.map +0 -1
  315. package/dist/scripts/smoke/smoke-consumer.d.ts +0 -2
  316. package/dist/scripts/smoke/smoke-consumer.d.ts.map +0 -1
  317. package/dist/scripts/smoke/smoke-consumer.js +0 -230
  318. package/dist/scripts/smoke/smoke-consumer.js.map +0 -1
  319. package/dist/scripts/smoke/smoke-opencode.d.ts +0 -2
  320. package/dist/scripts/smoke/smoke-opencode.d.ts.map +0 -1
  321. package/dist/scripts/smoke/smoke-opencode.js +0 -99
  322. package/dist/scripts/smoke/smoke-opencode.js.map +0 -1
  323. package/dist/src/hooks/opencode-mount.d.ts +0 -35
  324. package/dist/src/hooks/opencode-mount.d.ts.map +0 -1
  325. package/dist/src/hooks/opencode-mount.js +0 -352
  326. package/dist/src/hooks/opencode-mount.js.map +0 -1
  327. package/dist/src/hooks/runtime.d.ts +0 -37
  328. package/dist/src/hooks/runtime.d.ts.map +0 -1
  329. package/dist/src/hooks/runtime.js +0 -274
  330. package/dist/src/hooks/runtime.js.map +0 -1
  331. package/dist/src/hooks/types.d.ts +0 -196
  332. package/dist/src/hooks/types.d.ts.map +0 -1
  333. package/dist/src/hooks/types.js +0 -85
  334. package/dist/src/hooks/types.js.map +0 -1
  335. package/dist/src/lsp/cache.d.ts +0 -9
  336. package/dist/src/lsp/cache.d.ts.map +0 -1
  337. package/dist/src/lsp/cache.js +0 -216
  338. package/dist/src/lsp/cache.js.map +0 -1
  339. package/dist/src/lsp/client.d.ts +0 -24
  340. package/dist/src/lsp/client.d.ts.map +0 -1
  341. package/dist/src/lsp/client.js +0 -166
  342. package/dist/src/lsp/client.js.map +0 -1
  343. package/dist/src/lsp/detect.d.ts +0 -77
  344. package/dist/src/lsp/detect.d.ts.map +0 -1
  345. package/dist/src/lsp/detect.js +0 -116
  346. package/dist/src/lsp/detect.js.map +0 -1
  347. package/dist/src/mcp/server.d.ts.map +0 -1
  348. package/dist/src/mcp/server.js +0 -34
  349. package/dist/src/mcp/server.js.map +0 -1
  350. package/dist/src/mcp/tools/artifact.d.ts.map +0 -1
  351. package/dist/src/mcp/tools/artifact.js +0 -36
  352. package/dist/src/mcp/tools/artifact.js.map +0 -1
  353. package/dist/src/mcp/tools/history.d.ts.map +0 -1
  354. package/dist/src/mcp/tools/history.js +0 -29
  355. package/dist/src/mcp/tools/history.js.map +0 -1
  356. package/dist/src/mcp/tools/lsp.d.ts +0 -13
  357. package/dist/src/mcp/tools/lsp.d.ts.map +0 -1
  358. package/dist/src/mcp/tools/lsp.js +0 -225
  359. package/dist/src/mcp/tools/lsp.js.map +0 -1
  360. package/dist/src/mcp/tools/plan.d.ts.map +0 -1
  361. package/dist/src/mcp/tools/plan.js +0 -317
  362. package/dist/src/mcp/tools/plan.js.map +0 -1
  363. package/dist/src/mcp/tools/task.d.ts.map +0 -1
  364. package/dist/src/mcp/tools/task.js +0 -252
  365. package/dist/src/mcp/tools/task.js.map +0 -1
  366. package/dist/src/shared/invocations.d.ts +0 -74
  367. package/dist/src/shared/invocations.d.ts.map +0 -1
  368. package/dist/src/shared/invocations.js +0 -247
  369. package/dist/src/shared/invocations.js.map +0 -1
  370. package/dist/src/shared/json-store.d.ts.map +0 -1
  371. package/dist/src/shared/json-store.js.map +0 -1
  372. package/dist/src/shared/mcp-utils.d.ts.map +0 -1
  373. package/dist/src/shared/mcp-utils.js.map +0 -1
  374. package/dist/src/shared/package-root.d.ts +0 -6
  375. package/dist/src/shared/package-root.d.ts.map +0 -1
  376. package/dist/src/shared/package-root.js +0 -19
  377. package/dist/src/shared/package-root.js.map +0 -1
  378. package/dist/src/shared/paths.d.ts.map +0 -1
  379. package/dist/src/shared/paths.js +0 -117
  380. package/dist/src/shared/paths.js.map +0 -1
  381. package/dist/src/shared/tool-log.d.ts +0 -8
  382. package/dist/src/shared/tool-log.d.ts.map +0 -1
  383. package/dist/src/shared/tool-log.js +0 -22
  384. package/dist/src/shared/tool-log.js.map +0 -1
  385. package/dist/src/types/agent-config.d.ts +0 -22
  386. package/dist/src/types/agent-config.d.ts.map +0 -1
  387. package/dist/src/types/agent-config.js +0 -2
  388. package/dist/src/types/agent-config.js.map +0 -1
  389. package/dist/src/types/index.d.ts +0 -2
  390. package/dist/src/types/index.d.ts.map +0 -1
  391. package/dist/src/types/index.js +0 -2
  392. package/dist/src/types/index.js.map +0 -1
  393. package/dist/src/types/state.d.ts.map +0 -1
  394. package/dist/src/types/state.js.map +0 -1
  395. package/docs/consuming/codex-lead-merge.md +0 -106
  396. package/docs/contract/harness-io.md +0 -333
  397. package/docs/plugin-guide.md +0 -355
  398. package/docs/plugin-template/claude/.github/workflows/build.yml +0 -60
  399. package/docs/plugin-template/claude/README.md +0 -110
  400. package/docs/plugin-template/claude/package.json +0 -16
  401. package/docs/plugin-template/codex/.github/workflows/build.yml +0 -51
  402. package/docs/plugin-template/codex/README.md +0 -147
  403. package/docs/plugin-template/codex/install/install.sh +0 -60
  404. package/docs/plugin-template/codex/package.json +0 -17
  405. package/docs/plugin-template/opencode/.github/workflows/build.yml +0 -61
  406. package/docs/plugin-template/opencode/README.md +0 -121
  407. package/docs/plugin-template/opencode/package.json +0 -25
  408. package/docs/plugin-template/opencode/src/plugin.ts +0 -6
  409. /package/dist/{src/mcp/tools → mcp/handlers}/artifact.d.ts +0 -0
  410. /package/dist/{src/mcp/tools → mcp/handlers}/history.d.ts +0 -0
  411. /package/dist/{src/mcp/tools → mcp/handlers}/plan.d.ts +0 -0
  412. /package/dist/{src/mcp/tools → mcp/handlers}/task.d.ts +0 -0
  413. /package/dist/{src/shared → shared}/json-store.d.ts +0 -0
  414. /package/dist/{src/shared → shared}/mcp-utils.d.ts +0 -0
  415. /package/dist/{src/shared → shared}/mcp-utils.js +0 -0
@@ -1,272 +0,0 @@
1
- import type { HookHandler, NexusHookOutput } from "../../../src/hooks/types.js";
2
- import { existsSync, readFileSync, readdirSync } from "node:fs";
3
- import { join, resolve, dirname } from "node:path";
4
- import { parse as parseYaml } from "yaml";
5
- import {
6
- expandInvocations,
7
- type InvocationsMap,
8
- type Harness,
9
- } from "../../../src/shared/invocations.js";
10
-
11
- // Tag priority: specific variants first (m:gc > m, rule:name > rule, plan:auto > plan, init:reset > init)
12
- const TAG_PATTERNS: Array<{ name: string; regex: RegExp }> = [
13
- { name: "plan:auto", regex: /\[plan:auto\]/ },
14
- { name: "plan", regex: /\[plan\](?!\w)/ },
15
- { name: "run", regex: /\[run\](?!\w)/ },
16
- { name: "d", regex: /\[d\](?!\w)/ },
17
- { name: "m:gc", regex: /\[m:gc\]/ },
18
- { name: "m", regex: /\[m\](?!\w)/ },
19
- { name: "rule:name", regex: /\[rule:([a-zA-Z0-9_-]+)\]/ },
20
- { name: "rule", regex: /\[rule\](?!\w)/ },
21
- { name: "sync", regex: /\[sync\](?!\w)/ },
22
- { name: "init:reset", regex: /\[init:reset\]/ },
23
- { name: "init", regex: /\[init\](?!\w)/ },
24
- ];
25
-
26
- // ---------------------------------------------------------------------------
27
- // Invocations loader — cached per process
28
- // ---------------------------------------------------------------------------
29
-
30
- let _invocationsCache: InvocationsMap | null = null;
31
-
32
- function loadInvocations(): InvocationsMap {
33
- if (_invocationsCache) return _invocationsCache;
34
-
35
- // In the compiled consumer bundle, assets/ is absent — use data inlined at build time.
36
- const inlined = (globalThis as unknown as { __NEXUS_INLINE_INVOCATIONS__?: InvocationsMap }).__NEXUS_INLINE_INVOCATIONS__;
37
- if (inlined) {
38
- _invocationsCache = inlined;
39
- return inlined;
40
- }
41
-
42
- const selfDir = new URL(".", import.meta.url).pathname;
43
- // Walk up from handler directory to find assets/tools/tool-name-map.yml
44
- let dir = selfDir;
45
- while (dir !== "/") {
46
- const candidate = resolve(dir, "assets/tools/tool-name-map.yml");
47
- if (existsSync(candidate)) {
48
- const raw = readFileSync(candidate, "utf-8");
49
- const parsed = parseYaml(raw) as { invocations?: InvocationsMap };
50
- if (!parsed.invocations) {
51
- throw new Error("[prompt-router] tool-name-map.yml missing 'invocations' section");
52
- }
53
- _invocationsCache = parsed.invocations;
54
- return _invocationsCache;
55
- }
56
- const parent = dirname(dir);
57
- if (parent === dir) break;
58
- dir = parent;
59
- }
60
-
61
- throw new Error(`[prompt-router] Cannot locate assets/tools/tool-name-map.yml from ${selfDir}`);
62
- }
63
-
64
- // ---------------------------------------------------------------------------
65
- // Harness resolution
66
- // ---------------------------------------------------------------------------
67
-
68
- function resolveHarness(): Harness {
69
- const h = process.env["NEXUS_HARNESS"];
70
- if (h === "claude" || h === "opencode" || h === "codex") return h;
71
- if (h) {
72
- process.stderr.write(
73
- `[prompt-router] Unknown NEXUS_HARNESS="${h}", falling back to "claude"\n`
74
- );
75
- }
76
- return "claude";
77
- }
78
-
79
- // ---------------------------------------------------------------------------
80
- // Invocation expansion helper
81
- // ---------------------------------------------------------------------------
82
-
83
- function expand(template: string, harness: Harness): string {
84
- return expandInvocations(template, harness, loadInvocations());
85
- }
86
-
87
- // ---------------------------------------------------------------------------
88
- // Rule target loader
89
- // ---------------------------------------------------------------------------
90
-
91
- function loadValidRuleTargets(cwd: string): string[] {
92
- // In the compiled consumer bundle, cwd/assets/ is absent — use data inlined at build time.
93
- const inlined = (globalThis as unknown as { __NEXUS_INLINE_RULE_TARGETS__?: string[] }).__NEXUS_INLINE_RULE_TARGETS__;
94
- if (inlined && inlined.length > 0) return inlined;
95
-
96
- const targets: string[] = [];
97
- for (const dir of ["assets/agents", "assets/skills"]) {
98
- const absDir = join(cwd, dir);
99
- if (!existsSync(absDir)) continue;
100
- for (const entry of readdirSync(absDir, { withFileTypes: true })) {
101
- if (entry.isDirectory()) targets.push(entry.name);
102
- }
103
- }
104
- return targets;
105
- }
106
-
107
- // ---------------------------------------------------------------------------
108
- // Handler
109
- // ---------------------------------------------------------------------------
110
-
111
- const handler: HookHandler = async (input): Promise<NexusHookOutput | void> => {
112
- if (input.hook_event_name !== "UserPromptSubmit") return;
113
-
114
- const prompt = input.prompt;
115
- const detected: Array<{ name: string; arg?: string }> = [];
116
-
117
- // Detect all tags — use seen Set keyed on base tag name to prevent duplicates
118
- // (e.g. plan:auto and plan share base "plan"; whichever appears first wins)
119
- const seen = new Set<string>();
120
- for (const { name, regex } of TAG_PATTERNS) {
121
- const m = regex.exec(prompt);
122
- if (!m) continue;
123
- const base = name.split(":")[0];
124
- if (seen.has(base)) continue;
125
- seen.add(base);
126
- detected.push({ name, arg: m[1] });
127
- }
128
-
129
- const sessionDir = join(input.cwd, ".nexus/state", input.session_id);
130
- const planPath = join(sessionDir, "plan.json");
131
- const tasksPath = join(sessionDir, "tasks.json");
132
- const hasPlan = existsSync(planPath);
133
- const hasTasks = existsSync(tasksPath);
134
-
135
- const harness = resolveHarness();
136
-
137
- const notices: string[] = [];
138
- let decision: "block" | undefined;
139
- let block_reason: string | undefined;
140
-
141
- for (const tag of detected) {
142
- switch (tag.name) {
143
- case "plan":
144
- notices.push(
145
- `<system-notice>[plan] tag detected. ${expand('{{skill_activation skill="nx-plan"}}', harness)} for structured planning.</system-notice>`
146
- );
147
- break;
148
-
149
- case "plan:auto":
150
- notices.push(
151
- `<system-notice>[plan:auto] tag detected. ${expand('{{skill_activation skill="nx-plan" mode="auto"}}', harness)} for structured planning.</system-notice>`
152
- );
153
- break;
154
-
155
- case "run":
156
- if (!hasTasks) {
157
- notices.push(
158
- `<system-notice>[run] tag detected but no tasks.json. ${expand('{{skill_activation skill="nx-plan"}}', harness)} with args "auto" first to generate tasks, then run.</system-notice>`
159
- );
160
- } else {
161
- notices.push(
162
- `<system-notice>[run] tag detected. ${expand('{{skill_activation skill="nx-run"}}', harness)} to execute tasks.</system-notice>`
163
- );
164
- }
165
- break;
166
-
167
- case "d":
168
- if (!hasPlan) {
169
- decision = "block";
170
- block_reason =
171
- `[d] tag requires an active plan session. ${expand('{{skill_activation skill="nx-plan"}}', harness)} first.`;
172
- } else {
173
- notices.push(
174
- `<system-notice>[d] tag detected. Record decision via \`nx_plan_decide(issue_id, summary)\` MCP tool.</system-notice>`
175
- );
176
- }
177
- break;
178
-
179
- case "m":
180
- notices.push(
181
- `<system-notice>[m] tag detected. Save a memory note to \`.nexus/memory/<prefix>-<name>.md\`. Prefix: empirical-, external-, or pattern- (see architecture.md §2-1).</system-notice>`
182
- );
183
- break;
184
-
185
- case "m:gc":
186
- notices.push(
187
- `<system-notice>[m:gc] tag detected. Review \`.nexus/memory/\` for stale or duplicate entries and consolidate.</system-notice>`
188
- );
189
- break;
190
-
191
- case "rule": {
192
- const valid = loadValidRuleTargets(input.cwd);
193
- notices.push(
194
- `<system-notice>[rule] tag detected. Determine target from intent. Valid targets: ${valid.join(", ")}. Update \`.nexus/rules/<target>.md\`.</system-notice>`
195
- );
196
- break;
197
- }
198
-
199
- case "rule:name": {
200
- const valid = loadValidRuleTargets(input.cwd);
201
- const name = tag.arg ?? "";
202
- if (!valid.includes(name)) {
203
- decision = "block";
204
- block_reason = `[rule:${name}] invalid — must be one of: ${valid.join(", ")}`;
205
- } else {
206
- notices.push(
207
- `<system-notice>[rule:${name}] tag detected. Update \`.nexus/rules/${name}.md\` with user's directive.</system-notice>`
208
- );
209
- }
210
- break;
211
- }
212
-
213
- case "sync":
214
- notices.push(
215
- `<system-notice>[sync] tag detected. ${expand('{{skill_activation skill="nx-sync"}}', harness)} to synchronize \`.nexus/context/\`.</system-notice>`
216
- );
217
- break;
218
-
219
- case "init":
220
- notices.push(
221
- `<system-notice>[init] tag detected. ${expand('{{skill_activation skill="nx-init"}}', harness)} for project onboarding.</system-notice>`
222
- );
223
- break;
224
-
225
- case "init:reset":
226
- notices.push(
227
- `<system-notice>[init:reset] tag detected. ${expand('{{skill_activation skill="nx-init" mode="reset"}}', harness)} for full re-initialization.</system-notice>`
228
- );
229
- break;
230
- }
231
- }
232
-
233
- // No tags detected + active state → emit state notice
234
- if (detected.length === 0) {
235
- if (hasPlan) {
236
- try {
237
- const plan = JSON.parse(readFileSync(planPath, "utf-8")) as {
238
- topic?: string;
239
- issues?: Array<{ status: string }>;
240
- };
241
- const pending = plan.issues?.filter((i) => i.status === "pending").length ?? 0;
242
- notices.push(
243
- `<system-notice>Active plan session: "${plan.topic ?? "(unknown)"}", ${pending} issues pending.</system-notice>`
244
- );
245
- } catch {
246
- // Malformed plan.json — skip notice
247
- }
248
- } else if (hasTasks) {
249
- try {
250
- const tasks = JSON.parse(readFileSync(tasksPath, "utf-8")) as {
251
- tasks?: Array<{ status: string }>;
252
- };
253
- const pending = tasks.tasks?.filter((t) => t.status !== "completed").length ?? 0;
254
- if (pending > 0) {
255
- notices.push(
256
- `<system-notice>Active run session: ${pending} tasks remaining in tasks.json.</system-notice>`
257
- );
258
- }
259
- } catch {
260
- // Malformed tasks.json — skip notice
261
- }
262
- }
263
- }
264
-
265
- if (decision === "block") {
266
- return { decision, block_reason };
267
- }
268
- if (notices.length === 0) return;
269
- return { additional_context: notices.join("\n\n") };
270
- };
271
-
272
- export default handler;
@@ -1,11 +0,0 @@
1
- name: prompt-router
2
- description: Detect nexus tags, inject state notices and skill invocation guidance
3
- events: [UserPromptSubmit]
4
- matcher: "*"
5
- timeout: 10
6
- fallback: warn
7
- priority: 0
8
- requires_capabilities:
9
- - event.user_prompt_submit
10
- - output.additional_context.user_prompt
11
- - output.decision_block
@@ -1,274 +0,0 @@
1
- import { test, expect, describe, beforeEach, afterEach } from "bun:test";
2
- import * as fs from "node:fs";
3
- import * as os from "node:os";
4
- import * as path from "node:path";
5
- import * as crypto from "node:crypto";
6
- import handler from "./handler.ts";
7
-
8
- // ---------------------------------------------------------------------------
9
- // Helper
10
- // ---------------------------------------------------------------------------
11
-
12
- function makeTmpDir(): string {
13
- return fs.mkdtempSync(
14
- path.join(os.tmpdir(), `nexus-session-init-${crypto.randomUUID()}-`)
15
- );
16
- }
17
-
18
- function sessionDir(cwd: string, sid: string): string {
19
- return path.join(cwd, ".nexus/state", sid);
20
- }
21
-
22
- // ---------------------------------------------------------------------------
23
- // Scenario 1: New session_id (valid) → directory + files created
24
- // ---------------------------------------------------------------------------
25
-
26
- describe("scenario 1 — new session_id creates state files", () => {
27
- let cwd: string;
28
-
29
- beforeEach(() => {
30
- cwd = makeTmpDir();
31
- });
32
-
33
- afterEach(() => {
34
- fs.rmSync(cwd, { recursive: true, force: true });
35
- });
36
-
37
- test("creates .nexus/state/sessions/<sid>/ directory", async () => {
38
- const sid = crypto.randomUUID();
39
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
40
- expect(fs.existsSync(sessionDir(cwd, sid))).toBe(true);
41
- expect(fs.statSync(sessionDir(cwd, sid)).isDirectory()).toBe(true);
42
- });
43
-
44
- test("creates agent-tracker.json with content '[]'", async () => {
45
- const sid = crypto.randomUUID();
46
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
47
- const filePath = path.join(sessionDir(cwd, sid), "agent-tracker.json");
48
- expect(fs.existsSync(filePath)).toBe(true);
49
- expect(fs.readFileSync(filePath, "utf8")).toBe("[]");
50
- });
51
-
52
- test("creates tool-log.jsonl as empty file", async () => {
53
- const sid = crypto.randomUUID();
54
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
55
- const filePath = path.join(sessionDir(cwd, sid), "tool-log.jsonl");
56
- expect(fs.existsSync(filePath)).toBe(true);
57
- expect(fs.readFileSync(filePath, "utf8")).toBe("");
58
- });
59
- });
60
-
61
- // ---------------------------------------------------------------------------
62
- // Scenario 2: Existing session_id re-invoked → files overwritten (reset policy)
63
- // ---------------------------------------------------------------------------
64
-
65
- describe("scenario 2 — existing session_id re-initialises (overwrite)", () => {
66
- let cwd: string;
67
-
68
- beforeEach(() => {
69
- cwd = makeTmpDir();
70
- });
71
-
72
- afterEach(() => {
73
- fs.rmSync(cwd, { recursive: true, force: true });
74
- });
75
-
76
- test("overwrites agent-tracker.json even when it had prior content", async () => {
77
- const sid = crypto.randomUUID();
78
- // First call
79
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
80
- // Simulate prior state
81
- const trackerPath = path.join(sessionDir(cwd, sid), "agent-tracker.json");
82
- fs.writeFileSync(trackerPath, '[{"id":"agent-1"}]');
83
- // Second call — must reset
84
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
85
- expect(fs.readFileSync(trackerPath, "utf8")).toBe("[]");
86
- });
87
-
88
- test("overwrites tool-log.jsonl even when it had prior content", async () => {
89
- const sid = crypto.randomUUID();
90
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
91
- const logPath = path.join(sessionDir(cwd, sid), "tool-log.jsonl");
92
- fs.writeFileSync(logPath, '{"tool":"Bash","ts":"2026-01-01T00:00:00Z"}\n');
93
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
94
- expect(fs.readFileSync(logPath, "utf8")).toBe("");
95
- });
96
- });
97
-
98
- // ---------------------------------------------------------------------------
99
- // Scenario 3: Path traversal — session_id="../etc/passwd"
100
- // ---------------------------------------------------------------------------
101
-
102
- describe("scenario 3 — path traversal is prevented", () => {
103
- let cwd: string;
104
-
105
- beforeEach(() => {
106
- cwd = makeTmpDir();
107
- });
108
-
109
- afterEach(() => {
110
- fs.rmSync(cwd, { recursive: true, force: true });
111
- });
112
-
113
- test("does not write to the real /etc/passwd (mtime unchanged)", async () => {
114
- // Guard: confirm /etc/passwd exists so the test is meaningful
115
- expect(fs.existsSync("/etc/passwd")).toBe(true);
116
- const before = fs.statSync("/etc/passwd").mtimeMs;
117
- await handler({
118
- hook_event_name: "SessionStart",
119
- session_id: "../etc/passwd",
120
- cwd,
121
- });
122
- const after = fs.statSync("/etc/passwd").mtimeMs;
123
- expect(after).toBe(before);
124
- });
125
-
126
- test("any created path is contained within cwd", async () => {
127
- await handler({
128
- hook_event_name: "SessionStart",
129
- session_id: "../etc/passwd",
130
- cwd,
131
- });
132
- // Walk everything created and assert it all lives inside cwd
133
- const sessionsRoot = path.join(cwd, ".nexus/state");
134
- if (fs.existsSync(sessionsRoot)) {
135
- const entries = fs.readdirSync(sessionsRoot, { recursive: true, encoding: "utf8" }) as string[];
136
- for (const entry of entries) {
137
- const abs = path.resolve(sessionsRoot, entry);
138
- expect(abs.startsWith(cwd)).toBe(true);
139
- }
140
- }
141
- });
142
-
143
- test("basename extraction: if something is created it is named 'passwd' inside sessions", async () => {
144
- await handler({
145
- hook_event_name: "SessionStart",
146
- session_id: "../etc/passwd",
147
- cwd,
148
- });
149
- // basename('../etc/passwd') === 'passwd'
150
- // Handler must either create state/passwd (safe) or nothing.
151
- // It must NOT create state/../etc/passwd (which resolves to .nexus/etc/passwd — still inside cwd but wrong semantic).
152
- // The only acceptable directory name is 'passwd' directly under state.
153
- const sessionsRoot = path.join(cwd, ".nexus/state");
154
- if (fs.existsSync(sessionsRoot)) {
155
- const children = fs.readdirSync(sessionsRoot);
156
- // Each direct child must be a non-traversal name
157
- for (const child of children) {
158
- expect(child).not.toContain("..");
159
- expect(child).not.toContain("/");
160
- }
161
- }
162
- });
163
-
164
- test("session_id with embedded slash is rejected or sanitised — no nested subdirs under sessions", async () => {
165
- const sid = "foo/bar";
166
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
167
- // If handler created something it must not be a nested foo/bar under state.
168
- // Acceptable: nothing, or state/bar (basename). Not acceptable: state/foo/bar.
169
- const fooInsideSessions = path.join(cwd, ".nexus/state/foo");
170
- if (fs.existsSync(fooInsideSessions)) {
171
- // foo exists — bar must NOT be a subdirectory of it (that would be nested traversal)
172
- expect(fs.existsSync(path.join(fooInsideSessions, "bar"))).toBe(false);
173
- }
174
- });
175
- });
176
-
177
- // ---------------------------------------------------------------------------
178
- // Scenario 4: plan.json, tasks.json, memory-access.jsonl are not touched
179
- // ---------------------------------------------------------------------------
180
-
181
- describe("scenario 4 — project-level state files are not modified", () => {
182
- let cwd: string;
183
-
184
- beforeEach(() => {
185
- cwd = makeTmpDir();
186
- // Seed pre-existing project-level state files
187
- const stateDir = path.join(cwd, ".nexus/state");
188
- fs.mkdirSync(stateDir, { recursive: true });
189
- fs.writeFileSync(path.join(stateDir, "plan.json"), '{"version":1}');
190
- fs.writeFileSync(path.join(stateDir, "tasks.json"), '{"tasks":[]}');
191
- fs.writeFileSync(path.join(stateDir, "memory-access.jsonl"), "entry1\n");
192
- });
193
-
194
- afterEach(() => {
195
- fs.rmSync(cwd, { recursive: true, force: true });
196
- });
197
-
198
- test("plan.json content is unchanged after handler runs", async () => {
199
- const sid = crypto.randomUUID();
200
- const planPath = path.join(cwd, ".nexus/state/plan.json");
201
- const before = fs.readFileSync(planPath, "utf8");
202
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
203
- expect(fs.readFileSync(planPath, "utf8")).toBe(before);
204
- });
205
-
206
- test("tasks.json content is unchanged after handler runs", async () => {
207
- const sid = crypto.randomUUID();
208
- const tasksPath = path.join(cwd, ".nexus/state/tasks.json");
209
- const before = fs.readFileSync(tasksPath, "utf8");
210
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
211
- expect(fs.readFileSync(tasksPath, "utf8")).toBe(before);
212
- });
213
-
214
- test("memory-access.jsonl content is unchanged after handler runs", async () => {
215
- const sid = crypto.randomUUID();
216
- const memPath = path.join(cwd, ".nexus/state/memory-access.jsonl");
217
- const before = fs.readFileSync(memPath, "utf8");
218
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
219
- expect(fs.readFileSync(memPath, "utf8")).toBe(before);
220
- });
221
-
222
- test("plan.json mtime is unchanged after handler runs", async () => {
223
- const sid = crypto.randomUUID();
224
- const planPath = path.join(cwd, ".nexus/state/plan.json");
225
- const before = fs.statSync(planPath).mtimeMs;
226
- await handler({ hook_event_name: "SessionStart", session_id: sid, cwd });
227
- expect(fs.statSync(planPath).mtimeMs).toBe(before);
228
- });
229
- });
230
-
231
- // ---------------------------------------------------------------------------
232
- // Scenario 5: Return value is undefined / void
233
- // ---------------------------------------------------------------------------
234
-
235
- describe("scenario 5 — return value is undefined (void)", () => {
236
- let cwd: string;
237
-
238
- beforeEach(() => {
239
- cwd = makeTmpDir();
240
- });
241
-
242
- afterEach(() => {
243
- fs.rmSync(cwd, { recursive: true, force: true });
244
- });
245
-
246
- test("returns undefined for a valid SessionStart event", async () => {
247
- const sid = crypto.randomUUID();
248
- const result = await handler({
249
- hook_event_name: "SessionStart",
250
- session_id: sid,
251
- cwd,
252
- });
253
- expect(result).toBeUndefined();
254
- });
255
-
256
- test("returns undefined when hook_event_name is not SessionStart", async () => {
257
- const result = await handler({
258
- hook_event_name: "UserPromptSubmit",
259
- session_id: crypto.randomUUID(),
260
- cwd,
261
- prompt: "hello",
262
- });
263
- expect(result).toBeUndefined();
264
- });
265
-
266
- test("returns undefined for path traversal input (rejected)", async () => {
267
- const result = await handler({
268
- hook_event_name: "SessionStart",
269
- session_id: "../etc/passwd",
270
- cwd,
271
- });
272
- expect(result).toBeUndefined();
273
- });
274
- });
@@ -1,31 +0,0 @@
1
- import type { HookHandler } from "../../../src/hooks/types.js";
2
- import { mkdirSync, writeFileSync } from "node:fs";
3
- import { join, basename } from "node:path";
4
- import { getParentPid } from "../../../src/shared/paths.js";
5
-
6
- const handler: HookHandler = async (input) => {
7
- if (input.hook_event_name !== "SessionStart") return;
8
-
9
- const safeSid = basename(input.session_id);
10
- if (!safeSid || safeSid.startsWith(".") || safeSid.includes("/")) {
11
- process.stderr.write(`[session-init] invalid session_id: ${input.session_id}\n`);
12
- return;
13
- }
14
-
15
- const sessionDir = join(input.cwd, ".nexus/state", safeSid);
16
-
17
- mkdirSync(sessionDir, { recursive: true });
18
-
19
- writeFileSync(join(sessionDir, "agent-tracker.json"), "[]");
20
- writeFileSync(join(sessionDir, "tool-log.jsonl"), "");
21
-
22
- const ppid = getParentPid();
23
- const byPpidDir = join(input.cwd, ".nexus/state/runtime/by-ppid");
24
- mkdirSync(byPpidDir, { recursive: true });
25
- writeFileSync(
26
- join(byPpidDir, `${ppid}.json`),
27
- JSON.stringify({ session_id: input.session_id, updated_at: new Date().toISOString(), cwd: input.cwd }),
28
- );
29
- };
30
-
31
- export default handler;
@@ -1,9 +0,0 @@
1
- name: session-init
2
- description: Initialize per-session state files at session start
3
- events: [SessionStart]
4
- matcher: "*"
5
- timeout: 10
6
- fallback: warn
7
- priority: 0
8
- requires_capabilities:
9
- - event.session_start
@@ -1,55 +0,0 @@
1
- {
2
- "$schema": "./schema/lsp-servers.schema.json",
3
- "languages": {
4
- "typescript": {
5
- "extensions": {
6
- "ts": "typescript",
7
- "tsx": "typescriptreact",
8
- "js": "javascript",
9
- "jsx": "javascriptreact",
10
- "mjs": "javascript",
11
- "cjs": "javascript",
12
- "mts": "typescript",
13
- "cts": "typescript"
14
- },
15
- "server": {
16
- "command_chain": ["bunx", "npx"],
17
- "args": ["typescript-language-server", "--stdio"]
18
- },
19
- "install_hint": "npm i -g typescript-language-server"
20
- },
21
- "python": {
22
- "extensions": {
23
- "py": "python",
24
- "pyi": "python"
25
- },
26
- "server": {
27
- "command_chain": ["bunx", "npx"],
28
- "args": ["pyright-langserver", "--stdio"]
29
- },
30
- "install_hint": "npm i -g pyright"
31
- },
32
- "rust": {
33
- "extensions": {
34
- "rs": "rust"
35
- },
36
- "server": {
37
- "command_chain": ["rust-analyzer"],
38
- "search_paths": ["~/.cargo/bin/rust-analyzer"],
39
- "args": []
40
- },
41
- "install_hint": "rustup component add rust-analyzer"
42
- },
43
- "go": {
44
- "extensions": {
45
- "go": "go"
46
- },
47
- "server": {
48
- "command_chain": ["gopls"],
49
- "search_paths": ["~/go/bin/gopls", "/usr/local/go/bin/gopls"],
50
- "args": ["serve"]
51
- },
52
- "install_hint": "go install golang.org/x/tools/gopls@latest"
53
- }
54
- }
55
- }