*/ public static function snapshot(): array { $titles = ['Sistematizar a ideia', 'Análise preliminar', 'Decisão sobre a viabilidade', 'Estruturar o investimento', 'Constituição e registo', 'Preparar o dossier', 'Submeter quando aplicável', 'Licenciamento prévio', 'Necessidade de terra', 'Regularização da terra', 'Confirmar regularização aplicável', 'Necessidade e estrutura de financiamento', 'Diligência e negociação financeira', 'Decisão do financiador', 'Fecho e desembolso', 'Implementação', 'Inspecções, testes e licença de operação', 'Início de operação', 'Acompanhamento recorrente']; $steps = []; foreach ($titles as $index => $title) { $n = $index + 1; $steps[] = ['code' => sprintf('S%02d', $n), 'sequence' => $n, 'title' => $title, 'phase' => $n <= 4 ? 1 : ($n <= 7 ? 2 : ($n <= 11 ? 3 : ($n <= 15 ? 4 : 5))), 'source_paragraph' => 21 + $n, 'branch' => $n === 10 ? 'land_needed' : (in_array($n, [13, 14, 15], true) ? 'external_funding' : null), // Preparation has no dependencies. These only constrain the named consequential action. 'dependencies' => match ($n) { 7 => ['submit' => ['S06']], 15 => ['execute' => ['S14']], 18 => ['operate' => ['S17']], default => [], }]; } return ['kind' => 'investor-path', 'version' => 1, 'source_sha256' => 'aa13c53138ec15cd808de43d9dc2fc6808da86943d09d3352c9dd0944bdae364', 'phases' => [1 => 'Ideia e viabilidade', 2 => 'Formalização e dossier', 3 => 'Licenciamento e terra', 4 => 'Financiamento', 5 => 'Execução e acompanhamento'], 'states' => self::STATES, 'steps' => $steps, 'legacy_roadmaps' => ['virtual-desk:E0-E11', 'investor-guidance:7-phases', 'investment-roadmap:14-activities']]; } /** @param array $definition */ public static function validate(array $definition): void { $steps = $definition['steps'] ?? []; $expected = array_map(fn ($n) => sprintf('S%02d', $n), range(1, 19)); if (count($definition['phases'] ?? []) !== 5 || array_column($steps, 'code') !== $expected || array_column($steps, 'sequence') !== range(1, 19)) { throw new \LogicException('The five phases and nineteen source stages must remain traceable.'); } $edges = []; foreach ($steps as $step) { if (! in_array($step['phase'], range(1, 5), true) || ! in_array($step['branch'], [null, 'land_needed', 'external_funding'], true)) { throw new \LogicException('Unknown phase or applicability field.'); } $edges[$step['code']] = []; foreach ($step['dependencies'] as $action => $dependencies) { if (! in_array($action, ['submit', 'execute', 'operate'], true) || array_diff($dependencies, $expected)) { throw new \LogicException('Unknown action/dependency; preparation cannot be blocked.'); } $edges[$step['code']] = array_merge($edges[$step['code']], $dependencies); } } $visit = function (string $code, array $trail) use (&$visit, $edges): void { if (in_array($code, $trail, true)) { throw new \LogicException('Cyclic action dependencies.'); } foreach ($edges[$code] as $next) { $visit($next, [...$trail, $code]); } }; foreach ($expected as $code) { $visit($code, []); } } }