@doccov/sdk 0.24.0 → 0.24.1

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/index.d.ts CHANGED
@@ -1,951 +1,951 @@
1
- import { EntryPointDetectionMethod } from "@openpkg-ts/spec";
1
+ import { DocCovSpec } from "@doccov/spec";
2
+ import { OpenPkg as OpenPkg2 } from "@openpkg-ts/spec";
3
+ type OpenPkgSpec = OpenPkg2;
4
+ interface BuildDocCovOptions {
5
+ openpkgPath: string;
6
+ openpkg: OpenPkgSpec;
7
+ packagePath?: string;
8
+ }
2
9
  /**
3
- * Configuration types for DocCov.
4
- * These types are shared between CLI and API.
10
+ * Build a DocCov spec from an OpenPkg spec.
11
+ *
12
+ * @param options - Build options
13
+ * @returns DocCov specification with coverage analysis
5
14
  */
15
+ declare function buildDocCovSpec(options: BuildDocCovOptions): DocCovSpec;
6
16
  /**
7
- * Documentation configuration options.
17
+ * All possible drift type identifiers.
8
18
  */
9
- interface DocsConfig {
10
- /** Glob patterns for markdown docs to include */
11
- include?: string[];
12
- /** Glob patterns for markdown docs to exclude */
13
- exclude?: string[];
14
- }
19
+ type DriftType = "param-mismatch" | "param-type-mismatch" | "return-type-mismatch" | "generic-constraint-mismatch" | "optionality-mismatch" | "deprecated-mismatch" | "visibility-mismatch" | "async-mismatch" | "property-type-drift" | "example-drift" | "example-syntax-error" | "example-runtime-error" | "example-assertion-failed" | "broken-link";
20
+ type SpecDocDrift = {
21
+ type: DriftType;
22
+ target?: string;
23
+ issue: string;
24
+ suggestion?: string;
25
+ };
15
26
  /**
16
- * Example validation modes.
27
+ * Drift categories group related drift types for progressive disclosure.
17
28
  */
18
- type ExampleValidationMode = "presence" | "typecheck" | "run";
29
+ type DriftCategory = "structural" | "semantic" | "example";
19
30
  /**
20
- * Schema extraction modes for validation libraries (Zod, Valibot, TypeBox, ArkType).
21
- *
22
- * - 'static': TypeScript Compiler API only (no runtime, always safe)
23
- * - 'runtime': Standard Schema runtime extraction (requires built package)
24
- * - 'hybrid': Try runtime first, fall back to static
31
+ * Maps each drift type to its category.
25
32
  */
26
- type SchemaExtractionMode = "static" | "runtime" | "hybrid";
33
+ declare const DRIFT_CATEGORIES: Record<DriftType, DriftCategory>;
27
34
  /**
28
- * Check command configuration options.
35
+ * Human-readable category labels.
29
36
  */
30
- interface CheckConfig {
31
- /**
32
- * Example validation modes to run.
33
- * Can be a single mode, array of modes, or comma-separated string.
34
- * - 'presence': Check that @example blocks exist on exports
35
- * - 'typecheck': Compile examples with TypeScript
36
- * - 'run': Execute examples and validate assertions
37
- */
38
- examples?: ExampleValidationMode | ExampleValidationMode[] | string;
39
- /** Minimum coverage percentage required (0-100) */
40
- minCoverage?: number;
41
- /** Maximum drift percentage allowed (0-100) */
42
- maxDrift?: number;
43
- }
37
+ declare const DRIFT_CATEGORY_LABELS: Record<DriftCategory, string>;
44
38
  /**
45
- * Normalized DocCov configuration.
46
- * This is the parsed/normalized form used by commands.
39
+ * Category descriptions for help text.
47
40
  */
48
- interface DocCovConfig {
49
- /** Export include patterns */
50
- include?: string[];
51
- /** Export exclude patterns */
52
- exclude?: string[];
53
- /** Plugins (future) */
54
- plugins?: unknown[];
55
- /** Documentation configuration */
56
- docs?: DocsConfig;
57
- /** Check command configuration */
58
- check?: CheckConfig;
59
- /**
60
- * Schema extraction mode for validation libraries.
61
- *
62
- * - 'static' (default): Safe, uses TypeScript Compiler API
63
- * - 'runtime': Uses Standard Schema (requires built package)
64
- * - 'hybrid': Tries runtime first, falls back to static
65
- *
66
- * Runtime extraction provides richer JSON Schema output (formats, patterns)
67
- * but requires the package to be built first.
68
- */
69
- schemaExtraction?: SchemaExtractionMode;
41
+ declare const DRIFT_CATEGORY_DESCRIPTIONS: Record<DriftCategory, string>;
42
+ type SpecDocsMetadata = {
43
+ coverageScore?: number;
44
+ missing?: string[];
45
+ drift?: SpecDocDrift[];
46
+ };
47
+ /**
48
+ * Result of computing drift for a single export.
49
+ */
50
+ type ExportDriftResult = {
51
+ id: string;
52
+ drift: SpecDocDrift[];
53
+ };
54
+ /**
55
+ * Result of computing drift for all exports.
56
+ */
57
+ type DriftResult = {
58
+ exports: Map<string, SpecDocDrift[]>;
59
+ };
60
+ /**
61
+ * Information about an for context-aware suggestions.
62
+ */
63
+ interface ExportInfo {
64
+ name: string;
65
+ kind: string;
66
+ isCallable: boolean;
70
67
  }
71
68
  /**
72
- * Define a DocCov configuration.
73
- * Helper function for type-safe configuration in doccov.config.ts.
74
- *
75
- * @param config - Configuration object
76
- * @returns The configuration object (for type inference)
77
- *
78
- * @example
79
- * ```typescript
80
- * // doccov.config.ts
81
- * import { defineConfig } from '@doccov/sdk';
82
- *
83
- * defineConfig({
84
- * include: ['MyClass', 'myFunction'],
85
- * exclude: ['internal*'],
86
- * check: {
87
- * minCoverage: 80,
88
- * },
89
- * });
90
- * ```
69
+ * Registry of exports and types for cross-reference validation.
91
70
  */
92
- declare function defineConfig(config: DocCovConfig): DocCovConfig;
93
- interface DocCovOptions {
94
- includePrivate?: boolean;
95
- followImports?: boolean;
96
- maxDepth?: number;
97
- resolveExternalTypes?: boolean;
98
- /** Enable spec caching (default: true) */
99
- useCache?: boolean;
100
- /** Working directory for cache operations (default: process.cwd()) */
101
- cwd?: string;
102
- /**
103
- * Schema extraction mode for validation libraries (Zod, Valibot, etc.)
104
- *
105
- * - 'static' (default): TypeScript Compiler API only (no runtime)
106
- * - 'runtime': Standard Schema runtime extraction (requires built package)
107
- * - 'hybrid': Try runtime first, fall back to static
108
- */
109
- schemaExtraction?: SchemaExtractionMode;
71
+ interface ExportRegistry {
72
+ /** Map of names to their info (for context-aware suggestions) */
73
+ exports: Map<string, ExportInfo>;
74
+ /** Set of type names (interfaces, type aliases, etc.) */
75
+ types: Set<string>;
76
+ /** Combined set of all names (for backward compatibility) */
77
+ all: Set<string>;
110
78
  }
111
79
  /**
112
- * Pre-detected Standard Schema for a variable export.
80
+ * Extended drift with category and fixability metadata.
113
81
  */
114
- interface DetectedSchemaEntry {
115
- schema: Record<string, unknown>;
116
- vendor: string;
82
+ interface CategorizedDrift extends SpecDocDrift {
83
+ category: DriftCategory;
84
+ fixable: boolean;
117
85
  }
118
- import { OpenPkg as OpenPkg2 } from "@openpkg-ts/spec";
119
- type OpenPkgSpec = OpenPkg2;
120
86
  /**
121
- * Input for generation metadata that comes from the caller (CLI, API, etc.)
87
+ * Summary of drift issues by category.
122
88
  */
123
- interface GenerationInput {
124
- /** Entry point file path (relative to package root) */
125
- entryPoint: string;
126
- /** How the entry point was detected */
127
- entryPointSource: EntryPointDetectionMethod;
128
- /** Whether this is a declaration-only analysis (.d.ts file) */
129
- isDeclarationOnly?: boolean;
130
- /** Generator tool name */
131
- generatorName: string;
132
- /** Generator tool version */
133
- generatorVersion: string;
134
- /** Detected package manager */
135
- packageManager?: string;
136
- /** Whether this is a monorepo */
137
- isMonorepo?: boolean;
138
- /** Target package name (for monorepos) */
139
- targetPackage?: string;
89
+ interface DriftSummary {
90
+ total: number;
91
+ byCategory: Record<DriftCategory, number>;
92
+ fixable: number;
140
93
  }
141
94
  /**
142
- * Compute a hash of file contents.
143
- * Uses truncated SHA-256 for balance of speed and collision resistance.
95
+ * Categorize a single drift issue.
144
96
  *
145
- * @param filePath - Absolute path to the file
146
- * @returns 16-character hex hash, or null if file doesn't exist
97
+ * @param drift - The drift to categorize
98
+ * @returns The drift with category and fixable metadata
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * const drift: SpecDocDrift = {
103
+ * type: 'param-type-mismatch',
104
+ * target: 'userId',
105
+ * issue: 'Type mismatch'
106
+ * };
107
+ * const categorized = categorizeDrift(drift);
108
+ * console.log(categorized.category); // => 'structural'
109
+ * console.log(categorized.fixable); // => true
110
+ * ```
147
111
  */
148
- declare function hashFile(filePath: string): string | null;
112
+ declare function categorizeDrift(drift: SpecDocDrift): CategorizedDrift;
149
113
  /**
150
- * Hash a string value.
114
+ * Group drifts by category.
151
115
  *
152
- * @param content - String to hash
153
- * @returns 16-character hex hash
116
+ * @param drifts - Array of drift issues to group
117
+ * @returns Drifts organized by category
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * const grouped = groupDriftsByCategory(spec.docs.drift ?? []);
122
+ * console.log(grouped.structural.length); // Number of structural issues
123
+ * console.log(grouped.semantic.length); // Number of semantic issues
124
+ * console.log(grouped.example.length); // Number of example issues
125
+ * ```
154
126
  */
155
- declare function hashString(content: string): string;
127
+ declare function groupDriftsByCategory(drifts: SpecDocDrift[]): Record<DriftCategory, CategorizedDrift[]>;
156
128
  /**
157
- * Hash multiple files and return a map of relative paths to hashes.
129
+ * Get drift summary counts by category.
158
130
  *
159
- * @param filePaths - Array of absolute file paths
160
- * @param cwd - Base directory for relative path calculation
161
- * @returns Map of relative paths to their content hashes
131
+ * @param drifts - Array of drift issues
132
+ * @returns Summary with totals, category breakdown, and fixable count
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * const summary = getDriftSummary(exportEntry.docs?.drift ?? []);
137
+ * console.log(`${summary.total} issues: ${summary.fixable} fixable`);
138
+ * // => "5 issues: 3 fixable"
139
+ * ```
162
140
  */
163
- declare function hashFiles(filePaths: string[], cwd: string): Record<string, string>;
141
+ declare function getDriftSummary(drifts: SpecDocDrift[]): DriftSummary;
164
142
  /**
165
- * Compare two hash maps and return changed files.
143
+ * Format drift summary for CLI output (single line).
166
144
  *
167
- * @param cached - Hash map from cache
168
- * @param current - Current hash map
169
- * @returns Array of file paths that changed, were added, or were removed
145
+ * @param summary - Drift summary to format
146
+ * @returns Human-readable summary string
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * const summary = getDriftSummary(drifts);
151
+ * console.log(formatDriftSummaryLine(summary));
152
+ * // => "5 issues (3 structural, 1 semantic, 1 example)"
153
+ * ```
170
154
  */
171
- declare function diffHashes(cached: Record<string, string>, current: Record<string, string>): string[];
172
- import { OpenPkg as OpenPkg3 } from "@openpkg-ts/spec";
173
- /** Current cache format version */
174
- declare const CACHE_VERSION = "1.0.0";
175
- /** Default cache file path */
176
- declare const SPEC_CACHE_FILE = ".doccov/spec.cache.json";
155
+ declare function formatDriftSummaryLine(summary: DriftSummary): string;
156
+ import { SpecExport } from "@openpkg-ts/spec";
177
157
  /**
178
- * Configuration that affects spec generation output.
158
+ * Build a registry of all export/type names for cross-reference validation.
179
159
  */
180
- interface SpecCacheConfig {
181
- resolveExternalTypes: boolean;
182
- }
160
+ declare function buildExportRegistry(spec: OpenPkgSpec): ExportRegistry;
183
161
  /**
184
- * Cached spec with validation metadata.
162
+ * Compute drift for all exports in a spec.
163
+ *
164
+ * @param spec - The OpenPkg spec to analyze
165
+ * @returns Drift results per */
166
+ declare function computeDrift(spec: OpenPkgSpec): DriftResult;
167
+ /**
168
+ * Compute drift for a single export.
169
+ *
170
+ * @param entry - The to analyze
171
+ * @param registry - Registry of known exports and types for validation
172
+ * @returns Array of drift issues detected
185
173
  */
186
- interface SpecCache {
187
- /** Cache format version for migrations */
188
- cacheVersion: string;
189
- /** When cache was generated (ISO timestamp) */
190
- generatedAt: string;
191
- /** OpenPkg spec version (e.g., "0.3.0") */
192
- specVersion: string;
193
- /** Entry file that was analyzed (relative path) */
194
- entryFile: string;
195
- /** Hash validation data */
196
- hashes: {
197
- /** Hash of tsconfig.json content (null if not found) */
198
- tsconfig: string | null;
199
- /** Hash of package.json content */
200
- packageJson: string;
201
- /** Source file hashes: relative filepath → content hash */
202
- sourceFiles: Record<string, string>;
174
+ declare function computeExportDrift(entry: SpecExport, registry?: ExportRegistry): SpecDocDrift[];
175
+ /**
176
+ * Calculate aggregate coverage score from a spec's exports.
177
+ *
178
+ * This is a lightweight function that calculates coverage without
179
+ * requiring full quality evaluation. It handles three cases:
180
+ * 1. Exports with `docs.coverageScore` - uses that value
181
+ * 2. Exports without score but with description - counts as 100%
182
+ * 3. Exports without score and no description - counts as 0%
183
+ *
184
+ * @param spec - The OpenPkg spec to calculate coverage for
185
+ * @returns The aggregate coverage score (0-100)
186
+ *
187
+ * @example
188
+ * ```ts
189
+ * import { calculateAggregateCoverage } from '@doccov/sdk';
190
+ *
191
+ * const coverage = calculateAggregateCoverage(spec);
192
+ * console.log(`Coverage: ${coverage}%`);
193
+ * ```
194
+ */
195
+ declare function calculateAggregateCoverage(spec: OpenPkgSpec): number;
196
+ /**
197
+ * Ensure a spec has a top-level docs.coverageScore.
198
+ *
199
+ * If the spec already has `docs.coverageScore`, returns the spec unchanged.
200
+ * Otherwise, calculates aggregate coverage from exports and returns a
201
+ * new spec with the coverage score added.
202
+ *
203
+ * This is useful for commands like `diff` that need coverage scores
204
+ * but may receive raw specs that haven't been enriched.
205
+ *
206
+ * @param spec - The OpenPkg spec to ensure coverage for
207
+ * @returns The spec with guaranteed top-level coverage score
208
+ *
209
+ * @example
210
+ * ```ts
211
+ * import { ensureSpecCoverage } from '@doccov/sdk';
212
+ *
213
+ * // Works with raw or enriched specs
214
+ * const specWithCoverage = ensureSpecCoverage(rawSpec);
215
+ * console.log(specWithCoverage.docs?.coverageScore); // e.g., 85
216
+ * ```
217
+ */
218
+ declare function ensureSpecCoverage(spec: OpenPkgSpec): OpenPkgSpec & {
219
+ docs: {
220
+ coverageScore: number;
203
221
  };
204
- /** Analysis configuration that affects output */
205
- config: SpecCacheConfig;
206
- /** The cached OpenPkg spec */
207
- spec: OpenPkg3;
222
+ };
223
+ import { SpecExport as SpecExport2 } from "@openpkg-ts/spec";
224
+ interface ExampleRunResult {
225
+ success: boolean;
226
+ stdout: string;
227
+ stderr: string;
228
+ exitCode: number;
229
+ duration: number;
230
+ }
231
+ interface RunExampleOptions {
232
+ /** Timeout in milliseconds (default: 5000) */
233
+ timeout?: number;
234
+ /** Working directory for execution */
235
+ cwd?: string;
236
+ }
237
+ interface RunExamplesWithPackageOptions extends RunExampleOptions {
238
+ /** Path to the local package to install */
239
+ packagePath: string;
240
+ /** Package manager to use (auto-detected if not specified) */
241
+ packageManager?: "npm" | "pnpm" | "bun";
242
+ /** Timeout for package installation in ms (default: 60000) */
243
+ installTimeout?: number;
244
+ }
245
+ interface RunExamplesWithPackageResult {
246
+ /** Results for each example by index */
247
+ results: Map<number, ExampleRunResult>;
248
+ /** Whether package installation succeeded */
249
+ installSuccess: boolean;
250
+ /** Error message if installation failed */
251
+ installError?: string;
252
+ /** Total duration including install */
253
+ totalDuration: number;
208
254
  }
209
255
  /**
210
- * Result of cache validation.
256
+ * Run an example code snippet in an isolated Node process.
257
+ * Uses Node 22+ --experimental-strip-types for direct TS execution.
211
258
  */
212
- interface CacheValidationResult {
213
- /** Whether the cache is valid */
214
- valid: boolean;
215
- /** Reason for invalidation (if invalid) */
216
- reason?: "cache-version-mismatch" | "entry-file-changed" | "config-changed" | "tsconfig-changed" | "package-json-changed" | "source-files-changed";
217
- /** Files that changed (if reason is source-files-changed) */
218
- changedFiles?: string[];
219
- }
259
+ declare function runExample(code: string, options?: RunExampleOptions): Promise<ExampleRunResult>;
220
260
  /**
221
- * Context needed for cache operations.
261
+ * Run multiple examples and collect results
222
262
  */
223
- interface CacheContext {
224
- /** Entry file being analyzed (absolute path) */
225
- entryFile: string;
226
- /** Source files included in analysis (absolute paths) */
227
- sourceFiles: string[];
228
- /** Path to tsconfig.json (absolute, or null if not found) */
229
- tsconfigPath: string | null;
230
- /** Path to package.json (absolute) */
231
- packageJsonPath: string;
232
- /** Configuration that affects output */
233
- config: SpecCacheConfig;
234
- /** Working directory */
235
- cwd: string;
236
- }
263
+ declare function runExamples(examples: string[], options?: RunExampleOptions): Promise<Map<number, ExampleRunResult>>;
237
264
  /**
238
- * Load cached spec from disk.
239
- *
240
- * @param cwd - Working directory
241
- * @returns Cached spec, or null if not found or invalid JSON
265
+ * Run multiple examples with a pre-installed local package.
266
+ * Creates a single temp directory, installs the package once,
267
+ * runs all examples, then cleans up.
242
268
  */
243
- declare function loadSpecCache(cwd: string): SpecCache | null;
269
+ declare function runExamplesWithPackage(examples: string[], options: RunExamplesWithPackageOptions): Promise<RunExamplesWithPackageResult>;
244
270
  /**
245
- * Save spec to cache.
246
- *
247
- * @param spec - OpenPkg spec to cache
248
- * @param context - Cache context with file paths and config
271
+ * Detect runtime errors in @example blocks.
272
+ * Results are provided externally after running examples via runExamples().
249
273
  */
250
- declare function saveSpecCache(spec: OpenPkg3, context: CacheContext): void;
274
+ declare function detectExampleRuntimeErrors(entry: SpecExport2, runtimeResults: Map<number, ExampleRunResult>): SpecDocDrift[];
251
275
  /**
252
- * Validate if cached spec is still valid.
253
- *
254
- * Checks:
255
- * 1. Cache version matches
256
- * 2. Entry file matches
257
- * 3. Config matches
258
- * 4. tsconfig.json hash matches
259
- * 5. package.json hash matches
260
- * 6. All source file hashes match
261
- *
262
- * @param cache - Cached spec to validate
263
- * @param context - Current cache context
264
- * @returns Validation result
276
+ * Parse assertion comments from example code.
277
+ * Matches: // => expected_value
265
278
  */
266
- declare function validateSpecCache(cache: SpecCache, context: CacheContext): CacheValidationResult;
279
+ declare function parseAssertions(code: string): Array<{
280
+ lineNumber: number;
281
+ expected: string;
282
+ }>;
267
283
  /**
268
- * Clear the spec cache.
269
- *
270
- * @param cwd - Working directory
271
- * @returns True if cache was deleted, false if it didn't exist
284
+ * Check if code contains comments that are not assertion syntax.
285
+ * Used to determine if LLM fallback should be attempted.
272
286
  */
273
- declare function clearSpecCache(cwd: string): boolean;
287
+ declare function hasNonAssertionComments(code: string): boolean;
274
288
  /**
275
- * Get cache file path for a given working directory.
276
- *
277
- * @param cwd - Working directory
278
- * @returns Absolute path to cache file
289
+ * Detect assertion failures by comparing stdout to expected values.
279
290
  */
280
- declare function getSpecCachePath(cwd: string): string;
291
+ declare function detectExampleAssertionFailures(entry: SpecExport2, runtimeResults: Map<number, ExampleRunResult>): SpecDocDrift[];
292
+ import { OpenPkg as OpenPkg3, SpecExport as SpecExport7 } from "@openpkg-ts/spec";
281
293
  /**
282
- * Release stage/visibility tags that can be used for filtering.
283
- * Based on TSDoc release tags.
294
+ * An enriched with computed documentation metadata.
295
+ * Extends SpecExport with the `docs` field for coverage analysis.
284
296
  */
285
- type ReleaseTag = "public" | "beta" | "alpha" | "internal";
286
- interface FilterOptions {
287
- /** Include exports matching these patterns */
288
- include?: string[];
289
- /** Exclude exports matching these patterns */
290
- exclude?: string[];
291
- /** Filter by visibility/release stage (e.g., ['public', 'beta']) */
292
- visibility?: ReleaseTag[];
293
- }
294
- interface Diagnostic2 {
295
- message: string;
296
- severity: "error" | "warning" | "info";
297
- suggestion?: string;
298
- location?: {
299
- file: string;
300
- line?: number;
301
- column?: number;
302
- };
303
- }
304
- interface AnalysisResult {
305
- spec: OpenPkgSpec;
306
- diagnostics: Diagnostic2[];
307
- metadata: AnalysisMetadata;
308
- /** True if result came from cache (no fresh analysis) */
309
- fromCache?: boolean;
310
- /** Cache validation details (if cache was checked) */
311
- cacheStatus?: CacheValidationResult;
312
- }
313
- interface AnalysisMetadata {
314
- baseDir: string;
315
- configPath?: string;
316
- packageJsonPath?: string;
317
- hasNodeModules: boolean;
318
- resolveExternalTypes: boolean;
319
- /** Source files included in analysis (for caching) */
320
- sourceFiles?: string[];
321
- }
322
- interface AnalyzeOptions {
323
- filters?: FilterOptions;
324
- /** Generation metadata input (entry point info, tool version, etc.) */
325
- generationInput?: GenerationInput;
326
- }
327
- declare class DocCov {
328
- private readonly options;
329
- constructor(options?: DocCovOptions);
330
- analyze(code: string, fileName?: string, analyzeOptions?: AnalyzeOptions): Promise<OpenPkgSpec>;
331
- analyzeFile(filePath: string, analyzeOptions?: AnalyzeOptions): Promise<OpenPkgSpec>;
332
- analyzeProject(entryPath: string, analyzeOptions?: AnalyzeOptions): Promise<OpenPkgSpec>;
333
- analyzeWithDiagnostics(code: string, fileName?: string, analyzeOptions?: AnalyzeOptions): Promise<AnalysisResult>;
334
- analyzeFileWithDiagnostics(filePath: string, analyzeOptions?: AnalyzeOptions): Promise<AnalysisResult>;
335
- /**
336
- * Try to load spec from cache.
337
- * Returns null if cache is invalid or doesn't exist.
338
- */
339
- private tryLoadFromCache;
340
- /**
341
- * Get current source files from a fresh TypeScript program.
342
- * Used for cache validation to detect new files.
343
- */
344
- private getCurrentSourceFiles;
345
- /**
346
- * Save analysis result to cache.
347
- */
348
- private saveToCache;
349
- /**
350
- * Find tsconfig.json starting from a directory.
351
- */
352
- private findTsConfig;
353
- /**
354
- * Find package.json starting from a directory.
355
- */
356
- private findPackageJson;
297
+ type EnrichedExport = SpecExport7 & {
298
+ docs?: EnrichedDocsMetadata;
299
+ };
300
+ /**
301
+ * Extended docs metadata.
302
+ */
303
+ type EnrichedDocsMetadata = SpecDocsMetadata;
304
+ /**
305
+ * An enriched OpenPkg spec with computed documentation metadata.
306
+ * Extends OpenPkg with per-and aggregate coverage data.
307
+ */
308
+ type EnrichedOpenPkg = Omit<OpenPkg3, "exports"> & {
309
+ exports: EnrichedExport[];
310
+ docs?: EnrichedDocsMetadata;
311
+ /** Drift summary with category breakdown (if drift exists) */
312
+ driftSummary?: DriftSummary;
313
+ };
314
+ interface EnrichOptions {
357
315
  /**
358
- * Detect Standard Schema exports from compiled modules.
359
- * Only runs when schemaExtraction is 'runtime' or 'hybrid'.
360
- * Returns undefined if detection is disabled, fails, or no schemas found.
316
+ * Per-drift issues to include in enrichment.
317
+ * Map from ID to drift issues.
361
318
  */
362
- private detectSchemas;
363
- private normalizeDiagnostic;
364
- private mapSeverity;
365
- private normalizeMetadata;
366
- private applySpecFilters;
319
+ driftByExport?: Map<string, SpecDocDrift[]>;
367
320
  }
368
- declare function analyze(code: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
369
- declare function analyzeFile(filePath: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
370
- import { OpenPkg as OpenPkg4, SpecExport as SpecExport7 } from "@openpkg-ts/spec";
371
321
  /**
372
- * All possible drift type identifiers.
322
+ * Enrich an OpenPkg spec with documentation coverage metadata.
323
+ *
324
+ * Computes coverage scores and detects drift issues.
325
+ *
326
+ * @param spec - The pure OpenPkg spec to enrich
327
+ * @param options - Optional enrichment configuration
328
+ * @returns An enriched spec with documentation metadata
329
+ *
330
+ * @example
331
+ * ```ts
332
+ * import { DocCov, enrichSpec } from '@doccov/sdk';
333
+ *
334
+ * const doccov = new DocCov();
335
+ * const { spec } = await doccov.analyzeFileWithDiagnostics('src/index.ts');
336
+ *
337
+ * const enriched = enrichSpec(spec);
338
+ * console.log(enriched.docs?.coverageScore); // e.g., 85
339
+ * ```
373
340
  */
374
- type DriftType = "param-mismatch" | "param-type-mismatch" | "return-type-mismatch" | "generic-constraint-mismatch" | "optionality-mismatch" | "deprecated-mismatch" | "visibility-mismatch" | "async-mismatch" | "property-type-drift" | "example-drift" | "example-syntax-error" | "example-runtime-error" | "example-assertion-failed" | "broken-link";
375
- type SpecDocDrift = {
376
- type: DriftType;
377
- target?: string;
378
- issue: string;
379
- suggestion?: string;
380
- };
341
+ declare function enrichSpec(spec: OpenPkg3, options?: EnrichOptions): EnrichedOpenPkg;
342
+ import { OpenPkg as OpenPkg4 } from "@openpkg-ts/spec";
381
343
  /**
382
- * Drift categories group related drift types for progressive disclosure.
344
+ * DocCov report schema version.
383
345
  */
384
- type DriftCategory = "structural" | "semantic" | "example";
346
+ declare const REPORT_VERSION = "1.0.0";
385
347
  /**
386
- * Maps each drift type to its category.
348
+ * Default directory for DocCov outputs.
387
349
  */
388
- declare const DRIFT_CATEGORIES: Record<DriftType, DriftCategory>;
350
+ declare const DEFAULT_REPORT_DIR = ".doccov";
389
351
  /**
390
- * Human-readable category labels.
352
+ * Default path for cached DocCov reports.
391
353
  */
392
- declare const DRIFT_CATEGORY_LABELS: Record<DriftCategory, string>;
354
+ declare const DEFAULT_REPORT_PATH = ".doccov/report.json";
393
355
  /**
394
- * Category descriptions for help text.
356
+ * File extensions for each report format.
395
357
  */
396
- declare const DRIFT_CATEGORY_DESCRIPTIONS: Record<DriftCategory, string>;
397
- type SpecDocsMetadata = {
398
- coverageScore?: number;
399
- missing?: string[];
400
- drift?: SpecDocDrift[];
401
- };
358
+ declare const REPORT_EXTENSIONS: Record<string, string>;
402
359
  /**
403
- * Result of computing drift for a single export.
360
+ * Get the default report path for a given format.
361
+ *
362
+ * @param format - The report format (json, markdown, html, github)
363
+ * @param dir - The output directory (defaults to .doccov)
364
+ * @returns The full path to the report file
365
+ *
366
+ * @example
367
+ * ```ts
368
+ * getReportPath('markdown'); // '.doccov/report.md'
369
+ * getReportPath('html', 'reports'); // 'reports/report.html'
370
+ * ```
404
371
  */
405
- type ExportDriftResult = {
406
- id: string;
407
- drift: SpecDocDrift[];
408
- };
372
+ declare function getReportPath(format: string, dir?: string): string;
409
373
  /**
410
- * Result of computing drift for all exports.
374
+ * Get the report path for a diff comparison.
375
+ *
376
+ * Uses truncated hashes from both specs to create a unique, deterministic filename.
377
+ *
378
+ * @param baseHash - Hash of the base (before) spec
379
+ * @param headHash - Hash of the head (after) spec
380
+ * @param format - The report format (json, markdown, html, github)
381
+ * @param dir - The output directory (defaults to .doccov)
382
+ * @returns The full path to the diff report file
383
+ *
384
+ * @example
385
+ * ```ts
386
+ * getDiffReportPath('abc123def456', 'xyz789uvw012', 'markdown');
387
+ * // '.doccov/diff-abc123de-xyz789uv.md'
388
+ * ```
411
389
  */
412
- type DriftResult = {
413
- exports: Map<string, SpecDocDrift[]>;
414
- };
390
+ declare function getDiffReportPath(baseHash: string, headHash: string, format: string, dir?: string): string;
415
391
  /**
416
- * Information about an for context-aware suggestions.
392
+ * Drift summary with category breakdown.
417
393
  */
418
- interface ExportInfo {
419
- name: string;
420
- kind: string;
421
- isCallable: boolean;
394
+ interface DriftReportSummary {
395
+ /**
396
+ * Total number of drift issues.
397
+ */
398
+ total: number;
399
+ /**
400
+ * Count of issues per category.
401
+ */
402
+ byCategory: Record<DriftCategory, number>;
403
+ /**
404
+ * Number of auto-fixable issues.
405
+ */
406
+ fixable: number;
422
407
  }
423
408
  /**
424
- * Registry of exports and types for cross-reference validation.
409
+ * Drift report with progressive disclosure structure.
410
+ *
411
+ * Provides three levels of detail:
412
+ * 1. Summary - total counts by category
413
+ * 2. By category - grouped drift issues
414
+ * 3. All - flat list for backward compatibility
425
415
  */
426
- interface ExportRegistry {
427
- /** Map of names to their info (for context-aware suggestions) */
428
- exports: Map<string, ExportInfo>;
429
- /** Set of type names (interfaces, type aliases, etc.) */
430
- types: Set<string>;
431
- /** Combined set of all names (for backward compatibility) */
432
- all: Set<string>;
416
+ interface DriftReport {
417
+ /**
418
+ * High-level summary counts.
419
+ */
420
+ summary: DriftReportSummary;
421
+ /**
422
+ * Issues grouped by category.
423
+ */
424
+ byCategory: Record<DriftCategory, CategorizedDrift[]>;
425
+ /**
426
+ * Flat list of all drift issues (backward compatible).
427
+ */
428
+ all: CategorizedDrift[];
433
429
  }
434
430
  /**
435
- * Extended drift with category and fixability metadata.
431
+ * Coverage summary for an entire package or project.
436
432
  */
437
- interface CategorizedDrift extends SpecDocDrift {
438
- category: DriftCategory;
439
- fixable: boolean;
433
+ interface CoverageSummary {
434
+ /**
435
+ * Overall coverage score (0-100).
436
+ */
437
+ score: number;
438
+ /**
439
+ * Total number of exports analyzed.
440
+ */
441
+ totalExports: number;
442
+ /**
443
+ * Number of fully documented exports.
444
+ */
445
+ documentedExports: number;
446
+ /**
447
+ * Breakdown of missing documentation by rule ID.
448
+ */
449
+ missingByRule: Record<string, number>;
450
+ /**
451
+ * Total number of drift issues detected.
452
+ */
453
+ driftCount: number;
454
+ /**
455
+ * Drift summary with category breakdown.
456
+ */
457
+ driftSummary?: DriftReportSummary;
458
+ }
459
+ /**
460
+ * Coverage data for a single export.
461
+ */
462
+ interface ExportCoverageData {
463
+ /**
464
+ * Export name.
465
+ */
466
+ name: string;
467
+ /**
468
+ * Export kind (function, class, etc.).
469
+ */
470
+ kind: string;
471
+ /**
472
+ * Coverage score for this (0-100).
473
+ */
474
+ coverageScore: number;
475
+ /**
476
+ * Missing documentation rule IDs.
477
+ */
478
+ missing?: string[];
479
+ /**
480
+ * Drift issues for this export.
481
+ */
482
+ drift?: SpecDocDrift[];
440
483
  }
441
484
  /**
442
- * Summary of drift issues by category.
485
+ * DocCov report - a persistable coverage analysis result.
486
+ *
487
+ * This is the format saved to `.doccov/report.json` and returned
488
+ * by the `check` command with `--format json`.
443
489
  */
444
- interface DriftSummary {
445
- total: number;
446
- byCategory: Record<DriftCategory, number>;
447
- fixable: number;
490
+ interface DocCovReport {
491
+ /**
492
+ * JSON Schema reference for validation.
493
+ */
494
+ $schema: string;
495
+ /**
496
+ * Report format version.
497
+ */
498
+ version: string;
499
+ /**
500
+ * ISO 8601 timestamp when report was generated.
501
+ */
502
+ generatedAt: string;
503
+ /**
504
+ * Package/project metadata.
505
+ */
506
+ spec: {
507
+ name: string;
508
+ version?: string;
509
+ };
510
+ /**
511
+ * Aggregate coverage summary.
512
+ */
513
+ coverage: CoverageSummary;
514
+ /**
515
+ * Per-coverage data, keyed by ID.
516
+ */
517
+ exports: Record<string, ExportCoverageData>;
448
518
  }
449
519
  /**
450
- * Categorize a single drift issue.
520
+ * Generate a DocCov report from an OpenPkg spec.
451
521
  *
452
- * @param drift - The drift to categorize
453
- * @returns The drift with category and fixable metadata
522
+ * @param spec - The pure OpenPkg spec to analyze
523
+ * @returns A DocCov report with coverage analysis
454
524
  *
455
525
  * @example
456
526
  * ```ts
457
- * const drift: SpecDocDrift = {
458
- * type: 'param-type-mismatch',
459
- * target: 'userId',
460
- * issue: 'Type mismatch'
461
- * };
462
- * const categorized = categorizeDrift(drift);
463
- * console.log(categorized.category); // => 'structural'
464
- * console.log(categorized.fixable); // => true
465
- * ```
466
- */
467
- declare function categorizeDrift(drift: SpecDocDrift): CategorizedDrift;
468
- /**
469
- * Group drifts by category.
527
+ * import { DocCov, generateReport } from '@doccov/sdk';
470
528
  *
471
- * @param drifts - Array of drift issues to group
472
- * @returns Drifts organized by category
529
+ * const doccov = new DocCov();
530
+ * const { spec } = await doccov.analyzeFileWithDiagnostics('src/index.ts');
531
+ * const report = generateReport(spec);
473
532
  *
474
- * @example
475
- * ```ts
476
- * const grouped = groupDriftsByCategory(spec.docs.drift ?? []);
477
- * console.log(grouped.structural.length); // Number of structural issues
478
- * console.log(grouped.semantic.length); // Number of semantic issues
479
- * console.log(grouped.example.length); // Number of example issues
533
+ * console.log(`Coverage: ${report.coverage.score}%`);
480
534
  * ```
481
535
  */
482
- declare function groupDriftsByCategory(drifts: SpecDocDrift[]): Record<DriftCategory, CategorizedDrift[]>;
536
+ declare function generateReport(spec: OpenPkg4): DocCovReport;
483
537
  /**
484
- * Get drift summary counts by category.
538
+ * Generate a DocCov report from an already-enriched spec.
485
539
  *
486
- * @param drifts - Array of drift issues
487
- * @returns Summary with totals, category breakdown, and fixable count
540
+ * Use this when you've already called enrichSpec() and want to avoid
541
+ * recomputing coverage data.
488
542
  *
489
- * @example
490
- * ```ts
491
- * const summary = getDriftSummary(exportEntry.docs?.drift ?? []);
492
- * console.log(`${summary.total} issues: ${summary.fixable} fixable`);
493
- * // => "5 issues: 3 fixable"
494
- * ```
543
+ * @param enriched - The enriched OpenPkg spec
544
+ * @returns A DocCov report with coverage analysis
495
545
  */
496
- declare function getDriftSummary(drifts: SpecDocDrift[]): DriftSummary;
546
+ declare function generateReportFromEnriched(enriched: EnrichedOpenPkg): DocCovReport;
497
547
  /**
498
- * Format drift summary for CLI output (single line).
499
- *
500
- * @param summary - Drift summary to format
501
- * @returns Human-readable summary string
548
+ * Load a cached DocCov report from disk.
502
549
  *
503
- * @example
504
- * ```ts
505
- * const summary = getDriftSummary(drifts);
506
- * console.log(formatDriftSummaryLine(summary));
507
- * // => "5 issues (3 structural, 1 semantic, 1 example)"
508
- * ```
509
- */
510
- declare function formatDriftSummaryLine(summary: DriftSummary): string;
511
- import { SpecExport } from "@openpkg-ts/spec";
512
- /**
513
- * Build a registry of all export/type names for cross-reference validation.
550
+ * @param reportPath - Path to the report file (defaults to .doccov/report.json)
551
+ * @returns The cached report, or null if not found
514
552
  */
515
- declare function buildExportRegistry(spec: OpenPkgSpec): ExportRegistry;
516
- /**
517
- * Compute drift for all exports in a spec.
518
- *
519
- * @param spec - The OpenPkg spec to analyze
520
- * @returns Drift results per */
521
- declare function computeDrift(spec: OpenPkgSpec): DriftResult;
553
+ declare function loadCachedReport(reportPath?: string): DocCovReport | null;
522
554
  /**
523
- * Compute drift for a single export.
555
+ * Save a DocCov report to disk.
524
556
  *
525
- * @param entry - The to analyze
526
- * @param registry - Registry of known exports and types for validation
527
- * @returns Array of drift issues detected
557
+ * @param report - The report to save
558
+ * @param reportPath - Path to save the report (defaults to .doccov/report.json)
528
559
  */
529
- declare function computeExportDrift(entry: SpecExport, registry?: ExportRegistry): SpecDocDrift[];
560
+ declare function saveReport(report: DocCovReport, reportPath?: string): void;
530
561
  /**
531
- * Calculate aggregate coverage score from a spec's exports.
562
+ * Generate a git-trackable API surface markdown file from an OpenPkg spec.
532
563
  *
533
- * This is a lightweight function that calculates coverage without
534
- * requiring full quality evaluation. It handles three cases:
535
- * 1. Exports with `docs.coverageScore` - uses that value
536
- * 2. Exports without score but with description - counts as 100%
537
- * 3. Exports without score and no description - counts as 0%
564
+ * This produces a deterministic, sorted output suitable for version control.
565
+ * Changes to the API will show up as diffs in this file.
538
566
  *
539
- * @param spec - The OpenPkg spec to calculate coverage for
540
- * @returns The aggregate coverage score (0-100)
567
+ * @param spec - The OpenPkg spec to render
568
+ * @returns Markdown string representing the API surface
541
569
  *
542
570
  * @example
543
571
  * ```ts
544
- * import { calculateAggregateCoverage } from '@doccov/sdk';
545
- *
546
- * const coverage = calculateAggregateCoverage(spec);
547
- * console.log(`Coverage: ${coverage}%`);
548
- * ```
549
- */
550
- declare function calculateAggregateCoverage(spec: OpenPkgSpec): number;
551
- /**
552
- * Ensure a spec has a top-level docs.coverageScore.
553
- *
554
- * If the spec already has `docs.coverageScore`, returns the spec unchanged.
555
- * Otherwise, calculates aggregate coverage from exports and returns a
556
- * new spec with the coverage score added.
557
- *
558
- * This is useful for commands like `diff` that need coverage scores
559
- * but may receive raw specs that haven't been enriched.
560
- *
561
- * @param spec - The OpenPkg spec to ensure coverage for
562
- * @returns The spec with guaranteed top-level coverage score
572
+ * import { DocCov, renderApiSurface } from '@doccov/sdk';
563
573
  *
564
- * @example
565
- * ```ts
566
- * import { ensureSpecCoverage } from '@doccov/sdk';
574
+ * const doccov = new DocCov();
575
+ * const { spec } = await doccov.analyzeFileWithDiagnostics('src/index.ts');
576
+ * const apiSurface = renderApiSurface(spec);
567
577
  *
568
- * // Works with raw or enriched specs
569
- * const specWithCoverage = ensureSpecCoverage(rawSpec);
570
- * console.log(specWithCoverage.docs?.coverageScore); // e.g., 85
578
+ * fs.writeFileSync('api-surface.md', apiSurface);
571
579
  * ```
572
580
  */
573
- declare function ensureSpecCoverage(spec: OpenPkgSpec): OpenPkgSpec & {
574
- docs: {
575
- coverageScore: number;
576
- };
577
- };
578
- import { SpecExport as SpecExport2 } from "@openpkg-ts/spec";
579
- interface ExampleRunResult {
580
- success: boolean;
581
- stdout: string;
582
- stderr: string;
583
- exitCode: number;
584
- duration: number;
585
- }
586
- interface RunExampleOptions {
587
- /** Timeout in milliseconds (default: 5000) */
588
- timeout?: number;
589
- /** Working directory for execution */
590
- cwd?: string;
591
- }
592
- interface RunExamplesWithPackageOptions extends RunExampleOptions {
593
- /** Path to the local package to install */
594
- packagePath: string;
595
- /** Package manager to use (auto-detected if not specified) */
596
- packageManager?: "npm" | "pnpm" | "bun";
597
- /** Timeout for package installation in ms (default: 60000) */
598
- installTimeout?: number;
599
- }
600
- interface RunExamplesWithPackageResult {
601
- /** Results for each example by index */
602
- results: Map<number, ExampleRunResult>;
603
- /** Whether package installation succeeded */
604
- installSuccess: boolean;
605
- /** Error message if installation failed */
606
- installError?: string;
607
- /** Total duration including install */
608
- totalDuration: number;
609
- }
610
- /**
611
- * Run an example code snippet in an isolated Node process.
612
- * Uses Node 22+ --experimental-strip-types for direct TS execution.
613
- */
614
- declare function runExample(code: string, options?: RunExampleOptions): Promise<ExampleRunResult>;
615
- /**
616
- * Run multiple examples and collect results
617
- */
618
- declare function runExamples(examples: string[], options?: RunExampleOptions): Promise<Map<number, ExampleRunResult>>;
619
- /**
620
- * Run multiple examples with a pre-installed local package.
621
- * Creates a single temp directory, installs the package once,
622
- * runs all examples, then cleans up.
623
- */
624
- declare function runExamplesWithPackage(examples: string[], options: RunExamplesWithPackageOptions): Promise<RunExamplesWithPackageResult>;
625
- /**
626
- * Detect runtime errors in @example blocks.
627
- * Results are provided externally after running examples via runExamples().
628
- */
629
- declare function detectExampleRuntimeErrors(entry: SpecExport2, runtimeResults: Map<number, ExampleRunResult>): SpecDocDrift[];
581
+ declare function renderApiSurface(spec: OpenPkg4): string;
582
+ import { EntryPointDetectionMethod } from "@openpkg-ts/spec";
630
583
  /**
631
- * Parse assertion comments from example code.
632
- * Matches: // => expected_value
584
+ * Configuration types for DocCov.
585
+ * These types are shared between CLI and API.
633
586
  */
634
- declare function parseAssertions(code: string): Array<{
635
- lineNumber: number;
636
- expected: string;
637
- }>;
638
587
  /**
639
- * Check if code contains comments that are not assertion syntax.
640
- * Used to determine if LLM fallback should be attempted.
588
+ * Documentation configuration options.
641
589
  */
642
- declare function hasNonAssertionComments(code: string): boolean;
590
+ interface DocsConfig {
591
+ /** Glob patterns for markdown docs to include */
592
+ include?: string[];
593
+ /** Glob patterns for markdown docs to exclude */
594
+ exclude?: string[];
595
+ }
643
596
  /**
644
- * Detect assertion failures by comparing stdout to expected values.
597
+ * Example validation modes.
645
598
  */
646
- declare function detectExampleAssertionFailures(entry: SpecExport2, runtimeResults: Map<number, ExampleRunResult>): SpecDocDrift[];
599
+ type ExampleValidationMode = "presence" | "typecheck" | "run";
647
600
  /**
648
- * An enriched with computed documentation metadata.
649
- * Extends SpecExport with the `docs` field for coverage analysis.
601
+ * Schema extraction modes for validation libraries (Zod, Valibot, TypeBox, ArkType).
602
+ *
603
+ * - 'static': TypeScript Compiler API only (no runtime, always safe)
604
+ * - 'runtime': Standard Schema runtime extraction (requires built package)
605
+ * - 'hybrid': Try runtime first, fall back to static
650
606
  */
651
- type EnrichedExport = SpecExport7 & {
652
- docs?: EnrichedDocsMetadata;
653
- };
607
+ type SchemaExtractionMode = "static" | "runtime" | "hybrid";
654
608
  /**
655
- * Extended docs metadata.
609
+ * Check command configuration options.
656
610
  */
657
- type EnrichedDocsMetadata = SpecDocsMetadata;
611
+ interface CheckConfig {
612
+ /**
613
+ * Example validation modes to run.
614
+ * Can be a single mode, array of modes, or comma-separated string.
615
+ * - 'presence': Check that @example blocks exist on exports
616
+ * - 'typecheck': Compile examples with TypeScript
617
+ * - 'run': Execute examples and validate assertions
618
+ */
619
+ examples?: ExampleValidationMode | ExampleValidationMode[] | string;
620
+ /** Minimum coverage percentage required (0-100) */
621
+ minCoverage?: number;
622
+ /** Maximum drift percentage allowed (0-100) */
623
+ maxDrift?: number;
624
+ }
658
625
  /**
659
- * An enriched OpenPkg spec with computed documentation metadata.
660
- * Extends OpenPkg with per-and aggregate coverage data.
626
+ * Normalized DocCov configuration.
627
+ * This is the parsed/normalized form used by commands.
661
628
  */
662
- type EnrichedOpenPkg = Omit<OpenPkg4, "exports"> & {
663
- exports: EnrichedExport[];
664
- docs?: EnrichedDocsMetadata;
665
- /** Drift summary with category breakdown (if drift exists) */
666
- driftSummary?: DriftSummary;
667
- };
668
- interface EnrichOptions {
629
+ interface DocCovConfig {
630
+ /** Export include patterns */
631
+ include?: string[];
632
+ /** Export exclude patterns */
633
+ exclude?: string[];
634
+ /** Plugins (future) */
635
+ plugins?: unknown[];
636
+ /** Documentation configuration */
637
+ docs?: DocsConfig;
638
+ /** Check command configuration */
639
+ check?: CheckConfig;
669
640
  /**
670
- * Per-drift issues to include in enrichment.
671
- * Map from ID to drift issues.
641
+ * Schema extraction mode for validation libraries.
642
+ *
643
+ * - 'static' (default): Safe, uses TypeScript Compiler API
644
+ * - 'runtime': Uses Standard Schema (requires built package)
645
+ * - 'hybrid': Tries runtime first, falls back to static
646
+ *
647
+ * Runtime extraction provides richer JSON Schema output (formats, patterns)
648
+ * but requires the package to be built first.
672
649
  */
673
- driftByExport?: Map<string, SpecDocDrift[]>;
650
+ schemaExtraction?: SchemaExtractionMode;
674
651
  }
675
652
  /**
676
- * Enrich an OpenPkg spec with documentation coverage metadata.
677
- *
678
- * Computes coverage scores and detects drift issues.
653
+ * Define a DocCov configuration.
654
+ * Helper function for type-safe configuration in doccov.config.ts.
679
655
  *
680
- * @param spec - The pure OpenPkg spec to enrich
681
- * @param options - Optional enrichment configuration
682
- * @returns An enriched spec with documentation metadata
656
+ * @param config - Configuration object
657
+ * @returns The configuration object (for type inference)
683
658
  *
684
659
  * @example
685
- * ```ts
686
- * import { DocCov, enrichSpec } from '@doccov/sdk';
687
- *
688
- * const doccov = new DocCov();
689
- * const { spec } = await doccov.analyzeFileWithDiagnostics('src/index.ts');
660
+ * ```typescript
661
+ * // doccov.config.ts
662
+ * import { defineConfig } from '@doccov/sdk';
690
663
  *
691
- * const enriched = enrichSpec(spec);
692
- * console.log(enriched.docs?.coverageScore); // e.g., 85
664
+ * defineConfig({
665
+ * include: ['MyClass', 'myFunction'],
666
+ * exclude: ['internal*'],
667
+ * check: {
668
+ * minCoverage: 80,
669
+ * },
670
+ * });
693
671
  * ```
694
672
  */
695
- declare function enrichSpec(spec: OpenPkg4, options?: EnrichOptions): EnrichedOpenPkg;
696
- import { DocCovSpec } from "@doccov/spec";
697
- interface BuildDocCovOptions {
698
- openpkgPath: string;
699
- openpkg: OpenPkgSpec;
700
- packagePath?: string;
673
+ declare function defineConfig(config: DocCovConfig): DocCovConfig;
674
+ interface DocCovOptions {
675
+ includePrivate?: boolean;
676
+ followImports?: boolean;
677
+ maxDepth?: number;
678
+ resolveExternalTypes?: boolean;
679
+ /** Enable spec caching (default: true) */
680
+ useCache?: boolean;
681
+ /** Working directory for cache operations (default: process.cwd()) */
682
+ cwd?: string;
683
+ /**
684
+ * Schema extraction mode for validation libraries (Zod, Valibot, etc.)
685
+ *
686
+ * - 'static' (default): TypeScript Compiler API only (no runtime)
687
+ * - 'runtime': Standard Schema runtime extraction (requires built package)
688
+ * - 'hybrid': Try runtime first, fall back to static
689
+ */
690
+ schemaExtraction?: SchemaExtractionMode;
701
691
  }
702
692
  /**
703
- * Build a DocCov spec from an OpenPkg spec.
704
- *
705
- * @param options - Build options
706
- * @returns DocCov specification with coverage analysis
707
- */
708
- declare function buildDocCovSpec(options: BuildDocCovOptions): DocCovSpec;
709
- import { OpenPkg as OpenPkg5 } from "@openpkg-ts/spec";
710
- /**
711
- * DocCov report schema version.
693
+ * Pre-detected Standard Schema for a variable export.
712
694
  */
713
- declare const REPORT_VERSION = "1.0.0";
695
+ interface DetectedSchemaEntry {
696
+ schema: Record<string, unknown>;
697
+ vendor: string;
698
+ }
714
699
  /**
715
- * Default directory for DocCov outputs.
700
+ * Input for generation metadata that comes from the caller (CLI, API, etc.)
716
701
  */
717
- declare const DEFAULT_REPORT_DIR = ".doccov";
702
+ interface GenerationInput {
703
+ /** Entry point file path (relative to package root) */
704
+ entryPoint: string;
705
+ /** How the entry point was detected */
706
+ entryPointSource: EntryPointDetectionMethod;
707
+ /** Whether this is a declaration-only analysis (.d.ts file) */
708
+ isDeclarationOnly?: boolean;
709
+ /** Generator tool name */
710
+ generatorName: string;
711
+ /** Generator tool version */
712
+ generatorVersion: string;
713
+ /** Detected package manager */
714
+ packageManager?: string;
715
+ /** Whether this is a monorepo */
716
+ isMonorepo?: boolean;
717
+ /** Target package name (for monorepos) */
718
+ targetPackage?: string;
719
+ }
718
720
  /**
719
- * Default path for cached DocCov reports.
721
+ * Compute a hash of file contents.
722
+ * Uses truncated SHA-256 for balance of speed and collision resistance.
723
+ *
724
+ * @param filePath - Absolute path to the file
725
+ * @returns 16-character hex hash, or null if file doesn't exist
720
726
  */
721
- declare const DEFAULT_REPORT_PATH = ".doccov/report.json";
727
+ declare function hashFile(filePath: string): string | null;
722
728
  /**
723
- * File extensions for each report format.
729
+ * Hash a string value.
730
+ *
731
+ * @param content - String to hash
732
+ * @returns 16-character hex hash
724
733
  */
725
- declare const REPORT_EXTENSIONS: Record<string, string>;
734
+ declare function hashString(content: string): string;
726
735
  /**
727
- * Get the default report path for a given format.
728
- *
729
- * @param format - The report format (json, markdown, html, github)
730
- * @param dir - The output directory (defaults to .doccov)
731
- * @returns The full path to the report file
736
+ * Hash multiple files and return a map of relative paths to hashes.
732
737
  *
733
- * @example
734
- * ```ts
735
- * getReportPath('markdown'); // '.doccov/report.md'
736
- * getReportPath('html', 'reports'); // 'reports/report.html'
737
- * ```
738
+ * @param filePaths - Array of absolute file paths
739
+ * @param cwd - Base directory for relative path calculation
740
+ * @returns Map of relative paths to their content hashes
738
741
  */
739
- declare function getReportPath(format: string, dir?: string): string;
742
+ declare function hashFiles(filePaths: string[], cwd: string): Record<string, string>;
740
743
  /**
741
- * Get the report path for a diff comparison.
742
- *
743
- * Uses truncated hashes from both specs to create a unique, deterministic filename.
744
- *
745
- * @param baseHash - Hash of the base (before) spec
746
- * @param headHash - Hash of the head (after) spec
747
- * @param format - The report format (json, markdown, html, github)
748
- * @param dir - The output directory (defaults to .doccov)
749
- * @returns The full path to the diff report file
744
+ * Compare two hash maps and return changed files.
750
745
  *
751
- * @example
752
- * ```ts
753
- * getDiffReportPath('abc123def456', 'xyz789uvw012', 'markdown');
754
- * // '.doccov/diff-abc123de-xyz789uv.md'
755
- * ```
746
+ * @param cached - Hash map from cache
747
+ * @param current - Current hash map
748
+ * @returns Array of file paths that changed, were added, or were removed
756
749
  */
757
- declare function getDiffReportPath(baseHash: string, headHash: string, format: string, dir?: string): string;
750
+ declare function diffHashes(cached: Record<string, string>, current: Record<string, string>): string[];
751
+ import { OpenPkg as OpenPkg5 } from "@openpkg-ts/spec";
752
+ /** Current cache format version */
753
+ declare const CACHE_VERSION = "1.0.0";
754
+ /** Default cache file path */
755
+ declare const SPEC_CACHE_FILE = ".doccov/spec.cache.json";
758
756
  /**
759
- * Drift summary with category breakdown.
757
+ * Configuration that affects spec generation output.
760
758
  */
761
- interface DriftReportSummary {
762
- /**
763
- * Total number of drift issues.
764
- */
765
- total: number;
766
- /**
767
- * Count of issues per category.
768
- */
769
- byCategory: Record<DriftCategory, number>;
770
- /**
771
- * Number of auto-fixable issues.
772
- */
773
- fixable: number;
759
+ interface SpecCacheConfig {
760
+ resolveExternalTypes: boolean;
774
761
  }
775
762
  /**
776
- * Drift report with progressive disclosure structure.
777
- *
778
- * Provides three levels of detail:
779
- * 1. Summary - total counts by category
780
- * 2. By category - grouped drift issues
781
- * 3. All - flat list for backward compatibility
763
+ * Cached spec with validation metadata.
782
764
  */
783
- interface DriftReport {
784
- /**
785
- * High-level summary counts.
786
- */
787
- summary: DriftReportSummary;
788
- /**
789
- * Issues grouped by category.
790
- */
791
- byCategory: Record<DriftCategory, CategorizedDrift[]>;
792
- /**
793
- * Flat list of all drift issues (backward compatible).
794
- */
795
- all: CategorizedDrift[];
765
+ interface SpecCache {
766
+ /** Cache format version for migrations */
767
+ cacheVersion: string;
768
+ /** When cache was generated (ISO timestamp) */
769
+ generatedAt: string;
770
+ /** OpenPkg spec version (e.g., "0.3.0") */
771
+ specVersion: string;
772
+ /** Entry file that was analyzed (relative path) */
773
+ entryFile: string;
774
+ /** Hash validation data */
775
+ hashes: {
776
+ /** Hash of tsconfig.json content (null if not found) */
777
+ tsconfig: string | null;
778
+ /** Hash of package.json content */
779
+ packageJson: string;
780
+ /** Source file hashes: relative filepath → content hash */
781
+ sourceFiles: Record<string, string>;
782
+ };
783
+ /** Analysis configuration that affects output */
784
+ config: SpecCacheConfig;
785
+ /** The cached OpenPkg spec */
786
+ spec: OpenPkg5;
796
787
  }
797
788
  /**
798
- * Coverage summary for an entire package or project.
789
+ * Result of cache validation.
799
790
  */
800
- interface CoverageSummary {
801
- /**
802
- * Overall coverage score (0-100).
803
- */
804
- score: number;
805
- /**
806
- * Total number of exports analyzed.
807
- */
808
- totalExports: number;
809
- /**
810
- * Number of fully documented exports.
811
- */
812
- documentedExports: number;
813
- /**
814
- * Breakdown of missing documentation by rule ID.
815
- */
816
- missingByRule: Record<string, number>;
817
- /**
818
- * Total number of drift issues detected.
819
- */
820
- driftCount: number;
821
- /**
822
- * Drift summary with category breakdown.
823
- */
824
- driftSummary?: DriftReportSummary;
791
+ interface CacheValidationResult {
792
+ /** Whether the cache is valid */
793
+ valid: boolean;
794
+ /** Reason for invalidation (if invalid) */
795
+ reason?: "cache-version-mismatch" | "entry-file-changed" | "config-changed" | "tsconfig-changed" | "package-json-changed" | "source-files-changed";
796
+ /** Files that changed (if reason is source-files-changed) */
797
+ changedFiles?: string[];
825
798
  }
826
799
  /**
827
- * Coverage data for a single export.
800
+ * Context needed for cache operations.
828
801
  */
829
- interface ExportCoverageData {
830
- /**
831
- * Export name.
832
- */
833
- name: string;
834
- /**
835
- * Export kind (function, class, etc.).
836
- */
837
- kind: string;
838
- /**
839
- * Coverage score for this (0-100).
840
- */
841
- coverageScore: number;
842
- /**
843
- * Missing documentation rule IDs.
844
- */
845
- missing?: string[];
846
- /**
847
- * Drift issues for this export.
848
- */
849
- drift?: SpecDocDrift[];
802
+ interface CacheContext {
803
+ /** Entry file being analyzed (absolute path) */
804
+ entryFile: string;
805
+ /** Source files included in analysis (absolute paths) */
806
+ sourceFiles: string[];
807
+ /** Path to tsconfig.json (absolute, or null if not found) */
808
+ tsconfigPath: string | null;
809
+ /** Path to package.json (absolute) */
810
+ packageJsonPath: string;
811
+ /** Configuration that affects output */
812
+ config: SpecCacheConfig;
813
+ /** Working directory */
814
+ cwd: string;
850
815
  }
851
816
  /**
852
- * DocCov report - a persistable coverage analysis result.
817
+ * Load cached spec from disk.
853
818
  *
854
- * This is the format saved to `.doccov/report.json` and returned
855
- * by the `check` command with `--format json`.
819
+ * @param cwd - Working directory
820
+ * @returns Cached spec, or null if not found or invalid JSON
856
821
  */
857
- interface DocCovReport {
858
- /**
859
- * JSON Schema reference for validation.
860
- */
861
- $schema: string;
862
- /**
863
- * Report format version.
864
- */
865
- version: string;
866
- /**
867
- * ISO 8601 timestamp when report was generated.
868
- */
869
- generatedAt: string;
870
- /**
871
- * Package/project metadata.
872
- */
873
- spec: {
874
- name: string;
875
- version?: string;
876
- };
877
- /**
878
- * Aggregate coverage summary.
879
- */
880
- coverage: CoverageSummary;
881
- /**
882
- * Per-coverage data, keyed by ID.
883
- */
884
- exports: Record<string, ExportCoverageData>;
885
- }
822
+ declare function loadSpecCache(cwd: string): SpecCache | null;
886
823
  /**
887
- * Generate a DocCov report from an OpenPkg spec.
888
- *
889
- * @param spec - The pure OpenPkg spec to analyze
890
- * @returns A DocCov report with coverage analysis
891
- *
892
- * @example
893
- * ```ts
894
- * import { DocCov, generateReport } from '@doccov/sdk';
895
- *
896
- * const doccov = new DocCov();
897
- * const { spec } = await doccov.analyzeFileWithDiagnostics('src/index.ts');
898
- * const report = generateReport(spec);
824
+ * Save spec to cache.
899
825
  *
900
- * console.log(`Coverage: ${report.coverage.score}%`);
901
- * ```
826
+ * @param spec - OpenPkg spec to cache
827
+ * @param context - Cache context with file paths and config
902
828
  */
903
- declare function generateReport(spec: OpenPkg5): DocCovReport;
829
+ declare function saveSpecCache(spec: OpenPkg5, context: CacheContext): void;
904
830
  /**
905
- * Generate a DocCov report from an already-enriched spec.
831
+ * Validate if cached spec is still valid.
906
832
  *
907
- * Use this when you've already called enrichSpec() and want to avoid
908
- * recomputing coverage data.
833
+ * Checks:
834
+ * 1. Cache version matches
835
+ * 2. Entry file matches
836
+ * 3. Config matches
837
+ * 4. tsconfig.json hash matches
838
+ * 5. package.json hash matches
839
+ * 6. All source file hashes match
909
840
  *
910
- * @param enriched - The enriched OpenPkg spec
911
- * @returns A DocCov report with coverage analysis
841
+ * @param cache - Cached spec to validate
842
+ * @param context - Current cache context
843
+ * @returns Validation result
912
844
  */
913
- declare function generateReportFromEnriched(enriched: EnrichedOpenPkg): DocCovReport;
845
+ declare function validateSpecCache(cache: SpecCache, context: CacheContext): CacheValidationResult;
914
846
  /**
915
- * Load a cached DocCov report from disk.
847
+ * Clear the spec cache.
916
848
  *
917
- * @param reportPath - Path to the report file (defaults to .doccov/report.json)
918
- * @returns The cached report, or null if not found
849
+ * @param cwd - Working directory
850
+ * @returns True if cache was deleted, false if it didn't exist
919
851
  */
920
- declare function loadCachedReport(reportPath?: string): DocCovReport | null;
852
+ declare function clearSpecCache(cwd: string): boolean;
921
853
  /**
922
- * Save a DocCov report to disk.
854
+ * Get cache file path for a given working directory.
923
855
  *
924
- * @param report - The report to save
925
- * @param reportPath - Path to save the report (defaults to .doccov/report.json)
856
+ * @param cwd - Working directory
857
+ * @returns Absolute path to cache file
926
858
  */
927
- declare function saveReport(report: DocCovReport, reportPath?: string): void;
859
+ declare function getSpecCachePath(cwd: string): string;
928
860
  /**
929
- * Generate a git-trackable API surface markdown file from an OpenPkg spec.
930
- *
931
- * This produces a deterministic, sorted output suitable for version control.
932
- * Changes to the API will show up as diffs in this file.
933
- *
934
- * @param spec - The OpenPkg spec to render
935
- * @returns Markdown string representing the API surface
936
- *
937
- * @example
938
- * ```ts
939
- * import { DocCov, renderApiSurface } from '@doccov/sdk';
940
- *
941
- * const doccov = new DocCov();
942
- * const { spec } = await doccov.analyzeFileWithDiagnostics('src/index.ts');
943
- * const apiSurface = renderApiSurface(spec);
944
- *
945
- * fs.writeFileSync('api-surface.md', apiSurface);
946
- * ```
861
+ * Release stage/visibility tags that can be used for filtering.
862
+ * Based on TSDoc release tags.
947
863
  */
948
- declare function renderApiSurface(spec: OpenPkg5): string;
864
+ type ReleaseTag = "public" | "beta" | "alpha" | "internal";
865
+ interface FilterOptions {
866
+ /** Include exports matching these patterns */
867
+ include?: string[];
868
+ /** Exclude exports matching these patterns */
869
+ exclude?: string[];
870
+ /** Filter by visibility/release stage (e.g., ['public', 'beta']) */
871
+ visibility?: ReleaseTag[];
872
+ }
873
+ interface Diagnostic2 {
874
+ message: string;
875
+ severity: "error" | "warning" | "info";
876
+ suggestion?: string;
877
+ location?: {
878
+ file: string;
879
+ line?: number;
880
+ column?: number;
881
+ };
882
+ }
883
+ interface AnalysisResult {
884
+ spec: OpenPkgSpec;
885
+ diagnostics: Diagnostic2[];
886
+ metadata: AnalysisMetadata;
887
+ /** True if result came from cache (no fresh analysis) */
888
+ fromCache?: boolean;
889
+ /** Cache validation details (if cache was checked) */
890
+ cacheStatus?: CacheValidationResult;
891
+ }
892
+ interface AnalysisMetadata {
893
+ baseDir: string;
894
+ configPath?: string;
895
+ packageJsonPath?: string;
896
+ hasNodeModules: boolean;
897
+ resolveExternalTypes: boolean;
898
+ /** Source files included in analysis (for caching) */
899
+ sourceFiles?: string[];
900
+ }
901
+ interface AnalyzeOptions {
902
+ filters?: FilterOptions;
903
+ /** Generation metadata input (entry point info, tool version, etc.) */
904
+ generationInput?: GenerationInput;
905
+ }
906
+ declare class DocCov {
907
+ private readonly options;
908
+ constructor(options?: DocCovOptions);
909
+ analyze(code: string, fileName?: string, analyzeOptions?: AnalyzeOptions): Promise<OpenPkgSpec>;
910
+ analyzeFile(filePath: string, analyzeOptions?: AnalyzeOptions): Promise<OpenPkgSpec>;
911
+ analyzeProject(entryPath: string, analyzeOptions?: AnalyzeOptions): Promise<OpenPkgSpec>;
912
+ analyzeWithDiagnostics(code: string, fileName?: string, analyzeOptions?: AnalyzeOptions): Promise<AnalysisResult>;
913
+ analyzeFileWithDiagnostics(filePath: string, analyzeOptions?: AnalyzeOptions): Promise<AnalysisResult>;
914
+ /**
915
+ * Try to load spec from cache.
916
+ * Returns null if cache is invalid or doesn't exist.
917
+ */
918
+ private tryLoadFromCache;
919
+ /**
920
+ * Get current source files from a fresh TypeScript program.
921
+ * Used for cache validation to detect new files.
922
+ */
923
+ private getCurrentSourceFiles;
924
+ /**
925
+ * Save analysis result to cache.
926
+ */
927
+ private saveToCache;
928
+ /**
929
+ * Find tsconfig.json starting from a directory.
930
+ */
931
+ private findTsConfig;
932
+ /**
933
+ * Find package.json starting from a directory.
934
+ */
935
+ private findPackageJson;
936
+ /**
937
+ * Detect Standard Schema exports from compiled modules.
938
+ * Only runs when schemaExtraction is 'runtime' or 'hybrid'.
939
+ * Returns undefined if detection is disabled, fails, or no schemas found.
940
+ */
941
+ private detectSchemas;
942
+ private normalizeDiagnostic;
943
+ private mapSeverity;
944
+ private normalizeMetadata;
945
+ private applySpecFilters;
946
+ }
947
+ declare function analyze(code: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
948
+ declare function analyzeFile(filePath: string, options?: AnalyzeOptions): Promise<OpenPkgSpec>;
949
949
  /**
950
950
  * Project detection types for I/O-agnostic project analysis.
951
951
  * Used by both CLI (NodeFileSystem) and API (SandboxFileSystem).
@@ -1043,59 +1043,6 @@ interface AnalyzeProjectOptions {
1043
1043
  targetPackage?: string;
1044
1044
  }
1045
1045
  /**
1046
- * Options for resolving a target package/entry point.
1047
- */
1048
- interface ResolveTargetOptions {
1049
- /** Working directory (usually process.cwd()) */
1050
- cwd: string;
1051
- /** Target package name for monorepos */
1052
- package?: string;
1053
- /** Explicit entry point path (relative to cwd or package dir) */
1054
- entry?: string;
1055
- }
1056
- /**
1057
- * Result of resolving a target package/entry point.
1058
- */
1059
- interface ResolvedTarget {
1060
- /** Resolved directory containing the package */
1061
- targetDir: string;
1062
- /** Resolved entry point file path (absolute) */
1063
- entryFile: string;
1064
- /** Package info if this is a monorepo package */
1065
- packageInfo?: WorkspacePackage;
1066
- /** Entry point detection info */
1067
- entryPointInfo: EntryPointInfo;
1068
- }
1069
- /**
1070
- * Resolve a target package and entry point.
1071
- *
1072
- * This consolidates the repeated pattern from CLI commands:
1073
- * 1. If --package specified, detect monorepo and find the package
1074
- * 2. If no entry specified, auto-detect entry point
1075
- * 3. If entry is a directory, detect entry point within it
1076
- *
1077
- * @param fs - FileSystem implementation (NodeFileSystem or SandboxFileSystem)
1078
- * @param options - Resolution options
1079
- * @returns Resolved target info
1080
- * @throws Error if monorepo package not found, or entry point detection fails
1081
- *
1082
- * @example
1083
- * ```typescript
1084
- * import { NodeFileSystem, resolveTarget } from '@doccov/sdk';
1085
- *
1086
- * // Simple usage
1087
- * const fs = new NodeFileSystem(process.cwd());
1088
- * const { targetDir, entryFile } = await resolveTarget(fs, { cwd: process.cwd() });
1089
- *
1090
- * // With monorepo package
1091
- * const { targetDir, entryFile, packageInfo } = await resolveTarget(fs, {
1092
- * cwd: process.cwd(),
1093
- * package: '@myorg/core',
1094
- * });
1095
- * ```
1096
- */
1097
- declare function resolveTarget(fs: FileSystem, options: ResolveTargetOptions): Promise<ResolvedTarget>;
1098
- /**
1099
1046
  * Detect build configuration and exotic project indicators.
1100
1047
  *
1101
1048
  * @param fs - FileSystem implementation
@@ -1257,6 +1204,59 @@ declare function readPackageJson(fs: FileSystem, dir: string): Promise<PackageJs
1257
1204
  */
1258
1205
  declare function analyzeProject2(fs: FileSystem, options?: AnalyzeProjectOptions): Promise<ProjectInfo>;
1259
1206
  /**
1207
+ * Options for resolving a target package/entry point.
1208
+ */
1209
+ interface ResolveTargetOptions {
1210
+ /** Working directory (usually process.cwd()) */
1211
+ cwd: string;
1212
+ /** Target package name for monorepos */
1213
+ package?: string;
1214
+ /** Explicit entry point path (relative to cwd or package dir) */
1215
+ entry?: string;
1216
+ }
1217
+ /**
1218
+ * Result of resolving a target package/entry point.
1219
+ */
1220
+ interface ResolvedTarget {
1221
+ /** Resolved directory containing the package */
1222
+ targetDir: string;
1223
+ /** Resolved entry point file path (absolute) */
1224
+ entryFile: string;
1225
+ /** Package info if this is a monorepo package */
1226
+ packageInfo?: WorkspacePackage;
1227
+ /** Entry point detection info */
1228
+ entryPointInfo: EntryPointInfo;
1229
+ }
1230
+ /**
1231
+ * Resolve a target package and entry point.
1232
+ *
1233
+ * This consolidates the repeated pattern from CLI commands:
1234
+ * 1. If --package specified, detect monorepo and find the package
1235
+ * 2. If no entry specified, auto-detect entry point
1236
+ * 3. If entry is a directory, detect entry point within it
1237
+ *
1238
+ * @param fs - FileSystem implementation (NodeFileSystem or SandboxFileSystem)
1239
+ * @param options - Resolution options
1240
+ * @returns Resolved target info
1241
+ * @throws Error if monorepo package not found, or entry point detection fails
1242
+ *
1243
+ * @example
1244
+ * ```typescript
1245
+ * import { NodeFileSystem, resolveTarget } from '@doccov/sdk';
1246
+ *
1247
+ * // Simple usage
1248
+ * const fs = new NodeFileSystem(process.cwd());
1249
+ * const { targetDir, entryFile } = await resolveTarget(fs, { cwd: process.cwd() });
1250
+ *
1251
+ * // With monorepo package
1252
+ * const { targetDir, entryFile, packageInfo } = await resolveTarget(fs, {
1253
+ * cwd: process.cwd(),
1254
+ * package: '@myorg/core',
1255
+ * });
1256
+ * ```
1257
+ */
1258
+ declare function resolveTarget(fs: FileSystem, options: ResolveTargetOptions): Promise<ResolvedTarget>;
1259
+ /**
1260
1260
  * Example validation types and utilities.
1261
1261
  */
1262
1262
  /**
@@ -1981,6 +1981,21 @@ declare function getExtendedTrend(spec: OpenPkg8, cwd: string, options?: {
1981
1981
  branch?: string;
1982
1982
  tier?: RetentionTier;
1983
1983
  }): ExtendedTrendAnalysis;
1984
+ interface SchemaDetectionContext {
1985
+ baseDir: string;
1986
+ entryFile: string;
1987
+ }
1988
+ interface DetectedSchema {
1989
+ schema: Record<string, unknown>;
1990
+ vendor: string;
1991
+ }
1992
+ interface SchemaDetectionResult {
1993
+ schemas: Map<string, DetectedSchema>;
1994
+ errors: string[];
1995
+ /** Warning when runtime was requested but compiled JS not found */
1996
+ noCompiledJsWarning?: boolean;
1997
+ }
1998
+ declare function detectRuntimeSchemas(context: SchemaDetectionContext): Promise<SchemaDetectionResult>;
1984
1999
  import * as TS3 from "typescript";
1985
2000
  /**
1986
2001
  * A schema adapter can detect and extract output types from a specific
@@ -2120,21 +2135,60 @@ declare function extractStandardSchemas(compiledJsPath: string, options?: Extrac
2120
2135
  */
2121
2136
  declare function extractStandardSchemasFromProject(entryFile: string, baseDir: string, options?: ExtractStandardSchemasOptions): Promise<StandardSchemaExtractionOutput>;
2122
2137
  declare function extractPackageSpec(entryFile: string, packageDir?: string, content?: string, options?: DocCovOptions): Promise<OpenPkgSpec>;
2123
- interface SchemaDetectionContext {
2124
- baseDir: string;
2125
- entryFile: string;
2126
- }
2127
- interface DetectedSchema {
2128
- schema: Record<string, unknown>;
2129
- vendor: string;
2130
- }
2131
- interface SchemaDetectionResult {
2132
- schemas: Map<string, DetectedSchema>;
2133
- errors: string[];
2134
- /** Warning when runtime was requested but compiled JS not found */
2135
- noCompiledJsWarning?: boolean;
2138
+ /**
2139
+ * Source of filter options.
2140
+ */
2141
+ type FilterSource = "config" | "override" | "combined";
2142
+ /**
2143
+ * Resolved filter options after merging config and overrides.
2144
+ */
2145
+ interface ResolvedFilters {
2146
+ /** Include patterns */
2147
+ include?: string[];
2148
+ /** Exclude patterns */
2149
+ exclude?: string[];
2150
+ /** Source of the filters */
2151
+ source?: FilterSource;
2152
+ /** Whether filters were applied from config */
2153
+ fromConfig: boolean;
2154
+ /** Whether filters were applied from overrides */
2155
+ fromOverride: boolean;
2136
2156
  }
2137
- declare function detectRuntimeSchemas(context: SchemaDetectionContext): Promise<SchemaDetectionResult>;
2157
+ /**
2158
+ * Parse a comma-separated list flag into an array.
2159
+ *
2160
+ * @param value - String or string array from CLI flag
2161
+ * @returns Parsed array, or undefined if empty
2162
+ *
2163
+ * @example
2164
+ * ```typescript
2165
+ * parseListFlag('a,b,c'); // ['a', 'b', 'c']
2166
+ * parseListFlag(['a,b', 'c']); // ['a', 'b', 'c']
2167
+ * parseListFlag(undefined); // undefined
2168
+ * ```
2169
+ */
2170
+ declare function parseListFlag(value?: string | string[]): string[] | undefined;
2171
+ /**
2172
+ * Merge filter options from config and CLI/API overrides.
2173
+ *
2174
+ * Merge behavior:
2175
+ * - Include: CLI values intersect with config values (narrowing)
2176
+ * - Exclude: CLI values are added to config values (expanding)
2177
+ *
2178
+ * @param config - Configuration (from doccov.config.ts)
2179
+ * @param overrides - Override filters (from CLI flags or API params)
2180
+ * @returns Merged filter options
2181
+ *
2182
+ * @example
2183
+ * ```typescript
2184
+ * const config = { include: ['A', 'B', 'C'] };
2185
+ * const overrides = { include: ['B', 'C', 'D'] };
2186
+ *
2187
+ * const resolved = mergeFilters(config, overrides);
2188
+ * // resolved.include = ['B', 'C'] (intersection)
2189
+ * ```
2190
+ */
2191
+ declare function mergeFilters(config: DocCovConfig | null, overrides: FilterOptions): ResolvedFilters;
2138
2192
  import { OpenPkg as OpenPkg9 } from "@openpkg-ts/spec";
2139
2193
  /**
2140
2194
  * Parsed components of a GitHub URL.
@@ -2352,60 +2406,6 @@ declare function installDependencies(fs: FileSystem, cwd: string, runCommand: Co
2352
2406
  */
2353
2407
  declare function createNodeCommandRunner(): CommandRunner;
2354
2408
  /**
2355
- * Source of filter options.
2356
- */
2357
- type FilterSource = "config" | "override" | "combined";
2358
- /**
2359
- * Resolved filter options after merging config and overrides.
2360
- */
2361
- interface ResolvedFilters {
2362
- /** Include patterns */
2363
- include?: string[];
2364
- /** Exclude patterns */
2365
- exclude?: string[];
2366
- /** Source of the filters */
2367
- source?: FilterSource;
2368
- /** Whether filters were applied from config */
2369
- fromConfig: boolean;
2370
- /** Whether filters were applied from overrides */
2371
- fromOverride: boolean;
2372
- }
2373
- /**
2374
- * Parse a comma-separated list flag into an array.
2375
- *
2376
- * @param value - String or string array from CLI flag
2377
- * @returns Parsed array, or undefined if empty
2378
- *
2379
- * @example
2380
- * ```typescript
2381
- * parseListFlag('a,b,c'); // ['a', 'b', 'c']
2382
- * parseListFlag(['a,b', 'c']); // ['a', 'b', 'c']
2383
- * parseListFlag(undefined); // undefined
2384
- * ```
2385
- */
2386
- declare function parseListFlag(value?: string | string[]): string[] | undefined;
2387
- /**
2388
- * Merge filter options from config and CLI/API overrides.
2389
- *
2390
- * Merge behavior:
2391
- * - Include: CLI values intersect with config values (narrowing)
2392
- * - Exclude: CLI values are added to config values (expanding)
2393
- *
2394
- * @param config - Configuration (from doccov.config.ts)
2395
- * @param overrides - Override filters (from CLI flags or API params)
2396
- * @returns Merged filter options
2397
- *
2398
- * @example
2399
- * ```typescript
2400
- * const config = { include: ['A', 'B', 'C'] };
2401
- * const overrides = { include: ['B', 'C', 'D'] };
2402
- *
2403
- * const resolved = mergeFilters(config, overrides);
2404
- * // resolved.include = ['B', 'C'] (intersection)
2405
- * ```
2406
- */
2407
- declare function mergeFilters(config: DocCovConfig | null, overrides: FilterOptions): ResolvedFilters;
2408
- /**
2409
2409
  * Repository metadata from GitHub API.
2410
2410
  */
2411
2411
  interface GitHubRepoMetadata {