diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml
index 965dcb2..2364b2c 100644
--- a/.github/codeql/codeql-config.yml
+++ b/.github/codeql/codeql-config.yml
@@ -3,7 +3,7 @@ name: "BlorgFS CodeQL"
# Both packs pinned so a pack release can't silently change what a weekly
# run reports.
packs:
- - microsoft/windows-drivers@1.1.0
+ - microsoft/windows-drivers@1.10.0
- microsoft/cpp-queries@0.0.5
query-filters:
- include:
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index a1d3a56..bf8420a 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -1,11 +1,25 @@
name: "CodeQL Advanced"
-# Schedule-only on purpose: PREfast (RunCodeAnalysis=true in BlorgFS.vcxproj)
-# already gates every build.yml run on push/PR, so CodeQL runs weekly as a
-# deeper second opinion rather than duplicating that cost per push.
+# Weekly rather than per-push: PREfast (RunCodeAnalysis=true in
+# BlorgFS.vcxproj) already gates every build.yml run on push/PR, so CodeQL
+# is a deeper second opinion rather than a duplicate of that cost.
+#
+# The other two triggers exist because a schedule alone cannot validate a
+# change to this analysis. Scheduled workflows only ever run on the default
+# branch, so anything that alters what CodeQL reports -- a query-pack pin in
+# codeql-config.yml above all -- would be merged unrun and only surface as a
+# changed finding set the following Saturday. A pull request touching this
+# workflow or its config therefore runs the analysis it is changing, and
+# workflow_dispatch makes a re-scan available on demand rather than on a
+# seven-day wait (a pack bump, or re-triaging after a fix).
on:
schedule:
- cron: '41 23 * * 6'
+ workflow_dispatch:
+ pull_request:
+ paths:
+ - '.github/workflows/codeql.yml'
+ - '.github/codeql/**'
env:
SOLUTION_NAME: BlorgFS.sln
diff --git a/README.md b/README.md
index e869673..2b07c8b 100644
--- a/README.md
+++ b/README.md
@@ -69,6 +69,36 @@ not a substitute for running `Fast` yourself.)
script reports this as `CLOCK`, not `FAIL`. Confirm with
`Inf2Cat.exe /driver:x64\Debug\BlorgFS /os:10_x64 /uselocaltime`.
+## Continuous integration
+
+Three workflows, split by what a failure should cost you.
+
+| Workflow | Runs on | What it does |
+|---|---|---|
+| `build.yml` | push and PR to master | Both configurations, Fast tier. The merge gate. |
+| `verify.yml` | 03:00 UTC daily, or on demand | CBMC proofs and extended fuzz/interleaving runs. |
+| `codeql.yml` | Saturdays 23:41 UTC, on demand, and on any PR touching its own config | CodeQL with the pinned Microsoft driver query packs. |
+
+The daily and weekly ones are deliberately not gates: a CBMC regression or
+a new CodeQL finding is worth waking up to, not worth blocking a merge that
+PREfast and the Fast tier already cleared.
+
+`codeql.yml`'s third trigger is the one worth understanding. Scheduled
+workflows only ever run on the default branch, so a change to what CodeQL
+analyses -- above all a query-pack pin in `.github/codeql/codeql-config.yml`
+-- could otherwise only be merged unrun, and would first show up as a
+changed finding set the following Saturday. A PR touching that config or
+the workflow runs the analysis it is changing. `workflow_dispatch` covers
+the rest: re-scanning after a pack bump or a batch of fixes, without a
+seven-day wait.
+
+Both packs are pinned on purpose. A pack release must not silently change
+what a scheduled run reports -- but a pin that is never reviewed is lost
+coverage, and the windows-drivers pack is the one carrying the
+driver-specific IRQL and annotation queries. Bump it deliberately, let the
+PR trigger run it, and re-triage: previous false-positive verdicts do not
+carry across a pack version.
+
## Sanitizers
The usermode sandbox targets build with **ASan** (`EnableASAN`) — it owns
diff --git a/tests/sandbox/ClientFuzz.vcxproj b/tests/sandbox/ClientFuzz.vcxproj
index f1b27da..6bfe4db 100644
--- a/tests/sandbox/ClientFuzz.vcxproj
+++ b/tests/sandbox/ClientFuzz.vcxproj
@@ -41,6 +41,41 @@
+
+
+ $(Platform)\$(Configuration)\$(ProjectName)\
+
+
+
+
+
+ true
+
+
+
Level3
diff --git a/tests/sandbox/ClientSandbox.vcxproj b/tests/sandbox/ClientSandbox.vcxproj
index f17cb8f..98f81c2 100644
--- a/tests/sandbox/ClientSandbox.vcxproj
+++ b/tests/sandbox/ClientSandbox.vcxproj
@@ -41,6 +41,41 @@
+
+
+ $(Platform)\$(Configuration)\$(ProjectName)\
+
+
+
+
+
+ true
+
+
+
Level3
diff --git a/tests/sandbox/DispatchSandbox.vcxproj b/tests/sandbox/DispatchSandbox.vcxproj
index 0a8fc76..7baf95d 100644
--- a/tests/sandbox/DispatchSandbox.vcxproj
+++ b/tests/sandbox/DispatchSandbox.vcxproj
@@ -41,6 +41,41 @@
+
+
+ $(Platform)\$(Configuration)\$(ProjectName)\
+
+
+
+
+
+ true
+
+
+
Level3
diff --git a/tests/sandbox/NodeTableSandbox.vcxproj b/tests/sandbox/NodeTableSandbox.vcxproj
index 8bd7f3c..f8607db 100644
--- a/tests/sandbox/NodeTableSandbox.vcxproj
+++ b/tests/sandbox/NodeTableSandbox.vcxproj
@@ -41,6 +41,41 @@
+
+
+ $(Platform)\$(Configuration)\$(ProjectName)\
+
+
+
+
+
+ true
+
+
+
Level3
diff --git a/tests/sandbox/PrefetchSandbox.vcxproj b/tests/sandbox/PrefetchSandbox.vcxproj
index 9cd1a51..7378754 100644
--- a/tests/sandbox/PrefetchSandbox.vcxproj
+++ b/tests/sandbox/PrefetchSandbox.vcxproj
@@ -41,6 +41,41 @@
+
+
+ $(Platform)\$(Configuration)\$(ProjectName)\
+
+
+
+
+
+ true
+
+
+
Level3
diff --git a/tests/sandbox/SocketSandbox.vcxproj b/tests/sandbox/SocketSandbox.vcxproj
index 75d735d..4a84d8a 100644
--- a/tests/sandbox/SocketSandbox.vcxproj
+++ b/tests/sandbox/SocketSandbox.vcxproj
@@ -41,6 +41,41 @@
+
+
+ $(Platform)\$(Configuration)\$(ProjectName)\
+
+
+
+
+
+ true
+
+
+
Level3
diff --git a/tests/sandbox/TlsHandshakeSandbox.vcxproj b/tests/sandbox/TlsHandshakeSandbox.vcxproj
index 5687bb0..f22bb73 100644
--- a/tests/sandbox/TlsHandshakeSandbox.vcxproj
+++ b/tests/sandbox/TlsHandshakeSandbox.vcxproj
@@ -41,6 +41,41 @@
+
+
+ $(Platform)\$(Configuration)\$(ProjectName)\
+
+
+
+
+
+ true
+
+
+
Level3