import { type ParsedTestCounts } from '../test-log-parser.js'; import { type StructuredTestResults } from '../structured-test-results.js'; import { type LogFetchStats } from '../log-fetch-stats.js'; export interface BatchPackageResult { slug: string; success: boolean; logs: string; /** Inner pcall execution time reported by the Luau batch runner. */ durationMs?: number; testCounts?: ParsedTestCounts; /** Why this package failed, when the failure is the parser's own verdict. */ error?: string; /** * Luau tracebacks found in this package's section. Reported, not gated on: * jest cannot count these, since a deferred-callback crash fires outside any * test — often after the test that scheduled it already passed. */ tracebackCount: number; /** * Where `testCounts` came from. `returned` means the run handed them over as a * value; `scraped` means they were read out of log text, which is the channel * truncation destroys. Absent when there are no counts at all. * * Recorded because the two are otherwise indistinguishable in the output, and * a structured channel that quietly stopped flowing looks exactly like one * that never existed. */ countsSource?: 'returned' | 'scraped'; /** * True when this package's counts arrived but its log section did not. * * A narrower verdict than a package with a section gets: the counts say what * happened, but with no text there is nothing to check for tracebacks, and * nothing to read when something did go wrong. Reported so a pass that came * back half-blind cannot be mistaken for an ordinary one. */ logsLost?: boolean; /** * What this package's own run returned, recovered from the batch summary. * * One execution covers every package, so its return value belongs to none of * them — the batch runner splits the per-package results into the summary * instead, and this puts them back in the shape a single run's results have. * Lossy by design: the summary carries counts, not failure text, which is * per-package and already in that package's log section. */ testResults?: StructuredTestResults; } export interface ParseBatchTestLogsOptions { /** * What the fetch that produced `rawLogs` had to do to collect them, when the * caller knows. Not used to judge a package — it only tells a failure that * has already happened how much of the run's output ever arrived. */ logFetchStats?: LogFetchStats; /** * Where diagnostics go. When set, the parser reports through this instead of * printing, so a caller that renders the run's output can hold them until * after it: a remark about a log window reads as nonsense above the log it * is describing. */ onDiagnostic?: (level: BatchDiagnosticLevel, message: string) => void; /** * What the batch script returned, when the transport carries return values. * * The same summary the script also prints, taken from the one channel the * engine's log buffer cannot truncate — an oversize return value fails the * task outright rather than arriving short, so a summary that arrives here is * whole. Preferred over the printed copy, which is only reached when this is * absent (a local bridge run, or a task that ended without an output). */ returnValues?: unknown[]; } /** * `group` and `endgroup` bracket a run of diagnostics that belong together, so * a finding repeated across many packages can be collapsed into one block * instead of one line each. */ export type BatchDiagnosticLevel = 'info' | 'warn' | 'verbose' | 'group' | 'endgroup'; /** * Print one diagnostic, honoring the grouping levels. * * `useGroups` is passed in rather than looked up, so the whole run agrees about * whether it is emitting workflow commands. Asking `isCI()` separately here, in * the renderer and in the reporter is three answers to one question. */ export declare function emitDiagnostic(level: BatchDiagnosticLevel, message: string, useGroups: boolean): void; /** * Counts the batch runner folds in from what a package's test script returned. * * Present only for a package whose script returns its results. Carried in the * summary rather than left to the logs because the summary prints last and * survives a truncated log window, which is where scraped counts are lost. */ interface SummaryCounts { passed: number; failed: number; skipped: number; total: number; suitesPassed: number; suitesFailed: number; suitesTotal: number; } interface SummaryEntry { slug: string; success: boolean; durationMs?: number; error?: string; counts?: SummaryCounts; /** False for a smoke test, so zero counts are not read as "no tests found". */ ranJest?: boolean; } interface BeginToken { kind: 'begin'; slug: string; } interface EndToken { kind: 'end'; slug: string; durationMs?: number; } interface SummaryToken { kind: 'summary'; /** Where the marker sat, so the JSON payload can be looked up around it. */ lineIndex: number; } interface SummaryPayloadToken { kind: 'summaryPayload'; } interface ContentToken { kind: 'content'; /** The untrimmed line, since section logs are shown to a human verbatim. */ line: string; } /** One log line, classified. Every line becomes exactly one token. */ export type BatchLogToken = BeginToken | EndToken | SummaryToken | SummaryPayloadToken | ContentToken; /** * Parse the single batch execution's logs into per-package results. * * The batch Luau template prints structured markers around each package's output: * ===BATCH_TEST_BEGIN === * ... test output ... * ===BATCH_TEST_END PASS|FAIL === * ===BATCH_TEST_SUMMARY=== * [{"slug":"maid","success":true,"durationMs":1234}, ...] * * Success is determined from the JSON summary (based on pcall results), which is * immune to log reordering. The BEGIN/END markers are used only for splitting logs * into per-package sections. Jest failure detection provides a secondary override. */ export declare function parseBatchTestLogs(rawLogs: string, slugMap: Map, options?: ParseBatchTestLogsOptions): Map; /** * Classify every log line, so section splitting reads tokens instead of text. */ export declare function tokenizeBatchLog(lines: string[]): BatchLogToken[]; /** * Find the summary array among a task's return values. * * The batch script returns the same array it prints. Recognized by shape rather * than by position: a run is free to return other things, and an array of * objects that all carry a string `slug` is the summary and nothing else. */ export declare function findReturnedSummaryEntries(returnValues: unknown[] | undefined): SummaryEntry[] | undefined; /** * Find the summary array in the lines following the summary marker. * * The marker is printed last, but the API does not deliver messages in order, * so unrelated output can land after it. Treating everything past the marker as * one JSON blob therefore fails intermittently — the same batch parses on one * run and not the next. Scan for the array instead of assuming it is alone. */ export declare function findSummaryEntries(lines: string[], startIndex: number): SummaryEntry[] | undefined; export { countTracebacks } from '../test-log-parser.js'; //# sourceMappingURL=batch-log-parser.d.ts.map