0, 'face' => 1] || ($focus['default'] ?? null) !== 'face') { $failures[] = 'Рабочий config.json должен фиксировать явно согласованный focus=face.'; } foreach (['indpic', 'theme', 'degr', 'registration', 'bchoice', 'chb', 'tp'] as $key) { $setting = $config['utm'][$key] ?? null; if (!is_array($setting) || !is_array($setting['weights'] ?? null) || !is_string($setting['default'] ?? null)) { $failures[] = "Рабочий config.json должен хранить валидный stage-снимок UTM {$key}."; } } } $workflow = (string) file_get_contents($root . '/.gitea/workflows/deploy.yml'); $legacyStart = strpos($workflow, ' deploy:'); $stageStart = strpos($workflow, 'deploy-zoomstage:'); $productionStart = strpos($workflow, 'deploy-zoompixel-production:'); $legacyBlock = $legacyStart === false || $stageStart === false ? '' : substr($workflow, $legacyStart, $stageStart - $legacyStart); $stageBlock = $stageStart === false || $productionStart === false ? '' : substr($workflow, $stageStart, $productionStart - $stageStart); $productionBlock = $productionStart === false ? '' : substr($workflow, $productionStart); foreach ([ 'legacy FTP' => $legacyBlock, 'deploy-zoomstage' => $stageBlock, 'deploy-zoompixel-production' => $productionBlock, ] as $delivery => $block) { if ($block === '' || !str_contains($block, 'config\\.json$') || !str_contains($block, 'ensure-focus-config.php') || !str_contains($block, 'Preserve host config and add focus if absent')) { $failures[] = "{$delivery} обязан сохранять хостовый config.json и менять только явно согласованный focus."; } } if (is_file($root . '/config.json.example')) { $failures[] = 'config.json.example не должен существовать: рабочий config.json единственный.'; } if ($failures !== []) { fwrite(STDERR, "FAILED\n- " . implode("\n- ", $failures) . "\n"); exit(1); } fwrite(STDOUT, "OK: versioned stage config and ZoomPixel delivery\n");