Clean up CCC inconsistencies and DX issues before rc1 (part 3)
Follow-up to:
#3586192
_**Verify the issue problem and solution before proceeding.**_
## Title
**AI Context: Consistency / DX cleanup (final, constructor promotion, snake_case locals, service interfaces)**
---
## Description
Follow-up to #3586192 / naming & DX review. Addresses the remaining **consistency / DX** items that were explicitly out of scope for the naming MR. **No functional or API behavior changes** — style, clarity, and maintainability only.
### Background
The naming/DX MR covered route/permission renames, dead code removal, `new self` in final classes, and snake_case fixes in the worst-offender service files. These items were deferred per reviewer (note_914050) as optional polish.
### Scope
#### 1. Mark leaf classes `final` (3c — partial)
Add `final` to framework-instantiated leaf classes with no subclass use case:
- `Hook/DiffHooks`
- `Hook/DynamicEntityReferenceHooks`
- `Access/AiContextOverviewAccessCheck`
- `Access/AiContextUsageAccessCheck`
- `Routing/AiContextRouteSubscriber`
- `Routing/AiContextScopeRouteSubscriber`
- `AiContextUninstallValidator`
- `Service/AiContextEntityTargetResolver`
- `Plugin/views/field/JsonArrayField`
**Do not** mark `final`:
- `Plugin/AiContextScope/*` (documented extension point via `AiContextScopeBase`)
- `Plugin/diff/Field/DynamicEntityReferenceFieldBuilder`
- `AiContextScopeManager`, `AiContextItemScheduler`
- Entity handlers (`AiContextUsageViewsData`, `AiContextItemTranslationHandler`) unless explicitly agreed — diverges from core’s non-`final` handler pattern
**Effort:** ~9 one-line edits.
---
#### 2. Constructor promotion sweep (3f — remaining ~15 classes)
Convert traditional constructor + property declaration + assignment to PHP 8.1 constructor promotion in classes that still use the old pattern.
**Priority order:**
1. Controllers + list builders (quick wins)
2. Smaller forms, services, plugins
3. `Form/AiContextItemForm.php` (largest — 10 dependencies)
**Already promoted — skip:** most `Service/*`, access checks, event subscribers, models.
**Out of scope / separate pattern:**
- `AiContextScopeBase` (factory injection via `create()`, not a normal constructor)
- `MarkdownRenderer` (instantiates converter in constructor body)
**Effort:** ~15 files, ~250–350 net lines removed (mostly docblocks).
---
#### 3. Codebase-wide `$snake_case` locals (2f — consistency)
Normalize camelCase **local variables and method parameters** to Drupal-standard `$snake_case` in remaining files. Class properties may stay `$camelCase` (Drupal convention, especially with promotion).
**Primary targets:**
- `Service/AiContextSelector.php`
- `Service/AiContextRequestFactory.php`
- `Service/AiContextScopeResolver.php`
- `Model/AiContextRequest.php`
- `Model/AiContextRequestParamsData.php`
- `Model/AiContextResult.php`
**Note:** This is **consistency**, not PHPCS compliance — current Coder does not flag camelCase locals. Do not rename promoted constructor properties unless separately agreed.
**Effort:** Large; consider splitting into sub-tasks per file or directory.
---
#### 4. Service interfaces (3d — incremental)
Introduce interfaces for core service contracts to improve testability and document the public API. Follow the existing `AiContextSelectorInterface` pattern.
**Candidates (add as needed, not necessarily all at once):**
- `AiContextRenderer`
- `AiContextScopeResolver`
- `AiContextRequestFactory`
Register implementations in `ai_context.services.yml` and update `@var` / type hints where appropriate. Avoid a big-bang sweep — one interface per focused commit is fine.
---
### Acceptance criteria
- [ ] 9 leaf classes marked `final`; no extension-point classes sealed
- [ ] Remaining ~15 traditional constructors converted to promotion; `parent::__construct()` order preserved in forms
- [ ] camelCase locals normalized in Service/Model targets (or sub-tasks filed if split)
- [ ] At least one new service interface added following `AiContextSelectorInterface` pattern (or sub-tasks filed for remaining)
- [ ] `phpcs --standard=Drupal,DrupalPractice src/ tests/` clean
- [ ] `phpstan analyze` clean on touched files
- [ ] Existing test suite passes (Unit, Kernel, Functional)
---
### Suggested implementation order
Do in separate commits so they can be reviewed separately:
1. `final` on leaf classes (smallest, standalone commit)
2. Constructor promotion — controllers/list builders, then forms (exclude `AiContextItemForm` until last)
3. snake_case locals — one file at a time
4. Service interfaces — one service at a time as follow-up sub-tasks
**AI usage disclosures:**
- [x] AI Assisted Issue
- [ ] AI Assisted Code
issue