@moreih29/nexus-core 0.12.0 → 0.14.0

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 (245) hide show
  1. package/README.md +76 -57
  2. package/assets/agents/architect/body.ko.md +177 -0
  3. package/{agents → assets/agents}/architect/body.md +16 -0
  4. package/assets/agents/designer/body.ko.md +125 -0
  5. package/{agents → assets/agents}/designer/body.md +16 -0
  6. package/assets/agents/engineer/body.ko.md +106 -0
  7. package/{agents → assets/agents}/engineer/body.md +14 -0
  8. package/assets/agents/lead/body.ko.md +70 -0
  9. package/assets/agents/lead/body.md +70 -0
  10. package/assets/agents/postdoc/body.ko.md +122 -0
  11. package/{agents → assets/agents}/postdoc/body.md +16 -0
  12. package/assets/agents/researcher/body.ko.md +137 -0
  13. package/{agents → assets/agents}/researcher/body.md +15 -0
  14. package/assets/agents/reviewer/body.ko.md +138 -0
  15. package/{agents → assets/agents}/reviewer/body.md +15 -0
  16. package/assets/agents/strategist/body.ko.md +116 -0
  17. package/{agents → assets/agents}/strategist/body.md +16 -0
  18. package/assets/agents/tester/body.ko.md +195 -0
  19. package/{agents → assets/agents}/tester/body.md +15 -0
  20. package/assets/agents/writer/body.ko.md +122 -0
  21. package/{agents → assets/agents}/writer/body.md +14 -0
  22. package/assets/capability-matrix.yml +198 -0
  23. package/assets/hooks/agent-bootstrap/handler.test.ts +368 -0
  24. package/assets/hooks/agent-bootstrap/handler.ts +119 -0
  25. package/assets/hooks/agent-bootstrap/meta.yml +10 -0
  26. package/assets/hooks/agent-finalize/handler.test.ts +368 -0
  27. package/assets/hooks/agent-finalize/handler.ts +76 -0
  28. package/assets/hooks/agent-finalize/meta.yml +10 -0
  29. package/assets/hooks/capability-matrix.yml +313 -0
  30. package/assets/hooks/post-tool-telemetry/handler.test.ts +302 -0
  31. package/assets/hooks/post-tool-telemetry/handler.ts +49 -0
  32. package/assets/hooks/post-tool-telemetry/meta.yml +11 -0
  33. package/assets/hooks/prompt-router/handler.test.ts +801 -0
  34. package/assets/hooks/prompt-router/handler.ts +261 -0
  35. package/assets/hooks/prompt-router/meta.yml +11 -0
  36. package/assets/hooks/session-init/handler.test.ts +274 -0
  37. package/assets/hooks/session-init/handler.ts +30 -0
  38. package/assets/hooks/session-init/meta.yml +9 -0
  39. package/assets/lsp-servers.json +55 -0
  40. package/assets/schema/lsp-servers.schema.json +67 -0
  41. package/assets/skills/nx-init/body.ko.md +197 -0
  42. package/{skills → assets/skills}/nx-init/body.md +11 -0
  43. package/assets/skills/nx-plan/body.ko.md +361 -0
  44. package/{skills → assets/skills}/nx-plan/body.md +13 -0
  45. package/assets/skills/nx-run/body.ko.md +161 -0
  46. package/{skills → assets/skills}/nx-run/body.md +11 -0
  47. package/assets/skills/nx-sync/body.ko.md +92 -0
  48. package/{skills → assets/skills}/nx-sync/body.md +10 -0
  49. package/assets/tools/tool-name-map.yml +353 -0
  50. package/dist/assets/hooks/agent-bootstrap/handler.d.ts +4 -0
  51. package/dist/assets/hooks/agent-bootstrap/handler.d.ts.map +1 -0
  52. package/dist/assets/hooks/agent-bootstrap/handler.js +100 -0
  53. package/dist/assets/hooks/agent-bootstrap/handler.js.map +1 -0
  54. package/dist/assets/hooks/agent-finalize/handler.d.ts +4 -0
  55. package/dist/assets/hooks/agent-finalize/handler.d.ts.map +1 -0
  56. package/dist/assets/hooks/agent-finalize/handler.js +63 -0
  57. package/dist/assets/hooks/agent-finalize/handler.js.map +1 -0
  58. package/dist/assets/hooks/post-tool-telemetry/handler.d.ts +4 -0
  59. package/dist/assets/hooks/post-tool-telemetry/handler.d.ts.map +1 -0
  60. package/dist/assets/hooks/post-tool-telemetry/handler.js +40 -0
  61. package/dist/assets/hooks/post-tool-telemetry/handler.js.map +1 -0
  62. package/dist/assets/hooks/prompt-router/handler.d.ts +4 -0
  63. package/dist/assets/hooks/prompt-router/handler.d.ts.map +1 -0
  64. package/dist/assets/hooks/prompt-router/handler.js +204 -0
  65. package/dist/assets/hooks/prompt-router/handler.js.map +1 -0
  66. package/dist/assets/hooks/session-init/handler.d.ts +4 -0
  67. package/dist/assets/hooks/session-init/handler.d.ts.map +1 -0
  68. package/dist/assets/hooks/session-init/handler.js +23 -0
  69. package/dist/assets/hooks/session-init/handler.js.map +1 -0
  70. package/dist/hooks/agent-bootstrap.js +105 -0
  71. package/dist/hooks/agent-finalize.js +164 -0
  72. package/dist/hooks/post-tool-telemetry.js +55 -0
  73. package/dist/hooks/prompt-router.js +7300 -0
  74. package/dist/hooks/session-init.js +21 -0
  75. package/dist/manifests/claude-hooks.json +52 -0
  76. package/dist/manifests/codex-hooks.json +28 -0
  77. package/dist/manifests/opencode-manifest.json +44 -0
  78. package/dist/manifests/portability-report.json +87 -0
  79. package/dist/scripts/build-agents.d.ts +157 -0
  80. package/dist/scripts/build-agents.d.ts.map +1 -0
  81. package/dist/scripts/build-agents.js +737 -0
  82. package/dist/scripts/build-agents.js.map +1 -0
  83. package/dist/scripts/build-hooks.d.ts +16 -0
  84. package/dist/scripts/build-hooks.d.ts.map +1 -0
  85. package/dist/scripts/build-hooks.js +388 -0
  86. package/dist/scripts/build-hooks.js.map +1 -0
  87. package/dist/scripts/cli.d.ts +54 -0
  88. package/dist/scripts/cli.d.ts.map +1 -0
  89. package/dist/scripts/cli.js +467 -0
  90. package/dist/scripts/cli.js.map +1 -0
  91. package/dist/src/hooks/opencode-mount.d.ts +35 -0
  92. package/dist/src/hooks/opencode-mount.d.ts.map +1 -0
  93. package/dist/src/hooks/opencode-mount.js +352 -0
  94. package/dist/src/hooks/opencode-mount.js.map +1 -0
  95. package/dist/src/hooks/runtime.d.ts +37 -0
  96. package/dist/src/hooks/runtime.d.ts.map +1 -0
  97. package/dist/src/hooks/runtime.js +274 -0
  98. package/dist/src/hooks/runtime.js.map +1 -0
  99. package/dist/src/hooks/types.d.ts +196 -0
  100. package/dist/src/hooks/types.d.ts.map +1 -0
  101. package/dist/src/hooks/types.js +85 -0
  102. package/dist/src/hooks/types.js.map +1 -0
  103. package/dist/src/lsp/cache.d.ts +9 -0
  104. package/dist/src/lsp/cache.d.ts.map +1 -0
  105. package/dist/src/lsp/cache.js +216 -0
  106. package/dist/src/lsp/cache.js.map +1 -0
  107. package/dist/src/lsp/client.d.ts +24 -0
  108. package/dist/src/lsp/client.d.ts.map +1 -0
  109. package/dist/src/lsp/client.js +166 -0
  110. package/dist/src/lsp/client.js.map +1 -0
  111. package/dist/src/lsp/detect.d.ts +77 -0
  112. package/dist/src/lsp/detect.d.ts.map +1 -0
  113. package/dist/src/lsp/detect.js +116 -0
  114. package/dist/src/lsp/detect.js.map +1 -0
  115. package/dist/src/mcp/server.d.ts +5 -0
  116. package/dist/src/mcp/server.d.ts.map +1 -0
  117. package/dist/src/mcp/server.js +34 -0
  118. package/dist/src/mcp/server.js.map +1 -0
  119. package/dist/src/mcp/tools/artifact.d.ts +4 -0
  120. package/dist/src/mcp/tools/artifact.d.ts.map +1 -0
  121. package/dist/src/mcp/tools/artifact.js +36 -0
  122. package/dist/src/mcp/tools/artifact.js.map +1 -0
  123. package/dist/src/mcp/tools/history.d.ts +3 -0
  124. package/dist/src/mcp/tools/history.d.ts.map +1 -0
  125. package/dist/src/mcp/tools/history.js +29 -0
  126. package/dist/src/mcp/tools/history.js.map +1 -0
  127. package/dist/src/mcp/tools/lsp.d.ts +13 -0
  128. package/dist/src/mcp/tools/lsp.d.ts.map +1 -0
  129. package/dist/src/mcp/tools/lsp.js +225 -0
  130. package/dist/src/mcp/tools/lsp.js.map +1 -0
  131. package/dist/src/mcp/tools/plan.d.ts +3 -0
  132. package/dist/src/mcp/tools/plan.d.ts.map +1 -0
  133. package/dist/src/mcp/tools/plan.js +317 -0
  134. package/dist/src/mcp/tools/plan.js.map +1 -0
  135. package/dist/src/mcp/tools/task.d.ts +3 -0
  136. package/dist/src/mcp/tools/task.d.ts.map +1 -0
  137. package/dist/src/mcp/tools/task.js +252 -0
  138. package/dist/src/mcp/tools/task.js.map +1 -0
  139. package/dist/src/shared/invocations.d.ts +74 -0
  140. package/dist/src/shared/invocations.d.ts.map +1 -0
  141. package/dist/src/shared/invocations.js +247 -0
  142. package/dist/src/shared/invocations.js.map +1 -0
  143. package/dist/src/shared/json-store.d.ts +37 -0
  144. package/dist/src/shared/json-store.d.ts.map +1 -0
  145. package/dist/src/shared/json-store.js +163 -0
  146. package/dist/src/shared/json-store.js.map +1 -0
  147. package/dist/src/shared/mcp-utils.d.ts +3 -0
  148. package/dist/src/shared/mcp-utils.d.ts.map +1 -0
  149. package/dist/src/shared/mcp-utils.js +6 -0
  150. package/dist/src/shared/mcp-utils.js.map +1 -0
  151. package/dist/src/shared/paths.d.ts +21 -0
  152. package/dist/src/shared/paths.d.ts.map +1 -0
  153. package/dist/src/shared/paths.js +81 -0
  154. package/dist/src/shared/paths.js.map +1 -0
  155. package/dist/src/shared/tool-log.d.ts +8 -0
  156. package/dist/src/shared/tool-log.d.ts.map +1 -0
  157. package/dist/src/shared/tool-log.js +22 -0
  158. package/dist/src/shared/tool-log.js.map +1 -0
  159. package/dist/src/types/state.d.ts +862 -0
  160. package/dist/src/types/state.d.ts.map +1 -0
  161. package/dist/src/types/state.js +66 -0
  162. package/dist/src/types/state.js.map +1 -0
  163. package/docs/consuming/codex-lead-merge.md +106 -0
  164. package/docs/plugin-guide.md +396 -0
  165. package/docs/plugin-template/claude/.github/workflows/build.yml +60 -0
  166. package/docs/plugin-template/claude/README.md +110 -0
  167. package/docs/plugin-template/claude/package.json +16 -0
  168. package/docs/plugin-template/codex/.github/workflows/build.yml +51 -0
  169. package/docs/plugin-template/codex/README.md +147 -0
  170. package/docs/plugin-template/codex/package.json +17 -0
  171. package/docs/plugin-template/opencode/.github/workflows/build.yml +61 -0
  172. package/docs/plugin-template/opencode/README.md +121 -0
  173. package/docs/plugin-template/opencode/package.json +25 -0
  174. package/package.json +36 -28
  175. package/agents/architect/meta.yml +0 -13
  176. package/agents/designer/meta.yml +0 -13
  177. package/agents/engineer/meta.yml +0 -11
  178. package/agents/postdoc/meta.yml +0 -13
  179. package/agents/researcher/meta.yml +0 -12
  180. package/agents/reviewer/meta.yml +0 -12
  181. package/agents/strategist/meta.yml +0 -13
  182. package/agents/tester/meta.yml +0 -12
  183. package/agents/writer/meta.yml +0 -11
  184. package/conformance/README.md +0 -311
  185. package/conformance/examples/plan.extension.schema.example.json +0 -25
  186. package/conformance/lifecycle/README.md +0 -48
  187. package/conformance/lifecycle/agent-complete.json +0 -44
  188. package/conformance/lifecycle/agent-resume.json +0 -43
  189. package/conformance/lifecycle/agent-spawn.json +0 -36
  190. package/conformance/lifecycle/memory-access-record.json +0 -27
  191. package/conformance/lifecycle/session-end.json +0 -48
  192. package/conformance/scenarios/full-plan-cycle.json +0 -147
  193. package/conformance/scenarios/task-deps-ordering.json +0 -95
  194. package/conformance/schema/fixture.schema.json +0 -354
  195. package/conformance/state-schemas/agent-tracker.schema.json +0 -63
  196. package/conformance/state-schemas/history.schema.json +0 -134
  197. package/conformance/state-schemas/memory-access.schema.json +0 -36
  198. package/conformance/state-schemas/plan.schema.json +0 -77
  199. package/conformance/state-schemas/tasks.schema.json +0 -98
  200. package/conformance/tools/artifact-write.json +0 -97
  201. package/conformance/tools/context.json +0 -172
  202. package/conformance/tools/history-search.json +0 -219
  203. package/conformance/tools/plan-decide.json +0 -139
  204. package/conformance/tools/plan-start.json +0 -81
  205. package/conformance/tools/plan-status.json +0 -127
  206. package/conformance/tools/plan-update.json +0 -341
  207. package/conformance/tools/task-add.json +0 -156
  208. package/conformance/tools/task-close.json +0 -161
  209. package/conformance/tools/task-list.json +0 -177
  210. package/conformance/tools/task-update.json +0 -167
  211. package/docs/behavioral-contracts.md +0 -145
  212. package/docs/consumer-implementation-guide.md +0 -840
  213. package/docs/memory-lifecycle-contract.md +0 -119
  214. package/docs/nexus-layout.md +0 -224
  215. package/docs/nexus-outputs-contract.md +0 -344
  216. package/docs/nexus-state-overview.md +0 -170
  217. package/docs/nexus-tools-contract.md +0 -438
  218. package/manifest.json +0 -448
  219. package/schema/README.md +0 -69
  220. package/schema/agent.schema.json +0 -23
  221. package/schema/common.schema.json +0 -17
  222. package/schema/manifest.schema.json +0 -78
  223. package/schema/memory-policy.schema.json +0 -98
  224. package/schema/skill.schema.json +0 -54
  225. package/schema/task-exceptions.schema.json +0 -40
  226. package/schema/vocabulary.schema.json +0 -167
  227. package/scripts/.gitkeep +0 -0
  228. package/scripts/conformance-coverage.ts +0 -466
  229. package/scripts/import-from-claude-nexus.ts +0 -403
  230. package/scripts/lib/frontmatter.ts +0 -71
  231. package/scripts/lib/lint.ts +0 -348
  232. package/scripts/lib/structure.ts +0 -159
  233. package/scripts/lib/validate.ts +0 -796
  234. package/scripts/validate.ts +0 -90
  235. package/skills/nx-init/meta.yml +0 -8
  236. package/skills/nx-plan/meta.yml +0 -10
  237. package/skills/nx-run/meta.yml +0 -8
  238. package/skills/nx-sync/meta.yml +0 -7
  239. package/vocabulary/capabilities.yml +0 -65
  240. package/vocabulary/categories.yml +0 -11
  241. package/vocabulary/invocations.yml +0 -147
  242. package/vocabulary/memory_policy.yml +0 -88
  243. package/vocabulary/resume-tiers.yml +0 -11
  244. package/vocabulary/tags.yml +0 -60
  245. package/vocabulary/task-exceptions.yml +0 -29
@@ -0,0 +1,100 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const CORE_INDEX_SIZE_LIMIT = 2 * 1024; // 2KB
4
+ function loadValidRoles(cwd) {
5
+ const agentsDir = join(cwd, "assets/agents");
6
+ const roles = [];
7
+ if (existsSync(agentsDir)) {
8
+ for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
9
+ if (entry.isDirectory())
10
+ roles.push(entry.name);
11
+ }
12
+ }
13
+ return roles;
14
+ }
15
+ function readFirstLine(path) {
16
+ try {
17
+ const content = readFileSync(path, "utf-8");
18
+ const firstNonEmpty = content.split("\n").find((l) => l.trim().length > 0) ?? "";
19
+ return firstNonEmpty.replace(/^#+\s*/, "").slice(0, 80);
20
+ }
21
+ catch {
22
+ return "";
23
+ }
24
+ }
25
+ function buildCoreIndex(cwd) {
26
+ const entries = [];
27
+ for (const sub of [".nexus/memory", ".nexus/context"]) {
28
+ const absDir = join(cwd, sub);
29
+ if (!existsSync(absDir))
30
+ continue;
31
+ for (const f of readdirSync(absDir, { withFileTypes: true })) {
32
+ if (!f.isFile() || !f.name.endsWith(".md"))
33
+ continue;
34
+ const full = join(absDir, f.name);
35
+ entries.push({
36
+ path: `${sub}/${f.name}`,
37
+ mtime: statSync(full).mtimeMs,
38
+ line: readFirstLine(full),
39
+ });
40
+ }
41
+ }
42
+ entries.sort((a, b) => b.mtime - a.mtime);
43
+ const lines = [];
44
+ let bytes = 0;
45
+ for (const e of entries) {
46
+ const formatted = `- ${e.path}: ${e.line}`;
47
+ if (bytes + formatted.length + 1 > CORE_INDEX_SIZE_LIMIT)
48
+ break;
49
+ lines.push(formatted);
50
+ bytes += formatted.length + 1;
51
+ }
52
+ return lines.length > 0
53
+ ? "Available memory/context:\n" + lines.join("\n")
54
+ : "";
55
+ }
56
+ function getResumeCount(cwd, sessionId, agentId) {
57
+ const trackerPath = join(cwd, ".nexus/state", sessionId, "agent-tracker.json");
58
+ if (!existsSync(trackerPath))
59
+ return 0;
60
+ try {
61
+ const tracker = JSON.parse(readFileSync(trackerPath, "utf-8"));
62
+ const entry = Array.isArray(tracker)
63
+ ? tracker.find((e) => e.agent_id === agentId)
64
+ : null;
65
+ return entry?.resume_count ?? 0;
66
+ }
67
+ catch {
68
+ return 0;
69
+ }
70
+ }
71
+ const handler = async (input) => {
72
+ if (input.hook_event_name !== "SubagentStart")
73
+ return;
74
+ const { cwd, session_id, agent_type, agent_id } = input;
75
+ // fresh only — skip on resume
76
+ const resumeCount = getResumeCount(cwd, session_id, agent_id);
77
+ if (resumeCount > 0)
78
+ return;
79
+ // unregistered role: silent skip
80
+ const validRoles = loadValidRoles(cwd);
81
+ if (!validRoles.includes(agent_type))
82
+ return;
83
+ const parts = [];
84
+ const coreIndex = buildCoreIndex(cwd);
85
+ if (coreIndex) {
86
+ parts.push(`<system-notice>\n${coreIndex}\n</system-notice>`);
87
+ }
88
+ const rulePath = join(cwd, ".nexus/rules", `${agent_type}.md`);
89
+ if (existsSync(rulePath)) {
90
+ const ruleContent = readFileSync(rulePath, "utf-8").trim();
91
+ if (ruleContent) {
92
+ parts.push(`<system-notice>\nCustom rule for ${agent_type}:\n${ruleContent}\n</system-notice>`);
93
+ }
94
+ }
95
+ if (parts.length === 0)
96
+ return;
97
+ return { additional_context: parts.join("\n\n") };
98
+ };
99
+ export default handler;
100
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../assets/hooks/agent-bootstrap/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { HookHandler } from "../../../src/hooks/types.js";
2
+ declare const handler: HookHandler;
3
+ export default handler;
4
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../assets/hooks/agent-finalize/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAK/D,QAAA,MAAM,OAAO,EAAE,WAoEd,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { updateJsonFileLocked } from "../../../src/shared/json-store.js";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ const handler = async (input) => {
5
+ if (input.hook_event_name !== "SubagentStop")
6
+ return;
7
+ const { cwd, session_id, agent_type, agent_id } = input;
8
+ const lastMessage = (input.last_assistant_message ?? "").slice(0, 500);
9
+ const sessionDir = join(cwd, ".nexus/state", session_id);
10
+ const trackerPath = join(sessionDir, "agent-tracker.json");
11
+ const toolLogPath = join(sessionDir, "tool-log.jsonl");
12
+ const tasksPath = join(sessionDir, "tasks.json");
13
+ // 1. tracker update + files_touched aggregation (locked)
14
+ await updateJsonFileLocked(trackerPath, [], (tracker) => {
15
+ const entry = tracker.find((e) => e["agent_id"] === agent_id);
16
+ if (!entry)
17
+ return tracker;
18
+ entry["status"] = "completed";
19
+ entry["stopped_at"] = new Date().toISOString();
20
+ entry["last_message"] = lastMessage;
21
+ if (existsSync(toolLogPath)) {
22
+ const files = new Set();
23
+ const raw = readFileSync(toolLogPath, "utf-8");
24
+ for (const line of raw.split("\n")) {
25
+ if (!line.trim())
26
+ continue;
27
+ try {
28
+ const log = JSON.parse(line);
29
+ if (log["agent_id"] === agent_id && typeof log["file"] === "string") {
30
+ files.add(log["file"]);
31
+ }
32
+ }
33
+ catch {
34
+ // skip malformed lines
35
+ }
36
+ }
37
+ entry["files_touched"] = [...files];
38
+ }
39
+ return tracker;
40
+ });
41
+ // 2. pending tasks alert (owner.role === agent_type)
42
+ if (!existsSync(tasksPath))
43
+ return;
44
+ try {
45
+ const tasksData = JSON.parse(readFileSync(tasksPath, "utf-8"));
46
+ const tasks = Array.isArray(tasksData?.["tasks"])
47
+ ? tasksData["tasks"]
48
+ : [];
49
+ const incomplete = tasks.filter((t) => t["owner"]?.["role"] === agent_type &&
50
+ t["status"] !== "completed");
51
+ if (incomplete.length === 0)
52
+ return;
53
+ const ids = incomplete.map((t) => t["id"]).join(", ");
54
+ return {
55
+ additional_context: `<system-notice>\nSubagent "${agent_type}" finished. Tasks still pending with this role: ${ids}. Review status and coordinate remaining subagent delegation.\n</system-notice>`,
56
+ };
57
+ }
58
+ catch {
59
+ return;
60
+ }
61
+ };
62
+ export default handler;
63
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../assets/hooks/agent-finalize/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,OAAO,GAAgB,KAAK,EAAE,KAAK,EAAE,EAAE;IAC3C,IAAI,KAAK,CAAC,eAAe,KAAK,cAAc;QAAE,OAAO;IAErD,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACxD,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEvE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAEjD,yDAAyD;IACzD,MAAM,oBAAoB,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,OAAkB,EAAE,EAAE;QACjE,MAAM,KAAK,GAAI,OAAqC,CAAC,IAAI,CACvD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,QAAQ,CAClC,CAAC;QACF,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAC;QAE3B,KAAK,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC;QAC9B,KAAK,CAAC,YAAY,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/C,KAAK,CAAC,cAAc,CAAC,GAAG,WAAW,CAAC;QAEpC,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;YAChC,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAC/C,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;oBAAE,SAAS;gBAC3B,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;oBACxD,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ,EAAE,CAAC;wBACpE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,uBAAuB;gBACzB,CAAC;YACH,CAAC;YACD,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,qDAAqD;IACrD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO;IAEnC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAY,CAAC;QAC1E,MAAM,KAAK,GAA8B,KAAK,CAAC,OAAO,CACnD,SAAqC,EAAE,CAAC,OAAO,CAAC,CAClD;YACC,CAAC,CAAG,SAAqC,CAAC,OAAO,CAA+B;YAChF,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CACH,CAAC,CAAC,OAAO,CAAyC,EAAE,CAAC,MAAM,CAAC,KAAK,UAAU;YAC5E,CAAC,CAAC,QAAQ,CAAC,KAAK,WAAW,CAC9B,CAAC;QAEF,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEpC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,OAAO;YACL,kBAAkB,EAAE,8BAA8B,UAAU,mDAAmD,GAAG,iFAAiF;SACpM,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { HookHandler } from "../../../src/hooks/types.js";
2
+ declare const handler: HookHandler;
3
+ export default handler;
4
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../assets/hooks/post-tool-telemetry/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAY/D,QAAA,MAAM,OAAO,EAAE,WAkCd,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { appendJsonLine } from "../../../src/shared/json-store.js";
2
+ import { join, resolve, relative } from "node:path";
3
+ const EDIT_TOOLS = new Set(["Edit", "Write", "MultiEdit", "ApplyPatch", "NotebookEdit"]);
4
+ function isWithinMemory(filePath, projectRoot) {
5
+ const memRoot = resolve(projectRoot, ".nexus/memory");
6
+ const abs = resolve(filePath);
7
+ return abs.startsWith(memRoot + "/") || abs === memRoot;
8
+ }
9
+ const handler = async (input) => {
10
+ if (input.hook_event_name !== "PostToolUse")
11
+ return;
12
+ const { cwd, session_id, tool_name, agent_id } = input;
13
+ const toolInput = (input.tool_input ?? {});
14
+ // 1. Memory access tracking (Read)
15
+ if (tool_name === "Read") {
16
+ const filePath = toolInput.file_path;
17
+ if (filePath && isWithinMemory(filePath, cwd)) {
18
+ appendJsonLine(join(cwd, ".nexus/memory-access.jsonl"), {
19
+ path: relative(cwd, resolve(filePath)),
20
+ accessed_at: new Date().toISOString(),
21
+ agent: agent_id ?? null,
22
+ });
23
+ }
24
+ }
25
+ // 2. Tool-log append (edit tools + agent_id present)
26
+ if (EDIT_TOOLS.has(tool_name) && agent_id) {
27
+ const filePath = (toolInput.file_path ?? toolInput.notebook_path);
28
+ if (filePath) {
29
+ appendJsonLine(join(cwd, ".nexus/state", session_id, "tool-log.jsonl"), {
30
+ ts: new Date().toISOString(),
31
+ agent_id,
32
+ tool: tool_name,
33
+ file: relative(cwd, resolve(filePath)),
34
+ status: "ok",
35
+ });
36
+ }
37
+ }
38
+ };
39
+ export default handler;
40
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../assets/hooks/post-tool-telemetry/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEpD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC,CAAC;AAEzF,SAAS,cAAc,CAAC,QAAgB,EAAE,WAAmB;IAC3D,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,OAAO,CAAC;AAC1D,CAAC;AAED,MAAM,OAAO,GAAgB,KAAK,EAAE,KAAK,EAAE,EAAE;IAC3C,IAAI,KAAK,CAAC,eAAe,KAAK,aAAa;QAAE,OAAO;IAEpD,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACvD,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAA4B,CAAC;IAEtE,mCAAmC;IACnC,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,SAAS,CAAC,SAA+B,CAAC;QAC3D,IAAI,QAAQ,IAAI,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;YAC9C,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,4BAA4B,CAAC,EAAE;gBACtD,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACtC,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACrC,KAAK,EAAE,QAAQ,IAAI,IAAI;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,CAAC,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,aAAa,CAAuB,CAAC;QACxF,IAAI,QAAQ,EAAE,CAAC;YACb,cAAc,CACZ,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,CAAC,EACvD;gBACE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC5B,QAAQ;gBACR,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACtC,MAAM,EAAE,IAAI;aACb,CACF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { HookHandler } from "../../../src/hooks/types.js";
2
+ declare const handler: HookHandler;
3
+ export default handler;
4
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../assets/hooks/prompt-router/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAmB,MAAM,6BAA6B,CAAC;AAmGhF,QAAA,MAAM,OAAO,EAAE,WA+Jd,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,204 @@
1
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
2
+ import { join, resolve, dirname } from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+ import { expandInvocations, } from "../../../src/shared/invocations.js";
5
+ // Tag priority: specific variants first (m:gc > m, rule:name > rule, plan:auto > plan, init:reset > init)
6
+ const TAG_PATTERNS = [
7
+ { name: "plan:auto", regex: /\[plan:auto\]/ },
8
+ { name: "plan", regex: /\[plan\](?!\w)/ },
9
+ { name: "run", regex: /\[run\](?!\w)/ },
10
+ { name: "d", regex: /\[d\](?!\w)/ },
11
+ { name: "m:gc", regex: /\[m:gc\]/ },
12
+ { name: "m", regex: /\[m\](?!\w)/ },
13
+ { name: "rule:name", regex: /\[rule:([a-zA-Z0-9_-]+)\]/ },
14
+ { name: "rule", regex: /\[rule\](?!\w)/ },
15
+ { name: "sync", regex: /\[sync\](?!\w)/ },
16
+ { name: "init:reset", regex: /\[init:reset\]/ },
17
+ { name: "init", regex: /\[init\](?!\w)/ },
18
+ ];
19
+ // ---------------------------------------------------------------------------
20
+ // Invocations loader — cached per process
21
+ // ---------------------------------------------------------------------------
22
+ let _invocationsCache = null;
23
+ function loadInvocations() {
24
+ if (_invocationsCache)
25
+ return _invocationsCache;
26
+ const selfDir = new URL(".", import.meta.url).pathname;
27
+ // Walk up from handler directory to find assets/tools/tool-name-map.yml
28
+ let dir = selfDir;
29
+ while (dir !== "/") {
30
+ const candidate = resolve(dir, "assets/tools/tool-name-map.yml");
31
+ if (existsSync(candidate)) {
32
+ const raw = readFileSync(candidate, "utf-8");
33
+ const parsed = parseYaml(raw);
34
+ if (!parsed.invocations) {
35
+ throw new Error("[prompt-router] tool-name-map.yml missing 'invocations' section");
36
+ }
37
+ _invocationsCache = parsed.invocations;
38
+ return _invocationsCache;
39
+ }
40
+ const parent = dirname(dir);
41
+ if (parent === dir)
42
+ break;
43
+ dir = parent;
44
+ }
45
+ throw new Error(`[prompt-router] Cannot locate assets/tools/tool-name-map.yml from ${selfDir}`);
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Harness resolution
49
+ // ---------------------------------------------------------------------------
50
+ function resolveHarness() {
51
+ const h = process.env["NEXUS_HARNESS"];
52
+ if (h === "claude" || h === "opencode" || h === "codex")
53
+ return h;
54
+ if (h) {
55
+ process.stderr.write(`[prompt-router] Unknown NEXUS_HARNESS="${h}", falling back to "claude"\n`);
56
+ }
57
+ return "claude";
58
+ }
59
+ // ---------------------------------------------------------------------------
60
+ // Invocation expansion helper
61
+ // ---------------------------------------------------------------------------
62
+ function expand(template, harness) {
63
+ return expandInvocations(template, harness, loadInvocations());
64
+ }
65
+ // ---------------------------------------------------------------------------
66
+ // Rule target loader
67
+ // ---------------------------------------------------------------------------
68
+ function loadValidRuleTargets(cwd) {
69
+ const targets = [];
70
+ for (const dir of ["assets/agents", "assets/skills"]) {
71
+ const absDir = join(cwd, dir);
72
+ if (!existsSync(absDir))
73
+ continue;
74
+ for (const entry of readdirSync(absDir, { withFileTypes: true })) {
75
+ if (entry.isDirectory())
76
+ targets.push(entry.name);
77
+ }
78
+ }
79
+ return targets;
80
+ }
81
+ // ---------------------------------------------------------------------------
82
+ // Handler
83
+ // ---------------------------------------------------------------------------
84
+ const handler = async (input) => {
85
+ if (input.hook_event_name !== "UserPromptSubmit")
86
+ return;
87
+ const prompt = input.prompt;
88
+ const detected = [];
89
+ // Detect all tags — use seen Set keyed on base tag name to prevent duplicates
90
+ // (e.g. plan:auto and plan share base "plan"; whichever appears first wins)
91
+ const seen = new Set();
92
+ for (const { name, regex } of TAG_PATTERNS) {
93
+ const m = regex.exec(prompt);
94
+ if (!m)
95
+ continue;
96
+ const base = name.split(":")[0];
97
+ if (seen.has(base))
98
+ continue;
99
+ seen.add(base);
100
+ detected.push({ name, arg: m[1] });
101
+ }
102
+ const sessionDir = join(input.cwd, ".nexus/state", input.session_id);
103
+ const planPath = join(sessionDir, "plan.json");
104
+ const tasksPath = join(sessionDir, "tasks.json");
105
+ const hasPlan = existsSync(planPath);
106
+ const hasTasks = existsSync(tasksPath);
107
+ const harness = resolveHarness();
108
+ const notices = [];
109
+ let decision;
110
+ let block_reason;
111
+ for (const tag of detected) {
112
+ switch (tag.name) {
113
+ case "plan":
114
+ notices.push(`<system-notice>[plan] tag detected. ${expand('{{skill_activation skill="nx-plan"}}', harness)} for structured planning.</system-notice>`);
115
+ break;
116
+ case "plan:auto":
117
+ notices.push(`<system-notice>[plan:auto] tag detected. ${expand('{{skill_activation skill="nx-plan" mode="auto"}}', harness)} for structured planning.</system-notice>`);
118
+ break;
119
+ case "run":
120
+ if (!hasTasks) {
121
+ notices.push(`<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>`);
122
+ }
123
+ else {
124
+ notices.push(`<system-notice>[run] tag detected. ${expand('{{skill_activation skill="nx-run"}}', harness)} to execute tasks.</system-notice>`);
125
+ }
126
+ break;
127
+ case "d":
128
+ if (!hasPlan) {
129
+ decision = "block";
130
+ block_reason =
131
+ `[d] tag requires an active plan session. ${expand('{{skill_activation skill="nx-plan"}}', harness)} first.`;
132
+ }
133
+ else {
134
+ notices.push(`<system-notice>[d] tag detected. Record decision via \`nx_plan_decide(issue_id, summary)\` MCP tool.</system-notice>`);
135
+ }
136
+ break;
137
+ case "m":
138
+ notices.push(`<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>`);
139
+ break;
140
+ case "m:gc":
141
+ notices.push(`<system-notice>[m:gc] tag detected. Review \`.nexus/memory/\` for stale or duplicate entries and consolidate.</system-notice>`);
142
+ break;
143
+ case "rule": {
144
+ const valid = loadValidRuleTargets(input.cwd);
145
+ notices.push(`<system-notice>[rule] tag detected. Determine target from intent. Valid targets: ${valid.join(", ")}. Update \`.nexus/rules/<target>.md\`.</system-notice>`);
146
+ break;
147
+ }
148
+ case "rule:name": {
149
+ const valid = loadValidRuleTargets(input.cwd);
150
+ const name = tag.arg ?? "";
151
+ if (!valid.includes(name)) {
152
+ decision = "block";
153
+ block_reason = `[rule:${name}] invalid — must be one of: ${valid.join(", ")}`;
154
+ }
155
+ else {
156
+ notices.push(`<system-notice>[rule:${name}] tag detected. Update \`.nexus/rules/${name}.md\` with user's directive.</system-notice>`);
157
+ }
158
+ break;
159
+ }
160
+ case "sync":
161
+ notices.push(`<system-notice>[sync] tag detected. ${expand('{{skill_activation skill="nx-sync"}}', harness)} to synchronize \`.nexus/context/\`.</system-notice>`);
162
+ break;
163
+ case "init":
164
+ notices.push(`<system-notice>[init] tag detected. ${expand('{{skill_activation skill="nx-init"}}', harness)} for project onboarding.</system-notice>`);
165
+ break;
166
+ case "init:reset":
167
+ notices.push(`<system-notice>[init:reset] tag detected. ${expand('{{skill_activation skill="nx-init" mode="reset"}}', harness)} for full re-initialization.</system-notice>`);
168
+ break;
169
+ }
170
+ }
171
+ // No tags detected + active state → emit state notice
172
+ if (detected.length === 0) {
173
+ if (hasPlan) {
174
+ try {
175
+ const plan = JSON.parse(readFileSync(planPath, "utf-8"));
176
+ const pending = plan.issues?.filter((i) => i.status === "pending").length ?? 0;
177
+ notices.push(`<system-notice>Active plan session: "${plan.topic ?? "(unknown)"}", ${pending} issues pending.</system-notice>`);
178
+ }
179
+ catch {
180
+ // Malformed plan.json — skip notice
181
+ }
182
+ }
183
+ else if (hasTasks) {
184
+ try {
185
+ const tasks = JSON.parse(readFileSync(tasksPath, "utf-8"));
186
+ const pending = tasks.tasks?.filter((t) => t.status !== "completed").length ?? 0;
187
+ if (pending > 0) {
188
+ notices.push(`<system-notice>Active run session: ${pending} tasks remaining in tasks.json.</system-notice>`);
189
+ }
190
+ }
191
+ catch {
192
+ // Malformed tasks.json — skip notice
193
+ }
194
+ }
195
+ }
196
+ if (decision === "block") {
197
+ return { decision, block_reason };
198
+ }
199
+ if (notices.length === 0)
200
+ return;
201
+ return { additional_context: notices.join("\n\n") };
202
+ };
203
+ export default handler;
204
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../assets/hooks/prompt-router/handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { HookHandler } from "../../../src/hooks/types.js";
2
+ declare const handler: HookHandler;
3
+ export default handler;
4
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../assets/hooks/session-init/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAI/D,QAAA,MAAM,OAAO,EAAE,WAuBd,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { join, basename } from "node:path";
3
+ const handler = async (input) => {
4
+ if (input.hook_event_name !== "SessionStart")
5
+ return;
6
+ // Sanitize session_id to prevent path traversal
7
+ const safeSid = basename(input.session_id);
8
+ if (!safeSid || safeSid.startsWith(".") || safeSid.includes("/")) {
9
+ process.stderr.write(`[session-init] invalid session_id: ${input.session_id}\n`);
10
+ return;
11
+ }
12
+ const sessionDir = join(input.cwd, ".nexus/state", safeSid);
13
+ // Ensure directory exists (idempotent)
14
+ mkdirSync(sessionDir, { recursive: true });
15
+ // Initialize per-session state files — overwrite unconditionally (resume is intentional)
16
+ writeFileSync(join(sessionDir, "agent-tracker.json"), "[]");
17
+ writeFileSync(join(sessionDir, "tool-log.jsonl"), "");
18
+ // plan.json and tasks.json are MCP responsibility — not touched here
19
+ // memory-access.jsonl is project-level — not touched here
20
+ // No additional_context returned (decided: no context injection at session start)
21
+ };
22
+ export default handler;
23
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../assets/hooks/session-init/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,OAAO,GAAgB,KAAK,EAAE,KAAK,EAAE,EAAE;IAC3C,IAAI,KAAK,CAAC,eAAe,KAAK,cAAc;QAAE,OAAO;IAErD,gDAAgD;IAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;QACjF,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;IAE5D,uCAAuC;IACvC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3C,yFAAyF;IACzF,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5D,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEtD,qEAAqE;IACrE,0DAA0D;IAE1D,kFAAkF;AACpF,CAAC,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,105 @@
1
+ // assets/hooks/agent-bootstrap/handler.ts
2
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ var CORE_INDEX_SIZE_LIMIT = 2 * 1024;
5
+ function loadValidRoles(cwd) {
6
+ const agentsDir = join(cwd, "assets/agents");
7
+ const roles = [];
8
+ if (existsSync(agentsDir)) {
9
+ for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
10
+ if (entry.isDirectory())
11
+ roles.push(entry.name);
12
+ }
13
+ }
14
+ return roles;
15
+ }
16
+ function readFirstLine(path) {
17
+ try {
18
+ const content = readFileSync(path, "utf-8");
19
+ const firstNonEmpty = content.split(`
20
+ `).find((l) => l.trim().length > 0) ?? "";
21
+ return firstNonEmpty.replace(/^#+\s*/, "").slice(0, 80);
22
+ } catch {
23
+ return "";
24
+ }
25
+ }
26
+ function buildCoreIndex(cwd) {
27
+ const entries = [];
28
+ for (const sub of [".nexus/memory", ".nexus/context"]) {
29
+ const absDir = join(cwd, sub);
30
+ if (!existsSync(absDir))
31
+ continue;
32
+ for (const f of readdirSync(absDir, { withFileTypes: true })) {
33
+ if (!f.isFile() || !f.name.endsWith(".md"))
34
+ continue;
35
+ const full = join(absDir, f.name);
36
+ entries.push({
37
+ path: `${sub}/${f.name}`,
38
+ mtime: statSync(full).mtimeMs,
39
+ line: readFirstLine(full)
40
+ });
41
+ }
42
+ }
43
+ entries.sort((a, b) => b.mtime - a.mtime);
44
+ const lines = [];
45
+ let bytes = 0;
46
+ for (const e of entries) {
47
+ const formatted = `- ${e.path}: ${e.line}`;
48
+ if (bytes + formatted.length + 1 > CORE_INDEX_SIZE_LIMIT)
49
+ break;
50
+ lines.push(formatted);
51
+ bytes += formatted.length + 1;
52
+ }
53
+ return lines.length > 0 ? `Available memory/context:
54
+ ` + lines.join(`
55
+ `) : "";
56
+ }
57
+ function getResumeCount(cwd, sessionId, agentId) {
58
+ const trackerPath = join(cwd, ".nexus/state", sessionId, "agent-tracker.json");
59
+ if (!existsSync(trackerPath))
60
+ return 0;
61
+ try {
62
+ const tracker = JSON.parse(readFileSync(trackerPath, "utf-8"));
63
+ const entry = Array.isArray(tracker) ? tracker.find((e) => e.agent_id === agentId) : null;
64
+ return entry?.resume_count ?? 0;
65
+ } catch {
66
+ return 0;
67
+ }
68
+ }
69
+ var handler = async (input) => {
70
+ if (input.hook_event_name !== "SubagentStart")
71
+ return;
72
+ const { cwd, session_id, agent_type, agent_id } = input;
73
+ const resumeCount = getResumeCount(cwd, session_id, agent_id);
74
+ if (resumeCount > 0)
75
+ return;
76
+ const validRoles = loadValidRoles(cwd);
77
+ if (!validRoles.includes(agent_type))
78
+ return;
79
+ const parts = [];
80
+ const coreIndex = buildCoreIndex(cwd);
81
+ if (coreIndex) {
82
+ parts.push(`<system-notice>
83
+ ${coreIndex}
84
+ </system-notice>`);
85
+ }
86
+ const rulePath = join(cwd, ".nexus/rules", `${agent_type}.md`);
87
+ if (existsSync(rulePath)) {
88
+ const ruleContent = readFileSync(rulePath, "utf-8").trim();
89
+ if (ruleContent) {
90
+ parts.push(`<system-notice>
91
+ Custom rule for ${agent_type}:
92
+ ${ruleContent}
93
+ </system-notice>`);
94
+ }
95
+ }
96
+ if (parts.length === 0)
97
+ return;
98
+ return { additional_context: parts.join(`
99
+
100
+ `) };
101
+ };
102
+ var handler_default = handler;
103
+ export {
104
+ handler_default as default
105
+ };