@spexcode/spec-eval 0.6.5

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.
@@ -0,0 +1,307 @@
1
+ import { type ReviewDiffFile } from '@spexcode/spec-core';
2
+ import { loadSpecs } from '@spexcode/spec-core';
3
+ import { type AnchorHit, type RelationEntry } from '@spexcode/spec-core';
4
+ import { type EvalEntry, type EvalTimeline, type ScenarioInfo } from './evaltab.js';
5
+ import { type Scenario } from './scenarios.js';
6
+ import { type EvalHostPort } from './host.js';
7
+ export type { EvalHostPort } from './host.js';
8
+ export declare function setSessionEvalHost(next: EvalHostPort): void;
9
+ export declare function sessionEvalHost(): EvalHostPort;
10
+ type ScoreState = 'pass' | 'fail' | 'stalePass' | 'staleFail' | 'empty' | null;
11
+ export type ScenarioImpactReason = 'code' | 'contract' | 'measurement';
12
+ export type SessionScenarioInfo = ScenarioInfo & {
13
+ impact: ScenarioImpactReason[];
14
+ };
15
+ export type SessionImpactSelectorHit = AnchorHit & {
16
+ path: string;
17
+ };
18
+ export type SessionImpactScenarioDelta = {
19
+ kind: 'added' | 'removed' | 'modified' | 'unchanged';
20
+ semantic: boolean;
21
+ metadata: boolean;
22
+ metadataOnly: boolean;
23
+ };
24
+ export type SessionImpactScenario = {
25
+ name: string;
26
+ state: 'added' | 'removed' | 'present';
27
+ impact: ScenarioImpactReason[];
28
+ baseEffectiveCode: RelationEntry[];
29
+ headEffectiveCode: RelationEntry[];
30
+ selectorHits: SessionImpactSelectorHit[];
31
+ baseScenarioHash: string | null;
32
+ headScenarioHash: string | null;
33
+ delta: SessionImpactScenarioDelta;
34
+ };
35
+ export type SessionImpactNodeCause = {
36
+ kind: 'spec' | 'eval' | 'code' | 'related' | 'contract' | 'measurement';
37
+ paths: string[];
38
+ scenarios: string[];
39
+ selectorHits: SessionImpactSelectorHit[];
40
+ };
41
+ export type SessionImpactNode = {
42
+ id: string;
43
+ causes: SessionImpactNodeCause[];
44
+ scenarios: SessionImpactScenario[];
45
+ };
46
+ export type SessionImpactProjection = {
47
+ base: string;
48
+ head: string;
49
+ revision: string;
50
+ nodes: SessionImpactNode[];
51
+ };
52
+ export type SessionImpactOptions = {
53
+ base: string;
54
+ head: string;
55
+ measurements?: Readonly<Record<string, readonly string[]>>;
56
+ overlay?: SessionImpactOverlay;
57
+ };
58
+ export type SessionImpactOverlay = {
59
+ revision: string;
60
+ paths: string[];
61
+ baseRanges: Record<string, [number, number][]>;
62
+ ranges: Record<string, [number, number][]>;
63
+ specs: SessionImpactSpecSnapshot[];
64
+ evalSources: Record<string, string | null>;
65
+ files: Record<string, string | null>;
66
+ };
67
+ export type SessionImpactSpecSnapshot = Pick<LoadedSpec, 'id' | 'path' | 'code' | 'codeEntries' | 'codeScoped' | 'related' | 'relatedEntries' | 'relatedScoped' | 'relationProblems'>;
68
+ export declare class SessionEvalUnavailableError extends Error {
69
+ name: string;
70
+ }
71
+ export declare class SessionImpactUnavailableError extends SessionEvalUnavailableError {
72
+ name: string;
73
+ }
74
+ export declare class SessionImpactRevisionMovedError extends SessionImpactUnavailableError {
75
+ name: string;
76
+ }
77
+ type LoadedSpec = Awaited<ReturnType<typeof loadSpecs>>[number];
78
+ export declare function projectSessionImpact(root: string, options: SessionImpactOptions): Promise<SessionImpactProjection>;
79
+ export declare function projectSessionImpactUncached(root: string, options: SessionImpactOptions, base: string, head: string): Promise<SessionImpactProjection>;
80
+ type SessionEvalReading = EvalEntry & {
81
+ inSession: boolean;
82
+ };
83
+ export declare function scopeSessionScenarioRows(current: Scenario[], scenarioInfo: ScenarioInfo[], evals: SessionEvalReading[], projected: readonly SessionImpactScenario[]): {
84
+ scenarios: SessionScenarioInfo[];
85
+ evals: SessionEvalReading[];
86
+ };
87
+ export declare function completeExportNodeIds(changedNodeIds: Iterable<string>, scopedNodeIds: Iterable<string>): string[];
88
+ export type ExportReading = {
89
+ scenario: string;
90
+ expected: string;
91
+ impact: ScenarioImpactReason[];
92
+ verdict?: EvalEntry['verdict'];
93
+ fresh: boolean;
94
+ staleAxes: string[];
95
+ score: ScoreState;
96
+ evaluator?: string;
97
+ ts: string;
98
+ evidence: {
99
+ kind: 'image';
100
+ dataUri: string;
101
+ } | {
102
+ kind: 'video';
103
+ dataUri: string;
104
+ } | {
105
+ kind: 'transcript';
106
+ text: string;
107
+ } | {
108
+ kind: 'data';
109
+ text: string;
110
+ } | {
111
+ kind: 'miss';
112
+ } | {
113
+ kind: 'none';
114
+ };
115
+ };
116
+ export type ExportUnmeasured = {
117
+ scenario: string;
118
+ expected: string;
119
+ impact: ScenarioImpactReason[];
120
+ };
121
+ export type ExportFile = ReviewDiffFile & {
122
+ patch: string;
123
+ oldText: string | null;
124
+ newText: string | null;
125
+ truncated: boolean;
126
+ omitted: boolean;
127
+ };
128
+ export type ExportNode = {
129
+ id: string;
130
+ title: string;
131
+ hue: number;
132
+ desc: string;
133
+ files: ExportFile[];
134
+ additions: number;
135
+ deletions: number;
136
+ hasEvalFile: boolean;
137
+ uncoveredFrontend: boolean;
138
+ affectedScenarios: number;
139
+ score: ScoreState;
140
+ readings: ExportReading[];
141
+ unmeasured: ExportUnmeasured[];
142
+ };
143
+ export type ExportGate = {
144
+ label: string;
145
+ ok: boolean;
146
+ detail: string;
147
+ };
148
+ export type ExportModel = {
149
+ id: string;
150
+ node: string | null;
151
+ branch: string | null;
152
+ title: string;
153
+ generatedAt: string;
154
+ ahead: number;
155
+ dirtyNonRuntime: number;
156
+ gates: ExportGate[];
157
+ score: {
158
+ passed: number;
159
+ total: number;
160
+ fresh: number;
161
+ };
162
+ impact: SessionImpactProjection;
163
+ nodes: ExportNode[];
164
+ otherFiles: ExportFile[];
165
+ };
166
+ export declare function buildExportModel(id: string): Promise<ExportModel | null>;
167
+ export declare function scopedScenarioReadings(scenarios: SessionScenarioInfo[], readings: EvalEntry[]): {
168
+ latest: EvalEntry[];
169
+ unmeasured: SessionScenarioInfo[];
170
+ };
171
+ export declare function declaredLatest(tl: EvalTimeline): EvalEntry[];
172
+ export declare function nodeScore(hasEvalFile: boolean, latest: EvalEntry[], affectedScenarios?: number): ScoreState;
173
+ export declare function parsePorcelainPaths(out: string): Set<string>;
174
+ export declare function sessionImpactOverlay(wtPath: string, dirty: {
175
+ paths: ReadonlySet<string>;
176
+ status: string;
177
+ }): Promise<SessionImpactOverlay | undefined>;
178
+ export declare function renderExportHtml(m: ExportModel): string;
179
+ export type SessionEvalNode = {
180
+ id: string;
181
+ title: string;
182
+ hue: number;
183
+ desc: string;
184
+ hasEvalFile: boolean;
185
+ uncoveredFrontend: boolean;
186
+ unknownCoverage: string[];
187
+ causes: SessionImpactNodeCause[];
188
+ scenarios: SessionScenarioInfo[];
189
+ evals: (EvalEntry & {
190
+ inSession: boolean;
191
+ })[];
192
+ };
193
+ export type SessionEvals = {
194
+ id: string;
195
+ node: string | null;
196
+ branch: string | null;
197
+ title: string;
198
+ nodes: SessionEvalNode[];
199
+ impact: SessionImpactProjection;
200
+ summary?: SessionEvalSummary;
201
+ evalRevision: SessionEvalRevision;
202
+ order?: SessionEvalOrderRow[];
203
+ };
204
+ export type SessionEvalSummary = {
205
+ measured: number;
206
+ total: number;
207
+ pass: number;
208
+ fail: number;
209
+ review: number;
210
+ blind: number;
211
+ unknown: number;
212
+ };
213
+ export type SessionEvalRevision = {
214
+ epoch: string;
215
+ generation: number;
216
+ content: string;
217
+ };
218
+ export type SessionEvalProjection = {
219
+ epoch: string;
220
+ generation: number;
221
+ phase: 'loading' | 'updating' | 'ready' | 'error';
222
+ revision?: string;
223
+ value?: SessionEvalSummary;
224
+ lastKnown?: {
225
+ generation: number;
226
+ revision: string;
227
+ value: SessionEvalSummary;
228
+ };
229
+ };
230
+ export declare function sessionEvalSummary(nodes: SessionEvalNode[]): SessionEvalSummary;
231
+ export type SessionEvalOrderRow = {
232
+ node: string;
233
+ scenario: string;
234
+ ts: string | null;
235
+ };
236
+ export type SessionEvalFocus = (order: SessionEvalOrderRow[]) => readonly string[];
237
+ export declare function orderRowsOf(nodes: SessionEvalNode[]): SessionEvalOrderRow[];
238
+ export declare function sessionEvalContentRevision(wtPath: string): Promise<string>;
239
+ type SummaryBuildResult = {
240
+ kind: 'stable';
241
+ revision: string;
242
+ summary: SessionEvalSummary;
243
+ } | {
244
+ kind: 'unstable';
245
+ } | {
246
+ kind: 'missing';
247
+ };
248
+ export type SessionEvalSummaryBuilder = (id: string, path: string) => Promise<SummaryBuildResult>;
249
+ type ProjectionTarget = 'all' | {
250
+ id?: string;
251
+ path?: string;
252
+ };
253
+ export declare class SessionEvalProjectionCache {
254
+ private readonly build;
255
+ readonly epoch: string;
256
+ private readonly entries;
257
+ private readonly observerHolds;
258
+ private readonly observerWaiters;
259
+ private readonly flights;
260
+ private notify;
261
+ private precompute;
262
+ private readonly demands;
263
+ constructor(build: SessionEvalSummaryBuilder, notify?: () => void, epoch?: string, precompute?: boolean);
264
+ setNotify(notify: () => void): void;
265
+ setPrecompute(enabled: boolean): void;
266
+ private authorize;
267
+ private ensureEntry;
268
+ snapshot(sessions: {
269
+ id: string;
270
+ path: string;
271
+ liveness?: string;
272
+ }[]): Map<string, SessionEvalProjection>;
273
+ invalidate(target?: ProjectionTarget): number;
274
+ holdObserver(observer: string, target?: ProjectionTarget): boolean;
275
+ releaseObserver(observer: string): boolean;
276
+ isObserverHeld(id: string, path: string): boolean;
277
+ waitUntilObservable(id: string, path: string, timeoutMs: number): Promise<boolean>;
278
+ get(id: string): SessionEvalProjection | null;
279
+ demand<T>(id: string, path: string, run: () => Promise<T>): Promise<T>;
280
+ idle(): Promise<void>;
281
+ accept(id: string, generation: number, revision: string, value: SessionEvalSummary): boolean;
282
+ private project;
283
+ private matches;
284
+ private publish;
285
+ private startScheduled;
286
+ private startEntry;
287
+ private runEntry;
288
+ }
289
+ export declare function setSessionEvalProjectionNotify(notify: () => void): void;
290
+ export declare function setSessionEvalProjectionWarmup(enabled: boolean): void;
291
+ export declare function sessionEvalProjections(sessions: {
292
+ id: string;
293
+ path: string;
294
+ liveness?: string;
295
+ }[]): Map<string, SessionEvalProjection>;
296
+ export declare function sessionEvalProjection(id: string): SessionEvalProjection | null;
297
+ export declare function invalidateSessionEvalProjections(target?: 'all' | {
298
+ id?: string;
299
+ path?: string;
300
+ }): number;
301
+ export declare function holdSessionEvalProjectionObserver(observer: string, target?: 'all' | {
302
+ id?: string;
303
+ path?: string;
304
+ }): boolean;
305
+ export declare function releaseSessionEvalProjectionObserver(observer: string): boolean;
306
+ export declare function awaitSessionEvalProjectionIdle(): Promise<void>;
307
+ export declare function buildSessionEvals(id: string, pick?: SessionEvalFocus): Promise<SessionEvals | null>;