@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,313 +0,0 @@
1
- # capability-matrix.yml
2
- # nexus-core hook system capability matrix
3
- #
4
- # This file is the single source of truth for portability_tier auto-derivation
5
- # in build-hooks.ts. The build script reads this file via js-yaml (or equivalent)
6
- # and cross-references each hook's requires_capabilities[] against the matrix.
7
- #
8
- # Schema:
9
- # Each top-level key is a dot-notation capability ID.
10
- # Each entry has three harness keys: claude, codex, opencode.
11
- # Values: true | false | partial
12
- # true — fully supported, behavior is defined and verified
13
- # false — not supported; the build will apply fallback policy (warn|skip|error)
14
- # as specified in the hook's meta.yml
15
- # partial — supported only under specific conditions (see per-entry note)
16
- # note — required when value is partial or false; cites issue/PR where relevant
17
- #
18
- # Partial semantics: "operates only under specific matchers, timing conditions,
19
- # or platform constraints — not universally available within the event."
20
- #
21
- # Updated: 2026-04-18
22
- # Maintained by: nexus-core team
23
-
24
- capabilities:
25
-
26
- # ─── Event: session lifecycle ─────────────────────────────────────────────
27
-
28
- event.session_start:
29
- claude: true
30
- codex: true
31
- opencode: true
32
- note: >
33
- Claude: SessionStart hook. Codex: SessionStart hook (experimental flag required —
34
- see runtime.experimental_flag_required). OpenCode: session.created Bus event
35
- received via the generic `event` hook key.
36
-
37
- event.user_prompt_submit:
38
- claude: true
39
- codex: true
40
- opencode: true
41
- note: >
42
- Claude: UserPromptSubmit hook. Codex: UserPromptSubmit hook.
43
- OpenCode: UserPromptSubmit maps to experimental.chat.system.transform
44
- (fires immediately before each LLM call) or chat.message hook for
45
- per-message interception.
46
-
47
- # ─── Event: PreToolUse ────────────────────────────────────────────────────
48
-
49
- event.pre_tool_use.bash:
50
- claude: true
51
- codex: true
52
- opencode: true
53
- note: >
54
- Claude: PreToolUse matcher "Bash". Codex: PreToolUse currently emits only
55
- for Bash — https://github.com/openai/codex/issues/16732 (open, PR #18391 pending).
56
- OpenCode: tool.execute.before fires for all built-in tools including bash.
57
-
58
- event.pre_tool_use.edit:
59
- claude: true
60
- codex: false
61
- opencode: true
62
- note: >
63
- Codex: apply_patch does not emit PreToolUse/PostToolUse at this time.
64
- Fix prepared in PR #18391 (OpenAI employee fcoury-oai, approved by canvrno-oai,
65
- pending merge) — https://github.com/openai/codex/pull/18391.
66
- When merged, update codex value to true and add release note to sister projects.
67
- Claude: PreToolUse matcher "Edit|MultiEdit". OpenCode: tool.execute.before
68
- fires for edit and apply_patch tools.
69
-
70
- event.pre_tool_use.mcp:
71
- claude: true
72
- codex: false
73
- opencode: false
74
- note: >
75
- MCP tool interception is Claude-only. Codex does not emit PreToolUse for MCP
76
- tools — https://github.com/openai/codex/issues/16732. OpenCode tool.execute.before
77
- does not fire for MCP tool calls —
78
- https://github.com/sst/opencode/issues/2319 (open, unresolved).
79
- Tier 2 user plugins can add MCP PreToolUse hooks in Claude environments only.
80
-
81
- # ─── Event: PostToolUse ───────────────────────────────────────────────────
82
-
83
- event.post_tool_use.bash:
84
- claude: true
85
- codex: true
86
- opencode: true
87
- note: >
88
- Claude: PostToolUse matcher "Bash". Codex: PostToolUse emits for Bash
89
- (verified in direct experiment — codex-cli 0.121.0, macOS).
90
- OpenCode: tool.execute.after fires for bash tool.
91
-
92
- event.post_tool_use.read:
93
- claude: true
94
- codex: false
95
- opencode: true
96
- note: >
97
- Codex has no independent Read tool; file reads use shell (cat/head/tail).
98
- The wrapper Bash-parsing layer maps cat|head|tail|less|more to Read as a
99
- best-effort equivalent (see event.post_tool_use.bash_parsed).
100
- Direct Read-equivalent PostToolUse is not available natively in Codex.
101
- OpenCode: tool.execute.after fires for the read tool.
102
-
103
- event.post_tool_use.edit:
104
- claude: true
105
- codex: false
106
- opencode: true
107
- note: >
108
- Codex: apply_patch does not emit PostToolUse — same constraint as
109
- event.pre_tool_use.edit. PR #18391 addresses this —
110
- https://github.com/openai/codex/pull/18391.
111
- Shell-based edits (echo > file, sed -i, heredoc) are partially captured
112
- via event.post_tool_use.bash_parsed.
113
- Claude: PostToolUse matcher "Edit|MultiEdit|Write".
114
- OpenCode: tool.execute.after fires for edit, write, and apply_patch tools.
115
-
116
- event.post_tool_use.bash_parsed:
117
- claude: false
118
- codex: true
119
- opencode: false
120
- note: >
121
- Codex-specific capability: the nexus wrapper parses Bash commands to derive
122
- equivalent nexus tool_name values. Mapping table (best-effort, complex pipes
123
- and sudo are not parsed):
124
- cat|head|tail|less|more <file> -> Read
125
- ls <path> -> LS
126
- find <path> -> Glob
127
- rg|grep <pattern> <path> -> Grep
128
- echo <text> > <file> -> Write
129
- echo <text> >> <file> -> Edit
130
- sed -i <...> <file> -> Edit
131
- cat > <file> <<EOF (heredoc) -> Write
132
- tee <file> -> Write
133
- touch <file> -> Write
134
- cp <src> <dst> -> Write (dst)
135
- mv <src> <dst> -> Edit (dst)
136
- This provides partial PostToolUse coverage for file operations that Codex
137
- expresses as shell commands. Claude and OpenCode have dedicated first-class
138
- tools and do not require this shim.
139
-
140
- # ─── Event: subagent lifecycle ────────────────────────────────────────────
141
-
142
- event.subagent_start:
143
- claude: true
144
- codex: true
145
- opencode: true
146
- note: >
147
- Claude: SubagentStart hook. Codex: SubagentStart hook (thread_spawn jsonl
148
- payload in transcript — codex-nexus adapter parses spawn_agent call).
149
- OpenCode: tool.execute.before with input.tool === "task" matcher in mountHooks
150
- (opencode-nexus verified pattern). agent_id equals subagent session ID and is
151
- immutable across all three harnesses.
152
-
153
- event.subagent_stop:
154
- claude: true
155
- codex: true
156
- opencode: true
157
- note: >
158
- Claude: SubagentStop hook. Codex: SubagentStop hook (thread_close jsonl payload).
159
- OpenCode: tool.execute.after with input.tool === "task" matcher in mountHooks.
160
- agent-finalize uses tool.execute.after output.output append as an approved
161
- exception (#6 decision — SubagentStop is the sole approved use of
162
- tool.execute.after context injection in the nexus standard).
163
-
164
- # ─── Output: additionalContext injection ──────────────────────────────────
165
-
166
- output.additional_context.session_start:
167
- claude: true
168
- codex: true
169
- opencode: true
170
- note: >
171
- Claude: additionalContext field in SessionStart hook output injected as a
172
- system-reminder block (max 10,000 chars per hook; multiple hooks are merged).
173
- Codex: additionalContext in SessionStart hookSpecificOutput — verified in
174
- direct experiment (codex-cli 0.121.0, macOS).
175
- OpenCode: experimental.chat.system.transform output.system.push at
176
- session.created time.
177
-
178
- output.additional_context.user_prompt:
179
- claude: true
180
- codex: true
181
- opencode: true
182
- note: >
183
- Claude: additionalContext in UserPromptSubmit hook output.
184
- Codex: additionalContext field in UserPromptSubmit hook output.
185
- OpenCode: experimental.chat.system.transform fires before every LLM call;
186
- this is the primary context injection mechanism for user-prompt-equivalent
187
- interception. Note: fires on every LLM call, not only on new user messages —
188
- buffered state must be cleared after one injection to prevent duplication.
189
-
190
- output.additional_context.subagent_stop:
191
- claude: true
192
- codex: true
193
- opencode: true
194
- note: >
195
- Claude: additionalContext in SubagentStop hook output.
196
- Codex: additionalContext in SubagentStop (thread_close) hook output.
197
- OpenCode: agent-finalize hook uses tool.execute.after output.output append
198
- as an approved exception; the nexus wrapper translates this to the
199
- additional_context semantic for subagent stop notifications.
200
-
201
- output.additional_context.post_tool:
202
- claude: true
203
- codex: true
204
- opencode: false
205
- note: >
206
- OpenCode: tool.execute.after can technically append to output.output and the
207
- LLM receives the modified tool result (verified in direct experiment 2026-04-18).
208
- However, all three sister projects (claude-nexus, opencode-nexus, codex-nexus)
209
- use PostToolUse exclusively for telemetry/state-tracking side effects — not
210
- context injection. This capability is not adopted in the nexus standard
211
- (#6 decision — YAGNI). Marked false to prevent accidental use; user plugins
212
- may use tool.execute.after output.output append as an escape hatch.
213
- Context for future consideration: see .nexus/memory/external-opencode-hooks-tools.md §13.
214
- Claude: additionalContext in PostToolUse output.
215
- Codex: additionalContext in PostToolUse hookSpecificOutput.
216
-
217
- # ─── Output: decision / control flow ──────────────────────────────────────
218
-
219
- output.decision_block:
220
- claude: true
221
- codex: true
222
- opencode: true
223
- note: >
224
- Claude: decision:"block" in hook stdout JSON (or exit 2 + stderr).
225
- PostToolUse decision:block blocks the tool result from being fed back to
226
- the model (the tool itself has already executed).
227
- Codex: decision:"block" + reason in hook stdout JSON, or exit 2 + stderr;
228
- both are functionally equivalent. Priority order: continue:false >
229
- decision:block > exit 2.
230
- OpenCode: throw new Error(...) in tool.execute.before blocks tool execution;
231
- mountHooks translates nexus decision:block to throw. PostToolUse block is not
232
- available in OpenCode (tool.execute.after cannot prevent tool result delivery).
233
-
234
- output.updated_input.tool:
235
- claude: true
236
- codex: false
237
- opencode: true
238
- note: >
239
- Claude: updatedInput field in PreToolUse output completely replaces tool
240
- arguments (partial updates are not supported — any missing fields are lost).
241
- Effective only when permissionDecision is "allow" or "ask".
242
- Codex: updatedInput is parsed but is currently not applied — fail-open (noop).
243
- The field is silently ignored with no error or warning —
244
- https://github.com/openai/codex/issues/16732 (related tracking issue).
245
- OpenCode: output.args mutation in tool.execute.before; mountHooks assigns
246
- the nexus updatedInput value to output.args (reference is mutated in-place).
247
-
248
- output.continue_false:
249
- claude: true
250
- codex: true
251
- opencode: true
252
- note: >
253
- Claude: continue:false with optional stopReason (displayed to the user,
254
- not to the model). Globally terminates the current session turn immediately,
255
- taking precedence over all event-specific decision fields.
256
- Codex: continue:false is the highest-priority control flow signal —
257
- overrides decision:block and exit 2. Scope is turn termination (session-level
258
- termination is unconfirmed per documentation). Supported on
259
- SessionStart, UserPromptSubmit, PostToolUse, and Stop events.
260
- OpenCode: mountHooks translates continue:false to throw, which terminates
261
- tool execution and the current session turn.
262
-
263
- # ─── Runtime: flags and prerequisites ─────────────────────────────────────
264
-
265
- runtime.experimental_flag_required:
266
- claude: false
267
- codex: true
268
- opencode: false
269
- note: >
270
- Codex requires an opt-in feature flag to activate the hook system.
271
- ~/.codex/config.toml must contain:
272
- [features]
273
- codex_hooks = true
274
- Without this flag, hooks.json is silently ignored (no error, no warning).
275
- Windows: the entire Codex hook system is currently disabled regardless of
276
- the flag (documented as a temporary measure by OpenAI).
277
- Claude and OpenCode activate hook processing without any experimental flag.
278
-
279
- # ─── Permission hooks ──────────────────────────────────────────────────────
280
-
281
- event.permission_request:
282
- claude: true
283
- codex: partial
284
- opencode: false
285
- note: >
286
- Claude: PermissionRequest hook fires when a permission dialog is triggered;
287
- output supports permissionDecision allow|deny|ask|defer.
288
- Codex: permission_request.rs confirmed present in codex-rs/hooks/src/events/
289
- (discovered 2026-04-18 — external-codex-hooks-tools.md §12). This makes Codex
290
- hooks 6 events, not 5. stdin/stdout semantics and matcher behavior are
291
- unverified; marked partial pending investigation.
292
- OpenCode: permission.ask hook exists but is not firing due to a missing
293
- Plugin.trigger call in PermissionNext.ask() —
294
- https://github.com/sst/opencode/issues/7006 (open).
295
- PR #19453 (anomalyco fork) proposes a fix but is not merged into sst/opencode
296
- main. PermissionRequest is outside the portable standard until #7006 is resolved.
297
-
298
- # ─── Context injection: PreToolUse ────────────────────────────────────────
299
-
300
- output.additional_context.pre_tool:
301
- claude: true
302
- codex: partial
303
- opencode: true
304
- note: >
305
- Claude: additionalContext in PreToolUse output is injected as a system-reminder
306
- before tool execution (when permissionDecision is not "defer").
307
- Codex: additionalContext in PreToolUse output is parsed but the field is
308
- currently not implemented — fail-open (noop). Marked partial because the field
309
- is accepted without error but has no observable effect on the model.
310
- See external-codex-hooks-tools.md §10-2.
311
- OpenCode: tool.execute.before can prepend context to output.args for
312
- prompt-bearing tools (such as task/subagent), or buffer context for delivery
313
- via experimental.chat.system.transform on the subsequent LLM call.
@@ -1,302 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from "bun:test";
2
- import fs from "node:fs";
3
- import fsPromises from "node:fs/promises";
4
- import os from "node:os";
5
- import path from "node:path";
6
- import handler from "./handler.ts";
7
- import type { NexusHookInput } from "../../../src/hooks/types.ts";
8
-
9
- // ---------------------------------------------------------------------------
10
- // Fixture helpers
11
- // ---------------------------------------------------------------------------
12
-
13
- let tmpDir: string;
14
-
15
- beforeEach(() => {
16
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "nexus-post-tool-"));
17
- });
18
-
19
- afterEach(async () => {
20
- await fsPromises.rm(tmpDir, { recursive: true, force: true });
21
- });
22
-
23
- /** Build a minimal PostToolUse input */
24
- function makeInput(
25
- overrides: Partial<Extract<NexusHookInput, { hook_event_name: "PostToolUse" }>> & {
26
- tool_input?: Record<string, unknown>;
27
- },
28
- ): NexusHookInput {
29
- return {
30
- hook_event_name: "PostToolUse",
31
- session_id: "sid-test",
32
- cwd: tmpDir,
33
- tool_name: "Edit",
34
- agent_id: "agent-engineer",
35
- ...overrides,
36
- } as NexusHookInput;
37
- }
38
-
39
- function toolLogPath(sessionId = "sid-test"): string {
40
- return path.join(tmpDir, ".nexus/state", sessionId, "tool-log.jsonl");
41
- }
42
-
43
- function memAccessPath(): string {
44
- return path.join(tmpDir, ".nexus/memory-access.jsonl");
45
- }
46
-
47
- function readJsonLines(filePath: string): unknown[] {
48
- const raw = fs.readFileSync(filePath, "utf8");
49
- return raw
50
- .trimEnd()
51
- .split("\n")
52
- .filter((l) => l.trim() !== "")
53
- .map((l) => JSON.parse(l));
54
- }
55
-
56
- // ---------------------------------------------------------------------------
57
- // Scenario 1 — Edit + agent_id present → tool-log.jsonl 1-line append
58
- // ---------------------------------------------------------------------------
59
-
60
- describe("scenario 1: Edit + agent_id → tool-log append", () => {
61
- it("appends one record to .nexus/state/sessions/<sid>/tool-log.jsonl", async () => {
62
- const input = makeInput({
63
- tool_name: "Edit",
64
- agent_id: "agent-engineer",
65
- tool_input: { file_path: path.join(tmpDir, "src/foo.ts") },
66
- });
67
-
68
- const result = await handler(input);
69
-
70
- // No additional_context or block returned
71
- expect(result).toBeUndefined();
72
-
73
- const logFile = toolLogPath();
74
- expect(fs.existsSync(logFile)).toBe(true);
75
-
76
- const lines = readJsonLines(logFile);
77
- expect(lines).toHaveLength(1);
78
-
79
- const entry = lines[0] as Record<string, unknown>;
80
- expect(entry.agent_id).toBe("agent-engineer");
81
- expect(entry.tool).toBe("Edit");
82
- expect(entry.file).toBe("src/foo.ts");
83
- expect(entry.status).toBe("ok");
84
- expect(typeof entry.ts).toBe("string");
85
- expect(() => new Date(entry.ts as string)).not.toThrow();
86
- });
87
- });
88
-
89
- // ---------------------------------------------------------------------------
90
- // Scenario 2 — Read + file_path within .nexus/memory/** → memory-access.jsonl append
91
- // ---------------------------------------------------------------------------
92
-
93
- describe("scenario 2: Read + memory path → memory-access.jsonl append", () => {
94
- it("appends one record to .nexus/memory-access.jsonl", async () => {
95
- const memFile = path.join(tmpDir, ".nexus/memory/lessons.md");
96
- // File does not need to exist; only the path matters for the hook
97
-
98
- const input = makeInput({
99
- tool_name: "Read",
100
- agent_id: "agent-researcher",
101
- tool_input: { file_path: memFile },
102
- });
103
-
104
- await handler(input);
105
-
106
- const accFile = memAccessPath();
107
- expect(fs.existsSync(accFile)).toBe(true);
108
-
109
- const lines = readJsonLines(accFile);
110
- expect(lines).toHaveLength(1);
111
-
112
- const entry = lines[0] as Record<string, unknown>;
113
- expect(entry.path).toBe(".nexus/memory/lessons.md");
114
- expect(entry.agent).toBe("agent-researcher");
115
- expect(typeof entry.accessed_at).toBe("string");
116
- expect(() => new Date(entry.accessed_at as string)).not.toThrow();
117
- });
118
- });
119
-
120
- // ---------------------------------------------------------------------------
121
- // Scenario 3 — Read + other path (src/foo.ts) → memory-access.jsonl NOT written
122
- // ---------------------------------------------------------------------------
123
-
124
- describe("scenario 3: Read + non-memory path → memory-access skip", () => {
125
- it("does not create memory-access.jsonl for a non-memory file path", async () => {
126
- const input = makeInput({
127
- tool_name: "Read",
128
- agent_id: "agent-engineer",
129
- tool_input: { file_path: path.join(tmpDir, "src/foo.ts") },
130
- });
131
-
132
- await handler(input);
133
-
134
- expect(fs.existsSync(memAccessPath())).toBe(false);
135
- // tool-log is also not written because tool is Read (not an edit tool)
136
- expect(fs.existsSync(toolLogPath())).toBe(false);
137
- });
138
- });
139
-
140
- // ---------------------------------------------------------------------------
141
- // Scenario 4 — Lead (agent_id = null) + Edit → tool-log skip
142
- // ---------------------------------------------------------------------------
143
-
144
- describe("scenario 4: Lead (agent_id null) + Edit → tool-log skip", () => {
145
- it("does not write tool-log.jsonl when agent_id is null", async () => {
146
- const input = makeInput({
147
- tool_name: "Edit",
148
- agent_id: null,
149
- tool_input: { file_path: path.join(tmpDir, "src/bar.ts") },
150
- });
151
-
152
- await handler(input);
153
-
154
- expect(fs.existsSync(toolLogPath())).toBe(false);
155
- });
156
-
157
- it("does not write tool-log.jsonl when agent_id is undefined", async () => {
158
- const input: NexusHookInput = {
159
- hook_event_name: "PostToolUse",
160
- session_id: "sid-test",
161
- cwd: tmpDir,
162
- tool_name: "Edit",
163
- // agent_id intentionally omitted
164
- tool_input: { file_path: path.join(tmpDir, "src/bar.ts") },
165
- };
166
-
167
- await handler(input);
168
-
169
- expect(fs.existsSync(toolLogPath())).toBe(false);
170
- });
171
- });
172
-
173
- // ---------------------------------------------------------------------------
174
- // Scenario 5 — NotebookEdit + notebook_path (no file_path) → tool-log uses notebook_path
175
- // ---------------------------------------------------------------------------
176
-
177
- describe("scenario 5: NotebookEdit + notebook_path → tool-log with notebook_path", () => {
178
- it("uses notebook_path when file_path is absent", async () => {
179
- const nbPath = path.join(tmpDir, "notebooks/analysis.ipynb");
180
-
181
- const input = makeInput({
182
- tool_name: "NotebookEdit",
183
- agent_id: "agent-engineer",
184
- tool_input: { notebook_path: nbPath },
185
- // no file_path key
186
- });
187
-
188
- await handler(input);
189
-
190
- const logFile = toolLogPath();
191
- expect(fs.existsSync(logFile)).toBe(true);
192
-
193
- const lines = readJsonLines(logFile);
194
- expect(lines).toHaveLength(1);
195
-
196
- const entry = lines[0] as Record<string, unknown>;
197
- expect(entry.tool).toBe("NotebookEdit");
198
- expect(entry.file).toBe("notebooks/analysis.ipynb");
199
- expect(entry.agent_id).toBe("agent-engineer");
200
- expect(entry.status).toBe("ok");
201
- });
202
-
203
- it("prefers file_path over notebook_path when both are present", async () => {
204
- const input = makeInput({
205
- tool_name: "NotebookEdit",
206
- agent_id: "agent-engineer",
207
- tool_input: {
208
- file_path: path.join(tmpDir, "src/primary.ipynb"),
209
- notebook_path: path.join(tmpDir, "notebooks/secondary.ipynb"),
210
- },
211
- });
212
-
213
- await handler(input);
214
-
215
- const lines = readJsonLines(toolLogPath());
216
- const entry = lines[0] as Record<string, unknown>;
217
- // file_path is ?? first, so it wins
218
- expect(entry.file).toBe("src/primary.ipynb");
219
- });
220
- });
221
-
222
- // ---------------------------------------------------------------------------
223
- // Scenario 6 — 100 parallel appendJsonLine → jsonl integrity
224
- // ---------------------------------------------------------------------------
225
-
226
- describe("scenario 6: 100 parallel handler calls → jsonl integrity", () => {
227
- it("all 100 lines are valid JSON and each has expected shape", async () => {
228
- const inputs = Array.from({ length: 100 }, (_, i) =>
229
- makeInput({
230
- tool_name: "Edit",
231
- agent_id: `agent-${i}`,
232
- session_id: "sid-parallel",
233
- tool_input: { file_path: path.join(tmpDir, `src/file-${i}.ts`) },
234
- }),
235
- );
236
-
237
- await Promise.all(inputs.map((inp) => handler(inp)));
238
-
239
- const logFile = toolLogPath("sid-parallel");
240
- expect(fs.existsSync(logFile)).toBe(true);
241
-
242
- const raw = fs.readFileSync(logFile, "utf8");
243
- const lines = raw
244
- .trimEnd()
245
- .split("\n")
246
- .filter((l) => l.trim() !== "");
247
-
248
- expect(lines).toHaveLength(100);
249
-
250
- for (const line of lines) {
251
- let parsed: unknown;
252
- expect(() => {
253
- parsed = JSON.parse(line);
254
- }).not.toThrow();
255
-
256
- const entry = parsed as Record<string, unknown>;
257
- expect(typeof entry.ts).toBe("string");
258
- expect(typeof entry.agent_id).toBe("string");
259
- expect(entry.tool).toBe("Edit");
260
- expect(typeof entry.file).toBe("string");
261
- expect(entry.status).toBe("ok");
262
- }
263
- }, 15_000);
264
- });
265
-
266
- // ---------------------------------------------------------------------------
267
- // Scenario 7 — handler returns no additional_context and no block
268
- // ---------------------------------------------------------------------------
269
-
270
- describe("scenario 7: handler returns no additional_context / block", () => {
271
- it("returns undefined for Edit + agent_id call", async () => {
272
- const result = await handler(
273
- makeInput({
274
- tool_name: "Edit",
275
- agent_id: "agent-engineer",
276
- tool_input: { file_path: path.join(tmpDir, "src/x.ts") },
277
- }),
278
- );
279
- expect(result).toBeUndefined();
280
- });
281
-
282
- it("returns undefined for Read + memory path call", async () => {
283
- const result = await handler(
284
- makeInput({
285
- tool_name: "Read",
286
- agent_id: "agent-researcher",
287
- tool_input: { file_path: path.join(tmpDir, ".nexus/memory/ref.md") },
288
- }),
289
- );
290
- expect(result).toBeUndefined();
291
- });
292
-
293
- it("returns undefined for non-PostToolUse event (early return)", async () => {
294
- const input: NexusHookInput = {
295
- hook_event_name: "SessionStart",
296
- session_id: "sid-test",
297
- cwd: tmpDir,
298
- };
299
- const result = await handler(input);
300
- expect(result).toBeUndefined();
301
- });
302
- });
@@ -1,49 +0,0 @@
1
- import type { HookHandler } from "../../../src/hooks/types.js";
2
- import { appendJsonLine } from "../../../src/shared/json-store.js";
3
- import { join, resolve, relative } from "node:path";
4
-
5
- const EDIT_TOOLS = new Set(["Edit", "Write", "MultiEdit", "ApplyPatch", "NotebookEdit"]);
6
-
7
- function isWithinMemory(filePath: string, projectRoot: string): boolean {
8
- const memRoot = resolve(projectRoot, ".nexus/memory");
9
- const abs = resolve(filePath);
10
- return abs.startsWith(memRoot + "/") || abs === memRoot;
11
- }
12
-
13
- const handler: HookHandler = async (input) => {
14
- if (input.hook_event_name !== "PostToolUse") return;
15
-
16
- const { cwd, session_id, tool_name, agent_id } = input;
17
- const toolInput = (input.tool_input ?? {}) as Record<string, unknown>;
18
-
19
- // 1. Memory access tracking (Read)
20
- if (tool_name === "Read") {
21
- const filePath = toolInput.file_path as string | undefined;
22
- if (filePath && isWithinMemory(filePath, cwd)) {
23
- appendJsonLine(join(cwd, ".nexus/memory-access.jsonl"), {
24
- path: relative(cwd, resolve(filePath)),
25
- accessed_at: new Date().toISOString(),
26
- agent: agent_id ?? null,
27
- });
28
- }
29
- }
30
-
31
- // 2. Tool-log append (edit tools + agent_id present)
32
- if (EDIT_TOOLS.has(tool_name) && agent_id) {
33
- const filePath = (toolInput.file_path ?? toolInput.notebook_path) as string | undefined;
34
- if (filePath) {
35
- appendJsonLine(
36
- join(cwd, ".nexus/state", session_id, "tool-log.jsonl"),
37
- {
38
- ts: new Date().toISOString(),
39
- agent_id,
40
- tool: tool_name,
41
- file: relative(cwd, resolve(filePath)),
42
- status: "ok",
43
- },
44
- );
45
- }
46
- }
47
- };
48
-
49
- export default handler;
@@ -1,11 +0,0 @@
1
- name: post-tool-telemetry
2
- description: Track memory access and file-edit operations for strength/forgetting signals and audit
3
- events: [PostToolUse]
4
- matcher: "Read|Edit|Write|MultiEdit|ApplyPatch|NotebookEdit|Bash"
5
- timeout: 5
6
- fallback: warn
7
- priority: 10
8
- requires_capabilities:
9
- - event.post_tool_use.read
10
- - event.post_tool_use.edit
11
- - event.post_tool_use.bash_parsed