@moreih29/nexus-core 0.16.2 → 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 (413) 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 -4
  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 -198
  165. package/assets/hooks/agent-bootstrap/handler.test.ts +0 -368
  166. package/assets/hooks/agent-bootstrap/handler.ts +0 -119
  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 -11
  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 -30
  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 -100
  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 -23
  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 -121
  225. package/dist/claude/dist/hooks/agent-finalize.js +0 -180
  226. package/dist/claude/dist/hooks/prompt-router.js +0 -7336
  227. package/dist/claude/dist/hooks/session-init.js +0 -37
  228. package/dist/claude/hooks/hooks.json +0 -52
  229. package/dist/claude/settings.json +0 -3
  230. package/dist/claude/skills/nx-init/SKILL.md +0 -189
  231. package/dist/claude/skills/nx-plan/SKILL.md +0 -353
  232. package/dist/claude/skills/nx-run/SKILL.md +0 -154
  233. package/dist/claude/skills/nx-sync/SKILL.md +0 -87
  234. package/dist/codex/agents/architect.toml +0 -175
  235. package/dist/codex/agents/designer.toml +0 -123
  236. package/dist/codex/agents/engineer.toml +0 -105
  237. package/dist/codex/agents/lead.toml +0 -64
  238. package/dist/codex/agents/postdoc.toml +0 -120
  239. package/dist/codex/agents/researcher.toml +0 -136
  240. package/dist/codex/agents/reviewer.toml +0 -137
  241. package/dist/codex/agents/strategist.toml +0 -114
  242. package/dist/codex/agents/tester.toml +0 -194
  243. package/dist/codex/agents/writer.toml +0 -121
  244. package/dist/codex/dist/hooks/agent-bootstrap.js +0 -121
  245. package/dist/codex/dist/hooks/agent-finalize.js +0 -180
  246. package/dist/codex/dist/hooks/prompt-router.js +0 -7336
  247. package/dist/codex/dist/hooks/session-init.js +0 -37
  248. package/dist/codex/hooks/hooks.json +0 -28
  249. package/dist/codex/install/AGENTS.fragment.md +0 -60
  250. package/dist/codex/install/config.fragment.toml +0 -5
  251. package/dist/codex/install/install.sh +0 -60
  252. package/dist/codex/package.json +0 -20
  253. package/dist/codex/plugin/.codex-plugin/plugin.json +0 -57
  254. package/dist/codex/plugin/skills/nx-init/SKILL.md +0 -189
  255. package/dist/codex/plugin/skills/nx-plan/SKILL.md +0 -353
  256. package/dist/codex/plugin/skills/nx-run/SKILL.md +0 -154
  257. package/dist/codex/plugin/skills/nx-sync/SKILL.md +0 -87
  258. package/dist/codex/prompts/architect.md +0 -166
  259. package/dist/codex/prompts/designer.md +0 -114
  260. package/dist/codex/prompts/engineer.md +0 -97
  261. package/dist/codex/prompts/lead.md +0 -60
  262. package/dist/codex/prompts/postdoc.md +0 -111
  263. package/dist/codex/prompts/researcher.md +0 -127
  264. package/dist/codex/prompts/reviewer.md +0 -128
  265. package/dist/codex/prompts/strategist.md +0 -105
  266. package/dist/codex/prompts/tester.md +0 -185
  267. package/dist/codex/prompts/writer.md +0 -113
  268. package/dist/hooks/agent-bootstrap.js +0 -121
  269. package/dist/hooks/agent-finalize.js +0 -180
  270. package/dist/hooks/prompt-router.js +0 -7336
  271. package/dist/hooks/session-init.js +0 -37
  272. package/dist/manifests/claude-hooks.json +0 -52
  273. package/dist/manifests/codex-hooks.json +0 -28
  274. package/dist/manifests/opencode-manifest.json +0 -44
  275. package/dist/manifests/portability-report.json +0 -87
  276. package/dist/opencode/.opencode/skills/nx-init/SKILL.md +0 -189
  277. package/dist/opencode/.opencode/skills/nx-plan/SKILL.md +0 -353
  278. package/dist/opencode/.opencode/skills/nx-run/SKILL.md +0 -154
  279. package/dist/opencode/.opencode/skills/nx-sync/SKILL.md +0 -87
  280. package/dist/opencode/package.json +0 -23
  281. package/dist/opencode/src/agents/architect.ts +0 -176
  282. package/dist/opencode/src/agents/designer.ts +0 -124
  283. package/dist/opencode/src/agents/engineer.ts +0 -105
  284. package/dist/opencode/src/agents/lead.ts +0 -66
  285. package/dist/opencode/src/agents/postdoc.ts +0 -121
  286. package/dist/opencode/src/agents/researcher.ts +0 -136
  287. package/dist/opencode/src/agents/reviewer.ts +0 -137
  288. package/dist/opencode/src/agents/strategist.ts +0 -115
  289. package/dist/opencode/src/agents/tester.ts +0 -194
  290. package/dist/opencode/src/agents/writer.ts +0 -121
  291. package/dist/opencode/src/index.ts +0 -25
  292. package/dist/opencode/src/plugin.ts +0 -6
  293. package/dist/scripts/build-agents.d.ts +0 -164
  294. package/dist/scripts/build-agents.d.ts.map +0 -1
  295. package/dist/scripts/build-agents.js +0 -890
  296. package/dist/scripts/build-agents.js.map +0 -1
  297. package/dist/scripts/build-hooks.d.ts +0 -57
  298. package/dist/scripts/build-hooks.d.ts.map +0 -1
  299. package/dist/scripts/build-hooks.js +0 -555
  300. package/dist/scripts/build-hooks.js.map +0 -1
  301. package/dist/scripts/cli.d.ts +0 -54
  302. package/dist/scripts/cli.d.ts.map +0 -1
  303. package/dist/scripts/cli.js +0 -504
  304. package/dist/scripts/cli.js.map +0 -1
  305. package/dist/scripts/smoke/smoke-claude.d.ts +0 -2
  306. package/dist/scripts/smoke/smoke-claude.d.ts.map +0 -1
  307. package/dist/scripts/smoke/smoke-claude.js +0 -58
  308. package/dist/scripts/smoke/smoke-claude.js.map +0 -1
  309. package/dist/scripts/smoke/smoke-codex.d.ts +0 -2
  310. package/dist/scripts/smoke/smoke-codex.d.ts.map +0 -1
  311. package/dist/scripts/smoke/smoke-codex.js +0 -50
  312. package/dist/scripts/smoke/smoke-codex.js.map +0 -1
  313. package/dist/scripts/smoke/smoke-consumer.d.ts +0 -2
  314. package/dist/scripts/smoke/smoke-consumer.d.ts.map +0 -1
  315. package/dist/scripts/smoke/smoke-consumer.js +0 -80
  316. package/dist/scripts/smoke/smoke-consumer.js.map +0 -1
  317. package/dist/scripts/smoke/smoke-opencode.d.ts +0 -2
  318. package/dist/scripts/smoke/smoke-opencode.d.ts.map +0 -1
  319. package/dist/scripts/smoke/smoke-opencode.js +0 -99
  320. package/dist/scripts/smoke/smoke-opencode.js.map +0 -1
  321. package/dist/src/hooks/opencode-mount.d.ts +0 -35
  322. package/dist/src/hooks/opencode-mount.d.ts.map +0 -1
  323. package/dist/src/hooks/opencode-mount.js +0 -352
  324. package/dist/src/hooks/opencode-mount.js.map +0 -1
  325. package/dist/src/hooks/runtime.d.ts +0 -37
  326. package/dist/src/hooks/runtime.d.ts.map +0 -1
  327. package/dist/src/hooks/runtime.js +0 -274
  328. package/dist/src/hooks/runtime.js.map +0 -1
  329. package/dist/src/hooks/types.d.ts +0 -196
  330. package/dist/src/hooks/types.d.ts.map +0 -1
  331. package/dist/src/hooks/types.js +0 -85
  332. package/dist/src/hooks/types.js.map +0 -1
  333. package/dist/src/lsp/cache.d.ts +0 -9
  334. package/dist/src/lsp/cache.d.ts.map +0 -1
  335. package/dist/src/lsp/cache.js +0 -216
  336. package/dist/src/lsp/cache.js.map +0 -1
  337. package/dist/src/lsp/client.d.ts +0 -24
  338. package/dist/src/lsp/client.d.ts.map +0 -1
  339. package/dist/src/lsp/client.js +0 -166
  340. package/dist/src/lsp/client.js.map +0 -1
  341. package/dist/src/lsp/detect.d.ts +0 -77
  342. package/dist/src/lsp/detect.d.ts.map +0 -1
  343. package/dist/src/lsp/detect.js +0 -116
  344. package/dist/src/lsp/detect.js.map +0 -1
  345. package/dist/src/mcp/server.d.ts.map +0 -1
  346. package/dist/src/mcp/server.js +0 -34
  347. package/dist/src/mcp/server.js.map +0 -1
  348. package/dist/src/mcp/tools/artifact.d.ts.map +0 -1
  349. package/dist/src/mcp/tools/artifact.js +0 -36
  350. package/dist/src/mcp/tools/artifact.js.map +0 -1
  351. package/dist/src/mcp/tools/history.d.ts.map +0 -1
  352. package/dist/src/mcp/tools/history.js +0 -29
  353. package/dist/src/mcp/tools/history.js.map +0 -1
  354. package/dist/src/mcp/tools/lsp.d.ts +0 -13
  355. package/dist/src/mcp/tools/lsp.d.ts.map +0 -1
  356. package/dist/src/mcp/tools/lsp.js +0 -225
  357. package/dist/src/mcp/tools/lsp.js.map +0 -1
  358. package/dist/src/mcp/tools/plan.d.ts.map +0 -1
  359. package/dist/src/mcp/tools/plan.js +0 -317
  360. package/dist/src/mcp/tools/plan.js.map +0 -1
  361. package/dist/src/mcp/tools/task.d.ts.map +0 -1
  362. package/dist/src/mcp/tools/task.js +0 -252
  363. package/dist/src/mcp/tools/task.js.map +0 -1
  364. package/dist/src/shared/invocations.d.ts +0 -74
  365. package/dist/src/shared/invocations.d.ts.map +0 -1
  366. package/dist/src/shared/invocations.js +0 -247
  367. package/dist/src/shared/invocations.js.map +0 -1
  368. package/dist/src/shared/json-store.d.ts.map +0 -1
  369. package/dist/src/shared/json-store.js.map +0 -1
  370. package/dist/src/shared/mcp-utils.d.ts.map +0 -1
  371. package/dist/src/shared/mcp-utils.js.map +0 -1
  372. package/dist/src/shared/package-root.d.ts +0 -6
  373. package/dist/src/shared/package-root.d.ts.map +0 -1
  374. package/dist/src/shared/package-root.js +0 -19
  375. package/dist/src/shared/package-root.js.map +0 -1
  376. package/dist/src/shared/paths.d.ts.map +0 -1
  377. package/dist/src/shared/paths.js +0 -81
  378. package/dist/src/shared/paths.js.map +0 -1
  379. package/dist/src/shared/tool-log.d.ts +0 -8
  380. package/dist/src/shared/tool-log.d.ts.map +0 -1
  381. package/dist/src/shared/tool-log.js +0 -22
  382. package/dist/src/shared/tool-log.js.map +0 -1
  383. package/dist/src/types/agent-config.d.ts +0 -22
  384. package/dist/src/types/agent-config.d.ts.map +0 -1
  385. package/dist/src/types/agent-config.js +0 -2
  386. package/dist/src/types/agent-config.js.map +0 -1
  387. package/dist/src/types/index.d.ts +0 -2
  388. package/dist/src/types/index.d.ts.map +0 -1
  389. package/dist/src/types/index.js +0 -2
  390. package/dist/src/types/index.js.map +0 -1
  391. package/dist/src/types/state.d.ts.map +0 -1
  392. package/dist/src/types/state.js.map +0 -1
  393. package/docs/consuming/codex-lead-merge.md +0 -106
  394. package/docs/contract/harness-io.md +0 -333
  395. package/docs/plugin-guide.md +0 -355
  396. package/docs/plugin-template/claude/.github/workflows/build.yml +0 -60
  397. package/docs/plugin-template/claude/README.md +0 -110
  398. package/docs/plugin-template/claude/package.json +0 -16
  399. package/docs/plugin-template/codex/.github/workflows/build.yml +0 -51
  400. package/docs/plugin-template/codex/README.md +0 -147
  401. package/docs/plugin-template/codex/install/install.sh +0 -60
  402. package/docs/plugin-template/codex/package.json +0 -17
  403. package/docs/plugin-template/opencode/.github/workflows/build.yml +0 -61
  404. package/docs/plugin-template/opencode/README.md +0 -121
  405. package/docs/plugin-template/opencode/package.json +0 -25
  406. package/docs/plugin-template/opencode/src/plugin.ts +0 -6
  407. /package/dist/{src/mcp/tools → mcp/handlers}/artifact.d.ts +0 -0
  408. /package/dist/{src/mcp/tools → mcp/handlers}/history.d.ts +0 -0
  409. /package/dist/{src/mcp/tools → mcp/handlers}/plan.d.ts +0 -0
  410. /package/dist/{src/mcp/tools → mcp/handlers}/task.d.ts +0 -0
  411. /package/dist/{src/shared → shared}/json-store.d.ts +0 -0
  412. /package/dist/{src/shared → shared}/mcp-utils.d.ts +0 -0
  413. /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,30 +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
-
5
- const handler: HookHandler = async (input) => {
6
- if (input.hook_event_name !== "SessionStart") return;
7
-
8
- // Sanitize session_id to prevent path traversal
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
- // Ensure directory exists (idempotent)
18
- mkdirSync(sessionDir, { recursive: true });
19
-
20
- // Initialize per-session state files — overwrite unconditionally (resume is intentional)
21
- writeFileSync(join(sessionDir, "agent-tracker.json"), "[]");
22
- writeFileSync(join(sessionDir, "tool-log.jsonl"), "");
23
-
24
- // plan.json and tasks.json are MCP responsibility — not touched here
25
- // memory-access.jsonl is project-level — not touched here
26
-
27
- // No additional_context returned (decided: no context injection at session start)
28
- };
29
-
30
- 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
- }