@goondocks/myco 0.17.2 → 0.18.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 (182) hide show
  1. package/README.md +14 -22
  2. package/bin/myco-run +15 -2
  3. package/dist/{agent-run-7AYHXIEF.js → agent-run-2NFYMQXW.js} +7 -7
  4. package/dist/{agent-tasks-UUIFKBD4.js → agent-tasks-MEIYLXGN.js} +7 -7
  5. package/dist/{chunk-XD3NEN3Q.js → chunk-2V7HR7HB.js} +2 -2
  6. package/dist/{chunk-CTF7TQMJ.js → chunk-55QEICRO.js} +14 -4
  7. package/dist/chunk-55QEICRO.js.map +1 -0
  8. package/dist/{chunk-DT42247G.js → chunk-75AZFBFW.js} +3 -3
  9. package/dist/{chunk-ZSJPI5MS.js → chunk-7OYXB2NM.js} +2 -2
  10. package/dist/{chunk-XZWFMMJR.js → chunk-BUIR3JWM.js} +3 -3
  11. package/dist/{chunk-7DAH5GLC.js → chunk-CKJAWZQE.js} +5 -1
  12. package/dist/chunk-CKJAWZQE.js.map +1 -0
  13. package/dist/{chunk-ML6GTPZU.js → chunk-CML4MCYF.js} +2 -2
  14. package/dist/{chunk-BZDZORVP.js → chunk-DLFDBKEV.js} +4 -4
  15. package/dist/{chunk-SI5BBQAT.js → chunk-EO2RQW4S.js} +2 -2
  16. package/dist/{chunk-EBIYONNZ.js → chunk-FABWUX5G.js} +20 -2
  17. package/dist/chunk-FABWUX5G.js.map +1 -0
  18. package/dist/{chunk-RMJPQZGF.js → chunk-JDI4DPWD.js} +127 -125
  19. package/dist/chunk-JDI4DPWD.js.map +1 -0
  20. package/dist/chunk-JMOUFG6Y.js +65 -0
  21. package/dist/chunk-JMOUFG6Y.js.map +1 -0
  22. package/dist/{chunk-HPZ7YAMA.js → chunk-KWTOCJLB.js} +3 -3
  23. package/dist/{chunk-F6C4IC6R.js → chunk-NI23QCHB.js} +3 -3
  24. package/dist/{chunk-IGBHLFV5.js → chunk-NZI7WBZI.js} +2 -2
  25. package/dist/{chunk-C3C5QVLK.js → chunk-O3TRN3RC.js} +2 -2
  26. package/dist/{chunk-UTLWSKDV.js → chunk-OW433Q4C.js} +2 -2
  27. package/dist/{chunk-5ZISXCDC.js → chunk-PFWIPRF6.js} +39 -5
  28. package/dist/chunk-PFWIPRF6.js.map +1 -0
  29. package/dist/{chunk-3NCVCGUZ.js → chunk-RAV5YMRU.js} +3 -3
  30. package/dist/{chunk-RKPTMHED.js → chunk-U3J2DDSR.js} +2 -2
  31. package/dist/{chunk-25WHTV4N.js → chunk-U7GJTVSX.js} +2 -2
  32. package/dist/{chunk-NUSTG3BH.js → chunk-VOCGURV7.js} +3 -3
  33. package/dist/{chunk-VVGZL2HX.js → chunk-WYOE4IAX.js} +153 -15
  34. package/dist/{chunk-VVGZL2HX.js.map → chunk-WYOE4IAX.js.map} +1 -1
  35. package/dist/{cli-WJVYP2QT.js → cli-IIMBALPV.js} +40 -40
  36. package/dist/{client-LZ3ZR4HC.js → client-VZCUISHZ.js} +4 -4
  37. package/dist/{config-ZQIMG3FB.js → config-DA4IUVFL.js} +3 -3
  38. package/dist/{detect-NJ2OREDP.js → detect-GEM3NVK6.js} +2 -2
  39. package/dist/{detect-providers-C64L3QET.js → detect-providers-PSVKXTWE.js} +4 -4
  40. package/dist/{doctor-XEPBNHM3.js → doctor-QYD34X7Q.js} +12 -12
  41. package/dist/{executor-NXKJU5KW.js → executor-NSPRTH4M.js} +17 -17
  42. package/dist/{init-BHVQAQ27.js → init-WYYL44KZ.js} +13 -13
  43. package/dist/{installer-45ZLP2RP.js → installer-BWJED3ED.js} +2 -2
  44. package/dist/{llm-KTD6SR55.js → llm-KEDHK3TQ.js} +4 -4
  45. package/dist/{loader-SHRKUKOS.js → loader-Q3P3R4UP.js} +3 -3
  46. package/dist/{loader-NEX3UF6U.js → loader-SKKUMT5C.js} +3 -3
  47. package/dist/{main-YFVBIRRK.js → main-6PY3ITQ5.js} +388 -125
  48. package/dist/main-6PY3ITQ5.js.map +1 -0
  49. package/dist/{open-2U7ZRGA3.js → open-HRFMJDQX.js} +7 -7
  50. package/dist/{post-compact-QIBMEWL3.js → post-compact-HT24YMAN.js} +7 -7
  51. package/dist/{post-tool-use-ICGFXDVY.js → post-tool-use-DENRI5WB.js} +6 -6
  52. package/dist/{post-tool-use-failure-C7TLH3XQ.js → post-tool-use-failure-A6SNJX42.js} +7 -7
  53. package/dist/{pre-compact-IF7K4TQK.js → pre-compact-3Q4BALCL.js} +7 -7
  54. package/dist/{provider-check-LTLQ6BUZ.js → provider-check-AE3L5Z6R.js} +4 -4
  55. package/dist/{registry-TFQ22Z7N.js → registry-O2NZLO3V.js} +4 -4
  56. package/dist/{remove-FBGM2QVJ.js → remove-YB5A6HY2.js} +9 -9
  57. package/dist/{resolution-events-HGKIJOTA.js → resolution-events-XWYLLDRK.js} +4 -4
  58. package/dist/{restart-TQEECRNW.js → restart-RGDVHELZ.js} +8 -8
  59. package/dist/{search-NN5FC4Z6.js → search-WOHT3G55.js} +8 -8
  60. package/dist/{server-XMWJ4GF7.js → server-6SUNYDV7.js} +4 -4
  61. package/dist/{session-GLPAFYPO.js → session-W3SKRFRV.js} +9 -9
  62. package/dist/{session-end-TI3ILRBC.js → session-end-OUTY7AFF.js} +6 -6
  63. package/dist/{session-start-PJLJDVJJ.js → session-start-5MB3LFOA.js} +24 -13
  64. package/dist/{session-start-PJLJDVJJ.js.map → session-start-5MB3LFOA.js.map} +1 -1
  65. package/dist/{setup-llm-AQSWLXCZ.js → setup-llm-ZMYGIQX5.js} +8 -8
  66. package/dist/src/cli.js +1 -1
  67. package/dist/src/daemon/main.js +1 -1
  68. package/dist/src/hooks/post-tool-use.js +1 -1
  69. package/dist/src/hooks/session-end.js +1 -1
  70. package/dist/src/hooks/session-start.js +1 -1
  71. package/dist/src/hooks/stop.js +1 -1
  72. package/dist/src/hooks/user-prompt-submit.js +1 -1
  73. package/dist/src/mcp/server.js +1 -1
  74. package/dist/src/symbionts/manifests/codex.yaml +47 -0
  75. package/dist/src/symbionts/templates/claude-code/hooks.json +12 -12
  76. package/dist/src/symbionts/templates/claude-code/settings.json +3 -3
  77. package/dist/src/symbionts/templates/codex/hooks.json +4 -4
  78. package/dist/src/symbionts/templates/cursor/hooks.json +9 -9
  79. package/dist/src/symbionts/templates/cursor/settings.json +2 -2
  80. package/dist/src/symbionts/templates/gemini/hooks.json +6 -6
  81. package/dist/src/symbionts/templates/gemini/settings.json +2 -2
  82. package/dist/src/symbionts/templates/myco-run.cjs +44 -0
  83. package/dist/src/symbionts/templates/opencode/settings.json +2 -2
  84. package/dist/src/symbionts/templates/vscode-copilot/hooks.json +7 -7
  85. package/dist/src/symbionts/templates/vscode-copilot/settings.json +2 -2
  86. package/dist/src/symbionts/templates/windsurf/hooks.json +4 -4
  87. package/dist/src/symbionts/templates/windsurf/settings.json +2 -2
  88. package/dist/src/worker/package-lock.json +4338 -0
  89. package/dist/src/worker/package.json +5 -0
  90. package/dist/src/worker/src/index.ts +50 -63
  91. package/dist/src/worker/src/mcp/auth.ts +65 -0
  92. package/dist/src/worker/src/mcp/server.ts +53 -0
  93. package/dist/src/worker/src/mcp/tools/context.ts +13 -0
  94. package/dist/src/worker/src/mcp/tools/get.ts +15 -0
  95. package/dist/src/worker/src/mcp/tools/graph.ts +35 -0
  96. package/dist/src/worker/src/mcp/tools/search.ts +32 -0
  97. package/dist/src/worker/src/mcp/tools/sessions.ts +24 -0
  98. package/dist/src/worker/src/mcp/tools/skills.ts +16 -0
  99. package/dist/src/worker/src/mcp/tools/team.ts +9 -0
  100. package/dist/src/worker/src/schema.ts +3 -1
  101. package/dist/src/worker/src/search-helpers.ts +70 -0
  102. package/dist/src/worker/wrangler.toml +9 -0
  103. package/dist/{stats-BISBIBXZ.js → stats-DGI6B3HX.js} +9 -9
  104. package/dist/{stop-47BJ42EO.js → stop-YGHODSP7.js} +6 -6
  105. package/dist/{stop-failure-VU5BTLWX.js → stop-failure-7IJTPJ6W.js} +7 -7
  106. package/dist/{subagent-start-SPTKQRHU.js → subagent-start-ZBQ5PJB5.js} +7 -7
  107. package/dist/{subagent-stop-UU75BYLC.js → subagent-stop-N2TDQU2D.js} +7 -7
  108. package/dist/{task-completed-MVDO7TZF.js → task-completed-BDLMRSBB.js} +7 -7
  109. package/dist/{team-7X64J4Y6.js → team-2ZFGTSIN.js} +97 -14
  110. package/dist/team-2ZFGTSIN.js.map +1 -0
  111. package/dist/ui/assets/{index-rpmSpJpm.js → index-DtT9_nlT.js} +120 -120
  112. package/dist/ui/index.html +1 -1
  113. package/dist/{update-DA7VEXOS.js → update-STLAN7LR.js} +18 -9
  114. package/dist/update-STLAN7LR.js.map +1 -0
  115. package/dist/{user-prompt-submit-ADZ4NTVO.js → user-prompt-submit-4IBFUYQ3.js} +27 -7
  116. package/dist/user-prompt-submit-4IBFUYQ3.js.map +1 -0
  117. package/dist/{verify-QYSERHF7.js → verify-EJYPO7QA.js} +5 -5
  118. package/dist/{version-A72TAL2J.js → version-YPBIKH77.js} +2 -2
  119. package/package.json +1 -1
  120. package/dist/chunk-5ZISXCDC.js.map +0 -1
  121. package/dist/chunk-7DAH5GLC.js.map +0 -1
  122. package/dist/chunk-CTF7TQMJ.js.map +0 -1
  123. package/dist/chunk-EBIYONNZ.js.map +0 -1
  124. package/dist/chunk-RMJPQZGF.js.map +0 -1
  125. package/dist/main-YFVBIRRK.js.map +0 -1
  126. package/dist/src/symbionts/templates/hook-guard.cjs +0 -19
  127. package/dist/team-7X64J4Y6.js.map +0 -1
  128. package/dist/update-DA7VEXOS.js.map +0 -1
  129. package/dist/user-prompt-submit-ADZ4NTVO.js.map +0 -1
  130. /package/dist/{agent-run-7AYHXIEF.js.map → agent-run-2NFYMQXW.js.map} +0 -0
  131. /package/dist/{agent-tasks-UUIFKBD4.js.map → agent-tasks-MEIYLXGN.js.map} +0 -0
  132. /package/dist/{chunk-XD3NEN3Q.js.map → chunk-2V7HR7HB.js.map} +0 -0
  133. /package/dist/{chunk-DT42247G.js.map → chunk-75AZFBFW.js.map} +0 -0
  134. /package/dist/{chunk-ZSJPI5MS.js.map → chunk-7OYXB2NM.js.map} +0 -0
  135. /package/dist/{chunk-XZWFMMJR.js.map → chunk-BUIR3JWM.js.map} +0 -0
  136. /package/dist/{chunk-ML6GTPZU.js.map → chunk-CML4MCYF.js.map} +0 -0
  137. /package/dist/{chunk-BZDZORVP.js.map → chunk-DLFDBKEV.js.map} +0 -0
  138. /package/dist/{chunk-SI5BBQAT.js.map → chunk-EO2RQW4S.js.map} +0 -0
  139. /package/dist/{chunk-HPZ7YAMA.js.map → chunk-KWTOCJLB.js.map} +0 -0
  140. /package/dist/{chunk-F6C4IC6R.js.map → chunk-NI23QCHB.js.map} +0 -0
  141. /package/dist/{chunk-IGBHLFV5.js.map → chunk-NZI7WBZI.js.map} +0 -0
  142. /package/dist/{chunk-C3C5QVLK.js.map → chunk-O3TRN3RC.js.map} +0 -0
  143. /package/dist/{chunk-UTLWSKDV.js.map → chunk-OW433Q4C.js.map} +0 -0
  144. /package/dist/{chunk-3NCVCGUZ.js.map → chunk-RAV5YMRU.js.map} +0 -0
  145. /package/dist/{chunk-RKPTMHED.js.map → chunk-U3J2DDSR.js.map} +0 -0
  146. /package/dist/{chunk-25WHTV4N.js.map → chunk-U7GJTVSX.js.map} +0 -0
  147. /package/dist/{chunk-NUSTG3BH.js.map → chunk-VOCGURV7.js.map} +0 -0
  148. /package/dist/{cli-WJVYP2QT.js.map → cli-IIMBALPV.js.map} +0 -0
  149. /package/dist/{client-LZ3ZR4HC.js.map → client-VZCUISHZ.js.map} +0 -0
  150. /package/dist/{config-ZQIMG3FB.js.map → config-DA4IUVFL.js.map} +0 -0
  151. /package/dist/{detect-NJ2OREDP.js.map → detect-GEM3NVK6.js.map} +0 -0
  152. /package/dist/{detect-providers-C64L3QET.js.map → detect-providers-PSVKXTWE.js.map} +0 -0
  153. /package/dist/{doctor-XEPBNHM3.js.map → doctor-QYD34X7Q.js.map} +0 -0
  154. /package/dist/{executor-NXKJU5KW.js.map → executor-NSPRTH4M.js.map} +0 -0
  155. /package/dist/{init-BHVQAQ27.js.map → init-WYYL44KZ.js.map} +0 -0
  156. /package/dist/{installer-45ZLP2RP.js.map → installer-BWJED3ED.js.map} +0 -0
  157. /package/dist/{llm-KTD6SR55.js.map → llm-KEDHK3TQ.js.map} +0 -0
  158. /package/dist/{loader-NEX3UF6U.js.map → loader-Q3P3R4UP.js.map} +0 -0
  159. /package/dist/{loader-SHRKUKOS.js.map → loader-SKKUMT5C.js.map} +0 -0
  160. /package/dist/{open-2U7ZRGA3.js.map → open-HRFMJDQX.js.map} +0 -0
  161. /package/dist/{post-compact-QIBMEWL3.js.map → post-compact-HT24YMAN.js.map} +0 -0
  162. /package/dist/{post-tool-use-ICGFXDVY.js.map → post-tool-use-DENRI5WB.js.map} +0 -0
  163. /package/dist/{post-tool-use-failure-C7TLH3XQ.js.map → post-tool-use-failure-A6SNJX42.js.map} +0 -0
  164. /package/dist/{pre-compact-IF7K4TQK.js.map → pre-compact-3Q4BALCL.js.map} +0 -0
  165. /package/dist/{provider-check-LTLQ6BUZ.js.map → provider-check-AE3L5Z6R.js.map} +0 -0
  166. /package/dist/{registry-TFQ22Z7N.js.map → registry-O2NZLO3V.js.map} +0 -0
  167. /package/dist/{remove-FBGM2QVJ.js.map → remove-YB5A6HY2.js.map} +0 -0
  168. /package/dist/{resolution-events-HGKIJOTA.js.map → resolution-events-XWYLLDRK.js.map} +0 -0
  169. /package/dist/{restart-TQEECRNW.js.map → restart-RGDVHELZ.js.map} +0 -0
  170. /package/dist/{search-NN5FC4Z6.js.map → search-WOHT3G55.js.map} +0 -0
  171. /package/dist/{server-XMWJ4GF7.js.map → server-6SUNYDV7.js.map} +0 -0
  172. /package/dist/{session-GLPAFYPO.js.map → session-W3SKRFRV.js.map} +0 -0
  173. /package/dist/{session-end-TI3ILRBC.js.map → session-end-OUTY7AFF.js.map} +0 -0
  174. /package/dist/{setup-llm-AQSWLXCZ.js.map → setup-llm-ZMYGIQX5.js.map} +0 -0
  175. /package/dist/{stats-BISBIBXZ.js.map → stats-DGI6B3HX.js.map} +0 -0
  176. /package/dist/{stop-47BJ42EO.js.map → stop-YGHODSP7.js.map} +0 -0
  177. /package/dist/{stop-failure-VU5BTLWX.js.map → stop-failure-7IJTPJ6W.js.map} +0 -0
  178. /package/dist/{subagent-start-SPTKQRHU.js.map → subagent-start-ZBQ5PJB5.js.map} +0 -0
  179. /package/dist/{subagent-stop-UU75BYLC.js.map → subagent-stop-N2TDQU2D.js.map} +0 -0
  180. /package/dist/{task-completed-MVDO7TZF.js.map → task-completed-BDLMRSBB.js.map} +0 -0
  181. /package/dist/{verify-QYSERHF7.js.map → verify-EJYPO7QA.js.map} +0 -0
  182. /package/dist/{version-A72TAL2J.js.map → version-YPBIKH77.js.map} +0 -0
@@ -0,0 +1,65 @@
1
+ import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
+
3
+ // src/hooks/capture-rules.ts
4
+ function evaluateUserPromptRules(manifests, detectedAgent, ctx) {
5
+ for (const manifest of manifests) {
6
+ const rules = manifest.capture?.rules ?? [];
7
+ for (const rule of rules) {
8
+ if (rule.event !== "user_prompt") continue;
9
+ if (!scopePermits(rule, manifest.name, detectedAgent)) continue;
10
+ if (!whenMatches(rule, ctx)) continue;
11
+ return applyAction(rule, ctx);
12
+ }
13
+ }
14
+ return { action: "pass", prompt: ctx.prompt };
15
+ }
16
+ function evaluateSessionStartRules(manifests, detectedAgent, ctx) {
17
+ for (const manifest of manifests) {
18
+ const rules = manifest.capture?.rules ?? [];
19
+ for (const rule of rules) {
20
+ if (rule.event !== "session_start") continue;
21
+ if (!scopePermits(rule, manifest.name, detectedAgent)) continue;
22
+ if (!whenMatches(rule, { prompt: "", transcriptPath: ctx.transcriptPath })) continue;
23
+ if (rule.action === "drop") {
24
+ return { action: "drop", reason: rule.reason };
25
+ }
26
+ }
27
+ }
28
+ return { action: "pass" };
29
+ }
30
+ function scopePermits(rule, owningAgent, detectedAgent) {
31
+ if (rule.scope === "any_agent") return true;
32
+ return owningAgent === detectedAgent;
33
+ }
34
+ function whenMatches(rule, ctx) {
35
+ const { prompt_starts_with, prompt_contains, transcript_path_missing } = rule.when;
36
+ const hasAnyCondition = prompt_starts_with !== void 0 || prompt_contains !== void 0 || transcript_path_missing !== void 0;
37
+ if (!hasAnyCondition) return false;
38
+ if (prompt_starts_with && !ctx.prompt.startsWith(prompt_starts_with)) return false;
39
+ if (prompt_contains && !ctx.prompt.includes(prompt_contains)) return false;
40
+ if (transcript_path_missing !== void 0) {
41
+ const missing = !ctx.transcriptPath || ctx.transcriptPath.length === 0;
42
+ if (transcript_path_missing && !missing) return false;
43
+ if (!transcript_path_missing && missing) return false;
44
+ }
45
+ return true;
46
+ }
47
+ function applyAction(rule, ctx) {
48
+ if (rule.action === "drop") {
49
+ return { action: "drop", reason: rule.reason };
50
+ }
51
+ const marker = rule.extract_after;
52
+ if (!marker) return { action: "pass", prompt: ctx.prompt };
53
+ const idx = ctx.prompt.indexOf(marker);
54
+ if (idx === -1) return { action: "pass", prompt: ctx.prompt };
55
+ const after = ctx.prompt.slice(idx + marker.length);
56
+ const next = rule.trim ? after.trim() : after;
57
+ if (!next) return { action: "pass", prompt: ctx.prompt };
58
+ return { action: "rewrite", prompt: next, reason: rule.reason };
59
+ }
60
+
61
+ export {
62
+ evaluateUserPromptRules,
63
+ evaluateSessionStartRules
64
+ };
65
+ //# sourceMappingURL=chunk-JMOUFG6Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/capture-rules.ts"],"sourcesContent":["/**\n * Generic capture-rule evaluator.\n *\n * Each symbiont manifest declares `capture.rules` — a list of `{ event,\n * when, action }` records that describe how Myco should filter captured\n * events for that agent. This module loads rules from every manifest\n * in one place and exposes a pure evaluator the hook handlers call\n * without knowing anything symbiont-specific.\n *\n * Adding a new symbiont's capture behavior is a YAML-only change: edit\n * that agent's manifest file, no hook or evaluator changes needed.\n *\n * Rule scope (`this_agent` vs `any_agent`) lets rules opt into running\n * even when agent detection itself fails — useful for ephemeral\n * sub-invocations that legitimately lack the signals we key on.\n *\n * Conditions should prefer structural signals (e.g.,\n * `transcript_path_missing`) over text matching so rules stay robust\n * across upstream agent updates.\n */\n\nimport type { CaptureRule, SymbiontManifest } from '../symbionts/manifest-schema.js';\n\n/** Structured context a rule can match against at UserPromptSubmit time. */\nexport interface UserPromptRuleContext {\n /** The user prompt text as received from the hook. */\n prompt: string;\n /** Transcript path from the hook payload, if any. Empty/undefined signals an ephemeral session. */\n transcriptPath?: string;\n}\n\n/** Structured context a rule can match against at SessionStart time. */\nexport interface SessionStartRuleContext {\n /** Transcript path from the hook payload, if any. Empty/undefined signals an ephemeral session. */\n transcriptPath?: string;\n}\n\n/** Outcome of evaluating user_prompt rules. */\nexport type UserPromptDecision =\n | { action: 'pass'; prompt: string }\n | { action: 'rewrite'; prompt: string; reason?: string }\n | { action: 'drop'; reason?: string };\n\n/** Outcome of evaluating session_start rules. No rewrite — there's no prompt text yet. */\nexport type SessionStartDecision =\n | { action: 'pass' }\n | { action: 'drop'; reason?: string };\n\n/**\n * Evaluate all user_prompt rules from every manifest against one context.\n *\n * Rules are checked in declaration order, first-match-wins. A rule only\n * fires when:\n * 1. its `event` is `user_prompt`,\n * 2. its scope permits it (see scope semantics in manifest-schema.ts),\n * 3. every condition in its `when` block matches the context.\n *\n * If no rule matches, the prompt passes through unchanged.\n */\nexport function evaluateUserPromptRules(\n manifests: SymbiontManifest[],\n detectedAgent: string,\n ctx: UserPromptRuleContext,\n): UserPromptDecision {\n for (const manifest of manifests) {\n const rules = manifest.capture?.rules ?? [];\n for (const rule of rules) {\n if (rule.event !== 'user_prompt') continue;\n if (!scopePermits(rule, manifest.name, detectedAgent)) continue;\n if (!whenMatches(rule, ctx)) continue;\n return applyAction(rule, ctx);\n }\n }\n return { action: 'pass', prompt: ctx.prompt };\n}\n\n/**\n * Evaluate all session_start rules from every manifest.\n *\n * Same first-match-wins semantics as user_prompt rules. The only action\n * session_start rules can take is `drop` — text rewriting doesn't apply\n * because there's no prompt text at SessionStart time. Rules that\n * specify prompt-based conditions (prompt_starts_with / prompt_contains)\n * match against an empty prompt here, so they'll never fire on the\n * session_start pass.\n *\n * Callers should skip session registration when the result is `drop`.\n */\nexport function evaluateSessionStartRules(\n manifests: SymbiontManifest[],\n detectedAgent: string,\n ctx: SessionStartRuleContext,\n): SessionStartDecision {\n for (const manifest of manifests) {\n const rules = manifest.capture?.rules ?? [];\n for (const rule of rules) {\n if (rule.event !== 'session_start') continue;\n if (!scopePermits(rule, manifest.name, detectedAgent)) continue;\n if (!whenMatches(rule, { prompt: '', transcriptPath: ctx.transcriptPath })) continue;\n if (rule.action === 'drop') {\n return { action: 'drop', reason: rule.reason };\n }\n // rewrite_prompt is meaningless at session_start — skip and let\n // later rules have a chance to match.\n }\n }\n return { action: 'pass' };\n}\n\nfunction scopePermits(rule: CaptureRule, owningAgent: string, detectedAgent: string): boolean {\n if (rule.scope === 'any_agent') return true;\n return owningAgent === detectedAgent;\n}\n\nfunction whenMatches(rule: CaptureRule, ctx: UserPromptRuleContext): boolean {\n const { prompt_starts_with, prompt_contains, transcript_path_missing } = rule.when;\n\n // Refuse rules with no conditions — prevents a mistyped YAML file from\n // accidentally creating a blanket \"drop everything\" rule.\n const hasAnyCondition =\n prompt_starts_with !== undefined ||\n prompt_contains !== undefined ||\n transcript_path_missing !== undefined;\n if (!hasAnyCondition) return false;\n\n if (prompt_starts_with && !ctx.prompt.startsWith(prompt_starts_with)) return false;\n if (prompt_contains && !ctx.prompt.includes(prompt_contains)) return false;\n\n if (transcript_path_missing !== undefined) {\n const missing = !ctx.transcriptPath || ctx.transcriptPath.length === 0;\n if (transcript_path_missing && !missing) return false;\n if (!transcript_path_missing && missing) return false;\n }\n\n return true;\n}\n\nfunction applyAction(rule: CaptureRule, ctx: UserPromptRuleContext): UserPromptDecision {\n if (rule.action === 'drop') {\n return { action: 'drop', reason: rule.reason };\n }\n // rewrite_prompt — keep only the substring after the extract_after marker.\n // If the marker isn't in the prompt, fall through to `pass` so we don't\n // accidentally blank out a prompt that turned out not to match after all.\n const marker = rule.extract_after;\n if (!marker) return { action: 'pass', prompt: ctx.prompt };\n const idx = ctx.prompt.indexOf(marker);\n if (idx === -1) return { action: 'pass', prompt: ctx.prompt };\n const after = ctx.prompt.slice(idx + marker.length);\n const next = rule.trim ? after.trim() : after;\n if (!next) return { action: 'pass', prompt: ctx.prompt };\n return { action: 'rewrite', prompt: next, reason: rule.reason };\n}\n"],"mappings":";;;AA2DO,SAAS,wBACd,WACA,eACA,KACoB;AACpB,aAAW,YAAY,WAAW;AAChC,UAAM,QAAQ,SAAS,SAAS,SAAS,CAAC;AAC1C,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,UAAU,cAAe;AAClC,UAAI,CAAC,aAAa,MAAM,SAAS,MAAM,aAAa,EAAG;AACvD,UAAI,CAAC,YAAY,MAAM,GAAG,EAAG;AAC7B,aAAO,YAAY,MAAM,GAAG;AAAA,IAC9B;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,QAAQ,QAAQ,IAAI,OAAO;AAC9C;AAcO,SAAS,0BACd,WACA,eACA,KACsB;AACtB,aAAW,YAAY,WAAW;AAChC,UAAM,QAAQ,SAAS,SAAS,SAAS,CAAC;AAC1C,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,UAAU,gBAAiB;AACpC,UAAI,CAAC,aAAa,MAAM,SAAS,MAAM,aAAa,EAAG;AACvD,UAAI,CAAC,YAAY,MAAM,EAAE,QAAQ,IAAI,gBAAgB,IAAI,eAAe,CAAC,EAAG;AAC5E,UAAI,KAAK,WAAW,QAAQ;AAC1B,eAAO,EAAE,QAAQ,QAAQ,QAAQ,KAAK,OAAO;AAAA,MAC/C;AAAA,IAGF;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAEA,SAAS,aAAa,MAAmB,aAAqB,eAAgC;AAC5F,MAAI,KAAK,UAAU,YAAa,QAAO;AACvC,SAAO,gBAAgB;AACzB;AAEA,SAAS,YAAY,MAAmB,KAAqC;AAC3E,QAAM,EAAE,oBAAoB,iBAAiB,wBAAwB,IAAI,KAAK;AAI9E,QAAM,kBACJ,uBAAuB,UACvB,oBAAoB,UACpB,4BAA4B;AAC9B,MAAI,CAAC,gBAAiB,QAAO;AAE7B,MAAI,sBAAsB,CAAC,IAAI,OAAO,WAAW,kBAAkB,EAAG,QAAO;AAC7E,MAAI,mBAAmB,CAAC,IAAI,OAAO,SAAS,eAAe,EAAG,QAAO;AAErE,MAAI,4BAA4B,QAAW;AACzC,UAAM,UAAU,CAAC,IAAI,kBAAkB,IAAI,eAAe,WAAW;AACrE,QAAI,2BAA2B,CAAC,QAAS,QAAO;AAChD,QAAI,CAAC,2BAA2B,QAAS,QAAO;AAAA,EAClD;AAEA,SAAO;AACT;AAEA,SAAS,YAAY,MAAmB,KAAgD;AACtF,MAAI,KAAK,WAAW,QAAQ;AAC1B,WAAO,EAAE,QAAQ,QAAQ,QAAQ,KAAK,OAAO;AAAA,EAC/C;AAIA,QAAM,SAAS,KAAK;AACpB,MAAI,CAAC,OAAQ,QAAO,EAAE,QAAQ,QAAQ,QAAQ,IAAI,OAAO;AACzD,QAAM,MAAM,IAAI,OAAO,QAAQ,MAAM;AACrC,MAAI,QAAQ,GAAI,QAAO,EAAE,QAAQ,QAAQ,QAAQ,IAAI,OAAO;AAC5D,QAAM,QAAQ,IAAI,OAAO,MAAM,MAAM,OAAO,MAAM;AAClD,QAAM,OAAO,KAAK,OAAO,MAAM,KAAK,IAAI;AACxC,MAAI,CAAC,KAAM,QAAO,EAAE,QAAQ,QAAQ,QAAQ,IAAI,OAAO;AACvD,SAAO,EAAE,QAAQ,WAAW,QAAQ,MAAM,QAAQ,KAAK,OAAO;AAChE;","names":[]}
@@ -2,12 +2,12 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  LmStudioBackend,
4
4
  OllamaBackend
5
- } from "./chunk-ML6GTPZU.js";
5
+ } from "./chunk-CML4MCYF.js";
6
6
  import {
7
7
  EMBEDDING_REQUEST_TIMEOUT_MS,
8
8
  LLM_REQUEST_TIMEOUT_MS,
9
9
  PROVIDER_DETECT_TIMEOUT_MS
10
- } from "./chunk-7DAH5GLC.js";
10
+ } from "./chunk-CKJAWZQE.js";
11
11
 
12
12
  // node_modules/@anthropic-ai/sdk/internal/tslib.mjs
13
13
  function __classPrivateFieldSet(receiver, state, value, kind, f) {
@@ -5018,4 +5018,4 @@ export {
5018
5018
  createLlmProvider,
5019
5019
  createEmbeddingProvider
5020
5020
  };
5021
- //# sourceMappingURL=chunk-HPZ7YAMA.js.map
5021
+ //# sourceMappingURL=chunk-KWTOCJLB.js.map
@@ -11,7 +11,7 @@ import {
11
11
  SCHEDULABLE_POWER_STATES,
12
12
  USER_TASK_SOURCE,
13
13
  epochSeconds
14
- } from "./chunk-7DAH5GLC.js";
14
+ } from "./chunk-CKJAWZQE.js";
15
15
  import {
16
16
  require_dist
17
17
  } from "./chunk-D7TYRPRM.js";
@@ -464,7 +464,7 @@ async function registerBuiltInAgentsAndTasks(definitionsDir, vaultDir) {
464
464
  ).run(BUILT_IN_SOURCE, definition.name, ...validTaskIds);
465
465
  }
466
466
  if (vaultDir) {
467
- const { loadAllTasks } = await import("./registry-TFQ22Z7N.js");
467
+ const { loadAllTasks } = await import("./registry-O2NZLO3V.js");
468
468
  const allTasks = loadAllTasks(definitionsDir, vaultDir);
469
469
  for (const [name, task] of allTasks) {
470
470
  if (task.source === USER_TASK_SOURCE) {
@@ -505,4 +505,4 @@ export {
505
505
  resolveEffectiveConfig,
506
506
  registerBuiltInAgentsAndTasks
507
507
  };
508
- //# sourceMappingURL=chunk-F6C4IC6R.js.map
508
+ //# sourceMappingURL=chunk-NI23QCHB.js.map
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  SEARCH_PREVIEW_CHARS,
7
7
  SEARCH_RESULTS_DEFAULT_LIMIT
8
- } from "./chunk-7DAH5GLC.js";
8
+ } from "./chunk-CKJAWZQE.js";
9
9
 
10
10
  // src/db/queries/search.ts
11
11
  function fullTextSearch(query, options = {}) {
@@ -203,4 +203,4 @@ export {
203
203
  fullTextSearch,
204
204
  hydrateSearchResults
205
205
  };
206
- //# sourceMappingURL=chunk-IGBHLFV5.js.map
206
+ //# sourceMappingURL=chunk-NZI7WBZI.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-MYX5NCRH.js";
5
5
  import {
6
6
  DEFAULT_MACHINE_ID
7
- } from "./chunk-7DAH5GLC.js";
7
+ } from "./chunk-CKJAWZQE.js";
8
8
 
9
9
  // src/daemon/team-context.ts
10
10
  var teamSyncEnabled = false;
@@ -224,4 +224,4 @@ export {
224
224
  markSourceRowsSynced,
225
225
  backfillUnsynced
226
226
  };
227
- //# sourceMappingURL=chunk-C3C5QVLK.js.map
227
+ //# sourceMappingURL=chunk-O3TRN3RC.js.map
@@ -2,7 +2,7 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  DEFAULT_MACHINE_ID,
4
4
  epochSeconds
5
- } from "./chunk-7DAH5GLC.js";
5
+ } from "./chunk-CKJAWZQE.js";
6
6
 
7
7
  // src/db/schema-ddl.ts
8
8
  var SCHEMA_VERSION_TABLE = `
@@ -1014,4 +1014,4 @@ export {
1014
1014
  EMBEDDING_DIMENSIONS,
1015
1015
  createSchema
1016
1016
  };
1017
- //# sourceMappingURL=chunk-UTLWSKDV.js.map
1017
+ //# sourceMappingURL=chunk-OW433Q4C.js.map
@@ -1,10 +1,10 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  loadManifests
4
- } from "./chunk-EBIYONNZ.js";
4
+ } from "./chunk-FABWUX5G.js";
5
5
  import {
6
6
  STDIN_TIMEOUT_MS
7
- } from "./chunk-7DAH5GLC.js";
7
+ } from "./chunk-CKJAWZQE.js";
8
8
 
9
9
  // src/hooks/read-stdin.ts
10
10
  function readStdin() {
@@ -30,9 +30,29 @@ var DEFAULT_HOOK_FIELDS = {
30
30
  };
31
31
  var DEFAULT_AGENT_NAME = "claude-code";
32
32
  var cachedManifest;
33
- function detectManifest() {
33
+ function readSymbiontFlag(argv) {
34
+ for (let i = 0; i < argv.length; i++) {
35
+ const arg = argv[i];
36
+ if (arg === "--symbiont") {
37
+ const next = argv[i + 1];
38
+ if (next && !next.startsWith("-")) return next;
39
+ } else if (arg.startsWith("--symbiont=")) {
40
+ return arg.slice("--symbiont=".length);
41
+ }
42
+ }
43
+ return void 0;
44
+ }
45
+ function detectManifest(input) {
34
46
  if (cachedManifest !== void 0) return cachedManifest;
35
47
  const manifests = loadManifests();
48
+ const flagName = readSymbiontFlag(process.argv);
49
+ if (flagName) {
50
+ const m = manifests.find((x) => x.name === flagName);
51
+ if (m) {
52
+ cachedManifest = m;
53
+ return m;
54
+ }
55
+ }
36
56
  for (const m of manifests) {
37
57
  if (process.env[m.pluginRootEnvVar]) {
38
58
  cachedManifest = m;
@@ -45,6 +65,20 @@ function detectManifest() {
45
65
  return m;
46
66
  }
47
67
  }
68
+ if (input) {
69
+ const candidates = [];
70
+ const tp = input.transcript_path;
71
+ const cwd = input.cwd;
72
+ if (typeof tp === "string" && tp.length > 0) candidates.push(tp);
73
+ if (typeof cwd === "string" && cwd.length > 0) candidates.push(cwd);
74
+ for (const m of manifests) {
75
+ const marker = `/${m.configDir}/`;
76
+ if (candidates.some((c) => c.includes(marker))) {
77
+ cachedManifest = m;
78
+ return m;
79
+ }
80
+ }
81
+ }
48
82
  cachedManifest = null;
49
83
  return null;
50
84
  }
@@ -58,7 +92,7 @@ function resolveField(input, fieldPath) {
58
92
  return current;
59
93
  }
60
94
  function normalizeHookInput(input) {
61
- const manifest = detectManifest();
95
+ const manifest = detectManifest(input);
62
96
  const fields = manifest?.hookFields ?? DEFAULT_HOOK_FIELDS;
63
97
  const sessionIdFromInput = resolveField(input, fields.sessionId);
64
98
  const sessionIdFromEnv = "sessionIdEnv" in fields && fields.sessionIdEnv ? process.env[fields.sessionIdEnv] : void 0;
@@ -80,4 +114,4 @@ export {
80
114
  readStdin,
81
115
  normalizeHookInput
82
116
  };
83
- //# sourceMappingURL=chunk-5ZISXCDC.js.map
117
+ //# sourceMappingURL=chunk-PFWIPRF6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/read-stdin.ts","../src/hooks/normalize.ts"],"sourcesContent":["import { STDIN_TIMEOUT_MS } from '../constants.js';\n\nexport function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n process.stdin.on('data', (chunk: Buffer) => { data += chunk; });\n process.stdin.on('end', () => resolve(data));\n setTimeout(() => resolve(data || '{}'), STDIN_TIMEOUT_MS);\n });\n}\n","/**\n * Hook payload normalization layer.\n *\n * Each agent sends different field names in hook stdin (e.g., Claude Code uses\n * `session_id`, VS Code uses `sessionId`, Windsurf uses `trajectory_id`).\n * This module detects the active agent, loads its manifest, and maps the\n * raw input to a canonical shape that all hooks can consume uniformly.\n */\n\nimport { loadManifests } from '../symbionts/detect.js';\nimport type { SymbiontManifest } from '../symbionts/manifest-schema.js';\n\n/** Default field mappings when no agent manifest is detected (Claude Code conventions). */\nconst DEFAULT_HOOK_FIELDS = {\n sessionId: 'session_id',\n transcriptPath: 'transcript_path',\n lastResponse: 'last_assistant_message',\n prompt: 'prompt',\n toolName: 'tool_name',\n toolInput: 'tool_input',\n toolOutput: 'tool_output',\n} as const;\n\n/** Canonical hook input with normalized field names. */\nexport interface NormalizedHookInput {\n /** Detected agent name from manifest (e.g., 'claude-code', 'codex', 'windsurf'). */\n agent: string;\n sessionId: string;\n transcriptPath?: string;\n lastResponse?: string;\n prompt?: string;\n toolName?: string;\n toolInput?: unknown;\n toolOutput?: unknown;\n /** The full raw input for any fields not covered by the mapping. */\n raw: Record<string, unknown>;\n}\n\n/** Default agent name when no manifest is detected. */\nconst DEFAULT_AGENT_NAME = 'claude-code';\n\n/** Cached manifest for the detected agent — resolved once per process. */\nlet cachedManifest: SymbiontManifest | null | undefined;\n\n/**\n * Parse `--symbiont <name>` from process argv.\n *\n * The hook command line rendered by the installer for every symbiont's\n * hooks.json looks like:\n *\n * node .agents/myco-run.cjs hook session-start --symbiont codex\n *\n * `.agents/myco-run.cjs` resolves the myco binary via\n * `.myco/runtime.command` and execs it with all argv passed through, so\n * by the time the hook handler module loads, `process.argv` contains\n * the flag. This is the installer's explicit declaration of which\n * symbiont owns this invocation — strictly more reliable than any\n * runtime heuristic.\n *\n * Supports both `--symbiont codex` (two args) and `--symbiont=codex`\n * (one arg) to be forgiving about shell quoting on Windows.\n */\nexport function readSymbiontFlag(argv: readonly string[]): string | undefined {\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === '--symbiont') {\n const next = argv[i + 1];\n if (next && !next.startsWith('-')) return next;\n } else if (arg.startsWith('--symbiont=')) {\n return arg.slice('--symbiont='.length);\n }\n }\n return undefined;\n}\n\n/**\n * Detect which symbiont is driving this hook invocation.\n *\n * Detection strategies in order:\n * 1. **Primary** — `--symbiont <name>` argv flag rendered into each\n * agent's hooks.json at install time. Dead simple and unambiguous:\n * the installer knows which agent it's writing into, so we bake\n * the identity into the hook command itself.\n * 2. `pluginRootEnvVar` (e.g., `CLAUDE_PLUGIN_ROOT`) — set natively by\n * agents that cooperate with a plugin system. Fallback for older\n * installs that predate the argv flag.\n * 3. `sessionIdEnv` fallback (e.g., `GEMINI_SESSION_ID`) — set by agents\n * that expose the session via env var rather than payload field.\n * 4. Payload-driven heuristic: match the event's `transcript_path` /\n * `cwd` against each manifest's `configDir`. Safety net for pre-\n * flag installations that have somehow also lost their env-var\n * signal. Generic — works for every manifest without per-agent\n * branching.\n *\n * The cache is per-process, which is fine: each hook invocation is a\n * short-lived Node process. `input` is optional so callers that just\n * want env-based detection (e.g., at module import time) still work.\n */\nfunction detectManifest(input?: Record<string, unknown>): SymbiontManifest | null {\n if (cachedManifest !== undefined) return cachedManifest;\n\n const manifests = loadManifests();\n\n // 1) Primary: explicit --symbiont flag from the installer-rendered\n // hook command. This is the source of truth when present.\n const flagName = readSymbiontFlag(process.argv);\n if (flagName) {\n const m = manifests.find((x) => x.name === flagName);\n if (m) {\n cachedManifest = m;\n return m;\n }\n // Flag specified an unknown manifest — fall through to heuristics\n // rather than guessing. Logging happens at the handler level.\n }\n\n // 2) Env-var detection: check pluginRootEnvVar for each manifest.\n for (const m of manifests) {\n if (process.env[m.pluginRootEnvVar]) {\n cachedManifest = m;\n return m;\n }\n }\n\n // 3) sessionIdEnv fallback (e.g., GEMINI_SESSION_ID).\n for (const m of manifests) {\n if (m.hookFields.sessionIdEnv && process.env[m.hookFields.sessionIdEnv]) {\n cachedManifest = m;\n return m;\n }\n }\n\n // 4) Payload-driven heuristic: match configDir against transcript_path\n // / cwd. Kept as a safety net for pre-flag installations. Preferred\n // signals above always win when they're available.\n if (input) {\n const candidates: string[] = [];\n const tp = input.transcript_path;\n const cwd = input.cwd;\n if (typeof tp === 'string' && tp.length > 0) candidates.push(tp);\n if (typeof cwd === 'string' && cwd.length > 0) candidates.push(cwd);\n for (const m of manifests) {\n const marker = `/${m.configDir}/`;\n if (candidates.some((c) => c.includes(marker))) {\n cachedManifest = m;\n return m;\n }\n }\n }\n\n cachedManifest = null;\n return null;\n}\n\n/**\n * Resolve a potentially nested field path from the input.\n * Supports dot notation for nested objects (e.g., \"tool_info.command_line\").\n */\nfunction resolveField(input: Record<string, unknown>, fieldPath: string): unknown {\n const parts = fieldPath.split('.');\n let current: unknown = input;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n\n/**\n * Normalize a raw hook input using the active agent's manifest field mappings.\n * Falls back to Claude Code field names if no agent is detected.\n */\nexport function normalizeHookInput(input: Record<string, unknown>): NormalizedHookInput {\n const manifest = detectManifest(input);\n const fields = manifest?.hookFields ?? DEFAULT_HOOK_FIELDS;\n\n // Resolve session ID: try the mapped field, then env var fallback, then MYCO_SESSION_ID\n const sessionIdFromInput = resolveField(input, fields.sessionId) as string | undefined;\n const sessionIdFromEnv = 'sessionIdEnv' in fields && fields.sessionIdEnv\n ? process.env[fields.sessionIdEnv]\n : undefined;\n const sessionId = sessionIdFromInput\n ?? sessionIdFromEnv\n ?? process.env.MYCO_SESSION_ID\n ?? `s-${Date.now()}`;\n\n return {\n agent: manifest?.name ?? DEFAULT_AGENT_NAME,\n sessionId,\n transcriptPath: resolveField(input, fields.transcriptPath) as string | undefined,\n lastResponse: resolveField(input, fields.lastResponse) as string | undefined,\n prompt: resolveField(input, fields.prompt) as string | undefined,\n toolName: resolveField(input, fields.toolName) as string | undefined,\n toolInput: resolveField(input, fields.toolInput),\n toolOutput: resolveField(input, fields.toolOutput),\n raw: input,\n };\n}\n\n/** Reset cached manifest — exposed for testing only. */\nexport function _resetManifestCache(): void {\n cachedManifest = undefined;\n}\n"],"mappings":"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","names":[]}
@@ -3,14 +3,14 @@ import {
3
3
  AgentTaskSchema,
4
4
  loadAgentTasks,
5
5
  taskFromParsed
6
- } from "./chunk-F6C4IC6R.js";
6
+ } from "./chunk-NI23QCHB.js";
7
7
  import {
8
8
  BUILT_IN_SOURCE,
9
9
  MAX_TASK_NAME_LENGTH,
10
10
  TASK_NAME_PATTERN,
11
11
  USER_TASKS_DIR,
12
12
  USER_TASK_SOURCE
13
- } from "./chunk-7DAH5GLC.js";
13
+ } from "./chunk-CKJAWZQE.js";
14
14
  import {
15
15
  require_dist
16
16
  } from "./chunk-D7TYRPRM.js";
@@ -100,4 +100,4 @@ export {
100
100
  deleteUserTask,
101
101
  copyTaskToUser
102
102
  };
103
- //# sourceMappingURL=chunk-3NCVCGUZ.js.map
103
+ //# sourceMappingURL=chunk-RAV5YMRU.js.map
@@ -2,7 +2,7 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  getTeamMachineId,
4
4
  syncRow
5
- } from "./chunk-C3C5QVLK.js";
5
+ } from "./chunk-O3TRN3RC.js";
6
6
  import {
7
7
  getDatabase
8
8
  } from "./chunk-MYX5NCRH.js";
@@ -88,4 +88,4 @@ export {
88
88
  insertResolutionEvent,
89
89
  listResolutionEvents
90
90
  };
91
- //# sourceMappingURL=chunk-RKPTMHED.js.map
91
+ //# sourceMappingURL=chunk-U3J2DDSR.js.map
@@ -2,7 +2,7 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  getTeamMachineId,
4
4
  syncRow
5
- } from "./chunk-C3C5QVLK.js";
5
+ } from "./chunk-O3TRN3RC.js";
6
6
  import {
7
7
  getDatabase
8
8
  } from "./chunk-MYX5NCRH.js";
@@ -302,4 +302,4 @@ export {
302
302
  getSessionImpact,
303
303
  deleteSessionCascade
304
304
  };
305
- //# sourceMappingURL=chunk-25WHTV4N.js.map
305
+ //# sourceMappingURL=chunk-U7GJTVSX.js.map
@@ -5,13 +5,13 @@ import {
5
5
  import {
6
6
  normalizeHookInput,
7
7
  readStdin
8
- } from "./chunk-5ZISXCDC.js";
8
+ } from "./chunk-PFWIPRF6.js";
9
9
  import {
10
10
  resolveVaultDir
11
11
  } from "./chunk-5ZT2Q6P5.js";
12
12
  import {
13
13
  DaemonClient
14
- } from "./chunk-XZWFMMJR.js";
14
+ } from "./chunk-BUIR3JWM.js";
15
15
 
16
16
  // src/hooks/send-event.ts
17
17
  import fs from "fs";
@@ -39,4 +39,4 @@ async function sendEvent(hookName, buildEvent) {
39
39
  export {
40
40
  sendEvent
41
41
  };
42
- //# sourceMappingURL=chunk-NUSTG3BH.js.map
42
+ //# sourceMappingURL=chunk-VOCGURV7.js.map
@@ -208,9 +208,8 @@ function writeOrDeleteJsonFile(filePath, data) {
208
208
  // src/symbionts/install-helpers.ts
209
209
  import fs2 from "fs";
210
210
  import path2 from "path";
211
- var MYCO_HOOK_COMMAND_PREFIX = "myco-run";
212
211
  function isMycoHookCommand(command) {
213
- return command.startsWith(MYCO_HOOK_COMMAND_PREFIX) || command.includes(".agents/myco-hook.cjs");
212
+ return command.includes(".agents/myco-run.cjs") || command.includes(".agents/myco-hook.cjs") || command.startsWith("myco-run");
214
213
  }
215
214
  function isMycoHookGroup(group) {
216
215
  if (Array.isArray(group.hooks) && group.hooks.some((h) => h.command && isMycoHookCommand(h.command))) return true;
@@ -250,9 +249,10 @@ var GITIGNORE_COMMENT = "# Myco managed (machine-specific)";
250
249
  var GITIGNORE_SKILLS_COMMENT_LEGACY = "# Myco skill symlinks (machine-specific)";
251
250
  var WRANGLER_CACHE_DIR = ".wrangler/";
252
251
  var TEMPLATES_SUBDIR = "src/symbionts/templates";
253
- var HOOK_GUARD_TEMPLATE_FILENAME = "hook-guard.cjs";
254
- var HOOK_GUARD_INSTALLED_FILENAME = "myco-hook.cjs";
252
+ var HOOK_GUARD_TEMPLATE_FILENAME = "myco-run.cjs";
253
+ var HOOK_GUARD_INSTALLED_FILENAME = "myco-run.cjs";
255
254
  var HOOK_GUARD_PROJECT_PATH = `.agents/${HOOK_GUARD_INSTALLED_FILENAME}`;
255
+ var LEGACY_HOOK_GUARD_PATH = ".agents/myco-hook.cjs";
256
256
  var SKILLS_SUBDIR = "skills";
257
257
  var CANONICAL_SKILLS_DIR = ".agents/skills";
258
258
  var MYCO_MCP_SERVER_NAME = "myco";
@@ -306,33 +306,47 @@ var SymbiontInstaller = class {
306
306
  return true;
307
307
  }
308
308
  /**
309
- * Copy the hook-guard script into .agents/myco-hook.cjs.
310
- * Returns true if the file was written (or updated); false if skipped or N/A.
309
+ * Copy the hook guard script into .agents/myco-run.cjs and delete the
310
+ * legacy .agents/myco-hook.cjs if present.
311
+ *
312
+ * The guard is the cross-platform entry point for lifecycle hooks.
313
+ * Hook commands invoke `node .agents/myco-run.cjs …`, and the guard
314
+ * resolves which myco binary to exec via `.myco/runtime.command`.
315
+ * MCP server spawn continues to use the published `myco-run` binary.
316
+ * Returns true if the file was written (or updated); false if skipped
317
+ * or N/A.
311
318
  */
312
319
  installHookGuard() {
313
320
  const reg = this.manifest.registration;
314
321
  if (!reg?.hooksTarget) return false;
315
322
  const guardTemplate = this.readTemplateFile(HOOK_GUARD_TEMPLATE_FILENAME);
316
323
  if (!guardTemplate) return false;
324
+ try {
325
+ fs3.unlinkSync(path3.join(this.projectRoot, LEGACY_HOOK_GUARD_PATH));
326
+ } catch {
327
+ }
317
328
  return this.writeManagedFile(
318
329
  path3.join(this.projectRoot, HOOK_GUARD_PROJECT_PATH),
319
330
  guardTemplate
320
331
  );
321
332
  }
322
333
  /**
323
- * Remove the hook-guard script from .agents/myco-hook.cjs.
324
- * Returns true if the file was removed; false otherwise.
334
+ * Remove the hook guard script from .agents/myco-run.cjs.
335
+ * Also deletes the legacy .agents/myco-hook.cjs if present.
336
+ * Returns true if any file was removed; false otherwise.
325
337
  */
326
338
  uninstallHookGuard() {
327
339
  const reg = this.manifest.registration;
328
340
  if (!reg?.hooksTarget) return false;
329
- const targetPath = path3.join(this.projectRoot, HOOK_GUARD_PROJECT_PATH);
330
- try {
331
- fs3.unlinkSync(targetPath);
332
- return true;
333
- } catch {
334
- return false;
341
+ let removed = false;
342
+ for (const relPath of [HOOK_GUARD_PROJECT_PATH, LEGACY_HOOK_GUARD_PATH]) {
343
+ try {
344
+ fs3.unlinkSync(path3.join(this.projectRoot, relPath));
345
+ removed = true;
346
+ } catch {
347
+ }
335
348
  }
349
+ return removed;
336
350
  }
337
351
  /** Load a JSON template file for this symbiont. Returns null if not found. */
338
352
  loadTemplate(name) {
@@ -356,6 +370,7 @@ var SymbiontInstaller = class {
356
370
  install() {
357
371
  const reg = this.manifest.registration;
358
372
  this.installHookGuard();
373
+ this.cleanupLegacyMycoCmdEntries();
359
374
  const result = this.shouldBatchJsonTargets(reg) ? this.installBatchedJson(reg) : {
360
375
  hooks: this.installHooks(),
361
376
  mcp: this.installMcp(),
@@ -367,6 +382,129 @@ var SymbiontInstaller = class {
367
382
  this.updateGitignore();
368
383
  return result;
369
384
  }
385
+ /**
386
+ * Sweep legacy `MYCO_CMD` env-var writes and `myco-run` command-name
387
+ * entries from this symbiont's installed config files.
388
+ *
389
+ * Background: prior to the `.myco/runtime.command` refactor, `make
390
+ * dev-link` injected `MYCO_CMD=myco-dev` into each symbiont's env
391
+ * block (`.claude/settings.json` → `env`, `.cursor/mcp.json` →
392
+ * `mcp.myco.env`, `.codex/config.toml` →
393
+ * `[shell_environment_policy.set]`), and each symbiont's template
394
+ * permission allowlist listed `myco-run` as a callable command. The
395
+ * env-var pattern is now obsolete — `.myco/runtime.command` is the
396
+ * hook-side source of truth — while the old allowlist entries remain
397
+ * legacy noise after the permissions refactor.
398
+ *
399
+ * This cleanup runs automatically on every install/update pass so
400
+ * contributors upgrading across this refactor don't need to manually
401
+ * edit any config file. Idempotent: a second run after cleanup is a
402
+ * no-op. Safe to remove from the install pipeline once every known
403
+ * contributor has updated at least once.
404
+ */
405
+ cleanupLegacyMycoCmdEntries() {
406
+ const reg = this.manifest.registration;
407
+ if (!reg) return;
408
+ if (reg.settingsTarget) {
409
+ const settingsPath = path3.join(this.projectRoot, reg.settingsTarget);
410
+ const format = reg.settingsFormat ?? "json";
411
+ if (format === "toml") {
412
+ this.stripLegacyFromToml(settingsPath);
413
+ } else {
414
+ this.stripLegacyFromJson(settingsPath);
415
+ }
416
+ }
417
+ if (reg.mcpTarget && reg.mcpFormat !== "toml") {
418
+ this.stripLegacyFromJson(path3.join(this.projectRoot, reg.mcpTarget));
419
+ }
420
+ }
421
+ /**
422
+ * Walk a JSON settings/MCP file and delete legacy MYCO_CMD + myco-run
423
+ * entries. Writes back only if something changed.
424
+ *
425
+ * Removes:
426
+ * - `MYCO_CMD` key from any object named `env` anywhere in the tree
427
+ * - `myco-run` / `myco-run *` / `myco-run:*` / `Bash(myco-run *)` /
428
+ * `Bash(myco-run:*)` / `ShellTool(myco-run *)` from string arrays
429
+ * - `myco-run` / `myco-run *` keys from object-boolean maps like
430
+ * `chat.tools.terminal.autoApprove`
431
+ */
432
+ stripLegacyFromJson(filePath) {
433
+ let raw;
434
+ try {
435
+ raw = fs3.readFileSync(filePath, "utf-8");
436
+ } catch {
437
+ return;
438
+ }
439
+ let data;
440
+ try {
441
+ data = JSON.parse(raw);
442
+ } catch {
443
+ return;
444
+ }
445
+ let changed = false;
446
+ const LEGACY_STRINGS = /* @__PURE__ */ new Set([
447
+ "myco-run",
448
+ "myco-run *",
449
+ "myco-run:*",
450
+ "Bash(myco-run *)",
451
+ "Bash(myco-run:*)",
452
+ "ShellTool(myco-run *)"
453
+ ]);
454
+ const LEGACY_OBJECT_KEYS = ["myco-run", "myco-run *"];
455
+ const EXEC_ARGV_KEYS = /* @__PURE__ */ new Set(["command", "args"]);
456
+ const walk = (node, parentKey) => {
457
+ if (node === null || typeof node !== "object") return;
458
+ if (Array.isArray(node)) {
459
+ if (parentKey !== void 0 && EXEC_ARGV_KEYS.has(parentKey)) return;
460
+ for (let i = node.length - 1; i >= 0; i--) {
461
+ if (typeof node[i] === "string" && LEGACY_STRINGS.has(node[i])) {
462
+ node.splice(i, 1);
463
+ changed = true;
464
+ } else {
465
+ walk(node[i]);
466
+ }
467
+ }
468
+ return;
469
+ }
470
+ const obj = node;
471
+ if (parentKey === "env" && "MYCO_CMD" in obj) {
472
+ delete obj.MYCO_CMD;
473
+ changed = true;
474
+ }
475
+ for (const key of LEGACY_OBJECT_KEYS) {
476
+ if (key in obj) {
477
+ delete obj[key];
478
+ changed = true;
479
+ }
480
+ }
481
+ for (const [k, v] of Object.entries(obj)) {
482
+ walk(v, k);
483
+ }
484
+ };
485
+ walk(data);
486
+ if (changed) {
487
+ fs3.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
488
+ }
489
+ }
490
+ /**
491
+ * Strip `MYCO_CMD = "..."` from the `[shell_environment_policy.set]`
492
+ * section of a TOML settings file. Leaves the rest of the file
493
+ * untouched. Drops the `[shell_environment_policy.set]` header entirely
494
+ * when the section becomes empty.
495
+ */
496
+ stripLegacyFromToml(filePath) {
497
+ let raw;
498
+ try {
499
+ raw = fs3.readFileSync(filePath, "utf-8");
500
+ } catch {
501
+ return;
502
+ }
503
+ const next = removeTomlSectionKeys(raw, "shell_environment_policy.set", ["MYCO_CMD"]);
504
+ if (next !== raw) {
505
+ fs3.writeFileSync(filePath, next, "utf-8");
506
+ }
507
+ }
370
508
  /**
371
509
  * Check if ALL non-null JSON targets share the same file (e.g., Gemini).
372
510
  * Only batches when every target resolves to one path — partial overlaps
@@ -1102,4 +1240,4 @@ export {
1102
1240
  SymbiontInstaller,
1103
1241
  syncSkillSymlinks
1104
1242
  };
1105
- //# sourceMappingURL=chunk-VVGZL2HX.js.map
1243
+ //# sourceMappingURL=chunk-WYOE4IAX.js.map