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.
Files changed (78) hide show
  1. package/README.md +3 -1
  2. package/dist/adapters/registry.js +6 -1
  3. package/dist/adapters/types.d.ts +3 -0
  4. package/dist/cli/commands/approve.d.ts +1 -0
  5. package/dist/cli/commands/approve.js +118 -9
  6. package/dist/cli/commands/doctor.d.ts +10 -0
  7. package/dist/cli/commands/doctor.js +44 -29
  8. package/dist/cli/commands/fleet.js +199 -33
  9. package/dist/cli/commands/init.js +196 -6
  10. package/dist/cli/commands/plan.js +20 -4
  11. package/dist/cli/commands/resume.js +4 -2
  12. package/dist/cli/commands/run.js +11 -2
  13. package/dist/cli/commands/verify.js +102 -81
  14. package/dist/cli/help.d.ts +2 -0
  15. package/dist/cli/help.js +3 -1
  16. package/dist/config/config.d.ts +25 -8
  17. package/dist/config/config.js +41 -29
  18. package/dist/config/fleet-overlay.d.ts +3 -9
  19. package/dist/config/fleet-overlay.js +114 -19
  20. package/dist/config/fleet-why.d.ts +7 -0
  21. package/dist/config/fleet-why.js +5 -0
  22. package/dist/drivers/index.d.ts +15 -1
  23. package/dist/drivers/index.js +39 -10
  24. package/dist/drivers/orca.d.ts +119 -10
  25. package/dist/drivers/orca.js +781 -110
  26. package/dist/gates/baseline.d.ts +17 -3
  27. package/dist/gates/baseline.js +63 -15
  28. package/dist/gates/cache.d.ts +101 -0
  29. package/dist/gates/cache.js +401 -0
  30. package/dist/gates/llm.d.ts +3 -0
  31. package/dist/gates/llm.js +11 -0
  32. package/dist/gates/review.d.ts +28 -3
  33. package/dist/gates/review.js +106 -14
  34. package/dist/gates/run-gates.d.ts +9 -1
  35. package/dist/gates/run-gates.js +407 -102
  36. package/dist/gates/test-manifest.d.ts +128 -0
  37. package/dist/gates/test-manifest.js +463 -0
  38. package/dist/gates/test-reporter.d.ts +4 -0
  39. package/dist/gates/test-reporter.js +57 -0
  40. package/dist/graph/graph.d.ts +2 -0
  41. package/dist/graph/graph.js +45 -1
  42. package/dist/route/preference.d.ts +22 -1
  43. package/dist/route/preference.js +123 -25
  44. package/dist/route/router.js +31 -6
  45. package/dist/run/consult.js +5 -4
  46. package/dist/run/daemon.d.ts +15 -0
  47. package/dist/run/daemon.js +638 -167
  48. package/dist/run/execution-budget.d.ts +25 -0
  49. package/dist/run/execution-budget.js +142 -0
  50. package/dist/run/git.d.ts +50 -1
  51. package/dist/run/git.js +131 -12
  52. package/dist/run/journal.d.ts +16 -2
  53. package/dist/run/journal.js +115 -25
  54. package/dist/run/lease.d.ts +58 -0
  55. package/dist/run/lease.js +310 -0
  56. package/dist/run/merge.d.ts +2 -0
  57. package/dist/run/merge.js +91 -3
  58. package/dist/run/operator-state.d.ts +11 -0
  59. package/dist/run/operator-state.js +17 -3
  60. package/dist/run/recovery.d.ts +8 -0
  61. package/dist/run/recovery.js +25 -0
  62. package/dist/run/repair-selection.d.ts +12 -0
  63. package/dist/run/repair-selection.js +56 -0
  64. package/dist/run/stall.d.ts +6 -1
  65. package/dist/run/stall.js +60 -3
  66. package/dist/tui/cockpit/board.d.ts +96 -0
  67. package/dist/tui/cockpit/board.js +346 -0
  68. package/dist/tui/cockpit/decision-actions.js +2 -0
  69. package/dist/tui/cockpit/layout.d.ts +5 -1
  70. package/dist/tui/cockpit/layout.js +8 -3
  71. package/dist/tui/cockpit/live-runtime.js +71 -21
  72. package/dist/tui/cockpit/run-view.d.ts +7 -5
  73. package/dist/tui/cockpit/run-view.js +12 -11
  74. package/dist/tui/ink/fleet-app.d.ts +49 -27
  75. package/dist/tui/ink/fleet-app.js +229 -38
  76. package/package.json +2 -2
  77. package/skills/tickmarkr-overseer/SKILL.md +173 -113
  78. package/skills/tickmarkr-overseer/scripts/grade-ci.sh +29 -2
@@ -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 reported by the runner summary; null when unavailable. */
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 declare function compareToBaseline(cwd: string, commands: Record<string, string>, baseline: Baseline, enabled: string[], opts?: {
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 waitForCalmWindow(): Promise<number>;
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?: {
@@ -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"), fileCount: runnerFileCount(raw) };
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), fileCount: runnerFileCount(raw) };
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, "")))), fileCount: runnerFileCount(raw) };
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
- fileCount: runnerFileCount(raw),
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
- const provenance = { durationMs: r.durationMs ?? 0, referenceMs: entry?.durationMs ?? 0, waitedMs };
701
- results.push(...await compareToBaseline(cwd, { [name]: cmd }, baseline, [name], { ...opts, infraRerun: provenance }));
702
- continue;
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
- const provenance = { durationMs: r.durationMs ?? 0, referenceMs: entry?.durationMs ?? 0, waitedMs };
710
- results.push(...await compareToBaseline(cwd, { [name]: cmd }, baseline, [name], { ...opts, rerunOf: provenance }));
711
- continue;
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 async function waitForCalmWindow() {
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
- await new Promise((resolve) => setTimeout(resolve, calm.pollMs));
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;