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,194 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: demo
|
|
3
|
+
description: Record a short demo VIDEO of a PR or feature — drive the repo's web UI in a real headless browser, capture the session, and composite a titled, size-capped mp4 with ffmpeg. Use on the docker QA image when the deliverable is a playable demo clip (single walkthrough or before/after comparison), not a text/screenshot report.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
tags: [demo, video, browser, ffmpeg, evidence]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Demo
|
|
9
|
+
|
|
10
|
+
Turn a PR or feature into a short, polished **demo video**: drive the repo's
|
|
11
|
+
web UI in a real headless Chromium, screen-record the session, and composite a
|
|
12
|
+
titled, size-capped **mp4** the maintainer can watch inline.
|
|
13
|
+
|
|
14
|
+
This is the **video** sibling of `browser-qa` (screenshots) and `verify`/
|
|
15
|
+
`qa-test` (text evidence). It only works on the `lastlight-sandbox-qa:latest`
|
|
16
|
+
docker image, which bakes in Playwright + Chromium **and ffmpeg**. You have
|
|
17
|
+
bash + file tools but **no vision** — you reason over the driver's JSON stdout
|
|
18
|
+
and the ffprobe summary; you never "see" the video.
|
|
19
|
+
|
|
20
|
+
Compositing is **ffmpeg only** — there is no Remotion / cinematic-effects
|
|
21
|
+
pipeline. You get a title card, optional before/after side-by-side, trim/speed,
|
|
22
|
+
and a size cap. That's the deliverable: a clear, honest walkthrough, not a
|
|
23
|
+
marketing reel.
|
|
24
|
+
|
|
25
|
+
This skill uses **browser-qa** (the headless driver) and **building** (install
|
|
26
|
+
+ start the dev-server).
|
|
27
|
+
|
|
28
|
+
## When this applies
|
|
29
|
+
|
|
30
|
+
A phase on the docker QA image whose target is a **web app** the repo serves on
|
|
31
|
+
`localhost`, where a *moving* demonstration adds value over a screenshot. For a
|
|
32
|
+
CLI, a curl-able API, or pure pass/fail evidence, use `qa-test`/`verify`. For
|
|
33
|
+
static screenshot evidence, use `browser-qa`. Don't record a video you don't
|
|
34
|
+
need.
|
|
35
|
+
|
|
36
|
+
## FIRST — probe for a browser
|
|
37
|
+
|
|
38
|
+
The browser driver lives in the **browser-qa** skill bundle at
|
|
39
|
+
`<browser-qa-dir>/scripts/agent-browser.mjs`, and this skill's compositor at
|
|
40
|
+
`<demo-dir>/scripts/compose-demo.sh`. Resolve both `<…-dir>` paths from the
|
|
41
|
+
available-skills catalogue (it gives each skill's absolute staged path); do not
|
|
42
|
+
assume a relative path from `$PWD` — your cwd is the checked-out repo, the
|
|
43
|
+
bundles are siblings.
|
|
44
|
+
|
|
45
|
+
Run the runtime probe before anything else:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
node <browser-qa-dir>/scripts/agent-browser.mjs doctor
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- Exit 0 with `{"ok":true,...}` → proceed.
|
|
52
|
+
- Exit non-zero (lean image / gondolin / no Chromium) → **DO NOT attempt a demo.**
|
|
53
|
+
Report that the demo path was unavailable on this host and stop. (The workflow
|
|
54
|
+
gates this phase to the QA image, so this should be rare — but never fake a
|
|
55
|
+
recording.)
|
|
56
|
+
|
|
57
|
+
## Understand what to prove
|
|
58
|
+
|
|
59
|
+
Read the PR (description, diff, linked issue) from the context the prompt gives
|
|
60
|
+
you. For each change, ask: *what could a viewer confuse this with?* Design the
|
|
61
|
+
demo so the viewer sees something that **only happens if the feature works as
|
|
62
|
+
claimed** — both states (before/after, input/result) must appear on screen.
|
|
63
|
+
|
|
64
|
+
State your **commitments** up front, then honour them:
|
|
65
|
+
|
|
66
|
+
- **Layout** — `single` (default: a new feature, a fix proof, a walkthrough) or
|
|
67
|
+
`side-by-side` (only when the story is fundamentally a comparison: regression
|
|
68
|
+
fixed, behaviour-preserving refactor). Never fabricate a "before" to justify
|
|
69
|
+
side-by-side.
|
|
70
|
+
- **Speed** — target a watchable length; speed up dead time rather than leaving
|
|
71
|
+
it. 30–60s is a good single-feature target.
|
|
72
|
+
|
|
73
|
+
## Build and run the app
|
|
74
|
+
|
|
75
|
+
Follow the **building** skill to install dependencies, then start the repo's
|
|
76
|
+
dev-server **in the background** and poll with `curl` until it answers on
|
|
77
|
+
`localhost:PORT`. Note the port — you pass it as `--base-url`.
|
|
78
|
+
|
|
79
|
+
## Capture the session
|
|
80
|
+
|
|
81
|
+
Author a `flow.json` (same shape as **browser-qa**) that scripts the
|
|
82
|
+
interaction as a *director*, not an operator:
|
|
83
|
+
|
|
84
|
+
- **Record the baseline first** — the starting state is act one.
|
|
85
|
+
- **Hold after state changes** — add a `waitFor`/short pause so text is readable.
|
|
86
|
+
- **Verify between steps** — `waitFor` the expected element before the next
|
|
87
|
+
action; don't blindly fire keys into an unsettled page.
|
|
88
|
+
|
|
89
|
+
Record the session by passing `--record-dir`:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
node <browser-qa-dir>/scripts/agent-browser.mjs run flow.json \
|
|
93
|
+
--base-url http://localhost:PORT \
|
|
94
|
+
--record-dir /tmp/demo-cap
|
|
95
|
+
# → writes /tmp/demo-cap/session.webm, reports {"video":"…/session.webm", …}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Pick the viewport to match the layout so the clip isn't letterboxed:
|
|
99
|
+
`1280x720` for `single`; `~960x1000` per panel for `side-by-side` (set it in the
|
|
100
|
+
flow's `viewport`).
|
|
101
|
+
|
|
102
|
+
**Before/after comparison:** check out and run each branch in turn (the
|
|
103
|
+
`building` skill), recording the **same** scripted interaction against each —
|
|
104
|
+
`session-before.webm` (base branch) and `session-after.webm` (PR head). Only the
|
|
105
|
+
behaviour should differ.
|
|
106
|
+
|
|
107
|
+
## Compose the video
|
|
108
|
+
|
|
109
|
+
Composite the raw recording(s) into the final mp4 with the bundled wrapper:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Single walkthrough
|
|
113
|
+
<demo-dir>/scripts/compose-demo.sh \
|
|
114
|
+
--output <artifact-dir>/demo.mp4 \
|
|
115
|
+
--title "PR #42 — Add dark mode toggle" \
|
|
116
|
+
--subtitle "Toggling persists the theme across reloads" \
|
|
117
|
+
--layout single --speed 1.5 --target-size-mb 5 \
|
|
118
|
+
/tmp/demo-cap/session.webm
|
|
119
|
+
|
|
120
|
+
# Before/after comparison
|
|
121
|
+
<demo-dir>/scripts/compose-demo.sh \
|
|
122
|
+
--output <artifact-dir>/demo.mp4 \
|
|
123
|
+
--title "PR #51 — Fix flicker on load" \
|
|
124
|
+
--layout side-by-side --labels "BEFORE (main)" "AFTER (PR)" \
|
|
125
|
+
--target-size-mb 5 \
|
|
126
|
+
/tmp/before/session-before.webm /tmp/after/session-after.webm
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Flags: `--title` (required, on the card), `--subtitle`, `--layout
|
|
130
|
+
single|side-by-side`, `--labels A B` (side-by-side), `--speed N`, `--trim
|
|
131
|
+
START:END` (seconds, single layout), `--target-size-mb` (default 5),
|
|
132
|
+
`--width/--height` (default 1280×720), `--title-secs`. The script normalizes,
|
|
133
|
+
lays out, adds the title card, and does a **two-pass** encode to land under the
|
|
134
|
+
size cap (`+faststart`, `yuv420p`). It prints a JSON summary line:
|
|
135
|
+
`{"output":"…","resolution":"1280x720","duration":"38.4","size_mb":3.1}`.
|
|
136
|
+
|
|
137
|
+
## Guardrails — self-check before reporting
|
|
138
|
+
|
|
139
|
+
Confirm the output with `ffprobe` (the script's summary already reports these):
|
|
140
|
+
|
|
141
|
+
- **Resolution** matches the requested size (default 1920-free 1280×720).
|
|
142
|
+
- **Duration** is sane — not 0s, within a watchable band (~15–90s).
|
|
143
|
+
- **Size ≤ 5 MB** so GitHub embeds it inline (25 MB hard limit). If over, re-run
|
|
144
|
+
with a lower `--target-size-mb` or a higher `--speed`.
|
|
145
|
+
|
|
146
|
+
If the recording is too short to be meaningful (a couple of seconds), go back
|
|
147
|
+
and add interaction steps — don't ship a clip that proves nothing.
|
|
148
|
+
|
|
149
|
+
## Output location
|
|
150
|
+
|
|
151
|
+
Write `demo.mp4` into the **artifact directory the prompt provides** (the run's
|
|
152
|
+
`.lastlight/<issueKey>/` dir, referenced by the template variable the prompt
|
|
153
|
+
passes). The harness harvests it into the dashboard Artifacts view, and the
|
|
154
|
+
public artifact URL makes it playable inline on GitHub. Do **not** commit the
|
|
155
|
+
mp4 into the repo, and do **not** post it yourself — the workflow embeds it.
|
|
156
|
+
|
|
157
|
+
Video delivery requires **server-mode build-assets**. If the mp4 can't be
|
|
158
|
+
persisted (no artifact dir provided, or repo-mode), say so in the report and
|
|
159
|
+
describe what the demo showed instead.
|
|
160
|
+
|
|
161
|
+
## Evidence rules
|
|
162
|
+
|
|
163
|
+
Mirror `verify`/`browser-qa` — you are demonstrating real behaviour, not selling
|
|
164
|
+
it:
|
|
165
|
+
|
|
166
|
+
- **Never fake it.** Don't edit the code under test to force a nicer demo, and
|
|
167
|
+
don't stage a result the feature didn't actually produce.
|
|
168
|
+
- **Show the disambiguating moment** — the thing that only happens if the change
|
|
169
|
+
works. Off-camera claims don't count.
|
|
170
|
+
- If something doesn't work, the honest demo shows that — report it; don't trim
|
|
171
|
+
the failure out and call it a success.
|
|
172
|
+
|
|
173
|
+
## Report
|
|
174
|
+
|
|
175
|
+
Produce your report as your **final message** — the workflow posts it (don't
|
|
176
|
+
comment yourself). Keep it short:
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
## Demo: <target>
|
|
180
|
+
|
|
181
|
+
**Environment:** <branch / commit, package manager, how served, Chromium version>
|
|
182
|
+
|
|
183
|
+
<one or two sentences: what the video demonstrates and the key moment to watch>
|
|
184
|
+
|
|
185
|
+
- **Layout:** single | side-by-side
|
|
186
|
+
- **Video:** demo.mp4 (<resolution>, <duration>s, <size>MB)
|
|
187
|
+
|
|
188
|
+
### Not covered
|
|
189
|
+
<one line: anything the demo doesn't show, and why>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The workflow embeds the playable video from the artifact store; reference it as
|
|
193
|
+
`demo.mp4`. If the browser or compositor was unavailable, say so plainly instead
|
|
194
|
+
of pretending a clip exists.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# compose-demo.sh — composite a raw browser screen recording into a titled,
|
|
3
|
+
# size-capped demo mp4 using ffmpeg only (NO Remotion, NO headless render).
|
|
4
|
+
#
|
|
5
|
+
# Used by the `/demo` workflow: agent-browser records the session to a .webm,
|
|
6
|
+
# this script turns it into a polished, GitHub-embeddable mp4.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# compose-demo.sh --output demo.mp4 --title "PR #42 — Add dark mode" \
|
|
10
|
+
# [--subtitle "..."] [--layout single|side-by-side] \
|
|
11
|
+
# [--labels "BEFORE (main)" "AFTER (PR)"] [--speed 1.5] \
|
|
12
|
+
# [--trim START:END] [--target-size-mb 5] [--width 1280] [--height 720] \
|
|
13
|
+
# [--title-secs 2.5] <clip1.webm> [clip2.webm]
|
|
14
|
+
#
|
|
15
|
+
# What it does:
|
|
16
|
+
# 1. Normalizes each input clip (optional trim, speed-up, scale+pad to the
|
|
17
|
+
# panel size, fps/pixfmt/SAR normalize, optional per-panel label).
|
|
18
|
+
# 2. Lays out the body: a single panel, or two panels side-by-side (hstack).
|
|
19
|
+
# 3. Prepends a title/subtitle card (solid bg + drawtext).
|
|
20
|
+
# 4. Two-pass H.264 encode targeting --target-size-mb so the mp4 lands under
|
|
21
|
+
# GitHub's inline-embed limit; yuv420p + +faststart for web streaming.
|
|
22
|
+
# 5. Prints an ffprobe summary (resolution / duration / size).
|
|
23
|
+
#
|
|
24
|
+
# Prerequisites: ffmpeg, ffprobe (baked into lastlight-sandbox-qa:latest).
|
|
25
|
+
# Runs fully offline.
|
|
26
|
+
|
|
27
|
+
set -euo pipefail
|
|
28
|
+
|
|
29
|
+
die() { echo "compose-demo.sh: error: $*" >&2; exit 1; }
|
|
30
|
+
require_cmd() { command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"; }
|
|
31
|
+
require_cmd ffmpeg
|
|
32
|
+
require_cmd ffprobe
|
|
33
|
+
|
|
34
|
+
# ── Defaults ────────────────────────────────────────────────────────────────
|
|
35
|
+
OUTPUT=""
|
|
36
|
+
TITLE=""
|
|
37
|
+
SUBTITLE=""
|
|
38
|
+
LAYOUT="single"
|
|
39
|
+
LABEL1=""
|
|
40
|
+
LABEL2=""
|
|
41
|
+
SPEED="1"
|
|
42
|
+
TRIM=""
|
|
43
|
+
TARGET_MB="5"
|
|
44
|
+
WIDTH="1280"
|
|
45
|
+
HEIGHT="720"
|
|
46
|
+
TITLE_SECS="2.5"
|
|
47
|
+
CLIPS=()
|
|
48
|
+
|
|
49
|
+
# ── Parse args ──────────────────────────────────────────────────────────────
|
|
50
|
+
while [[ $# -gt 0 ]]; do
|
|
51
|
+
case "$1" in
|
|
52
|
+
--output) OUTPUT="$2"; shift 2;;
|
|
53
|
+
--title) TITLE="$2"; shift 2;;
|
|
54
|
+
--subtitle) SUBTITLE="$2"; shift 2;;
|
|
55
|
+
--layout) LAYOUT="$2"; shift 2;;
|
|
56
|
+
--labels) LABEL1="$2"; LABEL2="$3"; shift 3;;
|
|
57
|
+
--speed) SPEED="$2"; shift 2;;
|
|
58
|
+
--trim) TRIM="$2"; shift 2;;
|
|
59
|
+
--target-size-mb) TARGET_MB="$2"; shift 2;;
|
|
60
|
+
--width) WIDTH="$2"; shift 2;;
|
|
61
|
+
--height) HEIGHT="$2"; shift 2;;
|
|
62
|
+
--title-secs) TITLE_SECS="$2"; shift 2;;
|
|
63
|
+
-*) die "unknown flag: $1";;
|
|
64
|
+
*) CLIPS+=("$1"); shift;;
|
|
65
|
+
esac
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
[[ -n "$OUTPUT" ]] || die "--output is required"
|
|
69
|
+
[[ ${#CLIPS[@]} -ge 1 ]] || die "at least one input clip is required"
|
|
70
|
+
for c in "${CLIPS[@]}"; do [[ -f "$c" ]] || die "clip not found: $c"; done
|
|
71
|
+
if [[ "$LAYOUT" == "side-by-side" ]]; then
|
|
72
|
+
[[ ${#CLIPS[@]} -ge 2 ]] || die "side-by-side layout needs two clips"
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
WORK="$(mktemp -d "${TMPDIR:-/tmp}/compose-demo-XXXXXX")"
|
|
76
|
+
cleanup() { rm -rf "$WORK"; }
|
|
77
|
+
trap cleanup EXIT
|
|
78
|
+
|
|
79
|
+
# ── Font for drawtext ────────────────────────────────────────────────────────
|
|
80
|
+
# Prefer an explicit fontfile (Liberation ships in the QA image via
|
|
81
|
+
# fonts-liberation); fall back to fontconfig's default Sans family.
|
|
82
|
+
FONT="${DEMO_FONT:-}"
|
|
83
|
+
if [[ -z "$FONT" ]]; then
|
|
84
|
+
for f in \
|
|
85
|
+
/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf \
|
|
86
|
+
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf; do
|
|
87
|
+
[[ -f "$f" ]] && FONT="$f" && break
|
|
88
|
+
done
|
|
89
|
+
fi
|
|
90
|
+
if [[ -n "$FONT" ]]; then FONTARG="fontfile=${FONT}"; else FONTARG="font=Sans"; fi
|
|
91
|
+
|
|
92
|
+
# drawtext drives the title card and per-panel labels. The Debian `ffmpeg`
|
|
93
|
+
# package (the QA image) is built with libfreetype so it's present; but degrade
|
|
94
|
+
# gracefully on a build without it (omit text overlays) rather than failing the
|
|
95
|
+
# whole compose — the demo video is still worth shipping.
|
|
96
|
+
HAS_DRAWTEXT=0
|
|
97
|
+
if ffmpeg -hide_banner -filters 2>/dev/null | grep -q 'drawtext'; then
|
|
98
|
+
HAS_DRAWTEXT=1
|
|
99
|
+
else
|
|
100
|
+
echo "compose-demo.sh: warning: this ffmpeg lacks the drawtext filter — title card and labels omitted." >&2
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# Panel size: side-by-side splits the width into two equal panels.
|
|
104
|
+
PH="$HEIGHT"
|
|
105
|
+
if [[ "$LAYOUT" == "side-by-side" ]]; then PW=$(( WIDTH / 2 )); else PW="$WIDTH"; fi
|
|
106
|
+
|
|
107
|
+
# ── Stage A: normalize one clip into a body panel ─────────────────────────────
|
|
108
|
+
# Args: <input> <outfile> <label-file-or-empty> <apply-trim:0|1>
|
|
109
|
+
build_panel() {
|
|
110
|
+
local input="$1" outfile="$2" labelfile="$3" apply_trim="$4"
|
|
111
|
+
local trim_args=()
|
|
112
|
+
if [[ "$apply_trim" == "1" && -n "$TRIM" ]]; then
|
|
113
|
+
local start="${TRIM%%:*}" end="${TRIM##*:}"
|
|
114
|
+
[[ -n "$start" ]] && trim_args+=(-ss "$start")
|
|
115
|
+
[[ -n "$end" ]] && trim_args+=(-to "$end")
|
|
116
|
+
fi
|
|
117
|
+
local vf="setpts=PTS/${SPEED}"
|
|
118
|
+
vf+=",scale=${PW}:${PH}:force_original_aspect_ratio=decrease"
|
|
119
|
+
vf+=",pad=${PW}:${PH}:(ow-iw)/2:(oh-ih)/2:color=black"
|
|
120
|
+
vf+=",fps=30,format=yuv420p,setsar=1"
|
|
121
|
+
if [[ -n "$labelfile" && "$HAS_DRAWTEXT" == "1" ]]; then
|
|
122
|
+
vf+=",drawtext=${FONTARG}:textfile=${labelfile}:x=(w-text_w)/2:y=h-th-24"
|
|
123
|
+
vf+=":fontsize=26:fontcolor=white:box=1:boxcolor=black@0.55:boxborderw=12"
|
|
124
|
+
fi
|
|
125
|
+
# `${arr[@]+"${arr[@]}"}` expands to nothing when the array is empty without
|
|
126
|
+
# tripping `set -u` (an empty `"${arr[@]}"` errors on bash < 4.4, e.g. macOS).
|
|
127
|
+
ffmpeg -y -loglevel error ${trim_args[@]+"${trim_args[@]}"} -i "$input" \
|
|
128
|
+
-vf "$vf" -an -c:v libx264 -crf 20 -preset veryfast "$outfile"
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Per-panel labels (side-by-side) written to files to avoid drawtext escaping.
|
|
132
|
+
LABELFILE1=""; LABELFILE2=""
|
|
133
|
+
if [[ "$LAYOUT" == "side-by-side" ]]; then
|
|
134
|
+
if [[ -n "$LABEL1" ]]; then LABELFILE1="$WORK/label1.txt"; printf '%s' "$LABEL1" > "$LABELFILE1"; fi
|
|
135
|
+
if [[ -n "$LABEL2" ]]; then LABELFILE2="$WORK/label2.txt"; printf '%s' "$LABEL2" > "$LABELFILE2"; fi
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
echo "compose-demo.sh: normalizing clips (layout=$LAYOUT, speed=${SPEED}x)…" >&2
|
|
139
|
+
build_panel "${CLIPS[0]}" "$WORK/panel0.mp4" "$LABELFILE1" 1
|
|
140
|
+
BODY="$WORK/body.mp4"
|
|
141
|
+
if [[ "$LAYOUT" == "side-by-side" ]]; then
|
|
142
|
+
build_panel "${CLIPS[1]}" "$WORK/panel1.mp4" "$LABELFILE2" 1
|
|
143
|
+
ffmpeg -y -loglevel error -i "$WORK/panel0.mp4" -i "$WORK/panel1.mp4" \
|
|
144
|
+
-filter_complex "[0:v][1:v]hstack=inputs=2,format=yuv420p,setsar=1[v]" \
|
|
145
|
+
-map "[v]" -an -c:v libx264 -crf 20 -preset veryfast "$BODY"
|
|
146
|
+
else
|
|
147
|
+
BODY="$WORK/panel0.mp4"
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
# ── Stage B: title card (skipped when drawtext is unavailable) ───────────────
|
|
151
|
+
TITLE_CLIP=""
|
|
152
|
+
TITLE_DUR="0"
|
|
153
|
+
if [[ "$HAS_DRAWTEXT" == "1" ]]; then
|
|
154
|
+
TITLEFILE="$WORK/title.txt"; printf '%s' "${TITLE:-Demo}" > "$TITLEFILE"
|
|
155
|
+
TITLE_VF="drawtext=${FONTARG}:textfile=${TITLEFILE}:x=(w-text_w)/2:y=(h/2)-th-10:fontsize=48:fontcolor=white"
|
|
156
|
+
if [[ -n "$SUBTITLE" ]]; then
|
|
157
|
+
SUBFILE="$WORK/subtitle.txt"; printf '%s' "$SUBTITLE" > "$SUBFILE"
|
|
158
|
+
TITLE_VF+=",drawtext=${FONTARG}:textfile=${SUBFILE}:x=(w-text_w)/2:y=(h/2)+10:fontsize=26:fontcolor=0xb0b0b0"
|
|
159
|
+
fi
|
|
160
|
+
TITLE_VF+=",format=yuv420p"
|
|
161
|
+
ffmpeg -y -loglevel error -f lavfi -i "color=c=0x101418:s=${WIDTH}x${HEIGHT}:d=${TITLE_SECS}:r=30" \
|
|
162
|
+
-vf "$TITLE_VF" -c:v libx264 -crf 20 -preset veryfast "$WORK/title.mp4"
|
|
163
|
+
TITLE_CLIP="$WORK/title.mp4"
|
|
164
|
+
TITLE_DUR="$TITLE_SECS"
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# ── Stage C: (concat title +) body, two-pass size cap, faststart ─────────────
|
|
168
|
+
BODY_DUR="$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$BODY" || echo 0)"
|
|
169
|
+
TOTAL_DUR="$(awk -v a="$TITLE_DUR" -v b="$BODY_DUR" 'BEGIN{printf "%.3f", a + b}')"
|
|
170
|
+
# Target video bitrate (kbit/s) = target_bytes * 8 / duration / 1000, with a
|
|
171
|
+
# small headroom factor for the muxer; floored so very short clips still encode.
|
|
172
|
+
BR_K="$(awk -v mb="$TARGET_MB" -v d="$TOTAL_DUR" 'BEGIN{
|
|
173
|
+
if (d <= 0) d = 1;
|
|
174
|
+
br = (mb * 1024 * 1024 * 8) / d / 1000 * 0.92;
|
|
175
|
+
if (br < 200) br = 200;
|
|
176
|
+
printf "%d", br;
|
|
177
|
+
}')"
|
|
178
|
+
|
|
179
|
+
# With a title card: concat it ahead of the body. Without: pass the body
|
|
180
|
+
# through (`null`) so the same two-pass/faststart encode applies either way.
|
|
181
|
+
if [[ -n "$TITLE_CLIP" ]]; then
|
|
182
|
+
IN_ARGS=(-i "$TITLE_CLIP" -i "$BODY")
|
|
183
|
+
FILTER='[0:v][1:v]concat=n=2:v=1:a=0[v]'
|
|
184
|
+
else
|
|
185
|
+
IN_ARGS=(-i "$BODY")
|
|
186
|
+
FILTER='[0:v]null[v]'
|
|
187
|
+
fi
|
|
188
|
+
PASSLOG="$WORK/ff2pass"
|
|
189
|
+
echo "compose-demo.sh: encoding (${TOTAL_DUR}s, target ${TARGET_MB}MB → ${BR_K}kbit/s, two-pass)…" >&2
|
|
190
|
+
ffmpeg -y -loglevel error "${IN_ARGS[@]}" \
|
|
191
|
+
-filter_complex "$FILTER" -map "[v]" -an \
|
|
192
|
+
-c:v libx264 -b:v "${BR_K}k" -pass 1 -passlogfile "$PASSLOG" -preset medium -f mp4 /dev/null
|
|
193
|
+
ffmpeg -y -loglevel error "${IN_ARGS[@]}" \
|
|
194
|
+
-filter_complex "$FILTER" -map "[v]" -an \
|
|
195
|
+
-c:v libx264 -b:v "${BR_K}k" -pass 2 -passlogfile "$PASSLOG" -preset medium \
|
|
196
|
+
-pix_fmt yuv420p -movflags +faststart "$OUTPUT"
|
|
197
|
+
|
|
198
|
+
# ── Stage D: report ───────────────────────────────────────────────────────────
|
|
199
|
+
RES="$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0:s=x "$OUTPUT" || echo '?')"
|
|
200
|
+
DUR="$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$OUTPUT" || echo '?')"
|
|
201
|
+
BYTES="$(wc -c < "$OUTPUT" | tr -d ' ')"
|
|
202
|
+
MB="$(awk -v b="$BYTES" 'BEGIN{printf "%.2f", b/1024/1024}')"
|
|
203
|
+
echo "compose-demo.sh: wrote $OUTPUT (${RES}, ${DUR}s, ${MB}MB)" >&2
|
|
204
|
+
# Machine-readable line for the agent to parse.
|
|
205
|
+
echo "{\"output\":\"${OUTPUT}\",\"resolution\":\"${RES}\",\"duration\":\"${DUR}\",\"size_mb\":${MB}}"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issue-answer
|
|
3
|
+
description: Answer a question directly — a sourced, neutral reply to an information/explanation/comparison request, from a GitHub issue or a Slack thread. Research repo docs and the web, output the answer, label `question` (GitHub only), leave open. Never write an agent brief, mark ready-for-agent, or change code.
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
tags: [github, issues, questions]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Issue Answer
|
|
9
|
+
|
|
10
|
+
A user asked a **question** — they want information, an explanation, or a
|
|
11
|
+
comparison, not a code change. The router already decided this is a question;
|
|
12
|
+
your job is to **answer it well and stop**. Do not re-triage it into a work item.
|
|
13
|
+
|
|
14
|
+
The question reaches you from one of two places, and the prompt tells you which:
|
|
15
|
+
- a **GitHub issue** (an `issueNumber` is set), or
|
|
16
|
+
- a **Slack thread** (no `issueNumber`).
|
|
17
|
+
|
|
18
|
+
## How your answer is delivered
|
|
19
|
+
|
|
20
|
+
Your **final message is the answer** — the harness posts it for you (as a
|
|
21
|
+
comment on the issue for GitHub-initiated runs, or into the Slack thread for
|
|
22
|
+
Slack-initiated runs). So:
|
|
23
|
+
|
|
24
|
+
- Make your final message the complete, self-contained answer in clean markdown.
|
|
25
|
+
- **Do NOT post the answer yourself** with `github_add_issue_comment` — the
|
|
26
|
+
harness delivers it, and posting it too would double-post.
|
|
27
|
+
|
|
28
|
+
## Hard caps
|
|
29
|
+
|
|
30
|
+
This skill answers; it never queues work. Per invocation:
|
|
31
|
+
|
|
32
|
+
- Produce **one** answer (your final message).
|
|
33
|
+
- The only GitHub write you make is the `question` **label**, and only when
|
|
34
|
+
answering a GitHub issue.
|
|
35
|
+
- **Never** write an agent brief, apply `ready-for-agent` / `ready-for-human`,
|
|
36
|
+
create branches, push code, or open a PR.
|
|
37
|
+
- **Never** close the issue — leave it open for the human to close once the
|
|
38
|
+
answer satisfies them.
|
|
39
|
+
|
|
40
|
+
If, while reading, you conclude the request is actually a bug or feature request
|
|
41
|
+
(not a pure question), do **not** answer it as one. Make your final message a
|
|
42
|
+
short note saying it looks like work rather than a question and asking a
|
|
43
|
+
maintainer to `@last-light build` (or `explore`) it — let triage own work items.
|
|
44
|
+
|
|
45
|
+
## Procedure
|
|
46
|
+
|
|
47
|
+
1. **Understand the question.** Read the question from the prompt — the issue
|
|
48
|
+
title/body (and existing comments, for a GitHub issue) or the Slack message.
|
|
49
|
+
Identify exactly what the user wants to know.
|
|
50
|
+
2. **Research.**
|
|
51
|
+
- **The repo** — read what's relevant to the answer: `CONTEXT.md`,
|
|
52
|
+
`README`, `docs/`, `spec/`, and code only as needed to ground claims about
|
|
53
|
+
this project. Don't survey the whole codebase; read what the question needs.
|
|
54
|
+
- **The web** — when the question references anything outside this repo
|
|
55
|
+
(another tool, framework, library, standard, or a "X vs Y" comparison),
|
|
56
|
+
use the `web_search` and `web_fetch` tools to consult current,
|
|
57
|
+
authoritative sources. Prefer official docs and primary sources.
|
|
58
|
+
- **Budget your research and converge.** You have a bounded number of tool
|
|
59
|
+
calls before the run ends — research is for grounding the answer, not
|
|
60
|
+
exhaustive coverage. Front-load the searches you need, then stop looking.
|
|
61
|
+
**Critical:** the moment you think *"I have enough"* (or *"let me just
|
|
62
|
+
confirm one more thing"*), do **not** fire another tool call — write the
|
|
63
|
+
answer **now**, in that same turn. Your reply being cut off mid-research
|
|
64
|
+
delivers a useless half-sentence to the user, which is worse than an
|
|
65
|
+
answer that omits a minor detail. If a fact is unverified, state it as
|
|
66
|
+
unverified in the answer rather than spending your last turn chasing it.
|
|
67
|
+
For broad/open-ended questions (e.g. "what's missing vs tool X"), gather a
|
|
68
|
+
representative sample and answer from it — explicitly noting it's a
|
|
69
|
+
sample, not an exhaustive audit — rather than enumerating everything.
|
|
70
|
+
3. **Label (GitHub issue only).** Apply `question` with `github_add_labels`
|
|
71
|
+
(create it first with `github_create_label`, color `d876e3`; ignore a 422
|
|
72
|
+
"already exists"). If label creation/adding is denied, skip it — the answer
|
|
73
|
+
is the deliverable. For a Slack-initiated question there is no issue to label.
|
|
74
|
+
4. **Write the answer as your final message** (the harness delivers it — see
|
|
75
|
+
above; do not post it yourself):
|
|
76
|
+
- Direct and structured. Lead with the answer; use short sections or a
|
|
77
|
+
comparison table when it helps.
|
|
78
|
+
- **Neutral and grounded.** Claims about this project come from its docs;
|
|
79
|
+
claims about external things are **cited** with links to the sources you
|
|
80
|
+
used. Don't invent pricing, capabilities, or roadmap.
|
|
81
|
+
- **Honest about uncertainty.** If something is fast-moving or you couldn't
|
|
82
|
+
verify it, say so rather than stating it as fact.
|
|
83
|
+
5. **Stop.** The answer is the conversation; a human closes the issue when satisfied.
|
|
84
|
+
|
|
85
|
+
## Tool usage
|
|
86
|
+
|
|
87
|
+
- GitHub operations via `github_*` MCP tools only — never `gh` CLI, `curl`, or
|
|
88
|
+
raw HTTP. In chat you have no GitHub write tools beyond labelling; that's
|
|
89
|
+
expected — the answer is delivered as your final message.
|
|
90
|
+
- External research via the `web_search` / `web_fetch` tools only.
|
|
@@ -1,33 +1,47 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: issue-comment
|
|
3
|
-
description: Handle non-build maintainer
|
|
4
|
-
version:
|
|
3
|
+
description: Handle a non-build maintainer comment on an issue or PR — close, reopen, label, dedupe, answer a brief question, or triage. Action-only; redirect anything that needs code changes to /build.
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
tags: [github, issues, comments]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Issue Comment
|
|
8
|
+
# Issue Comment
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
A maintainer @mentioned the bot on an issue or PR with a request that is **not**
|
|
11
|
+
asking for code changes. Do the one bounded thing they asked, confirm it in one
|
|
12
|
+
short comment, and stop.
|
|
13
|
+
|
|
14
|
+
## Hard caps
|
|
15
|
+
|
|
16
|
+
This skill is deliberately small. Per invocation: **at most 2 file reads and 1
|
|
17
|
+
outgoing comment.** Never make code changes, create branches, or push.
|
|
12
18
|
|
|
13
19
|
## Procedure
|
|
14
20
|
|
|
15
|
-
1. **Read the
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
##
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
-
|
|
21
|
+
1. **Read the request.** The triggering comment is the job — read it, plus the
|
|
22
|
+
issue/PR title, body, existing labels, and existing comments for context.
|
|
23
|
+
2. **Do the bounded action:**
|
|
24
|
+
- Close / reopen → `github_update_issue`
|
|
25
|
+
- Label → `github_add_labels` / `github_remove_label` (use the canonical
|
|
26
|
+
triage roles from `docs/agents/triage-labels.md` where relevant)
|
|
27
|
+
- Duplicate check → search similar issues, link the original in one comment
|
|
28
|
+
- Answer a direct question → ≤5 sentences, ≤2 file reads. Don't survey the
|
|
29
|
+
codebase or compile a report.
|
|
30
|
+
3. **Confirm** in one short comment what you did. Done.
|
|
31
|
+
|
|
32
|
+
## Redirect, don't comply
|
|
33
|
+
|
|
34
|
+
The classifier owns intent routing. If a request that needs *building* reached
|
|
35
|
+
you anyway, the correct response is to **redirect, not do it** — even if the
|
|
36
|
+
comment seems to greenlight the work, and even if the issue body describes a
|
|
37
|
+
task. An issue titled "Security Review" asking you to "find and fix issues" is a
|
|
38
|
+
build request: reply asking the maintainer to use `@last-light build` (or
|
|
39
|
+
`@last-light explore`). Do **not** run the audit yourself from this skill.
|
|
40
|
+
|
|
41
|
+
If the request is unclear or out of scope, post one short comment asking them to
|
|
42
|
+
clarify or to use the right command. Do nothing else.
|
|
43
|
+
|
|
44
|
+
## Tool usage
|
|
45
|
+
|
|
46
|
+
GitHub operations via `github_*` MCP tools only — never `gh` CLI, `curl`, or raw
|
|
47
|
+
HTTP.
|