toolroll 0.9.79 → 0.9.82
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/CHANGELOG.md +47 -0
- package/dist/cli.js +1 -0
- package/dist/commit-extract.d.ts +18 -0
- package/dist/commit-extract.js +39 -1
- package/dist/converse.d.ts +12 -0
- package/dist/converse.js +18 -2
- package/dist/deploy-gate.js +8 -0
- package/dist/eval-gate.d.ts +51 -0
- package/dist/eval-gate.js +199 -0
- package/dist/eval-hooks.d.ts +39 -0
- package/dist/eval-hooks.js +477 -0
- package/dist/eval-oracle-main.d.ts +1 -0
- package/dist/eval-oracle-main.js +31 -0
- package/dist/eval-oracle.d.ts +60 -0
- package/dist/eval-oracle.js +217 -0
- package/dist/eval-world.d.ts +17 -0
- package/dist/eval-world.js +97 -0
- package/dist/evals.d.ts +299 -0
- package/dist/evals.js +964 -0
- package/dist/exec.js +15 -1
- package/dist/flow-draft.js +4 -0
- package/dist/flow-sort.js +4 -0
- package/dist/github-jobs.d.ts +25 -0
- package/dist/github-jobs.js +22 -0
- package/dist/guides.js +12 -9
- package/dist/invoke.d.ts +1 -1
- package/dist/invoke.js +14 -0
- package/dist/lead.js +4 -1
- package/dist/memory-pass.js +4 -0
- package/dist/nightly-check.d.ts +4 -1
- package/dist/nightly-check.js +5 -2
- package/dist/nightly-github.d.ts +316 -0
- package/dist/nightly-github.js +1022 -0
- package/dist/operate.d.ts +91 -1
- package/dist/operate.js +158 -1
- package/dist/project-knowledge.d.ts +4 -4
- package/dist/provider.d.ts +3 -0
- package/dist/provider.js +9 -2
- package/dist/release-adapters.d.ts +21 -21
- package/dist/release-adapters.js +53 -20
- package/dist/release-auto.d.ts +1 -1
- package/dist/release-auto.js +26 -0
- package/dist/release-card.js +3 -0
- package/dist/release-cli.js +59 -3
- package/dist/release-view.d.ts +3 -0
- package/dist/release-view.js +2 -0
- package/dist/release.d.ts +36 -17
- package/dist/release.js +74 -24
- package/dist/reported-usage.d.ts +69 -0
- package/dist/reported-usage.js +97 -0
- package/dist/server/chat.js +4 -0
- package/dist/server/render-tasks.js +1 -0
- package/dist/server/tasks.js +8 -1
- package/dist/store.d.ts +109 -1
- package/dist/store.js +394 -4
- package/dist/subagents.js +4 -0
- package/dist/subscription-chat.d.ts +2 -0
- package/dist/subscription-chat.js +52 -13
- package/dist/task-sizing.js +4 -0
- package/dist/teardown-git.d.ts +9 -2
- package/dist/teardown-git.js +56 -33
- package/evals/cases/catalog/case.json +25 -0
- package/evals/cases/catalog/fixture/README.md +3 -0
- package/evals/cases/catalog/fixture/package.json +8 -0
- package/evals/cases/catalog/fixture/test/catalog.test.mjs +4 -0
- package/evals/cases/catalog/oracle.mjs +23 -0
- package/evals/cases/catalog/probe.mjs +10 -0
- package/evals/cases/catalog/source.md +9 -0
- package/evals/cases/csv-quoting/case.json +23 -0
- package/evals/cases/csv-quoting/fixture/README.md +3 -0
- package/evals/cases/csv-quoting/fixture/csv.js +1 -0
- package/evals/cases/csv-quoting/fixture/package.json +8 -0
- package/evals/cases/csv-quoting/fixture/test/csv.test.mjs +5 -0
- package/evals/cases/csv-quoting/oracle.mjs +14 -0
- package/evals/cases/csv-quoting/probe.mjs +9 -0
- package/evals/cases/csv-quoting/source.md +9 -0
- package/evals/cases/dedupe/case.json +23 -0
- package/evals/cases/dedupe/fixture/README.md +3 -0
- package/evals/cases/dedupe/fixture/dedupe.js +1 -0
- package/evals/cases/dedupe/fixture/package.json +8 -0
- package/evals/cases/dedupe/fixture/test/dedupe.test.mjs +5 -0
- package/evals/cases/dedupe/oracle.mjs +16 -0
- package/evals/cases/dedupe/probe.mjs +13 -0
- package/evals/cases/dedupe/source.md +9 -0
- package/evals/cases/endpoint/case.json +25 -0
- package/evals/cases/endpoint/fixture/README.md +3 -0
- package/evals/cases/endpoint/fixture/package.json +8 -0
- package/evals/cases/endpoint/fixture/test/endpoint.test.mjs +4 -0
- package/evals/cases/endpoint/oracle.mjs +27 -0
- package/evals/cases/endpoint/probe.mjs +10 -0
- package/evals/cases/endpoint/source.md +11 -0
- package/evals/cases/math-divide/case.json +23 -0
- package/evals/cases/math-divide/fixture/README.md +3 -0
- package/evals/cases/math-divide/fixture/package.json +8 -0
- package/evals/cases/math-divide/fixture/src/math.js +1 -0
- package/evals/cases/math-divide/fixture/test/math.test.js +5 -0
- package/evals/cases/math-divide/oracle.mjs +13 -0
- package/evals/cases/math-divide/probe.mjs +9 -0
- package/evals/cases/math-divide/source.md +9 -0
- package/evals/cases/math-multiply/case.json +23 -0
- package/evals/cases/math-multiply/fixture/README.md +3 -0
- package/evals/cases/math-multiply/fixture/package.json +8 -0
- package/evals/cases/math-multiply/fixture/src/math.js +2 -0
- package/evals/cases/math-multiply/fixture/test/math.test.js +5 -0
- package/evals/cases/math-multiply/oracle.mjs +12 -0
- package/evals/cases/math-multiply/probe.mjs +9 -0
- package/evals/cases/math-multiply/source.md +9 -0
- package/evals/cases/math-subtract/case.json +23 -0
- package/evals/cases/math-subtract/fixture/README.md +3 -0
- package/evals/cases/math-subtract/fixture/package.json +8 -0
- package/evals/cases/math-subtract/fixture/src/math.js +1 -0
- package/evals/cases/math-subtract/fixture/test/math.test.js +5 -0
- package/evals/cases/math-subtract/oracle.mjs +12 -0
- package/evals/cases/math-subtract/probe.mjs +9 -0
- package/evals/cases/math-subtract/source.md +9 -0
- package/evals/cases/merge-config/case.json +23 -0
- package/evals/cases/merge-config/fixture/README.md +3 -0
- package/evals/cases/merge-config/fixture/config.js +1 -0
- package/evals/cases/merge-config/fixture/package.json +8 -0
- package/evals/cases/merge-config/fixture/test/config.test.mjs +5 -0
- package/evals/cases/merge-config/oracle.mjs +28 -0
- package/evals/cases/merge-config/probe.mjs +15 -0
- package/evals/cases/merge-config/source.md +9 -0
- package/evals/cases/paginate/case.json +23 -0
- package/evals/cases/paginate/fixture/README.md +3 -0
- package/evals/cases/paginate/fixture/package.json +8 -0
- package/evals/cases/paginate/fixture/paginate.js +1 -0
- package/evals/cases/paginate/fixture/test/paginate.test.mjs +5 -0
- package/evals/cases/paginate/oracle.mjs +18 -0
- package/evals/cases/paginate/probe.mjs +13 -0
- package/evals/cases/paginate/source.md +9 -0
- package/evals/cases/round2-asks/case.json +24 -0
- package/evals/cases/round2-asks/fixture/README.md +3 -0
- package/evals/cases/round2-asks/fixture/package.json +8 -0
- package/evals/cases/round2-asks/fixture/src/math.js +1 -0
- package/evals/cases/round2-asks/fixture/test/math.test.js +5 -0
- package/evals/cases/round2-asks/source.md +11 -0
- package/evals/manifest.json +15 -0
- package/package.json +2 -1
package/dist/exec.js
CHANGED
|
@@ -1847,6 +1847,11 @@ export function runClaudeStreamJsonl(file, args, options = {}) {
|
|
|
1847
1847
|
let initLine = null;
|
|
1848
1848
|
let initIdentityLine = null;
|
|
1849
1849
|
let conflictingInitLine = null;
|
|
1850
|
+
/** v140: the first init's model, and the first top-level init naming another (the parser reads them as a conflict:
|
|
1851
|
+
* unknown, never one of them). Kept even within one session id. */
|
|
1852
|
+
let initModel = null;
|
|
1853
|
+
let initModelLine = null;
|
|
1854
|
+
let modelConflictLine = null;
|
|
1850
1855
|
let initSessionId = null;
|
|
1851
1856
|
let resultLine = null;
|
|
1852
1857
|
let resultOverflowed = false;
|
|
@@ -1955,6 +1960,15 @@ export function runClaudeStreamJsonl(file, args, options = {}) {
|
|
|
1955
1960
|
if (type === "system" && String(event["subtype"] ?? "") === "init" && topLevelEvent(event)) {
|
|
1956
1961
|
if (initLine === null)
|
|
1957
1962
|
initLine = line;
|
|
1963
|
+
const model = typeof event["model"] === "string" ? event["model"] : null;
|
|
1964
|
+
if (model !== null) {
|
|
1965
|
+
if (initModel === null) {
|
|
1966
|
+
initModel = model;
|
|
1967
|
+
initModelLine = line;
|
|
1968
|
+
}
|
|
1969
|
+
else if (model !== initModel && modelConflictLine === null)
|
|
1970
|
+
modelConflictLine = line;
|
|
1971
|
+
}
|
|
1958
1972
|
const id = transportSessionId(event["session_id"]);
|
|
1959
1973
|
let identityWitness = false;
|
|
1960
1974
|
if (id !== null) {
|
|
@@ -2052,7 +2066,7 @@ export function runClaudeStreamJsonl(file, args, options = {}) {
|
|
|
2052
2066
|
liveProviders.delete(child);
|
|
2053
2067
|
framing.finish();
|
|
2054
2068
|
live?.detach();
|
|
2055
|
-
const lines = [initLine, initIdentityLine, conflictingInitLine, accountedResultLine(), overflowLine]
|
|
2069
|
+
const lines = [initLine, initIdentityLine, conflictingInitLine, initModelLine, modelConflictLine, accountedResultLine(), overflowLine]
|
|
2056
2070
|
.filter((one) => one !== null)
|
|
2057
2071
|
.filter((line, index, all) => all.indexOf(line) === index);
|
|
2058
2072
|
const settlement = container === null ? Promise.resolve(null) : settleContainer(container, options);
|
package/dist/flow-draft.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* nothing is sent: a later zone shows it to a person, and a later step posts
|
|
8
8
|
* it ({{stage.<id>}}).
|
|
9
9
|
*/
|
|
10
|
+
import { inEvalWorld } from "./eval-gate.js";
|
|
10
11
|
import { redactSecretLines, scanForSecrets } from "./evidence.js";
|
|
11
12
|
import { run } from "./exec.js";
|
|
12
13
|
import { CLAUDE_NO_TOOLS_ARGS, CLAUDE_SIGNED_OUT, claudeJsonBody, claudeModelArgs, inScratchDir } from "./claude-print.js";
|
|
@@ -59,6 +60,9 @@ export function keptDraft(text) {
|
|
|
59
60
|
/** The production runner: Claude through the sign-in on this computer, with no tools, no MCP servers and no repository. */
|
|
60
61
|
export function claudeDraftRunner(runner = run) {
|
|
61
62
|
return request => inScratchDir("standing-orders-draft-", async (dir) => {
|
|
63
|
+
// An eval world makes no provider call it can't cap and record (eval-gate.ts).
|
|
64
|
+
if (inEvalWorld())
|
|
65
|
+
return { ok: false, said: "Drafts aren't written in an eval world." };
|
|
62
66
|
const started = Date.now();
|
|
63
67
|
const result = await runner("claude", [
|
|
64
68
|
"-p", "--output-format", "json", ...CLAUDE_NO_TOOLS_ARGS, ...claudeModelArgs(request.model),
|
package/dist/flow-sort.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* second, with how sure it is. It never writes text, so nothing it returns
|
|
8
8
|
* is instructions: an answer is only ever one of the zone's own options.
|
|
9
9
|
*/
|
|
10
|
+
import { inEvalWorld } from "./eval-gate.js";
|
|
10
11
|
import { redactSecretLines, scanForSecrets } from "./evidence.js";
|
|
11
12
|
import { SORT_ROUTE_KEY, sortKeyOf, sortNoteKeyOf } from "./contracts/flow.js";
|
|
12
13
|
import { readJevReply } from "./contracts/sort-answer.js";
|
|
@@ -51,6 +52,9 @@ export function sortRequest(sort, state) {
|
|
|
51
52
|
}
|
|
52
53
|
/** Ask Jev through OpenRouter. Trouble reaching it (or a refused key, or no credit) is a reason to try again, in words. */
|
|
53
54
|
export async function askJev(fetcher, key, request) {
|
|
55
|
+
// An eval world makes no provider call it can't gate and record (eval-gate.ts), so nothing is sent.
|
|
56
|
+
if (inEvalWorld())
|
|
57
|
+
return { ok: false, said: "An eval world makes no Jev call." };
|
|
54
58
|
const started = Date.now();
|
|
55
59
|
let response;
|
|
56
60
|
try {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub's own job records, read by the plane's gh (release-adapters.ts for a release's checks, nightly-github.ts for
|
|
3
|
+
* GitHub's nightly): what each step of a finished job did. Step numbers and outcomes are the runner's records; nothing
|
|
4
|
+
* the tested code prints is read.
|
|
5
|
+
*/
|
|
6
|
+
/** One job's step outcomes as GitHub's Actions API reports them. */
|
|
7
|
+
export type JobRecord = {
|
|
8
|
+
id: number;
|
|
9
|
+
status: string;
|
|
10
|
+
conclusion: string | null;
|
|
11
|
+
steps: {
|
|
12
|
+
number: number;
|
|
13
|
+
name: string;
|
|
14
|
+
status: string;
|
|
15
|
+
conclusion: string | null;
|
|
16
|
+
}[];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Whether a finished, unsuccessful job ended before any of the workflow's own steps ran: every step after GitHub's own
|
|
20
|
+
* first one ("Set up job", always number 1) never ran (no conclusion, or skipped) — leaving out only GitHub's own
|
|
21
|
+
* closing "Complete job" when it is the last step. Step numbers and outcomes are the runner's records; nothing the
|
|
22
|
+
* candidate prints is read. A job with no steps never reached one. Anything else (a step that ran, even the checkout)
|
|
23
|
+
* is not confirmed infrastructure.
|
|
24
|
+
*/
|
|
25
|
+
export declare function failedBeforeTests(job: JobRecord): boolean;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub's own job records, read by the plane's gh (release-adapters.ts for a release's checks, nightly-github.ts for
|
|
3
|
+
* GitHub's nightly): what each step of a finished job did. Step numbers and outcomes are the runner's records; nothing
|
|
4
|
+
* the tested code prints is read.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Whether a finished, unsuccessful job ended before any of the workflow's own steps ran: every step after GitHub's own
|
|
8
|
+
* first one ("Set up job", always number 1) never ran (no conclusion, or skipped) — leaving out only GitHub's own
|
|
9
|
+
* closing "Complete job" when it is the last step. Step numbers and outcomes are the runner's records; nothing the
|
|
10
|
+
* candidate prints is read. A job with no steps never reached one. Anything else (a step that ran, even the checkout)
|
|
11
|
+
* is not confirmed infrastructure.
|
|
12
|
+
*/
|
|
13
|
+
export function failedBeforeTests(job) {
|
|
14
|
+
if (job.status !== "completed" || job.conclusion === "success" || job.conclusion === null)
|
|
15
|
+
return false;
|
|
16
|
+
const steps = [...job.steps].sort((a, b) => a.number - b.number);
|
|
17
|
+
if (new Set(steps.map(one => one.number)).size !== steps.length)
|
|
18
|
+
return false;
|
|
19
|
+
const last = steps.at(-1);
|
|
20
|
+
const own = steps.filter(one => one.number > 1 && !(one === last && one.name === "Complete job" && steps.length > 1));
|
|
21
|
+
return own.every(one => one.status !== "in_progress" && (one.conclusion === null || one.conclusion === "skipped"));
|
|
22
|
+
}
|
package/dist/guides.js
CHANGED
|
@@ -473,20 +473,23 @@ with a time limit.
|
|
|
473
473
|
saved first; if either name doesn't answer as the new build, both go
|
|
474
474
|
back. It goes on only when the console, worker and both names run the
|
|
475
475
|
gated commit. A rerun relinks without deploying again.
|
|
476
|
-
8. **ci**: waits for every pull-request check on the gated commit:
|
|
477
|
-
|
|
478
|
-
|
|
476
|
+
8. **ci**: waits for every pull-request check on the gated commit: Node 24
|
|
477
|
+
on Ubuntu and macOS, the area lanes (Linux cgroup and fence, Windows,
|
|
478
|
+
git 2.41 and 2.47), and Node 22 on Ubuntu and macOS, which runs on a
|
|
479
|
+
release-* branch's pull request.
|
|
480
|
+
Pending, missing, skipped, cancelled or failed never merges, and main's
|
|
481
|
+
protection must require every one of them.
|
|
479
482
|
9. **merge**: squash-merges with the head pinned to the gated commit,
|
|
480
483
|
once main has nothing the branch lacks, then deletes the remote branch
|
|
481
484
|
only if its head still matches. A resumed merge also finishes this cleanup.
|
|
482
485
|
10. **tree**: main's merge commit must have exactly the gated tree, or
|
|
483
486
|
nothing is tagged.
|
|
484
|
-
11. **tag**: pushes \`v<version>\` on that merge commit.
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
12. **publish**: waits for npm, the GitHub release and the tag's
|
|
489
|
-
|
|
487
|
+
11. **tag**: pushes \`v<version>\` on that merge commit. The tag runs no
|
|
488
|
+
tests again: publish.yml's release proof reads GitHub's record that the
|
|
489
|
+
tagged tree is the merged pull request's head tree and passed every
|
|
490
|
+
required check there, and npm and GitHub publication need it.
|
|
491
|
+
12. **publish**: waits for npm, the GitHub release and the tag's release
|
|
492
|
+
proof and publish jobs; not main's own push run on the merge commit.
|
|
490
493
|
13. **homebrew**: the release is published once npm and the GitHub release
|
|
491
494
|
are verified. It proposes the tap's formula change (checksum from npm's
|
|
492
495
|
tarball) and looks at its checks once: \`Published; Homebrew pending\`
|
package/dist/invoke.d.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { type AgentSpec, type Invocation, type ProviderRunner, type AgentEnding } from "./provider.js";
|
|
20
20
|
import { type VersionProbe } from "./attest.js";
|
|
21
|
-
import type
|
|
21
|
+
import { type Store } from "./store.js";
|
|
22
22
|
import type { RunOptions } from "./exec.js";
|
|
23
23
|
import type { Runner } from "./worktree.js";
|
|
24
24
|
import { type NetworkFence, type SignInGrants } from "./agent-fence.js";
|
package/dist/invoke.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* (`adapterFor`), and only builder, planner, reviewer, and scout import
|
|
17
17
|
* `invokeAgent`.
|
|
18
18
|
*/
|
|
19
|
+
import { takeEvalDispatch } from "./eval-gate.js";
|
|
19
20
|
import { adapterFor, auditOf, claudePluginEnv, isolationUnsupported, ALL_CREDENTIAL_ENV } from "./provider.js";
|
|
20
21
|
import { readProviderKey, readAuthModeStrict, PROVIDER_KEY_ENV, OWN_KEY_ENV } from "./keys.js";
|
|
21
22
|
import { ACP_AGENTS, isAcpProvider, isKeyedProvider } from "./acp-agents.js";
|
|
@@ -26,6 +27,7 @@ import { attestProvider } from "./attest.js";
|
|
|
26
27
|
import { run as runCommand, runOwnerTag, streamsInput } from "./exec.js";
|
|
27
28
|
import { spawnSync } from "node:child_process";
|
|
28
29
|
import { currentContainment } from "./containment.js";
|
|
30
|
+
import { recordRunBillingBasis, recordRunCostUnknown, recordRunModelReported } from "./store.js";
|
|
29
31
|
import { witnessedRunner } from "./process-custody.js";
|
|
30
32
|
import { underStopWatch } from "./task-control.js";
|
|
31
33
|
import { childDatabaseEnv, isolatedChildDatabase, removeChildDatabase as removeAgentDatabase } from "./child-database.js";
|
|
@@ -153,6 +155,12 @@ export async function invokeAgent(store, runId, spec, invocation, options) {
|
|
|
153
155
|
if (recordedSessionId !== null && requestedResumeSessionId === null && startSessionId !== recordedSessionId) {
|
|
154
156
|
throw new Error(`run ${runId} already records session ${recordedSessionId} but this invocation neither resumes nor starts under it`);
|
|
155
157
|
}
|
|
158
|
+
// An eval world (eval-gate.ts, docs/plans/evals-nightly.md part C): every dispatch takes one of the attempt's slots,
|
|
159
|
+
// named for this run so the runner can match it to the run's record; past the case's limit nothing spawns. Outside
|
|
160
|
+
// an eval world this changes nothing.
|
|
161
|
+
const evalSlot = takeEvalDispatch(`run:${runId}`);
|
|
162
|
+
if (evalSlot.active && !evalSlot.ok)
|
|
163
|
+
return { kind: "refused", reason: "containment", providerVersion: null, diagnostic: evalSlot.why };
|
|
156
164
|
const adapter = adapterFor(spec.provider);
|
|
157
165
|
const { startSessionId: _untrustedStartSessionId, streamInput: _untrustedStreamInput, ...invocationWithoutStart } = invocation;
|
|
158
166
|
// Live input (live-input.ts): only Claude's builds, only through a transport that keeps stdin open. The brief is
|
|
@@ -715,6 +723,8 @@ export async function invokeAgent(store, runId, spec, invocation, options) {
|
|
|
715
723
|
// An ACP run bills as its admission stamp says (store.acpBillingOfRun): its agent's own plan, or metered.
|
|
716
724
|
const acpBilling = isAcpProvider(spec.provider) ? (store.acpBillingOfRun(runId)?.kind === "plan" ? "subscription" : "api-key") : null;
|
|
717
725
|
store.fixRunBilling(runId, acpBilling ?? (authMode === "api-key" ? "api-key" : evidence ?? billingOf(spec.provider, store.handle)), new Date());
|
|
726
|
+
// v141: whether that billing is this run's own evidence or this computer's default (a guess: unknown money).
|
|
727
|
+
recordRunBillingBasis(store, runId, acpBilling !== null || authMode === "api-key" || evidence !== null ? "evidence" : "default");
|
|
718
728
|
const envelope = adapter.parse(result.stdout);
|
|
719
729
|
store.stampAgentReportedUsage(runId, envelope.agentReportedUsage ?? null);
|
|
720
730
|
// An installed CLI too old for a build's own setup refuses its flags
|
|
@@ -765,6 +775,10 @@ export async function invokeAgent(store, runId, spec, invocation, options) {
|
|
|
765
775
|
// How many agent turns it took, where the provider reports it (docs/plans/run-efficiency.md); unknown stays NULL.
|
|
766
776
|
...(envelope.ending?.turns == null ? {} : { agentTurns: envelope.ending.turns + (options.accumulateUsage ? run.agentTurns ?? 0 : 0) }),
|
|
767
777
|
});
|
|
778
|
+
// v141: a turn whose cost wasn't reported leaves the run's money unknown for good (a sticky column, never the note).
|
|
779
|
+
recordRunCostUnknown(store, runId, envelope.costUnknown === true);
|
|
780
|
+
// v140: the exact model the provider's own events named (null: not reported); a resumed turn adds its own to the run's.
|
|
781
|
+
recordRunModelReported(store, runId, envelope.modelReported ?? null, options.accumulateUsage === true);
|
|
768
782
|
// How the attempt ended, classified HERE where the structural terminal
|
|
769
783
|
// still exists; a sign-in that no longer works pauses its provider.
|
|
770
784
|
// A run that failed within seconds having produced nothing is read for
|
package/dist/lead.js
CHANGED
|
@@ -509,7 +509,10 @@ export async function runLeadTurn(input) {
|
|
|
509
509
|
return fail("over-reservation", LEAD_FAILURE_COPY.overReserved, true);
|
|
510
510
|
}
|
|
511
511
|
finishStep({ state: "answered", tokensIn: answer.tokensIn, tokensOut: answer.tokensOut, settledMicrousd: stepSettled, replyBytes: Buffer.byteLength(answer.text, "utf8"),
|
|
512
|
-
cacheReadTokens: answer.cacheReadTokens ?? null, cacheWriteTokens: answer.cacheWriteTokens ?? null
|
|
512
|
+
cacheReadTokens: answer.cacheReadTokens ?? null, cacheWriteTokens: answer.cacheWriteTokens ?? null,
|
|
513
|
+
// v140: what the provider itself reported for this request (absent: unreported, kept NULL).
|
|
514
|
+
modelReported: answer.modelReported ?? null, providerTurns: answer.providerTurns ?? null, reportedCostUsd: answer.reportedCostUsd ?? null,
|
|
515
|
+
billingReported: answer.billingReported ?? null });
|
|
513
516
|
tokensIn += answer.tokensIn;
|
|
514
517
|
tokensOut += answer.tokensOut;
|
|
515
518
|
if (answer.cacheReadTokens === undefined)
|
package/dist/memory-pass.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* is the one writer, and it writes through the ordinary knowledge and
|
|
11
11
|
* decision stores so every edit keeps its revision.
|
|
12
12
|
*/
|
|
13
|
+
import { inEvalWorld } from './eval-gate.js';
|
|
13
14
|
import { createHash } from 'node:crypto';
|
|
14
15
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
15
16
|
import { homedir } from 'node:os';
|
|
@@ -188,6 +189,9 @@ export function analysisPrompt(surface, openGaps) {
|
|
|
188
189
|
/** The production analyser: one call through the configured chat provider, no tools, no history. */
|
|
189
190
|
export function defaultAnalyzer(store, options) {
|
|
190
191
|
return async (input) => {
|
|
192
|
+
// An eval world makes no provider call it can't record (eval-gate.ts, Codex round 1 #3): the backward pass waits.
|
|
193
|
+
if (inEvalWorld())
|
|
194
|
+
return { ok: false, problem: 'The backward pass makes no provider call in an eval world.' };
|
|
191
195
|
const config = store.getChatConfig();
|
|
192
196
|
if (config === null)
|
|
193
197
|
return { ok: false, problem: 'Chat is not configured; the backward pass uses the chat model.' };
|
package/dist/nightly-check.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export declare const NIGHTLY_ACCEPTANCE: readonly {
|
|
|
18
18
|
}[];
|
|
19
19
|
/** The ledger act that records a person's approval of a nightly check, keyed by its trigger. */
|
|
20
20
|
export declare const NIGHTLY_APPROVED = "nightly check approved";
|
|
21
|
+
/** The ledger act that records a person turning GitHub's nightly into release debt for a project (nightly-github.ts). */
|
|
22
|
+
export declare const GITHUB_NIGHTLY_ON = "github nightly debt on";
|
|
21
23
|
/** The digest a person's approval of the nightly signs: the trigger, the project, the schedule, the check-only terms
|
|
22
24
|
* and the fixed words each firing files. */
|
|
23
25
|
export declare function nightlyDigestOf(trigger: number, repo: string, schedule: string, check: MainCheck): string;
|
|
@@ -44,7 +46,8 @@ export declare const TRUSTED_MAIN_CLEAR_MS: number;
|
|
|
44
46
|
* last read failed, or when the read was of another remote than the one recorded now (review round 2).
|
|
45
47
|
*/
|
|
46
48
|
export declare function trustedMainOf(store: Store, repo: string, now: Date, maxAgeMs: number): string | null;
|
|
47
|
-
/** The watch loop's read of each project's recorded remote main that the nightly check
|
|
49
|
+
/** The watch loop's read of each project's recorded remote main that the nightly check, GitHub's nightly (its runs count
|
|
50
|
+
* only at commits on main's history) or main's debt needs, at most
|
|
48
51
|
* every 30 minutes. Each read is a fresh fetch into a private directory. A failed read forgets the last one. A good
|
|
49
52
|
* one hands its verified objects to the project's Git store (hardened git, content-addressed: git checks every object
|
|
50
53
|
* against its hash, and filing verifies the commit again), so the nightly can check a merge the checkout never pulled. */
|
package/dist/nightly-check.js
CHANGED
|
@@ -36,6 +36,8 @@ export const NIGHTLY_NOT = "Changing anything: this is a check only.";
|
|
|
36
36
|
export const NIGHTLY_ACCEPTANCE = Object.freeze([{ id: "c1", statement: "The full release check passes on main", how: null, evidence: ["check"] }]);
|
|
37
37
|
/** The ledger act that records a person's approval of a nightly check, keyed by its trigger. */
|
|
38
38
|
export const NIGHTLY_APPROVED = "nightly check approved";
|
|
39
|
+
/** The ledger act that records a person turning GitHub's nightly into release debt for a project (nightly-github.ts). */
|
|
40
|
+
export const GITHUB_NIGHTLY_ON = "github nightly debt on";
|
|
39
41
|
/** The digest a person's approval of the nightly signs: the trigger, the project, the schedule, the check-only terms
|
|
40
42
|
* and the fixed words each firing files. */
|
|
41
43
|
export function nightlyDigestOf(trigger, repo, schedule, check) {
|
|
@@ -91,14 +93,15 @@ export function trustedMainOf(store, repo, now, maxAgeMs) {
|
|
|
91
93
|
}
|
|
92
94
|
return sha;
|
|
93
95
|
}
|
|
94
|
-
/** The watch loop's read of each project's recorded remote main that the nightly check
|
|
96
|
+
/** The watch loop's read of each project's recorded remote main that the nightly check, GitHub's nightly (its runs count
|
|
97
|
+
* only at commits on main's history) or main's debt needs, at most
|
|
95
98
|
* every 30 minutes. Each read is a fresh fetch into a private directory. A failed read forgets the last one. A good
|
|
96
99
|
* one hands its verified objects to the project's Git store (hardened git, content-addressed: git checks every object
|
|
97
100
|
* against its hash, and filing verifies the commit again), so the nightly can check a merge the checkout never pulled. */
|
|
98
101
|
export async function refreshTrustedMains(store, root, now, runner = run) {
|
|
99
102
|
const repos = new Set([
|
|
100
103
|
...store.handle.prepare("SELECT DISTINCT repo FROM main_check_failure WHERE cleared_at IS NULL").all().map(row => String(row["repo"])),
|
|
101
|
-
...store.handle.prepare("SELECT DISTINCT repo FROM action_ledger WHERE action
|
|
104
|
+
...store.handle.prepare("SELECT DISTINCT repo FROM action_ledger WHERE action IN (?, ?) AND repo IS NOT NULL").all(NIGHTLY_APPROVED, GITHUB_NIGHTLY_ON).map(row => String(row["repo"])),
|
|
102
105
|
]);
|
|
103
106
|
let read = 0;
|
|
104
107
|
const remotes = new RemoteMains(store, runner, root);
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { GITHUB_NIGHTLY_ON } from "./nightly-check.js";
|
|
2
|
+
import { type Store } from "./store.js";
|
|
3
|
+
export { GITHUB_NIGHTLY_ON };
|
|
4
|
+
/** The one workflow file whose runs count: exactly this path, never one with an `@` suffix or another folder's. */
|
|
5
|
+
export declare const NIGHTLY_WORKFLOW_PATH = ".github/workflows/nightly.yml";
|
|
6
|
+
/** GitHub's re-run horizon: a counted run is read again for new attempts for this long. */
|
|
7
|
+
export declare const NIGHTLY_WATCH_MS: number;
|
|
8
|
+
/** Listing never goes further back than this: no run older than it can still be unfinished. */
|
|
9
|
+
export declare const NIGHTLY_LIST_HORIZON_MS: number;
|
|
10
|
+
/** Pages of runs one read lists at most; a longer backlog resumes on the next read. */
|
|
11
|
+
export declare const NIGHTLY_PAGES_PER_READ = 10;
|
|
12
|
+
/** A boundary's one bounded read (deploy, merge, pre-tag), and the background read's overall deadline. */
|
|
13
|
+
export declare const NIGHTLY_BOUNDARY_READ_MS = 20000;
|
|
14
|
+
export declare const NIGHTLY_BACKGROUND_READ_MS = 60000;
|
|
15
|
+
/** How often the watch loop reads each opted-in project's nightly. */
|
|
16
|
+
export declare const NIGHTLY_BACKGROUND_EVERY_MS: number;
|
|
17
|
+
export declare const SHARDS_PASSED_STEP = "Every shard passed";
|
|
18
|
+
export declare const SHARDS_COVERED_STEP = "Every shard ran the whole suite";
|
|
19
|
+
/** One GitHub REST read through the plane's own gh (release-adapters.ts githubReads), bounded by `timeoutMs`. */
|
|
20
|
+
export type GhRead = (path: string, timeoutMs: number) => Promise<{
|
|
21
|
+
ok: true;
|
|
22
|
+
body: unknown;
|
|
23
|
+
} | {
|
|
24
|
+
ok: false;
|
|
25
|
+
why: string;
|
|
26
|
+
}>;
|
|
27
|
+
/** Main as the plane read it from the recorded remote: whether a commit is on its first-parent history ("unknown" when
|
|
28
|
+
* main hasn't been read lately, the commit isn't here yet, or the read of main is older than `since` — a run created
|
|
29
|
+
* after main was read may be on a main that read hasn't seen), and whether one main commit contains another. */
|
|
30
|
+
export type MainHistory = {
|
|
31
|
+
/** `deadline`: wall-clock milliseconds by which the local history work stops ("unknown" then). */
|
|
32
|
+
onMain(sha: string, since: string, deadline: number): "yes" | "no" | "unknown";
|
|
33
|
+
/** Three-state, like onMain: "unknown" when history couldn't be read whole or the deadline passed. */
|
|
34
|
+
mainContains(sha: string, ancestor: string, deadline: number): "yes" | "no" | "unknown";
|
|
35
|
+
};
|
|
36
|
+
export type NightlyDeps = MainHistory & {
|
|
37
|
+
gh: GhRead;
|
|
38
|
+
now: () => Date;
|
|
39
|
+
};
|
|
40
|
+
/** One read inside a read's deadline. */
|
|
41
|
+
type Get = (path: string) => Promise<{
|
|
42
|
+
ok: true;
|
|
43
|
+
body: unknown;
|
|
44
|
+
} | {
|
|
45
|
+
ok: false;
|
|
46
|
+
why: string;
|
|
47
|
+
}>;
|
|
48
|
+
/** Whether a project opted in, as the plane recorded a person's step: the newest such ledger row, read strictly. */
|
|
49
|
+
export declare function githubNightlyOf(store: Store, repo: string): {
|
|
50
|
+
slug: string;
|
|
51
|
+
url: string;
|
|
52
|
+
record: number;
|
|
53
|
+
by: string;
|
|
54
|
+
at: string;
|
|
55
|
+
} | null;
|
|
56
|
+
/** Every project that ever opted in (a broken or superseded record still counts here: its debt still holds). */
|
|
57
|
+
export declare function githubNightlyRepos(store: Store): string[];
|
|
58
|
+
/** A lane's stable id: its workflow file and the required check's name when it was seeded. */
|
|
59
|
+
export declare const laneIdOf: (workflow: string, name: string) => string;
|
|
60
|
+
/** One lane per required check whose name no lane (by its name or an alias) answers to yet. A retired lane whose name
|
|
61
|
+
* is required again opens again. */
|
|
62
|
+
export declare function seedLanes(store: Store, repo: string, now: Date): void;
|
|
63
|
+
/** The live lane a job of `workflow` named `name` belongs to: a person's alias first (the newest for that name), then
|
|
64
|
+
* the lane seeded under it. Never a guess: anything else is no lane. */
|
|
65
|
+
export declare function resolveLane(store: Store, repo: string, workflow: string, name: string): string | null;
|
|
66
|
+
/** The name a lane is shown by: its newest alias, else the name it was seeded under. */
|
|
67
|
+
export declare function laneName(store: Store, repo: string, laneId: string): string;
|
|
68
|
+
/** `toolroll release nightly --github`: a person turns GitHub's nightly into release debt for this project. The
|
|
69
|
+
* repository is the project's recorded remote's, never the checkout's. */
|
|
70
|
+
export declare function optInGithubNightly(store: Store, input: {
|
|
71
|
+
repo: string;
|
|
72
|
+
as: string;
|
|
73
|
+
token: string;
|
|
74
|
+
}, now: Date): {
|
|
75
|
+
ok: true;
|
|
76
|
+
slug: string;
|
|
77
|
+
lanes: number;
|
|
78
|
+
} | {
|
|
79
|
+
ok: false;
|
|
80
|
+
message: string;
|
|
81
|
+
};
|
|
82
|
+
/** `--lane-alias <old-id> <new name>`: a person says a renamed job is the same lane. Open debt goes with the lane. */
|
|
83
|
+
export declare function aliasNightlyLane(store: Store, input: {
|
|
84
|
+
repo: string;
|
|
85
|
+
laneId: string;
|
|
86
|
+
name: string;
|
|
87
|
+
as: string;
|
|
88
|
+
token: string;
|
|
89
|
+
}, now: Date): {
|
|
90
|
+
ok: true;
|
|
91
|
+
} | {
|
|
92
|
+
ok: false;
|
|
93
|
+
message: string;
|
|
94
|
+
};
|
|
95
|
+
/** `--lane-retire <lane-id>`: a person retires a lane no required check names any more; its open debt closes,
|
|
96
|
+
* recorded as theirs. */
|
|
97
|
+
export declare function retireNightlyLane(store: Store, input: {
|
|
98
|
+
repo: string;
|
|
99
|
+
laneId: string;
|
|
100
|
+
as: string;
|
|
101
|
+
token: string;
|
|
102
|
+
}, now: Date): {
|
|
103
|
+
ok: true;
|
|
104
|
+
closed: number;
|
|
105
|
+
} | {
|
|
106
|
+
ok: false;
|
|
107
|
+
message: string;
|
|
108
|
+
};
|
|
109
|
+
type GhRun = {
|
|
110
|
+
id: number;
|
|
111
|
+
path: string;
|
|
112
|
+
repository: string | null;
|
|
113
|
+
headRepository: string | null;
|
|
114
|
+
headBranch: string | null;
|
|
115
|
+
headSha: string;
|
|
116
|
+
event: string;
|
|
117
|
+
status: string;
|
|
118
|
+
runAttempt: number;
|
|
119
|
+
createdAt: string;
|
|
120
|
+
};
|
|
121
|
+
type GhStep = {
|
|
122
|
+
number: number;
|
|
123
|
+
name: string;
|
|
124
|
+
status: string;
|
|
125
|
+
conclusion: string | null;
|
|
126
|
+
};
|
|
127
|
+
export type GhJob = {
|
|
128
|
+
id: number;
|
|
129
|
+
name: string;
|
|
130
|
+
status: string;
|
|
131
|
+
conclusion: string | null;
|
|
132
|
+
startedAt: string | null;
|
|
133
|
+
completedAt: string | null;
|
|
134
|
+
headSha: string;
|
|
135
|
+
runId: number;
|
|
136
|
+
runAttempt: number | null;
|
|
137
|
+
steps: GhStep[] | null;
|
|
138
|
+
};
|
|
139
|
+
/** Whether a run is one of the project's own nightly runs on main (everything but main's history, checked apart). */
|
|
140
|
+
export declare function nightlyRunBinds(run: Pick<GhRun, "path" | "repository" | "headRepository" | "headBranch" | "event" | "headSha">, slug: string): boolean;
|
|
141
|
+
export type Cause = "passed" | "test-failure" | "runner-failure" | "not-run";
|
|
142
|
+
/**
|
|
143
|
+
* Why a completed lane job ended as it did, from GitHub's own job and step records in the same attempt
|
|
144
|
+
* (evals-nightly.md, "Cause of a failure"). Fails closed: anything not positively the runner's is a test failure.
|
|
145
|
+
*/
|
|
146
|
+
export declare function causeOf(job: GhJob, attempt: readonly GhJob[]): Cause;
|
|
147
|
+
export type NightlyRead = {
|
|
148
|
+
ok: true;
|
|
149
|
+
listed: number;
|
|
150
|
+
checked: number;
|
|
151
|
+
complete: boolean;
|
|
152
|
+
} | {
|
|
153
|
+
ok: false;
|
|
154
|
+
why: string;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* One read of the project's GitHub nightly within `budgetMs`: list runs from the cursor, re-read the watch list (new
|
|
158
|
+
* and unfinished runs first, then the oldest-checked), record every completed lane job, open and clear failures. A
|
|
159
|
+
* failed call stops where it is; what was recorded stays, and the cursor never moves past a page it couldn't read.
|
|
160
|
+
*/
|
|
161
|
+
export declare function readGithubNightly(store: Store, repo: string, deps: NightlyDeps, budgetMs: number): Promise<NightlyRead>;
|
|
162
|
+
/** Every job of one exact attempt of one run, every page, each GitHub's record of that run, attempt and commit. Null
|
|
163
|
+
* when any page can't be read whole. */
|
|
164
|
+
export declare function readAttemptJobs(get: Get, slug: string, run: number, attempt: number, sha: string): Promise<GhJob[] | null>;
|
|
165
|
+
/** A recorded open failure of a lane. */
|
|
166
|
+
export type LaneFailure = {
|
|
167
|
+
id: number;
|
|
168
|
+
repo: string;
|
|
169
|
+
laneId: string;
|
|
170
|
+
ghRun: number;
|
|
171
|
+
attempt: number;
|
|
172
|
+
jobId: number;
|
|
173
|
+
sha: string;
|
|
174
|
+
completedAt: string;
|
|
175
|
+
openedAt: string;
|
|
176
|
+
};
|
|
177
|
+
export declare function openFailures(store: Store, repo: string): LaneFailure[];
|
|
178
|
+
/**
|
|
179
|
+
* Clear each open failure that a later counted nightly run passed: a run created after the failed run (a rerun of an
|
|
180
|
+
* older run never clears newer debt; Codex round 1, finding 2), the same lane, a job started after the failed one
|
|
181
|
+
* completed, on a commit that contains the failed one. A re-run inside the same run never clears. Local history work
|
|
182
|
+
* stops at `wall` (wall-clock ms); what is left is settled on a later read.
|
|
183
|
+
*/
|
|
184
|
+
export declare function settleGithubNightly(store: Store, repo: string, history: Pick<MainHistory, "mainContains">, now: Date, wall?: number): {
|
|
185
|
+
cleared: number;
|
|
186
|
+
complete: boolean;
|
|
187
|
+
unresolved: string | null;
|
|
188
|
+
};
|
|
189
|
+
/** Main's history as the plane read it from the project's recorded remote (nightly-check.ts trustedMainOf), from the
|
|
190
|
+
* verified objects in the project's own Git store; never a ref a build could move. */
|
|
191
|
+
export declare function mainHistoryOf(store: Store, repo: string, now: Date): MainHistory;
|
|
192
|
+
/**
|
|
193
|
+
* The watch loop's background read (operate.ts refreshGithubNightlies): each opted-in project at most every
|
|
194
|
+
* NIGHTLY_BACKGROUND_EVERY_MS, claimed in the store so two processes don't both read, within one overall deadline.
|
|
195
|
+
*/
|
|
196
|
+
export declare function readGithubNightlies(store: Store, deps: {
|
|
197
|
+
gh: GhRead;
|
|
198
|
+
now: () => Date;
|
|
199
|
+
history?: (repo: string, now: Date) => MainHistory;
|
|
200
|
+
}, budgetMs?: number): Promise<number>;
|
|
201
|
+
/** What a hold stops: a deploy, the merge, the tag (pre-tag authorization), or an automatic approval (sealAutoGreen). */
|
|
202
|
+
export type NightlyPhase = "deploy" | "merge" | "tag" | "auto";
|
|
203
|
+
/** How long a boundary's re-read of a candidate's exemption stands for the stored checks inside the reservation, the
|
|
204
|
+
* deployment gate and the installed runtime's deploy check after it. */
|
|
205
|
+
export declare const EXEMPTION_FRESH_MS: number;
|
|
206
|
+
/** "Oct 30, 06:17 UTC". */
|
|
207
|
+
export declare const nightlyStamp: (iso: string) => string;
|
|
208
|
+
/** The words of a nightly hold: the first open failure, how many more, and the way out at this point. */
|
|
209
|
+
export declare function nightlyDebtWords(store: Store, held: readonly LaneFailure[], phase: NightlyPhase, release: boolean): string;
|
|
210
|
+
/**
|
|
211
|
+
* The stored check every boundary makes, inside the caller's own transaction where it has one (the deployment gate, the
|
|
212
|
+
* deploy and merge reservations, the pre-tag step, an automatic approval): the project's open lane failures, less those
|
|
213
|
+
* this exact task and candidate hold a fresh exemption for. Null when nothing holds. A project that never opted in has
|
|
214
|
+
* no lane failures.
|
|
215
|
+
*/
|
|
216
|
+
export declare function nightlyDebtHold(store: Store, input: {
|
|
217
|
+
repo: string;
|
|
218
|
+
taskId: string | null;
|
|
219
|
+
candidate: string | null;
|
|
220
|
+
phase: NightlyPhase;
|
|
221
|
+
release: boolean;
|
|
222
|
+
now: Date;
|
|
223
|
+
}): {
|
|
224
|
+
why: string;
|
|
225
|
+
failures: LaneFailure[];
|
|
226
|
+
} | null;
|
|
227
|
+
/** How the project's GitHub nightly stands: whether it is on, when it was last read (and why not), when it last ran. */
|
|
228
|
+
export type NightlyStatus = {
|
|
229
|
+
on: boolean;
|
|
230
|
+
lastOkAt: string | null;
|
|
231
|
+
lastWhy: string | null;
|
|
232
|
+
lastRunAt: string | null;
|
|
233
|
+
stale: boolean;
|
|
234
|
+
};
|
|
235
|
+
/** No nightly run seen for this long reads "hasn't run since". */
|
|
236
|
+
export declare const NIGHTLY_STALE_MS: number;
|
|
237
|
+
export declare function githubNightlyStatus(store: Store, repo: string, now: Date): NightlyStatus;
|
|
238
|
+
/** A warning that never holds anything (Decision 1): GitHub couldn't be read, or the nightly hasn't run lately. */
|
|
239
|
+
export declare function nightlyWarning(status: NightlyStatus, now: Date): string | null;
|
|
240
|
+
/** One workflow's newest pull-request run on a candidate head, as an exemption reads it. */
|
|
241
|
+
export type LaneJobs = {
|
|
242
|
+
run: number;
|
|
243
|
+
attempt: number;
|
|
244
|
+
status: string;
|
|
245
|
+
jobs: GhJob[];
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* A release candidate's own pull-request CI, as an exemption needs it (modelled on scripts/release-proof.mjs): for each
|
|
249
|
+
* workflow, the newest run on `head` from that pull request's `pull_request` event, that run's latest attempt's jobs
|
|
250
|
+
* with their times, then the run read again. The newest run is chosen first: one that doesn't bind to this pull
|
|
251
|
+
* request never lets an older run stand. `null` for a workflow with no such run; "unreadable" when anything can't be
|
|
252
|
+
* read whole or changed during the read.
|
|
253
|
+
*/
|
|
254
|
+
export declare function readLaneJobs(get: Get, slug: string, pr: number, head: string, workflows: readonly string[]): Promise<Map<string, LaneJobs | null> | "unreadable">;
|
|
255
|
+
/** The files a lane's job runs that the candidate could otherwise rewrite to make a job of that name pass: its workflow
|
|
256
|
+
* file and the CI scripts the workflows call. An exemption stands only when each is byte-identical (the same Git
|
|
257
|
+
* blob) on the candidate and at the failed commit. The tests themselves are the candidate's, as for every required
|
|
258
|
+
* check (the trust the required-checks gate already places in them). */
|
|
259
|
+
export declare const LANE_PINNED_FILES: readonly ["scripts/ci-shards.mjs", "scripts/ci-scope.mjs", "scripts/ci-git.sh", "scripts/ci-no-skips.mjs"];
|
|
260
|
+
export type NightlyBoundary = {
|
|
261
|
+
ok: true;
|
|
262
|
+
warning: string | null;
|
|
263
|
+
} | {
|
|
264
|
+
ok: false;
|
|
265
|
+
why: string;
|
|
266
|
+
warning: string | null;
|
|
267
|
+
};
|
|
268
|
+
/**
|
|
269
|
+
* A boundary (the coordinator's deploy, merge and pre-tag steps): one bounded read of GitHub's nightly, then this
|
|
270
|
+
* candidate's exemptions read again from its own pull-request CI — minted only before the merge (`deploy`, `merge`);
|
|
271
|
+
* at the tag an exemption obtained before the merge is re-read, never made — then the stored debt. A read that fails is
|
|
272
|
+
* a warning and the stored debt still holds; an exemption that can't be re-read is no exemption here.
|
|
273
|
+
*/
|
|
274
|
+
export declare function nightlyBoundary(store: Store, input: {
|
|
275
|
+
repo: string;
|
|
276
|
+
taskId: string;
|
|
277
|
+
candidate: string;
|
|
278
|
+
pr: number;
|
|
279
|
+
phase: Exclude<NightlyPhase, "auto">;
|
|
280
|
+
}, deps: NightlyDeps, budgetMs?: number): Promise<NightlyBoundary>;
|
|
281
|
+
/** One project-level Needs-you item: an open GitHub nightly lane failure, or a nightly check of main that failed. */
|
|
282
|
+
export type NightlyNeed = {
|
|
283
|
+
key: string;
|
|
284
|
+
repo: string;
|
|
285
|
+
title: string;
|
|
286
|
+
reason: string;
|
|
287
|
+
href: string;
|
|
288
|
+
since: string;
|
|
289
|
+
};
|
|
290
|
+
/**
|
|
291
|
+
* Needs you, for the projects `shown` admits: one item per open GitHub nightly lane failure (linking to its job on
|
|
292
|
+
* GitHub, under the opted-in repository the plane recorded), and one per nightly check of main with open failures
|
|
293
|
+
* (linking to its task). Oldest first.
|
|
294
|
+
*/
|
|
295
|
+
export declare function nightlyNeedsYou(store: Store, shown: (repo: string) => boolean): NightlyNeed[];
|
|
296
|
+
/** The release card's GitHub nightly lines: each open lane failure (held, or exempted for this candidate), then a
|
|
297
|
+
* warning when GitHub couldn't be read or the nightly hasn't run lately. Empty when there is nothing to say. */
|
|
298
|
+
export declare function nightlyReleaseLines(store: Store, input: {
|
|
299
|
+
repo: string;
|
|
300
|
+
taskId: string;
|
|
301
|
+
candidate: string | null;
|
|
302
|
+
now: Date;
|
|
303
|
+
}): string[];
|
|
304
|
+
/**
|
|
305
|
+
* A deploy run's own boundary (scripts/deploy-browser.mjs, through the installed runtime; Codex round 1, finding 3):
|
|
306
|
+
* the same bounded read as the coordinator's — GitHub's nightly, then this candidate's exemptions re-read — before the
|
|
307
|
+
* stored check, so a deploy started by hand neither misses a new failure nor rides an exemption its CI no longer
|
|
308
|
+
* supports. A task no release covers has no exemption to re-read; its nightly is still read. Anything that fails here
|
|
309
|
+
* takes away the candidate's stored exemptions; the stored check that follows decides.
|
|
310
|
+
*/
|
|
311
|
+
export declare function refreshNightlyForDeploy(store: Store, input: {
|
|
312
|
+
runId: number;
|
|
313
|
+
now: () => Date;
|
|
314
|
+
gh?: GhRead;
|
|
315
|
+
budgetMs?: number;
|
|
316
|
+
}): Promise<NightlyBoundary | null>;
|