@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
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Validate the `secrets`, `remoteEnv`, and `automations` blocks.
3
+ * Validate the `secrets`, `remoteEnv`, `automations`, and `sessionManager`
4
+ * blocks.
4
5
  *
5
6
  * These blocks are read by shell, by Node, and by generated workflows, so a
6
7
  * malformed one surfaces late and somewhere unhelpful — a container that fails
@@ -488,6 +489,307 @@ export function validateAutomations(automations, remoteEnv) {
488
489
  return problems;
489
490
  }
490
491
 
492
+ /**
493
+ * A manager session name: lowercase letters, digits, `-` and `_`, at most 64
494
+ * characters.
495
+ *
496
+ * Narrower than `managedBy=` accepts on purpose. The same string names the
497
+ * tmux session, the `claude -n` session that workers `SendMessage` to, and the
498
+ * default Telegram state dir. tmux silently rewrites `.` and `:` in session
499
+ * names, so a name containing either would start a session that `stop` could
500
+ * never find again by the name in config.
501
+ */
502
+ const SESSION_MANAGER_NAME = /^[a-z0-9][a-z0-9_-]{0,63}$/;
503
+
504
+ /** One path segment that cannot climb out of, or hide inside, its parent. */
505
+ const SAFE_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
506
+
507
+ /** Seconds per `/loop` interval unit. */
508
+ const INTERVAL_UNITS = { s: 1, m: 60, h: 3600, d: 86_400 };
509
+
510
+ /**
511
+ * A Telegram bot token's shape (`<bot id>:<secret>`).
512
+ *
513
+ * Matched on values as well as on credential-shaped key names, because the
514
+ * likeliest mistake is pasting the token into a plausible field rather than
515
+ * naming it `token`.
516
+ */
517
+ const TOKEN_VALUE = /^\d{5,}:[A-Za-z0-9_-]{30,}$/;
518
+
519
+ /** Key names that only ever hold a credential. */
520
+ const CREDENTIAL_KEY = /token|secret|password|passwd|api[-_]?key|credential/i;
521
+
522
+ /**
523
+ * Parse a `/loop` interval such as `5m` into seconds.
524
+ *
525
+ * One parser for the validator and every consumer (the status view's cadence,
526
+ * the launch command), so "valid" and "usable" cannot disagree about the same
527
+ * string.
528
+ * @param {unknown} text Interval as written in config.
529
+ * @returns {number|null} Seconds, or null when it does not parse or is zero.
530
+ */
531
+ export function parseLoopInterval(text) {
532
+ if (typeof text !== "string") return null;
533
+ const match = /^(\d+)([smhd])$/.exec(text);
534
+ if (!match) return null;
535
+ const seconds = Number(match[1]) * INTERVAL_UNITS[match[2]];
536
+ return seconds > 0 ? seconds : null;
537
+ }
538
+
539
+ /**
540
+ * Whether a value is a plain object (not null, not an array).
541
+ * @param {unknown} value Candidate.
542
+ * @returns {boolean} True for `{}`-shaped values.
543
+ */
544
+ function isPlainObject(value) {
545
+ return typeof value === "object" && value !== null && !Array.isArray(value);
546
+ }
547
+
548
+ /**
549
+ * Validate `sessionManager.repos.root`.
550
+ * @param {unknown} root The declared value.
551
+ * @returns {string[]} Problems found.
552
+ */
553
+ function validateReposRoot(root) {
554
+ if (root === undefined) return [];
555
+ const segments = typeof root === "string" ? root.split("/") : [];
556
+ if (segments.length && segments.every(part => SAFE_SEGMENT.test(part))) {
557
+ return [];
558
+ }
559
+ return [
560
+ `sessionManager.repos.root ${JSON.stringify(root)} must be a relative ` +
561
+ `path inside the project, such as "projects". Workers start there with ` +
562
+ `permissions bypassed.`,
563
+ ];
564
+ }
565
+
566
+ /**
567
+ * Validate one `sessionManager.repos.entries` entry.
568
+ * @param {string} key Repo key.
569
+ * @param {unknown} entry Its declaration.
570
+ * @returns {string[]} Problems found.
571
+ */
572
+ function validateRepoEntry(key, entry) {
573
+ if (!SAFE_SEGMENT.test(key)) {
574
+ return [
575
+ `sessionManager.repos.entries key ${JSON.stringify(key)} is not one ` +
576
+ `safe path segment. It is joined onto repos.root to find the repo.`,
577
+ ];
578
+ }
579
+ const hints = isPlainObject(entry) ? entry.hints : undefined;
580
+ const valid =
581
+ Array.isArray(hints) &&
582
+ hints.length > 0 &&
583
+ hints.every(hint => typeof hint === "string" && hint.trim() !== "");
584
+ return valid
585
+ ? []
586
+ : [
587
+ `sessionManager.repos.entries["${key}"] needs hints: a non-empty ` +
588
+ `array of words that identify work for this repo.`,
589
+ ];
590
+ }
591
+
592
+ /**
593
+ * Validate `sessionManager.repos`.
594
+ *
595
+ * Every entry needs hints, because hints are the only thing the manager routes
596
+ * a work item on. An entry without them can never be chosen, so a ticket meant
597
+ * for it is either asked about on every cycle or routed somewhere else.
598
+ * @param {unknown} repos The declared value.
599
+ * @returns {string[]} Problems found.
600
+ */
601
+ function validateSessionManagerRepos(repos) {
602
+ if (repos === undefined) return [];
603
+ if (!isPlainObject(repos)) {
604
+ return [
605
+ `sessionManager.repos must be an object with an "entries" map. Omit it ` +
606
+ `for a single-repo project.`,
607
+ ];
608
+ }
609
+ const entries = repos.entries;
610
+ if (!isPlainObject(entries) || Object.keys(entries).length === 0) {
611
+ return [
612
+ ...validateReposRoot(repos.root),
613
+ `sessionManager.repos.entries must name at least one repo. Omit ` +
614
+ `sessionManager.repos for a single-repo project.`,
615
+ ];
616
+ }
617
+ return [
618
+ ...validateReposRoot(repos.root),
619
+ ...Object.entries(entries).flatMap(([key, entry]) =>
620
+ validateRepoEntry(key, entry)
621
+ ),
622
+ ];
623
+ }
624
+
625
+ /**
626
+ * Check a block of numeric fields, each against its own predicate.
627
+ * @param {string} block Name under `sessionManager`, for messages.
628
+ * @param {unknown} value The declared block.
629
+ * @param {Record<string, [(n: number) => boolean, string]>} rules Per-key
630
+ * predicate and the phrase describing a legal value.
631
+ * @returns {string[]} Problems found.
632
+ */
633
+ function validateNumberBlock(block, value, rules) {
634
+ if (value === undefined) return [];
635
+ if (!isPlainObject(value))
636
+ return [`sessionManager.${block} must be an object`];
637
+ return Object.entries(rules).flatMap(([key, [legal, phrase]]) => {
638
+ const n = value[key];
639
+ if (n === undefined) return [];
640
+ if (typeof n === "number" && Number.isFinite(n) && legal(n)) return [];
641
+ return [
642
+ `sessionManager.${block}.${key} is ${JSON.stringify(n)}; it must be ` +
643
+ `${phrase}.`,
644
+ ];
645
+ });
646
+ }
647
+
648
+ /** Legal values for `sessionManager.capacity`. */
649
+ const CAPACITY_RULES = {
650
+ maxWorkers: [n => Number.isInteger(n) && n > 0, "a positive integer"],
651
+ gbPerWorker: [n => n > 0, "a positive number"],
652
+ reserveGb: [n => n >= 0, "zero or a positive number"],
653
+ cpuFraction: [n => n > 0 && n <= 1, "greater than 0 and at most 1"],
654
+ maxLoadPerCore: [n => n > 0, "a positive number"],
655
+ };
656
+
657
+ /** Legal values for `sessionManager.stall`. */
658
+ const STALL_RULES = {
659
+ noOutputMinutes: [n => n >= 0, "zero or a positive number"],
660
+ maxAttempts: [n => Number.isInteger(n) && n > 0, "a positive integer"],
661
+ requestionHours: [n => n >= 0, "zero or a positive number"],
662
+ };
663
+
664
+ /**
665
+ * Validate `sessionManager.notify`.
666
+ *
667
+ * `stateDir` is required rather than defaulted here: the default dir is shared
668
+ * by every project, and a shared dir is exactly how one project's bot gets
669
+ * taken over by another's session.
670
+ * @param {unknown} notify The declared value.
671
+ * @returns {string[]} Problems found.
672
+ */
673
+ function validateNotify(notify) {
674
+ if (notify !== undefined && !isPlainObject(notify)) {
675
+ return ["sessionManager.notify must be an object"];
676
+ }
677
+ const provider = notify?.provider;
678
+ const stateDir = notify?.stateDir;
679
+ return [
680
+ ...(provider === undefined || provider === "telegram"
681
+ ? []
682
+ : [
683
+ `sessionManager.notify.provider ${JSON.stringify(provider)} is not ` +
684
+ `supported. Only "telegram" is implemented.`,
685
+ ]),
686
+ ...(typeof stateDir === "string" && stateDir.trim() !== ""
687
+ ? []
688
+ : [
689
+ `sessionManager.notify.stateDir is missing. Each project needs its ` +
690
+ `own Telegram state dir, such as ` +
691
+ `"~/.claude/channels/telegram-<project>".`,
692
+ ]),
693
+ ];
694
+ }
695
+
696
+ /**
697
+ * Walk the block for anything that looks like a credential.
698
+ *
699
+ * Config is committed, and this block configures a bot that grants shell
700
+ * access over chat. The token belongs in the state dir's dotenv file (mode
701
+ * 0600), so a token here is both leaked and unused. The value is never echoed.
702
+ * @param {unknown} value Subtree.
703
+ * @param {string} path Dotted path so far.
704
+ * @returns {string[]} Problems found.
705
+ */
706
+ function findCredentials(value, path) {
707
+ if (typeof value === "string") {
708
+ return TOKEN_VALUE.test(value.trim())
709
+ ? [
710
+ `${path} looks like a bot token. Tokens never go in config; ` +
711
+ `/lisa:setup:session-manager stores it in the state dir.`,
712
+ ]
713
+ : [];
714
+ }
715
+ if (Array.isArray(value)) {
716
+ return value.flatMap((item, i) => findCredentials(item, `${path}[${i}]`));
717
+ }
718
+ if (!isPlainObject(value)) return [];
719
+ return Object.entries(value).flatMap(([key, child]) =>
720
+ CREDENTIAL_KEY.test(key)
721
+ ? [
722
+ `${path}.${key} names a credential. Tokens and secrets never go in ` +
723
+ `config; /lisa:setup:session-manager stores the bot token in the ` +
724
+ `state dir.`,
725
+ ]
726
+ : findCredentials(child, `${path}.${key}`)
727
+ );
728
+ }
729
+
730
+ /**
731
+ * Validate the opt-in `sessionManager` block.
732
+ *
733
+ * Structure only, like the rest of this file: whether the bot answers or tmux
734
+ * is installed is the setup skill's and doctor's business. An absent block is
735
+ * valid, because the manager is opt-in. Pass the merged block (local over
736
+ * global per key), since any field may come from either file.
737
+ * @param {unknown} block The block, if present.
738
+ * @returns {string[]} Problems found.
739
+ */
740
+ export function validateSessionManager(block) {
741
+ if (block === undefined || block === null) return [];
742
+ if (!isPlainObject(block)) return ["sessionManager must be an object"];
743
+
744
+ const nameOk =
745
+ typeof block.name === "string" && SESSION_MANAGER_NAME.test(block.name);
746
+ const intervalOk =
747
+ block.interval === undefined || parseLoopInterval(block.interval) !== null;
748
+ const trustedOk =
749
+ block.trustedAuthorIds === undefined ||
750
+ (Array.isArray(block.trustedAuthorIds) &&
751
+ block.trustedAuthorIds.every(id => typeof id === "string" && id !== ""));
752
+
753
+ return [
754
+ ...(nameOk
755
+ ? []
756
+ : [
757
+ `sessionManager.name ${JSON.stringify(block.name)} must be a slug: ` +
758
+ `lowercase letters, digits, "-" or "_", at most 64 characters. ` +
759
+ `It names the tmux session and the session workers message.`,
760
+ ]),
761
+ ...(intervalOk
762
+ ? []
763
+ : [
764
+ `sessionManager.interval ${JSON.stringify(block.interval)} is not a ` +
765
+ `/loop interval such as "30s", "5m", "2h" or "1d".`,
766
+ ]),
767
+ ...validateSessionManagerRepos(block.repos),
768
+ ...validateNumberBlock("capacity", block.capacity, CAPACITY_RULES),
769
+ ...validateNumberBlock("stall", block.stall, STALL_RULES),
770
+ ...validateNotify(block.notify),
771
+ ...(trustedOk
772
+ ? []
773
+ : [
774
+ `sessionManager.trustedAuthorIds must be an array of stable ` +
775
+ `tracker user ids (GitHub numeric user id, Jira accountId, ` +
776
+ `Linear user id), not logins or display names.`,
777
+ ]),
778
+ // An empty list reads as "set" but filters no author at all, so on a
779
+ // public repo it would dispatch anyone's item while looking configured.
780
+ ...(trustedOk &&
781
+ Array.isArray(block.trustedAuthorIds) &&
782
+ block.trustedAuthorIds.length === 0
783
+ ? [
784
+ `sessionManager.trustedAuthorIds must name at least one author id. ` +
785
+ `An empty list filters no author at all; remove the key instead ` +
786
+ `if every author's item may be dispatched.`,
787
+ ]
788
+ : []),
789
+ ...findCredentials(block, "sessionManager"),
790
+ ];
791
+ }
792
+
491
793
  /**
492
794
  * Validate every block this plan introduced.
493
795
  * @param {object} cfg Parsed `.lisa.config.json`.
@@ -498,19 +800,89 @@ export function validateConfig(cfg) {
498
800
  ...validateSecrets(cfg.secrets),
499
801
  ...validateRemoteEnv(cfg.remoteEnv),
500
802
  ...validateAutomations(cfg.automations, cfg.remoteEnv),
803
+ ...validateSessionManager(cfg.sessionManager),
501
804
  ];
502
805
  }
503
806
 
807
+ /** Keys a parsed JSON layer may not contribute to a merged object. */
808
+ const UNSAFE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
809
+
810
+ /**
811
+ * Merge config layers key by key, later layers winning — the
812
+ * `config-resolution` rule for `.lisa.config.local.json` over
813
+ * `.lisa.config.json`.
814
+ *
815
+ * Plain objects merge recursively; arrays and scalars are replaced, never
816
+ * concatenated: a local `hints` list means "these hints", not "these as well".
817
+ * Prototype keys are dropped, since a layer is parsed JSON. The session
818
+ * manager's runtime resolver uses this same function, so validation and the
819
+ * runtime can never disagree about what a local override means.
820
+ * @param {...unknown} layers Lowest precedence first.
821
+ * @returns {Record<string, unknown>} A new object; no layer is mutated.
822
+ */
823
+ export function mergeConfigLayers(...layers) {
824
+ const objects = layers.filter(isPlainObject);
825
+ const keys = [...new Set(objects.flatMap(Object.keys))].filter(
826
+ key => !UNSAFE_KEYS.has(key)
827
+ );
828
+ return Object.fromEntries(
829
+ keys.map(key => {
830
+ const values = objects
831
+ .filter(layer => Object.hasOwn(layer, key))
832
+ .map(layer => layer[key]);
833
+ const top = values.at(-1);
834
+ return [
835
+ key,
836
+ isPlainObject(top)
837
+ ? mergeConfigLayers(...values.filter(isPlainObject))
838
+ : top,
839
+ ];
840
+ })
841
+ );
842
+ }
843
+
844
+ /**
845
+ * Read a JSON file, or undefined when it does not exist.
846
+ * @param {string} file Absolute path.
847
+ * @returns {unknown} Parsed contents, or undefined.
848
+ */
849
+ function readJsonIfPresent(file) {
850
+ return existsSync(file) ? JSON.parse(readFileSync(file, "utf8")) : undefined;
851
+ }
852
+
853
+ /**
854
+ * Read the config this CLI validates from a project root.
855
+ *
856
+ * `sessionManager` is merged local over committed (deep, per key), because
857
+ * that is how the runtime resolves it and a bad local override must fail here,
858
+ * not at runtime. Every other block is read from `.lisa.config.json` alone,
859
+ * exactly as before, so their validation is unchanged.
860
+ * @param {string} root Project root.
861
+ * @returns {Record<string, unknown> | null} Config to validate, or null when
862
+ * neither file exists.
863
+ */
864
+ export function readValidationConfig(root) {
865
+ const committed = readJsonIfPresent(join(root, ".lisa.config.json"));
866
+ const local = readJsonIfPresent(join(root, ".lisa.config.local.json"));
867
+ if (committed === undefined && local === undefined) return null;
868
+ const base = isPlainObject(committed) ? committed : {};
869
+ const blocks = [base.sessionManager, local?.sessionManager].filter(
870
+ isPlainObject
871
+ );
872
+ if (blocks.length === 0) return base;
873
+ return { ...base, sessionManager: mergeConfigLayers(...blocks) };
874
+ }
875
+
504
876
  function main() {
505
- const path = join(process.cwd(), ".lisa.config.json");
506
- if (!existsSync(path)) {
877
+ const cfg = readValidationConfig(process.cwd());
878
+ if (cfg === null) {
507
879
  console.log("no .lisa.config.json — nothing to validate");
508
880
  return;
509
881
  }
510
- const problems = validateConfig(JSON.parse(readFileSync(path, "utf8")));
882
+ const problems = validateConfig(cfg);
511
883
  if (!problems.length) {
512
884
  console.log(
513
- "config: secrets, remoteEnv and automations blocks are well-formed"
885
+ "config: secrets, remoteEnv, automations and sessionManager blocks are well-formed"
514
886
  );
515
887
  return;
516
888
  }