@codyswann/lisa 4.85.0 → 4.86.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 (333) hide show
  1. package/all/copy-overwrite/scripts/lib/completion-proof-content.mjs +63 -22
  2. package/all/copy-overwrite/scripts/lib/npm-update-hosted-hook.mjs +6 -1
  3. package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +19 -3
  4. package/all/copy-overwrite/scripts/npm-updater-helper-graph.json +2 -2
  5. package/dist/cli/doctor-session-manager-pending.d.ts +17 -0
  6. package/dist/cli/doctor-session-manager-pending.d.ts.map +1 -0
  7. package/dist/cli/doctor-session-manager-pending.js +130 -0
  8. package/dist/cli/doctor-session-manager-pending.js.map +1 -0
  9. package/dist/cli/doctor-session-manager-token.d.ts +69 -0
  10. package/dist/cli/doctor-session-manager-token.d.ts.map +1 -0
  11. package/dist/cli/doctor-session-manager-token.js +264 -0
  12. package/dist/cli/doctor-session-manager-token.js.map +1 -0
  13. package/dist/cli/doctor-session-manager.d.ts +3 -1
  14. package/dist/cli/doctor-session-manager.d.ts.map +1 -1
  15. package/dist/cli/doctor-session-manager.js +168 -146
  16. package/dist/cli/doctor-session-manager.js.map +1 -1
  17. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  18. package/dist/core/lisa-owned-hash-ledger.js +16 -0
  19. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  20. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  21. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  22. package/dist/core/upstream-evidence-manifest.js +168 -26
  23. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  24. package/dist/opencode/plugin-templates/parity-safety-net.sh +19 -3
  25. package/package.json +4 -4
  26. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  28. package/plugins/lisa/.codex-plugin/skills/lisa-parity-sentry-sdk-setup/SKILL.md +24 -17
  29. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/SKILL.md +5 -3
  30. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  31. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/validate-config.mjs +86 -31
  32. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/SKILL.md +197 -54
  33. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/references/runbook-template.md +23 -10
  34. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  35. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  36. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  37. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  38. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  39. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  40. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  41. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  42. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  43. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/config.mjs +39 -11
  44. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  45. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  46. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  47. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  48. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  49. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  50. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  51. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  52. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  53. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  54. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  55. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  56. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  57. package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token.mjs +39 -120
  58. package/plugins/lisa/.codex-plugin/skills/lisa-setup-session-manager/SKILL.md +82 -19
  59. package/plugins/lisa/commands/session-manager.md +1 -1
  60. package/plugins/lisa/commands/setup/session-manager.md +1 -1
  61. package/plugins/lisa/hooks/parity-safety-net.sh +19 -3
  62. package/plugins/lisa/rules/reference/config-resolution.md +39 -7
  63. package/plugins/lisa/skills/lisa-parity-sentry-sdk-setup/SKILL.md +24 -17
  64. package/plugins/lisa/skills/lisa-secrets-access/SKILL.md +5 -3
  65. package/plugins/lisa/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  66. package/plugins/lisa/skills/lisa-secrets-access/scripts/validate-config.mjs +86 -31
  67. package/plugins/lisa/skills/lisa-session-manager/SKILL.md +197 -54
  68. package/plugins/lisa/skills/lisa-session-manager/references/runbook-template.md +23 -10
  69. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  70. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  71. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  72. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  73. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  74. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  75. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  76. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  77. package/plugins/lisa/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  78. package/plugins/lisa/skills/lisa-session-manager/scripts/config.mjs +39 -11
  79. package/plugins/lisa/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  80. package/plugins/lisa/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  81. package/plugins/lisa/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  82. package/plugins/lisa/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  83. package/plugins/lisa/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  84. package/plugins/lisa/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  85. package/plugins/lisa/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  86. package/plugins/lisa/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  87. package/plugins/lisa/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  88. package/plugins/lisa/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  89. package/plugins/lisa/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  90. package/plugins/lisa/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  91. package/plugins/lisa/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  92. package/plugins/lisa/skills/lisa-session-manager/scripts/token.mjs +39 -120
  93. package/plugins/lisa/skills/lisa-setup-session-manager/SKILL.md +82 -19
  94. package/plugins/lisa-agy/commands/lisa/session-manager.md +1 -1
  95. package/plugins/lisa-agy/commands/lisa/setup/session-manager.md +1 -1
  96. package/plugins/lisa-agy/hooks/parity-safety-net.sh +19 -3
  97. package/plugins/lisa-agy/plugin.json +1 -1
  98. package/plugins/lisa-agy/skills/lisa-parity-sentry-sdk-setup/SKILL.md +24 -17
  99. package/plugins/lisa-agy/skills/lisa-secrets-access/SKILL.md +5 -3
  100. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  101. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/validate-config.mjs +86 -31
  102. package/plugins/lisa-agy/skills/lisa-session-manager/SKILL.md +197 -54
  103. package/plugins/lisa-agy/skills/lisa-session-manager/references/runbook-template.md +23 -10
  104. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  105. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  106. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  107. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  108. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  109. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  110. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  111. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  112. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  113. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/config.mjs +39 -11
  114. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  115. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  116. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  117. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  118. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  119. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  120. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  121. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  122. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  123. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  124. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  125. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  126. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  127. package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token.mjs +39 -120
  128. package/plugins/lisa-agy/skills/lisa-setup-session-manager/SKILL.md +82 -19
  129. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  130. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  131. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  132. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  133. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  134. package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
  135. package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
  136. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  137. package/plugins/lisa-copilot/commands/lisa/session-manager.md +1 -1
  138. package/plugins/lisa-copilot/commands/lisa/setup/session-manager.md +1 -1
  139. package/plugins/lisa-copilot/hooks/parity-safety-net.sh +19 -3
  140. package/plugins/lisa-copilot/rules/reference/config-resolution.md +39 -7
  141. package/plugins/lisa-copilot/skills/lisa-parity-sentry-sdk-setup/SKILL.md +24 -17
  142. package/plugins/lisa-copilot/skills/lisa-secrets-access/SKILL.md +5 -3
  143. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  144. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/validate-config.mjs +86 -31
  145. package/plugins/lisa-copilot/skills/lisa-session-manager/SKILL.md +197 -54
  146. package/plugins/lisa-copilot/skills/lisa-session-manager/references/runbook-template.md +23 -10
  147. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  148. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  149. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  150. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  151. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  152. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  153. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  154. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  155. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  156. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/config.mjs +39 -11
  157. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  158. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  159. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  160. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  161. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  162. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  163. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  164. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  165. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  166. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  167. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  168. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  169. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  170. package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token.mjs +39 -120
  171. package/plugins/lisa-copilot/skills/lisa-setup-session-manager/SKILL.md +82 -19
  172. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  173. package/plugins/lisa-cursor/commands/lisa/session-manager.md +1 -1
  174. package/plugins/lisa-cursor/commands/lisa/setup/session-manager.md +1 -1
  175. package/plugins/lisa-cursor/hooks/parity-safety-net.sh +19 -3
  176. package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +39 -7
  177. package/plugins/lisa-cursor/skills/lisa-parity-sentry-sdk-setup/SKILL.md +24 -17
  178. package/plugins/lisa-cursor/skills/lisa-secrets-access/SKILL.md +5 -3
  179. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  180. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/validate-config.mjs +86 -31
  181. package/plugins/lisa-cursor/skills/lisa-session-manager/SKILL.md +197 -54
  182. package/plugins/lisa-cursor/skills/lisa-session-manager/references/runbook-template.md +23 -10
  183. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  184. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  185. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  186. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  187. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  188. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  189. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  190. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  191. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  192. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/config.mjs +39 -11
  193. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  194. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  195. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  196. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  197. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  198. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  199. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  200. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  201. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  202. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  203. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  204. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  205. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  206. package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token.mjs +39 -120
  207. package/plugins/lisa-cursor/skills/lisa-setup-session-manager/SKILL.md +82 -19
  208. package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
  209. package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
  210. package/plugins/lisa-devin/hooks/parity-safety-net.sh +19 -3
  211. package/plugins/lisa-devin/rules/reference/config-resolution.md +39 -7
  212. package/plugins/lisa-devin/skills/lisa-parity-sentry-sdk-setup/SKILL.md +24 -17
  213. package/plugins/lisa-devin/skills/lisa-secrets-access/SKILL.md +5 -3
  214. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  215. package/plugins/lisa-devin/skills/lisa-secrets-access/scripts/validate-config.mjs +86 -31
  216. package/plugins/lisa-devin/skills/lisa-session-manager/SKILL.md +197 -54
  217. package/plugins/lisa-devin/skills/lisa-session-manager/references/runbook-template.md +23 -10
  218. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  219. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  220. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  221. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  222. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  223. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  224. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  225. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  226. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  227. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/config.mjs +39 -11
  228. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  229. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  230. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  231. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  232. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  233. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  234. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  235. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  236. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  237. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  238. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  239. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  240. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  241. package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token.mjs +39 -120
  242. package/plugins/lisa-devin/skills/lisa-setup-session-manager/SKILL.md +82 -19
  243. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  244. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  245. package/plugins/lisa-expo-agy/plugin.json +1 -1
  246. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  247. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  248. package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
  249. package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
  250. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  251. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  252. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  253. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  254. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  255. package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
  256. package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
  257. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  258. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  259. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  260. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  261. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  262. package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
  263. package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
  264. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  265. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  266. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  267. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  268. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  269. package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
  270. package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
  271. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  272. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  273. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  274. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  275. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  276. package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
  277. package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
  278. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  279. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  280. package/plugins/lisa-rails-agy/plugin.json +1 -1
  281. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  282. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  283. package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
  284. package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
  285. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  286. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  287. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  288. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  289. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  290. package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
  291. package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
  292. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  293. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  294. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  295. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  296. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  297. package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
  298. package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
  299. package/plugins/src/base/commands/session-manager.md +1 -1
  300. package/plugins/src/base/commands/setup/session-manager.md +1 -1
  301. package/plugins/src/base/hooks/parity-safety-net.sh +19 -3
  302. package/plugins/src/base/rules/reference/config-resolution.md +39 -7
  303. package/plugins/src/base/skills/lisa-parity-sentry-sdk-setup/SKILL.md +24 -17
  304. package/plugins/src/base/skills/lisa-secrets-access/SKILL.md +5 -3
  305. package/plugins/src/base/skills/lisa-secrets-access/scripts/providers.mjs +121 -3
  306. package/plugins/src/base/skills/lisa-secrets-access/scripts/validate-config.mjs +86 -31
  307. package/plugins/src/base/skills/lisa-session-manager/SKILL.md +197 -54
  308. package/plugins/src/base/skills/lisa-session-manager/references/runbook-template.md +23 -10
  309. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-cycle.mjs +21 -3
  310. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-human.mjs +199 -0
  311. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-manager-token.mjs +99 -0
  312. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-manager.mjs +52 -52
  313. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-queue.mjs +51 -139
  314. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-runtime.mjs +5 -3
  315. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-setup.mjs +94 -14
  316. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-status.mjs +73 -0
  317. package/plugins/src/base/skills/lisa-session-manager/scripts/cli-usage.mjs +105 -15
  318. package/plugins/src/base/skills/lisa-session-manager/scripts/config.mjs +39 -11
  319. package/plugins/src/base/skills/lisa-session-manager/scripts/human-answer.mjs +162 -0
  320. package/plugins/src/base/skills/lisa-session-manager/scripts/human-needed.mjs +198 -0
  321. package/plugins/src/base/skills/lisa-session-manager/scripts/json-input.mjs +34 -0
  322. package/plugins/src/base/skills/lisa-session-manager/scripts/launch-shell.mjs +115 -0
  323. package/plugins/src/base/skills/lisa-session-manager/scripts/launch.mjs +69 -60
  324. package/plugins/src/base/skills/lisa-session-manager/scripts/ledger-questions.mjs +252 -0
  325. package/plugins/src/base/skills/lisa-session-manager/scripts/ledger.mjs +22 -56
  326. package/plugins/src/base/skills/lisa-session-manager/scripts/queue-github.mjs +117 -0
  327. package/plugins/src/base/skills/lisa-session-manager/scripts/session-manager.mjs +17 -5
  328. package/plugins/src/base/skills/lisa-session-manager/scripts/token-migrate.mjs +180 -0
  329. package/plugins/src/base/skills/lisa-session-manager/scripts/token-provider.mjs +150 -0
  330. package/plugins/src/base/skills/lisa-session-manager/scripts/token-read.mjs +166 -0
  331. package/plugins/src/base/skills/lisa-session-manager/scripts/token-store.mjs +248 -0
  332. package/plugins/src/base/skills/lisa-session-manager/scripts/token.mjs +39 -120
  333. package/plugins/src/base/skills/lisa-setup-session-manager/SKILL.md +82 -19
@@ -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
  /**
@@ -1,14 +1,19 @@
1
1
  ---
2
2
  name: lisa-setup-session-manager
3
- description: "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."
3
+ description: "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."
4
4
  allowed-tools: ["Bash", "Read", "Write", "Skill", "AskUserQuestion"]
5
5
  ---
6
6
 
7
7
  # Setup session manager
8
8
 
9
- After this skill the project has a `sessionManager` block, a bot token in its own state directory, a
10
- runbook at `.lisa/automations/session-manager.runbook.md`, and a running manager paired with the
11
- operator's Telegram chat. Re-running is safe: every step keeps what is already there.
9
+ After this skill the project has a `sessionManager` block, a runbook at
10
+ `.lisa/automations/session-manager.runbook.md`, and a running manager. Telegram is optional: with it,
11
+ the project also has its own bot token (in the project's secrets provider when one is configured,
12
+ else in its own state directory) and a manager paired with the operator's
13
+ Telegram chat; with no channel (the default), Steps 3 and 4 and the pairing in Step 9 are skipped,
14
+ and questions wait in the manager's ledger, where `status` shows them, and on the item itself,
15
+ which the manager marks human-needed while it keeps dispatching other work. Re-running is safe: every
16
+ step keeps what is already there.
12
17
 
13
18
  The manager itself always runs on Claude Code (see `lisa-session-manager` "Runtime parity"). Setup
14
19
  can run from any agent that can reach the scripts; `start` launches the Claude Code manager.
@@ -40,15 +45,23 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
40
45
 
41
46
  ## Step 2: Write the config block
42
47
 
43
- 1. Preview: `node "$SM/session-manager.mjs" init-config --project-root "$ROOT"`. It detects
48
+ 0. Ask the operator whether they want Telegram notifications: worker questions and status on their
49
+ phone, through a bot they create for this project. Say plainly that it is optional: without it
50
+ the manager runs normally, and questions wait in its ledger (shown by `status`) instead of
51
+ reaching a phone. Their answer is `<notify>`: `telegram` or `none` (the default).
52
+ 1. Preview: `node "$SM/session-manager.mjs" init-config --notify <notify> --project-root "$ROOT"`.
53
+ It detects
44
54
  `projects/*/.lisa.config.json`, or, when `projects/` holds none, the root's own children that
45
55
  have a `.lisa.config.json` and their own `.git` (written as `repos.root: "."`). It proposes
46
- `name`, `interval`, `repos`, `capacity`, `stall` and a per-project `notify.stateDir`. Repo
56
+ `name`, `interval`, `repos`, `capacity`, `stall` and `notify`: `{"provider":"none"}`, or with
57
+ `--notify telegram` the telegram provider and a per-project `notify.stateDir`. Repo
47
58
  detection leaves out linked worktrees and keeps one checkout per remote, so ticket worktrees and
48
59
  second clones are not proposed. Show the block to the operator and ask whether any repo is
49
60
  missing or should not be routed.
50
61
  2. Write it: the same command with `--write`. It adds only non-secret fields and never overwrites an
51
- existing block (`reason: "exists"` means keep it).
62
+ existing block (`reason: "exists"` means keep it). To add Telegram to an existing block later,
63
+ set `notify` to `{"provider":"telegram","stateDir":"~/.claude/channels/telegram-<project>"}`
64
+ (the `<project>` part as `init-config --notify telegram` would derive it) and re-run this skill.
52
65
  3. Each repo's `hints` are a draft: its name plus one per well-known dependency (`NestJS`, `Expo`,
53
66
  `AWS CDK`, ...). Ask the operator to correct them and add the areas that identify the repo
54
67
  (e.g. `api`: `["NestJS","migrations"]`, `web`: `["Expo","screens"]`), and whether to
@@ -68,6 +81,12 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
68
81
  "me", spelled as the tracker API returns it: the GitHub **login** (`gh api users/<login> --jq
69
82
  .login`), the Jira `accountId`, or the Linear user id (the operator's entry in the team's member
70
83
  list, or `viewer.id` only when the operator runs the lookup with their own credential).
84
+ **Recommend setting it in every setup**, even a single-user one: it is also who may answer a
85
+ human-needed question by replying on the item. With neither `operatorIds` nor
86
+ `trustedAuthorIds` set, the manager reads no answer off the item at all, because the tracker
87
+ credential's identity is the one the workers and the manager post as, so its comments cannot be
88
+ told apart from a human's answer. The operator then answers only at the terminal, with the
89
+ `answerCommand` that `status` lists. Say so plainly.
71
90
  5. Ask whether to set `sessionManager.backlogPickup` to `true` (default off). When the Ready queue
72
91
  is exhausted and a worker slot is still free, the manager then looks at backlog items (open
73
92
  leaves in no lifecycle role) that nobody else is assigned to, that are not human-held and have
@@ -79,12 +98,45 @@ writes `$SM`, and pass `--project-root "$ROOT"` (the absolute project root) on e
79
98
 
80
99
  ## Step 3: Store the bot token
81
100
 
101
+ Only when `sessionManager.notify.provider` is `telegram`. With no channel (`none`, or no `notify`
102
+ block) there is no token: skip Steps 3 and 4 and go to Step 5.
103
+
82
104
  The operator creates a bot with @BotFather, one per project. Then run
83
105
  `node "$SM/session-manager.mjs" store-token --project-root "$ROOT"`.
84
106
 
107
+ Where the token goes depends on the project's secrets provider (`secrets.provider` in
108
+ `.lisa.config.json`, read through `lisa-secrets-access`):
109
+
110
+ - **A provider is configured** (`secrets.provider` set and not `env`): the token is stored in it as
111
+ `TELEGRAM_BOT_TOKEN_<NAME>` (the manager name upper-snaked, e.g. `lisa-1a2b-manager` →
112
+ `TELEGRAM_BOT_TOKEN_LISA_1A2B_MANAGER`) and nothing is written to disk. `start` resolves it from
113
+ there each time. If `secrets.require` is declared, add that name to it first, or `store-token`
114
+ exits 2 saying so.
115
+ - **Migration.** If an older setup left a plaintext `<notify.stateDir>/.env`, `store-token`
116
+ moves it: it stores the token, reads it back and compares, and only then deletes the file. It
117
+ needs no prompt. Report it as "moved the bot token from `<path>` into `<provider>` and deleted
118
+ the file" (the `migratedFrom` and `deleted` fields), never with the value.
119
+ - `alreadyStored: true`: the provider already holds it; nothing to do. A matching leftover file
120
+ is deleted too.
121
+ - Exit 2 naming `--vault-project`: the provider project is ambiguous. Ask the operator which
122
+ project, then re-run with `--vault-project <id>`.
123
+ - Exit 2 because the file holds a different token or other keys: say what `message` reports and
124
+ let the operator decide (`--replace` makes the file's token the stored one).
125
+ - Exit 1 (provider unreachable or rate-limited): nothing was stored and the file was kept. Wait a
126
+ minute and run it again.
127
+ - A provider Lisa cannot write to (anything but Bitwarden today): the message asks the operator
128
+ to create `TELEGRAM_BOT_TOKEN_<NAME>` in the provider themselves; then re-run `store-token`,
129
+ which verifies it and deletes any plaintext copy.
130
+ - **No provider configured**: the token is written to `<notify.stateDir>/.env` (mode 0600) as
131
+ before. Tell the operator that this is a plaintext file, that doctor will warn about it, and that
132
+ configuring a secrets provider and re-running `store-token` moves it there.
133
+
134
+ Outcomes either way:
135
+
85
136
  - `stored: true`: done.
86
- - Exit 2 because a token already exists: keep it (re-running setup is safe). Only when the operator
87
- says the stored token is wrong or belongs to another project, re-run with `store-token --replace`.
137
+ - With no provider, exit 2 because a token already exists: keep it (re-running setup is safe). Only
138
+ when the operator says the stored token is wrong or belongs to another project, re-run with
139
+ `store-token --replace`.
88
140
  - `reason: "no-tty"` (an agent's Bash has no terminal): offer the operator both routes, and say
89
141
  plainly that Claude Code's `!` prefix has no terminal either, so it fails the same way:
90
142
  - **Clipboard (simplest):** they copy the token from the BotFather chat and tell you; then run
@@ -96,11 +148,13 @@ The operator creates a bot with @BotFather, one per project. Then run
96
148
  - `empty` / `invalid`: say what was wrong and ask again.
97
149
 
98
150
  Never ask for the token in chat, never echo, log or commit it, and never put it in
99
- `.lisa.config.json`. It lives only in `<notify.stateDir>/.env`.
151
+ `.lisa.config.json`. It lives only in the secrets provider, or in `<notify.stateDir>/.env` when
152
+ no provider is configured. Never read it back from either to check it: `store-token` already
153
+ verified the stored copy.
100
154
 
101
155
  ## Step 4: Telegram plugin scope
102
156
 
103
- Read `claude plugin list --json` and look at the `telegram@claude-plugins-official` entries.
157
+ Only when `notify.provider` is `telegram`. Read `claude plugin list --json` and look at the `telegram@claude-plugins-official` entries.
104
158
 
105
159
  - **Not installed:** ask the operator to install it with
106
160
  `claude plugin install telegram@claude-plugins-official -s user`, then re-check.
@@ -173,11 +227,17 @@ project), on every machine that runs the manager:
173
227
  bypass-permissions worker runs. Ask the operator for the IDs, add them, re-run `validate`, then
174
228
  continue. `lisa doctor` fails on the same condition.
175
229
  1. `node "$SM/session-manager.mjs" start --project-root "$ROOT"`. `started` and `already-running`
176
- are both fine. Exit 2 names what is missing (usually the token from Step 3), or that a tmux
177
- session of the same name belongs to another project root, or that the manager
178
- exited right after starting. For the last, ask the operator to run the printed foreground command
179
- in their own terminal: claude prints its own error there. Fix it, then run `start` again.
180
- 2. Walk the operator through pairing, in their own terminal:
230
+ are both fine. With no channel it needs no token, plugin or pairing and launches without
231
+ `--channels`. Exit 2 names what is missing (with Telegram, usually the token from Step 3, or a
232
+ plaintext `.env` left over beside a secrets provider: run the `store-token` command the message
233
+ names, which migrates it, then `start` again), or that a tmux session of the same name belongs
234
+ to another project root, or that the manager exited right after starting. For the last, ask the
235
+ operator to run the printed foreground command in their own terminal: claude prints its own
236
+ error there (with a provider, the line fetches the token itself; it never holds the value). Fix
237
+ it, then run `start` again. Exit 1 saying "Nothing was started" means the secrets provider could
238
+ not be reached or rate-limited the read: wait a minute and run `start` again.
239
+ 2. Only with Telegram (`notify` is `telegram` in the `start` output); with no channel there is no
240
+ pairing, so skip to Step 10. Walk the operator through pairing, in their own terminal:
181
241
  1. `tmux attach -t <name>` (the `attach` value from the output).
182
242
  2. Send any message to the bot in a private chat. The bot replies with a pairing code.
183
243
  3. In the attached manager session: `/telegram:access pair <code>`.
@@ -191,10 +251,13 @@ Telegram message asked for it. Every allowlisted sender effectively has shell ac
191
251
  ## Step 10: Verify
192
252
 
193
253
  Run `lisa doctor` (or `npx @codyswann/lisa doctor` when the `lisa` CLI is not on the PATH) and
194
- confirm the "Session manager Telegram isolation?" check is green. Fix every warning it names, then
254
+ confirm the "Session manager notifications?" check is green. With no channel its detail is
255
+ `notifications: none`, and it skips every Telegram check. Fix every warning it names, then
195
256
  `node "$SM/session-manager.mjs" status --project-root "$ROOT"` should show the manager running.
196
257
 
197
- Report: the config block written (or kept), where the token lives (the path, never the value), the
198
- plugin scope result, the runbook path, which repo dirs were already trusted and which the operator
258
+ Report: the config block written (or kept), the notification channel (`telegram` or `none`), and
259
+ with Telegram where the token lives (the provider and secret name, or the file path; never the
260
+ value), whether a plaintext `.env` was migrated and deleted, and the plugin scope result, the
261
+ runbook path, which repo dirs were already trusted and which the operator
199
262
  accepted trust in, what the competing-loop check found, the manager's tmux session name, and the
200
263
  doctor result.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.85.0",
3
+ "version": "4.86.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.85.0",
3
+ "version": "4.86.1",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.85.0",
3
+ "version": "4.86.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.85.0",
3
+ "version": "4.86.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.85.0",
3
+ "version": "4.86.1",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"