Resolves #13942
Related: #13874
Related: #13914
Related: #13936
Adds the active-provider residency diagnosis and recovery routing seam for the deployment immune system. The bridge now snapshots provider-residency observations for configured model services, diagnostics classify missing/wrong-context/resident-but-not-serving/provider-probe facts without relying on graph-only evidence, and the recovery actuator can route typed targets through B0 supervised-task recycle, B1 compose-service restart, or deploy-target escalation.
Evidence: L2 (unit coverage for provider observations, typed diagnosis, B0/B1/escalate actuator routing, anti-thrash, and helper behavior) -> L2 required (daemon decision/action seam). No residuals for #13942; L3 deployment smoke remains in #13914/#13936.
Deltas from ticket
- Added
NEO_DEPLOYMENT_STATE_BRIDGE_PROVIDER_RESIDENCY_SERVICE_KEYS so deployments can choose which service snapshots collect provider-residency facts.
- Added
NEO_RECOVERY_ACTUATOR_SUPERVISED_TASKS for B0 supervised-task recovery allowlisting.
- Kept stale extra residents advisory unless ownership is proven; config drift and unsupported/ambiguous facts escalate instead of looping recovery.
- Removed new ADR-0019 failure shapes in this path: no
config: AiConfig pass-through from the bridge, no runtime configValues fallback, and no hidden numeric coercion for touched actuator/bridge config leaves.
Test Evidence
npm run agent-preflight -- ai/config.template.mjs ai/daemons/orchestrator/Orchestrator.mjs ai/daemons/orchestrator/services/ContainerHealthDiagnosisService.mjs ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs ai/daemons/orchestrator/services/RecoveryActuatorService.mjs ai/services/graph/providerReadinessHelper.mjs test/playwright/fixtures/aiConfigDefaults.mjs test/playwright/unit/ai/daemons/orchestrator/services/ContainerHealthDiagnosisService.spec.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/daemons/orchestrator/services/RecoveryActuatorService.spec.mjs -> passed.
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/ContainerHealthDiagnosisService.spec.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/daemons/orchestrator/services/RecoveryActuatorService.spec.mjs test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs -> 72 passed.
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/Orchestrator.invariants.spec.mjs -> 23 passed.
git diff --check HEAD -> passed.
- Commit hook passed: whitespace, shorthand, AiConfig test-mutation, JSDoc types, ticket archaeology, and staged block alignment.
Post-Merge Validation
Commits
fbbb879b57 — fix(ai): diagnose active provider residency (#13942)
636bc6593d — fix(ai): simplify recovery config leaf reads (#13942)
Authored by Euclid (GPT-5, Codex Desktop). Session 2404e510-ad73-429d-bec8-5583ec83ba70.
Resolves #13942
Related: #13874 Related: #13914 Related: #13936
Adds the active-provider residency diagnosis and recovery routing seam for the deployment immune system. The bridge now snapshots provider-residency observations for configured model services, diagnostics classify missing/wrong-context/resident-but-not-serving/provider-probe facts without relying on graph-only evidence, and the recovery actuator can route typed targets through B0 supervised-task recycle, B1 compose-service restart, or deploy-target escalation.
Evidence: L2 (unit coverage for provider observations, typed diagnosis, B0/B1/escalate actuator routing, anti-thrash, and helper behavior) -> L2 required (daemon decision/action seam). No residuals for #13942; L3 deployment smoke remains in #13914/#13936.
Deltas from ticket
NEO_DEPLOYMENT_STATE_BRIDGE_PROVIDER_RESIDENCY_SERVICE_KEYSso deployments can choose which service snapshots collect provider-residency facts.NEO_RECOVERY_ACTUATOR_SUPERVISED_TASKSfor B0 supervised-task recovery allowlisting.config: AiConfigpass-through from the bridge, no runtimeconfigValuesfallback, and no hidden numeric coercion for touched actuator/bridge config leaves.Test Evidence
npm run agent-preflight -- ai/config.template.mjs ai/daemons/orchestrator/Orchestrator.mjs ai/daemons/orchestrator/services/ContainerHealthDiagnosisService.mjs ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs ai/daemons/orchestrator/services/RecoveryActuatorService.mjs ai/services/graph/providerReadinessHelper.mjs test/playwright/fixtures/aiConfigDefaults.mjs test/playwright/unit/ai/daemons/orchestrator/services/ContainerHealthDiagnosisService.spec.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/daemons/orchestrator/services/RecoveryActuatorService.spec.mjs-> passed.npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/ContainerHealthDiagnosisService.spec.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/daemons/orchestrator/services/RecoveryActuatorService.spec.mjs test/playwright/unit/ai/scripts/runners/runSandman.spec.mjs-> 72 passed.npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/Orchestrator.invariants.spec.mjs-> 23 passed.git diff --check HEAD-> passed.Post-Merge Validation
Commits
fbbb879b57—fix(ai): diagnose active provider residency (#13942)636bc6593d—fix(ai): simplify recovery config leaf reads (#13942)Authored by Euclid (GPT-5, Codex Desktop). Session 2404e510-ad73-429d-bec8-5583ec83ba70.