getMethod($method); $lines = file($reflection->getFileName()); if (!is_array($lines)) { throw new RuntimeException('method source must be readable'); } return implode('', array_slice( $lines, $reflection->getStartLine() - 1, $reflection->getEndLine() - $reflection->getStartLine() + 1 )); } $add = prescriptionAiWriteSafetySource('add'); $edit = prescriptionAiWriteSafetySource('editLocked'); prescriptionAiWriteSafetyExpect( str_contains($add, 'DiagnosisLogic::canManageDiagnosis'), 'prescription creation must enforce diagnosis write scope before loading patient data' ); prescriptionAiWriteSafetyExpect( str_contains($add, "->where('patient_id', \$diagnosisIdRule)"), 'client appointment id must be bound to the authorized diagnosis' ); foreach (['patient_id', 'patient_name', 'gender', 'age', 'phone'] as $field) { prescriptionAiWriteSafetyExpect( str_contains($add, "'{$field}' => \$diagnosis !== null"), "{$field} must be derived from the authorized diagnosis" ); } prescriptionAiWriteSafetyExpect( str_contains($add, "'case_record' => \$diagnosis !== null") && str_contains($add, "'doctor_name' => \$doctorName") && !str_contains($add, "'doctor_name' => \$doctorName !== ''"), 'case record and doctor identity must come from authoritative server state' ); prescriptionAiWriteSafetyExpect( str_contains($add, "'audit_status' => 0"), 'new AI-assisted prescriptions must always enter pending audit' ); prescriptionAiWriteSafetyExpect( str_contains($edit, '共享只扩大只读范围') && str_contains($edit, '处方不允许改绑其他诊单'), 'shared prescriptions must stay read-only and edits must not rebind diagnoses' ); echo "Prescription AI write safety contract: OK\n";