$meta['name'] ?? basename($filepath, '.md'), 'description' => $meta['description'] ?? '', 'version' => $meta['version'] ?? '1.0.0', 'auto_load' => (bool)($meta['auto-load'] ?? false), 'tags' => (array)($meta['tags'] ?? []), 'filename' => basename($filepath), ]; } usort($skills, fn($a, $b) => $b['auto_load'] <=> $a['auto_load']); return [ 'total' => count($skills), 'skills' => $skills, 'skills_dir' => str_replace(ABSPATH, '/', $dir), 'usage' => 'Call get_skill(name) to read any skill. Call get_page_context() to load all auto-load skills at once before building a landing page.', ]; } public static function getSkill(array $args): array { $name = sanitize_file_name($args['name'] ?? ''); if (empty($name)) throw new \RuntimeException('name is required.'); $name = preg_replace('/\.md$/i', '', $name); $filepath = self::dir() . $name . '.md'; $real = realpath($filepath); $dir = realpath(self::dir()); if (!$real || !str_starts_with($real, $dir)) { throw new \RuntimeException("Skill '{$name}' not found."); } $raw = file_get_contents($real); $meta = self::parseFrontMatterFromContent($raw); $body = self::stripFrontMatter($raw); return [ 'name' => $meta['name'] ?? $name, 'description' => $meta['description'] ?? '', 'version' => $meta['version'] ?? '1.0.0', 'auto_load' => (bool)($meta['auto-load'] ?? false), 'tags' => (array)($meta['tags'] ?? []), 'content' => $body, 'char_count' => strlen($body), ]; } public static function getPageContext(array $args): array { $dir = self::dir(); $files = glob($dir . '*.md') ?: []; $loaded = []; $skipped = []; foreach ($files as $filepath) { $raw = file_get_contents($filepath); $meta = self::parseFrontMatterFromContent($raw); if (!(bool)($meta['auto-load'] ?? false)) { $skipped[] = $meta['name'] ?? basename($filepath, '.md'); continue; } $loaded[] = ['name' => $meta['name'] ?? basename($filepath, '.md'), 'content' => self::stripFrontMatter($raw)]; } $combined = ''; foreach ($loaded as $skill) { $combined .= "\n\n" . str_repeat('=', 60) . "\n"; $combined .= "SKILL: {$skill['name']}\n"; $combined .= str_repeat('=', 60) . "\n\n"; $combined .= $skill['content']; } return [ 'loaded_skills' => array_column($loaded, 'name'), 'skipped_skills' => $skipped, 'total_loaded' => count($loaded), 'context' => trim($combined), 'char_count' => strlen($combined), 'usage_note' => 'This context contains your landing page build instructions. Follow them for every page you build. For motion/CSS patterns call get_skill("motion-and-css") separately.', ]; } private static function parseFrontMatter(string $filepath): ?array { $content = file_get_contents($filepath); if (!$content) return null; return self::parseFrontMatterFromContent($content); } private static function parseFrontMatterFromContent(string $content): array { if (!preg_match('/^---\s*\n(.*?)\n---/s', $content, $m)) return []; $meta = []; $lines = explode("\n", trim($m[1])); foreach ($lines as $line) { if (!preg_match('/^([a-zA-Z0-9_\-]+)\s*:\s*(.*)$/', $line, $lm)) continue; $key = trim($lm[1]); $val = trim($lm[2]); $val = preg_replace('/^["\'](.*)["\']$/', '$1', $val); if (strtolower($val) === 'true') $val = true; elseif (strtolower($val) === 'false') $val = false; elseif (is_numeric($val) && !str_starts_with($val, '0') && !str_contains($val, '.')) $val = (int)$val; if (is_string($val) && str_starts_with($val, '[') && str_ends_with($val, ']')) { $val = array_map(fn($v) => trim(trim($v), '"\''), explode(',', substr($val, 1, -1))); } $meta[$key] = $val; } return $meta; } private static function stripFrontMatter(string $content): string { return trim(preg_replace('/^---\s*\n.*?\n---\s*\n/s', '', $content)); } }