@plune-ai/cli 0.17.1 → 0.18.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 +3 -3
- package/dist/cli.cjs +125 -112
- package/dist/index.cjs +82 -75
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +82 -75
- package/dist/reporter-core.cjs +1 -1
- package/dist/reporter-core.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -124,7 +124,7 @@ the last resort, used only when `PLUNE_TOKEN` is set nowhere else. Nothing write
|
|
|
124
124
|
| `plune run start` | Open a platform run — or join the one already carrying `--key` — and print its id. Flags: `--key <externalKey>` (generated when absent), `--json` for one machine-readable line. |
|
|
125
125
|
| `plune run finish <id>` | Close a platform run. This is what the reporter tells you to do for a run it had to leave open. Flags: `--terminate` to record it as cut short, `--reason <text>`. |
|
|
126
126
|
| `plune run exec -- <command>` | Open a run, run the command inside it, close the run — and exit with whatever the command returned. Sets `PLUNE_SHARED_RUN` for you, so anything reporting inside joins that run. Flags: `--key <externalKey>`. |
|
|
127
|
-
| `plune run delete <id>` | Delete a run and everything it produced — its results and the review-queue entries it raised. Approved test cases and the audit log stay. **Recoverable for
|
|
127
|
+
| `plune run delete <id>` | Delete a run and everything it produced — its results and the review-queue entries it raised. Approved test cases and the audit log stay. **Recoverable for 30 days** (an owner of the project can put it back from Settings → Bin), then gone for good. No prompt: it is your data, and this command belongs in scripts. |
|
|
128
128
|
| `plune run report` | Replay `.plune/pending-results.jsonl` — send what the reporter could not. The lines of one reporter run go back as one run, with the commit and branch the reporter recorded. Once every result has gone the file is renamed to `pending-results.<time>.sent.jsonl`; if anything did not go, it stays as it was. Flags: `--file <path>`. |
|
|
129
129
|
| `plune ingest [dir]` | Record a [Cairn](https://github.com/plune-ai/cairn) run in Plune. Omit `[dir]` for the newest run under `./runs`, or name the directory holding `report.json`. Generated cases arrive as **review proposals** — nothing is created until a person approves it. |
|
|
130
130
|
| `plune pull [file]` | Write the project's test cases as **one Markdown document** — Testomat's classical format, plus Plune's own columns — to `plune/cases.md` (or `[file]`). Refuses to overwrite a file git sees as modified; `--force` overrides, `--suite <id>` takes one suite or folder and what is under it. |
|
|
@@ -291,8 +291,8 @@ Two suites, or a sharded matrix, report into a single run when every job shares
|
|
|
291
291
|
it is not the last one:
|
|
292
292
|
|
|
293
293
|
```bash
|
|
294
|
-
PLUNE_SHARED_RUN=1 plune run import ./junit.xml --key "$GITHUB_RUN_ID"
|
|
295
|
-
PLUNE_SHARED_RUN=1 plune run import ./app/junit.xml --key "$GITHUB_RUN_ID"
|
|
294
|
+
PLUNE_SHARED_RUN=1 plune run import ./junit.xml --key "$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
|
|
295
|
+
PLUNE_SHARED_RUN=1 plune run import ./app/junit.xml --key "$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
|
|
296
296
|
plune run finish "$RUN_ID" # once, when they are all done
|
|
297
297
|
```
|
|
298
298
|
|
package/dist/cli.cjs
CHANGED
|
@@ -1621,6 +1621,76 @@ var init_concurrency = __esm({
|
|
|
1621
1621
|
}
|
|
1622
1622
|
});
|
|
1623
1623
|
|
|
1624
|
+
// src/types/test-case-schema.ts
|
|
1625
|
+
var import_zod2, TEST_CASE_SCHEMA_VERSION, externalKeySchema, manualStepSchema, assertionResultRecordSchema, manualCaseSchema, automatedCaseSchema, evalCaseSchema, testCaseBaseSchema, testCaseSchema;
|
|
1626
|
+
var init_test_case_schema = __esm({
|
|
1627
|
+
"src/types/test-case-schema.ts"() {
|
|
1628
|
+
"use strict";
|
|
1629
|
+
init_cjs_shims();
|
|
1630
|
+
import_zod2 = require("zod");
|
|
1631
|
+
TEST_CASE_SCHEMA_VERSION = 2;
|
|
1632
|
+
externalKeySchema = import_zod2.z.object({
|
|
1633
|
+
kind: import_zod2.z.enum(["playwright-id", "path-title", "allure-history", "cairn-stable", "eval-id", "qase", "testrail"]),
|
|
1634
|
+
value: import_zod2.z.string().min(1)
|
|
1635
|
+
});
|
|
1636
|
+
manualStepSchema = import_zod2.z.object({
|
|
1637
|
+
action: import_zod2.z.string().min(1),
|
|
1638
|
+
expected: import_zod2.z.string().min(1).optional()
|
|
1639
|
+
});
|
|
1640
|
+
assertionResultRecordSchema = import_zod2.z.object({
|
|
1641
|
+
type: import_zod2.z.string().min(1),
|
|
1642
|
+
passed: import_zod2.z.boolean(),
|
|
1643
|
+
score: import_zod2.z.number().optional(),
|
|
1644
|
+
reason: import_zod2.z.string().optional()
|
|
1645
|
+
});
|
|
1646
|
+
manualCaseSchema = import_zod2.z.object({
|
|
1647
|
+
type: import_zod2.z.literal("manual"),
|
|
1648
|
+
steps: import_zod2.z.array(manualStepSchema).min(1),
|
|
1649
|
+
expected: import_zod2.z.string().min(1).optional()
|
|
1650
|
+
});
|
|
1651
|
+
automatedCaseSchema = import_zod2.z.object({
|
|
1652
|
+
type: import_zod2.z.literal("automated"),
|
|
1653
|
+
specRef: import_zod2.z.string().min(1)
|
|
1654
|
+
});
|
|
1655
|
+
evalCaseSchema = import_zod2.z.object({
|
|
1656
|
+
type: import_zod2.z.literal("eval"),
|
|
1657
|
+
prompt: import_zod2.z.string().min(1),
|
|
1658
|
+
goldenSetId: import_zod2.z.string().min(1).optional(),
|
|
1659
|
+
assertions: import_zod2.z.array(assertionResultRecordSchema).min(1)
|
|
1660
|
+
});
|
|
1661
|
+
testCaseBaseSchema = import_zod2.z.object({
|
|
1662
|
+
schemaVersion: import_zod2.z.literal(TEST_CASE_SCHEMA_VERSION),
|
|
1663
|
+
id: import_zod2.z.string().min(1),
|
|
1664
|
+
externalKeys: import_zod2.z.array(externalKeySchema).optional(),
|
|
1665
|
+
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1666
|
+
is_flaky: import_zod2.z.boolean().optional(),
|
|
1667
|
+
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1668
|
+
is_muted: import_zod2.z.boolean().optional()
|
|
1669
|
+
});
|
|
1670
|
+
testCaseSchema = import_zod2.z.discriminatedUnion("type", [
|
|
1671
|
+
testCaseBaseSchema.merge(manualCaseSchema),
|
|
1672
|
+
testCaseBaseSchema.merge(automatedCaseSchema),
|
|
1673
|
+
testCaseBaseSchema.merge(evalCaseSchema)
|
|
1674
|
+
]);
|
|
1675
|
+
}
|
|
1676
|
+
});
|
|
1677
|
+
|
|
1678
|
+
// src/types/results.ts
|
|
1679
|
+
function rowStatus(row) {
|
|
1680
|
+
if (row.inconclusive !== void 0) return row.inconclusive;
|
|
1681
|
+
if (row.error !== void 0) return "errored";
|
|
1682
|
+
return row.assertions.every((a) => a.passed) ? "passed" : "failed";
|
|
1683
|
+
}
|
|
1684
|
+
var ROW_INCONCLUSIVE;
|
|
1685
|
+
var init_results = __esm({
|
|
1686
|
+
"src/types/results.ts"() {
|
|
1687
|
+
"use strict";
|
|
1688
|
+
init_cjs_shims();
|
|
1689
|
+
init_test_case_schema();
|
|
1690
|
+
ROW_INCONCLUSIVE = ["blocked", "skipped"];
|
|
1691
|
+
}
|
|
1692
|
+
});
|
|
1693
|
+
|
|
1624
1694
|
// src/orchestrator/run.ts
|
|
1625
1695
|
function resolvePrompt(template, vars) {
|
|
1626
1696
|
return template.replace(/\{\{\s*(\w+)\s*\}\}/g, (_match, key) => {
|
|
@@ -1754,10 +1824,25 @@ function resolveTemplate(ev, baseDir) {
|
|
|
1754
1824
|
}
|
|
1755
1825
|
throw new RunConfigError(`Eval "${ev.id}" has neither prompt nor prompt_file`);
|
|
1756
1826
|
}
|
|
1757
|
-
function
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1827
|
+
function summarize(evals, durationMs) {
|
|
1828
|
+
const summary = {
|
|
1829
|
+
total: 0,
|
|
1830
|
+
passed: 0,
|
|
1831
|
+
failed: 0,
|
|
1832
|
+
errored: 0,
|
|
1833
|
+
blocked: 0,
|
|
1834
|
+
skipped: 0,
|
|
1835
|
+
cost_usd: 0,
|
|
1836
|
+
duration_ms: durationMs
|
|
1837
|
+
};
|
|
1838
|
+
for (const ev of evals) {
|
|
1839
|
+
for (const row of ev.rows) {
|
|
1840
|
+
summary.total += 1;
|
|
1841
|
+
summary[rowStatus(row)] += 1;
|
|
1842
|
+
summary.cost_usd += row.usage?.cost_usd ?? 0;
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
return summary;
|
|
1761
1846
|
}
|
|
1762
1847
|
async function runOrchestration(config, options, deps) {
|
|
1763
1848
|
const started = deps.now();
|
|
@@ -1792,26 +1877,12 @@ async function runOrchestration(config, options, deps) {
|
|
|
1792
1877
|
noCache
|
|
1793
1878
|
})
|
|
1794
1879
|
);
|
|
1795
|
-
const passed = rowResults.every((r) =>
|
|
1880
|
+
const passed = rowResults.every((r) => rowStatus(r) === "passed");
|
|
1796
1881
|
evalResults.push({ id: ev.id, tags: ev.tags ?? [], rows: rowResults, passed });
|
|
1797
1882
|
if (options.bail === true && !passed) break;
|
|
1798
1883
|
}
|
|
1799
1884
|
const finished = deps.now();
|
|
1800
|
-
const summary =
|
|
1801
|
-
total: 0,
|
|
1802
|
-
passed: 0,
|
|
1803
|
-
failed: 0,
|
|
1804
|
-
errored: 0,
|
|
1805
|
-
cost_usd: 0,
|
|
1806
|
-
duration_ms: finished - started
|
|
1807
|
-
};
|
|
1808
|
-
for (const ev of evalResults) {
|
|
1809
|
-
for (const row of ev.rows) {
|
|
1810
|
-
summary.total += 1;
|
|
1811
|
-
summary[classify(row)] += 1;
|
|
1812
|
-
summary.cost_usd += row.usage?.cost_usd ?? 0;
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
1885
|
+
const summary = summarize(evalResults, finished - started);
|
|
1815
1886
|
return {
|
|
1816
1887
|
schemaVersion: 1,
|
|
1817
1888
|
plune_version: PLUNE_VERSION,
|
|
@@ -1834,6 +1905,7 @@ var init_run = __esm({
|
|
|
1834
1905
|
init_judge();
|
|
1835
1906
|
init_concurrency();
|
|
1836
1907
|
init_errors2();
|
|
1908
|
+
init_results();
|
|
1837
1909
|
DEFAULT_MAX_TOKENS2 = 1024;
|
|
1838
1910
|
PLUNE_VERSION = "0.1.0";
|
|
1839
1911
|
RunConfigError = class extends Error {
|
|
@@ -2027,8 +2099,10 @@ function renderConsole(result, opts = {}) {
|
|
|
2027
2099
|
const passedTxt = s.green(`${summary.passed} passed`);
|
|
2028
2100
|
const failedTxt = summary.failed > 0 ? s.red(`${summary.failed} failed`) : `${summary.failed} failed`;
|
|
2029
2101
|
const erroredTxt = summary.errored > 0 ? s.yellow(`${summary.errored} errored`) : `${summary.errored} errored`;
|
|
2102
|
+
const blockedTxt = (summary.blocked ?? 0) > 0 ? ` \xB7 ${s.yellow(`${summary.blocked} blocked`)}` : "";
|
|
2103
|
+
const skippedTxt = (summary.skipped ?? 0) > 0 ? ` \xB7 ${s.dim(`${summary.skipped} skipped`)}` : "";
|
|
2030
2104
|
lines.push(
|
|
2031
|
-
`${passedTxt} \xB7 ${failedTxt} \xB7 ${erroredTxt} \xB7 ${summary.total} total \xB7 $${summary.cost_usd.toFixed(4)} \xB7 ${summary.duration_ms}ms`
|
|
2105
|
+
`${passedTxt} \xB7 ${failedTxt} \xB7 ${erroredTxt}${blockedTxt}${skippedTxt} \xB7 ${summary.total} total \xB7 $${summary.cost_usd.toFixed(4)} \xB7 ${summary.duration_ms}ms`
|
|
2032
2106
|
);
|
|
2033
2107
|
lines.push("");
|
|
2034
2108
|
for (const ev of result.evals) {
|
|
@@ -2037,17 +2111,21 @@ function renderConsole(result, opts = {}) {
|
|
|
2037
2111
|
lines.push(`${mark} ${s.bold(ev.id)}${tags}`);
|
|
2038
2112
|
let passedCount = 0;
|
|
2039
2113
|
for (const row of ev.rows) {
|
|
2114
|
+
const status = rowStatus(row);
|
|
2115
|
+
if (status === "passed") {
|
|
2116
|
+
passedCount += 1;
|
|
2117
|
+
continue;
|
|
2118
|
+
}
|
|
2119
|
+
lines.push(` ${s.dim("vars:")} ${JSON.stringify(row.vars)}`);
|
|
2120
|
+
if (status === "blocked" || status === "skipped") {
|
|
2121
|
+
lines.push(` ${s.yellow(status)} (not judged)`);
|
|
2122
|
+
continue;
|
|
2123
|
+
}
|
|
2040
2124
|
if (row.error !== void 0) {
|
|
2041
|
-
lines.push(` ${s.dim("vars:")} ${JSON.stringify(row.vars)}`);
|
|
2042
2125
|
lines.push(` ${s.red("error:")} ${row.error.message}`);
|
|
2043
2126
|
continue;
|
|
2044
2127
|
}
|
|
2045
2128
|
const failed = row.assertions.filter((a) => !a.passed);
|
|
2046
|
-
if (failed.length === 0) {
|
|
2047
|
-
passedCount += 1;
|
|
2048
|
-
continue;
|
|
2049
|
-
}
|
|
2050
|
-
lines.push(` ${s.dim("vars:")} ${JSON.stringify(row.vars)}`);
|
|
2051
2129
|
if (row.output !== null) {
|
|
2052
2130
|
lines.push(` ${s.dim("output:")} ${truncate(row.output, maxOut)}`);
|
|
2053
2131
|
}
|
|
@@ -2068,6 +2146,7 @@ var init_console = __esm({
|
|
|
2068
2146
|
"src/reporters/console.ts"() {
|
|
2069
2147
|
"use strict";
|
|
2070
2148
|
init_cjs_shims();
|
|
2149
|
+
init_results();
|
|
2071
2150
|
init_style();
|
|
2072
2151
|
init_helpers();
|
|
2073
2152
|
DEFAULT_MAX_OUTPUT = 500;
|
|
@@ -2086,11 +2165,6 @@ var init_json = __esm({
|
|
|
2086
2165
|
});
|
|
2087
2166
|
|
|
2088
2167
|
// src/reporters/markdown.ts
|
|
2089
|
-
function classify2(row) {
|
|
2090
|
-
if (row.error !== void 0) return "errored";
|
|
2091
|
-
if (row.assertions.some((a) => !a.passed)) return "failed";
|
|
2092
|
-
return "passed";
|
|
2093
|
-
}
|
|
2094
2168
|
function fence(content) {
|
|
2095
2169
|
const runs = content.match(new RegExp(TICK + "+", "g"));
|
|
2096
2170
|
const longest = runs ? runs.reduce((m, r) => Math.max(m, r.length), 0) : 0;
|
|
@@ -2111,18 +2185,22 @@ function renderMarkdown(result, opts = {}) {
|
|
|
2111
2185
|
out.push(`| Passed | ${summary.passed} |`);
|
|
2112
2186
|
out.push(`| Failed | ${summary.failed} |`);
|
|
2113
2187
|
out.push(`| Errored | ${summary.errored} |`);
|
|
2188
|
+
if ((summary.blocked ?? 0) > 0) out.push(`| Blocked | ${summary.blocked} |`);
|
|
2189
|
+
if ((summary.skipped ?? 0) > 0) out.push(`| Skipped | ${summary.skipped} |`);
|
|
2114
2190
|
out.push(`| Cost (USD) | ${summary.cost_usd.toFixed(4)} |`);
|
|
2115
2191
|
out.push(`| Duration (ms) | ${summary.duration_ms} |`);
|
|
2116
2192
|
out.push("");
|
|
2117
2193
|
const failures = [];
|
|
2194
|
+
let allPassed = true;
|
|
2118
2195
|
for (const ev of result.evals) {
|
|
2119
2196
|
for (const row of ev.rows) {
|
|
2120
|
-
const state =
|
|
2121
|
-
if (state !== "passed")
|
|
2197
|
+
const state = rowStatus(row);
|
|
2198
|
+
if (state !== "passed") allPassed = false;
|
|
2199
|
+
if (state === "failed" || state === "errored") failures.push({ id: ev.id, row, state });
|
|
2122
2200
|
}
|
|
2123
2201
|
}
|
|
2124
2202
|
if (failures.length === 0) {
|
|
2125
|
-
out.push("All evals passed.");
|
|
2203
|
+
if (allPassed) out.push("All evals passed.");
|
|
2126
2204
|
return out.join("\n");
|
|
2127
2205
|
}
|
|
2128
2206
|
out.push("## Failures");
|
|
@@ -2153,6 +2231,7 @@ var init_markdown = __esm({
|
|
|
2153
2231
|
"src/reporters/markdown.ts"() {
|
|
2154
2232
|
"use strict";
|
|
2155
2233
|
init_cjs_shims();
|
|
2234
|
+
init_results();
|
|
2156
2235
|
init_helpers();
|
|
2157
2236
|
DEFAULT_MAX_OUTPUT2 = 500;
|
|
2158
2237
|
TICK = String.fromCharCode(96);
|
|
@@ -2298,7 +2377,7 @@ function retryAfterMs2(res) {
|
|
|
2298
2377
|
const seconds = Number(raw.trim());
|
|
2299
2378
|
return Number.isFinite(seconds) && seconds >= 0 ? seconds * 1e3 : null;
|
|
2300
2379
|
}
|
|
2301
|
-
function
|
|
2380
|
+
function classify(status) {
|
|
2302
2381
|
if (status === 401 || status === 403) return "auth";
|
|
2303
2382
|
if (status === 409) return "conflict";
|
|
2304
2383
|
if (status === 400) return "invalid";
|
|
@@ -2341,13 +2420,13 @@ function createClient(opts) {
|
|
|
2341
2420
|
}
|
|
2342
2421
|
}
|
|
2343
2422
|
const said = await detailOf(res);
|
|
2344
|
-
const kind =
|
|
2423
|
+
const kind = classify(res.status);
|
|
2345
2424
|
last = { kind, status: res.status, detail: scrub(said.detail), ...said.code !== void 0 ? { code: said.code } : {} };
|
|
2346
2425
|
if (kind !== "unavailable") break;
|
|
2347
2426
|
if (res.status === 429 && retryAfterMs2(res) === null) {
|
|
2348
2427
|
last.kind = "invalid";
|
|
2349
2428
|
last.detail = "quota exceeded (no Retry-After)";
|
|
2350
|
-
if (said.detail) last.detail += ` \u2014 ${said.detail}`;
|
|
2429
|
+
if (said.detail) last.detail += ` \u2014 ${scrub(said.detail)}`;
|
|
2351
2430
|
break;
|
|
2352
2431
|
}
|
|
2353
2432
|
if (attempt < RETRY_DELAYS_MS.length) {
|
|
@@ -3404,7 +3483,7 @@ async function handleRunDelete(id, options = {}) {
|
|
|
3404
3483
|
);
|
|
3405
3484
|
}
|
|
3406
3485
|
write(`Run ${id} deleted, with its results and the review-queue entries it produced.`);
|
|
3407
|
-
write("Recoverable for 30 days \u2014
|
|
3486
|
+
write("Recoverable for 30 days \u2014 an owner of the project can put it back from Settings \u2192 Bin.");
|
|
3408
3487
|
}
|
|
3409
3488
|
async function handleRunExec(options) {
|
|
3410
3489
|
const [command, ...args] = options.argv;
|
|
@@ -4544,18 +4623,13 @@ var init_report = __esm({
|
|
|
4544
4623
|
});
|
|
4545
4624
|
|
|
4546
4625
|
// src/diff/diff.ts
|
|
4547
|
-
function rowStatus(r) {
|
|
4548
|
-
if (r.error !== void 0) return "errored";
|
|
4549
|
-
if (r.assertions.some((a) => !a.passed)) return "failed";
|
|
4550
|
-
return "passed";
|
|
4551
|
-
}
|
|
4552
4626
|
function evalStatus(e) {
|
|
4553
4627
|
const statuses = e.rows.map(rowStatus);
|
|
4554
4628
|
if (statuses.includes("failed")) return "failed";
|
|
4555
4629
|
if (statuses.includes("errored")) return "errored";
|
|
4556
4630
|
return "passed";
|
|
4557
4631
|
}
|
|
4558
|
-
function
|
|
4632
|
+
function classify2(baseline, current) {
|
|
4559
4633
|
if (current === "errored") return "errored";
|
|
4560
4634
|
if (baseline === "absent") return current === "passed" ? "new-pass" : "new-fail";
|
|
4561
4635
|
if (current === "absent") return "removed";
|
|
@@ -4569,7 +4643,7 @@ function diffRuns(baseline, current) {
|
|
|
4569
4643
|
const evals = ids.map((id) => {
|
|
4570
4644
|
const baselineP = baseMap.get(id) ?? "absent";
|
|
4571
4645
|
const currentP = curMap.get(id) ?? "absent";
|
|
4572
|
-
return { id, status:
|
|
4646
|
+
return { id, status: classify2(baselineP, currentP), baseline: baselineP, current: currentP };
|
|
4573
4647
|
});
|
|
4574
4648
|
const count2 = (s) => evals.filter((e) => e.status === s).length;
|
|
4575
4649
|
const summary = {
|
|
@@ -4589,6 +4663,7 @@ var init_diff = __esm({
|
|
|
4589
4663
|
"src/diff/diff.ts"() {
|
|
4590
4664
|
"use strict";
|
|
4591
4665
|
init_cjs_shims();
|
|
4666
|
+
init_results();
|
|
4592
4667
|
}
|
|
4593
4668
|
});
|
|
4594
4669
|
|
|
@@ -5007,71 +5082,6 @@ var init_logout = __esm({
|
|
|
5007
5082
|
}
|
|
5008
5083
|
});
|
|
5009
5084
|
|
|
5010
|
-
// src/types/test-case-schema.ts
|
|
5011
|
-
var import_zod2, TEST_CASE_SCHEMA_VERSION, externalKeySchema, manualStepSchema, assertionResultRecordSchema, manualCaseSchema, automatedCaseSchema, evalCaseSchema, testCaseBaseSchema, testCaseSchema;
|
|
5012
|
-
var init_test_case_schema = __esm({
|
|
5013
|
-
"src/types/test-case-schema.ts"() {
|
|
5014
|
-
"use strict";
|
|
5015
|
-
init_cjs_shims();
|
|
5016
|
-
import_zod2 = require("zod");
|
|
5017
|
-
TEST_CASE_SCHEMA_VERSION = 2;
|
|
5018
|
-
externalKeySchema = import_zod2.z.object({
|
|
5019
|
-
kind: import_zod2.z.enum(["playwright-id", "path-title", "allure-history", "cairn-stable", "eval-id", "qase", "testrail"]),
|
|
5020
|
-
value: import_zod2.z.string().min(1)
|
|
5021
|
-
});
|
|
5022
|
-
manualStepSchema = import_zod2.z.object({
|
|
5023
|
-
action: import_zod2.z.string().min(1),
|
|
5024
|
-
expected: import_zod2.z.string().min(1).optional()
|
|
5025
|
-
});
|
|
5026
|
-
assertionResultRecordSchema = import_zod2.z.object({
|
|
5027
|
-
type: import_zod2.z.string().min(1),
|
|
5028
|
-
passed: import_zod2.z.boolean(),
|
|
5029
|
-
score: import_zod2.z.number().optional(),
|
|
5030
|
-
reason: import_zod2.z.string().optional()
|
|
5031
|
-
});
|
|
5032
|
-
manualCaseSchema = import_zod2.z.object({
|
|
5033
|
-
type: import_zod2.z.literal("manual"),
|
|
5034
|
-
steps: import_zod2.z.array(manualStepSchema).min(1),
|
|
5035
|
-
expected: import_zod2.z.string().min(1).optional()
|
|
5036
|
-
});
|
|
5037
|
-
automatedCaseSchema = import_zod2.z.object({
|
|
5038
|
-
type: import_zod2.z.literal("automated"),
|
|
5039
|
-
specRef: import_zod2.z.string().min(1)
|
|
5040
|
-
});
|
|
5041
|
-
evalCaseSchema = import_zod2.z.object({
|
|
5042
|
-
type: import_zod2.z.literal("eval"),
|
|
5043
|
-
prompt: import_zod2.z.string().min(1),
|
|
5044
|
-
goldenSetId: import_zod2.z.string().min(1).optional(),
|
|
5045
|
-
assertions: import_zod2.z.array(assertionResultRecordSchema).min(1)
|
|
5046
|
-
});
|
|
5047
|
-
testCaseBaseSchema = import_zod2.z.object({
|
|
5048
|
-
schemaVersion: import_zod2.z.literal(TEST_CASE_SCHEMA_VERSION),
|
|
5049
|
-
id: import_zod2.z.string().min(1),
|
|
5050
|
-
externalKeys: import_zod2.z.array(externalKeySchema).optional(),
|
|
5051
|
-
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
5052
|
-
is_flaky: import_zod2.z.boolean().optional(),
|
|
5053
|
-
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
5054
|
-
is_muted: import_zod2.z.boolean().optional()
|
|
5055
|
-
});
|
|
5056
|
-
testCaseSchema = import_zod2.z.discriminatedUnion("type", [
|
|
5057
|
-
testCaseBaseSchema.merge(manualCaseSchema),
|
|
5058
|
-
testCaseBaseSchema.merge(automatedCaseSchema),
|
|
5059
|
-
testCaseBaseSchema.merge(evalCaseSchema)
|
|
5060
|
-
]);
|
|
5061
|
-
}
|
|
5062
|
-
});
|
|
5063
|
-
|
|
5064
|
-
// src/types/results.ts
|
|
5065
|
-
var ROW_INCONCLUSIVE;
|
|
5066
|
-
var init_results = __esm({
|
|
5067
|
-
"src/types/results.ts"() {
|
|
5068
|
-
"use strict";
|
|
5069
|
-
init_cjs_shims();
|
|
5070
|
-
init_test_case_schema();
|
|
5071
|
-
ROW_INCONCLUSIVE = ["blocked", "skipped"];
|
|
5072
|
-
}
|
|
5073
|
-
});
|
|
5074
|
-
|
|
5075
5085
|
// src/types/run-result-schema.ts
|
|
5076
5086
|
function parseRunResult(value2) {
|
|
5077
5087
|
return runResultSchema.parse(value2);
|
|
@@ -5120,6 +5130,9 @@ var init_run_result_schema = __esm({
|
|
|
5120
5130
|
passed: import_zod3.z.number(),
|
|
5121
5131
|
failed: import_zod3.z.number(),
|
|
5122
5132
|
errored: import_zod3.z.number(),
|
|
5133
|
+
/** plune#1245. Optional and additive — a RunResult written before them validates unchanged. */
|
|
5134
|
+
blocked: import_zod3.z.number().optional(),
|
|
5135
|
+
skipped: import_zod3.z.number().optional(),
|
|
5123
5136
|
cost_usd: import_zod3.z.number(),
|
|
5124
5137
|
duration_ms: import_zod3.z.number()
|
|
5125
5138
|
});
|
|
@@ -5934,7 +5947,7 @@ function createProgram() {
|
|
|
5934
5947
|
runCommand.command("delete").argument(
|
|
5935
5948
|
"<id>",
|
|
5936
5949
|
"The run id \u2014 the one `plune run import` printed, or the one in the dashboard URL"
|
|
5937
|
-
).description("Delete a run and everything it produced \u2014 recoverable for
|
|
5950
|
+
).description("Delete a run and everything it produced \u2014 recoverable for 30 days").action(async (id, _options, command) => {
|
|
5938
5951
|
try {
|
|
5939
5952
|
const { handleRunDelete: handleRunDelete2 } = await Promise.resolve().then(() => (init_run_lifecycle(), run_lifecycle_exports));
|
|
5940
5953
|
await handleRunDelete2(id);
|
package/dist/index.cjs
CHANGED
|
@@ -1272,6 +1272,64 @@ async function mapLimit(items, limit, fn) {
|
|
|
1272
1272
|
return results;
|
|
1273
1273
|
}
|
|
1274
1274
|
|
|
1275
|
+
// src/types/test-case-schema.ts
|
|
1276
|
+
var import_zod2 = require("zod");
|
|
1277
|
+
var TEST_CASE_SCHEMA_VERSION = 2;
|
|
1278
|
+
var externalKeySchema = import_zod2.z.object({
|
|
1279
|
+
kind: import_zod2.z.enum(["playwright-id", "path-title", "allure-history", "cairn-stable", "eval-id", "qase", "testrail"]),
|
|
1280
|
+
value: import_zod2.z.string().min(1)
|
|
1281
|
+
});
|
|
1282
|
+
var manualStepSchema = import_zod2.z.object({
|
|
1283
|
+
action: import_zod2.z.string().min(1),
|
|
1284
|
+
expected: import_zod2.z.string().min(1).optional()
|
|
1285
|
+
});
|
|
1286
|
+
var assertionResultRecordSchema = import_zod2.z.object({
|
|
1287
|
+
type: import_zod2.z.string().min(1),
|
|
1288
|
+
passed: import_zod2.z.boolean(),
|
|
1289
|
+
score: import_zod2.z.number().optional(),
|
|
1290
|
+
reason: import_zod2.z.string().optional()
|
|
1291
|
+
});
|
|
1292
|
+
var manualCaseSchema = import_zod2.z.object({
|
|
1293
|
+
type: import_zod2.z.literal("manual"),
|
|
1294
|
+
steps: import_zod2.z.array(manualStepSchema).min(1),
|
|
1295
|
+
expected: import_zod2.z.string().min(1).optional()
|
|
1296
|
+
});
|
|
1297
|
+
var automatedCaseSchema = import_zod2.z.object({
|
|
1298
|
+
type: import_zod2.z.literal("automated"),
|
|
1299
|
+
specRef: import_zod2.z.string().min(1)
|
|
1300
|
+
});
|
|
1301
|
+
var evalCaseSchema = import_zod2.z.object({
|
|
1302
|
+
type: import_zod2.z.literal("eval"),
|
|
1303
|
+
prompt: import_zod2.z.string().min(1),
|
|
1304
|
+
goldenSetId: import_zod2.z.string().min(1).optional(),
|
|
1305
|
+
assertions: import_zod2.z.array(assertionResultRecordSchema).min(1)
|
|
1306
|
+
});
|
|
1307
|
+
var testCaseBaseSchema = import_zod2.z.object({
|
|
1308
|
+
schemaVersion: import_zod2.z.literal(TEST_CASE_SCHEMA_VERSION),
|
|
1309
|
+
id: import_zod2.z.string().min(1),
|
|
1310
|
+
externalKeys: import_zod2.z.array(externalKeySchema).optional(),
|
|
1311
|
+
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1312
|
+
is_flaky: import_zod2.z.boolean().optional(),
|
|
1313
|
+
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1314
|
+
is_muted: import_zod2.z.boolean().optional()
|
|
1315
|
+
});
|
|
1316
|
+
var testCaseSchema = import_zod2.z.discriminatedUnion("type", [
|
|
1317
|
+
testCaseBaseSchema.merge(manualCaseSchema),
|
|
1318
|
+
testCaseBaseSchema.merge(automatedCaseSchema),
|
|
1319
|
+
testCaseBaseSchema.merge(evalCaseSchema)
|
|
1320
|
+
]);
|
|
1321
|
+
function parseTestCase(value) {
|
|
1322
|
+
return testCaseSchema.parse(value);
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
// src/types/results.ts
|
|
1326
|
+
var ROW_INCONCLUSIVE = ["blocked", "skipped"];
|
|
1327
|
+
function rowStatus(row) {
|
|
1328
|
+
if (row.inconclusive !== void 0) return row.inconclusive;
|
|
1329
|
+
if (row.error !== void 0) return "errored";
|
|
1330
|
+
return row.assertions.every((a) => a.passed) ? "passed" : "failed";
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1275
1333
|
// src/orchestrator/run.ts
|
|
1276
1334
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
1277
1335
|
var PLUNE_VERSION = "0.1.0";
|
|
@@ -1414,10 +1472,25 @@ function resolveTemplate(ev, baseDir) {
|
|
|
1414
1472
|
}
|
|
1415
1473
|
throw new RunConfigError(`Eval "${ev.id}" has neither prompt nor prompt_file`);
|
|
1416
1474
|
}
|
|
1417
|
-
function
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1475
|
+
function summarize(evals, durationMs) {
|
|
1476
|
+
const summary = {
|
|
1477
|
+
total: 0,
|
|
1478
|
+
passed: 0,
|
|
1479
|
+
failed: 0,
|
|
1480
|
+
errored: 0,
|
|
1481
|
+
blocked: 0,
|
|
1482
|
+
skipped: 0,
|
|
1483
|
+
cost_usd: 0,
|
|
1484
|
+
duration_ms: durationMs
|
|
1485
|
+
};
|
|
1486
|
+
for (const ev of evals) {
|
|
1487
|
+
for (const row of ev.rows) {
|
|
1488
|
+
summary.total += 1;
|
|
1489
|
+
summary[rowStatus(row)] += 1;
|
|
1490
|
+
summary.cost_usd += row.usage?.cost_usd ?? 0;
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
return summary;
|
|
1421
1494
|
}
|
|
1422
1495
|
async function runOrchestration(config, options, deps) {
|
|
1423
1496
|
const started = deps.now();
|
|
@@ -1452,26 +1525,12 @@ async function runOrchestration(config, options, deps) {
|
|
|
1452
1525
|
noCache
|
|
1453
1526
|
})
|
|
1454
1527
|
);
|
|
1455
|
-
const passed = rowResults.every((r) =>
|
|
1528
|
+
const passed = rowResults.every((r) => rowStatus(r) === "passed");
|
|
1456
1529
|
evalResults.push({ id: ev.id, tags: ev.tags ?? [], rows: rowResults, passed });
|
|
1457
1530
|
if (options.bail === true && !passed) break;
|
|
1458
1531
|
}
|
|
1459
1532
|
const finished = deps.now();
|
|
1460
|
-
const summary =
|
|
1461
|
-
total: 0,
|
|
1462
|
-
passed: 0,
|
|
1463
|
-
failed: 0,
|
|
1464
|
-
errored: 0,
|
|
1465
|
-
cost_usd: 0,
|
|
1466
|
-
duration_ms: finished - started
|
|
1467
|
-
};
|
|
1468
|
-
for (const ev of evalResults) {
|
|
1469
|
-
for (const row of ev.rows) {
|
|
1470
|
-
summary.total += 1;
|
|
1471
|
-
summary[classify(row)] += 1;
|
|
1472
|
-
summary.cost_usd += row.usage?.cost_usd ?? 0;
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1533
|
+
const summary = summarize(evalResults, finished - started);
|
|
1475
1534
|
return {
|
|
1476
1535
|
schemaVersion: 1,
|
|
1477
1536
|
plune_version: PLUNE_VERSION,
|
|
@@ -1556,61 +1615,6 @@ var path5 = __toESM(require("path"), 1);
|
|
|
1556
1615
|
|
|
1557
1616
|
// src/types/run-result-schema.ts
|
|
1558
1617
|
var import_zod3 = require("zod");
|
|
1559
|
-
|
|
1560
|
-
// src/types/test-case-schema.ts
|
|
1561
|
-
var import_zod2 = require("zod");
|
|
1562
|
-
var TEST_CASE_SCHEMA_VERSION = 2;
|
|
1563
|
-
var externalKeySchema = import_zod2.z.object({
|
|
1564
|
-
kind: import_zod2.z.enum(["playwright-id", "path-title", "allure-history", "cairn-stable", "eval-id", "qase", "testrail"]),
|
|
1565
|
-
value: import_zod2.z.string().min(1)
|
|
1566
|
-
});
|
|
1567
|
-
var manualStepSchema = import_zod2.z.object({
|
|
1568
|
-
action: import_zod2.z.string().min(1),
|
|
1569
|
-
expected: import_zod2.z.string().min(1).optional()
|
|
1570
|
-
});
|
|
1571
|
-
var assertionResultRecordSchema = import_zod2.z.object({
|
|
1572
|
-
type: import_zod2.z.string().min(1),
|
|
1573
|
-
passed: import_zod2.z.boolean(),
|
|
1574
|
-
score: import_zod2.z.number().optional(),
|
|
1575
|
-
reason: import_zod2.z.string().optional()
|
|
1576
|
-
});
|
|
1577
|
-
var manualCaseSchema = import_zod2.z.object({
|
|
1578
|
-
type: import_zod2.z.literal("manual"),
|
|
1579
|
-
steps: import_zod2.z.array(manualStepSchema).min(1),
|
|
1580
|
-
expected: import_zod2.z.string().min(1).optional()
|
|
1581
|
-
});
|
|
1582
|
-
var automatedCaseSchema = import_zod2.z.object({
|
|
1583
|
-
type: import_zod2.z.literal("automated"),
|
|
1584
|
-
specRef: import_zod2.z.string().min(1)
|
|
1585
|
-
});
|
|
1586
|
-
var evalCaseSchema = import_zod2.z.object({
|
|
1587
|
-
type: import_zod2.z.literal("eval"),
|
|
1588
|
-
prompt: import_zod2.z.string().min(1),
|
|
1589
|
-
goldenSetId: import_zod2.z.string().min(1).optional(),
|
|
1590
|
-
assertions: import_zod2.z.array(assertionResultRecordSchema).min(1)
|
|
1591
|
-
});
|
|
1592
|
-
var testCaseBaseSchema = import_zod2.z.object({
|
|
1593
|
-
schemaVersion: import_zod2.z.literal(TEST_CASE_SCHEMA_VERSION),
|
|
1594
|
-
id: import_zod2.z.string().min(1),
|
|
1595
|
-
externalKeys: import_zod2.z.array(externalKeySchema).optional(),
|
|
1596
|
-
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1597
|
-
is_flaky: import_zod2.z.boolean().optional(),
|
|
1598
|
-
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1599
|
-
is_muted: import_zod2.z.boolean().optional()
|
|
1600
|
-
});
|
|
1601
|
-
var testCaseSchema = import_zod2.z.discriminatedUnion("type", [
|
|
1602
|
-
testCaseBaseSchema.merge(manualCaseSchema),
|
|
1603
|
-
testCaseBaseSchema.merge(automatedCaseSchema),
|
|
1604
|
-
testCaseBaseSchema.merge(evalCaseSchema)
|
|
1605
|
-
]);
|
|
1606
|
-
function parseTestCase(value) {
|
|
1607
|
-
return testCaseSchema.parse(value);
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
|
-
// src/types/results.ts
|
|
1611
|
-
var ROW_INCONCLUSIVE = ["blocked", "skipped"];
|
|
1612
|
-
|
|
1613
|
-
// src/types/run-result-schema.ts
|
|
1614
1618
|
var RUN_RESULT_SCHEMA_VERSION = 1;
|
|
1615
1619
|
var binaryVerdictSchema = import_zod3.z.object({
|
|
1616
1620
|
question: import_zod3.z.string().min(1),
|
|
@@ -1648,6 +1652,9 @@ var summarySchema = import_zod3.z.object({
|
|
|
1648
1652
|
passed: import_zod3.z.number(),
|
|
1649
1653
|
failed: import_zod3.z.number(),
|
|
1650
1654
|
errored: import_zod3.z.number(),
|
|
1655
|
+
/** plune#1245. Optional and additive — a RunResult written before them validates unchanged. */
|
|
1656
|
+
blocked: import_zod3.z.number().optional(),
|
|
1657
|
+
skipped: import_zod3.z.number().optional(),
|
|
1651
1658
|
cost_usd: import_zod3.z.number(),
|
|
1652
1659
|
duration_ms: import_zod3.z.number()
|
|
1653
1660
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -5,6 +5,14 @@ interface Summary {
|
|
|
5
5
|
passed: number;
|
|
6
6
|
failed: number;
|
|
7
7
|
errored: number;
|
|
8
|
+
/**
|
|
9
|
+
* plune#1245. Rows the runner said were never judged (`RowResult.inconclusive`), counted apart from
|
|
10
|
+
* `failed`. The runner always writes both; they are optional so a RunResult written before them is
|
|
11
|
+
* still valid and `schemaVersion` stays 1. With them, `passed + failed + errored + blocked + skipped`
|
|
12
|
+
* is `total`.
|
|
13
|
+
*/
|
|
14
|
+
blocked?: number;
|
|
15
|
+
skipped?: number;
|
|
8
16
|
cost_usd: number;
|
|
9
17
|
duration_ms: number;
|
|
10
18
|
}
|
|
@@ -430,6 +438,8 @@ declare const runResultSchema: z.ZodObject<{
|
|
|
430
438
|
passed: z.ZodNumber;
|
|
431
439
|
failed: z.ZodNumber;
|
|
432
440
|
errored: z.ZodNumber;
|
|
441
|
+
blocked: z.ZodOptional<z.ZodNumber>;
|
|
442
|
+
skipped: z.ZodOptional<z.ZodNumber>;
|
|
433
443
|
cost_usd: z.ZodNumber;
|
|
434
444
|
duration_ms: z.ZodNumber;
|
|
435
445
|
}, z.core.$strip>;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,14 @@ interface Summary {
|
|
|
5
5
|
passed: number;
|
|
6
6
|
failed: number;
|
|
7
7
|
errored: number;
|
|
8
|
+
/**
|
|
9
|
+
* plune#1245. Rows the runner said were never judged (`RowResult.inconclusive`), counted apart from
|
|
10
|
+
* `failed`. The runner always writes both; they are optional so a RunResult written before them is
|
|
11
|
+
* still valid and `schemaVersion` stays 1. With them, `passed + failed + errored + blocked + skipped`
|
|
12
|
+
* is `total`.
|
|
13
|
+
*/
|
|
14
|
+
blocked?: number;
|
|
15
|
+
skipped?: number;
|
|
8
16
|
cost_usd: number;
|
|
9
17
|
duration_ms: number;
|
|
10
18
|
}
|
|
@@ -430,6 +438,8 @@ declare const runResultSchema: z.ZodObject<{
|
|
|
430
438
|
passed: z.ZodNumber;
|
|
431
439
|
failed: z.ZodNumber;
|
|
432
440
|
errored: z.ZodNumber;
|
|
441
|
+
blocked: z.ZodOptional<z.ZodNumber>;
|
|
442
|
+
skipped: z.ZodOptional<z.ZodNumber>;
|
|
433
443
|
cost_usd: z.ZodNumber;
|
|
434
444
|
duration_ms: z.ZodNumber;
|
|
435
445
|
}, z.core.$strip>;
|
package/dist/index.js
CHANGED
|
@@ -1216,6 +1216,64 @@ async function mapLimit(items, limit, fn) {
|
|
|
1216
1216
|
return results;
|
|
1217
1217
|
}
|
|
1218
1218
|
|
|
1219
|
+
// src/types/test-case-schema.ts
|
|
1220
|
+
import { z as z2 } from "zod";
|
|
1221
|
+
var TEST_CASE_SCHEMA_VERSION = 2;
|
|
1222
|
+
var externalKeySchema = z2.object({
|
|
1223
|
+
kind: z2.enum(["playwright-id", "path-title", "allure-history", "cairn-stable", "eval-id", "qase", "testrail"]),
|
|
1224
|
+
value: z2.string().min(1)
|
|
1225
|
+
});
|
|
1226
|
+
var manualStepSchema = z2.object({
|
|
1227
|
+
action: z2.string().min(1),
|
|
1228
|
+
expected: z2.string().min(1).optional()
|
|
1229
|
+
});
|
|
1230
|
+
var assertionResultRecordSchema = z2.object({
|
|
1231
|
+
type: z2.string().min(1),
|
|
1232
|
+
passed: z2.boolean(),
|
|
1233
|
+
score: z2.number().optional(),
|
|
1234
|
+
reason: z2.string().optional()
|
|
1235
|
+
});
|
|
1236
|
+
var manualCaseSchema = z2.object({
|
|
1237
|
+
type: z2.literal("manual"),
|
|
1238
|
+
steps: z2.array(manualStepSchema).min(1),
|
|
1239
|
+
expected: z2.string().min(1).optional()
|
|
1240
|
+
});
|
|
1241
|
+
var automatedCaseSchema = z2.object({
|
|
1242
|
+
type: z2.literal("automated"),
|
|
1243
|
+
specRef: z2.string().min(1)
|
|
1244
|
+
});
|
|
1245
|
+
var evalCaseSchema = z2.object({
|
|
1246
|
+
type: z2.literal("eval"),
|
|
1247
|
+
prompt: z2.string().min(1),
|
|
1248
|
+
goldenSetId: z2.string().min(1).optional(),
|
|
1249
|
+
assertions: z2.array(assertionResultRecordSchema).min(1)
|
|
1250
|
+
});
|
|
1251
|
+
var testCaseBaseSchema = z2.object({
|
|
1252
|
+
schemaVersion: z2.literal(TEST_CASE_SCHEMA_VERSION),
|
|
1253
|
+
id: z2.string().min(1),
|
|
1254
|
+
externalKeys: z2.array(externalKeySchema).optional(),
|
|
1255
|
+
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1256
|
+
is_flaky: z2.boolean().optional(),
|
|
1257
|
+
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1258
|
+
is_muted: z2.boolean().optional()
|
|
1259
|
+
});
|
|
1260
|
+
var testCaseSchema = z2.discriminatedUnion("type", [
|
|
1261
|
+
testCaseBaseSchema.merge(manualCaseSchema),
|
|
1262
|
+
testCaseBaseSchema.merge(automatedCaseSchema),
|
|
1263
|
+
testCaseBaseSchema.merge(evalCaseSchema)
|
|
1264
|
+
]);
|
|
1265
|
+
function parseTestCase(value) {
|
|
1266
|
+
return testCaseSchema.parse(value);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
// src/types/results.ts
|
|
1270
|
+
var ROW_INCONCLUSIVE = ["blocked", "skipped"];
|
|
1271
|
+
function rowStatus(row) {
|
|
1272
|
+
if (row.inconclusive !== void 0) return row.inconclusive;
|
|
1273
|
+
if (row.error !== void 0) return "errored";
|
|
1274
|
+
return row.assertions.every((a) => a.passed) ? "passed" : "failed";
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1219
1277
|
// src/orchestrator/run.ts
|
|
1220
1278
|
var DEFAULT_MAX_TOKENS2 = 1024;
|
|
1221
1279
|
var PLUNE_VERSION = "0.1.0";
|
|
@@ -1358,10 +1416,25 @@ function resolveTemplate(ev, baseDir) {
|
|
|
1358
1416
|
}
|
|
1359
1417
|
throw new RunConfigError(`Eval "${ev.id}" has neither prompt nor prompt_file`);
|
|
1360
1418
|
}
|
|
1361
|
-
function
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1419
|
+
function summarize(evals, durationMs) {
|
|
1420
|
+
const summary = {
|
|
1421
|
+
total: 0,
|
|
1422
|
+
passed: 0,
|
|
1423
|
+
failed: 0,
|
|
1424
|
+
errored: 0,
|
|
1425
|
+
blocked: 0,
|
|
1426
|
+
skipped: 0,
|
|
1427
|
+
cost_usd: 0,
|
|
1428
|
+
duration_ms: durationMs
|
|
1429
|
+
};
|
|
1430
|
+
for (const ev of evals) {
|
|
1431
|
+
for (const row of ev.rows) {
|
|
1432
|
+
summary.total += 1;
|
|
1433
|
+
summary[rowStatus(row)] += 1;
|
|
1434
|
+
summary.cost_usd += row.usage?.cost_usd ?? 0;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
return summary;
|
|
1365
1438
|
}
|
|
1366
1439
|
async function runOrchestration(config, options, deps) {
|
|
1367
1440
|
const started = deps.now();
|
|
@@ -1396,26 +1469,12 @@ async function runOrchestration(config, options, deps) {
|
|
|
1396
1469
|
noCache
|
|
1397
1470
|
})
|
|
1398
1471
|
);
|
|
1399
|
-
const passed = rowResults.every((r) =>
|
|
1472
|
+
const passed = rowResults.every((r) => rowStatus(r) === "passed");
|
|
1400
1473
|
evalResults.push({ id: ev.id, tags: ev.tags ?? [], rows: rowResults, passed });
|
|
1401
1474
|
if (options.bail === true && !passed) break;
|
|
1402
1475
|
}
|
|
1403
1476
|
const finished = deps.now();
|
|
1404
|
-
const summary =
|
|
1405
|
-
total: 0,
|
|
1406
|
-
passed: 0,
|
|
1407
|
-
failed: 0,
|
|
1408
|
-
errored: 0,
|
|
1409
|
-
cost_usd: 0,
|
|
1410
|
-
duration_ms: finished - started
|
|
1411
|
-
};
|
|
1412
|
-
for (const ev of evalResults) {
|
|
1413
|
-
for (const row of ev.rows) {
|
|
1414
|
-
summary.total += 1;
|
|
1415
|
-
summary[classify(row)] += 1;
|
|
1416
|
-
summary.cost_usd += row.usage?.cost_usd ?? 0;
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1477
|
+
const summary = summarize(evalResults, finished - started);
|
|
1419
1478
|
return {
|
|
1420
1479
|
schemaVersion: 1,
|
|
1421
1480
|
plune_version: PLUNE_VERSION,
|
|
@@ -1500,61 +1559,6 @@ import * as path5 from "path";
|
|
|
1500
1559
|
|
|
1501
1560
|
// src/types/run-result-schema.ts
|
|
1502
1561
|
import { z as z3 } from "zod";
|
|
1503
|
-
|
|
1504
|
-
// src/types/test-case-schema.ts
|
|
1505
|
-
import { z as z2 } from "zod";
|
|
1506
|
-
var TEST_CASE_SCHEMA_VERSION = 2;
|
|
1507
|
-
var externalKeySchema = z2.object({
|
|
1508
|
-
kind: z2.enum(["playwright-id", "path-title", "allure-history", "cairn-stable", "eval-id", "qase", "testrail"]),
|
|
1509
|
-
value: z2.string().min(1)
|
|
1510
|
-
});
|
|
1511
|
-
var manualStepSchema = z2.object({
|
|
1512
|
-
action: z2.string().min(1),
|
|
1513
|
-
expected: z2.string().min(1).optional()
|
|
1514
|
-
});
|
|
1515
|
-
var assertionResultRecordSchema = z2.object({
|
|
1516
|
-
type: z2.string().min(1),
|
|
1517
|
-
passed: z2.boolean(),
|
|
1518
|
-
score: z2.number().optional(),
|
|
1519
|
-
reason: z2.string().optional()
|
|
1520
|
-
});
|
|
1521
|
-
var manualCaseSchema = z2.object({
|
|
1522
|
-
type: z2.literal("manual"),
|
|
1523
|
-
steps: z2.array(manualStepSchema).min(1),
|
|
1524
|
-
expected: z2.string().min(1).optional()
|
|
1525
|
-
});
|
|
1526
|
-
var automatedCaseSchema = z2.object({
|
|
1527
|
-
type: z2.literal("automated"),
|
|
1528
|
-
specRef: z2.string().min(1)
|
|
1529
|
-
});
|
|
1530
|
-
var evalCaseSchema = z2.object({
|
|
1531
|
-
type: z2.literal("eval"),
|
|
1532
|
-
prompt: z2.string().min(1),
|
|
1533
|
-
goldenSetId: z2.string().min(1).optional(),
|
|
1534
|
-
assertions: z2.array(assertionResultRecordSchema).min(1)
|
|
1535
|
-
});
|
|
1536
|
-
var testCaseBaseSchema = z2.object({
|
|
1537
|
-
schemaVersion: z2.literal(TEST_CASE_SCHEMA_VERSION),
|
|
1538
|
-
id: z2.string().min(1),
|
|
1539
|
-
externalKeys: z2.array(externalKeySchema).optional(),
|
|
1540
|
-
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1541
|
-
is_flaky: z2.boolean().optional(),
|
|
1542
|
-
/** ADR 0045 / plune#1246 — optional, purely additive; schemaVersion stays 2. */
|
|
1543
|
-
is_muted: z2.boolean().optional()
|
|
1544
|
-
});
|
|
1545
|
-
var testCaseSchema = z2.discriminatedUnion("type", [
|
|
1546
|
-
testCaseBaseSchema.merge(manualCaseSchema),
|
|
1547
|
-
testCaseBaseSchema.merge(automatedCaseSchema),
|
|
1548
|
-
testCaseBaseSchema.merge(evalCaseSchema)
|
|
1549
|
-
]);
|
|
1550
|
-
function parseTestCase(value) {
|
|
1551
|
-
return testCaseSchema.parse(value);
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
// src/types/results.ts
|
|
1555
|
-
var ROW_INCONCLUSIVE = ["blocked", "skipped"];
|
|
1556
|
-
|
|
1557
|
-
// src/types/run-result-schema.ts
|
|
1558
1562
|
var RUN_RESULT_SCHEMA_VERSION = 1;
|
|
1559
1563
|
var binaryVerdictSchema = z3.object({
|
|
1560
1564
|
question: z3.string().min(1),
|
|
@@ -1592,6 +1596,9 @@ var summarySchema = z3.object({
|
|
|
1592
1596
|
passed: z3.number(),
|
|
1593
1597
|
failed: z3.number(),
|
|
1594
1598
|
errored: z3.number(),
|
|
1599
|
+
/** plune#1245. Optional and additive — a RunResult written before them validates unchanged. */
|
|
1600
|
+
blocked: z3.number().optional(),
|
|
1601
|
+
skipped: z3.number().optional(),
|
|
1595
1602
|
cost_usd: z3.number(),
|
|
1596
1603
|
duration_ms: z3.number()
|
|
1597
1604
|
});
|
package/dist/reporter-core.cjs
CHANGED
|
@@ -215,7 +215,7 @@ function createClient(opts) {
|
|
|
215
215
|
if (res.status === 429 && retryAfterMs(res) === null) {
|
|
216
216
|
last.kind = "invalid";
|
|
217
217
|
last.detail = "quota exceeded (no Retry-After)";
|
|
218
|
-
if (said.detail) last.detail += ` \u2014 ${said.detail}`;
|
|
218
|
+
if (said.detail) last.detail += ` \u2014 ${scrub(said.detail)}`;
|
|
219
219
|
break;
|
|
220
220
|
}
|
|
221
221
|
if (attempt < RETRY_DELAYS_MS.length) {
|
package/dist/reporter-core.js
CHANGED
|
@@ -166,7 +166,7 @@ function createClient(opts) {
|
|
|
166
166
|
if (res.status === 429 && retryAfterMs(res) === null) {
|
|
167
167
|
last.kind = "invalid";
|
|
168
168
|
last.detail = "quota exceeded (no Retry-After)";
|
|
169
|
-
if (said.detail) last.detail += ` \u2014 ${said.detail}`;
|
|
169
|
+
if (said.detail) last.detail += ` \u2014 ${scrub(said.detail)}`;
|
|
170
170
|
break;
|
|
171
171
|
}
|
|
172
172
|
if (attempt < RETRY_DELAYS_MS.length) {
|
package/package.json
CHANGED