<!---
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

# Maven Build Cache Extension — Feature & Test Coverage

## Table of Contents

1. [Overview](#1-overview)
2. [Feature Catalog](#2-feature-catalog) (F1–F13, 79 features)
3. [Test Matrix](#3-test-matrix) (Group BASE + Groups A–Q)
4. [Required Test Coverage](#4-required-test-coverage) (master traceability table)
5. [Implementation Backlog](#5-implementation-backlog)
6. [Coverage Gaps & Recommendations](#6-coverage-gaps--recommendations)
7. [Appendix: Property Reference](#7-appendix-property-reference)

---

## 1. Overview

This document is the single reference for every Build Cache Extension feature and its
integration test. It covers all 21 `maven.build.cache.*` system properties, all XML
configuration options, and the correctness behaviors (cache key inputs, invalidation)
verified by the test suite.

### How to use this document

| Goal                                            | Where to look                   |
|-------------------------------------------------|---------------------------------|
| Find the test that covers a specific feature    | §2 Feature Catalog → §4 TC# row |
| Plan which tests to implement next              | §5 Implementation Backlog       |
| Look up a system property or its XML equivalent | §7 Appendix: Property Reference |

### Reference project set

The last wave of integration tests run against projects in `src/test/projects/reference-test-projects/`.
Each project covers exactly one Maven behavior dimension not covered by any other, so that
a test failure points unambiguously to the feature being exercised.

19 reference configurations are defined in `documentation/maven-test-projects-universe.md`:

| ID  | Name                 | Unique dimension(s)                                          |
|-----|----------------------|--------------------------------------------------------------|
| P01 | superpom-minimal     | Super POM defaults; simplest single-module baseline          |
| P02 | local-parent-inherit | Local reactor parent; full dependency/plugin inheritance     |
| P03 | remote-parent        | `<relativePath/>` empty → parent resolved from repository    |
| P04 | ci-friendly          | `${revision}` + flatten-maven-plugin; CI-friendly versions   |
| P05 | bom-single           | Single BOM import; no explicit parent                        |
| P06 | dep-edge-cases       | Multi-BOM mediation; system/optional/classifier; enforcer    |
| P07 | plugin-rebinding     | `maven-plugin` packaging; lifecycle rebinding; plugin deps   |
| P08 | profiles-all         | All profile activation types; all property sources           |
| P09 | repos-mirrors        | POM `<repositories>`; settings mirror; snapshot updatePolicy |
| P10 | reactor-partial      | Nested reactor; `-pl -am`; chained external parent           |
| P11 | reactor-parallel     | `-T N` concurrent execution; cache thread-safety             |
| P12 | core-ext-forked      | Core extension + `maven-invoker-plugin` forked child         |
| P13 | toolchains-jdk       | `toolchains.xml`; external JDK selection                     |
| P14 | distrib-deploy       | `<distributionManagement>`; snapshot/release deploy          |
| P15 | relocation           | Consuming a dependency that carries `<relocation>` metadata  |
| P16 | snapshot-reactor     | Reactor SNAPSHOT deps; SNAPSHOT external; snapshot policy    |
| P17 | war-webapp           | WAR lifecycle; `src/main/webapp`; profile-filtered resources |
| P18 | maven4-native        | `<subprojects>`; `<packaging>bom</packaging>`; Maven 4       |
| P19 | cache-lifecycle      | `skipValues` reconciliation; lifecycle escalation config     |

### Testing paradigm

**Parametrized base:** `CacheBaseBehaviorParametrizedTest` runs 7 core behaviors against all
17 eligible reference projects (P01–P12, P14–P17, P19), producing 119 test runs. This
verifies that fundamental cache behavior is project-agnostic. P13 requires toolchain JDK
installations; P18 requires a Maven 4 binary — both are conditionally skipped in the base suite.

**Feature-specific:** Tests tied to one Maven dimension target the most relevant reference
project directly — for example, WAR packaging tests use P17, parallel-build tests use P11.

**Two additional projects** outside the reference set cover behavior not representable by any
existing project: `shade-plugin-project` (TC-079) and `assembly-plugin-project` (TC-080).

### Cache Key Input Reference

The cache key for a module is derived from a hash of all Maven project inputs listed below.
A change to any of these inputs must produce a cache miss on the next build.
This reference drives the correctness test cases in Group Q and `CacheInvalidationProjectTraitsTest`.

#### Source & File Inputs

| Input                                  | How fingerprinted                          | Reference project |
|----------------------------------------|--------------------------------------------|-------------------|
| `src/main/java/**` content             | File hash of every `.java` file            | P01 (baseline)    |
| `src/test/java/**` content             | File hash of every test `.java` file       | P01 (baseline)    |
| `src/main/resources/**` content        | File hash of every resource file           | P01 (baseline)    |
| `src/main/webapp/**` content           | File hash of webapp assets (WAR packaging) | P17               |
| System-scope JAR file (`<systemPath>`) | Hash of the JAR bytes at the declared path | P01, P06          |

#### Project Descriptor (POM) Inputs

| Input                                            | How fingerprinted                                    | Reference project |
|--------------------------------------------------|------------------------------------------------------|-------------------|
| Effective POM content (semantics)                | Canonical effective-POM hash (whitespace-normalised) | P01–P18           |
| Inline dependency coordinates + versions         | Part of effective POM                                | P01, P07–P09      |
| Parent-managed dependency versions               | Propagated into child effective POM                  | P02, P10          |
| BOM-managed dependency versions (single BOM)     | Resolved version in effective POM                    | P05               |
| BOM-managed versions (multi-BOM mediation order) | First-wins resolution in effective POM               | P06               |
| Exclusion declarations                           | Change resolved transitive classpath (effective POM) | P06               |
| Optional flag on a dependency                    | Changes dep propagation visible in effective POM     | P06               |
| Classifier qualifier on a dependency             | Changes resolved artifact coordinate                 | P06               |
| Plugin version (inline or managed)               | Part of effective POM plugin config                  | P01, P02          |
| Plugin configuration parameters                  | Tracked params contribute to key                     | P07               |
| Plugin phase rebinding (`<phase>`)               | Changes effective lifecycle map                      | P07               |
| Plugin classpath `<dependencies>`                | Changes what's on compiler/plugin classpath          | P07               |

#### Inheritance Chain Inputs

| Input                                               | How fingerprinted                             | Reference project |
|-----------------------------------------------------|-----------------------------------------------|-------------------|
| Local parent POM (managed deps/plugins/props)       | Resolved into child effective POM             | P02               |
| Remote parent POM version (empty `<relativePath/>`) | Fetched parent merged into effective POM      | P03               |
| External parent (chained `<relativePath/>` empty)   | Corp-parent config flows into all descendants | P10               |

#### Profile & Property Sources

| Input                                                 | How fingerprinted                                                  | Reference project |
|-------------------------------------------------------|--------------------------------------------------------------------|-------------------|
| POM `<properties>` values                             | Resolved into effective POM                                        | P01–P18           |
| Profile-injected properties (when profile is active)  | Effective POM includes active-profile contributions                | P08               |
| Profile activation: property trigger (`-Denv=ci`)     | Different active profiles → different effective POM                | P08               |
| Profile activation: file-existence trigger            | Presence/absence of `trigger.properties` → different effective POM | P08               |
| Profile activation: JDK range                         | Active on matching JDK → different effective POM                   | P08               |
| Profile activation: OS family                         | Active on matching OS → different effective POM                    | P08               |
| `activeByDefault` reset                               | Resets when any other profile activates                            | P08               |
| `settings.xml` profile properties                     | Contributes to effective POM via active settings profile           | P08, P09          |
| CLI `-D` system properties                            | Override all property sources; change effective POM                | P04, P08          |
| CI-friendly `${revision}`, `${sha1}`, `${changelist}` | Part of project version and POM properties                         | P04               |
| Environment variables `${env.*}`                      | Referenced in POM properties                                       | P08               |

#### Multi-Module Reactor Inputs

| Input                                            | How fingerprinted                                       | Reference project |
|--------------------------------------------------|---------------------------------------------------------|-------------------|
| Upstream module output (inter-module dependency) | Downstream receives new artifact → different input hash | P02, P10, P11     |
| Reactor SNAPSHOT module source change            | Same as upstream module output; no remote resolution    | P16               |
| External SNAPSHOT dependency content             | Remotely resolved artifact; `updatePolicy=always`       | P16               |

#### Packaging & Lifecycle

| Input                                       | How fingerprinted                           | Reference project |
|---------------------------------------------|---------------------------------------------|-------------------|
| `<packaging>jar</packaging>`                | Standard JAR lifecycle default bindings     | P01               |
| `<packaging>war</packaging>`                | WAR lifecycle bindings; webapp dir included | P17               |
| `<packaging>maven-plugin</packaging>`       | Custom lifecycle; descriptor + JAR          | P07               |
| `<packaging>pom</packaging>` BOM aggregator | No compiled sources; POM artifact           | P02, P05, P10     |

---

## 2. Feature Catalog

### Test status legend

| Symbol | Meaning                                                            |
|--------|--------------------------------------------------------------------|
| ✅      | Integration test exists and covers this behavior                   |
| ⚠️     | Partially covered (related test but does not directly assert this) |
| ❌      | No integration test — gap                                          |

---

### F1 Core Enablement

| ID   | Feature                                       | XML / System Property                       | Status | Test Reference                                                             |
|------|-----------------------------------------------|---------------------------------------------|--------|----------------------------------------------------------------------------|
| F1.1 | Build extension via POM `<build><extensions>` | `pom.xml <extensions>`                      | ✅      | `BuildExtensionTest`                                                       |
| F1.2 | Core extension via `.mvn/extensions.xml`      | `.mvn/extensions.xml`                       | ✅      | `CoreExtensionTest`                                                        |
| F1.3 | Global enable/disable (XML or CLI)            | `<enabled>` / `-Dmaven.build.cache.enabled` | ✅      | `BuildExtensionTest`, `SkipBuildExtensionTest.cacheDisabledViaCommandLine` |
| F1.4 | Config path override                          | `-Dmaven.build.cache.configPath`            | ✅      | `config/CustomConfigPathTest`                                              |
| F1.5 | Defaults-only mode (no XML file present)      | implicit                                    | ✅      | `config/NoConfigFileDefaultsTest`                                          |
| F1.6 | Maven version guard (requires ≥ 3.9.0)        | `CacheConfigImpl.initialize()`              | ❌      | —                                                                          |
| F1.7 | XML config validation                         | `<validateXml>`                             | ❌      | —                                                                          |
| F1.8 | Malformed XML → descriptive startup error     | implicit                                    | ✅      | `config/InvalidConfigXmlTest`                                              |

---

### F2 Input Fingerprinting

| ID    | Feature                                               | XML / System Property                                       | Status | Test Reference                                                    |
|-------|-------------------------------------------------------|-------------------------------------------------------------|--------|-------------------------------------------------------------------|
| F2.1  | Global glob pattern                                   | `<input><global><glob>` / `maven.build.cache.input.glob`    | ✅      | `IncludeExcludeTest`                                              |
| F2.2  | Global include paths                                  | `<input><global><includes>` / `maven.build.cache.input`     | ✅      | `IncludeExcludeTest`                                              |
| F2.3  | Global exclude paths                                  | `<input><global><excludes>` / `maven.build.cache.exclude.*` | ✅      | `IncludeExcludeTest`                                              |
| F2.4  | Source file added → cache miss                        | implicit                                                    | ✅      | `checksumcorrectness/AddedSourceFileInvalidatesCacheTest`         |
| F2.5  | Source file deleted → cache miss                      | implicit                                                    | ✅      | `checksumcorrectness/DeletedSourceFileInvalidatesCacheTest`       |
| F2.6  | Source file modified → cache miss                     | implicit                                                    | ✅      | `checksumcorrectness/SourceChangeInvalidatesCacheTest`            |
| F2.7  | POM functional change → cache miss                    | implicit                                                    | ✅      | `checksumcorrectness/PomChangeInvalidatesCacheTest`               |
| F2.8  | POM whitespace-only change → cache hit                | implicit                                                    | ✅      | `checksumcorrectness/WhitespaceOnlyPomChangeNoCacheMissTest`      |
| F2.9  | Property change → cache miss                          | `<properties>`                                              | ✅      | `checksumcorrectness/PropertyChangeInvalidatesCacheTest`          |
| F2.10 | Resource file change → cache miss                     | `src/main/resources`                                        | ✅      | `checksumcorrectness/ResourceChangeInvalidatesCacheTest`          |
| F2.11 | Test source change → cache miss                       | `src/test/java`                                             | ✅      | `checksumcorrectness/TestSourceChangeInvalidatesCacheTest`        |
| F2.12 | Dependency version change → cache miss                | effective POM                                               | ✅      | `checksumcorrectness/DependencyVersionChangeInvalidatesCacheTest` |
| F2.13 | Per-plugin `dirScan` configuration                    | `<input><plugins><plugin><dirScan>`                         | ❌      | —                                                                 |
| F2.14 | Per-execution `dirScan` override                      | `<input><plugins><plugin><executions>`                      | ❌      | —                                                                 |
| F2.15 | Effective POM property exclusion per plugin           | `<plugin><effectivePom><excludeProperties>`                 | ✅      | `inputfiltering/EffectivePomExcludePropertyTest`                  |
| F2.16 | Plugin dependency exclusion from fingerprint          | `<plugin><excludeDependencies>`                             | ❌      | —                                                                 |
| F2.17 | `processPlugins` flag                                 | `maven.build.cache.processPlugins`                          | ✅      | `inputfiltering/ProcessPluginsDisabledTest`                       |
| F2.18 | Project-level glob override (POM property)            | `maven.build.cache.input.glob` in `<properties>`            | ✅      | `inputfiltering/PerProjectGlobOverrideTest`                       |
| F2.19 | Project-level additional include (POM property)       | `maven.build.cache.input.*` in `<properties>`               | ✅      | `inputfiltering/ProjectLevelIncludeTest`                          |
| F2.20 | Project-level exclude (POM property)                  | `maven.build.cache.exclude.*` in `<properties>`             | ❌      | —                                                                 |
| F2.21 | Profile activation changes effective POM → cache miss | `-P profile`                                                | ✅      | `inputfiltering/ProfileCliActivationInvalidatesTest`              |
| F2.22 | Hidden files excluded automatically                   | implicit                                                    | ❌      | —                                                                 |

---

### F3 Hash Algorithms

| ID   | Feature                                                                        | XML / System Property              | Status | Test Reference                                            |
|------|--------------------------------------------------------------------------------|------------------------------------|--------|-----------------------------------------------------------|
| F3.1 | Default algorithm: XX (XXHash64)                                               | `<hashAlgorithm>XX`                | ✅      | (all existing ITs)                                        |
| F3.2 | All non-MM algorithms round-trip (SHA-1, SHA-256, SHA-384, SHA-512, METRO, XX) | `<hashAlgorithm>SHA-1\|SHA-256\|…` | ✅      | `hashalgorithm/HashAlgorithmRoundTripTest` (parametrized) |
| F3.3 | XXMM (memory-mapped, needs `--add-opens`)                                      | `<hashAlgorithm>XXMM`              | ❌      | —                                                         |
| F3.4 | METRO+MM (memory-mapped, needs `--add-opens`)                                  | `<hashAlgorithm>METRO+MM`          | ❌      | —                                                         |
| F3.5 | Invalid algorithm → startup failure                                            | `<hashAlgorithm>BOGUS`             | ✅      | `hashalgorithm/InvalidHashAlgorithmTest`                  |
| F3.6 | Algorithm change between builds → cache miss                                   | config change                      | ✅      | `hashalgorithm/HashAlgorithmChangeCacheMissTest`          |

---

### F4 Execution Control

| ID    | Feature                                    | XML / System Property                       | Status | Test Reference                                             |
|-------|--------------------------------------------|---------------------------------------------|--------|------------------------------------------------------------|
| F4.1  | `runAlways` by plugin coordinates          | `<executionControl><runAlways><plugins>`    | ✅      | `pluginexecution/RunAlwaysPluginTest`                      |
| F4.2  | `runAlways` by goal name                   | `<executionControl><runAlways><goalsLists>` | ✅      | `pluginexecution/RunAlwaysByGoalTest`                      |
| F4.3  | `runAlways` by execution ID                | `<executionControl><runAlways><executions>` | ✅      | `pluginexecution/RunAlwaysByExecutionIdTest`               |
| F4.4  | `alwaysRunPlugins` CLI property            | `-Dmaven.build.cache.alwaysRunPlugins`      | ✅      | `pluginexecution/AlwaysRunPluginsCliTest`                  |
| F4.5  | `ignoreMissing` — skip absent executions   | `<executionControl><ignoreMissing>`         | ✅      | `pluginexecution/IgnoreMissingPluginTest`                  |
| F4.6  | Reconcile: `skipValue` allows cache hit    | `<property skipValue="…">`                  | ✅      | `pluginexecution/TrackedPropertySkipValueAllowsReuseTest`  |
| F4.7  | Reconcile: mismatch → cache miss           | `<reconcile>…<property>`                    | ✅      | `pluginexecution/TrackedPropertyMismatchCacheMissTest`     |
| F4.8  | Reconcile: match → cache hit               | `<reconcile>…<property>`                    | ✅      | `pluginexecution/TrackedPropertyMatchCacheHitTest`         |
| F4.9  | Reconcile: `defaultValue` used when absent | `<property defaultValue="…">`               | ✅      | `pluginexecution/TrackedPropertyDefaultValueTest`          |
| F4.10 | Reconcile: `logAll` flag on goal           | `<reconcile><plugin logAll="true">`         | ✅      | `pluginexecution/LogAllPropertiesTest`                     |
| F4.11 | Reconcile: `nolog` suppresses property     | `<property nolog="true">`                   | ✅      | `pluginexecution/TrackedPropertyNologTest`                 |
| F4.12 | `logAllProperties` global flag             | `<reconcile><logAllProperties>`             | ✅      | `pluginexecution/LogAllPropertiesGlobalTest`               |
| F4.13 | Forked execution tracked correctly         | implicit                                    | ✅      | `ForkedExecutionsTest`, `ForkedExecutionCoreExtensionTest` |
| F4.14 | Duplicate goal executions within one build | implicit                                    | ✅      | `DuplicateGoalsTest`                                       |
| F4.15 | Missing cached execution → full rebuild    | `Build.getMissingExecutions()`              | ✅      | `pluginexecution/MissingExecutionTriggerRebuildTest`       |

---

### F5 Artifact Restore

| ID   | Feature                                         | XML / System Property                         | Status | Test Reference                               |
|------|-------------------------------------------------|-----------------------------------------------|--------|----------------------------------------------|
| F5.1 | Standard artifact restore (JAR → local repo)    | implicit                                      | ✅      | `BuildExtensionTest.simple`                  |
| F5.2 | Classified artifact restore (sources, javadoc)  | implicit                                      | ✅      | `IncrementalRestoreTest`                     |
| F5.3 | `lazyRestore` — defer remote download           | `-Dmaven.build.cache.lazyRestore`             | ✅      | `IncrementalRestoreTest`                     |
| F5.4 | `restoreGeneratedSources=false`                 | `-Dmaven.build.cache.restoreGeneratedSources` | ✅      | `artifacts/RestoreGeneratedSourcesFalseTest` |
| F5.5 | `restoreOnDiskArtifacts=false`                  | `-Dmaven.build.cache.restoreOnDiskArtifacts`  | ✅      | `artifacts/RestoreOnDiskArtifactsFalseTest`  |
| F5.6 | Corrupted/truncated ZIP handled gracefully      | implicit                                      | ✅      | `failurerecovery/CorruptedZipCacheEntryTest` |
| F5.7 | NORMALIZED_VERSION → SNAPSHOT bump is cache hit | `calculateProjectVersionChecksum=false`       | ✅      | `versioning/SnapshotVersionBumpCacheHitTest` |

---

### F6 Output Management

| ID   | Feature                                          | XML / System Property                       | Status | Test Reference                                                |
|------|--------------------------------------------------|---------------------------------------------|--------|---------------------------------------------------------------|
| F6.1 | Primary artifact stored/restored                 | implicit                                    | ✅      | `BuildExtensionTest.simple`                                   |
| F6.2 | `attachedOutputs` — additional directories       | `<attachedOutputs><dirName glob="…">`       | ✅      | `IncrementalRestoreTest` (extra-resources/, other-resources/) |
| F6.3 | `preservePermissions` — POSIX permissions        | `<attachedOutputs preservePermissions="…">` | ✅      | `output/PermissionsPreservationTest`                          |
| F6.4 | Output exclude patterns (regex)                  | `<output><exclude><patterns>`               | ✅      | `output/OutputExcludePatternTest`                             |
| F6.5 | `maxBuildsCached` LRU eviction                   | `<local><maxBuildsCached>`                  | ✅      | `output/MaxLocalBuildsCachedTest`                             |
| F6.6 | Custom local cache location                      | `-Dmaven.build.cache.location`              | ✅      | `BuildExtensionTest.skipSaving`                               |
| F6.7 | Stale artifacts in `target/` not leaked to cache | `stagePreExistingArtifacts` internal        | ✅      | `internal/StagingRemovesStaleClassesTest`                     |

---

### F7 Remote Cache

| ID   | Feature                                      | XML / System Property                                                 | Status | Test Reference                         |
|------|----------------------------------------------|-----------------------------------------------------------------------|--------|----------------------------------------|
| F7.1 | Remote cache read                            | `<remote><url>` / `-Dmaven.build.cache.remote.url`                    | ✅      | `RemoteCacheDavTest`                   |
| F7.2 | Remote cache enable/disable                  | `<remote enabled="…">` / `-Dmaven.build.cache.remote.enabled`         | ✅      | `RemoteCacheDavTest`                   |
| F7.3 | Remote save (push)                           | `<remote><save><enabled>` / `-Dmaven.build.cache.remote.save.enabled` | ✅      | `RemoteCacheDavTest`                   |
| F7.4 | `save.final` — prohibit overwrite            | `-Dmaven.build.cache.remote.save.final`                               | ✅      | `remote/SaveFinalRemoteTest`           |
| F7.5 | Server authentication via settings.xml       | `<remote id="…">` / `-Dmaven.build.cache.remote.server.id`            | ✅      | `RemoteCacheDavTest`                   |
| F7.6 | Remote unavailable → graceful local fallback | implicit                                                              | ✅      | `remote/RemoteUnavailableFallbackTest` |
| F7.7 | `failFast` on remote restore failure         | `-Dmaven.build.cache.failFast`                                        | ✅      | `admin/FailFastTest`                   |
| F7.8 | `baselineUrl` diff report                    | `-Dmaven.build.cache.baselineUrl`                                     | ✅      | `remote/BaselineDiffTest`              |

---

### F8 Multi-Module / Reactor

| ID   | Feature                                                 | XML / System Property                           | Status | Test Reference                                                          |
|------|---------------------------------------------------------|-------------------------------------------------|--------|-------------------------------------------------------------------------|
| F8.1 | Full reactor — each module independently cached                      | implicit                                        | ✅      | `Issue21Test`, `UpstreamModuleChangeDownstreamMissTest`                 |
| F8.2 | Partial reactor (`-pl`) — targeted modules cached                    | implicit `-pl`                                  | ✅      | `multimodule/MultiModulePartialBuildTest`                               |
| F8.3 | Partial reactor with upstream restore (`-pl -am`)                    | implicit `-pl -am`                              | ✅      | `multimodule/MultiModulePartialWithAmTest`                              |
| F8.4 | Parallel builds (`-T`) — no cross-thread corruption                  | implicit `-T`                                   | ✅      | `multimodule/ParallelBuildTest`                                         |
| F8.5 | `scanProfiles` — include active profiles in cache key                | `<multiModule><scanProfiles>`                   | ✅      | `multimodule/ScanProfilesTest`                                          |
| F8.6 | Per-module `skipCache` / `skipSave` / `enabled` override via POM     | `maven.build.cache.skipCache` / `.enabled`      | ✅      | `PerModuleFlagsTest`                                                    |
| F8.7 | Subtree build of leaf module — cache hit via `rootDirectory` anchor     | implicit (`.mvn/` traversal)                    | ✅      | `multimodule/SubtreeBuildCacheHitTest#subtreeBuildHitsCacheAfterFullReactorBuild`                          |
| F8.8 | Partial reactor with upstream dep — `-am` puts B in `session.getProjects()` so checksum matches; no discovery config | implicit `-pl -am`                              | ✅      | `multimodule/SubtreeBuildCacheHitTest#partialReactorWithAmHitsCacheWithoutDiscovery`                       |
| F8.9 | Subtree build with upstream dep + `<discovery><scanProfiles>` — full re-scan from root activates profile, discovers B with matching effective model | `<multiModule><discovery><scanProfiles>`         | ✅      | `multimodule/SubtreeBuildCacheHitTest#subtreeWithDiscoveryAndScanProfileHitsCacheAfterFullReactorBuild`    |

---

### F9 Lifecycle Phases

| ID   | Feature                                                 | XML / System Property                                     | Status | Test Reference                                                         |
|------|---------------------------------------------------------|-----------------------------------------------------------|--------|------------------------------------------------------------------------|
| F9.1 | `compile` phase cached and restored                     | implicit                                                  | ✅      | `lifecyclephases/CompilePhaseDefaultCachedTest`                        |
| F9.2 | `test-compile` phase cached                             | implicit                                                  | ✅      | `lifecyclephases/TestCompilePhaseTest`                                 |
| F9.3 | `package` phase cached                                  | implicit                                                  | ✅      | `lifecyclephases/CompileThenPackageEscalationTest`                     |
| F9.4 | `install` phase cached                                  | implicit                                                  | ✅      | `lifecyclephases/InstallPhaseTest`                                     |
| F9.5 | Phase escalation → prior phase restored, new phase runs | implicit                                                  | ✅      | `CompileThenPackageEscalationTest`, `PackageThenInstallEscalationTest` |
| F9.6 | `clean`-only run → cache bypassed entirely              | implicit                                                  | ✅      | `SkipBuildExtensionTest.simple`                                        |
| F9.7 | `clean verify` → clean runs first, then cache           | implicit                                                  | ✅      | `lifecyclephases/CleanVerifyTest`                                      |
| F9.8 | `mandatoryClean` blocks save without prior clean        | `<mandatoryClean>` / `-Dmaven.build.cache.mandatoryClean` | ✅      | `MandatoryCleanTest`                                                   |
| F9.9 | `verify` phase (with integration tests) cached          | implicit                                                  | ✅      | `BuildExtensionTest.simple`                                           |
| F9.10 | Single goal mapped to a phase cached (e.g. `compiler:compile`) | `-Dmaven.build.cache.cacheSingleGoal`              | ✅      | `singlegoal/CompileGoalCachedTest`                                    |
| F9.11 | Single-goal entry escalates to/from a phase build without error | implicit                                          | ✅      | `singlegoal/CompileGoalThenPackageEscalationTest`, `singlegoal/PackageThenCompileGoalTest` |
| F9.12 | `cacheSingleGoal=false` → single goal bypasses cache    | `-Dmaven.build.cache.cacheSingleGoal`                     | ✅      | `singlegoal/SingleGoalDisabledTest`                                   |
| F9.13 | Forked lifecycle of a CLI goal restores from cache (never saves) | `-Dmaven.build.cache.restoreForkedExecutions`    | ✅      | `singlegoal/ForkedLifecycleRestoreTest`, `singlegoal/ForkedRestoreDisabledTest`, `singlegoal/RunGoalNotCachedTest` |

---

### F10 Admin Controls

| ID    | Feature                                      | XML / System Property                | Status | Test Reference                                |
|-------|----------------------------------------------|--------------------------------------|--------|-----------------------------------------------|
| F10.1 | `skipCache` — force rebuild, still writes    | `-Dmaven.build.cache.skipCache`      | ✅      | `PerModuleFlagsTest`                          |
| F10.2 | `skipSave` — read-only cache usage           | `-Dmaven.build.cache.skipSave`       | ✅      | `BuildExtensionTest.skipSaving`               |
| F10.3 | `failFast` — abort on restore failure        | `-Dmaven.build.cache.failFast`       | ✅      | `admin/FailFastTest`                          |
| F10.4 | `mandatoryClean` — require clean before save | `-Dmaven.build.cache.mandatoryClean` | ✅      | `MandatoryCleanTest`                          |
| F10.5 | Mid-build failure → no partial cache entry   | implicit                             | ✅      | `failurerecovery/BuildFailsMidwayNoCacheTest` |
| F10.6 | `maxBuildsCached` LRU eviction               | `<local><maxBuildsCached>`           | ✅      | `output/MaxLocalBuildsCachedTest`             |

---

### F11 Configuration Injection

| ID    | Feature                                | Mechanism                              | Status | Test Reference                                            |
|-------|----------------------------------------|----------------------------------------|--------|-----------------------------------------------------------|
| F11.1 | XML file at default path               | `.mvn/maven-build-cache-config.xml`    | ✅      | all standard ITs                                          |
| F11.2 | XML file at custom path                | `-Dmaven.build.cache.configPath`       | ✅      | `config/CustomConfigPathTest`                             |
| F11.3 | CLI `-D` system property overrides XML | `-D<property>`                         | ✅      | `BuildExtensionTest.skipSaving`, `SkipBuildExtensionTest` |
| F11.4 | POM `<properties>` per-module override | `<properties>`                         | ✅      | `PerModuleFlagsTest`                                      |
| F11.5 | No XML file → built-in defaults active | implicit                               | ✅      | `config/NoConfigFileDefaultsTest`                         |
| F11.6 | `alwaysRunPlugins` CLI comma-list      | `-Dmaven.build.cache.alwaysRunPlugins` | ✅      | `pluginexecution/AlwaysRunPluginsCliTest`                 |

---

### F12 Project Versioning

| ID    | Feature                                       | XML / System Property                                  | Status | Test Reference                                       |
|-------|-----------------------------------------------|--------------------------------------------------------|--------|------------------------------------------------------|
| F12.1 | `adjustMetaInf` — normalize MANIFEST.MF       | `<projectVersioning><adjustMetaInf>`                   | ✅      | `versioning/MetaInfVersionAdjustmentTest`            |
| F12.2 | `calculateProjectVersionChecksum`             | `<projectVersioning><calculateProjectVersionChecksum>` | ✅      | `versioning/SnapshotVersionBumpWithChecksumFlagTest` |
| F12.3 | NORMALIZED_VERSION: SNAPSHOT bump → cache hit | implicit (default)                                     | ✅      | `versioning/SnapshotVersionBumpCacheHitTest`         |
| F12.4 | CI-friendly `${revision}` version stability   | flatten-maven-plugin pattern                           | ✅      | `versioning/CIFriendlyRevisionVersionTest`           |

---

### F13 Diagnostics

| ID    | Feature                                             | XML / System Property                 | Status | Test Reference                               |
|-------|-----------------------------------------------------|---------------------------------------|--------|----------------------------------------------|
| F13.1 | Per-goal `logAll` flag                              | `<reconcile><plugin logAll="true">`   | ✅      | `pluginexecution/LogAllPropertiesTest`       |
| F13.2 | `logAllProperties` global flag                      | `<reconcile><logAllProperties>`       | ✅      | `pluginexecution/LogAllPropertiesGlobalTest` |
| F13.3 | `buildinfo.xml` FileHash debug                      | `<debugs><debug>FileHash</debug>`     | ✅      | `reports/BuildInfoXmlDebugTest`              |
| F13.4 | `buildinfo.xml` EffectivePom debug                  | `<debugs><debug>EffectivePom</debug>` | ❌      | —                                            |
| F13.5 | `build-cache-report.xml` generated per build        | implicit                              | ✅      | `reports/CacheReportGeneratedTest`           |
| F13.6 | `buildsdiff.xml` generated with baselineUrl         | `-Dmaven.build.cache.baselineUrl`     | ✅      | `remote/BaselineDiffTest`                    |
| F13.7 | CacheSource field (LOCAL/REMOTE/BUILD) in buildinfo | `Build.source`                        | ✅      | `internal/CacheSourceTrackingTest`           |

---

## 3. Test Matrix

Each row defines a distinct, independently executable integration test targeting one primary
behavior. The matrix is **orthogonal**: every behavior appears in one primary row only.

The "Reference Project" column shows:

- `PARAM P01-P19` — parametrized test running against all eligible reference projects
- `P<n>` — specific reference project from `src/test/projects/reference-test-projects/`
- `legacy: <name>` — existing non-reference test project (pre-v3)
- `new: <name>` — a new project not in the reference set (2 cases only)

---

### Group BASE: Parametrized Cross-Project Base Tests

**Test class:** `CacheBaseBehaviorParametrizedTest` ✅ (implemented)
**Reference projects:** P01–P12, P14–P17, P19 (17 projects)
**Conditional:** P13 — skipped when toolchain JDK installations are not configured
**Maven 4 only:** P18 — included when running against Maven 4

Each BASE scenario runs as a `@ParameterizedTest(@MethodSource("allReferenceProjects"))`.
For multi-module projects the test targets the first leaf module.
This class provides **119 test runs** (17 projects × 7 scenarios) validating that core
cache behaviors are project-agnostic.

| ID      | Scenario                                             | Features         | Status |
|---------|------------------------------------------------------|------------------|--------|
| BASE-01 | First build completes; identical second build is hit | F1.1, F1.2, F5.1 | ✅      |
| BASE-02 | Source file modification → cache miss                | F2.6             | ✅      |
| BASE-03 | POM property value change → cache miss               | F2.9             | ✅      |
| BASE-04 | `enabled=false` CLI → build runs, cache bypassed     | F1.3             | ✅      |
| BASE-05 | `skipCache=true` → rebuild occurs; cache written     | F10.1            | ✅      |
| BASE-06 | `skipSave=true` → cache hit; no new write            | F10.2            | ✅      |
| BASE-07 | Compile→Package phase escalation → rebuild           | F9.5             | ✅      |

---

### Group A: Core Checksum Correctness

| ID   | Scenario                                                    | Features         | Reference Project              | Status                                                                                   |
|------|-------------------------------------------------------------|------------------|--------------------------------|------------------------------------------------------------------------------------------|
| A-01 | Build extension: hit/miss cycle                             | F1.1, F5.1, F6.1 | legacy: `build-extension`      | ✅ `BuildExtensionTest.simple`                                                            |
| A-02 | Core extension: hit/miss cycle                              | F1.2, F5.1       | PARAM P01-P19                  | ✅ `CoreExtensionTest` + BASE-01                                                          |
| A-03 | Source file added → miss                                    | F2.4             | legacy: `checksum-correctness` | ✅ `AddedSourceFileInvalidatesCacheTest`                                                  |
| A-04 | Source file deleted → miss                                  | F2.5             | legacy: `checksum-correctness` | ✅ `DeletedSourceFileInvalidatesCacheTest`                                                |
| A-05 | Source file modified → miss                                 | F2.6             | PARAM P01-P19                  | ✅ `SourceChangeInvalidatesCacheTest` + BASE-02                                           |
| A-06 | POM functional change → miss                                | F2.7             | legacy: `checksum-correctness` | ✅ `PomChangeInvalidatesCacheTest`                                                        |
| A-07 | POM whitespace-only → hit                                   | F2.8             | legacy: `checksum-correctness` | ✅ `WhitespaceOnlyPomChangeNoCacheMissTest`                                               |
| A-08 | Resource file change → miss                                 | F2.10            | legacy: `checksum-correctness` | ✅ `ResourceChangeInvalidatesCacheTest`                                                   |
| A-09 | Test source change → miss                                   | F2.11            | legacy: `checksum-correctness` | ✅ `TestSourceChangeInvalidatesCacheTest`                                                 |
| A-10 | Property change → miss                                      | F2.9             | PARAM P01-P19                  | ✅ `PropertyChangeInvalidatesCacheTest` + BASE-03                                         |
| A-11 | Dependency version change → miss                            | F2.12            | **P01**                        | ✅ `checksumcorrectness/DependencyVersionChangeInvalidatesCacheTest`                      |
| A-12 | System-scope JAR content change → miss                      | F2.9             | **P01**                        | ✅ `CacheInvalidationProjectTraitsTest.systemScopeJarContentChangeInvalidates`            |
| A-13 | Parent property bump propagates to declared dep → miss      | F2.12            | **P02**                        | ✅ `CacheInvalidationProjectTraitsTest.parentPropertyChangeInvalidates`                   |
| A-14 | BOM-managed unused dep version change → no miss (cache hit) | F2.12/BOM        | **P06**                        | ✅ `CacheInvalidationProjectTraitsTest.bomManagedUnusedDepVersionChangeDoesNotInvalidate` |

### Group B: Input Filtering

| ID   | Scenario                                                   | Features  | Reference Project         | Status                                                 |
|------|------------------------------------------------------------|-----------|---------------------------|--------------------------------------------------------|
| B-01 | Global include/exclude/glob                                | F2.1–F2.3 | legacy: `include-exclude` | ✅ `IncludeExcludeTest`                                 |
| B-02 | Project-level glob override via POM property               | F2.18     | **P02**                   | ✅ `inputfiltering/PerProjectGlobOverrideTest`          |
| B-03 | Project-level include via POM property                     | F2.19     | **P02**                   | ✅ `inputfiltering/ProjectLevelIncludeTest`             |
| B-04 | `processPlugins=false` skips param introspection           | F2.17     | **P01**                   | ✅ `inputfiltering/ProcessPluginsDisabledTest`          |
| B-05 | Per-plugin dirScan limits scanned paths                    | F2.13     | **P19**                   | ❌ `PerPluginDirScanTest`                               |
| B-06 | Effective POM property exclusion per plugin                | F2.15     | **P19**                   | ✅ `inputfiltering/EffectivePomExcludePropertyTest`     |
| B-07 | Profile activation changes effective POM → miss            | F2.21     | **P08**                   | ✅ `inputfiltering/ProfileCliActivationInvalidatesTest` |
| B-08 | OS env-var profile activation changes effective POM → miss | F2.21     | **P08**                   | ✅ `inputfiltering/EnvVariableChangeInvalidatesTest`    |

### Group C: Lifecycle Phases & Escalation

| ID   | Scenario                                 | Features   | Reference Project          | Status                                         |
|------|------------------------------------------|------------|----------------------------|------------------------------------------------|
| C-01 | Compile phase cached                     | F9.1       | legacy: `lifecycle-phases` | ✅ `CompilePhaseDefaultCachedTest`              |
| C-02 | Test-compile phase cached                | F9.2       | legacy: `lifecycle-phases` | ✅ `TestCompilePhaseTest`                       |
| C-03 | Compile→Package escalation → rebuild     | F9.3, F9.5 | PARAM P01-P19              | ✅ `CompileThenPackageEscalationTest` + BASE-07 |
| C-04 | Package→Install escalation → rebuild     | F9.4, F9.5 | legacy: `lifecycle-phases` | ✅ `PackageThenInstallEscalationTest`           |
| C-05 | Install phase: artifact in local repo    | F9.4       | legacy: `lifecycle-phases` | ✅ `InstallPhaseTest`                           |
| C-06 | Clean-only run → cache bypassed          | F9.6       | PARAM P01-P19              | ✅ `SkipBuildExtensionTest.simple`              |
| C-07 | `clean verify` — clean then cached build | F9.7       | PARAM P01-P19              | ✅ `lifecyclephases/CleanVerifyTest`            |
| C-08 | Single goal `compiler:compile` cached    | F9.10      | legacy: `lifecycle-phases` | ✅ `singlegoal/CompileGoalCachedTest`           |
| C-09 | Single-goal ↔ phase escalation (both directions) | F9.11 | legacy: `lifecycle-phases` | ✅ `singlegoal/CompileGoalThenPackageEscalationTest`, `singlegoal/PackageThenCompileGoalTest` |
| C-10 | `cacheSingleGoal=false` → goal bypasses cache | F9.12 | legacy: `lifecycle-phases` | ✅ `singlegoal/SingleGoalDisabledTest`          |
| C-11 | CLI goal fork restores compile (never saves) | F9.13 | new: `single-goal-fork` | ✅ `singlegoal/ForkedLifecycleRestoreTest`, `singlegoal/ForkedRestoreDisabledTest`, `singlegoal/RunGoalNotCachedTest` |

### Group D: Plugin Execution & Reconciliation

| ID   | Scenario                                     | Features     | Reference Project | Status                                                 |
|------|----------------------------------------------|--------------|-------------------|--------------------------------------------------------|
| D-01 | Tracked property match → hit                 | F4.8         | **P19**           | ✅ `TrackedPropertyMatchCacheHitTest`                   |
| D-02 | Tracked property mismatch → miss             | F4.7         | **P19**           | ✅ `TrackedPropertyMismatchCacheMissTest`               |
| D-03 | skipValue enables cache hit with skip flag   | F4.6         | **P19**           | ✅ `TrackedPropertySkipValueAllowsReuseTest`            |
| D-04 | logAll dumps all properties                  | F4.10, F13.1 | **P19**           | ✅ `LogAllPropertiesTest`                               |
| D-05 | Forked lifecycle execution tracked           | F4.13        | **P12**           | ✅ `ForkedExecutionsTest`                               |
| D-06 | Duplicate goal executions handled            | F4.14        | **P01**           | ✅ `DuplicateGoalsTest`                                 |
| D-07 | `runAlways` by plugin — plugin always runs   | F4.1         | **P19**           | ✅ `pluginexecution/RunAlwaysPluginTest`                |
| D-08 | `runAlways` by goal name                     | F4.2         | **P19**           | ✅ `pluginexecution/RunAlwaysByGoalTest`                |
| D-09 | `runAlways` by execution ID                  | F4.3         | **P19**           | ✅ `pluginexecution/RunAlwaysByExecutionIdTest`         |
| D-10 | `alwaysRunPlugins` CLI property              | F4.4, F11.6  | **P01**           | ✅ `pluginexecution/AlwaysRunPluginsCliTest`            |
| D-11 | `ignoreMissing` — absent executions skipped  | F4.5         | **P19**           | ✅ `pluginexecution/IgnoreMissingPluginTest`            |
| D-12 | Reconcile `defaultValue` for absent property | F4.9         | **P19**           | ✅ `pluginexecution/TrackedPropertyDefaultValueTest`    |
| D-13 | Missing cached execution → full rebuild      | F4.15        | **P19**           | ✅ `pluginexecution/MissingExecutionTriggerRebuildTest` |

### Group E: Artifact Restore

| ID   | Scenario                                          | Features         | Reference Project                 | Status                                         |
|------|---------------------------------------------------|------------------|-----------------------------------|------------------------------------------------|
| E-01 | Incremental restore + extra outputs + classifiers | F5.2, F5.3, F6.2 | legacy: `mbuildcache-incremental` | ✅ `IncrementalRestoreTest`                     |
| E-02 | `restoreGeneratedSources=false` skips sources     | F5.4             | **P01**                           | ✅ `artifacts/RestoreGeneratedSourcesFalseTest` |
| E-03 | `restoreOnDiskArtifacts=false` skips target/      | F5.5             | **P01**                           | ✅ `artifacts/RestoreOnDiskArtifactsFalseTest`  |
| E-04 | Corrupted ZIP entry → clean rebuild               | F5.6             | legacy: `failure-recovery`        | ✅ `CorruptedZipCacheEntryTest`                 |

### Group F: Output Management

| ID   | Scenario                                        | Features    | Reference Project | Status                                 |
|------|-------------------------------------------------|-------------|-------------------|----------------------------------------|
| F-01 | Output exclude pattern filters from cache entry | F6.4        | **P17**           | ✅ `output/OutputExcludePatternTest`    |
| F-02 | `preservePermissions=true` restores POSIX bits  | F6.3        | **P01**           | ✅ `output/PermissionsPreservationTest` |
| F-03 | `maxBuildsCached` evicts oldest entries         | F6.5, F10.6 | **P01**           | ✅ `output/MaxLocalBuildsCachedTest`    |

### Group G: Admin Controls

| ID   | Scenario                                      | Features    | Reference Project | Status                                                           |
|------|-----------------------------------------------|-------------|-------------------|------------------------------------------------------------------|
| G-01 | `skipCache=true` forces rebuild, still writes | F10.1, F8.6 | PARAM P01-P19     | ✅ `PerModuleFlagsTest` + BASE-05                                 |
| G-02 | `skipSave=true` reads from cache, no write    | F10.2       | PARAM P01-P19     | ✅ `BuildExtensionTest.skipSaving` + BASE-06                      |
| G-03 | `mandatoryClean=true` blocks save             | F9.8, F10.4 | PARAM P01-P19     | ✅ `MandatoryCleanTest`                                           |
| G-04 | Mid-reactor failure → no partial entry        | F10.5       | **P06**           | ✅ `BuildFailsMidwayNoCacheTest`                                  |
| G-05 | `-Dmaven.build.cache.enabled=false` via CLI   | F1.3, F11.3 | PARAM P01-P19     | ✅ `SkipBuildExtensionTest.cacheDisabledViaCommandLine` + BASE-04 |
| G-06 | `failFast=true` aborts on restore failure     | F7.7, F10.3 | **P01**           | ✅ `admin/FailFastTest`                                           |

### Group H: Configuration Injection

| ID   | Scenario                                     | Features    | Reference Project         | Status                              |
|------|----------------------------------------------|-------------|---------------------------|-------------------------------------|
| H-01 | XML at default path configures all behaviors | F11.1       | PARAM P01-P19             | ✅ all standard ITs                  |
| H-02 | CLI `-D` overrides XML setting               | F11.3       | legacy: `build-extension` | ✅ `SkipBuildExtensionTest`          |
| H-03 | POM `<properties>` per-module override       | F11.4       | **P10**                   | ✅ `PerModuleFlagsTest`              |
| H-04 | configPath override to non-default location  | F11.2, F1.4 | **P01**                   | ✅ `config/CustomConfigPathTest`     |
| H-05 | No XML file → built-in defaults active       | F11.5, F1.5 | **P01** (no-config)       | ✅ `config/NoConfigFileDefaultsTest` |
| H-06 | Malformed XML → descriptive startup error    | F1.8        | **P01**                   | ✅ `config/InvalidConfigXmlTest`     |

> **H-03 note:** `PerModuleFlagsTest` currently uses the legacy `per-module-flags` project.
> The preferred v3 reference is P10 (nested reactor) which can host per-module property tests.
>
> **H-05 note:** Test sets up P01 without a `.mvn/maven-build-cache-config.xml` file.

### Group I: Multi-Module & Reactor

| ID   | Scenario                                          | Features   | Reference Project         | Status                                                 |
|------|---------------------------------------------------|------------|---------------------------|--------------------------------------------------------|
| I-01 | Full reactor: each module independently cached    | F8.1       | legacy: `build-extension` | ✅ `Issue21Test`                                        |
| I-02 | Per-module skipCache / skipSave /disabled via POM | F8.6       | **P10**                   | ✅ `PerModuleFlagsTest`                                 |
| I-03 | Upstream module change → downstream miss          | F8.1       | **P02**                   | ✅ `multimodule/UpstreamModuleChangeDownstreamMissTest` |
| I-04 | Partial reactor `-pl module`                      | F8.2       | **P10**                   | ✅ `multimodule/MultiModulePartialBuildTest`            |
| I-05 | Partial reactor `-pl module -am` upstream restore | F8.3       | **P10**                   | ✅ `multimodule/MultiModulePartialWithAmTest`           |
| I-06 | Parallel build `-T2` cache correctness            | F8.4       | **P11**                   | ✅ `multimodule/ParallelBuildTest`                      |
| I-07 | scanProfiles includes active profile in cache key | F8.5       | **P08**                   | ✅ `multimodule/ScanProfilesTest`                       |
| I-08 | Subtree build of leaf (no deps): Maven finds `.mvn/` by traversal; cache key is identical from root or subdir because both anchor to the same `rootDirectory` | F8.7 | **P02** | ✅ `SubtreeBuildCacheHitTest#subtreeBuildHitsCacheAfterFullReactorBuild`                       |
| I-09 | Partial reactor (`-pl C -am`), no `<discovery>`: `-am` includes B in `session.getProjects()`, so the extension computes C's multi-module checksum with B as a reactor sibling (not an external dep) → same key as full build → cache hit | F8.8 | **P02** | ✅ `SubtreeBuildCacheHitTest#partialReactorWithAmHitsCacheWithoutDiscovery`                    |
| I-10 | Subtree from C's dir, `<discovery><scanProfiles>`: only C in `session.getProjects()`; extension detects submodule context, re-scans from root pom activating `full-reactor` profile (via `scanProfiles`), discovers B with same effective model as full build → C's checksum matches → cache hit | F8.9 | **P02** | ✅ `SubtreeBuildCacheHitTest#subtreeWithDiscoveryAndScanProfileHitsCacheAfterFullReactorBuild` |

### Group J: Remote Cache

| ID   | Scenario                             | Features        | Reference Project  | Status                                   |
|------|--------------------------------------|-----------------|--------------------|------------------------------------------|
| J-01 | Remote cache read + write via WebDAV | F7.1–F7.3, F7.5 | legacy: `dav`      | ✅ `RemoteCacheDavTest`                   |
| J-02 | Remote unavailable → local fallback  | F7.6            | **P01** (WireMock) | ✅ `remote/RemoteUnavailableFallbackTest` |
| J-03 | `save.final=true` — no overwrite     | F7.4            | **P01** (WireMock) | ✅ `remote/SaveFinalRemoteTest`           |
| J-04 | Baseline URL diff report             | F7.8, F13.6     | **P01** (WireMock) | ✅ `remote/BaselineDiffTest`              |

### Group K: Hash Algorithms

| ID   | Scenario                            | Features | Reference Project | Status                                     |
|------|-------------------------------------|----------|-------------------|--------------------------------------------|
| K-01 | SHA-256 algorithm correct hit/miss  | F3.2     | **P01**           | ✅ `hashalgorithm/HashAlgorithmRoundTripTest`  |
| K-02 | Invalid algorithm → startup failure | F3.7     | **P01**           | ✅ `hashalgorithm/InvalidHashAlgorithmTest` |

### Group L: Project Versioning

| ID   | Scenario                                                 | Features    | Reference Project | Status                                                  |
|------|----------------------------------------------------------|-------------|-------------------|---------------------------------------------------------|
| L-01 | SNAPSHOT version bump → cache hit (NORMALIZED_VERSION)   | F5.7, F12.3 | **P16**           | ✅ `versioning/SnapshotVersionBumpCacheHitTest`          |
| L-02 | SNAPSHOT bump + `calculateProjectVersionChecksum` → miss | F12.2       | **P16**           | ✅ `versioning/SnapshotVersionBumpWithChecksumFlagTest`  |
| L-03 | `adjustMetaInf=true` normalizes MANIFEST.MF              | F12.1       | **P01**           | ✅ `versioning/MetaInfVersionAdjustmentTest`             |
| L-04 | CI-friendly `${revision}` version: cache key stable      | F12.4       | **P04**           | ✅ `versioning/CIFriendlyRevisionVersionTest`            |
| L-05 | External parent version bump (relativePath) → miss       | F12, F2.12  | **P10**           | ✅ `versioning/ExternalParentVersionBumpInvalidatesTest` |
| L-06 | Remote parent version bump (local-repo) → miss           | F12, F2.12  | **P10**           | ✅ `versioning/RemoteParentVersionBumpInvalidatesTest`   |

### Group M: Portability & Cross-Environment

| ID   | Scenario                                                             | Features    | Reference Project | Status                                               |
|------|----------------------------------------------------------------------|-------------|-------------------|------------------------------------------------------|
| M-01 | Absolute path stripped from effective POM → same key across machines | portability | PARAM P01-P19     | ✅ `portability/AbsolutePathNormalizationTest`        |
| M-02 | Tracked `File` property normalized to relative                       | portability | **P19**           | ✅ `portability/TrackedPropertyPathNormalizationTest` |

### Group N: Project Type Variations

| ID   | Scenario                                                 | Features | Reference Project              | Status                                              |
|------|----------------------------------------------------------|----------|--------------------------------|-----------------------------------------------------|
| N-01 | WAR packaging: web resources cached/restored             | F6.1     | **P17**                        | ✅ `projecttypes/WarPackagingTest`                   |
| N-02 | POM packaging: no source scan, key from effective POM    | F9, F2   | **P02**                        | ✅ `projecttypes/PomPackagingTest`                   |
| N-03 | Test-jar classifier artifact cached                      | F5.2     | **P06**                        | ✅ `projecttypes/TestJarProjectTest`                 |
| N-04 | Shade plugin: shaded JAR is the cached artifact          | F6.1     | new: `shade-plugin-project`    | ✅ `projecttypes/ShadePluginArtifactReplacementTest` |
| N-05 | Assembly plugin: exclusion pattern prevents ZIP in cache | F6.4     | new: `assembly-plugin-project` | ✅ `projecttypes/AssemblyPluginZipExcludeTest`       |

### Group O: Report Generation & Diagnostics

| ID   | Scenario                                        | Features | Reference Project | Status                               |
|------|-------------------------------------------------|----------|-------------------|--------------------------------------|
| O-01 | `build-cache-report.xml` present after build    | F13.5    | **P01**           | ✅ `reports/CacheReportGeneratedTest` |
| O-02 | Report shows CACHED / REBUILT status per module | F13.5    | **P02**           | ✅ `reports/CacheReportStatusTest`    |
| O-03 | `buildinfo.xml` FileHash debug entries          | F13.3    | **P01**           | ✅ `reports/BuildInfoXmlDebugTest`    |

### Group P: Internal Architecture

| ID   | Scenario                                              | Features   | Reference Project | Status                                        |
|------|-------------------------------------------------------|------------|-------------------|-----------------------------------------------|
| P-01 | Stale `target/` artifacts not leaked into cache       | F6.7       | **P01**           | ✅ `internal/StagingRemovesStaleClassesTest`   |
| P-02 | Extra CLI goal after lifecycle goal (regression #399) | implicit   | **P01**           | ✅ `internal/AdditionalGoalAfterLifecycleTest` |
| P-03 | `Build` round-trip serialization (unit test)          | XmlService | —                 | ✅ `internal/BuildSerializationRoundTripTest`  |

### Group Q: Cache Invalidation — Project Traits

Tests verifying that each unique Maven input category correctly invalidates the cache.
Primary test class: `CacheInvalidationProjectTraitsTest`.

| ID   | Scenario                                                                | Features    | Reference Project | Status                                                                            |
|------|-------------------------------------------------------------------------|-------------|-------------------|-----------------------------------------------------------------------------------|
| Q-01 | WAR webapp file change → WAR module misses; unchanged JAR module hits   | F2.6, F8    | **P17**           | ✅ `CacheInvalidationProjectTraitsTest.webappFileChangeInvalidates`                |
| Q-02 | Parent-managed dep version change → child modules miss                  | F2.12       | **P02**           | ✅ `CacheInvalidationProjectTraitsTest.parentManagedDepVersionChangeInvalidates`   |
| Q-03 | Plugin version change in POM → cache miss                               | F2.7        | **P01**           | ✅ `CacheInvalidationProjectTraitsTest.pluginVersionChangeInvalidates`             |
| Q-04 | BOM version change for a *used* dependency → cache miss                 | F2.12       | **P05**           | ✅ `CacheInvalidationProjectTraitsTest.bomVersionChangeAffectedDepInvalidates`     |
| Q-05 | BOM import order change (first-wins) → resolved version changes → miss  | F2.12       | **P06**           | ✅ `CacheInvalidationProjectTraitsTest.bomImportOrderChangeInvalidates`            |
| Q-06 | Transitive exclusion removed → effective classpath changes → miss       | F2.12       | **P06**           | ✅ `CacheInvalidationProjectTraitsTest.exclusionRemovedInvalidatesCache`           |
| Q-07 | `<optional>true</optional>` flag removed → effective POM changes → miss | F2.12       | **P06**           | ✅ `CacheInvalidationProjectTraitsTest.optionalFlagChangeInvalidates`              |
| Q-08 | Classifier dep removed → resolved artifact coordinates change → miss    | F2.12       | **P06**           | ✅ `CacheInvalidationProjectTraitsTest.classifierDepRemovedInvalidates`            |
| Q-09 | Plugin `<phase>` rebinding change → effective lifecycle map → miss      | F2.7        | **P07**           | ✅ `CacheInvalidationProjectTraitsTest.phaseRebindingChangeInvalidates`            |
| Q-10 | Plugin `<dependencies>` version change → plugin classpath → miss        | F2.7        | **P07**           | ✅ `CacheInvalidationProjectTraitsTest.pluginClasspathDepVersionChangeInvalidates` |
| Q-11 | `maven-plugin` packaging cache round-trip                               | F9          | **P07**           | ✅ `CacheInvalidationProjectTraitsTest.mavenPluginPackagingCacheRoundTrip`         |
| Q-12 | Plugin goal prefix config change → plugin descriptor changed → miss     | F2.7        | **P07**           | ✅ `pluginexecution/PluginGoalPrefixChangeInvalidatesTest`                         |
| Q-13 | Profile file-trigger activates → effective POM changes → miss           | F2.21       | **P08**           | ✅ `CacheInvalidationProjectTraitsTest.profileFileActivationInvalidates`           |
| Q-14 | `settings.xml` profile property change → dep version or param → miss    | F2.9, F2.21 | **P08**           | ✅ `inputfiltering/SettingsProfilePropertyChangeInvalidatesTest`                   |
| Q-15 | `activeByDefault` profile resets when another activates → miss          | F2.21       | **P08**           | ✅ `inputfiltering/ActiveByDefaultResetInvalidatesTest`                            |
| Q-16 | Unchanged module not evicted when leaf module changes                   | F8.1        | **P02**           | ✅ `CacheInvalidationProjectTraitsTest.unchangedModuleStaysInCache`                |
| Q-17 | Parallel build: one module change invalidates only dependents           | F8.4        | **P11**           | ✅ `CacheInvalidationProjectTraitsTest.parallelBuildModuleChangeInvalidates`       |
| Q-18 | Reactor SNAPSHOT source change propagates to all dependent modules      | F8.1        | **P16**           | ✅ `CacheInvalidationProjectTraitsTest.reactorSnapshotSourceChangeInvalidates`     |
| Q-19 | WAR profile-filtered resource change → WAR module miss                  | F2.21, N    | **P17**           | ✅ `CacheInvalidationProjectTraitsTest.warProfileFilterChangeInvalidates`          |
| Q-20 | CI-driven version change without source change → cache hit              | F12.4       | **P04**           | ✅ `versioning/CiBuildDrivenProjectVersionChangeCachedTest`                        |

---

## 4. Required Test Coverage

Master traceability table mapping behaviors to test classes and reference projects.

**Status:** ✅ exists | ⚠️ partial | ❌ missing
**Reference Project:** `P<n>` = reference project · `PARAM` = parametrized across P01-P19
· `legacy: <name>` = existing non-reference project · `new: <name>` = new project needed

| TC#    | Behavior / Test Case                                                       | Test Class                                                    | Reference Project                 | Status |
|--------|----------------------------------------------------------------------------|---------------------------------------------------------------|-----------------------------------|--------|
| TC-001 | Build extension loads; first build saved, second restored                  | `BuildExtensionTest.simple`                                   | PARAM P01-P19                     | ✅      |
| TC-002 | Core extension loads; same hit/miss cycle                                  | `CoreExtensionTest`                                           | PARAM P01-P19                     | ✅      |
| TC-003 | `maven.build.cache.enabled=false` via CLI disables cache                   | `SkipBuildExtensionTest.cacheDisabledViaCommandLine`          | PARAM P01-P19                     | ✅      |
| TC-004 | Adding a source file invalidates cache                                     | `AddedSourceFileInvalidatesCacheTest`                         | legacy: `checksum-correctness`    | ✅      |
| TC-005 | Deleting a source file invalidates cache                                   | `DeletedSourceFileInvalidatesCacheTest`                       | legacy: `checksum-correctness`    | ✅      |
| TC-006 | Modifying a source file invalidates cache                                  | `SourceChangeInvalidatesCacheTest`                            | PARAM P01-P19                     | ✅      |
| TC-007 | Modifying POM (functional change) invalidates cache                        | `PomChangeInvalidatesCacheTest`                               | legacy: `checksum-correctness`    | ✅      |
| TC-008 | Whitespace-only POM change is a cache hit                                  | `WhitespaceOnlyPomChangeNoCacheMissTest`                      | legacy: `checksum-correctness`    | ✅      |
| TC-009 | Resource file change invalidates cache                                     | `ResourceChangeInvalidatesCacheTest`                          | legacy: `checksum-correctness`    | ✅      |
| TC-010 | Test source change invalidates cache                                       | `TestSourceChangeInvalidatesCacheTest`                        | legacy: `checksum-correctness`    | ✅      |
| TC-011 | POM `<properties>` value change invalidates cache                          | `PropertyChangeInvalidatesCacheTest`                          | PARAM P01-P19                     | ✅      |
| TC-012 | Dependency version change in POM invalidates cache                         | `DependencyVersionChangeInvalidatesCacheTest`                 | P01                               | ✅      |
| TC-013 | `compile` phase cached and restored                                        | `CompilePhaseDefaultCachedTest`                               | legacy: `lifecycle-phases`        | ✅      |
| TC-014 | `test-compile` phase cached and restored                                   | `TestCompilePhaseTest`                                        | legacy: `lifecycle-phases`        | ✅      |
| TC-015 | Phase escalation: compile→package forces rebuild                           | `CompileThenPackageEscalationTest`                            | PARAM P01-P19                     | ✅      |
| TC-016 | Phase escalation: package→install forces rebuild                           | `PackageThenInstallEscalationTest`                            | legacy: `lifecycle-phases`        | ✅      |
| TC-017 | Install phase: artifact available in local repo after restore              | `InstallPhaseTest`                                            | legacy: `lifecycle-phases`        | ✅      |
| TC-018 | Tracked property match → cache hit                                         | `TrackedPropertyMatchCacheHitTest`                            | P19                               | ✅      |
| TC-019 | Tracked property mismatch → cache miss                                     | `TrackedPropertyMismatchCacheMissTest`                        | P19                               | ✅      |
| TC-020 | skipValue allows cache hit when skip property set                          | `TrackedPropertySkipValueAllowsReuseTest`                     | P19                               | ✅      |
| TC-021 | Full reactor: modules cached independently                                 | `Issue21Test`                                                 | P02, P10, P11                     | ✅      |
| TC-022 | Mid-build failure: nothing written to cache                                | `BuildFailsMidwayNoCacheTest`                                 | P06                               | ✅      |
| TC-023 | Global include paths restrict fingerprinted sources                        | `IncludeExcludeTest`                                          | legacy: `include-exclude`         | ✅      |
| TC-024 | Global exclude paths ignore matching files                                 | `IncludeExcludeTest`                                          | legacy: `include-exclude`         | ✅      |
| TC-025 | Global glob pattern selects source subset                                  | `IncludeExcludeTest`                                          | legacy: `include-exclude`         | ✅      |
| TC-026 | Incremental restore + extra output dirs + classifiers                      | `IncrementalRestoreTest`                                      | legacy: `mbuildcache-incremental` | ✅      |
| TC-027 | Forked lifecycle execution tracked and cached                              | `ForkedExecutionsTest`                                        | P12                               | ✅      |
| TC-028 | Duplicate goal executions deduped correctly                                | `DuplicateGoalsTest`                                          | P01                               | ✅      |
| TC-029 | logAll flag dumps all mojo properties                                      | `LogAllPropertiesTest`                                        | P19                               | ✅      |
| TC-030 | Per-module skipCache / skipSave via POM property                           | `PerModuleFlagsTest`                                          | P10                               | ✅      |
| TC-031 | Per-module cache disabled via POM property                                 | `PerModuleFlagsTest`                                          | P10                               | ✅      |
| TC-032 | `skipCache=true` global: rebuilds all, still writes                        | `SkipBuildExtensionTest`                                      | PARAM P01-P19                     | ✅      |
| TC-033 | `skipSave=true`: reads cache, does not write                               | `BuildExtensionTest.skipSaving`                               | PARAM P01-P19                     | ✅      |
| TC-034 | `mandatoryClean=true`: save blocked without clean                          | `MandatoryCleanTest`                                          | PARAM P01-P19                     | ✅      |
| TC-035 | Corrupted ZIP cache entry: rebuild triggered                               | `CorruptedZipCacheEntryTest`                                  | PARAM P01-P19                     | ✅      |
| TC-036 | Remote cache read and write (WebDAV)                                       | `RemoteCacheDavTest`                                          | legacy: `dav`                     | ✅      |
| TC-037 | clean-only run: cache bypassed, no lookup                                  | `SkipBuildExtensionTest.simple`                               | PARAM P01-P19                     | ✅      |
| TC-038 | Upstream reactor module change → downstream cache miss                     | `UpstreamModuleChangeDownstreamMissTest`                      | P02                               | ✅      |
| TC-039 | No `.mvn/maven-build-cache-config.xml`: defaults active                    | `NoConfigFileDefaultsTest`                                    | P01 (no-config)                   | ✅      |
| TC-040 | configPath override: non-default XML loaded                                | `CustomConfigPathTest`                                        | P01                               | ✅      |
| TC-041 | Malformed XML config: descriptive error at startup                         | `InvalidConfigXmlTest`                                        | P01                               | ✅      |
| TC-042 | Profile activation changes effective POM → cache miss                      | `ProfileCliActivationInvalidatesTest`                         | P08                               | ✅      |
| TC-043 | `processPlugins=false`: plugin params not introspected                     | `ProcessPluginsDisabledTest`                                  | P01                               | ✅      |
| TC-044 | Project-level glob override in POM `<properties>`                          | `PerProjectGlobOverrideTest`                                  | P02                               | ✅      |
| TC-045 | Project-level additional include via POM properties                        | `ProjectLevelIncludeTest`                                     | P02                               | ✅      |
| TC-046 | Effective POM property exclusion for specific plugin                       | `EffectivePomExcludePropertyTest`                             | P19                               | ✅      |
| TC-047 | `runAlways` by plugin coordinates: plugin always executes                  | `RunAlwaysPluginTest`                                         | P19                               | ✅      |
| TC-048 | `runAlways` by goal name                                                   | `RunAlwaysByGoalTest`                                         | P19                               | ✅      |
| TC-049 | `runAlways` by execution ID                                                | `RunAlwaysByExecutionIdTest`                                  | P19                               | ✅      |
| TC-050 | `alwaysRunPlugins` CLI: comma-list of plugin:goal pairs                    | `AlwaysRunPluginsCliTest`                                     | P01                               | ✅      |
| TC-051 | `ignoreMissing`: absent cached execution skipped                           | `IgnoreMissingPluginTest`                                     | P19                               | ✅      |
| TC-052 | Reconcile `defaultValue` used when property absent                         | `TrackedPropertyDefaultValueTest`                             | P19                               | ✅      |
| TC-053 | Missing cached execution triggers full rebuild                             | `MissingExecutionTriggerRebuildTest`                          | P19                               | ✅      |
| TC-054 | `restoreGeneratedSources=false`: generated sources not restored            | `RestoreGeneratedSourcesFalseTest`                            | P01                               | ✅      |
| TC-055 | `restoreOnDiskArtifacts=false`: target/ artifacts not restored             | `RestoreOnDiskArtifactsFalseTest`                             | P01                               | ✅      |
| TC-056 | Partial reactor `-pl module-a`: targeted module only                       | `MultiModulePartialBuildTest`                                 | P10                               | ✅      |
| TC-057 | Partial reactor `-pl module-b -am`: upstream restored                      | `MultiModulePartialWithAmTest`                                | P10                               | ✅      |
| TC-058 | WAR packaging: web resources cached and restored                           | `WarPackagingTest`                                            | P17                               | ✅      |
| TC-059 | POM packaging: no source scan, effective POM is key                        | `PomPackagingTest`                                            | P02                               | ✅      |
| TC-060 | CI-friendly `${revision}` version: cache key stable                        | `CIFriendlyRevisionVersionTest`                               | P04                               | ✅      |
| TC-061 | `clean verify`: clean runs before cache lookup                             | `CleanVerifyTest`                                             | PARAM P01-P19                     | ✅      |
| TC-062 | Output exclude regex pattern filters files from entry                      | `OutputExcludePatternTest`                                    | P17                               | ✅      |
| TC-063 | `preservePermissions=true`: POSIX bits restored                            | `PermissionsPreservationTest`                                 | P01 (Linux only)                  | ✅      |
| TC-064 | `maxBuildsCached=2`: third build evicts oldest entry                       | `MaxLocalBuildsCachedTest`                                    | P01                               | ✅      |
| TC-065 | `save.final=true`: `<final>true</final>` embedded in pushed buildinfo      | `SaveFinalRemoteTest`                                         | P01 (WireMock)                    | ✅      |
| TC-066 | Remote server unavailable: falls back to local cache                       | `RemoteUnavailableFallbackTest`                               | P01 (unreachable URL)             | ✅      |
| TC-067 | `failFast=true`: build aborts on restore failure                           | `FailFastTest`                                                | P01                               | ✅      |
| TC-068 | Parallel build `-T2`: cache correctness maintained                         | `ParallelBuildTest`                                           | P11                               | ✅      |
| TC-069 | Per-plugin `dirScan` limits paths scanned                                  | `PerPluginDirScanTest`                                        | P19                               | ❌      |
| TC-070 | Plugin dependency exclusion from fingerprint                               | `ExcludeDependenciesPluginTest`                               | P07                               | ❌      |
| TC-071 | SHA-256 algorithm: correct hit/miss behavior                               | `HashAlgorithmRoundTripTest`                                  | P01                               | ✅      |
| TC-072 | Invalid hash algorithm: descriptive startup failure                        | `InvalidHashAlgorithmTest`                                    | P01                               | ✅      |
| TC-073 | SNAPSHOT version bump → cache hit (NORMALIZED_VERSION)                     | `SnapshotVersionBumpCacheHitTest`                             | P16                               | ✅      |
| TC-074 | SNAPSHOT bump + `calculateProjectVersionChecksum` → miss                   | `SnapshotVersionBumpWithChecksumFlagTest`                     | P16                               | ✅      |
| TC-075 | `adjustMetaInf=true`: MANIFEST.MF version normalized                       | `MetaInfVersionAdjustmentTest`                                | P01                               | ✅      |
| TC-076 | Absolute path stripped → same cache key across workspaces                  | `AbsolutePathNormalizationTest`                               | PARAM P01-P19                     | ✅      |
| TC-077 | Tracked `File` property normalized to relative path                        | `TrackedPropertyPathNormalizationTest`                        | P19                               | ✅      |
| TC-078 | Test-jar classifier artifact cached and restored                           | `TestJarProjectTest`                                          | P06                               | ✅      |
| TC-079 | Shade plugin: shaded JAR (not empty original) is cached                    | `ShadePluginArtifactReplacementTest`                          | new: `shade-plugin-project`       | ✅      |
| TC-080 | Assembly plugin: output exclusion prevents ZIP in cache                    | `AssemblyPluginZipExcludeTest`                                | new: `assembly-plugin-project`    | ✅      |
| TC-081 | Extra CLI goal after lifecycle goal (regression #399)                      | `AdditionalGoalAfterLifecycleTest`                            | P01                               | ✅      |
| TC-082 | `build-cache-report.xml` generated after each build                        | `CacheReportGeneratedTest`                                    | P01                               | ✅      |
| TC-083 | Report shows correct CACHED/REBUILT per module                             | `CacheReportStatusTest`                                       | P02                               | ✅      |
| TC-084 | Stale `target/` files not included in new cache entry                      | `StagingRemovesStaleClassesTest`                              | P01                               | ✅      |
| TC-085 | `scanProfiles` includes active profiles in reactor key                     | `ScanProfilesTest`                                            | P08                               | ✅      |
| TC-086 | `logAllProperties` global flag dumps all params                            | `LogAllPropertiesGlobalTest`                                  | P19                               | ✅      |
| TC-087 | `buildinfo.xml` debug: FileHash entries present                            | `BuildInfoXmlDebugTest`                                       | P01                               | ✅      |
| TC-088 | CacheSource field: LOCAL after local hit                                   | `CacheSourceTrackingTest`                                     | P01                               | ✅      |
| TC-089 | `baselineUrl` diff: `buildsdiff.xml` generated                             | `BaselineDiffTest`                                            | P01 + remote                      | ✅      |
| TC-090 | `Build` object serializes and deserializes cleanly                         | `BuildSerializationRoundTripTest`                             | —                                 | ✅      |
| TC-091 | Exclusion FILENAME vs PATH rule types (unit)                               | `ExclusionRuleTypesTest`                                      | —                                 | ✅      |
| TC-092 | `nolog` suppresses property from reconcile output                          | `TrackedPropertyNologTest`                                    | P19                               | ✅      |
| TC-093 | System-scope JAR content change (SNAPSHOT ver.) → cache miss               | `CacheInvalidationProjectTraitsTest`                          | P01                               | ✅      |
| TC-094 | Parent `<properties>` bump propagates to declared dep → miss               | `CacheInvalidationProjectTraitsTest`                          | P02                               | ✅      |
| TC-095 | BOM-managed unused dep version change → cache hit (no miss)                | `CacheInvalidationProjectTraitsTest`                          | P06                               | ✅      |
| TC-096 | OS env-var activates profile → effective POM changes → miss                | `EnvVariableChangeInvalidatesTest`                            | P08                               | ✅      |
| TC-097 | External parent version bump (relativePath) → cache miss                   | `ExternalParentVersionBumpInvalidatesTest`                    | P10                               | ✅      |
| TC-098 | Remote parent version bump (local-repo install) → cache miss               | `RemoteParentVersionBumpInvalidatesTest`                      | P10                               | ✅      |
| TC-099 | WAR webapp file change → webapp-war misses; webapp-lib hits                | `CacheInvalidationProjectTraitsTest`                          | P17                               | ✅      |
| TC-100 | Parent-managed dep version change → all child modules miss                 | `CacheInvalidationProjectTraitsTest`                          | P02                               | ✅      |
| TC-101 | Plugin version change in POM → cache miss                                  | `CacheInvalidationProjectTraitsTest`                          | P01                               | ✅      |
| TC-102 | BOM version change for a used dep → resolved version changes → miss        | `CacheInvalidationProjectTraitsTest`                          | P05                               | ✅      |
| TC-103 | BOM import order swap (first-wins) → different resolved version → miss     | `CacheInvalidationProjectTraitsTest`                          | P06                               | ✅      |
| TC-104 | Transitive exclusion removed → effective classpath changes → miss          | `CacheInvalidationProjectTraitsTest`                          | P06                               | ✅      |
| TC-105 | `<optional>true</optional>` removed → effective POM dep changes → miss     | `CacheInvalidationProjectTraitsTest`                          | P06                               | ✅      |
| TC-106 | Classifier dep removed → resolved artifact coordinates change → miss       | `CacheInvalidationProjectTraitsTest`                          | P06                               | ✅      |
| TC-107 | Plugin `<phase>` rebinding change → effective lifecycle map changes → miss | `CacheInvalidationProjectTraitsTest`                          | P07                               | ✅      |
| TC-108 | Plugin `<dependencies>` version change → plugin classpath → miss           | `CacheInvalidationProjectTraitsTest`                          | P07                               | ✅      |
| TC-109 | Plugin goal prefix config change → plugin descriptor changed → miss        | `pluginexecution/PluginGoalPrefixChangeInvalidatesTest`       | P07                               | ✅      |
| TC-110 | Profile file-trigger activates → effective POM changes → miss              | `CacheInvalidationProjectTraitsTest`                          | P08                               | ✅      |
| TC-111 | `settings.xml` profile property change → effective-POM dep/param → miss    | `inputfiltering/SettingsProfilePropertyChangeInvalidatesTest` | P08                               | ✅      |
| TC-112 | `activeByDefault` profile resets when another profile activates → miss     | `inputfiltering/ActiveByDefaultResetInvalidatesTest`          | P08                               | ✅      |
| TC-113 | CI-driven version changes without source change → cache hit                | `versioning/CiBuildDrivenProjectVersionChangeCachedTest`      | P04                               | ✅      |
| TC-114 | Unchanged module not evicted when only a leaf module changes               | `CacheInvalidationProjectTraitsTest`                          | P02                               | ✅      |
| TC-115 | Parallel build: one module change invalidates its dependents only          | `CacheInvalidationProjectTraitsTest`                          | P11                               | ✅      |
| TC-116 | Reactor SNAPSHOT source change propagates to all dependent modules         | `CacheInvalidationProjectTraitsTest`                          | P16                               | ✅      |
| TC-117 | WAR profile-filtered resource change → WAR module miss                     | `CacheInvalidationProjectTraitsTest`                          | P17                               | ✅      |
| TC-118 | `maven-plugin` packaging: build+restore round-trip succeeds                | `CacheInvalidationProjectTraitsTest`                          | P07                               | ✅      |
| TC-119 | Subtree build of leaf module-api (no inter-module deps) from its own directory: Maven traverses up to `.mvn/`; cache key anchored to `rootDirectory` is identical to the full-reactor key → cache hit | `SubtreeBuildCacheHitTest#subtreeBuildHitsCacheAfterFullReactorBuild` | P02 | ✅ |
| TC-120 | Partial reactor `-pl module-core -am` (no discovery): `-am` puts module-api into `session.getProjects()`; extension computes module-core's checksum with module-api as a reactor sibling, matching the full-reactor key → cache hit for both B and C | `SubtreeBuildCacheHitTest#partialReactorWithAmHitsCacheWithoutDiscovery` | P02 | ✅ |
| TC-121 | Subtree build from module-core's dir with `<discovery><scanProfiles><scanProfile>full-reactor</scanProfile></scanProfiles>`: only C in reactor; extension detects non-root context, re-scans from root pom activating the `full-reactor` profile (whose property is in every module's effective POM), discovers module-api with the same checksum as the full-reactor build → cache hit for C | `SubtreeBuildCacheHitTest#subtreeWithDiscoveryAndScanProfileHitsCacheAfterFullReactorBuild` | P02 | ✅ |
| TC-122 | Single goal `compiler:compile` cached and restored on second run                | `singlegoal/CompileGoalCachedTest`                | legacy: `lifecycle-phases` | ✅ |
| TC-123 | `compiler:compile` then `package`: escalates without "Unsupported phase"        | `singlegoal/CompileGoalThenPackageEscalationTest` | legacy: `lifecycle-phases` | ✅ |
| TC-124 | `package` then `compiler:compile`: compares cleanly without "Unsupported phase" | `singlegoal/PackageThenCompileGoalTest`           | legacy: `lifecycle-phases` | ✅ |
| TC-125 | `cacheSingleGoal=false`: single goal bypasses cache                             | `singlegoal/SingleGoalDisabledTest`               | legacy: `lifecycle-phases` | ✅ |
| TC-126 | CLI goal's forked lifecycle (`dependency:analyze` → test-compile) restores compile from cache | `singlegoal/ForkedLifecycleRestoreTest` | new: `single-goal-fork` | ✅ |
| TC-127 | `restoreForkedExecutions=false`: forked lifecycle recompiles (no restore)       | `singlegoal/ForkedRestoreDisabledTest`            | new: `single-goal-fork`    | ✅ |
| TC-128 | Run-style goal with no default phase saves no cache entry                       | `singlegoal/RunGoalNotCachedTest`                 | new: `single-goal-fork`    | ✅ |

**Summary:**

| Total TCs | ✅ Existing | ❌ Missing |
|-----------|------------|-----------|
| **128**   | **126**    | **2**     |

---

## 5. Implementation Backlog

Sprints 1–7 are complete. Two test classes remain unimplemented (see §6 for details):

| TC#    | Test Class                      | Reference Project | Notes                                                                              |
|--------|---------------------------------|-------------------|------------------------------------------------------------------------------------|
| TC-069 | `PerPluginDirScanTest`          | P19               | `<dirScan>` on `maven-compiler-plugin` to `src/main/java`; resource change → hit  |
| TC-070 | `ExcludeDependenciesPluginTest` | P07               | `excludeDependencies=true` on plugin; bump its dep version → cache still hits      |

### Projects excluded from the BASE parametrized suite

| Project | Reason                                          | How to enable                                          |
|---------|-------------------------------------------------|--------------------------------------------------------|
| P13     | Requires JDK at specific `toolchains.xml` paths | Conditional skip; run in CI with toolchains configured |
| P18     | Requires Maven 4 binary                         | Run in Maven 4 CI job only                             |

---

## 6. Appendix: Property Reference

All `maven.build.cache.*` properties recognized by `CacheConfigImpl`. Resolution order:
**user properties** (CLI `-D`) → **system properties** → default.

| Property                                    | Default                                                | Type       | XML equivalent                                     |
|---------------------------------------------|--------------------------------------------------------|------------|----------------------------------------------------|
| `maven.build.cache.configPath`              | `(multimodule root)/.mvn/maven-build-cache-config.xml` | path       | —                                                  |
| `maven.build.cache.enabled`                 | `true`                                                 | boolean    | `<configuration><enabled>`                         |
| `maven.build.cache.location`                | `~/.m2/build-cache`                                    | path       | `<configuration><local><location>`                 |
| `maven.build.cache.remote.enabled`          | `false`                                                | boolean    | `<configuration><remote enabled="…">`              |
| `maven.build.cache.remote.url`              | —                                                      | URL        | `<configuration><remote><url>`                     |
| `maven.build.cache.remote.server.id`        | —                                                      | string     | `<configuration><remote id="…">`                   |
| `maven.build.cache.remote.save.enabled`     | `false`                                                | boolean    | `<configuration><remote><save><enabled>`           |
| `maven.build.cache.remote.save.final`       | `false`                                                | boolean    | — (CLI only)                                       |
| `maven.build.cache.failFast`                | `false`                                                | boolean    | — (CLI only)                                       |
| `maven.build.cache.baselineUrl`             | —                                                      | URL        | — (CLI only)                                       |
| `maven.build.cache.lazyRestore`             | `false`                                                | boolean    | — (CLI only)                                       |
| `maven.build.cache.restoreGeneratedSources` | `true`                                                 | boolean    | — (CLI / POM property)                             |
| `maven.build.cache.restoreOnDiskArtifacts`  | `true`                                                 | boolean    | — (CLI / POM property)                             |
| `maven.build.cache.alwaysRunPlugins`        | —                                                      | comma-list | `<executionControl><runAlways>` (partial override) |
| `maven.build.cache.skipCache`               | `false`                                                | boolean    | — (CLI / POM property)                             |
| `maven.build.cache.skipSave`                | `false`                                                | boolean    | — (CLI / POM property)                             |
| `maven.build.cache.mandatoryClean`          | `false`                                                | boolean    | `<configuration><mandatoryClean>`                  |
| `maven.build.cache.processPlugins`          | `true`                                                 | boolean    | — (POM property per-project)                       |
| `maven.build.cache.input.glob`              | —                                                      | glob       | `<input><global><glob>` (per-project override)     |
| `maven.build.cache.input.*`                 | —                                                      | path       | `<input><global><includes>` (per-project)          |
| `maven.build.cache.exclude.*`               | —                                                      | path/glob  | `<input><global><excludes>` (per-project)          |

### Key XML-only elements

| XML Element                                                           | Description                                                                           |
|-----------------------------------------------------------------------|---------------------------------------------------------------------------------------|
| `<configuration><hashAlgorithm>`                                      | `XX` (default), `XXMM`, `METRO`, `METRO+MM`, `SHA-1`, `SHA-256`, `SHA-384`, `SHA-512` |
| `<configuration><attachedOutputs><dirName glob="…">`                  | Extra output dirs to capture/restore beyond primary artifact                          |
| `<configuration><attachedOutputs preservePermissions="…">`            | Restore POSIX permissions (default `true`)                                            |
| `<configuration><local><maxBuildsCached>`                             | LRU limit on local cache entries per project                                          |
| `<configuration><multiModule><scanProfiles>`                          | Profile names to include in multi-module reactor key                                  |
| `<configuration><projectVersioning><adjustMetaInf>`                   | Normalize `Implementation-Version` in MANIFEST.MF                                     |
| `<configuration><projectVersioning><calculateProjectVersionChecksum>` | Include project version in cache key                                                  |
| `<input><global><glob>`                                               | Global file glob for source selection                                                 |
| `<input><global><includes>`                                           | Additional always-included paths                                                      |
| `<input><global><excludes>`                                           | Always-excluded paths                                                                 |
| `<input><plugins><plugin><dirScan>`                                   | Per-plugin directory scan override                                                    |
| `<input><plugins><plugin><effectivePom><excludeProperties>`           | POM properties excluded from plugin fingerprint                                       |
| `<input><plugins><plugin><excludeDependencies>`                       | Exclude plugin dependencies from fingerprint                                          |
| `<executionControl><runAlways><plugins>`                              | Plugins that always run regardless of cache hit                                       |
| `<executionControl><runAlways><goalsLists>`                           | Goals that always run                                                                 |
| `<executionControl><runAlways><executions>`                           | Execution IDs that always run                                                         |
| `<executionControl><ignoreMissing><plugins>`                          | Executions to silently skip if absent in cached build                                 |
| `<executionControl><reconcile><plugins>`                              | Tracked plugin parameters for key reconciliation                                      |
| `<executionControl><reconcile><logAllProperties>`                     | Dump all plugin parameters globally                                                   |
| `<output><exclude><patterns>`                                         | Regex patterns for files excluded from cache bundle                                   |

---
