lastlight 0.7.5 → 0.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/config/default.yaml +1 -0
  2. package/dist/admin/auth.d.ts +25 -0
  3. package/dist/admin/auth.js +55 -10
  4. package/dist/admin/auth.js.map +1 -1
  5. package/dist/admin/routes.js +18 -1
  6. package/dist/admin/routes.js.map +1 -1
  7. package/dist/cli/cli-config.d.ts +9 -1
  8. package/dist/cli/cli-config.js +22 -0
  9. package/dist/cli/cli-config.js.map +1 -1
  10. package/dist/cli/cli.js +60 -4
  11. package/dist/cli/cli.js.map +1 -1
  12. package/dist/config/config.js +1 -0
  13. package/dist/config/config.js.map +1 -1
  14. package/dist/engine/dispatcher.js +19 -1
  15. package/dist/engine/dispatcher.js.map +1 -1
  16. package/dist/engine/executors/orchestrator.js +10 -1
  17. package/dist/engine/executors/orchestrator.js.map +1 -1
  18. package/dist/engine/github/github-app-client.d.ts +16 -0
  19. package/dist/engine/github/github-app-client.js +17 -0
  20. package/dist/engine/github/github-app-client.js.map +1 -1
  21. package/dist/engine/github/github.d.ts +33 -0
  22. package/dist/engine/github/github.js +51 -1
  23. package/dist/engine/github/github.js.map +1 -1
  24. package/dist/engine/github/review-poster.d.ts +98 -0
  25. package/dist/engine/github/review-poster.js +177 -0
  26. package/dist/engine/github/review-poster.js.map +1 -0
  27. package/dist/engine/router.js +8 -4
  28. package/dist/engine/router.js.map +1 -1
  29. package/dist/engine/screen/classifier.js +8 -3
  30. package/dist/engine/screen/classifier.js.map +1 -1
  31. package/dist/workflows/phase-executor.d.ts +24 -0
  32. package/dist/workflows/phase-executor.js +186 -0
  33. package/dist/workflows/phase-executor.js.map +1 -1
  34. package/dist/workflows/schema.d.ts +2 -0
  35. package/dist/workflows/schema.js +9 -1
  36. package/dist/workflows/schema.js.map +1 -1
  37. package/package.json +1 -1
  38. package/plugins/lastlight/.claude-plugin/plugin.json +12 -3
  39. package/plugins/lastlight/skills/lastlight-evals/SKILL.md +9 -1
  40. package/skills/pr-review/SKILL.md +83 -33
  41. package/skills/pr-review/references/findings-schema.md +89 -0
  42. package/workflows/pr-review.yaml +21 -0
@@ -1,36 +1,42 @@
1
1
  ---
2
2
  name: pr-review
3
3
  description: Review a GitHub pull request and post one formal review — advance the existing discussion and give precision-first, high-signal feedback. A pure code review — no building. Use when asked to review a PR or on a cron PR scan.
4
- version: 5.0.0
4
+ version: 7.0.0
5
5
  tags: [github, review, code-quality]
6
6
  ---
7
7
 
8
8
  # PR Review
9
9
 
10
- Review an open PR and post **one formal review** — high-signal findings only.
11
- This is a **pure code review**: read the change and reason about it. Do **not**
12
- install dependencies, build, or run tests — that is CI's job, and it validates
13
- whether the change actually works far more reliably than you re-running it here.
14
- Your job is judgement on the diff, not a build gate. A noisy review gets muted,
15
- so precision matters more than volume.
10
+ Review an open PR — high-signal findings only. This is a **pure code review**:
11
+ read the change and reason about it. Do **not** install dependencies, build, or
12
+ run tests — that is CI's job, and it validates whether the change actually works
13
+ far more reliably than you re-running it here. Your job is judgement on the diff,
14
+ not a build gate. A noisy review gets muted, so precision matters more than
15
+ volume.
16
+
17
+ You do **not** post the review yourself. You write your findings to a JSON file
18
+ (`.lastlight/pr-review/findings.json`) and a deterministic follow-up step posts
19
+ one formal review, anchoring each finding to its diff line as an inline comment
20
+ (§4).
16
21
 
17
22
  This skill is the PR-specific procedure. It uses the **code-review** skill for
18
23
  the precision bar and what-to-check rubric.
19
24
 
20
25
  ## Workspace
21
26
 
22
- The harness pre-clones the PR's head ref into a `<repo>/` **subdirectory** of
23
- your cwd (the cwd holds `AGENTS.md`; the repo is one level deeper). `ls -la`
24
- if you see `<repo>/.git/`, `cd <repo>` and use git directly. To refresh:
27
+ The harness pre-clones the PR's head ref and drops you **inside the checkout**
28
+ your cwd **is** the repo (`ls -la` shows `.git/` directly; `AGENTS.md` is the
29
+ sibling one level up at `../`). Use `git`/`read`/`grep` from here. To refresh:
25
30
  `git fetch origin <branch> --depth 50 && git reset --hard FETCH_HEAD`. If the
26
- pre-clone is missing, `git clone https://github.com/{{owner}}/{{repo}}.git {{repo}}`.
31
+ checkout is somehow missing, `git clone https://github.com/{{owner}}/{{repo}}.git .`.
27
32
 
28
33
  **Read code from this local checkout, never the API.** Use `git`/`read`/`grep`
29
34
  on disk for the diff and file contents. Do **not** call
30
35
  `github_get_pull_request_diff`, `github_list_pull_request_files`, or
31
36
  `github_get_file_contents` — the API patch is a large redundant payload that
32
37
  re-bloats context every turn. The `github_*` tools are for *API* operations only
33
- (metadata, comments, posting the review).
38
+ (reading metadata + prior comments in §1–2). You never post the review via a
39
+ tool — you write the findings file and the follow-up step posts it.
34
40
 
35
41
  ## Procedure
36
42
 
@@ -66,33 +72,77 @@ git diff --stat origin/<baseRef>...HEAD # churn
66
72
  git diff origin/<baseRef>...HEAD # the patch
67
73
  ```
68
74
 
69
- ### 4. Assess and submit
75
+ ### 4. Assess and write your findings
70
76
 
71
77
  Apply the **code-review** skill's rubric — read each changed file in context;
72
78
  check correctness / edge-cases / security / regression-risk / test-coverage.
73
79
  Reason about the code statically; **don't build or run it** — trust CI to catch
74
80
  what only running reveals, and spend your effort on what a human reviewer sees.
75
- Follow that skill's **precision-first** rule: post **only Critical and Important**
76
- findings, each with a `path:line` reference and a one-line concrete impact (what
77
- breaks, for which input or caller) plus an inline code suggestion where it helps.
78
- Drop Suggestions and Nits.
79
-
80
- Before submitting, run the **confidence gate**: re-read each finding against the
81
- actual code and try to refute it; drop any you can't defend against what the code
82
- really does. A clean PR should be approved with few or no comments — that is a
83
- good review, not a lazy one.
84
-
85
- Then write the review:
86
-
87
- - One or two sentences on what the PR does.
88
- - The surviving Critical/Important findings, each with its `path:line` + impact.
89
- - For a complex PR, an impact note (affected paths, regression risks).
90
- - An overall assessment, and thanks to the contributor.
81
+ Follow that skill's **precision-first** rule: keep **only Critical and Important**
82
+ findings, each anchored to a `path:line` with a one-line concrete impact (what
83
+ breaks, for which input or caller). Drop Suggestions and Nits.
84
+
85
+ Before writing anything, run the **confidence gate**: re-read each finding
86
+ against the actual code and try to refute it; drop any you can't defend against
87
+ what the code really does. A clean PR should be approved with few or no
88
+ findings that is a good review, not a lazy one.
89
+
90
+ **Do not call `github_create_pull_request_review` (or any review-submitting
91
+ tool).** Write your findings to `.lastlight/pr-review/findings.json` instead. A
92
+ deterministic follow-up step reads that file and posts one formal review with
93
+ your findings as inline comments anchored to the diff. The full contract with
94
+ worked examples is in [references/findings-schema.md](references/findings-schema.md);
95
+ the shape is:
96
+
97
+ ```json
98
+ {
99
+ "skip": false,
100
+ "summary": "One or two sentences on what the PR does + overall assessment.",
101
+ "event": "COMMENT",
102
+ "findings": [
103
+ {
104
+ "path": "src/foo.ts",
105
+ "line": 42,
106
+ "side": "RIGHT",
107
+ "severity": "Critical",
108
+ "title": "Short label for the finding",
109
+ "body": "Concrete impact — what breaks, for which input or caller.",
110
+ "suggestion": "exact replacement text for the anchored line(s)"
111
+ }
112
+ ]
113
+ }
114
+ ```
91
115
 
92
- Submit with `github_create_pull_request_review` (a **formal** review, not a plain
93
- issue comment), event `APPROVE` / `REQUEST_CHANGES` / `COMMENT` to match what
94
- survived the gate.
116
+ Write **only these content fields** `skip?` / `summary` / `event` /
117
+ `findings[]`. The follow-up step already knows the PR number, base ref, head
118
+ SHA and diff from the harness's own context and the checkout, so you do **not**
119
+ record any of that metadata (that reliance was a footgun — omit it).
120
+
121
+ Rules:
122
+ - **Anchor precisely.** `path` must match the diff path exactly; `line`/`side`
123
+ must point at a line that appears in the diff (added/context → `side: RIGHT`;
124
+ removed/context → `side: LEFT`). A finding whose line isn't in the diff is
125
+ demoted to the summary body, so get the anchor right. Use optional `start_line`
126
+ (same side) for a multi-line range.
127
+ - `severity` is `Critical` or `Important` only.
128
+ - `suggestion` is optional — include it only when a concrete one-to-few-line fix
129
+ is obvious. It must be the exact replacement text for the anchored line(s),
130
+ nothing else; GitHub renders it as an applyable suggestion.
131
+ - `event` is `APPROVE` / `REQUEST_CHANGES` / `COMMENT`, matching what survived
132
+ the gate. A clean PR is an `APPROVE` with an empty `findings` array and a short
133
+ `summary`.
134
+ - Create the dir and keep the file out of git first:
135
+ `mkdir -p .lastlight/pr-review && echo '.lastlight/' >> .git/info/exclude`.
136
+
137
+ **Stop / skip:** if a stop condition in §1 holds (bot-authored, merged, already
138
+ reviewed at the current head SHA), write `{"skip": true, "summary": "<reason>"}`
139
+ and stop — the follow-up step then posts nothing.
95
140
 
96
141
  ## Verification
97
142
 
98
- Confirm the review posted by checking the PR's reviews list.
143
+ Confirm `.lastlight/pr-review/findings.json` is valid JSON and every finding
144
+ carries `path` + `line`. The first-class `post-review` action then posts the
145
+ review — anchoring each finding to its diff line, demoting any off-diff finding
146
+ to the body, and logging how many landed inline vs in the body. If the file is
147
+ missing after a real review (not a `skip`), that step **fails the run** loudly
148
+ rather than posting nothing.
@@ -0,0 +1,89 @@
1
+ # PR review findings schema
2
+
3
+ The `pr-review` skill writes its findings to `.lastlight/pr-review/findings.json`
4
+ (relative to the repo checkout — your cwd). The first-class `post-review` action
5
+ reads this file and posts **one** formal GitHub review:
6
+
7
+ - Each finding whose `line`/`side` anchors to a line that appears in the PR diff
8
+ becomes an **inline comment** on that exact line.
9
+ - Any finding whose anchor isn't in the diff is **demoted** into the review body
10
+ under an "Additional findings" heading (GitHub rejects comments off the diff).
11
+ - If the diff can't be computed (git failure), **all** findings go into the
12
+ body — the review still posts, so nothing is lost.
13
+
14
+ You write only the review **content** — `skip?` / `summary` / `event` /
15
+ `findings[]`. The PR number, base ref, head SHA and diff come from the harness's
16
+ own run context and the checkout, so you do **not** record any of that metadata.
17
+ You never call `github_create_pull_request_review` yourself; writing this file is
18
+ how you submit.
19
+
20
+ ## Top-level object
21
+
22
+ | Field | Type | Required | Meaning |
23
+ |---|---|---|---|
24
+ | `skip` | boolean | no | `true` → you decided not to review (bot-authored / merged / already reviewed at head). The action posts nothing. |
25
+ | `summary` | string | yes | One or two sentences on what the PR does + your overall assessment. Becomes the review body. |
26
+ | `event` | string | yes | `APPROVE` \| `REQUEST_CHANGES` \| `COMMENT`. A clean PR is `APPROVE` with an empty `findings` array. |
27
+ | `findings` | array | yes | The surviving Critical/Important findings (may be empty). |
28
+
29
+ ## Finding object
30
+
31
+ | Field | Type | Required | Meaning |
32
+ |---|---|---|---|
33
+ | `path` | string | yes | Repo-relative file path, matching the diff path exactly. |
34
+ | `line` | number | yes | Line number on `side` that the comment anchors to. Must appear in the diff. |
35
+ | `side` | string | no | `RIGHT` (added/context line — default) or `LEFT` (removed/context line). |
36
+ | `start_line` | number | no | Start of a multi-line range (same `side` as `line`). |
37
+ | `severity` | string | yes | `Critical` or `Important` only. |
38
+ | `title` | string | yes | Short label for the finding. |
39
+ | `body` | string | yes | Concrete impact — what breaks, for which input or caller. |
40
+ | `suggestion` | string | no | Exact replacement text for the anchored line(s). Rendered as an applyable ```suggestion block. Include only when a concrete one-to-few-line fix is obvious. |
41
+
42
+ ## Example — findings with an inline suggestion
43
+
44
+ ```json
45
+ {
46
+ "skip": false,
47
+ "summary": "Adds a `--config` flag to the CLI and threads it into the connect path. Solid overall; one crash on the default path and one missing-await.",
48
+ "event": "REQUEST_CHANGES",
49
+ "findings": [
50
+ {
51
+ "path": "src/cli.ts",
52
+ "line": 42,
53
+ "side": "RIGHT",
54
+ "severity": "Critical",
55
+ "title": "Null deref when --config is omitted",
56
+ "body": "`cfg.host` is undefined when no config file is passed, so every default-path invocation throws before connecting.",
57
+ "suggestion": "const host = cfg.host ?? DEFAULT_HOST;"
58
+ },
59
+ {
60
+ "path": "src/connect.ts",
61
+ "line": 88,
62
+ "side": "RIGHT",
63
+ "severity": "Important",
64
+ "title": "Missing await on disconnect()",
65
+ "body": "`disconnect()` returns a promise that's never awaited, so the socket can leak if the caller exits immediately after."
66
+ }
67
+ ]
68
+ }
69
+ ```
70
+
71
+ ## Example — clean PR (approve, no findings)
72
+
73
+ ```json
74
+ {
75
+ "skip": false,
76
+ "summary": "Small, well-tested refactor of the retry helper. No correctness or regression concerns.",
77
+ "event": "APPROVE",
78
+ "findings": []
79
+ }
80
+ ```
81
+
82
+ ## Example — skip (already reviewed this SHA)
83
+
84
+ ```json
85
+ {
86
+ "skip": true,
87
+ "summary": "A last-light[bot] review already exists on the current head SHA; nothing new to add."
88
+ }
89
+ ```
@@ -16,6 +16,27 @@ phases:
16
16
  # pr-review: the PR procedure (primary). code-review: the finding-tier +
17
17
  # what-to-check rubric. No `building` — pr-review is a pure code review; CI
18
18
  # validates that the change builds/runs.
19
+ #
20
+ # The agent does NOT submit the review itself — it writes structured
21
+ # findings (content only: skip? / summary / event / findings[]) to
22
+ # .lastlight/pr-review/findings.json. The first-class `post-review` action
23
+ # below reads that file and posts one formal review.
19
24
  skills: [pr-review, code-review]
20
25
  model: "{{models.review}}"
21
26
  variant: "{{variants.review}}"
27
+
28
+ # First-class, in-process submission (type: post-review → PhaseExecutor.
29
+ # runPostReview). Reads the agent's findings.json for the review *content*
30
+ # (skip? / summary / event / findings[]) and supplies everything else from
31
+ # the harness itself — PR number (run context), base ref (baseBranch), head
32
+ # SHA + diff (the pre-cloned checkout) — so the AI never hand-copies metadata.
33
+ # It anchors each finding to a changed line, demotes off-diff findings to the
34
+ # body (GitHub 422s on off-diff lines), and posts ONE review via GitHubClient
35
+ # (App auth in prod; token + githubApiBaseUrl against the eval mock). A
36
+ # genuine failure — missing findings after a real review, or a GitHub error
37
+ # that survives the body-only retry — FAILS this phase visibly; a legitimate
38
+ # `skip` succeeds without posting. Idempotent on resume (no-op if a bot review
39
+ # already exists on the head SHA).
40
+ - name: post-review
41
+ label: Post inline review
42
+ type: post-review