lastlight-evals 0.7.30 → 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/README.md +38 -1
- package/datasets/dependency-merge/README.md +69 -0
- package/datasets/dependency-merge/instances.json +168 -0
- package/datasets/dependency-merge/tier.json +5 -0
- package/datasets/fix/README.md +57 -0
- package/datasets/fix/instances.json +229 -0
- package/datasets/fix/repos/fix__env-mismatch-node-version/.github/workflows/ci.yml +15 -0
- package/datasets/fix/repos/fix__env-mismatch-node-version/README.md +3 -0
- package/datasets/fix/repos/fix__env-mismatch-node-version/package.json +15 -0
- package/datasets/fix/repos/fix__env-mismatch-node-version/src/group.js +4 -0
- package/datasets/fix/repos/fix__env-mismatch-node-version/test/group.test.js +9 -0
- package/datasets/fix/repos/fix__flaky-promoted/.github/workflows/ci.yml +15 -0
- package/datasets/fix/repos/fix__flaky-promoted/README.md +3 -0
- package/datasets/fix/repos/fix__flaky-promoted/package.json +12 -0
- package/datasets/fix/repos/fix__flaky-promoted/src/poll.js +9 -0
- package/datasets/fix/repos/fix__flaky-promoted/test/poll.test.js +8 -0
- package/datasets/fix/repos/fix__flaky-timeout/.github/workflows/ci.yml +15 -0
- package/datasets/fix/repos/fix__flaky-timeout/README.md +3 -0
- package/datasets/fix/repos/fix__flaky-timeout/package.json +12 -0
- package/datasets/fix/repos/fix__flaky-timeout/src/poll.js +9 -0
- package/datasets/fix/repos/fix__flaky-timeout/test/poll.test.js +8 -0
- package/datasets/fix/repos/fix__infra-dependent-e2e/.github/workflows/ci.yml +28 -0
- package/datasets/fix/repos/fix__infra-dependent-e2e/README.md +3 -0
- package/datasets/fix/repos/fix__infra-dependent-e2e/e2e/smoke.test.js +10 -0
- package/datasets/fix/repos/fix__infra-dependent-e2e/package.json +12 -0
- package/datasets/fix/repos/fix__infra-dependent-e2e/src/retry.js +13 -0
- package/datasets/fix/repos/fix__infra-dependent-e2e/test/retry.test.js +8 -0
- package/datasets/fix/repos/fix__reproducible-api-removal/.github/workflows/ci.yml +15 -0
- package/datasets/fix/repos/fix__reproducible-api-removal/README.md +3 -0
- package/datasets/fix/repos/fix__reproducible-api-removal/package.json +15 -0
- package/datasets/fix/repos/fix__reproducible-api-removal/src/slug.js +6 -0
- package/datasets/fix/repos/fix__reproducible-api-removal/test/slug.test.js +7 -0
- package/datasets/fix/repos/fix__reproducible-api-removal/vendor/tiny-case/index.js +4 -0
- package/datasets/fix/repos/fix__upstream-broken-base-red/.github/workflows/ci.yml +15 -0
- package/datasets/fix/repos/fix__upstream-broken-base-red/README.md +3 -0
- package/datasets/fix/repos/fix__upstream-broken-base-red/package.json +12 -0
- package/datasets/fix/repos/fix__upstream-broken-base-red/src/format.js +6 -0
- package/datasets/fix/repos/fix__upstream-broken-base-red/src/rates.js +6 -0
- package/datasets/fix/repos/fix__upstream-broken-base-red/test/format.test.js +7 -0
- package/datasets/fix/repos/fix__upstream-broken-base-red/test/rates.test.js +7 -0
- package/datasets/fix/repos-head/fix__env-mismatch-node-version/package.json +15 -0
- package/datasets/fix/repos-head/fix__flaky-promoted/package.json +12 -0
- package/datasets/fix/repos-head/fix__flaky-timeout/package.json +12 -0
- package/datasets/fix/repos-head/fix__infra-dependent-e2e/package.json +12 -0
- package/datasets/fix/repos-head/fix__reproducible-api-removal/package.json +15 -0
- package/datasets/fix/repos-head/fix__reproducible-api-removal/vendor/tiny-case/index.js +4 -0
- package/datasets/fix/repos-head/fix__upstream-broken-base-red/package.json +12 -0
- package/datasets/fix/tier.json +5 -0
- package/datasets/repo-config/instances.json +35 -0
- package/datasets/repo-config/lastlight/repoconfig__prompt-override/agent-context/repo-notes.md +9 -0
- package/datasets/repo-config/lastlight/repoconfig__prompt-override/lastlight.yml +22 -0
- package/datasets/repo-config/lastlight/repoconfig__prompt-override/workflows/prompts/answer.md +27 -0
- package/datasets/repo-config/tier.json +5 -0
- package/dist/fake-github.js +228 -5
- package/dist/fake-github.js.map +1 -1
- package/dist/grade.js +90 -1
- package/dist/grade.js.map +1 -1
- package/dist/mechanism.test.js +420 -2
- package/dist/mechanism.test.js.map +1 -1
- package/dist/pr-context.js +162 -0
- package/dist/pr-context.js.map +1 -0
- package/dist/repo-config.js +141 -0
- package/dist/repo-config.js.map +1 -0
- package/dist/run-instance.js +134 -7
- package/dist/run-instance.js.map +1 -1
- package/dist/run.js +8 -0
- package/dist/run.js.map +1 -1
- package/dist/schema.js +0 -13
- package/dist/schema.js.map +1 -1
- package/dist/seed.js +7 -0
- package/dist/seed.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Resolve once `check()` returns true, polling every `intervalMs`. */
|
|
2
|
+
export async function pollUntil(check, { intervalMs = 10, timeoutMs = 200 } = {}) {
|
|
3
|
+
const deadline = Date.now() + timeoutMs;
|
|
4
|
+
for (;;) {
|
|
5
|
+
if (await check()) return true;
|
|
6
|
+
if (Date.now() > deadline) throw new Error("pollUntil: timed out");
|
|
7
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Resolve once `check()` returns true, polling every `intervalMs`. */
|
|
2
|
+
export async function pollUntil(check, { intervalMs = 10, timeoutMs = 200 } = {}) {
|
|
3
|
+
const deadline = Date.now() + timeoutMs;
|
|
4
|
+
for (;;) {
|
|
5
|
+
if (await check()) return true;
|
|
6
|
+
if (Date.now() > deadline) throw new Error("pollUntil: timed out");
|
|
7
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: actions/setup-node@v4
|
|
13
|
+
with:
|
|
14
|
+
node-version: "22"
|
|
15
|
+
- run: npm test
|
|
16
|
+
|
|
17
|
+
e2e:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: "22"
|
|
24
|
+
# Needs the deployed staging API and its credentials.
|
|
25
|
+
- run: node --test e2e/
|
|
26
|
+
env:
|
|
27
|
+
STAGING_BASE_URL: ${{ secrets.STAGING_BASE_URL }}
|
|
28
|
+
STAGING_TOKEN: ${{ secrets.STAGING_TOKEN }}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
// Runs only in the `e2e` job, against the deployed staging API.
|
|
5
|
+
test("staging answers /health", async () => {
|
|
6
|
+
const base = process.env.STAGING_BASE_URL;
|
|
7
|
+
assert.ok(base, "STAGING_BASE_URL is not set");
|
|
8
|
+
const res = await fetch(new URL("/health", base));
|
|
9
|
+
assert.equal(res.status, 200);
|
|
10
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Retry `fn` up to `attempts` times with a fixed delay. */
|
|
2
|
+
export async function retry(fn, { attempts = 3, delayMs = 0 } = {}) {
|
|
3
|
+
let last;
|
|
4
|
+
for (let i = 0; i < attempts; i++) {
|
|
5
|
+
try {
|
|
6
|
+
return await fn();
|
|
7
|
+
} catch (err) {
|
|
8
|
+
last = err;
|
|
9
|
+
if (delayMs) await new Promise((r) => setTimeout(r, delayMs));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
throw last;
|
|
13
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { retry } from "../src/retry.js";
|
|
4
|
+
|
|
5
|
+
test("retries until it succeeds", async () => {
|
|
6
|
+
let n = 0;
|
|
7
|
+
assert.equal(await retry(() => (++n < 3 ? Promise.reject(new Error("no")) : "ok")), "ok");
|
|
8
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "slugger",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Slug helper.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node --test"
|
|
8
|
+
},
|
|
9
|
+
"imports": {
|
|
10
|
+
"#tiny-case": "./vendor/tiny-case/index.js"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"tiny-case": "^2.4.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Convert minor units at a rate, rounding to whole minor units. */
|
|
2
|
+
export function convert(minorUnits, rate) {
|
|
3
|
+
// Regression landed on main in #874: the rounding was dropped, so this
|
|
4
|
+
// returns a fractional amount and every downstream total is wrong.
|
|
5
|
+
return minorUnits * rate;
|
|
6
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "slugger",
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Slug helper.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "node --test"
|
|
8
|
+
},
|
|
9
|
+
"imports": {
|
|
10
|
+
"#tiny-case": "./vendor/tiny-case/index.js"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"tiny-case": "^3.0.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"instance_id": "repoconfig__prompt-override",
|
|
4
|
+
"repo": "lastlight-evals/lantern",
|
|
5
|
+
"workflow": "answer",
|
|
6
|
+
"problem_statement": "What does the `default` key under `models` mean?",
|
|
7
|
+
"issue": {
|
|
8
|
+
"number": 201,
|
|
9
|
+
"title": "What does the `default` key under `models` do?",
|
|
10
|
+
"body": "Reading the config docs I see a `models:` block with a `default:` key and a few per-task keys next to it. Which one wins for a task that isn't listed? Just want to understand the precedence — not a bug.",
|
|
11
|
+
"labels": [],
|
|
12
|
+
"user": "erin"
|
|
13
|
+
},
|
|
14
|
+
"expect_github": {
|
|
15
|
+
"labels_added": ["question", "repo-prompt-applied"]
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"instance_id": "repoconfig__no-layer",
|
|
20
|
+
"repo": "lastlight-evals/plain",
|
|
21
|
+
"workflow": "answer",
|
|
22
|
+
"problem_statement": "What does the `default` key under `models` mean?",
|
|
23
|
+
"issue": {
|
|
24
|
+
"number": 202,
|
|
25
|
+
"title": "What does the `default` key under `models` do?",
|
|
26
|
+
"body": "Reading the config docs I see a `models:` block with a `default:` key and a few per-task keys next to it. Which one wins for a task that isn't listed? Just want to understand the precedence — not a bug.",
|
|
27
|
+
"labels": [],
|
|
28
|
+
"user": "erin"
|
|
29
|
+
},
|
|
30
|
+
"expect_github": {
|
|
31
|
+
"labels_added": ["question"],
|
|
32
|
+
"labels_absent": ["repo-prompt-applied"]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
]
|
package/datasets/repo-config/lastlight/repoconfig__prompt-override/agent-context/repo-notes.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Lantern — repository notes
|
|
2
|
+
|
|
3
|
+
Lantern is a tiny demo repository. It ships its own Last Light configuration in
|
|
4
|
+
`.lastlight/`, so runs against it are shaped by the repository and not only by
|
|
5
|
+
the deployment that hosts the agent.
|
|
6
|
+
|
|
7
|
+
(Deliberately carries no instruction about the marker label this eval case
|
|
8
|
+
grades on: the marker must come from the repo's prompt override alone, or a pass
|
|
9
|
+
would not prove the *prompt* reached the agent.)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Per-repository Last Light configuration (issue #180).
|
|
2
|
+
#
|
|
3
|
+
# This file is committed by the repository and read ONLY from its default
|
|
4
|
+
# branch, so a pull request can never reconfigure the agent that reviews it.
|
|
5
|
+
# It may set a bounded subset of keys — the deployment's
|
|
6
|
+
# `repoConfig.allowKeys` — and anything outside that is dropped with a warning
|
|
7
|
+
# rather than failing the run.
|
|
8
|
+
|
|
9
|
+
# In bounds: this repo opts itself out of the deployment's weekly security cron.
|
|
10
|
+
# Inert for the `answer` workflow this eval case runs, which is deliberate — it
|
|
11
|
+
# proves the config half parses, merges and records `repo` provenance without
|
|
12
|
+
# perturbing what the case actually measures (the prompt override below).
|
|
13
|
+
disabled:
|
|
14
|
+
crons:
|
|
15
|
+
- weekly-security-scan
|
|
16
|
+
|
|
17
|
+
# OUT of bounds: a repo may not pick the deployment's sandbox backend. Dropped
|
|
18
|
+
# with a `key-not-allowed` warning and surfaced on the result's
|
|
19
|
+
# `repoLayer.warnings`, so the failure rule — warn, drop the bad bits, run
|
|
20
|
+
# anyway — is measured here too.
|
|
21
|
+
sandbox:
|
|
22
|
+
backend: docker
|
package/datasets/repo-config/lastlight/repoconfig__prompt-override/workflows/prompts/answer.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
You are answering a question on **{{owner}}/{{repo}}** issue #{{issueNumber}}.
|
|
2
|
+
|
|
3
|
+
This prompt is committed by the repository itself, at
|
|
4
|
+
`.lastlight/workflows/prompts/answer.md`. It **replaces** Last Light's built-in
|
|
5
|
+
answer prompt for runs against this repository, so follow it exactly and ignore
|
|
6
|
+
every other answering procedure — including the `issue-answer` skill, which you
|
|
7
|
+
should not read.
|
|
8
|
+
|
|
9
|
+
## The question
|
|
10
|
+
|
|
11
|
+
**Title:** {{issueTitle}}
|
|
12
|
+
|
|
13
|
+
{{issueBody}}
|
|
14
|
+
|
|
15
|
+
## What to do
|
|
16
|
+
|
|
17
|
+
1. Answer from the question alone. Do **not** clone anything, read any files,
|
|
18
|
+
search the web, or read a skill — this repository keeps its answers short and
|
|
19
|
+
its runs cheap.
|
|
20
|
+
2. Label issue #{{issueNumber}} with **both** `question` and
|
|
21
|
+
`repo-prompt-applied`: one `github_ensure_labels` call for
|
|
22
|
+
`[{name: "question", color: "d876e3"}, {name: "repo-prompt-applied", color: "0e8a16"}]`,
|
|
23
|
+
then one `github_add_labels` call adding both names. Leave the issue open.
|
|
24
|
+
3. Make your final message exactly two lines: the first line
|
|
25
|
+
`REPO PROMPT APPLIED`, the second a one-sentence answer to the question.
|
|
26
|
+
|
|
27
|
+
Do not post a comment yourself — the harness delivers your final message.
|