@codyswann/lisa 4.84.11 → 4.86.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 (322) hide show
  1. package/dist/cli/doctor-session-manager-pending.d.ts +17 -0
  2. package/dist/cli/doctor-session-manager-pending.d.ts.map +1 -0
  3. package/dist/cli/doctor-session-manager-pending.js +130 -0
  4. package/dist/cli/doctor-session-manager-pending.js.map +1 -0
  5. package/dist/cli/doctor-session-manager-token.d.ts +69 -0
  6. package/dist/cli/doctor-session-manager-token.d.ts.map +1 -0
  7. package/dist/cli/doctor-session-manager-token.js +264 -0
  8. package/dist/cli/doctor-session-manager-token.js.map +1 -0
  9. package/dist/cli/doctor-session-manager.d.ts +3 -1
  10. package/dist/cli/doctor-session-manager.d.ts.map +1 -1
  11. package/dist/cli/doctor-session-manager.js +168 -146
  12. package/dist/cli/doctor-session-manager.js.map +1 -1
  13. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  14. package/dist/core/lisa-owned-hash-ledger.js +34 -0
  15. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  16. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  17. package/dist/core/nightly-e2e-guard-behavior-certificate.js.map +1 -1
  18. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  19. package/dist/core/upstream-evidence-manifest.js +172 -23
  20. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  21. package/package.json +4 -4
  22. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  24. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/SKILL.md +5 -3
  25. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  26. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
  27. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/SKILL.md +197 -54
  28. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/references/runbook-template.md +23 -10
  29. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  30. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  31. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  32. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  33. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  34. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  35. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  36. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  37. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  38. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/config.mjs +39 -11
  39. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  40. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  41. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  42. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  43. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  44. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  45. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  46. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  47. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  48. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  49. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  50. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  51. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  52. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token.mjs +39 -120
  53. package/plugins/lisa/.codex-plugin/skills/lisa-setup-session-manager/SKILL.md +82 -19
  54. package/plugins/lisa/commands/session-manager.md +1 -1
  55. package/plugins/lisa/commands/setup/session-manager.md +1 -1
  56. package/plugins/lisa/rules/reference/config-resolution.md +39 -7
  57. package/plugins/lisa/skills/lisa-secrets-access/SKILL.md +5 -3
  58. package/plugins/lisa/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  59. package/plugins/lisa/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
  60. package/plugins/lisa/skills/lisa-session-manager/SKILL.md +197 -54
  61. package/plugins/lisa/skills/lisa-session-manager/references/runbook-template.md +23 -10
  62. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  63. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  64. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  65. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  66. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  67. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  68. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  69. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  70. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  71. package/plugins/lisa/skills/lisa-session-manager/scripts/config.mjs +39 -11
  72. package/plugins/lisa/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  73. package/plugins/lisa/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  74. package/plugins/lisa/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  75. package/plugins/lisa/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  76. package/plugins/lisa/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  77. package/plugins/lisa/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  78. package/plugins/lisa/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  79. package/plugins/lisa/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  80. package/plugins/lisa/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  81. package/plugins/lisa/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  82. package/plugins/lisa/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  83. package/plugins/lisa/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  84. package/plugins/lisa/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  85. package/plugins/lisa/skills/lisa-session-manager/scripts/token.mjs +39 -120
  86. package/plugins/lisa/skills/lisa-setup-session-manager/SKILL.md +82 -19
  87. package/plugins/lisa-agy/commands/lisa/session-manager.md +1 -1
  88. package/plugins/lisa-agy/commands/lisa/setup/session-manager.md +1 -1
  89. package/plugins/lisa-agy/plugin.json +1 -1
  90. package/plugins/lisa-agy/skills/lisa-secrets-access/SKILL.md +5 -3
  91. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  92. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
  93. package/plugins/lisa-agy/skills/lisa-session-manager/SKILL.md +197 -54
  94. package/plugins/lisa-agy/skills/lisa-session-manager/references/runbook-template.md +23 -10
  95. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  96. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  97. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  98. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  99. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  100. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  101. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  102. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  103. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  104. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/config.mjs +39 -11
  105. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  106. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  107. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  108. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  109. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  110. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  111. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  112. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  113. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  114. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  115. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  116. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  117. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  118. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token.mjs +39 -120
  119. package/plugins/lisa-agy/skills/lisa-setup-session-manager/SKILL.md +82 -19
  120. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  121. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  122. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  123. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  124. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  125. package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
  126. package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
  127. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  128. package/plugins/lisa-copilot/commands/lisa/session-manager.md +1 -1
  129. package/plugins/lisa-copilot/commands/lisa/setup/session-manager.md +1 -1
  130. package/plugins/lisa-copilot/rules/reference/config-resolution.md +39 -7
  131. package/plugins/lisa-copilot/skills/lisa-secrets-access/SKILL.md +5 -3
  132. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  133. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
  134. package/plugins/lisa-copilot/skills/lisa-session-manager/SKILL.md +197 -54
  135. package/plugins/lisa-copilot/skills/lisa-session-manager/references/runbook-template.md +23 -10
  136. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  137. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  138. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  139. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  140. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  141. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  142. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  143. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  144. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  145. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/config.mjs +39 -11
  146. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  147. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  148. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  149. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  150. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  151. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  152. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  153. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  154. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  155. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  156. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  157. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  158. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  159. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token.mjs +39 -120
  160. package/plugins/lisa-copilot/skills/lisa-setup-session-manager/SKILL.md +82 -19
  161. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  162. package/plugins/lisa-cursor/commands/lisa/session-manager.md +1 -1
  163. package/plugins/lisa-cursor/commands/lisa/setup/session-manager.md +1 -1
  164. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +39 -7
  165. package/plugins/lisa-cursor/skills/lisa-secrets-access/SKILL.md +5 -3
  166. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  167. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
  168. package/plugins/lisa-cursor/skills/lisa-session-manager/SKILL.md +197 -54
  169. package/plugins/lisa-cursor/skills/lisa-session-manager/references/runbook-template.md +23 -10
  170. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  171. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  172. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  173. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  174. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  175. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  176. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  177. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  178. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  179. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/config.mjs +39 -11
  180. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  181. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  182. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  183. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  184. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  185. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  186. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  187. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  188. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  189. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  190. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  191. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  192. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  193. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token.mjs +39 -120
  194. package/plugins/lisa-cursor/skills/lisa-setup-session-manager/SKILL.md +82 -19
  195. package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
  196. package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
  197. package/plugins/lisa-devin/rules/reference/config-resolution.md +39 -7
  198. package/plugins/lisa-devin/skills/lisa-secrets-access/SKILL.md +5 -3
  199. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  200. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
  201. package/plugins/lisa-devin/skills/lisa-session-manager/SKILL.md +197 -54
  202. package/plugins/lisa-devin/skills/lisa-session-manager/references/runbook-template.md +23 -10
  203. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  204. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  205. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  206. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  207. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  208. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  209. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  210. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  211. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  212. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/config.mjs +39 -11
  213. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  214. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  215. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  216. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  217. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  218. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  219. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  220. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  221. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  222. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  223. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  224. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  225. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  226. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token.mjs +39 -120
  227. package/plugins/lisa-devin/skills/lisa-setup-session-manager/SKILL.md +82 -19
  228. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  229. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  230. package/plugins/lisa-expo-agy/plugin.json +1 -1
  231. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  232. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  233. package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
  234. package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
  235. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  236. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  237. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  238. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  239. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  240. package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
  241. package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
  242. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  243. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  244. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  245. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  246. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  247. package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
  248. package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
  249. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  250. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  251. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  252. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  253. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  254. package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
  255. package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
  256. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  257. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  258. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  259. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  260. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  261. package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
  262. package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
  263. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  264. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  265. package/plugins/lisa-rails-agy/plugin.json +1 -1
  266. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  267. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  268. package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
  269. package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
  270. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  271. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  272. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  273. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  274. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  275. package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
  276. package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
  277. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  278. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  279. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  280. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  281. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  282. package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
  283. package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
  284. package/plugins/src/base/commands/session-manager.md +1 -1
  285. package/plugins/src/base/commands/setup/session-manager.md +1 -1
  286. package/plugins/src/base/rules/reference/config-resolution.md +39 -7
  287. package/plugins/src/base/skills/lisa-secrets-access/SKILL.md +5 -3
  288. package/plugins/src/base/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  289. package/plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs +47 -26
  290. package/plugins/src/base/skills/lisa-session-manager/SKILL.md +197 -54
  291. package/plugins/src/base/skills/lisa-session-manager/references/runbook-template.md +23 -10
  292. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  293. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  294. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  295. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  296. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  297. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  298. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  299. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  300. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  301. package/plugins/src/base/skills/lisa-session-manager/scripts/config.mjs +39 -11
  302. package/plugins/src/base/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  303. package/plugins/src/base/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  304. package/plugins/src/base/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  305. package/plugins/src/base/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  306. package/plugins/src/base/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  307. package/plugins/src/base/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  308. package/plugins/src/base/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  309. package/plugins/src/base/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  310. package/plugins/src/base/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  311. package/plugins/src/base/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  312. package/plugins/src/base/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  313. package/plugins/src/base/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  314. package/plugins/src/base/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  315. package/plugins/src/base/skills/lisa-session-manager/scripts/token.mjs +39 -120
  316. package/plugins/src/base/skills/lisa-setup-session-manager/SKILL.md +82 -19
  317. package/rails/copy-overwrite/scripts/lisa-rspec-shards.mjs +747 -0
  318. package/rails/copy-overwrite/scripts/lisa_rspec_shard_recorder.rb +143 -0
  319. package/rails/copy-overwrite/scripts/lisa_simplecov_collate.rb +51 -0
  320. package/rails/create-only/.github/workflows/ci.yml +4 -0
  321. package/scripts/two-channel-couplings.json +89 -7
  322. package/typescript/copy-overwrite/.prettierignore +1 -0
@@ -0,0 +1,248 @@
1
+ /**
2
+ * The Telegram bot token held in the project's secrets provider (#4555).
3
+ *
4
+ * Before this, `store-token` wrote the token in plaintext to
5
+ * `<notify.stateDir>/.env`: the only Lisa-managed secret outside the secrets
6
+ * contract. When the project declares a secrets provider (`secrets.provider`
7
+ * set and not `env`), the token instead lives in that provider under one
8
+ * per-project name ({@link telegramSecretName}), and nothing is written to
9
+ * disk:
10
+ * - `store-token` stores it there: from a leftover plaintext file (migration)
11
+ * or from the operator's prompt or clipboard. It reads the secret back and
12
+ * compares hashes, and only then deletes the file.
13
+ * - `start` resolves it once and hands it to tmux on stdin, never argv. A
14
+ * plaintext file left behind stops `start` with the exact command that
15
+ * migrates it. An unreachable, rate-limited or slow provider is a failure
16
+ * (exit 1) with retry guidance, never a fallback to a stale file.
17
+ * With no provider configured the old `.env` path in token.mjs is unchanged.
18
+ *
19
+ * Every provider call goes through `lisa-secrets-access` (`surfaces.mjs` for
20
+ * the config, `providers.mjs` for reads and writes), behind an injectable
21
+ * adapter so tests run against a fake vault. The token is never returned to
22
+ * the CLI, put in a message, or logged: errors carry fixed reason text, never
23
+ * a provider's raw error, since a failed write's error can quote its argv.
24
+ *
25
+ * The adapter and provider-error handling live in token-provider.mjs and the
26
+ * plaintext-file migration helpers in token-migrate.mjs; this module keeps
27
+ * the two flows and re-exports what the CLI imports.
28
+ * @module session-manager/token-store
29
+ */
30
+ import * as nodeFs from "node:fs";
31
+
32
+ import {
33
+ TOKEN_VAR,
34
+ TokenStoreError,
35
+ assertMigratable,
36
+ digest,
37
+ holdsToken,
38
+ keepExisting,
39
+ readEnvFile,
40
+ removeAfterVerify,
41
+ setupError,
42
+ } from "./token-migrate.mjs";
43
+ import { guarded } from "./token-provider.mjs";
44
+ import { validateBotToken } from "./token.mjs";
45
+
46
+ export { TokenStoreError } from "./token-migrate.mjs";
47
+ export {
48
+ classifyProviderFailure,
49
+ defaultSecretsAdapter,
50
+ loadTokenSecrets,
51
+ } from "./token-provider.mjs";
52
+
53
+ /** Providers whose secrets live in a project that a create must name. */
54
+ const PROJECT_SCOPED = new Set(["bitwarden"]);
55
+
56
+ /** The usage note stored with the secret (format: note-format.mjs). */
57
+ const NOTE = [
58
+ "Telegram bot token for a Lisa session manager, stored by its store-token command and read only by its start command.",
59
+ "scope: one Telegram bot - whoever holds it can read and send that bot's messages",
60
+ "owner: lisa-session-manager",
61
+ ].join("\n");
62
+
63
+ /**
64
+ * The provider secret name for one manager: `TELEGRAM_BOT_TOKEN_<NAME>`, with
65
+ * the manager name upper-snaked. The `TELEGRAM_` prefix keeps
66
+ * `scrubWorkerEnv` stripping it from every worker's environment.
67
+ * @param {string} managerName - `sessionManager.name`, e.g. `lisa-1a2b-manager`
68
+ * @returns {string} e.g. `TELEGRAM_BOT_TOKEN_LISA_1A2B_MANAGER`
69
+ */
70
+ export function telegramSecretName(managerName) {
71
+ const suffix = String(managerName)
72
+ .toUpperCase()
73
+ .replaceAll(/[^A-Z0-9]+/g, "_");
74
+ return `${TOKEN_VAR}_${suffix}`;
75
+ }
76
+
77
+ /**
78
+ * Refuse a name the project's `secrets.require` allowlist does not declare:
79
+ * the provider would never hand it to this project.
80
+ * @param {{ require?: string[] | null }} cfg - Secrets config
81
+ * @param {string} name - Secret name
82
+ */
83
+ function assertDeclared(cfg, name) {
84
+ if (Array.isArray(cfg.require) && !cfg.require.includes(name)) {
85
+ throw setupError(
86
+ `${name} is not declared in secrets.require in .lisa.config.json, so ` +
87
+ `this project may not read it. Add "${name}" to secrets.require, ` +
88
+ `then run this again.`
89
+ );
90
+ }
91
+ }
92
+
93
+ /**
94
+ * The provider project a new secret goes in: `--vault-project`, else the one
95
+ * project `secrets.narrow.projectIds` names, else the one project every
96
+ * visible secret lives in. Exit 2 rather than guess.
97
+ * @param {object} cfg - Secrets config
98
+ * @param {Array<{ projectId: string | null }>} rows - Visible secrets
99
+ * @param {{ name: string, vaultProject?: string }} input - Secret and flag
100
+ * @returns {string | undefined} Project id (undefined: provider has none)
101
+ */
102
+ function chooseProject(cfg, rows, { name, vaultProject }) {
103
+ if (!PROJECT_SCOPED.has(cfg.provider)) return undefined;
104
+ const narrowed = cfg.narrow?.projectIds ?? [];
105
+ if (vaultProject) {
106
+ if (narrowed.length > 0 && !narrowed.includes(vaultProject)) {
107
+ throw setupError(
108
+ `--vault-project ${vaultProject} is not in secrets.narrow.projectIds, ` +
109
+ `so ${name} would be stored where this project cannot read it.`
110
+ );
111
+ }
112
+ return vaultProject;
113
+ }
114
+ if (narrowed.length === 1) return narrowed[0];
115
+ const seen = [...new Set(rows.map(row => row.projectId).filter(Boolean))];
116
+ if (seen.length === 1) return seen[0];
117
+ throw setupError(
118
+ `Cannot tell which ${cfg.provider} project to store ${name} in ` +
119
+ `(${seen.length} projects are visible). Run store-token again with ` +
120
+ `--vault-project <project id>.`
121
+ );
122
+ }
123
+
124
+ /**
125
+ * Store the bot token in the secrets provider: look it up, take it from the
126
+ * plaintext file (migration) or `readToken` (prompt or clipboard), create or
127
+ * replace it, read it back and compare hashes, and only then delete the
128
+ * file. An existing secret is kept unless `replace`.
129
+ * @param {{ cfg: object, adapter: object, name: string, stateDir: string,
130
+ * replace?: boolean, vaultProject?: string,
131
+ * readToken: () => Promise<{ token?: string, clear?: () => boolean,
132
+ * stored?: boolean, reason?: string, message?: string }>,
133
+ * fs?: object }} input - Config, adapter, secret
134
+ * name, resolved state dir, flags, the token reader and an fs seam
135
+ * @returns {Promise<object>} `{stored:true,storage:"provider",...}`, or the
136
+ * reader's `{stored:false,...}` outcome
137
+ */
138
+ export async function storeTokenInProvider(input) {
139
+ const { cfg, adapter, name, replace = false, fs = nodeFs } = input;
140
+ const where = {
141
+ provider: cfg.provider,
142
+ name,
143
+ retry:
144
+ `Could not store the Telegram bot token in ${cfg.provider}: <reason>. ` +
145
+ `Nothing was stored and any plaintext token file was kept. Wait a ` +
146
+ `minute and run store-token again.`,
147
+ };
148
+ assertDeclared(cfg, name);
149
+ const file = readEnvFile(input.stateDir, fs);
150
+ assertMigratable(file);
151
+ await guarded(() => adapter.preflight(cfg), where);
152
+ const rows = await guarded(() => adapter.list(cfg), where);
153
+ const existing = rows.find(row => row.key === name);
154
+ if (existing && !replace) {
155
+ return keepExisting(existing, file, { cfg, name, fs });
156
+ }
157
+
158
+ const read = holdsToken(file)
159
+ ? { token: file.token }
160
+ : await input.readToken();
161
+ if (read.token === undefined) return read;
162
+ const projectId = existing ? undefined : chooseProject(cfg, rows, input);
163
+ await guarded(
164
+ () =>
165
+ existing
166
+ ? adapter.replace(cfg, { id: existing.id, value: read.token })
167
+ : adapter.create(cfg, {
168
+ name,
169
+ value: read.token,
170
+ projectId,
171
+ note: NOTE,
172
+ }),
173
+ where
174
+ );
175
+ const after = (await guarded(() => adapter.list(cfg), where)).find(
176
+ row => row.key === name
177
+ );
178
+ if (after === undefined || digest(after.value) !== digest(read.token)) {
179
+ throw new TokenStoreError(
180
+ `Reading ${name} back from ${cfg.provider} did not return what was ` +
181
+ `written, so the token is not proven stored. Any plaintext token ` +
182
+ `file was kept. Run store-token again.`,
183
+ 1
184
+ );
185
+ }
186
+ return {
187
+ stored: true,
188
+ storage: "provider",
189
+ provider: cfg.provider,
190
+ secret: name,
191
+ verified: true,
192
+ ...removeAfterVerify(file, fs),
193
+ ...(read.clear ? { clipboardCleared: read.clear() } : {}),
194
+ };
195
+ }
196
+
197
+ /**
198
+ * Resolve the bot token for `start`, once, from the provider. Refuses (exit
199
+ * 2) a leftover plaintext file that holds a token line, naming `fixCommand`
200
+ * (the `store-token` call that migrates it; an empty or comment-only file
201
+ * holds nothing to migrate and does not stop `start`), an undeclared or
202
+ * missing secret, and a value that is not
203
+ * bot-token shaped; fails (exit 1) when the provider is unreachable,
204
+ * rate-limited or slow, saying nothing was started.
205
+ * @param {{ cfg: object, adapter: object, name: string, stateDir: string,
206
+ * fixCommand: string, fs?: object }} input - Config, adapter, secret name,
207
+ * resolved state dir, the migrating command and an fs seam
208
+ * @returns {Promise<string>} The token, for the tmux stdin line only
209
+ */
210
+ export async function resolveTelegramToken(input) {
211
+ const { cfg, adapter, name, fixCommand, fs = nodeFs } = input;
212
+ assertDeclared(cfg, name);
213
+ const file = readEnvFile(input.stateDir, fs);
214
+ if (holdsToken(file)) {
215
+ throw setupError(
216
+ `A plaintext Telegram bot token file is still at ${file.path}. With a ` +
217
+ `secrets provider configured the token must live in ` +
218
+ `${cfg.provider} only. Nothing was started. Move it there (this ` +
219
+ `stores the token, verifies it and deletes the file), then run start ` +
220
+ `again:\n ${fixCommand}`
221
+ );
222
+ }
223
+ const where = {
224
+ provider: cfg.provider,
225
+ name,
226
+ retry:
227
+ `Could not read the Telegram bot token from ${cfg.provider}: ` +
228
+ `<reason>. Nothing was started. Wait a minute and run start again; if ` +
229
+ `it keeps failing, check ${cfg.provider}'s status and this machine's ` +
230
+ `network.`,
231
+ };
232
+ await guarded(() => adapter.preflight(cfg), where);
233
+ const rows = await guarded(() => adapter.list(cfg), where);
234
+ const hit = rows.find(row => row.key === name);
235
+ if (!hit?.value) {
236
+ throw setupError(
237
+ `${cfg.provider} has no secret named ${name}, so the manager has no ` +
238
+ `bot token. Nothing was started. Store it with:\n ${fixCommand}`
239
+ );
240
+ }
241
+ if (!validateBotToken(hit.value)) {
242
+ throw setupError(
243
+ `${name} in ${cfg.provider} does not look like a Telegram bot token. ` +
244
+ `Nothing was started. Run store-token --replace to store the right one.`
245
+ );
246
+ }
247
+ return hit.value;
248
+ }
@@ -5,30 +5,40 @@
5
5
  * reachable), and never put in argv, a return value, an error message or a
6
6
  * log line. An existing token is replaced only on request. Split out of
7
7
  * launch.mjs, which re-exports everything here.
8
+ *
9
+ * The `.env` file is the storage only when the project has no secrets
10
+ * provider; with one, token-store.mjs stores the token there instead and
11
+ * reuses the prompt and clipboard readers (#4555).
12
+ *
13
+ * Validation, the prompt and clipboard readers and the printed `store-token`
14
+ * command live in token-read.mjs, re-exported here, to keep this module under
15
+ * the line budget.
8
16
  * @module token
9
17
  */
10
18
  import { randomUUID } from "node:crypto";
11
19
  import * as nodeFs from "node:fs";
12
20
  import path from "node:path";
13
21
 
14
- import { readClipboard } from "./clipboard.mjs";
15
22
  import { LaunchError, resolveStateDir } from "./state-dir.mjs";
23
+ import {
24
+ readTokenFromClipboard,
25
+ readTokenFromPrompt,
26
+ shellQuote,
27
+ validateBotToken,
28
+ } from "./token-read.mjs";
16
29
 
17
- /** The shape of a BotFather token: `<bot id>:<secret>`. */
18
- const BOT_TOKEN_PATTERN = /^\d+:[A-Za-z0-9_-]{30,}$/;
30
+ export {
31
+ buildStoreTokenCommand,
32
+ loadPromptSecret,
33
+ readTokenFromClipboard,
34
+ readTokenFromPrompt,
35
+ shellQuote,
36
+ validateBotToken,
37
+ } from "./token-read.mjs";
19
38
 
20
39
  /** The plugin reads its token from this file in the state dir. */
21
40
  const TOKEN_FILE_NAME = ".env";
22
41
 
23
- /**
24
- * Whether `token` looks like a BotFather bot token.
25
- * @param {unknown} token - Candidate
26
- * @returns {boolean} True for `<digits>:<30+ of [A-Za-z0-9_-]>`
27
- */
28
- export function validateBotToken(token) {
29
- return typeof token === "string" && BOT_TOKEN_PATTERN.test(token);
30
- }
31
-
32
42
  /**
33
43
  * Write `<stateDir>/.env` as `TELEGRAM_BOT_TOKEN=<token>`.
34
44
  *
@@ -64,65 +74,6 @@ export function writeTokenFile(stateDir, token, seams = {}) {
64
74
  return { path: target };
65
75
  }
66
76
 
67
- /**
68
- * Load `promptSecret`/`canPrompt` from the secrets-access skill, by path
69
- * relative to this file, the same way other skills reach it. Lazy so the
70
- * argv builders never pay for it.
71
- * @returns {Promise<{ promptSecret: Function, canPrompt: Function }>} Module
72
- */
73
- export function loadPromptSecret() {
74
- return import(
75
- new URL(
76
- "../../lisa-secrets-access/scripts/prompt-secret.mjs",
77
- import.meta.url
78
- ).href
79
- );
80
- }
81
-
82
- /**
83
- * Quote one word for a POSIX shell.
84
- * @param {string} word - Word to quote
85
- * @returns {string} Single-quoted word
86
- */
87
- function shellQuote(word) {
88
- const escaped = String(word).replaceAll("'", String.raw`'\''`);
89
- return `'${escaped}'`;
90
- }
91
-
92
- /**
93
- * The command an operator pastes into their own terminal to store the token,
94
- * for when the caller (an agent's Bash) has no TTY to prompt on.
95
- * @param {{ scriptsDir: string, projectRoot: string, replace?: boolean }}
96
- * input - Script and project locations, and whether to carry `--replace`
97
- * @returns {string} One shell line
98
- */
99
- export function buildStoreTokenCommand({
100
- scriptsDir,
101
- projectRoot,
102
- replace,
103
- fromClipboard = false,
104
- }) {
105
- const script = shellQuote(path.join(scriptsDir, "session-manager.mjs"));
106
- const flags =
107
- (replace ? " --replace" : "") + (fromClipboard ? " --from-clipboard" : "");
108
- return `node ${script} store-token${flags} --project-root ${shellQuote(projectRoot)}`;
109
- }
110
-
111
- /** Why `store-token` cannot prompt here, and the two ways forward. */
112
- const NO_TTY_HINT =
113
- "No terminal to prompt on, and Claude Code's ! prefix has no TTY either. " +
114
- "Run `command` in a separate terminal app, or copy the token from " +
115
- "BotFather and run `clipboardCommand`.";
116
-
117
- /** The `invalid` outcome; names the expected shape, never the input. */
118
- const INVALID = Object.freeze({
119
- stored: false,
120
- reason: "invalid",
121
- message:
122
- "That does not look like a Telegram bot token " +
123
- "(expected <digits>:<30 or more letters, digits, _ or ->).",
124
- });
125
-
126
77
  /**
127
78
  * Refuse to overwrite an existing token unless `replace` was asked for: a
128
79
  * second project that shares this state dir by mistake would otherwise
@@ -161,31 +112,17 @@ export function storeTokenFromClipboard(input) {
161
112
  const { replace = false, io = {} } = input;
162
113
  const stateDir = resolveStateDir(input.stateDir, input);
163
114
  assertReplaceable(stateDir, replace, io);
164
- const clip = (io.readClipboard ?? readClipboard)();
165
- if (!clip.ok) {
166
- return { stored: false, reason: clip.reason, message: clip.message };
167
- }
168
- const token = clip.text.trim();
169
- if (!token) {
170
- return {
171
- stored: false,
172
- reason: "empty",
173
- message: "The clipboard is empty.",
174
- };
175
- }
176
- if (!validateBotToken(token)) return { ...INVALID };
177
- const written = writeTokenFile(stateDir, token, io);
178
- return { stored: true, ...written, clipboardCleared: clip.clear() };
115
+ const read = readTokenFromClipboard(io);
116
+ if (read.token === undefined) return read;
117
+ const written = writeTokenFile(stateDir, read.token, io);
118
+ return { stored: true, ...written, clipboardCleared: read.clear() };
179
119
  }
180
120
 
181
121
  /**
182
- * Prompt for the bot token on the operator's terminal and store it.
183
- *
184
- * An existing token is never overwritten without `replace`. With no TTY this
185
- * does not prompt and does not fail: it returns the exact command for the
186
- * operator to run in a separate terminal app, and the `--from-clipboard` form
187
- * of it, because an agent's Bash (and Claude Code's `!` prefix) can never
188
- * answer a prompt and a hung setup looks like a slow one.
122
+ * Prompt for the bot token on the operator's terminal and store it in
123
+ * `<stateDir>/.env`. An existing token is never overwritten without
124
+ * `replace`; with no TTY it returns the commands that work instead (see
125
+ * {@link readTokenFromPrompt}).
189
126
  * @param {{ stateDir: string, scriptsDir: string, projectRoot: string,
190
127
  * replace?: boolean, env?: Record<string, string | undefined>,
191
128
  * homedir?: string, io?: { canPrompt?: () => boolean,
@@ -200,33 +137,15 @@ export async function storeToken(input) {
200
137
  const { scriptsDir, projectRoot, replace = false, io = {} } = input;
201
138
  const stateDir = resolveStateDir(input.stateDir, input);
202
139
  assertReplaceable(stateDir, replace, io);
203
- const loaded =
204
- io.canPrompt && io.promptSecret ? null : await loadPromptSecret();
205
- const canPrompt = io.canPrompt ?? (() => loaded.canPrompt());
206
- const promptSecret = io.promptSecret ?? loaded.promptSecret;
207
-
208
- if (!canPrompt()) {
209
- return {
210
- stored: false,
211
- reason: "no-tty",
212
- message: NO_TTY_HINT,
213
- command: buildStoreTokenCommand({ scriptsDir, projectRoot, replace }),
214
- clipboardCommand: buildStoreTokenCommand({
215
- scriptsDir,
216
- projectRoot,
217
- replace,
218
- fromClipboard: true,
219
- }),
220
- };
221
- }
222
- const typed = promptSecret(
223
- `Paste the Telegram bot token for ${stateDir} (input is hidden): `
224
- );
225
- if (!typed) {
226
- return { stored: false, reason: "empty", message: "Nothing entered." };
227
- }
228
- if (!validateBotToken(typed)) return { ...INVALID };
229
- return { stored: true, ...writeTokenFile(stateDir, typed, io) };
140
+ const read = await readTokenFromPrompt({
141
+ label: stateDir,
142
+ scriptsDir,
143
+ projectRoot,
144
+ replace,
145
+ io,
146
+ });
147
+ if (read.token === undefined) return read;
148
+ return { stored: true, ...writeTokenFile(stateDir, read.token, io) };
230
149
  }
231
150
 
232
151
  /**
@@ -3,14 +3,19 @@ name: lisa-setup-session-manager
3
3
  description: "Set up the local session…"
4
4
  allowed-tools: ["Bash", "Read", "Write", "Skill", "AskUserQuestion"]
5
5
  ---
6
- Set up the local session manager for this project: writes the non-secret `sessionManager` block to `.lisa.config.json` (detecting a multi-repo layout: repos under `projects/`, or directly under the project root), stores the project's own Telegram bot token outside the repo, checks the Telegram plugin is installed but not enabled at user scope, keeps the manager's state out of git, seeds the checked-in runbook, starts the manager in tmux, walks the operator through pairing, and finishes with doctor's session-manager check. Idempotent.
6
+ Set up the local session manager for this project: writes the non-secret `sessionManager` block to `.lisa.config.json` (detecting a multi-repo layout: repos under `projects/`, or directly under the project root), optionally sets up a Telegram notification channel (the project's own bot token stored in its secrets provider, or outside the repo when none is configured, with a leftover plaintext token file migrated into the provider, the Telegram plugin installed but not enabled at user scope, pairing; skipped entirely with no channel, the default), keeps the manager's state out of git, seeds the checked-in runbook, starts the manager in tmux, and finishes with doctor's session-manager check. Idempotent.
7
7
 
8
8
 
9
9
  # Setup session manager
10
10
 
11
- After this skill the project has a `sessionManager` block, a bot token in its own state directory, a
12
- runbook at `.lisa/automations/session-manager.runbook.md`, and a running manager paired with the
13
- operator's Telegram chat. Re-running is safe: every step keeps what is already there.
11
+ After this skill the project has a `sessionManager` block, a runbook at
12
+ `.lisa/automations/session-manager.runbook.md`, and a running manager. Telegram is optional: with it,
13
+ the project also has its own bot token (in the project's secrets provider when one is configured,
14
+ else in its own state directory) and a manager paired with the operator's
15
+ Telegram chat; with no channel (the default), Steps 3 and 4 and the pairing in Step 9 are skipped,
16
+ and questions wait in the manager's ledger, where `status` shows them, and on the item itself,
17
+ which the manager marks human-needed while it keeps dispatching other work. Re-running is safe: every
18
+ step keeps what is already there.
14
19
 
15
20
  The manager itself always runs on Claude Code (see `lisa-session-manager` "Runtime parity"). Setup
16
21
  can run from any agent that can reach the scripts; `start` launches the Claude Code manager.
@@ -42,15 +47,23 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
42
47
 
43
48
  ## Step 2: Write the config block
44
49
 
45
- 1. Preview: `node "$SM/session-manager.mjs" init-config --project-root "$ROOT"`. It detects
50
+ 0. Ask the operator whether they want Telegram notifications: worker questions and status on their
51
+ phone, through a bot they create for this project. Say plainly that it is optional: without it
52
+ the manager runs normally, and questions wait in its ledger (shown by `status`) instead of
53
+ reaching a phone. Their answer is `<notify>`: `telegram` or `none` (the default).
54
+ 1. Preview: `node "$SM/session-manager.mjs" init-config --notify <notify> --project-root "$ROOT"`.
55
+ It detects
46
56
  `projects/*/.lisa.config.json`, or, when `projects/` holds none, the root's own children that
47
57
  have a `.lisa.config.json` and their own `.git` (written as `repos.root: "."`). It proposes
48
- `name`, `interval`, `repos`, `capacity`, `stall` and a per-project `notify.stateDir`. Repo
58
+ `name`, `interval`, `repos`, `capacity`, `stall` and `notify`: `{"provider":"none"}`, or with
59
+ `--notify telegram` the telegram provider and a per-project `notify.stateDir`. Repo
49
60
  detection leaves out linked worktrees and keeps one checkout per remote, so ticket worktrees and
50
61
  second clones are not proposed. Show the block to the operator and ask whether any repo is
51
62
  missing or should not be routed.
52
63
  2. Write it: the same command with `--write`. It adds only non-secret fields and never overwrites an
53
- existing block (`reason: "exists"` means keep it).
64
+ existing block (`reason: "exists"` means keep it). To add Telegram to an existing block later,
65
+ set `notify` to `{"provider":"telegram","stateDir":"~/.claude/channels/telegram-<project>"}`
66
+ (the `<project>` part as `init-config --notify telegram` would derive it) and re-run this skill.
54
67
  3. Each repo's `hints` are a draft: its name plus one per well-known dependency (`NestJS`, `Expo`,
55
68
  `AWS CDK`, ...). Ask the operator to correct them and add the areas that identify the repo
56
69
  (e.g. `api`: `["NestJS","migrations"]`, `web`: `["Expo","screens"]`), and whether to
@@ -70,6 +83,12 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
70
83
  "me", spelled as the tracker API returns it: the GitHub **login** (`gh api users/<login> --jq
71
84
  .login`), the Jira `accountId`, or the Linear user id (the operator's entry in the team's member
72
85
  list, or `viewer.id` only when the operator runs the lookup with their own credential).
86
+ **Recommend setting it in every setup**, even a single-user one: it is also who may answer a
87
+ human-needed question by replying on the item. With neither `operatorIds` nor
88
+ `trustedAuthorIds` set, the manager reads no answer off the item at all, because the tracker
89
+ credential's identity is the one the workers and the manager post as, so its comments cannot be
90
+ told apart from a human's answer. The operator then answers only at the terminal, with the
91
+ `answerCommand` that `status` lists. Say so plainly.
73
92
  5. Ask whether to set `sessionManager.backlogPickup` to `true` (default off). When the Ready queue
74
93
  is exhausted and a worker slot is still free, the manager then looks at backlog items (open
75
94
  leaves in no lifecycle role) that nobody else is assigned to, that are not human-held and have
@@ -81,12 +100,45 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
81
100
 
82
101
  ## Step 3: Store the bot token
83
102
 
103
+ Only when `sessionManager.notify.provider` is `telegram`. With no channel (`none`, or no `notify`
104
+ block) there is no token: skip Steps 3 and 4 and go to Step 5.
105
+
84
106
  The operator creates a bot with @BotFather, one per project. Then run
85
107
  `node "$SM/session-manager.mjs" store-token --project-root "$ROOT"`.
86
108
 
109
+ Where the token goes depends on the project's secrets provider (`secrets.provider` in
110
+ `.lisa.config.json`, read through `lisa-secrets-access`):
111
+
112
+ - **A provider is configured** (`secrets.provider` set and not `env`): the token is stored in it as
113
+ `TELEGRAM_BOT_TOKEN_<NAME>` (the manager name upper-snaked, e.g. `lisa-1a2b-manager` →
114
+ `TELEGRAM_BOT_TOKEN_LISA_1A2B_MANAGER`) and nothing is written to disk. `start` resolves it from
115
+ there each time. If `secrets.require` is declared, add that name to it first, or `store-token`
116
+ exits 2 saying so.
117
+ - **Migration.** If an older setup left a plaintext `<notify.stateDir>/.env`, `store-token`
118
+ moves it: it stores the token, reads it back and compares, and only then deletes the file. It
119
+ needs no prompt. Report it as "moved the bot token from `<path>` into `<provider>` and deleted
120
+ the file" (the `migratedFrom` and `deleted` fields), never with the value.
121
+ - `alreadyStored: true`: the provider already holds it; nothing to do. A matching leftover file
122
+ is deleted too.
123
+ - Exit 2 naming `--vault-project`: the provider project is ambiguous. Ask the operator which
124
+ project, then re-run with `--vault-project <id>`.
125
+ - Exit 2 because the file holds a different token or other keys: say what `message` reports and
126
+ let the operator decide (`--replace` makes the file's token the stored one).
127
+ - Exit 1 (provider unreachable or rate-limited): nothing was stored and the file was kept. Wait a
128
+ minute and run it again.
129
+ - A provider Lisa cannot write to (anything but Bitwarden today): the message asks the operator
130
+ to create `TELEGRAM_BOT_TOKEN_<NAME>` in the provider themselves; then re-run `store-token`,
131
+ which verifies it and deletes any plaintext copy.
132
+ - **No provider configured**: the token is written to `<notify.stateDir>/.env` (mode 0600) as
133
+ before. Tell the operator that this is a plaintext file, that doctor will warn about it, and that
134
+ configuring a secrets provider and re-running `store-token` moves it there.
135
+
136
+ Outcomes either way:
137
+
87
138
  - `stored: true`: done.
88
- - Exit 2 because a token already exists: keep it (re-running setup is safe). Only when the operator
89
- says the stored token is wrong or belongs to another project, re-run with `store-token --replace`.
139
+ - With no provider, exit 2 because a token already exists: keep it (re-running setup is safe). Only
140
+ when the operator says the stored token is wrong or belongs to another project, re-run with
141
+ `store-token --replace`.
90
142
  - `reason: "no-tty"` (an agent's Bash has no terminal): offer the operator both routes, and say
91
143
  plainly that Claude Code's `!` prefix has no terminal either, so it fails the same way:
92
144
  - **Clipboard (simplest):** they copy the token from the BotFather chat and tell you; then run
@@ -98,11 +150,13 @@ The operator creates a bot with @BotFather, one per project. Then run
98
150
  - `empty` / `invalid`: say what was wrong and ask again.
99
151
 
100
152
  Never ask for the token in chat, never echo, log or commit it, and never put it in
101
- `.lisa.config.json`. It lives only in `<notify.stateDir>/.env`.
153
+ `.lisa.config.json`. It lives only in the secrets provider, or in `<notify.stateDir>/.env` when
154
+ no provider is configured. Never read it back from either to check it: `store-token` already
155
+ verified the stored copy.
102
156
 
103
157
  ## Step 4: Telegram plugin scope
104
158
 
105
- Read `claude plugin list --json` and look at the `telegram@claude-plugins-official` entries.
159
+ Only when `notify.provider` is `telegram`. Read `claude plugin list --json` and look at the `telegram@claude-plugins-official` entries.
106
160
 
107
161
  - **Not installed:** ask the operator to install it with
108
162
  `claude plugin install telegram@claude-plugins-official -s user`, then re-check.
@@ -175,11 +229,17 @@ project), on every machine that runs the manager:
175
229
  bypass-permissions worker runs. Ask the operator for the IDs, add them, re-run `validate`, then
176
230
  continue. `lisa doctor` fails on the same condition.
177
231
  1. `node "$SM/session-manager.mjs" start --project-root "$ROOT"`. `started` and `already-running`
178
- are both fine. Exit 2 names what is missing (usually the token from Step 3), or that a tmux
179
- session of the same name belongs to another project root, or that the manager
180
- exited right after starting. For the last, ask the operator to run the printed foreground command
181
- in their own terminal: claude prints its own error there. Fix it, then run `start` again.
182
- 2. Walk the operator through pairing, in their own terminal:
232
+ are both fine. With no channel it needs no token, plugin or pairing and launches without
233
+ `--channels`. Exit 2 names what is missing (with Telegram, usually the token from Step 3, or a
234
+ plaintext `.env` left over beside a secrets provider: run the `store-token` command the message
235
+ names, which migrates it, then `start` again), or that a tmux session of the same name belongs
236
+ to another project root, or that the manager exited right after starting. For the last, ask the
237
+ operator to run the printed foreground command in their own terminal: claude prints its own
238
+ error there (with a provider, the line fetches the token itself; it never holds the value). Fix
239
+ it, then run `start` again. Exit 1 saying "Nothing was started" means the secrets provider could
240
+ not be reached or rate-limited the read: wait a minute and run `start` again.
241
+ 2. Only with Telegram (`notify` is `telegram` in the `start` output); with no channel there is no
242
+ pairing, so skip to Step 10. Walk the operator through pairing, in their own terminal:
183
243
  1. `tmux attach -t <name>` (the `attach` value from the output).
184
244
  2. Send any message to the bot in a private chat. The bot replies with a pairing code.
185
245
  3. In the attached manager session: `/telegram:access pair <code>`.
@@ -193,10 +253,13 @@ Telegram message asked for it. Every allowlisted sender effectively has shell ac
193
253
  ## Step 10: Verify
194
254
 
195
255
  Run `lisa doctor` (or `npx @codyswann/lisa doctor` when the `lisa` CLI is not on the PATH) and
196
- confirm the "Session manager Telegram isolation?" check is green. Fix every warning it names, then
256
+ confirm the "Session manager notifications?" check is green. With no channel its detail is
257
+ `notifications: none`, and it skips every Telegram check. Fix every warning it names, then
197
258
  `node "$SM/session-manager.mjs" status --project-root "$ROOT"` should show the manager running.
198
259
 
199
- Report: the config block written (or kept), where the token lives (the path, never the value), the
200
- plugin scope result, the runbook path, which repo dirs were already trusted and which the operator
260
+ Report: the config block written (or kept), the notification channel (`telegram` or `none`), and
261
+ with Telegram where the token lives (the provider and secret name, or the file path; never the
262
+ value), whether a plaintext `.env` was migrated and deleted, and the plugin scope result, the
263
+ runbook path, which repo dirs were already trusted and which the operator
201
264
  accepted trust in, what the competing-loop check found, the manager's tmux session name, and the
202
265
  doctor result.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Run the local session manager: one dispatch-and-relay cycle (the /loop prompt), or start, stop or show the tmux-hosted manager. Dispatches Ready work items to fresh background worker sessions and relays their questions over the project's Telegram bot. Claude Code only; configure it with /lisa:setup:session-manager."
2
+ description: "Run the local session manager: one dispatch-and-relay cycle (the /loop prompt), or start, stop or show the tmux-hosted manager. Dispatches Ready work items to fresh background worker sessions and relays their questions over the project's Telegram bot when one is configured (Telegram is optional). Claude Code only; configure it with /lisa:setup:session-manager."
3
3
  allowed-tools: ["Skill"]
4
4
  argument-hint: "[cycle|start|stop|status]"
5
5
  ---
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Set up the local session manager for this project: write the sessionManager config block, store the project's own Telegram bot token, check the Telegram plugin scope, seed the runbook, start the manager in tmux, walk through pairing, and run doctor's session-manager check."
2
+ description: "Set up the local session manager for this project: write the sessionManager config block, optionally set up Telegram notifications (store the project's own bot token in its secrets provider, migrating any plaintext token file, check the plugin scope, walk through pairing; skipped with no channel, the default), seed the runbook, start the manager in tmux, and run doctor's session-manager check."
3
3
  allowed-tools: ["Skill"]
4
4
  ---
5
5