Handle the case when scope plugin values are no longer available
**Problem:**
Scope values can disappear after context items or agents have already selected them. For example:
- A context item targets `node:1234`, then that node is deleted.
- A context item or agent subscribes to the `hr` site section, then that site section is removed.
- A context item or agent uses the `foobar` AI context tag, then that tag term is deleted.
When this happens, the module should gracefully remove stale values from stored context item scope, agent scope subscriptions, and any related selection indexes. Target entity references should also be removed when the target entity is deleted, so items do not remain invisibly restricted to missing entities.
**Acceptance criteria:**
- Deleted AI context tag terms are removed from context items and agent scope subscriptions.
- Removed configured site sections are removed from context items and agent scope subscriptions.
- Deleted target entities are removed from context item target references.
- Scope index data stays in sync after cleanup.
- Custom site-section path patterns are preserved.
- Regression tests cover tag, site section, target entity, and index cleanup behavior.
**Stale behavior:**
_How will the selection behave when the stale values are there and haven't been cleaned up yet?_
Selection mostly “fails quiet,” but not always safely.
For stale `tag` or `site_section` values stored on context items:
- If the agent/request does not subscribe to that stale value, the item usually just won’t get scope credit for it.
- If the item has only stale values for a subscribed scope, it is treated as specifically scoped, not broad, so it may score lower or be excluded instead of behaving like “no scope.”
- If the agent config also still has the same stale subscription value, the item can still match by raw stored ID, even though the tag/section no longer exists.
- Because the scope index stores raw values, stale index rows can keep participating in prefiltering until the context item is saved/reindexed.
For stale `site_section` values specifically, hard current-context filtering probably won’t reject the item just because the section disappeared. If no current section can be detected, the base plugin behavior returns “no opinion,” so the item passes that hard filter and is then handled by subscription scoring.
For stale `target_entities` references:
- `hasTargetEntities()` still sees the field as non-empty, even if the referenced entity is deleted.
- The target entity plugin treats it as a targeted item.
- If there is no current entity context, it is excluded.
- If there is a different current entity, it is excluded.
- Since the deleted entity can’t normally become the current entity, the item can become effectively invisible unless it is explicitly always included.
So the biggest practical risks are: deleted target entities can hide context items, and stale tag/site-section subscriptions can keep matching stale raw IDs or distort scoring. That’s why cleanup is still worth doing rather than relying only on display behavior.
**AI usage disclosures:**
- [x] AI Assisted Issue
- [x] AI Generated Code
issue