, entryCount: int} */ public static function validate_agent_map(mixed $decoded): array { $schema = is_array($decoded) ? (string) ($decoded['schemaVersion'] ?? '') : ''; return TheDotDevAgenticBridge_Artifact_Validator::validate_agent_map_strict($decoded, $schema === '1.1'); } /** * @param array $payload */ public static function semantic_fingerprint(array $payload): string { $normalized = $payload; if (isset($normalized['agent_map']) && is_array($normalized['agent_map'])) { unset($normalized['agent_map']['generatedAt']); } unset($normalized['published_at']); return hash('sha256', wp_json_encode($normalized) ?: ''); } /** * @param list $manifest_ids * @return array{status: string, checkedCount: int, ineligibleCount: int, missingCount: int, divergentCount: int} */ public static function evaluate_manifest_exposure(array $manifest_ids): array { $checked = 0; $ineligible = 0; $missing = 0; foreach ($manifest_ids as $id) { $post_id = (int) $id; if ($post_id <= 0) { continue; } ++$checked; $post = get_post($post_id); if ($post === null) { ++$missing; continue; } if (!TheDotDevAgenticBridge_Content_Metadata::is_artifact_eligible($post)) { ++$ineligible; } } $status = 'pass'; if ($ineligible > 0 || $missing > 0) { $status = 'fail'; } return [ 'status' => $status, 'checkedCount' => $checked, 'ineligibleCount' => $ineligible, 'missingCount' => $missing, 'divergentCount' => 0, ]; } /** * @param list $manifest_ids * @param list $entry_ids */ public static function count_divergent_ids(array $manifest_ids, array $entry_ids): int { $manifest = array_values(array_unique(array_map('intval', $manifest_ids))); $entries = array_values(array_unique(array_map('intval', $entry_ids))); sort($manifest); sort($entries); return $manifest === $entries ? 0 : max(count($manifest), count($entries)); } /** * @return array{match: bool|null, fingerprint: string, expectedFingerprint: string} */ public static function compare_public_agent_map(mixed $decoded): array { if (!TheDotDevAgenticBridge_Storage::artifacts_published()) { return ['match' => null, 'fingerprint' => '', 'expectedFingerprint' => '']; } $settings = TheDotDevAgenticBridge_Storage::get(); $last_known = is_array($settings['last_known_good'] ?? null) ? $settings['last_known_good'] : []; $expected_payload = TheDotDevAgenticBridge_Artifact_Validator::sanitize_published_lkg($last_known) ?? TheDotDevAgenticBridge_Artifact_Validator::empty_safe_payload(); $expected_map = $expected_payload['agent_map']; unset($expected_map['generatedAt']); $expected_fp = hash('sha256', wp_json_encode($expected_map) ?: ''); if (!is_array($decoded)) { return ['match' => false, 'fingerprint' => '', 'expectedFingerprint' => $expected_fp]; } $route_map = $decoded; unset($route_map['generatedAt']); $route_fp = hash('sha256', wp_json_encode($route_map) ?: ''); return [ 'match' => hash_equals($expected_fp, $route_fp), 'fingerprint' => $route_fp, 'expectedFingerprint' => $expected_fp, ]; } /** @param array $map @return list */ public static function entry_ids_from_map(array $map): array { $ids = []; $entries = is_array($map['entries'] ?? null) ? $map['entries'] : []; foreach ($entries as $entry) { if (!is_array($entry)) { continue; } $id = (int) ($entry['contentId'] ?? 0); if ($id > 0) { $ids[] = $id; } } return array_values(array_unique($ids)); } /** @param array $map */ public static function entries_with_metadata_actions(array $map): int { $count = 0; $entries = is_array($map['entries'] ?? null) ? $map['entries'] : []; foreach ($entries as $entry) { if (!is_array($entry)) { continue; } $actions = $entry['allowedActions'] ?? null; if (!is_array($actions) || $actions === []) { continue; } $valid = true; foreach ($actions as $action) { if (!is_array($action) || ($action['mode'] ?? '') !== 'metadata_only' || ($action['executable'] ?? true) !== false) { $valid = false; break; } } if ($valid) { ++$count; } } return $count; } }