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
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How many anchoring calls this laptop may still start today, kept in
|
|
3
|
+
* Balladeer's config home.
|
|
4
|
+
*
|
|
5
|
+
* Every anchoring call runs on the person's own subscription, so the push
|
|
6
|
+
* check spends at most this many a day, whatever the repository: 20 by
|
|
7
|
+
* default, or `BALLADEER_ANCHOR_DAILY_BUDGET` (a whole number from 0 to 500)
|
|
8
|
+
* when the person sets it. A call counts when it starts, so a call that ran
|
|
9
|
+
* into its cap or failed has still been spent. The day is the laptop's own
|
|
10
|
+
* calendar day.
|
|
11
|
+
*
|
|
12
|
+
* The same file remembers which promises a call already came back empty or
|
|
13
|
+
* capped for today, so a promise nothing on the list realizes is not asked
|
|
14
|
+
* about again on every push. It never leaves the laptop.
|
|
15
|
+
*/
|
|
16
|
+
export declare const ANCHOR_BUDGET_FILE = "anchor-budget.json";
|
|
17
|
+
export declare const DEFAULT_DAILY_ANCHORINGS = 20;
|
|
18
|
+
export declare const ANCHOR_BUDGET_VARIABLE = "BALLADEER_ANCHOR_DAILY_BUDGET";
|
|
19
|
+
export type AnchorBudget = Readonly<{
|
|
20
|
+
/** Calls allowed a day on this laptop. */
|
|
21
|
+
limit: number;
|
|
22
|
+
/** Calls still allowed today. */
|
|
23
|
+
remaining(): number;
|
|
24
|
+
/** Take one call from today's budget, or say there is none left. */
|
|
25
|
+
take(): boolean;
|
|
26
|
+
/** Whether a call for this promise and meaning already came back empty or capped today. */
|
|
27
|
+
settledToday(key: string): "empty" | "capped" | undefined;
|
|
28
|
+
/** Remember that today's call for this promise and meaning came back empty or capped. */
|
|
29
|
+
settle(key: string, outcome: "empty" | "capped"): void;
|
|
30
|
+
}>;
|
|
31
|
+
/** The laptop's own calendar day, as YYYY-MM-DD. */
|
|
32
|
+
export declare function localDay(now: Date): string;
|
|
33
|
+
/** The daily limit: the person's setting when it is a whole number from 0 to 500, else 20. */
|
|
34
|
+
export declare function dailyAnchorLimit(environment: NodeJS.ProcessEnv): number;
|
|
35
|
+
export declare function anchorBudgetPath(environment: NodeJS.ProcessEnv): string;
|
|
36
|
+
/**
|
|
37
|
+
* This laptop's budget for today. Each change is read from and written back to
|
|
38
|
+
* the file at once, so two pushes in two repositories share one budget.
|
|
39
|
+
*/
|
|
40
|
+
export declare function anchorBudget(environment: NodeJS.ProcessEnv, now: () => Date): AnchorBudget;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { configHome } from "./store.js";
|
|
5
|
+
/**
|
|
6
|
+
* How many anchoring calls this laptop may still start today, kept in
|
|
7
|
+
* Balladeer's config home.
|
|
8
|
+
*
|
|
9
|
+
* Every anchoring call runs on the person's own subscription, so the push
|
|
10
|
+
* check spends at most this many a day, whatever the repository: 20 by
|
|
11
|
+
* default, or `BALLADEER_ANCHOR_DAILY_BUDGET` (a whole number from 0 to 500)
|
|
12
|
+
* when the person sets it. A call counts when it starts, so a call that ran
|
|
13
|
+
* into its cap or failed has still been spent. The day is the laptop's own
|
|
14
|
+
* calendar day.
|
|
15
|
+
*
|
|
16
|
+
* The same file remembers which promises a call already came back empty or
|
|
17
|
+
* capped for today, so a promise nothing on the list realizes is not asked
|
|
18
|
+
* about again on every push. It never leaves the laptop.
|
|
19
|
+
*/
|
|
20
|
+
export const ANCHOR_BUDGET_FILE = "anchor-budget.json";
|
|
21
|
+
export const DEFAULT_DAILY_ANCHORINGS = 20;
|
|
22
|
+
export const ANCHOR_BUDGET_VARIABLE = "BALLADEER_ANCHOR_DAILY_BUDGET";
|
|
23
|
+
/** The laptop's own calendar day, as YYYY-MM-DD. */
|
|
24
|
+
export function localDay(now) {
|
|
25
|
+
const pad = (value) => String(value).padStart(2, "0");
|
|
26
|
+
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
|
|
27
|
+
}
|
|
28
|
+
/** The daily limit: the person's setting when it is a whole number from 0 to 500, else 20. */
|
|
29
|
+
export function dailyAnchorLimit(environment) {
|
|
30
|
+
const raw = environment[ANCHOR_BUDGET_VARIABLE]?.trim();
|
|
31
|
+
if (raw === undefined || raw === "")
|
|
32
|
+
return DEFAULT_DAILY_ANCHORINGS;
|
|
33
|
+
const value = Number(raw);
|
|
34
|
+
return Number.isInteger(value) && value >= 0 && value <= 500 ? value : DEFAULT_DAILY_ANCHORINGS;
|
|
35
|
+
}
|
|
36
|
+
export function anchorBudgetPath(environment) {
|
|
37
|
+
return join(configHome(environment), ANCHOR_BUDGET_FILE);
|
|
38
|
+
}
|
|
39
|
+
function read(path, day) {
|
|
40
|
+
try {
|
|
41
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
42
|
+
if (parsed?.day === day &&
|
|
43
|
+
typeof parsed.used === "number" &&
|
|
44
|
+
Number.isInteger(parsed.used) &&
|
|
45
|
+
parsed.used >= 0) {
|
|
46
|
+
const settled = {};
|
|
47
|
+
if (parsed.settled !== null && typeof parsed.settled === "object")
|
|
48
|
+
for (const [key, value] of Object.entries(parsed.settled))
|
|
49
|
+
if (value === "empty" || value === "capped")
|
|
50
|
+
settled[key] = value;
|
|
51
|
+
return { day, used: parsed.used, settled };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
/* Missing or unreadable: a new day. */
|
|
56
|
+
}
|
|
57
|
+
return { day, used: 0, settled: {} };
|
|
58
|
+
}
|
|
59
|
+
function write(path, value) {
|
|
60
|
+
try {
|
|
61
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
62
|
+
const temporary = `${path}.${randomBytes(8).toString("hex")}.tmp`;
|
|
63
|
+
try {
|
|
64
|
+
writeFileSync(temporary, `${JSON.stringify(value)}\n`, { flag: "wx", mode: 0o600 });
|
|
65
|
+
renameSync(temporary, path);
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
try {
|
|
69
|
+
unlinkSync(temporary);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
/* Renamed, or never written. */
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
/* A budget that cannot be written is spent in memory only, for this run. */
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* This laptop's budget for today. Each change is read from and written back to
|
|
82
|
+
* the file at once, so two pushes in two repositories share one budget.
|
|
83
|
+
*/
|
|
84
|
+
export function anchorBudget(environment, now) {
|
|
85
|
+
const path = anchorBudgetPath(environment);
|
|
86
|
+
const limit = dailyAnchorLimit(environment);
|
|
87
|
+
// What this run spent, in case the file cannot be written: never fewer than that.
|
|
88
|
+
let spent = { day: "", used: 0 };
|
|
89
|
+
const current = () => {
|
|
90
|
+
const state = read(path, localDay(now()));
|
|
91
|
+
return spent.day === state.day ? { ...state, used: Math.max(state.used, spent.used) } : state;
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
limit,
|
|
95
|
+
remaining: () => Math.max(0, limit - current().used),
|
|
96
|
+
take: () => {
|
|
97
|
+
const state = current();
|
|
98
|
+
if (state.used >= limit)
|
|
99
|
+
return false;
|
|
100
|
+
spent = { day: state.day, used: state.used + 1 };
|
|
101
|
+
write(path, { ...state, used: state.used + 1 });
|
|
102
|
+
return true;
|
|
103
|
+
},
|
|
104
|
+
settledToday: (key) => current().settled[key],
|
|
105
|
+
settle: (key, outcome) => {
|
|
106
|
+
const state = current();
|
|
107
|
+
write(path, { ...state, settled: { ...state.settled, [key]: outcome } });
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import type { AnchorBudget } from "./anchor-budget.js";
|
|
2
|
+
import { type AnchorEntryPoint, type AnchorSymbol, type PromiseAnchors } from "./anchors-schema.js";
|
|
3
|
+
import type { AnchoredPromise, AnchorsClient } from "./anchors-client.js";
|
|
4
|
+
import { type BehaviorMap } from "./behavior-map-schema.js";
|
|
5
|
+
import { type HeadlessAgentOptions, type HeadlessAgentResult, type HeadlessClient, type LoginCheck } from "./headless-agent.js";
|
|
6
|
+
import type { PromiseMeaning, PromiseReader } from "./promise-meaning.js";
|
|
7
|
+
import { type ExportedName, type RepositoryGraph } from "./risk/graph-cache.js";
|
|
8
|
+
import type { ImportGraph } from "./risk/import-graph.js";
|
|
9
|
+
import { type Idf } from "./risk/text.js";
|
|
10
|
+
/**
|
|
11
|
+
* Promise anchors on the laptop: where an agreed promise's behavior lives,
|
|
12
|
+
* written by one small call on the person's own Claude Code or Codex, or cut
|
|
13
|
+
* from a behavior map, and shared through the server with every teammate.
|
|
14
|
+
*
|
|
15
|
+
* The call is `anchor-brief/v3`, frozen on 1 October 2026 after the
|
|
16
|
+
* measurement in `docs/agentic-testing/evidence/20261001/anchors-measurement.md`.
|
|
17
|
+
* The index, the shortlist and the brief below are
|
|
18
|
+
* `scripts/agentic-eval/anchors-fresh.ts` at v3, word for word. They were tuned
|
|
19
|
+
* on the seventeen in-window cases, so any change to them is a new revision
|
|
20
|
+
* with a label of its own, measured before it ships; never edit v3 in place.
|
|
21
|
+
*/
|
|
22
|
+
export declare const ANCHOR_BRIEF_REVISION = "anchor-brief/v3";
|
|
23
|
+
/**
|
|
24
|
+
* Each anchoring call's caps. The measured calls wrote at most 1,157 output
|
|
25
|
+
* tokens and took at most 9.3 seconds; one runaway call in 291 wrote 128,690.
|
|
26
|
+
* A call that reaches either cap leaves its promise unanchored.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ANCHOR_CALL_CAPS: {
|
|
29
|
+
readonly outputTokens: 8000;
|
|
30
|
+
readonly wallMs: 60000;
|
|
31
|
+
};
|
|
32
|
+
export type IndexEntry = Readonly<{
|
|
33
|
+
file: string;
|
|
34
|
+
names: readonly ExportedName[];
|
|
35
|
+
words: ReadonlySet<string>;
|
|
36
|
+
}>;
|
|
37
|
+
export type AnchorIndex = Readonly<{
|
|
38
|
+
sha: string;
|
|
39
|
+
entries: readonly IndexEntry[];
|
|
40
|
+
idf: Idf;
|
|
41
|
+
}>;
|
|
42
|
+
/** Every non-test source file the graph knows, with the top-level names it exports. */
|
|
43
|
+
export declare function anchorIndex(repository: RepositoryGraph): AnchorIndex;
|
|
44
|
+
type BriefExample = {
|
|
45
|
+
label?: string;
|
|
46
|
+
setup?: string;
|
|
47
|
+
expectedOutcome?: string;
|
|
48
|
+
};
|
|
49
|
+
type BriefMeaning = {
|
|
50
|
+
title: string;
|
|
51
|
+
observableOutcome: string;
|
|
52
|
+
passingExamples: BriefExample[];
|
|
53
|
+
failingExamples: BriefExample[];
|
|
54
|
+
nonGoals: string[];
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* The promise as the measured brief showed it: title, outcome, the cases'
|
|
58
|
+
* label, setup and outcome, and the non-goals. Nothing else of the meaning is
|
|
59
|
+
* read, so what the model sees is what was measured.
|
|
60
|
+
*/
|
|
61
|
+
export declare function briefMeaning(meaning: PromiseMeaning): BriefMeaning;
|
|
62
|
+
/** The files whose path and names share the most weighted words with the promise. */
|
|
63
|
+
export declare function shortlist(index: AnchorIndex, meaning: BriefMeaning): IndexEntry[];
|
|
64
|
+
/** `anchor-brief/v3`, word for word. */
|
|
65
|
+
export declare function anchorBrief(meaning: BriefMeaning, candidates: readonly IndexEntry[]): string;
|
|
66
|
+
/**
|
|
67
|
+
* The first complete JSON value in a model's answer, fenced or bare, as the
|
|
68
|
+
* measurement read it. Undefined when there is none.
|
|
69
|
+
*/
|
|
70
|
+
export declare function firstJsonValue(answer: string): unknown;
|
|
71
|
+
export type Picks = Readonly<{
|
|
72
|
+
entryPoints: AnchorEntryPoint[];
|
|
73
|
+
symbols: AnchorSymbol[];
|
|
74
|
+
/** What the model named that was not kept, as `entry file#name` or `symbol file#name`. */
|
|
75
|
+
dropped: string[];
|
|
76
|
+
}>;
|
|
77
|
+
/**
|
|
78
|
+
* What the model picked, kept only when its file is on the shortlist and its
|
|
79
|
+
* name is declared or exported in that file, and only when both pass the data
|
|
80
|
+
* boundary. Anything else is dropped. The measurement kept any name in a
|
|
81
|
+
* listed file; a name the file does not declare would read as gone on the next
|
|
82
|
+
* push, so it is dropped here instead (2 of the 1,268 measured picks).
|
|
83
|
+
*/
|
|
84
|
+
export declare function readPicks(raw: unknown, candidates: readonly IndexEntry[], declared: (file: string) => ReadonlySet<string> | undefined): Picks;
|
|
85
|
+
/** Linked tests, from the graph: test files that import an anchor file directly. */
|
|
86
|
+
export declare function linkedTestsFor(graph: ImportGraph, files: Iterable<string>): {
|
|
87
|
+
file: string;
|
|
88
|
+
}[];
|
|
89
|
+
/**
|
|
90
|
+
* Files one import step from the anchor files, either way: what they import
|
|
91
|
+
* and what imports them, tests left out (linked tests are listed apart). This
|
|
92
|
+
* is the judge's neighborhood: where to look next if the behavior reaches
|
|
93
|
+
* further than the anchors.
|
|
94
|
+
*/
|
|
95
|
+
export declare function neighborhood(graph: ImportGraph, files: readonly string[], limit?: number): string[];
|
|
96
|
+
/**
|
|
97
|
+
* Anchors cut from a behavior map, with no model: its entry points, its core
|
|
98
|
+
* symbols, its resources and its linked tests, each kept only when it passes
|
|
99
|
+
* the data boundary, up to the contract's limits. A map's notes are not
|
|
100
|
+
* carried. Undefined when nothing anchorable is left.
|
|
101
|
+
*/
|
|
102
|
+
export declare function seedFromMap(map: BehaviorMap, at: Date): PromiseAnchors | undefined;
|
|
103
|
+
export type GoneCheck = Readonly<{
|
|
104
|
+
/** The anchors with every gone entry point, symbol and linked test taken out. */
|
|
105
|
+
surviving: PromiseAnchors;
|
|
106
|
+
/** What has gone, as `file#name` or a linked test's file. */
|
|
107
|
+
gone: readonly string[];
|
|
108
|
+
}>;
|
|
109
|
+
/**
|
|
110
|
+
* Which anchors have gone at a commit, read off the graph with no model: an
|
|
111
|
+
* entry point or symbol whose file is not in the tree, or whose name its file
|
|
112
|
+
* no longer declares. A file the graph does not read (another language, from a
|
|
113
|
+
* map) is checked for being there only.
|
|
114
|
+
*/
|
|
115
|
+
export declare function goneAnchors(anchors: PromiseAnchors, repository: RepositoryGraph): GoneCheck;
|
|
116
|
+
export type AnchorCall = Readonly<{
|
|
117
|
+
status: "anchored";
|
|
118
|
+
anchors: PromiseAnchors;
|
|
119
|
+
tokens: number;
|
|
120
|
+
dropped: readonly string[];
|
|
121
|
+
ms: number;
|
|
122
|
+
}> | Readonly<{
|
|
123
|
+
status: "empty";
|
|
124
|
+
tokens: number;
|
|
125
|
+
dropped: readonly string[];
|
|
126
|
+
}> | Readonly<{
|
|
127
|
+
status: "capped" | "failed" | "stopped";
|
|
128
|
+
reason: string;
|
|
129
|
+
tokens: number;
|
|
130
|
+
}>;
|
|
131
|
+
/**
|
|
132
|
+
* One promise anchored by one headless call: no tools, in an empty folder,
|
|
133
|
+
* with an output-token cap and a time limit. Only picks from the shortlist are
|
|
134
|
+
* kept, linked tests come from the graph, and the result is checked against
|
|
135
|
+
* the data boundary before anyone sees it.
|
|
136
|
+
*/
|
|
137
|
+
export declare function anchorWithCall(input: Readonly<{
|
|
138
|
+
promiseId: string;
|
|
139
|
+
semanticDigest: string;
|
|
140
|
+
meaning: PromiseMeaning;
|
|
141
|
+
repository: RepositoryGraph;
|
|
142
|
+
index: AnchorIndex;
|
|
143
|
+
login: LoginCheck;
|
|
144
|
+
environment: NodeJS.ProcessEnv;
|
|
145
|
+
now: () => Date;
|
|
146
|
+
timeoutMs?: number;
|
|
147
|
+
signal?: AbortSignal;
|
|
148
|
+
scratch?: string;
|
|
149
|
+
runAgent?: (options: HeadlessAgentOptions) => Promise<HeadlessAgentResult>;
|
|
150
|
+
}>): Promise<AnchorCall>;
|
|
151
|
+
/** The model name as the contract carries it, or `unknown` when the run did not say. */
|
|
152
|
+
export declare function anchorModelName(model: string | undefined): string;
|
|
153
|
+
export type AnchorStatus =
|
|
154
|
+
/** Its current anchors stand, all of them still in the code. */
|
|
155
|
+
"current"
|
|
156
|
+
/** Anchored now by a call. */
|
|
157
|
+
| "anchored"
|
|
158
|
+
/** Anchored now from its behavior map, with no call. */
|
|
159
|
+
| "seeded"
|
|
160
|
+
/** Some of its anchors have gone and it was not anchored again; judged on what is left. */
|
|
161
|
+
| "stale" | "budget" | "capped" | "failed" | "empty"
|
|
162
|
+
/** A call came back empty or capped earlier today, so it was not asked again. */
|
|
163
|
+
| "settled" | "no_login" | "unreadable"
|
|
164
|
+
/** The push check ran out of time before its turn. */
|
|
165
|
+
| "time";
|
|
166
|
+
export type AnchorOutcome = Readonly<{
|
|
167
|
+
promiseId: string;
|
|
168
|
+
title: string;
|
|
169
|
+
status: AnchorStatus;
|
|
170
|
+
/** Anchored again because code it was anchored to had gone. */
|
|
171
|
+
again?: boolean;
|
|
172
|
+
/** For anchored, seeded: whether the server kept them. Absent when not sent. */
|
|
173
|
+
recorded?: boolean;
|
|
174
|
+
recordReason?: string;
|
|
175
|
+
reason?: string;
|
|
176
|
+
tokens?: number;
|
|
177
|
+
}>;
|
|
178
|
+
export type AnchorRun = Readonly<{
|
|
179
|
+
/** Each promise's anchors to judge on now: current, fresh, or what is left of stale ones. */
|
|
180
|
+
anchors: ReadonlyMap<string, PromiseAnchors>;
|
|
181
|
+
/**
|
|
182
|
+
* Each promise's anchor files to select it by: those of its anchors as
|
|
183
|
+
* Balladeer kept them, gone ones included, and those of any fresh ones. A
|
|
184
|
+
* change that deletes or moves an anchor file edits it, so the promise is
|
|
185
|
+
* selected even though that anchor has gone at the change's head.
|
|
186
|
+
*/
|
|
187
|
+
selectBy: ReadonlyMap<string, readonly string[]>;
|
|
188
|
+
outcomes: readonly AnchorOutcome[];
|
|
189
|
+
/** Tokens the calls spent. */
|
|
190
|
+
tokens: number;
|
|
191
|
+
client?: HeadlessClient;
|
|
192
|
+
budget: AnchorBudget;
|
|
193
|
+
}>;
|
|
194
|
+
export type AnchorRunInput = Readonly<{
|
|
195
|
+
promises: readonly AnchoredPromise[];
|
|
196
|
+
/** Promise ids to anchor anew whatever they have now (`balladeer anchor <promise>`). */
|
|
197
|
+
force?: ReadonlySet<string>;
|
|
198
|
+
/** Only these promises are anchored when given; the others keep what they have. */
|
|
199
|
+
only?: ReadonlySet<string>;
|
|
200
|
+
/** Each promise's behavior map when this checkout has one for its current meaning. */
|
|
201
|
+
currentMaps: ReadonlyMap<string, BehaviorMap>;
|
|
202
|
+
repository: RepositoryGraph;
|
|
203
|
+
client: AnchorsClient;
|
|
204
|
+
reader: PromiseReader | undefined;
|
|
205
|
+
login: () => Promise<LoginCheck | undefined>;
|
|
206
|
+
budget: AnchorBudget;
|
|
207
|
+
environment: NodeJS.ProcessEnv;
|
|
208
|
+
now: () => Date;
|
|
209
|
+
/** No new call starts after this instant (milliseconds since the epoch). */
|
|
210
|
+
deadline?: number;
|
|
211
|
+
signal?: AbortSignal;
|
|
212
|
+
concurrency?: number;
|
|
213
|
+
scratch?: string;
|
|
214
|
+
/** A key for this repository, so "came back empty today" is remembered per repository. */
|
|
215
|
+
repositoryKey: string;
|
|
216
|
+
runAgent?: (options: HeadlessAgentOptions) => Promise<HeadlessAgentResult>;
|
|
217
|
+
}>;
|
|
218
|
+
/**
|
|
219
|
+
* Every agreed promise brought to current anchors as far as today's budget
|
|
220
|
+
* and the time allow: kept when current, cut from a current map with no model,
|
|
221
|
+
* else anchored by a call; anchors whose code has gone are anchored again, and
|
|
222
|
+
* judged on what is left of them meanwhile. A promise left unanchored says why.
|
|
223
|
+
*/
|
|
224
|
+
export declare function bringAnchorsCurrent(input: AnchorRunInput): Promise<AnchorRun>;
|
|
225
|
+
/**
|
|
226
|
+
* What anchoring did, in at most four lines a person reads in one go: what
|
|
227
|
+
* was anchored and what it cost with what is left of today's budget; what was
|
|
228
|
+
* left unanchored, so not checked, and why; what is checked on part of its
|
|
229
|
+
* anchors; and anchors not shared with the team. Nothing when anchoring had
|
|
230
|
+
* nothing to do.
|
|
231
|
+
*
|
|
232
|
+
* From the push check (`push`), a promise left unanchored that the push
|
|
233
|
+
* selected anyway (by an anchor file it moved or deleted) is not listed as
|
|
234
|
+
* unchecked, because it was judged; from `balladeer anchor` there is no push,
|
|
235
|
+
* and the lines say what the push check can do instead.
|
|
236
|
+
*/
|
|
237
|
+
export declare function anchoringLines(run: AnchorRun, context?: Readonly<{
|
|
238
|
+
push: boolean;
|
|
239
|
+
judged?: ReadonlySet<string>;
|
|
240
|
+
}>): string[];
|
|
241
|
+
export {};
|