lastlight 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lastlight",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "GitHub repository maintenance agent — Agent SDK harness",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin.json",
3
3
  "name": "lastlight",
4
4
  "displayName": "Last Light",
5
- "version": "0.8.0",
5
+ "version": "0.9.0",
6
6
  "description": "Install, configure and operate Last Light (GitHub maintenance agent) — its server, CLI client, deployment overlay, and the Last Light Evals harness.",
7
7
  "author": {
8
8
  "name": "Clifton Cunningham"
@@ -18,6 +18,7 @@ Light's *internal* sandbox skills under the repo's top-level `skills/` dir
18
18
  | `lastlight-client` | Point the `lastlight` **CLI client** at an existing server and log in. |
19
19
  | `lastlight-overlay` | Create a deployment **overlay** instance and fork/customize workflows, prompts, skills, or the agent persona. |
20
20
  | `lastlight-evals` | Scaffold and run a **Last Light Evals** workspace (datasets, models, model comparisons). |
21
+ | `lastlight-evals-loop` | **Drive an eval toward a target score** with a disciplined, anti-gaming improvement loop — diagnose on a train split, validate on a blind held-out split, propose one generic fix at a time. |
21
22
 
22
23
  ## Install
23
24
 
@@ -28,6 +28,7 @@ they want, then go:
28
28
  | Author one case from a GitHub PR or issue | **§6** |
29
29
  | **Build a PR-review dataset from my own gold PRs** | **§6 → "Build a PR-review dataset"** |
30
30
  | Add cases by hand / understand the schema | **§5** + `references/instance-schema.md` |
31
+ | **Iteratively improve the score toward a target** | the **`lastlight-evals-loop`** skill |
31
32
 
32
33
  New to the whole plugin (server / overlay / client, not just evals)? That's the
33
34
  **`lastlight-guide`** skill — this one is evals-only.
@@ -123,6 +124,7 @@ lastlight-evals run pr-review --limit 3 # only the first 3 cases of the
123
124
  lastlight-evals run triage --instance <id[,id2]> # only these exact instance_id(s), comma-separated (or set EVAL_INSTANCE)
124
125
  lastlight-evals run pr-review --f-beta 0.5 # pr-review F-beta β (default 1=F1; 0.5=precision 2×). Or EVAL_F_BETA
125
126
  lastlight-evals run pr-review --judge-with-diff # feed the PR diff to the judge (higher fidelity; off by default)
127
+ lastlight-evals run pr-review --no-inject-context # DON'T inject synthetic repo-context into the checkout (clean A/B control)
126
128
  lastlight-evals run pr-review --sandbox gondolin # isolate the agent's tools in a QEMU micro-VM (anti-spoil). Or EVAL_SANDBOX
127
129
  lastlight-evals run triage --no-open # don't open the report
128
130
  # Plain layout: add --overlay . (e.g. lastlight-evals run triage --overlay .)
@@ -168,6 +170,15 @@ Quick shape (paths are relative to the workspace's `evals/` dir):
168
170
  with `add-case --pr <url> --review` (see §6 and
169
171
  **`references/authoring-pr-review.md`**). Grading needs a judge model
170
172
  (`EVAL_JUDGE_MODEL`, else a strong default per provider key).
173
+ - **Repo-context injection (pr-review).** The harness can drop a synthetic
174
+ `AGENTS.md`/`CLAUDE.md` into the checked-out repo so the reviewing agent reads
175
+ it — a **generic** block from `<overlay>/repo-context/AGENTS.md` (every repo)
176
+ plus a **per-repo** block from `datasets/pr-review/context/<instance_id>/AGENTS.md`.
177
+ Presence-based (just create the file), on by default; `--no-inject-context`
178
+ (or `EVAL_INJECT_CONTEXT=0`) forces a clean control for an A/B. It appends to
179
+ a real `AGENTS.md`/`CLAUDE.md` if the repo ships one (never shadowing it). This
180
+ is how you prove *"adding this to your repo improves review quality"* — and the
181
+ lever the **`lastlight-evals-loop`** skill drives.
171
182
  - **Custom tier:** a new `evals/datasets/<tier>/` with `tier.json` +
172
183
  `instances.json` (+ `repos/` & `tests/` for code-fix-style tiers). Discovery is
173
184
  automatic — no code change.
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: lastlight-evals-loop
3
+ description: Drive a Last Light EVAL toward a target score with a disciplined, anti-gaming improvement loop — run → diagnose → propose ONE generic fix → re-measure → keep or revert → repeat. Use when the user wants to "improve / raise the pr-review F1", "make the reviewer better against the eval", "close the loop on evals", "iterate on prompts/skills to pass more cases", or "tune the workflow to hit a score target". The loop diagnoses on a TRAIN split and validates on a BLIND held-out split so fixes must generalize, not overfit; it prefers generic overlay prompt/skill edits, and stops for human sign-off before editing any gold answer. For a one-off run/compare use lastlight-evals; to hand-fork a workflow/prompt use lastlight-overlay. Needs an already-scaffolded evals workspace (lastlight-evals) with a pr-review dataset.
4
+ version: 1.0.0
5
+ tags: [lastlight, evals, loop, improvement, overfitting, pr-review]
6
+ ---
7
+
8
+ # Improve an eval, honestly
9
+
10
+ A loop that raises an eval score **without gaming it**. The trap: the loop can see
11
+ both the gold answer and the agent's answer for every case, so it could overfit —
12
+ hardcode a repo's finding into a prompt, or edit a gold answer to force a pass.
13
+ That lifts the number and ruins the reviewer. Every guardrail here exists to force
14
+ **generic, cross-cutting** changes that would help on repos the loop has never seen.
15
+
16
+ Scope: the **pr-review** tier (its judge trace gives you the agent-vs-gold detail
17
+ diagnosis needs). The pattern extends to triage/code-fix, but start here.
18
+
19
+ ## Prerequisites
20
+
21
+ - A scaffolded evals workspace with a **pr-review** dataset and a working provider
22
+ key — set up via **`lastlight-evals`** first if you don't have one. Confirm a
23
+ bare `lastlight-evals run pr-review --limit 1 --no-open` grades a case.
24
+ - An **`instance/` overlay** (the deployment overlay) to receive generic edits —
25
+ see **`lastlight-overlay`**. The loop edits copies here, never core.
26
+ - The `diff-runs.ts` helper ships with the evals package
27
+ (`scripts/diff-runs.ts`) — it compares two runs and calls keep/revert.
28
+
29
+ ## The one rule
30
+
31
+ **One change per iteration.** Propose a single hypothesis, measure its effect in
32
+ isolation, keep or revert, then move on. No batching — batching hides which edit
33
+ moved the number and invites scattershot overfitting.
34
+
35
+ ## Start here
36
+
37
+ | You have… | Go to |
38
+ |---|---|
39
+ | Never run this loop on this dataset | **§1 Set up the split** then §2 |
40
+ | A split + baseline already recorded | **§3 Diagnose** |
41
+ | A proposed change ready to test | **§5 Audit → §6 Apply → §7 Measure → §8 Decide** |
42
+
43
+ ## 1. Set up the split (once per dataset)
44
+
45
+ Split the tier's `instance_id`s into **TRAIN** (you diagnose on these — traces
46
+ visible) and **HELD-OUT** (blind — you NEVER read their traces; only their
47
+ aggregate F1 gates a keep). ~70/30, deterministic (sort ids, take the first 70%
48
+ as train). Record both lists at the top of the journal (§9) — they must stay
49
+ fixed across the whole loop, or the held-out gate means nothing.
50
+
51
+ ```bash
52
+ # list the ids (jq over instances.json), then split deterministically
53
+ lastlight-evals run pr-review --instance <all-ids> --no-open # or omit --instance for the whole tier
54
+ ```
55
+
56
+ Set a **target**: an F1 goal (e.g. 0.55) or "improve until plateau" (N=3
57
+ consecutive no-keep iterations).
58
+
59
+ ## 2. Baseline
60
+
61
+ Run both splits and record `avgFbeta` for each in the journal. Use the cheapest
62
+ adequate model while iterating on prompts; switch to the real target model only to
63
+ confirm a kept change.
64
+
65
+ ```bash
66
+ lastlight-evals run pr-review --overlay instance --instance <train-ids> --no-open
67
+ lastlight-evals run pr-review --overlay instance --instance <heldout-ids> --no-open
68
+ ```
69
+
70
+ Each writes `eval-results/pr-review/<runId>/scorecard.json`. Note the two runIds.
71
+
72
+ ## 3. Diagnose (TRAIN only)
73
+
74
+ Read the TRAIN scorecard's `results[].review` and `review.trace`. **Do not open
75
+ held-out traces.** For each failing case:
76
+ - `falseNegatives` (with `severity`) = **recall** loss — real issues the agent missed.
77
+ - `falsePositives` = **precision** loss — noise the agent posted that matched no gold.
78
+
79
+ Cluster across cases and name the **systematic pattern** — not a one-off. Good
80
+ patterns generalize: *"misses security-relevant findings"*, *"posts style nits the
81
+ rubric says to suppress"*, *"confidence bar too low → noise"*, *"no awareness of the
82
+ repo's conventions → wrong-fit findings"*. See **references/levers.md** for how
83
+ each pattern maps to an edit.
84
+
85
+ ## 4. Hypothesis — ONE change, lowest lever first
86
+
87
+ Pick the **lowest** lever that could move the whole cluster (full detail in
88
+ **references/levers.md**):
89
+
90
+ - **(a) generic — auto.** Edit an overlay prompt/skill/persona, or add a generic
91
+ `instance/repo-context/AGENTS.md` injected into every repo. Must be general.
92
+ - **(b) per-repo context — signed-off.** A `datasets/pr-review/context/<id>/AGENTS.md`
93
+ the harness injects only for that repo — the portable *"add this to your repo"*
94
+ finding. Human approves before writing.
95
+ - **(c) the eval itself — rare, signed-off.** Edit `review_gold[]` ONLY when the
96
+ gold is demonstrably wrong/incomplete; name the evidence. Human approves.
97
+
98
+ Escalate only when a lower lever genuinely can't address the pattern, and write
99
+ down why.
100
+
101
+ ## 5. Audit the change (adversarial sub-agent)
102
+
103
+ Before applying, spawn a **generality + leak auditor** sub-agent (prompt template
104
+ in **references/guardrails.md**). It **REJECTS** if the change:
105
+ - names a specific repo / `instance_id` / file path (lever a must be generic), or
106
+ - **encodes the gold answer** — injected repo context that describes the specific
107
+ findings is cheating. It must read as plausible maintainer guidance written
108
+ *without* knowledge of this PR's bug (conventions, architecture, review
109
+ priorities), never "look for bug X".
110
+
111
+ Rejected → back to §4.
112
+
113
+ ## 6. Apply (hybrid autonomy)
114
+
115
+ - **Lever (a)** (incl. generic `repo-context/AGENTS.md`): apply automatically to
116
+ `instance/…` once the auditor passes.
117
+ - **Lever (b)/(c)**: **STOP.** Present the diff + the written justification and ask
118
+ the human to approve before writing to the dataset.
119
+
120
+ ## 7. Re-measure
121
+
122
+ Re-run both splits (§2) with the change, then diff against the baseline:
123
+
124
+ ```bash
125
+ npx tsx scripts/diff-runs.ts <baseline-train.json> <candidate-train.json> \
126
+ --train <train-ids> --heldout <heldout-ids>
127
+ ```
128
+
129
+ Point it at the run pair that covers both splits (or run the two splits in one
130
+ `--instance <all-ids>` run so a single scorecard holds both). It prints per-case
131
+ F1 deltas, the arm-summary delta, and a **KEEP / REVERT verdict**.
132
+
133
+ ## 8. Decide
134
+
135
+ - **KEEP** iff train F1 improved **and** held-out did **not** regress (the helper's
136
+ verdict). Train ↑ with held-out ↓ = **overfit → revert**.
137
+ - **Lever (b)** per-repo edits are case-scoped: keep iff that case improved, the
138
+ auditor passed, and the human approved — recorded as a per-repo recommendation,
139
+ not a workflow change (no held-out claim is made for it).
140
+ - Else **REVERT**: `git checkout` the overlay file, or remove the sidecar.
141
+
142
+ ## 9. Journal, then repeat
143
+
144
+ Append one entry per iteration (schema in **references/journal-format.md**):
145
+ pattern, lever, the diff/context, auditor verdict, train Δ, held-out Δ, decision,
146
+ running best. Then return to §3. Stop at the target or the plateau.
147
+
148
+ Run the loop on a cadence with the built-in `/loop` if you want it to keep going
149
+ unattended between your check-ins — but the lever-(b)/(c) sign-off stops still
150
+ apply.
151
+
152
+ ## Done when
153
+
154
+ The target F1 is reached or the loop plateaus, the journal records every
155
+ hypothesis and its train/held-out deltas, kept changes live in `instance/` (and,
156
+ with sign-off, per-repo `context/` sidecars), and **no** change was kept that
157
+ regressed the blind held-out set. Report: baseline → final F1 (train and
158
+ held-out), the kept changes, any per-repo recommendations, and anything that
159
+ needed human sign-off.
@@ -0,0 +1,86 @@
1
+ # Guardrails — keeping the loop honest
2
+
3
+ The loop sees the gold answer and the agent's answer, so it *could* game the score.
4
+ These guardrails make that hard and, where it isn't automatable, put a human in the
5
+ way. None is optional.
6
+
7
+ ## 1. Held-out split (empirical anti-overfit gate)
8
+
9
+ Diagnose on TRAIN; validate on a BLIND HELD-OUT split whose traces you never read.
10
+ A generic (lever a) change is kept only if **train F1 improves AND held-out F1 does
11
+ not regress** beyond a small epsilon. A train gain with a held-out regression is
12
+ overfitting — revert it. `scripts/diff-runs.ts` computes this verdict for you; do
13
+ not override it by eyeballing train alone.
14
+
15
+ The split ids are fixed for the whole loop. If you re-split (e.g. to add cases),
16
+ say so in the journal and treat prior held-out results as no longer comparable.
17
+
18
+ ## 2. One change per iteration
19
+
20
+ Isolates causal effect. If two edits ship together and the number moves, you can't
21
+ attribute it — and you can't tell an overfit edit riding along with a good one.
22
+
23
+ ## 3. The generality + leak auditor (adversarial sub-agent)
24
+
25
+ Before applying ANY change, spawn a fresh sub-agent to try to reject it. It is
26
+ adversarial on purpose — its job is to find the reason this is gaming, not to
27
+ approve. Give it the diff (or the injected-context text), the diagnosed pattern,
28
+ and this instruction:
29
+
30
+ > You are auditing a proposed change to a code-review agent that is being tuned
31
+ > against an eval. Your job is to REJECT changes that game the eval instead of
32
+ > genuinely improving the reviewer. Default to REJECT when unsure.
33
+ >
34
+ > REJECT if the change:
35
+ > 1. names or targets a specific repository, `instance_id`, file path, function,
36
+ > or PR — a generic prompt/skill/persona edit (lever a) must apply to any repo;
37
+ > 2. encodes the eval's gold answer — e.g. injected repo context or a prompt that
38
+ > describes the specific findings the agent is "supposed to" make. Injected
39
+ > repo context must read as plausible standing maintainer guidance written
40
+ > WITHOUT knowledge of this PR's bug (conventions, architecture, review
41
+ > priorities), never "check for <the specific issue>";
42
+ > 3. hard-codes an answer, a magic string, or a case count to pass a known case;
43
+ > 4. (for a gold/eval edit) lacks concrete evidence that the existing gold is
44
+ > wrong — "it makes a case pass" is not evidence.
45
+ >
46
+ > Otherwise ACCEPT. Reply with a verdict (ACCEPT/REJECT) and a one-line reason.
47
+
48
+ A REJECT sends you back to reformulating a more general change. Record the verdict
49
+ either way.
50
+
51
+ ## 4. The lever ladder + sign-off
52
+
53
+ Generic (a) edits auto-apply once the auditor passes. Per-repo context (b) and any
54
+ gold/PR-text edit (c) **stop for human sign-off** with a written justification —
55
+ they are the game-able levers, so a human always ratifies them. Never edit
56
+ `review_gold` to make a failing case pass; only when the gold is demonstrably wrong.
57
+
58
+ ## 5. Never touch core
59
+
60
+ Edits live in `instance/` (overlay) and, with sign-off, dataset sidecars / gold.
61
+ Core workflow code is never modified — the whole value of the harness is that the
62
+ *real* workflow runs. If a fix seems to require a core change, it's out of scope
63
+ for the loop; note it for the maintainers instead.
64
+
65
+ ## 6. Auditable journal + provenance
66
+
67
+ Every hypothesis → diff → train/held-out deltas → decision is recorded
68
+ (references/journal-format.md), and every run records which injected context it saw
69
+ (`injectedContext` on each result). A reviewer can reconstruct exactly what changed
70
+ and why the number moved — no silent wins.
71
+
72
+ ## The keep/revert decision, precisely
73
+
74
+ ```
75
+ lever (a) generic:
76
+ KEEP iff trainΔ > epsilon AND heldoutΔ >= -epsilon (else REVERT)
77
+ lever (b) per-repo:
78
+ KEEP iff that case improved AND auditor ACCEPTED AND human approved
79
+ (recorded as a per-repo recommendation; no held-out claim)
80
+ lever (c) gold/eval:
81
+ APPLY iff auditor ACCEPTED AND human approved AND evidence recorded
82
+ (this changes what "correct" means — it's a dataset fix, not a score win)
83
+ ```
84
+
85
+ If a split is missing (e.g. you forgot to run held-out), the helper says
86
+ INCONCLUSIVE / REVIEW rather than KEEP — don't keep on train alone.
@@ -0,0 +1,54 @@
1
+ # Journal format — the auditable ledger
2
+
3
+ The loop appends one entry per iteration to a single Markdown file, by default
4
+ `eval-results/loop-journal.md` in the workspace (next to the runs it references).
5
+ It is the record that lets a human reconstruct every change and why the score
6
+ moved — keep it complete even for reverted iterations (a revert is a result).
7
+
8
+ ## Header (write once, at the top)
9
+
10
+ ```markdown
11
+ # pr-review improvement loop
12
+
13
+ - Model under test: anthropic/claude-sonnet-5 (iterating cheap: haiku)
14
+ - Judge model: <EVAL_JUDGE_MODEL or default>
15
+ - Target: F1 >= 0.55 (or: improve until 3 consecutive no-keep iterations)
16
+ - Split (FIXED for this loop):
17
+ - TRAIN (n): id1, id2, id3, ...
18
+ - HELDOUT (n): idA, idB, ...
19
+ - Baseline: train F1 = 0.33, heldout F1 = 0.31 (runIds: <train>, <heldout>)
20
+ ```
21
+
22
+ ## Per-iteration entry
23
+
24
+ ```markdown
25
+ ## Iteration <N> — <one-line hypothesis>
26
+
27
+ - Pattern: <the systematic failure named in §3, e.g. "posts style nits the rubric suppresses (precision loss across 4 train cases)">
28
+ - Lever: (a) generic | (b) per-repo | (c) gold — <why this lever; why not lower>
29
+ - Change:
30
+ file: instance/skills/code-review/SKILL.md
31
+ diff: |
32
+ <the actual diff, or the injected-context text>
33
+ - Auditor: ACCEPT | REJECT — <one-line reason>
34
+ - Applied: auto | human-approved (<who/when>) | not applied (auditor rejected)
35
+ - Result (diff-runs.ts):
36
+ train: 0.33 -> 0.41 (Δ +0.08)
37
+ heldout: 0.31 -> 0.31 (Δ +0.00)
38
+ per-case regressions: 0
39
+ - Decision: KEEP | REVERT | (b) recorded as per-repo recommendation
40
+ - Running best: train F1 = 0.41, heldout F1 = 0.31
41
+ ```
42
+
43
+ ## Rules
44
+
45
+ - **One entry per iteration**, including reverts and auditor rejections — the tail
46
+ of no-keep iterations is the plateau signal.
47
+ - Paste the **actual diff / context text**, not a paraphrase — the point is
48
+ reproducibility.
49
+ - Always record **both** train and held-out deltas. A missing held-out number
50
+ means the decision is INCONCLUSIVE, not KEEP.
51
+ - For lever (b)/(c), record the **human sign-off** and, for (c), the **evidence**
52
+ that the gold was wrong.
53
+ - Keep the **Running best** line current — it's the at-a-glance progress toward
54
+ the target and the input to the plateau check.
@@ -0,0 +1,80 @@
1
+ # The three levers — what to edit, and the escalation ladder
2
+
3
+ All three levers change eval outcomes **without touching core** — the real
4
+ production workflow always runs unmodified. You only edit the deployment overlay
5
+ (`instance/`) and, with sign-off, the dataset. Prefer the lowest lever that can
6
+ move the whole failure cluster; escalate only with a written reason.
7
+
8
+ ## Pattern → lever map
9
+
10
+ | Diagnosed pattern (from TRAIN traces) | Most likely lever |
11
+ |---|---|
12
+ | Posts noise / nits the rubric says to suppress (precision loss) | (a) tighten the severity/precision bar in `code-review` skill |
13
+ | Misses a whole class of real issues, e.g. security, concurrency (recall loss) | (a) add that class to the reviewer's what-to-check rubric/prompt |
14
+ | Reviews against the wrong conventions for a repo | (a) generic repo-context, or (b) per-repo context |
15
+ | Wrong-fit findings because it lacks a repo's build/test/domain norms | (b) per-repo `AGENTS.md` (a portable recommendation) |
16
+ | A gold comment is a non-actionable nit, or a clear real finding scores as a false positive because gold omits it | (c) fix the gold — rare, evidence required |
17
+
18
+ ## (a) Prompts / skills / persona + generic repo-context — *generic, auto*
19
+
20
+ The preferred lever. A change here must generalize to every repo. Edit copies in
21
+ the overlay (fork with `lastlight fork <workflow>` / `lastlight fork agent-context`,
22
+ or create the shadowing file at the same logical path — see the **lastlight-overlay**
23
+ skill). Common targets:
24
+
25
+ - `instance/skills/code-review/SKILL.md` — the severity rubric + precision bar
26
+ (what findings survive). The highest-leverage file for precision problems.
27
+ - `instance/skills/pr-review/SKILL.md` — the review procedure (confidence gate,
28
+ findings-file contract).
29
+ - `instance/workflows/prompts/reviewer.md` — the reviewer prompt text.
30
+ - `instance/workflows/pr-review.yaml` — phase wiring (which skills a phase loads).
31
+ - `instance/agent-context/rules.md` / `soul.md` — global persona/rules the agent
32
+ reads via the workspace `AGENTS.md`.
33
+ - `instance/repo-context/AGENTS.md` — **generic** synthetic repo context the
34
+ harness injects into *every* seeded pr-review repo. Use for guidance that would
35
+ help a reviewer on any codebase (e.g. "prefer concrete, line-anchored findings;
36
+ suppress pure style nits"). Held-out gates a keep, so it must genuinely
37
+ generalize.
38
+
39
+ ## (b) Per-repo injected context — *portable finding, signed-off*
40
+
41
+ A dataset sidecar the harness injects **only for that case's repo**:
42
+
43
+ ```
44
+ datasets/pr-review/context/<instance_id>/AGENTS.md (or CLAUDE.md)
45
+ ```
46
+
47
+ This is the *"add this to your repo and your reviews improve by X"* recommendation
48
+ — honest because it's exactly what a maintainer could commit. It is **case-scoped**,
49
+ so the held-out generalization gate doesn't apply; instead it needs human sign-off
50
+ and must pass the no-gold-leak auditor (it must NOT describe this PR's specific
51
+ findings — only standing repo conventions, architecture, and review priorities).
52
+
53
+ How injection works (so you can trust it lands): the harness writes the block into
54
+ the file the agent's runtime actually reads — it appends to an existing
55
+ `AGENTS.md`, else an existing `CLAUDE.md` (never creating an `AGENTS.md` that would
56
+ shadow it), else creates a fresh `AGENTS.md`. Pi auto-loads that file walking up
57
+ from the agent's cwd, so it reaches the model every phase with no prompt change.
58
+ Toggle off for a clean control run with `--no-inject-context` (or
59
+ `EVAL_INJECT_CONTEXT=0`). Provenance is recorded on each result
60
+ (`injectedContext`).
61
+
62
+ ## (c) The eval itself — *rare, signed-off*
63
+
64
+ Edit the case in `datasets/pr-review/instances.json`:
65
+
66
+ - `review_gold[]` (`{ file?, line?, severity, description }`) — the correct answer.
67
+ - `pr.body` / `problem_statement` — what the agent is told about the PR.
68
+
69
+ Only when the gold is **demonstrably wrong or incomplete** — never to force a
70
+ failing case to pass. The justification must name the evidence (e.g. "the human
71
+ PR review made this exact point; gold omitted it, so a correct finding scored as a
72
+ false positive"). Martian's gold set is known-incomplete by design, so a
73
+ real-but-unlisted finding scoring as a false positive is expected — that is *not*
74
+ on its own grounds to edit gold; it's why the headline metric is F1, not F0.5.
75
+
76
+ ## Escalation ladder
77
+
78
+ Try (a) first. Escalate to (b) only when the pattern is genuinely repo-specific
79
+ (a convention that doesn't generalize). Escalate to (c) only when the eval is
80
+ wrong. Record the reason for every escalation in the journal.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lastlight-guide
3
- description: Orientation & router for the Last Light skills. Use ONLY when the user has NOT named a concrete Last Light task — i.e. they're unsure which skill/flow they need, ask "what can Last Light do / where do I start", say "help me with Last Light" with no specific goal, or want a guided tour across server / client / overlay / evals. Do NOT use when the ask already names a task — "set up/deploy a server" → lastlight-server, "connect/log in my CLI" → lastlight-client, "customize a workflow/prompt/persona/config" → lastlight-overlay, "run evals / compare models / author a case / build a PR-review dataset" → lastlight-evals: invoke that skill directly. This skill only routes and, when the goal is ambiguous, asks. Also invocable as /lastlight-guide.
3
+ description: Orientation & router for the Last Light skills. Use ONLY when the user has NOT named a concrete Last Light task — i.e. they're unsure which skill/flow they need, ask "what can Last Light do / where do I start", say "help me with Last Light" with no specific goal, or want a guided tour across server / client / overlay / evals. Do NOT use when the ask already names a task — "set up/deploy a server" → lastlight-server, "connect/log in my CLI" → lastlight-client, "customize a workflow/prompt/persona/config" → lastlight-overlay, "run evals / compare models / author a case / build a PR-review dataset" → lastlight-evals, "iteratively improve an eval toward a target score" → lastlight-evals-loop: invoke that skill directly. This skill only routes and, when the goal is ambiguous, asks. Also invocable as /lastlight-guide.
4
4
  version: 1.0.0
5
5
  tags: [lastlight, guide, router, orientation, help]
6
6
  ---
@@ -66,6 +66,11 @@ exactly what you ship. The loop that ties it together:
66
66
  > customize in **`lastlight-overlay`** → measure the change with
67
67
  > **`lastlight-evals --overlay .`** → keep it or revert.
68
68
 
69
+ To run that loop *toward a target score* — automatically, and without overfitting
70
+ to specific cases — use **`lastlight-evals-loop`**: it diagnoses on a train split,
71
+ validates on a blind held-out split, and proposes one generic overlay fix at a
72
+ time (stopping for sign-off before it touches a gold answer).
73
+
69
74
  ## Quick menu — "I want to…"
70
75
 
71
76
  | …do this | go to |
@@ -76,6 +81,7 @@ exactly what you ship. The loop that ties it together:
76
81
  | Run evals, compare models, browse past runs | **`lastlight-evals`** |
77
82
  | Author an eval case from a GitHub PR or issue | **`lastlight-evals`** (§6) |
78
83
  | Build a PR-review eval dataset from a list of gold PRs | **`lastlight-evals`** (§6) |
84
+ | Iteratively improve a workflow/prompt to raise an eval score | **`lastlight-evals-loop`** |
79
85
 
80
86
  ## Preconditions (what every flow assumes)
81
87