The pattern is everywhere. Here it is superseded.
An agent adds customer lookup to a migrated orders service. It copies the direct database access it can see in two hundred places across the legacy tree. Mneme resolves ADR-042 against the path being changed: deny in the migrated tree, skip in the legacy tree.
During a migration the codebase teaches the wrong pattern.
Both architectures legitimately exist while the migration runs. The agent follows the majority, which is the architecture being removed. This trace ends at the block and at the skip that explains it.
ADR-042 · Direct database access is superseded by RepositoryPort. Migrated modules reach persistence through the port. The legacy tree keeps its existing calls until its components migrate, so the rule carries explicit path selectors rather than applying everywhere.
-
01 Decision
The superseded pattern is recorded with the paths it governs and the paths it must leave alone.
ADR-042 · include: modern/** · exclude: legacy/** -
02 Agent change
The agent mirrors the dominant pattern it found in the repository, inside a module that has already migrated.
+ db.query(Customer).filter_by(id=customer_id) -
03 MnemeDENY
Strict mode resolves the decision against the changed path and blocks the migrated module.
DENY [ADR-042] · modern/orders/customer_lookup.py · exit 2 -
04 Same rule, legacy path
The identical decision is evaluated against an unmigrated component and reports why it did not apply.
PATH SKIP [ADR-042] · legacy/orders/service.py · outside include_paths
Reproduction recipe
Reproduce the scoped migration check
Record ADR-042 with its path selectors, compile it, then evaluate a proposed diff against the migrated module.
pipx install "mneme-hq>=0.6.0"
mneme adr import docs/adr --memory .mneme/project_memory.json --apply
mneme check \
--memory .mneme/project_memory.json \
--input orders-service.diff \
--target-path modern/orders/customer_lookup.py \
--query "migrated module data access" --mode strict
# FAIL [ADR-042] · Result: FAIL · exit 2
This page is a recipe, not a turnkey fixture: you provide the ADR and the proposed diff. The legacy-path skip in step 04 is the same command run against a file outside the include selector.
What happened
Two hundred legacy call sites against twenty migrated ones make the old pattern look canonical. Statistically it is. It is also the thing the migration exists to remove.
Forbidding the pattern everywhere breaks the legacy tree that is still in production. Allowing it everywhere is what created the problem. The selectors resolve that per file.
Step 04 is the machine confirming that a component has not migrated yet. Over a long migration that reporting is how a team can see where the boundary actually is.
Common questions
Why does the same rule deny in one file and skip in another?
Because applicability is evaluated against the path being changed. ADR-042 carries include_paths for the migrated tree and exclude_paths for the legacy tree, so it governs modern/orders/ and is deliberately silent in legacy/orders/. That is what lets both architectures coexist while the migration runs.
Is the legacy code being ignored?
No. It is being left correct. The legacy pattern was the standard when that code was written and remains in force until its component migrates. Denying it everywhere would break a tree that is still running in production.
Why not just tell the agent about the migration in the prompt?
A prompt is advisory and is dropped when context is compacted. A migration runs across many sessions, agents and months, so the constraint has to be evaluated at the moment the agent acts rather than remembered from the top of a session.
What happens when the legacy component finishes migrating?
Its path moves under the include selector, so the same decision starts governing it. The transitional decision that permitted the compatibility adapter is marked superseded at that point, and the record stays as the reason the exception existed.
Keep the target architecture enforceable.
Record the migration decision once, then enforce it in the editor and at the merge gate for as long as the migration runs.
pipx install "mneme-hq>=0.6.0"