@codyswann/lisa 4.80.2 → 4.81.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 (327) 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 +257 -12
  22. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  23. package/package.json +4 -4
  24. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  26. package/plugins/lisa/.codex-plugin/skills/lisa-automation-status/SKILL.md +10 -0
  27. package/plugins/lisa/.codex-plugin/skills/lisa-implement/SKILL.md +17 -2
  28. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  29. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/SKILL.md +287 -0
  30. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/agents/openai.yaml +4 -0
  31. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/references/runbook-template.md +66 -0
  32. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  33. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  34. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  35. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  36. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  37. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  38. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  39. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/config.mjs +265 -0
  40. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  41. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  42. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  43. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  44. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  45. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  46. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  47. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token.mjs +191 -0
  48. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  49. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  50. package/plugins/lisa/.codex-plugin/skills/lisa-setup-session-manager/SKILL.md +158 -0
  51. package/plugins/lisa/.codex-plugin/skills/lisa-setup-session-manager/agents/openai.yaml +4 -0
  52. package/plugins/lisa/.codex-plugin/skills/lisa-tear-down-automations/SKILL.md +10 -0
  53. package/plugins/lisa/commands/implement.md +2 -2
  54. package/plugins/lisa/commands/session-manager.md +7 -0
  55. package/plugins/lisa/commands/setup/session-manager.md +6 -0
  56. package/plugins/lisa/rules/reference/automation-runbook-contract.md +14 -0
  57. package/plugins/lisa/rules/reference/config-resolution.md +58 -0
  58. package/plugins/lisa/scripts/automation-status-claude-adapter.mjs +4 -1
  59. package/plugins/lisa/scripts/automation-status-codex-adapter.mjs +4 -1
  60. package/plugins/lisa/scripts/automation-status-expected-fleet.mjs +98 -0
  61. package/plugins/lisa/scripts/automation-status-run-history.mjs +29 -7
  62. package/plugins/lisa/scripts/ready-queue-order.mjs +352 -0
  63. package/plugins/lisa/skills/lisa-automation-status/SKILL.md +10 -0
  64. package/plugins/lisa/skills/lisa-implement/SKILL.md +17 -2
  65. package/plugins/lisa/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  66. package/plugins/lisa/skills/lisa-session-manager/SKILL.md +285 -0
  67. package/plugins/lisa/skills/lisa-session-manager/agents/openai.yaml +4 -0
  68. package/plugins/lisa/skills/lisa-session-manager/references/runbook-template.md +66 -0
  69. package/plugins/lisa/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  70. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  71. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  72. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  73. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  74. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  75. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  76. package/plugins/lisa/skills/lisa-session-manager/scripts/config.mjs +265 -0
  77. package/plugins/lisa/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  78. package/plugins/lisa/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  79. package/plugins/lisa/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  80. package/plugins/lisa/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  81. package/plugins/lisa/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  82. package/plugins/lisa/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  83. package/plugins/lisa/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  84. package/plugins/lisa/skills/lisa-session-manager/scripts/token.mjs +191 -0
  85. package/plugins/lisa/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  86. package/plugins/lisa/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  87. package/plugins/lisa/skills/lisa-setup-session-manager/SKILL.md +156 -0
  88. package/plugins/lisa/skills/lisa-setup-session-manager/agents/openai.yaml +4 -0
  89. package/plugins/lisa/skills/lisa-tear-down-automations/SKILL.md +10 -0
  90. package/plugins/lisa-agy/commands/lisa/implement.md +2 -2
  91. package/plugins/lisa-agy/commands/lisa/session-manager.md +7 -0
  92. package/plugins/lisa-agy/commands/lisa/setup/session-manager.md +6 -0
  93. package/plugins/lisa-agy/plugin.json +1 -1
  94. package/plugins/lisa-agy/scripts/automation-status-claude-adapter.mjs +4 -1
  95. package/plugins/lisa-agy/scripts/automation-status-codex-adapter.mjs +4 -1
  96. package/plugins/lisa-agy/scripts/automation-status-expected-fleet.mjs +98 -0
  97. package/plugins/lisa-agy/scripts/automation-status-run-history.mjs +29 -7
  98. package/plugins/lisa-agy/scripts/ready-queue-order.mjs +352 -0
  99. package/plugins/lisa-agy/skills/lisa-automation-status/SKILL.md +10 -0
  100. package/plugins/lisa-agy/skills/lisa-implement/SKILL.md +17 -2
  101. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  102. package/plugins/lisa-agy/skills/lisa-session-manager/SKILL.md +285 -0
  103. package/plugins/lisa-agy/skills/lisa-session-manager/references/runbook-template.md +66 -0
  104. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  105. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  106. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  107. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  108. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  109. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  110. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  111. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/config.mjs +265 -0
  112. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  113. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  114. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  115. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  116. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  117. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  118. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  119. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token.mjs +191 -0
  120. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  121. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  122. package/plugins/lisa-agy/skills/lisa-setup-session-manager/SKILL.md +156 -0
  123. package/plugins/lisa-agy/skills/lisa-tear-down-automations/SKILL.md +10 -0
  124. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  125. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  126. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  127. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  128. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  129. package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
  130. package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
  131. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  132. package/plugins/lisa-copilot/commands/lisa/implement.md +2 -2
  133. package/plugins/lisa-copilot/commands/lisa/session-manager.md +7 -0
  134. package/plugins/lisa-copilot/commands/lisa/setup/session-manager.md +6 -0
  135. package/plugins/lisa-copilot/rules/reference/automation-runbook-contract.md +14 -0
  136. package/plugins/lisa-copilot/rules/reference/config-resolution.md +58 -0
  137. package/plugins/lisa-copilot/scripts/automation-status-claude-adapter.mjs +4 -1
  138. package/plugins/lisa-copilot/scripts/automation-status-codex-adapter.mjs +4 -1
  139. package/plugins/lisa-copilot/scripts/automation-status-expected-fleet.mjs +98 -0
  140. package/plugins/lisa-copilot/scripts/automation-status-run-history.mjs +29 -7
  141. package/plugins/lisa-copilot/scripts/ready-queue-order.mjs +352 -0
  142. package/plugins/lisa-copilot/skills/lisa-automation-status/SKILL.md +10 -0
  143. package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +17 -2
  144. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  145. package/plugins/lisa-copilot/skills/lisa-session-manager/SKILL.md +285 -0
  146. package/plugins/lisa-copilot/skills/lisa-session-manager/references/runbook-template.md +66 -0
  147. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  148. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  149. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  150. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  151. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  152. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  153. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  154. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/config.mjs +265 -0
  155. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  156. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  157. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  158. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  159. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  160. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  161. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  162. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token.mjs +191 -0
  163. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  164. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  165. package/plugins/lisa-copilot/skills/lisa-setup-session-manager/SKILL.md +156 -0
  166. package/plugins/lisa-copilot/skills/lisa-tear-down-automations/SKILL.md +10 -0
  167. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  168. package/plugins/lisa-cursor/commands/lisa/implement.md +2 -2
  169. package/plugins/lisa-cursor/commands/lisa/session-manager.md +7 -0
  170. package/plugins/lisa-cursor/commands/lisa/setup/session-manager.md +6 -0
  171. package/plugins/lisa-cursor/rules/automation-runbook-contract-reference.mdc +14 -0
  172. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +58 -0
  173. package/plugins/lisa-cursor/scripts/automation-status-claude-adapter.mjs +4 -1
  174. package/plugins/lisa-cursor/scripts/automation-status-codex-adapter.mjs +4 -1
  175. package/plugins/lisa-cursor/scripts/automation-status-expected-fleet.mjs +98 -0
  176. package/plugins/lisa-cursor/scripts/automation-status-run-history.mjs +29 -7
  177. package/plugins/lisa-cursor/scripts/ready-queue-order.mjs +352 -0
  178. package/plugins/lisa-cursor/skills/lisa-automation-status/SKILL.md +10 -0
  179. package/plugins/lisa-cursor/skills/lisa-implement/SKILL.md +17 -2
  180. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  181. package/plugins/lisa-cursor/skills/lisa-session-manager/SKILL.md +285 -0
  182. package/plugins/lisa-cursor/skills/lisa-session-manager/references/runbook-template.md +66 -0
  183. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  184. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  185. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  186. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  187. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  188. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  189. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  190. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/config.mjs +265 -0
  191. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  192. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  193. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  194. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  195. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  196. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  197. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  198. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token.mjs +191 -0
  199. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  200. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  201. package/plugins/lisa-cursor/skills/lisa-setup-session-manager/SKILL.md +156 -0
  202. package/plugins/lisa-cursor/skills/lisa-tear-down-automations/SKILL.md +10 -0
  203. package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
  204. package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
  205. package/plugins/lisa-devin/rules/reference/automation-runbook-contract.md +14 -0
  206. package/plugins/lisa-devin/rules/reference/config-resolution.md +58 -0
  207. package/plugins/lisa-devin/scripts/automation-status-claude-adapter.mjs +4 -1
  208. package/plugins/lisa-devin/scripts/automation-status-codex-adapter.mjs +4 -1
  209. package/plugins/lisa-devin/scripts/automation-status-expected-fleet.mjs +98 -0
  210. package/plugins/lisa-devin/scripts/automation-status-run-history.mjs +29 -7
  211. package/plugins/lisa-devin/scripts/ready-queue-order.mjs +352 -0
  212. package/plugins/lisa-devin/skills/lisa-automation-status/SKILL.md +10 -0
  213. package/plugins/lisa-devin/skills/lisa-implement/SKILL.md +17 -2
  214. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  215. package/plugins/lisa-devin/skills/lisa-session-manager/SKILL.md +285 -0
  216. package/plugins/lisa-devin/skills/lisa-session-manager/references/runbook-template.md +66 -0
  217. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  218. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  219. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  220. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  221. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  222. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  223. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  224. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/config.mjs +265 -0
  225. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  226. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  227. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  228. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  229. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  230. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  231. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  232. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token.mjs +191 -0
  233. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  234. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  235. package/plugins/lisa-devin/skills/lisa-setup-session-manager/SKILL.md +156 -0
  236. package/plugins/lisa-devin/skills/lisa-tear-down-automations/SKILL.md +10 -0
  237. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  238. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  239. package/plugins/lisa-expo-agy/plugin.json +1 -1
  240. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  241. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  242. package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
  243. package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
  244. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  245. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  246. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  247. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  248. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  249. package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
  250. package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
  251. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  252. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  253. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  254. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  255. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  256. package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
  257. package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
  258. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  259. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  260. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  261. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  262. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  263. package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
  264. package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
  265. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  266. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  267. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  268. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  269. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  270. package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
  271. package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
  272. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  273. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  274. package/plugins/lisa-rails-agy/plugin.json +1 -1
  275. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  276. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  277. package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
  278. package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
  279. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  280. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  281. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  282. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  283. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  284. package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
  285. package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
  286. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  287. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  288. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  289. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  290. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  291. package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
  292. package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
  293. package/plugins/src/base/commands/implement.md +2 -2
  294. package/plugins/src/base/commands/session-manager.md +7 -0
  295. package/plugins/src/base/commands/setup/session-manager.md +6 -0
  296. package/plugins/src/base/rules/reference/automation-runbook-contract.md +14 -0
  297. package/plugins/src/base/rules/reference/config-resolution.md +58 -0
  298. package/plugins/src/base/scripts/automation-status-claude-adapter.mjs +4 -1
  299. package/plugins/src/base/scripts/automation-status-codex-adapter.mjs +4 -1
  300. package/plugins/src/base/scripts/automation-status-expected-fleet.mjs +98 -0
  301. package/plugins/src/base/scripts/automation-status-run-history.mjs +29 -7
  302. package/plugins/src/base/scripts/ready-queue-order.mjs +352 -0
  303. package/plugins/src/base/skills/lisa-automation-status/SKILL.md +10 -0
  304. package/plugins/src/base/skills/lisa-implement/SKILL.md +17 -2
  305. package/plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs +377 -5
  306. package/plugins/src/base/skills/lisa-session-manager/SKILL.md +285 -0
  307. package/plugins/src/base/skills/lisa-session-manager/references/runbook-template.md +66 -0
  308. package/plugins/src/base/skills/lisa-session-manager/scripts/capacity.mjs +186 -0
  309. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-cycle.mjs +262 -0
  310. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-manager.mjs +308 -0
  311. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-queue.mjs +148 -0
  312. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-runtime.mjs +326 -0
  313. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-usage.mjs +114 -0
  314. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-workers.mjs +295 -0
  315. package/plugins/src/base/skills/lisa-session-manager/scripts/config.mjs +265 -0
  316. package/plugins/src/base/skills/lisa-session-manager/scripts/isolation.mjs +130 -0
  317. package/plugins/src/base/skills/lisa-session-manager/scripts/launch.mjs +234 -0
  318. package/plugins/src/base/skills/lisa-session-manager/scripts/ledger.mjs +445 -0
  319. package/plugins/src/base/skills/lisa-session-manager/scripts/reconcile.mjs +134 -0
  320. package/plugins/src/base/skills/lisa-session-manager/scripts/session-manager.mjs +274 -0
  321. package/plugins/src/base/skills/lisa-session-manager/scripts/state-dir.mjs +112 -0
  322. package/plugins/src/base/skills/lisa-session-manager/scripts/telegram-route.mjs +210 -0
  323. package/plugins/src/base/skills/lisa-session-manager/scripts/token.mjs +191 -0
  324. package/plugins/src/base/skills/lisa-session-manager/scripts/worker-launch.mjs +92 -0
  325. package/plugins/src/base/skills/lisa-session-manager/scripts/workers.mjs +406 -0
  326. package/plugins/src/base/skills/lisa-setup-session-manager/SKILL.md +156 -0
  327. package/plugins/src/base/skills/lisa-tear-down-automations/SKILL.md +10 -0
@@ -0,0 +1,262 @@
1
+ /**
2
+ * Per-cycle subcommands of the session-manager CLI: ledger, route,
3
+ * blocked-plan and record-cycle (`queue` lives in cli-queue.mjs).
4
+ *
5
+ * Every piece of untrusted text these commands take (a worker's question, a
6
+ * Telegram message, a finish reason, the cycle summary, an item's body and
7
+ * comments) arrives on stdin or in a file, never in argv.
8
+ * @module session-manager/cli-cycle
9
+ */
10
+ import {
11
+ AUTOMATION_RUN_OUTCOMES,
12
+ recordAutomationRun,
13
+ } from "../../../scripts/automation-run-record.mjs";
14
+ import {
15
+ CliError,
16
+ EXIT,
17
+ asSetupErrorAsync,
18
+ humanNeededLabel,
19
+ intFlag,
20
+ loadProject,
21
+ requirePositional,
22
+ stdinText,
23
+ } from "./cli-runtime.mjs";
24
+ import { parseJson, readJsonFile } from "./cli-queue.mjs";
25
+ import {
26
+ clearPendingQuestion,
27
+ readLedger,
28
+ recordFinish,
29
+ recordSpawn,
30
+ setControl,
31
+ setPendingQuestion,
32
+ } from "./ledger.mjs";
33
+ import { planBlockedRelease } from "./reconcile.mjs";
34
+ import { formatAnswer, routeInbound } from "./telegram-route.mjs";
35
+
36
+ /** The automation loop id every cycle records under. */
37
+ const LOOP_ID = "session-manager";
38
+
39
+ /** The runbook the automation-runbook contract requires for this loop. */
40
+ const RUNBOOK = ".lisa/automations/session-manager.runbook.md";
41
+ /**
42
+ * Parse `--paused true|false`.
43
+ * @param {string | undefined} value - Flag value
44
+ * @returns {boolean | undefined} Parsed value
45
+ */
46
+ function pausedFlag(value) {
47
+ if (value === undefined) return undefined;
48
+ if (value !== "true" && value !== "false") {
49
+ throw new CliError("--paused must be true or false.", 2);
50
+ }
51
+ return value === "true";
52
+ }
53
+
54
+ /**
55
+ * Parse a flag where `none` clears the value.
56
+ * @param {string | undefined} value - Flag value
57
+ * @param {(value: string) => unknown} parse - Parser for a real value
58
+ * @returns {unknown} Parsed value, null for `none`, undefined when absent
59
+ */
60
+ function clearable(value, parse) {
61
+ if (value === undefined) return undefined;
62
+ return value === "none" ? null : parse(value);
63
+ }
64
+
65
+ /**
66
+ * With `--sender <name>`, refuse (exit 2) unless the ledger holds `ref` for
67
+ * exactly that worker. The manager passes the cross-session sender of a
68
+ * worker's report, so one worker can never finish or question another
69
+ * worker's item; the manager's own calls (stall, operator stop, repo-routing
70
+ * questions) omit the flag.
71
+ * @param {object} ctx - CLI context
72
+ * @param {string} ref - Ref the report names
73
+ * @returns {Promise<void>}
74
+ */
75
+ async function assertSender(ctx, ref) {
76
+ const sender = ctx.values.sender;
77
+ if (sender === undefined) return;
78
+ const items = (await readLedger(ctx.root)).items;
79
+ const worker = Object.hasOwn(items, ref) ? items[ref].worker : null;
80
+ if (worker !== sender) {
81
+ throw new CliError(
82
+ `${sender} is not the worker for ${ref} (the ledger has ` +
83
+ `${worker ?? "no worker"}); ignoring its message.`,
84
+ 2
85
+ );
86
+ }
87
+ }
88
+
89
+ /** One handler per `ledger <action>`. */
90
+ const LEDGER_ACTIONS = {
91
+ async get(ctx) {
92
+ const ledger = await readLedger(ctx.root);
93
+ const [ref] = ctx.positionals;
94
+ if (!ref) return ledger;
95
+ if (!Object.hasOwn(ledger.items, ref)) {
96
+ throw new CliError(`${ref} is not in the ledger.`, 2);
97
+ }
98
+ return ledger.items[ref];
99
+ },
100
+ "record-spawn": ctx =>
101
+ recordSpawn(ctx.root, {
102
+ ref: requirePositional(ctx, "ref"),
103
+ worker: requireValue(ctx, "worker"),
104
+ sessionId: ctx.values["session-id"] ?? null,
105
+ repo: ctx.values.repo ?? ".",
106
+ }),
107
+ async "set-question"(ctx) {
108
+ const ref = requirePositional(ctx, "ref");
109
+ await assertSender(ctx, ref);
110
+ return setPendingQuestion(ctx.root, {
111
+ ref,
112
+ text: stdinText(ctx, "question"),
113
+ telegramMessageId:
114
+ intFlag(ctx.values["telegram-message-id"], "--telegram-message-id") ??
115
+ null,
116
+ });
117
+ },
118
+ "clear-question": ctx =>
119
+ clearPendingQuestion(ctx.root, { ref: requirePositional(ctx, "ref") }),
120
+ async finish(ctx) {
121
+ const status = ctx.values.status;
122
+ if (status !== "DONE" && status !== "FAILED") {
123
+ throw new CliError("--status must be DONE or FAILED.", 2);
124
+ }
125
+ const ref = requirePositional(ctx, "ref");
126
+ await assertSender(ctx, ref);
127
+ return recordFinish(ctx.root, {
128
+ ref,
129
+ status,
130
+ reason: stdinText(ctx, "reason", { required: false }),
131
+ });
132
+ },
133
+ control: ctx =>
134
+ setControl(
135
+ ctx.root,
136
+ Object.fromEntries(
137
+ Object.entries({
138
+ paused: pausedFlag(ctx.values.paused),
139
+ maxWorkers: clearable(ctx.values["max-workers"], value =>
140
+ intFlag(value, "--max-workers")
141
+ ),
142
+ me: clearable(ctx.values.me, value => value),
143
+ }).filter(([, value]) => value !== undefined)
144
+ )
145
+ ),
146
+ };
147
+
148
+ /** Ledger actions the CLI accepts, for usage and argv specs. */
149
+ export const LEDGER_ACTION_NAMES = Object.keys(LEDGER_ACTIONS);
150
+
151
+ /**
152
+ * A required flag value, or exit 2.
153
+ * @param {object} ctx - CLI context
154
+ * @param {string} flag - Flag name without dashes
155
+ * @returns {string} Value
156
+ */
157
+ function requireValue(ctx, flag) {
158
+ const value = ctx.values[flag];
159
+ if (!value) throw new CliError(`Missing --${flag}.`, 2);
160
+ return value;
161
+ }
162
+
163
+ /**
164
+ * `ledger <action>`: read or update the manager's ledger.
165
+ * @param {object} ctx - CLI context; `ctx.action` is the ledger action
166
+ * @returns {Promise<{ json: unknown }>} The item, control or whole ledger
167
+ */
168
+ export async function ledger(ctx) {
169
+ const handler = LEDGER_ACTIONS[ctx.action];
170
+ return { json: await asSetupErrorAsync(() => handler(ctx)) };
171
+ }
172
+
173
+ /**
174
+ * `route [--reply-to <id>] [--owner <name>]`: decide what one Telegram message
175
+ * (on stdin) is: an answer for a worker, an operator command, or ambiguous.
176
+ * @param {object} ctx - CLI context
177
+ * @returns {Promise<{ json: object }>} Route, plus `message` for an answer
178
+ * when `--owner` is given
179
+ */
180
+ export async function route(ctx) {
181
+ const text = stdinText(ctx, "message", { required: false });
182
+ const routed = routeInbound({
183
+ text,
184
+ replyToMessageId: intFlag(ctx.values["reply-to"], "--reply-to") ?? null,
185
+ ledger: await readLedger(ctx.root),
186
+ });
187
+ const owner = ctx.values.owner;
188
+ if (routed.kind === "answer" && owner) {
189
+ return { json: { ...routed, message: formatAnswer(owner, routed.body) } };
190
+ }
191
+ return { json: routed };
192
+ }
193
+
194
+ /**
195
+ * `blocked-plan [--input <file>] [--ref <ref>]`: plan one Blocked item from
196
+ * its JSON (stdin, or the file). `--ref` fills in the ledger's pending
197
+ * question when the input does not carry one.
198
+ *
199
+ * Who may release a human hold comes from `sessionManager.trustedAuthorIds`
200
+ * only. Any `trustedHumanActorIds` in the input is discarded: the input is
201
+ * assembled from the item's own (untrusted) body and comments, so a list
202
+ * carried beside them would let the item's text vouch for itself.
203
+ * @param {object} ctx - CLI context
204
+ * @returns {Promise<{ json: object }>} `{action,reason,edges,gate}`
205
+ */
206
+ export async function blockedPlan(ctx) {
207
+ const input = ctx.values.input
208
+ ? readJsonFile(ctx.values.input)
209
+ : parseJson(stdinText(ctx, "item JSON"), "stdin");
210
+ const ref = ctx.values.ref;
211
+ const pendingQuestion =
212
+ input.pendingQuestion ??
213
+ (ref ? (await readLedger(ctx.root)).items[ref]?.pendingQuestion : null);
214
+ const project = loadProject(ctx.root);
215
+ const trustedHumanActorIds = project.config?.trustedAuthorIds ?? [];
216
+ return {
217
+ json: planBlockedRelease({
218
+ ...input,
219
+ // The configured label, so a Jira `Human Needed` hold is still a hold.
220
+ humanNeededLabel:
221
+ input.humanNeededLabel ?? humanNeededLabel(project, undefined),
222
+ pendingQuestion,
223
+ trustedHumanActorIds,
224
+ }),
225
+ };
226
+ }
227
+
228
+ /**
229
+ * `record-cycle --outcome <o> [--ref <url>]... [--run-id <id>]`: record this
230
+ * cycle's run outcome, with the one-line summary on stdin.
231
+ * @param {object} ctx - CLI context
232
+ * @returns {Promise<{ json: object }>} What was recorded
233
+ */
234
+ export async function recordCycle(ctx) {
235
+ const outcome = ctx.values.outcome;
236
+ if (!AUTOMATION_RUN_OUTCOMES.includes(outcome)) {
237
+ throw new CliError(
238
+ `--outcome must be one of: ${AUTOMATION_RUN_OUTCOMES.join(", ")}.`,
239
+ EXIT.SETUP
240
+ );
241
+ }
242
+ const result = await asSetupErrorAsync(() =>
243
+ recordAutomationRun({
244
+ projectRoot: ctx.root,
245
+ loopId: LOOP_ID,
246
+ runbook: RUNBOOK,
247
+ outcome,
248
+ summary: stdinText(ctx, "cycle summary"),
249
+ refs: ctx.values.ref ?? [],
250
+ ...(ctx.values["run-id"] ? { runId: ctx.values["run-id"] } : {}),
251
+ })
252
+ );
253
+ return {
254
+ json: {
255
+ path: result.path,
256
+ appended: result.appended,
257
+ loop_id: result.record.loop_id,
258
+ outcome: result.record.outcome,
259
+ run_id: result.record.run_id,
260
+ },
261
+ };
262
+ }
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Manager and setup subcommands of the session-manager CLI: start, stop,
3
+ * status, repo-dir, validate, init-config and store-token.
4
+ *
5
+ * `start` hosts the manager in tmux. It refuses (exit 2) unless the bot
6
+ * token file exists with owner-only permissions in the project's own state
7
+ * dir, and it treats an existing tmux session started in this root as
8
+ * "already running" rather than starting a second poller on the same bot. A
9
+ * session of that name started in another root is another project's manager,
10
+ * so both `start` and `stop` refuse it (exit 2). `stop` kills only the
11
+ * manager's tmux session: workers hold claimed work and keep running.
12
+ * @module session-manager/cli-manager
13
+ */
14
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
15
+ import path from "node:path";
16
+
17
+ import {
18
+ CliError,
19
+ EXIT,
20
+ GLOBAL_CONFIG_FILE,
21
+ asSetupError,
22
+ asSetupErrorAsync,
23
+ intFlag,
24
+ listAgents,
25
+ loadProject,
26
+ mustRun,
27
+ requireConfig,
28
+ requireLisaRepo,
29
+ run,
30
+ } from "./cli-runtime.mjs";
31
+ import { buildDefaultBlock, detectRepos, resolveRepoDir } from "./config.mjs";
32
+ import {
33
+ defaultProjectSlug,
34
+ probeOwnSession,
35
+ sessionSurvives,
36
+ } from "./isolation.mjs";
37
+ import {
38
+ assertTokenPresent,
39
+ buildForegroundCommand,
40
+ buildHasSession,
41
+ buildManagerLaunch,
42
+ buildStopManager,
43
+ resolveStateDir,
44
+ storeToken as storeTokenFile,
45
+ } from "./launch.mjs";
46
+ import { readLedger } from "./ledger.mjs";
47
+ import { parseWorkerName, scrubWorkerEnv } from "./workers.mjs";
48
+
49
+ /**
50
+ * The configured state dir, resolved (exit 2 for the shared default dir).
51
+ * @param {object} ctx - CLI context
52
+ * @param {object} config - Resolved block
53
+ * @returns {string} Absolute state dir
54
+ */
55
+ function stateDirOf(ctx, config) {
56
+ return asSetupError(() =>
57
+ resolveStateDir(config.notify?.stateDir, {
58
+ env: ctx.env,
59
+ homedir: ctx.homedir,
60
+ })
61
+ );
62
+ }
63
+
64
+ /** How long a new manager session must survive before `start` says so. */
65
+ const DEFAULT_SETTLE_MS = 3000;
66
+
67
+ /** Upper bound for `--settle-ms`, so `start` always returns promptly. */
68
+ const MAX_SETTLE_MS = 60_000;
69
+
70
+ /**
71
+ * `--settle-ms`, defaulted and bounded, or exit 2.
72
+ * @param {object} ctx - CLI context
73
+ * @returns {number} Milliseconds
74
+ */
75
+ function settleMsOf(ctx) {
76
+ const value = intFlag(ctx.values["settle-ms"], "--settle-ms");
77
+ if (value !== undefined && value > MAX_SETTLE_MS) {
78
+ throw new CliError(
79
+ `--settle-ms must be at most ${MAX_SETTLE_MS}.`,
80
+ EXIT.SETUP
81
+ );
82
+ }
83
+ return value ?? DEFAULT_SETTLE_MS;
84
+ }
85
+
86
+ /**
87
+ * `start [--settle-ms <n>]`: host the manager in a detached tmux session,
88
+ * and report `started` only once the session has survived the settle window
89
+ * (claude can exit at once on a bad argv; tmux then closes the session).
90
+ * @param {object} ctx - CLI context
91
+ * @returns {Promise<{ json: object }>} `{status,name,...}`
92
+ */
93
+ export async function start(ctx) {
94
+ const settleMs = settleMsOf(ctx);
95
+ const config = requireConfig(ctx);
96
+ const stateDir = stateDirOf(ctx, config);
97
+ // tmux gets the scrubbed env: if this call starts the tmux server, its
98
+ // global environment must not carry a TELEGRAM_* value into other sessions.
99
+ const env = scrubWorkerEnv(ctx.env);
100
+ const session = probeOwnSession(ctx, config.name, env);
101
+ if (session.missing) throw new CliError("tmux is not on PATH.", EXIT.SETUP);
102
+ if (session.running) {
103
+ return { json: { status: "already-running", name: config.name } };
104
+ }
105
+ asSetupError(() => assertTokenPresent(stateDir));
106
+ const argv = asSetupError(() =>
107
+ buildManagerLaunch({
108
+ name: config.name,
109
+ root: ctx.root,
110
+ stateDir,
111
+ scriptsDir: ctx.scriptsDir,
112
+ interval: config.interval,
113
+ })
114
+ );
115
+ mustRun("tmux", argv, { env, cwd: ctx.root });
116
+ if (!(await sessionSurvives(config.name, env, settleMs))) {
117
+ const foreground = buildForegroundCommand(argv);
118
+ throw new CliError(
119
+ `The manager's tmux session "${config.name}" exited within ` +
120
+ `${settleMs} ms of starting, so the manager is not running. Run the ` +
121
+ `launch in the foreground to see claude's error:\n ${foreground}`,
122
+ EXIT.SETUP
123
+ );
124
+ }
125
+ return {
126
+ json: {
127
+ status: "started",
128
+ name: config.name,
129
+ stateDir,
130
+ attach: `tmux attach -t ${config.name}`,
131
+ },
132
+ };
133
+ }
134
+
135
+ /**
136
+ * `stop`: kill the manager's tmux session only, and only when it was started
137
+ * in this root (exit 2 for another project's session of the same name).
138
+ * @param {object} ctx - CLI context
139
+ * @returns {{ json: object }} `{status:"stopped"|"not-running",name}`
140
+ */
141
+ export function stop(ctx) {
142
+ const config = requireConfig(ctx);
143
+ const env = scrubWorkerEnv(ctx.env);
144
+ if (!probeOwnSession(ctx, config.name, env).running) {
145
+ return { json: { status: "not-running", name: config.name } };
146
+ }
147
+ const result = run("tmux", buildStopManager(config.name), { env });
148
+ const stopped = result.status === 0;
149
+ return {
150
+ json: { status: stopped ? "stopped" : "not-running", name: config.name },
151
+ };
152
+ }
153
+
154
+ /**
155
+ * `repo-dir [--repo <key>] [--raw]`: the directory a claim or worker for this
156
+ * repo key must run in.
157
+ * @param {object} ctx - CLI context
158
+ * @returns {{ json?: object, text?: string }} JSON, or the bare path
159
+ */
160
+ export function repoDir(ctx) {
161
+ const config = requireConfig(ctx);
162
+ const key = ctx.values.repo;
163
+ const dir = requireLisaRepo(
164
+ asSetupError(() => resolveRepoDir(config, key, ctx.root))
165
+ );
166
+ if (ctx.values.raw) return { text: `${dir}\n` };
167
+ return { json: { repo: key ?? ".", dir } };
168
+ }
169
+
170
+ /**
171
+ * Problems `validateSessionManager` cannot see: they need the filesystem.
172
+ * @param {object} ctx - CLI context
173
+ * @param {object} config - Resolved block
174
+ * @returns {string[]} Problems
175
+ */
176
+ function environmentProblems(ctx, config) {
177
+ const problems = Object.keys(config.repos?.entries ?? {}).flatMap(key => {
178
+ try {
179
+ requireLisaRepo(resolveRepoDir(config, key, ctx.root));
180
+ return [];
181
+ } catch (error) {
182
+ return [`sessionManager.repos.entries.${key}: ${error.message}`];
183
+ }
184
+ });
185
+ if (typeof config.notify?.stateDir === "string") {
186
+ try {
187
+ stateDirOf(ctx, config);
188
+ } catch (error) {
189
+ problems.push(`sessionManager.notify.stateDir: ${error.message}`);
190
+ }
191
+ }
192
+ return problems;
193
+ }
194
+
195
+ /**
196
+ * `validate`: every problem with the block, exit 2 when there is any.
197
+ * @param {object} ctx - CLI context
198
+ * @returns {{ json: object, exitCode: number }} `{valid,errors}`
199
+ */
200
+ export function validate(ctx) {
201
+ const project = loadProject(ctx.root);
202
+ const errors = project.config
203
+ ? [...project.errors, ...environmentProblems(ctx, project.config)]
204
+ : [`No sessionManager block in ${GLOBAL_CONFIG_FILE}.`];
205
+ return {
206
+ json: { valid: errors.length === 0, errors },
207
+ exitCode: errors.length === 0 ? EXIT.OK : EXIT.SETUP,
208
+ };
209
+ }
210
+
211
+ /**
212
+ * `init-config [--slug <slug>] [--write]`: the default block for this
213
+ * project, written to `.lisa.config.json` only with `--write` and only when
214
+ * no block exists. Non-secret fields only; the token never goes here.
215
+ * @param {object} ctx - CLI context
216
+ * @returns {{ json: object }} `{written,block,...}`
217
+ */
218
+ export function initConfig(ctx) {
219
+ const { global } = loadProject(ctx.root);
220
+ if (global?.sessionManager) {
221
+ return {
222
+ json: { written: false, reason: "exists", block: global.sessionManager },
223
+ };
224
+ }
225
+ const slug =
226
+ ctx.values.slug ?? defaultProjectSlug(ctx.root, global?.github?.repo);
227
+ const block = asSetupError(() =>
228
+ buildDefaultBlock({
229
+ projectSlug: slug,
230
+ detectedRepos: detectRepos(ctx.root),
231
+ })
232
+ );
233
+ if (!ctx.values.write) return { json: { written: false, block } };
234
+
235
+ const file = path.join(ctx.root, GLOBAL_CONFIG_FILE);
236
+ if (!existsSync(file)) {
237
+ throw new CliError(
238
+ `${file} does not exist; set up Lisa in this project first.`,
239
+ EXIT.SETUP
240
+ );
241
+ }
242
+ const current = JSON.parse(readFileSync(file, "utf8"));
243
+ writeFileSync(
244
+ file,
245
+ `${JSON.stringify({ ...current, sessionManager: block }, null, 2)}\n`
246
+ );
247
+ return { json: { written: true, path: file, block } };
248
+ }
249
+
250
+ /**
251
+ * `store-token [--replace]`: prompt for the bot token on the operator's
252
+ * terminal and write `<stateDir>/.env`. An existing token is kept (exit 2)
253
+ * unless `--replace` is given. With no TTY it prints the command the operator
254
+ * must run themselves and exits 0 with `stored:false`.
255
+ * @param {object} ctx - CLI context
256
+ * @returns {Promise<{ json: object, exitCode: number }>} Outcome
257
+ */
258
+ export async function storeToken(ctx) {
259
+ const config = requireConfig(ctx);
260
+ const result = await asSetupErrorAsync(() =>
261
+ storeTokenFile({
262
+ stateDir: config.notify?.stateDir,
263
+ scriptsDir: ctx.scriptsDir,
264
+ projectRoot: ctx.root,
265
+ replace: ctx.values.replace === true,
266
+ env: ctx.env,
267
+ homedir: ctx.homedir,
268
+ })
269
+ );
270
+ const refused = result.stored === false && result.reason !== "no-tty";
271
+ return { json: result, exitCode: refused ? EXIT.SETUP : EXIT.OK };
272
+ }
273
+
274
+ /**
275
+ * `status`: is the manager's tmux session up, and what does the ledger say
276
+ * about each worker it dispatched.
277
+ * @param {object} ctx - CLI context
278
+ * @returns {Promise<{ json: object }>} `{manager,control,workers,untracked}`
279
+ */
280
+ export async function status(ctx) {
281
+ const config = requireConfig(ctx);
282
+ const tmux = run("tmux", buildHasSession(config.name), { env: ctx.env });
283
+ const agents = listAgents(ctx, { all: true });
284
+ const ledger = await readLedger(ctx.root);
285
+ const liveNames = new Set(
286
+ agents.filter(agent => agent.active).map(agent => agent.name)
287
+ );
288
+ const tracked = new Set(Object.values(ledger.items).map(i => i.worker));
289
+ return {
290
+ json: {
291
+ manager: { name: config.name, running: tmux.status === 0 },
292
+ control: ledger.control,
293
+ workers: Object.entries(ledger.items).map(([ref, item]) => ({
294
+ ref,
295
+ worker: item.worker ?? null,
296
+ sessionId: item.sessionId ?? null,
297
+ repo: item.repo ?? null,
298
+ status: item.status ?? null,
299
+ attempts: item.attempts ?? 0,
300
+ pendingQuestion: Boolean(item.pendingQuestion),
301
+ live: liveNames.has(item.worker),
302
+ })),
303
+ untracked: [...liveNames]
304
+ .filter(name => parseWorkerName(name) !== null && !tracked.has(name))
305
+ .sort(),
306
+ },
307
+ };
308
+ }