balladeer 1.0.16 → 1.0.18
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/dist/anchor-budget.d.ts +40 -0
- package/dist/anchor-budget.js +110 -0
- package/dist/anchoring.d.ts +241 -0
- package/dist/anchoring.js +766 -0
- package/dist/anchors-client.d.ts +62 -0
- package/dist/anchors-client.js +197 -0
- package/dist/anchors-schema.d.ts +85 -0
- package/dist/anchors-schema.js +246 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +24 -7
- package/dist/commands/anchor-usage.d.ts +6 -0
- package/dist/commands/anchor-usage.js +19 -0
- package/dist/commands/anchor.d.ts +127 -0
- package/dist/commands/anchor.js +303 -0
- package/dist/commands/guidance.d.ts +2 -1
- package/dist/commands/guidance.js +55 -0
- package/dist/commands/judge.d.ts +219 -12
- package/dist/commands/judge.js +911 -103
- package/dist/commands/map.d.ts +46 -2
- package/dist/commands/map.js +244 -5
- package/dist/commands/mcp.js +2 -2
- package/dist/guidance-hook.mjs +282 -95
- package/dist/guidance.d.ts +7 -0
- package/dist/guidance.js +10 -1
- package/dist/headless-agent.d.ts +19 -1
- package/dist/headless-agent.js +22 -5
- package/dist/hook-trust.d.ts +41 -9
- package/dist/hook-trust.js +98 -16
- package/dist/judge-brief.d.ts +33 -3
- package/dist/judge-brief.js +39 -2
- package/dist/judge-hook.d.ts +188 -14
- package/dist/judge-hook.js +919 -61
- package/dist/judge-said.d.ts +52 -0
- package/dist/judge-said.js +181 -0
- package/dist/promise-meaning.d.ts +25 -0
- package/dist/promise-meaning.js +24 -7
- package/dist/relay.d.ts +71 -0
- package/dist/relay.js +193 -0
- package/dist/remove-earlier.js +4 -2
- package/dist/risk/git.d.ts +3 -1
- package/dist/risk/git.js +3 -3
- package/dist/risk/graph-cache.d.ts +83 -0
- package/dist/risk/graph-cache.js +291 -0
- package/dist/risk/import-graph.d.ts +43 -0
- package/dist/risk/import-graph.js +88 -34
- package/dist/risk/index.d.ts +1 -1
- package/dist/risk/index.js +1 -1
- package/dist/risk/pipeline.d.ts +13 -0
- package/dist/risk/pipeline.js +15 -4
- package/dist/risk/score.d.ts +10 -0
- package/dist/risk/score.js +11 -2
- package/dist/scratch-worktree.d.ts +5 -1
- package/dist/scratch-worktree.js +9 -2
- package/dist/user-scope.d.ts +74 -3
- package/dist/user-scope.js +270 -9
- package/dist/wire.d.ts +19 -3
- package/dist/wire.js +2 -2
- package/package.json +7 -2
package/dist/commands/judge.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import type { AnchorBudget } from "../anchor-budget.js";
|
|
2
|
+
import type { AnchorsClient } from "../anchors-client.js";
|
|
1
3
|
import { type BehaviorMap } from "../behavior-map-schema.js";
|
|
2
4
|
import { type HeadlessAgentOptions, type HeadlessAgentResult, type HeadlessClient, type LoginCheck } from "../headless-agent.js";
|
|
3
|
-
import { type HookHost } from "../judge-hook.js";
|
|
5
|
+
import { type HookHost, type MergeTarget } from "../judge-hook.js";
|
|
4
6
|
import { type PromiseDocument, type PromiseReader } from "../promise-meaning.js";
|
|
7
|
+
import type { RepositoryGraph } from "../risk/graph-cache.js";
|
|
8
|
+
import { type CarriedFile } from "../scratch-worktree.js";
|
|
9
|
+
import type { Features } from "../risk/contract.js";
|
|
10
|
+
import type { AnchorStage, JudgeAnchors } from "./anchor.js";
|
|
5
11
|
/**
|
|
6
12
|
* `balladeer judge`: for a change about to leave this machine, ask the person's
|
|
7
13
|
* own coding agent, one promise at a time, whether the change keeps it.
|
|
@@ -18,7 +24,15 @@ export declare const JUDGE_VERDICT_SCHEMA_VERSION = "balladeer-judge-verdict/v1"
|
|
|
18
24
|
export declare const JUDGE_CONFIG_SCHEMA_VERSION = "balladeer-judge-config/v1";
|
|
19
25
|
export declare const JUDGE_CONFIG_PATH = ".continuity/judge.json";
|
|
20
26
|
export declare const JUDGE_LOG_DIRECTORY = ".continuity/judge-log";
|
|
27
|
+
/**
|
|
28
|
+
* Where a verified reproduction's files are kept, one folder per promise and
|
|
29
|
+
* pushed commit, inside the judge log so git ignores them like the log itself.
|
|
30
|
+
*/
|
|
31
|
+
export declare const KEPT_REPRODUCTIONS_DIRECTORY = ".continuity/judge-log/reproductions";
|
|
32
|
+
export declare const KEPT_REPRODUCTION_SCHEMA_VERSION = "balladeer-kept-reproduction/v1";
|
|
21
33
|
export declare const STILL_JUDGING = "still judging; rerun `balladeer judge --wait`";
|
|
34
|
+
/** Block mode's answer to a line that commits and then pushes: the check runs before the line. */
|
|
35
|
+
export declare const COMMIT_THEN_PUSH = "Held: this command makes a commit and then pushes it, and the check runs before the command, so it cannot see a commit that has not been made yet. Commit first, then push in a separate command.";
|
|
22
36
|
export type JudgeConfig = Readonly<{
|
|
23
37
|
schemaVersion: typeof JUDGE_CONFIG_SCHEMA_VERSION;
|
|
24
38
|
mode: "report" | "block";
|
|
@@ -28,6 +42,13 @@ export type JudgeConfig = Readonly<{
|
|
|
28
42
|
sampleBelowLine: number;
|
|
29
43
|
alwaysJudge: readonly string[];
|
|
30
44
|
client: HeadlessClient | "auto";
|
|
45
|
+
/**
|
|
46
|
+
* Which promises the risk report hands to a judge: "direct" (the default)
|
|
47
|
+
* takes every promise whose own code or tests the change edits, and nothing
|
|
48
|
+
* else; "ranked" takes the top `topK` in the report's order plus a random
|
|
49
|
+
* sample below that line.
|
|
50
|
+
*/
|
|
51
|
+
select: "direct" | "ranked";
|
|
31
52
|
/**
|
|
32
53
|
* From the push hook, also read the change for rules no promise records and
|
|
33
54
|
* hand at most three to the pushing session as offers. Off unless set.
|
|
@@ -64,10 +85,25 @@ export type JudgeVerdict = {
|
|
|
64
85
|
failsOnHead: boolean;
|
|
65
86
|
passesOnBase: boolean;
|
|
66
87
|
digest: string;
|
|
88
|
+
/**
|
|
89
|
+
* Where the reproduction was kept on this machine, repository-relative:
|
|
90
|
+
* a folder holding `manifest.json` and, under `files/`, the files the
|
|
91
|
+
* judge added, at the paths it wrote them. Only for a break verified both
|
|
92
|
+
* ways, and absent when keeping it failed.
|
|
93
|
+
*/
|
|
94
|
+
keptIn?: string;
|
|
95
|
+
/** The kept files' repository-relative paths, each under `<keptIn>/files/`. */
|
|
96
|
+
keptFiles?: string[];
|
|
67
97
|
} | null;
|
|
68
98
|
reproductionRejected: string | null;
|
|
69
99
|
exercisedCases: string[];
|
|
70
100
|
notes: string;
|
|
101
|
+
/**
|
|
102
|
+
* On a could-not-tell the judge itself reached because the tests need
|
|
103
|
+
* something this machine lacks: the one step that would let them run, as
|
|
104
|
+
* the judge wrote it. Absent otherwise. It never changes the verdict.
|
|
105
|
+
*/
|
|
106
|
+
nextStep?: string;
|
|
71
107
|
judge: {
|
|
72
108
|
client: HeadlessClient;
|
|
73
109
|
model: string;
|
|
@@ -77,6 +113,8 @@ export type JudgeVerdict = {
|
|
|
77
113
|
};
|
|
78
114
|
briefRevision: string;
|
|
79
115
|
mapUsed: boolean;
|
|
116
|
+
/** The judge was handed the promise's anchors and their neighborhood, where it had no map. */
|
|
117
|
+
anchorsUsed?: boolean;
|
|
80
118
|
linkedTestRun: {
|
|
81
119
|
file: string;
|
|
82
120
|
outcome: "pass" | "fail" | "error" | "none";
|
|
@@ -101,6 +139,8 @@ export type ReproductionCheck = Readonly<{
|
|
|
101
139
|
rejected: string | null;
|
|
102
140
|
/** The budget ran out while it was being run, so there is no answer yet. */
|
|
103
141
|
stopped: boolean;
|
|
142
|
+
/** The files the judge added, carried to base and fingerprinted into `digest`. */
|
|
143
|
+
files: readonly CarriedFile[];
|
|
104
144
|
}>;
|
|
105
145
|
/**
|
|
106
146
|
* Run a judge's reproduction both ways.
|
|
@@ -123,6 +163,42 @@ export declare function verifyReproduction(input: Readonly<{
|
|
|
123
163
|
signal?: AbortSignal;
|
|
124
164
|
scratch?: string;
|
|
125
165
|
}>): Promise<ReproductionCheck>;
|
|
166
|
+
export type KeptReproduction = Readonly<{
|
|
167
|
+
/** Repository-relative, forward slashes: the folder under the judge log. */
|
|
168
|
+
keptIn: string;
|
|
169
|
+
/** The files kept, repository-relative, each at `<keptIn>/files/<path>`. */
|
|
170
|
+
files: string[];
|
|
171
|
+
}>;
|
|
172
|
+
/**
|
|
173
|
+
* Keep a verified reproduction on this machine, so the break can become a
|
|
174
|
+
* lasting test instead of vanishing with the judge's checkout.
|
|
175
|
+
*
|
|
176
|
+
* The files the judge added are copied from its checkout into
|
|
177
|
+
* `.continuity/judge-log/reproductions/<promise id>-<first 12 of head>/files/`
|
|
178
|
+
* at the paths the judge wrote them, beside a `manifest.json` that says which
|
|
179
|
+
* promise, meaning and change they reproduce a break of, with the command,
|
|
180
|
+
* its cwd, the digest and each file's own fingerprint. The digest can be
|
|
181
|
+
* recomputed from the manifest alone. A reproduction that added no files
|
|
182
|
+
* keeps just the manifest. The judge log carries its own `.gitignore`, so
|
|
183
|
+
* nothing here is ever committed, and nothing here is sent anywhere.
|
|
184
|
+
*
|
|
185
|
+
* The folder is written beside its final name and then renamed into place,
|
|
186
|
+
* replacing an earlier one for the same promise and commit, so a reader never
|
|
187
|
+
* sees half of one. Keeping is a courtesy to the person, never a condition of
|
|
188
|
+
* the verdict: when it fails, the verdict stands and says nothing was kept.
|
|
189
|
+
*/
|
|
190
|
+
export declare function keepReproduction(input: Readonly<{
|
|
191
|
+
root: string;
|
|
192
|
+
headTree: string;
|
|
193
|
+
promiseId: string;
|
|
194
|
+
semanticDigest: string;
|
|
195
|
+
base: string;
|
|
196
|
+
head: string;
|
|
197
|
+
command: string;
|
|
198
|
+
cwd: string;
|
|
199
|
+
digest: string;
|
|
200
|
+
files: readonly CarriedFile[];
|
|
201
|
+
}>): KeptReproduction | undefined;
|
|
126
202
|
/**
|
|
127
203
|
* How this repository runs one test file, when it can be told from the files
|
|
128
204
|
* alone. A runner that cannot be told is `none`, and the judge is left to find
|
|
@@ -137,13 +213,19 @@ type JudgeAnswer = Readonly<{
|
|
|
137
213
|
}>;
|
|
138
214
|
exercisedCases: string[];
|
|
139
215
|
notes: string;
|
|
216
|
+
nextStep?: string;
|
|
140
217
|
}>;
|
|
218
|
+
/** The longest `nextStep` kept from a judge's answer, in characters. */
|
|
219
|
+
export declare const NEXT_STEP_LIMIT = 500;
|
|
141
220
|
/** The judge's final JSON, read strictly enough that a malformed answer is not a verdict. */
|
|
142
221
|
export declare function readJudgeAnswer(json: Record<string, unknown> | undefined): JudgeAnswer | undefined;
|
|
222
|
+
export type { JudgeAnchors } from "./anchor.js";
|
|
143
223
|
export type JudgePromiseInput = Readonly<{
|
|
144
224
|
root: string;
|
|
145
225
|
promise: PromiseDocument;
|
|
146
226
|
map?: BehaviorMap;
|
|
227
|
+
/** Handed only when there is no map. */
|
|
228
|
+
anchors?: JudgeAnchors;
|
|
147
229
|
base: string;
|
|
148
230
|
head: string;
|
|
149
231
|
changedFiles: readonly string[];
|
|
@@ -180,6 +262,10 @@ export type JudgeArguments = Readonly<{
|
|
|
180
262
|
mode?: "report" | "block";
|
|
181
263
|
wait: boolean;
|
|
182
264
|
hook?: HookHost;
|
|
265
|
+
/** Run by the entry setup writes at the host's user scope, which stands aside where it has nothing to do. */
|
|
266
|
+
userScope?: true;
|
|
267
|
+
/** Turn this laptop's user-scope push check on or off. */
|
|
268
|
+
pushCheck?: "on" | "off";
|
|
183
269
|
installHook?: HookHost | "agents";
|
|
184
270
|
fromFile?: string;
|
|
185
271
|
map?: string;
|
|
@@ -188,13 +274,20 @@ export type JudgeArguments = Readonly<{
|
|
|
188
274
|
repository?: string;
|
|
189
275
|
controlPlane: string;
|
|
190
276
|
}>;
|
|
191
|
-
export declare const JUDGE_USAGE = " npx -y balladeer@latest judge [--promises <id,id>] [--top <k>] [--base <ref>] [--head <ref>]\n [--report-only | --block] [--wait] [--json] [--client auto|claude|codex]\n [--from-file <promise.json> [--map <map.json>]]\n [--hook claude|codex|git] [--install-hook [claude|codex|git]]\n Judge whether this change keeps the promises it could break, one promise\n at a time, on your own Claude Code or Codex login. A break counts only\n with a command that fails with the change and passes without it, and\n this command runs it both ways itself; anything unproven is \"could not\n tell\". Report mode prints one line per promise and never stops anything;\n --block exits 2 on a reproduced break, and when judges are still running\n at the time limit it holds the push rather than letting it through.\n --wait runs without the time limit. Promises come from --promises, else\n
|
|
277
|
+
export declare const JUDGE_USAGE = " npx -y balladeer@latest judge [--promises <id,id>] [--top <k>] [--base <ref>] [--head <ref>]\n [--report-only | --block] [--wait] [--json] [--client auto|claude|codex]\n [--from-file <promise.json> [--map <map.json>]]\n [--hook claude|codex|git] [--install-hook [claude|codex|git]]\n [--push-check on|off]\n Judge whether this change keeps the promises it could break, one promise\n at a time, on your own Claude Code or Codex login. A break counts only\n with a command that fails with the change and passes without it, and\n this command runs it both ways itself; anything unproven is \"could not\n tell\". Report mode prints one line per promise and never stops anything;\n --block exits 2 on a reproduced break, and when judges are still running\n at the time limit it holds the push rather than letting it through.\n --wait runs without the time limit. Promises come from --promises, else\n every agreed promise whose anchored code the change edits, and every\n promise with a behavior map whose own code or tests it edits (with\n \"select\": \"ranked\" in .continuity/judge.json, the top of the maps'\n ranking and a small random sample); plus that file's alwaysJudge. A\n promise with no anchors yet is anchored first, by one small call on\n your own login (see `balladeer anchor`), at most 20 a day on this\n laptop, and a line says what that cost. Verdicts are kept in\n .continuity/judge-log/, which git ignores. --install-hook adds the push\n hook to .claude/settings.json and .codex/hooks.json, before and after\n each shell command: report mode judges after a push has landed, so the\n push never waits, and block mode judges before it. With git it writes\n .git/hooks/pre-push, which judges before the push in both modes. With\n \"offers\": true in .continuity/judge.json, the push hook also reads the\n change for rules no promise records and offers at most three to\n whoever is pushing; it records nothing and never holds a push (see\n `balladeer offers`). Setup also writes the same pair of entries at\n each host's user scope, running `judge --hook <host> --user-scope`,\n so the check runs in every connected repository with agreed promises\n and says nothing anywhere else; a checkout with its own entry keeps\n the check to that entry. --push-check off turns the user-scope check\n off on this laptop, and --push-check on turns it back on.\n";
|
|
192
278
|
export declare function parseJudgeArguments(argv: readonly string[]): JudgeArguments;
|
|
193
|
-
/**
|
|
279
|
+
/**
|
|
280
|
+
* The subset of `balladeer-risk/v1` this command reads: enough to order the
|
|
281
|
+
* entries the way `balladeer risk` does. An entry without `features` reads as
|
|
282
|
+
* reaching its promise not at all, and one without `evidence` as none.
|
|
283
|
+
*/
|
|
194
284
|
export type RiskEntry = Readonly<{
|
|
195
285
|
promiseId: string;
|
|
196
286
|
score: number;
|
|
197
287
|
band: string;
|
|
288
|
+
features?: Features;
|
|
289
|
+
/** The total weight of the entry's reasons. */
|
|
290
|
+
evidence?: number;
|
|
198
291
|
}>;
|
|
199
292
|
/** Read a risk report out of whatever `balladeer risk --json` printed. */
|
|
200
293
|
export declare function readRiskOutput(stdout: string): RiskEntry[] | undefined;
|
|
@@ -206,18 +299,39 @@ export declare function defaultBase(root: string, head: string): Promise<string
|
|
|
206
299
|
export declare function changedFiles(root: string, base: string, head: string): Promise<string[]>;
|
|
207
300
|
export type Selection = Readonly<{
|
|
208
301
|
promiseId: string;
|
|
209
|
-
why: "file" | "named" | "risk" | "sample" | "mapped" | "always";
|
|
302
|
+
why: "file" | "named" | "risk" | "anchored" | "sample" | "mapped" | "always";
|
|
210
303
|
}>;
|
|
211
304
|
/**
|
|
212
|
-
* Which promises to judge: named ones
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
305
|
+
* Which promises to judge: named ones; else the promises the change selects
|
|
306
|
+
* by their anchors and by their maps; then `alwaysJudge`.
|
|
307
|
+
*
|
|
308
|
+
* By anchors (`anchored`, chosen before this from the files the change edits):
|
|
309
|
+
* every promise one of whose anchor files (an entry point's or a symbol's
|
|
310
|
+
* file) the change edits, with no widening by import distance. The
|
|
311
|
+
* measurement of 1 October 2026 found that widening multiplied the promises
|
|
312
|
+
* selected and caught nothing more.
|
|
313
|
+
*
|
|
314
|
+
* By maps, from the risk report, in the order `balladeer risk` lists it (how
|
|
315
|
+
* directly the change reaches each promise, then score, then evidence, then
|
|
316
|
+
* id; a score alone ties at 1 and falls to the alphabet):
|
|
317
|
+
*
|
|
318
|
+
* - "direct" takes every mapped promise whose own code or tests the change
|
|
319
|
+
* edits (directness tier 3), and nothing else. Only a `--top` given by hand
|
|
320
|
+
* caps it, and it caps anchored and mapped promises together.
|
|
321
|
+
* - "ranked" takes the top k mapped promises with a score above zero, plus a
|
|
322
|
+
* random sample below that line. The sample is what keeps a ranking honest:
|
|
323
|
+
* a break found below the line is a miss the ranking made, counted rather
|
|
324
|
+
* than never seen. Anchored promises are taken too, before the sample.
|
|
325
|
+
*
|
|
326
|
+
* Without a risk report, every mapped promise. Anchored and mapped promises
|
|
327
|
+
* are listed together in the report's order, and one the report does not
|
|
328
|
+
* list comes after those it does.
|
|
216
329
|
*/
|
|
217
330
|
export declare function selectPromises(input: Readonly<{
|
|
218
331
|
named?: readonly string[];
|
|
219
332
|
risk?: readonly RiskEntry[];
|
|
220
333
|
mapped: readonly string[];
|
|
334
|
+
anchored?: readonly string[];
|
|
221
335
|
config: JudgeConfig;
|
|
222
336
|
topK?: number;
|
|
223
337
|
random: () => number;
|
|
@@ -234,14 +348,55 @@ export declare function findLoggedVerdict(root: string, key: Readonly<{
|
|
|
234
348
|
base: string;
|
|
235
349
|
head: string;
|
|
236
350
|
}>, now: Date): JudgeVerdict | undefined;
|
|
237
|
-
/**
|
|
238
|
-
export declare
|
|
351
|
+
/** Said after "fix the behavior": a deliberate change is the person's, and the promise its owner's. */
|
|
352
|
+
export declare const DELIBERATE_CHANGE = "If the person changed this behavior on purpose, do not undo their change: tell them it breaks this promise, whose meaning only its owner can change.";
|
|
353
|
+
export type VerdictLineContext = Readonly<{
|
|
354
|
+
/** The verdict was reached earlier for this same commit and read back from the log. */
|
|
355
|
+
reused?: boolean;
|
|
356
|
+
/**
|
|
357
|
+
* Whether the promise has a Balladeer check bound, as its connection said.
|
|
358
|
+
* Absent when that is unknown (a promise from a file or a map's excerpt),
|
|
359
|
+
* and then the line says nothing about a check rather than guessing.
|
|
360
|
+
*/
|
|
361
|
+
checkBound?: boolean;
|
|
362
|
+
}>;
|
|
363
|
+
/**
|
|
364
|
+
* What to do after a reproduced break, as one line an agent reads in order:
|
|
365
|
+
* where the test that shows it is kept, fix the behavior rather than the
|
|
366
|
+
* test, then make the break a lasting check in this repository's own tests,
|
|
367
|
+
* committed with the fix and linked to the promise's map, and tell the person
|
|
368
|
+
* in one line what was added. When the promise's own Balladeer check missed
|
|
369
|
+
* the break, a repair of that check is proposed to its owner as well.
|
|
370
|
+
*/
|
|
371
|
+
export declare function afterBreakLine(verdict: JudgeVerdict, checkBound?: boolean): string;
|
|
372
|
+
/**
|
|
373
|
+
* The verdict as it may be told now: a reproduction said to be kept whose
|
|
374
|
+
* folder is no longer on this machine (a verdict read back from the log after
|
|
375
|
+
* somebody cleared it) loses its kept fields, so the line never points at a
|
|
376
|
+
* file that is not there.
|
|
377
|
+
*/
|
|
378
|
+
export declare function stillKept(root: string, verdict: JudgeVerdict): JudgeVerdict;
|
|
379
|
+
/**
|
|
380
|
+
* One line per verdict, the promise named by its title and id. A broken one
|
|
381
|
+
* carries a second, indented line saying what to do next.
|
|
382
|
+
*/
|
|
383
|
+
export declare function verdictLine(verdict: JudgeVerdict, title: string, context?: VerdictLineContext): string;
|
|
239
384
|
export type JudgeDependencies = Readonly<{
|
|
240
385
|
runAgent?: (options: HeadlessAgentOptions) => Promise<HeadlessAgentResult>;
|
|
241
386
|
resolveLogin?: (requested: HeadlessClient | "auto", prefer?: HeadlessClient) => Promise<LoginCheck | undefined>;
|
|
242
|
-
riskReport?: (root: string, base: string, head: string
|
|
387
|
+
riskReport?: (root: string, base: string, head: string,
|
|
388
|
+
/** The maps in use and, in a map's shape, the anchors of the promises they select. */
|
|
389
|
+
maps: readonly BehaviorMap[]) => Promise<readonly RiskEntry[] | undefined>;
|
|
243
390
|
/** `null` means "no connection", without trying to find one. */
|
|
244
391
|
reader?: PromiseReader | null;
|
|
392
|
+
/** The anchors route; `null` means none, without trying to find one. */
|
|
393
|
+
anchors?: AnchorsClient | null;
|
|
394
|
+
/** The anchoring call, when it is not the person's own agent. */
|
|
395
|
+
anchorAgent?: (options: HeadlessAgentOptions) => Promise<HeadlessAgentResult>;
|
|
396
|
+
/** The repository graph at a commit, when it is not built from this laptop's cache. */
|
|
397
|
+
graph?: (root: string, head: string) => RepositoryGraph;
|
|
398
|
+
/** Today's anchoring budget, when it is not this laptop's own. */
|
|
399
|
+
anchorBudget?: AnchorBudget;
|
|
245
400
|
random?: () => number;
|
|
246
401
|
now?: () => Date;
|
|
247
402
|
stdin?: () => Promise<string>;
|
|
@@ -250,7 +405,15 @@ export type JudgeDependencies = Readonly<{
|
|
|
250
405
|
judge?: (input: JudgePromiseInput) => Promise<JudgeOutcome>;
|
|
251
406
|
/** The agent run that reads the change for offers, when they are on. */
|
|
252
407
|
offerAgent?: (options: HeadlessAgentOptions) => Promise<HeadlessAgentResult>;
|
|
408
|
+
/** The head commit of the pull request a `gh pr merge` names. */
|
|
409
|
+
pullRequestHead?: (root: string, target: MergeTarget) => Promise<string | undefined>;
|
|
410
|
+
/** Whether this laptop has a connection for the checkout, read locally. */
|
|
411
|
+
connected?: (root: string) => boolean;
|
|
253
412
|
}>;
|
|
413
|
+
/** Said instead of verdicts when the check cannot tell which repository a push leaves from. */
|
|
414
|
+
export declare const PUSH_REPOSITORY_UNKNOWN = "Balladeer judge: this push was not judged, because the check could not tell which repository it pushes.";
|
|
415
|
+
/** Said instead of verdicts when every pull request the command opens or merges is in another repository. */
|
|
416
|
+
export declare function pullRequestElsewhereLine(repo: string): string;
|
|
254
417
|
export type JudgeRunOptions = Readonly<{
|
|
255
418
|
args: JudgeArguments;
|
|
256
419
|
cwd: string;
|
|
@@ -259,7 +422,52 @@ export type JudgeRunOptions = Readonly<{
|
|
|
259
422
|
error: (text: string) => void;
|
|
260
423
|
deps?: JudgeDependencies;
|
|
261
424
|
}>;
|
|
425
|
+
/** What `--push-check off` and `--push-check on` say. */
|
|
426
|
+
export declare const PUSH_CHECK_OFF_LINE = "The push check is off on this laptop: after a push it now says nothing, in every repository. A repository's own entry from `balladeer judge --install-hook` still runs. Turn it back on with `balladeer judge --push-check on`.";
|
|
427
|
+
export declare const PUSH_CHECK_ON_LINE = "The push check is back on for this laptop: after a push in a connected repository with agreed promises, it reports what the push may have broken, and it never holds the push.";
|
|
428
|
+
/**
|
|
429
|
+
* Whether the push check's user-scope entry has this push to itself, decided
|
|
430
|
+
* before anything is started or fetched: the entry runs on every shell command
|
|
431
|
+
* in every folder on the laptop, and most folders have nothing to judge. It
|
|
432
|
+
* stands aside, saying nothing, when the laptop turned the check off, the
|
|
433
|
+
* folder is in no checkout, or the checkout has the push check's own project
|
|
434
|
+
* entry for this host (that entry owns the check there, so a push is judged
|
|
435
|
+
* once). Only then is the connection looked for, which reads the checkout's
|
|
436
|
+
* remotes, and a checkout this laptop has not connected is left alone too.
|
|
437
|
+
*
|
|
438
|
+
* A connected checkout is not left alone for having no behavior map: since
|
|
439
|
+
* promise anchors (approved 30 September 2026), its agreed promises are
|
|
440
|
+
* anchored and checked without one. Whether it has any agreed promise is the
|
|
441
|
+
* server's to say, after the push, and with none (and no map) the entry still
|
|
442
|
+
* says nothing.
|
|
443
|
+
*/
|
|
444
|
+
export declare function userScopeTakesThePush(input: {
|
|
445
|
+
cwd: string;
|
|
446
|
+
host: "claude" | "codex";
|
|
447
|
+
environment: NodeJS.ProcessEnv;
|
|
448
|
+
connected: (root: string) => boolean;
|
|
449
|
+
}): boolean;
|
|
450
|
+
/**
|
|
451
|
+
* The one line said when nothing was selected, and its code: no agreed
|
|
452
|
+
* promise here; nothing anchored or mapped (with why, when the anchors could
|
|
453
|
+
* not be read); or nothing the change touches.
|
|
454
|
+
*/
|
|
455
|
+
export declare function nothingSelected(input: Readonly<{
|
|
456
|
+
stage: AnchorStage | undefined;
|
|
457
|
+
maps: number;
|
|
458
|
+
anchors: number;
|
|
459
|
+
push: boolean;
|
|
460
|
+
}>): {
|
|
461
|
+
reason: string;
|
|
462
|
+
message: string;
|
|
463
|
+
};
|
|
262
464
|
/** `balladeer judge`, from arguments already parsed. */
|
|
465
|
+
/**
|
|
466
|
+
* The line an answer opens with when the command makes a commit before it
|
|
467
|
+
* pushes. Robert approved it on 30 September 2026: the check keeps running
|
|
468
|
+
* before the push, and says plainly that it did not see the commit.
|
|
469
|
+
*/
|
|
470
|
+
export declare function commitFirstLine(made: string): string;
|
|
263
471
|
export declare function runJudge(options: JudgeRunOptions): Promise<number>;
|
|
264
472
|
/** `balladeer judge ...` from raw arguments, as `cli.ts` hands them over. */
|
|
265
473
|
export declare function judgeCommand(argv: readonly string[], io: Readonly<{
|
|
@@ -268,4 +476,3 @@ export declare function judgeCommand(argv: readonly string[], io: Readonly<{
|
|
|
268
476
|
write: (text: string) => void;
|
|
269
477
|
error: (text: string) => void;
|
|
270
478
|
}>): Promise<number>;
|
|
271
|
-
export {};
|