@ngcompass/planner 0.1.1-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,826 @@
1
+ import { CacheContext, CacheKeyContext, ResultCache } from '@ngcompass/cache';
2
+ import { RuleSeverity, ResolvedRule, ConfigOverride, AnalysisResult, Result } from '@ngcompass/common';
3
+ export { Err, Ok, Result } from '@ngcompass/common';
4
+
5
+ /**
6
+ * Execution Plan Types
7
+ *
8
+ * Maps discovered files + resolved rules → executable tasks with indexes.
9
+ */
10
+
11
+ /**
12
+ * Complete execution plan output (plan + tasks + indexes)
13
+ *
14
+ * - tasks: Flat array of all tasks (task-centric, content-addressed)
15
+ * - plan: File-grouped view (file-centric, backward compatible)
16
+ * - indexes: Pre-computed indexes for both file and task queries
17
+ */
18
+ interface ExecutionPlanOutput {
19
+ /** All tasks to execute (primary execution structure) */
20
+ readonly tasks: ReadonlyArray<Task>;
21
+ /** File-grouped view (backward compatible, derived from tasks) */
22
+ readonly plan: ExecutionPlan;
23
+ /** Pre-computed indexes for efficient queries */
24
+ readonly indexes: ExecutionIndexes;
25
+ /** Tasks that were skipped */
26
+ readonly skippedTasks: ReadonlyArray<Task>;
27
+ /** Pre-loaded cached results (taskId → result) */
28
+ readonly cachedResults?: ReadonlyMap<string, unknown>;
29
+ /** Global content hash for the entire plan */
30
+ readonly globalHash?: string;
31
+ /** Pre-computed analysis result (if fully cached) */
32
+ readonly precomputedAnalysis?: AnalysisResult;
33
+ /**
34
+ * Files whose tasks were not found in the result cache and will be
35
+ * re-analysed. Populated when `options.cache` is provided and incremental
36
+ * filtering has run. `undefined` when caching is disabled.
37
+ */
38
+ readonly changedFiles?: ReadonlyArray<string>;
39
+ /**
40
+ * Files whose tasks were found in the result cache and skipped.
41
+ * Populated when `options.cache` is provided and incremental
42
+ * filtering has run. `undefined` when caching is disabled.
43
+ */
44
+ readonly cachedFiles?: ReadonlyArray<string>;
45
+ }
46
+ /**
47
+ * Execution plan - one entry per discovered file
48
+ */
49
+ type ExecutionPlan = Readonly<Record<string, FileAnalysisUnit>>;
50
+ /**
51
+ * A single file that needs to be analyzed
52
+ */
53
+ interface FileAnalysisUnit {
54
+ /** The primary file being analyzed */
55
+ readonly file: FileInfo;
56
+ /** All the tasks/rules that will run on this file */
57
+ readonly tasks: ReadonlyArray<RuleTask>;
58
+ }
59
+ /**
60
+ * Information about the file being analyzed
61
+ */
62
+ interface FileInfo {
63
+ /** File path (absolute) */
64
+ readonly path: string;
65
+ /** File type (component, service, etc) */
66
+ readonly type: FileType;
67
+ /** Content hash for cache invalidation */
68
+ readonly hash: string;
69
+ }
70
+ /**
71
+ * File type classification.
72
+ *
73
+ * `'unknown'` is used for files that do not match any recognised Angular or
74
+ * TypeScript pattern (e.g. stray JSON, Markdown, or binary files that
75
+ * somehow enter the file list). Rules are never applied to `'unknown'` files.
76
+ */
77
+ type FileType = 'component' | 'directive' | 'pipe' | 'service' | 'module' | 'guard' | 'logic' | 'angular-class' | 'spec' | 'template' | 'style' | 'config' | 'unknown';
78
+ /**
79
+ * A single rule execution task
80
+ */
81
+ interface RuleTask {
82
+ /** Which rule to run */
83
+ readonly ruleName: string;
84
+ /** Rule severity level */
85
+ readonly severity: RuleSeverity;
86
+ /** Rule options (configuration from resolved rules) */
87
+ readonly options: Readonly<Record<string, unknown>>;
88
+ /** Cache key for this specific task */
89
+ readonly cacheKey: string;
90
+ /** What files this task needs to read and analyze */
91
+ readonly inputs: TaskInputs;
92
+ /**
93
+ * Whether this task requires the TypeScript type-checker (expensive!).
94
+ * When true the file is included in `indexes.filesNeedingTypeChecker` so
95
+ * the engine can set up a full TypeScript Program for that file.
96
+ */
97
+ readonly needsTypeChecker?: boolean;
98
+ /**
99
+ * Whether this task requires a pre-computed `ProjectContext` (CTX-001).
100
+ * Routed to the type-aware execution path alongside `needsTypeChecker`.
101
+ */
102
+ readonly needsProjectContext?: boolean;
103
+ }
104
+ /**
105
+ * All the files this task needs to read
106
+ */
107
+ interface TaskInputs {
108
+ /** TypeScript file input (always present) */
109
+ typescript: FileInput;
110
+ /** Template file input (if needed) */
111
+ template?: FileInput;
112
+ /** Style files input (if needed) */
113
+ styles?: ReadonlyArray<FileInput>;
114
+ /** Spec file input (if needed) */
115
+ spec?: FileInput;
116
+ }
117
+ /**
118
+ * A single file input for a task
119
+ */
120
+ interface FileInput {
121
+ /** Path to the file (absolute) */
122
+ readonly path: string;
123
+ /** Content hash of this file (SHA-256) */
124
+ readonly hash: string;
125
+ /** Does this task need to parse this file into AST? */
126
+ readonly needsAst: boolean;
127
+ }
128
+ /**
129
+ * Resource type enum
130
+ */
131
+ type ResourceType = 'typescript' | 'template' | 'styles' | 'spec';
132
+ /**
133
+ * A single executable task (task-centric architecture)
134
+ *
135
+ * Task is the fundamental unit of execution with content-based identity.
136
+ * Unlike RuleTask (file-centric), Task uses content-addressable cache keys
137
+ * that survive file renames and enable precise cache invalidation.
138
+ *
139
+ * Key differences from RuleTask:
140
+ * - taskId: Content-based (SHA-256 of all inputs + options)
141
+ * - filePath: Explicit (not embedded in cache key)
142
+ * - inputs: Include content hashes for each file
143
+ */
144
+ interface Task {
145
+ /**
146
+ * Content-based task identifier (primary cache key)
147
+ *
148
+ * Format: SHA256(ruleName + typescript.hash + template?.hash + styles?.hashes + spec?.hash + options)
149
+ *
150
+ * This enables:
151
+ * - Cache hits even after file renames (content unchanged)
152
+ * - Precise invalidation (only affected tasks)
153
+ * - Cross-project cache sharing (same content = same ID)
154
+ */
155
+ readonly taskId: string;
156
+ /** Which rule to execute */
157
+ readonly ruleName: string;
158
+ /** Which file is being analyzed */
159
+ readonly filePath: string;
160
+ /** Rule severity level */
161
+ readonly severity: RuleSeverity;
162
+ /** Rule options (configuration) */
163
+ readonly options: Readonly<Record<string, unknown>>;
164
+ /** Input files with content hashes */
165
+ readonly inputs: TaskInputs;
166
+ /**
167
+ * Whether this task requires the TypeScript type-checker (expensive!).
168
+ * Mirrors `RuleTask.needsTypeChecker` on the task-centric view.
169
+ */
170
+ readonly needsTypeChecker?: boolean;
171
+ /**
172
+ * Whether this task requires a pre-computed `ProjectContext` (CTX-001).
173
+ *
174
+ * When `true` the task is routed to the type-aware execution path on the
175
+ * main thread (same as `needsTypeChecker`) because `ProjectContext` is
176
+ * built from the TypeScript `Program` created there.
177
+ * Rules receive the context via `RuleContext.project`.
178
+ */
179
+ readonly needsProjectContext?: boolean;
180
+ }
181
+ /**
182
+ * Pre-computed indexes for efficient engine queries
183
+ *
184
+ * - File-level indexes: For parsing optimization (parse once, reuse)
185
+ * - Task-level indexes: For execution strategies (by rule, by severity, etc)
186
+ */
187
+ interface ExecutionIndexes {
188
+ /** Files that need TypeScript AST parsing */
189
+ readonly filesNeedingTsAst: ReadonlyArray<string>;
190
+ /** Files that need HTML AST parsing */
191
+ readonly filesNeedingHtmlAst: ReadonlyArray<string>;
192
+ /** Files that need CSS AST parsing */
193
+ readonly filesNeedingCssAst: ReadonlyArray<string>;
194
+ /**
195
+ * Files that need the TypeScript type-checker (expensive!).
196
+ * The engine should allocate a full TypeScript Program only for these files.
197
+ */
198
+ readonly filesNeedingTypeChecker: ReadonlyArray<string>;
199
+ /** Tasks grouped by file path: filePath → tasks */
200
+ readonly tasksByFile: Readonly<Record<string, ReadonlyArray<Task>>>;
201
+ /** Tasks grouped by rule name: ruleName → tasks */
202
+ readonly tasksByRule: Readonly<Record<string, ReadonlyArray<string>>>;
203
+ /** Tasks grouped by severity: severity → tasks */
204
+ readonly tasksBySeverityLevel: Readonly<Record<RuleSeverity, ReadonlyArray<Task>>>;
205
+ /** Files grouped by type: fileType → file paths */
206
+ readonly filesByType: Readonly<Record<FileType, ReadonlyArray<string>>>;
207
+ /** Task count by severity level (backward compatible) */
208
+ readonly tasksBySeverity: Readonly<Record<RuleSeverity, number>>;
209
+ /** Global statistics */
210
+ readonly stats: ExecutionStats;
211
+ }
212
+ /**
213
+ * Global execution statistics
214
+ */
215
+ interface ExecutionStats {
216
+ /** Total files in the plan */
217
+ readonly totalFiles: number;
218
+ /** Total tasks to execute */
219
+ readonly totalTasks: number;
220
+ /** Average tasks per file */
221
+ readonly avgTasksPerFile: number;
222
+ /** Files with templates */
223
+ readonly filesWithTemplates: number;
224
+ /** Files with styles */
225
+ readonly filesWithStyles: number;
226
+ /** Files with specs */
227
+ readonly filesWithSpecs: number;
228
+ }
229
+ /**
230
+ * Options for building the execution plan
231
+ */
232
+ interface ExecutionPlanOptions {
233
+ /** Discovered files from Phase 1 */
234
+ readonly files: ReadonlyArray<string>;
235
+ /** Resolved rules from Phase 1.5 */
236
+ readonly rules: ReadonlyMap<string, ResolvedRule>;
237
+ /** Root directory for resolving relative paths */
238
+ readonly rootDir: string;
239
+ /** Optional cache context for persistent optimizations */
240
+ readonly cache?: CacheContext;
241
+ /** Debug mode for detailed timing logging */
242
+ readonly debug?: boolean;
243
+ /** Options for incremental filtering */
244
+ readonly incremental?: IncrementalFilterOptions;
245
+ /**
246
+ * Version context for cache key generation.
247
+ * When provided, toolVersion and ruleRegistryHash are embedded in taskIds
248
+ * and globalHash, ensuring caches are invalidated on tool / rule-set upgrades.
249
+ *
250
+ * Strongly recommended for production use. Omitting risks stale result-cache
251
+ * hits after an upgrade.
252
+ */
253
+ readonly cacheKeyCtx?: CacheKeyContext;
254
+ /**
255
+ * Number of files at which task-building switches from sequential to
256
+ * parallel (worker threads). Defaults to 10 000.
257
+ *
258
+ * Lower this value to enable parallelism on smaller projects.
259
+ * Set to `Infinity` to always use the sequential path (useful for debugging).
260
+ */
261
+ readonly parallelThreshold?: number;
262
+ /**
263
+ * Number of worker threads to use when parallel mode is active.
264
+ * Defaults to 4.
265
+ */
266
+ readonly workerCount?: number;
267
+ /**
268
+ * Per-file rule overrides from config.overrides[].
269
+ *
270
+ * Each override entry's `files` glob patterns are matched against each
271
+ * analysed file path. Matching override rules are merged on top of the
272
+ * global resolved rules before tasks are created for that file.
273
+ * Last matching override wins.
274
+ *
275
+ * - `'off'` → rule is disabled for matching files
276
+ * - `'warn'|'error'` → severity changed, options inherited from global
277
+ * - object form → severity + options merged (override wins on conflicts)
278
+ */
279
+ readonly overrides?: ReadonlyArray<ConfigOverride>;
280
+ }
281
+ /**
282
+ * Incremental execution plan with cache-based filtering
283
+ */
284
+ interface IncrementalPlan {
285
+ /** Tasks with results in cache (can be skipped) */
286
+ readonly skippedTasks: ReadonlyArray<Task>;
287
+ /** Tasks without cache entries (must be executed) */
288
+ readonly tasks: ReadonlyArray<Task>;
289
+ /** Pre-loaded cached results (taskId → result) */
290
+ readonly cachedResults: ReadonlyMap<string, unknown>;
291
+ /** Cache statistics */
292
+ readonly stats: CacheFilterStats;
293
+ }
294
+ /**
295
+ * Cache filtering statistics
296
+ */
297
+ interface CacheFilterStats {
298
+ /** Total tasks in execution plan */
299
+ readonly totalTasks: number;
300
+ /** Tasks found in cache */
301
+ readonly cachedTasks: number;
302
+ /** Tasks not in cache (need execution) */
303
+ readonly pendingTasks: number;
304
+ /** Cache hit rate (0.0 to 1.0) */
305
+ readonly cacheHitRate: number;
306
+ /**
307
+ * Estimated percentage of execution time saved due to caching (0–100).
308
+ *
309
+ * Computed as `cacheHitRate × 100`, which is accurate when tasks have
310
+ * roughly equal cost. Use as a fast approximation for progress UIs and
311
+ * log messages.
312
+ */
313
+ readonly timeSavedEstimate: number;
314
+ }
315
+ /**
316
+ * Options for incremental filtering
317
+ */
318
+ interface IncrementalFilterOptions {
319
+ /** Force re-execution even if cached */
320
+ readonly forceRerun?: boolean;
321
+ /** Load cached results into memory */
322
+ readonly loadCachedResults?: boolean;
323
+ /** Maximum age of cached results (ms) */
324
+ readonly maxCacheAge?: number;
325
+ }
326
+ /**
327
+ * Options for cache pruning
328
+ */
329
+ interface CachePruneOptions {
330
+ /** Maximum age of cache entries (ms) */
331
+ readonly maxAge?: number;
332
+ /** Maximum number of entries to keep */
333
+ readonly maxEntries?: number;
334
+ /** Minimum hit count to keep */
335
+ readonly minHits?: number;
336
+ }
337
+
338
+ /**
339
+ * Execution Plan Builder
340
+ *
341
+ * Builds an execution plan from discovered files and resolved rules.
342
+ * Produces both task-centric and file-centric representations plus indexes.
343
+ */
344
+
345
+ /**
346
+ * Builds complete execution plan with indexes and optional caching.
347
+ *
348
+ * @param options - Build options (files + rules)
349
+ * @returns ExecutionPlanOutput with tasks[] + plan + indexes
350
+ */
351
+ declare const buildExecutionPlan: (options: ExecutionPlanOptions) => Promise<Result<ExecutionPlanOutput>>;
352
+ /**
353
+ * Gets execution plan summary (for logging).
354
+ *
355
+ * @param output - Execution plan output
356
+ * @returns Summary string
357
+ */
358
+ declare const getExecutionPlanSummary: (output: ExecutionPlanOutput) => string;
359
+
360
+ /**
361
+ * File Type Detection
362
+ *
363
+ * Pure functions for detecting Angular file types based on naming conventions.
364
+ * Follows FP principles: pure, deterministic, no side effects.
365
+ */
366
+
367
+ /**
368
+ * Detects file type based on file path and naming conventions.
369
+ *
370
+ * Convention rules:
371
+ * - *.component.ts → component
372
+ * - *.directive.ts → directive
373
+ * - *.pipe.ts → pipe
374
+ * - *.service.ts → service
375
+ * - *.module.ts → module
376
+ * - *.guard.ts → guard
377
+ * - *.html → template
378
+ * - *.css, *.scss, *.sass, *.less → style
379
+ * - *.config.ts, *.json → config
380
+ * - *.ts (other TypeScript) → logic
381
+ * - Everything else → unknown (rules are never applied to unknown files)
382
+ *
383
+ * @param filePath - Absolute or relative file path
384
+ * @returns FileType classification
385
+ */
386
+ declare const detectFileType: (filePath: string) => FileType;
387
+ /**
388
+ * Checks if a file is a TypeScript file.
389
+ *
390
+ * @param filePath - File path
391
+ * @returns true if TypeScript file
392
+ */
393
+ declare const isTypeScriptFile: (filePath: string) => boolean;
394
+ /**
395
+ * Checks if a file is a template file (HTML).
396
+ *
397
+ * @param filePath - File path
398
+ * @returns true if template file
399
+ */
400
+ declare const isTemplateFile: (filePath: string) => boolean;
401
+ /**
402
+ * Checks if a file is a style file (CSS/SCSS/etc).
403
+ *
404
+ * @param filePath - File path
405
+ * @returns true if style file
406
+ */
407
+ declare const isStyleFile: (filePath: string) => boolean;
408
+ /**
409
+ * Checks if a file is a spec file (test).
410
+ *
411
+ * @param filePath - File path
412
+ * @returns true if spec file
413
+ */
414
+ declare const isSpecFile: (filePath: string) => boolean;
415
+ /**
416
+ * Checks if a file is a component file.
417
+ *
418
+ * @param filePath - File path
419
+ * @returns true if component file
420
+ */
421
+ declare const isComponentFile: (filePath: string) => boolean;
422
+ /**
423
+ * Gets the base name without Angular suffix.
424
+ * Example: "user.component.ts" → "user"
425
+ *
426
+ * @param filePath - File path
427
+ * @returns Base name without suffix
428
+ */
429
+ declare const getBaseName: (filePath: string) => string;
430
+
431
+ /**
432
+ * Resource Discovery
433
+ *
434
+ * Pure functions for discovering related files (templates, styles, specs)
435
+ * using convention-based detection (no parsing).
436
+ */
437
+
438
+ /**
439
+ * Discovers all related resources for a TypeScript file.
440
+ *
441
+ * @param tsFilePath - TypeScript file path (absolute)
442
+ * @param needsTsAst - Whether TypeScript input requires AST
443
+ * @param needsHtmlAst - Whether template input requires AST
444
+ * @param needsCssAst - Whether styles inputs require AST
445
+ * @param needsSpecAst - Whether spec input requires AST
446
+ * @param directoryCache - Optional directory listing cache
447
+ * @returns TaskInputs with all discovered resources
448
+ */
449
+ declare const discoverResources: (tsFilePath: string, needsTsAst: boolean, needsHtmlAst: boolean, needsCssAst: boolean, needsSpecAst: boolean, directoryCache?: Map<string, string[]>) => Promise<TaskInputs>;
450
+ /**
451
+ * Checks if any resource file exists for the given TypeScript file.
452
+ *
453
+ * @param tsFilePath - TypeScript file path
454
+ * @param resourceType - Type of resource to check
455
+ * @param directoryCache - Optional directory listing cache
456
+ * @returns true if resource exists
457
+ */
458
+ declare const resourceExists: (tsFilePath: string, resourceType: "template" | "style" | "spec", directoryCache?: Map<string, string[]>) => Promise<boolean>;
459
+ /**
460
+ * Gets all style file paths for a component.
461
+ *
462
+ * @param tsFilePath - Component TypeScript file path
463
+ * @param directoryCache - Optional directory listing cache
464
+ * @returns Array of style file paths
465
+ */
466
+ declare const getStyleFiles: (tsFilePath: string, directoryCache?: Map<string, string[]>) => Promise<ReadonlyArray<string>>;
467
+ /**
468
+ * Gets the template file path for a component.
469
+ *
470
+ * @param tsFilePath - Component TypeScript file path
471
+ * @param directoryCache - Optional directory listing cache
472
+ * @returns Template file path or null if not found
473
+ */
474
+ declare const getTemplateFile: (tsFilePath: string, directoryCache?: Map<string, string[]>) => Promise<string | null>;
475
+ /**
476
+ * Gets the spec file path.
477
+ *
478
+ * @param tsFilePath - TypeScript file path
479
+ * @param directoryCache - Optional directory listing cache
480
+ * @returns Spec file path or null if not found
481
+ */
482
+ declare const getSpecFile: (tsFilePath: string, directoryCache?: Map<string, string[]>) => Promise<string | null>;
483
+
484
+ interface ComponentNode {
485
+ tsPath: string;
486
+ templatePath?: string;
487
+ stylePaths: string[];
488
+ specPath?: string;
489
+ type: FileType;
490
+ }
491
+ /**
492
+ * A graph of component dependencies (template, styles, specs).
493
+ * Built in a single pass to avoid repeated directory scans.
494
+ */
495
+ declare class ComponentDependencyGraph {
496
+ private graph;
497
+ /**
498
+ * Builds the graph from a list of files.
499
+ * O(N) complexity where N is the number of files.
500
+ * Falls back to decorator-based templateUrl/styleUrls extraction when
501
+ * convention-based discovery finds no template or styles.
502
+ */
503
+ build(files: ReadonlyArray<string>): Promise<void>;
504
+ /**
505
+ * Gets resources for a given component file.
506
+ * O(1) lookup.
507
+ */
508
+ getResources(tsPath: string): ComponentNode | undefined;
509
+ }
510
+
511
+ /**
512
+ * Task Builder
513
+ *
514
+ * Pure functions for building executable tasks by matching rules to files.
515
+ */
516
+
517
+ interface GraphStats {
518
+ hits: number;
519
+ misses: number;
520
+ fallbacks: number;
521
+ }
522
+ /**
523
+ * Context for task building to enable memoization and shared caches.
524
+ */
525
+ interface TaskBuilderContext {
526
+ hashCache?: Map<string, string>;
527
+ resourceCache?: Map<string, TaskInputs>;
528
+ directoryCache?: Map<string, string[]>;
529
+ globalHash?: string;
530
+ componentGraph?: ComponentDependencyGraph;
531
+ graphStats?: GraphStats;
532
+ /**
533
+ * Version context forwarded to calculateTaskId.
534
+ * When provided, toolVersion and ruleRegistryHash are mixed into every
535
+ * taskId so that upgrading the tool or a plugin invalidates per-task
536
+ * result-cache entries automatically.
537
+ */
538
+ cacheKeyCtx?: CacheKeyContext;
539
+ }
540
+ /**
541
+ * Checks if a rule should be applied to a file type.
542
+ *
543
+ * @param rule - Resolved rule
544
+ * @param fileType - File type
545
+ * @returns true if rule applies to this file type
546
+ */
547
+ declare const shouldApplyRule: (rule: ResolvedRule, fileType: FileType) => boolean;
548
+ /**
549
+ * Filters rules that require a specific analysis capability.
550
+ *
551
+ * @param rules - All resolved rules
552
+ * @param astType - Capability to filter by
553
+ * @returns Filtered rules
554
+ */
555
+ declare const filterRulesByAstRequirement: (rules: ReadonlyMap<string, ResolvedRule>, astType: "tsAst" | "htmlAst" | "cssAst" | "typeChecker" | "projectContext") => ReadonlyArray<ResolvedRule>;
556
+ /**
557
+ * Groups rules by dependency type.
558
+ *
559
+ * @param rules - All resolved rules
560
+ * @returns Rules grouped by dependency type
561
+ */
562
+ declare const groupRulesByDependencyType: (rules: ReadonlyMap<string, ResolvedRule>) => Readonly<Record<string, ReadonlyArray<ResolvedRule>>>;
563
+ /**
564
+ * Builds a single task with content-based taskId.
565
+ *
566
+ * @param filePath - File path
567
+ * @param fileType - File type
568
+ * @param rule - Resolved rule
569
+ * @param context - Optional builder context
570
+ * @returns Task or null if rule does not apply
571
+ */
572
+ declare const buildTask: (filePath: string, fileType: FileType, rule: ResolvedRule, context?: TaskBuilderContext) => Promise<Task | null>;
573
+ /**
574
+ * Builds all applicable tasks for a file.
575
+ *
576
+ * @param filePath - File path
577
+ * @param fileType - File type
578
+ * @param rules - All resolved rules
579
+ * @param context - Optional context
580
+ * @returns Array of tasks
581
+ */
582
+ declare const buildTasksForFileTaskCentric: (filePath: string, fileType: FileType, rules: ReadonlyMap<string, ResolvedRule>, context?: TaskBuilderContext) => Promise<ReadonlyArray<Task>>;
583
+
584
+ /**
585
+ * Content Hashing
586
+ *
587
+ * Deterministic hashing utilities for cache invalidation.
588
+ * Hash inputs may include: file content, related resources, and active rules.
589
+ */
590
+
591
+ /**
592
+ * Reads file content and returns a content hash.
593
+ *
594
+ * @param filePath - File path
595
+ * @param cache - Optional in-memory cache
596
+ * @returns Content hash
597
+ */
598
+ declare const hashFile: (filePath: string, cache?: Map<string, string>) => Promise<string>;
599
+ /**
600
+ * Calculates a combined hash for multiple files.
601
+ *
602
+ * @param filePaths - Array of file paths
603
+ * @param cache - Optional hash cache
604
+ * @returns Combined hash
605
+ */
606
+ declare const hashFiles: (filePaths: ReadonlyArray<string>, cache?: Map<string, string>) => Promise<string>;
607
+ /**
608
+ * Calculates hash for rules configuration.
609
+ *
610
+ * @param rules - Rules that apply to this file
611
+ * @returns Rules hash
612
+ */
613
+ declare const hashRules: (rules: ReadonlyArray<ResolvedRule>) => string;
614
+ /**
615
+ * Calculates combined hash for a file and its resources.
616
+ *
617
+ * @param inputs - Task inputs with hashes
618
+ * @param applicableRules - Rules that apply to this file
619
+ * @returns Combined content hash
620
+ */
621
+ declare const calculateFileHash: (inputs: TaskInputs, applicableRules: ReadonlyArray<ResolvedRule>) => string;
622
+ /**
623
+ * Calculates hash for task inputs only (no rules).
624
+ *
625
+ * @param inputs - Task inputs
626
+ * @returns Inputs hash
627
+ */
628
+ declare const hashTaskInputs: (inputs: TaskInputs) => Promise<string>;
629
+ /**
630
+ * Fast hash using only file stats.
631
+ *
632
+ * @param filePath - File path
633
+ * @returns Stats-based hash
634
+ */
635
+ declare const hashFileStats: (filePath: string) => Promise<string>;
636
+
637
+ /**
638
+ * Index Builder
639
+ *
640
+ * Pure functions for building pre-computed indexes for O(1) queries.
641
+ * Indexes enable efficient incremental execution strategies.
642
+ */
643
+
644
+ /**
645
+ * Builds all indexes from execution plan and optional task list.
646
+ *
647
+ * @param plan - Execution plan (file-centric view)
648
+ * @param tasks - Task-centric list (optional for backward compatibility)
649
+ * @returns Comprehensive pre-computed indexes
650
+ */
651
+ declare function buildIndexes(plan: ExecutionPlan): ExecutionIndexes;
652
+ declare function buildIndexes(plan: ExecutionPlan, tasks: ReadonlyArray<Task>): ExecutionIndexes;
653
+ /**
654
+ * Filters index to get files for specific rules.
655
+ *
656
+ * @param index - TasksByRule index
657
+ * @param ruleNames - Rule names to filter by
658
+ * @returns Combined array of file paths
659
+ */
660
+ declare const getFilesForRules: (index: Readonly<Record<string, ReadonlyArray<string>>>, ruleNames: ReadonlyArray<string>) => ReadonlyArray<string>;
661
+ /**
662
+ * Gets total task count from indexes.
663
+ *
664
+ * @param indexes - Execution indexes
665
+ * @returns Total task count
666
+ */
667
+ declare const getTotalTasks: (indexes: ExecutionIndexes) => number;
668
+ /**
669
+ * Gets tasks count for a specific severity level.
670
+ *
671
+ * @param indexes - Execution indexes
672
+ * @param severity - Severity level
673
+ * @returns Task count
674
+ */
675
+ declare const getTasksCountBySeverity: (indexes: ExecutionIndexes, severity: RuleSeverity) => number;
676
+
677
+ /**
678
+ * Incremental Planner (Phase 2.0)
679
+ *
680
+ * Filters execution tasks by cache status.
681
+ * Splits tasks into cached (skip) and pending (execute).
682
+ */
683
+
684
+ /**
685
+ * Filters tasks by cache status.
686
+ *
687
+ * @param tasks - All tasks from execution plan
688
+ * @param cache - Result cache
689
+ * @param options - Filter options
690
+ * @returns Incremental plan with cache split
691
+ */
692
+ declare const filterCachedTasks: (tasks: ReadonlyArray<Task>, cache: ResultCache, options?: IncrementalFilterOptions) => Promise<IncrementalPlan>;
693
+ /**
694
+ * Checks if all tasks are cached.
695
+ *
696
+ * @param tasks - Tasks to check
697
+ * @param cache - Result cache
698
+ * @returns true if all tasks are cached
699
+ */
700
+ declare const areAllTasksCached: (tasks: ReadonlyArray<Task>, cache: ResultCache) => Promise<boolean>;
701
+ /**
702
+ * Gets cache hit rate for a set of tasks.
703
+ *
704
+ * @param tasks - Tasks to check
705
+ * @param cache - Result cache
706
+ * @returns Cache hit rate (0.0 to 1.0)
707
+ */
708
+ declare const getCacheHitRate: (tasks: ReadonlyArray<Task>, cache: ResultCache) => Promise<number>;
709
+ /**
710
+ * Prunes stale cache entries.
711
+ *
712
+ * @param taskIds - All current task IDs
713
+ * @param cache - Result cache
714
+ * @param options - Prune options
715
+ * @returns Number of entries removed
716
+ */
717
+ declare const pruneStaleCache: (taskIds: ReadonlyArray<string>, cache: ResultCache, options?: CachePruneOptions) => Promise<number>;
718
+
719
+ /**
720
+ * Groups tasks by file path.
721
+ *
722
+ * @param tasks - Flat list of tasks
723
+ * @returns Map keyed by file path
724
+ */
725
+ declare const groupTasksByFile: (tasks: ReadonlyArray<Task>) => Map<string, Task[]>;
726
+
727
+ /**
728
+ * Scanner → Planner Bridge Utilities
729
+ *
730
+ * Convenience helpers that convert `@ngcompass/scanner`'s `ScanResult` into
731
+ * the inputs expected by `@ngcompass/planner`'s `buildExecutionPlan`.
732
+ *
733
+ * Using this module eliminates the boilerplate of manually forwarding
734
+ * `ScanResult.files` and keeps the two packages loosely coupled — if either
735
+ * package changes its contract, only this file needs updating.
736
+ */
737
+
738
+ /**
739
+ * Minimal `ScanResult` shape consumed by the bridge.
740
+ *
741
+ * This matches `@ngcompass/scanner`'s `ScanResult` interface and is kept
742
+ * inline to avoid a circular package dependency (scanner → planner would
743
+ * create a cycle). Only the fields actually used by `scanResultToPlanInput`
744
+ * are listed here.
745
+ */
746
+ interface ScanResultBridge {
747
+ /** Discovered file paths (absolute). */
748
+ readonly files: ReadonlyArray<string>;
749
+ /** Optional scan timestamp (ms since epoch). */
750
+ readonly timestamp?: number;
751
+ }
752
+ /**
753
+ * Options for converting a scan result into planner inputs.
754
+ */
755
+ interface ScanToPlanOptions {
756
+ /** Resolved rules produced by the rule resolver (Phase 1.5). */
757
+ readonly rules: ReadonlyMap<string, ResolvedRule>;
758
+ /** Absolute path to the project root. */
759
+ readonly rootDir: string;
760
+ /** Optional cache context for persistent plan and result caching. */
761
+ readonly cache?: CacheContext;
762
+ /** Debug mode: emit detailed timing output to the planner logger. */
763
+ readonly debug?: boolean;
764
+ /** Options for incremental (cache-based) task filtering. */
765
+ readonly incremental?: IncrementalFilterOptions;
766
+ /**
767
+ * Version context for cache key generation. Strongly recommended for
768
+ * production use — omitting risks stale cache hits after a tool upgrade.
769
+ */
770
+ readonly cacheKeyCtx?: CacheKeyContext;
771
+ /**
772
+ * File count threshold above which task-building switches to parallel
773
+ * worker threads. Forwarded verbatim to `ExecutionPlanOptions`.
774
+ * @default 10000
775
+ */
776
+ readonly parallelThreshold?: number;
777
+ /**
778
+ * Number of worker threads used in parallel mode.
779
+ * @default 4
780
+ */
781
+ readonly workerCount?: number;
782
+ }
783
+ /**
784
+ * Converts a `ScanResult` (from `@ngcompass/scanner`) into an
785
+ * `ExecutionPlanOptions` object ready to pass to `buildExecutionPlan`.
786
+ *
787
+ * @example
788
+ * ```typescript
789
+ * import { scan } from '@ngcompass/scanner';
790
+ * import { buildExecutionPlan } from '@ngcompass/planner';
791
+ * import { scanResultToPlanInput } from '@ngcompass/planner/integration';
792
+ *
793
+ * const scanResult = await scan({ rootDir: '.', include: [], exclude: [] });
794
+ * if (!scanResult.ok) throw scanResult.error;
795
+ *
796
+ * const planOptions = scanResultToPlanInput(scanResult.data, {
797
+ * rules,
798
+ * rootDir: '.',
799
+ * cache,
800
+ * });
801
+ *
802
+ * const plan = await buildExecutionPlan(planOptions);
803
+ * ```
804
+ *
805
+ * @param scanResult - Result of a successful `scan()` call.
806
+ * @param opts - Planner configuration (rules, rootDir, cache, …).
807
+ * @returns `ExecutionPlanOptions` ready for `buildExecutionPlan`.
808
+ */
809
+ declare const scanResultToPlanInput: (scanResult: ScanResultBridge, opts: ScanToPlanOptions) => ExecutionPlanOptions;
810
+ /**
811
+ * Returns `true` if the scan produced at least one file that the planner
812
+ * can operate on (i.e. the file list is non-empty).
813
+ *
814
+ * Useful as a fast guard before calling `buildExecutionPlan`.
815
+ *
816
+ * @param scanResult - Bridge-compatible scan result.
817
+ */
818
+ declare const hasScanFiles: (scanResult: ScanResultBridge) => boolean;
819
+ /**
820
+ * Returns the discovered file count from a scan result.
821
+ *
822
+ * @param scanResult - Bridge-compatible scan result.
823
+ */
824
+ declare const getScanFileCount: (scanResult: ScanResultBridge) => number;
825
+
826
+ export { type CacheFilterStats, type CachePruneOptions, type ExecutionIndexes, type ExecutionPlan, type ExecutionPlanOptions, type ExecutionPlanOutput, type ExecutionStats, type FileAnalysisUnit, type FileInfo, type FileInput, type FileType, type IncrementalFilterOptions, type IncrementalPlan, type ResourceType, type RuleTask, type ScanResultBridge, type ScanToPlanOptions, type Task, type TaskInputs, areAllTasksCached, buildExecutionPlan, buildIndexes, buildTask, buildTasksForFileTaskCentric as buildTasksForFile, calculateFileHash, detectFileType, discoverResources, filterCachedTasks, filterRulesByAstRequirement, getBaseName, getCacheHitRate, getExecutionPlanSummary, getFilesForRules, getScanFileCount, getSpecFile, getStyleFiles, getTasksCountBySeverity, getTemplateFile, getTotalTasks, groupRulesByDependencyType, groupTasksByFile, hasScanFiles, hashFile, hashFileStats, hashFiles, hashRules, hashTaskInputs, isComponentFile, isSpecFile, isStyleFile, isTemplateFile, isTypeScriptFile, pruneStaleCache, resourceExists, scanResultToPlanInput, shouldApplyRule };