Docs

Overview

Last Light ships with a roster of default workflows, grouped by family: build; question-answering (answer, issue-comment, pr-comment); triage; review (pr-review); fix (pr-fix); reporting (repo-health); and security (security-review, security-feedback) — several with optional cron variants. Each is a YAML file in workflows/ that the runner executes phase-by-phase. The harness itself knows nothing about "build" or "triage" specifically — it just runs whatever phases a workflow declares.

Workflows fall into three categories based on complexity:

Multi-phase workflows

These run multiple agent sessions in sequence, often with loops and approval gates. Each phase runs in an isolated Docker sandbox with a shared workspace so files persist between phases.

Single-phase workflows

Each runs one focused agent session — fast, cheap, and targeted.

Issue triage

Classifies, labels, and responds to new or reopened issues.

1 phase · webhook + cron
Issue comment

Conversational reply when a maintainer comments without requesting a build.

1 phase · webhook
Answer

Researches docs + web and posts a single sourced answer when an issue or message is a question.

1 phase · webhook + slack
PR comment

Answers a maintainer's question about an open PR with concrete, code-cited evidence.

1 phase · webhook
PR review

Reads a PR diff and posts line-anchored inline review comments. Read-only — no code modifications.

2 phases · webhook + cron
PR fix

Lightweight diagnose-then-fix-and-push — no architect or reviewer. Classifies why the PR is red first, then fixes it and pushes, or stops if nothing here can repair it.

2 phases · webhook
Dependabot CI fix

Fixes a dependency-update PR whose checks failed — diagnoses the breakage first, brings the branch up to date, pushes the smallest fix, and hands the merge decision to dependabot-pr-merge once CI is green. Via webhook and a daily per-PR cron backstop.

2 phases · webhook + cron
Dependabot PR merge

Finds already-green dependency-update PRs and enables auto-merge on the safe ones — including a major bump whose impact is low enough — via webhook and a daily per-PR cron backstop.

1 phase · webhook + cron
Repo health

Weekly health report — open/stale issues, PR velocity, action items.

1 phase · cron
Security review

Scans a repo with npm audit, semgrep, gitleaks + AI review and files one grouped summary issue per run.

1 phase · cron + webhook + slack
Security feedback

Acts on maintainer feedback to a security issue — split into issues, accept risk, false-positive, or reopen.

1 phase · webhook
Verify

Tests a behaviour claim in the sandbox and reports CONFIRMED / REFUTED / INCONCLUSIVE with evidence.

1 phase · webhook + slack + cli
QA test

Drives a CLI or locally-served app through a flow and reports step-level pass/fail with evidence.

1 phase · webhook + slack + cli
Demo

Records a short demo video of a PR/feature — drives the web UI in a headless browser, composites a titled mp4 with ffmpeg, and embeds it inline.

2 phases · docker QA image · webhook + slack + cli

Direct chat

Not a YAML workflow — Slack messages that don't match any of the above intents are handled by the chat skill, which runs an in-process @earendil-works/pi-ai chat loop (no sandbox spawn) for low-latency replies. Each Slack thread maps to one persistent pi-ai conversation, rehydrated from the messaging_messages SQLite table on every turn, so context holds across messages.

The LLM classifier routes messages to chat when the intent is conversational — questions, discussion, status checks, and anything that isn't explicitly a build, explore, triage, review, or approval.

How workflows are triggered

Trigger Workflows How it works
GitHub webhook issue-triage, pr-review, build, pr-fix, dependabot-ci-fix, dependabot-pr-merge, issue-comment, answer, pr-comment, security-feedback, verify, qa-test, demo GitHub App sends events to the harness. The router + LLM classifier decides which workflow to run. A newly-opened issue classified as a question routes to answer; a comment on a PR routes to pr-comment; an @last-light mention on a security-labelled issue routes to security-feedback. A PR whose CI fails (a check_suite failure) is classified and routes to dependabot-ci-fix when it's a dependency update; a dependency PR whose CI passes (a check_suite success) routes deterministically to dependabot-pr-merge. Under review.trigger: after-checks, a settled check suite on any other PR routes to pr-review; adding the review.requestLabel, requesting a review from the bot, or pressing Re-run on the last-light/review check all do the same. @last-light verify <claim> / qa-test <target> / demo <notes> (or the equivalent classifier intent) route to verify / qa-test / demo.
Slack message explore, build, triage, review, answer, security-review, verify, qa-test, demo, all others via chat Natural language in DMs or threads. The classifier extracts intent and repo from the message. Questions route to answer; "security review owner/repo" runs security-review. The two dependency workflows are GitHub-only — they need a PR number no Slack message carries, so such a request falls through to chat. Which triggers the bot will actually suggest in a thread is composed from the workflows that declare a chat: block and are enabled on that deployment, so the set is per-instance.
Cron schedule issue-triage, pr-review, repo-health, security-review, dependabot-pr-merge, dependabot-ci-fix Periodic scans. The triage cron is a fallback for deployments without webhooks. The review sweep (every 30 min) runs even with webhooks on: it is what reaches a PR whose fix chain ended without pushing a commit — attempts exhausted, an infrastructure failure, a flaky deferral — where no further check_suite event will ever fire, and it is the re-pickup that makes dropping (rather than queueing) the loser of the per-PR run lock safe. The security-review cron runs weekly (Monday 10:00), fanning out one run per managed repo. The two dependency-PR backstops run daily even with webhooks on — dependabot-pr-merge (14:00) discovers green (clean) dependency PRs and dependabot-ci-fix (15:00) discovers ones that can't merge on their own — settled-red checks, or a behind / dirty / blocked mergeable_state — each fanning out one bounded run per PR as a safety net for the real-time pr.checks_passed / pr.checks_failed paths. The sweeps only find candidates; whether a PR may be acted on (escalation, budgets, already-assessed, forks, a run already in flight) is decided at dispatch, in one place both they and the webhooks pass through.
CLI All npm run cli -- build owner/repo#N or npm run cli -- health owner/repo
Dashboard All (via approval resume) Approve/reject buttons on paused workflows in the admin dashboard.

One label stops all of it. Apply the hold label — lastlight-ignore by default, configurable as hold.label — to any issue or pull request and no workflow in this table runs on it: not triage, not review, not a fix, not a merge, and no comment. It is checked before every routing rule and before every dispatch, so the crons, the webhooks and a direct @last-light … request all honour it — the direct request gets exactly one reply naming the label, so it is refused rather than silently ignored. Remove the label and the bot resumes, with nothing to clear.

Permission profiles

Each workflow runs in a Docker sandbox with a scoped GitHub token. The permission profile determines what the agent can do:

Profile Workflows Permissions
repo-write build, pr-fix, dependabot-ci-fix, dependabot-pr-merge Full read/write — can push commits, create branches, open PRs (dependabot-ci-fix pushes fixes but never merges; dependabot-pr-merge enables auto-merge / merges and never pushes)
repo-write security-feedback Full read/write — updates SECURITY.md via PR and creates issues
review-write pr-review Can post review comments but not push code
issues-write issue-triage, issue-comment, pr-comment, explore, answer, security-review, verify, qa-test, demo Can read code, create/edit issues, post comments
read repo-health Read-only access to repo contents and metadata