diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 0000000..c71302a
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,21 @@
+
+
+
+
+ $(MSBuildProjectExtensionsPath)single-framework.packages.lock.json
+
+
+
diff --git a/scripts/validate.sh b/scripts/validate.sh
index 6850f46..b43e40b 100755
--- a/scripts/validate.sh
+++ b/scripts/validate.sh
@@ -199,6 +199,15 @@ fi
# This packs it and builds a real net8.0 consumer against the .nupkg, then builds this
# repository's own packaged projects, from a copy, with that analyzer attached. `full` only:
# it packs and restores, which the inner loop should not pay for on every run.
+# Dependabot's NuGet discovery restores referenced projects one framework at a time, which used
+# to rewrite the multi-targeted lock files without net8.0 (#63). Directory.Build.targets stops
+# that; this reproduces the exact invocation in a copy of the tree and fails if any lock file
+# changes. `full` only: it restores every test project's graph.
+if [[ "$MODE" == "full" ]]; then
+ step "A single-framework restore leaves the lock files alone"
+ run "lockfile-probe" tools/lockfile-probe/check.sh || true
+fi
+
if [[ "$MODE" == "full" ]]; then
step "Analyzer reaches a consumer, and the kernel passes it"
run "analyzer-probe" tools/analyzer-probe/check.sh || true
diff --git a/tools/lockfile-probe/check.sh b/tools/lockfile-probe/check.sh
new file mode 100755
index 0000000..276493f
--- /dev/null
+++ b/tools/lockfile-probe/check.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+# check.sh -- prove a single-framework restore cannot rewrite a multi-targeted lock file.
+#
+# Dependabot's NuGet discovery runs, in each project directory:
+# dotnet msbuild /t:Restore,ResolveProjectReferences,GenerateBuildDependencyFile
+# /p:ProjectReferenceBuildTargets="Restore;ResolveProjectReferences;GenerateBuildDependencyFile"
+# (dependabot-core, nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs).
+# Through the project references, that restored RulesKernel, RulesKernel.Randomness and
+# RulesKernel.Testing with one TargetFramework each and wrote net10.0-only lock files: issue #63,
+# reproduced exactly this way. Directory.Build.targets redirects the lock file in that context.
+#
+# This runs the same invocation from every test project in a clean copy of the tree and fails
+# if any tracked packages.lock.json changed. It reads the copy's own `git status`, so a lock file
+# that changed is named, not inferred.
+#
+# tools/lockfile-probe/check.sh
+set -euo pipefail
+
+REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
+WORK="$(mktemp -d)"
+trap 'rm -rf "$WORK"' EXIT
+
+# A copy of the working tree -- tracked files plus untracked ones that are not ignored, the
+# inventory tools/repo-checks.py examines -- committed into a scratch repository so its lock
+# files have a baseline to diff against. This checkout's obj/ and lock files are never touched.
+mkdir -p "$WORK/tree"
+(cd "$REPO_ROOT" && git ls-files -z --cached --others --exclude-standard | xargs -0 cp --parents -t "$WORK/tree")
+(cd "$WORK/tree" && git init -q && git add -A \
+ && git -c user.name=probe -c user.email=probe@example.invalid commit -qm baseline)
+
+mapfile -t projects < <(cd "$WORK/tree" && grep -rl --include=*.csproj 'true' tests probes | sort)
+if [[ "${#projects[@]}" -eq 0 ]]; then
+ echo "FAIL: no test projects found to restore from -- this check proved nothing"
+ exit 1
+fi
+
+for project in "${projects[@]}"; do
+ if ! (cd "$WORK/tree/$(dirname "$project")" && dotnet msbuild "$(basename "$project")" \
+ "/t:Restore,ResolveProjectReferences,GenerateBuildDependencyFile" \
+ '/p:ProjectReferenceBuildTargets="Restore;ResolveProjectReferences;GenerateBuildDependencyFile"' \
+ /p:TreatWarningsAsErrors=false -nologo -v:q) >"$WORK/restore.log" 2>&1; then
+ echo "FAIL: the Dependabot-style restore of $project did not run"
+ tail -10 "$WORK/restore.log"
+ exit 1
+ fi
+done
+
+changed="$(cd "$WORK/tree" && git status --porcelain -- '*packages.lock.json')"
+if [[ -n "$changed" ]]; then
+ echo "FAIL: a Dependabot-style restore rewrote lock files (issue #63):"
+ printf '%s\n' "$changed" | sed 's/^/ /'
+ exit 1
+fi
+echo "ok ${#projects[@]} Dependabot-style restore(s) left every packages.lock.json unchanged"