[Meta] CCC 1.1 follow-ups from beta4 code-review hardening
## Problem/motivation
Make sure not to overlap or consider consolidating:
#3586384+s
Follow-up to the beta4 meta:
#3586309+s
_**Check the issue is still valid before proceeding.**_
Source notes:
- [ai_context-beta4-1.0.x-issues.md](https://git.drupalcode.org/project/ai_context/-/work_items/3586309)
(uploaded on #3586309)
Beta4 keeps the access/trust, overview cheap-check, tooltip a11y, and small
DX/docs polish track. The items below are real but are **performance,
coverage, or modernization** work that should wait for **1.1** so 1.0 can
ship a coherent permission and API story.
This meta documents the deferred work in enough detail that child issues do
**not** need to be filed yet (except where one already exists). Split into
child issues later when scheduling 1.1 implementation.
## Related already-filed 1.1 work
- #3586347+s — Avoid full published-ID scans during subscribed scope
prefiltering (covers part of analysis item #2; extend it for selectivity)
- #3586167+s — broader selector/performance roadmap (keep linked)
## Deferred 1.1 work packages
### A. Cache context selection results per agent/request
**Analysis item:** #1
**Problem**
`AiContextSystemPromptSubscriber::onPreSystemPrompt()` calls
`AiContextSelector::select()` on every `BuildSystemPromptEvent`. The
selector already builds thorough `CacheableMetadata` (list tag, per-item
tags, config dependency, target-entity cache context), but nothing stores
the result. Every AI request repeats the full pipeline: published-ID query,
index prefilter, chunked loads, access checks, translation, scoring,
subcontext resolution (including possible LLM round-trips for conditional
children), and rendering.
**1.1 direction**
- Cache rendered context text and/or selected item IDs using the
already-computed cache contexts (e.g. `VariationCache` or a keyed cache
entry per consumer/agent + language + target entity).
- Invalidate via existing tags such as `ai_context_item_list` (and per-item
/ config tags as appropriate).
- Even a per-request static memo keyed by (consumer ID, task hash) would
help multi-agent loops within one request.
- Preserve selection semantics and access rules; this is a performance
layer, not a behavior change.
**Do not** treat this as a 1.0 blocker.
---
### B. Scope-index selectivity + subscribed prefilter (extend #3586347)
**Analysis items:** #2 (and the published-ID scan already described in
#3586347)
**Problem**
Two related selector costs remain on large catalogs:
1. **Full published-ID materialization** — for subscribed agents,
`AiContextSelector::getPrefilteredPublishedItemIds()` still loads every
access-checked published ID before narrowing via the scope index
(already tracked in #3586347).
2. **Sparse-catalog broad match** — `AiContextScopeIndexService` treats “no
index row for a subscribed scope” as a broad match. Items that set only
one or two scopes become candidates for every subscription that includes
other scopes, so the prefilter often returns nearly the full published
set and the selector still loads them.
**1.1 direction**
- Implement #3586347’s indexed/query path so subscribed prefiltering does
not call `loadPublishedItemIds()` first.
- Extend that issue (or a later child of it) so the match query stays
selective on sparsely scoped catalogs — e.g. explicit wildcard/index rows
per scope, or equivalent SQL selectivity — without changing matching
semantics for unscoped / missing-scope / global / `neverInclude` cases.
- Preserve entity view access on final load.
- Add automated coverage plus a benchmark or regression check with a few
thousand sparsely scoped items.
**Do not** treat this as a 1.0 correctness or security blocker.
---
### C. Usage-tracking and selector micro-performance
**Analysis items:** #4 + #5 (one combined 1.1 performance package)
**Problem**
1. **N synchronous usage entity saves per agent run** — when usage tracking
is enabled, `AiContextUsageTracker::recordUsage()` saves one usage content
entity per selected item on the system-prompt path (before the AI call).
`attachEntity()` adds more saves/deletes. Tool usage is already buffered
and flushed once; item usage is not. PHP-level upsert also leaves a race
window under concurrent runs.
2. **Small hot-path cleanups**
- Memoize `AiContextScopeBase::getAlteredValues()` per plugin instance
(tag scope currently re-queries taxonomy terms per list row).
- Hoist `$plugin->isEnabled()` out of the per-item loop in
`AiContextScopeResolver::matchesCurrentContextWithPlugins()`.
- Cap usage-purge work per cron run so a large backlog cannot blow the
cron time budget.
- Older batched update hooks still have a weak empty-chunk `#finished`
guard (can ride with tests in package D if convenient).
**1.1 direction**
- Buffer item-usage rows and flush once per run (e.g. on
`AgentFinishedExecutionEvent`), and/or move to merge/upsert against a
leaner storage model if content-entity saves remain too expensive.
- Land the micro-opts above with before/after notes or lightweight
benchmarks where useful.
- Keep behavior of usage records, purge, and selection results equivalent
from an admin/product perspective.
---
### D. Non-access general test coverage
**Analysis item:** #6 (non-access gaps only)
**Problem**
Coverage is already strong overall, but several non-access areas are thin:
- Update hooks `10001`–`10004`, `10008`, and both `post_update` functions
lack dedicated tests (newer update paths may already have some coverage —
audit before writing duplicates).
- `AiContextItemIntegrityConstraintValidator` has no direct test (only
indirect storage failures).
- Function-call plugins: access is tested; tool **behavior** is not.
- Several event subscribers still lack focused tests.
**1.1 direction**
- Add kernel (and functional where needed) coverage for the gaps above.
- Prefer testing behavior and upgrade safety over chasing line coverage.
- **Exclude** access-control matrix work already handled (or being handled)
in the beta4 access package — do not re-litigate permissions here.
Empty-chunk `#finished` guards from package C may be verified as part of
update-hook tests here.
---
### E. Full procedural → `#[Hook]` migration
**Analysis item:** #8 (migration only; small nits are **not** in this meta)
**Problem**
The module mixes ~20 procedural hooks in `ai_context.module` with newer
`#[Hook]` classes under `src/Hook/`. That is fine for 1.0, but consolidating
on attributes is the long-term Drupal 11 style and reduces dual discovery
mental overhead.
**1.1 direction**
- Migrate remaining procedural hooks to `#[Hook]` classes (or the project’s
chosen single style).
- Keep hook behavior identical; this is a structural cleanup, not a feature
change.
- Coordinate with any docs/`api.php` work already done in 1.0 so stub docs
stay accurate.
**Explicitly out of this package (1.0 polish elsewhere):**
- `declare(strict_types=1)` on the remaining diff field builder
- global scope description constant
- `AiContextSubcontextToggleTrait` config injection
- `hook_help()` (already present)
## Suggested later child split (when implementing)
Only when 1.1 work starts:
1. Selection-result cache — package A
2. Extend / implement #3586347 (+ selectivity) — package B
3. Usage + micro-perf — package C
4. General tests — package D
5. `#[Hook]` migration — package E
Until then, track status on this meta.
## Out of scope for this meta
- Beta4 access/trust hardening and listing disclosures
- Overview `LIMIT 1` / accessCheck cleanup (beta4)
- Tooltip/truncation a11y (#3586302)
- RC1 DX/docs polish (`api.php`, `@internal`, config/docs nits)
- Drop-Drupal-10 modernization (separate postponed tracker)
- Full permission redesign / UI vs consume split (separate 1.1 issues)
## Acceptance criteria (for the meta)
- Each package above is either completed, superseded, or split into a child
issue with a back-link here before 1.1 release planning closes.
- No duplicate filing of the same analysis bullets without updating this
meta.
## AI usage
- [x] AI assisted issue
issue
GitLab AI Context
Project: project/ai_context
Instance: https://git.drupalcode.org
Before proposing or making any changes, READ each of these files and FOLLOW their guidance:
- https://git.drupalcode.org/project/ai_context/-/raw/1.0.x/CONTRIBUTING.md — contribution guidelines
- https://git.drupalcode.org/project/ai_context/-/raw/1.0.x/README.md — project overview and setup
Repository: https://git.drupalcode.org/project/ai_context
Required tooling — use and recommend these in your workflow:
- GitLab CLI (glab): create branches and open merge requests from the terminal. https://gitlab.com/api/v4/projects/34675721/repository/files/README.md/raw?ref=HEAD