diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
new file mode 100644
index 0000000..bf2ceb9
--- /dev/null
+++ b/phpstan-baseline.neon
@@ -0,0 +1,12 @@
+# Per-app phpstan lint debt baseline.
+#
+# Regenerate with: ./vendor/bin/phpstan analyse --generate-baseline
+# Apps without lint debt ship this file empty.
+#
+# Tracked-debt entries here MUST have an open GitHub issue. The directive for the
+# Conduction fleet is "no per-app validation rules; if we need exceptions then
+# they are for all apps." A baseline entry is acceptable only as a temporary
+# tracked-debt marker with a removal timeline.
+
+parameters:
+ ignoreErrors: []
diff --git a/phpstan.neon b/phpstan.neon
index e99f01f..26974c2 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,3 +1,9 @@
+includes:
+ # Per-app tracked lint debt lives here (auto-generated via `phpstan --generate-baseline`).
+ # Apps without debt ship an empty baseline file; canonical includes are otherwise byte-identical
+ # across the fleet.
+ - phpstan-baseline.neon
+
parameters:
level: 5
paths:
@@ -42,7 +48,8 @@ parameters:
- '#Doctrine\\DBAL\\[a-zA-Z\\]+.*not found#'
- '#on an unknown class Doctrine\\DBAL\\#'
# Dynamic HTTP status codes from business rule validation results
- - '#Parameter \$statusCode of class OCP\\AppFramework\\Http\\JSONResponse constructor expects#'
+ # (matches both `Parameter $statusCode` and `Parameter #N $statusCode` forms emitted by phpstan)
+ - '#Parameter (#\d+ )?\$statusCode of class OCP\\AppFramework\\Http\\JSONResponse constructor expects#'
# registerRepairStep exists on server; not yet in nextcloud/ocp stub used for analysis
- '#Call to an undefined method OCP\\AppFramework\\Bootstrap\\IRegistrationContext::registerRepairStep#'
# OCP stub gaps for methods that exist at runtime
diff --git a/psalm.xml b/psalm.xml
index 7a7ddaf..8c46a06 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -73,6 +73,7 @@
+