SourceFileScanner::relativePath($file), 'line' => $line, 'snippet' => SourceFileScanner::snippet($source, $line), ]; $offset = $position + strlen($needle); } } if ($violations !== []) { $messages = array_map(static function (array $violation): string { return sprintf( "%s:%d\n%s", $violation['file'], $violation['line'], $violation['snippet'], ); }, $violations); $this->fail( "Legacy notification reference(s) found:\n\n".implode("\n\n", $messages) ); } expect($violations)->toBe([]); })->group('ops-ux'); it('keeps in-scope database notifications routed through the shared presenter seam', function (): void { $root = SourceFileScanner::projectRoot(); $files = [ $root.'/app/Notifications/Findings/FindingEventNotification.php', $root.'/app/Notifications/OperationRunQueued.php', $root.'/app/Notifications/OperationRunCompleted.php', ]; $needles = [ 'FilamentNotification::make(', '->getDatabaseMessage(', ]; $violations = []; foreach ($files as $file) { $source = SourceFileScanner::read($file); foreach ($needles as $needle) { if (! str_contains($source, $needle)) { continue; } $offset = 0; while (($position = strpos($source, $needle, $offset)) !== false) { $line = substr_count(substr($source, 0, $position), "\n") + 1; $violations[] = [ 'file' => SourceFileScanner::relativePath($file), 'line' => $line, 'snippet' => SourceFileScanner::snippet($source, $line), ]; $offset = $position + strlen($needle); } } } if ($violations !== []) { $messages = array_map(static function (array $violation): string { return sprintf( "%s:%d\n%s", $violation['file'], $violation['line'], $violation['snippet'], ); }, $violations); $this->fail( "Local database-notification payload composition found in in-scope consumers:\n\n".implode("\n\n", $messages) ); } expect($violations)->toBe([]); })->group('ops-ux'); it('keeps alert email delivery outside the shared database notification contract boundary', function (): void { $source = SourceFileScanner::read( SourceFileScanner::projectRoot().'/app/Notifications/Alerts/EmailAlertNotification.php' ); expect($source)->not->toContain('OperationUxPresenter') ->and($source)->not->toContain('FilamentNotification'); })->group('ops-ux');