@codyswann/lisa 4.80.2 → 4.81.1

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 (334) hide show
  1. package/all/copy-contents/gitignore +5 -0
  2. package/dist/cli/doctor-session-manager-trust.d.ts +62 -0
  3. package/dist/cli/doctor-session-manager-trust.d.ts.map +1 -0
  4. package/dist/cli/doctor-session-manager-trust.js +174 -0
  5. package/dist/cli/doctor-session-manager-trust.js.map +1 -0
  6. package/dist/cli/doctor-session-manager.d.ts +35 -0
  7. package/dist/cli/doctor-session-manager.d.ts.map +1 -0
  8. package/dist/cli/doctor-session-manager.js +209 -0
  9. package/dist/cli/doctor-session-manager.js.map +1 -0
  10. package/dist/cli/doctor.d.ts.map +1 -1
  11. package/dist/cli/doctor.js +3 -0
  12. package/dist/cli/doctor.js.map +1 -1
  13. package/dist/cli/lisa-test-run-bootstrap.js +28 -0
  14. package/dist/cli/lisa-test-run-bootstrap.js.map +1 -1
  15. package/dist/cli/session-manager-config-merge.d.ts +25 -0
  16. package/dist/cli/session-manager-config-merge.d.ts.map +1 -0
  17. package/dist/cli/session-manager-config-merge.js +54 -0
  18. package/dist/cli/session-manager-config-merge.js.map +1 -0
  19. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  20. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  21. package/dist/core/upstream-evidence-manifest.js +258 -12
  22. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  23. package/dist/migrations/deploy-outcome-guard-edit.d.ts.map +1 -1
  24. package/dist/migrations/deploy-outcome-guard-edit.js +35 -14
  25. package/dist/migrations/deploy-outcome-guard-edit.js.map +1 -1
  26. package/dist/migrations/deploy-outcome-guard-yaml.d.ts +30 -1
  27. package/dist/migrations/deploy-outcome-guard-yaml.d.ts.map +1 -1
  28. package/dist/migrations/deploy-outcome-guard-yaml.js +88 -7
  29. package/dist/migrations/deploy-outcome-guard-yaml.js.map +1 -1
  30. package/package.json +4 -4
  31. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  32. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  33. package/plugins/lisa/.codex-plugin/skills/lisa-automation-status/SKILL.md +10 -0
  34. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +17 -2
  35. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  36. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/SKILL.md +287 -0
  37. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/agents/openai.yaml +4 -0
  38. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/references/runbook-template.md +66 -0
  39. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  40. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  41. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  42. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  43. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  44. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  45. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  46. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/config.mjs +265 -0
  47. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  48. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  49. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  50. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  51. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  52. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  53. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  54. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token.mjs +191 -0
  55. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  56. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  57. package/plugins/lisa/.codex-plugin/skills/lisa-setup-session-manager/SKILL.md +158 -0
  58. package/plugins/lisa/.codex-plugin/skills/lisa-setup-session-manager/agents/openai.yaml +4 -0
  59. package/plugins/lisa/.codex-plugin/skills/lisa-tear-down-automations/SKILL.md +10 -0
  60. package/plugins/lisa/commands/implement.md +2 -2
  61. package/plugins/lisa/commands/session-manager.md +7 -0
  62. package/plugins/lisa/commands/setup/session-manager.md +6 -0
  63. package/plugins/lisa/rules/reference/automation-runbook-contract.md +14 -0
  64. package/plugins/lisa/rules/reference/config-resolution.md +58 -0
  65. package/plugins/lisa/scripts/automation-status-claude-adapter.mjs +4 -1
  66. package/plugins/lisa/scripts/automation-status-codex-adapter.mjs +4 -1
  67. package/plugins/lisa/scripts/automation-status-expected-fleet.mjs +98 -0
  68. package/plugins/lisa/scripts/automation-status-run-history.mjs +29 -7
  69. package/plugins/lisa/scripts/ready-queue-order.mjs +352 -0
  70. package/plugins/lisa/skills/lisa-automation-status/SKILL.md +10 -0
  71. package/plugins/lisa/skills/lisa-implement/SKILL.md +17 -2
  72. package/plugins/lisa/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  73. package/plugins/lisa/skills/lisa-session-manager/SKILL.md +285 -0
  74. package/plugins/lisa/skills/lisa-session-manager/agents/openai.yaml +4 -0
  75. package/plugins/lisa/skills/lisa-session-manager/references/runbook-template.md +66 -0
  76. package/plugins/lisa/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  77. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  78. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  79. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  80. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  81. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  82. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  83. package/plugins/lisa/skills/lisa-session-manager/scripts/config.mjs +265 -0
  84. package/plugins/lisa/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  85. package/plugins/lisa/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  86. package/plugins/lisa/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  87. package/plugins/lisa/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  88. package/plugins/lisa/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  89. package/plugins/lisa/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  90. package/plugins/lisa/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  91. package/plugins/lisa/skills/lisa-session-manager/scripts/token.mjs +191 -0
  92. package/plugins/lisa/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  93. package/plugins/lisa/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  94. package/plugins/lisa/skills/lisa-setup-session-manager/SKILL.md +156 -0
  95. package/plugins/lisa/skills/lisa-setup-session-manager/agents/openai.yaml +4 -0
  96. package/plugins/lisa/skills/lisa-tear-down-automations/SKILL.md +10 -0
  97. package/plugins/lisa-agy/commands/lisa/implement.md +2 -2
  98. package/plugins/lisa-agy/commands/lisa/session-manager.md +7 -0
  99. package/plugins/lisa-agy/commands/lisa/setup/session-manager.md +6 -0
  100. package/plugins/lisa-agy/plugin.json +1 -1
  101. package/plugins/lisa-agy/scripts/automation-status-claude-adapter.mjs +4 -1
  102. package/plugins/lisa-agy/scripts/automation-status-codex-adapter.mjs +4 -1
  103. package/plugins/lisa-agy/scripts/automation-status-expected-fleet.mjs +98 -0
  104. package/plugins/lisa-agy/scripts/automation-status-run-history.mjs +29 -7
  105. package/plugins/lisa-agy/scripts/ready-queue-order.mjs +352 -0
  106. package/plugins/lisa-agy/skills/lisa-automation-status/SKILL.md +10 -0
  107. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +17 -2
  108. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  109. package/plugins/lisa-agy/skills/lisa-session-manager/SKILL.md +285 -0
  110. package/plugins/lisa-agy/skills/lisa-session-manager/references/runbook-template.md +66 -0
  111. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  112. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  113. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  114. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  115. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  116. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  117. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  118. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/config.mjs +265 -0
  119. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  120. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  121. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  122. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  123. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  124. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  125. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  126. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token.mjs +191 -0
  127. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  128. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  129. package/plugins/lisa-agy/skills/lisa-setup-session-manager/SKILL.md +156 -0
  130. package/plugins/lisa-agy/skills/lisa-tear-down-automations/SKILL.md +10 -0
  131. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  132. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  133. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  134. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  135. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  136. package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
  137. package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
  138. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  139. package/plugins/lisa-copilot/commands/lisa/implement.md +2 -2
  140. package/plugins/lisa-copilot/commands/lisa/session-manager.md +7 -0
  141. package/plugins/lisa-copilot/commands/lisa/setup/session-manager.md +6 -0
  142. package/plugins/lisa-copilot/rules/reference/automation-runbook-contract.md +14 -0
  143. package/plugins/lisa-copilot/rules/reference/config-resolution.md +58 -0
  144. package/plugins/lisa-copilot/scripts/automation-status-claude-adapter.mjs +4 -1
  145. package/plugins/lisa-copilot/scripts/automation-status-codex-adapter.mjs +4 -1
  146. package/plugins/lisa-copilot/scripts/automation-status-expected-fleet.mjs +98 -0
  147. package/plugins/lisa-copilot/scripts/automation-status-run-history.mjs +29 -7
  148. package/plugins/lisa-copilot/scripts/ready-queue-order.mjs +352 -0
  149. package/plugins/lisa-copilot/skills/lisa-automation-status/SKILL.md +10 -0
  150. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +17 -2
  151. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  152. package/plugins/lisa-copilot/skills/lisa-session-manager/SKILL.md +285 -0
  153. package/plugins/lisa-copilot/skills/lisa-session-manager/references/runbook-template.md +66 -0
  154. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  155. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  156. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  157. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  158. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  159. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  160. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  161. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/config.mjs +265 -0
  162. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  163. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  164. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  165. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  166. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  167. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  168. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  169. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token.mjs +191 -0
  170. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  171. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  172. package/plugins/lisa-copilot/skills/lisa-setup-session-manager/SKILL.md +156 -0
  173. package/plugins/lisa-copilot/skills/lisa-tear-down-automations/SKILL.md +10 -0
  174. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  175. package/plugins/lisa-cursor/commands/lisa/implement.md +2 -2
  176. package/plugins/lisa-cursor/commands/lisa/session-manager.md +7 -0
  177. package/plugins/lisa-cursor/commands/lisa/setup/session-manager.md +6 -0
  178. package/plugins/lisa-cursor/rules/automation-runbook-contract-reference.mdc +14 -0
  179. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +58 -0
  180. package/plugins/lisa-cursor/scripts/automation-status-claude-adapter.mjs +4 -1
  181. package/plugins/lisa-cursor/scripts/automation-status-codex-adapter.mjs +4 -1
  182. package/plugins/lisa-cursor/scripts/automation-status-expected-fleet.mjs +98 -0
  183. package/plugins/lisa-cursor/scripts/automation-status-run-history.mjs +29 -7
  184. package/plugins/lisa-cursor/scripts/ready-queue-order.mjs +352 -0
  185. package/plugins/lisa-cursor/skills/lisa-automation-status/SKILL.md +10 -0
  186. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +17 -2
  187. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  188. package/plugins/lisa-cursor/skills/lisa-session-manager/SKILL.md +285 -0
  189. package/plugins/lisa-cursor/skills/lisa-session-manager/references/runbook-template.md +66 -0
  190. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  191. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  192. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  193. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  194. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  195. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  196. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  197. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/config.mjs +265 -0
  198. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  199. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  200. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  201. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  202. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  203. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  204. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  205. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token.mjs +191 -0
  206. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  207. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  208. package/plugins/lisa-cursor/skills/lisa-setup-session-manager/SKILL.md +156 -0
  209. package/plugins/lisa-cursor/skills/lisa-tear-down-automations/SKILL.md +10 -0
  210. package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
  211. package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
  212. package/plugins/lisa-devin/rules/reference/automation-runbook-contract.md +14 -0
  213. package/plugins/lisa-devin/rules/reference/config-resolution.md +58 -0
  214. package/plugins/lisa-devin/scripts/automation-status-claude-adapter.mjs +4 -1
  215. package/plugins/lisa-devin/scripts/automation-status-codex-adapter.mjs +4 -1
  216. package/plugins/lisa-devin/scripts/automation-status-expected-fleet.mjs +98 -0
  217. package/plugins/lisa-devin/scripts/automation-status-run-history.mjs +29 -7
  218. package/plugins/lisa-devin/scripts/ready-queue-order.mjs +352 -0
  219. package/plugins/lisa-devin/skills/lisa-automation-status/SKILL.md +10 -0
  220. package/plugins/lisa-devin/skills/lisa-implement/SKILL.md +17 -2
  221. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  222. package/plugins/lisa-devin/skills/lisa-session-manager/SKILL.md +285 -0
  223. package/plugins/lisa-devin/skills/lisa-session-manager/references/runbook-template.md +66 -0
  224. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  225. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  226. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  227. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  228. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  229. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  230. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  231. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/config.mjs +265 -0
  232. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  233. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  234. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  235. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  236. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  237. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  238. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  239. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token.mjs +191 -0
  240. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  241. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  242. package/plugins/lisa-devin/skills/lisa-setup-session-manager/SKILL.md +156 -0
  243. package/plugins/lisa-devin/skills/lisa-tear-down-automations/SKILL.md +10 -0
  244. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  245. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  246. package/plugins/lisa-expo-agy/plugin.json +1 -1
  247. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  248. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  249. package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
  250. package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
  251. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  252. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  253. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  254. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  255. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  256. package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
  257. package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
  258. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  259. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  260. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  261. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  262. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  263. package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
  264. package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
  265. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  266. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  267. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  268. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  269. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  270. package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
  271. package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
  272. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  273. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  274. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  275. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  276. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  277. package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
  278. package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
  279. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  280. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  281. package/plugins/lisa-rails-agy/plugin.json +1 -1
  282. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  283. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  284. package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
  285. package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
  286. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  287. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  288. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  289. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  290. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  291. package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
  292. package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
  293. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  294. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  295. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  296. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  297. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  298. package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
  299. package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
  300. package/plugins/src/base/commands/implement.md +2 -2
  301. package/plugins/src/base/commands/session-manager.md +7 -0
  302. package/plugins/src/base/commands/setup/session-manager.md +6 -0
  303. package/plugins/src/base/rules/reference/automation-runbook-contract.md +14 -0
  304. package/plugins/src/base/rules/reference/config-resolution.md +58 -0
  305. package/plugins/src/base/scripts/automation-status-claude-adapter.mjs +4 -1
  306. package/plugins/src/base/scripts/automation-status-codex-adapter.mjs +4 -1
  307. package/plugins/src/base/scripts/automation-status-expected-fleet.mjs +98 -0
  308. package/plugins/src/base/scripts/automation-status-run-history.mjs +29 -7
  309. package/plugins/src/base/scripts/ready-queue-order.mjs +352 -0
  310. package/plugins/src/base/skills/lisa-automation-status/SKILL.md +10 -0
  311. package/plugins/src/base/skills/lisa-implement/SKILL.md +17 -2
  312. package/plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  313. package/plugins/src/base/skills/lisa-session-manager/SKILL.md +285 -0
  314. package/plugins/src/base/skills/lisa-session-manager/references/runbook-template.md +66 -0
  315. package/plugins/src/base/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  316. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  317. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  318. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  319. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  320. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  321. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  322. package/plugins/src/base/skills/lisa-session-manager/scripts/config.mjs +265 -0
  323. package/plugins/src/base/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  324. package/plugins/src/base/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  325. package/plugins/src/base/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  326. package/plugins/src/base/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  327. package/plugins/src/base/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  328. package/plugins/src/base/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  329. package/plugins/src/base/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  330. package/plugins/src/base/skills/lisa-session-manager/scripts/token.mjs +191 -0
  331. package/plugins/src/base/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  332. package/plugins/src/base/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  333. package/plugins/src/base/skills/lisa-setup-session-manager/SKILL.md +156 -0
  334. package/plugins/src/base/skills/lisa-tear-down-automations/SKILL.md +10 -0
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * The session manager's decision for one Blocked item: release it to Ready,
4
+ * keep it, escalate it, or leave it to a human.
5
+ *
6
+ * ## Why this composes rather than decides
7
+ *
8
+ * Two shared modules already own the hard questions, and both exist because a
9
+ * local re-implementation went wrong. `humanGateVerdict` is the only answer to
10
+ * "is a person holding this?" — a label-only reader promoted held items
11
+ * (#3805) — and it is the only place a hold ends, honouring only a release
12
+ * from a trusted human actor. `resolveBlockerEdges` is the only answer to "is
13
+ * this dependency satisfied?" — containment, never closure, and a NOT_PLANNED
14
+ * blocker escalates instead of dissolving (#3472). This module imports both
15
+ * and adds only the precedence between them, so the manager can never drift
16
+ * from repair-intake's Class A ruling.
17
+ *
18
+ * ## Scope
19
+ *
20
+ * Only dependency blocks (Class A) and the manager's own pending questions.
21
+ * An item blocked with no dependency edges is a gate self-block or a
22
+ * clarification block (Class B/C); those belong to repair-intake and humans,
23
+ * so this plan keeps them rather than guessing. The plan is pure: the caller
24
+ * reads the item and computes containment, then performs the writes.
25
+ * @module session-manager/reconcile
26
+ */
27
+
28
+ import { resolveBlockerEdges } from "../../../scripts/blocker-edge-resolution.mjs";
29
+ import { humanGateVerdict } from "../../../scripts/intake-blocker-reprobe.mjs";
30
+
31
+ /** Every action the plan may return. */
32
+ export const BLOCKED_RELEASE_ACTIONS = Object.freeze([
33
+ "release",
34
+ "keep",
35
+ "escalate",
36
+ "skip-human-gate",
37
+ ]);
38
+
39
+ /**
40
+ * Plan what to do with one Blocked item.
41
+ *
42
+ * Precedence, first match wins: a held human gate (`skip-human-gate`), a
43
+ * pending manager question (`keep`), no edges (`keep`), every edge dissolves
44
+ * (`release`), any edge escalates (`escalate`), otherwise `keep`.
45
+ *
46
+ * `edges` carries the per-edge decisions — each input edge plus its `action`
47
+ * and `reason` — so the caller can quote them in the explanatory tracker
48
+ * comment. It is empty when the edges were never judged.
49
+ * @param {{
50
+ * labels?: unknown,
51
+ * body?: unknown,
52
+ * comments?: unknown,
53
+ * trustedHumanActorIds?: unknown,
54
+ * humanNeededLabel?: unknown,
55
+ * edges?: readonly object[] | null | undefined,
56
+ * pendingQuestion?: unknown,
57
+ * }} [input] The item's hold surfaces, its judged edges, and the ledger question.
58
+ * @returns {{
59
+ * action: string,
60
+ * reason: string,
61
+ * edges: {action: string, reason: string}[],
62
+ * gate: ReturnType<typeof humanGateVerdict>,
63
+ * }} The decision, why, and the evidence behind it.
64
+ */
65
+ export function planBlockedRelease(input = {}) {
66
+ const gate = humanGateVerdict({
67
+ labels: input.labels,
68
+ body: input.body,
69
+ comments: input.comments,
70
+ trustedHumanActorIds: input.trustedHumanActorIds,
71
+ humanNeededLabel: input.humanNeededLabel,
72
+ });
73
+
74
+ if (gate.held) {
75
+ return {
76
+ action: "skip-human-gate",
77
+ reason:
78
+ "a person is holding this item and no trusted human has released it, so its edges are " +
79
+ "not the manager's to judge.",
80
+ edges: [],
81
+ gate,
82
+ };
83
+ }
84
+
85
+ if (input.pendingQuestion) {
86
+ return {
87
+ action: "keep",
88
+ reason:
89
+ "the manager is still waiting on an answer to its question about this item.",
90
+ edges: [],
91
+ gate,
92
+ };
93
+ }
94
+
95
+ const edges = Array.isArray(input.edges) ? input.edges : [];
96
+ if (edges.length === 0) {
97
+ return {
98
+ action: "keep",
99
+ reason:
100
+ "the item has no dependency edges, so it is a gate or clarification block; those are left " +
101
+ "to repair-intake and humans.",
102
+ edges: [],
103
+ gate,
104
+ };
105
+ }
106
+
107
+ const resolution = resolveBlockerEdges(edges);
108
+ if (resolution.proceed) {
109
+ return {
110
+ action: "release",
111
+ reason:
112
+ "every blocker's code is on the branch this item builds from, so each edge dissolves.",
113
+ edges: resolution.decisions,
114
+ gate,
115
+ };
116
+ }
117
+
118
+ if (resolution.escalations > 0) {
119
+ return {
120
+ action: "escalate",
121
+ reason: `${resolution.escalations} of ${edges.length} blocker edge(s) need a human decision.`,
122
+ edges: resolution.decisions,
123
+ gate,
124
+ };
125
+ }
126
+
127
+ return {
128
+ action: "keep",
129
+ reason:
130
+ "at least one blocker has not shipped to the branch this item builds from.",
131
+ edges: resolution.decisions,
132
+ gate,
133
+ };
134
+ }
@@ -0,0 +1,274 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * The session manager's one entrypoint: every skill call goes through here.
4
+ *
5
+ * It parses argv, builds one context, runs a subcommand and maps the outcome
6
+ * to an exit code the manager skill branches on (0 ok, 1 failure, 2 bad repo
7
+ * or config, 3 no capacity, 4 live worker). The logic lives in the pure
8
+ * modules beside it; this file only wires real seams into them.
9
+ *
10
+ * The real environment is read in exactly one place, the call at the bottom
11
+ * of this file. It is passed down as `ctx.env`, and every child that could be
12
+ * a worker or could host one gets it through `scrubWorkerEnv`, which drops
13
+ * every `TELEGRAM_*` key. Children are started with argv arrays, never a shell
14
+ * string, and untrusted text arrives on stdin, so a ticket title or a
15
+ * Telegram message can never become shell syntax.
16
+ *
17
+ * Runtime parity: the manager PROCESS is always Claude Code, because it needs
18
+ * background sessions (`claude --bg`, `claude agents`), cross-session
19
+ * messaging and channels, which no other supported agent has. Codex, Cursor,
20
+ * OpenCode, Antigravity, Copilot and Devin can run the setup-time subcommands
21
+ * (init-config, store-token, validate, start), and `start` hosts a Claude Code
22
+ * manager in tmux whatever agent ran it; they cannot run a manager cycle
23
+ * themselves. OpenCode copies skill folders without the plugin-level
24
+ * `scripts/` directory, so `queue` and `record-cycle` (which import from it)
25
+ * are unavailable there unless the npm package provides that directory.
26
+ * @module session-manager
27
+ */
28
+ import { readFileSync, realpathSync } from "node:fs";
29
+ import os from "node:os";
30
+ import path from "node:path";
31
+ import { fileURLToPath } from "node:url";
32
+ import { parseArgs } from "node:util";
33
+
34
+ import {
35
+ LEDGER_ACTION_NAMES,
36
+ blockedPlan,
37
+ ledger,
38
+ recordCycle,
39
+ route,
40
+ } from "./cli-cycle.mjs";
41
+ import {
42
+ initConfig,
43
+ repoDir,
44
+ start,
45
+ status,
46
+ stop,
47
+ storeToken,
48
+ validate,
49
+ } from "./cli-manager.mjs";
50
+ import { queue } from "./cli-queue.mjs";
51
+ import { CliError, EXIT } from "./cli-runtime.mjs";
52
+ import { USAGE } from "./cli-usage.mjs";
53
+ import { capacity, classify, resume, spawn } from "./cli-workers.mjs";
54
+
55
+ const text = { type: "string" };
56
+ const flag = { type: "boolean" };
57
+ const MEASURE = { "max-workers": text, meminfo: text };
58
+
59
+ /** Each subcommand: handler, accepted flags, and how many positionals. */
60
+ const COMMANDS = {
61
+ capacity: { run: capacity, options: MEASURE, positionals: 0 },
62
+ spawn: { run: spawn, options: { ...MEASURE, repo: text }, positionals: 1 },
63
+ resume: { run: resume, options: {}, positionals: 1 },
64
+ classify: { run: classify, options: {}, positionals: 1 },
65
+ status: { run: status, options: {}, positionals: 0 },
66
+ start: { run: start, options: { "settle-ms": text }, positionals: 0 },
67
+ stop: { run: stop, options: {}, positionals: 0 },
68
+ "store-token": {
69
+ run: storeToken,
70
+ options: { replace: flag },
71
+ positionals: 0,
72
+ },
73
+ "repo-dir": {
74
+ run: repoDir,
75
+ options: { repo: text, raw: flag },
76
+ positionals: 0,
77
+ },
78
+ validate: { run: validate, options: {}, positionals: 0 },
79
+ "init-config": {
80
+ run: initConfig,
81
+ options: { slug: text, write: flag },
82
+ positionals: 0,
83
+ },
84
+ queue: {
85
+ run: queue,
86
+ options: {
87
+ tracker: text,
88
+ input: text,
89
+ me: text,
90
+ label: text,
91
+ "github-repo": text,
92
+ },
93
+ positionals: 0,
94
+ },
95
+ ledger: { run: ledger, options: {}, positionals: 0 },
96
+ route: {
97
+ run: route,
98
+ options: { "reply-to": text, owner: text },
99
+ positionals: 0,
100
+ },
101
+ "blocked-plan": {
102
+ run: blockedPlan,
103
+ options: { input: text, ref: text },
104
+ positionals: 0,
105
+ },
106
+ "record-cycle": {
107
+ run: recordCycle,
108
+ options: {
109
+ outcome: text,
110
+ ref: { ...text, multiple: true },
111
+ "run-id": text,
112
+ },
113
+ positionals: 0,
114
+ },
115
+ };
116
+
117
+ /** Flags and positionals for each `ledger <action>`. */
118
+ const LEDGER_SPECS = {
119
+ get: { options: {}, positionals: 1 },
120
+ "record-spawn": {
121
+ options: { worker: text, "session-id": text, repo: text },
122
+ positionals: 1,
123
+ },
124
+ "set-question": {
125
+ options: { "telegram-message-id": text, sender: text },
126
+ positionals: 1,
127
+ },
128
+ "clear-question": { options: {}, positionals: 1 },
129
+ finish: { options: { status: text, sender: text }, positionals: 1 },
130
+ control: {
131
+ options: { paused: text, "max-workers": text, me: text },
132
+ positionals: 0,
133
+ },
134
+ };
135
+
136
+ const COMMON = { "project-root": text, help: { ...flag, short: "h" } };
137
+
138
+ /**
139
+ * Resolve the subcommand (and ledger action) and parse its argv strictly.
140
+ * @param {string[]} argv - Arguments after the script path
141
+ * @returns {{ command: object, action: string | undefined,
142
+ * values: Record<string, any>, positionals: string[] }} Parsed call
143
+ */
144
+ function parseCall(argv) {
145
+ const [name, ...rest] = argv;
146
+ const command = Object.hasOwn(COMMANDS, name) ? COMMANDS[name] : null;
147
+ if (!command) throw new CliError(`Unknown subcommand "${name}".`, EXIT.SETUP);
148
+ const isLedger = name === "ledger";
149
+ const action = isLedger ? rest.shift() : undefined;
150
+ if (isLedger && !LEDGER_ACTION_NAMES.includes(action ?? "")) {
151
+ throw new CliError(
152
+ `ledger needs one of: ${LEDGER_ACTION_NAMES.join(", ")}.`,
153
+ EXIT.SETUP
154
+ );
155
+ }
156
+ const spec = isLedger ? LEDGER_SPECS[action] : command;
157
+ const { values, positionals } = parseArgs({
158
+ args: rest,
159
+ options: { ...COMMON, ...spec.options },
160
+ allowPositionals: true,
161
+ strict: true,
162
+ });
163
+ if (positionals.length > spec.positionals) {
164
+ throw new CliError(
165
+ `Unexpected argument "${positionals[spec.positionals]}".`,
166
+ EXIT.SETUP
167
+ );
168
+ }
169
+ return { command, action, values, positionals };
170
+ }
171
+
172
+ /**
173
+ * The project root: `--project-root` (absolute), else the cwd.
174
+ * @param {string | undefined} value - Flag value
175
+ * @returns {string} Absolute root
176
+ */
177
+ function projectRoot(value) {
178
+ if (value === undefined) return process.cwd();
179
+ if (!path.isAbsolute(value)) {
180
+ throw new CliError("--project-root must be an absolute path.", EXIT.SETUP);
181
+ }
182
+ return path.resolve(value);
183
+ }
184
+
185
+ /**
186
+ * Read all of stdin. Refuses an interactive terminal rather than waiting on
187
+ * a read nobody will answer.
188
+ * @returns {string} stdin contents
189
+ */
190
+ function readStdin() {
191
+ if (process.stdin.isTTY) {
192
+ throw new CliError("Pipe the input on stdin.", EXIT.SETUP);
193
+ }
194
+ return readFileSync(0, "utf8");
195
+ }
196
+
197
+ /**
198
+ * Run one CLI call.
199
+ * @param {string[]} argv - Arguments after the script path
200
+ * @param {{ env: Record<string, string | undefined> }} seams - The real
201
+ * environment, read once by the caller
202
+ * @returns {Promise<number>} Exit code
203
+ */
204
+ async function main(argv, { env }) {
205
+ const out = chunk => process.stdout.write(chunk);
206
+ const warn = message => process.stderr.write(`${message}\n`);
207
+ try {
208
+ if (argv.length === 0 || ["help", "--help", "-h"].includes(argv[0])) {
209
+ out(USAGE);
210
+ return EXIT.OK;
211
+ }
212
+ const { command, action, values, positionals } = parseCall(argv);
213
+ if (values.help) {
214
+ out(USAGE);
215
+ return EXIT.OK;
216
+ }
217
+ const result = await command.run({
218
+ root: projectRoot(values["project-root"]),
219
+ env,
220
+ values,
221
+ positionals,
222
+ action,
223
+ platform: process.platform,
224
+ homedir: os.homedir(),
225
+ scriptsDir: path.dirname(fileURLToPath(import.meta.url)),
226
+ now: () => new Date(),
227
+ readStdin,
228
+ warn,
229
+ });
230
+ if (result.text !== undefined) out(result.text);
231
+ if (result.json !== undefined) out(`${JSON.stringify(result.json)}\n`);
232
+ return result.exitCode ?? EXIT.OK;
233
+ } catch (error) {
234
+ if (error?.json !== undefined) out(`${JSON.stringify(error.json)}\n`);
235
+ warn(error?.message ?? String(error));
236
+ if (typeof error?.exitCode === "number") return error.exitCode;
237
+ if (String(error?.code ?? "").startsWith("ERR_PARSE_ARGS")) {
238
+ warn("Run with --help for usage.");
239
+ return EXIT.SETUP;
240
+ }
241
+ return EXIT.FAILURE;
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Whether this module is the one node was asked to run. Both sides are
247
+ * realpath'd, so a worktree, a symlinked checkout or a /tmp path on macOS
248
+ * still runs the CLI instead of silently exiting 0. A local copy rather than
249
+ * an import, because plugin payload scripts ship standalone.
250
+ * @param {string} moduleUrl - The caller's own `import.meta.url`
251
+ * @param {string | undefined} [argv1] - Entry path
252
+ * @returns {boolean} Whether to run the CLI body
253
+ */
254
+ function invokedAsScript(moduleUrl, argv1 = process.argv[1]) {
255
+ if (!argv1) return false;
256
+ try {
257
+ return realpathSync(argv1) === realpathSync(fileURLToPath(moduleUrl));
258
+ } catch {
259
+ return false;
260
+ }
261
+ }
262
+
263
+ if (invokedAsScript(import.meta.url)) {
264
+ // The single read of the real environment (see the module header).
265
+ main(process.argv.slice(2), { env: { ...process.env } }).then(
266
+ code => {
267
+ process.exitCode = code;
268
+ },
269
+ error => {
270
+ process.stderr.write(`${error?.message ?? error}\n`);
271
+ process.exitCode = EXIT.FAILURE;
272
+ }
273
+ );
274
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * The manager's per-project Telegram state dir, and the refusal error every
3
+ * launch-time check throws.
4
+ *
5
+ * The official Telegram plugin keeps its token, pairing list, inbox and
6
+ * `bot.pid` in one state dir (`TELEGRAM_STATE_DIR`, else
7
+ * `<CLAUDE_CONFIG_DIR>/channels/telegram`), and on start it SIGTERMs whichever
8
+ * poller holds the `bot.pid` in the same dir. So the shared default dir is
9
+ * refused outright, including through a symlink. Split out of launch.mjs,
10
+ * which re-exports everything here.
11
+ * @module state-dir
12
+ */
13
+ import * as nodeFs from "node:fs";
14
+ import os from "node:os";
15
+ import path from "node:path";
16
+
17
+ /** Exit code for every refusal here: a setup problem the operator must fix. */
18
+ const EXIT_SETUP = 2;
19
+
20
+ /**
21
+ * A refusal that the CLI maps to a process exit code (always 2 here: the
22
+ * operator must fix setup before the manager can start).
23
+ */
24
+ export class LaunchError extends Error {
25
+ /**
26
+ * @param {string} message - Operator-readable reason; never contains a token
27
+ * @param {number} [exitCode] - Process exit code the CLI should use
28
+ */
29
+ constructor(message, exitCode = EXIT_SETUP) {
30
+ super(message);
31
+ this.name = "LaunchError";
32
+ this.exitCode = exitCode;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Paths the plugin falls back to when `TELEGRAM_STATE_DIR` is unset. Both the
38
+ * `CLAUDE_CONFIG_DIR` one and the `~/.claude` one are refused, because the
39
+ * operator's own sessions may run with either.
40
+ * @param {{ env?: Record<string, string | undefined>, homedir?: string }} seams
41
+ * - Injected env and home dir
42
+ * @returns {string[]} Absolute shared-default dirs
43
+ */
44
+ function sharedDefaultDirs({ env = {}, homedir = os.homedir() }) {
45
+ const roots = [path.join(homedir, ".claude")];
46
+ if (env.CLAUDE_CONFIG_DIR) roots.push(path.resolve(env.CLAUDE_CONFIG_DIR));
47
+ return roots.map(root => path.join(root, "channels", "telegram"));
48
+ }
49
+
50
+ /**
51
+ * Resolve symlinks in the longest existing prefix of `target`, keeping the
52
+ * not-yet-created remainder as written. A state dir usually does not exist
53
+ * before `store-token` creates it, but its parent (or `~/.claude`) may be a
54
+ * symlink, and a plain string comparison would miss the shared dir behind it.
55
+ * @param {string} target - Absolute path
56
+ * @param {Pick<typeof nodeFs, "realpathSync">} fs - Injected fs
57
+ * @returns {string} Path with every existing component's symlinks resolved
58
+ */
59
+ export function realpathExisting(target, fs = nodeFs) {
60
+ const rest = [];
61
+ let current = target;
62
+ for (;;) {
63
+ try {
64
+ return path.join(fs.realpathSync(current), ...rest);
65
+ } catch {
66
+ const parent = path.dirname(current);
67
+ if (parent === current) return target;
68
+ rest.unshift(path.basename(current));
69
+ current = parent;
70
+ }
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Resolve the configured state dir to an absolute path, refusing the shared
76
+ * default. Both sides are compared after resolving symlinks where the path
77
+ * exists, so an alias of the shared dir is refused too. The comparison ignores
78
+ * case because macOS volumes usually do.
79
+ * @param {string} stateDir - `sessionManager.notify.stateDir`, `~` allowed
80
+ * @param {{ env?: Record<string, string | undefined>, homedir?: string }} [seams]
81
+ * - Injected env (for CLAUDE_CONFIG_DIR) and home dir
82
+ * @returns {string} Absolute, normalized dir
83
+ */
84
+ export function resolveStateDir(stateDir, seams = {}) {
85
+ const homedir = seams.homedir ?? os.homedir();
86
+ if (typeof stateDir !== "string" || stateDir.trim() === "") {
87
+ throw new LaunchError("notify.stateDir is empty; set a per-project dir.");
88
+ }
89
+ const expanded =
90
+ stateDir === "~" || stateDir.startsWith("~/")
91
+ ? path.join(homedir, stateDir.slice(1))
92
+ : stateDir;
93
+ if (!path.isAbsolute(expanded)) {
94
+ throw new LaunchError(
95
+ `notify.stateDir "${stateDir}" must be absolute or start with ~/.`
96
+ );
97
+ }
98
+ const resolved = path.resolve(expanded);
99
+ const real = realpathExisting(resolved).toLowerCase();
100
+ const shared = sharedDefaultDirs({ ...seams, homedir }).flatMap(dir => [
101
+ dir.toLowerCase(),
102
+ realpathExisting(dir).toLowerCase(),
103
+ ]);
104
+ if (shared.includes(resolved.toLowerCase()) || shared.includes(real)) {
105
+ throw new LaunchError(
106
+ `notify.stateDir ${resolved} is the shared Telegram default. Pick a ` +
107
+ `per-project dir (e.g. ~/.claude/channels/telegram-<project>), or the ` +
108
+ `manager and your own Telegram session will kill each other's poller.`
109
+ );
110
+ }
111
+ return resolved;
112
+ }