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