Commit 65aac67
* feat(config): extend unified tree with detectors.categories, detectors.include, indexing.parsers
Prep for Phase-2 retirement of the legacy ProjectConfigLoader static API.
The Analyzer pipeline currently reads language/detector/parser/parallelism
filters from the legacy ProjectConfig POJO via ProjectConfigLoader.loadProjectConfig;
moving those call sites onto the injected CodeIqUnifiedConfig bean requires
the unified tree to carry the same fields. This commit adds:
- DetectorsConfig: categories, include (List<String>). empty() updated.
- IndexingConfig: parsers (List<String>); parallelism changed from String to
Integer with null = auto-detect. empty() updated.
- UnifiedConfigLoader: reads detectors.categories/include (snake_case) with
camelCase aliases detectorCategories/detectorInclude (deprecated, per-load
WARN via existing pick() helper); reads indexing.parsers; parses parallelism
as Integer via requireIntOrNull.
- EnvVarOverlay: CODEIQ_DETECTORS_CATEGORIES, CODEIQ_DETECTORS_INCLUDE,
CODEIQ_INDEXING_PARSERS (CSV); CODEIQ_INDEXING_PARALLELISM now parses to
Integer and throws ConfigLoadException on malformed input.
- ConfigMerger: merges the three new leaves with full provenance tracking.
- ConfigValidator: indexing.parallelism must be > 0 if set (null = auto).
- ConfigDefaults.builtIn(): parallelism = null (auto), parsers = [],
detectors.categories = [], detectors.include = []. No behavior change on
the default path.
- ProjectConfigLoader.translateLegacyToUnified: maps the nested legacy shape
(detectors.categories, detectors.include, parsers map, pipeline.parallelism)
plus the flat top-level aliases detector_categories / detector_include into
the new unified fields. parsers map is flattened to its values (Analyzer
never consumed the per-language map at runtime).
- docs/codeiq.yml.example: documents parsers, detectors.categories, and
detectors.include; notes parallelism: null = auto.
Test coverage (+16 cases):
- UnifiedConfigLoaderTest: snake_case load, camelCase alias WARN, parallelism
as Integer, malformed parallelism throws, missing detectors section =
empty lists.
- EnvVarOverlayTest: CSV parsing for the three new vars, Integer parallelism,
malformed parallelism throws.
- ConfigMergerTest: layer-replacement for categories/include/parsers,
parallelism merge, provenance attribution.
- ConfigValidatorTest: parallelism > 0 rejection + null-is-valid (auto).
- ConfigDefaultsTest: baseline assertions for new defaults.
Full suite: 3275 -> 3291 tests, 0 failures, 31 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(analyzer): drop ProjectConfigLoader reload, read filters from CodeIqUnifiedConfig
Before: runWithCache/runBatchedWithCache/runAnalyzeBatched each called
ProjectConfigLoader.loadProjectConfig(root) and re-parsed .osscodeiq.yml
from disk to pull detector category/include filters, language filter,
exclude patterns, and pipeline.parallelism. The unified config bean has
already resolved these at startup (UnifiedConfigBeans.codeIqUnifiedConfig)
so the per-call file I/O is pure waste.
After: inject CodeIqUnifiedConfig into Analyzer and project the relevant
leaves through a small private PipelineFilters record (categories, include,
languages, exclude, parallelism). All three call sites now read filters
from the injected tree; no file I/O, no legacy POJO, no static loader.
Back-compat constructor (6-arg, used by 5 existing tests) preserved —
defaults the unified overlay to CodeIqUnifiedConfig.empty(), matching the
pre-Phase-B "no .osscodeiq.yml present" path (no filters, auto parallelism).
SmartIndexTest.setUp updated to the new 9-arg primary constructor with
CodeIqUnifiedConfig.empty() (no filter semantics — the test doesn't
exercise filters).
Full suite: 3291 tests, 0 failures, 31 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(cli): drop redundant ProjectConfigLoader reload in CliOutput
CliOutput.configureFromOptions called ProjectConfigLoader.loadIfPresent
to re-apply cache_dir / max_depth / max_radius from .osscodeiq.yml onto
the injected CodeIqConfig bean. Those fields are already resolved at
Spring startup by UnifiedConfigBeans.codeIqConfig (via ConfigResolver +
UnifiedConfigAdapter), so the re-read was pure duplication.
Removed the reload call. The `root` parameter became unused and was
dropped from the method signature; two callers (AnalyzeCommand,
IndexCommand) updated accordingly.
Full suite: 3291 tests, 0 failures, 31 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(test): port ProjectConfigLoaderApplyOverridesTest to unified config pipeline
The legacy static API (ProjectConfigLoader.loadIfPresent /
loadProjectConfig / parseProjectConfig) is being removed in the next
commit. This test file previously exercised those methods directly;
all cases are rewritten to drive the same behaviour through the
Phase-B canonical shim ProjectConfigLoader.loadFrom(Path), asserting
on the returned CodeIqUnifiedConfig (and the projected CodeIqConfig
via UnifiedConfigAdapter for legacy-POJO-shaped assertions).
Ported cases (11):
- legacy cache_dir/max_depth/max_radius flow through to CodeIqConfig.
- legacy languages/detectors.categories/detectors.include/exclude/parsers/
pipeline sections populate CodeIqUnifiedConfig.
- missing .osscodeiq.yml returns CodeIqUnifiedConfig.empty() with no
deprecation warning emitted.
- SafeConstructor rejects unsafe YAML tags without executing arbitrary
code (either returns a safe representation or throws
ConfigLoadException; no code execution is the invariant).
Dropped cases (3):
- nestedAnalysisSectionDoesNotCrash / nestedOutputSectionDoesNotCrash:
exercised dead branches inside the legacy applyOverrides that are
being deleted entirely.
- invalidMaxDepthFallsBackToDefault: the legacy applyOverrides
silently coerced non-numeric max_depth back to the default via its
toInt helper. The unified loader is deliberately strict — malformed
scalars throw ConfigLoadException with the field path. That behaviour
change is already covered by UnifiedConfigLoaderTest; preserving the
old lenient semantics would mask real misconfiguration.
Full suite: 3291 -> 3288 tests (-3 net), 0 failures, 31 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(test): delete ConfigDrivenPipelineTest (superseded by unified-pipeline tests)
ConfigDrivenPipelineTest exclusively exercised ProjectConfigLoader.parseProjectConfig(Map)
and .loadProjectConfig(Path) — the deprecated static legacy-POJO parsers being
deleted in the next commit. Every unique assertion has equivalent coverage on
the unified pipeline:
- languages/detectors.categories/detectors.include/exclude/parsers/pipeline map
parsing: covered by UnifiedConfigLoaderTest (loadsDetectorsCategoriesAndInclude,
loadsIndexingParsersList, loadsIndexingParallelismAsInteger, fullFileRoundTripsEveryField).
- legacy .osscodeiq.yml end-to-end with flat keys: covered by
ProjectConfigLoaderApplyOverridesTest (ported in the prior commit).
- empty/missing-file semantics: covered by
UnifiedConfigLoaderTest.missingFileProducesEmptyOverlay and
ProjectConfigLoaderApplyOverridesTest.missingConfigFileReturnsEmptyOverlay.
- ProjectConfig.empty() "no filters" assertion: equivalent to
CodeIqUnifiedConfig.empty() behavior pinned in ConfigDefaultsTest.
No unique coverage lost. Removing the file (not porting) keeps the test tree
clean — parseProjectConfig is a private implementation detail of the legacy
shim, not an API worth separate test coverage after migration.
Full suite: 3288 -> 3277 tests (-11), 0 failures, 31 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(config): delete legacy static ProjectConfigLoader API + orphaned ProjectConfig POJO
With Analyzer and CliOutput migrated off the legacy static API (prior two
commits) and the legacy-only tests rewritten against loadFrom(Path) (prior
two commits), the deprecated surface has no remaining callers.
Removed from ProjectConfigLoader:
- public static boolean loadIfPresent(Path, CodeIqConfig)
- public static ProjectConfig loadProjectConfig(Path)
- package-private static ProjectConfig parseProjectConfig(Map)
- private static applyOverrides / toInt helpers (only used by loadIfPresent)
- LEGACY_CONFIG_FILE_NAMES array (only used by the deleted statics; the
new surface only honors codeiq.yml and .osscodeiq.yml).
Inlined parseProjectConfig's logic directly into translateLegacyToUnified
so the legacy ProjectConfig POJO has no remaining reference. The
translator now reads languages/detectors/exclude/parsers/pipeline.* in
place from the raw YAML map, without the intermediate POJO.
Deleted:
- src/main/java/io/github/randomcodespace/iq/config/ProjectConfig.java
(orphaned after inlining)
Kept:
- ProjectConfigLoader#loadFrom(Path) — canonical Phase-B surface.
- ProjectConfigLoader.LoadResult — returned record.
- translateLegacyToUnified + readAndTranslateLegacy + countLegacyKeys —
internal helpers for the .osscodeiq.yml deprecation shim.
ProjectConfigLoaderTest trimmed: removed 5 tests that exclusively
exercised the deleted legacy-file-name (.code-iq.yml/.yaml) paths plus
the removed return-false-and-mutate-CodeIqConfig semantics. Ported 2
meaningful tests (empty-file handling, invalid-YAML resilience) onto
loadFrom(Path); those pin safety behaviour of the deprecation shim.
Full suite: 3277 -> 3272 tests (-5), 0 failures, 31 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 2292051 commit 65aac67
25 files changed
Lines changed: 612 additions & 824 deletions
File tree
- docs
- src
- main/java/io/github/randomcodespace/iq
- analyzer
- cli
- config
- unified
- test
- java/io/github/randomcodespace/iq
- analyzer
- config
- unified
- resources/config-unified
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
| 42 | + | |
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
| |||
92 | 93 | | |
93 | 94 | | |
94 | 95 | | |
| 96 | + | |
| 97 | + | |
95 | 98 | | |
96 | 99 | | |
97 | 100 | | |
| |||
Lines changed: 89 additions & 59 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
10 | | - | |
| 9 | + | |
11 | 10 | | |
12 | 11 | | |
13 | 12 | | |
| |||
88 | 87 | | |
89 | 88 | | |
90 | 89 | | |
| 90 | + | |
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
94 | 120 | | |
95 | 121 | | |
96 | 122 | | |
| |||
100 | 126 | | |
101 | 127 | | |
102 | 128 | | |
| 129 | + | |
103 | 130 | | |
104 | 131 | | |
105 | 132 | | |
| |||
109 | 136 | | |
110 | 137 | | |
111 | 138 | | |
| 139 | + | |
112 | 140 | | |
113 | 141 | | |
114 | 142 | | |
115 | 143 | | |
116 | | - | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
117 | 153 | | |
118 | 154 | | |
119 | 155 | | |
| |||
123 | 159 | | |
124 | 160 | | |
125 | 161 | | |
| 162 | + | |
126 | 163 | | |
127 | 164 | | |
128 | 165 | | |
| |||
188 | 225 | | |
189 | 226 | | |
190 | 227 | | |
191 | | - | |
192 | | - | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
193 | 231 | | |
194 | 232 | | |
195 | | - | |
196 | | - | |
197 | | - | |
198 | | - | |
199 | | - | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
200 | 237 | | |
201 | 238 | | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | | - | |
206 | | - | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
207 | 243 | | |
208 | 244 | | |
209 | | - | |
210 | | - | |
211 | | - | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
212 | 248 | | |
213 | 249 | | |
214 | 250 | | |
215 | 251 | | |
216 | 252 | | |
217 | 253 | | |
218 | 254 | | |
219 | | - | |
220 | | - | |
221 | | - | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
222 | 258 | | |
223 | 259 | | |
224 | 260 | | |
225 | | - | |
| 261 | + | |
226 | 262 | | |
227 | 263 | | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
232 | 267 | | |
233 | 268 | | |
234 | 269 | | |
235 | | - | |
| 270 | + | |
236 | 271 | | |
237 | 272 | | |
238 | 273 | | |
| |||
486 | 521 | | |
487 | 522 | | |
488 | 523 | | |
489 | | - | |
490 | | - | |
| 524 | + | |
| 525 | + | |
491 | 526 | | |
492 | 527 | | |
493 | | - | |
494 | | - | |
495 | | - | |
496 | | - | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
497 | 531 | | |
498 | | - | |
499 | | - | |
500 | | - | |
501 | | - | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
502 | 535 | | |
503 | | - | |
504 | | - | |
| 536 | + | |
| 537 | + | |
505 | 538 | | |
506 | 539 | | |
507 | 540 | | |
508 | 541 | | |
509 | 542 | | |
510 | 543 | | |
511 | 544 | | |
512 | | - | |
513 | | - | |
| 545 | + | |
| 546 | + | |
514 | 547 | | |
515 | 548 | | |
516 | 549 | | |
517 | | - | |
| 550 | + | |
518 | 551 | | |
519 | | - | |
520 | | - | |
521 | | - | |
| 552 | + | |
| 553 | + | |
522 | 554 | | |
523 | 555 | | |
524 | 556 | | |
525 | | - | |
| 557 | + | |
526 | 558 | | |
527 | 559 | | |
528 | 560 | | |
| |||
790 | 822 | | |
791 | 823 | | |
792 | 824 | | |
793 | | - | |
| 825 | + | |
794 | 826 | | |
795 | 827 | | |
796 | | - | |
797 | | - | |
798 | | - | |
| 828 | + | |
| 829 | + | |
799 | 830 | | |
800 | | - | |
801 | | - | |
802 | | - | |
| 831 | + | |
| 832 | + | |
803 | 833 | | |
804 | | - | |
805 | | - | |
| 834 | + | |
| 835 | + | |
806 | 836 | | |
807 | 837 | | |
808 | 838 | | |
809 | 839 | | |
810 | | - | |
811 | | - | |
| 840 | + | |
| 841 | + | |
812 | 842 | | |
813 | 843 | | |
814 | | - | |
| 844 | + | |
815 | 845 | | |
816 | | - | |
| 846 | + | |
817 | 847 | | |
818 | 848 | | |
819 | 849 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | | - | |
| 61 | + | |
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
| |||
Lines changed: 10 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
80 | 80 | | |
81 | 81 | | |
82 | 82 | | |
83 | | - | |
| 83 | + | |
84 | 84 | | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
85 | 93 | | |
86 | 94 | | |
87 | | - | |
88 | | - | |
| 95 | + | |
89 | 96 | | |
90 | 97 | | |
91 | 98 | | |
| |||
95 | 102 | | |
96 | 103 | | |
97 | 104 | | |
98 | | - | |
99 | 105 | | |
100 | 106 | | |
101 | 107 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
73 | | - | |
| 73 | + | |
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
| |||
0 commit comments