lastlight 0.1.15 → 0.2.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.
- package/README.md +265 -118
- package/agent-context/rules.md +62 -9
- package/agent-context/security.md +69 -0
- package/config/default.yaml +89 -0
- package/deploy/.env.production.example +20 -2
- package/deploy/entrypoint.sh +16 -17
- package/deploy/native/README.md +160 -0
- package/deploy/native/install.sh +110 -0
- package/deploy/native/lastlight.env.example +95 -0
- package/deploy/native/lastlight.service +50 -0
- package/deploy/sandbox-entrypoint.sh +59 -42
- package/dist/admin/auth.d.ts +1 -1
- package/dist/admin/auth.js +3 -1
- package/dist/admin/auth.js.map +1 -1
- package/dist/admin/chat-session-reader.d.ts +11 -14
- package/dist/admin/chat-session-reader.js +27 -51
- package/dist/admin/chat-session-reader.js.map +1 -1
- package/dist/admin/docker.d.ts +37 -0
- package/dist/admin/docker.js +86 -1
- package/dist/admin/docker.js.map +1 -1
- package/dist/admin/index.js +38 -3
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/log-search.test.d.ts +1 -0
- package/dist/admin/log-search.test.js +78 -0
- package/dist/admin/log-search.test.js.map +1 -0
- package/dist/admin/routes.d.ts +52 -3
- package/dist/admin/routes.js +780 -63
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/routes.test.js +680 -14
- package/dist/admin/routes.test.js.map +1 -1
- package/dist/admin/server-logs.test.d.ts +1 -0
- package/dist/admin/server-logs.test.js +58 -0
- package/dist/admin/server-logs.test.js.map +1 -0
- package/dist/admin/sessions.d.ts +26 -39
- package/dist/admin/sessions.js +86 -310
- package/dist/admin/sessions.js.map +1 -1
- package/dist/admin/sessions.test.d.ts +1 -0
- package/dist/admin/sessions.test.js +78 -0
- package/dist/admin/sessions.test.js.map +1 -0
- package/dist/admin/version.d.ts +15 -0
- package/dist/admin/version.js +73 -0
- package/dist/admin/version.js.map +1 -0
- package/dist/admin/version.test.d.ts +1 -0
- package/dist/admin/version.test.js +71 -0
- package/dist/admin/version.test.js.map +1 -0
- package/dist/cli-config.d.ts +55 -0
- package/dist/cli-config.js +119 -0
- package/dist/cli-config.js.map +1 -0
- package/dist/cli-config.test.d.ts +1 -0
- package/dist/cli-config.test.js +92 -0
- package/dist/cli-config.test.js.map +1 -0
- package/dist/cli-format.d.ts +19 -0
- package/dist/cli-format.js +107 -0
- package/dist/cli-format.js.map +1 -0
- package/dist/cli-server.d.ts +73 -0
- package/dist/cli-server.js +347 -0
- package/dist/cli-server.js.map +1 -0
- package/dist/cli-server.test.d.ts +1 -0
- package/dist/cli-server.test.js +38 -0
- package/dist/cli-server.test.js.map +1 -0
- package/dist/cli-timeline.d.ts +35 -0
- package/dist/cli-timeline.js +373 -0
- package/dist/cli-timeline.js.map +1 -0
- package/dist/cli-timeline.test.d.ts +1 -0
- package/dist/cli-timeline.test.js +104 -0
- package/dist/cli-timeline.test.js.map +1 -0
- package/dist/cli.d.ts +0 -19
- package/dist/cli.js +910 -194
- package/dist/cli.js.map +1 -1
- package/dist/config-overlay.test.d.ts +1 -0
- package/dist/config-overlay.test.js +112 -0
- package/dist/config-overlay.test.js.map +1 -0
- package/dist/config-resolve.d.ts +28 -0
- package/dist/config-resolve.js +47 -0
- package/dist/config-resolve.js.map +1 -0
- package/dist/config-resolve.test.d.ts +1 -0
- package/dist/config-resolve.test.js +68 -0
- package/dist/config-resolve.test.js.map +1 -0
- package/dist/config.d.ts +62 -49
- package/dist/config.js +452 -76
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +201 -32
- package/dist/config.test.js.map +1 -1
- package/dist/connectors/github-webhook.js +83 -5
- package/dist/connectors/github-webhook.js.map +1 -1
- package/dist/connectors/github-webhook.test.d.ts +1 -0
- package/dist/connectors/github-webhook.test.js +156 -0
- package/dist/connectors/github-webhook.test.js.map +1 -0
- package/dist/connectors/messaging/session-manager.d.ts +18 -0
- package/dist/connectors/messaging/session-manager.js +83 -2
- package/dist/connectors/messaging/session-manager.js.map +1 -1
- package/dist/connectors/messaging/session-manager.test.d.ts +1 -0
- package/dist/connectors/messaging/session-manager.test.js +144 -0
- package/dist/connectors/messaging/session-manager.test.js.map +1 -0
- package/dist/connectors/slack/connector.d.ts +9 -0
- package/dist/connectors/slack/connector.js +15 -0
- package/dist/connectors/slack/connector.js.map +1 -1
- package/dist/connectors/slack/mrkdwn.js +81 -0
- package/dist/connectors/slack/mrkdwn.js.map +1 -1
- package/dist/connectors/slack/mrkdwn.test.js +49 -0
- package/dist/connectors/slack/mrkdwn.test.js.map +1 -1
- package/dist/connectors/types.d.ts +1 -1
- package/dist/cron/fanout.d.ts +33 -0
- package/dist/cron/fanout.js +55 -0
- package/dist/cron/fanout.js.map +1 -0
- package/dist/cron/fanout.test.d.ts +1 -0
- package/dist/cron/fanout.test.js +73 -0
- package/dist/cron/fanout.test.js.map +1 -0
- package/dist/cron/jobs.d.ts +5 -0
- package/dist/cron/jobs.js +10 -3
- package/dist/cron/jobs.js.map +1 -1
- package/dist/cron/scheduler.d.ts +12 -0
- package/dist/cron/scheduler.js +27 -1
- package/dist/cron/scheduler.js.map +1 -1
- package/dist/engine/agent-executor.d.ts +158 -0
- package/dist/engine/agent-executor.js +1140 -0
- package/dist/engine/agent-executor.js.map +1 -0
- package/dist/engine/agent-executor.test.d.ts +1 -0
- package/dist/engine/agent-executor.test.js +395 -0
- package/dist/engine/agent-executor.test.js.map +1 -0
- package/dist/engine/chat-runner.d.ts +123 -0
- package/dist/engine/chat-runner.js +379 -0
- package/dist/engine/chat-runner.js.map +1 -0
- package/dist/engine/chat-runner.test.d.ts +1 -0
- package/dist/engine/chat-runner.test.js +104 -0
- package/dist/engine/chat-runner.test.js.map +1 -0
- package/dist/engine/chat-skills.d.ts +45 -0
- package/dist/engine/chat-skills.js +184 -0
- package/dist/engine/chat-skills.js.map +1 -0
- package/dist/engine/chat-skills.test.d.ts +1 -0
- package/dist/engine/chat-skills.test.js +20 -0
- package/dist/engine/chat-skills.test.js.map +1 -0
- package/dist/engine/chat.d.ts +20 -23
- package/dist/engine/chat.js +251 -155
- package/dist/engine/chat.js.map +1 -1
- package/dist/engine/chat.test.d.ts +1 -0
- package/dist/engine/chat.test.js +42 -0
- package/dist/engine/chat.test.js.map +1 -0
- package/dist/engine/classifier.d.ts +35 -2
- package/dist/engine/classifier.js +170 -31
- package/dist/engine/classifier.js.map +1 -1
- package/dist/engine/classifier.test.d.ts +1 -0
- package/dist/engine/classifier.test.js +115 -0
- package/dist/engine/classifier.test.js.map +1 -0
- package/dist/engine/dispatcher.d.ts +60 -0
- package/dist/engine/dispatcher.js +601 -0
- package/dist/engine/dispatcher.js.map +1 -0
- package/dist/engine/dispatcher.test.d.ts +1 -0
- package/dist/engine/dispatcher.test.js +511 -0
- package/dist/engine/dispatcher.test.js.map +1 -0
- package/dist/engine/event-shim.d.ts +117 -0
- package/dist/engine/event-shim.js +435 -0
- package/dist/engine/event-shim.js.map +1 -0
- package/dist/engine/event-shim.test.d.ts +1 -0
- package/dist/engine/event-shim.test.js +194 -0
- package/dist/engine/event-shim.test.js.map +1 -0
- package/dist/engine/git-auth.d.ts +13 -17
- package/dist/engine/git-auth.js +99 -42
- package/dist/engine/git-auth.js.map +1 -1
- package/dist/engine/git-auth.test.d.ts +1 -0
- package/dist/engine/git-auth.test.js +117 -0
- package/dist/engine/git-auth.test.js.map +1 -0
- package/dist/engine/github-app-client.d.ts +7 -0
- package/dist/engine/github-app-client.js +16 -0
- package/dist/engine/github-app-client.js.map +1 -0
- package/dist/engine/github-app-client.test.d.ts +1 -0
- package/dist/engine/github-app-client.test.js +44 -0
- package/dist/engine/github-app-client.test.js.map +1 -0
- package/dist/engine/github-tools.d.ts +12 -0
- package/dist/engine/github-tools.js +261 -0
- package/dist/engine/github-tools.js.map +1 -0
- package/dist/engine/github.d.ts +1027 -43
- package/dist/engine/github.js +153 -14
- package/dist/engine/github.js.map +1 -1
- package/dist/engine/llm.d.ts +47 -0
- package/dist/engine/llm.js +221 -0
- package/dist/engine/llm.js.map +1 -0
- package/dist/engine/llm.test.d.ts +1 -0
- package/dist/engine/llm.test.js +189 -0
- package/dist/engine/llm.test.js.map +1 -0
- package/dist/engine/profiles.d.ts +249 -0
- package/dist/engine/profiles.js +42 -0
- package/dist/engine/profiles.js.map +1 -0
- package/dist/engine/router.d.ts +12 -6
- package/dist/engine/router.js +339 -81
- package/dist/engine/router.js.map +1 -1
- package/dist/engine/router.test.js +428 -78
- package/dist/engine/router.test.js.map +1 -1
- package/dist/engine/screen.d.ts +41 -0
- package/dist/engine/screen.js +93 -0
- package/dist/engine/screen.js.map +1 -0
- package/dist/engine/screen.test.d.ts +1 -0
- package/dist/engine/screen.test.js +82 -0
- package/dist/engine/screen.test.js.map +1 -0
- package/dist/index.js +377 -432
- package/dist/index.js.map +1 -1
- package/dist/managed-repos.d.ts +7 -9
- package/dist/managed-repos.js +12 -15
- package/dist/managed-repos.js.map +1 -1
- package/dist/managed-repos.test.js +24 -19
- package/dist/managed-repos.test.js.map +1 -1
- package/dist/notify/index.d.ts +15 -0
- package/dist/notify/index.js +6 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/model.d.ts +57 -0
- package/dist/notify/model.js +89 -0
- package/dist/notify/model.js.map +1 -0
- package/dist/notify/model.test.d.ts +1 -0
- package/dist/notify/model.test.js +109 -0
- package/dist/notify/model.test.js.map +1 -0
- package/dist/notify/notifier.d.ts +17 -0
- package/dist/notify/notifier.js +87 -0
- package/dist/notify/notifier.js.map +1 -0
- package/dist/notify/notifier.test.d.ts +1 -0
- package/dist/notify/notifier.test.js +100 -0
- package/dist/notify/notifier.test.js.map +1 -0
- package/dist/notify/render.d.ts +21 -0
- package/dist/notify/render.js +59 -0
- package/dist/notify/render.js.map +1 -0
- package/dist/notify/render.test.d.ts +1 -0
- package/dist/notify/render.test.js +65 -0
- package/dist/notify/render.test.js.map +1 -0
- package/dist/notify/transports/github.d.ts +26 -0
- package/dist/notify/transports/github.js +26 -0
- package/dist/notify/transports/github.js.map +1 -0
- package/dist/notify/transports/slack.d.ts +26 -0
- package/dist/notify/transports/slack.js +28 -0
- package/dist/notify/transports/slack.js.map +1 -0
- package/dist/notify/transports.test.d.ts +1 -0
- package/dist/notify/transports.test.js +71 -0
- package/dist/notify/transports.test.js.map +1 -0
- package/dist/notify/types.d.ts +95 -0
- package/dist/notify/types.js +16 -0
- package/dist/notify/types.js.map +1 -0
- package/dist/sandbox/docker-compose.test.d.ts +1 -0
- package/dist/sandbox/docker-compose.test.js +128 -0
- package/dist/sandbox/docker-compose.test.js.map +1 -0
- package/dist/sandbox/docker.d.ts +97 -9
- package/dist/sandbox/docker.js +192 -41
- package/dist/sandbox/docker.js.map +1 -1
- package/dist/sandbox/docker.test.d.ts +1 -0
- package/dist/sandbox/docker.test.js +137 -0
- package/dist/sandbox/docker.test.js.map +1 -0
- package/dist/sandbox/egress-allowlist.d.ts +69 -0
- package/dist/sandbox/egress-allowlist.js +164 -0
- package/dist/sandbox/egress-allowlist.js.map +1 -0
- package/dist/sandbox/egress-allowlist.test.d.ts +1 -0
- package/dist/sandbox/egress-allowlist.test.js +65 -0
- package/dist/sandbox/egress-allowlist.test.js.map +1 -0
- package/dist/sandbox/egress-firewall-config.d.ts +127 -0
- package/dist/sandbox/egress-firewall-config.js +434 -0
- package/dist/sandbox/egress-firewall-config.js.map +1 -0
- package/dist/sandbox/egress-firewall-config.test.d.ts +1 -0
- package/dist/sandbox/egress-firewall-config.test.js +244 -0
- package/dist/sandbox/egress-firewall-config.test.js.map +1 -0
- package/dist/sandbox/images.d.ts +23 -0
- package/dist/sandbox/images.js +55 -0
- package/dist/sandbox/images.js.map +1 -0
- package/dist/sandbox/index.d.ts +82 -3
- package/dist/sandbox/index.js +223 -93
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/index.test.d.ts +1 -0
- package/dist/sandbox/index.test.js +157 -0
- package/dist/sandbox/index.test.js.map +1 -0
- package/dist/session-log.d.ts +63 -0
- package/dist/session-log.js +290 -0
- package/dist/session-log.js.map +1 -0
- package/dist/session-log.test.d.ts +1 -0
- package/dist/session-log.test.js +85 -0
- package/dist/session-log.test.js.map +1 -0
- package/dist/setup.d.ts +30 -1
- package/dist/setup.js +241 -25
- package/dist/setup.js.map +1 -1
- package/dist/setup.test.js +138 -6
- package/dist/setup.test.js.map +1 -1
- package/dist/state/approval-store.d.ts +86 -0
- package/dist/state/approval-store.js +140 -0
- package/dist/state/approval-store.js.map +1 -0
- package/dist/state/build-assets.d.ts +50 -0
- package/dist/state/build-assets.js +154 -0
- package/dist/state/build-assets.js.map +1 -0
- package/dist/state/build-assets.test.d.ts +1 -0
- package/dist/state/build-assets.test.js +106 -0
- package/dist/state/build-assets.test.js.map +1 -0
- package/dist/state/db.d.ts +65 -333
- package/dist/state/db.js +112 -835
- package/dist/state/db.js.map +1 -1
- package/dist/state/db.test.js +127 -91
- package/dist/state/db.test.js.map +1 -1
- package/dist/state/execution-store.d.ts +257 -0
- package/dist/state/execution-store.js +527 -0
- package/dist/state/execution-store.js.map +1 -0
- package/dist/state/migrate.d.ts +15 -0
- package/dist/state/migrate.js +175 -0
- package/dist/state/migrate.js.map +1 -0
- package/dist/state/workflow-run-store.d.ts +195 -0
- package/dist/state/workflow-run-store.js +363 -0
- package/dist/state/workflow-run-store.js.map +1 -0
- package/dist/state/workflow-run-store.test.d.ts +1 -0
- package/dist/state/workflow-run-store.test.js +264 -0
- package/dist/state/workflow-run-store.test.js.map +1 -0
- package/dist/telemetry/index.d.ts +38 -0
- package/dist/telemetry/index.js +253 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/index.test.d.ts +1 -0
- package/dist/telemetry/index.test.js +73 -0
- package/dist/telemetry/index.test.js.map +1 -0
- package/dist/telemetry/pi-events.d.ts +12 -0
- package/dist/telemetry/pi-events.js +134 -0
- package/dist/telemetry/pi-events.js.map +1 -0
- package/dist/telemetry/pi-events.test.d.ts +1 -0
- package/dist/telemetry/pi-events.test.js +69 -0
- package/dist/telemetry/pi-events.test.js.map +1 -0
- package/dist/workflows/dag.d.ts +13 -1
- package/dist/workflows/dag.js +7 -3
- package/dist/workflows/dag.js.map +1 -1
- package/dist/workflows/dag.test.js +22 -0
- package/dist/workflows/dag.test.js.map +1 -1
- package/dist/workflows/golden-build.test.d.ts +1 -0
- package/dist/workflows/golden-build.test.js +45 -0
- package/dist/workflows/golden-build.test.js.map +1 -0
- package/dist/workflows/loader-overlay.test.d.ts +1 -0
- package/dist/workflows/loader-overlay.test.js +101 -0
- package/dist/workflows/loader-overlay.test.js.map +1 -0
- package/dist/workflows/loader.d.ts +36 -11
- package/dist/workflows/loader.js +311 -87
- package/dist/workflows/loader.js.map +1 -1
- package/dist/workflows/loader.test.js +114 -10
- package/dist/workflows/loader.test.js.map +1 -1
- package/dist/workflows/loop-eval.js +2 -0
- package/dist/workflows/loop-eval.js.map +1 -1
- package/dist/workflows/loop-eval.test.js +14 -0
- package/dist/workflows/loop-eval.test.js.map +1 -1
- package/dist/workflows/phase-executor.d.ts +145 -0
- package/dist/workflows/phase-executor.js +691 -0
- package/dist/workflows/phase-executor.js.map +1 -0
- package/dist/workflows/phase-executor.test.d.ts +1 -0
- package/dist/workflows/phase-executor.test.js +434 -0
- package/dist/workflows/phase-executor.test.js.map +1 -0
- package/dist/workflows/phase-ref.d.ts +44 -0
- package/dist/workflows/phase-ref.js +78 -0
- package/dist/workflows/phase-ref.js.map +1 -0
- package/dist/workflows/phase-ref.test.d.ts +1 -0
- package/dist/workflows/phase-ref.test.js +24 -0
- package/dist/workflows/phase-ref.test.js.map +1 -0
- package/dist/workflows/resume.d.ts +5 -11
- package/dist/workflows/resume.js +88 -7
- package/dist/workflows/resume.js.map +1 -1
- package/dist/workflows/runner.d.ts +34 -27
- package/dist/workflows/runner.js +252 -930
- package/dist/workflows/runner.js.map +1 -1
- package/dist/workflows/runner.test.js +346 -35
- package/dist/workflows/runner.test.js.map +1 -1
- package/dist/workflows/schema.d.ts +52 -10
- package/dist/workflows/schema.js +147 -7
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/simple.d.ts +67 -3
- package/dist/workflows/simple.js +248 -87
- package/dist/workflows/simple.js.map +1 -1
- package/dist/workflows/simple.test.d.ts +1 -0
- package/dist/workflows/simple.test.js +107 -0
- package/dist/workflows/simple.test.js.map +1 -0
- package/dist/workflows/templates.d.ts +29 -0
- package/dist/workflows/templates.js +42 -4
- package/dist/workflows/templates.js.map +1 -1
- package/dist/workflows/templates.test.js +103 -0
- package/dist/workflows/templates.test.js.map +1 -1
- package/dist/workflows/triggers.d.ts +21 -0
- package/dist/workflows/triggers.js +44 -0
- package/dist/workflows/triggers.js.map +1 -0
- package/dist/workflows/verdict.d.ts +19 -0
- package/dist/workflows/verdict.js +30 -0
- package/dist/workflows/verdict.js.map +1 -0
- package/dist/workflows/verdict.test.d.ts +1 -0
- package/dist/workflows/verdict.test.js +44 -0
- package/dist/workflows/verdict.test.js.map +1 -0
- package/dist/worktree/manager.d.ts +1 -1
- package/dist/worktree/manager.js +14 -14
- package/dist/worktree/manager.js.map +1 -1
- package/dist/worktree/manager.test.d.ts +1 -0
- package/dist/worktree/manager.test.js +87 -0
- package/dist/worktree/manager.test.js.map +1 -0
- package/docker-compose.yml +206 -5
- package/package.json +19 -9
- package/sandbox.Dockerfile +97 -18
- package/skills/README.md +40 -0
- package/skills/browser-qa/SKILL.md +193 -0
- package/skills/browser-qa/scripts/agent-browser.mjs +380 -0
- package/skills/building/SKILL.md +95 -0
- package/skills/chat/SKILL.md +30 -11
- package/skills/code-review/SKILL.md +59 -0
- package/skills/debug-production/SKILL.md +108 -0
- package/skills/demo/SKILL.md +194 -0
- package/skills/demo/scripts/compose-demo.sh +205 -0
- package/skills/issue-answer/SKILL.md +90 -0
- package/skills/issue-comment/SKILL.md +38 -24
- package/skills/issue-triage/SKILL.md +103 -37
- package/skills/issue-triage/references/AGENT-BRIEF.md +61 -0
- package/skills/pr-comment/SKILL.md +64 -0
- package/skills/pr-review/SKILL.md +65 -49
- package/skills/qa-test/SKILL.md +97 -0
- package/skills/repo-health/SKILL.md +48 -45
- package/skills/security-feedback/SKILL.md +173 -0
- package/skills/security-feedback/references/templates.md +77 -0
- package/skills/security-review/SKILL.md +213 -0
- package/skills/security-review/references/issue-format.md +302 -0
- package/skills/verify/SKILL.md +118 -0
- package/workflows/answer.yaml +37 -0
- package/workflows/build.yaml +32 -22
- package/workflows/cron-security.yaml +6 -0
- package/workflows/demo.yaml +55 -0
- package/workflows/explore.yaml +9 -0
- package/workflows/pr-comment.yaml +16 -0
- package/workflows/pr-fix.yaml +3 -0
- package/workflows/pr-review.yaml +4 -1
- package/workflows/prompts/answer.md +67 -0
- package/workflows/prompts/architect.md +24 -7
- package/workflows/prompts/demo.md +100 -0
- package/workflows/prompts/executor.md +29 -20
- package/workflows/prompts/explore-ask.md +51 -22
- package/workflows/prompts/explore-publish.md +2 -2
- package/workflows/prompts/explore-read.md +24 -10
- package/workflows/prompts/explore-synthesize.md +15 -8
- package/workflows/prompts/fix.md +9 -10
- package/workflows/prompts/guardrails.md +26 -8
- package/workflows/prompts/pr-fix.md +6 -7
- package/workflows/prompts/pr.md +11 -10
- package/workflows/prompts/qa-browser.md +95 -0
- package/workflows/prompts/qa-synth.md +44 -0
- package/workflows/prompts/qa-test.md +60 -0
- package/workflows/prompts/re-reviewer.md +8 -9
- package/workflows/prompts/reviewer.md +10 -9
- package/workflows/prompts/verify-browser.md +93 -0
- package/workflows/prompts/verify-synth.md +44 -0
- package/workflows/prompts/verify.md +63 -0
- package/workflows/qa-test.yaml +87 -0
- package/workflows/security-feedback.yaml +25 -0
- package/workflows/security-review.yaml +29 -0
- package/workflows/verify.yaml +85 -0
- package/deploy/mcp-config.tmpl.json +0 -14
- package/dist/cron/rate-limits.d.ts +0 -26
- package/dist/cron/rate-limits.js +0 -193
- package/dist/cron/rate-limits.js.map +0 -1
- package/dist/engine/executor.d.ts +0 -75
- package/dist/engine/executor.js +0 -292
- package/dist/engine/executor.js.map +0 -1
- package/mcp-github-app/package.json +0 -18
- package/mcp-github-app/src/auth.js +0 -66
- package/mcp-github-app/src/github.js +0 -371
- package/mcp-github-app/src/index.js +0 -534
- package/skills/devops/webhook-subscriptions/SKILL.md +0 -180
- package/skills/github/DESCRIPTION.md +0 -3
- package/skills/github/codebase-inspection/SKILL.md +0 -115
- package/skills/github/github-auth/SKILL.md +0 -54
- package/skills/github/github-auth/scripts/gh-env.sh +0 -66
- package/skills/github/github-code-review/SKILL.md +0 -480
- package/skills/github/github-code-review/references/review-output-template.md +0 -74
- package/skills/github/github-issues/SKILL.md +0 -369
- package/skills/github/github-issues/templates/bug-report.md +0 -35
- package/skills/github/github-issues/templates/feature-request.md +0 -31
- package/skills/github/github-pr-workflow/SKILL.md +0 -395
- package/skills/github/github-pr-workflow/references/ci-troubleshooting.md +0 -183
- package/skills/github/github-pr-workflow/references/conventional-commits.md +0 -71
- package/skills/github/github-pr-workflow/templates/pr-body-bugfix.md +0 -35
- package/skills/github/github-pr-workflow/templates/pr-body-feature.md +0 -33
- package/skills/github/github-repo-management/SKILL.md +0 -515
- package/skills/github/github-repo-management/references/github-api-cheatsheet.md +0 -161
- package/skills/github-orchestrator/SKILL.md +0 -103
- package/skills/mcp/DESCRIPTION.md +0 -3
- package/skills/mcp/mcporter/SKILL.md +0 -122
- package/skills/mcp/native-mcp/SKILL.md +0 -356
- package/skills/software-development/architect/SKILL.md +0 -154
- package/skills/software-development/assure-guardrails/SKILL.md +0 -239
- package/skills/software-development/plan/SKILL.md +0 -64
- package/skills/software-development/requesting-code-review/SKILL.md +0 -291
- package/skills/software-development/subagent-driven-development/SKILL.md +0 -433
- package/skills/software-development/systematic-debugging/SKILL.md +0 -366
- package/skills/software-development/test-driven-development/SKILL.md +0 -342
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { COREDNS_OPEN_IP, COREDNS_STRICT_IP, NGINX_OPEN_IP, NGINX_STRICT_IP, OTEL_COLLECTOR_IP, OTEL_COLLECTOR_OTLP_GRPC_PORT, OTEL_COLLECTOR_OTLP_HTTP_PORT, OTEL_COLLECTOR_SANDBOX_ENDPOINT, renderCorefileOpen, renderCorefileStrict, renderNginxOpenConf, renderNginxStrictConf, renderOtelCollectorConfig, SANDBOX_EGRESS_SUBNET, } from "./egress-firewall-config.js";
|
|
3
|
+
import { DEFAULT_ALLOWLIST } from "./egress-allowlist.js";
|
|
4
|
+
import { parse as parseYaml } from "yaml";
|
|
5
|
+
describe("static IP constants", () => {
|
|
6
|
+
it("all four service IPs sit inside the sandbox-egress subnet", () => {
|
|
7
|
+
const prefix = SANDBOX_EGRESS_SUBNET.split("/")[0].split(".").slice(0, 3).join(".");
|
|
8
|
+
for (const ip of [COREDNS_STRICT_IP, COREDNS_OPEN_IP, NGINX_STRICT_IP, NGINX_OPEN_IP]) {
|
|
9
|
+
expect(ip.startsWith(prefix + ".")).toBe(true);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
it("strict and open IPs are distinct in both pairs", () => {
|
|
13
|
+
expect(COREDNS_STRICT_IP).not.toBe(COREDNS_OPEN_IP);
|
|
14
|
+
expect(NGINX_STRICT_IP).not.toBe(NGINX_OPEN_IP);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
describe("nginx strict config", () => {
|
|
18
|
+
const conf = renderNginxStrictConf();
|
|
19
|
+
it("listens on 443 with ssl_preread enabled", () => {
|
|
20
|
+
expect(conf).toMatch(/listen\s+443;/);
|
|
21
|
+
expect(conf).toMatch(/ssl_preread\s+on;/);
|
|
22
|
+
});
|
|
23
|
+
it("defaults unknown SNIs to a black-hole upstream (instant reset)", () => {
|
|
24
|
+
expect(conf).toMatch(/default\s+127\.0\.0\.1:1;/);
|
|
25
|
+
});
|
|
26
|
+
it("emits a leading-dot map entry per allowlist host (apex+subdomain match)", () => {
|
|
27
|
+
for (const host of DEFAULT_ALLOWLIST) {
|
|
28
|
+
// nginx's `.foo.com` syntax matches `foo.com` and any subdomain.
|
|
29
|
+
// Upstream is the live SNI value, not pinned at config time.
|
|
30
|
+
expect(conf).toContain(`.${host} $ssl_preread_server_name:443;`);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
it("uses docker's embedded DNS as the upstream resolver", () => {
|
|
34
|
+
expect(conf).toMatch(/resolver\s+127\.0\.0\.11/);
|
|
35
|
+
});
|
|
36
|
+
it("declares `hostnames` in the map block so leading-dot wildcards work", () => {
|
|
37
|
+
// Without `hostnames;`, nginx's `map` does exact string match only —
|
|
38
|
+
// `.github.com` becomes a literal key that never matches anything.
|
|
39
|
+
// We hit this in prod: every allowlisted host fell through to the
|
|
40
|
+
// black-hole default. Pin the contract so it can't regress.
|
|
41
|
+
expect(conf).toMatch(/map\s+\$ssl_preread_server_name\s+\$upstream_target\s*\{\s*\n\s*hostnames;/);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe("nginx open config", () => {
|
|
45
|
+
const conf = renderNginxOpenConf();
|
|
46
|
+
it("tunnels whatever SNI was sent — no allowlist map", () => {
|
|
47
|
+
expect(conf).toMatch(/proxy_pass\s+\$ssl_preread_server_name:443;/);
|
|
48
|
+
expect(conf).not.toMatch(/map\s+\$ssl_preread_server_name/);
|
|
49
|
+
});
|
|
50
|
+
it("still listens on 443 with ssl_preread enabled", () => {
|
|
51
|
+
expect(conf).toMatch(/listen\s+443;/);
|
|
52
|
+
expect(conf).toMatch(/ssl_preread\s+on;/);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe("coredns strict Corefile", () => {
|
|
56
|
+
const conf = renderCorefileStrict();
|
|
57
|
+
it("uses a SINGLE template block with one match line per allowlist host", () => {
|
|
58
|
+
// CoreDNS only honours one `template` block per (class, type, zone) —
|
|
59
|
+
// multiple blocks silently shadow each other. Catching a regression
|
|
60
|
+
// matters because we hit this exact bug in prod.
|
|
61
|
+
const templateBlocks = conf.match(/template\s+IN\s+A\s*\{/g) || [];
|
|
62
|
+
expect(templateBlocks.length).toBe(1);
|
|
63
|
+
for (const host of DEFAULT_ALLOWLIST) {
|
|
64
|
+
const escaped = host.replaceAll(".", "\\.");
|
|
65
|
+
expect(conf).toContain(`(^|\\.)${escaped}\\.$`);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
it("answers with the nginx-strict IP", () => {
|
|
69
|
+
expect(conf).toContain(`IN A ${NGINX_STRICT_IP}`);
|
|
70
|
+
});
|
|
71
|
+
it("catches every unmatched query with an NXDOMAIN template", () => {
|
|
72
|
+
expect(conf).toMatch(/template\s+IN\s+ANY\s*\{[\s\S]*rcode\s+NXDOMAIN[\s\S]*\}/);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe("coredns open Corefile", () => {
|
|
76
|
+
const conf = renderCorefileOpen();
|
|
77
|
+
it("returns the nginx-open IP for arbitrary A queries", () => {
|
|
78
|
+
expect(conf).toContain(`IN A ${NGINX_OPEN_IP}`);
|
|
79
|
+
});
|
|
80
|
+
it("hard-denies cloud metadata literals even in unrestricted mode", () => {
|
|
81
|
+
// Each hard-deny host gets its own zone block so CoreDNS's
|
|
82
|
+
// longest-suffix routing intercepts the apex + subdomains before
|
|
83
|
+
// the catch-all `.` zone sees them.
|
|
84
|
+
expect(conf).toMatch(/metadata\.google\.internal:53\s*\{[\s\S]*?rcode\s+NXDOMAIN/);
|
|
85
|
+
expect(conf).toMatch(/169\.254\.169\.254:53\s*\{[\s\S]*?rcode\s+NXDOMAIN/);
|
|
86
|
+
});
|
|
87
|
+
it("returns NOERROR / empty for AAAA so IPv6 doesn't accidentally bypass us", () => {
|
|
88
|
+
expect(conf).toMatch(/template\s+IN\s+AAAA\s*\{[\s\S]*rcode\s+NOERROR[\s\S]*\}/);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("otel collector config", () => {
|
|
92
|
+
// Most tests run with forwarding active; the gating tests below cover inactive.
|
|
93
|
+
const renderActive = (env) => parseYaml(renderOtelCollectorConfig({ active: true, env }));
|
|
94
|
+
it("sandbox endpoint points at the collector's static IP + OTLP/HTTP port", () => {
|
|
95
|
+
expect(OTEL_COLLECTOR_SANDBOX_ENDPOINT).toBe(`http://${OTEL_COLLECTOR_IP}:${OTEL_COLLECTOR_OTLP_HTTP_PORT}`);
|
|
96
|
+
});
|
|
97
|
+
it("receives OTLP on both http and grpc, on all interfaces", () => {
|
|
98
|
+
const cfg = renderActive({});
|
|
99
|
+
expect(cfg.receivers.otlp.protocols.http.endpoint).toBe(`0.0.0.0:${OTEL_COLLECTOR_OTLP_HTTP_PORT}`);
|
|
100
|
+
expect(cfg.receivers.otlp.protocols.grpc.endpoint).toBe(`0.0.0.0:${OTEL_COLLECTOR_OTLP_GRPC_PORT}`);
|
|
101
|
+
});
|
|
102
|
+
it("re-exports to the generic endpoint (as a base URL) with parsed auth headers on every signal", () => {
|
|
103
|
+
const cfg = renderActive({
|
|
104
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: "https://collector.example.com:4318",
|
|
105
|
+
OTEL_EXPORTER_OTLP_HEADERS: "api-key=secret-123,x-tenant=acme",
|
|
106
|
+
});
|
|
107
|
+
for (const signal of ["traces", "metrics", "logs"]) {
|
|
108
|
+
const exp = cfg.exporters[`otlphttp/${signal}`];
|
|
109
|
+
// Generic endpoint → `endpoint` field (collector appends /v1/<signal>).
|
|
110
|
+
expect(exp.endpoint).toBe("https://collector.example.com:4318");
|
|
111
|
+
expect(exp[`${signal}_endpoint`]).toBeUndefined();
|
|
112
|
+
expect(exp.headers).toEqual({ "api-key": "secret-123", "x-tenant": "acme" });
|
|
113
|
+
expect(cfg.service.pipelines[signal].exporters).toEqual([`otlphttp/${signal}`]);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
it("routes per-signal endpoints to their own pipeline (no fallback-chain misrouting)", () => {
|
|
117
|
+
// The bug the reviewer flagged: separate traces/metrics endpoints must not
|
|
118
|
+
// both export to whichever one won a `||` chain.
|
|
119
|
+
const cfg = renderActive({
|
|
120
|
+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "https://traces.example.com/v1/traces",
|
|
121
|
+
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: "https://metrics.example.com/v1/metrics",
|
|
122
|
+
});
|
|
123
|
+
// Signal-specific endpoints are used verbatim via `<signal>_endpoint`.
|
|
124
|
+
expect(cfg.exporters["otlphttp/traces"].traces_endpoint).toBe("https://traces.example.com/v1/traces");
|
|
125
|
+
expect(cfg.exporters["otlphttp/metrics"].metrics_endpoint).toBe("https://metrics.example.com/v1/metrics");
|
|
126
|
+
expect(cfg.service.pipelines.traces.exporters).toEqual(["otlphttp/traces"]);
|
|
127
|
+
expect(cfg.service.pipelines.metrics.exporters).toEqual(["otlphttp/metrics"]);
|
|
128
|
+
// logs had no endpoint configured → debug, not silently misrouted.
|
|
129
|
+
expect(cfg.service.pipelines.logs.exporters).toEqual(["debug"]);
|
|
130
|
+
expect(cfg.exporters.debug).toBeDefined();
|
|
131
|
+
});
|
|
132
|
+
it("honours a logs-only endpoint instead of dropping it (the silent-drop case)", () => {
|
|
133
|
+
const cfg = renderActive({
|
|
134
|
+
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: "https://logs.example.com/v1/logs",
|
|
135
|
+
});
|
|
136
|
+
expect(cfg.exporters["otlphttp/logs"].logs_endpoint).toBe("https://logs.example.com/v1/logs");
|
|
137
|
+
expect(cfg.service.pipelines.logs.exporters).toEqual(["otlphttp/logs"]);
|
|
138
|
+
expect(cfg.service.pipelines.traces.exporters).toEqual(["debug"]);
|
|
139
|
+
expect(cfg.service.pipelines.metrics.exporters).toEqual(["debug"]);
|
|
140
|
+
});
|
|
141
|
+
it("lets a signal-specific endpoint override the generic one for just that signal", () => {
|
|
142
|
+
const cfg = renderActive({
|
|
143
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: "https://generic.example.com",
|
|
144
|
+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "https://traces.example.com/v1/traces",
|
|
145
|
+
});
|
|
146
|
+
// traces → verbatim specific URL; metrics/logs → generic base.
|
|
147
|
+
expect(cfg.exporters["otlphttp/traces"].traces_endpoint).toBe("https://traces.example.com/v1/traces");
|
|
148
|
+
expect(cfg.exporters["otlphttp/metrics"].endpoint).toBe("https://generic.example.com");
|
|
149
|
+
expect(cfg.exporters["otlphttp/logs"].endpoint).toBe("https://generic.example.com");
|
|
150
|
+
});
|
|
151
|
+
it("applies per-signal header overrides, falling back to generic headers", () => {
|
|
152
|
+
const cfg = renderActive({
|
|
153
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: "https://generic.example.com",
|
|
154
|
+
OTEL_EXPORTER_OTLP_HEADERS: "authorization=generic",
|
|
155
|
+
OTEL_EXPORTER_OTLP_TRACES_HEADERS: "authorization=traces-only",
|
|
156
|
+
});
|
|
157
|
+
expect(cfg.exporters["otlphttp/traces"].headers.authorization).toBe("traces-only");
|
|
158
|
+
expect(cfg.exporters["otlphttp/metrics"].headers.authorization).toBe("generic");
|
|
159
|
+
});
|
|
160
|
+
it("supports a non-443 / custom-port HTTPS backend the strict SNI firewall could not reach", () => {
|
|
161
|
+
// This is the case the reviewer flagged for the old direct-forward path.
|
|
162
|
+
// It now works because the collector dials the backend on its trusted
|
|
163
|
+
// outbound leg, not through ssl_preread.
|
|
164
|
+
const cfg = renderActive({ OTEL_EXPORTER_OTLP_ENDPOINT: "https://otel.internal:4318" });
|
|
165
|
+
expect(cfg.exporters["otlphttp/traces"].endpoint).toBe("https://otel.internal:4318");
|
|
166
|
+
});
|
|
167
|
+
it("preserves '=' inside header values (bearer tokens survive intact)", () => {
|
|
168
|
+
const cfg = renderActive({
|
|
169
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: "https://b.example.com",
|
|
170
|
+
OTEL_EXPORTER_OTLP_HEADERS: "authorization=Bearer abc=def==",
|
|
171
|
+
});
|
|
172
|
+
expect(cfg.exporters["otlphttp/traces"].headers.authorization).toBe("Bearer abc=def==");
|
|
173
|
+
});
|
|
174
|
+
it("falls back to a debug exporter (no data leaves) when active but no backend is configured", () => {
|
|
175
|
+
const cfg = renderActive({});
|
|
176
|
+
expect(cfg.exporters.debug).toBeDefined();
|
|
177
|
+
expect(cfg.exporters["otlphttp/traces"]).toBeUndefined();
|
|
178
|
+
for (const signal of ["traces", "metrics", "logs"]) {
|
|
179
|
+
expect(cfg.service.pipelines[signal].exporters).toEqual(["debug"]);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
it("produces valid YAML even with quote/backslash-bearing header values", () => {
|
|
183
|
+
// Crucially, a single quote in a header value no longer fails anything:
|
|
184
|
+
// it lives in the host-side collector config, never a sandbox shell wrap.
|
|
185
|
+
const cfg = renderActive({
|
|
186
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: "https://b.example.com",
|
|
187
|
+
OTEL_EXPORTER_OTLP_HEADERS: `x-quote=it's "quoted" \\ backslash`,
|
|
188
|
+
});
|
|
189
|
+
expect(cfg.exporters["otlphttp/traces"].headers["x-quote"]).toBe(`it's "quoted" \\ backslash`);
|
|
190
|
+
});
|
|
191
|
+
it("drops CR/LF-bearing header pairs (no header injection, no broken YAML) but keeps the rest", () => {
|
|
192
|
+
// A newline in a header value would be header injection on the
|
|
193
|
+
// collector→backend leg and would also break the YAML scalar.
|
|
194
|
+
const raw = renderOtelCollectorConfig({
|
|
195
|
+
active: true,
|
|
196
|
+
env: {
|
|
197
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: "https://b.example.com",
|
|
198
|
+
OTEL_EXPORTER_OTLP_HEADERS: "x-good=ok,x-bad=line1\nline2",
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
expect(() => parseYaml(raw)).not.toThrow();
|
|
202
|
+
const cfg = parseYaml(raw);
|
|
203
|
+
expect(cfg.exporters["otlphttp/traces"].headers).toEqual({ "x-good": "ok" });
|
|
204
|
+
});
|
|
205
|
+
describe("forwarding gate (security floor)", () => {
|
|
206
|
+
it("when inactive, drops every signal to debug and emits no backend endpoint or credential", () => {
|
|
207
|
+
const raw = renderOtelCollectorConfig({
|
|
208
|
+
active: false,
|
|
209
|
+
env: {
|
|
210
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: "https://real-backend.example.com",
|
|
211
|
+
OTEL_EXPORTER_OTLP_HEADERS: "authorization=super-secret-token",
|
|
212
|
+
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: "https://traces.example.com",
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
// No backend URL or secret leaks into the generated file at all.
|
|
216
|
+
expect(raw).not.toContain("real-backend.example.com");
|
|
217
|
+
expect(raw).not.toContain("super-secret-token");
|
|
218
|
+
expect(raw).not.toContain("traces.example.com");
|
|
219
|
+
expect(raw).not.toContain("otlphttp");
|
|
220
|
+
const cfg = parseYaml(raw);
|
|
221
|
+
expect(cfg.exporters.debug).toBeDefined();
|
|
222
|
+
for (const signal of ["traces", "metrics", "logs"]) {
|
|
223
|
+
expect(cfg.service.pipelines[signal].exporters).toEqual(["debug"]);
|
|
224
|
+
}
|
|
225
|
+
// Receiver still listens so sandboxes don't get connection errors.
|
|
226
|
+
expect(cfg.receivers.otlp.protocols.http.endpoint).toBe(`0.0.0.0:${OTEL_COLLECTOR_OTLP_HTTP_PORT}`);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
describe("apex + subdomain match sanity", () => {
|
|
231
|
+
// Pin behaviour: a bare entry like "github.com" must match both
|
|
232
|
+
// the apex and any subdomain in both backends.
|
|
233
|
+
it("'github.com' generates an nginx leading-dot map entry", () => {
|
|
234
|
+
const conf = renderNginxStrictConf();
|
|
235
|
+
expect(conf).toMatch(/\s\.github\.com\s+\$ssl_preread_server_name:443;/);
|
|
236
|
+
});
|
|
237
|
+
it("'github.com' generates a CoreDNS pattern matching apex + subdomains", () => {
|
|
238
|
+
const conf = renderCorefileStrict();
|
|
239
|
+
// (^|\.)github\.com\.$ matches both "github.com." and "api.github.com."
|
|
240
|
+
// in FQDN-with-trailing-dot form.
|
|
241
|
+
expect(conf).toContain("(^|\\.)github\\.com\\.$");
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
//# sourceMappingURL=egress-firewall-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress-firewall-config.test.js","sourceRoot":"","sources":["../../src/sandbox/egress-firewall-config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox image names + the docker availability probes. Kept in this
|
|
3
|
+
* dependency-light module (only `child_process`, no `./docker.js`) so callers
|
|
4
|
+
* like the workflow runner can check image availability without importing the
|
|
5
|
+
* full `DockerSandbox` machinery — `docker.ts` runs `promisify(execFile)` at
|
|
6
|
+
* module load, which trips test suites that mock `child_process`.
|
|
7
|
+
*/
|
|
8
|
+
/** The lean default sandbox image (`sandbox.Dockerfile`). */
|
|
9
|
+
export declare const SANDBOX_IMAGE = "lastlight-sandbox:latest";
|
|
10
|
+
/**
|
|
11
|
+
* The enriched browser-QA image (Playwright + Chromium baked in). Built only
|
|
12
|
+
* when QA is enabled (`sandbox-qa.Dockerfile`); a phase opts into it with
|
|
13
|
+
* `sandbox_image: qa`. Fixed name, deliberately not overridable.
|
|
14
|
+
*/
|
|
15
|
+
export declare const SANDBOX_IMAGE_QA = "lastlight-sandbox-qa:latest";
|
|
16
|
+
/** Check if Docker sandbox mode is available (docker up + lean image built). */
|
|
17
|
+
export declare function isSandboxAvailable(): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Whether the browser-QA sandbox image is present on this host. Used by the
|
|
20
|
+
* runner to gracefully skip a `sandbox_image: qa` phase when the image hasn't
|
|
21
|
+
* been built (the lean default deploy), rather than failing the run.
|
|
22
|
+
*/
|
|
23
|
+
export declare function qaImageAvailable(): boolean;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Sandbox image names + the docker availability probes. Kept in this
|
|
4
|
+
* dependency-light module (only `child_process`, no `./docker.js`) so callers
|
|
5
|
+
* like the workflow runner can check image availability without importing the
|
|
6
|
+
* full `DockerSandbox` machinery — `docker.ts` runs `promisify(execFile)` at
|
|
7
|
+
* module load, which trips test suites that mock `child_process`.
|
|
8
|
+
*/
|
|
9
|
+
/** The lean default sandbox image (`sandbox.Dockerfile`). */
|
|
10
|
+
export const SANDBOX_IMAGE = "lastlight-sandbox:latest";
|
|
11
|
+
/**
|
|
12
|
+
* The enriched browser-QA image (Playwright + Chromium baked in). Built only
|
|
13
|
+
* when QA is enabled (`sandbox-qa.Dockerfile`); a phase opts into it with
|
|
14
|
+
* `sandbox_image: qa`. Fixed name, deliberately not overridable.
|
|
15
|
+
*/
|
|
16
|
+
export const SANDBOX_IMAGE_QA = "lastlight-sandbox-qa:latest";
|
|
17
|
+
/** Check if Docker sandbox mode is available (docker up + lean image built). */
|
|
18
|
+
export function isSandboxAvailable() {
|
|
19
|
+
return dockerAvailable() && sandboxImageExists(SANDBOX_IMAGE);
|
|
20
|
+
}
|
|
21
|
+
/** Cached check — only probe for the QA image once per process. */
|
|
22
|
+
let _qaImageAvailable = null;
|
|
23
|
+
/**
|
|
24
|
+
* Whether the browser-QA sandbox image is present on this host. Used by the
|
|
25
|
+
* runner to gracefully skip a `sandbox_image: qa` phase when the image hasn't
|
|
26
|
+
* been built (the lean default deploy), rather than failing the run.
|
|
27
|
+
*/
|
|
28
|
+
export function qaImageAvailable() {
|
|
29
|
+
if (_qaImageAvailable === null) {
|
|
30
|
+
_qaImageAvailable = dockerAvailable() && sandboxImageExists(SANDBOX_IMAGE_QA);
|
|
31
|
+
}
|
|
32
|
+
return _qaImageAvailable;
|
|
33
|
+
}
|
|
34
|
+
function dockerAvailable() {
|
|
35
|
+
try {
|
|
36
|
+
execFileSync("docker", ["info"], { stdio: "ignore", timeout: 5000 });
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function sandboxImageExists(imageName) {
|
|
44
|
+
try {
|
|
45
|
+
const out = execFileSync("docker", ["images", "-q", imageName], {
|
|
46
|
+
encoding: "utf-8",
|
|
47
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
48
|
+
});
|
|
49
|
+
return out.trim().length > 0;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.js","sourceRoot":"","sources":["../../src/sandbox/images.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;GAMG;AAEH,6DAA6D;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAExD;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,6BAA6B,CAAC;AAE9D,gFAAgF;AAChF,MAAM,UAAU,kBAAkB;IAChC,OAAO,eAAe,EAAE,IAAI,kBAAkB,CAAC,aAAa,CAAC,CAAC;AAChE,CAAC;AAED,mEAAmE;AACnE,IAAI,iBAAiB,GAAmB,IAAI,CAAC;AAE7C;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,iBAAiB,GAAG,eAAe,EAAE,IAAI,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAChF,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,SAAS,eAAe;IACtB,IAAI,CAAC;QACH,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE;YAC9D,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/sandbox/index.d.ts
CHANGED
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
import { DockerSandbox } from "./docker.js";
|
|
2
2
|
export { DockerSandbox } from "./docker.js";
|
|
3
|
+
export { SANDBOX_IMAGE, SANDBOX_IMAGE_QA, isSandboxAvailable, qaImageAvailable, } from "./images.js";
|
|
3
4
|
/**
|
|
4
5
|
* Clean up orphaned sandbox containers from previous runs.
|
|
5
6
|
* Called on startup to remove containers that survived a harness restart.
|
|
6
7
|
*/
|
|
7
8
|
export declare function cleanupOrphanedSandboxes(): void;
|
|
9
|
+
export declare function sandboxAvailable(): boolean;
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
11
|
+
* Set up the per-task worktree directory (mkdir + optional pre-clone) without
|
|
12
|
+
* touching Docker. Used by the non-docker sandbox modes (gondolin / none) where
|
|
13
|
+
* agentic-pi runs in-process or in a VM rather than a container, but still
|
|
14
|
+
* wants a per-task workspace cloned from the target branch.
|
|
10
15
|
*/
|
|
11
|
-
export declare function
|
|
12
|
-
|
|
16
|
+
export declare function setupTaskWorktree(opts: {
|
|
17
|
+
taskId: string;
|
|
18
|
+
stateDir: string;
|
|
19
|
+
sandboxDir?: string;
|
|
20
|
+
prePopulate?: {
|
|
21
|
+
owner: string;
|
|
22
|
+
repo: string;
|
|
23
|
+
branch: string;
|
|
24
|
+
token: string;
|
|
25
|
+
/** Owning run id — stamped into a marker so a reused per-PR workspace
|
|
26
|
+
* refreshes across runs but is preserved between phases of one run. */
|
|
27
|
+
runId?: string;
|
|
28
|
+
/** Clone shallowly (`--depth 1 --single-branch`) for read-only workflows. */
|
|
29
|
+
shallow?: boolean;
|
|
30
|
+
};
|
|
31
|
+
}): string;
|
|
13
32
|
/**
|
|
14
33
|
* Create a sandbox for a task. Returns the sandbox and a cleanup function.
|
|
15
34
|
* If Docker is not available, returns null (caller should fall back to direct execution).
|
|
@@ -19,8 +38,68 @@ export declare function createTaskSandbox(opts: {
|
|
|
19
38
|
stateDir: string;
|
|
20
39
|
sandboxDir?: string;
|
|
21
40
|
env?: Record<string, string>;
|
|
41
|
+
/**
|
|
42
|
+
* When set, the harness clones the repo into workDir at the named branch
|
|
43
|
+
* before starting the sandbox container. The agent then enters a
|
|
44
|
+
* workspace that's already checked out, avoiding a redundant
|
|
45
|
+
* `clone_repo` MCP call inside the session.
|
|
46
|
+
*
|
|
47
|
+
* Token must be alphanumeric (shape asserted upstream) and is embedded
|
|
48
|
+
* into the clone URL just for this one-shot operation — git's own
|
|
49
|
+
* credential.helper inside the sandbox covers subsequent push/pull.
|
|
50
|
+
*/
|
|
51
|
+
prePopulate?: {
|
|
52
|
+
owner: string;
|
|
53
|
+
repo: string;
|
|
54
|
+
branch: string;
|
|
55
|
+
token: string;
|
|
56
|
+
/** Owning run id — stamped into a marker so a reused per-PR workspace
|
|
57
|
+
* refreshes across runs but is preserved between phases of one run. */
|
|
58
|
+
runId?: string;
|
|
59
|
+
/** Clone shallowly (`--depth 1 --single-branch`) for read-only workflows. */
|
|
60
|
+
shallow?: boolean;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* IP of the coredns sidecar to use as the sandbox's DNS resolver.
|
|
64
|
+
* Selects the egress policy: `172.30.0.10` (coredns-strict) for the
|
|
65
|
+
* default allowlist, `172.30.0.11` (coredns-open) for phases that
|
|
66
|
+
* declared `unrestricted_egress: true`. Passed to `docker run` as
|
|
67
|
+
* `--dns <ip>`. See src/sandbox/egress-firewall-config.ts.
|
|
68
|
+
*/
|
|
69
|
+
dnsIp?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Override the container image. Defaults to the lean `SANDBOX_IMAGE`; a
|
|
72
|
+
* browser-QA phase passes `SANDBOX_IMAGE_QA`. The caller is responsible for
|
|
73
|
+
* ensuring the image exists (see `qaImageAvailable`).
|
|
74
|
+
*/
|
|
75
|
+
imageName?: string;
|
|
22
76
|
}): Promise<{
|
|
23
77
|
sandbox: DockerSandbox;
|
|
24
78
|
workDir: string;
|
|
25
79
|
cleanup: () => Promise<void>;
|
|
26
80
|
} | null>;
|
|
81
|
+
type PrePopulate = {
|
|
82
|
+
owner: string;
|
|
83
|
+
repo: string;
|
|
84
|
+
branch: string;
|
|
85
|
+
token: string;
|
|
86
|
+
runId?: string;
|
|
87
|
+
shallow?: boolean;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Clone the repo into `<workDir>/<repo>` at the given branch.
|
|
91
|
+
*
|
|
92
|
+
* Three cases:
|
|
93
|
+
* - **Fresh dir** (no `.git`): clone. `--depth 1 --single-branch` for
|
|
94
|
+
* read-only workflows (`pre.shallow`), `--depth 50` otherwise.
|
|
95
|
+
* - **Same run revisiting the workspace** (`.git` exists, run marker matches
|
|
96
|
+
* `pre.runId`): preserve — this is a later phase of the same run reading
|
|
97
|
+
* what an earlier phase wrote (architect's `plan.md`, the reviewer's
|
|
98
|
+
* checkout). No git ops.
|
|
99
|
+
* - **A fresh run reusing an old per-PR workspace** (`.git` exists, marker
|
|
100
|
+
* differs/absent): fetch + hard-reset to the remote branch + `git clean`
|
|
101
|
+
* that **keeps `node_modules`** so the next `npm install` is incremental.
|
|
102
|
+
* This is the re-review fast path from issue #107.
|
|
103
|
+
*/
|
|
104
|
+
export { prePopulateWorkspace as __prePopulateWorkspaceForTest };
|
|
105
|
+
declare function prePopulateWorkspace(workDir: string, pre: PrePopulate): void;
|