tickmarkr 2.5.4 → 2.5.6
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/README.md +3 -1
- package/dist/adapters/registry.js +6 -1
- package/dist/adapters/types.d.ts +3 -0
- package/dist/cli/commands/approve.d.ts +1 -0
- package/dist/cli/commands/approve.js +118 -9
- package/dist/cli/commands/doctor.d.ts +10 -0
- package/dist/cli/commands/doctor.js +44 -29
- package/dist/cli/commands/fleet.js +199 -33
- package/dist/cli/commands/init.js +196 -6
- package/dist/cli/commands/plan.js +20 -4
- package/dist/cli/commands/resume.js +4 -2
- package/dist/cli/commands/run.js +11 -2
- package/dist/cli/commands/verify.js +102 -81
- package/dist/cli/help.d.ts +2 -0
- package/dist/cli/help.js +3 -1
- package/dist/config/config.d.ts +25 -8
- package/dist/config/config.js +41 -29
- package/dist/config/fleet-overlay.d.ts +3 -9
- package/dist/config/fleet-overlay.js +114 -19
- package/dist/config/fleet-why.d.ts +7 -0
- package/dist/config/fleet-why.js +5 -0
- package/dist/drivers/index.d.ts +15 -1
- package/dist/drivers/index.js +39 -10
- package/dist/drivers/orca.d.ts +119 -10
- package/dist/drivers/orca.js +781 -110
- package/dist/gates/baseline.d.ts +17 -3
- package/dist/gates/baseline.js +63 -15
- package/dist/gates/cache.d.ts +101 -0
- package/dist/gates/cache.js +401 -0
- package/dist/gates/llm.d.ts +3 -0
- package/dist/gates/llm.js +11 -0
- package/dist/gates/review.d.ts +28 -3
- package/dist/gates/review.js +106 -14
- package/dist/gates/run-gates.d.ts +9 -1
- package/dist/gates/run-gates.js +407 -102
- package/dist/gates/test-manifest.d.ts +128 -0
- package/dist/gates/test-manifest.js +463 -0
- package/dist/gates/test-reporter.d.ts +4 -0
- package/dist/gates/test-reporter.js +57 -0
- package/dist/graph/graph.d.ts +2 -0
- package/dist/graph/graph.js +45 -1
- package/dist/route/preference.d.ts +22 -1
- package/dist/route/preference.js +123 -25
- package/dist/route/router.js +31 -6
- package/dist/run/consult.js +5 -4
- package/dist/run/daemon.d.ts +15 -0
- package/dist/run/daemon.js +638 -167
- package/dist/run/execution-budget.d.ts +25 -0
- package/dist/run/execution-budget.js +142 -0
- package/dist/run/git.d.ts +50 -1
- package/dist/run/git.js +131 -12
- package/dist/run/journal.d.ts +16 -2
- package/dist/run/journal.js +115 -25
- package/dist/run/lease.d.ts +58 -0
- package/dist/run/lease.js +310 -0
- package/dist/run/merge.d.ts +2 -0
- package/dist/run/merge.js +91 -3
- package/dist/run/operator-state.d.ts +11 -0
- package/dist/run/operator-state.js +17 -3
- package/dist/run/recovery.d.ts +8 -0
- package/dist/run/recovery.js +25 -0
- package/dist/run/repair-selection.d.ts +12 -0
- package/dist/run/repair-selection.js +56 -0
- package/dist/run/stall.d.ts +6 -1
- package/dist/run/stall.js +60 -3
- package/dist/tui/cockpit/board.d.ts +96 -0
- package/dist/tui/cockpit/board.js +346 -0
- package/dist/tui/cockpit/decision-actions.js +2 -0
- package/dist/tui/cockpit/layout.d.ts +5 -1
- package/dist/tui/cockpit/layout.js +8 -3
- package/dist/tui/cockpit/live-runtime.js +71 -21
- package/dist/tui/cockpit/run-view.d.ts +7 -5
- package/dist/tui/cockpit/run-view.js +12 -11
- package/dist/tui/ink/fleet-app.d.ts +49 -27
- package/dist/tui/ink/fleet-app.js +229 -38
- package/package.json +2 -2
- package/skills/tickmarkr-overseer/SKILL.md +173 -113
- package/skills/tickmarkr-overseer/scripts/grade-ci.sh +29 -2
package/dist/gates/baseline.d.ts
CHANGED
|
@@ -31,12 +31,19 @@ export interface BaselineCommand {
|
|
|
31
31
|
durationMs?: number;
|
|
32
32
|
/** Sum of the per-file durations named by the runner; null when its output names none. */
|
|
33
33
|
fileDurationSumMs?: number | null;
|
|
34
|
-
/** Total files
|
|
34
|
+
/** Total files the runner would collect; null when unavailable. */
|
|
35
35
|
fileCount?: number | null;
|
|
36
|
+
/** OBS-1044: `manifest` when `fileCount` came from the runner's own listing (test-manifest.ts's
|
|
37
|
+
* discovery seam) rather than a stdout summary sum. Absent on every pre-2.5.6 entry and on every
|
|
38
|
+
* scripted non-runner command, whose summary count keeps the stdout deficit rule byte-identically. */
|
|
39
|
+
fileCountSource?: "manifest";
|
|
36
40
|
/** fileDurationSumMs / durationMs — average implied file concurrency, not a configured fork count. */
|
|
37
41
|
impliedParallelism?: number | null;
|
|
38
42
|
/** The slowest per-file entry named by the runner; null when per-file timing is unavailable. */
|
|
39
43
|
longestFile?: BaselineFileDuration | null;
|
|
44
|
+
/** VL-1: every per-file duration the runner named, so a later per-file hang budget (test-manifest.ts)
|
|
45
|
+
* can be derived per file rather than from one slowest-file number; null when unavailable. */
|
|
46
|
+
fileDurations?: BaselineFileDuration[] | null;
|
|
40
47
|
/** The ceiling that measurement implies, persisted so every later battery uses the same number. */
|
|
41
48
|
ceilingMs?: number;
|
|
42
49
|
/**
|
|
@@ -147,6 +154,9 @@ export declare function ceilingKillResult(gate: string, r: ShResult, ceilingMs:
|
|
|
147
154
|
* shell asks it to finish faster than the thing it is measuring.
|
|
148
155
|
*/
|
|
149
156
|
export declare const CAPTURE_CEILING_MS = 1800000;
|
|
157
|
+
/** OBS-1044: a cached vitest entry whose count is a stdout sum may be inflated; only a manifest-derived
|
|
158
|
+
* count is safe to apply as a deficit floor. A null count compares nothing and is safe as-is. */
|
|
159
|
+
export declare function staleFileCountCommands(baseline: Baseline, commands: Record<string, string>, cwd: string): string[];
|
|
150
160
|
export declare function captureBaseline(cwd: string, commands: Record<string, string>): Promise<Baseline>;
|
|
151
161
|
export interface VacuousOracleWarning {
|
|
152
162
|
kind: "vacuous-oracle";
|
|
@@ -158,7 +168,10 @@ export declare function detectVacuousOracles(cwd: string, tasks: ReadonlyArray<{
|
|
|
158
168
|
id: string;
|
|
159
169
|
acceptance: AcceptanceItem[];
|
|
160
170
|
}>): Promise<VacuousOracleWarning[]>;
|
|
161
|
-
export
|
|
171
|
+
export interface RetryOptions {
|
|
172
|
+
authorizeRetry?: (cause: "infra" | "host-starved") => boolean;
|
|
173
|
+
}
|
|
174
|
+
export declare function compareToBaseline(cwd: string, commands: Record<string, string>, baseline: Baseline, enabled: string[], opts?: RetryOptions & {
|
|
162
175
|
rerunOf?: HostStarvedRerun;
|
|
163
176
|
infraRerun?: HostStarvedRerun;
|
|
164
177
|
selected?: readonly string[];
|
|
@@ -182,7 +195,8 @@ interface CalmWindow {
|
|
|
182
195
|
}
|
|
183
196
|
export declare function setCalmWindowForTests(over: Partial<CalmWindow>): void;
|
|
184
197
|
export declare function resetCalmWindowForTests(): void;
|
|
185
|
-
export declare function
|
|
198
|
+
export declare function calmWindowReady(): boolean;
|
|
199
|
+
export declare function waitForCalmWindow(signal?: AbortSignal): Promise<number>;
|
|
186
200
|
/** Summary totals survive digit-normalized fingerprints and exclude test-owned echoed output. */
|
|
187
201
|
export declare function runnerFileCount(raw: string): number | null;
|
|
188
202
|
export declare function fileCountDeficit(entry: BaselineCommand | undefined, raw: string, opts?: {
|
package/dist/gates/baseline.js
CHANGED
|
@@ -2,6 +2,8 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { availableParallelism, loadavg } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { DEFAULT_SHELL_TIMEOUT_MS, describeCapacity, sameCapacity, sh } from "../run/git.js";
|
|
5
|
+
import { executionSignal } from "../run/execution-budget.js";
|
|
6
|
+
import { isVitestTestCommand, manifestFileCount } from "./test-manifest.js";
|
|
5
7
|
// incident #2 (run-20260709-104447): a vitest ✓ PASS line with "error" in the test NAME, wrapped in ANSI
|
|
6
8
|
// codes that varied between baseline and worktree runs, was reported as a "new failure". Strip ANSI first;
|
|
7
9
|
// a pass-marker line is never a failure. [\d;#] covers raw ANSI and digit-normalized ANSI ("\x1b[#m") from
|
|
@@ -230,13 +232,14 @@ function fileTiming(output, wallClockMs) {
|
|
|
230
232
|
files.push({ file: match[1], durationMs });
|
|
231
233
|
}
|
|
232
234
|
if (!files.length)
|
|
233
|
-
return { fileDurationSumMs: null, impliedParallelism: null, longestFile: null };
|
|
235
|
+
return { fileDurationSumMs: null, impliedParallelism: null, longestFile: null, fileDurations: null };
|
|
234
236
|
const fileDurationSumMs = files.reduce((sum, entry) => sum + entry.durationMs, 0);
|
|
235
237
|
const longestFile = files.reduce((longest, entry) => entry.durationMs > longest.durationMs ? entry : longest);
|
|
236
238
|
return {
|
|
237
239
|
fileDurationSumMs,
|
|
238
240
|
impliedParallelism: wallClockMs > 0 ? fileDurationSumMs / wallClockMs : null,
|
|
239
241
|
longestFile,
|
|
242
|
+
fileDurations: files,
|
|
240
243
|
};
|
|
241
244
|
}
|
|
242
245
|
// A failing command whose output holds no shape any runner here names. The marker is content-free and
|
|
@@ -463,6 +466,27 @@ const invalidCaptureEntry = (durationMs, invalidCause, invalidatingLines = []) =
|
|
|
463
466
|
ceilingMs: effectiveCeilingMs({ durationMs }),
|
|
464
467
|
...(invalidatingLines.length ? { invalidatingLines } : {}),
|
|
465
468
|
});
|
|
469
|
+
// OBS-1044: a vitest command's count is the manifest discovery seam's (the same listing the gate
|
|
470
|
+
// asks the report to certify), never a sum of every summary line in stdout — tests that spawn
|
|
471
|
+
// nested runners echo their own summaries through the filter and inflated a baseline by two files,
|
|
472
|
+
// so any diff that changed the nested echo read as a deficit. The listing is a collection, not a
|
|
473
|
+
// run: the suite still runs exactly once here. Any other command keeps the stdout sum.
|
|
474
|
+
const captureFileCount = async (cwd, cmd, raw) => {
|
|
475
|
+
if (!isVitestTestCommand(cmd, cwd))
|
|
476
|
+
return { fileCount: runnerFileCount(raw) };
|
|
477
|
+
const fileCount = await manifestFileCount(cmd, cwd);
|
|
478
|
+
return fileCount === null ? { fileCount } : { fileCount, fileCountSource: "manifest" };
|
|
479
|
+
};
|
|
480
|
+
/** OBS-1044: a cached vitest entry whose count is a stdout sum may be inflated; only a manifest-derived
|
|
481
|
+
* count is safe to apply as a deficit floor. A null count compares nothing and is safe as-is. */
|
|
482
|
+
export function staleFileCountCommands(baseline, commands, cwd) {
|
|
483
|
+
return Object.entries(commands)
|
|
484
|
+
.filter(([name, cmd]) => {
|
|
485
|
+
const entry = baseline.commands[name];
|
|
486
|
+
return entry?.fileCount != null && entry.fileCountSource !== "manifest" && isVitestTestCommand(cmd, cwd);
|
|
487
|
+
})
|
|
488
|
+
.map(([name]) => name);
|
|
489
|
+
}
|
|
466
490
|
export async function captureBaseline(cwd, commands) {
|
|
467
491
|
const base = { commands: {} };
|
|
468
492
|
for (const [name, cmd] of Object.entries(commands)) {
|
|
@@ -494,7 +518,7 @@ export async function captureBaseline(cwd, commands) {
|
|
|
494
518
|
console.error(`tickmarkr: baseline capture for "${name}" was killed at its ${CAPTURE_CEILING_MS}ms ceiling — `
|
|
495
519
|
+ `it recorded NO fingerprints, so nothing is forgiven and every gate will treat a pre-existing `
|
|
496
520
|
+ `failure as a fresh one. Raise the ceiling or shorten the command.`);
|
|
497
|
-
base.commands[name] = { ...invalidCaptureEntry(durationMs, "ceiling-kill"),
|
|
521
|
+
base.commands[name] = { ...invalidCaptureEntry(durationMs, "ceiling-kill"), ...await captureFileCount(cwd, cmd, raw) };
|
|
498
522
|
continue;
|
|
499
523
|
}
|
|
500
524
|
// Run 2137: the child exited and printed ordinary FAIL/AssertionError lines, so the gate-side
|
|
@@ -508,7 +532,7 @@ export async function captureBaseline(cwd, commands) {
|
|
|
508
532
|
+ `it recorded NO exit-code verdict and NO fingerprints, so nothing is forgiven for this command; `
|
|
509
533
|
+ `the measurement cannot distinguish a pre-existing failure from one caused by exhaustion. `
|
|
510
534
|
+ `First invalidating line: ${invalidatingLines[0]}`);
|
|
511
|
-
base.commands[name] = { ...invalidCaptureEntry(durationMs, "resource-exhaustion", invalidatingLines),
|
|
535
|
+
base.commands[name] = { ...invalidCaptureEntry(durationMs, "resource-exhaustion", invalidatingLines), ...await captureFileCount(cwd, cmd, raw) };
|
|
512
536
|
continue;
|
|
513
537
|
}
|
|
514
538
|
// OBS-966: a worker RPC timeout is infra even beside an all-green summary.
|
|
@@ -516,7 +540,7 @@ export async function captureBaseline(cwd, commands) {
|
|
|
516
540
|
const runnerVerdict = classifyRunnerOutput(raw, r.code);
|
|
517
541
|
if (runnerVerdict === "infra") {
|
|
518
542
|
console.error(`tickmarkr: baseline capture for "${name}" carries runner-infrastructure evidence — it recorded NO verdict; nothing is forgiven for this command`);
|
|
519
|
-
base.commands[name] = { ...invalidCaptureEntry(durationMs, "infra", withoutVitestEchoBlocks(combinedOutput).filter((line) => isInfraLine(line.replace(ANSI_RE, "")))),
|
|
543
|
+
base.commands[name] = { ...invalidCaptureEntry(durationMs, "infra", withoutVitestEchoBlocks(combinedOutput).filter((line) => isInfraLine(line.replace(ANSI_RE, "")))), ...await captureFileCount(cwd, cmd, raw) };
|
|
520
544
|
continue;
|
|
521
545
|
}
|
|
522
546
|
base.commands[name] = {
|
|
@@ -528,7 +552,7 @@ export async function captureBaseline(cwd, commands) {
|
|
|
528
552
|
missingCommand: missingConfiguredCommand(cmd, r),
|
|
529
553
|
durationMs,
|
|
530
554
|
...fileTiming(raw, durationMs),
|
|
531
|
-
|
|
555
|
+
...await captureFileCount(cwd, cmd, raw),
|
|
532
556
|
ceilingMs: effectiveCeilingMs({ durationMs }),
|
|
533
557
|
// T7: the world this measurement was taken in, so a later reader can ask whether its own world
|
|
534
558
|
// is the same one. Recorded from THIS command's own shell result, never re-derived here.
|
|
@@ -614,7 +638,10 @@ export async function compareToBaseline(cwd, commands, baseline, enabled, opts =
|
|
|
614
638
|
// T7: every verdict below carries the capacity ITS OWN command ran under, taken off the shell
|
|
615
639
|
// result rather than re-derived after the fact. The skip row above ran no command and therefore
|
|
616
640
|
// states no capacity — a row that never divided the machine must not claim that it did.
|
|
641
|
+
let recoveryBlocked;
|
|
617
642
|
const record = (g) => {
|
|
643
|
+
if (recoveryBlocked)
|
|
644
|
+
g = { ...g, meta: { ...g.meta, recoveryBlocked } };
|
|
618
645
|
const withReap = r.reapedGroup ? { ...g, meta: { ...g.meta, reapedGroup: true } } : g;
|
|
619
646
|
const withReapError = r.reapError ? { ...withReap, meta: { ...withReap.meta, reapError: r.reapError } } : withReap;
|
|
620
647
|
const withRerun = rerunOf ? {
|
|
@@ -696,19 +723,37 @@ export async function compareToBaseline(cwd, commands, baseline, enabled, opts =
|
|
|
696
723
|
// retain the whole-output read so a repeated infra abort can never be baseline-forgiven as green.
|
|
697
724
|
const classification = classifyFreshRunnerOutput(entry, raw, r.code);
|
|
698
725
|
if (name === "test" && classification === "infra" && !rerunOf && !opts.infraRerun) {
|
|
699
|
-
const waitedMs = await waitForCalmWindow();
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
726
|
+
const waitedMs = await waitForCalmWindow(executionSignal());
|
|
727
|
+
if (opts.authorizeRetry && !calmWindowReady()) {
|
|
728
|
+
recoveryBlocked = "calm window unavailable within the existing wait ceiling";
|
|
729
|
+
}
|
|
730
|
+
else if (opts.authorizeRetry && !opts.authorizeRetry("infra")) {
|
|
731
|
+
recoveryBlocked = "infrastructure retry allowance exhausted or subject unavailable";
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
const provenance = { durationMs: r.durationMs ?? 0, referenceMs: entry?.durationMs ?? 0, waitedMs };
|
|
735
|
+
results.push(...await compareToBaseline(cwd, { [name]: cmd }, baseline, [name], { ...opts, infraRerun: provenance }));
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
703
738
|
}
|
|
704
739
|
// OBS-896: every fresh failure must be timeout-class, and the suite must take at least twice its
|
|
705
740
|
// own baseline measurement. The first read buys one calm rerun here, never a worker repair.
|
|
706
741
|
if (name === "test" && classification !== "infra" && failing.length && !rerunOf && !opts.infraRerun
|
|
707
742
|
&& hostStarved(failing.join("\n"), r.durationMs ?? 0, entry?.durationMs)) {
|
|
708
|
-
const waitedMs = await waitForCalmWindow();
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
743
|
+
const waitedMs = await waitForCalmWindow(executionSignal());
|
|
744
|
+
if (opts.authorizeRetry && !calmWindowReady()) {
|
|
745
|
+
recoveryBlocked = "calm window unavailable within the existing wait ceiling";
|
|
746
|
+
}
|
|
747
|
+
else if (opts.authorizeRetry && !opts.authorizeRetry("host-starved")) {
|
|
748
|
+
recoveryBlocked = "verification retry allowance exhausted or subject unavailable";
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
// Compatibility with OBS-896, not an infrastructure reclassification: a persistent
|
|
752
|
+
// timeout remains the ordinary conservative verdict after the single bounded remeasure.
|
|
753
|
+
const provenance = { durationMs: r.durationMs ?? 0, referenceMs: entry?.durationMs ?? 0, waitedMs };
|
|
754
|
+
results.push(...await compareToBaseline(cwd, { [name]: cmd }, baseline, [name], { ...opts, rerunOf: provenance }));
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
712
757
|
}
|
|
713
758
|
if (classification === "infra") {
|
|
714
759
|
const evidence = failing.length
|
|
@@ -826,11 +871,14 @@ const DEFAULT_CALM = {
|
|
|
826
871
|
let calm = DEFAULT_CALM;
|
|
827
872
|
export function setCalmWindowForTests(over) { calm = { ...calm, ...over }; }
|
|
828
873
|
export function resetCalmWindowForTests() { calm = DEFAULT_CALM; }
|
|
829
|
-
export
|
|
874
|
+
export function calmWindowReady() { return calm.loadProvider() <= calm.calmLoad(); }
|
|
875
|
+
export async function waitForCalmWindow(signal) {
|
|
830
876
|
const started = Date.now();
|
|
831
877
|
while (calm.loadProvider() > calm.calmLoad() && Date.now() - started < calm.maxWaitMs) {
|
|
832
|
-
|
|
878
|
+
signal?.throwIfAborted();
|
|
879
|
+
await new Promise((resolve) => setTimeout(resolve, signal ? Math.min(calm.pollMs, 100) : calm.pollMs));
|
|
833
880
|
}
|
|
881
|
+
signal?.throwIfAborted();
|
|
834
882
|
return Date.now() - started;
|
|
835
883
|
}
|
|
836
884
|
/** Summary totals survive digit-normalized fingerprints and exclude test-owned echoed output. */
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { Baseline } from "./baseline.js";
|
|
2
|
+
import type { GateResult } from "./types.js";
|
|
3
|
+
import { type RunCapacity, type VerificationProtocol } from "../run/git.js";
|
|
4
|
+
export declare const DEFAULT_VERDICT_CACHE_BOUND = 128;
|
|
5
|
+
export declare function setVerdictCacheBoundForTests(bound: number | undefined): void;
|
|
6
|
+
export declare function resetVerdictCacheBoundForTests(): void;
|
|
7
|
+
export declare const LOCKFILES: readonly ["package-lock.json", "npm-shrinkwrap.json", "pnpm-lock.yaml", "yarn.lock", "bun.lock", "bun.lockb"];
|
|
8
|
+
export declare function lockfileHash(worktree: string): string;
|
|
9
|
+
export declare function canonicalJson(obj: unknown): string;
|
|
10
|
+
export declare function baselineIdentity(baseline?: Baseline): string;
|
|
11
|
+
export declare function getWorktreeTree(worktree: string): Promise<string>;
|
|
12
|
+
export interface GateEnvironmentInput {
|
|
13
|
+
nodeRuntime?: string;
|
|
14
|
+
lockfile?: string;
|
|
15
|
+
worktree?: string;
|
|
16
|
+
capacity?: RunCapacity;
|
|
17
|
+
selectedSet?: readonly string[];
|
|
18
|
+
scope?: VerificationScope;
|
|
19
|
+
/** R41: the verification protocol + runner lifecycle policy; defaults to this process's. */
|
|
20
|
+
verification?: VerificationProtocol;
|
|
21
|
+
}
|
|
22
|
+
export interface EnvironmentParts {
|
|
23
|
+
nodeRuntime: string;
|
|
24
|
+
lockfile: string;
|
|
25
|
+
capacity: RunCapacity;
|
|
26
|
+
selectedSet?: readonly string[];
|
|
27
|
+
verification: VerificationProtocol;
|
|
28
|
+
}
|
|
29
|
+
export declare function environmentFingerprint(env: GateEnvironmentInput): {
|
|
30
|
+
fingerprint: string;
|
|
31
|
+
parts: EnvironmentParts;
|
|
32
|
+
};
|
|
33
|
+
export type VerificationScope = "battery" | "tip" | "standalone";
|
|
34
|
+
export interface VerificationIdentity {
|
|
35
|
+
/** the gate the verdict answers — build/lint/test may share one command and are still three verdicts */
|
|
36
|
+
gate?: string;
|
|
37
|
+
/** which verifier produced it: a battery gate row or an integration-tip row (own report, own forgiveness rule) */
|
|
38
|
+
scope?: VerificationScope;
|
|
39
|
+
/** Checkout location is diagnostic metadata; equal trees share verdicts across worktrees. */
|
|
40
|
+
worktree?: string;
|
|
41
|
+
tree: string;
|
|
42
|
+
command: string;
|
|
43
|
+
baseline: string;
|
|
44
|
+
environment: string;
|
|
45
|
+
envParts?: EnvironmentParts;
|
|
46
|
+
}
|
|
47
|
+
export declare function computeVerificationIdentity(params: {
|
|
48
|
+
worktree: string;
|
|
49
|
+
gate: string;
|
|
50
|
+
scope?: VerificationScope;
|
|
51
|
+
command: string;
|
|
52
|
+
baseline?: Baseline;
|
|
53
|
+
selectedSet?: readonly string[];
|
|
54
|
+
capacity?: RunCapacity;
|
|
55
|
+
tree?: string;
|
|
56
|
+
lockfile?: string;
|
|
57
|
+
nodeRuntime?: string;
|
|
58
|
+
verification?: VerificationProtocol;
|
|
59
|
+
}): Promise<VerificationIdentity | undefined>;
|
|
60
|
+
export declare function verificationIdentityKey(id: VerificationIdentity): string;
|
|
61
|
+
export declare function formatReusedDetails(originalDetails: string, id: VerificationIdentity): string;
|
|
62
|
+
export interface CachedVerdict {
|
|
63
|
+
gate: string;
|
|
64
|
+
pass: boolean;
|
|
65
|
+
details: string;
|
|
66
|
+
exitCode?: number;
|
|
67
|
+
meta?: Record<string, unknown>;
|
|
68
|
+
capacity?: RunCapacity;
|
|
69
|
+
}
|
|
70
|
+
export declare function formatReusedRow(cached: CachedVerdict, id: VerificationIdentity): GateResult;
|
|
71
|
+
export declare function reusedIdentity(id: VerificationIdentity): Record<string, unknown>;
|
|
72
|
+
export declare function isInfraResult(result: GateResult | {
|
|
73
|
+
meta?: Record<string, unknown>;
|
|
74
|
+
details?: string;
|
|
75
|
+
cause?: string;
|
|
76
|
+
exitCode?: number;
|
|
77
|
+
}): boolean;
|
|
78
|
+
export declare function resolveStateDir(worktree: string, artifactDir?: string): string;
|
|
79
|
+
export declare function resolveVerdictStoreDir(stateDir: string): string;
|
|
80
|
+
export interface StoredVerdictRecord {
|
|
81
|
+
key: string;
|
|
82
|
+
identity: VerificationIdentity;
|
|
83
|
+
verdict: CachedVerdict;
|
|
84
|
+
timestamp: number;
|
|
85
|
+
sequence: number;
|
|
86
|
+
}
|
|
87
|
+
export declare function resetGlobalStoreSequenceForTests(): void;
|
|
88
|
+
export declare class VerdictStore {
|
|
89
|
+
readonly dir: string;
|
|
90
|
+
constructor(dir: string);
|
|
91
|
+
private initSequenceFromDisk;
|
|
92
|
+
private static unknownPolicy;
|
|
93
|
+
get(id?: VerificationIdentity): CachedVerdict | undefined;
|
|
94
|
+
set(id: VerificationIdentity | undefined, verdict: GateResult | CachedVerdict): boolean;
|
|
95
|
+
size(): number;
|
|
96
|
+
clear(): void;
|
|
97
|
+
evictOldest(bound?: number): number;
|
|
98
|
+
}
|
|
99
|
+
export declare function getVerdictStore(stateDir: string, options?: {
|
|
100
|
+
bound?: number;
|
|
101
|
+
}): VerdictStore;
|